🦊 App → GKE via GitLab CI
Build, scan, push to registry, deploy to GKE — GitLab-native pipeline with prod-delta hardening. · ~45 min
Reviewed: ·Tested on: Kubernetes 1.29, Terraform 1.8, Ubuntu 22.04
If you're on Kubernetes 1.27 or older
- Ingress: networking.k8s.io/v1 is required — v1beta1 removed in 1.22+
- Pod Security: PodSecurityPolicy removed in 1.25 — use Pod Security Admission (PSA) labels
- HPA v2 autoscaling/v2 is stable — check API version in manifests
If you're on Kubernetes 1.28
- Sidecar containers (1.29+) change init-container ordering — review sidecar docs before upgrade
- Verify metrics-server and HPA after control plane bump
If you're on Terraform 1.7 or older
- S3 native locking (use_lockfile) differs from DynamoDB — don't mix backends mid-migration
- Provider version constraints: run terraform init -upgrade after bump
- terraform test (1.6+) replaces some external test harness patterns
1. Dockerfile + K8s manifests in repo
App code, Dockerfile, and k8s/ on default branch.
2. Add .gitlab-ci.yml
stages:
- build
- scan
- deploy
build:
stage: build
image: docker:24
services:
- docker:24-dind
script:
- docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
scan:
stage: scan
image: aquasec/trivy:latest
script:
- trivy image --exit-code 1 --severity CRITICAL $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
deploy:
stage: deploy
image: bitnami/kubectl:latest
script:
- kubectl set image deploy/myapp app=$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA -n apps
- kubectl rollout status deploy/myapp -n apps
only:
- main3. CI variables (no static cloud keys in prod)
Use GCP Workload Identity or GitLab OIDC. Masked + protected vars on main.
4. Prod delta before merge
OIDC auth, branch protection, scan gate — compare minimal vs production.
5. Verify + rollback
kubectl rollout status deploy/myapp -n apps kubectl get ingress -n apps curl -I https://app.example.com/health # rollback: kubectl rollout undo deploy/myapp -n apps