DevOps Admin

Guia Completo de GitLab CI/CD: Pipelines, Runners e Integração com Kubernetes Já leu

Introdução ao GitLab CI/CD: Automação de Ponta a Ponta GitLab CI/CD é um sistema integrado de integração contínua e entrega contínua que permite automatizar testes, builds e deploys diretamente a partir do seu repositório. Diferentemente de ferramentas externas, o GitLab CI/CD funciona nativamente dentro da plataforma, eliminando necessidade de integrações complexas. Cada push para o repositório dispara automaticamente uma sequência de jobs configurados em um arquivo , permitindo que você valide código, execute testes e implante aplicações sem intervenção manual. A beleza do GitLab CI/CD reside na simplicidade e poder combinados. Você não precisa provisionar servidores separados ou gerenciar credenciais complexas — tudo é orquestrado através de uma configuração declarativa. Quando implementado corretamente, elimina erros humanos, acelera o ciclo de desenvolvimento e fornece visibilidade completa sobre o status de cada etapa do pipeline. Entendendo Pipelines: Estrutura e Execução O que é um Pipeline? Um pipeline é uma série de estágios que são executados sequencialmente ou em paralelo. Cada estágio contém

Introdução ao GitLab CI/CD: Automação de Ponta a Ponta

GitLab CI/CD é um sistema integrado de integração contínua e entrega contínua que permite automatizar testes, builds e deploys diretamente a partir do seu repositório. Diferentemente de ferramentas externas, o GitLab CI/CD funciona nativamente dentro da plataforma, eliminando necessidade de integrações complexas. Cada push para o repositório dispara automaticamente uma sequência de jobs configurados em um arquivo .gitlab-ci.yml, permitindo que você valide código, execute testes e implante aplicações sem intervenção manual.

A beleza do GitLab CI/CD reside na simplicidade e poder combinados. Você não precisa provisionar servidores separados ou gerenciar credenciais complexas — tudo é orquestrado através de uma configuração declarativa. Quando implementado corretamente, elimina erros humanos, acelera o ciclo de desenvolvimento e fornece visibilidade completa sobre o status de cada etapa do pipeline.

Entendendo Pipelines: Estrutura e Execução

O que é um Pipeline?

Um pipeline é uma série de estágios que são executados sequencialmente ou em paralelo. Cada estágio contém um ou mais jobs que realizam tarefas específicas. A execução só prossegue para o próximo estágio se todos os jobs do estágio anterior forem bem-sucedidos (comportamento padrão).

Estrutura Básica do .gitlab-ci.yml

O arquivo de configuração define toda a lógica do pipeline. Você especifica variáveis globais, estágios, imagens Docker, e os jobs que serão executados. GitLab processa este arquivo YAML e cria os jobs automaticamente.

# Definição global
image: python:3.11

variables:
  PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip"

stages:
  - test
  - build
  - deploy

# Job no estágio "test"
unit_tests:
  stage: test
  script:
    - pip install -r requirements.txt
    - pytest tests/ -v --cov=src
  artifacts:
    reports:
      coverage_report:
        coverage_format: cobertura
        path: coverage.xml
  coverage: '/TOTAL.*\s+(\d+%)$/'

# Job no estágio "build"
build_artifact:
  stage: build
  script:
    - pip install -r requirements.txt
    - python -m PyInstaller --onefile src/main.py
  artifacts:
    paths:
      - dist/main
    expire_in: 30 days
  dependencies:
    - unit_tests

# Job no estágio "deploy"
deploy_production:
  stage: deploy
  script:
    - echo "Deploying to production..."
    - ./deploy.sh
  environment:
    name: production
    url: https://app.exemplo.com
  only:
    - main

Neste exemplo, o estágio test executa testes unitários com cobertura. O estágio build depende do sucesso do test e gera um artefato. Finalmente, deploy_production só executa em merges para a branch main. O atributo dependencies garante que apenas os artefatos necessários sejam baixados.

