Add drone-k8s-auto-deploy skill
This commit is contained in:
parent
310cb7b17b
commit
5c17268af3
1 changed files with 162 additions and 0 deletions
162
dot_claude/skills/drone-k8s-auto-deploy/SKILL.md
Normal file
162
dot_claude/skills/drone-k8s-auto-deploy/SKILL.md
Normal file
|
|
@ -0,0 +1,162 @@
|
||||||
|
---
|
||||||
|
name: drone-k8s-auto-deploy
|
||||||
|
description: |
|
||||||
|
Set up Drone CI pipelines that build Docker images and auto-deploy to Kubernetes.
|
||||||
|
Use when: (1) setting up CI/CD for a project running on a k8s cluster with Drone,
|
||||||
|
(2) need to trigger a k8s deployment update from a Drone pipeline step,
|
||||||
|
(3) want to avoid manual kubectl rollout restart after image push. Covers pipeline
|
||||||
|
type selection, k8s API patching via service account token, and build-number tagging.
|
||||||
|
author: Claude Code
|
||||||
|
version: 1.0.0
|
||||||
|
date: 2026-02-06
|
||||||
|
---
|
||||||
|
|
||||||
|
# Drone CI Kubernetes Auto-Deploy
|
||||||
|
|
||||||
|
## Problem
|
||||||
|
After pushing a new Docker image from Drone CI, the Kubernetes deployment still runs
|
||||||
|
the old image. Manual `kubectl rollout restart` is needed, breaking the automated
|
||||||
|
pipeline.
|
||||||
|
|
||||||
|
## Context / Trigger Conditions
|
||||||
|
- Drone CI is running on a Kubernetes cluster (not as a standalone Docker host)
|
||||||
|
- The deployment uses a specific image tag (not `:latest` with `imagePullPolicy: Always`)
|
||||||
|
- You want push-to-main to automatically build, push, and deploy
|
||||||
|
- The Drone service account has RBAC permissions to patch deployments (e.g. cluster-admin)
|
||||||
|
|
||||||
|
## Solution
|
||||||
|
|
||||||
|
### 1. Use `type: kubernetes` pipeline
|
||||||
|
|
||||||
|
When Drone runs on k8s, pipeline steps execute as pods with access to the cluster
|
||||||
|
API via mounted service account tokens.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
kind: pipeline
|
||||||
|
type: kubernetes # NOT 'docker'
|
||||||
|
name: my-app
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Tag images with build number
|
||||||
|
|
||||||
|
Use `${DRONE_BUILD_NUMBER}` for unique, incrementing tags. Push both `:latest` and
|
||||||
|
the build number for flexibility.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- name: docker
|
||||||
|
image: plugins/docker
|
||||||
|
settings:
|
||||||
|
repo: myregistry/myapp
|
||||||
|
tags:
|
||||||
|
- latest
|
||||||
|
- "${DRONE_BUILD_NUMBER}"
|
||||||
|
username:
|
||||||
|
from_secret: docker_username
|
||||||
|
password:
|
||||||
|
from_secret: docker_password
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Patch the deployment via k8s API
|
||||||
|
|
||||||
|
Use `curl` to PATCH the deployment's container image to the new tag. The service
|
||||||
|
account token is auto-mounted at `/var/run/secrets/kubernetes.io/serviceaccount/token`.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- name: deploy
|
||||||
|
image: alpine
|
||||||
|
commands:
|
||||||
|
- apk add --no-cache curl
|
||||||
|
- |
|
||||||
|
curl -sfk -X PATCH \
|
||||||
|
"https://<K8S_API_HOST>:6443/apis/apps/v1/namespaces/<NAMESPACE>/deployments/<DEPLOYMENT>" \
|
||||||
|
-H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" \
|
||||||
|
-H "Content-Type: application/strategic-merge-patch+json" \
|
||||||
|
-d '{"spec":{"template":{"spec":{"containers":[{"name":"<CONTAINER_NAME>","image":"myregistry/myapp:'"${DRONE_BUILD_NUMBER}"'"}]}}}}'
|
||||||
|
```
|
||||||
|
|
||||||
|
This is the API equivalent of `kubectl set image deployment/<name> <container>=<image>:<tag>`.
|
||||||
|
|
||||||
|
### 4. Required Drone secrets
|
||||||
|
|
||||||
|
Configure these in the Drone UI for the repository:
|
||||||
|
- `docker_username` — Docker Hub username
|
||||||
|
- `docker_password` — Docker Hub access token (PAT works)
|
||||||
|
|
||||||
|
No kubectl credentials needed — the pipeline uses the Drone pod's service account.
|
||||||
|
|
||||||
|
## Verification
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check Drone build passed
|
||||||
|
# In the Drone UI, verify all 3 steps (build, docker, deploy) are green
|
||||||
|
|
||||||
|
# Verify deployment updated
|
||||||
|
kubectl -n <namespace> get deployment <name> -o jsonpath='{.spec.template.spec.containers[0].image}'
|
||||||
|
# Should show: myregistry/myapp:<build-number>
|
||||||
|
|
||||||
|
# Verify pod is running new image
|
||||||
|
kubectl -n <namespace> get pods -o jsonpath='{.items[*].status.containerStatuses[*].image}'
|
||||||
|
```
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
Full `.drone.yml` for a Node.js app deployed to k8s:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
kind: pipeline
|
||||||
|
type: kubernetes
|
||||||
|
name: my-app
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
limit: 1
|
||||||
|
|
||||||
|
trigger:
|
||||||
|
branch:
|
||||||
|
- main
|
||||||
|
event:
|
||||||
|
- push
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: build
|
||||||
|
image: node:18-alpine
|
||||||
|
commands:
|
||||||
|
- npm ci
|
||||||
|
- npm run build
|
||||||
|
|
||||||
|
- name: docker
|
||||||
|
image: plugins/docker
|
||||||
|
settings:
|
||||||
|
repo: myuser/myapp
|
||||||
|
tags:
|
||||||
|
- latest
|
||||||
|
- "${DRONE_BUILD_NUMBER}"
|
||||||
|
username:
|
||||||
|
from_secret: docker_username
|
||||||
|
password:
|
||||||
|
from_secret: docker_password
|
||||||
|
|
||||||
|
- name: deploy
|
||||||
|
image: alpine
|
||||||
|
commands:
|
||||||
|
- apk add --no-cache curl
|
||||||
|
- |
|
||||||
|
curl -sfk -X PATCH \
|
||||||
|
"https://10.0.20.100:6443/apis/apps/v1/namespaces/myapp/deployments/myapp" \
|
||||||
|
-H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" \
|
||||||
|
-H "Content-Type: application/strategic-merge-patch+json" \
|
||||||
|
-d '{"spec":{"template":{"spec":{"containers":[{"name":"myapp","image":"myuser/myapp:'"${DRONE_BUILD_NUMBER}"'"}]}}}}'
|
||||||
|
```
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
- The k8s API host (`10.0.20.100:6443`) is cluster-specific — find it with `kubectl cluster-info`
|
||||||
|
- The `-k` flag on curl skips TLS verification for the k8s API (common for internal clusters with self-signed certs)
|
||||||
|
- The `-sf` flags make curl fail silently on HTTP errors and return non-zero exit code, which fails the pipeline step
|
||||||
|
- The container `name` in the PATCH must match the container name in the deployment spec
|
||||||
|
- RBAC: The Drone service account needs permissions to PATCH deployments in the target namespace
|
||||||
|
- See also: `kubernetes-latest-tag-image-pull` for why build-number tags are preferred over `:latest`
|
||||||
|
|
||||||
|
## References
|
||||||
|
- [Kubernetes API: Patch Deployment](https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/deployment-v1/#patch-replace-the-specified-deployment)
|
||||||
|
- [Drone Docker Plugin](https://plugins.drone.io/plugins/docker)
|
||||||
|
- [Drone Kubernetes Pipelines](https://docs.drone.io/pipeline/kubernetes/overview/)
|
||||||
Loading…
Add table
Add a link
Reference in a new issue