Как настроить автоматический деплой в Kubernetes при коммите в Git?

Ответ

Есть два основных подхода: классический CI/CD и GitOps. Я использовал оба, но для production-проектов сейчас предпочитаю GitOps с ArgoCD.

1. GitOps-подход с ArgoCD (Рекомендуемый) В этом подходе Git-репозиторий — единственный источник истины. ArgoCD, установленный в кластере, постоянно сравнивает состояние кластера с манифестами в репозитории и автоматически синхронизирует их.

Как я это настраивал:

  1. Устанавливаем ArgoCD в кластер: kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml.
  2. В репозитории с кодом приложения храним Kubernetes-манифесты (например, в папке k8s/).
  3. Создаем Application CRD, который указывает ArgoCD на этот репозиторий:
    # application.yaml
    apiVersion: argoproj.io/v1alpha1
    kind: Application
    metadata:
    name: myapp-production
    namespace: argocd
    spec:
    project: default
    source:
    repoURL: 'git@github.com:myorg/myapp.git'
    targetRevision: main # Следим за веткой main
    path: k8s/overlays/production # Используем Kustomize для оверлеев
    destination:
    server: 'https://kubernetes.default.svc'
    namespace: production
    syncPolicy:
    automated:
      prune: true # Удалять ресурсы, удаленные из Git
      selfHeal: true # Автоматически исправлять дрейф конфигурации
    syncOptions:
      - CreateNamespace=true

    Теперь при любом коммите в main ветку (или при мерже PR) манифесты обновляются, и ArgoCD автоматически применяет изменения в кластере.

2. Классический CI/CD-подход (например, с GitHub Actions) Пайплайн в CI сам обновляет кластер, используя kubectl.

# .github/workflows/deploy.yml
name: Deploy to K8s
on:
  push:
    branches: [ main ]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
      - name: Set up Kubeconfig
        run: |
          mkdir -p ~/.kube
          echo "${{ secrets.KUBE_CONFIG }}" > ~/.kube/config
      - name: Deploy to Kubernetes
        run: |
          kubectl apply -f k8s/manifests/ -n production
          # Или использовать Kustomize/Helm
          kubectl rollout status deployment/myapp -n production

Сравнение: GitOps (ArgoCD) обеспечивает лучшую наблюдаемость, безопасность (изменения только через Git) и возможность легкого отката через revert коммита.

Ответ 18+ 🔞

А, ну вот, классика жанра! Два лагеря, два подхода, как будто на дворе 2002-й год и спорят, что лучше — Windows XP или Linux. Я оба пробовал, и скажу тебе честно: для продакшена сейчас — только GitOps с ArgoCD, без вариантов. Это как сравнивать телегу с реактивным самолётом.

1. GitOps с ArgoCD (То, что доктор прописал) Представь себе, что твой Git-репозиторий — это священное писание, единственный источник истины. А ArgoCD, который ты в кластер воткнёшь, — это такой фанатичный монах, который постоянно сравнивает, что написано в священном писании, с тем, что творится в реальном мире (то есть в кластере). И если видит расхождение — сразу начинает синхронизировать, чтобы было по канону. Удивление пиздец, как удобно!

Как я это городил, ебать мои старые костыли:

  1. Запихиваем ArgoCD в кластер одной командой, проще некуда: kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml.
  2. В репозитории с твоим приложением просто хранишь манифесты для кубера. Допустим, в папочке k8s/.
  3. Создаёшь этот самый Application CRD, который тычешь ArgoCD носом в нужный репозиторий. Смотри, как просто:
# application.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: myapp-production
  namespace: argocd
spec:
  project: default
  source:
    repoURL: 'git@github.com:myorg/myapp.git'
    targetRevision: main # Следим за веткой main, как ястреб
    path: k8s/overlays/production # Можно через Kustomize оверлеи делать — красота!
  destination:
    server: 'https://kubernetes.default.svc'
    namespace: production
  syncPolicy:
    automated:
      prune: true # Если что-то из Git удалил — в кластере тоже похерит. Аккуратно!
      selfHeal: true # Автоматически ловит дрейф конфигурации и возвращает как было. Вообще огонь!
    syncOptions:
      - CreateNamespace=true

И всё, ёпта! Закомитил что-то в main ветку — ArgoCD это увидел, схватил манифесты и сам всё применил в кластере. Сиди себе, пей кофе, пока он работает. Доверия ебать ноль к ручным деплоям после этого.

2. Классический CI/CD (Ну, типа GitHub Actions) Старая школа. Твой пайплайн в CI сам, как обезьяна с гранатой, лезет в кластер и командует kubectl apply. Выглядит примерно так:

# .github/workflows/deploy.yml
name: Deploy to K8s
on:
  push:
    branches: [ main ]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
      - name: Set up Kubeconfig
        run: |
          mkdir -p ~/.kube
          echo "${{ secrets.KUBE_CONFIG }}" > ~/.kube/config
      - name: Deploy to Kubernetes
        run: |
          kubectl apply -f k8s/manifests/ -n production
          # Или использовать Kustomize/Helm
          kubectl rollout status deployment/myapp -n production

Так в чём же разница, спросишь ты? А разница, чувак, — овердохуища! С GitOps у тебя полная прозрачность: кто, что и когда задеплоил — всё по коммитам видно. Безопасность — изменить кластер можно только через Git, а не каким-то левым kubectl edit из консоли. И откат — это просто git revert, и всё само откатится. А с классическим подходом ты как будто в тумане: пайплайн отработал — а что там по факту в кластере, хрен поймёшь. Так что выбор, я считаю, очевиден.