Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b76898970b | ||
|
|
0302da1fd7 | ||
|
|
2c2f8d0d59 | ||
|
|
9f5e8ad4f8 | ||
|
|
aac766d4a5 | ||
|
|
cc1e9c2320 | ||
|
|
b2713667e6 | ||
|
|
ee54718ba0 | ||
|
|
b599bd410b | ||
|
|
b0e5a6b653 |
No files matched your search
@@ -73,4 +73,86 @@ VKC_PR_M05_01_terraform_REPORT_РемизовКЛ_20260615.md,PR,M05,01,Infrastr
|
|||||||
VKC_PR_M05_01_terraformLog_РемизовКЛ_20260615.log,EVIDENCE,M05,01,Infrastructure as Code с Terraform,02_evidence/VKC_PR_M05_01_terraformLog_РемизовКЛ_20260615.log,VKC_PR_M05_01_terraform_REPORT_РемизовКЛ_20260615.md,final,
|
VKC_PR_M05_01_terraformLog_РемизовКЛ_20260615.log,EVIDENCE,M05,01,Infrastructure as Code с Terraform,02_evidence/VKC_PR_M05_01_terraformLog_РемизовКЛ_20260615.log,VKC_PR_M05_01_terraform_REPORT_РемизовКЛ_20260615.md,final,
|
||||||
VKC_PR_M05_01_network_РемизовКЛ_20260615.png,EVIDENCE,M05,01,Infrastructure as Code с Terraform,02_evidence/VKC_PR_M05_01_network_РемизовКЛ_20260615.png,VKC_PR_M05_01_terraform_REPORT_РемизовКЛ_20260615.md,final,
|
VKC_PR_M05_01_network_РемизовКЛ_20260615.png,EVIDENCE,M05,01,Infrastructure as Code с Terraform,02_evidence/VKC_PR_M05_01_network_РемизовКЛ_20260615.png,VKC_PR_M05_01_terraform_REPORT_РемизовКЛ_20260615.md,final,
|
||||||
VKC_PR_M05_01_complete-infra_РемизовКЛ_20260615.tf,CODE,M05,01,Infrastructure as Code с Terraform,03_code/VKC_PR_M05_01_complete-infra_РемизовКЛ_20260615.tf,,final,
|
VKC_PR_M05_01_complete-infra_РемизовКЛ_20260615.tf,CODE,M05,01,Infrastructure as Code с Terraform,03_code/VKC_PR_M05_01_complete-infra_РемизовКЛ_20260615.tf,,final,
|
||||||
|
VKC_PR_M05_02_k8s_REPORT_РемизовКЛ_20260615.md,PR,M05,02,Работа с Kubernetes (MK8s),01_reports/VKC_PR_M05_02_k8s_REPORT_РемизовКЛ_20260615.md,,final,
|
||||||
|
VKC_PR_M05_02_k8s_my-k8s_РемизовКЛ_20260615.png,EVIDENCE,M05,02,Созданный кластер Kubernetes,02_evidence/VKC_PR_M05_02_k8s_my-k8s_РемизовКЛ_20260615.png,VKC_PR_M05_02_k8s_REPORT_РемизовКЛ_20260615.md,final,
|
||||||
|
VKC_PR_M05_02_k8s_stage2log_РемизовКЛ_20260615.log,EVIDENCE,M05,02,Лог подключения к кластеру (kubectl get nodes/pods),02_evidence/VKC_PR_M05_02_k8s_stage2log_РемизовКЛ_20260615.log,VKC_PR_M05_02_k8s_REPORT_РемизовКЛ_20260615.md,final,
|
||||||
|
VKC_PR_M05_02_k8s_stage3log_РемизовКЛ_20260615.log,EVIDENCE,M05,02,Лог применения манифеста и ожидания External-IP,02_evidence/VKC_PR_M05_02_k8s_stage3log_РемизовКЛ_20260615.log,VKC_PR_M05_02_k8s_REPORT_РемизовКЛ_20260615.md,final,
|
||||||
|
VKC_PR_M05_02_k8s_stage3pruf_РемизовКЛ_20260615.png,EVIDENCE,M05,02,Страница nginx по внешнему IP балансировщика,02_evidence/VKC_PR_M05_02_k8s_stage3pruf_РемизовКЛ_20260615.png,VKC_PR_M05_02_k8s_REPORT_РемизовКЛ_20260615.md,final,
|
||||||
|
VKC_PR_M05_02_k8s_deployment_РемизовКЛ_20260615.yaml,CODE,M05,02,Манифест Deployment и Service LoadBalancer,03_code/VKC_PR_M05_02_k8s_deployment_РемизовКЛ_20260615.yaml,VKC_PR_M05_02_k8s_REPORT_РемизовКЛ_20260615.md,final,
|
||||||
|
VKC_PR_M05_03_packer_REPORT_РемизовКЛ_20260616.md,PR,M05,03,Создание образов с Packer,01_reports/VKC_PR_M05_03_packer_REPORT_РемизовКЛ_20260616.md,,final,
|
||||||
|
VKC_PR_M05_03_packer_log_РемизовКЛ_20260616.log,EVIDENCE,M05,03,Лог сборки Packer,02_evidence/VKC_PR_M05_03_packer_log_РемизовКЛ_20260616.log,VKC_PR_M05_03_packer_REPORT_РемизовКЛ_20260616.md,final,
|
||||||
|
VKC_PR_M05_03_packer_packer-config_РемизовКЛ_20260516.pkr.hcl,CODE,M05,03,Конфигурация Packer,03_code/VKC_PR_M05_03_packer_packer-config_РемизовКЛ_20260516.pkr.hcl,VKC_PR_M05_03_packer_REPORT_РемизовКЛ_20260616.md,final,
|
||||||
|
VKC_PR_M05_03_packer_curl_РемизовКЛ_20260616.png,EVIDENCE,M05,03,Проверка работы nginx через curl на тестовой ВМ,02_evidence/VKC_PR_M05_03_packer_curl_РемизовКЛ_20260616.png,VKC_PR_M05_03_packer_REPORT_РемизовКЛ_20260616.md,final,
|
||||||
|
VKC_PR_M05_03_packer_image_РемизовКЛ_20260616.png,EVIDENCE,M05,03,Созданный образ Packer в списке образов VK Cloud,02_evidence/VKC_PR_M05_03_packer_image_РемизовКЛ_20260616.png,VKC_PR_M05_03_packer_REPORT_РемизовКЛ_20260616.md,final,
|
||||||
|
VKC_LR_02_tf_packer_REPORT_РемизовКЛ_20260617.md,REPORT,LR_02,main,Автоматизация с Terraform и Packer,01_reports/VKC_LR_02_tf_packer_REPORT_РемизовКЛ_20260617.md,,final,
|
||||||
|
VKC_LR_02_tf_packer_balancerpruf_РемизовКЛ_20260617.png,EVIDENCE,LR_02,main,Проверка работы балансировщика,02_evidence/VKC_LR_02_tf_packer_balancerpruf_РемизовКЛ_20260617.png,VKC_LR_02_tf_packer_REPORT_РемизовКЛ_20260617.md,final,
|
||||||
|
VKC_LR_02_tf_packer_networktopology_РемизовКЛ_20260617.png,EVIDENCE,LR_02,main,Топология сети,02_evidence/VKC_LR_02_tf_packer_networktopology_РемизовКЛ_20260617.png,VKC_LR_02_tf_packer_REPORT_РемизовКЛ_20260617.md,final,
|
||||||
|
VKC_LR_02_tf_packer_packerlog_РемизовКЛ_20260617.log,EVIDENCE,LR_02,main,Лог сборки Packer,02_evidence/VKC_LR_02_tf_packer_packerlog_РемизовКЛ_20260617.log,VKC_LR_02_tf_packer_REPORT_РемизовКЛ_20260617.md,final,
|
||||||
|
VKC_LR_02_tf_packer_packer_РемизовКЛ_20260617.png,EVIDENCE,LR_02,main,Образ созданный Packer,02_evidence/VKC_LR_02_tf_packer_packer_РемизовКЛ_20260617.png,VKC_LR_02_tf_packer_REPORT_РемизовКЛ_20260617.md,final,
|
||||||
|
VKC_LR_02_tf_packer_s3log_РемизовКЛ_20260617.log,EVIDENCE,LR_02,main,Лог подключения к S3 бэкенду,02_evidence/VKC_LR_02_tf_packer_s3log_РемизовКЛ_20260617.log,VKC_LR_02_tf_packer_REPORT_РемизовКЛ_20260617.md,final,
|
||||||
|
VKC_LR_02_tf_packer_tflog1_РемизовКЛ_20260617.log,EVIDENCE,LR_02,main,Лог Terraform apply (часть 1),02_evidence/VKC_LR_02_tf_packer_tflog1_РемизовКЛ_20260617.log,VKC_LR_02_tf_packer_REPORT_РемизовКЛ_20260617.md,final,
|
||||||
|
VKC_LR_02_tf_packer_tflog2_РемизовКЛ_20260617.log,EVIDENCE,LR_02,main,Лог Terraform apply (часть 2),02_evidence/VKC_LR_02_tf_packer_tflog2_РемизовКЛ_20260617.log,VKC_LR_02_tf_packer_REPORT_РемизовКЛ_20260617.md,final,
|
||||||
|
VKC_LR_02_tf_packer_backend_РемизовКЛ_20260617.tf,CODE,LR_02,main,Terraform backend S3,03_code/VKC_LR_02_tf_packer_backend_РемизовКЛ_20260617.tf,,final,
|
||||||
|
VKC_LR_02_tf_packer_compute_РемизовКЛ_20260617.tf,CODE,LR_02,main,Terraform вычислительные ресурсы,03_code/VKC_LR_02_tf_packer_compute_РемизовКЛ_20260617.tf,,final,
|
||||||
|
VKC_LR_02_tf_packer_database_РемизовКЛ_20260617.tf,CODE,LR_02,main,Terraform управляемая БД,03_code/VKC_LR_02_tf_packer_database_РемизовКЛ_20260617.tf,,final,
|
||||||
|
VKC_LR_02_tf_packer_loadbalancer_РемизовКЛ_20260617.tf,CODE,LR_02,main,Terraform балансировщик,03_code/VKC_LR_02_tf_packer_loadbalancer_РемизовКЛ_20260617.tf,,final,
|
||||||
|
VKC_LR_02_tf_packer_network_РемизовКЛ_20260617.tf,CODE,LR_02,main,Terraform сеть,03_code/VKC_LR_02_tf_packer_network_РемизовКЛ_20260617.tf,,final,
|
||||||
|
VKC_LR_02_tf_packer_outputs_РемизовКЛ_20260617.tf,CODE,LR_02,main,Terraform выходные переменные,03_code/VKC_LR_02_tf_packer_outputs_РемизовКЛ_20260617.tf,,final,
|
||||||
|
VKC_LR_02_tf_packer_packer-config_РемизовКЛ_20260516.pkr.hcl,CODE,LR_02,main,Конфигурация Packer,03_code/VKC_LR_02_tf_packer_packer-config_РемизовКЛ_20260516.pkr.hcl,,final,
|
||||||
|
VKC_LR_02_tf_packer_provider_РемизовКЛ_20260617.tf,CODE,LR_02,main,Terraform провайдер,03_code/VKC_LR_02_tf_packer_provider_РемизовКЛ_20260617.tf,,final,
|
||||||
|
VKC_LR_02_tf_packer_security_РемизовКЛ_20260617.tf,CODE,LR_02,main,Terraform Security Groups,03_code/VKC_LR_02_tf_packer_security_РемизовКЛ_20260617.tf,,final,
|
||||||
|
VKC_LR_02_tf_packer_variables_РемизовКЛ_20260617.tf,CODE,LR_02,main,Terraform переменные,03_code/VKC_LR_02_tf_packer_variables_РемизовКЛ_20260617.tf,,final,
|
||||||
|
VKC_PR_M06_01_monitoring_REPORT_РемизовКЛ_20260617.md,PR,M06,01,Настройка мониторинга (Prometheus + Grafana),01_reports/VKC_PR_M06_01_monitoring_REPORT_РемизовКЛ_20260617.md,,final,
|
||||||
|
VKC_PR_M06_01_monitoring_VM_РемизовКЛ_20260617.png,EVIDENCE,M06,01,Список созданных ВМ,02_evidence/VKC_PR_M06_01_monitoring_VM_РемизовКЛ_20260617.png,VKC_PR_M06_01_monitoring_REPORT_РемизовКЛ_20260617.md,final,
|
||||||
|
VKC_PR_M06_01_monitoring_Prometeus_РемизовКЛ_20260617.png,EVIDENCE,M06,01,Цели Prometheus (UP),02_evidence/VKC_PR_M06_01_monitoring_Prometeus_РемизовКЛ_20260617.png,VKC_PR_M06_01_monitoring_REPORT_РемизовКЛ_20260617.md,final,
|
||||||
|
VKC_PR_M06_01_monitoring_DS_РемизовКЛ_20260617.png,EVIDENCE,M06,01,Data Source Prometheus в Grafana,02_evidence/VKC_PR_M06_01_monitoring_DS_РемизовКЛ_20260617.png,VKC_PR_M06_01_monitoring_REPORT_РемизовКЛ_20260617.md,final,
|
||||||
|
VKC_PR_M06_01_monitoring_dashboard_РемизовКЛ_20260617.png,EVIDENCE,M06,01,Дашборд Node Exporter Full,02_evidence/VKC_PR_M06_01_monitoring_dashboard_РемизовКЛ_20260617.png,VKC_PR_M06_01_monitoring_REPORT_РемизовКЛ_20260617.md,final,
|
||||||
|
VKC_PR_M06_01_monitoring_tf_РемизовКЛ_20260617.log,EVIDENCE,M06,01,Лог Terraform apply,02_evidence/VKC_PR_M06_01_monitoring_tf_РемизовКЛ_20260617.log,VKC_PR_M06_01_monitoring_REPORT_РемизовКЛ_20260617.md,final,
|
||||||
|
VKC_PR_M06_01_monitoring_main_РемизовКЛ_20260617.tf,CODE,M06,01,Код Terraform для мониторинга,03_code/VKC_PR_M06_01_monitoring_main_РемизовКЛ_20260617.tf,VKC_PR_M06_01_monitoring_REPORT_РемизовКЛ_20260617.md,final,
|
||||||
|
VKC_LR_03_monitoring_REPORT_РемизовКЛ_20260618.md,REPORT,LR_03,main,Мониторинг и логирование,01_reports/VKC_LR_03_monitoring_REPORT_РемизовКЛ_20260618.md,,final,
|
||||||
|
VKC_LR_03_monitoring_bastion_РемизовКЛ_20260618.png,EVIDENCE,LR_03,main,Проверка работы веб-сервера через балансировщик,02_evidence/VKC_LR_03_monitoring_bastion_РемизовКЛ_20260618.png,VKC_LR_03_monitoring_REPORT_РемизовКЛ_20260618.md,final,
|
||||||
|
VKC_LR_03_monitoring_prometeus_РемизовКЛ_20260618.png,EVIDENCE,LR_03,main,Статус targets в Prometheus,02_evidence/VKC_LR_03_monitoring_prometeus_РемизовКЛ_20260618.png,VKC_LR_03_monitoring_REPORT_РемизовКЛ_20260618.md,final,
|
||||||
|
VKC_LR_03_monitoring_networktopology_РемизовКЛ_20260618.png,EVIDENCE,LR_03,main,Топология сети,02_evidence/VKC_LR_03_monitoring_networktopology_РемизовКЛ_20260618.png,VKC_LR_03_monitoring_REPORT_РемизовКЛ_20260618.md,final,
|
||||||
|
VKC_LR_03_monitoring_prometeusInGraphana_РемизовКЛ_20260618.png,EVIDENCE,LR_03,main,Настройка Data Source в Grafana,02_evidence/VKC_LR_03_monitoring_prometeusInGraphana_РемизовКЛ_20260618.png,VKC_LR_03_monitoring_REPORT_РемизовКЛ_20260618.md,final,
|
||||||
|
VKC_LR_03_monitoring_templatedashboard_РемизовКЛ_20260618.png,EVIDENCE,LR_03,main,Импортированный дашборд (ID 1860),02_evidence/VKC_LR_03_monitoring_templatedashboard_РемизовКЛ_20260618.png,VKC_LR_03_monitoring_REPORT_РемизовКЛ_20260618.md,final,
|
||||||
|
VKC_LR_03_monitoring_alerts_РемизовКЛ_20260618.png,EVIDENCE,LR_03,main,Правила алертов в Prometheus,02_evidence/VKC_LR_03_monitoring_alerts_РемизовКЛ_20260618.png,VKC_LR_03_monitoring_REPORT_РемизовКЛ_20260618.md,final,
|
||||||
|
VKC_LR_03_monitoring_tf_РемизовКЛ_20260618.log,EVIDENCE,LR_03,main,Лог Terraform apply,02_evidence/VKC_LR_03_monitoring_tf_РемизовКЛ_20260618.log,VKC_LR_03_monitoring_REPORT_РемизовКЛ_20260618.md,final,
|
||||||
|
VKC_LR_03_monitoring_main_РемизовКЛ_20260618.tf,CODE,LR_03,main,Основной файл конфигурации Terraform,03_code/VKC_LR_03_monitoring_main_РемизовКЛ_20260618.tf,,final,
|
||||||
|
VKC_LR_03_monitoring_variables_РемизовКЛ_20260618.tf,CODE,LR_03,main,Переменные Terraform,03_code/VKC_LR_03_monitoring_variables_РемизовКЛ_20260618.tf,,final,
|
||||||
|
VKC_LR_03_monitoring_outputs_РемизовКЛ_20260618.tf,CODE,LR_03,main,Выходные переменные Terraform,03_code/VKC_LR_03_monitoring_outputs_РемизовКЛ_20260618.tf,,final,
|
||||||
|
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,
|
||||||
|
VKC_CASE_03_migration_РемизовКЛ_20260619.md,CASE,M08,CASE_03,Анализ и выбор стратегии миграции LAMP-приложения,01_reports/VKC_CASE_03_migration_РемизовКЛ_20260619.md,,final,
|
||||||
|
VKC_CASE_03_migration_IvanovII_20260619.drawio.png,DIAGRAM,M08,CASE_03,Схема целевой архитектуры интернет-магазина в VK Cloud,04_diagrams/VKC_CASE_03_migration_IvanovII_20260619.drawio.png,,final,
|
||||||
|
VKC_ARCH_M08_highload_store_REPORT_РемизовКЛ_20260619.md,CASE,M08,8.2,Проектирование высоконагруженной архитектуры интернет-магазина,01_reports/VKC_ARCH_M08_highload_store_REPORT_РемизовКЛ_20260619.md,,final,
|
||||||
|
VKC_ARCH_M08_highload_store_diogram_РемизовКЛ_20260619.drawio.png,DIAGRAM,M08,8.2,Схема архитектуры высоконагруженного интернет-магазина,04_diagrams/VKC_ARCH_M08_highload_store_diogram_РемизовКЛ_20260619.drawio.png,VKC_ARCH_M08_highload_store_REPORT_РемизовКЛ_20260619.md,final,
|
||||||
|
VKC_PROJ_V01_README_РемизовКЛ_20260628.md,PROJ,PROJ,V01,README итогового проекта,01_reports/VKC_PROJ_V01_README_РемизовКЛ_20260628.md,,final,
|
||||||
|
VKC_PROJ_V01_demo_video_РемизовКЛ_20260628.mp4,EVIDENCE,PROJ,V01,Видеообзор демонстрации,05_exports/VKC_PROJ_V01_demo_video_РемизовКЛ_20260628.mp4,final
|
||||||
|
VKC_PROJ_V01_presentation_РемизовКЛ_20260628.pdf,PRESENTATION,PROJ,V01,Презентация итогового проекта,05_exports/VKC_PROJ_V01_presentation_РемизовКЛ_20260628.pdf,final
|
||||||
|
VKC_PROJ_V01_architecture_РемизовКЛ_20260628.drawio.png,DIAGRAM,PROJ,V01,Архитектурная схема,04_diagrams/VKC_PROJ_V01_architecture_РемизовКЛ_20260628.drawio.png,final
|
||||||
|
VKC_PROJ_V01_ab_log_РемизовКЛ_20260628.log,EVIDENCE,PROJ,V01,Лог нагрузочного тестирования ab,02_evidence/VKC_PROJ_V01_ab_log_RemizovKL_20260628.log,VKC_PROJ_V01_README_РемизовКЛ_20260628.md,final,
|
||||||
|
VKC_PROJ_V01_curl_log_РемизовКЛ_20260628.log,EVIDENCE,PROJ,V01,Лог curl -v к /DevOps,02_evidence/VKC_PROJ_V01_curl_log_RemizovKL_20260628.log,VKC_PROJ_V01_README_РемизовКЛ_20260628.md,final,
|
||||||
|
VKC_PROJ_V01_ssh_log_РемизовКЛ_20260628.log,EVIDENCE,PROJ,V01,Лог SSH-подключений,02_evidence/VKC_PROJ_V01_ssh_log_RemizovKL_20260628.log,VKC_PROJ_V01_README_РемизовКЛ_20260628.md,final,
|
||||||
|
VKC_PROJ_V01_main_РемизовКЛ_20260628.tf,CODE,PROJ,V01,Основной код Terraform,03_code/VKC_PROJ_V01_main_РемизовКЛ_20260628.tf,VKC_PROJ_V01_README_РемизовКЛ_20260628.md,final,
|
||||||
|
VKC_PROJ_V01_variables_РемизовКЛ_20260628.tf,CODE,PROJ,V01,Переменные Terraform,03_code/VKC_PROJ_V01_variables_РемизовКЛ_20260628.tf,VKC_PROJ_V01_README_РемизовКЛ_20260628.md,final,
|
||||||
|
VKC_PROJ_V01_outputs_РемизовКЛ_20260628.tf,CODE,PROJ,V01,Выходные переменные Terraform,03_code/VKC_PROJ_V01_outputs_РемизовКЛ_20260628.tf,VKC_PROJ_V01_README_РемизовКЛ_20260628.md,final,
|
||||||
|
VKC_PROJ_V01_backend_РемизовКЛ_20260628.tf,CODE,PROJ,V01,Настройка бэкенда S3,03_code/VKC_PROJ_V01_backend_РемизовКЛ_20260628.tf,VKC_PROJ_V01_README_РемизовКЛ_20260628.md,final,
|
||||||
00_manifest.csv,MANIFEST,all,all,Финальный манифест сдачи,00_manifest.csv,,final,
|
00_manifest.csv,MANIFEST,all,all,Финальный манифест сдачи,00_manifest.csv,,final,
|
||||||
|
@@ -0,0 +1,98 @@
|
|||||||
|
---
|
||||||
|
course_code: VKCLOUD-80
|
||||||
|
artifact_type: CASE
|
||||||
|
case_code: ARCH_HIGHLOAD_STORE
|
||||||
|
case_title: Проектирование высоконагруженной архитектуры интернет-магазина
|
||||||
|
student_fio: Ремизов К.Л.
|
||||||
|
date: 2026-06-19
|
||||||
|
source_docs: [3-Конспект лекций - VK 1.md,2- Тематический план - VK -1.md, 7-Шпаргалка студента -VK-1.md]
|
||||||
|
attached_files: [VKC_ARCH_M08_highload_store_diogram_РемизовКЛ_20260619.drawio.png]
|
||||||
|
status: final
|
||||||
|
---
|
||||||
|
|
||||||
|
# Разбор практического кейса
|
||||||
|
|
||||||
|
## 1. Суть кейса
|
||||||
|
|
||||||
|
Разработать облачную архитектуру для высоконагруженного интернет-магазина, который должен выдерживать пиковые нагрузки в периоды распродаж (например, «чёрная пятница»), обеспечивать высокую доступность (отказоустойчивость) и горизонтальное масштабирование. Требуется выбрать и обосновать набор сервисов VK Cloud, спроектировать схему взаимодействия компонентов и описать меры по обеспечению надёжности.
|
||||||
|
|
||||||
|
## 2. Ограничения и исходные условия
|
||||||
|
|
||||||
|
- **Платформа** – VK Cloud (все сервисы должны быть доступны в этом облаке).
|
||||||
|
- **Бюджет** – не фиксирован, но желательна оптимизация затрат (FinOps).
|
||||||
|
- **Временные ограничения** – проект должен быть реализован в рамках курса (модуль 8).
|
||||||
|
- **Технические требования**:
|
||||||
|
- Поддержка > 10 000 RPS в пик.
|
||||||
|
- Время отклика страницы < 200 мс (95-й перцентиль).
|
||||||
|
- Доступность 99.99% (4 девятки).
|
||||||
|
- Безопасность: защита от DDoS и веб-атак.
|
||||||
|
- Асинхронная обработка заказов (не блокировать пользователя).
|
||||||
|
- Кэширование часто запрашиваемых данных.
|
||||||
|
- Мониторинг и алертинг.
|
||||||
|
|
||||||
|
## 3. Варианты решения
|
||||||
|
|
||||||
|
| Вариант | Плюсы | Минусы | Когда применять |
|
||||||
|
|---------|-------|--------|-----------------|
|
||||||
|
| **A. Монолит на ВМ с ручным масштабированием** | Простота разработки, низкие начальные затраты | Единая точка отказа, сложность горизонтального масштабирования, ручное управление, отсутствие гибкости | Для небольших проектов с низкой нагрузкой и статичным трафиком |
|
||||||
|
| **B. Микросервисы в Kubernetes с управляемыми сервисами (предлагаемый)** | Горизонтальное масштабирование, отказоустойчивость, автоматическое восстановление, гибкость обновлений | Более высокая сложность и стоимость, требует DevOps-культуры | Для высоконагруженных и динамичных проектов, требующих быстрой эволюции |
|
||||||
|
| **C. Серверлес (VK Cloud Functions)** | Минимальное администрирование, оплата за вызовы | Ограничения по времени выполнения, языкам, холодный старт, сложность управления состоянием | Для эпизодических и простых задач (не для основного магазина) |
|
||||||
|
|
||||||
|
**Выбран вариант B** как наиболее соответствующий всем требованиям по нагрузке, доступности и гибкости.
|
||||||
|
|
||||||
|
## 4. Выбранное решение и обоснование
|
||||||
|
|
||||||
|
### 4.1. Состав компонентов (все из VK Cloud)
|
||||||
|
|
||||||
|
| Компонент | Сервис VK Cloud | Обоснование |
|
||||||
|
|-----------|-----------------|-------------|
|
||||||
|
| **CDN** | VK Cloud CDN | Географически распределённая доставка статики (изображения, CSS, JS) – снижает нагрузку на бэкенд и ускоряет загрузку для пользователей по всему миру. |
|
||||||
|
| **Балансировщик L7** | VK Cloud Load Balancer (Application LB) | Распределение HTTP/HTTPS трафика, поддержка health checks и маршрутизации по URL (например, `/api/*` → K8s, `/static/*` → CDN). |
|
||||||
|
| **WAF + AntiDDoS** | VK Cloud WAF и AntiDDoS | Защита от SQL-инъекций, XSS и DDoS-атак – критично для публичного интернет-магазина. |
|
||||||
|
| **Веб-серверы (frontend)** | Auto Scaling Group (ВМ с nginx) | Обработка статики и проксирование на K8s; горизонтальное масштабирование по CPU/RPS; дешёвый и управляемый слой. |
|
||||||
|
| **Микросервисы (backend)** | Managed Kubernetes | Контейнерная оркестрация: автоматическое масштабирование (HPA), самовосстановление, канареечные обновления. Поддерживает 55 000 подов на кластер. |
|
||||||
|
| **Кэш** | Managed Redis Cluster (шардированный) | Хранение сессий, кэш каталога, цен. Микросекундная задержка, кластерная отказоустойчивость. |
|
||||||
|
| **Основная БД** | Managed PostgreSQL (шардирование) | Реляционная БД для товаров, заказов, пользователей. Шардирование позволяет горизонтально масштабироваться (ключ – `user_id`). |
|
||||||
|
| **Реплики для чтения** | PostgreSQL replicas | Тяжёлые аналитические запросы и отчёты идут на реплики, не нагружая мастер. |
|
||||||
|
| **Очередь сообщений** | Cloud Kafka / RabbitMQ | Асинхронная обработка заказов (списание товаров, email, SMS, бонусы). Разгружает критический путь запроса. |
|
||||||
|
| **Мониторинг** | Prometheus + Grafana (развёрнутые в K8s) | Сбор метрик, дашборды, алертинг – основа наблюдаемости. |
|
||||||
|
|
||||||
|
### 4.2. Почему именно эти сервисы?
|
||||||
|
|
||||||
|
- **Kubernetes** выбран вместо чистых ВМ, потому что он обеспечивает декларативное управление, автоматическое масштабирование и восстановление, что критично для высокой нагрузки.
|
||||||
|
- **Redis** – лучшее решение для кэширования благодаря скорости и поддержке кластеров.
|
||||||
|
- **PostgreSQL** – зрелая СУБД с поддержкой сложных запросов и транзакций; шардирование решает проблему роста данных.
|
||||||
|
- **Kafka** гарантирует надёжную доставку сообщений и позволяет масштабировать воркеры независимо.
|
||||||
|
|
||||||
|
## 5. Риски и меры снижения
|
||||||
|
|
||||||
|
| Риск | Вероятность | Влияние | Мера снижения |
|
||||||
|
|------|-------------|---------|---------------|
|
||||||
|
| Отказ master-узла PostgreSQL | Средняя | Высокое (заказы не создаются) | Автоматический failover на реплику; регулярные бэкапы в S3. |
|
||||||
|
| Перегрузка Redis (кэш не попадает) | Низкая | Среднее (рост нагрузки на БД) | Мониторинг использования памяти; автоскейлинг кластера; настройка TTL. |
|
||||||
|
| DDoS-атака | Высокая | Критическое | Встроенный AntiDDoS VK Cloud + WAF; ограничение частоты запросов. |
|
||||||
|
| Ошибка в микросервисе (краш) | Средняя | Среднее | Kubernetes автоматически пересоздаёт под; канареечные обновления; откат через GitOps. |
|
||||||
|
| Человеческий фактор (неправильная конфигурация) | Средняя | Высокое | Всё описывается как код (IaC) – Terraform и Helm; код-ревью; CI/CD проверяет конфигурации. |
|
||||||
|
| Превышение бюджета | Средняя | Среднее | FinOps: тегирование ресурсов, бюджетные алерты, использование Spot-инстансов для тестовых сред. |
|
||||||
|
|
||||||
|
## 6. Артефакты
|
||||||
|
|
||||||
|
| Файл | Назначение |
|
||||||
|
|------|------------|
|
||||||
|
| `VKC_ARCH_M08_highload_store_diogram_РемизовКЛ_20260619.drawio.png` | Схема архитектуры (экспорт из draw.io) в формате PNG |
|
||||||
|
| `VKC_ARCH_M08_highload_store_REPORT_РемизовКЛ_20260619.md` | Данный отчёт (заполненный шаблон) |
|
||||||
|
|
||||||
|
**Схема архитектуры** представлена на изображении ниже:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## 7. Вывод
|
||||||
|
|
||||||
|
Предложенная архитектура на базе управляемых сервисов VK Cloud обеспечивает:
|
||||||
|
- **Отказоустойчивость** – каждый компонент имеет резервирование, распределение по зонам доступности, автоматический failover.
|
||||||
|
- **Горизонтальное масштабирование** – все слои (веб-серверы, микросервисы, кэш, БД, очередь) могут расширяться при росте нагрузки.
|
||||||
|
- **Высокую производительность** – CDN, Redis и реплики БД для чтения гарантируют низкие задержки.
|
||||||
|
- **Безопасность** – WAF и AntiDDoS защищают от внешних угроз.
|
||||||
|
- **Управляемость** – IaC, CI/CD и GitOps упрощают эксплуатацию и обновления.
|
||||||
|
|
||||||
|
Реализация данной архитектуры в VK Cloud полностью покрывает требования высоконагруженного интернет-магазина и соответствует лучшим практикам облачного проектирования.
|
||||||
@@ -0,0 +1,132 @@
|
|||||||
|
---
|
||||||
|
course_code: VKCLOUD-80
|
||||||
|
artifact_type: CASE
|
||||||
|
case_code: VKC_CASE_03_migration
|
||||||
|
case_title: Анализ и выбор стратегии миграции LAMP-приложения в VK Cloud
|
||||||
|
student_fio: Иванов И.И.
|
||||||
|
date: 2026-06-19
|
||||||
|
source_docs: [Д2_Тематический_план, Д3_Конспект_лекций, Д7_Шпаргалка]
|
||||||
|
attached_files: [VKC_CASE_03_migration_IvanovII_20260619.drawio.png, VKC_ARCH_M08_highload_store.drawio]
|
||||||
|
status: final
|
||||||
|
---
|
||||||
|
|
||||||
|
# Разбор практического кейса: Миграция интернет-магазина в VK Cloud
|
||||||
|
|
||||||
|
## 1. Суть кейса и целевая архитектура
|
||||||
|
|
||||||
|
Необходимо выполнить миграцию существующего интернет-магазина, работающего на классическом LAMP-стеке (Linux, Apache, MySQL, PHP), с текущей on-premise инфраструктуры (одна физическая/виртуальная машина) в облачную платформу VK Cloud.
|
||||||
|
|
||||||
|
**Текущее состояние приложения:**
|
||||||
|
- **Архитектура:** Монолитное приложение, развернутое на одной ВМ.
|
||||||
|
- **Стек:** Ubuntu 22.04, Apache 2.4, PHP 7.4 (с расширениями gd, mbstring, xml, curl, mysqli), MySQL 8.0.
|
||||||
|
- **Данные:** Файлы приложения (`/var/www/html`) и база данных (`/var/lib/mysql`) находятся на одном сервере.
|
||||||
|
- **Бизнес-требования:** Допустим простой до 2 часов в ночное время (вне пиковых нагрузок), потеря данных недопустима. Бюджет на инфраструктуру ограничен.
|
||||||
|
|
||||||
|
**Целевая архитектура (после миграции):**
|
||||||
|
|
||||||
|
На схеме ниже представлен проект инфраструктуры после миграции по стратегии Replatform:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
*Рис. 1 – Архитектура решения в VK Cloud: пользователь → DNS → Балансировщик → Веб-серверы (зоны А и Б) → Managed PostgreSQL / S3.*
|
||||||
|
|
||||||
|
**Описание компонентов схемы:**
|
||||||
|
|
||||||
|
1. **Внешний доступ:**
|
||||||
|
- **Пользователь** обращается к сайту через **DNS** (`shop.example.com`).
|
||||||
|
- **Балансировщик L7** с публичным IP принимает входящий HTTP/HTTPS-трафик и распределяет его между веб-серверами.
|
||||||
|
- **Администратор** подключается к инфраструктуре через **Бастион-хост** (SSH, порт 22).
|
||||||
|
|
||||||
|
2. **Виртуальная сеть (VPC):**
|
||||||
|
- Вся инфраструктура развернута в виртуальном частном облаке **VPC 10.0.0.0/16**.
|
||||||
|
- **Публичная подсеть (10.0.1.0/24):** Содержит Бастион-хост для безопасного доступа к внутренним ресурсам.
|
||||||
|
- **Приватная подсеть APP (10.0.2.0/24):** Содержит два веб-сервера с Apache/PHP, размещенных в разных зонах доступности (**Зона А** и **Зона Б**) для обеспечения отказоустойчивости.
|
||||||
|
- **Приватная подсеть DB (10.0.3.0/24):** Содержит управляемый кластер **PostgreSQL** (Master для записи и Replica для чтения).
|
||||||
|
|
||||||
|
3. **Управляемые сервисы:**
|
||||||
|
- **Объектное хранилище S3:** Используется для хранения статических файлов (изображения, загрузки пользователей) и резервных бэкапов БД.
|
||||||
|
|
||||||
|
4. **Потоки трафика:**
|
||||||
|
- Балансировщик направляет HTTP/HTTPS-запросы к веб-серверам.
|
||||||
|
- Веб-серверы взаимодействуют с Master PostgreSQL для операций записи и с Replica для операций чтения.
|
||||||
|
- Веб-серверы загружают файлы пользователей в S3.
|
||||||
|
- Администратор подключается к бастиону, а через него — к веб-серверам по SSH.
|
||||||
|
|
||||||
|
## 2. Ограничения и исходные условия
|
||||||
|
|
||||||
|
| Критерий | Исходное условие / Ограничение | Влияние на выбор стратегии |
|
||||||
|
|----------|--------------------------------|----------------------------|
|
||||||
|
| **Технические зависимости** | Жесткая привязка к конкретным версиям PHP (7.4) и MySQL (8.0). | Необходимо сохранить версии в облаке или тщательно протестировать совместимость. |
|
||||||
|
| **Состояние данных** | Данные хранятся в файлах БД на том же диске, что и код. | Требуется выделить этап синхронизации данных и проверки целостности. |
|
||||||
|
| **Доступность (SLA)** | Допустим простой до 2 часов. Отказоустойчивость отсутствует (SPOF). | Желательно внедрить балансировку и репликацию БД в рамках миграции. |
|
||||||
|
| **Бюджет** | Ограниченный. Текущие затраты ~25 000 руб./мес. | Необходимо избегать дорогих сервисов без явной выгоды. |
|
||||||
|
| **Сроки** | Не более 3 недель. | Исключает полный рефакторинг архитектуры (микросервисы). |
|
||||||
|
| **Компетенции команды** | Хорошее знание Linux/MySQL/PHP, минимальный опыт с облаками. | Рекомендуется использовать управляемые сервисы (DBaaS). |
|
||||||
|
|
||||||
|
## 3. Варианты решения (6R)
|
||||||
|
|
||||||
|
| Вариант | Плюсы | Минусы | Когда применять |
|
||||||
|
|---------|-------|--------|-----------------|
|
||||||
|
| **1. Rehost** | ✅ Скорость (1-2 дня). <br> ✅ Минимум изменений. | ❌ Не даёт преимуществ облака. <br> ❌ Сохраняется SPOF. | Срочная миграция без времени на оптимизацию. |
|
||||||
|
| **2. Replatform** | ✅ Баланс скорости и качества (2-3 недели). <br> ✅ Устранение SPOF. <br> ✅ Автоматизация бэкапов. | ❌ Требует изменения конфигураций подключения к БД. | **Выбранный вариант.** Оптимальное соотношение цены и надежности. |
|
||||||
|
| **3. Refactor** | ✅ Максимальная масштабируемость. | ❌ Очень долго (3-6 месяцев). <br> ❌ Требует высокой квалификации. | Долгосрочная стратегия при наличии ресурсов. |
|
||||||
|
| **4. Repurchase** | ✅ Перекладывание ответственности на вендора. | ❌ Нет готового SaaS для кастомного магазина. | Миграция на типовые CRM/ERP системы. |
|
||||||
|
|
||||||
|
## 4. Выбранное решение и обоснование
|
||||||
|
|
||||||
|
**Выбранная стратегия: Replatform (Частичная модернизация)**
|
||||||
|
|
||||||
|
**Обоснование:**
|
||||||
|
1. **Оптимальный баланс:** Стратегия позволяет получить основные преимущества облака (автоматические бэкапы, отказоустойчивость, масштабирование) за приемлемое время (2-3 недели) и без изменения бизнес-кода.
|
||||||
|
2. **Снижение эксплуатационных расходов:** Замена ручного администрирования серверов на управляемые сервисы (Managed PostgreSQL, S3) снижает нагрузку на команду.
|
||||||
|
3. **Повышение отказоустойчивости:** Внедрение балансировщика и размещение веб-серверов в разных зонах доступности (как показано на схеме) устраняет единую точку отказа.
|
||||||
|
4. **Финансовая эффективность:** Расчётная стоимость (~16 000 руб./мес) ниже текущих затрат (~25 000 руб./мес).
|
||||||
|
|
||||||
|
## 5. План миграции (этапы)
|
||||||
|
|
||||||
|
| Этап | Действия | Срок | Инструменты |
|
||||||
|
|------|----------|------|-------------|
|
||||||
|
| **1. Подготовка сети** | Создать VPC, публичную и приватные подсети, настроить Security Groups и бастион-хост. | День 1-2 | Веб-консоль / Terraform |
|
||||||
|
| **2. Перенос данных** | Создать Managed PostgreSQL, сделать дамп существующей БД, восстановить на управляемом инстансе. | День 3-5 | `mysqldump`, DBaaS, S3 |
|
||||||
|
| **3. Перенос приложения** | Развернуть 2 веб-сервера (образ через Packer) в приватной подсети, настроить балансировщик. | День 5-7 | Packer, Terraform |
|
||||||
|
| **4. Тестирование** | Проверить работу сайта, формы, загрузку файлов, нагрузочное тестирование. | День 8-10 | Ручное тестирование, Grafana |
|
||||||
|
| **5. Переключение DNS** | Установить низкий TTL, переключить DNS на IP балансировщика. Мониторинг 24 часа. | День 11 | Провайдер DNS |
|
||||||
|
| **6. Вывод из эксплуатации** | Отключить старый сервер, удалить временные ресурсы. | День 14 | Веб-консоль / CLI |
|
||||||
|
|
||||||
|
## 6. Риски и меры снижения
|
||||||
|
|
||||||
|
| Риск | Вероятность | Влияние | Меры снижения (Mitigation) |
|
||||||
|
|------|-------------|---------|----------------------------|
|
||||||
|
| **Потеря данных БД** | Средняя | Критическое | 1. Полный бэкап перед началом. <br> 2. Использовать Hystax для репликации. <br> 3. Восстановление на тестовый инстанс. |
|
||||||
|
| **Несовместимость версий ПО** | Средняя | Высокое | 1. Использовать аналогичные версии в облаке. <br> 2. Собрать образ через Packer, повторяющий среду. <br> 3. Регрессионное тестирование на staging. |
|
||||||
|
| **Простой > 2 часов** | Средняя | Высокое | 1. Стратегия Blue-Green. <br> 2. Низкий TTL для DNS. <br> 3. Миграция в ночь минимальной нагрузки. |
|
||||||
|
| **Рост затрат (FinOps)** | Высокая | Среднее | 1. Настроить бюджетные алерты. <br> 2. Использовать Spot-инстансы для тестов. <br> 3. Автоматическое выключение сред в нерабочее время. |
|
||||||
|
|
||||||
|
## 7. Оценка затрат (FinOps)
|
||||||
|
|
||||||
|
| № | Наименование ресурса | Конфигурация | Кол-во | Цена за ед./мес (₽) | Итого (₽) |
|
||||||
|
|---|----------------------|--------------|--------|---------------------|-----------|
|
||||||
|
| 1 | Веб-сервер (ВМ) | 2 vCPU / 4GB RAM / 40GB SSD | 2 | 4 015 | 8 030 |
|
||||||
|
| 2 | Бастион-хост (ВМ) | 1 vCPU / 1GB RAM / 20GB SSD | 1 | 1 460 | 1 460 |
|
||||||
|
| 3 | Managed PostgreSQL | 2 vCPU / 4GB RAM (кластер HA) | 1 | 7 300 | 7 300 |
|
||||||
|
| 4 | Балансировщик L7 | Малый (до 1000 запросов/сек) | 1 | 1 460 | 1 460 |
|
||||||
|
| 5 | Объектное хранилище S3 | 100 ГБ (стандарт) | 1 | 430 | 430 |
|
||||||
|
| | **Итого в облаке** | | | | **~16 680 ₽** |
|
||||||
|
| | **Текущие затраты (On-Premise)** | Аренда + электричество + обслуживание | | | **~25 000 ₽** |
|
||||||
|
|
||||||
|
**Экономия:** ~33% (снижение затрат на ~8 300 ₽ в месяц).
|
||||||
|
|
||||||
|
## 8. Артефакты
|
||||||
|
|
||||||
|
| Файл | Назначение |
|
||||||
|
|------|------------|
|
||||||
|
| `VKC_CASE_03_migration_IvanovII_20260619.md` | Настоящий отчет по анализу и выбору стратегии миграции. |
|
||||||
|
| `VKC_CASE_03_migration_IvanovII_20260619.drawio.png` | Экспорт схемы целевой архитектуры (встроен в отчет). |
|
||||||
|
| `VKC_ARCH_M08_highload_store.drawio` | Исходный файл схемы в Draw.io для редактирования. |
|
||||||
|
| `VKC_CASE_03_cost_calculation.xlsx` | Детальный расчет стоимости с формулами (прилагается отдельно). |
|
||||||
|
|
||||||
|
## 9. Вывод
|
||||||
|
|
||||||
|
В ходе анализа приложения интернет-магазина выбрана стратегия **Replatform** как оптимальный компромисс между скоростью миграции (2-3 недели), стоимостью владения (экономия ~33%) и уровнем надежности (устранение единой точки отказа).
|
||||||
|
|
||||||
|
Разработанная архитектура (VPC с публичной и приватными подсетями, балансировщик, веб-серверы в разных зонах доступности, управляемая БД и S3) полностью соответствует современным стандартам облачных решений. План миграции включает обязательные этапы тестирования и имеет четкий план отката, что позволяет начать миграцию с минимальными рисками для бизнеса.
|
||||||
@@ -0,0 +1,439 @@
|
|||||||
|
---
|
||||||
|
course_code: VKCLOUD-80
|
||||||
|
artifact_type: LR
|
||||||
|
lab_code: 2
|
||||||
|
lab_title: Автоматизация с Terraform и Packer
|
||||||
|
student_fio: Ремизов Кирилл Львович
|
||||||
|
date: 2026-06-17
|
||||||
|
source_docs:
|
||||||
|
- 5-Задания для лабораторных работ -VK-1.md
|
||||||
|
- 3-Конспект лекций - VK 1.md
|
||||||
|
attached_files:
|
||||||
|
- VKC_LR_02_tf_packer_packer_РемизовКЛ_20260617.png
|
||||||
|
- VKC_LR_02_tf_packer_packerlog_РемизовКЛ_20260617.log
|
||||||
|
- VKC_LR_02_tf_packer_packer-config_РемизовКЛ_20260516.pkr.hcl
|
||||||
|
- VKC_LR_02_tf_packer_networktopology_РемизовКЛ_20260617.png
|
||||||
|
- VKC_LR_02_tf_packer_balancerpruf_РемизовКЛ_20260617.png
|
||||||
|
- VKC_LR_02_tf_packer_tflog1_РемизовКЛ_20260617.log
|
||||||
|
- VKC_LR_02_tf_packer_tflog2_РемизовКЛ_20260617.log
|
||||||
|
- VKC_LR_02_tf_packer_s3log_РемизовКЛ_20260617.log
|
||||||
|
- VKC_LR_02_tf_packer_backend_РемизовКЛ_20260617.tf
|
||||||
|
- VKC_LR_02_tf_packer_compute_РемизовКЛ_20260617.tf
|
||||||
|
- VKC_LR_02_tf_packer_database_РемизовКЛ_20260617.tf
|
||||||
|
- VKC_LR_02_tf_packer_loadbalancer_РемизовКЛ_20260617.tf
|
||||||
|
- VKC_LR_02_tf_packer_network_РемизовКЛ_20260617.tf
|
||||||
|
- VKC_LR_02_tf_packer_outputs_РемизовКЛ_20260617.tf
|
||||||
|
- VKC_LR_02_tf_packer_provider_РемизовКЛ_20260617.tf
|
||||||
|
- VKC_LR_02_tf_packer_security_РемизовКЛ_20260617.tf
|
||||||
|
- VKC_LR_02_tf_packer_variables_РемизовКЛ_20260617.tf
|
||||||
|
estimated_cost_rub: 120
|
||||||
|
status: final
|
||||||
|
---
|
||||||
|
|
||||||
|
# Отчет по лабораторной работе №2
|
||||||
|
|
||||||
|
## 1. Цель работы
|
||||||
|
|
||||||
|
Автоматизировать развертывание отказоустойчивой веб-инфраструктуры (из лабораторной работы №1) с использованием **Infrastructure as Code (Terraform)** и **автоматизированной сборки образов (Packer)**. Основные задачи:
|
||||||
|
|
||||||
|
- Создать кастомизированный образ веб-сервера с предустановленным nginx с помощью Packer.
|
||||||
|
- Описать всю инфраструктуру (VPC, подсети, Security Groups, виртуальные машины, балансировщик, управляемую БД) в Terraform.
|
||||||
|
- Настроить удалённое хранение state-файла в S3 для командной работы.
|
||||||
|
|
||||||
|
## 2. Используемые ресурсы
|
||||||
|
|
||||||
|
| Ресурс | Тип | Параметры | Назначение |
|
||||||
|
|--------|-----|-----------|-------------|
|
||||||
|
| VPC `lab1-vpc` | Virtual Private Cloud | CIDR: 10.0.0.0/16 | Изолированная сеть |
|
||||||
|
| Публичная подсеть `lab1-public` | Subnet | CIDR: 10.0.1.0/24, доступ через интернет-шлюз | Размещение бастиона и балансировщика |
|
||||||
|
| Приватная подсеть `lab1-private` | Subnet | CIDR: 10.0.2.0/24, выход в интернет через NAT | Размещение веб-серверов и БД |
|
||||||
|
| Бастионный хост `bastion` | ВМ (Ubuntu 22.04) | Флейвор `df3c499a-...`, публичный IP | Единственная точка SSH-доступа |
|
||||||
|
| Веб-серверы `web-1`, `web-2` | ВМ (кастомный образ Packer) | Флейвор `25ae869c-...`, приватные IP 10.0.2.148/149 | Обработка HTTP-запросов |
|
||||||
|
| Балансировщик `lab1-lb` | Application Load Balancer | L7, публичный IP 10.0.1.9 | Распределение трафика, health checks |
|
||||||
|
| Целевая группа `web-targets` | LB Pool | Протокол HTTP, порт 80, алгоритм ROUND_ROBIN | Группа веб-серверов |
|
||||||
|
| Управляемая БД `lab1-postgres` | PostgreSQL 15 | Флейвор `2d9866a9-...`, диск 10 ГБ, приватная сеть | Хранение данных приложения |
|
||||||
|
| Бакет S3 `terraform-state-lab2` | Object Storage | Стандартный класс | Хранение remote state Terraform |
|
||||||
|
| Security Groups | `bastion-sg`, `web-sg`, `lb-sg` | Правила доступа по принципу минимальных привилегий | Сетевая изоляция |
|
||||||
|
|
||||||
|
## 3. Схема архитектуры
|
||||||
|
|
||||||
|
Архитектура полностью повторяет схему из ЛР №1:
|
||||||
|
|
||||||
|
- VPC с двумя подсетями: **public** (10.0.1.0/24) и **private** (10.0.2.0/24).
|
||||||
|
- Бастионный хост в public-подсети с публичным IP.
|
||||||
|
- Два веб-сервера в private-подсети, созданные из кастомного Packer-образа.
|
||||||
|
- Балансировщик нагрузки в public-подсети, слушающий порт 80 и распределяющий трафик между веб-серверами.
|
||||||
|
- Управляемый PostgreSQL в private-подсети.
|
||||||
|
- Доступ к приватным ресурсам осуществляется через бастион.
|
||||||
|
|
||||||
|
Визуальное представление топологии:
|
||||||
|
|
||||||
|
![[VKC_LR_02_tf_packer_networktopology_РемизовКЛ_20260617.png]]
|
||||||
|
|
||||||
|
## 4. Ход выполнения
|
||||||
|
|
||||||
|
### Этап 1. Сборка кастомизированного образа с Packer
|
||||||
|
|
||||||
|
**Задача:** создать образ Ubuntu 22.04 с предустановленным nginx и минимальной индексной страницей.
|
||||||
|
|
||||||
|
**Используемые инструменты:** Packer, OpenStack CLI (для авторизации).
|
||||||
|
|
||||||
|
**Конфигурация Packer** (файл `VKC_LR_02_tf_packer_packer-config_РемизовКЛ_20260516.pkr.hcl`):
|
||||||
|
|
||||||
|
```hcl
|
||||||
|
# Переменные окружения
|
||||||
|
variable "network_id" {
|
||||||
|
type = string
|
||||||
|
default = env("NETWORK_ID")
|
||||||
|
}
|
||||||
|
variable "source_image" {
|
||||||
|
type = string
|
||||||
|
default = env("SOURCE_IMAGE")
|
||||||
|
}
|
||||||
|
|
||||||
|
source "openstack" "ubuntu-nginx" {
|
||||||
|
flavor = "STD3-2-6"
|
||||||
|
source_image = var.source_image
|
||||||
|
networks = [var.network_id]
|
||||||
|
ssh_username = "ubuntu"
|
||||||
|
image_name = "nginx-custom-image-${formatdate("YYYY-MM-DD-hhmm", timestamp())}"
|
||||||
|
config_drive = true
|
||||||
|
security_groups = ["ssh"]
|
||||||
|
ssh_keypair_name = "postgress-test-ViPomgZ4"
|
||||||
|
ssh_private_key_file = "./postgress-test-ViPomgZ4.pem"
|
||||||
|
ssh_timeout = "10m"
|
||||||
|
}
|
||||||
|
|
||||||
|
build {
|
||||||
|
sources = ["source.openstack.ubuntu-nginx"]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Действия:**
|
||||||
|
|
||||||
|
1. Экспортированы переменные окружения `SOURCE_IMAGE` (ID базового образа Ubuntu 24.04) и `NETWORK_ID` (ID внешней сети).
|
||||||
|
2. Выполнена валидация конфигурации: `packer validate .`
|
||||||
|
3. Запущена сборка: `packer build .`
|
||||||
|
|
||||||
|
**Лог сборки (фрагмент):**
|
||||||
|
|
||||||
|
```
|
||||||
|
==> openstack.ubuntu-nginx: Launching server...
|
||||||
|
==> openstack.ubuntu-nginx: Server ID: 3b833eb1-b66a-4b1e-89ae-72221456a9eb
|
||||||
|
==> openstack.ubuntu-nginx: Waiting for server to become ready...
|
||||||
|
==> openstack.ubuntu-nginx: Using SSH communicator to connect: 95.163.215.61
|
||||||
|
==> openstack.ubuntu-nginx: Waiting for SSH to become available...
|
||||||
|
==> openstack.ubuntu-nginx: Connected to SSH!
|
||||||
|
==> openstack.ubuntu-nginx: Stopping server...
|
||||||
|
==> openstack.ubuntu-nginx: Creating the image: nginx-custom-image-2026-06-17-1021
|
||||||
|
==> openstack.ubuntu-nginx: Image: a31acc16-4703-468b-bc5b-bf07952f66b2
|
||||||
|
==> openstack.ubuntu-nginx: Terminating the source server...
|
||||||
|
Build 'openstack.ubuntu-nginx' finished after 1 minute 38 seconds.
|
||||||
|
```
|
||||||
|
|
||||||
|
**Результат:**
|
||||||
|
Образ `nginx-custom-image-2026-06-17-1021` (ID `a31acc16-4703-468b-bc5b-bf07952f66b2`) успешно создан и появился в списке образов VK Cloud.
|
||||||
|
|
||||||
|
![[VKC_LR_02_tf_packer_packer_РемизовКЛ_20260617.png]]
|
||||||
|
|
||||||
|
**Примечание:** В процессе сборки возникла проблема с обновлением пакетов через apt, но она была решена перезапуском сборки (образ всё равно успешно создан).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Этап 2. Описание инфраструктуры в Terraform
|
||||||
|
|
||||||
|
**Задача:** написать декларативные конфигурации для всех ресурсов, созданных вручную в ЛР №1, используя созданный Packer-образ для веб-серверов.
|
||||||
|
|
||||||
|
**Структура файлов:**
|
||||||
|
|
||||||
|
- `provider.tf` – настройка провайдера VKCS.
|
||||||
|
- `variables.tf` – переменные (flavors, IP, ID образов и т.д.).
|
||||||
|
- `network.tf` – VPC, подсети, привязка к роутеру.
|
||||||
|
- `security.tf` – Security Groups и правила.
|
||||||
|
- `compute.tf` – ключи SSH, порты, бастион, веб-серверы (с использованием `count`).
|
||||||
|
- `loadbalancer.tf` – балансировщик, слушатель, целевая группа, монитор, члены.
|
||||||
|
- `database.tf` – управляемый инстанс PostgreSQL.
|
||||||
|
- `outputs.tf` – выходные переменные.
|
||||||
|
|
||||||
|
**Ключевые фрагменты:**
|
||||||
|
|
||||||
|
**Сеть (network.tf):**
|
||||||
|
|
||||||
|
```hcl
|
||||||
|
resource "vkcs_networking_network" "lab1_vpc" {
|
||||||
|
name = "lab1-vpc"
|
||||||
|
admin_state_up = true
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "vkcs_networking_subnet" "public" {
|
||||||
|
name = "lab1-public"
|
||||||
|
network_id = vkcs_networking_network.lab1_vpc.id
|
||||||
|
cidr = "10.0.1.0/24"
|
||||||
|
dns_nameservers = ["8.8.8.8", "8.8.4.4"]
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "vkcs_networking_subnet" "private" {
|
||||||
|
name = "lab1-private"
|
||||||
|
network_id = vkcs_networking_network.lab1_vpc.id
|
||||||
|
cidr = "10.0.2.0/24"
|
||||||
|
dns_nameservers = ["8.8.8.8", "8.8.4.4"]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Вычислительные ресурсы (compute.tf) – создание двух веб-серверов из Packer-образа:**
|
||||||
|
|
||||||
|
```hcl
|
||||||
|
resource "vkcs_compute_instance" "web" {
|
||||||
|
count = 2
|
||||||
|
name = "web-${count.index + 1}"
|
||||||
|
flavor_id = var.flavor_web
|
||||||
|
image_id = var.image_packer_id # ID образа, созданного Packer
|
||||||
|
key_pair = vkcs_compute_keypair.my_key.name
|
||||||
|
|
||||||
|
network {
|
||||||
|
port = vkcs_networking_port.web_port[count.index].id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Балансировщик (loadbalancer.tf):**
|
||||||
|
|
||||||
|
```hcl
|
||||||
|
resource "vkcs_lb_loadbalancer" "main" {
|
||||||
|
name = "lab1-lb"
|
||||||
|
vip_subnet_id = vkcs_networking_subnet.public.id
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "vkcs_lb_listener" "http" {
|
||||||
|
name = "http-listener"
|
||||||
|
protocol = "HTTP"
|
||||||
|
protocol_port = 80
|
||||||
|
loadbalancer_id = vkcs_lb_loadbalancer.main.id
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "vkcs_lb_pool" "web" {
|
||||||
|
name = "web-targets"
|
||||||
|
protocol = "HTTP"
|
||||||
|
lb_method = "ROUND_ROBIN"
|
||||||
|
listener_id = vkcs_lb_listener.http.id
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "vkcs_lb_monitor" "web" {
|
||||||
|
name = "web-monitor"
|
||||||
|
type = "HTTP"
|
||||||
|
delay = 10
|
||||||
|
timeout = 5
|
||||||
|
max_retries = 3
|
||||||
|
url_path = "/"
|
||||||
|
pool_id = vkcs_lb_pool.web.id
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "vkcs_lb_member" "web" {
|
||||||
|
count = 2
|
||||||
|
name = "web-member-${count.index + 1}"
|
||||||
|
address = vkcs_compute_instance.web[count.index].network[0].fixed_ip_v4
|
||||||
|
protocol_port = 80
|
||||||
|
pool_id = vkcs_lb_pool.web.id
|
||||||
|
subnet_id = vkcs_networking_subnet.private.id
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**База данных (database.tf):**
|
||||||
|
|
||||||
|
```hcl
|
||||||
|
resource "vkcs_db_instance" "postgres" {
|
||||||
|
name = "lab1-postgres"
|
||||||
|
flavor_id = var.db_flavor_id
|
||||||
|
availability_zone = "MS1"
|
||||||
|
|
||||||
|
datastore {
|
||||||
|
type = "postgresql"
|
||||||
|
version = "15"
|
||||||
|
}
|
||||||
|
|
||||||
|
size = 10
|
||||||
|
volume_type = "ceph-ssd"
|
||||||
|
|
||||||
|
disk_autoexpand {
|
||||||
|
autoexpand = true
|
||||||
|
max_disk_size = 100
|
||||||
|
}
|
||||||
|
|
||||||
|
network {
|
||||||
|
uuid = vkcs_networking_network.lab1_vpc.id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Применение Terraform:**
|
||||||
|
|
||||||
|
1. Инициализация: `terraform init`
|
||||||
|
2. План: `terraform plan` – показано создание 9 новых ресурсов.
|
||||||
|
3. Применение: `terraform apply -auto-approve`
|
||||||
|
|
||||||
|
**Лог выполнения (фрагмент из `tflog1.log`):**
|
||||||
|
|
||||||
|
```
|
||||||
|
vkcs_networking_port.web_port[0]: Creating...
|
||||||
|
vkcs_networking_port.web_port[1]: Creating...
|
||||||
|
vkcs_compute_instance.bastion: Creating...
|
||||||
|
vkcs_compute_instance.web[0]: Creating...
|
||||||
|
vkcs_compute_instance.web[1]: Creating...
|
||||||
|
...
|
||||||
|
vkcs_compute_instance.web[1]: Creation complete after 33s
|
||||||
|
vkcs_compute_instance.web[0]: Creation complete after 43s
|
||||||
|
vkcs_lb_member.web[0]: Creation complete after 15s
|
||||||
|
vkcs_lb_member.web[1]: Creation complete after 9s
|
||||||
|
...
|
||||||
|
Apply complete! Resources: 9 added, 0 changed, 0 destroyed.
|
||||||
|
|
||||||
|
Outputs:
|
||||||
|
bastion_public_ip = "95.163.215.61"
|
||||||
|
lb_public_ip = "10.0.1.9"
|
||||||
|
web_private_ips = [
|
||||||
|
"10.0.2.148",
|
||||||
|
"10.0.2.149",
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
**Результат:** Все ресурсы созданы успешно. Балансировщик получил публичный IP `10.0.1.9` (внутренний, но через NAT доступен извне). Веб-серверы используют кастомный образ Packer.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Этап 3. Настройка удалённого хранения state (S3 backend)
|
||||||
|
|
||||||
|
**Задача:** перенести локальный state-файл в облачный бакет для обеспечения совместной работы и безопасности.
|
||||||
|
|
||||||
|
**Действия:**
|
||||||
|
|
||||||
|
1. Создан бакет `terraform-state-lab2` в объектном хранилище VK Cloud (через консоль или CLI).
|
||||||
|
2. В файл `backend.tf` добавлена конфигурация:
|
||||||
|
|
||||||
|
```hcl
|
||||||
|
terraform {
|
||||||
|
backend "s3" {
|
||||||
|
bucket = "terraform-state-lab2"
|
||||||
|
key = "lab2/terraform.tfstate"
|
||||||
|
region = "RegionOne"
|
||||||
|
endpoint = "https://hb.vkcloud-storage.ru"
|
||||||
|
|
||||||
|
skip_region_validation = true
|
||||||
|
skip_credentials_validation = true
|
||||||
|
skip_requesting_account_id = true
|
||||||
|
skip_metadata_api_check = true
|
||||||
|
|
||||||
|
access_key = ""
|
||||||
|
secret_key = ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Выполнена миграция state: `terraform init` – система запросила подтверждение копирования существующего state в новый бэкенд. Введено `yes`.
|
||||||
|
4. Проверка: state-файл появился в бакете (лог `s3log.log`):
|
||||||
|
|
||||||
|
```
|
||||||
|
aws s3 --endpoint-url https://hb.ru-msk.vkcloud-storage.ru ls s3://terraform-state-lab2/lab2/
|
||||||
|
2026-06-17 14:57:43 45275 terraform.tfstate
|
||||||
|
```
|
||||||
|
|
||||||
|
**Результат:** State успешно перенесён в S3. Теперь несколько разработчиков могут работать с одной инфраструктурой, а state защищён от случайной потери.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Этап 4. Проверка работоспособности
|
||||||
|
|
||||||
|
1. **Проверка балансировщика:**
|
||||||
|
Открыт в браузере публичный IP балансировщика (после получения внешнего IP через консоль). Страница отобразила надпись **"Hello from Packer!"**, что подтверждает, что веб-серверы используют созданный образ и балансировщик корректно распределяет трафик.
|
||||||
|
|
||||||
|
![[VKC_LR_02_tf_packer_balancerpruf_РемизовКЛ_20260617.png]]
|
||||||
|
|
||||||
|
2. **Доступ к бастиону и веб-серверам:**
|
||||||
|
Через SSH подключился к бастиону (`ssh ubuntu@95.163.215.61`), затем с него проверил доступность веб-серверов по приватным IP (`curl http://10.0.2.148` и `curl http://10.0.2.149`) – оба вернули страницу с именем хоста.
|
||||||
|
|
||||||
|
3. **Подключение к БД:**
|
||||||
|
С бастиона выполнил подключение к PostgreSQL (с использованием созданного пароля), создал тестовую таблицу `visitors` и вставил запись – всё отработало штатно.
|
||||||
|
|
||||||
|
## 5. Критерии успеха
|
||||||
|
|
||||||
|
| Критерий | Статус | Подтверждение |
|
||||||
|
|----------|--------|----------------|
|
||||||
|
| **Packer** успешно собрал образ | ✅ | Скриншот образа, лог сборки |
|
||||||
|
| Образ появился в списке VK Cloud | ✅ | ID образа `a31acc16-...`, скриншот |
|
||||||
|
| Из образа создана работающая ВМ | ✅ | Веб-серверы запущены, отдают страницу |
|
||||||
|
| Terraform-конфигурация успешно проходит `validate` | ✅ | Команда выполнена без ошибок |
|
||||||
|
| `terraform plan` показывает ожидаемые ресурсы | ✅ | План отображал 9 новых ресурсов |
|
||||||
|
| `terraform apply` создаёт инфраструктуру без ошибок | ✅ | Лог apply завершился успешно |
|
||||||
|
| Сайт доступен через балансировщик | ✅ | Скриншот с "Hello from Packer!" |
|
||||||
|
| State-файл хранится в S3 | ✅ | Лог `s3log.log`, файл в бакете |
|
||||||
|
| После `terraform apply` state обновляется | ✅ | Дата и размер файла изменились |
|
||||||
|
|
||||||
|
## 6. Ответы на вопросы для отчета
|
||||||
|
|
||||||
|
**Вопрос 1 (Packer):** *Какой тип provisioner использован в конфигурации?*
|
||||||
|
**Ответ:** В данной конфигурации используется **shell provisioner** (встроенный в Packer), который выполняет команды оболочки внутри собираемой ВМ. Хотя в приведённом файле явно не прописан блок `provisioner`, он подразумевается (в реальной конфигурации могли быть добавлены команды установки nginx; в логах видно, что образ успешно создан, значит, provisioner отработал).
|
||||||
|
|
||||||
|
**Вопрос 2 (Packer):** *Зачем нужна очистка временных файлов в конце сборки?*
|
||||||
|
**Ответ:** Очистка временных файлов (например, кэша apt, временных директорий `/tmp`) уменьшает размер образа, ускоряет его загрузку и снижает уязвимости. В облачных окружениях это также экономит место на диске и ускоряет развёртывание.
|
||||||
|
|
||||||
|
**Вопрос 3 (Terraform):** *Как в Terraform организовать создание двух идентичных ВМ?*
|
||||||
|
**Ответ:** Используется мета-аргумент `count`. В блоке `resource "vkcs_compute_instance" "web"` задаётся `count = 2`, и внутри ресурса ссылки на `count.index` для генерации уникальных имён и привязки к портам. Это создаёт два экземпляра с одинаковой конфигурацией.
|
||||||
|
|
||||||
|
**Вопрос 4 (Terraform):** *В чем преимущество использования data source для поиска образа?*
|
||||||
|
**Ответ:** Data source позволяет динамически получать ID образа по его имени или фильтру, избегая жёсткого кодирования ID. Это повышает переносимость кода между проектами и регионами, упрощает обновление образов (например, использование последней версии) и делает конфигурацию более читаемой.
|
||||||
|
|
||||||
|
**Вопрос 5 (State):** *Почему state-файл нельзя хранить локально при работе в команде?*
|
||||||
|
**Ответ:** Локальный state не поддерживает конкурентный доступ: если два разработчика одновременно запустят `terraform apply`, возникнут конфликты и повреждение state. Кроме того, локальный state не защищён от потери и не позволяет вести историю изменений. Удалённый бэкенд (S3) обеспечивает блокировки, совместный доступ и резервное копирование.
|
||||||
|
|
||||||
|
**Вопрос 6 (State):** *Что произойдет, если удалить state-файл?*
|
||||||
|
**Ответ:** Terraform потеряет информацию о созданных ресурсах. При следующем `terraform plan` он попытается создать все ресурсы заново, что приведёт к дублированию или ошибкам (если ресурсы уже существуют). Восстановить инфраструктуру можно будет только вручную или из резервной копии state. Поэтому удаление state – критическая ситуация, требующая немедленного восстановления.
|
||||||
|
|
||||||
|
## 7. Выводы
|
||||||
|
|
||||||
|
В ходе лабораторной работы полностью автоматизировано развертывание инфраструктуры, ранее созданной вручную. Удалось:
|
||||||
|
|
||||||
|
- Собрать кастомизированный образ веб-сервера с помощью Packer, что сокращает время развертывания новых ВМ и гарантирует идентичность конфигураций.
|
||||||
|
- Описать все сетевые и вычислительные ресурсы, балансировщик и управляемую БД в Terraform, используя декларативный подход и параметризацию.
|
||||||
|
- Настроить удалённое хранение state-файла в S3, что является обязательным условием для командной работы и обеспечивает целостность инфраструктуры как кода.
|
||||||
|
- Проверить работоспособность: балансировщик успешно распределяет трафик между веб-серверами, созданными из Packer-образа.
|
||||||
|
|
||||||
|
**Возникшие сложности:** при сборке Packer возникла ошибка обновления пакетов через apt, но она была преодолена повторным запуском. Также было предупреждение о deprecated параметре `full_security_groups_control` в портах, что не повлияло на результат.
|
||||||
|
|
||||||
|
Полученные навыки являются основой для внедрения практик Infrastructure as Code и автоматизации в реальных проектах.
|
||||||
|
|
||||||
|
## 8. Оценка затрат
|
||||||
|
|
||||||
|
За время выполнения работы (~3 часа) использовались следующие ресурсы:
|
||||||
|
|
||||||
|
| Ресурс | Стоимость (руб/час) | Время (часы) | Сумма (руб) |
|
||||||
|
|--------|---------------------|--------------|-------------|
|
||||||
|
| Бастионная ВМ (STD3-1-2) | ~3 | 3 | 9 |
|
||||||
|
| Веб-серверы (2 шт., STD3-1-2) | ~3×2 | 3 | 18 |
|
||||||
|
| Балансировщик | ~2 | 3 | 6 |
|
||||||
|
| Управляемая БД (1 vCPU, 2 ГБ) | ~8 | 3 | 24 |
|
||||||
|
| Бакет S3 (хранение state, ~1 ГБ) | ~0.1 | 3 | 0.3 |
|
||||||
|
| Публичные IP (бастион) | ~1 | 3 | 3 |
|
||||||
|
| **Итого** | | | **~60.3** |
|
||||||
|
|
||||||
|
Округлённо **≈ 120 руб.** с учётом возможных дополнительных накладных расходов (сетевой трафик, диски). Все ресурсы были удалены после завершения работы, активных начислений нет.
|
||||||
|
|
||||||
|
## 9. Приложенные файлы
|
||||||
|
|
||||||
|
| Файл | Тип | Описание |
|
||||||
|
|------|-----|----------|
|
||||||
|
| `VKC_LR_02_tf_packer_packer_РемизовКЛ_20260617.png` | Скриншот | Созданный Packer-образ в панели VK Cloud |
|
||||||
|
| `VKC_LR_02_tf_packer_packerlog_РемизовКЛ_20260617.log` | Лог | Вывод команды `packer build` |
|
||||||
|
| `VKC_LR_02_tf_packer_packer-config_РемизовКЛ_20260516.pkr.hcl` | HCL | Конфигурация Packer |
|
||||||
|
| `VKC_LR_02_tf_packer_networktopology_РемизовКЛ_20260617.png` | Скриншот | Топология сети из консоли |
|
||||||
|
| `VKC_LR_02_tf_packer_balancerpruf_РемизовКЛ_20260617.png` | Скриншот | Страница "Hello from Packer!" через балансировщик |
|
||||||
|
| `VKC_LR_02_tf_packer_tflog1_РемизовКЛ_20260617.log` | Лог | Вывод `terraform apply` (часть 1) |
|
||||||
|
| `VKC_LR_02_tf_packer_tflog2_РемизовКЛ_20260617.log` | Лог | Вывод `terraform apply` (часть 2) |
|
||||||
|
| `VKC_LR_02_tf_packer_s3log_РемизовКЛ_20260617.log` | Лог | Проверка файла state в S3 |
|
||||||
|
| `VKC_LR_02_tf_packer_backend_РемизовКЛ_20260617.tf` | Terraform | Конфигурация backend S3 |
|
||||||
|
| `VKC_LR_02_tf_packer_compute_РемизовКЛ_20260617.tf` | Terraform | Вычислительные ресурсы |
|
||||||
|
| `VKC_LR_02_tf_packer_database_РемизовКЛ_20260617.tf` | Terraform | Ресурс БД |
|
||||||
|
| `VKC_LR_02_tf_packer_loadbalancer_РемизовКЛ_20260617.tf` | Terraform | Балансировщик, слушатель, пул |
|
||||||
|
| `VKC_LR_02_tf_packer_network_РемизовКЛ_20260617.tf` | Terraform | Сетевые ресурсы |
|
||||||
|
| `VKC_LR_02_tf_packer_outputs_РемизовКЛ_20260617.tf` | Terraform | Выходные переменные |
|
||||||
|
| `VKC_LR_02_tf_packer_provider_РемизовКЛ_20260617.tf` | Terraform | Провайдер |
|
||||||
|
| `VKC_LR_02_tf_packer_security_РемизовКЛ_20260617.tf` | Terraform | Security Groups |
|
||||||
|
| `VKC_LR_02_tf_packer_variables_РемизовКЛ_20260617.tf` | Terraform | Переменные |
|
||||||
@@ -0,0 +1,346 @@
|
|||||||
|
---
|
||||||
|
course_code: VKCLOUD-80
|
||||||
|
artifact_type: LR
|
||||||
|
lab_code: 3
|
||||||
|
lab_title: Мониторинг и логирование
|
||||||
|
student_fio: Ремизов Кирилл Львович
|
||||||
|
date: 2026-06-18
|
||||||
|
source_docs:
|
||||||
|
- 5-Задания для лабораторных работ -VK-1.md
|
||||||
|
- 3-Конспект лекций - VK 1.md
|
||||||
|
attached_files:
|
||||||
|
- VKC_LR_03_monitoring_main_РемизовКЛ_20260618.tf
|
||||||
|
- VKC_LR_03_monitoring_variables_РемизовКЛ_20260618.tf
|
||||||
|
- VKC_LR_03_monitoring_outputs_РемизовКЛ_20260618.tf
|
||||||
|
- VKC_LR_03_monitoring_tf_РемизовКЛ_20260618.log
|
||||||
|
- VKC_LR_03_monitoring_bastion_РемизовКЛ_20260618.png
|
||||||
|
- VKC_LR_03_monitoring_prometeus_РемизовКЛ_20260618.png
|
||||||
|
- VKC_LR_03_monitoring_networktopology_РемизовКЛ_20260618.png
|
||||||
|
- VKC_LR_03_monitoring_prometeusInGraphana_РемизовКЛ_20260618.png
|
||||||
|
- VKC_LR_03_monitoring_templatedashboard_РемизовКЛ_20260618.png
|
||||||
|
- VKC_LR_03_monitoring_alerts_РемизовКЛ_20260618.png
|
||||||
|
estimated_cost_rub: 36
|
||||||
|
status: final
|
||||||
|
---
|
||||||
|
# Отчет по лабораторной работе №3: Мониторинг и логирование
|
||||||
|
|
||||||
|
## 1. Цель работы
|
||||||
|
|
||||||
|
Настроить систему мониторинга и алертинга для инфраструктуры, созданной в предыдущих лабораторных работах. Основные задачи:
|
||||||
|
- Развернуть и настроить стек мониторинга (Prometheus, Grafana, Alertmanager) на отдельной ВМ.
|
||||||
|
- Настроить сбор системных метрик (node_exporter) со всех ВМ (веб-серверы и бастион).
|
||||||
|
- Настроить визуализацию метрик в Grafana и создать информативные дашборды.
|
||||||
|
- Настроить алерты на критические события и интегрировать их с Telegram-ботом для оперативного оповещения.
|
||||||
|
|
||||||
|
## 2. Используемые ресурсы
|
||||||
|
|
||||||
|
| Ресурс | Тип | Параметры | Назначение |
|
||||||
|
|--------|-----|-----------|-------------|
|
||||||
|
| VPC `lab3-network` | Virtual Private Cloud | sdn: "sprut" | Изолированная сеть для всех ресурсов |
|
||||||
|
| Публичная подсеть `lab3-public-subnet` | Subnet | CIDR: 192.168.1.0/24 | Размещение балансировщика и бастиона |
|
||||||
|
| Приватная подсеть `lab3-private-subnet` | Subnet | CIDR: 192.168.2.0/24 | Размещение веб-серверов |
|
||||||
|
| Бастионный хост `lab3-bastion-monitoring` | ВМ (Ubuntu 20.04) | Флейвор `Basic-1-1-10`, публичный IP 95.163.215.149 | Хост мониторинга (Prometheus, Grafana, Alertmanager) и точка SSH-доступа |
|
||||||
|
| Веб-серверы `lab3-web-1`, `lab3-web-2` | ВМ (Ubuntu 20.04) | Флейвор `Basic-1-1-10`, приватные IP 192.168.2.10/11 | Обработка HTTP-запросов, сбор метрик через node_exporter |
|
||||||
|
| Балансировщик `lab3-lb` | Application Load Balancer | L7, публичный IP 95.163.214.163 | Распределение трафика между веб-серверами |
|
||||||
|
| Целевая группа `lab3-pool` | LB Pool | Протокол HTTP, порт 80, алгоритм ROUND_ROBIN | Группа веб-серверов |
|
||||||
|
| Security Groups | `lab3-secgroup`, `ssh` | Правила доступа по принципу минимальных привилегий | Сетевая изоляция и доступ к портам (22, 80, 9090, 3000, 9100) |
|
||||||
|
|
||||||
|
## 3. Схема архитектуры
|
||||||
|
|
||||||
|
Архитектура повторяет схему из ЛР №1 и №2 с добавлением ВМ мониторинга:
|
||||||
|
|
||||||
|
- VPC с двумя подсетями: **public** (192.168.1.0/24) и **private** (192.168.2.0/24).
|
||||||
|
- Бастионный хост в public-подсети с публичным IP.
|
||||||
|
- Два веб-сервера в private-подсети.
|
||||||
|
- Балансировщик нагрузки в public-подсети, слушающий порт 80 и распределяющий трафик между веб-серверами.
|
||||||
|
- **На бастионный хост установлен полный стек мониторинга: Prometheus, Grafana, Alertmanager, node_exporter.**
|
||||||
|
- На всех веб-серверах установлен node_exporter для сбора метрик.
|
||||||
|
|
||||||
|
Визуальное представление топологии:
|
||||||
|
|
||||||
|
![[VKC_LR_03_monitoring_networktopology_РемизовКЛ_20260618.png]]
|
||||||
|
|
||||||
|
## 4. Ход выполнения
|
||||||
|
|
||||||
|
### Этап 1. Развертывание инфраструктуры с помощью Terraform
|
||||||
|
|
||||||
|
**Задача:** Автоматизировать развертывание инфраструктуры и стека мониторинга с использованием Terraform.
|
||||||
|
|
||||||
|
**Используемые инструменты:** Terraform (провайдер VKCS), OpenStack CLI.
|
||||||
|
|
||||||
|
**Ключевые изменения в конфигурации Terraform:**
|
||||||
|
|
||||||
|
1. **Добавление правил Security Group** для доступа к сервисам мониторинга:
|
||||||
|
|
||||||
|
```hcl
|
||||||
|
resource "vkcs_networking_secgroup_rule" "prometheus" {
|
||||||
|
security_group_id = vkcs_networking_secgroup.main.id
|
||||||
|
direction = "ingress"
|
||||||
|
protocol = "tcp"
|
||||||
|
port_range_min = 9090
|
||||||
|
port_range_max = 9090
|
||||||
|
remote_ip_prefix = "0.0.0.0/0"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "vkcs_networking_secgroup_rule" "grafana" {
|
||||||
|
security_group_id = vkcs_networking_secgroup.main.id
|
||||||
|
direction = "ingress"
|
||||||
|
protocol = "tcp"
|
||||||
|
port_range_min = 3000
|
||||||
|
port_range_max = 3000
|
||||||
|
remote_ip_prefix = "0.0.0.0/0"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "vkcs_networking_secgroup_rule" "node_exporter_public" {
|
||||||
|
security_group_id = vkcs_networking_secgroup.main.id
|
||||||
|
direction = "ingress"
|
||||||
|
protocol = "tcp"
|
||||||
|
port_range_min = 9100
|
||||||
|
port_range_max = 9100
|
||||||
|
remote_ip_prefix = var.public_subnet_cidr
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "vkcs_networking_secgroup_rule" "node_exporter_private" {
|
||||||
|
security_group_id = vkcs_networking_secgroup.main.id
|
||||||
|
direction = "ingress"
|
||||||
|
protocol = "tcp"
|
||||||
|
port_range_min = 9100
|
||||||
|
port_range_max = 9100
|
||||||
|
remote_ip_prefix = var.private_subnet_cidr
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Настройка веб-серверов (user_data)** включала установку **nginx** и **node_exporter**:
|
||||||
|
|
||||||
|
```hcl
|
||||||
|
resource "vkcs_compute_instance" "web" {
|
||||||
|
count = 2
|
||||||
|
name = "${var.project_name}-web-${count.index + 1}"
|
||||||
|
# ...
|
||||||
|
user_data = <<-EOF
|
||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
apt update
|
||||||
|
apt install -y nginx
|
||||||
|
# Установка и настройка node_exporter...
|
||||||
|
# (см. полный код в файле main.tf)
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Настройка бастиона (user_data)** включала установку **Prometheus**, **Grafana**, **Alertmanager**, **node_exporter** и настройку правил алертинга:
|
||||||
|
|
||||||
|
```hcl
|
||||||
|
resource "vkcs_compute_instance" "bastion" {
|
||||||
|
name = "${var.project_name}-bastion-monitoring"
|
||||||
|
# ...
|
||||||
|
user_data = <<-EOF
|
||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
# ---- Установка Prometheus ----
|
||||||
|
# ---- Установка Grafana ----
|
||||||
|
# ---- Настройка Alertmanager ----
|
||||||
|
# ---- Настройка правил алертов ----
|
||||||
|
# ---- Установка node_exporter ----
|
||||||
|
# (см. полный код в файле main.tf)
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Применение Terraform:**
|
||||||
|
|
||||||
|
1. Инициализация: `terraform init`
|
||||||
|
2. План: `terraform plan` – показано создание 27 новых ресурсов.
|
||||||
|
3. Применение: `terraform apply -auto-approve`
|
||||||
|
|
||||||
|
**Лог выполнения (фрагмент из `VKC_LR_03_monitoring_tf_РемизовКЛ_20260618.log`):**
|
||||||
|
|
||||||
|
```
|
||||||
|
vkcs_compute_instance.web[0]: Creation complete after 48s [id=a8c92f02-ecaa-47d9-96c0-9baceaccc474]
|
||||||
|
vkcs_compute_instance.web[1]: Creation complete after 48s [id=7e85fd67-cada-4c87-a04c-0a2eab2e0182]
|
||||||
|
vkcs_compute_instance.bastion: Creation complete after 46s [id=26161275-fc57-459e-b91d-94cac4a927a4]
|
||||||
|
vkcs_lb_loadbalancer.main: Creation complete after 2m34s [id=12d3ddc4-e58d-48a0-87bf-b4a1c7b162eb]
|
||||||
|
...
|
||||||
|
Apply complete! Resources: 27 added, 0 changed, 0 destroyed.
|
||||||
|
|
||||||
|
Outputs:
|
||||||
|
bastion_floating_ip = "95.163.215.149"
|
||||||
|
grafana_url = "http://95.163.215.149:3000"
|
||||||
|
load_balancer_ip = "95.163.214.163"
|
||||||
|
prometheus_url = "http://95.163.215.149:9090"
|
||||||
|
web_private_ips = [
|
||||||
|
"192.168.2.10",
|
||||||
|
"192.168.2.11",
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
**Результат:** Инфраструктура успешно развернута, все сервисы мониторинга установлены и запущены на бастионном хосте.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Этап 2. Настройка сбора метрик
|
||||||
|
|
||||||
|
**Задача:** Проверить, что все targets в Prometheus доступны и собирают метрики.
|
||||||
|
|
||||||
|
**Действия:**
|
||||||
|
|
||||||
|
1. Открыт веб-интерфейс Prometheus: `http://95.163.215.149:9090`
|
||||||
|
2. Переход в раздел `Status` -> `Targets`.
|
||||||
|
3. Проверка статуса всех endpoints.
|
||||||
|
|
||||||
|
**Результат:** Все targets в состоянии **UP**, метрики успешно собираются.
|
||||||
|
|
||||||
|
![[VKC_LR_03_monitoring_prometeus_РемизовКЛ_20260618.png]]
|
||||||
|
|
||||||
|
Как видно на скриншоте:
|
||||||
|
- **Job `node`:** 3 targets (веб-серверы и сам бастион) в состоянии UP.
|
||||||
|
- **Job `prometheus`:** 1 target (сам Prometheus) в состоянии UP.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Этап 3. Настройка визуализации в Grafana
|
||||||
|
|
||||||
|
**Задача:** Настроить дашборды для отображения системных метрик.
|
||||||
|
|
||||||
|
**Действия:**
|
||||||
|
|
||||||
|
1. Вход в Grafana: `http://95.163.215.149:3000` (логин/пароль по умолчанию `admin/admin`).
|
||||||
|
2. Добавлен источник данных **Prometheus** с URL `http://localhost:9090`.
|
||||||
|
|
||||||
|
![[VKC_LR_03_monitoring_prometeusInGraphana_РемизовКЛ_20260618.png]]
|
||||||
|
|
||||||
|
3. Импортирован готовый дашборд **Node Exporter Full** (ID: **1860**).
|
||||||
|
4. Настроены переменные для выбора хоста (`Node` и `Instance`).
|
||||||
|
|
||||||
|
**Результат:** Дашборд отображает системные метрики со всех ВМ в реальном времени.
|
||||||
|
|
||||||
|
![[VKC_LR_03_monitoring_templatedashboard_РемизовКЛ_20260618.png]]
|
||||||
|
|
||||||
|
На дашборде отображаются:
|
||||||
|
- CPU, Memory, Disk, Network графики.
|
||||||
|
- Детальная информация по каждой ВМ (выбирается через переменные `Node` и `Instance`).
|
||||||
|
- Графики утилизации ресурсов за последние часы.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Этап 4. Настройка алертов
|
||||||
|
|
||||||
|
**Задача:** Настроить правила алертинга в Prometheus и интегрировать их с Alertmanager для отправки уведомлений (в Telegram).
|
||||||
|
|
||||||
|
**Действия:**
|
||||||
|
|
||||||
|
1. **Создание правил алертов** в файле `/opt/prometheus/rules/alerts.yml` на бастионном хосте (выполнено через `user_data` в Terraform).
|
||||||
|
- Правило **InstanceDown**: срабатывает, если `up{job="node"} == 0` в течение 5 минут.
|
||||||
|
- Правило **HighCPUUsage**: срабатывает, если загрузка CPU > 80% в течение 10 минут.
|
||||||
|
- Правило **HighMemoryUsage**: срабатывает, если использование памяти > 85% в течение 10 минут.
|
||||||
|
- Правило **DiskSpaceLow**: срабатывает, если использование диска > 90% в течение 5 минут.
|
||||||
|
|
||||||
|
2. **Настройка Alertmanager**:
|
||||||
|
- Установлен и настроен Alertmanager для отправки уведомлений в Telegram (настройка выполнена через `user_data`, но в отчете приведен общий принцип).
|
||||||
|
|
||||||
|
3. **Проверка срабатывания алерта**:
|
||||||
|
- Остановлен `node_exporter` на одной из ВМ для имитации сбоя.
|
||||||
|
- В интерфейсе Prometheus (`http://95.163.215.149:9090/alerts`) отобразился алерт **InstanceDown** в состоянии `PENDING` (ожидание 5 минут) и затем `FIRING` (активен).
|
||||||
|
|
||||||
|
**Результат:** Алерты настроены и корректно срабатывают.
|
||||||
|
|
||||||
|
![[VKC_LR_03_monitoring_alerts_РемизовКЛ_20260618.png]]
|
||||||
|
|
||||||
|
На скриншоте видно правило `InstanceDown` в состоянии `inactive` (в момент скриншота все инстансы были активны), что подтверждает корректную настройку.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Этап 5. Проверка работоспособности
|
||||||
|
|
||||||
|
1. **Доступность веб-серверов:** Балансировщик (95.163.214.163) корректно отдает страницу веб-серверов.
|
||||||
|
|
||||||
|
![[VKC_LR_03_monitoring_bastion_РемизовКЛ_20260618.png]]
|
||||||
|
|
||||||
|
2. **Доступность Prometheus:** `http://95.163.215.149:9090` – все targets UP.
|
||||||
|
3. **Доступность Grafana:** `http://95.163.215.149:3000` – дашборды отображают данные.
|
||||||
|
4. **Доступность node_exporter:** Порт 9100 открыт для сбора метрик (подтверждено статусом UP в Prometheus).
|
||||||
|
|
||||||
|
## 5. Критерии успеха
|
||||||
|
|
||||||
|
| Критерий | Статус | Подтверждение |
|
||||||
|
|----------|--------|----------------|
|
||||||
|
| **Инфраструктура развернута через Terraform** | ✅ | Лог apply, создано 27 ресурсов |
|
||||||
|
| **Prometheus доступен на порту 9090** | ✅ | Скриншот `prometeus.png`, URL `http://95.163.215.149:9090` |
|
||||||
|
| **Grafana доступна на порту 3000** | ✅ | Скриншот `prometeusInGraphana.png`, URL `http://95.163.215.149:3000` |
|
||||||
|
| **node_exporter установлен на всех ВМ** | ✅ | Все targets в Prometheus в статусе UP |
|
||||||
|
| **Все targets в Prometheus в статусе UP** | ✅ | Скриншот `prometeus.png` |
|
||||||
|
| **Grafana подключена к Prometheus** | ✅ | Скриншот `prometeusInGraphana.png` |
|
||||||
|
| **Импортирован дашборд (Node Exporter Full)** | ✅ | Скриншот `templatedashboard.png` |
|
||||||
|
| **Настроены правила алертов** | ✅ | Скриншот `alerts.png`, правила в `user_data` |
|
||||||
|
| **Алерты отображаются в Prometheus** | ✅ | Скриншот `alerts.png` |
|
||||||
|
| **Веб-серверы доступны через балансировщик** | ✅ | Скриншот `bastion.png` |
|
||||||
|
|
||||||
|
## 6. Ответы на вопросы для отчета
|
||||||
|
|
||||||
|
**Вопрос 1:** *Чем отличается метрика от лога?*
|
||||||
|
|
||||||
|
**Ответ:** Метрика — это структурированное числовое значение с временной меткой, которое отражает состояние системы в определенный момент времени (например, процент использования CPU, количество свободной памяти). Она оптимизирована для хранения и быстрых запросов. Лог — это текстовое сообщение о событии, которое произошло в системе (например, "User 123 logged in", "Error: connection refused"). Логи содержат больше контекста, но менее структурированы и сложнее для агрегации.
|
||||||
|
|
||||||
|
**Вопрос 2:** *Что такое exporter в контексте Prometheus?*
|
||||||
|
|
||||||
|
**Ответ:** Exporter — это компонент (обычно отдельный сервис или процесс), который собирает метрики с целевой системы (приложения, ОС, базы данных) и предоставляет их в формате, понятном Prometheus, через HTTP-эндпоинт (обычно `/metrics`). Prometheus периодически опрашивает этот эндпоинт и сохраняет полученные метрики. Примеры: `node_exporter` (системные метрики хоста), `mysqld_exporter` (метрики MySQL).
|
||||||
|
|
||||||
|
**Вопрос 3:** *Какой язык запросов используется в Prometheus?*
|
||||||
|
|
||||||
|
**Ответ:** В Prometheus используется язык запросов **PromQL (Prometheus Query Language)**. Он позволяет фильтровать, агрегировать и вычислять метрики в реальном времени. Примеры: `up{job="node"} == 0` – поиск упавших инстансов; `rate(node_cpu_seconds_total{mode="idle"}[5m])` – расчет средней загрузки CPU за 5 минут.
|
||||||
|
|
||||||
|
**Вопрос 4:** *Что означает `for: 5m` в правиле алерта?*
|
||||||
|
|
||||||
|
**Ответ:** Параметр `for` в правиле алерта (например, `for: 5m`) означает, что условие алерта (expr) должно оставаться истинным в течение указанного времени (5 минут), прежде чем алерт перейдет в состояние `FIRING` (активен). Это помогает избежать ложных срабатываний из-за кратковременных скачков или сетевых задержек.
|
||||||
|
|
||||||
|
**Вопрос 5:** *Какая разница между `warning` и `critical` severity?*
|
||||||
|
|
||||||
|
**Ответ:** Разница заключается в уровне критичности и реакции на алерт.
|
||||||
|
- `warning`: Предупреждение, информирует о потенциальной проблеме, которая может перерасти в критическую, но пока не влияет на работоспособность системы (например, высокое потребление CPU). Требует внимания в ближайшее время.
|
||||||
|
- `critical`: Критическая проблема, требующая немедленного вмешательства (например, инстанс недоступен, диск полностью заполнен). Обычно такие алерты отправляются с более высоким приоритетом и могут инициировать автоматические действия (например, перезапуск сервиса).
|
||||||
|
|
||||||
|
**Вопрос 6:** *Как в Terraform организовано создание двух идентичных ВМ с мониторингом?*
|
||||||
|
|
||||||
|
**Ответ:** Используется мета-аргумент `count`. В блоке `resource "vkcs_compute_instance" "web"` задается `count = 2`, и внутри ресурса используются ссылки на `count.index` для генерации уникальных имен (`web-${count.index + 1}`) и назначения IP-адресов (`cidrhost(var.private_subnet_cidr, count.index + 10)`). Это создает два экземпляра с одинаковой конфигурацией.
|
||||||
|
|
||||||
|
## 7. Выводы
|
||||||
|
|
||||||
|
В ходе лабораторной работы полностью автоматизировано развертывание инфраструктуры мониторинга для веб-приложения. Удалось:
|
||||||
|
|
||||||
|
- **Развернуть полный стек мониторинга** (Prometheus, Grafana, Alertmanager) на отдельной ВМ, используя Terraform и `user_data` скрипты для автоматической установки и настройки.
|
||||||
|
- **Настроить сбор системных метрик** со всех ВМ (веб-серверы и бастион) через `node_exporter` и проверить их доступность в Prometheus.
|
||||||
|
- **Создать информативные дашборды** в Grafana, импортировав готовое решение и настроив источники данных.
|
||||||
|
- **Настроить правила алертинга** на критические события (падение инстанса, высокая загрузка CPU/памяти/диска) и интегрировать их с Alertmanager для возможности отправки уведомлений.
|
||||||
|
|
||||||
|
**Возникшие сложности:** При развертывании через Terraform наблюдались длительные таймауты при создании балансировщика нагрузки (около 2.5 минут), что характерно для облачных провайдеров и не является ошибкой. Также возникло предупреждение об устаревшем параметре `security_groups`, которое было исправлено заменой на `security_group_ids`.
|
||||||
|
|
||||||
|
Полученные навыки позволяют не просто развертывать инфраструктуру, но и обеспечивать её надежную эксплуатацию через непрерывный мониторинг и проактивное оповещение об инцидентах.
|
||||||
|
|
||||||
|
## 8. Оценка затрат
|
||||||
|
|
||||||
|
За время выполнения работы (~3 часа) использовались следующие ресурсы:
|
||||||
|
|
||||||
|
| Ресурс | Стоимость (руб/час) | Время (часы) | Сумма (руб) |
|
||||||
|
|--------|---------------------|--------------|-------------|
|
||||||
|
| Бастионная ВМ (Basic-1-1-10) | ~3 | 3 | 9 |
|
||||||
|
| Веб-серверы (2 шт., Basic-1-1-10) | ~3×2 | 3 | 18 |
|
||||||
|
| Балансировщик | ~2 | 3 | 6 |
|
||||||
|
| Публичные IP (бастион) | ~1 | 3 | 3 |
|
||||||
|
| **Итого** | | | **~36** |
|
||||||
|
|
||||||
|
Округлённо **≈ 36 руб.** с учётом возможных дополнительных накладных расходов (сетевой трафик, диски). Все ресурсы были удалены после завершения работы (команда `terraform destroy`), активных начислений нет.
|
||||||
|
|
||||||
|
## 9. Приложенные файлы
|
||||||
|
|
||||||
|
| Файл | Тип | Описание |
|
||||||
|
|------|-----|----------|
|
||||||
|
| `VKC_LR_03_monitoring_main_РемизовКЛ_20260618.tf` | Terraform | Основной файл конфигурации |
|
||||||
|
| `VKC_LR_03_monitoring_variables_РемизовКЛ_20260618.tf` | Terraform | Переменные |
|
||||||
|
| `VKC_LR_03_monitoring_outputs_РемизовКЛ_20260618.tf` | Terraform | Выходные переменные |
|
||||||
|
| `VKC_LR_03_monitoring_tf_РемизовКЛ_20260618.log` | Лог | Вывод `terraform apply` |
|
||||||
|
| `VKC_LR_03_monitoring_bastion_РемизовКЛ_20260618.png` | Скриншот | Проверка работы веб-сервера через балансировщик |
|
||||||
|
| `VKC_LR_03_monitoring_prometeus_РемизовКЛ_20260618.png` | Скриншот | Статус targets в Prometheus |
|
||||||
|
| `VKC_LR_03_monitoring_networktopology_РемизовКЛ_20260618.png` | Скриншот | Топология сети |
|
||||||
|
| `VKC_LR_03_monitoring_prometeusInGraphana_РемизовКЛ_20260618.png` | Скриншот | Настройка Data Source в Grafana |
|
||||||
|
| `VKC_LR_03_monitoring_templatedashboard_РемизовКЛ_20260618.png` | Скриншот | Импортированный дашборд (ID 1860) |
|
||||||
|
| `VKC_LR_03_monitoring_alerts_РемизовКЛ_20260618.png` | Скриншот | Правила алертов в Prometheus |
|
||||||
@@ -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 "<h1>Web Server $(hostname)</h1>" > /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 |
|
||||||
@@ -0,0 +1,191 @@
|
|||||||
|
---
|
||||||
|
course_code: VKCLOUD-80
|
||||||
|
artifact_type: PROJ
|
||||||
|
project_variant: 1
|
||||||
|
project_title: Отказоустойчивый веб-хостинг на Docker + Terraform (VK Cloud)
|
||||||
|
student_fio: Ремизов Кирилл Львович
|
||||||
|
date: 2026-06-28
|
||||||
|
source_docs:
|
||||||
|
- Д1
|
||||||
|
- Д9
|
||||||
|
attached_files:
|
||||||
|
- VKC_PROJ_V01_demo_video_RemizovKL_20260628.mp4
|
||||||
|
- VKC_PROJ_V01_ab_log_RemizovKL_20260628.log
|
||||||
|
- VKC_PROJ_V01_curl_log_RemizovKL_20260628.log
|
||||||
|
- VKC_PROJ_V01_ssh_log_RemizovKL_20260628.log
|
||||||
|
- VKC_PROJ_V01_terraform_state_list_RemizovKL_20260628.txt
|
||||||
|
- VKC_PROJ_V01_architecture.drawio.png
|
||||||
|
- VKC_PROJ_V01_backend_РемизовКЛ_20260628.tf
|
||||||
|
- VKC_PROJ_V01_main_РемизовКЛ_20260628.tf
|
||||||
|
- VKC_PROJ_V01_outputs_РемизовКЛ_20260628.tf
|
||||||
|
- VKC_PROJ_V01_variables_РемизовКЛ_20260628.tf
|
||||||
|
repo_url:
|
||||||
|
- https://github.com/BlackCorbeau/final_assessment
|
||||||
|
- https://git.rustprogersteam.ru/Black_Raven/MyResume
|
||||||
|
demo_url: http://95.163.213.173/DevOps
|
||||||
|
status: final
|
||||||
|
---
|
||||||
|
|
||||||
|
# README итогового проекта
|
||||||
|
|
||||||
|
## 1. Цель проекта
|
||||||
|
|
||||||
|
Развернуть отказоустойчивую инфраструктуру для веб‑приложения (сайт‑резюме), упакованного в Docker‑образ, с использованием виртуальных машин, балансировщика нагрузки и управляемой базы данных (PostgreSQL) в облаке VK Cloud. Вся инфраструктура описывается кодом (Terraform), управляется через GitHub Actions и обеспечивает доступность сайта при отказе одного из веб‑серверов (SLA 99.9%).
|
||||||
|
|
||||||
|
## 2. Выбранный вариант и почему он выбран
|
||||||
|
|
||||||
|
**Выбран вариант №1 из Документа 9** – *«Отказоустойчивый веб‑хостинг на ВМ»*, но с заменой ручного Nginx на Docker‑контейнер с собственным приложением.
|
||||||
|
|
||||||
|
**Почему выбран:**
|
||||||
|
- Этот вариант покрывает все ключевые темы курса: сеть, безопасность, балансировка, работа с базами данных, автоматизация.
|
||||||
|
- Он позволяет продемонстрировать навыки работы с Terraform, Docker, CI/CD и облачными сервисами VK Cloud.
|
||||||
|
- Стек соответствует реальным задачам промышленной эксплуатации.
|
||||||
|
- Проект имеет чёткие критерии успеха и позволяет наглядно показать отказоустойчивость.
|
||||||
|
|
||||||
|
## 3. Архитектура
|
||||||
|
|
||||||
|
### Схема
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
*Схема создана в draw.io и отражает все компоненты инфраструктуры.*
|
||||||
|
|
||||||
|
### Основные компоненты
|
||||||
|
|
||||||
|
- **Виртуальные машины**:
|
||||||
|
- **2 веб‑сервера** (flavor `Basic-1-1-10`) в приватной подсети – на каждом запущен Docker‑контейнер с приложением (образ из приватного реестра).
|
||||||
|
- **Бастион** (flavor `Basic-1-1-10`) в публичной подсети – единственная точка входа по SSH для управления.
|
||||||
|
- **Балансировщик нагрузки** (Application L7) с публичным Floating IP – распределяет HTTP‑трафик между веб‑серверами, выполняет health‑check по пути `/DevOps`.
|
||||||
|
- **Управляемая PostgreSQL** (flavor `Standard-2-8-50`) – создана в приватной подсети, но приложение к ней не подключается (архитектурный задел для будущей интеграции).
|
||||||
|
|
||||||
|
### Сетевой контур
|
||||||
|
|
||||||
|
- **VPC** с двумя подсетями:
|
||||||
|
- **public** (192.168.1.0/24) – для балансировщика и бастиона.
|
||||||
|
- **private** (192.168.2.0/24) – для веб‑серверов и БД.
|
||||||
|
- Интернет‑шлюз подключён к роутеру, обеспечивает доступ к публичным IP.
|
||||||
|
- Бастион имеет Floating IP, доступ по SSH разрешён только с моего IP-адреса.
|
||||||
|
|
||||||
|
### Безопасность
|
||||||
|
|
||||||
|
- **Security Groups**:
|
||||||
|
- `main` – разрешает HTTP (80) для всех, SSH (22) только с моего IP, исходящий трафик разрешён.
|
||||||
|
- `db_sg` – разрешает доступ к PostgreSQL (5432) только из приватной подсети.
|
||||||
|
- SSH‑доступ к веб‑серверам возможен только через бастион (используется проброс агента или скопированный ключ).
|
||||||
|
- Пароль к БД задан в коде (захардкожен для упрощения, в продакшене следует использовать переменные окружения или Vault).
|
||||||
|
|
||||||
|
### Мониторинг
|
||||||
|
|
||||||
|
- Health‑check балансировщика по HTTP `/DevOps` – проверяет доступность приложения.
|
||||||
|
- Нагрузочное тестирование с `ab` подтверждает стабильность (99.9% успешных запросов).
|
||||||
|
|
||||||
|
### Управление затратами
|
||||||
|
|
||||||
|
- Использованы минимальные флейворы `Basic-1-1-10` для ВМ и `Standard-2-8-50` для БД.
|
||||||
|
- Все ресурсы управляются Terraform, после защиты будут удалены командой `terraform destroy`.
|
||||||
|
- State хранится в S3, что исключает потерю состояния и лишние расходы.
|
||||||
|
|
||||||
|
## 4. Используемый стек
|
||||||
|
|
||||||
|
| Компонент | Технология |
|
||||||
|
|--------------------|------------------------------------------|
|
||||||
|
| Инфраструктура | Terraform (provider vkcs) |
|
||||||
|
| Оркестрация | Docker (контейнеры на ВМ) |
|
||||||
|
| Балансировка | VK Cloud Load Balancer (Application L7) |
|
||||||
|
| База данных | VK Cloud DBaaS (PostgreSQL 14) |
|
||||||
|
| CI/CD | GitHub Actions |
|
||||||
|
| Хранение состояния | S3 (VK Cloud Object Storage) |
|
||||||
|
| Язык приложения | Python (Flask) + Gunicorn |
|
||||||
|
| Контейнеризация | Docker, образ из приватного реестра |
|
||||||
|
|
||||||
|
## 5. Репозитории проекта
|
||||||
|
|
||||||
|
Исходный код проекта размещён в двух репозиториях:
|
||||||
|
|
||||||
|
- **GitHub (основной)** – [https://github.com/BlackCorbeau/final_assessment](https://github.com/BlackCorbeau/final_assessment)
|
||||||
|
- **Forgejo (зеркало)** – [https://git.rustprogersteam.ru/Black_Raven/MyResume](https://git.rustprogersteam.ru/Black_Raven/MyResume)
|
||||||
|
|
||||||
|
## 6. Порядок развертывания
|
||||||
|
|
||||||
|
1. **Подготовка окружения:**
|
||||||
|
- Убедиться, что установлены Terraform, OpenStack CLI, Docker (локально).
|
||||||
|
- Получить RC‑файл для доступа к VK Cloud, экспортировать переменные окружения или задать их в `terraform.tfvars`.
|
||||||
|
- Создать S3‑бакет для хранения state (имя `tf-state-final-assessment`).
|
||||||
|
|
||||||
|
2. **Клонирование репозитория:**
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/BlackCorbeau/final_assessment.git
|
||||||
|
cd final_assessment/terraform
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Настройка переменных:**
|
||||||
|
- Скопировать `terraform.tfvars.example` в `terraform.tfvars` и заполнить все обязательные переменные:
|
||||||
|
```hcl
|
||||||
|
my_ip = "ваш_публичный_IP/32"
|
||||||
|
project_name = "final_assessment"
|
||||||
|
docker_image = "git.rustprogersteam.ru/black_raven/myresume/resume:latest"
|
||||||
|
vkcs_username = "..."
|
||||||
|
vkcs_password = "..."
|
||||||
|
vkcs_project_id = "..."
|
||||||
|
vkcs_region = "RegionOne"
|
||||||
|
vkcs_auth_url = "https://infra.mail.ru:35357/v3/"
|
||||||
|
ssh_public_key = "~/.ssh/id_rsa.pub"
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **Инициализация и применение:**
|
||||||
|
```bash
|
||||||
|
terraform init
|
||||||
|
terraform plan
|
||||||
|
terraform apply -auto-approve
|
||||||
|
```
|
||||||
|
|
||||||
|
5. **Автоматический деплой через GitHub Actions:**
|
||||||
|
- При пуше в ветку `main` workflow выполняет `terraform plan` и `apply` автоматически (требуются секреты: `VKCS_USERNAME`, `VKCS_PASSWORD`, `VKCS_PROJECT_ID`, `VKCS_AUTH_URL`, `MY_IP`, `SSH_PUBLIC_KEY` и др.).
|
||||||
|
|
||||||
|
6. **Проверка outputs:**
|
||||||
|
- После успешного apply получаем:
|
||||||
|
- `load_balancer_ip` – публичный IP балансировщика.
|
||||||
|
- `bastion_floating_ip` – IP бастиона.
|
||||||
|
- `db_host`, `db_name`, `db_user`, `db_password` – параметры БД.
|
||||||
|
|
||||||
|
## 7. Проверка работоспособности
|
||||||
|
|
||||||
|
Все этапы проверки зафиксированы в видеообзоре `VKC_PROJ_V01_demo_video_RemizovKL_20260628.mp4`:
|
||||||
|
|
||||||
|
| Этап | Действие | Метка времени в видео |
|
||||||
|
| ---- | ---------------------------------------------------------------------------------------------- | --------------------- |
|
||||||
|
| 1 | Просмотр созданных ресурсов в консоли VK Cloud (ВМ, балансировщик, БД) | 00:00 – 01:13 |
|
||||||
|
| 2 | Проверка доступности сайта через браузер (http://95.163.213.173/DevOps) | 01:14 – 01:26 |
|
||||||
|
| 3 | Подключение к бастиону и веб‑серверам через SSH, проверка запущенных контейнеров (`docker ps`) | 01:27 – 01:50 |
|
||||||
|
| 4 | Остановка контейнера на web-1 (`docker stop`), проверка, что сайт продолжает работать | 01:51 – 03:09 |
|
||||||
|
| 5 | Запуск контейнера обратно (`docker start`), возвращение в пул | 03:10 – 04:15 |
|
||||||
|
| 6 | Подключение к PostgreSQL через `psql` (подтверждение наличия БД) | 04:16 – 05:32 |
|
||||||
|
| 7 | Нагрузочное тестирование `ab -n 1000 -c 10` с выводом результатов | 05:33 – 05:53 |
|
||||||
|
|
||||||
|
Также приложены отдельные логи:
|
||||||
|
- `VKC_PROJ_V01_ab_log_RemizovKL_20260628.log` – полный вывод нагрузочного теста.
|
||||||
|
- `VKC_PROJ_V01_curl_log_RemizovKL_20260628.log` – вывод `curl -v`.
|
||||||
|
- `VKC_PROJ_V01_ssh_log_RemizovKL_20260628.log` – лог SSH-сессий.
|
||||||
|
|
||||||
|
## 8. Известные ограничения
|
||||||
|
|
||||||
|
- Пароль БД захардкожен в коде – в продакшене использовать переменные.
|
||||||
|
- Health‑check использует `/DevOps` (не выделенный `/health`).
|
||||||
|
- Образ собран с тегом `latest` – обновление требует ручного изменения тега.
|
||||||
|
- Отсутствует мониторинг (Prometheus/Grafana) – проект сфокусирован на базовой отказоустойчивости.
|
||||||
|
|
||||||
|
## 9. Приложенные файлы
|
||||||
|
|
||||||
|
| Файл | Назначение |
|
||||||
|
|------|------------|
|
||||||
|
| `VKC_PROJ_V01_README_RemizovKL_20260628.md` | Данный файл – полный отчёт по проекту. |
|
||||||
|
| `VKC_PROJ_V01_demo_video_RemizovKL_20260628.mp4` | **Видеообзор** со всеми этапами проверки (сайт, SSH, отказоустойчивость, нагрузка, БД, консоль). |
|
||||||
|
| `VKC_PROJ_V01_ab_log_RemizovKL_20260628.log` | Лог нагрузочного тестирования `ab`. |
|
||||||
|
| `VKC_PROJ_V01_curl_log_RemizovKL_20260628.log` | Лог `curl -v` к `/DevOps`. |
|
||||||
|
| `VKC_PROJ_V01_ssh_log_RemizovKL_20260628.log` | Лог SSH-подключений и проверки контейнеров. |
|
||||||
|
| `VKC_PROJ_V01_terraform_state_list_RemizovKL_20260628.txt` | Вывод `terraform state list`. |
|
||||||
|
| `VKC_PROJ_V01_architecture.drawio.png` | Архитектурная схема. |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Итог:** Проект полностью соответствует требованиям варианта №1, все критерии успеха выполнены, инфраструктура работоспособна и готова к защите. Видеообзор содержит все необходимые доказательства.
|
||||||
@@ -0,0 +1,174 @@
|
|||||||
|
---
|
||||||
|
course_code: VKCLOUD-80
|
||||||
|
artifact_type: PR
|
||||||
|
module: 5
|
||||||
|
task_code: 2
|
||||||
|
task_title: Работа с Kubernetes (MK8s)
|
||||||
|
student_fio: Ремизов Кирилл Львович
|
||||||
|
date: 2026-06-15
|
||||||
|
source_docs:
|
||||||
|
- 3-Конспект лекций - VK 1.md
|
||||||
|
- 4-Практические работы - VK -1.md
|
||||||
|
commands_used:
|
||||||
|
- kubectl get nodes
|
||||||
|
- kubectl get pods --all-namespaces
|
||||||
|
- kubectl apply -f deployment.yaml
|
||||||
|
- kubectl get pods
|
||||||
|
- kubectl get services
|
||||||
|
- kubectl get service nginx-service -w
|
||||||
|
attached_files:
|
||||||
|
- VKC_PR_M05_02_k8s_my-k8s_РемизовКЛ_20260615.png
|
||||||
|
- VKC_PR_M05_02_k8s_stage2log_РемизовКЛ_20260615.log
|
||||||
|
- VKC_PR_M05_02_k8s_stage3log_РемизовКЛ_20260615.log
|
||||||
|
- VKC_PR_M05_02_k8s_stage3pruf_РемизовКЛ_20260615.png
|
||||||
|
- VKC_PR_M05_02_k8s_deployment_РемизовКЛ_20260615.yaml
|
||||||
|
status: final
|
||||||
|
---
|
||||||
|
# Отчёт по практической демонстрации
|
||||||
|
|
||||||
|
## 1. Цель
|
||||||
|
|
||||||
|
Освоить базовые навыки работы с **управляемым сервисом Kubernetes (MK8s)** в VK Cloud. Научиться создавать кластер через веб‑консоль, подключаться к нему с помощью `kubectl`, разворачивать контейнеризированное приложение (nginx) с несколькими репликами и обеспечивать его доступность из интернета через сервис типа `LoadBalancer`.
|
||||||
|
|
||||||
|
## 2. Что было прочитано перед выполнением
|
||||||
|
|
||||||
|
- **Документ:** 3-Конспект лекций - VK 1.md
|
||||||
|
- **Раздел/тема:** Модуль 5 «Контейнеризация и автоматизация», тема 5.2 «Контейнеры и оркестрация (Kubernetes)»
|
||||||
|
- **Ключевые понятия:**
|
||||||
|
- Контейнеры (Docker) vs виртуальные машины
|
||||||
|
- Kubernetes: кластер, ноды (master/worker), control plane
|
||||||
|
- Объекты: Pod, Deployment, Service (типы ClusterIP, LoadBalancer)
|
||||||
|
- Managed Kubernetes в VK Cloud (MK8s)
|
||||||
|
- `kubectl` – клиент для управления кластером
|
||||||
|
- Манифесты в формате YAML (Deployment + Service)
|
||||||
|
|
||||||
|
- **Дополнительно:** Документ 4-Практические работы - VK -1.md, демонстрация 5.2 «Работа с Kubernetes (MK8s)» (этапы создания кластера, подключения, развёртывания приложения).
|
||||||
|
|
||||||
|
## 3. Ход выполнения
|
||||||
|
|
||||||
|
### Демонстрация 5.2: Работа с Kubernetes (MK8s)
|
||||||
|
|
||||||
|
#### Этап 1. Создание кластера (веб-консоль)
|
||||||
|
|
||||||
|
**Действие:**
|
||||||
|
В разделе **«Контейнеры» → «Kubernetes»** создал новый кластер со следующими параметрами:
|
||||||
|
|
||||||
|
| Параметр | Значение |
|
||||||
|
|------------------------|---------------------------------------|
|
||||||
|
| Имя кластера | `my-k8s` |
|
||||||
|
| Версия Kubernetes | v1.34.2 |
|
||||||
|
| Тип кластера | Стандартный (1 master, 2 worker) |
|
||||||
|
| Сеть | `my-k8s` (создана ранее) |
|
||||||
|
| Подсеть worker‑узлов | `subnet_8887` |
|
||||||
|
| Тип виртуальной машины | `STD3-2-8` для master, `Standard-2-4` для worker |
|
||||||
|
| Количество worker‑нод | 2 |
|
||||||
|
| Зона доступности | Москва (PA2) |
|
||||||
|
|
||||||
|
**Результат:**
|
||||||
|
Через 5–7 минут кластер перешёл в статус **Running**.
|
||||||
|
*Скриншот страницы с параметрами кластера приложен:*
|
||||||
|
[[VKC_PR_M05_02_k8s_my-k8s_РемизовКЛ_20260615.png]]
|
||||||
|
|
||||||
|
#### Этап 2. Подключение к кластеру (kubectl)
|
||||||
|
|
||||||
|
**Действие:**
|
||||||
|
1. Скачал `kubeconfig` из консоли VK Cloud (файл `my-k8s-kubeconfig`).
|
||||||
|
2. Установил переменную окружения:
|
||||||
|
```bash
|
||||||
|
export KUBECONFIG=~/Downloads/my-k8s-kubeconfig
|
||||||
|
```
|
||||||
|
3. Проверил доступность узлов и системных подов:
|
||||||
|
```bash
|
||||||
|
kubectl get nodes
|
||||||
|
kubectl get pods --all-namespaces
|
||||||
|
```
|
||||||
|
|
||||||
|
**Результат:**
|
||||||
|
- Оба worker‑узла находятся в состоянии **Ready** (версия v1.34.2).
|
||||||
|
- В пространстве `kube-system` работают основные компоненты: сетевой плагин Calico, драйвер CSI для дисков, другие системные поды.
|
||||||
|
|
||||||
|
*Полный вывод команд сохранён в логе:*
|
||||||
|
[[VKC_PR_M05_02_k8s_stage2log_РемизовКЛ_20260615.log]]
|
||||||
|
|
||||||
|
#### Этап 3. Развёртывание приложения (Deployment + LoadBalancer)
|
||||||
|
|
||||||
|
**Действие:**
|
||||||
|
1. Создал файл манифеста `deployment.yaml` (см. приложение). В нём описаны:
|
||||||
|
- **Deployment** `nginx-deployment` с 3 репликами, использующий образ `nginx:latest`, с ограничениями по CPU и памяти.
|
||||||
|
- **Service** типа `LoadBalancer`, который слушает порт 80 и направляет трафик на поды с меткой `app: nginx`.
|
||||||
|
2. Применил манифест:
|
||||||
|
```bash
|
||||||
|
kubectl apply -f deployment.yaml
|
||||||
|
```
|
||||||
|
3. Отследил создание подов и назначение внешнего IP:
|
||||||
|
```bash
|
||||||
|
kubectl get pods
|
||||||
|
kubectl get services
|
||||||
|
kubectl get service nginx-service -w
|
||||||
|
```
|
||||||
|
4. Дождался, когда в поле `EXTERNAL-IP` появится реальный IP‑адрес (процесс занял около 3 минут).
|
||||||
|
5. Открыл в браузере полученный IP и убедился, что отображается стандартная приветственная страница nginx.
|
||||||
|
|
||||||
|
**Результат:**
|
||||||
|
- Три пода `nginx-deployment-*` перешли в статус `Running`.
|
||||||
|
- Сервис `nginx-service` получил внешний IP (в логе после ожидания IP не отобразился, но скриншот браузера подтверждает доступность).
|
||||||
|
- При обращении по этому IP видна страница **Welcome to nginx!**
|
||||||
|
|
||||||
|
*Лог применения манифеста и ожидания:*
|
||||||
|
[[VKC_PR_M05_02_k8s_stage3log_РемизовКЛ_20260615.log]]
|
||||||
|
*Скриншот работающего приложения:*
|
||||||
|
[[VKC_PR_M05_02_k8s_stage3pruf_РемизовКЛ_20260615.png]]
|
||||||
|
*Файл манифеста:*
|
||||||
|
[[VKC_PR_M05_02_k8s_deployment_РемизовКЛ_20260615.yaml]]
|
||||||
|
|
||||||
|
## 4. Ошибки и исправления
|
||||||
|
|
||||||
|
| Проблема | Решение |
|
||||||
|
| :--- | :--- |
|
||||||
|
| После применения манифеста сервис долго (более 2 минут) имел статус `EXTERNAL-IP = <pending>`. | Это нормальное поведение для облачного провайдера: требуется время на автоматическое создание облачного балансировщика нагрузки (Octavia) и выделение ему плавающего IP. Достаточно подождать 3–5 минут – IP назначается автоматически. |
|
||||||
|
| В логе `stage3log` внешний IP так и не отобразился (вывод прерван `^C`). | Студент прервал команду `kubectl get service -w` раньше, чем IP появился. Однако позже IP был получен (доказательство – скриншот браузера). В следующий раз стоит дождаться появления адреса или использовать `kubectl describe service nginx-service`. |
|
||||||
|
|
||||||
|
## 5. Критерии успеха
|
||||||
|
|
||||||
|
- [x] Кластер Kubernetes успешно создан (статус Running, 2 worker‑ноды).
|
||||||
|
- [x] `kubectl get nodes` показывает `Ready` для обеих нод.
|
||||||
|
- [x] Deployment с 3 репликами nginx запущен и все поды находятся в статусе `Running`.
|
||||||
|
- [x] Сервис типа `LoadBalancer` получил внешний IP.
|
||||||
|
- [x] При обращении по внешнему IP открывается стандартная страница nginx.
|
||||||
|
|
||||||
|
## 6. Приложенные доказательства
|
||||||
|
|
||||||
|
| Файл | Тип | Что подтверждает |
|
||||||
|
| ----------------------------------------------------------------- | ------------- | ----------------------------------------------------- |
|
||||||
|
| VKC_PR_M05_02_k8s_my-k8s_РемизовКЛ_20260615.png | Скриншот | Параметры созданного кластера (версия, ноды, сеть) |
|
||||||
|
| VKC_PR_M05_02_k8s_stage2log_РемизовКЛ_20260615.log | Текстовый лог | Вывод `kubectl get nodes` и `get pods --all-namespaces` (готовность кластера) |
|
||||||
|
| VKC_PR_M05_02_k8s_stage3log_РемизовКЛ_20260615.log | Текстовый лог | Применение манифеста, создание подов, ожидание External‑IP |
|
||||||
|
| VKC_PR_M05_02_k8s_stage3pruf_РемизовКЛ_20260615.png | Скриншот | Страница nginx, доступная по внешнему IP балансировщика |
|
||||||
|
| VKC_PR_M05_02_k8s_deployment_РемизовКЛ_20260615.yaml | YAML‑манифест | Код развёртывания Deployment и Service LoadBalancer |
|
||||||
|
|
||||||
|
## 7. Самопроверка
|
||||||
|
|
||||||
|
- **Что получилось:**
|
||||||
|
Успешно создал managed‑кластер Kubernetes в VK Cloud, подключился к нему, развернул масштабируемое приложение (3 реплики nginx) и открыл доступ к нему из интернета через LoadBalancer. На практике убедился в простоте использования управляемого сервиса: не требуется настраивать control plane, достаточно скачать kubeconfig.
|
||||||
|
|
||||||
|
- **Что осталось непонятным:**
|
||||||
|
- Каким образом VK Cloud автоматически создаёт балансировщик для сервиса типа LoadBalancer (используется ли Octavia, как долго это происходит в зависимости от региона).
|
||||||
|
- Как настроить Ingress‑контроллер для маршрутизации на основе доменных имён, вместо использования одного LoadBalancer на сервис.
|
||||||
|
- Почему в выводе `kubectl get service -w` внешний IP долго не появлялся, хотя балансировщик в консоли VK Cloud создался быстрее – возможно, задержка связана с обновлением состояния в `kubectl`.
|
||||||
|
|
||||||
|
- **Что можно улучшить:**
|
||||||
|
- Добавить в манифест `livenessProbe` и `readinessProbe` для надёжного мониторинга состояния подов.
|
||||||
|
- Использовать `ConfigMap` для вынесения конфигурации nginx (например, кастомной index.html).
|
||||||
|
- Включить **Horizontal Pod Autoscaler** для автоматического масштабирования реплик по CPU.
|
||||||
|
- Применить GitOps‑подход: выложить манифесты в Git и настроить ArgoCD для синхронизации.
|
||||||
|
|
||||||
|
## 8. Краткий вывод
|
||||||
|
|
||||||
|
Практическая работа показала, что **управляемый Kubernetes (MK8s)** в VK Cloud позволяет быстро развернуть готовый кластер, не тратя время на установку и настройку control plane. С помощью стандартного инструмента `kubectl` и декларативных YAML‑манифестов можно за минуты запустить приложение в контейнерах, обеспечить его масштабирование и сделать доступным из интернета через облачный балансировщик нагрузки.
|
||||||
|
|
||||||
|
Особую ценность имеют:
|
||||||
|
- **Простота начала работы** – кластер создаётся «по кнопке», kubeconfig скачивается готовым.
|
||||||
|
- **Стандартизация** – Kubernetes предоставляет единые API‑объекты (Deployment, Service), которые работают одинаково в любом облаке.
|
||||||
|
- **Автоматизация** – сервис типа LoadBalancer автоматически интегрируется с облачной сетью, избавляя от ручного назначения плавающих IP.
|
||||||
|
|
||||||
|
Полученные навыки являются базой для дальнейшего изучения более сложных тем: Helm, Ingress, Service Mesh, GitOps и построения production‑ready микросервисных архитектур в облаке.
|
||||||
@@ -0,0 +1,177 @@
|
|||||||
|
---
|
||||||
|
course_code: VKCLOUD-80
|
||||||
|
artifact_type: PR
|
||||||
|
module: 5
|
||||||
|
task_code: 3
|
||||||
|
task_title: Создание образов с Packer
|
||||||
|
student_fio: Ремизов Кирилл Львович
|
||||||
|
date: 2026-06-16
|
||||||
|
source_docs:
|
||||||
|
- 3-Конспект лекций - VK 1.md
|
||||||
|
- 4-Практические работы - VK -1.md
|
||||||
|
commands_used:
|
||||||
|
- packer --version
|
||||||
|
- packer plugins installed
|
||||||
|
- packer init .
|
||||||
|
- packer validate .
|
||||||
|
- packer build .
|
||||||
|
- openstack image list
|
||||||
|
- openstack server create
|
||||||
|
- ssh
|
||||||
|
- curl
|
||||||
|
attached_files:
|
||||||
|
- VKC_PR_M05_03_packer_log_РемизовКЛ_20260616.log
|
||||||
|
- VKC_PR_M05_03_packer_packer-config_РемизовКЛ_20260516.pkr.hcl
|
||||||
|
- VKC_PR_M05_03_packer_image_РемизовКЛ_20260616.png
|
||||||
|
- VKC_PR_M05_03_packer_curl_РемизовКЛ_20260616.png
|
||||||
|
status: final
|
||||||
|
---
|
||||||
|
|
||||||
|
# Отчёт по практической демонстрации
|
||||||
|
|
||||||
|
## 1. Цель
|
||||||
|
|
||||||
|
Освоить инструмент **Packer** для автоматизации создания кастомизированных образов виртуальных машин в облаке VK Cloud. Научиться:
|
||||||
|
|
||||||
|
- описывать процесс сборки образа декларативно с помощью HCL-конфигурации;
|
||||||
|
- использовать провизоры (shell) для установки и настройки ПО внутри собираемой ВМ;
|
||||||
|
- решать проблемы с сетью и DNS в процессе сборки;
|
||||||
|
- проверять работоспособность созданного образа путём запуска тестовой ВМ.
|
||||||
|
|
||||||
|
## 2. Что было прочитано перед выполнением
|
||||||
|
|
||||||
|
- **Документ:** 3-Конспект лекций - VK 1.md
|
||||||
|
- **Раздел/тема:** Модуль 5 «Контейнеризация и автоматизация», тема 5.3 «Создание образов с Packer»
|
||||||
|
- **Ключевые понятия:**
|
||||||
|
- Packer как инструмент для автоматической сборки образов (Immutable Infrastructure).
|
||||||
|
- Структура конфигурации: `packer` (плагины), `source` (параметры облака, базовый образ, сеть, ключи), `build` (провизоры).
|
||||||
|
- Использование провизора `shell` для выполнения команд внутри собираемой ВМ.
|
||||||
|
- Интеграция с OpenStack (плагин `openstack`).
|
||||||
|
- Переменные окружения для гибкой настройки.
|
||||||
|
|
||||||
|
- **Дополнительно:** Документ 4-Практические работы - VK -1.md, демонстрация 5.3 «Создание образов с Packer».
|
||||||
|
|
||||||
|
## 3. Ход выполнения
|
||||||
|
|
||||||
|
### Демонстрация 5.3: Создание образов с Packer
|
||||||
|
|
||||||
|
#### Этап 0. Подготовка окружения
|
||||||
|
|
||||||
|
- Проверена версия Packer: `1.15.4` (команда `packer --version`).
|
||||||
|
- Установлен плагин OpenStack версии `1.1.3` (подтверждено `packer plugins installed`).
|
||||||
|
- Заданы переменные окружения:
|
||||||
|
```bash
|
||||||
|
export SOURCE_IMAGE=8582cdba-6be5-41d4-834f-b0fa920b3dcf # базовый Ubuntu 22.04
|
||||||
|
export NETWORK_ID=ec8c610e-6387-447e-83d2-d2c541e88164 # сеть internet
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Этап 1. Инициализация и валидация конфигурации
|
||||||
|
|
||||||
|
- Выполнена инициализация:
|
||||||
|
```bash
|
||||||
|
packer init .
|
||||||
|
```
|
||||||
|
Плагин OpenStack загружен (уже был установлен, повторная загрузка подтверждена).
|
||||||
|
|
||||||
|
- Проверена корректность конфигурации:
|
||||||
|
```bash
|
||||||
|
packer validate .
|
||||||
|
```
|
||||||
|
Результат: `The configuration is valid.`
|
||||||
|
|
||||||
|
#### Этап 2. Сборка образа с помощью Packer
|
||||||
|
|
||||||
|
Запущен процесс сборки:
|
||||||
|
```bash
|
||||||
|
packer build .
|
||||||
|
```
|
||||||
|
|
||||||
|
В логе видна последовательность действий Packer:
|
||||||
|
|
||||||
|
1. **Загрузка flavour** `STD3-2-6` (ID подтверждён).
|
||||||
|
2. **Создание тома** (block storage volume) для временной ВМ.
|
||||||
|
3. **Запуск сервера** с указанными параметрами: сеть `internet`, группа безопасности `ssh`, ключ `postgress-test-ViPomgZ4`.
|
||||||
|
4. **Ожидание готовности** – сервер получает публичный IP (`95.163.214.208`).
|
||||||
|
5. **Подключение по SSH** – используется коммуникатор SSH с приватным ключом `postgress-test-ViPomgZ4.pem`.
|
||||||
|
6. **Выполнение провизора `shell`** – внутри ВМ последовательно выполняются команды:
|
||||||
|
- Фикс файла `/etc/hosts` (добавление записи `127.0.0.1 $(hostname)`).
|
||||||
|
- Настройка DNS: удаление существующего `resolv.conf`, установка `nameserver 8.8.8.8` и `1.1.1.1`, защита от перезаписи (`chattr +i`).
|
||||||
|
- Обновление списка пакетов (`apt-get update`). На этом этапе возникли временные ошибки разрешения доменов, но благодаря фиксам DNS и наличию кеша пакетов установка nginx прошла успешно (пакет уже был установлен в базовом образе).
|
||||||
|
- Включение и запуск nginx.
|
||||||
|
- Создание тестовой страницы `/var/www/html/index.html` с содержимым `<h1>Hello from Packer!</h1>`.
|
||||||
|
- Очистка временных файлов и кэша пакетов.
|
||||||
|
7. **Завершение работы** – временная ВМ останавливается, создаётся образ, затем ВМ и том удаляются. В логе появилась ошибка `Error terminating server, may still be around: Resource not found`, но это не повлияло на создание образа.
|
||||||
|
8. **Создание образа** – финальный образ с именем `nginx-custom-image-2026-06-16-2107` (ID `f69ca872-96a2-40a9-ad31-4e098b0f9b0e`).
|
||||||
|
|
||||||
|
**Время сборки:** 7 минут 44 секунды.
|
||||||
|
|
||||||
|
#### Этап 3. Проверка созданного образа
|
||||||
|
|
||||||
|
- Проверено, что образ появился в списке:
|
||||||
|
```bash
|
||||||
|
openstack image list | grep nginx-custom
|
||||||
|
```
|
||||||
|
Образ активен.
|
||||||
|
|
||||||
|
- Запущена тестовая ВМ из этого образа:
|
||||||
|
```bash
|
||||||
|
openstack server create --image nginx-custom-image-2026-06-16-2107 --flavor Basic-1-2-20 --network internet --key-name postgress-test-ViPomgZ4 --security-group all --wait test-nginx
|
||||||
|
```
|
||||||
|
ВМ получила публичный IP `95.163.214.174`.
|
||||||
|
|
||||||
|
- Подключение по SSH и проверка работы веб-сервера:
|
||||||
|
```bash
|
||||||
|
ssh -i postgress-test-ViPomgZ4.pem ubuntu@95.163.214.174
|
||||||
|
curl localhost
|
||||||
|
```
|
||||||
|
Вывод: `<h1>Hello from Packer!</h1>` – всё работает (скриншот приложен).
|
||||||
|
|
||||||
|
## 4. Ошибки и исправления
|
||||||
|
|
||||||
|
| Проблема | Решение |
|
||||||
|
| :--- | :--- |
|
||||||
|
| В процессе выполнения `apt-get update` возникли ошибки разрешения DNS (`Temporary failure resolving`). | В конфигурацию Packer добавлены шаги по принудительной настройке DNS: удаление стандартного `/etc/resolv.conf`, установка публичных DNS-серверов (8.8.8.8, 1.1.1.1) и защита файла от перезаписи через `chattr +i`. Также добавлена запись `127.0.0.1 $(hostname)` в `/etc/hosts` для корректной работы `sudo`. |
|
||||||
|
| После завершения сборки в логе появилась ошибка `Error terminating server, may still be around: Resource not found`. | Это не критично – сервер уже был остановлен и образ создан. Ошибка возникает из-за попытки повторного удаления уже удалённого ресурса. На результат сборки не влияет. |
|
||||||
|
|
||||||
|
## 5. Критерии успеха
|
||||||
|
|
||||||
|
- [x] Packer-конфигурация написана и успешно проходит валидацию (`packer validate .`).
|
||||||
|
- [x] Сборка образа завершена без ошибок (статус `Builds finished`).
|
||||||
|
- [x] Создан новый образ с именем, содержащим временную метку.
|
||||||
|
- [x] В логе сборки видно, что провизор успешно выполнил все команды (установка nginx, создание тестовой страницы).
|
||||||
|
- [x] Тестовая ВМ, запущенная из созданного образа, отвечает на запрос `curl localhost` корректным содержимым.
|
||||||
|
|
||||||
|
## 6. Приложенные доказательства
|
||||||
|
|
||||||
|
| Файл | Тип | Что подтверждает |
|
||||||
|
| ---------------------------------------------------------------------------- | ------------- | ----------------------------------------------------- |
|
||||||
|
| VKC_PR_M05_03_packer_log_РемизовКЛ_20260616.log | Текстовый лог | Полный вывод всех этапов: инициализация, валидация, сборка, проверка |
|
||||||
|
| VKC_PR_M05_03_packer_packer-config_РемизовКЛ_20260516.pkr.hcl | Конфигурация | Исходный код Packer с добавленными фиксами DNS |
|
||||||
|
| VKC_PR_M05_03_packer_image_РемизовКЛ_20260616.png | Скриншот | Созданный образ в списке образов VK Cloud |
|
||||||
|
| VKC_PR_M05_03_packer_curl_РемизовКЛ_20260616.png | Скриншот | Вывод `curl localhost` на тестовой ВМ |
|
||||||
|
|
||||||
|
## 7. Самопроверка
|
||||||
|
|
||||||
|
- **Что получилось:**
|
||||||
|
Успешно автоматизировал создание кастомизированного образа с nginx, используя Packer. Столкнулся с проблемами DNS в процессе сборки и решил их, добавив явную настройку резолвера и защиту от перезаписи. Это позволило сборке завершиться успешно, несмотря на временные сетевые ошибки.
|
||||||
|
|
||||||
|
- **Что осталось непонятным:**
|
||||||
|
- Почему в базовом образе Ubuntu 22.04 возникли проблемы с DNS – возможно, это связано с конфигурацией DHCP в облачной сети.
|
||||||
|
- Как более элегантно решать подобные проблемы без вмешательства в файловую систему (например, через параметры сети при создании ВМ).
|
||||||
|
- Как организовать хранение SSH-ключей в CI/CD-среде, чтобы не хранить приватный ключ в репозитории.
|
||||||
|
|
||||||
|
- **Что можно улучшить:**
|
||||||
|
- Добавить в образ больше метаданных (тегов) для идентификации версии приложения.
|
||||||
|
- Использовать провизор `file` для копирования конфигурационных файлов (например, конфига nginx) вместо редактирования через shell.
|
||||||
|
- Настроить автоматический запуск Packer в пайплайне CI/CD при изменении кода приложения.
|
||||||
|
|
||||||
|
## 8. Краткий вывод
|
||||||
|
|
||||||
|
Практическая работа продемонстрировала, что **Packer** – мощный инструмент для создания предварительно настроенных образов виртуальных машин. В ходе выполнения удалось не только автоматизировать процесс сборки, но и столкнуться с реальными проблемами сети и DNS, что позволило применить навыки диагностики и исправления конфигурации.
|
||||||
|
|
||||||
|
Ключевые преимущества, подтверждённые на практике:
|
||||||
|
- **Декларативность** – вся логика сборки описана в одном файле, который можно хранить в Git.
|
||||||
|
- **Гибкость** – легко адаптировать провизоры под любые требования (например, фиксы DNS).
|
||||||
|
- **Воспроизводимость** – каждый запуск даёт идентичный результат, что критично для production-сред.
|
||||||
|
|
||||||
|
Полученный образ `nginx-custom-image-2026-06-16-2107` готов к использованию в Terraform или для ручного запуска, что ускоряет развёртывание новых инстансов и упрощает поддержку инфраструктуры.
|
||||||
@@ -0,0 +1,182 @@
|
|||||||
|
---
|
||||||
|
course_code: VKCLOUD-80
|
||||||
|
artifact_type: PR
|
||||||
|
module: 6
|
||||||
|
task_code: 1
|
||||||
|
task_title: Настройка мониторинга (Prometheus + Grafana)
|
||||||
|
student_fio: Ремизов Кирилл Львович
|
||||||
|
date: 2026-06-17
|
||||||
|
source_docs:
|
||||||
|
- 3-Конспект лекций - VK 1.md
|
||||||
|
- 4-Практические работы - VK -1.md
|
||||||
|
commands_used:
|
||||||
|
- terraform init
|
||||||
|
- terraform plan
|
||||||
|
- terraform apply -auto-approve
|
||||||
|
- openstack server list
|
||||||
|
- curl http://localhost:9090
|
||||||
|
- curl http://localhost:3000
|
||||||
|
attached_files:
|
||||||
|
- VKC_PR_M06_01_monitoring_tf_РемизовКЛ_20260617.log
|
||||||
|
- VKC_PR_M06_01_monitoring_main_РемизовКЛ_20260617.tf
|
||||||
|
- VKC_PR_M06_01_monitoring_VM_РемизовКЛ_20260617.png
|
||||||
|
- VKC_PR_M06_01_monitoring_Prometeus_РемизовКЛ_20260617.png
|
||||||
|
- VKC_PR_M06_01_monitoring_DS_РемизовКЛ_20260617.png
|
||||||
|
- VKC_PR_M06_01_monitoring_dashboard_РемизовКЛ_20260617.png
|
||||||
|
status: final
|
||||||
|
---
|
||||||
|
# Отчёт по практической демонстрации
|
||||||
|
|
||||||
|
## 1. Цель
|
||||||
|
|
||||||
|
Освоить настройку мониторинга виртуальных машин в облаке VK Cloud с использованием стека **Prometheus + Grafana**. Научиться:
|
||||||
|
|
||||||
|
- разворачивать инфраструктуру для мониторинга с помощью **Terraform**;
|
||||||
|
- устанавливать и настраивать **Node Exporter** на целевых ВМ для сбора системных метрик;
|
||||||
|
- развёртывать **Prometheus** как центральный сервер сбора метрик;
|
||||||
|
- устанавливать и настраивать **Grafana** для визуализации метрик;
|
||||||
|
- подключать **Grafana** к **Prometheus** в качестве источника данных;
|
||||||
|
- импортировать готовый дашборд и убедиться в его работоспособности.
|
||||||
|
|
||||||
|
## 2. Что было прочитано перед выполнением
|
||||||
|
|
||||||
|
- **Документ:** 3-Конспект лекций - VK 1.md
|
||||||
|
- **Раздел/тема:** Модуль 6 «Мониторинг, логирование и Observability», тема 6.1 «Стек мониторинга (Prometheus, Grafana)»
|
||||||
|
- **Ключевые понятия:**
|
||||||
|
- **Prometheus** — система сбора метрик с временными рядами, использующая подход pull (активный опрос экспортеров).
|
||||||
|
- **Node Exporter** — агент, собирающий метрики хоста (CPU, RAM, Disk, Network) и предоставляющий их Prometheus через HTTP endpoint на порту 9100.
|
||||||
|
- **Grafana** — платформа для визуализации данных, подключаемая к Prometheus как к источнику данных.
|
||||||
|
- **PromQL** — язык запросов к метрикам Prometheus.
|
||||||
|
- **Targets** — цели, с которых Prometheus собирает метрики (в данном случае — Node Exporter на каждой ВМ).
|
||||||
|
|
||||||
|
- **Дополнительно:** Документ 4-Практические работы - VK -1.md, демонстрация 6.1 «Настройка Prometheus и Grafana».
|
||||||
|
|
||||||
|
## 3. Ход выполнения
|
||||||
|
|
||||||
|
### Демонстрация 6.1: Настройка Prometheus и Grafana
|
||||||
|
|
||||||
|
#### Этап 0. Подготовка окружения
|
||||||
|
|
||||||
|
- Убедился, что Terraform установлен и настроен для работы с VK Cloud.
|
||||||
|
- Создал директорию для проекта и подготовил файл `main.tf` с конфигурацией инфраструктуры.
|
||||||
|
|
||||||
|
#### Этап 1. Развертывание инфраструктуры с помощью Terraform
|
||||||
|
|
||||||
|
В файле `VKC_PR_M06_01_monitoring_main_РемизовКЛ_20260617.tf` описаны следующие ресурсы:
|
||||||
|
|
||||||
|
1. **Провайдер VKCS** — для взаимодействия с VK Cloud через OpenStack API.
|
||||||
|
2. **Переменные** — внешняя сеть (`internet`), ID роутера, образ (`ubuntu-20-202602051631.gite7a38aaf`), flavour (`Basic-1-2-20`), зона доступности (`MS1`).
|
||||||
|
3. **Data-источники** — для получения идентификаторов внешней сети, роутера, образа и flavour.
|
||||||
|
4. **Внутренняя сеть** (`monitoring-internal-net`) с подсетью `192.168.200.0/24` и подключением к существующему роутеру для выхода в интернет.
|
||||||
|
5. **Security Group** (`monitoring-sg`) с правилами для SSH (22), Grafana (3000), Prometheus (9090), Node Exporter (9100) — доступ разрешён с `0.0.0.0/0` (для демонстрации).
|
||||||
|
6. **SSH-ключ** — `monitoring-key`, создаётся из публичного ключа `~/.ssh/id_rsa.pub`.
|
||||||
|
7. **App-ВМ** (`app-vm-1`) — одна ВМ, на которую через `user_data` устанавливается **Node Exporter**.
|
||||||
|
8. **Monitoring-ВМ** (`monitoring-vm`) — ВМ, на которую через `user_data` устанавливаются:
|
||||||
|
- **Node Exporter** (для сбора метрик самой мониторинговой ВМ),
|
||||||
|
- **Prometheus** (сервер сбора метрик, порт 9090),
|
||||||
|
- **Grafana** (сервер визуализации, порт 3000).
|
||||||
|
9. **Floating IP** — публичный IP для мониторинговой ВМ, который ассоциируется с ней.
|
||||||
|
|
||||||
|
**Выполнение Terraform:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
terraform apply -auto-approve
|
||||||
|
```
|
||||||
|
|
||||||
|
План показал создание 13 ресурсов (сеть, подсеть, интерфейс роутера, security group, правила, ключ, две ВМ, floating IP, ассоциация). Применение прошло успешно, все ресурсы созданы за ~2 минуты.
|
||||||
|
|
||||||
|
**Результат:**
|
||||||
|
- `monitoring-vm` получила публичный IP: `95.163.215.1` (floating IP)
|
||||||
|
- `app-vm-1` получила внутренний IP: `192.168.200.9` (доступ к ней осуществляется через мониторинговую ВМ или напрямую по публичному IP невозможен)
|
||||||
|
- URL Prometheus: `http://95.163.215.1:9090`
|
||||||
|
- URL Grafana: `http://95.163.215.1:3000`
|
||||||
|
- Пароль для SSH (задан в `user_data`): `debian` (логин: `ubuntu`)
|
||||||
|
|
||||||
|
#### Этап 2. Настройка Prometheus
|
||||||
|
|
||||||
|
На мониторинговой ВМ был установлен Prometheus. В файле конфигурации `/opt/prometheus/prometheus.yml` необходимо было добавить цели (targets) для сбора метрик:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
scrape_configs:
|
||||||
|
- job_name: 'node'
|
||||||
|
static_configs:
|
||||||
|
- targets:
|
||||||
|
- '192.168.200.9:9100' # app-vm-1 (внутренний IP)
|
||||||
|
- '95.163.215.1:9100' # monitoring-vm (публичный IP, т.к. node_exporter установлен и на ней)
|
||||||
|
```
|
||||||
|
|
||||||
|
После перезапуска Prometheus цели стали доступны для опроса. В веб-интерфейсе Prometheus (порт 9090) в разделе **Targets** обе цели отображаются в статусе **UP**.
|
||||||
|
|
||||||
|
#### Этап 3. Настройка Grafana
|
||||||
|
|
||||||
|
- Grafana установлена и запущена на порту 3000.
|
||||||
|
- Первый вход выполнен с учётными данными по умолчанию: `admin` / `admin` (пароль был изменён при первом входе).
|
||||||
|
- Добавлен **Data Source** типа **Prometheus** с URL `http://localhost:9090` (так как Grafana и Prometheus находятся на одной ВМ). Data source помечен как **default**.
|
||||||
|
|
||||||
|
#### Этап 4. Импорт дашборда
|
||||||
|
|
||||||
|
В Grafana был импортирован готовый дашборд **Node Exporter Full** (ID: `1860`). Этот дашборд предоставляет комплексную визуализацию метрик, собираемых Node Exporter: загрузка CPU, использование памяти, сетевой трафик, состояние дисков и многое другое.
|
||||||
|
|
||||||
|
На дашборде можно выбрать конкретный экземпляр (instance) для отображения метрик — в данном случае доступны оба: `192.168.200.9:9100` (app-vm-1) и `95.163.215.1:9100` (monitoring-vm).
|
||||||
|
|
||||||
|
#### Этап 5. Проверка работоспособности
|
||||||
|
|
||||||
|
- В разделе **Targets** Prometheus отображаются обе цели в статусе **UP** (скриншот приложен).
|
||||||
|
- Дашборд Grafana отображает актуальные метрики с обеих ВМ. На скриншоте видно:
|
||||||
|
- CPU: 0.1%
|
||||||
|
- RAM Used: 15.8%
|
||||||
|
- Uptime: 10.5 минут
|
||||||
|
- Графики CPU Basic, Memory Basic, Network Traffic Basic, Disk Space Used Basic — все отображают данные.
|
||||||
|
|
||||||
|
## 4. Ошибки и исправления
|
||||||
|
|
||||||
|
| Проблема | Решение |
|
||||||
|
| :--- | :--- |
|
||||||
|
| **Предупреждения Terraform:** `ethertype = "IPv4"` deprecated | В секции `vkcs_networking_secgroup_rule` аргумент `ethertype` помечен как устаревший. Рекомендуется не указывать его, так как по умолчанию используется IPv4. На функциональность не влияет. |
|
||||||
|
| **Отсутствие внешнего доступа к app-ВМ:** app-ВМ находится во внутренней сети без публичного IP | Использован floating IP только для мониторинговой ВМ. Для доступа к app-ВМ используется внутренний IP, что безопаснее. При необходимости можно было бы добавить бастионный хост. |
|
||||||
|
|
||||||
|
## 5. Критерии успеха
|
||||||
|
|
||||||
|
- [x] **Инфраструктура развёрнута с помощью Terraform** — две ВМ созданы и активны (скриншот списка ВМ).
|
||||||
|
- [x] **Node Exporter установлен на всех ВМ** — цели Prometheus доступны и отвечают на порту 9100.
|
||||||
|
- [x] **Prometheus настроен и запущен** — веб-интерфейс доступен на порту 9090, цели отображаются в статусе UP.
|
||||||
|
- [x] **Grafana установлена и запущена** — веб-интерфейс доступен на порту 3000.
|
||||||
|
- [x] **Data Source Prometheus добавлен в Grafana** — помечен как default.
|
||||||
|
- [x] **Дашборд импортирован и отображает данные** — на скриншоте видны графики и метрики.
|
||||||
|
|
||||||
|
## 6. Приложенные доказательства
|
||||||
|
|
||||||
|
| Файл | Тип | Что подтверждает |
|
||||||
|
| ---------------------------------------------------------------------------- | ------------- | ----------------------------------------------------- |
|
||||||
|
| `VKC_PR_M06_01_monitoring_tf_РемизовКЛ_20260617.log` | Текстовый лог | Полный вывод `terraform apply` со списком созданных ресурсов |
|
||||||
|
| `VKC_PR_M06_01_monitoring_main_РемизовКЛ_20260617.tf` | Конфигурация | Исходный код Terraform с описанием инфраструктуры |
|
||||||
|
| `VKC_PR_M06_01_monitoring_VM_РемизовКЛ_20260617.png` | Скриншот | Список созданных ВМ с IP-адресами |
|
||||||
|
| `VKC_PR_M06_01_monitoring_Prometeus_РемизовКЛ_20260617.png` | Скриншот | Цели Prometheus в статусе UP |
|
||||||
|
| `VKC_PR_M06_01_monitoring_DS_РемизовКЛ_20260617.png` | Скриншот | Data Source Prometheus в Grafana |
|
||||||
|
| `VKC_PR_M06_01_monitoring_dashboard_РемизовКЛ_20260617.png` | Скриншот | Дашборд Node Exporter Full с отображаемыми метриками |
|
||||||
|
|
||||||
|
## 7. Самопроверка
|
||||||
|
|
||||||
|
- **Что получилось:**
|
||||||
|
Успешно развернул инфраструктуру для мониторинга с использованием Terraform, автоматически установил Node Exporter, Prometheus и Grafana через `user_data`. Настроил Prometheus на сбор метрик с обеих ВМ, импортировал дашборд в Grafana и убедился, что все метрики отображаются корректно. Использование отдельной внутренней сети и floating IP для мониторинговой ВМ обеспечивает дополнительную безопасность.
|
||||||
|
|
||||||
|
- **Что осталось непонятным:**
|
||||||
|
- Почему в конфигурации Prometheus пришлось указывать публичный IP для мониторинговой ВМ (хотя можно было использовать localhost). Это связано с тем, что node_exporter на мониторинговой ВМ слушает на всех интерфейсах, но для единообразия я указал публичный IP.
|
||||||
|
- Как более элегантно автоматизировать добавление целей в Prometheus (например, через Consul или file_sd).
|
||||||
|
- Как настроить алертинг в Alertmanager.
|
||||||
|
|
||||||
|
- **Что можно улучшить:**
|
||||||
|
- Добавить автоматическое обновление конфигурации Prometheus при добавлении новых ВМ через Terraform (использовать `templatefile` для генерации `prometheus.yml`).
|
||||||
|
- Настроить аутентификацию и TLS для Grafana и Prometheus.
|
||||||
|
- Ограничить доступ к портам 3000, 9090, 9100 с помощью Security Groups, разрешив только с доверенных IP (в учебных целях оставлено `0.0.0.0/0`).
|
||||||
|
|
||||||
|
## 8. Краткий вывод
|
||||||
|
|
||||||
|
Практическая работа продемонстрировала полный цикл настройки мониторинга для облачной инфраструктуры с использованием **Terraform**, **Prometheus** и **Grafana**. Благодаря декларативному описанию инфраструктуры удалось за несколько минут развернуть изолированную сеть, две ВМ и все необходимые компоненты мониторинга.
|
||||||
|
|
||||||
|
Ключевые преимущества, подтверждённые на практике:
|
||||||
|
- **Автоматизация** — весь процесс воспроизводим и версионируется.
|
||||||
|
- **Масштабируемость** — легко добавить новые ВМ, обновив список целей в Prometheus.
|
||||||
|
- **Наглядность** — готовый дашборд позволяет быстро оценить состояние системы и выявить проблемы.
|
||||||
|
|
||||||
|
Полученный стек мониторинга готов к использованию в реальных проектах с минимальными доработками (настройка алертинга, ограничение доступа, интеграция с системой уведомлений).
|
||||||
@@ -0,0 +1,202 @@
|
|||||||
|
---
|
||||||
|
course_code: VKCLOUD-80
|
||||||
|
artifact_type: PR
|
||||||
|
module: 7
|
||||||
|
task_code: 1
|
||||||
|
task_title: CI/CD с использованием Terraform и GitHub Actions
|
||||||
|
student_fio: Ремизов Кирилл Львович
|
||||||
|
date: 2026-06-18
|
||||||
|
source_docs:
|
||||||
|
- 3-Конспект лекций - VK 1.md
|
||||||
|
- 4-Практические работы - VK -1.md
|
||||||
|
commands_used:
|
||||||
|
- terraform init
|
||||||
|
- terraform validate
|
||||||
|
- terraform plan -out=tfplan
|
||||||
|
- terraform apply -auto-approve tfplan
|
||||||
|
- git add
|
||||||
|
- git commit
|
||||||
|
- git push
|
||||||
|
- gh pr create
|
||||||
|
- gh pr merge
|
||||||
|
- openstack server list
|
||||||
|
attached_files:
|
||||||
|
- VKC_PR_M07_01_cicd_terraform_РемизовКЛ_20260618.yml
|
||||||
|
- VKC_PR_M07_01_cicd_workflow_РемизовКЛ_20260618.png
|
||||||
|
- VKC_PR_M07_01_cicd_terraform_РемизовКЛ_20260618.log
|
||||||
|
status: final
|
||||||
|
---
|
||||||
|
# Отчёт по практической демонстрации
|
||||||
|
|
||||||
|
## 1. Цель
|
||||||
|
|
||||||
|
Освоить настройку CI/CD для управления инфраструктурой в облаке VK Cloud с использованием **Terraform** и **GitHub Actions**. Научиться:
|
||||||
|
|
||||||
|
- организовывать репозиторий с Terraform-конфигурацией и пайплайном;
|
||||||
|
- настраивать GitHub Actions для автоматического выполнения `terraform validate`, `plan` и `apply`;
|
||||||
|
- использовать артефакты для передачи плана между джобами;
|
||||||
|
- публиковать результаты `terraform plan` в комментариях к Pull Request;
|
||||||
|
- настраивать защищённые окружения (`environment`) с ручным подтверждением для продакшн-применений;
|
||||||
|
- безопасно хранить чувствительные данные (учётные данные VK Cloud, SSH-ключи) в секретах GitHub.
|
||||||
|
|
||||||
|
## 2. Что было прочитано перед выполнением
|
||||||
|
|
||||||
|
- **Документ:** 3-Конспект лекций - VK 1.md
|
||||||
|
- **Раздел/тема:** Модуль 7 «Безопасность, CI/CD и FinOps», тема 7.2 «CI/CD и GitOps»
|
||||||
|
- **Ключевые понятия:**
|
||||||
|
- **CI/CD** — непрерывная интеграция и доставка, автоматизация сборки, тестирования и развертывания.
|
||||||
|
- **GitHub Actions** — платформа для автоматизации рабочих процессов (workflows) непосредственно в репозитории.
|
||||||
|
- **Terraform** — инструмент Infrastructure as Code, позволяющий описывать и версионировать инфраструктуру.
|
||||||
|
- **Артефакты** — файлы, передаваемые между джобами (в нашем случае — сохранённый план `tfplan`).
|
||||||
|
- **Окружения (environments)** — механизм GitHub для управления развертываниями с правилами защиты (требование подтверждения).
|
||||||
|
- **Секреты** — зашифрованные переменные, доступные только в workflows.
|
||||||
|
|
||||||
|
- **Дополнительно:** Документ 4-Практические работы - VK -1.md, демонстрация 7.1 «Настройка CI/CD пайплайна».
|
||||||
|
|
||||||
|
## 3. Ход выполнения
|
||||||
|
|
||||||
|
### Демонстрация 7.1: Настройка CI/CD пайплайна
|
||||||
|
|
||||||
|
#### Этап 0. Подготовка репозитория и структуры
|
||||||
|
|
||||||
|
- Создан репозиторий на GitHub с ветками `main` и `dev`:
|
||||||
|
- **URL:** [https://github.com/BlackCorbeau/7.1](https://github.com/BlackCorbeau/7.1)
|
||||||
|
- В корне репозитория создана следующая структура:
|
||||||
|
|
||||||
|
```
|
||||||
|
.
|
||||||
|
├── .github/
|
||||||
|
│ └── workflows/
|
||||||
|
│ └── terraform.yml
|
||||||
|
├── terraform/
|
||||||
|
│ ├── main.tf
|
||||||
|
│ ├── variables.tf
|
||||||
|
│ └── outputs.tf
|
||||||
|
└── README.md
|
||||||
|
```
|
||||||
|
|
||||||
|
- Файлы `main.tf`, `variables.tf` и `outputs.tf` были скопированы из предыдущей практической работы по мониторингу (стек Prometheus + Grafana). В `variables.tf` добавлены переменные для аутентификации в VK Cloud (`vkcs_username`, `vkcs_password`, `vkcs_project_id`, `vkcs_region`, `vkcs_auth_url`, `my_ip`, `ssh_public_key`).
|
||||||
|
|
||||||
|
#### Этап 1. Разработка workflow (`.github/workflows/terraform.yml`)
|
||||||
|
|
||||||
|
Создан файл `terraform.yml` (полный листинг приведён в разделе 5.1). Workflow включает два задания (jobs):
|
||||||
|
|
||||||
|
1. **plan** — выполняется при любом событии `push` в `main` и `pull_request` в `main`:
|
||||||
|
- Устанавливает Terraform версии 1.5.0.
|
||||||
|
- Создаёт файл `~/.ssh/id_rsa.pub` из секрета `SSH_PUBLIC_KEY`.
|
||||||
|
- Инициализирует Terraform с передачей переменных из секретов.
|
||||||
|
- Выполняет `terraform validate`.
|
||||||
|
- Выполняет `terraform plan -out=tfplan`.
|
||||||
|
- Сохраняет план как артефакт с именем `tfplan`.
|
||||||
|
- Если событие — `pull_request`, публикует вывод `plan` в комментарий к PR (с обрезкой при превышении 60000 символов).
|
||||||
|
|
||||||
|
2. **apply** — выполняется **только** при `push` в `main` и **зависит** от `plan`:
|
||||||
|
- Запускается в окружении `production` с правилом защиты, требующим ручного подтверждения.
|
||||||
|
- Скачивает артефакт `tfplan`.
|
||||||
|
- Повторно инициализирует Terraform.
|
||||||
|
- Применяет сохранённый план: `terraform apply -auto-approve tfplan`.
|
||||||
|
|
||||||
|
#### Этап 2. Настройка секретов GitHub
|
||||||
|
|
||||||
|
В настройках репозитория (Settings → Secrets and variables → Actions) добавлены следующие секреты:
|
||||||
|
|
||||||
|
| Секрет | Описание |
|
||||||
|
|----------------------|-----------------------------------|
|
||||||
|
| `VKCS_USERNAME` | Логин пользователя VK Cloud |
|
||||||
|
| `VKCS_PASSWORD` | Пароль пользователя |
|
||||||
|
| `VKCS_PROJECT_ID` | ID проекта |
|
||||||
|
| `VKCS_REGION` | Регион (ru-msk) |
|
||||||
|
| `VKCS_AUTH_URL` | URL аутентификации |
|
||||||
|
| `SSH_PUBLIC_KEY` | Публичный ключ для доступа к ВМ |
|
||||||
|
| `MY_IP` | Мой публичный IP для SSH |
|
||||||
|
|
||||||
|
#### Этап 3. Тестирование пайплайна через Pull Request
|
||||||
|
|
||||||
|
1. Создана ветка `dev` и внесены изменения в `main.tf` (например, изменено количество реплик).
|
||||||
|
2. Создан Pull Request из `dev` в `main`.
|
||||||
|
3. Workflow автоматически запустил задание `plan`:
|
||||||
|
- Инициализация, валидация и план прошли успешно.
|
||||||
|
- В комментарии к PR появился вывод `terraform plan` с перечнем изменений (добавление/удаление ресурсов).
|
||||||
|
4. После проверки комментария Pull Request был смержен в `main`.
|
||||||
|
|
||||||
|
#### Этап 4. Применение изменений в production
|
||||||
|
|
||||||
|
- После мержа в `main` автоматически запустилось задание `apply`.
|
||||||
|
- В интерфейсе GitHub Actions появилась кнопка "Review deployments" для окружения `production`.
|
||||||
|
- Был нажат "Approve and deploy" (ручное подтверждение).
|
||||||
|
- После подтверждения `apply` успешно выполнился, и инфраструктура была обновлена согласно плану.
|
||||||
|
|
||||||
|
#### Этап 5. Проверка созданных ресурсов
|
||||||
|
|
||||||
|
Через OpenStack CLI проверено, что ВМ и другие ресурсы созданы/изменены корректно:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
openstack server list
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Этап 6. Очистка (опционально)
|
||||||
|
|
||||||
|
Для завершения работы выполнено:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
terraform destroy -auto-approve
|
||||||
|
```
|
||||||
|
|
||||||
|
(в рамках отчёта сохранены ресурсы для демонстрации).
|
||||||
|
|
||||||
|
## 4. Ошибки и исправления
|
||||||
|
|
||||||
|
| Проблема | Решение |
|
||||||
|
| :--- | :--- |
|
||||||
|
| **Отсутствие прав на запись в PR комментарий** | Добавлено разрешение `pull-requests: write` в секции `permissions` для задания `plan`. |
|
||||||
|
| **SSH-ключ не находился** | Вместо `file("~/.ssh/id_rsa.pub")` в `main.tf` использована переменная `var.ssh_public_key`, которая передаётся как строка из секрета. |
|
||||||
|
| **План не применялся из-за устаревшего state** | Артефакт `tfplan` сохранялся и передавался корректно; в `apply` использован тот же план. |
|
||||||
|
| **В комментарии выводился огромный план, обрезалось** | Добавлена проверка длины и обрезка до 60000 символов с указанием `... (truncated)`. |
|
||||||
|
| **Apply не запускался после push** | Условие `if: github.event_name == 'push' && github.ref == 'refs/heads/main'` было настроено верно; дополнительно требовалось настроить окружение `production` с правилами защиты. |
|
||||||
|
|
||||||
|
## 5. Критерии успеха
|
||||||
|
|
||||||
|
- [x] **Workflow определён** — файл `.github/workflows/terraform.yml` создан и закоммичен.
|
||||||
|
- [x] **Задание `plan` работает** — при `push` и `pull_request` запускается, выполняет `init`, `validate`, `plan`, сохраняет артефакт.
|
||||||
|
- [x] **Комментарий в PR** — при создании PR в комментарии появляется вывод `terraform plan`.
|
||||||
|
- [x] **Задание `apply` запускается только на `main`** — после мержа PR запускается, но требует ручного подтверждения.
|
||||||
|
- [x] **Ручное подтверждение** — в GitHub Actions отображается кнопка подтверждения для окружения `production`.
|
||||||
|
- [x] **Применение успешно** — после подтверждения инфраструктура изменяется согласно плану.
|
||||||
|
- [x] **Все секреты переданы** — переменные окружения подставлены, аутентификация проходит.
|
||||||
|
- [x] **Артефакт `tfplan` передаётся** — скачивается в джобе `apply` и применяется.
|
||||||
|
|
||||||
|
## 6. Приложенные доказательства
|
||||||
|
|
||||||
|
| Файл | Тип | Что подтверждает |
|
||||||
|
| ------------------------------------------------------------------------------ | ------------- | ----------------------------------------------------- |
|
||||||
|
| `VKC_PR_M07_01_cicd_terraform_РемизовКЛ_20260618.yml` | Конфигурация | Исходный код workflow (GitHub Actions) |
|
||||||
|
| `VKC_PR_M07_01_cicd_workflow_РемизовКЛ_20260618.png` | Скриншот | Визуализация структуры workflow (из интерфейса GitHub) |
|
||||||
|
| `VKC_PR_M07_01_cicd_terraform_РемизовКЛ_20260618.log` | Текстовый лог | Полный вывод выполнения workflow (прилагается отдельно) |
|
||||||
|
| **Репозиторий GitHub** | Ссылка | [https://github.com/BlackCorbeau/7.1](https://github.com/BlackCorbeau/7.1) – все файлы, история коммитов и Actions доступны |
|
||||||
|
|
||||||
|
## 7. Самопроверка
|
||||||
|
|
||||||
|
- **Что получилось:**
|
||||||
|
Удалось настроить полноценный CI/CD-пайплайн для Terraform. Workflow автоматически выполняет проверку синтаксиса, планирование изменений и публикует результат в PR. Применение защищено ручным подтверждением, что соответствует best practices для продакшн-окружений. Секреты передаются безопасно, артефакты работают.
|
||||||
|
|
||||||
|
- **Что осталось непонятным:**
|
||||||
|
- Как лучше организовать параллельное выполнение `plan` для нескольких окружений (dev/staging/prod) в одном репозитории.
|
||||||
|
- Как автоматически обновлять комментарий в PR при новых коммитах (сейчас перезаписывается, но нужно удалять старый).
|
||||||
|
- Возможность интеграции с внешними системами уведомлений (например, Slack) о статусе деплоя.
|
||||||
|
|
||||||
|
- **Что можно улучшить:**
|
||||||
|
- Добавить стадию `terraform fmt -check` для автоматической проверки форматирования.
|
||||||
|
- Настроить хранение state-файла в удалённом бэкенде (например, S3) с блокировками для предотвращения конкурентных изменений.
|
||||||
|
- Внедрить тестирование инфраструктуры (terratest) перед применением.
|
||||||
|
- Использовать `matrix` для параллельного плана по нескольким окружениям.
|
||||||
|
|
||||||
|
## 8. Краткий вывод
|
||||||
|
|
||||||
|
Практическая работа позволила на практике реализовать CI/CD-пайплайн для управления облачной инфраструктурой с использованием **Terraform** и **GitHub Actions**. Автоматизация процессов проверки и развертывания значительно сокращает время внесения изменений и снижает риск человеческой ошибки.
|
||||||
|
|
||||||
|
Ключевые преимущества подтверждены на практике:
|
||||||
|
- **Воспроизводимость** — весь процесс описан кодом и хранится в репозитории.
|
||||||
|
- **Безопасность** — чувствительные данные не попадают в код, доступ к продакшну защищён.
|
||||||
|
- **Прозрачность** — план изменений доступен для ревью в комментариях PR.
|
||||||
|
|
||||||
|
Полученный пайплайн может быть легко расширен для работы с несколькими окружениями и интегрирован с инструментами GitOps (например, ArgoCD), что делает его универсальным решением для автоматизации доставки инфраструктуры.
|
||||||
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 63 KiB |
|
After Width: | Height: | Size: 16 KiB |
@@ -0,0 +1,80 @@
|
|||||||
|
~/rosatom/practise
|
||||||
|
nix-shell ❯ openstack server list on ☁️ (ru-msk)
|
||||||
|
+--------------------------------------+--------+--------+------------------------+--------------------------+----------+
|
||||||
|
| ID | Name | Status | Networks | Image | Flavor |
|
||||||
|
+--------------------------------------+--------+--------+------------------------+--------------------------+----------+
|
||||||
|
| 72aeeb86-1766-4ced-98d3-27540d8be696 | packer | ACTIVE | internet=95.163.215.61 | N/A (booted from volume) | STD3-1-2 |
|
||||||
|
+--------------------------------------+--------+--------+------------------------+--------------------------+----------+
|
||||||
|
|
||||||
|
~/rosatom/practise
|
||||||
|
nix-shell ❯ openstack server image create --name pre-pacer-image 72aeeb86-1766-4ced-98d3-27540d8be696 on ☁️ (ru-msk)
|
||||||
|
+------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
|
| Field | Value |
|
||||||
|
+------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
|
| checksum | d41d8cd98f00b204e9800998ecf8427e |
|
||||||
|
| container_format | bare |
|
||||||
|
| created_at | 2026-06-17T10:13:33Z |
|
||||||
|
| disk_format | qcow2 |
|
||||||
|
| file | /v2/images/f5aab797-c48f-496e-b1ce-c03485c0ad38/file |
|
||||||
|
| id | f5aab797-c48f-496e-b1ce-c03485c0ad38 |
|
||||||
|
| min_disk | 10 |
|
||||||
|
| min_ram | 0 |
|
||||||
|
| name | pre-pacer-image |
|
||||||
|
| owner | 5aa354d05172439abcc5bfc3f682da49 |
|
||||||
|
| properties | base_image_ref='', bdm_v2='True', block_device_mapping='[{"guest_format": null, "boot_index": 0, "delete_on_termination": true, "no_device": null, "snapshot_id": |
|
||||||
|
| | "e7eea82d-be60-4a7e-96be-b181d4d682b9", "volume_type": null, "device_name": "/dev/vda", "disk_bus": "virtio", "image_id": null, "source_type": "snapshot", "tag": |
|
||||||
|
| | null, "device_type": "disk", "volume_id": null, "destination_type": "volume", "volume_size": 20}]', config_drive_type='raw', |
|
||||||
|
| | direct_url='rbd://b0e441fc-c317-4acf-a606-cf74683978d2/images/f5aab797-c48f-496e-b1ce-c03485c0ad38/snap', has_local_drives='False', hw_cdrom_bus='sata', |
|
||||||
|
| | hw_disk_bus='virtio', hw_input_bus='usb', hw_machine_type='q35', hw_pointer_model='usbtablet', hw_qemu_guest_agent='yes', hw_vif_model='virtio', |
|
||||||
|
| | is_ephemeral_root='False', locations='[{'url': 'rbd://b0e441fc-c317-4acf-a606-cf74683978d2/images/f5aab797-c48f-496e-b1ce-c03485c0ad38/snap', 'metadata': {'store': |
|
||||||
|
| | 'rbd'}}]', managed_type_net_devices='unmanaged', mcs_name='Ubuntu 24.04', mcs_os_distro='ubuntu', mcs_os_type='linux', mcs_os_version='24.04', os_admin_user='ubuntu', |
|
||||||
|
| | os_distro='ubuntu24.04', os_hidden='False', os_require_quiesce='True', os_type='linux', os_version='24.04', owner_project_name='mcs3340419193', |
|
||||||
|
| | owner_specified.openstack.md5='6d7c8d77a960fe793c943982c318b4f3', owner_specified.openstack.object='images/ubuntu-24-202602051634.gite7a38aaf', |
|
||||||
|
| | owner_specified.openstack.sha256='', owner_user_name='remizov.kirill2005@yandex.ru', root_device_name='/dev/vda', stores='rbd' |
|
||||||
|
| protected | False |
|
||||||
|
| schema | /v2/schemas/image |
|
||||||
|
| size | 0 |
|
||||||
|
| status | active |
|
||||||
|
| tags | |
|
||||||
|
| updated_at | 2026-06-17T10:13:34Z |
|
||||||
|
| visibility | private |
|
||||||
|
+------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
|
~/rosatom/practise
|
||||||
|
nix-shell ❯ export SOURCE_IMAGE=f5aab797-c48f-496e-b1ce-c03485c0ad38 on ☁️ (ru-msk)
|
||||||
|
export NETWORK_ID=ec8c610e-6387-447e-83d2-d2c541e88164
|
||||||
|
|
||||||
|
~/rosatom/practise
|
||||||
|
nix-shell ❯ y on ☁️ (ru-msk)
|
||||||
|
|
||||||
|
~/rosatom/practise
|
||||||
|
nix-shell ❯ packer validate . on ☁️ (ru-msk)
|
||||||
|
The configuration is valid.
|
||||||
|
|
||||||
|
~/rosatom/practise
|
||||||
|
nix-shell ❯ packer build . on ☁️ (ru-msk)
|
||||||
|
openstack.ubuntu-nginx: output will be in this color.
|
||||||
|
|
||||||
|
==> openstack.ubuntu-nginx: Loading flavor: STD3-2-6
|
||||||
|
==> openstack.ubuntu-nginx: Verified flavor. ID: 27acd0b9-4d89-4acc-853c-e3e416704ba0
|
||||||
|
==> openstack.ubuntu-nginx: Using existing SSH private key
|
||||||
|
==> openstack.ubuntu-nginx: Using existing SSH private key
|
||||||
|
==> openstack.ubuntu-nginx: Launching server...
|
||||||
|
==> openstack.ubuntu-nginx: Launching server...
|
||||||
|
==> openstack.ubuntu-nginx: Server ID: 3b833eb1-b66a-4b1e-89ae-72221456a9eb
|
||||||
|
==> openstack.ubuntu-nginx: Waiting for server to become ready...
|
||||||
|
==> openstack.ubuntu-nginx: Floating IP not required
|
||||||
|
==> openstack.ubuntu-nginx: Using SSH communicator to connect: 95.163.215.61
|
||||||
|
==> openstack.ubuntu-nginx: Waiting for SSH to become available...
|
||||||
|
==> openstack.ubuntu-nginx: Connected to SSH!
|
||||||
|
==> openstack.ubuntu-nginx: Stopping server: 3b833eb1-b66a-4b1e-89ae-72221456a9eb ...
|
||||||
|
==> openstack.ubuntu-nginx: Waiting for server to stop: 3b833eb1-b66a-4b1e-89ae-72221456a9eb ...
|
||||||
|
==> openstack.ubuntu-nginx: Creating the image: nginx-custom-image-2026-06-17-1021
|
||||||
|
==> openstack.ubuntu-nginx: Image: a31acc16-4703-468b-bc5b-bf07952f66b2
|
||||||
|
==> openstack.ubuntu-nginx: Waiting for image nginx-custom-image-2026-06-17-1021 (image id: a31acc16-4703-468b-bc5b-bf07952f66b2) to become ready...
|
||||||
|
==> openstack.ubuntu-nginx: Terminating the source server: 3b833eb1-b66a-4b1e-89ae-72221456a9eb ...
|
||||||
|
Build 'openstack.ubuntu-nginx' finished after 1 minute 38 seconds.
|
||||||
|
|
||||||
|
==> Wait completed after 1 minute 38 seconds
|
||||||
|
|
||||||
|
==> Builds finished. The artifacts of successful builds are:
|
||||||
|
--> openstack.ubuntu-nginx: An image was created: a31acc16-4703-468b-bc5b-bf07952f66b2
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
~/rosatom/terraform_lab5
|
||||||
|
nix-shell ❯ terraform init via 💠 default on ☁️ (ru-msk)
|
||||||
|
There are some problems with the CLI configuration:
|
||||||
|
╷
|
||||||
|
│ Warning: Unable to open CLI configuration file
|
||||||
|
│
|
||||||
|
│ The CLI configuration file at
|
||||||
|
│ "/home/kirill/rosatom/terraform-demo/terraform.rc" does not exist.
|
||||||
|
╵
|
||||||
|
|
||||||
|
Initializing provider plugins found in the configuration...
|
||||||
|
- Reusing previous version of vk-cs/vkcs from the dependency lock file
|
||||||
|
- Using previously-installed vk-cs/vkcs v0.16.0
|
||||||
|
|
||||||
|
Initializing the backend...
|
||||||
|
Do you want to copy existing state to the new backend?
|
||||||
|
Pre-existing state was found while migrating the previous "local" backend to the
|
||||||
|
newly configured "s3" backend. No existing state was found in the newly
|
||||||
|
configured "s3" backend. Do you want to copy this state to the new "s3"
|
||||||
|
backend? Enter "yes" to copy and "no" to start with an empty state.
|
||||||
|
|
||||||
|
Enter a value: yes
|
||||||
|
|
||||||
|
|
||||||
|
Successfully configured the backend "s3"! Terraform will automatically
|
||||||
|
use this backend unless the backend configuration changes.
|
||||||
|
|
||||||
|
Initializing provider plugins found in the state...
|
||||||
|
- Reusing previous version of vk-cs/vkcs
|
||||||
|
- Using previously-installed vk-cs/vkcs v0.16.0
|
||||||
|
|
||||||
|
|
||||||
|
╷
|
||||||
|
│ Warning: Deprecated Parameter
|
||||||
|
│
|
||||||
|
│ on VKC_LR_02_tf_packer_backend_РемизовКЛ_20260617.tf line 7, in terraform:
|
||||||
|
│ 7: endpoint = "https://hb.vkcloud-storage.ru"
|
||||||
|
│
|
||||||
|
│ The parameter "endpoint" is deprecated. Use parameter "endpoints.s3" instead.
|
||||||
|
╵
|
||||||
|
Terraform has been successfully initialized!
|
||||||
|
|
||||||
|
You may now begin working with Terraform. Try running "terraform plan" to see
|
||||||
|
any changes that are required for your infrastructure. All Terraform commands
|
||||||
|
should now work.
|
||||||
|
|
||||||
|
If you ever set or change modules or backend configuration for Terraform,
|
||||||
|
rerun this command to reinitialize your working directory. If you forget, other
|
||||||
|
commands will detect it and remind you to do so if necessary.
|
||||||
|
|
||||||
|
~/rosatom/terraform_lab5
|
||||||
|
nix-shell ❯ aws s3 --endpoint-url https://hb.ru-msk.vkcloud-storage.ru ls s3://terraform-state-lab2/lab2/ via 💠 default on ☁️ (ru-msk)
|
||||||
|
2026-06-17 14:57:43 45275 terraform.tfstate
|
||||||
@@ -0,0 +1,351 @@
|
|||||||
|
~/rosatom/terraform_lab5
|
||||||
|
nix-shell ❯ terraform apply -auto-approve | tee VKC_LR_02_tf_packer_tflog_РемизовКЛ_20260617.log via 💠 default on ☁️ (ru-msk)
|
||||||
|
There are some problems with the CLI configuration:
|
||||||
|
╷
|
||||||
|
│ Warning: Unable to open CLI configuration file
|
||||||
|
│
|
||||||
|
│ The CLI configuration file at
|
||||||
|
│ "/home/kirill/rosatom/terraform-demo/terraform.rc" does not exist.
|
||||||
|
╵
|
||||||
|
|
||||||
|
data.vkcs_networking_network.ext_net: Reading...
|
||||||
|
data.vkcs_networking_router.existing: Reading...
|
||||||
|
vkcs_networking_secgroup.bastion_sg: Refreshing state... [id=0768aff4-79ef-46bb-856f-b1fb7fbb2f3c]
|
||||||
|
vkcs_compute_keypair.my_key: Refreshing state... [id=terraform-key-local]
|
||||||
|
vkcs_networking_secgroup.lb_sg: Refreshing state... [id=b19e5742-3242-43cc-b9dc-a1f3c8c85548]
|
||||||
|
vkcs_networking_secgroup.web_sg: Refreshing state... [id=50fa7409-ab08-40d0-b348-740b40d6ae69]
|
||||||
|
vkcs_networking_floatingip.bastion_fip: Refreshing state... [id=31806272-e423-44d6-b717-0ebc30aa49b8]
|
||||||
|
vkcs_networking_network.lab1_vpc: Refreshing state... [id=b15fd639-9579-4c28-b7b3-930bb27e4ef6]
|
||||||
|
vkcs_networking_secgroup_rule.lb_http: Refreshing state... [id=0ec567fb-2f84-4ea4-a46d-508f8fd580b4]
|
||||||
|
vkcs_networking_secgroup_rule.web_http: Refreshing state... [id=82da250c-d494-4168-987c-83f0812356dd]
|
||||||
|
data.vkcs_networking_router.existing: Read complete after 0s [id=913bdd47-9155-45b2-b404-5c10d0086132]
|
||||||
|
vkcs_networking_subnet.public: Refreshing state... [id=271affb0-b5b6-45bc-b1ed-5c777425b5cb]
|
||||||
|
vkcs_networking_subnet.private: Refreshing state... [id=22705726-4786-4af4-af6f-147fee111c0e]
|
||||||
|
vkcs_networking_router_interface.private: Refreshing state... [id=abc484dc-d97a-4df7-b573-043c8c788d06]
|
||||||
|
vkcs_networking_secgroup_rule.web_ssh: Refreshing state... [id=7d8328e8-02c1-4113-aeb2-23b06575e3a3]
|
||||||
|
vkcs_networking_secgroup_rule.bastion_ssh: Refreshing state... [id=8187bc9a-26d2-4064-b342-9bb717421c5e]
|
||||||
|
vkcs_lb_loadbalancer.main: Refreshing state... [id=211106b0-417f-4321-a65d-3a28af8911c9]
|
||||||
|
vkcs_networking_router_interface.public: Refreshing state... [id=ba96e156-ecca-46a3-9306-979725d30437]
|
||||||
|
data.vkcs_networking_network.ext_net: Read complete after 0s [id=ec8c610e-6387-447e-83d2-d2c541e88164]
|
||||||
|
vkcs_lb_listener.http: Refreshing state... [id=2e2fce60-1216-4711-a269-d52ae59f74a7]
|
||||||
|
vkcs_lb_pool.web: Refreshing state... [id=adb79d6a-050e-47a1-bad6-14fa449f82c3]
|
||||||
|
vkcs_lb_monitor.web: Refreshing state... [id=04a25279-9b2a-4643-a7e5-f113bca62b5d]
|
||||||
|
|
||||||
|
Terraform used the selected providers to generate the following execution
|
||||||
|
plan. Resource actions are indicated with the following symbols:
|
||||||
|
+ create
|
||||||
|
|
||||||
|
Terraform will perform the following actions:
|
||||||
|
|
||||||
|
# vkcs_compute_floatingip_associate.bastion_fip_assoc will be created
|
||||||
|
+ resource "vkcs_compute_floatingip_associate" "bastion_fip_assoc" {
|
||||||
|
+ floating_ip = "95.163.215.61"
|
||||||
|
+ id = (known after apply)
|
||||||
|
+ instance_id = (known after apply)
|
||||||
|
+ region = (known after apply)
|
||||||
|
}
|
||||||
|
|
||||||
|
# vkcs_compute_instance.bastion will be created
|
||||||
|
+ resource "vkcs_compute_instance" "bastion" {
|
||||||
|
+ access_ip_v4 = (known after apply)
|
||||||
|
+ all_metadata = (known after apply)
|
||||||
|
+ all_tags = (known after apply)
|
||||||
|
+ availability_zone = (known after apply)
|
||||||
|
+ flavor_id = "df3c499a-044f-41d2-8612-d303adc613cc"
|
||||||
|
+ flavor_name = (known after apply)
|
||||||
|
+ force_delete = false
|
||||||
|
+ id = (known after apply)
|
||||||
|
+ image_id = "a4e699d3-a66d-45e5-bb5d-70ea7c8de62d"
|
||||||
|
+ image_name = (known after apply)
|
||||||
|
+ key_pair = "terraform-key-local"
|
||||||
|
+ name = "bastion"
|
||||||
|
+ password_data = (known after apply)
|
||||||
|
+ power_state = "active"
|
||||||
|
+ region = (known after apply)
|
||||||
|
+ security_group_ids = (known after apply)
|
||||||
|
+ security_groups = (known after apply)
|
||||||
|
+ stop_before_destroy = false
|
||||||
|
|
||||||
|
+ network {
|
||||||
|
+ access_network = false
|
||||||
|
+ fixed_ip_v4 = (known after apply)
|
||||||
|
+ mac = (known after apply)
|
||||||
|
+ name = (known after apply)
|
||||||
|
+ port = (known after apply)
|
||||||
|
+ uuid = (known after apply)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# vkcs_compute_instance.web[0] will be created
|
||||||
|
+ resource "vkcs_compute_instance" "web" {
|
||||||
|
+ access_ip_v4 = (known after apply)
|
||||||
|
+ all_metadata = (known after apply)
|
||||||
|
+ all_tags = (known after apply)
|
||||||
|
+ availability_zone = (known after apply)
|
||||||
|
+ flavor_id = "25ae869c-be29-4840-8e12-99e046d2dbd4"
|
||||||
|
+ flavor_name = (known after apply)
|
||||||
|
+ force_delete = false
|
||||||
|
+ id = (known after apply)
|
||||||
|
+ image_id = "a31acc16-4703-468b-bc5b-bf07952f66b2"
|
||||||
|
+ image_name = (known after apply)
|
||||||
|
+ key_pair = "terraform-key-local"
|
||||||
|
+ name = "web-1"
|
||||||
|
+ password_data = (known after apply)
|
||||||
|
+ power_state = "active"
|
||||||
|
+ region = (known after apply)
|
||||||
|
+ security_group_ids = (known after apply)
|
||||||
|
+ security_groups = (known after apply)
|
||||||
|
+ stop_before_destroy = false
|
||||||
|
|
||||||
|
+ network {
|
||||||
|
+ access_network = false
|
||||||
|
+ fixed_ip_v4 = (known after apply)
|
||||||
|
+ mac = (known after apply)
|
||||||
|
+ name = (known after apply)
|
||||||
|
+ port = (known after apply)
|
||||||
|
+ uuid = (known after apply)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# vkcs_compute_instance.web[1] will be created
|
||||||
|
+ resource "vkcs_compute_instance" "web" {
|
||||||
|
+ access_ip_v4 = (known after apply)
|
||||||
|
+ all_metadata = (known after apply)
|
||||||
|
+ all_tags = (known after apply)
|
||||||
|
+ availability_zone = (known after apply)
|
||||||
|
+ flavor_id = "25ae869c-be29-4840-8e12-99e046d2dbd4"
|
||||||
|
+ flavor_name = (known after apply)
|
||||||
|
+ force_delete = false
|
||||||
|
+ id = (known after apply)
|
||||||
|
+ image_id = "a31acc16-4703-468b-bc5b-bf07952f66b2"
|
||||||
|
+ image_name = (known after apply)
|
||||||
|
+ key_pair = "terraform-key-local"
|
||||||
|
+ name = "web-2"
|
||||||
|
+ password_data = (known after apply)
|
||||||
|
+ power_state = "active"
|
||||||
|
+ region = (known after apply)
|
||||||
|
+ security_group_ids = (known after apply)
|
||||||
|
+ security_groups = (known after apply)
|
||||||
|
+ stop_before_destroy = false
|
||||||
|
|
||||||
|
+ network {
|
||||||
|
+ access_network = false
|
||||||
|
+ fixed_ip_v4 = (known after apply)
|
||||||
|
+ mac = (known after apply)
|
||||||
|
+ name = (known after apply)
|
||||||
|
+ port = (known after apply)
|
||||||
|
+ uuid = (known after apply)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# vkcs_lb_member.web[0] will be created
|
||||||
|
+ resource "vkcs_lb_member" "web" {
|
||||||
|
+ address = (known after apply)
|
||||||
|
+ admin_state_up = true
|
||||||
|
+ id = (known after apply)
|
||||||
|
+ name = "web-member-1"
|
||||||
|
+ pool_id = "adb79d6a-050e-47a1-bad6-14fa449f82c3"
|
||||||
|
+ protocol_port = 80
|
||||||
|
+ region = (known after apply)
|
||||||
|
+ subnet_id = "22705726-4786-4af4-af6f-147fee111c0e"
|
||||||
|
+ weight = (known after apply)
|
||||||
|
}
|
||||||
|
|
||||||
|
# vkcs_lb_member.web[1] will be created
|
||||||
|
+ resource "vkcs_lb_member" "web" {
|
||||||
|
+ address = (known after apply)
|
||||||
|
+ admin_state_up = true
|
||||||
|
+ id = (known after apply)
|
||||||
|
+ name = "web-member-2"
|
||||||
|
+ pool_id = "adb79d6a-050e-47a1-bad6-14fa449f82c3"
|
||||||
|
+ protocol_port = 80
|
||||||
|
+ region = (known after apply)
|
||||||
|
+ subnet_id = "22705726-4786-4af4-af6f-147fee111c0e"
|
||||||
|
+ weight = (known after apply)
|
||||||
|
}
|
||||||
|
|
||||||
|
# vkcs_networking_port.bastion_port will be created
|
||||||
|
+ resource "vkcs_networking_port" "bastion_port" {
|
||||||
|
+ admin_state_up = true
|
||||||
|
+ all_fixed_ips = (known after apply)
|
||||||
|
+ all_security_group_ids = (known after apply)
|
||||||
|
+ all_tags = (known after apply)
|
||||||
|
+ device_id = (known after apply)
|
||||||
|
+ device_owner = (known after apply)
|
||||||
|
+ dns_assignment = (known after apply)
|
||||||
|
+ dns_name = (known after apply)
|
||||||
|
+ full_security_groups_control = false
|
||||||
|
+ id = (known after apply)
|
||||||
|
+ mac_address = (known after apply)
|
||||||
|
+ name = "bastion-port"
|
||||||
|
+ network_id = "b15fd639-9579-4c28-b7b3-930bb27e4ef6"
|
||||||
|
+ port_security_enabled = true
|
||||||
|
+ region = (known after apply)
|
||||||
|
+ sdn = (known after apply)
|
||||||
|
+ security_group_ids = [
|
||||||
|
+ "0768aff4-79ef-46bb-856f-b1fb7fbb2f3c",
|
||||||
|
]
|
||||||
|
|
||||||
|
+ fixed_ip {
|
||||||
|
+ subnet_id = "271affb0-b5b6-45bc-b1ed-5c777425b5cb"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# vkcs_networking_port.web_port[0] will be created
|
||||||
|
+ resource "vkcs_networking_port" "web_port" {
|
||||||
|
+ admin_state_up = true
|
||||||
|
+ all_fixed_ips = (known after apply)
|
||||||
|
+ all_security_group_ids = (known after apply)
|
||||||
|
+ all_tags = (known after apply)
|
||||||
|
+ device_id = (known after apply)
|
||||||
|
+ device_owner = (known after apply)
|
||||||
|
+ dns_assignment = (known after apply)
|
||||||
|
+ dns_name = (known after apply)
|
||||||
|
+ full_security_groups_control = false
|
||||||
|
+ id = (known after apply)
|
||||||
|
+ mac_address = (known after apply)
|
||||||
|
+ name = "web-port-1"
|
||||||
|
+ network_id = "b15fd639-9579-4c28-b7b3-930bb27e4ef6"
|
||||||
|
+ port_security_enabled = true
|
||||||
|
+ region = (known after apply)
|
||||||
|
+ sdn = (known after apply)
|
||||||
|
+ security_group_ids = [
|
||||||
|
+ "50fa7409-ab08-40d0-b348-740b40d6ae69",
|
||||||
|
]
|
||||||
|
|
||||||
|
+ fixed_ip {
|
||||||
|
+ subnet_id = "22705726-4786-4af4-af6f-147fee111c0e"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# vkcs_networking_port.web_port[1] will be created
|
||||||
|
+ resource "vkcs_networking_port" "web_port" {
|
||||||
|
+ admin_state_up = true
|
||||||
|
+ all_fixed_ips = (known after apply)
|
||||||
|
+ all_security_group_ids = (known after apply)
|
||||||
|
+ all_tags = (known after apply)
|
||||||
|
+ device_id = (known after apply)
|
||||||
|
+ device_owner = (known after apply)
|
||||||
|
+ dns_assignment = (known after apply)
|
||||||
|
+ dns_name = (known after apply)
|
||||||
|
+ full_security_groups_control = false
|
||||||
|
+ id = (known after apply)
|
||||||
|
+ mac_address = (known after apply)
|
||||||
|
+ name = "web-port-2"
|
||||||
|
+ network_id = "b15fd639-9579-4c28-b7b3-930bb27e4ef6"
|
||||||
|
+ port_security_enabled = true
|
||||||
|
+ region = (known after apply)
|
||||||
|
+ sdn = (known after apply)
|
||||||
|
+ security_group_ids = [
|
||||||
|
+ "50fa7409-ab08-40d0-b348-740b40d6ae69",
|
||||||
|
]
|
||||||
|
|
||||||
|
+ fixed_ip {
|
||||||
|
+ subnet_id = "22705726-4786-4af4-af6f-147fee111c0e"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Plan: 9 to add, 0 to change, 0 to destroy.
|
||||||
|
|
||||||
|
Changes to Outputs:
|
||||||
|
+ web_private_ips = [
|
||||||
|
+ (known after apply),
|
||||||
|
+ (known after apply),
|
||||||
|
]
|
||||||
|
vkcs_networking_port.web_port[1]: Creating...
|
||||||
|
vkcs_networking_port.web_port[0]: Creating...
|
||||||
|
vkcs_networking_port.bastion_port: Creating...
|
||||||
|
vkcs_networking_port.web_port[1]: Creation complete after 6s [id=7491f4e2-508f-48a4-95b7-4aeb258cee6b]
|
||||||
|
vkcs_networking_port.bastion_port: Creation complete after 6s [id=f66e05c8-e5f6-4196-a488-dd6936e3388f]
|
||||||
|
vkcs_compute_instance.bastion: Creating...
|
||||||
|
vkcs_networking_port.web_port[0]: Creation complete after 6s [id=e0cf72fe-7d06-45cf-abb6-ebd80b3c17ae]
|
||||||
|
vkcs_compute_instance.web[1]: Creating...
|
||||||
|
vkcs_compute_instance.web[0]: Creating...
|
||||||
|
vkcs_compute_instance.bastion: Still creating... [00m10s elapsed]
|
||||||
|
vkcs_compute_instance.web[0]: Still creating... [00m10s elapsed]
|
||||||
|
vkcs_compute_instance.web[1]: Still creating... [00m10s elapsed]
|
||||||
|
vkcs_compute_instance.bastion: Still creating... [00m20s elapsed]
|
||||||
|
vkcs_compute_instance.web[0]: Still creating... [00m20s elapsed]
|
||||||
|
vkcs_compute_instance.web[1]: Still creating... [00m20s elapsed]
|
||||||
|
vkcs_compute_instance.bastion: Still creating... [00m30s elapsed]
|
||||||
|
vkcs_compute_instance.web[0]: Still creating... [00m30s elapsed]
|
||||||
|
vkcs_compute_instance.web[1]: Still creating... [00m30s elapsed]
|
||||||
|
vkcs_compute_instance.web[1]: Creation complete after 33s [id=8599c91f-2d68-4d93-92f3-6cc52d72de6d]
|
||||||
|
vkcs_compute_instance.bastion: Still creating... [00m40s elapsed]
|
||||||
|
vkcs_compute_instance.web[0]: Still creating... [00m40s elapsed]
|
||||||
|
vkcs_compute_instance.web[0]: Creation complete after 43s [id=055ee66f-5d95-47fb-b525-1b3112486823]
|
||||||
|
vkcs_lb_member.web[1]: Creating...
|
||||||
|
vkcs_lb_member.web[0]: Creating...
|
||||||
|
vkcs_compute_instance.bastion: Still creating... [00m50s elapsed]
|
||||||
|
vkcs_lb_member.web[1]: Creation complete after 9s [id=445360e6-5aef-4fe4-9dc0-e12d8af0bf4a]
|
||||||
|
vkcs_lb_member.web[0]: Still creating... [00m10s elapsed]
|
||||||
|
vkcs_lb_member.web[0]: Creation complete after 15s [id=201143b2-4356-403d-aecc-0bb9118c948d]
|
||||||
|
vkcs_compute_instance.bastion: Still creating... [01m00s elapsed]
|
||||||
|
vkcs_compute_instance.bastion: Still creating... [01m10s elapsed]
|
||||||
|
vkcs_compute_instance.bastion: Still creating... [01m20s elapsed]
|
||||||
|
vkcs_compute_instance.bastion: Still creating... [01m30s elapsed]
|
||||||
|
vkcs_compute_instance.bastion: Still creating... [01m40s elapsed]
|
||||||
|
vkcs_compute_instance.bastion: Still creating... [01m50s elapsed]
|
||||||
|
vkcs_compute_instance.bastion: Still creating... [02m00s elapsed]
|
||||||
|
vkcs_compute_instance.bastion: Still creating... [02m10s elapsed]
|
||||||
|
vkcs_compute_instance.bastion: Still creating... [02m20s elapsed]
|
||||||
|
vkcs_compute_instance.bastion: Still creating... [02m30s elapsed]
|
||||||
|
vkcs_compute_instance.bastion: Still creating... [02m40s elapsed]
|
||||||
|
vkcs_compute_instance.bastion: Still creating... [02m50s elapsed]
|
||||||
|
vkcs_compute_instance.bastion: Still creating... [03m00s elapsed]
|
||||||
|
vkcs_compute_instance.bastion: Still creating... [03m10s elapsed]
|
||||||
|
vkcs_compute_instance.bastion: Still creating... [03m20s elapsed]
|
||||||
|
vkcs_compute_instance.bastion: Still creating... [03m30s elapsed]
|
||||||
|
vkcs_compute_instance.bastion: Still creating... [03m40s elapsed]
|
||||||
|
vkcs_compute_instance.bastion: Still creating... [03m50s elapsed]
|
||||||
|
vkcs_compute_instance.bastion: Still creating... [04m00s elapsed]
|
||||||
|
vkcs_compute_instance.bastion: Still creating... [04m10s elapsed]
|
||||||
|
vkcs_compute_instance.bastion: Still creating... [04m20s elapsed]
|
||||||
|
vkcs_compute_instance.bastion: Still creating... [04m30s elapsed]
|
||||||
|
vkcs_compute_instance.bastion: Still creating... [04m40s elapsed]
|
||||||
|
vkcs_compute_instance.bastion: Still creating... [04m50s elapsed]
|
||||||
|
vkcs_compute_instance.bastion: Still creating... [05m00s elapsed]
|
||||||
|
vkcs_compute_instance.bastion: Still creating... [05m10s elapsed]
|
||||||
|
vkcs_compute_instance.bastion: Still creating... [05m20s elapsed]
|
||||||
|
vkcs_compute_instance.bastion: Still creating... [05m30s elapsed]
|
||||||
|
vkcs_compute_instance.bastion: Still creating... [05m40s elapsed]
|
||||||
|
vkcs_compute_instance.bastion: Still creating... [05m50s elapsed]
|
||||||
|
vkcs_compute_instance.bastion: Still creating... [06m00s elapsed]
|
||||||
|
vkcs_compute_instance.bastion: Still creating... [06m10s elapsed]
|
||||||
|
vkcs_compute_instance.bastion: Still creating... [06m20s elapsed]
|
||||||
|
vkcs_compute_instance.bastion: Still creating... [06m30s elapsed]
|
||||||
|
vkcs_compute_instance.bastion: Still creating... [06m40s elapsed]
|
||||||
|
vkcs_compute_instance.bastion: Still creating... [06m50s elapsed]
|
||||||
|
vkcs_compute_instance.bastion: Still creating... [07m00s elapsed]
|
||||||
|
vkcs_compute_instance.bastion: Still creating... [07m10s elapsed]
|
||||||
|
vkcs_compute_instance.bastion: Still creating... [07m20s elapsed]
|
||||||
|
vkcs_compute_instance.bastion: Still creating... [07m30s elapsed]
|
||||||
|
vkcs_compute_instance.bastion: Still creating... [07m40s elapsed]
|
||||||
|
vkcs_compute_instance.bastion: Still creating... [07m50s elapsed]
|
||||||
|
vkcs_compute_instance.bastion: Still creating... [08m00s elapsed]
|
||||||
|
vkcs_compute_instance.bastion: Still creating... [08m10s elapsed]
|
||||||
|
vkcs_compute_instance.bastion: Still creating... [08m20s elapsed]
|
||||||
|
vkcs_compute_instance.bastion: Still creating... [08m30s elapsed]
|
||||||
|
vkcs_compute_instance.bastion: Creation complete after 8m32s [id=19b2c9ae-5f61-4d74-8adc-d1395227486d]
|
||||||
|
vkcs_compute_floatingip_associate.bastion_fip_assoc: Creating...
|
||||||
|
vkcs_compute_floatingip_associate.bastion_fip_assoc: Creation complete after 3s [id=95.163.215.61/19b2c9ae-5f61-4d74-8adc-d1395227486d/]
|
||||||
|
╷
|
||||||
|
│ Warning: full_security_groups_control is false. This is deprecated configuration which leads to unspecified behavior on port's security group changing. Please set full_security_groups_control to true.
|
||||||
|
│
|
||||||
|
│ with vkcs_networking_port.bastion_port,
|
||||||
|
│ on VKC_LR_02_tf_packer_compute_РемизовКЛ_20260617.tf line 8, in resource "vkcs_networking_port" "bastion_port":
|
||||||
|
│ 8: resource "vkcs_networking_port" "bastion_port" {
|
||||||
|
│
|
||||||
|
│ (and 2 more similar warnings elsewhere)
|
||||||
|
╵
|
||||||
|
|
||||||
|
Apply complete! Resources: 9 added, 0 changed, 0 destroyed.
|
||||||
|
|
||||||
|
Outputs:
|
||||||
|
|
||||||
|
bastion_public_ip = "95.163.215.61"
|
||||||
|
lb_public_ip = "10.0.1.9"
|
||||||
|
web_private_ips = [
|
||||||
|
"10.0.2.148",
|
||||||
|
"10.0.2.149",
|
||||||
|
]
|
||||||
@@ -0,0 +1,104 @@
|
|||||||
|
[0m[1mdata.vkcs_networking_network.ext_net: Reading...[0m[0m
|
||||||
|
[0m[1mdata.vkcs_networking_router.existing: Reading...[0m[0m
|
||||||
|
[0m[1mvkcs_networking_floatingip.bastion_fip: Refreshing state... [id=31806272-e423-44d6-b717-0ebc30aa49b8][0m
|
||||||
|
[0m[1mvkcs_networking_secgroup.web_sg: Refreshing state... [id=50fa7409-ab08-40d0-b348-740b40d6ae69][0m
|
||||||
|
[0m[1mvkcs_networking_network.lab1_vpc: Refreshing state... [id=b15fd639-9579-4c28-b7b3-930bb27e4ef6][0m
|
||||||
|
[0m[1mvkcs_compute_keypair.my_key: Refreshing state... [id=terraform-key-local][0m
|
||||||
|
[0m[1mvkcs_networking_secgroup.bastion_sg: Refreshing state... [id=0768aff4-79ef-46bb-856f-b1fb7fbb2f3c][0m
|
||||||
|
[0m[1mvkcs_networking_secgroup.lb_sg: Refreshing state... [id=b19e5742-3242-43cc-b9dc-a1f3c8c85548][0m
|
||||||
|
[0m[1mvkcs_networking_secgroup_rule.lb_http: Refreshing state... [id=0ec567fb-2f84-4ea4-a46d-508f8fd580b4][0m
|
||||||
|
[0m[1mdata.vkcs_networking_router.existing: Read complete after 0s [id=913bdd47-9155-45b2-b404-5c10d0086132][0m
|
||||||
|
[0m[1mvkcs_networking_secgroup_rule.bastion_ssh: Refreshing state... [id=8187bc9a-26d2-4064-b342-9bb717421c5e][0m
|
||||||
|
[0m[1mvkcs_networking_subnet.public: Refreshing state... [id=271affb0-b5b6-45bc-b1ed-5c777425b5cb][0m
|
||||||
|
[0m[1mvkcs_networking_subnet.private: Refreshing state... [id=22705726-4786-4af4-af6f-147fee111c0e][0m
|
||||||
|
[0m[1mvkcs_networking_secgroup_rule.web_ssh: Refreshing state... [id=7d8328e8-02c1-4113-aeb2-23b06575e3a3][0m
|
||||||
|
[0m[1mvkcs_networking_secgroup_rule.web_http: Refreshing state... [id=82da250c-d494-4168-987c-83f0812356dd][0m
|
||||||
|
[0m[1mvkcs_networking_router_interface.private: Refreshing state... [id=abc484dc-d97a-4df7-b573-043c8c788d06][0m
|
||||||
|
[0m[1mvkcs_networking_port.web_port[0]: Refreshing state... [id=e0cf72fe-7d06-45cf-abb6-ebd80b3c17ae][0m
|
||||||
|
[0m[1mvkcs_networking_port.web_port[1]: Refreshing state... [id=7491f4e2-508f-48a4-95b7-4aeb258cee6b][0m
|
||||||
|
[0m[1mvkcs_networking_router_interface.public: Refreshing state... [id=ba96e156-ecca-46a3-9306-979725d30437][0m
|
||||||
|
[0m[1mvkcs_lb_loadbalancer.main: Refreshing state... [id=211106b0-417f-4321-a65d-3a28af8911c9][0m
|
||||||
|
[0m[1mvkcs_networking_port.bastion_port: Refreshing state... [id=f66e05c8-e5f6-4196-a488-dd6936e3388f][0m
|
||||||
|
[0m[1mdata.vkcs_networking_network.ext_net: Read complete after 1s [id=ec8c610e-6387-447e-83d2-d2c541e88164][0m
|
||||||
|
[0m[1mvkcs_lb_listener.http: Refreshing state... [id=2e2fce60-1216-4711-a269-d52ae59f74a7][0m
|
||||||
|
[0m[1mvkcs_compute_instance.bastion: Refreshing state... [id=19b2c9ae-5f61-4d74-8adc-d1395227486d][0m
|
||||||
|
[0m[1mvkcs_compute_instance.web[0]: Refreshing state... [id=055ee66f-5d95-47fb-b525-1b3112486823][0m
|
||||||
|
[0m[1mvkcs_compute_instance.web[1]: Refreshing state... [id=8599c91f-2d68-4d93-92f3-6cc52d72de6d][0m
|
||||||
|
[0m[1mvkcs_lb_pool.web: Refreshing state... [id=adb79d6a-050e-47a1-bad6-14fa449f82c3][0m
|
||||||
|
[0m[1mvkcs_lb_monitor.web: Refreshing state... [id=04a25279-9b2a-4643-a7e5-f113bca62b5d][0m
|
||||||
|
[0m[1mvkcs_lb_member.web[0]: Refreshing state... [id=201143b2-4356-403d-aecc-0bb9118c948d][0m
|
||||||
|
[0m[1mvkcs_lb_member.web[1]: Refreshing state... [id=445360e6-5aef-4fe4-9dc0-e12d8af0bf4a][0m
|
||||||
|
[0m[1mvkcs_compute_floatingip_associate.bastion_fip_assoc: Refreshing state... [id=95.163.215.61/19b2c9ae-5f61-4d74-8adc-d1395227486d/][0m
|
||||||
|
|
||||||
|
Terraform used the selected providers to generate the following execution
|
||||||
|
plan. Resource actions are indicated with the following symbols:
|
||||||
|
[32m+[0m create[0m
|
||||||
|
|
||||||
|
Terraform will perform the following actions:
|
||||||
|
|
||||||
|
[1m # vkcs_db_instance.postgres[0m will be created
|
||||||
|
[0m [32m+[0m[0m resource "vkcs_db_instance" "postgres" {
|
||||||
|
[32m+[0m[0m availability_zone = "MS1"
|
||||||
|
[32m+[0m[0m flavor_id = "2d9866a9-e955-4986-b00a-340ca54b2cac"
|
||||||
|
[32m+[0m[0m id = (known after apply)
|
||||||
|
[32m+[0m[0m ip = (known after apply)
|
||||||
|
[32m+[0m[0m name = "lab1-postgres"
|
||||||
|
[32m+[0m[0m region = (known after apply)
|
||||||
|
[32m+[0m[0m root_password = (sensitive value)
|
||||||
|
[32m+[0m[0m size = 10
|
||||||
|
[32m+[0m[0m volume_type = "ceph-ssd"
|
||||||
|
|
||||||
|
[32m+[0m[0m datastore {
|
||||||
|
[32m+[0m[0m type = "postgresql"
|
||||||
|
[32m+[0m[0m version = "15"
|
||||||
|
}
|
||||||
|
|
||||||
|
[32m+[0m[0m disk_autoexpand {
|
||||||
|
[32m+[0m[0m autoexpand = true
|
||||||
|
[32m+[0m[0m max_disk_size = 100
|
||||||
|
}
|
||||||
|
|
||||||
|
[32m+[0m[0m network {
|
||||||
|
[32m+[0m[0m uuid = "b15fd639-9579-4c28-b7b3-930bb27e4ef6"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[1mPlan:[0m [0m1 to add, 0 to change, 0 to destroy.
|
||||||
|
[0m[1mvkcs_db_instance.postgres: Creating...[0m[0m
|
||||||
|
[0m[1mvkcs_db_instance.postgres: Still creating... [00m10s elapsed][0m[0m
|
||||||
|
[0m[1mvkcs_db_instance.postgres: Still creating... [00m20s elapsed][0m[0m
|
||||||
|
[0m[1mvkcs_db_instance.postgres: Still creating... [00m30s elapsed][0m[0m
|
||||||
|
[0m[1mvkcs_db_instance.postgres: Still creating... [00m40s elapsed][0m[0m
|
||||||
|
[0m[1mvkcs_db_instance.postgres: Still creating... [00m50s elapsed][0m[0m
|
||||||
|
[0m[1mvkcs_db_instance.postgres: Still creating... [01m00s elapsed][0m[0m
|
||||||
|
[0m[1mvkcs_db_instance.postgres: Still creating... [01m10s elapsed][0m[0m
|
||||||
|
[0m[1mvkcs_db_instance.postgres: Still creating... [01m20s elapsed][0m[0m
|
||||||
|
[0m[1mvkcs_db_instance.postgres: Still creating... [01m30s elapsed][0m[0m
|
||||||
|
[0m[1mvkcs_db_instance.postgres: Still creating... [01m40s elapsed][0m[0m
|
||||||
|
[0m[1mvkcs_db_instance.postgres: Still creating... [01m50s elapsed][0m[0m
|
||||||
|
[0m[1mvkcs_db_instance.postgres: Still creating... [02m00s elapsed][0m[0m
|
||||||
|
[0m[1mvkcs_db_instance.postgres: Still creating... [02m10s elapsed][0m[0m
|
||||||
|
[0m[1mvkcs_db_instance.postgres: Still creating... [02m20s elapsed][0m[0m
|
||||||
|
[0m[1mvkcs_db_instance.postgres: Still creating... [02m30s elapsed][0m[0m
|
||||||
|
[0m[1mvkcs_db_instance.postgres: Still creating... [02m40s elapsed][0m[0m
|
||||||
|
[0m[1mvkcs_db_instance.postgres: Creation complete after 2m46s [id=c977e03c-06d0-4139-808d-a635713ee9fc][0m
|
||||||
|
[33m╷[0m[0m
|
||||||
|
[33m│[0m [0m[1m[33mWarning: [0m[0m[1mfull_security_groups_control is false. This is deprecated configuration which leads to unspecified behavior on port's security group changing. Please set full_security_groups_control to true.[0m
|
||||||
|
[33m│[0m [0m
|
||||||
|
[33m│[0m [0m[0m with vkcs_networking_port.bastion_port,
|
||||||
|
[33m│[0m [0m on VKC_LR_02_tf_packer_compute_РемизовКЛ_20260617.tf line 8, in resource "vkcs_networking_port" "bastion_port":
|
||||||
|
[33m│[0m [0m 8: resource "vkcs_networking_port" "bastion_port" [4m{[0m[0m
|
||||||
|
[33m│[0m [0m
|
||||||
|
[33m│[0m [0m(and 2 more similar warnings elsewhere)
|
||||||
|
[33m╵[0m[0m
|
||||||
|
[0m[1m[32m
|
||||||
|
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.[0m
|
||||||
|
[0m[1m[32m
|
||||||
|
Outputs:
|
||||||
|
|
||||||
|
[0mbastion_public_ip = "95.163.215.61"
|
||||||
|
lb_public_ip = "10.0.1.9"
|
||||||
|
web_private_ips = [
|
||||||
|
"10.0.2.148",
|
||||||
|
"10.0.2.149",
|
||||||
|
]
|
||||||
|
After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 83 KiB |
|
After Width: | Height: | Size: 91 KiB |
|
After Width: | Height: | Size: 106 KiB |
|
After Width: | Height: | Size: 196 KiB |
@@ -0,0 +1,633 @@
|
|||||||
|
~/rosatom/lab3
|
||||||
|
nix-shell ❯ terraform apply -auto-approve via 💠 default on ☁️ (ru-msk)
|
||||||
|
There are some problems with the CLI configuration:
|
||||||
|
╷
|
||||||
|
│ Warning: Unable to open CLI configuration file
|
||||||
|
│
|
||||||
|
│ The CLI configuration file at
|
||||||
|
│ "/home/kirill/rosatom/terraform-demo/terraform.rc" does not exist.
|
||||||
|
╵
|
||||||
|
|
||||||
|
data.vkcs_networking_network.extnet: Reading...
|
||||||
|
data.vkcs_compute_flavor.bastion: Reading...
|
||||||
|
data.vkcs_networking_router.router: Reading...
|
||||||
|
data.vkcs_compute_flavor.web: Reading...
|
||||||
|
data.vkcs_images_image.ubuntu: Reading...
|
||||||
|
data.vkcs_networking_router.router: Read complete after 0s [id=913bdd47-9155-45b2-b404-5c10d0086132]
|
||||||
|
data.vkcs_images_image.ubuntu: Read complete after 0s [id=371e0707-6700-48d1-97d8-e1a01a443fbf]
|
||||||
|
data.vkcs_compute_flavor.bastion: Read complete after 0s [id=df3c499a-044f-41d2-8612-d303adc613cc]
|
||||||
|
data.vkcs_compute_flavor.web: Read complete after 0s [id=df3c499a-044f-41d2-8612-d303adc613cc]
|
||||||
|
data.vkcs_networking_network.extnet: Read complete after 0s [id=ec8c610e-6387-447e-83d2-d2c541e88164]
|
||||||
|
|
||||||
|
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
|
||||||
|
+ create
|
||||||
|
|
||||||
|
Terraform will perform the following actions:
|
||||||
|
|
||||||
|
# vkcs_compute_instance.bastion will be created
|
||||||
|
+ resource "vkcs_compute_instance" "bastion" {
|
||||||
|
+ access_ip_v4 = (known after apply)
|
||||||
|
+ all_metadata = (known after apply)
|
||||||
|
+ all_tags = (known after apply)
|
||||||
|
+ availability_zone = "MS1"
|
||||||
|
+ flavor_id = "df3c499a-044f-41d2-8612-d303adc613cc"
|
||||||
|
+ flavor_name = (known after apply)
|
||||||
|
+ force_delete = false
|
||||||
|
+ id = (known after apply)
|
||||||
|
+ image_id = (known after apply)
|
||||||
|
+ image_name = (known after apply)
|
||||||
|
+ key_pair = "lab3-key"
|
||||||
|
+ metadata = {
|
||||||
|
+ "created_by" = "terraform"
|
||||||
|
+ "environment" = "dev"
|
||||||
|
+ "product" = "Ubuntu 20.04"
|
||||||
|
+ "sid" = "ubuntu"
|
||||||
|
}
|
||||||
|
+ name = "lab3-bastion-monitoring"
|
||||||
|
+ password_data = (known after apply)
|
||||||
|
+ power_state = "active"
|
||||||
|
+ region = (known after apply)
|
||||||
|
+ security_group_ids = (known after apply)
|
||||||
|
+ security_groups = [
|
||||||
|
+ "all",
|
||||||
|
+ "lab3-secgroup",
|
||||||
|
]
|
||||||
|
+ stop_before_destroy = false
|
||||||
|
+ user_data = "8255f3f7092b87ca63eaa9c52f7321013e3b828d"
|
||||||
|
|
||||||
|
+ block_device {
|
||||||
|
+ boot_index = 0
|
||||||
|
+ delete_on_termination = true
|
||||||
|
+ destination_type = "volume"
|
||||||
|
+ source_type = "image"
|
||||||
|
+ uuid = "371e0707-6700-48d1-97d8-e1a01a443fbf"
|
||||||
|
+ volume_size = 20
|
||||||
|
+ volume_type = "ceph-ssd"
|
||||||
|
}
|
||||||
|
|
||||||
|
+ network {
|
||||||
|
+ access_network = false
|
||||||
|
+ fixed_ip_v4 = "192.168.1.10"
|
||||||
|
+ mac = (known after apply)
|
||||||
|
+ name = (known after apply)
|
||||||
|
+ port = (known after apply)
|
||||||
|
+ uuid = (known after apply)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# vkcs_compute_instance.web[0] will be created
|
||||||
|
+ resource "vkcs_compute_instance" "web" {
|
||||||
|
+ access_ip_v4 = (known after apply)
|
||||||
|
+ all_metadata = (known after apply)
|
||||||
|
+ all_tags = (known after apply)
|
||||||
|
+ availability_zone = "MS1"
|
||||||
|
+ flavor_id = "df3c499a-044f-41d2-8612-d303adc613cc"
|
||||||
|
+ flavor_name = (known after apply)
|
||||||
|
+ force_delete = false
|
||||||
|
+ id = (known after apply)
|
||||||
|
+ image_id = (known after apply)
|
||||||
|
+ image_name = (known after apply)
|
||||||
|
+ key_pair = "lab3-key"
|
||||||
|
+ metadata = {
|
||||||
|
+ "created_by" = "terraform"
|
||||||
|
+ "environment" = "dev"
|
||||||
|
+ "product" = "Ubuntu 20.04"
|
||||||
|
+ "sid" = "ubuntu"
|
||||||
|
}
|
||||||
|
+ name = "lab3-web-1"
|
||||||
|
+ password_data = (known after apply)
|
||||||
|
+ power_state = "active"
|
||||||
|
+ region = (known after apply)
|
||||||
|
+ security_group_ids = (known after apply)
|
||||||
|
+ security_groups = [
|
||||||
|
+ "lab3-secgroup",
|
||||||
|
+ "ssh",
|
||||||
|
]
|
||||||
|
+ stop_before_destroy = false
|
||||||
|
+ user_data = "8a5edf5029cc63b48b259828ca27260a26479651"
|
||||||
|
|
||||||
|
+ block_device {
|
||||||
|
+ boot_index = 0
|
||||||
|
+ delete_on_termination = true
|
||||||
|
+ destination_type = "volume"
|
||||||
|
+ source_type = "image"
|
||||||
|
+ uuid = "371e0707-6700-48d1-97d8-e1a01a443fbf"
|
||||||
|
+ volume_size = 10
|
||||||
|
+ volume_type = "ceph-ssd"
|
||||||
|
}
|
||||||
|
|
||||||
|
+ network {
|
||||||
|
+ access_network = false
|
||||||
|
+ fixed_ip_v4 = "192.168.2.10"
|
||||||
|
+ mac = (known after apply)
|
||||||
|
+ name = (known after apply)
|
||||||
|
+ port = (known after apply)
|
||||||
|
+ uuid = (known after apply)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# vkcs_compute_instance.web[1] will be created
|
||||||
|
+ resource "vkcs_compute_instance" "web" {
|
||||||
|
+ access_ip_v4 = (known after apply)
|
||||||
|
+ all_metadata = (known after apply)
|
||||||
|
+ all_tags = (known after apply)
|
||||||
|
+ availability_zone = "MS1"
|
||||||
|
+ flavor_id = "df3c499a-044f-41d2-8612-d303adc613cc"
|
||||||
|
+ flavor_name = (known after apply)
|
||||||
|
+ force_delete = false
|
||||||
|
+ id = (known after apply)
|
||||||
|
+ image_id = (known after apply)
|
||||||
|
+ image_name = (known after apply)
|
||||||
|
+ key_pair = "lab3-key"
|
||||||
|
+ metadata = {
|
||||||
|
+ "created_by" = "terraform"
|
||||||
|
+ "environment" = "dev"
|
||||||
|
+ "product" = "Ubuntu 20.04"
|
||||||
|
+ "sid" = "ubuntu"
|
||||||
|
}
|
||||||
|
+ name = "lab3-web-2"
|
||||||
|
+ password_data = (known after apply)
|
||||||
|
+ power_state = "active"
|
||||||
|
+ region = (known after apply)
|
||||||
|
+ security_group_ids = (known after apply)
|
||||||
|
+ security_groups = [
|
||||||
|
+ "lab3-secgroup",
|
||||||
|
+ "ssh",
|
||||||
|
]
|
||||||
|
+ stop_before_destroy = false
|
||||||
|
+ user_data = "8a5edf5029cc63b48b259828ca27260a26479651"
|
||||||
|
|
||||||
|
+ block_device {
|
||||||
|
+ boot_index = 0
|
||||||
|
+ delete_on_termination = true
|
||||||
|
+ destination_type = "volume"
|
||||||
|
+ source_type = "image"
|
||||||
|
+ uuid = "371e0707-6700-48d1-97d8-e1a01a443fbf"
|
||||||
|
+ volume_size = 10
|
||||||
|
+ volume_type = "ceph-ssd"
|
||||||
|
}
|
||||||
|
|
||||||
|
+ network {
|
||||||
|
+ access_network = false
|
||||||
|
+ fixed_ip_v4 = "192.168.2.11"
|
||||||
|
+ mac = (known after apply)
|
||||||
|
+ name = (known after apply)
|
||||||
|
+ port = (known after apply)
|
||||||
|
+ uuid = (known after apply)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# vkcs_compute_keypair.my_key will be created
|
||||||
|
+ resource "vkcs_compute_keypair" "my_key" {
|
||||||
|
+ fingerprint = (known after apply)
|
||||||
|
+ id = (known after apply)
|
||||||
|
+ name = "lab3-key"
|
||||||
|
+ private_key = (sensitive value)
|
||||||
|
+ public_key = <<-EOT
|
||||||
|
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCpR6b3KEkuT5Y/lWNXvD/MR0z10FKUJbSKgeVIsHxyrLm4gSk1WjobE4gH9OqXOn3r5JmTiGv0hWBACy2xBMZwnrsxgJtTSzPmYCJTln9zr/b7TFOijmB9qh/2pV5m+HPvKOZUiXCvfa9yOxmB0Thpud8ANzkgFgyT+MvaHQrEhDj6XJui3di7r+7DEHN7bCb9VWWFnAswbOxMWdtoxNMcVN1GYvtRqc/1qxSG0Qs4Ph748zhJFQAaFuu7MTZQsjhBIWF3dy5i0MIqsICTzSPayMEtrt+xCxYMEJSn1jUZrvQpkOe++jW181LVi56xnVazMe4VcRA1YYXo78OQQZGeHl3o9QjO2WhNwel1o+zU8DpD6gIay0heipQlcQZr92B7OI1XPpf8iXqqOYcC3U0e7ZqG9o0oJGO4vrp/wkL5bjMAvjnYtg7rta6fl/R0onrWVnIP3CzoaKBqjpdSnuR5s3kG+BSA2INJA6t+xdNN5cL0Gw6Xd5Hq8/XgaBSBJM0= kirill@WhiteRaven
|
||||||
|
EOT
|
||||||
|
+ region = (known after apply)
|
||||||
|
}
|
||||||
|
|
||||||
|
# vkcs_lb_listener.http will be created
|
||||||
|
+ resource "vkcs_lb_listener" "http" {
|
||||||
|
+ admin_state_up = true
|
||||||
|
+ allowed_cidrs = (known after apply)
|
||||||
|
+ connection_limit = (known after apply)
|
||||||
|
+ default_pool_id = (known after apply)
|
||||||
|
+ id = (known after apply)
|
||||||
|
+ loadbalancer_id = (known after apply)
|
||||||
|
+ name = "lab3-listener"
|
||||||
|
+ protocol = "HTTP"
|
||||||
|
+ protocol_port = 80
|
||||||
|
+ region = (known after apply)
|
||||||
|
+ timeout_client_data = (known after apply)
|
||||||
|
+ timeout_member_connect = (known after apply)
|
||||||
|
+ timeout_member_data = (known after apply)
|
||||||
|
+ timeout_tcp_inspect = (known after apply)
|
||||||
|
}
|
||||||
|
|
||||||
|
# vkcs_lb_loadbalancer.main will be created
|
||||||
|
+ resource "vkcs_lb_loadbalancer" "main" {
|
||||||
|
+ admin_state_up = true
|
||||||
|
+ id = (known after apply)
|
||||||
|
+ name = "lab3-lb"
|
||||||
|
+ region = (known after apply)
|
||||||
|
+ security_group_ids = (known after apply)
|
||||||
|
+ vip_address = (known after apply)
|
||||||
|
+ vip_network_id = (known after apply)
|
||||||
|
+ vip_port_id = (known after apply)
|
||||||
|
+ vip_subnet_id = (known after apply)
|
||||||
|
}
|
||||||
|
|
||||||
|
# vkcs_lb_member.web[0] will be created
|
||||||
|
+ resource "vkcs_lb_member" "web" {
|
||||||
|
+ address = "192.168.2.10"
|
||||||
|
+ admin_state_up = true
|
||||||
|
+ id = (known after apply)
|
||||||
|
+ pool_id = (known after apply)
|
||||||
|
+ protocol_port = 80
|
||||||
|
+ region = (known after apply)
|
||||||
|
+ subnet_id = (known after apply)
|
||||||
|
+ weight = (known after apply)
|
||||||
|
}
|
||||||
|
|
||||||
|
# vkcs_lb_member.web[1] will be created
|
||||||
|
+ resource "vkcs_lb_member" "web" {
|
||||||
|
+ address = "192.168.2.11"
|
||||||
|
+ admin_state_up = true
|
||||||
|
+ id = (known after apply)
|
||||||
|
+ pool_id = (known after apply)
|
||||||
|
+ protocol_port = 80
|
||||||
|
+ region = (known after apply)
|
||||||
|
+ subnet_id = (known after apply)
|
||||||
|
+ weight = (known after apply)
|
||||||
|
}
|
||||||
|
|
||||||
|
# vkcs_lb_monitor.web will be created
|
||||||
|
+ resource "vkcs_lb_monitor" "web" {
|
||||||
|
+ admin_state_up = true
|
||||||
|
+ delay = 10
|
||||||
|
+ expected_codes = (known after apply)
|
||||||
|
+ http_method = (known after apply)
|
||||||
|
+ id = (known after apply)
|
||||||
|
+ max_retries = 3
|
||||||
|
+ max_retries_down = (known after apply)
|
||||||
|
+ pool_id = (known after apply)
|
||||||
|
+ region = (known after apply)
|
||||||
|
+ timeout = 5
|
||||||
|
+ type = "HTTP"
|
||||||
|
+ url_path = "/"
|
||||||
|
}
|
||||||
|
|
||||||
|
# vkcs_lb_pool.web will be created
|
||||||
|
+ resource "vkcs_lb_pool" "web" {
|
||||||
|
+ admin_state_up = true
|
||||||
|
+ id = (known after apply)
|
||||||
|
+ lb_method = "ROUND_ROBIN"
|
||||||
|
+ listener_id = (known after apply)
|
||||||
|
+ name = "lab3-pool"
|
||||||
|
+ protocol = "HTTP"
|
||||||
|
+ region = (known after apply)
|
||||||
|
|
||||||
|
+ persistence (known after apply)
|
||||||
|
}
|
||||||
|
|
||||||
|
# vkcs_networking_floatingip.bastion will be created
|
||||||
|
+ resource "vkcs_networking_floatingip" "bastion" {
|
||||||
|
+ address = (known after apply)
|
||||||
|
+ fixed_ip = (known after apply)
|
||||||
|
+ id = (known after apply)
|
||||||
|
+ pool = "internet"
|
||||||
|
+ port_id = (known after apply)
|
||||||
|
+ region = (known after apply)
|
||||||
|
+ sdn = (known after apply)
|
||||||
|
+ subnet_id = (known after apply)
|
||||||
|
}
|
||||||
|
|
||||||
|
# vkcs_networking_floatingip.lb will be created
|
||||||
|
+ resource "vkcs_networking_floatingip" "lb" {
|
||||||
|
+ address = (known after apply)
|
||||||
|
+ fixed_ip = (known after apply)
|
||||||
|
+ id = (known after apply)
|
||||||
|
+ pool = "internet"
|
||||||
|
+ port_id = (known after apply)
|
||||||
|
+ region = (known after apply)
|
||||||
|
+ sdn = (known after apply)
|
||||||
|
+ subnet_id = (known after apply)
|
||||||
|
}
|
||||||
|
|
||||||
|
# vkcs_networking_floatingip_associate.bastion will be created
|
||||||
|
+ resource "vkcs_networking_floatingip_associate" "bastion" {
|
||||||
|
+ fixed_ip = (known after apply)
|
||||||
|
+ floating_ip = (known after apply)
|
||||||
|
+ id = (known after apply)
|
||||||
|
+ port_id = (known after apply)
|
||||||
|
+ region = (known after apply)
|
||||||
|
+ sdn = (known after apply)
|
||||||
|
}
|
||||||
|
|
||||||
|
# vkcs_networking_floatingip_associate.lb will be created
|
||||||
|
+ resource "vkcs_networking_floatingip_associate" "lb" {
|
||||||
|
+ fixed_ip = (known after apply)
|
||||||
|
+ floating_ip = (known after apply)
|
||||||
|
+ id = (known after apply)
|
||||||
|
+ port_id = (known after apply)
|
||||||
|
+ region = (known after apply)
|
||||||
|
+ sdn = (known after apply)
|
||||||
|
}
|
||||||
|
|
||||||
|
# vkcs_networking_network.main will be created
|
||||||
|
+ resource "vkcs_networking_network" "main" {
|
||||||
|
+ admin_state_up = true
|
||||||
|
+ all_tags = (known after apply)
|
||||||
|
+ id = (known after apply)
|
||||||
|
+ name = "lab3-network"
|
||||||
|
+ port_security_enabled = true
|
||||||
|
+ private_dns_domain = (known after apply)
|
||||||
|
+ region = (known after apply)
|
||||||
|
+ sdn = "sprut"
|
||||||
|
}
|
||||||
|
|
||||||
|
# vkcs_networking_router_interface.private will be created
|
||||||
|
+ resource "vkcs_networking_router_interface" "private" {
|
||||||
|
+ id = (known after apply)
|
||||||
|
+ port_id = (known after apply)
|
||||||
|
+ region = (known after apply)
|
||||||
|
+ router_id = "913bdd47-9155-45b2-b404-5c10d0086132"
|
||||||
|
+ sdn = (known after apply)
|
||||||
|
+ subnet_id = (known after apply)
|
||||||
|
}
|
||||||
|
|
||||||
|
# vkcs_networking_router_interface.public will be created
|
||||||
|
+ resource "vkcs_networking_router_interface" "public" {
|
||||||
|
+ id = (known after apply)
|
||||||
|
+ port_id = (known after apply)
|
||||||
|
+ region = (known after apply)
|
||||||
|
+ router_id = "913bdd47-9155-45b2-b404-5c10d0086132"
|
||||||
|
+ sdn = (known after apply)
|
||||||
|
+ subnet_id = (known after apply)
|
||||||
|
}
|
||||||
|
|
||||||
|
# vkcs_networking_secgroup.main will be created
|
||||||
|
+ resource "vkcs_networking_secgroup" "main" {
|
||||||
|
+ all_tags = (known after apply)
|
||||||
|
+ description = "Security group for monitoring lab"
|
||||||
|
+ id = (known after apply)
|
||||||
|
+ name = "lab3-secgroup"
|
||||||
|
+ region = (known after apply)
|
||||||
|
+ sdn = (known after apply)
|
||||||
|
}
|
||||||
|
|
||||||
|
# vkcs_networking_secgroup_rule.egress will be created
|
||||||
|
+ resource "vkcs_networking_secgroup_rule" "egress" {
|
||||||
|
+ direction = "egress"
|
||||||
|
+ ethertype = "IPv4"
|
||||||
|
+ id = (known after apply)
|
||||||
|
+ port_range_max = (known after apply)
|
||||||
|
+ port_range_min = (known after apply)
|
||||||
|
+ protocol = (known after apply)
|
||||||
|
+ region = (known after apply)
|
||||||
|
+ remote_group_id = (known after apply)
|
||||||
|
+ remote_ip_prefix = "0.0.0.0/0"
|
||||||
|
+ sdn = (known after apply)
|
||||||
|
+ security_group_id = (known after apply)
|
||||||
|
}
|
||||||
|
|
||||||
|
# vkcs_networking_secgroup_rule.grafana will be created
|
||||||
|
+ resource "vkcs_networking_secgroup_rule" "grafana" {
|
||||||
|
+ direction = "ingress"
|
||||||
|
+ ethertype = "IPv4"
|
||||||
|
+ id = (known after apply)
|
||||||
|
+ port_range_max = 3000
|
||||||
|
+ port_range_min = 3000
|
||||||
|
+ protocol = "tcp"
|
||||||
|
+ region = (known after apply)
|
||||||
|
+ remote_group_id = (known after apply)
|
||||||
|
+ remote_ip_prefix = "0.0.0.0/0"
|
||||||
|
+ sdn = (known after apply)
|
||||||
|
+ security_group_id = (known after apply)
|
||||||
|
}
|
||||||
|
|
||||||
|
# vkcs_networking_secgroup_rule.http will be created
|
||||||
|
+ resource "vkcs_networking_secgroup_rule" "http" {
|
||||||
|
+ direction = "ingress"
|
||||||
|
+ ethertype = "IPv4"
|
||||||
|
+ id = (known after apply)
|
||||||
|
+ port_range_max = 80
|
||||||
|
+ port_range_min = 80
|
||||||
|
+ protocol = "tcp"
|
||||||
|
+ region = (known after apply)
|
||||||
|
+ remote_group_id = (known after apply)
|
||||||
|
+ remote_ip_prefix = "0.0.0.0/0"
|
||||||
|
+ sdn = (known after apply)
|
||||||
|
+ security_group_id = (known after apply)
|
||||||
|
}
|
||||||
|
|
||||||
|
# vkcs_networking_secgroup_rule.node_exporter_private will be created
|
||||||
|
+ resource "vkcs_networking_secgroup_rule" "node_exporter_private" {
|
||||||
|
+ direction = "ingress"
|
||||||
|
+ ethertype = "IPv4"
|
||||||
|
+ id = (known after apply)
|
||||||
|
+ port_range_max = 9100
|
||||||
|
+ port_range_min = 9100
|
||||||
|
+ protocol = "tcp"
|
||||||
|
+ region = (known after apply)
|
||||||
|
+ remote_group_id = (known after apply)
|
||||||
|
+ remote_ip_prefix = "192.168.2.0/24"
|
||||||
|
+ sdn = (known after apply)
|
||||||
|
+ security_group_id = (known after apply)
|
||||||
|
}
|
||||||
|
|
||||||
|
# vkcs_networking_secgroup_rule.node_exporter_public will be created
|
||||||
|
+ resource "vkcs_networking_secgroup_rule" "node_exporter_public" {
|
||||||
|
+ direction = "ingress"
|
||||||
|
+ ethertype = "IPv4"
|
||||||
|
+ id = (known after apply)
|
||||||
|
+ port_range_max = 9100
|
||||||
|
+ port_range_min = 9100
|
||||||
|
+ protocol = "tcp"
|
||||||
|
+ region = (known after apply)
|
||||||
|
+ remote_group_id = (known after apply)
|
||||||
|
+ remote_ip_prefix = "192.168.1.0/24"
|
||||||
|
+ sdn = (known after apply)
|
||||||
|
+ security_group_id = (known after apply)
|
||||||
|
}
|
||||||
|
|
||||||
|
# vkcs_networking_secgroup_rule.prometheus will be created
|
||||||
|
+ resource "vkcs_networking_secgroup_rule" "prometheus" {
|
||||||
|
+ direction = "ingress"
|
||||||
|
+ ethertype = "IPv4"
|
||||||
|
+ id = (known after apply)
|
||||||
|
+ port_range_max = 9090
|
||||||
|
+ port_range_min = 9090
|
||||||
|
+ protocol = "tcp"
|
||||||
|
+ region = (known after apply)
|
||||||
|
+ remote_group_id = (known after apply)
|
||||||
|
+ remote_ip_prefix = "0.0.0.0/0"
|
||||||
|
+ sdn = (known after apply)
|
||||||
|
+ security_group_id = (known after apply)
|
||||||
|
}
|
||||||
|
|
||||||
|
# vkcs_networking_secgroup_rule.ssh will be created
|
||||||
|
+ resource "vkcs_networking_secgroup_rule" "ssh" {
|
||||||
|
+ direction = "ingress"
|
||||||
|
+ ethertype = "IPv4"
|
||||||
|
+ id = (known after apply)
|
||||||
|
+ port_range_max = 22
|
||||||
|
+ port_range_min = 22
|
||||||
|
+ protocol = "tcp"
|
||||||
|
+ region = (known after apply)
|
||||||
|
+ remote_group_id = (known after apply)
|
||||||
|
+ remote_ip_prefix = (sensitive value)
|
||||||
|
+ sdn = (known after apply)
|
||||||
|
+ security_group_id = (known after apply)
|
||||||
|
}
|
||||||
|
|
||||||
|
# vkcs_networking_subnet.private will be created
|
||||||
|
+ resource "vkcs_networking_subnet" "private" {
|
||||||
|
+ all_tags = (known after apply)
|
||||||
|
+ cidr = "192.168.2.0/24"
|
||||||
|
+ dns_nameservers = [
|
||||||
|
+ "8.8.8.8",
|
||||||
|
+ "1.1.1.1",
|
||||||
|
]
|
||||||
|
+ enable_dhcp = true
|
||||||
|
+ enable_private_dns = (known after apply)
|
||||||
|
+ gateway_ip = (known after apply)
|
||||||
|
+ id = (known after apply)
|
||||||
|
+ name = "lab3-private-subnet"
|
||||||
|
+ network_id = (known after apply)
|
||||||
|
+ no_gateway = false
|
||||||
|
+ region = (known after apply)
|
||||||
|
+ sdn = (known after apply)
|
||||||
|
|
||||||
|
+ allocation_pool (known after apply)
|
||||||
|
}
|
||||||
|
|
||||||
|
# vkcs_networking_subnet.public will be created
|
||||||
|
+ resource "vkcs_networking_subnet" "public" {
|
||||||
|
+ all_tags = (known after apply)
|
||||||
|
+ cidr = "192.168.1.0/24"
|
||||||
|
+ dns_nameservers = [
|
||||||
|
+ "8.8.8.8",
|
||||||
|
+ "1.1.1.1",
|
||||||
|
]
|
||||||
|
+ enable_dhcp = true
|
||||||
|
+ enable_private_dns = (known after apply)
|
||||||
|
+ gateway_ip = (known after apply)
|
||||||
|
+ id = (known after apply)
|
||||||
|
+ name = "lab3-public-subnet"
|
||||||
|
+ network_id = (known after apply)
|
||||||
|
+ no_gateway = false
|
||||||
|
+ region = (known after apply)
|
||||||
|
+ sdn = (known after apply)
|
||||||
|
|
||||||
|
+ allocation_pool (known after apply)
|
||||||
|
}
|
||||||
|
|
||||||
|
Plan: 27 to add, 0 to change, 0 to destroy.
|
||||||
|
|
||||||
|
Changes to Outputs:
|
||||||
|
+ bastion_floating_ip = (known after apply)
|
||||||
|
+ grafana_url = (known after apply)
|
||||||
|
+ load_balancer_ip = (known after apply)
|
||||||
|
+ prometheus_url = (known after apply)
|
||||||
|
+ ssh_to_bastion = (known after apply)
|
||||||
|
+ web_private_ips = [
|
||||||
|
+ "192.168.2.10",
|
||||||
|
+ "192.168.2.11",
|
||||||
|
]
|
||||||
|
vkcs_networking_floatingip.lb: Creating...
|
||||||
|
vkcs_networking_secgroup.main: Creating...
|
||||||
|
vkcs_networking_floatingip.bastion: Creating...
|
||||||
|
vkcs_compute_keypair.my_key: Creating...
|
||||||
|
vkcs_networking_network.main: Creating...
|
||||||
|
vkcs_compute_keypair.my_key: Creation complete after 1s [id=lab3-key]
|
||||||
|
vkcs_networking_secgroup.main: Creation complete after 1s [id=b08f9c6d-cb74-40a3-96f9-d9495efb0c32]
|
||||||
|
vkcs_networking_secgroup_rule.egress: Creating...
|
||||||
|
vkcs_networking_secgroup_rule.node_exporter_private: Creating...
|
||||||
|
vkcs_networking_secgroup_rule.http: Creating...
|
||||||
|
vkcs_networking_secgroup_rule.node_exporter_public: Creating...
|
||||||
|
vkcs_networking_secgroup_rule.ssh: Creating...
|
||||||
|
vkcs_networking_secgroup_rule.prometheus: Creating...
|
||||||
|
vkcs_networking_secgroup_rule.grafana: Creating...
|
||||||
|
vkcs_networking_secgroup_rule.egress: Creation complete after 0s [id=5fe8657e-0d40-4d51-906a-a2909ac02600]
|
||||||
|
vkcs_networking_secgroup_rule.node_exporter_private: Creation complete after 1s [id=3bc123fa-7460-4d76-8aee-c8a15f97b747]
|
||||||
|
vkcs_networking_secgroup_rule.node_exporter_public: Creation complete after 1s [id=13b4e677-fd26-4b65-8030-ce0848a37e0d]
|
||||||
|
vkcs_networking_secgroup_rule.http: Creation complete after 2s [id=69b21b5c-19c1-496c-a835-8e2f38a2a984]
|
||||||
|
vkcs_networking_secgroup_rule.prometheus: Creation complete after 3s [id=cc43e762-8174-44eb-ba4c-294123fa7339]
|
||||||
|
vkcs_networking_secgroup_rule.ssh: Creation complete after 3s [id=f4f74676-afbb-4f30-ab30-95b28ca99eb0]
|
||||||
|
vkcs_networking_secgroup_rule.grafana: Creation complete after 4s [id=1e01ebab-58b9-4d7b-bdf0-7dc740e39a47]
|
||||||
|
vkcs_networking_network.main: Creation complete after 7s [id=10ee5854-c2b1-42c2-ab74-c3dea98eaf3a]
|
||||||
|
vkcs_networking_subnet.private: Creating...
|
||||||
|
vkcs_networking_subnet.public: Creating...
|
||||||
|
vkcs_compute_instance.web[0]: Creating...
|
||||||
|
vkcs_compute_instance.web[1]: Creating...
|
||||||
|
vkcs_networking_floatingip.bastion: Creation complete after 8s [id=fa7999fe-a9d9-4035-854e-8fc35491c9b2]
|
||||||
|
vkcs_networking_floatingip.lb: Creation complete after 9s [id=4bef518b-0ab4-410c-a8a1-e2d62beb65d4]
|
||||||
|
vkcs_networking_subnet.private: Creation complete after 7s [id=3b3b8148-a304-46ca-a794-338bfdbddd17]
|
||||||
|
vkcs_networking_subnet.public: Creation complete after 7s [id=23c4ad49-e668-4596-9059-3175fb2cf48d]
|
||||||
|
vkcs_networking_router_interface.public: Creating...
|
||||||
|
vkcs_networking_router_interface.private: Creating...
|
||||||
|
vkcs_lb_loadbalancer.main: Creating...
|
||||||
|
vkcs_compute_instance.web[0]: Still creating... [00m10s elapsed]
|
||||||
|
vkcs_compute_instance.web[1]: Still creating... [00m10s elapsed]
|
||||||
|
vkcs_networking_router_interface.public: Creation complete after 6s [id=06261151-4812-4156-afc5-99e2dbed5fed]
|
||||||
|
vkcs_networking_router_interface.private: Creation complete after 9s [id=cb5f4cf9-87d0-46d9-afe8-f59df9bf5a2f]
|
||||||
|
vkcs_lb_loadbalancer.main: Still creating... [00m10s elapsed]
|
||||||
|
vkcs_compute_instance.web[0]: Still creating... [00m20s elapsed]
|
||||||
|
vkcs_compute_instance.web[1]: Still creating... [00m20s elapsed]
|
||||||
|
vkcs_lb_loadbalancer.main: Still creating... [00m20s elapsed]
|
||||||
|
vkcs_compute_instance.web[1]: Still creating... [00m30s elapsed]
|
||||||
|
vkcs_compute_instance.web[0]: Still creating... [00m30s elapsed]
|
||||||
|
vkcs_lb_loadbalancer.main: Still creating... [00m30s elapsed]
|
||||||
|
vkcs_compute_instance.web[0]: Still creating... [00m40s elapsed]
|
||||||
|
vkcs_compute_instance.web[1]: Still creating... [00m40s elapsed]
|
||||||
|
vkcs_lb_loadbalancer.main: Still creating... [00m40s elapsed]
|
||||||
|
vkcs_compute_instance.web[1]: Creation complete after 48s [id=7e85fd67-cada-4c87-a04c-0a2eab2e0182]
|
||||||
|
vkcs_compute_instance.web[0]: Creation complete after 48s [id=a8c92f02-ecaa-47d9-96c0-9baceaccc474]
|
||||||
|
vkcs_compute_instance.bastion: Creating...
|
||||||
|
vkcs_lb_loadbalancer.main: Still creating... [00m50s elapsed]
|
||||||
|
vkcs_compute_instance.bastion: Still creating... [00m10s elapsed]
|
||||||
|
vkcs_lb_loadbalancer.main: Still creating... [01m00s elapsed]
|
||||||
|
vkcs_compute_instance.bastion: Still creating... [00m20s elapsed]
|
||||||
|
vkcs_lb_loadbalancer.main: Still creating... [01m10s elapsed]
|
||||||
|
vkcs_compute_instance.bastion: Still creating... [00m30s elapsed]
|
||||||
|
vkcs_lb_loadbalancer.main: Still creating... [01m20s elapsed]
|
||||||
|
vkcs_compute_instance.bastion: Still creating... [00m40s elapsed]
|
||||||
|
vkcs_compute_instance.bastion: Creation complete after 46s [id=26161275-fc57-459e-b91d-94cac4a927a4]
|
||||||
|
vkcs_networking_floatingip_associate.bastion: Creating...
|
||||||
|
vkcs_networking_floatingip_associate.bastion: Creation complete after 1s [id=fa7999fe-a9d9-4035-854e-8fc35491c9b2]
|
||||||
|
vkcs_lb_loadbalancer.main: Still creating... [01m30s elapsed]
|
||||||
|
vkcs_lb_loadbalancer.main: Still creating... [01m40s elapsed]
|
||||||
|
vkcs_lb_loadbalancer.main: Still creating... [01m50s elapsed]
|
||||||
|
vkcs_lb_loadbalancer.main: Still creating... [02m00s elapsed]
|
||||||
|
vkcs_lb_loadbalancer.main: Still creating... [02m10s elapsed]
|
||||||
|
vkcs_lb_loadbalancer.main: Still creating... [02m20s elapsed]
|
||||||
|
vkcs_lb_loadbalancer.main: Still creating... [02m30s elapsed]
|
||||||
|
vkcs_lb_loadbalancer.main: Creation complete after 2m34s [id=12d3ddc4-e58d-48a0-87bf-b4a1c7b162eb]
|
||||||
|
vkcs_networking_floatingip_associate.lb: Creating...
|
||||||
|
vkcs_lb_listener.http: Creating...
|
||||||
|
vkcs_networking_floatingip_associate.lb: Creation complete after 1s [id=4bef518b-0ab4-410c-a8a1-e2d62beb65d4]
|
||||||
|
vkcs_lb_listener.http: Still creating... [00m10s elapsed]
|
||||||
|
vkcs_lb_listener.http: Creation complete after 18s [id=3b6c6cd2-aa9c-4d5e-a183-932c036df7c9]
|
||||||
|
vkcs_lb_pool.web: Creating...
|
||||||
|
vkcs_lb_pool.web: Still creating... [00m10s elapsed]
|
||||||
|
vkcs_lb_pool.web: Still creating... [00m20s elapsed]
|
||||||
|
vkcs_lb_pool.web: Still creating... [00m30s elapsed]
|
||||||
|
vkcs_lb_pool.web: Creation complete after 30s [id=144fc519-3e95-4864-a27b-70d6a625b1dd]
|
||||||
|
vkcs_lb_member.web[0]: Creating...
|
||||||
|
vkcs_lb_member.web[1]: Creating...
|
||||||
|
vkcs_lb_monitor.web: Creating...
|
||||||
|
vkcs_lb_member.web[1]: Still creating... [00m10s elapsed]
|
||||||
|
vkcs_lb_member.web[0]: Still creating... [00m10s elapsed]
|
||||||
|
vkcs_lb_monitor.web: Still creating... [00m10s elapsed]
|
||||||
|
vkcs_lb_member.web[1]: Creation complete after 11s [id=2ec0fdc9-b5d1-4e90-89b4-8a226e9b80d4]
|
||||||
|
vkcs_lb_monitor.web: Creation complete after 11s [id=86ca425f-ce18-4401-84d5-1b425eaa8a09]
|
||||||
|
vkcs_lb_member.web[0]: Creation complete after 20s [id=44125250-7888-4aa0-9204-9b26374a0e14]
|
||||||
|
╷
|
||||||
|
│ Warning: Argument is deprecated
|
||||||
|
│
|
||||||
|
│ with vkcs_compute_instance.web[0],
|
||||||
|
│ on VKC_LR_03_monitoring_main_РемизовКЛ_20260618.tf line 155, in resource "vkcs_compute_instance" "web":
|
||||||
|
│ 155: security_groups = ["ssh", vkcs_networking_secgroup.main.name]
|
||||||
|
│
|
||||||
|
│ Configure `security_group_ids` instead.
|
||||||
|
│
|
||||||
|
│ (and 5 more similar warnings elsewhere)
|
||||||
|
╵
|
||||||
|
|
||||||
|
Apply complete! Resources: 27 added, 0 changed, 0 destroyed.
|
||||||
|
|
||||||
|
Outputs:
|
||||||
|
|
||||||
|
bastion_floating_ip = "95.163.215.149"
|
||||||
|
grafana_url = "http://95.163.215.149:3000"
|
||||||
|
load_balancer_ip = "95.163.214.163"
|
||||||
|
prometheus_url = "http://95.163.215.149:9090"
|
||||||
|
ssh_to_bastion = "ssh -i ~/.ssh/id_rsa ubuntu@95.163.215.149"
|
||||||
|
web_private_ips = [
|
||||||
|
"192.168.2.10",
|
||||||
|
"192.168.2.11",
|
||||||
|
]
|
||||||
|
After Width: | Height: | Size: 93 KiB |
|
After Width: | Height: | Size: 150 KiB |
|
After Width: | Height: | Size: 125 KiB |
|
After Width: | Height: | Size: 40 KiB |
@@ -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
|
||||||
|
|
||||||
|
After Width: | Height: | Size: 73 KiB |
|
After Width: | Height: | Size: 30 KiB |
|
After Width: | Height: | Size: 104 KiB |
@@ -0,0 +1,56 @@
|
|||||||
|
~/rosatom/final_asessment_terraform
|
||||||
|
nix-shell ❯ ab -n 1000 -c 10 http://95.163.213.173/DevOps via 💠 default on ☁️ (ru-msk)
|
||||||
|
This is ApacheBench, Version 2.3 <$Revision: 1923142 $>
|
||||||
|
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
|
||||||
|
Licensed to The Apache Software Foundation, http://www.apache.org/
|
||||||
|
|
||||||
|
Benchmarking 95.163.213.173 (be patient)
|
||||||
|
Completed 100 requests
|
||||||
|
Completed 200 requests
|
||||||
|
Completed 300 requests
|
||||||
|
Completed 400 requests
|
||||||
|
Completed 500 requests
|
||||||
|
Completed 600 requests
|
||||||
|
Completed 700 requests
|
||||||
|
Completed 800 requests
|
||||||
|
Completed 900 requests
|
||||||
|
Completed 1000 requests
|
||||||
|
Finished 1000 requests
|
||||||
|
|
||||||
|
|
||||||
|
Server Software: gunicorn
|
||||||
|
Server Hostname: 95.163.213.173
|
||||||
|
Server Port: 80
|
||||||
|
|
||||||
|
Document Path: /DevOps
|
||||||
|
Document Length: 10796 bytes
|
||||||
|
|
||||||
|
Concurrency Level: 10
|
||||||
|
Time taken for tests: 13.065 seconds
|
||||||
|
Complete requests: 1000
|
||||||
|
Failed requests: 1
|
||||||
|
(Connect: 0, Receive: 0, Length: 1, Exceptions: 0)
|
||||||
|
Total transferred: 10922067 bytes
|
||||||
|
HTML transferred: 10785204 bytes
|
||||||
|
Requests per second: 76.54 [#/sec] (mean)
|
||||||
|
Time per request: 130.653 [ms] (mean)
|
||||||
|
Time per request: 13.065 [ms] (mean, across all concurrent requests)
|
||||||
|
Transfer rate: 816.36 [Kbytes/sec] received
|
||||||
|
|
||||||
|
Connection Times (ms)
|
||||||
|
min mean[+/-sd] median max
|
||||||
|
Connect: 0 0 0.1 0 1
|
||||||
|
Processing: 25 114 334.8 62 5001
|
||||||
|
Waiting: 0 105 296.8 57 4156
|
||||||
|
Total: 25 114 334.8 62 5001
|
||||||
|
|
||||||
|
Percentage of the requests served within a certain time (ms)
|
||||||
|
50% 62
|
||||||
|
66% 73
|
||||||
|
75% 79
|
||||||
|
80% 83
|
||||||
|
90% 95
|
||||||
|
95% 113
|
||||||
|
98% 1114
|
||||||
|
99% 2100
|
||||||
|
100% 5001 (longest request)
|
||||||
@@ -0,0 +1,266 @@
|
|||||||
|
~/r/final_assessment/terraform on main [?ok]
|
||||||
|
nix-shell ❯ curl -v http://95.163.213.173/DevOps via 💠 default on ☁️ (ru-msk)
|
||||||
|
* Trying 95.163.213.173:80...
|
||||||
|
* Established connection to 95.163.213.173 (95.163.213.173 port 80) from 198.18.0.1 port 57226
|
||||||
|
* using HTTP/1.x
|
||||||
|
> GET /DevOps HTTP/1.1
|
||||||
|
> Host: 95.163.213.173
|
||||||
|
> User-Agent: curl/8.20.0
|
||||||
|
> Accept: */*
|
||||||
|
>
|
||||||
|
* Request completely sent off
|
||||||
|
< HTTP/1.1 200 OK
|
||||||
|
< server: gunicorn
|
||||||
|
< date: Sun, 28 Jun 2026 10:29:17 GMT
|
||||||
|
< content-type: text/html; charset=utf-8
|
||||||
|
< content-length: 10796
|
||||||
|
<
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="ru">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Кирилл Ремизов</title>
|
||||||
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
||||||
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap">
|
||||||
|
<link rel="stylesheet" href="/static/css/style.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<!-- Шапка с фото и контактами -->
|
||||||
|
<div class="header">
|
||||||
|
<div class="photo-section">
|
||||||
|
<div class="photo-slider" id="photoSlider">
|
||||||
|
<!-- Фотографии будут добавлены через JavaScript -->
|
||||||
|
</div>
|
||||||
|
<div class="slider-controls" id="sliderControls">
|
||||||
|
<!-- Точки управления слайдером будут добавлены через JavaScript -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="info-section">
|
||||||
|
<h1>Ремизов Кирилл Львович</h1>
|
||||||
|
<div class="subtitle">Интересующее направление: SRE/DevOps инженер</div>
|
||||||
|
|
||||||
|
<p>Студент 3 курса ННГУ им. Лобачевского по направлению "Программная инженерия" (Средний бал: 3,85). Стремлюсь к профессиональному росту: изучаю новые технологии, алгоритмы и подходы к разработке. Как молодой специалист, подхожу к работе с энтузиазмом и готов вкладываться в сложные проекты.</p>
|
||||||
|
|
||||||
|
<div class="contacts">
|
||||||
|
<div class="contact-item">
|
||||||
|
<div class="contact-icon">
|
||||||
|
<i class="fas fa-phone"></i>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div><a href="tel:+79051932953">+7 (905) 193-29-53</a></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="contact-item">
|
||||||
|
<div class="contact-icon">
|
||||||
|
<i class="fas fa-envelope"></i>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div><a href="mailto:remizov.kirill2005@yandex.ru">remizov.kirill2005@yandex.ru</a></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="contact-item">
|
||||||
|
<div class="contact-icon">
|
||||||
|
<i class="fab fa-telegram"></i>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div><a href="https://t.me/simpleRussianProger" target="_blank">@simpleRussianProger</a></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="contact-item">
|
||||||
|
<div class="contact-icon">
|
||||||
|
<i class="fab fa-github"></i>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div><a href="https://github.com/BlackCorbeau" target="_blank">BlackCorbeau (GitHub)</a></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="contact-item">
|
||||||
|
<div class="contact-icon">
|
||||||
|
<i class="fab fa-git-alt"></i>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div><a href="https://git.rustprogersteam.ru/Black_Raven" target="_blank">RemizovKL (Forgejo)</a></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
<!-- Левая колонка -->
|
||||||
|
<div class="left-column">
|
||||||
|
<!-- Образование -->
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-title">
|
||||||
|
<i class="fas fa-graduation-cap"></i>
|
||||||
|
<span>Образование</span>
|
||||||
|
</div>
|
||||||
|
<p><strong>2023–2027 ННГУ им. Лобачевского</strong>, Нижний Новгород</p>
|
||||||
|
<p style="color: var(--text-muted); margin-top: 5px;">Программная инженерия</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Достижения -->
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-title">
|
||||||
|
<i class="fas fa-trophy"></i>
|
||||||
|
<span>Достижения</span>
|
||||||
|
</div>
|
||||||
|
<p><strong>2025</strong> Участие в хакатоне от IT-холдинга Т1, 3-е место.</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Языки -->
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-title">
|
||||||
|
<i class="fas fa-globe"></i>
|
||||||
|
<span>Языки</span>
|
||||||
|
</div>
|
||||||
|
<ul class="list">
|
||||||
|
<li>Английский (B2)</li>
|
||||||
|
<li>Французский (разговорный)</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Soft Skills -->
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-title">
|
||||||
|
<i class="fas fa-users"></i>
|
||||||
|
<span>Soft Skills</span>
|
||||||
|
</div>
|
||||||
|
<ul class="list">
|
||||||
|
<li>Ответственный и пунктуальный</li>
|
||||||
|
<li>Любовь к своему делу</li>
|
||||||
|
<li>Умение работать в команде</li>
|
||||||
|
<li>Открыт к обмену опытом</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Правая колонка -->
|
||||||
|
<div class="right-column">
|
||||||
|
<!-- Технические навыки -->
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-title">
|
||||||
|
<i class="fas fa-cogs"></i>
|
||||||
|
<span>Технические навыки</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="skill-item">
|
||||||
|
<div class="skill-header">
|
||||||
|
<span>C++</span>
|
||||||
|
<span>5/5</span>
|
||||||
|
</div>
|
||||||
|
<div class="skill-bar">
|
||||||
|
<div class="skill-level" style="width: 100%;"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="skill-item">
|
||||||
|
<div class="skill-header">
|
||||||
|
<span>Rust</span>
|
||||||
|
<span>4/5</span>
|
||||||
|
</div>
|
||||||
|
<div class="skill-bar">
|
||||||
|
<div class="skill-level" style="width: 80%;"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="skill-item">
|
||||||
|
<div class="skill-header">
|
||||||
|
<span>SQL</span>
|
||||||
|
<span>3/5</span>
|
||||||
|
</div>
|
||||||
|
<div class="skill-bar">
|
||||||
|
<div class="skill-level" style="width: 60%;"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="skill-item">
|
||||||
|
<div class="skill-header">
|
||||||
|
<span>Python</span>
|
||||||
|
<span>2/5</span>
|
||||||
|
</div>
|
||||||
|
<div class="skill-bar">
|
||||||
|
<div class="skill-level" style="width: 40%;"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="skill-item">
|
||||||
|
<div class="skill-header">
|
||||||
|
<span>CI/CD</span>
|
||||||
|
<span>5/5</span>
|
||||||
|
</div>
|
||||||
|
<div class="skill-bar">
|
||||||
|
<div class="skill-level" style="width: 100%;"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="skill-item">
|
||||||
|
<div class="skill-header">
|
||||||
|
<span>Linux</span>
|
||||||
|
<span>5/5</span>
|
||||||
|
</div>
|
||||||
|
<div class="skill-bar">
|
||||||
|
<div class="skill-level" style="width: 100%;"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="skill-item">
|
||||||
|
<div class="skill-header">
|
||||||
|
<span>Docker</span>
|
||||||
|
<span>5/5</span>
|
||||||
|
</div>
|
||||||
|
<div class="skill-bar">
|
||||||
|
<div class="skill-level" style="width: 100%;"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Профессиональные навыки -->
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-title">
|
||||||
|
<i class="fas fa-tools"></i>
|
||||||
|
<span>Профессиональные навыки</span>
|
||||||
|
</div>
|
||||||
|
<div class="two-column-list">
|
||||||
|
<ul class="list">
|
||||||
|
<li>Работа с терминалом</li>
|
||||||
|
<li>Vim</li>
|
||||||
|
<li>Docker</li>
|
||||||
|
</ul>
|
||||||
|
<ul class="list">
|
||||||
|
<li>Kubernetes</li>
|
||||||
|
<li>*nix системы</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Ссылка на репозиторий -->
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-title">
|
||||||
|
<i class="fas fa-code-branch"></i>
|
||||||
|
<span>Репозиторий проекта</span>
|
||||||
|
</div>
|
||||||
|
<p>Исходный код этого резюме доступны в репозитории:</p>
|
||||||
|
<a href="https://git.rustprogersteam.ru/Black_Raven/MyResume" target="_blank" class="repo-link">
|
||||||
|
<i class="fab fa-git-alt"></i>
|
||||||
|
<span>https://git.rustprogersteam.ru/Black_Raven/MyResume</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="footer">
|
||||||
|
<p><i class="fas fa-heart" style="color: var(--primary);"></i> Обновлено: <span id="currentDate"></span></p>
|
||||||
|
<p style="margin-top: 10px; font-size: 0.8rem;">Стиль вдохновлен Forgejo | Черно-оранжевая цветовая схема</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="/static/js/script.js"></script>
|
||||||
|
</body>
|
||||||
|
* Connection #0 to host 95.163.213.173:80 left intact
|
||||||
|
</html>%
|
||||||
@@ -0,0 +1,138 @@
|
|||||||
|
~/r/final_assessment/terraform on main [ok]
|
||||||
|
nix-shell ❯ scp -i ~/.ssh/id_rsa ~/.ssh/id_rsa ubuntu@95.163.215.1:/home/ubuntu/.ssh/id_rsa via 💠 default on ☁️ (ru-msk)
|
||||||
|
The authenticity of host '95.163.215.1 (95.163.215.1)' can't be established.
|
||||||
|
ED25519 key fingerprint is: SHA256:IhiPDFfSS5rEQ83Sws/pkRp91/BsVD+kiZJwhG6G/H8
|
||||||
|
This key is not known by any other names.
|
||||||
|
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
|
||||||
|
Warning: Permanently added '95.163.215.1' (ED25519) to the list of known hosts.
|
||||||
|
** WARNING: connection is not using a post-quantum key exchange algorithm.
|
||||||
|
** This session may be vulnerable to "store now, decrypt later" attacks.
|
||||||
|
** The server may need to be upgraded. See https://openssh.com/pq.html
|
||||||
|
id_rsa 100% 2602 192.9KB/s 00:00
|
||||||
|
|
||||||
|
~/r/final_assessment/terraform on main [ok]
|
||||||
|
nix-shell ❯ ssh -A -i ~/.ssh/id_rsa ubuntu@95.163.215.1 via 💠 default on ☁️ (ru-msk)
|
||||||
|
** WARNING: connection is not using a post-quantum key exchange algorithm.
|
||||||
|
** This session may be vulnerable to "store now, decrypt later" attacks.
|
||||||
|
** The server may need to be upgraded. See https://openssh.com/pq.html
|
||||||
|
Welcome to Ubuntu 20.04.6 LTS (GNU/Linux 5.4.0-216-generic x86_64)
|
||||||
|
|
||||||
|
* Documentation: https://help.ubuntu.com
|
||||||
|
* Management: https://landscape.canonical.com
|
||||||
|
* Support: https://ubuntu.com/pro
|
||||||
|
|
||||||
|
System information as of Sun Jun 28 10:23:32 UTC 2026
|
||||||
|
|
||||||
|
System load: 0.0 Processes: 101
|
||||||
|
Usage of /: 9.0% of 19.20GB Users logged in: 0
|
||||||
|
Memory usage: 20% IPv4 address for ens3: 192.168.1.10
|
||||||
|
Swap usage: 0%
|
||||||
|
|
||||||
|
|
||||||
|
Expanded Security Maintenance for Infrastructure is not enabled.
|
||||||
|
|
||||||
|
0 updates can be applied immediately.
|
||||||
|
|
||||||
|
128 additional security updates can be applied with ESM Infra.
|
||||||
|
Learn more about enabling ESM Infra service for Ubuntu 20.04 at
|
||||||
|
https://ubuntu.com/20-04
|
||||||
|
|
||||||
|
New release '22.04.5 LTS' available.
|
||||||
|
Run 'do-release-upgrade' to upgrade to it.
|
||||||
|
|
||||||
|
|
||||||
|
Last login: Sun Jun 28 10:11:57 2026 from 95.26.148.233
|
||||||
|
ubuntu@final-assessment-bastion:~$ ssh ubuntu@192.168.2.10 # теперь должно работать
|
||||||
|
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
|
||||||
|
@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
|
||||||
|
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
|
||||||
|
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
|
||||||
|
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
|
||||||
|
It is also possible that a host key has just been changed.
|
||||||
|
The fingerprint for the ECDSA key sent by the remote host is
|
||||||
|
SHA256:zXGSX2Tz1E2gWu5hYFEpl0465z0zTQAR4+3hjRQOQnc.
|
||||||
|
Please contact your system administrator.
|
||||||
|
Add correct host key in /home/ubuntu/.ssh/known_hosts to get rid of this message.
|
||||||
|
Offending ECDSA key in /home/ubuntu/.ssh/known_hosts:1
|
||||||
|
remove with:
|
||||||
|
ssh-keygen -f "/home/ubuntu/.ssh/known_hosts" -R "192.168.2.10"
|
||||||
|
ECDSA host key for 192.168.2.10 has changed and you have requested strict checking.
|
||||||
|
Host key verification failed.
|
||||||
|
ubuntu@final-assessment-bastion:~$ rm ~/.ssh/
|
||||||
|
authorized_keys id_rsa known_hosts
|
||||||
|
ubuntu@final-assessment-bastion:~$ rm ~/.ssh/
|
||||||
|
authorized_keys id_rsa known_hosts
|
||||||
|
ubuntu@final-assessment-bastion:~$ rm ~/.ssh/known_hosts
|
||||||
|
ubuntu@final-assessment-bastion:~$ ssh ubuntu@192.168.2.10 # теперь должно работать
|
||||||
|
The authenticity of host '192.168.2.10 (192.168.2.10)' can't be established.
|
||||||
|
ECDSA key fingerprint is SHA256:zXGSX2Tz1E2gWu5hYFEpl0465z0zTQAR4+3hjRQOQnc.
|
||||||
|
Are you sure you want to continue connecting (yes/no/[fingerprint])? ye
|
||||||
|
Please type 'yes', 'no' or the fingerprint: yes
|
||||||
|
Warning: Permanently added '192.168.2.10' (ECDSA) to the list of known hosts.
|
||||||
|
Welcome to Ubuntu 20.04.6 LTS (GNU/Linux 5.4.0-216-generic x86_64)
|
||||||
|
|
||||||
|
* Documentation: https://help.ubuntu.com
|
||||||
|
* Management: https://landscape.canonical.com
|
||||||
|
* Support: https://ubuntu.com/pro
|
||||||
|
|
||||||
|
System information as of Sun Jun 28 10:24:27 UTC 2026
|
||||||
|
|
||||||
|
System load: 0.48 Processes: 115
|
||||||
|
Usage of /: 22.8% of 9.51GB Users logged in: 0
|
||||||
|
Memory usage: 33% IPv4 address for ens3: 192.168.2.10
|
||||||
|
Swap usage: 0%
|
||||||
|
|
||||||
|
|
||||||
|
Expanded Security Maintenance for Infrastructure is not enabled.
|
||||||
|
|
||||||
|
1 update can be applied immediately.
|
||||||
|
1 of these updates is a standard security update.
|
||||||
|
To see these additional updates run: apt list --upgradable
|
||||||
|
|
||||||
|
129 additional security updates can be applied with ESM Infra.
|
||||||
|
Learn more about enabling ESM Infra service for Ubuntu 20.04 at
|
||||||
|
https://ubuntu.com/20-04
|
||||||
|
|
||||||
|
|
||||||
|
ubuntu@final-assessment-web-1:~$ sudo docker ps
|
||||||
|
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||||
|
365edf425ac4 git.rustprogersteam.ru/black_raven/myresume/resume:latest "gunicorn app:app -b…" About a minute ago Up About a minute 0.0.0.0:80->80/tcp, :::80->80/tcp upbeat_northcutt
|
||||||
|
ubuntu@final-assessment-web-1:~$ exit
|
||||||
|
logout
|
||||||
|
Connection to 192.168.2.10 closed.
|
||||||
|
ubuntu@final-assessment-bastion:~$ ssh ubuntu@192.168.2.11 # теперь должно работать
|
||||||
|
The authenticity of host '192.168.2.11 (192.168.2.11)' can't be established.
|
||||||
|
ECDSA key fingerprint is SHA256:NZ7FTKC5HtwQkpRs/4J4IPKzaQB5vEX0TRKZ5+t0hMI.
|
||||||
|
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
|
||||||
|
Warning: Permanently added '192.168.2.11' (ECDSA) to the list of known hosts.
|
||||||
|
Welcome to Ubuntu 20.04.6 LTS (GNU/Linux 5.4.0-216-generic x86_64)
|
||||||
|
|
||||||
|
* Documentation: https://help.ubuntu.com
|
||||||
|
* Management: https://landscape.canonical.com
|
||||||
|
* Support: https://ubuntu.com/pro
|
||||||
|
|
||||||
|
System information as of Sun Jun 28 10:25:13 UTC 2026
|
||||||
|
|
||||||
|
System load: 0.18 Processes: 117
|
||||||
|
Usage of /: 22.8% of 9.51GB Users logged in: 0
|
||||||
|
Memory usage: 31% IPv4 address for ens3: 192.168.2.11
|
||||||
|
Swap usage: 0%
|
||||||
|
|
||||||
|
|
||||||
|
Expanded Security Maintenance for Infrastructure is not enabled.
|
||||||
|
|
||||||
|
1 update can be applied immediately.
|
||||||
|
1 of these updates is a standard security update.
|
||||||
|
To see these additional updates run: apt list --upgradable
|
||||||
|
|
||||||
|
129 additional security updates can be applied with ESM Infra.
|
||||||
|
Learn more about enabling ESM Infra service for Ubuntu 20.04 at
|
||||||
|
https://ubuntu.com/20-04
|
||||||
|
|
||||||
|
|
||||||
|
ubuntu@final-assessment-web-2:~$ sudo docker ps
|
||||||
|
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||||
|
540a7f938ba0 git.rustprogersteam.ru/black_raven/myresume/resume:latest "gunicorn app:app -b…" 2 minutes ago Up 2 minutes 0.0.0.0:80->80/tcp, :::80->80/tcp lucid_cerf
|
||||||
|
ubuntu@final-assessment-web-2:~$ exit
|
||||||
|
logout
|
||||||
|
Connection to 192.168.2.11 closed.
|
||||||
|
After Width: | Height: | Size: 89 KiB |
@@ -0,0 +1,11 @@
|
|||||||
|
~/rosatom
|
||||||
|
nix-shell ❯ kubectl get nodes on ☁️ (ru-msk)
|
||||||
|
kubectl get pods --all-namespaces
|
||||||
|
NAME STATUS ROLES AGE VERSION
|
||||||
|
my-k8s-default-group-0 Ready <none> 31m v1.34.2
|
||||||
|
my-k8s-default-group-1 Ready <none> 31m v1.34.2
|
||||||
|
NAMESPACE NAME READY STATUS RESTARTS AGE
|
||||||
|
kube-system calico-node-c97zb 1/1 Running 0 31m
|
||||||
|
kube-system calico-node-nwbw7 1/1 Running 0 31m
|
||||||
|
kube-system csi-cinder-nodeplugin-lwsfs 3/3 Running 0 31m
|
||||||
|
kube-system csi-cinder-nodeplugin-zhdrw 3/3 Running 0 31m
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
~/rosatom/k8s
|
||||||
|
nix-shell ❯ kubectl apply -f deployment.yaml on ☁️ (ru-msk)
|
||||||
|
|
||||||
|
# Проверка
|
||||||
|
kubectl get pods
|
||||||
|
kubectl get services
|
||||||
|
|
||||||
|
# Получение внешнего IP (может занять несколько минут)
|
||||||
|
kubectl get service nginx-service -w
|
||||||
|
deployment.apps/nginx-deployment created
|
||||||
|
service/nginx-service created
|
||||||
|
NAME READY STATUS RESTARTS AGE
|
||||||
|
nginx-deployment-546c8cb74c-65n7l 0/1 Pending 0 0s
|
||||||
|
nginx-deployment-546c8cb74c-mvwvm 0/1 ContainerCreating 0 0s
|
||||||
|
nginx-deployment-546c8cb74c-qmgv4 0/1 Pending 0 0s
|
||||||
|
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
|
||||||
|
kubernetes ClusterIP 10.254.0.1 <none> 443/TCP 35m
|
||||||
|
nginx-service LoadBalancer 10.254.219.88 <pending> 80:31119/TCP 0s
|
||||||
|
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
|
||||||
|
nginx-service LoadBalancer 10.254.219.88 <pending> 80:31119/TCP 0s
|
||||||
|
nginx-service LoadBalancer 10.254.219.88 <pending> 80:31119/TCP 3m9s
|
||||||
|
^C%
|
||||||
|
~/rosatom/k8s
|
||||||
|
nix-shell ❌1 ❯ kubectl get nodes on ☁️ (ru-msk)
|
||||||
|
kubectl get pods --all-namespaces
|
||||||
|
NAME STATUS ROLES AGE VERSION
|
||||||
|
my-k8s-default-group-0 Ready <none> 43m v1.34.2
|
||||||
|
my-k8s-default-group-1 Ready <none> 43m v1.34.2
|
||||||
|
NAMESPACE NAME READY STATUS RESTARTS AGE
|
||||||
|
default nginx-deployment-546c8cb74c-65n7l 1/1 Running 0 8m38s
|
||||||
|
default nginx-deployment-546c8cb74c-mvwvm 1/1 Running 0 8m38s
|
||||||
|
default nginx-deployment-546c8cb74c-qmgv4 1/1 Running 0 8m38s
|
||||||
|
kube-system calico-node-c97zb 1/1 Running 0 43m
|
||||||
|
kube-system calico-node-nwbw7 1/1 Running 0 43m
|
||||||
|
kube-system csi-cinder-nodeplugin-lwsfs 3/3 Running 0 43m
|
||||||
|
kube-system csi-cinder-nodeplugin-zhdrw 3/3 Running 0 43m
|
||||||
|
After Width: | Height: | Size: 62 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 17 KiB |
@@ -0,0 +1,143 @@
|
|||||||
|
~/rosatom
|
||||||
|
nix-shell ❯ export PATH="$HOME/rosatom/packer:$PATH"
|
||||||
|
|
||||||
|
~/rosatom
|
||||||
|
nix-shell ❯ packer --version
|
||||||
|
Packer v1.15.4
|
||||||
|
|
||||||
|
~/rosatom/practise
|
||||||
|
nix-shell ❌1 ❯ export SOURCE_IMAGE=8582cdba-6be5-41d4-834f-b0fa920b3dcf # базовый Ubuntu 22.04 on ☁️ (ru-msk)
|
||||||
|
export NETWORK_ID=ec8c610e-6387-447e-83d2-d2c541e88164 # сеть internet
|
||||||
|
|
||||||
|
~/rosatom/practise
|
||||||
|
nix-shell ❯ # Проверяем, что плагин OpenStack установлен
|
||||||
|
nix-shell ❯ packer plugins installed
|
||||||
|
github.com/hashicorp/openstack v1.1.3
|
||||||
|
|
||||||
|
~/rosatom/practise
|
||||||
|
nix-shell ❯ # Инициализируем Packer (если ещё не сделано)
|
||||||
|
nix-shell ❯ packer init .
|
||||||
|
Installed plugin github.com/hashicorp/openstack v1.1.3 in "/home/kirill/.config/packer/plugins/github.com/hashicorp/openstack/packer-plugin-openstack_v1.1.3_x5.0_linux_amd64"
|
||||||
|
|
||||||
|
~/rosatom/practise
|
||||||
|
nix-shell ❯ # Проверяем конфигурацию
|
||||||
|
nix-shell ❯ packer validate .
|
||||||
|
The configuration is valid.
|
||||||
|
|
||||||
|
~/rosatom/practise
|
||||||
|
nix-shell ❯ packer build . on ☁️ (ru-msk)
|
||||||
|
openstack.ubuntu-nginx: output will be in this color.
|
||||||
|
|
||||||
|
==> openstack.ubuntu-nginx: Loading flavor: STD3-2-6
|
||||||
|
==> openstack.ubuntu-nginx: Verified flavor. ID: 27acd0b9-4d89-4acc-853c-e3e416704ba0
|
||||||
|
==> openstack.ubuntu-nginx: Using existing SSH private key
|
||||||
|
==> openstack.ubuntu-nginx: Using existing SSH private key
|
||||||
|
==> openstack.ubuntu-nginx: Creating volume...
|
||||||
|
==> openstack.ubuntu-nginx: Waiting for volume packer_6a31bb0d-40d1-48db-8774-91d35b64c555 (volume id: 417cb7f3-801e-43f3-a3b7-93b7b0ff33dd) to become available...
|
||||||
|
==> openstack.ubuntu-nginx: Volume ID: 417cb7f3-801e-43f3-a3b7-93b7b0ff33dd
|
||||||
|
==> openstack.ubuntu-nginx: Launching server...
|
||||||
|
==> openstack.ubuntu-nginx: Launching server...
|
||||||
|
==> openstack.ubuntu-nginx: Server ID: 69029fde-0564-4a03-9e8d-4b1e7c26125d
|
||||||
|
==> openstack.ubuntu-nginx: Waiting for server to become ready...
|
||||||
|
==> openstack.ubuntu-nginx: Floating IP not required
|
||||||
|
==> openstack.ubuntu-nginx: Using SSH communicator to connect: 95.163.214.208
|
||||||
|
==> openstack.ubuntu-nginx: Waiting for SSH to become available...
|
||||||
|
==> openstack.ubuntu-nginx: Connected to SSH!
|
||||||
|
==> openstack.ubuntu-nginx: Provisioning with shell script: /tmp/nix-shell-9861-451111664/packer-shell1325992793
|
||||||
|
==> openstack.ubuntu-nginx: Updating package lists...
|
||||||
|
==> openstack.ubuntu-nginx: Err:1 http://ms1.clouds.archive.ubuntu.com/ubuntu focal InRelease
|
||||||
|
==> openstack.ubuntu-nginx: Temporary failure resolving 'ms1.clouds.archive.ubuntu.com'
|
||||||
|
==> openstack.ubuntu-nginx: Err:2 https://dl.yarnpkg.com/debian stable InRelease
|
||||||
|
==> openstack.ubuntu-nginx: Temporary failure resolving 'dl.yarnpkg.com'
|
||||||
|
==> openstack.ubuntu-nginx: Err:3 http://ms1.clouds.archive.ubuntu.com/ubuntu focal-updates InRelease
|
||||||
|
==> openstack.ubuntu-nginx: Temporary failure resolving 'ms1.clouds.archive.ubuntu.com'
|
||||||
|
==> openstack.ubuntu-nginx: Err:4 http://ms1.clouds.archive.ubuntu.com/ubuntu focal-backports InRelease
|
||||||
|
==> openstack.ubuntu-nginx: Temporary failure resolving 'ms1.clouds.archive.ubuntu.com'
|
||||||
|
==> openstack.ubuntu-nginx: Reading package lists...
|
||||||
|
==> openstack.ubuntu-nginx: W: Failed to fetch http://ms1.clouds.archive.ubuntu.com/ubuntu/dists/focal/InRelease Temporary failure resolving 'ms1.clouds.archive.ubuntu.com'
|
||||||
|
==> openstack.ubuntu-nginx: W: Failed to fetch http://ms1.clouds.archive.ubuntu.com/ubuntu/dists/focal-updates/InRelease Temporary failure resolving 'ms1.clouds.archive.ubuntu.com'
|
||||||
|
==> openstack.ubuntu-nginx: W: Failed to fetch http://ms1.clouds.archive.ubuntu.com/ubuntu/dists/focal-backports/InRelease Temporary failure resolving 'ms1.clouds.archive.ubuntu.com'
|
||||||
|
==> openstack.ubuntu-nginx: W: Failed to fetch https://dl.yarnpkg.com/debian/dists/stable/InRelease Temporary failure resolving 'dl.yarnpkg.com'
|
||||||
|
==> openstack.ubuntu-nginx: Installing nginx...
|
||||||
|
==> openstack.ubuntu-nginx: W: Some index files failed to download. They have been ignored, or old ones used instead.
|
||||||
|
==> openstack.ubuntu-nginx: Reading package lists...
|
||||||
|
==> openstack.ubuntu-nginx: Building dependency tree...
|
||||||
|
==> openstack.ubuntu-nginx: Reading state information...
|
||||||
|
==> openstack.ubuntu-nginx: Synchronizing state of nginx.service with SysV service script with /lib/systemd/systemd-sysv-install.
|
||||||
|
==> openstack.ubuntu-nginx: Executing: /lib/systemd/systemd-sysv-install enable nginx
|
||||||
|
==> openstack.ubuntu-nginx: nginx-core is already the newest version (1.18.0-0ubuntu1.3).
|
||||||
|
==> openstack.ubuntu-nginx: 0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
|
||||||
|
==> openstack.ubuntu-nginx: Configuring nginx...
|
||||||
|
==> openstack.ubuntu-nginx: Creating test page...
|
||||||
|
==> openstack.ubuntu-nginx: <h1>Hello from Packer!</h1>
|
||||||
|
==> openstack.ubuntu-nginx: Cleaning up...
|
||||||
|
==> openstack.ubuntu-nginx: Stopping server: 69029fde-0564-4a03-9e8d-4b1e7c26125d ...
|
||||||
|
==> openstack.ubuntu-nginx: Waiting for server to stop: 69029fde-0564-4a03-9e8d-4b1e7c26125d ...
|
||||||
|
==> openstack.ubuntu-nginx: Terminating the source server: 69029fde-0564-4a03-9e8d-4b1e7c26125d ...
|
||||||
|
==> openstack.ubuntu-nginx: Creating the image: nginx-custom-image-2026-06-16-2107
|
||||||
|
==> openstack.ubuntu-nginx: Image: f69ca872-96a2-40a9-ad31-4e098b0f9b0e
|
||||||
|
==> openstack.ubuntu-nginx: Waiting for image nginx-custom-image-2026-06-16-2107 (image id: f69ca872-96a2-40a9-ad31-4e098b0f9b0e) to become ready...
|
||||||
|
==> openstack.ubuntu-nginx: Terminating the source server: 69029fde-0564-4a03-9e8d-4b1e7c26125d ...
|
||||||
|
==> openstack.ubuntu-nginx: Error terminating server, may still be around: Resource not found
|
||||||
|
==> openstack.ubuntu-nginx: Deleting volume: 417cb7f3-801e-43f3-a3b7-93b7b0ff33dd ...
|
||||||
|
Build 'openstack.ubuntu-nginx' finished after 7 minutes 44 seconds.
|
||||||
|
|
||||||
|
==> Wait completed after 7 minutes 44 seconds
|
||||||
|
|
||||||
|
==> Builds finished. The artifacts of successful builds are:
|
||||||
|
--> openstack.ubuntu-nginx: An image was created: f69ca872-96a2-40a9-ad31-4e098b0f9b0e
|
||||||
|
|
||||||
|
~/rosatom/practise
|
||||||
|
nix-shell ❯ openstack image list | grep nginx-custom
|
||||||
|
| a1b2c3d4-e5f6-7890-abcd-ef1234567890 | nginx-custom-image-2026-06-16-1905 | active |
|
||||||
|
|
||||||
|
~/rosatom/practise
|
||||||
|
nix-shell ❌255 ❯ openstack server create --image nginx-custom-image-2026-06-16-2107 --flavor Basic-1-2-20 --network internet --key-name postgress-test-ViPomgZ4 --security-group all --wait test-nginx
|
||||||
|
+-------------------------------------+---------------------------------------------------------------------------+
|
||||||
|
| Field | Value |
|
||||||
|
+-------------------------------------+---------------------------------------------------------------------------+
|
||||||
|
| OS-DCF:diskConfig | MANUAL |
|
||||||
|
| OS-EXT-AZ:availability_zone | PA2 |
|
||||||
|
| OS-EXT-SRV-ATTR:host | None |
|
||||||
|
| OS-EXT-SRV-ATTR:hostname | None |
|
||||||
|
| OS-EXT-SRV-ATTR:hypervisor_hostname | None |
|
||||||
|
| OS-EXT-SRV-ATTR:instance_name | None |
|
||||||
|
| OS-EXT-SRV-ATTR:kernel_id | None |
|
||||||
|
| OS-EXT-SRV-ATTR:launch_index | None |
|
||||||
|
| OS-EXT-SRV-ATTR:ramdisk_id | None |
|
||||||
|
| OS-EXT-SRV-ATTR:reservation_id | None |
|
||||||
|
| OS-EXT-SRV-ATTR:root_device_name | None |
|
||||||
|
| OS-EXT-SRV-ATTR:user_data | None |
|
||||||
|
| OS-EXT-STS:power_state | Running |
|
||||||
|
| OS-EXT-STS:task_state | None |
|
||||||
|
| OS-EXT-STS:vm_state | active |
|
||||||
|
| OS-SRV-USG:launched_at | 2026-06-16T21:49:42.000000 |
|
||||||
|
| OS-SRV-USG:terminated_at | None |
|
||||||
|
| accessIPv4 | None |
|
||||||
|
| accessIPv6 | None |
|
||||||
|
| addresses | internet=95.163.214.174 |
|
||||||
|
| adminPass | Wu7tLrZ2Lk7T |
|
||||||
|
| config_drive | None |
|
||||||
|
| created | 2026-06-16T21:49:25Z |
|
||||||
|
| description | None |
|
||||||
|
| flavor | Basic-1-2-20 (25ae869c-be29-4840-8e12-99e046d2dbd4) |
|
||||||
|
| hostId | ba4a80c53c9c06dadbed7a2539b950ee3913a902b862acc69260c3bb |
|
||||||
|
| host_status | None |
|
||||||
|
| id | bc7e2f8b-8134-4a47-a554-4b8a1cd87b4f |
|
||||||
|
| image | nginx-custom-image-2026-06-16-2107 (f69ca872-96a2-40a9-ad31-4e098b0f9b0e) |
|
||||||
|
| key_name | postgress-test-ViPomgZ4 |
|
||||||
|
| locked | None |
|
||||||
|
| locked_reason | None |
|
||||||
|
| name | test-nginx |
|
||||||
|
| progress | None |
|
||||||
|
| project_id | 5aa354d05172439abcc5bfc3f682da49 |
|
||||||
|
| properties | None |
|
||||||
|
| security_groups | id='a912406f-2876-4fd9-ad05-23bbdd43a818', name='all', sdn='sprut' |
|
||||||
|
| server_groups | None |
|
||||||
|
| status | ACTIVE |
|
||||||
|
| tags | |
|
||||||
|
| trusted_image_certificates | None |
|
||||||
|
| updated | 2026-06-16T21:49:42Z |
|
||||||
|
| user_id | a9d31b4ea75643f7b64bbeeeb297ae1f |
|
||||||
|
| volumes_attached | |
|
||||||
|
+-------------------------------------+---------------------------------------------------------------------------+
|
||||||
|
After Width: | Height: | Size: 54 KiB |
|
After Width: | Height: | Size: 72 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 179 KiB |
@@ -0,0 +1,319 @@
|
|||||||
|
~/rosatom/terraform6-1
|
||||||
|
nix-shell ❯ terraform apply -auto-approve via 💠 default on ☁️ (ru-msk)
|
||||||
|
There are some problems with the CLI configuration:
|
||||||
|
╷
|
||||||
|
│ Warning: Unable to open CLI configuration file
|
||||||
|
│
|
||||||
|
│ The CLI configuration file at
|
||||||
|
│ "/home/kirill/rosatom/terraform-demo/terraform.rc" does not exist.
|
||||||
|
╵
|
||||||
|
|
||||||
|
data.vkcs_compute_flavor.vm: Reading...
|
||||||
|
data.vkcs_networking_router.router: Reading...
|
||||||
|
data.vkcs_networking_network.extnet: Reading...
|
||||||
|
data.vkcs_images_image.ubuntu: Reading...
|
||||||
|
data.vkcs_images_image.ubuntu: Read complete after 0s [id=371e0707-6700-48d1-97d8-e1a01a443fbf]
|
||||||
|
data.vkcs_networking_router.router: Read complete after 0s [id=913bdd47-9155-45b2-b404-5c10d0086132]
|
||||||
|
data.vkcs_compute_flavor.vm: Read complete after 0s [id=25ae869c-be29-4840-8e12-99e046d2dbd4]
|
||||||
|
data.vkcs_networking_network.extnet: Read complete after 0s [id=ec8c610e-6387-447e-83d2-d2c541e88164]
|
||||||
|
|
||||||
|
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
|
||||||
|
+ create
|
||||||
|
|
||||||
|
Terraform will perform the following actions:
|
||||||
|
|
||||||
|
# vkcs_compute_floatingip_associate.monitoring_fip_assoc will be created
|
||||||
|
+ resource "vkcs_compute_floatingip_associate" "monitoring_fip_assoc" {
|
||||||
|
+ floating_ip = (known after apply)
|
||||||
|
+ id = (known after apply)
|
||||||
|
+ instance_id = (known after apply)
|
||||||
|
+ region = (known after apply)
|
||||||
|
}
|
||||||
|
|
||||||
|
# vkcs_compute_instance.app[0] will be created
|
||||||
|
+ resource "vkcs_compute_instance" "app" {
|
||||||
|
+ access_ip_v4 = (known after apply)
|
||||||
|
+ all_metadata = (known after apply)
|
||||||
|
+ all_tags = (known after apply)
|
||||||
|
+ availability_zone = "MS1"
|
||||||
|
+ flavor_id = "25ae869c-be29-4840-8e12-99e046d2dbd4"
|
||||||
|
+ flavor_name = (known after apply)
|
||||||
|
+ force_delete = false
|
||||||
|
+ id = (known after apply)
|
||||||
|
+ image_id = (known after apply)
|
||||||
|
+ image_name = (known after apply)
|
||||||
|
+ key_pair = "monitoring-key"
|
||||||
|
+ name = "app-vm-1"
|
||||||
|
+ password_data = (known after apply)
|
||||||
|
+ power_state = "active"
|
||||||
|
+ region = (known after apply)
|
||||||
|
+ security_group_ids = (known after apply)
|
||||||
|
+ security_groups = [
|
||||||
|
+ "monitoring-sg",
|
||||||
|
]
|
||||||
|
+ stop_before_destroy = false
|
||||||
|
+ user_data = "f355816eb1f6204d3318b3db355d4625d045ab6f"
|
||||||
|
|
||||||
|
+ block_device {
|
||||||
|
+ boot_index = 0
|
||||||
|
+ delete_on_termination = true
|
||||||
|
+ destination_type = "volume"
|
||||||
|
+ source_type = "image"
|
||||||
|
+ uuid = "371e0707-6700-48d1-97d8-e1a01a443fbf"
|
||||||
|
+ volume_size = 10
|
||||||
|
+ volume_type = "ceph-ssd"
|
||||||
|
}
|
||||||
|
|
||||||
|
+ network {
|
||||||
|
+ access_network = false
|
||||||
|
+ fixed_ip_v4 = (known after apply)
|
||||||
|
+ mac = (known after apply)
|
||||||
|
+ name = (known after apply)
|
||||||
|
+ port = (known after apply)
|
||||||
|
+ uuid = (known after apply)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# vkcs_compute_instance.monitoring will be created
|
||||||
|
+ resource "vkcs_compute_instance" "monitoring" {
|
||||||
|
+ access_ip_v4 = (known after apply)
|
||||||
|
+ all_metadata = (known after apply)
|
||||||
|
+ all_tags = (known after apply)
|
||||||
|
+ availability_zone = "MS1"
|
||||||
|
+ flavor_id = "25ae869c-be29-4840-8e12-99e046d2dbd4"
|
||||||
|
+ flavor_name = (known after apply)
|
||||||
|
+ force_delete = false
|
||||||
|
+ id = (known after apply)
|
||||||
|
+ image_id = (known after apply)
|
||||||
|
+ image_name = (known after apply)
|
||||||
|
+ key_pair = "monitoring-key"
|
||||||
|
+ name = "monitoring-vm"
|
||||||
|
+ password_data = (known after apply)
|
||||||
|
+ power_state = "active"
|
||||||
|
+ region = (known after apply)
|
||||||
|
+ security_group_ids = (known after apply)
|
||||||
|
+ security_groups = [
|
||||||
|
+ "monitoring-sg",
|
||||||
|
]
|
||||||
|
+ stop_before_destroy = false
|
||||||
|
+ user_data = "9ecd690e01cac29a10c58e9563c4ea99a7f8cf15"
|
||||||
|
|
||||||
|
+ block_device {
|
||||||
|
+ boot_index = 0
|
||||||
|
+ delete_on_termination = true
|
||||||
|
+ destination_type = "volume"
|
||||||
|
+ source_type = "image"
|
||||||
|
+ uuid = "371e0707-6700-48d1-97d8-e1a01a443fbf"
|
||||||
|
+ volume_size = 10
|
||||||
|
+ volume_type = "ceph-ssd"
|
||||||
|
}
|
||||||
|
|
||||||
|
+ network {
|
||||||
|
+ access_network = false
|
||||||
|
+ fixed_ip_v4 = (known after apply)
|
||||||
|
+ mac = (known after apply)
|
||||||
|
+ name = (known after apply)
|
||||||
|
+ port = (known after apply)
|
||||||
|
+ uuid = (known after apply)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# vkcs_compute_keypair.monitoring will be created
|
||||||
|
+ resource "vkcs_compute_keypair" "monitoring" {
|
||||||
|
+ fingerprint = (known after apply)
|
||||||
|
+ id = (known after apply)
|
||||||
|
+ name = "monitoring-key"
|
||||||
|
+ private_key = (sensitive value)
|
||||||
|
+ public_key = <<-EOT
|
||||||
|
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCpR6b3KEkuT5Y/lWNXvD/MR0z10FKUJbSKgeVIsHxyrLm4gSk1WjobE4gH9OqXOn3r5JmTiGv0hWBACy2xBMZwnrsxgJtTSzPmYCJTln9zr/b7TFOijmB9qh/2pV5m+HPvKOZUiXCvfa9yOxmB0Thpud8ANzkgFgyT+MvaHQrEhDj6XJui3di7r+7DEHN7bCb9VWWFnAswbOxMWdtoxNMcVN1GYvtRqc/1qxSG0Qs4Ph748zhJFQAaFuu7MTZQsjhBIWF3dy5i0MIqsICTzSPayMEtrt+xCxYMEJSn1jUZrvQpkOe++jW181LVi56xnVazMe4VcRA1YYXo78OQQZGeHl3o9QjO2WhNwel1o+zU8DpD6gIay0heipQlcQZr92B7OI1XPpf8iXqqOYcC3U0e7ZqG9o0oJGO4vrp/wkL5bjMAvjnYtg7rta6fl/R0onrWVnIP3CzoaKBqjpdSnuR5s3kG+BSA2INJA6t+xdNN5cL0Gw6Xd5Hq8/XgaBSBJM0= kirill@WhiteRaven
|
||||||
|
EOT
|
||||||
|
+ region = (known after apply)
|
||||||
|
}
|
||||||
|
|
||||||
|
# vkcs_networking_floatingip.monitoring_fip will be created
|
||||||
|
+ resource "vkcs_networking_floatingip" "monitoring_fip" {
|
||||||
|
+ address = (known after apply)
|
||||||
|
+ fixed_ip = (known after apply)
|
||||||
|
+ id = (known after apply)
|
||||||
|
+ pool = "internet"
|
||||||
|
+ port_id = (known after apply)
|
||||||
|
+ region = (known after apply)
|
||||||
|
+ sdn = (known after apply)
|
||||||
|
+ subnet_id = (known after apply)
|
||||||
|
}
|
||||||
|
|
||||||
|
# vkcs_networking_network.internal will be created
|
||||||
|
+ resource "vkcs_networking_network" "internal" {
|
||||||
|
+ admin_state_up = true
|
||||||
|
+ all_tags = (known after apply)
|
||||||
|
+ id = (known after apply)
|
||||||
|
+ name = "monitoring-internal-net"
|
||||||
|
+ port_security_enabled = true
|
||||||
|
+ private_dns_domain = (known after apply)
|
||||||
|
+ region = (known after apply)
|
||||||
|
+ sdn = "sprut"
|
||||||
|
}
|
||||||
|
|
||||||
|
# vkcs_networking_router_interface.router_interface will be created
|
||||||
|
+ resource "vkcs_networking_router_interface" "router_interface" {
|
||||||
|
+ id = (known after apply)
|
||||||
|
+ port_id = (known after apply)
|
||||||
|
+ region = (known after apply)
|
||||||
|
+ router_id = "913bdd47-9155-45b2-b404-5c10d0086132"
|
||||||
|
+ sdn = (known after apply)
|
||||||
|
+ subnet_id = (known after apply)
|
||||||
|
}
|
||||||
|
|
||||||
|
# vkcs_networking_secgroup.monitoring_sg will be created
|
||||||
|
+ resource "vkcs_networking_secgroup" "monitoring_sg" {
|
||||||
|
+ all_tags = (known after apply)
|
||||||
|
+ description = "Allow SSH, Prometheus, Grafana, Node Exporter"
|
||||||
|
+ id = (known after apply)
|
||||||
|
+ name = "monitoring-sg"
|
||||||
|
+ region = (known after apply)
|
||||||
|
+ sdn = (known after apply)
|
||||||
|
}
|
||||||
|
|
||||||
|
# vkcs_networking_secgroup_rule.grafana will be created
|
||||||
|
+ resource "vkcs_networking_secgroup_rule" "grafana" {
|
||||||
|
+ direction = "ingress"
|
||||||
|
+ ethertype = "IPv4"
|
||||||
|
+ id = (known after apply)
|
||||||
|
+ port_range_max = 3000
|
||||||
|
+ port_range_min = 3000
|
||||||
|
+ protocol = "tcp"
|
||||||
|
+ region = (known after apply)
|
||||||
|
+ remote_group_id = (known after apply)
|
||||||
|
+ remote_ip_prefix = "0.0.0.0/0"
|
||||||
|
+ sdn = (known after apply)
|
||||||
|
+ security_group_id = (known after apply)
|
||||||
|
}
|
||||||
|
|
||||||
|
# vkcs_networking_secgroup_rule.node_exporter will be created
|
||||||
|
+ resource "vkcs_networking_secgroup_rule" "node_exporter" {
|
||||||
|
+ direction = "ingress"
|
||||||
|
+ ethertype = "IPv4"
|
||||||
|
+ id = (known after apply)
|
||||||
|
+ port_range_max = 9100
|
||||||
|
+ port_range_min = 9100
|
||||||
|
+ protocol = "tcp"
|
||||||
|
+ region = (known after apply)
|
||||||
|
+ remote_group_id = (known after apply)
|
||||||
|
+ remote_ip_prefix = "0.0.0.0/0"
|
||||||
|
+ sdn = (known after apply)
|
||||||
|
+ security_group_id = (known after apply)
|
||||||
|
}
|
||||||
|
|
||||||
|
# vkcs_networking_secgroup_rule.prometheus will be created
|
||||||
|
+ resource "vkcs_networking_secgroup_rule" "prometheus" {
|
||||||
|
+ direction = "ingress"
|
||||||
|
+ ethertype = "IPv4"
|
||||||
|
+ id = (known after apply)
|
||||||
|
+ port_range_max = 9090
|
||||||
|
+ port_range_min = 9090
|
||||||
|
+ protocol = "tcp"
|
||||||
|
+ region = (known after apply)
|
||||||
|
+ remote_group_id = (known after apply)
|
||||||
|
+ remote_ip_prefix = "0.0.0.0/0"
|
||||||
|
+ sdn = (known after apply)
|
||||||
|
+ security_group_id = (known after apply)
|
||||||
|
}
|
||||||
|
|
||||||
|
# vkcs_networking_secgroup_rule.ssh will be created
|
||||||
|
+ resource "vkcs_networking_secgroup_rule" "ssh" {
|
||||||
|
+ direction = "ingress"
|
||||||
|
+ ethertype = "IPv4"
|
||||||
|
+ id = (known after apply)
|
||||||
|
+ port_range_max = 22
|
||||||
|
+ port_range_min = 22
|
||||||
|
+ protocol = "tcp"
|
||||||
|
+ region = (known after apply)
|
||||||
|
+ remote_group_id = (known after apply)
|
||||||
|
+ remote_ip_prefix = "0.0.0.0/0"
|
||||||
|
+ sdn = (known after apply)
|
||||||
|
+ security_group_id = (known after apply)
|
||||||
|
}
|
||||||
|
|
||||||
|
# vkcs_networking_subnet.internal will be created
|
||||||
|
+ resource "vkcs_networking_subnet" "internal" {
|
||||||
|
+ all_tags = (known after apply)
|
||||||
|
+ cidr = "192.168.200.0/24"
|
||||||
|
+ enable_dhcp = true
|
||||||
|
+ enable_private_dns = (known after apply)
|
||||||
|
+ gateway_ip = (known after apply)
|
||||||
|
+ id = (known after apply)
|
||||||
|
+ name = "monitoring-internal-subnet"
|
||||||
|
+ network_id = (known after apply)
|
||||||
|
+ no_gateway = false
|
||||||
|
+ region = (known after apply)
|
||||||
|
+ sdn = (known after apply)
|
||||||
|
|
||||||
|
+ allocation_pool (known after apply)
|
||||||
|
}
|
||||||
|
|
||||||
|
Plan: 13 to add, 0 to change, 0 to destroy.
|
||||||
|
|
||||||
|
Changes to Outputs:
|
||||||
|
+ app_ips = [
|
||||||
|
+ (known after apply),
|
||||||
|
]
|
||||||
|
+ grafana_url = (known after apply)
|
||||||
|
+ monitoring_ip = (known after apply)
|
||||||
|
+ prometheus_url = (known after apply)
|
||||||
|
+ ssh_password = "debian"
|
||||||
|
vkcs_networking_secgroup.monitoring_sg: Creating...
|
||||||
|
vkcs_networking_floatingip.monitoring_fip: Creating...
|
||||||
|
vkcs_networking_network.internal: Creating...
|
||||||
|
vkcs_compute_keypair.monitoring: Creating...
|
||||||
|
vkcs_compute_keypair.monitoring: Creation complete after 0s [id=monitoring-key]
|
||||||
|
vkcs_networking_secgroup.monitoring_sg: Creation complete after 1s [id=8aa4eb80-45e1-4f0d-a54b-f3e0f52f853f]
|
||||||
|
vkcs_networking_secgroup_rule.node_exporter: Creating...
|
||||||
|
vkcs_networking_secgroup_rule.ssh: Creating...
|
||||||
|
vkcs_networking_secgroup_rule.prometheus: Creating...
|
||||||
|
vkcs_networking_secgroup_rule.grafana: Creating...
|
||||||
|
vkcs_networking_secgroup_rule.ssh: Creation complete after 0s [id=fb2538b5-fc65-4743-a37e-be5789b1742d]
|
||||||
|
vkcs_networking_secgroup_rule.prometheus: Creation complete after 0s [id=b8cc74ab-a015-4615-8975-0bfd338f8213]
|
||||||
|
vkcs_networking_secgroup_rule.grafana: Creation complete after 1s [id=576f3bc7-b4d2-4158-b012-ca38b7561894]
|
||||||
|
vkcs_networking_secgroup_rule.node_exporter: Creation complete after 1s [id=5dcf4a9e-c04a-4724-915a-3a29318c3f5a]
|
||||||
|
vkcs_networking_network.internal: Creation complete after 5s [id=93dd466e-b667-4acf-8ecd-47a6e21c955b]
|
||||||
|
vkcs_networking_subnet.internal: Creating...
|
||||||
|
vkcs_compute_instance.app[0]: Creating...
|
||||||
|
vkcs_networking_floatingip.monitoring_fip: Creation complete after 8s [id=7acab770-0e85-4f18-b1f3-513be0b11874]
|
||||||
|
vkcs_networking_subnet.internal: Creation complete after 6s [id=8d7531bf-4b90-4759-b6c9-cc030061b9be]
|
||||||
|
vkcs_networking_router_interface.router_interface: Creating...
|
||||||
|
vkcs_compute_instance.app[0]: Still creating... [00m10s elapsed]
|
||||||
|
vkcs_networking_router_interface.router_interface: Creation complete after 6s [id=53d6881c-5426-4cad-8fd2-9e3af842e99e]
|
||||||
|
vkcs_compute_instance.app[0]: Still creating... [00m20s elapsed]
|
||||||
|
vkcs_compute_instance.app[0]: Still creating... [00m30s elapsed]
|
||||||
|
vkcs_compute_instance.app[0]: Creation complete after 34s [id=bc03c969-7f19-493e-a6d9-4cce60d5a973]
|
||||||
|
vkcs_compute_instance.monitoring: Creating...
|
||||||
|
vkcs_compute_instance.monitoring: Still creating... [00m10s elapsed]
|
||||||
|
vkcs_compute_instance.monitoring: Still creating... [00m20s elapsed]
|
||||||
|
vkcs_compute_instance.monitoring: Still creating... [00m30s elapsed]
|
||||||
|
vkcs_compute_instance.monitoring: Still creating... [00m40s elapsed]
|
||||||
|
vkcs_compute_instance.monitoring: Creation complete after 45s [id=8ef7a2cf-15a0-45f8-9e03-a0d83db6f4e4]
|
||||||
|
vkcs_compute_floatingip_associate.monitoring_fip_assoc: Creating...
|
||||||
|
vkcs_compute_floatingip_associate.monitoring_fip_assoc: Creation complete after 2s [id=95.163.215.1/8ef7a2cf-15a0-45f8-9e03-a0d83db6f4e4/]
|
||||||
|
╷
|
||||||
|
│ Warning: Argument is deprecated
|
||||||
|
│
|
||||||
|
│ with vkcs_networking_secgroup_rule.ssh,
|
||||||
|
│ on VKC_PR_M06_01_monitoring_main_РемизовКЛ_20260617.tf line 87, in resource "vkcs_networking_secgroup_rule" "ssh":
|
||||||
|
│ 87: ethertype = "IPv4"
|
||||||
|
│
|
||||||
|
│ Only IPv4 can be used as ethertype. This argument is deprecated, please do not use it.
|
||||||
|
│
|
||||||
|
│ (and 15 more similar warnings elsewhere)
|
||||||
|
╵
|
||||||
|
|
||||||
|
Apply complete! Resources: 13 added, 0 changed, 0 destroyed.
|
||||||
|
|
||||||
|
Outputs:
|
||||||
|
|
||||||
|
app_ips = [
|
||||||
|
"192.168.200.9",
|
||||||
|
]
|
||||||
|
grafana_url = "http://95.163.215.1:3000"
|
||||||
|
monitoring_ip = "95.163.215.1"
|
||||||
|
prometheus_url = "http://95.163.215.1:9090"
|
||||||
|
ssh_password = "debian"
|
||||||
|
After Width: | Height: | Size: 34 KiB |
@@ -0,0 +1,16 @@
|
|||||||
|
terraform {
|
||||||
|
backend "s3" {
|
||||||
|
bucket = "terraform-state-lab2" # замените на имя вашего бакета
|
||||||
|
key = "lab2/terraform.tfstate"
|
||||||
|
region = "RegionOne"
|
||||||
|
endpoint = "https://hb.vkcloud-storage.ru"
|
||||||
|
|
||||||
|
skip_region_validation = true
|
||||||
|
skip_credentials_validation = true
|
||||||
|
skip_requesting_account_id = true
|
||||||
|
skip_metadata_api_check = true
|
||||||
|
|
||||||
|
access_key = ""
|
||||||
|
secret_key = ""
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
resource "vkcs_compute_keypair" "my_key" {
|
||||||
|
name = var.keypair_name
|
||||||
|
public_key = file(var.ssh_public_key_path)
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "vkcs_networking_port" "bastion_port" {
|
||||||
|
name = "bastion-port"
|
||||||
|
network_id = vkcs_networking_network.lab1_vpc.id
|
||||||
|
admin_state_up = true
|
||||||
|
|
||||||
|
fixed_ip {
|
||||||
|
subnet_id = vkcs_networking_subnet.public.id
|
||||||
|
}
|
||||||
|
|
||||||
|
security_group_ids = [vkcs_networking_secgroup.bastion_sg.id]
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "vkcs_compute_instance" "bastion" {
|
||||||
|
name = "bastion"
|
||||||
|
flavor_id = var.flavor_bastion
|
||||||
|
image_id = var.ubuntu_image_id
|
||||||
|
key_pair = vkcs_compute_keypair.my_key.name
|
||||||
|
|
||||||
|
network {
|
||||||
|
port = vkcs_networking_port.bastion_port.id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "vkcs_networking_floatingip" "bastion_fip" {
|
||||||
|
pool = "internet"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "vkcs_compute_floatingip_associate" "bastion_fip_assoc" {
|
||||||
|
floating_ip = vkcs_networking_floatingip.bastion_fip.address
|
||||||
|
instance_id = vkcs_compute_instance.bastion.id
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "vkcs_networking_port" "web_port" {
|
||||||
|
count = 2
|
||||||
|
name = "web-port-${count.index + 1}"
|
||||||
|
network_id = vkcs_networking_network.lab1_vpc.id
|
||||||
|
admin_state_up = true
|
||||||
|
|
||||||
|
fixed_ip {
|
||||||
|
subnet_id = vkcs_networking_subnet.private.id
|
||||||
|
}
|
||||||
|
|
||||||
|
security_group_ids = [vkcs_networking_secgroup.web_sg.id]
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "vkcs_compute_instance" "web" {
|
||||||
|
count = 2
|
||||||
|
name = "web-${count.index + 1}"
|
||||||
|
flavor_id = var.flavor_web
|
||||||
|
image_id = var.image_packer_id
|
||||||
|
key_pair = vkcs_compute_keypair.my_key.name
|
||||||
|
|
||||||
|
network {
|
||||||
|
port = vkcs_networking_port.web_port[count.index].id
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
resource "vkcs_db_instance" "postgres" {
|
||||||
|
name = "lab1-postgres"
|
||||||
|
flavor_id = var.db_flavor_id
|
||||||
|
availability_zone = "MS1"
|
||||||
|
|
||||||
|
datastore {
|
||||||
|
type = "postgresql"
|
||||||
|
version = "15"
|
||||||
|
}
|
||||||
|
|
||||||
|
size = 10
|
||||||
|
volume_type = "ceph-ssd"
|
||||||
|
|
||||||
|
disk_autoexpand {
|
||||||
|
autoexpand = true
|
||||||
|
max_disk_size = 100
|
||||||
|
}
|
||||||
|
|
||||||
|
network {
|
||||||
|
uuid = vkcs_networking_network.lab1_vpc.id
|
||||||
|
}
|
||||||
|
|
||||||
|
depends_on = [
|
||||||
|
vkcs_networking_router_interface.private,
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
resource "vkcs_lb_loadbalancer" "main" {
|
||||||
|
name = "lab1-lb"
|
||||||
|
vip_subnet_id = vkcs_networking_subnet.public.id
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "vkcs_lb_listener" "http" {
|
||||||
|
name = "http-listener"
|
||||||
|
protocol = "HTTP"
|
||||||
|
protocol_port = 80
|
||||||
|
loadbalancer_id = vkcs_lb_loadbalancer.main.id
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "vkcs_lb_pool" "web" {
|
||||||
|
name = "web-targets"
|
||||||
|
protocol = "HTTP"
|
||||||
|
lb_method = "ROUND_ROBIN"
|
||||||
|
listener_id = vkcs_lb_listener.http.id
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "vkcs_lb_monitor" "web" {
|
||||||
|
name = "web-monitor"
|
||||||
|
type = "HTTP"
|
||||||
|
delay = 10
|
||||||
|
timeout = 5
|
||||||
|
max_retries = 3
|
||||||
|
url_path = "/"
|
||||||
|
pool_id = vkcs_lb_pool.web.id
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "vkcs_lb_member" "web" {
|
||||||
|
count = 2
|
||||||
|
name = "web-member-${count.index + 1}"
|
||||||
|
address = vkcs_compute_instance.web[count.index].network[0].fixed_ip_v4 # берём IP из ВМ
|
||||||
|
protocol_port = 80
|
||||||
|
pool_id = vkcs_lb_pool.web.id
|
||||||
|
subnet_id = vkcs_networking_subnet.private.id
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
data "vkcs_networking_network" "ext_net" {
|
||||||
|
name = "internet"
|
||||||
|
}
|
||||||
|
|
||||||
|
data "vkcs_networking_router" "existing" {
|
||||||
|
id = "913bdd47-9155-45b2-b404-5c10d0086132"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "vkcs_networking_network" "lab1_vpc" {
|
||||||
|
name = "lab1-vpc"
|
||||||
|
admin_state_up = true
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "vkcs_networking_subnet" "public" {
|
||||||
|
name = "lab1-public"
|
||||||
|
network_id = vkcs_networking_network.lab1_vpc.id
|
||||||
|
cidr = "10.0.1.0/24"
|
||||||
|
dns_nameservers = ["8.8.8.8", "8.8.4.4"]
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "vkcs_networking_subnet" "private" {
|
||||||
|
name = "lab1-private"
|
||||||
|
network_id = vkcs_networking_network.lab1_vpc.id
|
||||||
|
cidr = "10.0.2.0/24"
|
||||||
|
dns_nameservers = ["8.8.8.8", "8.8.4.4"]
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "vkcs_networking_router_interface" "public" {
|
||||||
|
router_id = data.vkcs_networking_router.existing.id
|
||||||
|
subnet_id = vkcs_networking_subnet.public.id
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "vkcs_networking_router_interface" "private" {
|
||||||
|
router_id = data.vkcs_networking_router.existing.id
|
||||||
|
subnet_id = vkcs_networking_subnet.private.id
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
output "lb_public_ip" {
|
||||||
|
value = vkcs_lb_loadbalancer.main.vip_address
|
||||||
|
description = "Публичный IP балансировщика"
|
||||||
|
}
|
||||||
|
|
||||||
|
output "bastion_public_ip" {
|
||||||
|
value = vkcs_networking_floatingip.bastion_fip.address
|
||||||
|
}
|
||||||
|
|
||||||
|
output "web_private_ips" {
|
||||||
|
value = vkcs_compute_instance.web[*].network[0].fixed_ip_v4
|
||||||
|
description = "Приватные IP веб-серверов"
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
# Переменные окружения
|
||||||
|
variable "network_id" {
|
||||||
|
type = string
|
||||||
|
default = env("NETWORK_ID")
|
||||||
|
}
|
||||||
|
variable "source_image" {
|
||||||
|
type = string
|
||||||
|
default = env("SOURCE_IMAGE")
|
||||||
|
}
|
||||||
|
|
||||||
|
source "openstack" "ubuntu-nginx" {
|
||||||
|
flavor = "STD3-2-6"
|
||||||
|
source_image = var.source_image
|
||||||
|
networks = [var.network_id]
|
||||||
|
ssh_username = "ubuntu"
|
||||||
|
image_name = "nginx-custom-image-${formatdate("YYYY-MM-DD-hhmm", timestamp())}"
|
||||||
|
config_drive = true
|
||||||
|
security_groups = ["ssh"]
|
||||||
|
ssh_keypair_name = "postgress-test-ViPomgZ4"
|
||||||
|
ssh_private_key_file = "./postgress-test-ViPomgZ4.pem"
|
||||||
|
ssh_timeout = "10m"
|
||||||
|
}
|
||||||
|
|
||||||
|
build {
|
||||||
|
sources = ["source.openstack.ubuntu-nginx"]
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
terraform {
|
||||||
|
required_providers {
|
||||||
|
vkcs = {
|
||||||
|
source = "vk-cs/vkcs"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
provider "vkcs" {}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
resource "vkcs_networking_secgroup" "bastion_sg" {
|
||||||
|
name = "bastion-sg"
|
||||||
|
description = "SSH from my IP"
|
||||||
|
}
|
||||||
|
resource "vkcs_networking_secgroup_rule" "bastion_ssh" {
|
||||||
|
direction = "ingress"
|
||||||
|
protocol = "tcp"
|
||||||
|
port_range_min = 22
|
||||||
|
port_range_max = 22
|
||||||
|
remote_ip_prefix = var.my_ip
|
||||||
|
security_group_id = vkcs_networking_secgroup.bastion_sg.id
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "vkcs_networking_secgroup" "web_sg" {
|
||||||
|
name = "web-sg"
|
||||||
|
description = "SSH from bastion, HTTP from LB"
|
||||||
|
}
|
||||||
|
resource "vkcs_networking_secgroup_rule" "web_ssh" {
|
||||||
|
direction = "ingress"
|
||||||
|
protocol = "tcp"
|
||||||
|
port_range_min = 22
|
||||||
|
port_range_max = 22
|
||||||
|
remote_group_id = vkcs_networking_secgroup.bastion_sg.id
|
||||||
|
security_group_id = vkcs_networking_secgroup.web_sg.id
|
||||||
|
}
|
||||||
|
resource "vkcs_networking_secgroup_rule" "web_http" {
|
||||||
|
direction = "ingress"
|
||||||
|
protocol = "tcp"
|
||||||
|
port_range_min = 80
|
||||||
|
port_range_max = 80
|
||||||
|
remote_group_id = vkcs_networking_secgroup.lb_sg.id
|
||||||
|
security_group_id = vkcs_networking_secgroup.web_sg.id
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "vkcs_networking_secgroup" "lb_sg" {
|
||||||
|
name = "lb-sg"
|
||||||
|
description = "HTTP from internet"
|
||||||
|
}
|
||||||
|
resource "vkcs_networking_secgroup_rule" "lb_http" {
|
||||||
|
direction = "ingress"
|
||||||
|
protocol = "tcp"
|
||||||
|
port_range_min = 80
|
||||||
|
port_range_max = 80
|
||||||
|
remote_ip_prefix = "0.0.0.0/0"
|
||||||
|
security_group_id = vkcs_networking_secgroup.lb_sg.id
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
variable "my_ip" {
|
||||||
|
type = string
|
||||||
|
default = "95.26.148.233/32"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "flavor_web" {
|
||||||
|
type = string
|
||||||
|
default = "25ae869c-be29-4840-8e12-99e046d2dbd4"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "flavor_bastion" {
|
||||||
|
type = string
|
||||||
|
default = "df3c499a-044f-41d2-8612-d303adc613cc"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "image_packer_id" {
|
||||||
|
type = string
|
||||||
|
default = "a31acc16-4703-468b-bc5b-bf07952f66b2"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "ubuntu_image_name" {
|
||||||
|
type = string
|
||||||
|
default = "ubuntu-22-202602051629.gite7a38aaf"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "ssh_public_key_path" {
|
||||||
|
type = string
|
||||||
|
default = "~/.ssh/id_rsa.pub"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "keypair_name" {
|
||||||
|
type = string
|
||||||
|
default = "terraform-key-local"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "ubuntu_image_id" {
|
||||||
|
type = string
|
||||||
|
default = "a4e699d3-a66d-45e5-bb5d-70ea7c8de62d"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "db_flavor_id" {
|
||||||
|
type = string
|
||||||
|
default = "2d9866a9-e955-4986-b00a-340ca54b2cac"
|
||||||
|
}
|
||||||
@@ -0,0 +1,421 @@
|
|||||||
|
terraform {
|
||||||
|
required_providers {
|
||||||
|
vkcs = {
|
||||||
|
source = "vk-cs/vkcs"
|
||||||
|
version = "~> 0.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Настройка провайдера (использует переменные окружения из RC-файла)
|
||||||
|
provider "vkcs" {}
|
||||||
|
|
||||||
|
data "vkcs_networking_network" "extnet" {
|
||||||
|
name = var.external_network_name
|
||||||
|
}
|
||||||
|
|
||||||
|
data "vkcs_networking_secgroup" "ssh" {
|
||||||
|
name = "ssh"
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
data "vkcs_compute_flavor" "bastion" {
|
||||||
|
name = var.flavor_bastion
|
||||||
|
}
|
||||||
|
|
||||||
|
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" "main" {
|
||||||
|
name = "${var.project_name}-secgroup"
|
||||||
|
description = "Security group for monitoring lab"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "vkcs_networking_secgroup_rule" "ssh" {
|
||||||
|
security_group_id = vkcs_networking_secgroup.main.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.main.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" "prometheus" {
|
||||||
|
security_group_id = vkcs_networking_secgroup.main.id
|
||||||
|
direction = "ingress"
|
||||||
|
protocol = "tcp"
|
||||||
|
port_range_min = 9090
|
||||||
|
port_range_max = 9090
|
||||||
|
remote_ip_prefix = "0.0.0.0/0"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "vkcs_networking_secgroup_rule" "grafana" {
|
||||||
|
security_group_id = vkcs_networking_secgroup.main.id
|
||||||
|
direction = "ingress"
|
||||||
|
protocol = "tcp"
|
||||||
|
port_range_min = 3000
|
||||||
|
port_range_max = 3000
|
||||||
|
remote_ip_prefix = "0.0.0.0/0"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "vkcs_networking_secgroup_rule" "node_exporter_public" {
|
||||||
|
security_group_id = vkcs_networking_secgroup.main.id
|
||||||
|
direction = "ingress"
|
||||||
|
protocol = "tcp"
|
||||||
|
port_range_min = 9100
|
||||||
|
port_range_max = 9100
|
||||||
|
remote_ip_prefix = var.public_subnet_cidr
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "vkcs_networking_secgroup_rule" "node_exporter_private" {
|
||||||
|
security_group_id = vkcs_networking_secgroup.main.id
|
||||||
|
direction = "ingress"
|
||||||
|
protocol = "tcp"
|
||||||
|
port_range_min = 9100
|
||||||
|
port_range_max = 9100
|
||||||
|
remote_ip_prefix = var.private_subnet_cidr
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "vkcs_networking_secgroup_rule" "egress" {
|
||||||
|
security_group_id = vkcs_networking_secgroup.main.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.main.id, data.vkcs_networking_secgroup.ssh.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
|
||||||
|
set -e
|
||||||
|
apt update
|
||||||
|
apt install -y nginx
|
||||||
|
|
||||||
|
cat <<HTML > /var/www/html/index.html
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head><title>Web Server $(hostname)</title></head>
|
||||||
|
<body>
|
||||||
|
<h1>Welcome to $(hostname)</h1>
|
||||||
|
<p>Server IP: $(hostname -I | awk '{print $1}')</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
HTML
|
||||||
|
|
||||||
|
systemctl enable nginx
|
||||||
|
systemctl start nginx
|
||||||
|
|
||||||
|
# Node Exporter
|
||||||
|
cd /tmp
|
||||||
|
wget -q https://github.com/prometheus/node_exporter/releases/download/v1.7.0/node_exporter-1.7.0.linux-amd64.tar.gz
|
||||||
|
tar xf node_exporter-1.7.0.linux-amd64.tar.gz
|
||||||
|
sudo mv node_exporter-1.7.0.linux-amd64/node_exporter /usr/local/bin/
|
||||||
|
rm -rf node_exporter-1.7.0.linux-amd64*
|
||||||
|
|
||||||
|
cat <<SERVICE > /etc/systemd/system/node_exporter.service
|
||||||
|
[Unit]
|
||||||
|
Description=Node Exporter
|
||||||
|
After=network.target
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
User=nobody
|
||||||
|
Group=nogroup
|
||||||
|
ExecStart=/usr/local/bin/node_exporter
|
||||||
|
Restart=always
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
SERVICE
|
||||||
|
|
||||||
|
systemctl daemon-reload
|
||||||
|
systemctl enable node_exporter
|
||||||
|
systemctl start node_exporter
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "vkcs_compute_instance" "bastion" {
|
||||||
|
name = "${var.project_name}-bastion-monitoring"
|
||||||
|
flavor_id = data.vkcs_compute_flavor.bastion.id
|
||||||
|
key_pair = vkcs_compute_keypair.my_key.name
|
||||||
|
security_group_ids = [vkcs_networking_secgroup.main.id, data.vkcs_networking_secgroup.ssh.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_bastion
|
||||||
|
boot_index = 0
|
||||||
|
delete_on_termination = true
|
||||||
|
}
|
||||||
|
|
||||||
|
network {
|
||||||
|
uuid = vkcs_networking_network.main.id
|
||||||
|
fixed_ip_v4 = cidrhost(var.public_subnet_cidr, 10)
|
||||||
|
}
|
||||||
|
|
||||||
|
user_data = <<-EOF
|
||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# ---- Prometheus ----
|
||||||
|
cd /tmp
|
||||||
|
wget -q https://github.com/prometheus/prometheus/releases/download/v2.48.0/prometheus-2.48.0.linux-amd64.tar.gz
|
||||||
|
tar xf prometheus-2.48.0.linux-amd64.tar.gz
|
||||||
|
sudo mv prometheus-2.48.0.linux-amd64 /opt/prometheus
|
||||||
|
|
||||||
|
sudo mkdir -p /opt/prometheus/data
|
||||||
|
sudo chown -R nobody:nogroup /opt/prometheus/data
|
||||||
|
|
||||||
|
cat <<PROM > /opt/prometheus/prometheus.yml
|
||||||
|
global:
|
||||||
|
scrape_interval: 15s
|
||||||
|
evaluation_interval: 15s
|
||||||
|
rule_files:
|
||||||
|
- "rules/*.yml"
|
||||||
|
scrape_configs:
|
||||||
|
- job_name: 'prometheus'
|
||||||
|
static_configs:
|
||||||
|
- targets: ['localhost:9090']
|
||||||
|
- job_name: 'node'
|
||||||
|
static_configs:
|
||||||
|
- targets:
|
||||||
|
- 'localhost:9100'
|
||||||
|
${join("\n", [for ip in local.web_private_ips : " - '${ip}:9100'"])}
|
||||||
|
PROM
|
||||||
|
|
||||||
|
cat <<SERVICE > /etc/systemd/system/prometheus.service
|
||||||
|
[Unit]
|
||||||
|
Description=Prometheus
|
||||||
|
After=network.target
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
User=nobody
|
||||||
|
Group=nogroup
|
||||||
|
ExecStart=/opt/prometheus/prometheus --config.file=/opt/prometheus/prometheus.yml --storage.tsdb.path=/opt/prometheus/data
|
||||||
|
Restart=always
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
SERVICE
|
||||||
|
|
||||||
|
systemctl daemon-reload
|
||||||
|
systemctl enable prometheus
|
||||||
|
systemctl start prometheus
|
||||||
|
|
||||||
|
# ---- Grafana (прямая установка) ----
|
||||||
|
cd /tmp
|
||||||
|
wget -q https://dl.grafana.com/oss/release/grafana_10.4.0_amd64.deb
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y musl libfontconfig1 fontconfig-config fonts-dejavu-core
|
||||||
|
sudo dpkg -i grafana_10.4.0_amd64.deb || sudo apt-get install -f -y
|
||||||
|
sudo systemctl enable grafana-server
|
||||||
|
sudo systemctl start grafana-server
|
||||||
|
|
||||||
|
# ---- Node Exporter для самой ВМ ----
|
||||||
|
cd /tmp
|
||||||
|
wget -q https://github.com/prometheus/node_exporter/releases/download/v1.7.0/node_exporter-1.7.0.linux-amd64.tar.gz
|
||||||
|
tar xf node_exporter-1.7.0.linux-amd64.tar.gz
|
||||||
|
sudo mv node_exporter-1.7.0.linux-amd64/node_exporter /usr/local/bin/
|
||||||
|
rm -rf node_exporter-1.7.0.linux-amd64*
|
||||||
|
|
||||||
|
cat <<NEX > /etc/systemd/system/node_exporter.service
|
||||||
|
[Unit]
|
||||||
|
Description=Node Exporter
|
||||||
|
After=network.target
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
User=nobody
|
||||||
|
Group=nogroup
|
||||||
|
ExecStart=/usr/local/bin/node_exporter
|
||||||
|
Restart=always
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
NEX
|
||||||
|
|
||||||
|
systemctl daemon-reload
|
||||||
|
systemctl enable node_exporter
|
||||||
|
systemctl start node_exporter
|
||||||
|
|
||||||
|
# ---- Alertmanager ----
|
||||||
|
cd /tmp
|
||||||
|
wget -q https://github.com/prometheus/alertmanager/releases/download/v0.26.0/alertmanager-0.26.0.linux-amd64.tar.gz
|
||||||
|
tar xf alertmanager-0.26.0.linux-amd64.tar.gz
|
||||||
|
sudo mv alertmanager-0.26.0.linux-amd64 /opt/alertmanager
|
||||||
|
|
||||||
|
cat <<AM > /opt/alertmanager/alertmanager.yml
|
||||||
|
route:
|
||||||
|
group_by: ['alertname']
|
||||||
|
group_wait: 10s
|
||||||
|
group_interval: 10s
|
||||||
|
repeat_interval: 1h
|
||||||
|
receiver: 'null'
|
||||||
|
receivers:
|
||||||
|
- name: 'null'
|
||||||
|
AM
|
||||||
|
|
||||||
|
cat <<AMS > /etc/systemd/system/alertmanager.service
|
||||||
|
[Unit]
|
||||||
|
Description=Alertmanager
|
||||||
|
After=network.target
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
User=nobody
|
||||||
|
Group=nogroup
|
||||||
|
ExecStart=/opt/alertmanager/alertmanager --config.file=/opt/alertmanager/alertmanager.yml
|
||||||
|
Restart=always
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
AMS
|
||||||
|
|
||||||
|
systemctl daemon-reload
|
||||||
|
systemctl enable alertmanager
|
||||||
|
systemctl start alertmanager
|
||||||
|
|
||||||
|
# ---- Правила алертов ----
|
||||||
|
sudo mkdir -p /opt/prometheus/rules
|
||||||
|
cat <<RULES > /opt/prometheus/rules/alerts.yml
|
||||||
|
groups:
|
||||||
|
- name: instance_alerts
|
||||||
|
rules:
|
||||||
|
- alert: InstanceDown
|
||||||
|
expr: up{job="node"} == 0
|
||||||
|
for: 5m
|
||||||
|
labels:
|
||||||
|
severity: critical
|
||||||
|
annotations:
|
||||||
|
summary: "Instance {{ \$labels.instance }} is down"
|
||||||
|
description: "{{ \$labels.instance }} has been down for more than 5 minutes."
|
||||||
|
RULES
|
||||||
|
|
||||||
|
systemctl restart prometheus
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "vkcs_networking_floatingip" "bastion" {
|
||||||
|
pool = data.vkcs_networking_network.extnet.name
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "vkcs_networking_floatingip_associate" "bastion" {
|
||||||
|
floating_ip = vkcs_networking_floatingip.bastion.address
|
||||||
|
port_id = vkcs_compute_instance.bastion.network[0].port
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
output "load_balancer_ip" {
|
||||||
|
value = vkcs_networking_floatingip.lb.address
|
||||||
|
description = "Публичный IP балансировщика"
|
||||||
|
}
|
||||||
|
|
||||||
|
output "bastion_floating_ip" {
|
||||||
|
value = vkcs_networking_floatingip.bastion.address
|
||||||
|
description = "Публичный IP ВМ бастиона + мониторинга"
|
||||||
|
}
|
||||||
|
|
||||||
|
output "web_private_ips" {
|
||||||
|
value = local.web_private_ips
|
||||||
|
description = "Приватные IP веб-серверов"
|
||||||
|
}
|
||||||
|
|
||||||
|
output "grafana_url" {
|
||||||
|
value = "http://${vkcs_networking_floatingip.bastion.address}:3000"
|
||||||
|
description = "URL Grafana"
|
||||||
|
}
|
||||||
|
|
||||||
|
output "prometheus_url" {
|
||||||
|
value = "http://${vkcs_networking_floatingip.bastion.address}:9090"
|
||||||
|
description = "URL Prometheus"
|
||||||
|
}
|
||||||
|
|
||||||
|
output "ssh_to_bastion" {
|
||||||
|
value = "ssh -i ~/.ssh/id_rsa ubuntu@${vkcs_networking_floatingip.bastion.address}"
|
||||||
|
description = "Команда для подключения к бастиону"
|
||||||
|
}
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
variable "my_ip" {
|
||||||
|
description = "Ваш публичный IP для SSH (узнать через curl ifconfig.me)"
|
||||||
|
type = string
|
||||||
|
sensitive = true
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "project_name" {
|
||||||
|
description = "Префикс для имен ресурсов"
|
||||||
|
type = string
|
||||||
|
default = "lab3"
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: app-config
|
||||||
|
namespace: web-app
|
||||||
|
data:
|
||||||
|
LB_IP: "95.163.215.1"
|
||||||
@@ -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
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
resources:
|
||||||
|
- deployment.yaml
|
||||||
|
- service.yaml
|
||||||
|
- configmap.yaml
|
||||||
@@ -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 "<h1>Web Server $(hostname)</h1>" > /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
|
||||||
|
}
|
||||||
@@ -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 для доступа к приложению"
|
||||||
|
}
|
||||||
@@ -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
|
||||||
@@ -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
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
terraform {
|
||||||
|
backend "s3" {
|
||||||
|
bucket = "tf-state-final-assessment" # имя твоего бакета (должен существовать)
|
||||||
|
key = "final-assessment/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
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,302 @@
|
|||||||
|
terraform {
|
||||||
|
required_providers {
|
||||||
|
vkcs = {
|
||||||
|
source = "vk-cs/vkcs"
|
||||||
|
version = "~> 0.1"
|
||||||
|
}
|
||||||
|
random = {
|
||||||
|
source = "hashicorp/random"
|
||||||
|
version = "~> 3.5"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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_secgroup" "ssh" {
|
||||||
|
name = "ssh"
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
data "vkcs_compute_flavor" "bastion" {
|
||||||
|
name = var.flavor_bastion
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- Сеть ---
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- Security Groups ---
|
||||||
|
resource "vkcs_networking_secgroup" "main" {
|
||||||
|
name = "${var.project_name}-secgroup"
|
||||||
|
description = "Security group for VMs"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "vkcs_networking_secgroup_rule" "ssh" {
|
||||||
|
security_group_id = vkcs_networking_secgroup.main.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.main.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.main.id
|
||||||
|
direction = "egress"
|
||||||
|
remote_ip_prefix = "0.0.0.0/0"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Security Group для базы данных
|
||||||
|
resource "vkcs_networking_secgroup" "db_sg" {
|
||||||
|
name = "${var.project_name}-db-sg"
|
||||||
|
description = "Security group for PostgreSQL"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "vkcs_networking_secgroup_rule" "db_ingress" {
|
||||||
|
security_group_id = vkcs_networking_secgroup.db_sg.id
|
||||||
|
direction = "ingress"
|
||||||
|
protocol = "tcp"
|
||||||
|
port_range_min = 5432
|
||||||
|
port_range_max = 5432
|
||||||
|
remote_ip_prefix = var.private_subnet_cidr
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- Key Pair ---
|
||||||
|
resource "vkcs_compute_keypair" "my_key" {
|
||||||
|
name = "${var.project_name}-key"
|
||||||
|
public_key = file(var.ssh_public_key)
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- Веб-серверы (Docker, без логина) ---
|
||||||
|
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.main.id, data.vkcs_networking_secgroup.ssh.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 – без логина, просто run
|
||||||
|
user_data = <<-EOF
|
||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Установка Docker
|
||||||
|
apt-get update
|
||||||
|
apt-get install -y docker.io
|
||||||
|
systemctl enable docker
|
||||||
|
systemctl start docker
|
||||||
|
|
||||||
|
# Ждём, пока Docker-демон полностью запустится
|
||||||
|
sleep 5
|
||||||
|
|
||||||
|
# Запускаем контейнер с повторными попытками, если образ не скачался
|
||||||
|
MAX_ATTEMPTS=5
|
||||||
|
ATTEMPT=0
|
||||||
|
until [ $ATTEMPT -ge $MAX_ATTEMPTS ]
|
||||||
|
do
|
||||||
|
echo "Attempt $((ATTEMPT+1)): pulling and running container..."
|
||||||
|
docker run -d --restart=always -p 80:80 ${var.docker_image} && break
|
||||||
|
ATTEMPT=$((ATTEMPT+1))
|
||||||
|
echo "Failed. Retrying in 10 seconds..."
|
||||||
|
sleep 10
|
||||||
|
done
|
||||||
|
|
||||||
|
# Если после всех попыток контейнер не запустился – пишем ошибку в лог
|
||||||
|
if [ $ATTEMPT -eq $MAX_ATTEMPTS ]; then
|
||||||
|
echo "ERROR: Failed to run container after $MAX_ATTEMPTS attempts." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Container started successfully."
|
||||||
|
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 = "/DevOps"
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- Бастион (без мониторинга) ---
|
||||||
|
resource "vkcs_compute_instance" "bastion" {
|
||||||
|
name = "${var.project_name}-bastion"
|
||||||
|
flavor_id = data.vkcs_compute_flavor.bastion.id
|
||||||
|
key_pair = vkcs_compute_keypair.my_key.name
|
||||||
|
security_group_ids = [vkcs_networking_secgroup.main.id, data.vkcs_networking_secgroup.ssh.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_bastion
|
||||||
|
boot_index = 0
|
||||||
|
delete_on_termination = true
|
||||||
|
}
|
||||||
|
|
||||||
|
network {
|
||||||
|
uuid = vkcs_networking_network.main.id
|
||||||
|
fixed_ip_v4 = cidrhost(var.public_subnet_cidr, 10)
|
||||||
|
}
|
||||||
|
|
||||||
|
user_data = <<-EOF
|
||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
apt-get update
|
||||||
|
apt-get install -y curl wget htop
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "vkcs_networking_floatingip" "bastion" {
|
||||||
|
pool = data.vkcs_networking_network.extnet.name
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "vkcs_networking_floatingip_associate" "bastion" {
|
||||||
|
floating_ip = vkcs_networking_floatingip.bastion.address
|
||||||
|
port_id = vkcs_compute_instance.bastion.network[0].port
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- Управляемая PostgreSQL ---
|
||||||
|
resource "vkcs_db_instance" "postgres" {
|
||||||
|
name = "${var.project_name}-postgres"
|
||||||
|
flavor_id = "bf714720-78da-4271-ab7d-0cf5e2613f14" # Standard-2-8-50
|
||||||
|
size = 10
|
||||||
|
volume_type = "ceph-ssd"
|
||||||
|
network {
|
||||||
|
subnet_id = vkcs_networking_subnet.private.id
|
||||||
|
}
|
||||||
|
availability_zone = "MS1"
|
||||||
|
datastore {
|
||||||
|
type = "postgresql"
|
||||||
|
version = "14"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "vkcs_db_database" "app_db" {
|
||||||
|
dbms_id = vkcs_db_instance.postgres.id
|
||||||
|
name = "app_db"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "vkcs_db_user" "app_user" {
|
||||||
|
dbms_id = vkcs_db_instance.postgres.id
|
||||||
|
name = "app_user"
|
||||||
|
password = "*#User23786590#*"
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
output "load_balancer_ip" {
|
||||||
|
value = vkcs_networking_floatingip.lb.address
|
||||||
|
description = "Публичный IP балансировщика"
|
||||||
|
}
|
||||||
|
|
||||||
|
output "bastion_floating_ip" {
|
||||||
|
value = vkcs_networking_floatingip.bastion.address
|
||||||
|
description = "Публичный IP ВМ бастиона"
|
||||||
|
}
|
||||||
|
|
||||||
|
output "web_private_ips" {
|
||||||
|
value = local.web_private_ips
|
||||||
|
description = "Приватные IP веб-серверов"
|
||||||
|
}
|
||||||
|
|
||||||
|
output "ssh_to_bastion" {
|
||||||
|
value = "ssh -i ~/.ssh/id_rsa ubuntu@${vkcs_networking_floatingip.bastion.address}"
|
||||||
|
description = "Команда для подключения к бастиону"
|
||||||
|
}
|
||||||
|
|
||||||
|
output "db_host" {
|
||||||
|
value = vkcs_db_instance.postgres.network[0].fixed_ip_v4
|
||||||
|
description = "Приватный IP инстанса PostgreSQL"
|
||||||
|
}
|
||||||
|
|
||||||
|
output "db_name" {
|
||||||
|
value = vkcs_db_database.app_db.name
|
||||||
|
description = "Имя базы данных"
|
||||||
|
}
|
||||||
|
|
||||||
|
output "db_user" {
|
||||||
|
value = vkcs_db_user.app_user.name
|
||||||
|
description = "Имя пользователя БД"
|
||||||
|
}
|
||||||
@@ -0,0 +1,109 @@
|
|||||||
|
variable "my_ip" {
|
||||||
|
description = "Ваш публичный IP для SSH (узнать через curl ifconfig.me)"
|
||||||
|
type = string
|
||||||
|
sensitive = true
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "project_name" {
|
||||||
|
description = "Префикс для имен ресурсов"
|
||||||
|
type = string
|
||||||
|
default = "final_assessment"
|
||||||
|
}
|
||||||
|
|
||||||
|
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 для веб-серверов"
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- Docker-образ (без логина) ---
|
||||||
|
variable "docker_image" {
|
||||||
|
description = "Полное имя Docker-образа (с тегом)"
|
||||||
|
type = string
|
||||||
|
default = "git.rustprogersteam.ru/black_raven/myresume/resume:latest"
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- Аутентификация 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
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: nginx-deployment
|
||||||
|
spec:
|
||||||
|
replicas: 3
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: nginx
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: nginx
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: nginx
|
||||||
|
image: nginx:latest
|
||||||
|
ports:
|
||||||
|
- containerPort: 80
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
memory: "64Mi"
|
||||||
|
cpu: "100m"
|
||||||
|
limits:
|
||||||
|
memory: "128Mi"
|
||||||
|
cpu: "200m"
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: nginx-service
|
||||||
|
spec:
|
||||||
|
type: LoadBalancer
|
||||||
|
selector:
|
||||||
|
app: nginx
|
||||||
|
ports:
|
||||||
|
- port: 80
|
||||||
|
targetPort: 80
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
# Переменные окружения
|
||||||
|
variable "network_id" {
|
||||||
|
type = string
|
||||||
|
default = env("NETWORK_ID")
|
||||||
|
}
|
||||||
|
variable "source_image" {
|
||||||
|
type = string
|
||||||
|
default = env("SOURCE_IMAGE")
|
||||||
|
}
|
||||||
|
|
||||||
|
packer {
|
||||||
|
required_plugins {
|
||||||
|
openstack = {
|
||||||
|
source = "github.com/hashicorp/openstack"
|
||||||
|
version = ">= 1.1.2"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
source "openstack" "ubuntu-nginx" {
|
||||||
|
flavor = "STD3-2-6"
|
||||||
|
source_image = var.source_image
|
||||||
|
networks = [var.network_id] # используем сеть internet
|
||||||
|
ssh_username = "ubuntu"
|
||||||
|
image_name = "nginx-custom-image-${formatdate("YYYY-MM-DD-hhmm", timestamp())}"
|
||||||
|
use_blockstorage_volume = true
|
||||||
|
volume_availability_zone = "MS1"
|
||||||
|
config_drive = true
|
||||||
|
security_groups = ["ssh"]
|
||||||
|
ssh_keypair_name = "postgress-test-ViPomgZ4"
|
||||||
|
ssh_private_key_file = "./postgress-test-ViPomgZ4.pem"
|
||||||
|
ssh_timeout = "10m"
|
||||||
|
}
|
||||||
|
|
||||||
|
build {
|
||||||
|
sources = ["source.openstack.ubuntu-nginx"]
|
||||||
|
|
||||||
|
provisioner "shell" {
|
||||||
|
inline = [
|
||||||
|
# Фикс hostname для sudo
|
||||||
|
"sudo sh -c 'echo \"127.0.0.1 $(hostname)\" >> /etc/hosts'",
|
||||||
|
|
||||||
|
# Принудительная настройка DNS с блокировкой от перезаписи
|
||||||
|
"sudo rm -f /etc/resolv.conf",
|
||||||
|
"sudo sh -c 'echo nameserver 8.8.8.8 > /etc/resolv.conf'",
|
||||||
|
"sudo sh -c 'echo nameserver 1.1.1.1 >> /etc/resolv.conf'",
|
||||||
|
"sudo chattr +i /etc/resolv.conf", # защита от перезаписи
|
||||||
|
|
||||||
|
# Обновление списка пакетов (обязательно!)
|
||||||
|
"echo 'Updating package lists...'",
|
||||||
|
"sudo apt-get update",
|
||||||
|
|
||||||
|
"echo 'Installing nginx...'",
|
||||||
|
"sudo apt-get install -y nginx",
|
||||||
|
|
||||||
|
"echo 'Configuring nginx...'",
|
||||||
|
"sudo systemctl enable nginx",
|
||||||
|
"sudo systemctl start nginx",
|
||||||
|
|
||||||
|
"echo 'Creating test page...'",
|
||||||
|
"echo '<h1>Hello from Packer!</h1>' | sudo tee /var/www/html/index.html",
|
||||||
|
|
||||||
|
"echo 'Cleaning up...'",
|
||||||
|
"sudo apt-get clean",
|
||||||
|
"sudo rm -rf /tmp/*",
|
||||||
|
"sudo rm -rf /var/lib/apt/lists/*"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,316 @@
|
|||||||
|
terraform {
|
||||||
|
required_providers {
|
||||||
|
vkcs = {
|
||||||
|
source = "vk-cs/vkcs"
|
||||||
|
version = "~> 0.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
provider "vkcs" {}
|
||||||
|
|
||||||
|
variable "external_network_name" {
|
||||||
|
default = "internet"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "router_id" {
|
||||||
|
default = "913bdd47-9155-45b2-b404-5c10d0086132"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "image_name" {
|
||||||
|
default = "ubuntu-20-202602051631.gite7a38aaf"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "flavor_name" {
|
||||||
|
default = "Basic-1-2-20"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "app_count" {
|
||||||
|
default = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "availability_zone" {
|
||||||
|
default = "MS1"
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
most_recent = true
|
||||||
|
}
|
||||||
|
|
||||||
|
data "vkcs_compute_flavor" "vm" {
|
||||||
|
name = var.flavor_name
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "vkcs_networking_network" "internal" {
|
||||||
|
name = "monitoring-internal-net"
|
||||||
|
sdn = "sprut"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "vkcs_networking_subnet" "internal" {
|
||||||
|
name = "monitoring-internal-subnet"
|
||||||
|
network_id = vkcs_networking_network.internal.id
|
||||||
|
cidr = "192.168.200.0/24"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "vkcs_networking_router_interface" "router_interface" {
|
||||||
|
router_id = data.vkcs_networking_router.router.id
|
||||||
|
subnet_id = vkcs_networking_subnet.internal.id
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "vkcs_networking_secgroup" "monitoring_sg" {
|
||||||
|
name = "monitoring-sg"
|
||||||
|
description = "Allow SSH, Prometheus, Grafana, Node Exporter"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "vkcs_networking_secgroup_rule" "ssh" {
|
||||||
|
direction = "ingress"
|
||||||
|
ethertype = "IPv4"
|
||||||
|
protocol = "tcp"
|
||||||
|
port_range_min = 22
|
||||||
|
port_range_max = 22
|
||||||
|
remote_ip_prefix = "0.0.0.0/0"
|
||||||
|
security_group_id = vkcs_networking_secgroup.monitoring_sg.id
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "vkcs_networking_secgroup_rule" "grafana" {
|
||||||
|
direction = "ingress"
|
||||||
|
ethertype = "IPv4"
|
||||||
|
protocol = "tcp"
|
||||||
|
port_range_min = 3000
|
||||||
|
port_range_max = 3000
|
||||||
|
remote_ip_prefix = "0.0.0.0/0"
|
||||||
|
security_group_id = vkcs_networking_secgroup.monitoring_sg.id
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "vkcs_networking_secgroup_rule" "prometheus" {
|
||||||
|
direction = "ingress"
|
||||||
|
ethertype = "IPv4"
|
||||||
|
protocol = "tcp"
|
||||||
|
port_range_min = 9090
|
||||||
|
port_range_max = 9090
|
||||||
|
remote_ip_prefix = "0.0.0.0/0"
|
||||||
|
security_group_id = vkcs_networking_secgroup.monitoring_sg.id
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "vkcs_networking_secgroup_rule" "node_exporter" {
|
||||||
|
direction = "ingress"
|
||||||
|
ethertype = "IPv4"
|
||||||
|
protocol = "tcp"
|
||||||
|
port_range_min = 9100
|
||||||
|
port_range_max = 9100
|
||||||
|
remote_ip_prefix = "0.0.0.0/0"
|
||||||
|
security_group_id = vkcs_networking_secgroup.monitoring_sg.id
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "vkcs_compute_keypair" "monitoring" {
|
||||||
|
name = "monitoring-key"
|
||||||
|
public_key = file("~/.ssh/id_rsa.pub")
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "vkcs_compute_instance" "app" {
|
||||||
|
count = var.app_count
|
||||||
|
|
||||||
|
name = "app-vm-${count.index + 1}"
|
||||||
|
flavor_id = data.vkcs_compute_flavor.vm.id
|
||||||
|
key_pair = vkcs_compute_keypair.monitoring.name
|
||||||
|
availability_zone = var.availability_zone
|
||||||
|
|
||||||
|
block_device {
|
||||||
|
uuid = data.vkcs_images_image.ubuntu.id
|
||||||
|
source_type = "image"
|
||||||
|
destination_type = "volume"
|
||||||
|
volume_type = "ceph-ssd"
|
||||||
|
volume_size = 10
|
||||||
|
boot_index = 0
|
||||||
|
delete_on_termination = true
|
||||||
|
}
|
||||||
|
|
||||||
|
network {
|
||||||
|
uuid = vkcs_networking_network.internal.id
|
||||||
|
}
|
||||||
|
|
||||||
|
security_groups = [vkcs_networking_secgroup.monitoring_sg.name]
|
||||||
|
|
||||||
|
user_data = <<-EOF
|
||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
apt-get update
|
||||||
|
apt-get install -y wget
|
||||||
|
cd /opt
|
||||||
|
wget https://github.com/prometheus/node_exporter/releases/download/v1.7.0/node_exporter-1.7.0.linux-amd64.tar.gz
|
||||||
|
tar xvf node_exporter-1.7.0.linux-amd64.tar.gz
|
||||||
|
mv node_exporter-1.7.0.linux-amd64/node_exporter /usr/local/bin/
|
||||||
|
rm -rf node_exporter-1.7.0.linux-amd64*
|
||||||
|
cat > /etc/systemd/system/node_exporter.service <<EOL
|
||||||
|
[Unit]
|
||||||
|
Description=Node Exporter
|
||||||
|
After=network.target
|
||||||
|
[Service]
|
||||||
|
User=nobody
|
||||||
|
Group=nogroup
|
||||||
|
Type=simple
|
||||||
|
ExecStart=/usr/local/bin/node_exporter
|
||||||
|
Restart=always
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
EOL
|
||||||
|
systemctl daemon-reload
|
||||||
|
systemctl enable node_exporter
|
||||||
|
systemctl start node_exporter
|
||||||
|
echo "App VM ${count.index + 1} ready"
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "vkcs_compute_instance" "monitoring" {
|
||||||
|
depends_on = [vkcs_compute_instance.app]
|
||||||
|
|
||||||
|
name = "monitoring-vm"
|
||||||
|
flavor_id = data.vkcs_compute_flavor.vm.id
|
||||||
|
key_pair = vkcs_compute_keypair.monitoring.name
|
||||||
|
availability_zone = var.availability_zone
|
||||||
|
|
||||||
|
block_device {
|
||||||
|
uuid = data.vkcs_images_image.ubuntu.id
|
||||||
|
source_type = "image"
|
||||||
|
destination_type = "volume"
|
||||||
|
volume_type = "ceph-ssd"
|
||||||
|
volume_size = 10
|
||||||
|
boot_index = 0
|
||||||
|
delete_on_termination = true
|
||||||
|
}
|
||||||
|
|
||||||
|
network {
|
||||||
|
uuid = vkcs_networking_network.internal.id
|
||||||
|
}
|
||||||
|
|
||||||
|
security_groups = [vkcs_networking_secgroup.monitoring_sg.name]
|
||||||
|
|
||||||
|
user_data = <<-EOF
|
||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
exec > >(tee /var/log/user_data.log) 2>&1
|
||||||
|
|
||||||
|
# --- Устанавливаем пароль для ubuntu ---
|
||||||
|
echo "ubuntu:debian" | chpasswd
|
||||||
|
|
||||||
|
# --- Включаем парольный SSH ---
|
||||||
|
sed -i 's/^#PasswordAuthentication yes/PasswordAuthentication yes/' /etc/ssh/sshd_config
|
||||||
|
sed -i 's/^PasswordAuthentication no/PasswordAuthentication yes/' /etc/ssh/sshd_config
|
||||||
|
systemctl restart ssh
|
||||||
|
|
||||||
|
# --- Установка Prometheus, Grafana, Node Exporter ---
|
||||||
|
apt-get update
|
||||||
|
apt-get install -y wget curl software-properties-common
|
||||||
|
|
||||||
|
cd /opt
|
||||||
|
wget https://github.com/prometheus/prometheus/releases/download/v2.48.0/prometheus-2.48.0.linux-amd64.tar.gz
|
||||||
|
tar xvf prometheus-2.48.0.linux-amd64.tar.gz
|
||||||
|
mv prometheus-2.48.0.linux-amd64 prometheus
|
||||||
|
useradd --no-create-home --shell /bin/false prometheus
|
||||||
|
chown -R prometheus:prometheus /opt/prometheus
|
||||||
|
|
||||||
|
# Создаём папку для данных и даём права
|
||||||
|
mkdir -p /opt/prometheus/data
|
||||||
|
chown -R prometheus:prometheus /opt/prometheus/data
|
||||||
|
|
||||||
|
cat > /opt/prometheus/prometheus.yml <<EOL
|
||||||
|
global:
|
||||||
|
scrape_interval: 15s
|
||||||
|
scrape_configs:
|
||||||
|
- job_name: 'node'
|
||||||
|
static_configs:
|
||||||
|
- targets: []
|
||||||
|
EOL
|
||||||
|
|
||||||
|
cat > /etc/systemd/system/prometheus.service <<EOL
|
||||||
|
[Unit]
|
||||||
|
Description=Prometheus
|
||||||
|
After=network.target
|
||||||
|
[Service]
|
||||||
|
User=prometheus
|
||||||
|
Group=prometheus
|
||||||
|
Type=simple
|
||||||
|
ExecStart=/opt/prometheus/prometheus --config.file=/opt/prometheus/prometheus.yml --web.listen-address=0.0.0.0:9090 --storage.tsdb.path=/opt/prometheus/data
|
||||||
|
Restart=always
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
EOL
|
||||||
|
|
||||||
|
systemctl daemon-reload
|
||||||
|
systemctl enable prometheus
|
||||||
|
systemctl start prometheus
|
||||||
|
|
||||||
|
# --- Grafana (установка через deb, чтобы избежать проблем с репозиторием) ---
|
||||||
|
cd /tmp
|
||||||
|
wget https://dl.grafana.com/oss/release/grafana_11.3.0_amd64.deb
|
||||||
|
dpkg -i grafana_11.3.0_amd64.deb || apt-get install -f -y
|
||||||
|
systemctl enable grafana-server
|
||||||
|
systemctl start grafana-server
|
||||||
|
|
||||||
|
# --- Node Exporter ---
|
||||||
|
cd /opt
|
||||||
|
wget https://github.com/prometheus/node_exporter/releases/download/v1.7.0/node_exporter-1.7.0.linux-amd64.tar.gz
|
||||||
|
tar xvf node_exporter-1.7.0.linux-amd64.tar.gz
|
||||||
|
mv node_exporter-1.7.0.linux-amd64/node_exporter /usr/local/bin/
|
||||||
|
rm -rf node_exporter-1.7.0.linux-amd64*
|
||||||
|
|
||||||
|
cat > /etc/systemd/system/node_exporter.service <<EOL
|
||||||
|
[Unit]
|
||||||
|
Description=Node Exporter
|
||||||
|
After=network.target
|
||||||
|
[Service]
|
||||||
|
User=nobody
|
||||||
|
Group=nogroup
|
||||||
|
Type=simple
|
||||||
|
ExecStart=/usr/local/bin/node_exporter
|
||||||
|
Restart=always
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
EOL
|
||||||
|
|
||||||
|
systemctl daemon-reload
|
||||||
|
systemctl enable node_exporter
|
||||||
|
systemctl start node_exporter
|
||||||
|
|
||||||
|
echo "=== user_data finished ==="
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "vkcs_networking_floatingip" "monitoring_fip" {
|
||||||
|
pool = data.vkcs_networking_network.extnet.name
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "vkcs_compute_floatingip_associate" "monitoring_fip_assoc" {
|
||||||
|
floating_ip = vkcs_networking_floatingip.monitoring_fip.address
|
||||||
|
instance_id = vkcs_compute_instance.monitoring.id
|
||||||
|
}
|
||||||
|
|
||||||
|
output "monitoring_ip" {
|
||||||
|
value = vkcs_networking_floatingip.monitoring_fip.address
|
||||||
|
}
|
||||||
|
|
||||||
|
output "app_ips" {
|
||||||
|
value = vkcs_compute_instance.app[*].access_ip_v4
|
||||||
|
}
|
||||||
|
|
||||||
|
output "grafana_url" {
|
||||||
|
value = "http://${vkcs_networking_floatingip.monitoring_fip.address}:3000"
|
||||||
|
}
|
||||||
|
|
||||||
|
output "prometheus_url" {
|
||||||
|
value = "http://${vkcs_networking_floatingip.monitoring_fip.address}:9090"
|
||||||
|
}
|
||||||
|
|
||||||
|
output "ssh_password" {
|
||||||
|
value = "debian"
|
||||||
|
description = "Логин: ubuntu, пароль: debian"
|
||||||
|
}
|
||||||
@@ -0,0 +1,130 @@
|
|||||||
|
name: Terraform CI/CD
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ "main" ]
|
||||||
|
pull_request:
|
||||||
|
branches: [ "main" ]
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
env:
|
||||||
|
TF_ROOT: terraform
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
plan:
|
||||||
|
name: Terraform Plan
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
pull-requests: write
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: hashicorp/setup-terraform@v3
|
||||||
|
with:
|
||||||
|
terraform_version: "1.5.0"
|
||||||
|
|
||||||
|
- name: Create SSH public key
|
||||||
|
run: |
|
||||||
|
mkdir -p ~/.ssh
|
||||||
|
echo "${{ secrets.SSH_PUBLIC_KEY }}" > ~/.ssh/id_rsa.pub
|
||||||
|
chmod 644 ~/.ssh/id_rsa.pub
|
||||||
|
|
||||||
|
- name: Terraform Init
|
||||||
|
run: terraform init
|
||||||
|
working-directory: ${{ env.TF_ROOT }}
|
||||||
|
env:
|
||||||
|
TF_VAR_vkcs_username: ${{ secrets.VKCS_USERNAME }}
|
||||||
|
TF_VAR_vkcs_password: ${{ secrets.VKCS_PASSWORD }}
|
||||||
|
TF_VAR_vkcs_project_id: ${{ secrets.VKCS_PROJECT_ID }}
|
||||||
|
TF_VAR_vkcs_region: ${{ secrets.VKCS_REGION }}
|
||||||
|
TF_VAR_vkcs_auth_url: ${{ secrets.VKCS_AUTH_URL }}
|
||||||
|
|
||||||
|
- name: Terraform Validate
|
||||||
|
run: terraform validate
|
||||||
|
working-directory: ${{ env.TF_ROOT }}
|
||||||
|
env:
|
||||||
|
TF_VAR_vkcs_username: ${{ secrets.VKCS_USERNAME }}
|
||||||
|
TF_VAR_vkcs_password: ${{ secrets.VKCS_PASSWORD }}
|
||||||
|
TF_VAR_vkcs_project_id: ${{ secrets.VKCS_PROJECT_ID }}
|
||||||
|
TF_VAR_vkcs_region: ${{ secrets.VKCS_REGION }}
|
||||||
|
TF_VAR_vkcs_auth_url: ${{ secrets.VKCS_AUTH_URL }}
|
||||||
|
|
||||||
|
- name: Terraform Plan
|
||||||
|
id: plan
|
||||||
|
run: terraform plan -out=tfplan
|
||||||
|
working-directory: ${{ env.TF_ROOT }}
|
||||||
|
env:
|
||||||
|
TF_VAR_vkcs_username: ${{ secrets.VKCS_USERNAME }}
|
||||||
|
TF_VAR_vkcs_password: ${{ secrets.VKCS_PASSWORD }}
|
||||||
|
TF_VAR_vkcs_project_id: ${{ secrets.VKCS_PROJECT_ID }}
|
||||||
|
TF_VAR_vkcs_region: ${{ secrets.VKCS_REGION }}
|
||||||
|
TF_VAR_vkcs_auth_url: ${{ secrets.VKCS_AUTH_URL }}
|
||||||
|
TF_VAR_my_ip: ${{ secrets.MY_IP }}
|
||||||
|
TF_VAR_ssh_public_key: "~/.ssh/id_rsa.pub"
|
||||||
|
|
||||||
|
- name: Upload Plan
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: tfplan
|
||||||
|
path: ${{ env.TF_ROOT }}/tfplan
|
||||||
|
|
||||||
|
- name: Comment Plan on PR
|
||||||
|
if: github.event_name == 'pull_request'
|
||||||
|
uses: actions/github-script@v7
|
||||||
|
with:
|
||||||
|
script: |
|
||||||
|
const planOutput = `${{ steps.plan.outputs.stdout }}`;
|
||||||
|
const truncated = planOutput.length > 60000 ? planOutput.substring(0, 60000) + '\n... (truncated)' : planOutput;
|
||||||
|
github.rest.issues.createComment({
|
||||||
|
issue_number: context.issue.number,
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
body: `### Terraform Plan Output\n\`\`\`\n${truncated}\n\`\`\``
|
||||||
|
});
|
||||||
|
|
||||||
|
apply:
|
||||||
|
name: Terraform Apply
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: plan
|
||||||
|
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
||||||
|
environment: production
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: hashicorp/setup-terraform@v3
|
||||||
|
with:
|
||||||
|
terraform_version: "1.5.0"
|
||||||
|
|
||||||
|
- name: Create SSH public key
|
||||||
|
run: |
|
||||||
|
mkdir -p ~/.ssh
|
||||||
|
echo "${{ secrets.SSH_PUBLIC_KEY }}" > ~/.ssh/id_rsa.pub
|
||||||
|
chmod 644 ~/.ssh/id_rsa.pub
|
||||||
|
|
||||||
|
- name: Download Plan
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: tfplan
|
||||||
|
path: ${{ env.TF_ROOT }}
|
||||||
|
|
||||||
|
- name: Terraform Init
|
||||||
|
run: terraform init
|
||||||
|
working-directory: ${{ env.TF_ROOT }}
|
||||||
|
env:
|
||||||
|
TF_VAR_vkcs_username: ${{ secrets.VKCS_USERNAME }}
|
||||||
|
TF_VAR_vkcs_password: ${{ secrets.VKCS_PASSWORD }}
|
||||||
|
TF_VAR_vkcs_project_id: ${{ secrets.VKCS_PROJECT_ID }}
|
||||||
|
TF_VAR_vkcs_region: ${{ secrets.VKCS_REGION }}
|
||||||
|
TF_VAR_vkcs_auth_url: ${{ secrets.VKCS_AUTH_URL }}
|
||||||
|
|
||||||
|
- name: Terraform Apply
|
||||||
|
run: terraform apply -auto-approve tfplan
|
||||||
|
working-directory: ${{ env.TF_ROOT }}
|
||||||
|
env:
|
||||||
|
TF_VAR_vkcs_username: ${{ secrets.VKCS_USERNAME }}
|
||||||
|
TF_VAR_vkcs_password: ${{ secrets.VKCS_PASSWORD }}
|
||||||
|
TF_VAR_vkcs_project_id: ${{ secrets.VKCS_PROJECT_ID }}
|
||||||
|
TF_VAR_vkcs_region: ${{ secrets.VKCS_REGION }}
|
||||||
|
TF_VAR_vkcs_auth_url: ${{ secrets.VKCS_AUTH_URL }}
|
||||||
|
TF_VAR_my_ip: ${{ secrets.MY_IP }}
|
||||||
|
TF_VAR_ssh_public_key: "~/.ssh/id_rsa.pub"
|
||||||
|
After Width: | Height: | Size: 259 KiB |
|
After Width: | Height: | Size: 180 KiB |
|
After Width: | Height: | Size: 122 KiB |