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
+}