Conditions e Triggers Avançados

Você pode controlar quando jobs executam usando condições. only restringe a branches ou tags; except faz o inverso. Para lógica mais complexa, use rules:

deploy_staging:
  stage: deploy
  script:
    - echo "Deploying to staging..."
  rules:
    # Executa em merge requests
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
    # Executa em pushes para branches que começam com "feature/"
    - if: '$CI_COMMIT_BRANCH =~ /^feature\/.*/'
    # Caso nenhuma condição seja atendida, não executa
  environment:
    name: staging
    url: https://staging.exemplo.com

GitLab Runners: Executores do Pipeline

O que é um Runner?

Um Runner é um agente que executa os jobs definidos no pipeline. GitLab fornece runners compartilhados, mas em ambientes corporativos você frequentemente provisiona seus próprios runners para ter controle total sobre recursos, segurança e dependências.

Instalação e Configuração de um Runner

Um runner pode ser instalado em Linux, macOS ou Windows. Vamos usar Linux como exemplo. O processo envolve instalar o binário, registrá-lo com sua instância GitLab e deixá-lo rodando como serviço.

# 1. Baixar e instalar o runner (Ubuntu/Debian)
curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh | sudo bash
sudo apt-get install gitlab-runner

# 2. Registrar o runner
sudo gitlab-runner register \
  --url https://gitlab.seu-dominio.com/ \
  --registration-token <seu-token> \
  --executor docker \
  --docker-image alpine:latest \
  --description "Docker runner principal" \
  --docker-volumes /var/run/docker.sock:/var/run/docker.sock

# 3. Iniciar o runner
sudo gitlab-runner start

Após o registro, o runner aparecerá na interface do GitLab e estará pronto para executar jobs. Cada job é isolado em um container Docker (se você escolher o executor docker), garantindo ambiente limpo e reproduzível.

Executores Disponíveis

GitLab oferece vários executores. O docker é padrão em CI/CD moderno, mas shell executa diretamente na máquina host (útil para builds nativos), kubernetes integra com clusters K8s, e docker-machine escala automaticamente com máquinas virtuais.

# Exemplo usando executor shell
build_native:
  stage: build
  tags:
    - shell
    - macos
  script:
    - xcodebuild -scheme MyApp -configuration Release

# Exemplo usando docker
build_containerized:
  stage: build
  image: node:18
  tags:
    - docker
  script:
    - npm install
    - npm run build

O atributo tags conecta o job a runners específicos. Se você tem múltiplos runners registrados com tags diferentes, o GitLab escolhe o runner apropriado baseado nas tags do job.

Caching e Artefatos

Caching acelera pipelines reutilizando dependências entre execuções. Artefatos armazenam outputs que precisam passar entre estágios ou serem disponibilizados para download.

stages:
  - dependencies
  - build
  - test

# Job que popula o cache
install_deps:
  stage: dependencies
  image: node:18
  script:
    - npm install
  cache:
    key: npm-cache-${CI_COMMIT_REF_SLUG}
    paths:
      - node_modules/

# Job que usa o cache
build_app:
  stage: build
  image: node:18
  script:
    - npm run build
  cache:
    key: npm-cache-${CI_COMMIT_REF_SLUG}
    paths:
      - node_modules/
  artifacts:
    paths:
      - dist/
    expire_in: 1 week

# Job que usa o artefato do build
test_app:
  stage: test
  image: node:18
  script:
    - npm run test
  cache:
    key: npm-cache-${CI_COMMIT_REF_SLUG}
    paths:
      - node_modules/
  dependencies:
    - build_app

A chave do cache inclui a branch (CI_COMMIT_REF_SLUG) para isolar caches por branch. O build_app job gera um artefato na pasta dist/, que test_app pode acessar via dependencies.

Integração com Kubernetes

Arquitetura: GitLab e Kubernetes

