Перейти к основному содержимому

Практикум GitOps — обновление через Git

В GitOps релиз — изменение в Git. Оператор не запускает kubectl apply вручную на проде. Argo CD обнаруживает diff между repo и кластером и запускает rolling update — поочерёдную замену Pod без простоя.

Предварительно Application demo-nginx должна быть Synced / Healthy (шаг 2).


Предварительные требования

ПроверкаКомандаОжидание
Application синхронизированаargocd app get demo-nginxSync: Synced
Два Pod работаютkubectl get pods -n demo2/2 Running
Git remote настроенgit remote -vorigin → ваш repo

Архитектура релиза


Сценарий релиза

  1. CI собрал образ с новым tag (в lab меняем tag в deployment.yaml вручную).
  2. В репозитории infra-git меняете поле image: в apps/demo/deployment.yaml.
  3. Commit и push → Argo CD обнаруживает изменение → sync → rolling update.

Ручное изменение tag (lab)

Откройте apps/demo/deployment.yaml и измените образ:

image: nginx:1.26-alpine

Commit:

git add apps/demo/deployment.yaml
git commit -m "chore: bump nginx to 1.26-alpine"
git push origin main

Ожидаемое поведение Argo CD (через 1–3 минуты при poll):

Sync Status: Synced
Health: Progressing → Healthy
Revision: <новый SHA commit>

Pin по digest (рекомендуется для supply chain)

Tag образа можно подменить злоумышленником. Надёжнее фиксировать digest (SHA256 слоя образа):

docker pull nginx:1.27-alpine
docker inspect nginx:1.27-alpine --format='{{index .RepoDigests 0}}'

Пример строки в манифесте:

image: nginx:1.27-alpine@sha256:5041775884a... # полный digest из inspect

Подробнее — Supply chain.


Наблюдение за rollout

kubectl rollout status deployment/demo-nginx -n demo --timeout=120s

Ожидаемый вывод:

Waiting for deployment "demo-nginx" rollout to finish: 1 out of 2 new replicas have been updated...
Waiting for deployment "demo-nginx" rollout to finish: 2 old replicas are pending termination...
deployment "demo-nginx" successfully rolled out

История ReplicaSet:

kubectl rollout history deployment/demo-nginx -n demo

Argo CD CLI:

argocd app get demo-nginx
argocd app history demo-nginx

В UI раздел History and Rollback показывает Git commits — видно, какой commit вызвал изменение. Это аудит через Git без ручных правок в кластере.

Проверка версии nginx внутри Pod:

kubectl exec -n demo deploy/demo-nginx -- nginx -v

Ожидаемая строка содержит nginx/1.26 после bump.


Имитация CI (GitHub Actions)

В production CI обновляет манифест после сборки и push образа в registry. Для lab — workflow с ручным запуском:

# .github/workflows/update-manifest.yml
name: Bump nginx tag
on:
workflow_dispatch:
inputs:
image_tag:
description: "Minor nginx version, e.g. 1.26"
required: true
type: string
jobs:
bump:
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v4
- name: Patch deployment
run: |
sed -i "s|image: nginx:.*|image: nginx:${{ inputs.image_tag }}-alpine|" apps/demo/deployment.yaml
- name: Commit and push
run: |
git config user.name "ci-bot"
git config user.email "ci-bot@users.noreply.github.com"
git commit -am "chore: bump nginx to ${{ inputs.image_tag }}"
git push

После push Argo CD подхватит commit так же, как при ручном изменении.

Полные рецепты CI/CD — /lab/Примеры/1134, раздел DevOps.


Проверка шага 3

ШагКомандаОжидание
1argocd app get demo-nginxRevision = последний commit
2kubectl get rs -n demoНовый ReplicaSet с desired 2
3curl localhost:8888 (port-forward)HTTP 200
4UI HistoryЗапись с message bump

Устранение неполадок

СимптомПричинаРешение
Argo не видит commitЗадержка poll (3 min default)Sync в UI вручную или уменьшите timeout repo
Rollout stuckНехватка ресурсовkubectl describe rs -n demo
ImagePullBackOffНеверный tagПроверьте tag на Docker Hub
Sync OK, образ старыйКэш на нодеkubectl delete pod -n demo -l app=demo-nginx

Canary (опционально)

Для production используйте Argo Rollouts или два Application (stable и canary). Базовые стратегии развёртывания — 8.04/111. В этом lab достаточно стандартного Deployment rolling update.


Заметки по безопасности

  1. CI-bot должен иметь право только на infra-repo, не на kubeconfig prod.
  2. Pin digest снижает риск подмены образа в registry.
  3. Review PR перед merge — DevSecOps.

Следующий шаг — drift и откат.


Webhook вместо poll (production)

По умолчанию Argo CD опрашивает Git каждые 3 минуты. Для быстрого deploy настройте webhook в GitHub:

  1. Argo CD Settings → Repositories → ваш repo → Webhook URL.
  2. GitHub → repo → Settings → Webhooks → Payload URL из Argo CD, content type application/json.
  3. Events: push.

После push sync начнётся за секунды. Теория — GitOps.


Kustomize overlay (опционально)

Структура с Kustomize — разные overlay для dev/prod без дублирования YAML:

apps/demo/
base/
deployment.yaml
service.yaml
kustomization.yaml
overlays/
dev/
kustomization.yaml
prod/
kustomization.yaml

В Application укажите path: apps/demo/overlays/dev. Argo CD вызовет kustomize build автоматически.


Проверка ReplicaSet во время rollout

kubectl get rs -n demo -l app=demo-nginx -o wide
watch kubectl get pods -n demo -l app=demo-nginx

