deploy-to-aks
Skill43 starsChanged 5 months agoMITView on GitHub
End-to-end orchestrator that takes a source repository through analysis → Dockerfile → image build → security scan → AKS cluster prep → ACR push → Kubernetes manifests → deploy → verify on a real **Azure AKS** cluster. Trigger ONLY when the user explicitly names Azure, AKS, or ACR — e.g. "deploy to AKS", "deploy to Azure", "ship to Azure", "push to ACR", "containerize and deploy to Azure", "AKS dev loop", "run this on AKS", "get this on AKS". Do **NOT** trigger on generic deployment phrasing like "deploy this app", "deploy to kubernetes", "deploy to k8s", "deploy to the cloud", "deploy to minikube", "deploy to kind", "deploy locally", or any other non-Azure target — those are not this skill. If the target is ambiguous, ask the user whether they mean AKS before starting. Required inputs: container registry login server (e.g. `myregistry.azurecr.io`), resource group, AKS cluster name. Optional: namespace, image name.
In this repository6 other files it gives its agents.
- AGENTS.mdAGENTS.md
- ca-releaseSkill
- analyze-repoSkill
- fix-dockerfileSkill
- generate-dockerfileSkill
- generate-k8s-manifestsSkill
The file
Show its rules and text
We split this skill into the rules it gives an agent
37 rules. About 0 are common, 10 are distinctive, and 27 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈10
Distinctive · estimate
This author's own choices. Worth a look.
27
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 23
After collection, echo back the resolved values in one block and ask the user to confirm before running Step 1.
- Distinctive: line 27
Run the steps strictly in order.
- Very specific: line 34
If the chosen tenant differs from the active one, run az login --tenant "<selectedTenantId>" and re-check.
- Very specific: line 57
If userType == "user": az ad signed-in-user show --query id -o tsv → callerPrincipalId.
- Very specific: line 60
Do not: run any kubectl here. RBAC + kubeconfig fetch happen in Step 11.
- Very specific: line 71
If attach also fails (e.g.
- Very specific: line 78
Follow the analyze-repo skill against the current working directory.
- Distinctive: line 88
Do these exist as Azure PaaS services (Azure Database for PostgreSQL, Azure Cache for Redis, …)?
- Distinctive: line 89
If yes, collect server hostname(s) and database name(s) per module.
- Very specific: line 110
If no Dockerfile exists, follow the generate-dockerfile skill with the analysis context, environment production, and platform linux/amd64.
- Very specific: line 111
If a Dockerfile exists, follow the fix-dockerfile skill against it.
- Very specific: line 117
Call the build-image-context tool with:
- Very specific: line 123
If the failure looks like a Dockerfile issue (syntax, missing files, base image not found, dependency error): follow the fix-dockerfile …
- Very specific: line 129
Call the scan-image tool with the built image ID.
- Very specific: line 131
If any critical or high issues are reported: follow the fix-dockerfile skill using the scan results as context, then rebuild (Step 9) and …
- Distinctive: line 132
Do not proceed past unresolved critical findings unless the user explicitly approves.
- Very specific: line 136
Skip this step entirely: if isAutomatic !== true AND isAzureRbac !== true.
- Very specific: line 158
If create namespaces == no but all namespace-scoped probes pass, surface this and continue only if an admin will pre-create the namespace.
- Very specific: line 159
If any namespace-scoped probe returns no: halt, emit the remediation block for missing roles:
- Very specific: line 162
Wait for the user, then poll the failed kubectl auth can-i checks every 10 s for up to 2 min.
- Very specific: line 181
If kubeconfig is missing, run az aks get-credentials --resource-group <resourceGroup> --name <clusterName> first.
- Very specific: line 185
Call the tag-image tool to produce <loginServer>/<imageName>:<tag>.
- Very specific: line 190
Call the push-image tool to push the tagged image to <loginServer>.
- Very specific: line 196
If no manifests exist for the target module(s), follow the generate-k8s-manifests skill.
- Very specific: line 217
Ensure the namespace exists (idempotent): kubectl create namespace <namespace> --dry-run=client -o yaml | kubectl apply -f -.
- Very specific: line 223
Call the verify-deploy tool with <namespace> to check pod status, readiness, and events.
- Very specific: line 225
If a Service of type LoadBalancer or an Ingress is configured, report the external IP / hostname to the user.
- Distinctive: line 244
Always retry a failed step up to 2 times: before halting and reporting.
- Very specific: line 245
After every step, send a short status line to the user (✅ Step N — <heading>).
- Distinctive: line 246
If a tool or skill returns chain hints / next-step suggestions, follow them.
- Very specific: line 247
Use linux/amd64 for all builds (standard AKS node arch).
- Distinctive: line 249
If the RBAC check in Step 11 halts the workflow, follow its embedded instructions exactly: emit the missing-roles diagnostic, wait for the …
- Very specific: line 250
Do NOT suggest az aks command invoke as an RBAC bypass when isAzureRbac == true — it authenticates as the caller and hits the same …
- Very specific: line 251
Do NOT suggest --admin kubeconfig when localAccountsDisabled == true — AKS will reject it.
- Very specific: line 252
When using vscode_askQuestions for pickers, always include a free-text input so the user can type a value manually.
- Distinctive: line 253
Do not invent Azure resources, role names, or commands.
- Distinctive: line 257
After Step 17 passes, summarize:
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Deploy to AKS
You are driving a full repository → running pod on AKS iteration loop. This skill orchestrates other skills — read each one before you run its step, pass results forward, and don't duplicate their logic here.
Inputs
Collect (ask the user once if any are missing):
registry(required) — ACR login server, e.g.myregistry.azurecr.ioresourceGroup(required) — Azure RG containing the AKS clusterclusterName(required) — AKS cluster namenamespace(optional) — defaults to a unique name likestaging-<short-hash>imageName(optional) — defaults to the repo directory namerepoPath— the current working directory (confirm with user)targetPlatform— fixedlinux/amd64(standard AKS node arch)environment— fixedproduction
After collection, echo back the resolved values in one block and ask the user to confirm before running Step 1.
Workflow
Run the steps strictly in order. Retry each step up to 2 times before halting. Keep the user informed after every step.
Step 1 — Select and validate the Azure tenant
az account show --query "{tenantId:tenantId, tenantDisplayName:tenantDisplayName, user:user.name}" -o json→ current tenant.az account tenant list --query "[].{tenantId:tenantId, displayName:displayName, defaultDomain:defaultDomain}" -o json(fall back toaz account list ... | dedupe by tenantIdif unavailable).- Present a picker (default = current tenant; additional = other tenants; free-text fallback). Use
vscode_askQuestionsif available. - If the chosen tenant differs from the active one, run
az login --tenant "<selectedTenantId>"and re-check. - Validate
az account show --query tenantId -o tsv==<selectedTenantId>. - Record
tenantId. Confirm: "Using tenant<displayName>(<tenantId>)."
Step 2 — Select and validate the Azure subscription
az account show --query "{id:id, name:name, tenantId:tenantId}" -o json.az account list --query "[?state=='Enabled' && tenantId=='<tenantId>'].{id:id, name:name}" -o json.- Picker (default = current sub; additional = other enabled subs in tenant; free-text fallback).
- Validate with
az account show --subscription "<id>" ...—tenantIdmust match Step 1. az account set --subscription "<id>". Confirm: "Using subscription<name>(<id>)."
Step 3 — Select and validate the AKS cluster (metadata only — no kubectl yet)
az aks list -g <resourceGroup> --query "[].{name:name, sku:sku.name, fqdn:fqdn}" -o json.- Picker (default =
clusterNamefrom input or first listed; additional = other clusters in RG; free-text fallback). - Validate:
az aks show -g <resourceGroup> -n "<clusterName>" --query "{name:name, fqdn:fqdn, sku:sku.name, azureRbac:aadProfile.enableAzureRbac, localAccountsDisabled:disableLocalAccounts}" -o json. - Record metadata:
isAutomatic=sku == "Automatic"isAzureRbac=azureRbac == truelocalAccountsDisabled=localAccountsDisabled == true
- Capture caller identity:
az account show -o json→subscriptionId,userName,userType.- If
userType == "user":az ad signed-in-user show --query id -o tsv→callerPrincipalId. - If
userType == "servicePrincipal":az ad sp show --id <userName> --query id -o tsv→callerPrincipalId. - Else fall back to
userNameascallerPrincipalId.
- Do not run any
kubectlhere. RBAC + kubeconfig fetch happen in Step 11.
Step 4 — Select and validate the Azure Container Registry
az acr list --query "[].{name:name, loginServer:loginServer}" -o json.- Picker (default = the input
registrymatched byloginServer, or first ACR; free-text fallback). - Normalize so you retain both
<acrName>and<loginServer>. - Validate:
az acr show --name "<acrName>" --query "{name:name, loginServer:loginServer}" -o json. - Validate AKS→ACR pull authorization:
az aks check-acr -g <resourceGroup> -n <clusterName> --acr <loginServer>.- On failure, try
az aks update -g <resourceGroup> -n <clusterName> --attach-acr <acrName>. - If attach also fails (e.g.
AuthorizationFailed), tell the user:"The AKS cluster cannot pull from this ACR. Attaching requires Owner or User Access Administrator on the ACR resource. Ask someone with that role to run:
az aks update -g <rg> -n <cluster> --attach-acr <acrName>." - Halt until pull access is verified.
- Confirm: "Using ACR
<loginServer>(<acrName>). Cluster pull access verified."
Step 5 — Analyze the repository
Follow the analyze-repo skill against the current working directory.
- Confirm the detected language, framework, modules, existing Dockerfiles,
detectedDatabases, anddetectedEnvVarswith the user. - For monorepos, list independently deployable modules and ask which one(s) to target.
- Forward the full analysis to every later step that needs it.
Step 6 — Database dependency check
For each target module where detectedDatabases is non-empty, ask:
- Do these exist as Azure PaaS services (Azure Database for PostgreSQL, Azure Cache for Redis, …)?
- If yes, collect server hostname(s) and database name(s) per module.
- Confirm the managed identity client ID for workload identity auth.
Skip if no module has detected databases.
Step 7 — Environment variable check
For each target module where detectedEnvVars is non-empty, ask:
- Confirm the
secret/database/configclassifications are correct. - For secret vars, confirm they will be injected at runtime (not baked into the image).
- For config vars, confirm default values or ask for the correct ones.
Pass the confirmed detectedEnvVars to the Dockerfile and manifest generation steps.
Skip if no module has detected env vars.
Step 8 — Generate or remediate the Dockerfile
For each target module:
- If no Dockerfile exists, follow the
generate-dockerfileskill with the analysis context, environmentproduction, and platformlinux/amd64. - If a Dockerfile exists, follow the
fix-dockerfileskill against it; it writes the remediated file back to disk.
Retry up to 2 times if generation/remediation fails.
Step 9 — Build the image
- Call the
build-image-contexttool with:path= repo (or module) pathimageName=<imageName>:dev(or an immutable tag like<imageName>:git-<shortSha>)platform=linux/amd64
- Execute the returned build command to produce the local Docker image.
- On failure:
- If the failure looks like a Dockerfile issue (syntax, missing files, base image not found, dependency error): follow the
fix-dockerfileskill against the current Dockerfile, then retry. - Otherwise retry the build directly.
- Maximum 2 retries per failure mode.
- If the failure looks like a Dockerfile issue (syntax, missing files, base image not found, dependency error): follow the
Step 10 — Scan the image
- Call the
scan-imagetool with the built image ID. - Review vulnerabilities.
- If any critical or high issues are reported: follow the
fix-dockerfileskill using the scan results as context, then rebuild (Step 9) and rescan. Retry the fix/rebuild/scan loop up to 2 times. - Do not proceed past unresolved critical findings unless the user explicitly approves.
Step 11 — Verify effective access (AKS Automatic / Azure RBAC)
Skip this step entirely if isAutomatic !== true AND isAzureRbac !== true.
Otherwise:
- Compute scopes:
clusterScope=/subscriptions/<subscriptionId>/resourceGroups/<resourceGroup>/providers/Microsoft.ContainerService/managedClusters/<clusterName>namespaceScope=<clusterScope>/namespaces/<namespace>
- Control-plane probe — fetch kubeconfig:
az aks get-credentials -g <resourceGroup> -n "<clusterName>" --overwrite-existing(omit--admin; AKS Automatic disables local accounts).- On failure: halt, run the
canSelfRemediateprobe below, emit the remediation block (Case A or B) for missing roleAzure Kubernetes Service Cluster User Role @ <clusterScope>, wait for the user, then pollaz aks get-credentialsevery 15 s for up to 5 min.
canSelfRemediateprobe (used by Steps 2 and 4 remediation):az rest --method post --url "https://management.azure.com<clusterScope>/providers/Microsoft.Authorization/permissions?api-version=2022-04-01"— inspectactions/notActionsforMicrosoft.Authorization/roleAssignments/write.- Fallback:
az role assignment list --assignee <callerPrincipalId> --scope <clusterScope> --include-inherited -o jsonfor any ofOwner,User Access Administrator,Role Based Access Control Administrator. If that also fails withAuthorizationFailed, setcanSelfRemediate = false.
- Data-plane probes (run before any read calls):
kubectl auth can-i create namespaces(cluster-scoped)kubectl auth can-i create deployments -n <namespace>kubectl auth can-i create services -n <namespace>kubectl auth can-i create configmaps -n <namespace>kubectl auth can-i get pods -n <namespace>- If
create namespaces == nobut all namespace-scoped probes pass, surface this and continue only if an admin will pre-create the namespace. - If any namespace-scoped probe returns
no: halt, emit the remediation block for missing roles:Azure Kubernetes Service RBAC Writer @ <namespaceScope>(for deploy/services/configmaps)Azure Kubernetes Service RBAC Admin @ <clusterScope>(additionally, if namespace must be created)
- Wait for the user, then poll the failed
kubectl auth can-ichecks every 10 s for up to 2 min.
- Connectivity sanity: compare
fqdnfrom Step 3 to the hostname inkubectl config view --minify -o jsonpath='{.clusters[0].cluster.server}'. Runkubectl get nodes --no-headers. Checkkubectl get namespace <namespace> --no-headers --ignore-not-foundand recordnamespaceExists. - Confirm: "✅ Effective access verified for caller
<userName>on cluster<clusterName>. Proceeding."
Remediation block format (use for any HALT in Steps 2 and 4):
- Case A —
canSelfRemediate === true: present a⚠️summary, the missing role(s), and oneaz role assignment create --role "<Role>" --assignee <callerPrincipalId> --scope "<scope>"command per role. Offer to run it (with confirmation), then poll. - Case B —
canSelfRemediate === false: present the same summary + roles, but tell the user to ask an Owner, User Access Administrator, or Role Based Access Control Administrator to run the sameaz role assignment createcommands. Include hand-off identifiers (callerPrincipalId,userType,clusterScope,namespaceScope). Do NOT attempt the role assignment yourself. - Append "Note: AKS Automatic disables local accounts;
--adminkubeconfig is unavailable." whenlocalAccountsDisabledorisAutomaticis true.
Step 12 — Prepare the cluster
- Call the
prepare-clustertool with:clusterType: "generic"(assumes the existing AKS cluster)namespace:<namespace>targetPlatform: "linux/amd64"
- Retry up to 2 times.
- If kubeconfig is missing, run
az aks get-credentials --resource-group <resourceGroup> --name <clusterName>first.
Step 13 — Tag the image for ACR
- Call the
tag-imagetool to produce<loginServer>/<imageName>:<tag>. - Retry up to 2 times.
Step 14 — Push the image to ACR
- Call the
push-imagetool to push the tagged image to<loginServer>. - Retry up to 2 times.
- On auth failure, prompt the user to run
az acr login --name <acrName>and retry.
Step 15 — Generate Kubernetes manifests (if missing)
If no manifests exist for the target module(s), follow the generate-k8s-manifests skill.
- Parameters to pass to the skill:
modulePath= target module pathnamespace=<namespace>environment=productionimage=<loginServer>/<imageName>:<tag>detectedDatabasesanddetectedEnvVarsfrom Step 5analysis= the analyze-repo result
- The skill writes one YAML file per resource to
<modulePath>/k8s/.
AKS Automatic hardening — if isAutomatic === true, before applying, verify the generated manifests contain:
- Pod-level:
securityContext.runAsNonRoot: trueandsecurityContext.seccompProfile.type: RuntimeDefault. - Container-level:
securityContext.allowPrivilegeEscalation: falseandcapabilities.drop: ["ALL"]. - Resource
requestsandlimitson every container (e.g.cpu: 500m / 1000m,memory: 512Mi / 1Gi).
The generate-k8s-manifests skill already produces these for environment == production; only add what is missing.
Step 16 — Deploy
- Ensure the namespace exists (idempotent):
kubectl create namespace <namespace> --dry-run=client -o yaml | kubectl apply -f -. - Apply manifests:
kubectl apply -f <modulePath>/k8s/ --namespace <namespace>. - Retry up to 2 times.
Step 17 — Verify
- Call the
verify-deploytool with<namespace>to check pod status, readiness, and events. - On failure: inspect pod logs and events, fix the underlying issue (re-run an earlier step if needed), redeploy. Retry up to 2 times.
- If a
Serviceof typeLoadBalanceror anIngressis configured, report the external IP / hostname to the user.
Tool / skill catalog used by this loop
| Step | Component | Kind |
| 5 | analyze-repo | skill |
| 8 (gen) | generate-dockerfile | skill |
| 8 (fix), 9 (on-fail), 10 (on-vuln) | fix-dockerfile | skill |
| 9 | build-image-context | tool |
| 10 | scan-image | tool |
| 12 | prepare-cluster | tool |
| 13 | tag-image | tool |
| 14 | push-image | tool |
| 15 | generate-k8s-manifests | skill |
| 17 | verify-deploy | tool |
Rules
- Always retry a failed step up to 2 times before halting and reporting.
- After every step, send a short status line to the user (
✅ Step N — <heading>). - If a tool or skill returns chain hints / next-step suggestions, follow them.
- Use
linux/amd64for all builds (standard AKS node arch). - For ACR auth issues, guide the user through
az acr loginbefore retrying push. - If the RBAC check in Step 11 halts the workflow, follow its embedded instructions exactly: emit the missing-roles diagnostic, wait for the user, and poll until access propagates. Do NOT proceed to deploy or verify until probes pass.
- Do NOT suggest
az aks command invokeas an RBAC bypass whenisAzureRbac == true— it authenticates as the caller and hits the sameForbidden. - Do NOT suggest
--adminkubeconfig whenlocalAccountsDisabled == true— AKS will reject it. - When using
vscode_askQuestionsfor pickers, always include a free-text input so the user can type a value manually. - Do not invent Azure resources, role names, or commands. If something is unclear, ask.
Final report
After Step 17 passes, summarize:
- Cluster, namespace, image reference, and resource group.
- Deployed resources (deployment, service, configmap, secret, serviceaccount, hpa as applicable).
- External endpoint, if any.
- Anything skipped (e.g. database setup deferred, vulnerabilities accepted by user).
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

