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

Практикум GitOps — репозиторий и Application

Git становится единственным источником правды (source of truth) для конфигурации кластера. Argo CD читает репозиторий и создаёт ресурсы через объект Application — Custom Resource, который описывает "откуда брать манифесты" и "куда их применять".

Предварительно завершите шаг 1: кластер, Argo CD UI, namespace demo.


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

КомпонентСтатус
Argo CD UI на https://localhost:8080port-forward активен
namespace demoсоздан
Аккаунт GitHub/GitLabдля push репозитория
git локальноgit init, remote add

Архитектура шага 2


1. Структура Git-репозитория

Создайте каталог и инициализируйте repo:

mkdir -p infra-gitops-lab/apps/demo infra-gitops-lab/argocd
cd infra-gitops-lab
git init
git branch -M main

Целевая структура:

infra-gitops-lab/
apps/
demo/
deployment.yaml
service.yaml
argocd/
demo-app.yaml

deployment.yaml

Deployment — контроллер, который держит заданное число одинаковых Pod (контейнеров). Pod — минимальная единица запуска в Kubernetes.

apiVersion: apps/v1
kind: Deployment
metadata:
name: demo-nginx
namespace: demo
spec:
replicas: 2
selector:
matchLabels:
app: demo-nginx
template:
metadata:
labels:
app: demo-nginx
spec:
containers:
- name: nginx
image: nginx:1.27-alpine
ports:
- containerPort: 80
resources:
requests:
cpu: 50m
memory: 64Mi
limits:
cpu: 200m
memory: 128Mi

Поле replicas: 2 — два Pod для демонстрации rolling update в шаге 3. Tag образа 1.27-alpine — фиксированная версия; :latest в GitOps избегают.

service.yaml

Service — стабильный DNS и IP для доступа к Pod по label app: demo-nginx.

apiVersion: v1
kind: Service
metadata:
name: demo-nginx
namespace: demo
spec:
selector:
app: demo-nginx
ports:
- port: 80
targetPort: 80
type: ClusterIP

ClusterIP — доступ только внутри кластера; для проверки используем kubectl port-forward.

Первый commit и push

git add apps/demo/
git commit -m "feat: add demo nginx deployment and service"
git remote add origin https://github.com/YOUR_USER/infra-gitops-lab.git
git push -u origin main

Замените YOUR_USER на свой логин. Для private repo настройте credentials в Argo CD (см. раздел "Безопасность" ниже).

Пример минимальных манифестов — /lab/Примеры/11115.


2. Argo CD Application

Application связывает Git-путь с namespace в кластере. Файл argocd/demo-app.yaml:

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: demo-nginx
namespace: argocd
finalizers:
- resources-finalizer.argocd.argoproj.io
spec:
project: default
source:
repoURL: https://github.com/YOUR_USER/infra-gitops-lab.git
targetRevision: main
path: apps/demo
destination:
server: https://kubernetes.default.svc
namespace: demo
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
ПараметрСмысл
repoURLHTTPS или SSH URL Git-репозитория
pathКаталог с манифестами относительно корня repo
targetRevisionВетка, tag или commit SHA
destination.namespaceКуда применять ресурсы
automated.pruneУдаляет ресурсы, которых больше нет в Git
automated.selfHealВозвращает кластер к Git при ручных правках
CreateNamespace=trueСоздаёт namespace, если его ещё нет

Теория pull-based deploy — GitOps.

Применение Application

Application можно применить из того же repo или локально:

kubectl apply -f argocd/demo-app.yaml

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

application.argoproj.io/demo-nginx created

Либо через CLI после push argocd/ в Git:

argocd app create demo-nginx \
--repo https://github.com/YOUR_USER/infra-gitops-lab.git \
--path apps/demo \
--dest-server https://kubernetes.default.svc \
--dest-namespace demo \
--sync-policy automated \
--auto-prune \
--self-heal

Проверка в UI

Откройте Argo CD UI → Application demo-nginx. Ожидаемые статусы:

ПолеЗначение
Sync StatusSynced
HealthHealthy
RevisionSHA последнего commit на main

Если Progressing — подождите 1–2 минуты. Если Unknown или Failed — см. troubleshooting ниже.


3. Проверка в кластере

kubectl get deployment,svc,pods -n demo

Ожидаемый результат:

NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/demo-nginx 2/2 2 2 1m

NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/demo-nginx ClusterIP 10.96.xxx.x <none> 80/TCP 1m

NAME READY STATUS RESTARTS AGE
pod/demo-nginx-xxxxxxxxxx-xxxxx 1/1 Running 0 1m
pod/demo-nginx-xxxxxxxxxx-yyyyy 1/1 Running 0 1m

Доступ к nginx через port-forward:

kubectl port-forward svc/demo-nginx -n demo 8888:80

В другом терминале:

curl -s -o /dev/null -w "%{http_code}\n" http://localhost:8888

Ожидаемый код 200. Тело ответа — HTML страница "Welcome to nginx!".

CLI Argo CD:

