| name | kubernetes |
| description | Use ao gerar manifests Kubernetes, configuração ArgoCD e pipeline GitLab CI/CD para o projeto. Cobre estrutura Kustomize (base + overlays por ambiente), ApplicationSet do ArgoCD central multi-cluster, e .gitlab-ci.yml com modelo GitOps. Agnóstico de stack de aplicação. |
Kubernetes + ArgoCD + GitLab CI/CD
Padrões universais do projeto estão em CLAUDE.md. Esta skill cobre
apenas o que é específico da infraestrutura Kubernetes e do pipeline CI/CD.
Modelo adotado: GitOps com ArgoCD central
GitLab CI (pipeline)
├── lint → test → sonarqube → build → push imagem → Harbor
└── atualiza tag da imagem no repo Git (commit automático)
↓
ArgoCD central (detecta mudança no Git)
├── App dev → sincroniza no cluster dev
├── App staging → sincroniza no cluster staging
└── App prod → sincroniza no cluster prod (manual)
Importante: o pipeline CI/CD nunca roda kubectl apply diretamente.
Ele só atualiza a tag da imagem no arquivo deploy/k8s/overlays/<env>/image.yaml
via commit — o ArgoCD detecta a mudança e aplica no cluster correspondente.
Isso resolve o problema de rede: o runner não precisa alcançar o cluster,
o ArgoCD (dentro do cluster) é que puxa do Git.
Variáveis de ambiente obrigatórias
Configurar no GitLab: Settings → CI/CD → Variables.
REGISTRY_URL = registry.empresa.com
REGISTRY_USER = ci-bot
REGISTRY_TOKEN = <token>
ARGOCD_SERVER = argocd.empresa.com
ARGOCD_TOKEN = <token>
ENV_DEV = dev
ENV_STAGING = staging
ENV_PROD = prod
Adicionar ao .env.example do projeto (sem valores reais):
REGISTRY_URL=
REGISTRY_USER=
REGISTRY_TOKEN=
ARGOCD_SERVER=
ARGOCD_TOKEN=
ENV_DEV=dev
ENV_STAGING=staging
ENV_PROD=prod
Estrutura de pastas gerada
deploy/
├── k8s/
│ ├── base/ ← manifests genéricos, sem valores de ambiente
│ │ ├── deployment.yaml
│ │ ├── service.yaml
│ │ ├── ingress.yaml
│ │ ├── configmap.yaml
│ │ └── kustomization.yaml
│ └── overlays/
│ ├── dev/
│ │ ├── kustomization.yaml ← herda base, aplica patches dev
│ │ ├── image.yaml ← tag da imagem (atualizada pelo CI)
│ │ └── patches/
│ │ └── resources.yaml ← recursos menores para dev
│ ├── staging/
│ │ ├── kustomization.yaml
│ │ ├── image.yaml
│ │ └── patches/
│ └── prod/
│ ├── kustomization.yaml
│ ├── image.yaml
│ └── patches/
│ └── replicas.yaml ← mais réplicas em produção
├── argocd/
│ └── applicationset.yaml ← ApplicationSet multi-ambiente no ArgoCD central
└── .gitlab-ci.yml ← na raiz do projeto
base/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend
labels:
app: backend
spec:
replicas: 1
selector:
matchLabels:
app: backend
template:
metadata:
labels:
app: backend
spec:
containers:
- name: backend
image: backend:latest
ports:
- containerPort: 3001
envFrom:
- secretRef:
name: app-secrets
- configMapRef:
name: app-config
livenessProbe:
httpGet:
path: /healthz
port: 3001
initialDelaySeconds: 10
periodSeconds:
Probes: ajustar o path conforme a stack (Java usa /actuator/health/liveness
e /actuator/health/readiness). Ver CLAUDE.md seção "Observabilidade".
base/ingress.yaml (NGINX — parametrizado para Traefik no futuro)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: backend
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
rules:
- host: PLACEHOLDER_HOST
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: backend
port:
number: 3001
overlays/dev/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: ${ENV_DEV}-${PROJECT_NAME}
resources:
- ../../base
namePrefix: dev-
images:
- name: backend
newName: ${REGISTRY_URL}/${PROJECT_NAME}/backend
newTag: latest
patches:
- path: patches/resources.yaml
configMapGenerator:
- name: app-config
literals:
- ENV=development
- LOG_LEVEL=debug
storageClassName: ${STORAGE_CLASS_NAME:-default}
overlays/dev/patches/resources.yaml (recursos menores em dev)
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend
spec:
replicas: 1
template:
spec:
containers:
- name: backend
resources:
requests:
cpu: "50m"
memory: "64Mi"
limits:
cpu: "200m"
memory: "256Mi"
deploy/argocd/applicationset.yaml
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: ${PROJECT_NAME}
namespace: argocd
spec:
generators:
- list:
elements:
- env: dev
cluster: https://rancher-dev.empresa.com/k8s/clusters/c-xxxxx
namespace: dev-${PROJECT_NAME}
syncPolicy: automated
- env: staging
cluster: https://rancher-staging.empresa.com/k8s/clusters/c-yyyyy
namespace: staging-${PROJECT_NAME}
syncPolicy: automated
- env: prod
cluster: https://rancher-prod.empresa.com/k8s/clusters/c-zzzzz
namespace: prod-${PROJECT_NAME}
syncPolicy: none
template:
metadata:
name: "{{env}}-${PROJECT_NAME}"
spec:
project:
Substituir as URLs dos clusters com os valores reais do Rancher.
Ver URL do kubeconfig em: Rancher → Cluster → Kubeconfig → server:.
.gitlab-ci.yml
variables:
ENV_DEV: "dev"
ENV_STAGING: "staging"
ENV_PROD: "prod"
STORAGE_CLASS_NAME: "default"
PROJECT_NAME: "${CI_PROJECT_NAME}"
IMAGE_BACKEND: "${REGISTRY_URL}/${CI_PROJECT_NAME}/backend"
IMAGE_FRONTEND: "${REGISTRY_URL}/${CI_PROJECT_NAME}/frontend"
stages:
- lint
- quality
- test
- sonarqube
- build
- security
- push
- deploy-dev
- deploy-staging
- deploy-prod
lint-backend:
stage: lint
script:
- docker compose run --rm backend <golangci-lint run | flake8 |
[, , ]
[, , ]
[, ]
[, ]
[, , ]
[]
[, ]
[, ]
[, ]
[, ]
[, ]
[]
[]
[]
Secrets do Kubernetes
Criar os secrets antes do primeiro deploy (uma vez por cluster):
kubectl create secret generic app-secrets \
--from-literal=DATABASE_URL="postgres://..." \
--from-literal=REDIS_URL="redis://..." \
--namespace=dev-${PROJECT_NAME}
kubectl create secret docker-registry harbor-pull-secret \
--docker-server=${REGISTRY_URL} \
--docker-username=${REGISTRY_USER} \
--docker-password=${REGISTRY_TOKEN} \
--namespace=dev-${PROJECT_NAME}
Se o Kubernetes já tem credencial global para o Harbor (como você confirmou),
o imagePullSecret no Deployment não é necessário.
Migração NGINX → Traefik
Quando migrar o Ingress controller, apenas altere a anotação em base/ingress.yaml:
kubernetes.io/ingress.class: "nginx"
kubernetes.io/ingress.class: "traefik"
E remova as anotações específicas do NGINX. O Kustomize propaga para todos os overlays automaticamente.
Checklist de entrega