Integrar GitLab CI/CD com Kubernetes permite deploys automáticos e escaláveis. A abordagem moderna usa o executor kubernetes para runners, executando jobs diretamente em pods do cluster. Para isso, você registra um runner que se conecta ao seu cluster K8s via kubeconfig.

Registrando um Runner em Kubernetes

# 1. Criar namespace para runners
kubectl create namespace gitlab-runners

# 2. Criar service account
kubectl create serviceaccount gitlab-runner -n gitlab-runners

# 3. Dar permissões
kubectl create clusterrolebinding gitlab-runner \
  --clusterrole=cluster-admin \
  --serviceaccount=gitlab-runners:gitlab-runner

# 4. Obter token
RUNNER_TOKEN=$(kubectl create token gitlab-runner -n gitlab-runners --duration=87600h)

# 5. Registrar runner
gitlab-runner register \
  --url https://gitlab.seu-dominio.com/ \
  --registration-token <seu-token> \
  --executor kubernetes \
  --kubernetes-host https://seu-k8s-api:6443 \
  --kubernetes-cert-file /path/to/ca.crt \
  --kubernetes-key-file /path/to/key.pem \
  --kubernetes-cert-file /path/to/cert.pem \
  --kubernetes-namespace gitlab-runners \
  --description "K8s runner"

Agora, quando um job é disparado, GitLab cria um pod ephemeral no cluster, executa o job, e o destrói após conclusão. Isso é extremamente eficiente para CI/CD em larga escala.

Deploy em Kubernetes via GitLab CI/CD

stages:
  - build
  - deploy

variables:
  REGISTRY: registry.seu-dominio.com
  IMAGE_NAME: minha-app
  IMAGE_TAG: ${CI_COMMIT_SHA}

build_image:
  stage: build
  image: docker:24
  services:
    - docker:24-dind
  script:
    - docker login -u $REGISTRY_USER -p $REGISTRY_PASSWORD $REGISTRY
    - docker build -t $REGISTRY/$IMAGE_NAME:$IMAGE_TAG .
    - docker push $REGISTRY/$IMAGE_NAME:$IMAGE_TAG

deploy_k8s:
  stage: deploy
  image: bitnami/kubectl:latest
  script:
    # Configurar kubectl
    - kubectl config use-context <seu-cluster-context>

    # Criar namespace se não existir
    - kubectl create namespace production --dry-run=client -o yaml | kubectl apply -f -

    # Fazer deploy usando kubectl apply
    - kubectl set image deployment/minha-app minha-app=$REGISTRY/$IMAGE_NAME:$IMAGE_TAG -n production

    # Aguardar rollout
    - kubectl rollout status deployment/minha-app -n production
  environment:
    name: production
    url: https://app.seu-dominio.com
    kubernetes:
      namespace: production
  only:
    - main

O job build_image constrói a imagem Docker e a envia para um registry. O job deploy_k8s então atualiza o deployment do Kubernetes com a nova imagem. O atributo environment.kubernetes.namespace integra a informação do K8s diretamente no GitLab, fornecendo visualização sobre pods e resources.

Exemplo Avançado: GitOps com ArgoCD

Para uma abordagem GitOps verdadeira, integre GitLab CI/CD com ArgoCD. GitLab dispara builds e atualiza manifests Git; ArgoCD sincroniza automaticamente o cluster com os manifests.

stages:
  - build
  - update-manifest

build_and_push:
  stage: build
  image: docker:24
  services:
    - docker:24-dind
  script:
    - docker build -t $REGISTRY/$IMAGE_NAME:$CI_COMMIT_SHA .
    - docker push $REGISTRY/$IMAGE_NAME:$CI_COMMIT_SHA