argocd app get demo-nginx
argocd app diff demo-nginx

Пустой diff означает совпадение Git и кластера.


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

Статус в UIПричинаРешение
OutOfSyncРучные правки или задержка syncНажмите Sync или дождитесь automated
ComparisonErrorНеверный repoURL, нет доступаПроверьте URL, для private — Repository credentials
InvalidSpecErrorОпечатка в YAML Applicationkubectl describe application demo-nginx -n argocd
Pods ImagePullBackOffНет сети к Docker HubПроверьте docker pull nginx:1.27-alpine на хосте
DegradedReadiness probe failkubectl logs -n demo -l app=demo-nginx

Для private repository в UI: Settings → Repositories → Connect repo (HTTPS token или SSH key).


Подключение private repository

Если репозиторий private, Argo CD не прочитает манифесты без credentials.

HTTPS с Personal Access Token

  1. GitHub → Settings → Developer settings → Personal access tokens → fine-grained token.
  2. Права: Repository → Contents → Read-only на infra-gitops-lab.
  3. В Argo CD UI: Settings → Repositories → Connect repo using HTTPS.
  4. URL: https://github.com/YOUR_USER/infra-gitops-lab.git, username — логин, password — token.

CLI:

argocd repo add https://github.com/YOUR_USER/infra-gitops-lab.git \
--username YOUR_USER \
--password ghp_xxxxxxxx \
--name infra-gitops-lab
argocd repo list

Ожидаемый статус: Successful.

SSH (альтернатива)

argocd repo add git@github.com:YOUR_USER/infra-gitops-lab.git \
--ssh-private-key-path ~/.ssh/id_ed25519

Публичный ключ добавьте в GitHub → Repository → Deploy keys (read-only достаточно для Argo CD).


Разбор полей Application построчно

ПолеПримерОбъяснение
apiVersionargoproj.io/v1alpha1Версия CRD Argo CD
kindApplicationТип ресурса
metadata.namespaceargocdApplication живёт рядом с Argo CD
spec.projectdefaultAppProject — RBAC и whitelist repo
spec.source.repoURLhttps://github.com/...Откуда clone
spec.source.pathapps/demoПодкаталог с YAML
spec.source.targetRevisionmainВетка или tag
spec.destination.serverhttps://kubernetes.default.svcIn-cluster API
spec.destination.namespacedemoTarget namespace
syncPolicy.automatedprune, selfHealАвто-sync

Теория pull model — GitOps 8.12/4.


AppProject (расширение lab)

AppProject ограничивает, какие repo и namespace может использовать Application. Пример для команды:

apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
name: demo-team
namespace: argocd
spec:
sourceRepos:
- https://github.com/YOUR_USER/infra-gitops-lab.git
destinations:
- namespace: demo
server: https://kubernetes.default.svc
clusterResourceWhitelist:
- group: apps
kind: Deployment
- group: ""
kind: Service

В Application замените project: default на project: demo-team. В production whitelist не даёт применить ClusterRole из случайного path.


Health и Sync — что видит UI

Argo CD вычисляет health по типу ресурса:

РесурсHealthy когда
Deploymentdesired replicas = ready replicas
ServiceClusterIP назначен
PodRunning и probes OK

Sync status:

СтатусЗначение
SyncedLive = Git
OutOfSyncЕсть diff
UnknownОшибка сравнения

Команда для JSON status:

kubectl get application demo-nginx -n argocd -o jsonpath='{.status.sync.status}{" "}{.status.health.status}{"\n"}'

Ожидаемо: Synced Healthy.


Расширенная проверка сети внутри кластера

kubectl run curl-test --rm -it --restart=Never -n demo --image=curlimages/curl -- \
curl -s -o /dev/null -w "%{http_code}" http://demo-nginx.demo.svc.cluster.local

Ожидаемый код 200 — Service резолвится через DNS имя.namespace.svc.cluster.local — см. 8.06 Service.


Частые вопросы

Почему Argo CD не создал Deployment сразу?
Repo server clone + manifest generate занимает 30–120 секунд. Проверьте Events: kubectl describe application demo-nginx -n argocd.

Можно ли один repo на много Application?
Да. Разные pathapps/team-a, apps/team-b — и разные destination.namespace.

Нужен ли Helm?
Нет для lab. Argo CD поддерживает plain YAML, Helm, Kustomize — см. 8.06/211.


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

  1. Добавьте label app.kubernetes.io/version: "1.27" в Deployment template metadata.
  2. Commit и push — убедитесь в UI, что diff только по labels.
  3. Добавьте livenessProbe httpGet на / port 80 — перезапустите sync при Degraded Pod.

Пример probe:

livenessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 5
periodSeconds: 10

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

СимптомДиагностикаРешение
rpc error: code = Unknown в repoargocd repo getПроверьте token / SSH
Application MissingCRD не установленПереустановите Argo CD manifest
Duplicate resourceДва Application на один pathУдалите дубликат
Sync Failed invalid YAMLkubectl apply --dry-run=client -f локальноИсправьте syntax в Git

