diff --git a/00_manifest.csv b/00_manifest.csv index 8037e1c..c835a98 100644 --- a/00_manifest.csv +++ b/00_manifest.csv @@ -123,4 +123,21 @@ VKC_LR_03_monitoring_outputs_РемизовКЛ_20260618.tf,CODE,LR_03,main,Вы VKC_PR_M07_01_cicd_REPORT_РемизовКЛ_20260618.md,PR,M07,01,CI/CD с использованием Terraform и GitHub Actions,01_reports/VKC_PR_M07_01_cicd_REPORT_РемизовКЛ_20260618.md,,final, VKC_PR_M07_01_cicd_workflow_РемизовКЛ_20260618.png,EVIDENCE,M07,01,Визуализация workflow GitHub Actions,02_evidence/VKC_PR_M07_01_cicd_workflow_РемизовКЛ_20260618.png,VKC_PR_M07_01_cicd_REPORT_РемизовКЛ_20260618.md,final, VKC_PR_M07_01_cicd_terraform_РемизовКЛ_20260618.yml,CODE,M07,01,Workflow GitHub Actions для Terraform,03_code/VKC_PR_M07_01_cicd_terraform_РемизовКЛ_20260618.yml,,final, +VKC_LR_04_cicd_gitops_REPORT_РемизовКЛ_20260619.md,REPORT,LR_04,main,CI/CD и GitOps (ЛР4),01_reports/VKC_LR_04_cicd_gitops_REPORT_РемизовКЛ_20260619.md,,final, +VKC_LR_04_cicd_gitops_main_РемизовКЛ_20260619.tf,CODE,LR_04,main,Основной файл Terraform,03_code/VKC_LR_04_cicd_gitops_main_РемизовКЛ_20260619.tf,,final, +VKC_LR_04_cicd_gitops_variables_РемизовКЛ_20260619.tf,CODE,LR_04,main,Переменные Terraform,03_code/VKC_LR_04_cicd_gitops_variables_РемизовКЛ_20260619.tf,,final, +VKC_LR_04_cicd_gitops_outputs_РемизовКЛ_20260619.tf,CODE,LR_04,main,Выходные переменные Terraform,03_code/VKC_LR_04_cicd_gitops_outputs_РемизовКЛ_20260619.tf,,final, +VKC_LR_04_cicd_gitops_backend_РемизовКЛ_20260619.tf,CODE,LR_04,main,Настройка бэкенда S3,03_code/VKC_LR_04_cicd_gitops_backend_РемизовКЛ_20260619.tf,,final, +VKC_LR_04_cicd_gitops_deployment_РемизовКЛ_20260619.yaml,CODE,LR_04,main,Манифест Deployment,03_code/VKC_LR_04_cicd_gitops_deployment_РемизовКЛ_20260619.yaml,,final, +VKC_LR_04_cicd_gitops_service_РемизовКЛ_20260619.yaml,CODE,LR_04,main,Манифест Service,03_code/VKC_LR_04_cicd_gitops_service_РемизовКЛ_20260619.yaml,,final, +VKC_LR_04_cicd_gitops_configmap_РемизовКЛ_20260619.yaml,CODE,LR_04,main,Манифест ConfigMap,03_code/VKC_LR_04_cicd_gitops_configmap_РемизовКЛ_20260619.yaml,,final, +VKC_LR_04_cicd_gitops_kustomization_РемизовКЛ_20260619.yaml,CODE,LR_04,main,Манифест Kustomization,03_code/VKC_LR_04_cicd_gitops_kustomization_РемизовКЛ_20260619.yaml,,final, +VKC_LR_04_cicd_gitops_AgroCDsettings_РемизовКЛ_20260619.png,EVIDENCE,LR_04,main,Настройки ArgoCD,02_evidence/VKC_LR_04_cicd_gitops_AgroCDsettings_РемизовКЛ_20260619.png,VKC_LR_04_cicd_gitops_REPORT_РемизовКЛ_20260619.md,final, +VKC_LR_04_cicd_gitops_sync_РемизовКЛ_20260619.png,EVIDENCE,LR_04,main,Синхронизация ArgoCD (OutOfSync),02_evidence/VKC_LR_04_cicd_gitops_sync_РемизовКЛ_20260619.png,VKC_LR_04_cicd_gitops_REPORT_РемизовКЛ_20260619.md,final, +VKC_LR_04_cicd_gitops_SucsessfulSync_РемизовКЛ_20260619.png,EVIDENCE,LR_04,main,Успешная синхронизация ArgoCD,02_evidence/VKC_LR_04_cicd_gitops_SucsessfulSync_РемизовКЛ_20260619.png,VKC_LR_04_cicd_gitops_REPORT_РемизовКЛ_20260619.md,final, +VKC_LR_04_cicd_gitops_networktopology_РемизовКЛ_20260619.png,EVIDENCE,LR_04,main,Топология сети,02_evidence/VKC_LR_04_cicd_gitops_networktopology_РемизовКЛ_20260619.png,VKC_LR_04_cicd_gitops_REPORT_РемизовКЛ_20260619.md,final, +VKC_LR_04_cicd_gitops_k8s_РемизовКЛ_20260619.png,EVIDENCE,LR_04,main,Кластер Kubernetes,02_evidence/VKC_LR_04_cicd_gitops_k8s_РемизовКЛ_20260619.png,VKC_LR_04_cicd_gitops_REPORT_РемизовКЛ_20260619.md,final, +VKC_LR_04_cicd_gitops_s3_РемизовКЛ_20260619.png,EVIDENCE,LR_04,main,Бакет S3 с state-файлом,02_evidence/VKC_LR_04_cicd_gitops_s3_РемизовКЛ_20260619.png,VKC_LR_04_cicd_gitops_REPORT_РемизовКЛ_20260619.md,final, +VKC_LR_04_cicd_gitops_app-config_РемизовКЛ_20260619.png,EVIDENCE,LR_04,main,ConfigMap приложения,02_evidence/VKC_LR_04_cicd_gitops_app-config_РемизовКЛ_20260619.png,VKC_LR_04_cicd_gitops_REPORT_РемизовКЛ_20260619.md,final, +VKC_LR_04_cicd_gitops_log_РемизовКЛ_20260619.log,EVIDENCE,LR_04,main,Лог выполнения команд (установка ArgoCD),02_evidence/VKC_LR_04_cicd_gitops_log_РемизовКЛ_20260619.log,VKC_LR_04_cicd_gitops_REPORT_РемизовКЛ_20260619.md,final, 00_manifest.csv,MANIFEST,all,all,Финальный манифест сдачи,00_manifest.csv,,final, diff --git a/01_reports/VKC_LR_03_monitoring_REPORT_РемизовКЛ_20260618.md b/01_reports/VKC_LR_03_monitoring_REPORT_РемизовКЛ_20260618.md index 76c2c08..0c14cee 100644 --- a/01_reports/VKC_LR_03_monitoring_REPORT_РемизовКЛ_20260618.md +++ b/01_reports/VKC_LR_03_monitoring_REPORT_РемизовКЛ_20260618.md @@ -22,7 +22,6 @@ attached_files: estimated_cost_rub: 36 status: final --- - # Отчет по лабораторной работе №3: Мониторинг и логирование ## 1. Цель работы diff --git a/01_reports/VKC_LR_04_cicd_gitops_REPORT_РемизовКЛ_20260619.md b/01_reports/VKC_LR_04_cicd_gitops_REPORT_РемизовКЛ_20260619.md new file mode 100644 index 0000000..7764dc2 --- /dev/null +++ b/01_reports/VKC_LR_04_cicd_gitops_REPORT_РемизовКЛ_20260619.md @@ -0,0 +1,413 @@ +--- +course_code: VKCLOUD-80 +artifact_type: LR +lab_code: 4 +lab_title: CI/CD и GitOps +student_fio: Ремизов Кирилл Львович +date: 2026-06-19 +source_docs: + - 5-Задания для лабораторных работ -VK-1.md + - 3-Конспект лекций - VK 1.md +attached_files: + - VKC_LR_04_cicd_gitops_main_РемизовКЛ_20260619.tf + - VKC_LR_04_cicd_gitops_variables_РемизовКЛ_20260619.tf + - VKC_LR_04_cicd_gitops_outputs_РемизовКЛ_20260619.tf + - VKC_LR_04_cicd_gitops_backend_РемизовКЛ_20260619.tf + - VKC_LR_04_cicd_gitops_deployment_РемизовКЛ_20260619.yaml + - VKC_LR_04_cicd_gitops_service_РемизовКЛ_20260619.yaml + - VKC_LR_04_cicd_gitops_configmap_РемизовКЛ_20260619.yaml + - VKC_LR_04_cicd_gitops_kustomization_РемизовКЛ_20260619.yaml + - VKC_LR_04_cicd_gitops_log_РемизовКЛ_20260619.log + - VKC_LR_04_cicd_gitops_AgroCDsettings_РемизовКЛ_20260619.png + - VKC_LR_04_cicd_gitops_sync_РемизовКЛ_20260619.png + - VKC_LR_04_cicd_gitops_SucsessfulSync_РемизовКЛ_20260619.png + - VKC_LR_04_cicd_gitops_networktopology_РемизовКЛ_20260619.png + - VKC_LR_04_cicd_gitops_k8s_РемизовКЛ_20260619.png + - VKC_LR_04_cicd_gitops_s3_РемизовКЛ_20260619.png + - VKC_LR_04_cicd_gitops_app-config_РемизовКЛ_20260619.png +estimated_cost_rub: 80 +status: final +--- + +# Отчет по лабораторной работе №4: CI/CD и GitOps + +## Цель работы + +Настроить CI/CD пайплайн для автоматического развертывания инфраструктуры и приложения, освоить GitOps подход с использованием **ArgoCD**. Основные задачи: +- Развернуть инфраструктуру (VPC, веб-серверы, балансировщик) с помощью **Terraform**, используя удаленное состояние в S3. +- Создать кластер **Kubernetes** и установить **ArgoCD**. +- Подготовить Git-репозиторий с манифестами приложения (Deployment, Service, ConfigMap) и настроить автоматическую синхронизацию через ArgoCD. +- Интегрировать Terraform и Kubernetes: передать IP-адрес балансировщика в ConfigMap приложения. + +--- + +## Используемые ресурсы + +| Ресурс | Тип | Параметры | Назначение | +|--------|-----|-----------|-------------| +| VPC `lab4-network` | Virtual Private Cloud | sdn: "sprut" | Изолированная сеть для всех ресурсов | +| Публичная подсеть `lab4-public-subnet` | Subnet | CIDR: 192.168.1.0/24 | Размещение балансировщика и внешних ресурсов | +| Приватная подсеть `lab4-private-subnet` | Subnet | CIDR: 192.168.2.0/24 | Размещение веб-серверов и внутренних ресурсов | +| Веб-серверы `lab4-web-1`, `lab4-web-2` | ВМ (Ubuntu 20.04) | Флейвор `Basic-1-1-10`, приватные IP 192.168.2.10/11 | Обработка HTTP-запросов, работающие за балансировщиком | +| Балансировщик `lab4-lb` | Application Load Balancer | L7, публичный IP 95.163.215.1 | Распределение трафика между веб-серверами | +| Бакет S3 `tf-state-lab4` | Object Storage | Регион ru-msk | Хранение state-файла Terraform (backend) | +| Кластер Kubernetes `lab-4` | Managed K8s | 1 мастер-узел, 1 узел (STD3-1-2) | Среда выполнения контейнеризированного приложения | +| ArgoCD | Kubernetes приложение | Установлено в namespace `argocd` | GitOps-инструмент для синхронизации состояния кластера с Git-репозиторием | + +--- + +## Схема архитектуры + +Архитектура включает две основные части: + +1. **Инфраструктура (Terraform):** + - VPC с двумя подсетями (публичная и приватная). + - Два веб-сервера в приватной подсети с установленным nginx. + - Балансировщик нагрузки в публичной подсети, распределяющий трафик между веб-серверами. + - Бакет S3 для удаленного хранения state-файла. + +2. **Приложение и GitOps (Kubernetes + ArgoCD):** + - Кластер Kubernetes, развернутый отдельно. + - ArgoCD, установленный в кластер и подключенный к Git-репозиторию с манифестами. + - В репозитории находятся: + - `deployment.yaml` – развертывание nginx (2 реплики). + - `service.yaml` – сервис типа LoadBalancer для доступа к приложению. + - `configmap.yaml` – содержит IP-адрес балансировщика инфраструктуры. + - `kustomization.yaml` – для управления ресурсами. + - ArgoCD автоматически синхронизирует состояние кластера с репозиторием. + +![[VKC_LR_04_cicd_gitops_networktopology_РемизовКЛ_20260619.png]] + +--- + +## Ход выполнения + +### Шаг 1. Развертывание инфраструктуры с помощью Terraform + +**Задача:** Автоматизировать создание сети, веб-серверов и балансировщика с использованием Terraform, настроить удаленное состояние в S3. + +**Используемые инструменты:** Terraform (провайдер VKCS), OpenStack CLI, S3. + +**Ключевые изменения в конфигурации Terraform:** + +1. **Настройка бэкенда S3** (`backend.tf`): + ```hcl + terraform { + backend "s3" { + bucket = "tf-state-lab4" + key = "lab4/terraform.tfstate" + region = "ru-msk" + endpoint = "https://hb.ru-msk.vkcloud-storage.ru" + skip_region_validation = true + skip_credentials_validation = true + skip_metadata_api_check = true + } + } + ``` + +2. **Создание сети и подсетей** – аналогично предыдущим работам. + +3. **Создание двух веб-серверов** через `count`: + ```hcl + resource "vkcs_compute_instance" "web" { + count = 2 + name = "${var.project_name}-web-${count.index + 1}" + flavor_id = data.vkcs_compute_flavor.web.id + # ... + network { + fixed_ip_v4 = cidrhost(var.private_subnet_cidr, count.index + 10) + } + user_data = <<-EOF + #!/bin/bash + apt update + apt install -y nginx + echo "

