<p><strong>Meta Description:</strong> Aprenda a testar aplicações em Kubernetes: Helm, deployments, services, configmaps e como integrar testes ao ciclo de deploy em K8s.</p>

<hr>
<h2>Kubernetes para QA</h2>

<h3>Por Que Kubernetes?</h3>

<ul><li><strong>Isolamento</strong> - Cada ambiente isolado</li><ol><li><strong>Reproducibilidade</strong> - Ambientes idênticos</li>
<li><strong>Escalabilidade</strong> - Teste com múltiplas réplicas</li>
<li><strong>Orquestração</strong> - Deploys atômicos</li></ol></ul>

<hr>
<h2>Recursos Kubernetes</h2>

<h3>Pod</h3>

<pre><code># pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: api-test-pod
  labels:
    app: api
    env: test
spec:
  containers:
  - name: api
    image: api:latest
    ports:
    - containerPort: 8080
    env:
    - name: DATABASE_URL
      valueFrom:
        secretKeyRef:
          name: api-secrets
          key: database-url
    resources:
      requests:
        memory: "256Mi"
        cpu: "250m"
      limits:
        memory: "512Mi"
        cpu: "500m"
    readinessProbe:
      httpGet:
        path: /health
        port: 8080
      initialDelaySeconds: 5
      periodSeconds: 10
    livenessProbe:
      httpGet:
        path: /health
        port: 8080
      initialDelaySeconds: 15
      periodSeconds: 20
</code></pre>

<h3>Deployment</h3>

<pre><code># deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: api-deployment
spec:
  replicas: 3
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
  selector:
    matchLabels:
      app: api
  template:
    metadata:
      labels:
        app: api
    spec:
      containers:
      - name: api
        image: api:v1.0.0
        ports:
        - containerPort: 8080
        env:
        - name: ENV
          value: "production"
        livenessProbe:
          httpGet:
            path: /health
            port: 8080
        readinessProbe:
          httpGet:
            path: /ready
            port: 8080
</code></pre>

<h3>Service</h3>

<pre><code># service.yaml
apiVersion: v1
kind: Service
metadata:
  name: api-service
spec:
  type: ClusterIP
  selector:
    app: api
  ports:
  - port: 80
    targetPort: 8080
    name: http
</code></pre>

<hr>
<h2>Helm - Gerenciamento de Charts</h2>

<h3>Estrutura</h3>

<pre><code>myapp/
├── Chart.yaml
├── values.yaml
├── charts/
├── templates/
│   ├── deployment.yaml
│   ├── service.yaml
│   ├── ingress.yaml
│   ├── _helpers.tpl
│   └── tests/
│       └── test-connection.yaml
└── README.md
</code></pre>

<h3>Chart.yaml</h3>

<pre><code># Chart.yaml
apiVersion: v2
name: myapp
description: A Helm chart for MyApp
type: application
version: 1.0.0
appVersion: "1.0.0"
keywords:
  - web
  - api
home: https://myapp.com
maintainers:
  - name: DevOps Team
    email: devops@myapp.com
dependencies:
  - name: postgresql
    version: "12.x"
    repository: "https://charts.bitnami.com/bitnami"
    condition: postgresql.enabled
</code></pre>

<h3>values.yaml</h3>

<pre><code># values.yaml
replicaCount: 3

<p>image:<br>  repository: myapp/api<br>  tag: latest<br>  pullPolicy: IfNotPresent</p>

<p>service:<br>  type: ClusterIP<br>  port: 80</p>

<p>ingress:<br>  enabled: true<br>  className: "nginx"<br>  annotations:<br>    cert-manager.io/cluster-issuer: "letsencrypt-prod"<br>  hosts:<br>    - host: api.myapp.com<br>      paths:<br>        - path: /<br>          pathType: Prefix<br>  tls:<br>    - secretName: api-tls<br>      hosts:<br>        - api.myapp.com</p>

<p>resources:<br>  limits:<br>    cpu: 500m<br>    memory: 512Mi<br>  requests:<br>    cpu: 100m<br>    memory: 256Mi</p>

<p>autoscaling:<br>  enabled: true<br>  minReplicas: 2<br>  maxReplicas: 10<br>  targetCPUUtilizationPercentage: 70</p>

<p>postgresql:<br>  enabled: true<br>  auth:<br>    database: myapp<br>    username: myapp<br>    password: changeme</p>

<p>tests:<br>  enabled: true<br>  image: curlimages/curl:latest<br></code></pre></p>

<h3>Test Template</h3>

<pre><code># templates/tests/test-connection.yaml
apiVersion: v1
kind: Pod
metadata:
  name: "{{ include "myapp.fullname" . }}-test-connection"
  labels:
    helm.sh/hook: test
    helm.sh/hook-delete-policy: before-hook-creation
  annotations:
    "helm.sh/hook": test