update_manifest:
  stage: update-manifest
  image: alpine:latest
  script:
    # Clonar repositório de manifests
    - apk add --no-cache git
    - git clone https://oauth2:${DEPLOY_TOKEN}@gitlab.seu-dominio.com/seu-usuario/k8s-manifests.git
    - cd k8s-manifests

    # Atualizar tag da imagem no manifest
    - sed -i "s|image: .*|image: $REGISTRY/$IMAGE_NAME:$CI_COMMIT_SHA|" deployment.yaml

    # Commit e push
    - git config user.email "ci@seu-dominio.com"
    - git config user.name "CI Pipeline"
    - git add deployment.yaml
    - git commit -m "Update image to $CI_COMMIT_SHA"
    - git push origin main
  only:
    - main

Quando o manifesto é atualizado, ArgoCD detecta a mudança e sincroniza automaticamente com o cluster. Isso desacopla a execução do pipeline (push de imagem) da aplicação (deploy no cluster), oferecendo mais segurança e auditoria.

Boas Práticas e Troubleshooting

Segurança: Variáveis e Secrets

Nunca commit credenciais no repositório. Use variáveis do GitLab com escopo limitado.

# Em Settings > CI/CD > Variables, crie:
# REGISTRY_USER (Protected, Masked)
# REGISTRY_PASSWORD (Protected, Masked, não exibir em logs)
# KUBE_CONFIG (Protected, Masked, conteúdo completo do kubeconfig)

deploy:
  stage: deploy
  script:
    # A variável é injetada no ambiente e mascarda em logs
    - echo "Usando registry user: ${REGISTRY_USER:0:5}***"
    - kubectl config view --raw > /tmp/config

Marque variáveis como Protected (executam apenas em branches protegidas) e Masked (ocultam valor em logs). Para grandes secrets como kubeconfig, use arquivos ao invés de variáveis de texto simples.

Debugging: Logs e Failed Pipelines

Quando um job falha, o GitLab mostra logs completos. Use variáveis de debug para aumentar verbosidade:

debug_job:
  stage: test
  script:
    - set -x  # Bash: mostra cada comando antes de executar
    - echo "CI_PROJECT_DIR: $CI_PROJECT_DIR"
    - echo "CI_COMMIT_SHA: $CI_COMMIT_SHA"
    - pwd
    - ls -la
  artifacts:
    paths:
      - debug-logs/
    when: always  # Coleta artefatos mesmo se job falha

O comando set -x em bash mostra cada linha antes de executar. O atributo when: always garante que artefatos sejam coletados mesmo em caso de falha, essencial para debugging.

Paralelização e Otimização

Reduce tempo total do pipeline executando jobs em paralelo:

stages:
  - test
  - build

# Estes três jobs rodam em paralelo no estágio "test"
unit_tests:
  stage: test
  script:
    - pytest tests/unit/ -v

integration_tests:
  stage: test
  script:
    - pytest tests/integration/ -v

lint:
  stage: test
  script:
    - flake8 src/
    - black --check src/

# Só inicia após todos os jobs do estágio "test"
build:
  stage: build
  script:
    - python setup.py sdist bdist_wheel

Os três jobs do estágio test executam simultaneamente, reduzindo o tempo total de pipeline. Para jobs muito rápidos (como lint), execute-os em paralelo com testes para maximizar eficiência.

Conclusão

Dominando GitLab CI/CD você adquire três competências críticas: primeira, automação completa de pipelines eliminando deploy manual e reduzindo erros, usando .gitlab-ci.yml como fonte única da verdade; segunda, provisionar e gerenciar runners adequados ao seu contexto, seja docker, shell ou kubernetes, entendendo tradeoffs entre simplicidade e poder; terceira, integrar completamente com Kubernetes para deploys escaláveis e reproducíveis, aproveitando GitOps para auditoria e reversão automática.

Referências

  1. GitLab CI/CD Documentation - Official
  2. GitLab Runner - Installation and Configuration
  3. Kubernetes Executor for GitLab Runner
  4. ArgoCD and GitOps Best Practices
  5. Docker-in-Docker for CI/CD

Artigos relacionados