Во время rolling update видны Pod с разными hash в имени — старый ReplicaSet scale down, новый scale up.


Semver и image tag policy

Рекомендации для команды:

ПрактикаПример
Фиксированный tagnginx:1.27-alpine
Digest pinnginx@sha256:abc...
Избегатьnginx:latest

Supply chain — 8.12/1.


CI/CD pipeline end-to-end (схема)

Примеры workflow — /lab/Примеры/1134.


Дополнительное задание

  1. Измените replicas с 2 на 3 через Git — наблюдайте rolling без downtime.
  2. Добавьте annotation argocd.argoproj.io/sync-wave: "1" — порядок sync при нескольких ресурсах.
  3. Запустите GitHub Actions bump из раздела выше с tag 1.25.

Устранение неполадок (расширение)

СимптомКомандаРешение
Old pods не terminatekubectl describe pod -n demoПроверьте PDB, grace period
Argo Progressing долгоargocd app get demo-nginx --hard-refreshПринудительный refresh
Wrong image после synckubectl get deploy -o yaml | grep imageПроверьте branch в Application

Связанные материалы


Полный walkthrough релиза через Git

Сценарий от текущего состояния (Synced/Healthy) до нового образа в кластере.

Подготовка — зафиксируйте baseline

argocd app get demo-nginx
kubectl get deployment demo-nginx -n demo -o jsonpath='{.spec.template.spec.containers[0].image}{"\n"}'
kubectl get pods -n demo -l app=demo-nginx

Ожидаемый образ до bump — nginx:1.27-alpine (или ваш из шага 2). Два Pod в Running.

Изменение в Git

cd infra-gitops-lab
sed -i 's|nginx:1.27-alpine|nginx:1.26-alpine|' apps/demo/deployment.yaml
git diff apps/demo/deployment.yaml
git add apps/demo/deployment.yaml
git commit -m "chore: bump nginx to 1.26-alpine"
git push origin main

Ожидаемый git diff — одна строка image:.

Ожидание sync Argo CD

for i in 1 2 3 4 5 6 7 8 9 10; do
REV=$(kubectl get application demo-nginx -n argocd -o jsonpath='{.status.sync.status}' 2>/dev/null)
IMG=$(kubectl get deployment demo-nginx -n demo -o jsonpath='{.spec.template.spec.containers[0].image}' 2>/dev/null)
echo "sync=$REV image=$IMG"
echo "$IMG" | grep -q 1.26 && break
sleep 15
done

Ожидаемо — image=nginx:1.26-alpine и Sync Status Synced.

Проверка rollout

kubectl rollout status deployment/demo-nginx -n demo --timeout=120s
kubectl exec -n demo deploy/demo-nginx -- nginx -v 2>&1 | head -1

Ожидаемая строка nginx содержит nginx/1.26.


Ожидаемый вывод argocd app history

argocd app history demo-nginx

Фрагмент при успехе:

ID DATE REVISION
0 2026-06-15 10:00:00 +0000 UTC abc1234 (feat: add demo nginx)
1 2026-06-15 11:30:00 +0000 UTC def5678 (chore: bump nginx to 1.26-alpine)

Типичные ошибки шага 3

СимптомОжидаемое при OKДиагностикаРешение
Argo не видит commit 5+ минRevision = новый SHAargocd app get demo-nginx --refreshHard refresh или webhook
ImagePullBackOffPod Runningkubectl describe pod -n demoПроверьте tag на hub.docker.com
Synced, образ старыйimage в deploy = Gitargocd app diff demo-nginxПроверьте branch targetRevision
Rollout stuckrollout finishedkubectl get rs -n demoНехватка CPU — describe pod
Progressing > 10 minHealthykubectl logs -n demo -l app=demo-nginxReadiness probe

Предупреждения безопасности

  1. CI-bot с правом push в infra-repo без kubeconfig prod — только Git.
  2. Pin digest вместо tag снижает риск подмены образа в registry.
  3. Review PR перед merge — DevSecOps.
  4. Не используйте :latest в Git — непредсказуемый rollout.
  5. Webhook URL Argo CD не публикуйте без auth.

Чек-лист завершения шага 3

#ПроверкаКомандаОжидание
1Новый revisionargocd app get demo-nginxSHA последнего commit
2Образ обновлёнjsonpath imagenginx:1.26-alpine
3Rollout OKkubectl rollout statussuccessfully rolled out
4nginx -vexec в podверсия 1.26
5HTTP 200port-forward + curlкод 200
6History в UIArgo CD UIзапись bump

Дальше — drift и откат.


GitHub Actions — полный workflow с проверкой

Добавьте в repo .github/workflows/update-manifest.yml из раздела выше. После push workflow:

gh run list --workflow=update-manifest.yml --limit 3
gh run view <run-id> --log

Ожидаемый лог — commit chore: bump nginx и push в main. Argo CD подхватит тот же commit.


Имитация сбоя rollout (lab)

Намеренно укажите несуществующий tag:

image: nginx:9.99-nonexistent

После push — Pod в ImagePullBackOff, Application Degraded. Откат через git revert — тема шага 4.

kubectl get pods -n demo -l app=demo-nginx
# STATUS ImagePullBackOff — ожидаемо для учебного сбоя
git revert HEAD --no-edit && git push

Метрики успеха релиза

МетрикаКак измеритьЦель lab
Time to syncот push до Synced< 5 min (poll)
Rollout durationrollout status< 2 min
Downtimecurl в цикле0 (rolling)
Replicas readyget pods2/2

Наблюдение rollout в реальном времени

kubectl get pods -n demo -l app=demo-nginx -w
# в другом терминале — push commit с bump

Ожидаемая последовательность — Terminating старых pod, Running новых с другим hash в имени.