Entendi. Vou criar um guia completo e detalhado para manifestos YAML no K3s, focando em cada componente e suas configurações. Vou estruturar isso de forma clara e didática.
apiVersion: apps/v1
kind: Deployment
metadata:
name: nome-do-deployment
spec:
replicas: 3
selector:
matchLabels:
app: nome-do-app
template:
metadata:
labels:
app: nome-do-app
spec:
containers:
- name: nome-container
image: imagem:tag| Campo | Descrição | Obrigatório | Exemplo |
|---|---|---|---|
| name | Nome do deployment | Sim | meu-app |
| namespace | Namespace onde será criado | Não | default |
| labels | Etiquetas para organização | Não | app: meu-app |
| Campo | Descrição | Obrigatório | Opções |
|---|---|---|---|
| replicas | Número de pods | Sim | Número inteiro (1-n) |
| selector | Seletor de pods | Sim | matchLabels ou matchExpressions |
| strategy | Estratégia de atualização | Não | RollingUpdate/Recreate |
apiVersion: apps/v1
kind: Deployment
metadata:
name: minha-aplicacao # Nome único do deployment
namespace: producao # Namespace onde será criado
labels: # Labels para organização
app: minha-aplicacao
ambiente: producao
spec:
replicas: 3 # Número de réplicas desejadas
strategy:
type: RollingUpdate # Tipo de estratégia de atualização
rollingUpdate:
maxSurge: 1 # Máximo de pods extras durante atualização
maxUnavailable: 0 # Mínimo de pods indisponíveis
selector:
matchLabels:
app: minha-aplicacao # Deve corresponder aos labels do template
template:
metadata:
labels:
app: minha-aplicacao # Labels dos pods
spec:
containers:
- name: app-container # Nome do container
image: nginx:1.19 # Imagem do container
ports:
- containerPort: 80 # Porta exposta pelo container
resources: # Limites de recursos
requests:
cpu: "100m"
memory: "128Mi"
limits:
cpu: "200m"
memory: "256Mi"
livenessProbe: # Verificação de saúde
httpGet:
path: /health
port: 80
initialDelaySeconds: 30
periodSeconds: 10apiVersion: v1
kind: Service
metadata:
name: nome-do-servico
spec:
type: ClusterIP
selector:
app: nome-do-app
ports:
- port: 80
targetPort: 8080| Tipo | Uso | Descrição |
|---|---|---|
| ClusterIP | Interno | IP interno ao cluster |
| NodePort | Externo | Expõe porta no node |
| LoadBalancer | Externo | Usa load balancer |
| ExternalName | DNS | Alias DNS |
| Campo | Descrição | Obrigatório | Exemplo |
|---|---|---|---|
| port | Porta do serviço | Sim | 80 |
| targetPort | Porta do pod | Não | 8080 |
| nodePort | Porta do node | Não | 30000 |
apiVersion: v1
kind: Service
metadata:
name: meu-servico # Nome do serviço
namespace: producao # Namespace
labels:
app: minha-aplicacao
spec:
type: LoadBalancer # Tipo do serviço
selector: # Seletor para pods
app: minha-aplicacao
ports:
- name: http # Nome da porta (opcional)
port: 80 # Porta do serviço
targetPort: 8080 # Porta do container
protocol: TCP # Protocolo
sessionAffinity: None # Afinidade de sessãoapiVersion: v1
kind: ConfigMap
metadata:
name: nome-do-configmap
data:
chave1: valor1
chave2: valor2- Aceita pares chave-valor
- Valores podem ser strings ou blocos de texto
- Tamanho máximo: 1MB
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
namespace: producao
data:
# Configurações simples
API_URL: "http://api.exemplo.com"
TIMEOUT: "30"
# Arquivo de configuração
config.yaml: |
server:
port: 8080
timeout: 30
database:
host: localhost
port: 5432apiVersion: v1
kind: Secret
metadata:
name: nome-do-secret
type: Opaque
data:
username: <base64>
password: <base64>| Tipo | Uso | Descrição |
|---|---|---|
| Opaque | Geral | Dados arbitrários (padrão) |
| kubernetes.io/tls | TLS | Certificados TLS |
| kubernetes.io/dockerconfigjson | Docker | Credenciais de registro |
| kubernetes.io/service-account-token | Service Account | Token de autenticação |
data:
# Deve ser codificado em base64
username: YWRtaW4= # echo -n 'admin' | base64
password: MWYyZDFlMmU2N2Rm # echo -n 'senha' | base64
stringData:
# Pode ser texto puro (será convertido automaticamente)
config.yaml: |
api_key: "123456"apiVersion: v1
kind: Secret
metadata:
name: app-secrets
namespace: producao
type: Opaque
data:
# Credenciais de banco de dados
DB_USER: YWRtaW4=
DB_PASS: cGFzc3dvcmQxMjM=
stringData:
# Arquivo de configuração com credenciais
credentials.json: |
{
"apiKey": "chave-secreta-123",
"authToken": "token-456"
}apiVersion: v1
kind: PersistentVolume
metadata:
name: meu-pv
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: local-storage
local:
path: /mnt/data
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- worker-node1apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: meu-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
storageClassName: local-storage| Modo | Descrição |
|---|---|
| ReadWriteOnce (RWO) | Montado como leitura-escrita por um único nó |
| ReadOnlyMany (ROX) | Montado como somente leitura por múltiplos nós |
| ReadWriteMany (RWX) | Montado como leitura-escrita por múltiplos nós |
| Política | Descrição |
|---|---|
| Retain | Mantém o PV e seus dados |
| Delete | Remove o PV e seus dados |
| Recycle | Limpa os dados mas mantém o PV |
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: nome-da-policy
spec:
podSelector:
matchLabels:
app: minha-app
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector:
matchLabels:
role: frontend
egress:
- to:
- podSelector:
matchLabels:
role: databaseapiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: api-network-policy
namespace: producao
spec:
podSelector: # Seleciona pods que a política se aplica
matchLabels:
app: api-service
policyTypes: # Tipos de regras
- Ingress
- Egress
ingress: # Regras de entrada
- from:
- namespaceSelector: # Permite tráfego do namespace frontend
matchLabels:
name: frontend
- podSelector: # E de pods com label role: frontend
matchLabels:
role: frontend
ports: # Nas portas especificadas
- protocol: TCP
port: 8080
egress: # Regras de saída
- to:
- podSelector: # Permite tráfego para pods database
matchLabels:
role: database
ports:
- protocol: TCP
port: 5432apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: nome-do-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: nome-do-deployment
minReplicas: 1
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 80apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: api-hpa
namespace: producao
spec:
scaleTargetRef: # Referência ao recurso a ser escalado
apiVersion: apps/v1
kind: Deployment
name: api-deployment
minReplicas: 2 # Mínimo de réplicas
maxReplicas: 10 # Máximo de réplicas
metrics: # Métricas para escalonamento
- type: Resource
resource:
name: cpu # Baseado em CPU
target:
type: Utilization
averageUtilization: 80 # Escala quando CPU > 80%
- type: Resource
resource:
name: memory # Baseado em Memória
target:
type: Utilization
averageUtilization: 80 # Escala quando Memória > 80%
behavior: # Comportamento de escalonamento
scaleUp:
stabilizationWindowSeconds: 60 # Janela de estabilização
policies:
- type: Percent
value: 100 # Dobra o número de pods
periodSeconds: 15
scaleDown:
stabilizationWindowSeconds: 300 # Espera 5 min antes de reduzir
policies:
- type: Percent
value: 50 # Reduz 50% dos pods
periodSeconds: 60apiVersion: apps/v1
kind: StatefulSet
metadata:
name: nome-do-statefulset
spec:
serviceName: nome-do-servico-headless
replicas: 3
selector:
matchLabels:
app: nome-do-app
template:
metadata:
labels:
app: nome-do-app
spec:
containers:
- name: nome-container
image: imagem:tagapiVersion: apps/v1
kind: StatefulSet
metadata:
name: postgres-cluster
namespace: database
spec:
serviceName: postgres-headless # Serviço Headless associado
replicas: 3 # Número de réplicas
podManagementPolicy: OrderedReady # Política de gerenciamento
updateStrategy:
type: RollingUpdate # Estratégia de atualização
selector:
matchLabels:
app: postgres
template:
metadata:
labels:
app: postgres
spec:
terminationGracePeriodSeconds: 10
containers:
- name: postgres
image: postgres:14
ports:
- containerPort: 5432
env:
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: postgres-secrets
key: password
volumeMounts:
- name: data
mountPath: /var/lib/postgresql/data
volumeClaimTemplates: # Template para PVCs
- metadata:
name: data
spec:
accessModes: [ "ReadWriteOnce" ]
storageClassName: "standard"
resources:
requests:
storage: 10GiapiVersion: apps/v1
kind: DaemonSet
metadata:
name: nome-do-daemonset
spec:
selector:
matchLabels:
app: nome-do-app
template:
metadata:
labels:
app: nome-do-app
spec:
containers:
- name: nome-container
image: imagem:tagapiVersion: apps/v1
kind: DaemonSet
metadata:
name: fluentd-collector
namespace: monitoring
spec:
selector:
matchLabels:
app: fluentd
template:
metadata:
labels:
app: fluentd
spec:
tolerations: # Tolerações para rodar em todos os nós
- key: node-role.kubernetes.io/master
effect: NoSchedule
containers:
- name: fluentd
image: fluentd:v1.14
resources:
limits:
memory: 200Mi
requests:
cpu: 100m
memory: 200Mi
volumeMounts:
- name: varlog
mountPath: /var/log
- name: varlibdockercontainers
mountPath: /var/lib/docker/containers
readOnly: true
volumes:
- name: varlog
hostPath:
path: /var/log
- name: varlibdockercontainers
hostPath:
path: /var/lib/docker/containersapiVersion: batch/v1
kind: Job
metadata:
name: processo-batch
spec:
completions: 3 # Número total de conclusões bem-sucedidas
parallelism: 2 # Número de pods que podem rodar em paralelo
backoffLimit: 4 # Número de tentativas antes de falhar
activeDeadlineSeconds: 100 # Tempo máximo de execução
template:
spec:
containers:
- name: job-task
image: python:3.9
command: ["python", "-c", "print('Executando tarefa...')"]
restartPolicy: NeverapiVersion: batch/v1
kind: CronJob
metadata:
name: backup-database
spec:
schedule: "0 2 * * *" # Executa às 2h da manhã todos os dias
concurrencyPolicy: Forbid # Não permite execuções concorrentes
successfulJobsHistoryLimit: 3
failedJobsHistoryLimit: 1
jobTemplate:
spec:
template:
spec:
containers:
- name: backup
image: backup-tool:1.0
command:
- /scripts/backup.sh
env:
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-secrets
key: password
restartPolicy: OnFailureapiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nome-do-ingress
spec:
ingressClassName: nginx
rules:
- host: app.exemplo.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: nome-do-servico
port:
number: 80apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: web-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
ingressClassName: nginx
tls: # Configuração TLS
- hosts:
- app.exemplo.com
secretName: app-tls-secret
rules:
- host: app.exemplo.com # Nome do host
http:
paths:
- path: /api # Caminho da API
pathType: Prefix
backend:
service:
name: api-service
port:
number: 8080
- path: / # Frontend
pathType: Prefix
backend:
service:
name: frontend-service
port:
number: 80apiVersion: v1
kind: ServiceAccount
metadata:
name: app-service-account
namespace: producao
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: app-role
namespace: producao
rules:
- apiGroups: [""]
resources: ["pods", "services"]
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: app-role-binding
namespace: producao
subjects:
- kind: ServiceAccount
name: app-service-account
namespace: producao
roleRef:
kind: Role
name: app-role
apiGroup: rbac.authorization.k8s.iok3s-project/
├── environments/
│ ├── development/
│ │ ├── kustomization.yaml
│ │ └── env-specific-configs/
│ ├── staging/
│ └── production/
├── base/
│ ├── deployments/
│ ├── services/
│ ├── configs/
│ └── secrets/
├── charts/ # Helm charts personalizados
└── manifests/
├── monitoring/
├── logging/
└── security/
# base/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deployments/web-app.yaml
- services/web-service.yaml
- configs/app-config.yaml
# environments/production/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
bases:
- ../../base
patchesStrategicMerge:
- patches/increase-replicas.yaml
namePrefix: prod-
namespace: productionClaro! Vou explicar detalhadamente os Padrões DevOps Comuns e suas melhores práticas no K3s.
Este é um padrão de implantação que reduz o tempo de inatividade e risco. Funciona mantendo duas versões idênticas do ambiente:
- Blue: Versão atual em produção
- Green: Nova versão a ser implantada
# Versão Blue (Atual)
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-blue
spec:
replicas: 3
template:
metadata:
labels:
app: myapp
version: blue
spec:
containers:
- name: app
image: myapp:1.0# Versão Green (Nova)
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-green
spec:
replicas: 3
template:
metadata:
labels:
app: myapp
version: green
spec:
containers:
- name: app
image: myapp:1.1# blue-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-blue
spec:
replicas: 3
template:
metadata:
labels:
app: myapp
version: blue
spec:
containers:
- name: app
image: myapp:1.0
---
# green-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-green
spec:
replicas: 3
template:
metadata:
labels:
app: myapp
version: green
spec:
containers:
- name: app
image: myapp:1.1
---
# service-switcher.yaml
apiVersion: v1
kind: Service
metadata:
name: app-service
spec:
selector:
app: myapp
version: blue # Alternar entre blue e green
ports:
- port: 80Como funciona:
- Ambiente Blue está em produção
- Deploy da nova versão no ambiente Green
- Testes no ambiente Green
- Troca do tráfego de Blue para Green através do Service
- Se houver problemas, volta rapidamente para Blue
Vantagens:
- Zero downtime
- Rollback rápido
- Testes em ambiente idêntico ao de produção
Padrão que libera uma nova versão gradualmente para um subconjunto de usuários. É como um "teste em produção" controlado.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: canary-ingress
annotations:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-weight: "20" # 20% do tráfego
spec:
rules:
- host: app.exemplo.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: app-canary
port:
number: 80apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: canary-ingress
annotations:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-weight: "20"
spec:
rules:
- host: app.exemplo.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: app-canary
port:
number: 80Como funciona:
- Deploy da nova versão (canary)
- Roteamento de pequena % do tráfego para nova versão
- Monitoramento de métricas e erros
- Aumento gradual do tráfego se tudo OK
- Rollback fácil se problemas detectados
Vantagens:
- Risco reduzido
- Teste real com usuários
- Detecção precoce de problemas
Padrão mais comum, onde pods são atualizados gradualmente, um por um.
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-deployment
spec:
replicas: 4
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1 # Quantos pods extras podem ser criados
maxUnavailable: 0 # Quantos pods podem ficar indisponíveis
template:
spec:
containers:
- name: app
image: myapp:1.1Como funciona:
- Criação de novo pod com nova versão
- Espera pod ficar healthy
- Remoção de pod antigo
- Repete até todos estarem atualizados
Vantagens:
- Simples de implementar
- Sem downtime
- Controle sobre a velocidade da atualização
Padrão que permite habilitar/desabilitar funcionalidades em runtime.
apiVersion: v1
kind: ConfigMap
metadata:
name: feature-flags
data:
features.yaml: |
features:
newUI: true
beta-feature: false
dark-mode: trueComo funciona:
- Definição de flags em ConfigMap
- Aplicação lê configuração
- Features ativadas/desativadas sem deploy
Vantagens:
- Controle fino de funcionalidades
- Testes A/B facilitados
- Rollout gradual de features
Padrão que previne falhas em cascata em arquiteturas distribuídas.
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: circuit-breaker
spec:
host: my-service
trafficPolicy:
outlierDetection:
consecutiveErrors: 5
interval: 30s
baseEjectionTime: 30sComo funciona:
- Monitoramento de erros
- Ao atingir limite, "abre" circuito
- Rejeita requisições por tempo determinado
- Tenta "fechar" circuito após período
Vantagens:
- Previne sobrecarga
- Falhas isoladas
- Auto-recuperação
-
Monitoramento é Crucial
- Implemente métricas detalhadas
- Use dashboards para visualização
- Configure alertas
-
Automação
- Use CI/CD pipelines
- Automatize testes
- Automatize rollbacks
-
Documentação
- Mantenha runbooks atualizados
- Documente procedimentos de rollback
- Registre decisões arquiteturais
-
Segurança
- Implemente RBAC
- Use secrets management
- Faça scan de vulnerabilidades
-
Observabilidade
- Logs centralizados
- Tracing distribuído
- Métricas de negócio
Estes padrões DevOps são fundamentais para operações modernas em K3s e podem ser combinados conforme necessidade. A escolha do padrão depende de:
- Requisitos de negócio
- Complexidade aceitável
- Recursos disponíveis
- SLAs necessários
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: app-monitor
namespace: monitoring
spec:
selector:
matchLabels:
app: minha-aplicacao
endpoints:
- port: metrics
interval: 15s
path: /metricsapiVersion: v1
kind: ConfigMap
metadata:
name: app-dashboard
namespace: monitoring
labels:
grafana_dashboard: "true"
data:
dashboard.json: |
{
"dashboard": {
"title": "App Dashboard",
"panels": [
// ... configuração dos painéis
]
}
}apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
spec:
podSelector: {}
policyTypes:
- Ingress
- EgressapiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
name: restricted
spec:
privileged: false
seLinux:
rule: RunAsAny
runAsUser:
rule: MustRunAsNonRoot
fsGroup:
rule: RunAsAny
volumes:
- 'configMap'
- 'emptyDir'
- 'projected'
- 'secret'
- 'downwardAPI'
- 'persistentVolumeClaim'apiVersion: apps/v1
kind: Deployment
metadata:
name: ha-app
spec:
template:
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- ha-app
topologyKey: "kubernetes.io/hostname"apiVersion: apps/v1
kind: Deployment
metadata:
name: resilient-app
spec:
template:
spec:
containers:
- name: app
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
startupProbe:
httpGet:
path: /startup
port: 8080
failureThreshold: 30
periodSeconds: 10apiVersion: v1
kind: ResourceQuota
metadata:
name: compute-quota
namespace: team-a
spec:
hard:
requests.cpu: "4"
requests.memory: 8Gi
limits.cpu: "8"
limits.memory: 16GiapiVersion: v1
kind: LimitRange
metadata:
name: resource-limits
spec:
limits:
- default:
memory: 512Mi
cpu: 500m
defaultRequest:
memory: 256Mi
cpu: 200m
type: ContainerapiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
config.yaml: |
environments:
development:
logLevel: DEBUG
features:
featureA: true
featureB: true
production:
logLevel: INFO
features:
featureA: true
featureB: falseapiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: app-secrets
spec:
refreshInterval: 1h
secretStoreRef:
name: vault-backend
kind: ClusterSecretStore
target:
name: app-secrets
data:
- secretKey: APP_SECRET
remoteRef:
key: secret/data/application
property: app-secretEstes padrões e configurações adicionais fornecem uma base sólida para implementações em produção, garantindo:
- Alta disponibilidade
- Segurança
- Escalabilidade
- Observabilidade
- Gerenciamento eficiente de recursos
- Facilidade de manutenção