Web Server $(hostname)

" > /var/www/html/index.html + systemctl enable nginx + systemctl start nginx + EOF + } + ``` + +4. **Балансировщик нагрузки** и его настройка (слушатель, пул, монитор, члены). + +5. **Выходные переменные** (`outputs.tf`): + ```hcl + output "load_balancer_ip" { + value = vkcs_networking_floatingip.lb.address + } + ``` + +**Применение Terraform:** + +```bash +terraform init +terraform plan +terraform apply -auto-approve +``` + +В результате был получен публичный IP балансировщика – `95.163.215.1`. State-файл успешно сохранился в бакете `tf-state-lab4` (папка `lab4/`). + +![[VKC_LR_04_cicd_gitops_s3_РемизовКЛ_20260619.png]] + +--- + +### Шаг 2. Создание кластера Kubernetes + +**Задача:** Создать управляемый кластер Kubernetes для размещения приложения. + +**Действия:** +- В консоли VK Cloud создан кластер с именем `lab-4` (1 мастер-узел, 1 рабочий узел, конфигурация STD3-1-2). +- Получен конфигурационный файл `kubeconfig` для доступа к кластеру. + +![[VKC_LR_04_cicd_gitops_k8s_РемизовКЛ_20260619.png]] + +--- + +### Шаг 3. Установка ArgoCD + +**Задача:** Развернуть ArgoCD в кластере Kubernetes и получить доступ к UI. + +**Действия:** + +1. Создание namespace `argocd`: + ```bash + kubectl create namespace argocd + ``` + +2. Установка ArgoCD из официального манифеста: + ```bash + kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml --server-side + ``` + +3. Проверка запуска подов: + ```bash + kubectl get pods -n argocd + ``` + Все поды перешли в состояние `Running`. + +4. Получение пароля администратора: + ```bash + kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d + ``` + Пароль: `weSuC1mk3y7zG3Hp` (сгенерирован автоматически). + +5. Настройка доступа к ArgoCD через port-forward: + ```bash + kubectl port-forward svc/argocd-server -n argocd 8080:443 + ``` + После этого интерфейс ArgoCD стал доступен по адресу `https://localhost:8080`. + +![[VKC_LR_04_cicd_gitops_AgroCDsettings_РемизовКЛ_20260619.png]] + +--- + +### Шаг 4. Подготовка манифестов приложения + +**Задача:** Создать Git-репозиторий с манифестами Kubernetes для развертывания приложения (nginx) и настроить Kustomize. + +**Состав манифестов:** + +**deployment.yaml:** +```yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: nginx-deployment + namespace: web-app + labels: + app: nginx +spec: + replicas: 2 + selector: + matchLabels: + app: nginx + template: + metadata: + labels: + app: nginx + spec: + containers: + - name: nginx + image: nginx:1.21.6 + ports: + - containerPort: 80 +``` + +**service.yaml:** +```yaml +apiVersion: v1 +kind: Service +metadata: + name: nginx-service + namespace: web-app +spec: + selector: + app: nginx + ports: + - protocol: TCP + port: 80 + targetPort: 80 + type: LoadBalancer +``` + +**configmap.yaml:** +```yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: app-config + namespace: web-app +data: + LB_IP: "95.163.215.1" +``` + +**kustomization.yaml:** +```yaml +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: +- deployment.yaml +- service.yaml +- configmap.yaml +``` + +--- + +### Шаг 5. Настройка приложения в ArgoCD и синхронизация + +**Задача:** Создать Application в ArgoCD, указав репозиторий с манифестами, и выполнить синхронизацию. + +**Действия:** + +1. В UI ArgoCD добавлен новый Application: + - **Имя:** `lab4` + - **Проект:** `default` + - **Репозиторий:** `https://github.com/BlackCorbear/lab4` + - **Путь:** `kubernetes/` + - **Целевая ревизия:** `main` + - **Кластер:** `in-cluster` + - **Namespace:** `web-app` + +2. Включена автоматическая синхронизация (`Auto-Sync`) с опциями `Prune Resources` и `SelfHeal`. + +3. После создания Application ArgoCD показал состояние **OutOfSync**. Нажата кнопка **Sync**. + +![[VKC_LR_04_cicd_gitops_sync_РемизовКЛ_20260619.png]] + +4. Синхронизация прошла успешно – все ресурсы созданы, Application перешло в состояние **Synced** и **Healthy**. + +![[VKC_LR_04_cicd_gitops_SucsessfulSync_РемизовКЛ_20260619.png]] + +--- + +### Шаг 6. Проверка работы приложения и ConfigMap + +**Задача:** Убедиться, что приложение развернуто, сервис получил внешний IP, а ConfigMap содержит корректный IP балансировщика. + +**Проверка ConfigMap:** +```bash +kubectl get configmap app-config -n web-app -o yaml +``` +Вывод: +```yaml +apiVersion: v1 +data: + LB_IP: 95.163.215.1 +kind: ConfigMap +metadata: + annotations: + argocd.argoproj.io/tracking-id: lab4:/ConfigMap:web-app/app-config + kubectl.kubernetes.io/last-applied-configuration: | + {"apiVersion":"v1","data":{"LB_IP":"95.163.215.1"},"kind":"ConfigMap",...} + name: app-config + namespace: web-app + ... +``` + +Значение `LB_IP` соответствует IP балансировщика из Terraform, что подтверждает успешную интеграцию. + +![[VKC_LR_04_cicd_gitops_app-config_РемизовКЛ_20260619.png]] + +**Доступность приложения:** +- Сервис типа LoadBalancer получил внешний IP. +- При обращении к этому IP открывается страница nginx. + +--- + +## Критерии успеха + +| Критерий | Статус | Подтверждение | +|----------|--------|----------------| +| Инфраструктура развернута через Terraform с S3 backend | ✅ | State-файл в бакете, скриншот бакета | +| Кластер Kubernetes создан | ✅ | Скриншот кластера | +| ArgoCD установлен и доступен | ✅ | Лог установки, скриншот ArgoCD Settings | +| Манифесты приложения подготовлены | ✅ | Файлы приложены, скриншот ConfigMap | +| Application в ArgoCD синхронизирован | ✅ | Скриншот Successful Sync | +| ConfigMap содержит корректный IP балансировщика | ✅ | Вывод `kubectl get configmap` | + +--- + +## Ответы на вопросы для отчета + +**Вопрос 1:** *Что такое GitOps и в чем его преимущества по сравнению с традиционным CI/CD?* +**Ответ:** GitOps – это подход к управлению инфраструктурой и приложениями, при котором Git-репозиторий является единственным источником истины (single source of truth) для декларативного описания желаемого состояния системы. ArgoCD постоянно сравнивает состояние кластера с состоянием в Git и автоматически применяет изменения. Преимущества: повышенная прозрачность (все изменения в Git), простота отката, автоматическая синхронизация (self-healing), упрощение аудита. + +**Вопрос 2:** *Как ArgoCD синхронизируется с Git-репозиторием?* +**Ответ:** ArgoCD периодически опрашивает репозиторий (или получает уведомления через webhook) и сравнивает манифесты в Git с текущим состоянием ресурсов в кластере. При обнаружении расхождений ArgoCD может выполнить автоматическую синхронизацию (если включено) или показать diff для ручного применения. + +**Вопрос 3:** *Как Terraform может обновлять манифесты Kubernetes (например, ConfigMap) при изменении IP балансировщика?* +**Ответ:** Можно использовать механизм шаблонизации в Terraform: после применения изменений Terraform генерирует YAML-файл ConfigMap с новым IP, используя `templatefile` или `local_file`. Затем этот файл коммитится и пушится в Git-репозиторий, после чего ArgoCD автоматически подхватывает изменения. + +**Вопрос 4:** *Как в Terraform организовано создание двух идентичных ВМ?* +**Ответ:** Используется мета-аргумент `count`. В блоке ресурса задается `count = 2`, и внутри ресурса используются ссылки на `count.index` для генерации уникальных имен и IP-адресов. + +**Вопрос 5:** *Какие преимущества дает использование Kustomize в GitOps-пайплайне?* +**Ответ:** Kustomize позволяет управлять конфигурацией без шаблонизации, используя патчи и наложения (overlays). Это упрощает поддержку разных окружений (dev/staging/prod) – можно иметь базовые манифесты и переопределять только отличающиеся параметры. + +--- + +## Выводы + +В ходе лабораторной работы был реализован полный цикл CI/CD и GitOps для автоматизации развертывания инфраструктуры и приложения: + +- Развернута инфраструктура (VPC, веб-серверы, балансировщик) с помощью Terraform с удаленным состоянием в S3. +- Создан кластер Kubernetes и установлен ArgoCD – инструмент GitOps. +- Подготовлены манифесты приложения с использованием Kustomize. +- Выполнена интеграция Terraform и Kubernetes через передачу IP-адреса балансировщика в ConfigMap. +- Настроена автоматическая синхронизация ArgoCD, гарантирующая, что кластер всегда соответствует описанию в Git. + +Полученные навыки позволяют строить production-решения с высокой степенью автоматизации, наблюдаемости и надежности. + +--- + +## Оценка затрат + +За время выполнения работы (~4 часа) использовались следующие ресурсы: + +| Ресурс | Стоимость (руб/час) | Время (часы) | Сумма (руб) | +|--------|---------------------|--------------|-------------| +| Веб-серверы (2 шт., Basic-1-1-10) | ~3×2 | 4 | 24 | +| Балансировщик | ~2 | 4 | 8 | +| Публичный IP (балансировщик) | ~1 | 4 | 4 | +| Бакет S3 (хранение state) | ~0.02 | 4 | 0.08 | +| Кластер Kubernetes (STD3-1-2) | ~10 | 4 | 40 | +| **Итого** | | | **~76** | + +Округлённо **≈ 80 руб.** Все ресурсы были удалены после завершения работы. + +--- + +## Приложенные файлы + +| Файл | Тип | Описание | +|------|-----|----------| +| `VKC_LR_04_cicd_gitops_main_РемизовКЛ_20260619.tf` | Terraform | Основной файл конфигурации инфраструктуры | +| `VKC_LR_04_cicd_gitops_variables_РемизовКЛ_20260619.tf` | Terraform | Переменные | +| `VKC_LR_04_cicd_gitops_outputs_РемизовКЛ_20260619.tf` | Terraform | Выходные переменные | +| `VKC_LR_04_cicd_gitops_backend_РемизовКЛ_20260619.tf` | Terraform | Настройка бэкенда S3 | +| `VKC_LR_04_cicd_gitops_deployment_РемизовКЛ_20260619.yaml` | Kubernetes | Манифест Deployment | +| `VKC_LR_04_cicd_gitops_service_РемизовКЛ_20260619.yaml` | Kubernetes | Манифест Service | +| `VKC_LR_04_cicd_gitops_configmap_РемизовКЛ_20260619.yaml` | Kubernetes | Манифест ConfigMap | +| `VKC_LR_04_cicd_gitops_kustomization_РемизовКЛ_20260619.yaml` | Kubernetes | Kustomization | +| `VKC_LR_04_cicd_gitops_log_РемизовКЛ_20260619.log` | Лог | Вывод команд | +| Скриншоты | PNG | Настройки ArgoCD, синхронизация, топология, кластер, бакет, ConfigMap | diff --git a/02_evidence/VKC_LR_04_cicd_gitops_AgroCDsettings_РемизовКЛ_20260619.png b/02_evidence/VKC_LR_04_cicd_gitops_AgroCDsettings_РемизовКЛ_20260619.png new file mode 100644 index 0000000..e6ae95e Binary files /dev/null and b/02_evidence/VKC_LR_04_cicd_gitops_AgroCDsettings_РемизовКЛ_20260619.png differ diff --git a/02_evidence/VKC_LR_04_cicd_gitops_SucsessfulSync_РемизовКЛ_20260619.png b/02_evidence/VKC_LR_04_cicd_gitops_SucsessfulSync_РемизовКЛ_20260619.png new file mode 100644 index 0000000..f0f6eb6 Binary files /dev/null and b/02_evidence/VKC_LR_04_cicd_gitops_SucsessfulSync_РемизовКЛ_20260619.png differ diff --git a/02_evidence/VKC_LR_04_cicd_gitops_app-config_РемизовКЛ_20260619.png b/02_evidence/VKC_LR_04_cicd_gitops_app-config_РемизовКЛ_20260619.png new file mode 100644 index 0000000..69e181a Binary files /dev/null and b/02_evidence/VKC_LR_04_cicd_gitops_app-config_РемизовКЛ_20260619.png differ diff --git a/02_evidence/VKC_LR_04_cicd_gitops_k8s_РемизовКЛ_20260619.png b/02_evidence/VKC_LR_04_cicd_gitops_k8s_РемизовКЛ_20260619.png new file mode 100644 index 0000000..6acea42 Binary files /dev/null and b/02_evidence/VKC_LR_04_cicd_gitops_k8s_РемизовКЛ_20260619.png differ diff --git a/02_evidence/VKC_LR_04_cicd_gitops_log_РемизовКЛ_20260619.log b/02_evidence/VKC_LR_04_cicd_gitops_log_РемизовКЛ_20260619.log new file mode 100644 index 0000000..791e376 --- /dev/null +++ b/02_evidence/VKC_LR_04_cicd_gitops_log_РемизовКЛ_20260619.log @@ -0,0 +1,86 @@ + ~/r/lab4 on main [ok] +nix-shell ❯ kubectl create namespace argocd on ☁️ (ru-msk) +namespace/argocd created + + ~/r/lab4 on main [ok] +nix-shell ❯ kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml --server-side on ☁️ (ru-msk) +customresourcedefinition.apiextensions.k8s.io/applications.argoproj.io serverside-applied +customresourcedefinition.apiextensions.k8s.io/applicationsets.argoproj.io serverside-applied +customresourcedefinition.apiextensions.k8s.io/appprojects.argoproj.io serverside-applied +serviceaccount/argocd-application-controller serverside-applied +serviceaccount/argocd-applicationset-controller serverside-applied +serviceaccount/argocd-dex-server serverside-applied +serviceaccount/argocd-notifications-controller serverside-applied +serviceaccount/argocd-redis serverside-applied +serviceaccount/argocd-repo-server serverside-applied +serviceaccount/argocd-server serverside-applied +role.rbac.authorization.k8s.io/argocd-application-controller serverside-applied +role.rbac.authorization.k8s.io/argocd-applicationset-controller serverside-applied +role.rbac.authorization.k8s.io/argocd-dex-server serverside-applied +role.rbac.authorization.k8s.io/argocd-notifications-controller serverside-applied +role.rbac.authorization.k8s.io/argocd-redis serverside-applied +role.rbac.authorization.k8s.io/argocd-server serverside-applied +clusterrole.rbac.authorization.k8s.io/argocd-application-controller serverside-applied +clusterrole.rbac.authorization.k8s.io/argocd-applicationset-controller serverside-applied +clusterrole.rbac.authorization.k8s.io/argocd-server serverside-applied +rolebinding.rbac.authorization.k8s.io/argocd-application-controller serverside-applied +rolebinding.rbac.authorization.k8s.io/argocd-applicationset-controller serverside-applied +rolebinding.rbac.authorization.k8s.io/argocd-dex-server serverside-applied +rolebinding.rbac.authorization.k8s.io/argocd-notifications-controller serverside-applied +rolebinding.rbac.authorization.k8s.io/argocd-redis serverside-applied +rolebinding.rbac.authorization.k8s.io/argocd-server serverside-applied +clusterrolebinding.rbac.authorization.k8s.io/argocd-application-controller serverside-applied +clusterrolebinding.rbac.authorization.k8s.io/argocd-applicationset-controller serverside-applied +clusterrolebinding.rbac.authorization.k8s.io/argocd-server serverside-applied +configmap/argocd-cm serverside-applied +configmap/argocd-cmd-params-cm serverside-applied +configmap/argocd-gpg-keys-cm serverside-applied +configmap/argocd-notifications-cm serverside-applied +configmap/argocd-rbac-cm serverside-applied +configmap/argocd-ssh-known-hosts-cm serverside-applied +configmap/argocd-tls-certs-cm serverside-applied +secret/argocd-notifications-secret serverside-applied +secret/argocd-secret serverside-applied +service/argocd-applicationset-controller serverside-applied +service/argocd-dex-server serverside-applied +service/argocd-metrics serverside-applied +service/argocd-notifications-controller-metrics serverside-applied +service/argocd-redis serverside-applied +service/argocd-repo-server serverside-applied +service/argocd-server serverside-applied +service/argocd-server-metrics serverside-applied +deployment.apps/argocd-applicationset-controller serverside-applied +deployment.apps/argocd-dex-server serverside-applied +deployment.apps/argocd-notifications-controller serverside-applied +deployment.apps/argocd-redis serverside-applied +deployment.apps/argocd-repo-server serverside-applied +deployment.apps/argocd-server serverside-applied +statefulset.apps/argocd-application-controller serverside-applied +networkpolicy.networking.k8s.io/argocd-application-controller-network-policy serverside-applied +networkpolicy.networking.k8s.io/argocd-applicationset-controller-network-policy serverside-applied +networkpolicy.networking.k8s.io/argocd-dex-server-network-policy serverside-applied +networkpolicy.networking.k8s.io/argocd-notifications-controller-network-policy serverside-applied +networkpolicy.networking.k8s.io/argocd-redis-network-policy serverside-applied +networkpolicy.networking.k8s.io/argocd-repo-server-network-policy serverside-applied +networkpolicy.networking.k8s.io/argocd-server-network-policy serverside-applied + + ~/r/lab4 on main [ok] +nix-shell ❯ kubectl get pods -n argocd on ☁️ (ru-msk) +NAME READY STATUS RESTARTS AGE +argocd-application-controller-0 1/1 Running 0 43s +argocd-applicationset-controller-78d66cfd5b-9rzxc 1/1 Running 0 44s +argocd-dex-server-795b9b7569-lllcw 1/1 Running 0 43s +argocd-notifications-controller-85db9b54dd-tvs55 1/1 Running 0 43s +argocd-redis-5c7789bdf-bxfrm 1/1 Running 0 43s +argocd-repo-server-575f949f6-8kkpg 1/1 Running 0 43s +argocd-server-78bf4dfbcb-g9x4j 1/1 Running 0 43s + + ~/r/lab4 on main [ok] +nix-shell ❯ kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d && echo on ☁️ (ru-msk) +weSuC1mk3y7zG3Hp + + ~/r/lab4 on main [ok] +nix-shell ❯ kubectl port-forward svc/argocd-server -n argocd 8080:443 on ☁️ (ru-msk) +Forwarding from 127.0.0.1:8080 -> 8080 +Forwarding from [::1]:8080 -> 8080 + diff --git a/02_evidence/VKC_LR_04_cicd_gitops_networktopology_РемизовКЛ_20260619.png b/02_evidence/VKC_LR_04_cicd_gitops_networktopology_РемизовКЛ_20260619.png new file mode 100644 index 0000000..cb6af36 Binary files /dev/null and b/02_evidence/VKC_LR_04_cicd_gitops_networktopology_РемизовКЛ_20260619.png differ diff --git a/02_evidence/VKC_LR_04_cicd_gitops_s3_РемизовКЛ_20260619.png b/02_evidence/VKC_LR_04_cicd_gitops_s3_РемизовКЛ_20260619.png new file mode 100644 index 0000000..cc77105 Binary files /dev/null and b/02_evidence/VKC_LR_04_cicd_gitops_s3_РемизовКЛ_20260619.png differ diff --git a/02_evidence/VKC_LR_04_cicd_gitops_sync_РемизовКЛ_20260619.png b/02_evidence/VKC_LR_04_cicd_gitops_sync_РемизовКЛ_20260619.png new file mode 100644 index 0000000..e85f19c Binary files /dev/null and b/02_evidence/VKC_LR_04_cicd_gitops_sync_РемизовКЛ_20260619.png differ diff --git a/03_code/VKC_LR_04_cicd_gitops_backend_РемизовКЛ_20260619.tf b/03_code/VKC_LR_04_cicd_gitops_backend_РемизовКЛ_20260619.tf new file mode 100644 index 0000000..f5de654 --- /dev/null +++ b/03_code/VKC_LR_04_cicd_gitops_backend_РемизовКЛ_20260619.tf @@ -0,0 +1,11 @@ +terraform { + backend "s3" { + bucket = "tf-state-lab4" # имя твоего бакета (должен существовать) + key = "lab4/terraform.tfstate" # путь к файлу состояния внутри бакета + region = "ru-msk" # твой регион + endpoint = "https://hb.ru-msk.vkcloud-storage.ru" + skip_region_validation = true + skip_credentials_validation = true + skip_metadata_api_check = true + } +} diff --git a/03_code/VKC_LR_04_cicd_gitops_configmap_РемизовКЛ_20260619.yaml b/03_code/VKC_LR_04_cicd_gitops_configmap_РемизовКЛ_20260619.yaml new file mode 100644 index 0000000..09653a6 --- /dev/null +++ b/03_code/VKC_LR_04_cicd_gitops_configmap_РемизовКЛ_20260619.yaml @@ -0,0 +1,7 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: app-config + namespace: web-app +data: + LB_IP: "95.163.215.1" diff --git a/03_code/VKC_LR_04_cicd_gitops_deployment_РемизовКЛ_20260619.yaml b/03_code/VKC_LR_04_cicd_gitops_deployment_РемизовКЛ_20260619.yaml new file mode 100644 index 0000000..fd5763c --- /dev/null +++ b/03_code/VKC_LR_04_cicd_gitops_deployment_РемизовКЛ_20260619.yaml @@ -0,0 +1,22 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: nginx-deployment + namespace: web-app + labels: + app: nginx +spec: + replicas: 2 + selector: + matchLabels: + app: nginx + template: + metadata: + labels: + app: nginx + spec: + containers: + - name: nginx + image: nginx:1.21.6 + ports: + - containerPort: 80 diff --git a/03_code/VKC_LR_04_cicd_gitops_kustomization_РемизовКЛ_20260619.yaml b/03_code/VKC_LR_04_cicd_gitops_kustomization_РемизовКЛ_20260619.yaml new file mode 100644 index 0000000..5a4504f --- /dev/null +++ b/03_code/VKC_LR_04_cicd_gitops_kustomization_РемизовКЛ_20260619.yaml @@ -0,0 +1,6 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: +- deployment.yaml +- service.yaml +- configmap.yaml diff --git a/03_code/VKC_LR_04_cicd_gitops_main_РемизовКЛ_20260619.tf b/03_code/VKC_LR_04_cicd_gitops_main_РемизовКЛ_20260619.tf new file mode 100644 index 0000000..bfc5ad0 --- /dev/null +++ b/03_code/VKC_LR_04_cicd_gitops_main_РемизовКЛ_20260619.tf @@ -0,0 +1,177 @@ +terraform { + required_providers { + vkcs = { + source = "vk-cs/vkcs" + version = "~> 0.1" + } + } +} + +provider "vkcs" { + username = var.vkcs_username + password = var.vkcs_password + project_id = var.vkcs_project_id + region = var.vkcs_region + auth_url = var.vkcs_auth_url +} + +data "vkcs_networking_network" "extnet" { + name = var.external_network_name +} + +data "vkcs_networking_router" "router" { + id = var.router_id +} + +data "vkcs_images_image" "ubuntu" { + name = var.image_name +} + +data "vkcs_compute_flavor" "web" { + name = var.flavor_web +} + +resource "vkcs_networking_network" "main" { + name = "${var.project_name}-network" + sdn = "sprut" +} + +resource "vkcs_networking_subnet" "public" { + name = "${var.project_name}-public-subnet" + network_id = vkcs_networking_network.main.id + cidr = var.public_subnet_cidr + dns_nameservers = ["8.8.8.8", "1.1.1.1"] +} + +resource "vkcs_networking_subnet" "private" { + name = "${var.project_name}-private-subnet" + network_id = vkcs_networking_network.main.id + cidr = var.private_subnet_cidr + dns_nameservers = ["8.8.8.8", "1.1.1.1"] +} + +resource "vkcs_networking_router_interface" "public" { + router_id = data.vkcs_networking_router.router.id + subnet_id = vkcs_networking_subnet.public.id +} + +resource "vkcs_networking_router_interface" "private" { + router_id = data.vkcs_networking_router.router.id + subnet_id = vkcs_networking_subnet.private.id +} + +resource "vkcs_networking_secgroup" "web" { + name = "${var.project_name}-secgroup" + description = "Allow SSH and HTTP" +} + +resource "vkcs_networking_secgroup_rule" "ssh" { + security_group_id = vkcs_networking_secgroup.web.id + direction = "ingress" + protocol = "tcp" + port_range_min = 22 + port_range_max = 22 + remote_ip_prefix = "${var.my_ip}/32" +} + +resource "vkcs_networking_secgroup_rule" "http" { + security_group_id = vkcs_networking_secgroup.web.id + direction = "ingress" + protocol = "tcp" + port_range_min = 80 + port_range_max = 80 + remote_ip_prefix = "0.0.0.0/0" +} + +resource "vkcs_networking_secgroup_rule" "egress" { + security_group_id = vkcs_networking_secgroup.web.id + direction = "egress" + remote_ip_prefix = "0.0.0.0/0" +} + +resource "vkcs_compute_keypair" "my_key" { + name = "${var.project_name}-key" + public_key = file(var.ssh_public_key) +} + +resource "vkcs_compute_instance" "web" { + count = 2 + name = "${var.project_name}-web-${count.index + 1}" + flavor_id = data.vkcs_compute_flavor.web.id + key_pair = vkcs_compute_keypair.my_key.name + security_group_ids = [vkcs_networking_secgroup.web.id] + availability_zone = "MS1" + + block_device { + uuid = data.vkcs_images_image.ubuntu.id + source_type = "image" + destination_type = "volume" + volume_type = "ceph-ssd" + volume_size = var.volume_size_web + boot_index = 0 + delete_on_termination = true + } + + network { + uuid = vkcs_networking_network.main.id + fixed_ip_v4 = cidrhost(var.private_subnet_cidr, count.index + 10) + } + + user_data = <<-EOF + #!/bin/bash + apt update + apt install -y nginx + echo "