spec:
  containers:
  - name: wget
    image: "{{ .Values.tests.image }}"
    command: ['sh', '-c']
    args:
      - |
        echo "Testing API health endpoint..."
        response=$(curl -f http://{{ include "myapp.fullname" . }}:{{ .Values.service.port }}/health || echo "FAILED")
        echo "Response: $response"
        if [ "$response" != "OK" ]; then
          exit 1
        fi
  restartPolicy: Never
</code></pre>

<hr>
<h2>Testando no Kubernetes</h2>

<h3>Testes de Integração com Kind</h3>

<pre><code># Criar cluster Kind
kind create cluster --name qa-tests

<p># Deploy app<br>kubectl apply -f deployment.yaml</p>

<p># Run tests<br>kubectl run test-runner --image=myapp/test-runner -- curl http://api-service/health</p>

<p># Ver resultado<br>kubectl logs test-runner</p>

<p># Cleanup<br>kind delete cluster --name qa-tests<br></code></pre></p>

<h3>kubectl Testing Commands</h3>

<pre><code># Verificar pods
kubectl get pods -l app=api

<p># Ver logs<br>kubectl logs -l app=api --tail=100</p>

<p># Port-forward para teste local<br>kubectl port-forward svc/api-service 8080:80</p>

<p># Executar testes<br>kubectl exec -it api-pod -- python -m pytest tests/</p>

<p># Ver events<br>kubectl get events --sort-by='.lastTimestamp'<br></code></pre></p>

<h3>Teste com cURL</h3>

<pre><code>#!/bin/bash
# test-api.sh

<p>API_URL="http://api-service"</p>

<p>echo "Testing API endpoints..."</p>

<p># Health check<br>echo "1. Health check..."<br>response=$(curl -s -o /dev/null -w "{6727d158e4474b0847515bd23a8ee4bebd5f1aac7a18bc968e51d8985dccb442}{http_code}" $API_URL/health)<br>if [ "$response" != "200" ]; then<br>  echo "FAILED: Health check returned $response"<br>  exit 1<br>fi<br>echo "OK"</p>

<p># Teste de endpoint<br>echo "2. GET /users..."<br>response=$(curl -s $API_URL/users)<br>if echo "$response" | grep -q "users"; then<br>  echo "OK"<br>else<br>  echo "FAILED"<br>  exit 1<br>fi</p>

<p>echo "All tests passed!"<br></code></pre></p>

<hr>
<h2>CI/CD com Kubernetes</h2>

<h3>GitHub Actions</h3>

<pre><code># .github/workflows/k8s-tests.yml
name: Kubernetes Tests

<p>on:<br>  push:<br>    branches: [main, develop]</p>

<p>jobs:<br>  test:<br>    runs-on: ubuntu-latest<br>    steps:<br>      - uses: actions/checkout@v4</p>

<p>- name: Setup kubectl<br>        uses: azure/setup-kubectl@v3</p>

<p>- name: Configure kubectl<br>        run: |<br>          echo "${{ secrets.KUBE_CONFIG }}" | base64 -d &gt; kubeconfig<br>          export KUBECONFIG=kubeconfig</p>

<p>- name: Deploy to test<br>        run: |<br>          helm upgrade --install myapp ./chart <br>            --namespace test <br>            --create-namespace <br>            --values ./chart/values-test.yaml <br>            --wait --timeout 5m</p>

<p>- name: Wait for pods<br>        run: |<br>          kubectl wait --for=condition=ready pod -l app=myapp <br>            -n test --timeout=300s</p>

<p>- name: Run API tests<br>        run: |<br>          kubectl exec -n test deploy/myapp -- <br>            python -m pytest tests/ -v --junit-xml=/tmp/results.xml</p>

<p>- name: Run integration tests<br>        run: |<br>          kubectl run test-runner -n test <br>            --image=myapp/test-runner <br>            --rm -it --restart=Never <br>            -- curl -f http://myapp/health</p>

<p>- name: Collect test results<br>        uses: actions/upload-artifact@v4<br>        with:<br>          name: test-results<br>          path: /tmp/results.xml</p>

<p>- name: Cleanup<br>        if: always()<br>        run: helm uninstall myapp -n test<br></code></pre></p>

<hr>
<h2>Conclusão</h2>

<p>Kubernetes facilita testes em ambientes controlados. As chaves são:<br><ol><li><strong>Containerização</strong> - Ambientes reproduzíveis</li><br><li><strong>Helm charts</strong> - Deploys versionados</li><br><li><strong>Test hooks</strong> - Testes no ciclo de deploy</li><br><li><strong>CI/CD integration</strong> - Automação completa</li><br><li><strong>Monitoring</strong> - Observabilidade em testes</li></ol></p>