Этот репозиторий содержит полностью рабочий тестовый DevOps‑стенд, включающий:
- k3d Kubernetes кластер (1 control-plane + 2 workers)
- Gitea (Git, Docker Registry, Gitea Actions CI/CD)
- Argo CD (GitOps деплой всех манифестов)
- Demo‑app (Nginx приложение + Deployment + Service + Ingress)
- kube‑prometheus‑stack (Prometheus + Alertmanager + Grafana)
- Полностью автоматический pipeline: push → build image → push to Gitea registry → ArgoCD auto-sync → deploy
- Подходит для локальной отработки GitOps/CI/CD, демонстраций и интервью
- Установи зависимости (Docker Desktop/Engine, k3d, kubectl, Helm).
- Подними k3d кластер (или
./scripts/create-k3d.sh):k3d cluster create infra --servers 1 --agents 2 --api-port 6445 -p "80:80@loadbalancer" --k3s-arg "--disable=traefik@server:0" kubectl cluster-info && kubectl get nodes -o wide
- Запусти Gitea + registry:
cd gitea && docker compose up -d. - Подними runner:
cd ../gitea-runner && docker compose up -d. - Импортируй (или форкни) репозиторий в Gitea, включи Docker Registry в
app.ini. - Подключи Argo CD и нацеливай
infra-manifests/application-root.yamlкак root‑app. - Проверь:
kubectl get apps -n argocdkubectl get pods -n apps,kubectl get pods -n monitoring- Argo CD UI доступна, Grafана через
kubectl -n monitoring port-forward svc/kube-prometheus-stack-grafana 3000:80.
- Docker (Desktop/Engine) с рабочим Docker socket.
- k3d ≥ 5.x, kubectl ≥ 1.27, Helm ≥ 3.12.
- Ресурсы: ~4 CPU, 6–8 GB RAM, 10+ GB диска.
- Порты: 80 (ingress), 3000 (Gitea/registry), 6445 (k3d API).
┌───────────────────────────────────────────┐
│ Gitea │
│-------------------------------------------│
│ Git repos │
│ Docker Registry (<gitea-ip>:3000/v2/) │
│ Gitea Actions (CI) │
└───────────────────────────────────────────┘
│ Push + Image Push
▼
┌─────────────────────────────────────────────────────────────────────┐
│ Argo CD │
│──────────────────────────────────────────────────────────────────── │
│ GitOps синхронизация из репозитория infra-manifests │
│ Автодеплой demo-app + мониторинга │
└─────────────────────────────────────────────────────────────────────┘
│ Apply manifests
▼
┌───────────────────────────────────────────────────┐
│ k3d cluster │
│────────────────────────────────────────────────── │
│ - k3d-infra-server-0 (control-plane) │
│ - k3d-infra-agent-0 │
│ - k3d-infra-agent-1 │
│ │
│ Ingress NGINX → demo-app │
│ Prometheus + Grafana (kube-prometheus-stack) │
└───────────────────────────────────────────────────┘
- Git push в
demo-app-src→ Gitea Actions билдит image → пуш в Gitea Registry. - ArgoCD (application-root) смотрит
infra-manifests→ auto-sync → деплой demo‑app и kube‑prometheus‑stack. - Ingress → demo‑app Service → pod.
- Prometheus собирает метрики, Grafana визуализирует, Alertmanager шлёт алерты.
Зачем каждая часть:
- k3d — быстрый локальный кластер.
- Gitea — Git + registry + CI в одном.
- Gitea Actions — CI сборка и пуш образов.
- ArgoCD — GitOps синхронизация манифестов.
- kube-prometheus-stack — метрики/алерты/дашборды.
- demo-app — проверка контура деплоя/ingress.
- gitea-runner — исполняет workflow с доступом к Docker.
Рекомендации по структуре репо:
infra-manifests/— только декларативка (Helm/ArgoCD Applications); разделяйinfra/иapps/.demo-app-src/— код и CI workflows;demo-app-image/— минимальный образ.gitea/,gitea-runner/— окружение SCM/CI.- Добавь
docs/(схемы) иscripts/(автоматизация) при дальнейшем росте.
test-infra-stand/
├── infra-manifests/ # GitOps для Argo CD
│ ├── application-demo-app.yaml
│ ├── application-monitoring.yaml
│ └── apps/
│ └── demo-app/
│ ├── deployment.yaml
│ ├── service.yaml
│ └── ingress.yaml
│
├── gitea-runner/ # Gitea Actions runner
│ └── docker-compose.yml
│
├── demo-app-src/ # Исходники demo-приложения
│ ├── Dockerfile
│ ├── index.html
│ └── .gitea/workflows/build.yml
│
├── scripts/ # bootstrap: k3d, ArgoCD
│ ├── create-k3d.sh
│ └── bootstrap-argocd.sh
│
└── README.md # Этот файл
k3d cluster create infra --servers 1 --agents 2 --api-port 6445 -p "80:80@loadbalancer" --k3s-arg "--disable=traefik@server:0"Проверка:
kubectl cluster-info
kubectl get nodes -o wideLinux: ставим Docker + k3d (curl install). Windows: Docker Desktop + WSL2, k3d ставим внутри WSL; kubectl/Helm тоже внутри. Убедись, что /var/run/docker.sock доступен runner'у.
docker-compose.yml:
version: "3"
services:
gitea:
image: gitea/gitea:latest
container_name: gitea
ports:
- "3000:3000"
- "2222:22"
volumes:
- ./data:/data
restart: alwaysЗапуск:
docker compose up -dВ app.ini:
[packages.container.registry]
ENABLED = true
Адрес реестра:
http://<gitea-ip>:3000
Логин:
docker login http://<gitea-ip>:3000.gitea/workflows/build.yml:
name: Build Docker image
on:
push:
branches: [ main ]
jobs:
build:
runs-on: docker
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Build and Push Image
run: |
docker build -t <gitea-ip>:3000/gitea/demo-app-src/demo:latest .
docker push <gitea-ip>:3000/gitea/demo-app-src/demo:latestУлучшенный пример с тегами/кешем/проверкой:
name: Build & Push demo-app
on:
push:
branches: [ main ]
env:
REGISTRY: "<gitea-ip>:3000"
IMAGE_NAME: "gitea/demo-app-src/demo"
jobs:
build:
runs-on: ubuntu-docker
steps:
- uses: actions/checkout@v4
- name: Set up meta
id: meta
run: |
SHA_TAG=${GITHUB_SHA::7}
echo "sha_tag=$SHA_TAG" >> $GITHUB_OUTPUT
echo "latest_tag=latest" >> $GITHUB_OUTPUT
echo "main_tag=main" >> $GITHUB_OUTPUT
- name: Docker buildx (cache)
run: |
docker buildx create --use --driver docker-container
docker buildx build \
-t $REGISTRY/$IMAGE_NAME:${{ steps.meta.outputs.sha_tag }} \
-t $REGISTRY/$IMAGE_NAME:${{ steps.meta.outputs.main_tag }} \
-t $REGISTRY/$IMAGE_NAME:${{ steps.meta.outputs.latest_tag }} \
--cache-from type=registry,ref=$REGISTRY/$IMAGE_NAME:cache \
--cache-to type=registry,ref=$REGISTRY/$IMAGE_NAME:cache,mode=max \
--load .
- name: Smoke test image
run: |
docker run --rm -p 8080:80 -d --name demo-test $REGISTRY/$IMAGE_NAME:${{ steps.meta.outputs.sha_tag }}
sleep 5
curl -f http://127.0.0.1:8080
docker rm -f demo-test
- name: Push images
run: |
docker login $REGISTRY -u $GITEA_USERNAME -p $GITEA_TOKEN
docker push $REGISTRY/$IMAGE_NAME:${{ steps.meta.outputs.sha_tag }}
docker push $REGISTRY/$IMAGE_NAME:${{ steps.meta.outputs.main_tag }}
docker push $REGISTRY/$IMAGE_NAME:${{ steps.meta.outputs.latest_tag }}Почему так:
- Теги:
latestдля удобства,mainдля стабильной ветки,shaдля точного pin в ArgoCD. - Buildx cache ускоряет сборку.
- Smoke test не даёт пушить битый образ.
- Runner: держи label
ubuntu-dockerс доступом к Docker socket; для прод‑подобных тестов выделяй отдельный runner.
Добавляем приложение:
Быстрая установка:
./scripts/bootstrap-argocd.sh(создаёт namespace и ставит ArgoCD).
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: demo-app
spec:
project: default
source:
repoURL: https://github.com/<your>/test-infra-stand.git
path: infra-manifests/apps/demo-app
targetRevision: main
destination:
server: https://kubernetes.default.svc
namespace: apps
syncPolicy:
automated:
prune: true
selfHeal: trueArgoCI сам подтянет все манифесты.
Рекомендации по GitOps/ArgoCD:
- Включи
automated+selfHeal+prune, чтобы дрифт лечился сам. - Организуй namespaces:
infra(argocd, ingress),apps(приложения),monitoring(обсервабилити). - Разделяй
infra-manifests/infra(CRD/ingress/операторы) иinfra-manifests/apps. - Используй Sync Waves: infra -1/0, приложения 1+, чтобы зависимости применялись корректно.
- Безопасный доступ: RBAC per project, ingress с BasicAuth/SSO, network policies; секреты — через sealed-secrets или vault plugin.
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: kube-prometheus-stack
spec:
project: default
source:
repoURL: https://prometheus-community.github.io/helm-charts
chart: kube-prometheus-stack
targetRevision: 65.x.x
destination:
server: https://kubernetes.default.svc
namespace: monitoring
syncPolicy:
automated:
prune: true
selfHeal: trueGrafana доступна по:
kubectl port-forward -n monitoring svc/kube-prometheus-stack-grafana 3000:80
Что даёт из коробки:
- Prometheus, Alertmanager, Grafана, kube-state-metrics, node-exporter.
- Готовые алерты по control-plane, pods, узлам; дашборды для k8s/ingress.
Проверки:
kubectl get pods -n monitoring— статус Running.kubectl -n monitoring port-forward svc/kube-prometheus-stack-prometheus 9090:9090и открыть UI.- В Grafana открыть стандартные Kubernetes/Nodes дашборды.
Улучшения:
- Алерты на заполнение диска registry, ошибки ingress, SLA demo‑app.
- Дашборд латентности/доступности demo‑app.
- Опционально включить remote write для долгого хранения.
Получился полноценный DevOps стенд:
- Git → Build → Push → Deploy → Monitor
- GitOps через ArgoCD
- CI/CD через Gitea Actions
- Docker Registry встроенный
- Полная Observability
- k3d кластер с несколькими нодами
Используй как основы для CV, pet‑project или дальнейшей автоматизации.
- Обучение: безопасно тренировать GitOps/CI/CD/мониторинг.
- Тестирование: воспроизведение багов CI или ArgoCD без влияния на прод.
- Собеседования: показать end‑to‑end pipeline в действии.
- Pet‑проекты: быстрый старт для микросервисов.
ImagePullBackOffв demo-app: проверь тег (sha/main), добавь imagePullSecret для registry.- Registry недоступен: порт/TLS/firewall; при HTTP — настрой
insecureSkipVerifyв containerd. - Runner не билдит: нет доступа к
/var/run/docker.sockили k3d в другой WSL-дистрибуции. - ArgoCD Application OutOfSync: нет прав на namespace → добавь манифест Namespace.
- k3d не стартует: проверь RAM/CPU лимиты Docker Desktop.
- Registry: TLS или доверенная сеть, запрети анонимный доступ, отдельные токены для CI.
- ArgoCD: RBAC per project, SSO/BasicAuth, network policies; не храни токены в открытом виде.
- Grafana: смени admin пароль, роли по принципу минимальных прав, ограничь ingress.