Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Added demand functionality to ADO pipelines #862

Merged
merged 4 commits into from
Aug 8, 2022
Merged
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 79 additions & 1 deletion content/docs/2.8/scalers/azure-pipelines.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ triggers:
# Optional: Target queue length
targetPipelinesQueueLength: "1" # Default 1
activationTargetPipelinesQueueLength: "5" # Default 0
# Optional: Parent template to read demands from
parent: "{parent ADO agent name}"
# Optional: Demands string to read demands from ScaledObject
demands: "{demands}"
authenticationRef:
name: pipeline-trigger-auth
```
Expand All @@ -39,6 +43,8 @@ triggers:
- `targetPipelinesQueueLength` - Target value for the amount of pending jobs in the queue to scale on. (Default: `1`, Optional)
- Example - If one pod can handle 10 jobs, set the queue length target to 10. If the actual number of jobs in the queue is 30, the scaler scales to 3 pods.
- `activationTargetPipelinesQueueLength` - Target value for activating the scaler. Learn more about activation [here](./../concepts/scaling-deployments.md#activating-and-scaling-thresholds).(Default: `0`, Optional)
- `parent` - Put the name of the ADO agent that matched the ScaledObject. e.g. mavenagent-scaledobject may have an initial deployment called "mavenagent-keda-template"; this is the deployment that is made offline. This name is provided to the initial deployment as the environment variable "AZP_NAME"
- `demands` - Put the demands string that was provided to the ScaledObject. This MUST be a subset of the actual capability list the agent has. e.g. `maven,docker`

> 💡 **NOTE:** You can either use `poolID` or `poolName`. If both are specified, then `poolName` will be used.

Expand All @@ -62,7 +68,52 @@ The URL should be similar to `https://dev.azure.com/{organization}/_settings/age

Finally, it is also possible get the pool ID from the response of a HTTP request by calling the `https://dev.azure.com/{organizationName}/_apis/distributedtask/pools?poolname={agentPoolName}` endpoint in the key `value[0].id`.

### Example
### Supporting demands in agents

By default, if you do not wish to use demands in your agent scaler then it will scale based simply on the pool's queue length.

Demands (Capabilities) are useful when you have multiple agents with different capabilities existing within the same pool,
for instance in a kube cluster you may have an agent supporting dotnet5, dotnet6, java or maven;
particularly these would be exclusive agents where jobs would fail if run on the wrong agent. This is Microsoft's demands feature.

- **Using Parent:** Azure DevOps is able to determine which agents can match any job it is waiting for. If you specify a parent template then KEDA will further interrogate the job request to determine if the parent is able to fulfill the job. If the parent is able to complete the job it scales the workload fulfill the request. The parent template that is generally offline must stay in the Pool's Agent list.

- **Using demands:** KEDA will determine which agents can fulfill the job based on the demands provided. The demands are provided as a comma-separated list and must be a subset of the actual capabilities of the agent. (For example `maven,java,make`. Note: `Agent.Version` is ignored)

Microsoft's documentation: [https://docs.microsoft.com/en-us/azure/devops/pipelines/agent/agent-pool-demands](https://docs.microsoft.com/en-us/azure/devops/pipelines/agent/agent-pool-demands)

Please note that the parent template feature is exclusive to KEDA and not Microsoft and is another way of supporting demands.

If you wish to use demands in your agent scaler then you can do so by adding the following to your pipeline:

```yaml
pool:
- name: "{agentPoolName}"
demands:
- example-demands
- another-demand -equals /bin/executable
```

Then, you can use the `demands` parameter to specify the demands that your agent supports or the `parent` parameter to link a template that matches you scaled object.

KEDA will use the following evaluation order:
1) If neither parent nor demands are defined in the scaling definition, it will scale the workload to fulfill the job.
2) If `parent` is set, KEDA will interrogate the job request to determine if the parent is able to fulfill the job. If the parent is able to complete the job it scales the workload to fulfill the request.
3) Finally, if the demands are set in the scaling definition then KEDA will determine which agents can fulfill the job based on the demands provided.

> Note: If more than one scaling definition is able to fulfill the demands of the job then they will both spin up an agent.

#### How it works under the hood

Azure DevOps has a Job Request API with returns a list of all jobs, and the agent that they are assigned to, or could potentially be assigned to. This is an undocumented Microsoft API.

This is the API: https://dev.azure.com/<organisation>/_apis/distributedtask/pools/<poolid>/jobrequests
Eldarrin marked this conversation as resolved.
Show resolved Hide resolved

KEDA will interpret this request to find any matching template from the defined parent in the scaling definition, or any agent that can satisfy the demands specified in the scaling definition.

Once it finds it, it will scale the workload that matched the definition and Azure DevOps will assign it to that agent.

### Example for ScaledObject

```yaml
apiVersion: v1
Expand Down Expand Up @@ -99,6 +150,33 @@ spec:
metadata:
poolID: "1"
organizationURLFromEnv: "AZP_URL"
parent: "example-keda-template"
demands: "maven,docker"
authenticationRef:
name: pipeline-trigger-auth
```

###Example for Parent Deployment or StatefulSet

```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: agent
spec:
replicas: 1
selector:
matchLabels:
app: agent
spec:
containers:
- name: agent
image: [SAME AS SCALED JOB]
envFrom:
- secretRef:
name: ado-pat-tokens
env:
- name: AZP_AGENT_NAME
value: example-keda-template # Matches Scaled Job Parent

```