Workflow Examples
Overview
This page provides complete, production-ready workflow examples that you can use as templates for your own deployment pipelines.
Basic Workflows
Simple Deployment
A basic deployment workflow for Kubernetes applications:
apiVersion: v1kind: Workflowmetadata: name: simple-deploy description: Basic application deploymentspec: env: APP_NAME: my-app NAMESPACE: default
jobs: - name: deploy description: Deploy application steps: - name: apply-manifests command: kubectl apply -f manifests/
- name: wait-for-rollout command: kubectl rollout status deployment/${APP_NAME} -n ${NAMESPACE}
- name: verify command: kubectl get pods -n ${NAMESPACE} -l app=${APP_NAME}Configuration Update
Update application configuration:
apiVersion: v1kind: Workflowmetadata: name: update-config description: Update application configurationspec: env: APP_NAME: my-app NAMESPACE: default
jobs: - name: update steps: - name: update-configmap command: kubectl create configmap ${APP_NAME}-config --from-file=config/ -n ${NAMESPACE} --dry-run=client -o yaml | kubectl apply -f -
- name: restart-deployment command: kubectl rollout restart deployment/${APP_NAME} -n ${NAMESPACE}
- name: wait command: kubectl rollout status deployment/${APP_NAME} -n ${NAMESPACE}Docker Workflows
Build and Push
Build Docker image with validation:
apiVersion: v1kind: Workflowmetadata: name: docker-build description: Build and push Docker imagesspec: requirements: tools: - name: docker version: "20.10" description: Docker CLI for building images secrets: - name: DOCKER_TOKEN provider: docker required: true description: Docker Hub authentication token
env: IMAGE_NAME: my-app IMAGE_TAG: latest REGISTRY: docker.io REGISTRY_USER: myuser
jobs: - name: build description: Build Docker image steps: - name: docker-build script: | docker build \ -t ${REGISTRY}/${REGISTRY_USER}/${IMAGE_NAME}:${IMAGE_TAG} \ -t ${REGISTRY}/${REGISTRY_USER}/${IMAGE_NAME}:$(git rev-parse --short HEAD) \ . echo "✅ Build complete"
- name: push description: Push to registry dependsOn: [build] steps: - name: docker-login script: | echo "$DOCKER_TOKEN" | docker login ${REGISTRY} -u ${REGISTRY_USER} --password-stdin
- name: docker-push script: | docker push ${REGISTRY}/${REGISTRY_USER}/${IMAGE_NAME}:${IMAGE_TAG} docker push ${REGISTRY}/${REGISTRY_USER}/${IMAGE_NAME}:$(git rev-parse --short HEAD) echo "✅ Push complete"Multi-Architecture Build
Build for multiple architectures:
apiVersion: v1kind: Workflowmetadata: name: docker-multi-arch description: Build multi-architecture Docker imagesspec: requirements: tools: - name: docker version: "20.10" - name: buildx description: Docker Buildx for multi-platform builds secrets: - name: DOCKER_TOKEN provider: docker required: true
env: IMAGE_NAME: my-app VERSION: "1.0.0" PLATFORMS: "linux/amd64,linux/arm64,linux/arm/v7"
jobs: - name: setup steps: - name: create-builder command: docker buildx create --name multiarch --use
- name: build-push dependsOn: [setup] steps: - name: login script: echo "$DOCKER_TOKEN" | docker login -u ${DOCKER_USER} --password-stdin
- name: build-multi-platform script: | docker buildx build \ --platform ${PLATFORMS} \ --tag ${IMAGE_NAME}:${VERSION} \ --tag ${IMAGE_NAME}:latest \ --push \ .Kubernetes Deployment Workflows
Complete Deployment Pipeline
Full deployment with pre-checks and post-validation:
apiVersion: v1kind: Workflowmetadata: name: deployment-pipeline description: Complete deployment pipelinespec: requirements: tools: - name: kubectl version: "1.28" - name: helm version: "3.12"
env: APP_NAME: my-application NAMESPACE: production CHART_PATH: ./charts/my-app
jobs: - name: pre-checks description: Pre-deployment validation steps: - name: check-cluster command: kubectl cluster-info
- name: check-namespace script: | if ! kubectl get namespace ${NAMESPACE}; then kubectl create namespace ${NAMESPACE} fi
- name: lint-chart command: helm lint ${CHART_PATH}
- name: deploy description: Deploy application dependsOn: [pre-checks] steps: - name: helm-upgrade command: | helm upgrade --install ${APP_NAME} ${CHART_PATH} \ --namespace ${NAMESPACE} \ --wait \ --timeout 10m
- name: wait-for-pods command: kubectl wait --for=condition=ready pod -l app=${APP_NAME} -n ${NAMESPACE} --timeout=300s
- name: post-checks description: Post-deployment validation dependsOn: [deploy] steps: - name: check-pods command: kubectl get pods -n ${NAMESPACE} -l app=${APP_NAME}
- name: check-services command: kubectl get services -n ${NAMESPACE} -l app=${APP_NAME}
- name: smoke-test script: | SERVICE_URL=$(kubectl get service ${APP_NAME} -n ${NAMESPACE} -o jsonpath='{.status.loadBalancer.ingress[0].ip}') curl -f http://${SERVICE_URL}/health || exit 1 echo "✅ Smoke test passed"Blue-Green Deployment
Zero-downtime deployment pattern:
apiVersion: v1kind: Workflowmetadata: name: blue-green-deploy description: Blue-green deployment strategyspec: env: APP_NAME: my-app NAMESPACE: production NEW_VERSION: "v2"
jobs: - name: deploy-green description: Deploy new version (green) steps: - name: create-green-deployment script: | kubectl apply -f - <<EOF apiVersion: apps/v1 kind: Deployment metadata: name: ${APP_NAME}-green namespace: ${NAMESPACE} spec: replicas: 3 selector: matchLabels: app: ${APP_NAME} version: ${NEW_VERSION} slot: green template: metadata: labels: app: ${APP_NAME} version: ${NEW_VERSION} slot: green spec: containers: - name: app image: myapp:${NEW_VERSION} EOF
- name: wait-green-ready command: kubectl wait --for=condition=available deployment/${APP_NAME}-green -n ${NAMESPACE} --timeout=5m
- name: test-green description: Test green deployment dependsOn: [deploy-green] steps: - name: smoke-test script: | # Test green deployment through temporary service kubectl run test-${NEW_VERSION} --image=curlimages/curl:latest --rm -i --restart=Never -- \ curl -f http://${APP_NAME}-green:8080/health
- name: switch-traffic description: Switch traffic to green dependsOn: [test-green] steps: - name: update-service script: | kubectl patch service ${APP_NAME} -n ${NAMESPACE} -p '{"spec":{"selector":{"slot":"green"}}}'
- name: verify-traffic command: kubectl describe service ${APP_NAME} -n ${NAMESPACE}
- name: cleanup-blue description: Remove old deployment dependsOn: [switch-traffic] steps: - name: scale-down-blue command: kubectl scale deployment/${APP_NAME}-blue --replicas=0 -n ${NAMESPACE}
- name: delete-blue command: kubectl delete deployment/${APP_NAME}-blue -n ${NAMESPACE}CI/CD Workflows
GitOps Deployment
Triggered by Git commits:
apiVersion: v1kind: Workflowmetadata: name: gitops-deploy description: GitOps continuous deploymentspec: requirements: tools: - name: git - name: kubectl version: "1.28" secrets: - name: GITHUB_TOKEN provider: github required: false
env: REPO_URL: https://github.com/company/k8s-manifests.git BRANCH: main MANIFEST_DIR: manifests/production
jobs: - name: fetch-manifests description: Fetch latest manifests from Git steps: - name: clone-repo script: | rm -rf /tmp/k8s-manifests git clone ${REPO_URL} /tmp/k8s-manifests cd /tmp/k8s-manifests git checkout ${BRANCH}
- name: deploy description: Apply manifests dependsOn: [fetch-manifests] steps: - name: apply-all command: kubectl apply -f /tmp/k8s-manifests/${MANIFEST_DIR} --recursive
- name: wait-rollout script: | for deployment in $(kubectl get deployments -n production -o name); do kubectl rollout status $deployment -n production doneTest and Deploy
Run tests before deployment:
apiVersion: v1kind: Workflowmetadata: name: test-and-deploy description: Test before deployingspec: requirements: tools: - name: go version: "1.21" - name: kubectl version: "1.28"
env: APP_NAME: my-service NAMESPACE: production
jobs: - name: test description: Run tests steps: - name: unit-tests command: go test ./... -v
- name: integration-tests command: go test ./tests/integration -v
- name: build command: go build -o app .
- name: deploy description: Deploy if tests pass dependsOn: [test] steps: - name: update-image script: | kubectl set image deployment/${APP_NAME} \ ${APP_NAME}=myregistry/myapp:$(git rev-parse --short HEAD) \ -n ${NAMESPACE}
- name: wait-rollout command: kubectl rollout status deployment/${APP_NAME} -n ${NAMESPACE}Infrastructure Workflows
Database Backup
Regular database backup:
apiVersion: v1kind: Workflowmetadata: name: db-backup description: Backup databasespec: requirements: tools: - name: kubectl - name: aws description: AWS CLI for S3 upload secrets: - name: AWS_ACCESS_KEY_ID provider: aws required: true - name: AWS_SECRET_ACCESS_KEY provider: aws required: true
env: DB_POD: postgres-0 DB_NAME: myapp NAMESPACE: database S3_BUCKET: my-backups BACKUP_PREFIX: postgres
jobs: - name: backup steps: - name: create-backup script: | TIMESTAMP=$(date +%Y%m%d-%H%M%S) kubectl exec ${DB_POD} -n ${NAMESPACE} -- \ pg_dump -U postgres ${DB_NAME} > /tmp/backup-${TIMESTAMP}.sql
- name: upload-s3 script: | TIMESTAMP=$(date +%Y%m%d-%H%M%S) aws s3 cp /tmp/backup-${TIMESTAMP}.sql \ s3://${S3_BUCKET}/${BACKUP_PREFIX}/backup-${TIMESTAMP}.sql
- name: cleanup-old script: | # Keep last 7 days find /tmp -name "backup-*.sql" -mtime +7 -deleteCertificate Renewal
Renew SSL certificates:
apiVersion: v1kind: Workflowmetadata: name: cert-renewal description: Renew SSL certificatesspec: requirements: tools: - name: kubectl - name: certbot description: Let's Encrypt certificate tool
env: DOMAIN: example.com EMAIL: admin@example.com SECRET_NAME: tls-secret NAMESPACE: default
jobs: - name: renew steps: - name: certbot-renew script: | certbot renew --non-interactive --agree-tos -m ${EMAIL}
- name: update-secret script: | kubectl create secret tls ${SECRET_NAME} \ --cert=/etc/letsencrypt/live/${DOMAIN}/fullchain.pem \ --key=/etc/letsencrypt/live/${DOMAIN}/privkey.pem \ --namespace=${NAMESPACE} \ --dry-run=client -o yaml | kubectl apply -f -
- name: restart-ingress command: kubectl rollout restart deployment nginx-ingress -n ingress-nginxMonitoring and Observability
Deploy Monitoring Stack
apiVersion: v1kind: Workflowmetadata: name: setup-monitoring description: Deploy monitoring stackspec: requirements: tools: - name: helm version: "3.12" - name: kubectl secrets: - name: DATADOG_API_KEY provider: datadog required: false
env: NAMESPACE: monitoring
jobs: - name: prometheus description: Install Prometheus steps: - name: add-repo command: helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
- name: update-repos command: helm repo update
- name: install-prometheus command: | helm upgrade --install prometheus prometheus-community/kube-prometheus-stack \ --namespace ${NAMESPACE} \ --create-namespace \ --wait
- name: grafana description: Configure Grafana dependsOn: [prometheus] steps: - name: get-password script: | kubectl get secret -n ${NAMESPACE} prometheus-grafana \ -o jsonpath="{.data.admin-password}" | base64 --decode echo ""
- name: port-forward-info script: | echo "To access Grafana:" echo "kubectl port-forward -n ${NAMESPACE} svc/prometheus-grafana 3000:80"