# Глобальные переменные IMAGE ?= ansible TAG ?= 0.1 REGISTRY ?= inecs/ansible # По умолчанию используем docker. Для локальной разработки используйте docker-compose RUN_MODE ?= docker # Определение команды RUN в зависимости от RUN_MODE ifeq ($(RUN_MODE), docker-compose) RUN = docker compose run --rm $(IMAGE) else ifeq ($(RUN_MODE), docker) RUN = docker run -it --rm \ --name $(IMAGE) \ -v $(PWD):/ansible \ -v /var/run/docker.sock:/var/run/docker.sock \ -v ~/.ssh/id_rsa:/root/.ssh/id_rsa:ro \ -e ANSIBLE_VAULT_PASSWORD_FILE=/ansible/vault-password.txt \ --privileged \ --workdir /ansible \ $(REGISTRY)/$(IMAGE) else $(error Invalid RUN_MODE. Use "docker-compose" or "docker") endif view create edit show delete test lint deploy new init build rebuild prune release images push pull shell: @true #################################################################################################### # Инициализация новой роли #################################################################################################### init: @echo "Шаг 1: Создание Docker-образа..." @make docker build @echo "Шаг 2: Создание Docker-образов для запуска Molecule..." @make docker images @echo "Шаг 3: Создание нового vault-файла с паролем..." @read -p "Введите пароль для vault: " VAULT_PASSWORD; \ echo "$$VAULT_PASSWORD" > vault-password.txt; \ make vault create @echo "Шаг 4: Создание нового брэнча в гите..." @make git new @echo "Шаг 5: Создание новой роли..." @make role new #################################################################################################### # Управление контейнерами с помощью docker compose или docker run #################################################################################################### docker: @case "$(word 2, $(MAKECMDGOALS))" in \ build) \ docker buildx create --use --name multiarch-builder --driver docker-container; \ if [ "$(RUN_MODE)" = "docker-compose" ]; then \ docker compose build $(c); \ else \ docker build -t $(REGISTRY)/$(IMAGE) .; \ fi;; \ rebuild) \ docker buildx create --use --name multiarch-builder --driver docker-container; \ if [ "$(RUN_MODE)" = "docker-compose" ]; then \ docker compose build --no-cache $(c); \ else \ docker build --no-cache -t $(REGISTRY)/$(IMAGE) .; \ fi;; \ prune) \ docker system prune -af;; \ shell) \ clear; \ echo "Entering to Ansible container shell..."; \ $(RUN) bash ;; \ release) \ docker buildx create --use --name multiarch-builder --driver docker-container; \ docker login $(REGISTRY); \ docker buildx build -t $(REGISTRY)/$(IMAGE):$(TAG) -t $(REGISTRY)/$(IMAGE):latest --platform linux/amd64,linux/arm64 --push .;; \ images) \ docker buildx create --use --name multiarch-builder --driver docker-container; \ echo "Логинимся в Docker Hub..."; \ docker login; \ echo "Собираем и пушим основной Ansible образ..."; \ docker buildx build -t $(REGISTRY)/$(IMAGE):$(TAG) -t $(REGISTRY)/$(IMAGE):latest --platform linux/amd64,linux/arm64 --push .; \ echo "Собираем и пушим образ CentOS..."; \ docker buildx build -t $(REGISTRY):centos --platform linux/amd64,linux/arm64 --push -f Dockerfile-CentOS .; \ echo "Собираем и пушим образ Ubuntu..."; \ docker buildx build -t $(REGISTRY):ubuntu --platform linux/amd64,linux/arm64 --push -f Dockerfile-Ubuntu .; \ echo "Образы успешно опубликованы в Docker Hub: $(REGISTRY)";; \ *) echo "Unknown action. Available actions: build, rebuild, prune, release";; \ esac #################################################################################################### # Работа с ролью #################################################################################################### vault: @case "$(word 2, $(MAKECMDGOALS))" in \ show) $(RUN) bash -c "ansible-vault view --vault-password-file vault-password.txt vars/secrets.yml";; \ create) $(RUN) bash -c "ansible-vault create --encrypt-vault-id default --vault-password-file vault-password.txt vars/secrets.yml";; \ edit) $(RUN) bash -c "ansible-vault edit --vault-password-file vault-password.txt vars/secrets.yml";; \ delete) $(RUN) bash -c "rm vars/secrets.yml";; \ rekey) $(RUN) bash -c "ansible-vault rekey --vault-password-file vault-password.txt vars/secrets.yml";; \ decrypt) $(RUN) bash -c "ansible-vault decrypt --vault-password-file vault-password.txt vars/secrets.yml";; \ encrypt) $(RUN) bash -c "ansible-vault encrypt --encrypt-vault-id default --vault-password-file vault-password.txt vars/secrets.yml";; \ *) echo "Unknown action";; \ esac role: @case "$(word 2, $(MAKECMDGOALS))" in \ new) \ clear; \ echo "Введите название новой роли на английском:"; \ read ROLE_NAME; \ echo "Введите описание роли:"; \ read ROLE_DESC; \ cp -r default/ "roles/$${ROLE_NAME}"; \ printf "\n- name: $${ROLE_DESC}" >> roles/deploy.yaml; \ printf "\n import_playbook: $${ROLE_NAME}/deploy.yaml" >> roles/deploy.yaml; \ printf '\n - ../../roles/%s' "$$ROLE_NAME" >> molecule/default/converge.yml; \ printf "\n - $${ROLE_NAME}" >> roles/$$ROLE_NAME/deploy.yaml;; \ lint) \ clear; \ echo "Check your role..."; \ $(RUN) bash -c "ansible-vault decrypt --vault-password-file vault-password.txt vars/secrets.yml"; \ $(RUN) bash -c "ansible-lint roles/*"; \ $(RUN) bash -c "ansible-vault encrypt vars/secrets.yml --encrypt-vault-id default --vault-password-file vault-password.txt";; \ test) \ clear; \ echo "Running test roles..."; \ $(RUN) bash -c "ansible-vault decrypt --vault-password-file vault-password.txt vars/secrets.yml"; \ $(RUN) bash -c "docker login $(REGISTRY) && molecule test --parallel --destroy=always"; \ $(RUN) bash -c "ansible-vault encrypt vars/secrets.yml --encrypt-vault-id default --vault-password-file vault-password.txt";; \ deploy) \ clear; \ echo "Deploying roles to production..."; \ $(RUN) bash -c "ansible-playbook roles/deploy.yaml";; \ *) echo "Unknown action";; \ esac #################################################################################################### # Работа с Git #################################################################################################### git: @case "$(word 2, $(MAKECMDGOALS))" in \ push) \ git branch; \ read -p "Выберите ветку для пуша: " BRANCH; \ read -p "Введите описание коммита: " COMMIT; \ commitname=$$COMMIT; \ git add . ; \ git commit -m "$$commitname"; \ git push -u origin $$BRANCH; \ echo "Изменения внесены в Git";; \ pull) \ git pull;; \ new) \ read -p "Введите имя новой ветки: " BRANCH_NAME; \ NEW_BRANCH="$$BRANCH_NAME"; \ git checkout -b $$NEW_BRANCH; \ echo "Создана и переключена на новую ветку: $$NEW_BRANCH";; \ *) echo "Unknown action. Available actions: push, pull, cluster-branch";; \ esac # ====== УНИВЕРСАЛЬНАЯ ЛАБОРАТОРИЯ (Molecule universal) ====== SCENARIO ?= universal COMPOSE ?= docker compose lab-up: ## Поднять контроллер $(COMPOSE) up -d lab-down: ## Погасить контроллер $(COMPOSE) down -v lab-sh: ## Войти в контроллер docker exec -it ansible-controller bash lab-test: lab-up ## Полный цикл Molecule (create+converge+verify+destroy) docker exec -e MOLECULE_EPHEMERAL_DIRECTORY=/tmp/molecule ansible-controller \ bash -lc 'cd /ansible && molecule test -s $(SCENARIO)' lab-create: lab-up ## Создать инфраструктуру лаборатории docker exec -e MOLECULE_EPHEMERAL_DIRECTORY=/tmp/molecule ansible-controller \ bash -lc 'cd /ansible && molecule create -s $(SCENARIO)' lab-converge: ## Запустить роли в лаборатории docker exec -e MOLECULE_EPHEMERAL_DIRECTORY=/tmp/molecule ansible-controller \ bash -lc 'cd /ansible && molecule converge -s $(SCENARIO)' lab-verify: ## Проверить работу лаборатории docker exec -e MOLECULE_EPHEMERAL_DIRECTORY=/tmp/molecule ansible-controller \ bash -lc 'cd /ansible && molecule verify -s $(SCENARIO)' lab-destroy: ## Уничтожить инфраструктуру лаборатории docker exec -e MOLECULE_EPHEMERAL_DIRECTORY=/tmp/molecule ansible-controller \ bash -lc 'cd /ansible && molecule destroy -s $(SCENARIO)' lab-reset: lab-destroy lab-down lab-up ## Полный сброс лаборатории # ====== K8S ХЕЛПЕРЫ ====== kube-sh: ## Shell с kubectl/helm/istioctl внутри контейнера docker exec -it ansible-controller bash kube-cmd: ## make kube-cmd CLUSTER=lab CMD="get pods -A" ifeq ($(strip $(CLUSTER)),) @echo "Usage: make kube-cmd CLUSTER=lab CMD=\"get pods -A\""; exit 1 endif docker exec -it ansible-controller bash -lc 'kubectl --context kind-$(CLUSTER) $(CMD)' kube-enter: ## make kube-enter CLUSTER=lab ifeq ($(strip $(CLUSTER)),) @echo "Usage: make kube-enter CLUSTER=lab"; exit 1 endif docker exec -it ansible-controller bash -lc '\ POD=$$(kubectl --context kind-$(CLUSTER) -n lab-demo get pod -l app=toolbox -o jsonpath="{.items[0].metadata.name}"); \ [ -n "$$POD" ] || { echo "toolbox pod not found"; exit 1; }; \ kubectl --context kind-$(CLUSTER) -n lab-demo exec -it $$POD -- /bin/sh' # Port-forward Kiali (http://localhost:20001) kiali-port-forward: ## make kiali-port-forward CLUSTER=lab ifeq ($(strip $(CLUSTER)),) @echo "Usage: make kiali-port-forward CLUSTER=lab"; exit 1 endif docker exec -d ansible-controller bash -lc 'kubectl --context kind-$(CLUSTER) -n istio-system port-forward svc/kiali 20001:20001' # Port-forward Istio IngressGateway (HTTP 8082, HTTPS 8444) istio-gw-port-forward: ## make istio-gw-port-forward CLUSTER=lab ifeq ($(strip $(CLUSTER)),) @echo "Usage: make istio-gw-port-forward CLUSTER=lab"; exit 1 endif docker exec -d ansible-controller bash -lc 'kubectl --context kind-$(CLUSTER) -n istio-system port-forward svc/istio-ingressgateway 8082:80 8444:443' @echo "Istio GW forwarded: http://localhost:8082 https://localhost:8444" # Port-forward Grafana (http://localhost:3000) grafana-port-forward: ## make grafana-port-forward CLUSTER=lab ifeq ($(strip $(CLUSTER)),) @echo "Usage: make grafana-port-forward CLUSTER=lab"; exit 1 endif docker exec -d ansible-controller bash -lc 'kubectl --context kind-$(CLUSTER) -n monitoring port-forward svc/monitoring-grafana 3000:80' @echo "Grafana: http://localhost:3000 (admin/admin)" # Port-forward Prometheus (http://localhost:9090) prom-port-forward: ## make prom-port-forward CLUSTER=lab ifeq ($(strip $(CLUSTER)),) @echo "Usage: make prom-port-forward CLUSTER=lab"; exit 1 endif docker exec -d ansible-controller bash -lc 'kubectl --context kind-$(CLUSTER) -n monitoring port-forward svc/monitoring-kube-prometheus-prometheus 9090:9090' @echo "Prometheus: http://localhost:9090" # Stop all port-forwards kube-pf-stop: ## убить все port-forward в контроллере docker exec -it ansible-controller bash -lc 'pkill -f "kubectl .* port-forward" || true' # ====== ОТЧЕТЫ ====== lab-report: ## Сгенерировать HTML отчет docker exec ansible-controller bash -lc 'python3 /ansible/scripts/report_html.py /ansible/reports/lab-health.json /ansible/reports/lab-report.html' @echo "HTML report: reports/lab-report.html" # ====== ДОПОЛНИТЕЛЬНЫЕ ХЕЛПЕРЫ ====== bookinfo-url: ## echo productpage URL via Istio Gateway (needs istio-gw-port-forward first) @echo "Open: http://localhost:8082/productpage" grafana-open: ## echo URL to Grafana + hint dashboards @echo "Grafana: http://localhost:3000 (admin/admin)" @echo "Dashboards:" @echo " - Istio • Overview (uid: istio-overview)" @echo " - Service • SLI (uid: service-sli)" # ====== СНАПШОТЫ И ОЧИСТКА ====== lab-snapshot: ## Сохранить снапшот лаборатории bash scripts/snapshot.sh lab-restore: ## Восстановить из снапшота bash scripts/restore.sh lab-cleanup: ## Очистить лабораторию bash scripts/cleanup.sh