Web Server $(hostname)

" > /var/www/html/index.html + systemctl enable nginx + systemctl start nginx + EOF +} + +locals { + web_private_ips = vkcs_compute_instance.web[*].network[0].fixed_ip_v4 +} + +resource "vkcs_lb_loadbalancer" "main" { + name = "${var.project_name}-lb" + vip_subnet_id = vkcs_networking_subnet.public.id +} + +resource "vkcs_lb_listener" "http" { + name = "${var.project_name}-listener" + loadbalancer_id = vkcs_lb_loadbalancer.main.id + protocol = "HTTP" + protocol_port = 80 +} + +resource "vkcs_lb_pool" "web" { + name = "${var.project_name}-pool" + protocol = "HTTP" + lb_method = "ROUND_ROBIN" + listener_id = vkcs_lb_listener.http.id +} + +resource "vkcs_lb_monitor" "web" { + pool_id = vkcs_lb_pool.web.id + type = "HTTP" + url_path = "/" + delay = 10 + timeout = 5 + max_retries = 3 +} + +resource "vkcs_lb_member" "web" { + count = 2 + pool_id = vkcs_lb_pool.web.id + address = local.web_private_ips[count.index] + protocol_port = 80 + subnet_id = vkcs_networking_subnet.private.id +} + +resource "vkcs_networking_floatingip" "lb" { + pool = data.vkcs_networking_network.extnet.name +} + +resource "vkcs_networking_floatingip_associate" "lb" { + floating_ip = vkcs_networking_floatingip.lb.address + port_id = vkcs_lb_loadbalancer.main.vip_port_id +} diff --git a/03_code/VKC_LR_04_cicd_gitops_outputs_РемизовКЛ_20260619.tf b/03_code/VKC_LR_04_cicd_gitops_outputs_РемизовКЛ_20260619.tf new file mode 100644 index 0000000..8502ee7 --- /dev/null +++ b/03_code/VKC_LR_04_cicd_gitops_outputs_РемизовКЛ_20260619.tf @@ -0,0 +1,14 @@ +output "load_balancer_ip" { + value = vkcs_networking_floatingip.lb.address + description = "Публичный IP балансировщика" +} + +output "web_private_ips" { + value = local.web_private_ips + description = "Приватные IP веб-серверов" +} + +output "lb_url" { + value = "http://${vkcs_networking_floatingip.lb.address}" + description = "URL для доступа к приложению" +} diff --git a/03_code/VKC_LR_04_cicd_gitops_service_РемизовКЛ_20260619.yaml b/03_code/VKC_LR_04_cicd_gitops_service_РемизовКЛ_20260619.yaml new file mode 100644 index 0000000..1899223 --- /dev/null +++ b/03_code/VKC_LR_04_cicd_gitops_service_РемизовКЛ_20260619.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Service +metadata: + name: nginx-service + namespace: web-app +spec: + selector: + app: nginx + ports: + - protocol: TCP + port: 80 + targetPort: 80 + type: LoadBalancer diff --git a/03_code/VKC_LR_04_cicd_gitops_variables_РемизовКЛ_20260619.tf b/03_code/VKC_LR_04_cicd_gitops_variables_РемизовКЛ_20260619.tf new file mode 100644 index 0000000..cb886d2 --- /dev/null +++ b/03_code/VKC_LR_04_cicd_gitops_variables_РемизовКЛ_20260619.tf @@ -0,0 +1,102 @@ +variable "my_ip" { + description = "Ваш публичный IP для SSH (узнать через curl ifconfig.me)" + type = string + sensitive = true +} + +variable "project_name" { + description = "Префикс для имен ресурсов" + type = string + default = "lab4" +} + +variable "router_id" { + description = "ID существующего роутера" + type = string + default = "913bdd47-9155-45b2-b404-5c10d0086132" +} + +variable "external_network_name" { + description = "Имя внешней сети для Floating IP" + type = string + default = "internet" +} + +variable "ssh_public_key" { + description = "Путь к публичному SSH-ключу" + type = string + default = "~/.ssh/id_rsa.pub" +} + +variable "image_name" { + description = "Имя образа Ubuntu 20.04" + type = string + default = "ubuntu-20-202602051631.gite7a38aaf" +} + +variable "flavor_web" { + description = "Flavor для веб-серверов (используется только как ID, т.к. загрузка с тома)" + type = string + default = "Basic-1-1-10" +} + +variable "flavor_bastion" { + description = "Flavor для ВМ бастиона" + type = string + default = "Basic-1-1-10" +} + +variable "public_subnet_cidr" { + description = "CIDR публичной подсети" + type = string + default = "192.168.1.0/24" +} + +variable "private_subnet_cidr" { + description = "CIDR приватной подсети" + type = string + default = "192.168.2.0/24" +} + +variable "volume_size_web" { + description = "Размер диска для веб-серверов (ГБ)" + type = number + default = 10 +} + +variable "volume_size_bastion" { + description = "Размер диска для бастиона (ГБ)" + type = number + default = 20 +} + +# --- Аутентификация VKCS --- +variable "vkcs_username" { + description = "VK Cloud username (из RC-файла)" + type = string + sensitive = true +} + +variable "vkcs_password" { + description = "VK Cloud password" + type = string + sensitive = true +} + +variable "vkcs_project_id" { + description = "VK Cloud project ID (из RC-файла)" + type = string + sensitive = true +} + +variable "vkcs_region" { + description = "VK Cloud region (например, RegionOne или MS1)" + type = string + default = "RegionOne" +} + +variable "vkcs_auth_url" { + description = "VK Cloud Auth URL (например, https://infra.mail.ru:35357/v3/)" + type = string + sensitive = true +}