Логи repo-server:

kubectl logs -n argocd -l app.kubernetes.io/name=argocd-repo-server --tail=50

Полный пошаговый сценарий (copy-paste lab)

Ниже — последовательность без пропусков для проверки end-to-end после шага 1.

Создание repo локально

mkdir -p ~/infra-gitops-lab/apps/demo ~/infra-gitops-lab/argocd
cd ~/infra-gitops-lab

Скопируйте deployment.yaml и service.yaml из раздела 1 выше. Затем:

git init && git branch -M main
git add apps/demo/
git commit -m "feat: demo nginx manifests"
git remote add origin https://github.com/YOUR_USER/infra-gitops-lab.git
git push -u origin main

Application manifest

Сохраните argocd/demo-app.yaml, замените YOUR_USER, commit optional (можно apply локально):

kubectl apply -f argocd/demo-app.yaml

Ожидание sync

for i in 1 2 3 4 5 6 7 8 9 10; do
STATUS=$(kubectl get application demo-nginx -n argocd -o jsonpath='{.status.sync.status}' 2>/dev/null)
HEALTH=$(kubectl get application demo-nginx -n argocd -o jsonpath='{.status.health.status}' 2>/dev/null)
echo "sync=$STATUS health=$HEALTH"
[ "$STATUS" = "Synced" ] && [ "$HEALTH" = "Healthy" ] && break
sleep 15
done

Финальная проверка

kubectl get pods -n demo -l app=demo-nginx
kubectl port-forward svc/demo-nginx -n demo 8888:80 &
sleep 2
curl -s -o /dev/null -w "HTTP %{http_code}\n" http://localhost:8888
kill %1 2>/dev/null

Ожидается HTTP 200 и два Pod Running.


Интеграция с Vault ExternalSecret (preview)

После Vault practicum шаг 3 добавьте в apps/demo/ файл external-secret.yaml без password в Git. Argo CD sync создаст ExternalSecret; ESO создаст Kubernetes Secret. Deployment ссылается на secretRef — password только в Vault.


Метрики успеха шага 2

КритерийКак проверить
Git содержит манифестыgit ls-files apps/demo/
Application существуетkubectl get app demo-nginx -n argocd
Synced + HealthyUI или jsonpath
2 Pod Runningkubectl get pods -n demo
Service отвечаетcurl через port-forward
Diff пустойargocd app diff demo-nginx

Справочник полей deployment.yaml

Строка YAMLНазначение
apiVersion: apps/v1API группа Deployment
kind: DeploymentТип ресурса — контроллер реплик Pod
metadata.nameИмя Deployment в namespace
metadata.namespacedemo — изоляция от argocd
spec.replicasЖелаемое число Pod
spec.selector.matchLabelsКак Deployment находит свои Pod
spec.template.metadata.labelsLabels на Pod — должны match selector
spec.template.spec.containersСписок контейнеров в Pod
containers[].imageDocker-образ из registry
containers[].portsПорты контейнера — для Service targetPort
resources.requestsМинимум CPU/RAM для scheduler
resources.limitsМаксимум CPU/RAM для контейнера

Подробнее о каждом kind — 8.06/211.


Справочник полей service.yaml

ПолеЗначение в lab
spec.selector.appСвязь с Pod label demo-nginx
spec.ports.portПорт Service внутри кластера (80)
spec.ports.targetPortПорт контейнера nginx (80)
type: ClusterIPДоступ только inside cluster

DNS имя Service: demo-nginx.demo.svc.cluster.local.


Ожидаемый вывод kubectl describe application

kubectl describe application demo-nginx -n argocd

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

Status:
Health:
Status: Healthy
Sync:
Status: Synced
Revision: abc1234...
Conditions:
Type: Synced
Message: successfully synced
Events:
Normal ResourceUpdated application-controller Updated sync status

При ошибке repo clone Events содержат ComparisonError и текст authentication required.


Kustomize и Helm в том же repo

Argo CD autodetect tool по файлам в path:

Файл в pathTool
kustomization.yamlKustomize
Chart.yamlHelm
Только .yamlPlain directory

Пример kustomization.yaml в apps/demo/:

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deployment.yaml
- service.yaml
commonLabels:
app.kubernetes.io/part-of: gitops-lab

Commit и push — Argo CD пересоберёт manifest через kustomize build.


Multi-source Application (preview)

Argo CD 2.x поддерживает несколько source в одной Application — например chart + values из второго repo. Для enterprise fleet; в lab достаточно single source. Документация связана с GitOps 8.12/4.


Безопасность

  1. Секреты (пароли, ключи API) не храните в открытом виде в Git — см. практикум Vault и Sealed Secrets.
  2. Для private-репозитория добавьте credentials в Argo CD (SSH-ключ или token с минимальными правами read).
  3. Политики на манифесты — DevSecOps.
  4. Не коммитьте argocd-initial-admin-secret и kubeconfig в infra-repo.

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