diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..9aee960 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,2 @@ +.github + diff --git a/.github/workflows/ansible-test.yml b/.github/workflows/ansible-test.yml deleted file mode 100644 index b7a9614..0000000 --- a/.github/workflows/ansible-test.yml +++ /dev/null @@ -1,44 +0,0 @@ -name: Ansible Testing -on: [push, pull_request] - -jobs: - lint: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: Setup Python - uses: actions/setup-python@v4 - with: - python-version: '3.11' - - name: Install dependencies - run: | - pip install ansible ansible-lint - ansible-galaxy collection install -r requirements.yml - - name: Run lint - run: make role lint - - test: - runs-on: ubuntu-latest - needs: lint - strategy: - matrix: - preset: [minimal, default, performance] - steps: - - uses: actions/checkout@v4 - - name: Setup Docker - run: | - sudo systemctl start docker - sudo usermod -aG docker $USER - - name: Run tests - run: make role test ${{ matrix.preset }} - - deploy-check: - runs-on: ubuntu-latest - needs: [lint, test] - if: github.ref == 'refs/heads/main' - steps: - - uses: actions/checkout@v4 - - name: Check deployment - run: make role deploy - env: - ANSIBLE_HOST_KEY_CHECKING: false diff --git a/.gitignore b/.gitignore index ea9bb01..0b461c0 100644 --- a/.gitignore +++ b/.gitignore @@ -180,3 +180,6 @@ cython_debug/ # Cursor IDE .cursor/ +# Kubernetes kubeconfig +kubeconfig + diff --git a/Makefile b/Makefile index 30e3526..723f8b4 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ # ============================================================================= -# AnsibleLab - Универсальная система тестирования Ansible ролей +# DevOpsLab - Универсальная система тестирования Ansible ролей # Автор: Сергей Антропов # Сайт: https://devops.org.ru # ============================================================================= @@ -20,11 +20,12 @@ WHITE := \033[0;37m RESET := \033[0m # Глобальные переменные -PROJECT_NAME ?= ansible-lab +PROJECT_NAME ?= devops-lab VERSION ?= 0.1.0 AUTHOR ?= "Сергей Антропов" SITE ?= "https://devops.org.ru" DOCKER_IMAGE ?= inecs/ansible-lab:ansible-controller-latest +DOCKER_K8S_IMAGE ?= inecs/ansible-lab:k8s-latest DOCKER_DIND_IMAGE ?= docker:27-dind CONTAINER_NAME ?= ansible-controller @@ -40,7 +41,7 @@ DOCKER_BUILDX_BUILDER ?= multiarch-builder # Базовые образы и их теги BASE_IMAGES := altlinux/p9 astralinux/astra-1.7 redos/redos:9 registry.access.redhat.com/ubi8/ubi centos:7 quay.io/centos/centos:8 quay.io/centos/centos:stream9 almalinux:8 rockylinux:8 ubuntu:20.04 ubuntu:22.04 ubuntu:24.04 debian:9 debian:10 debian:11 debian:bookworm -.PHONY: role vault git docker presets controller help update-playbooks generate-docs setup-cicd list create delete +.PHONY: role vault git docker presets controller k8s help update-playbooks generate-docs setup-cicd list create delete # ============================================================================= # КОМАНДЫ ДЛЯ РАБОТЫ С РОЛЯМИ @@ -914,11 +915,15 @@ docker-get-base-tag: TAG=$$(docker inspect --format='{{.RepoTags}}' $$BASE_IMAGE 2>/dev/null | tr -d '[]' | cut -d',' -f1 | cut -d':' -f2 | tr -d ' ' || echo "latest");; \ ansible-controller) \ TAG="latest";; \ - *) \ - echo "❌ Неизвестный образ: $(IMAGE)"; \ - exit 1;; \ - esac; \ - echo "$$TAG" + k8s) \ + TAG="latest";; \ + k8s-portforward) \ + TAG="latest";; \ + *) \ + echo "❌ Неизвестный образ: $(IMAGE)"; \ + exit 1;; \ +esac; \ +echo "$$TAG" # Сборка одного образа с multi-arch docker-build-image: @@ -1022,12 +1027,428 @@ controller: echo " 💡 Удаляет: контейнеры и сети";; \ esac +# ============================================================================= +# КОМАНДЫ ДЛЯ РАБОТЫ С KUBERNETES KIND +# ============================================================================= +k8s: + @case "$(word 2, $(MAKECMDGOALS))" in \ + create) \ + echo "☸️ Создание Kind кластера..."; \ + PRESET_ARG="$(word 3, $(MAKECMDGOALS))"; \ + if [ -z "$$PRESET_ARG" ]; then \ + PRESET=k8s-minimal; \ + echo "📋 Используется preset по умолчанию: $$PRESET (минимальный без аддонов)"; \ + else \ + PRESET=$$PRESET_ARG; \ + echo "📋 Используется preset: $$PRESET"; \ + fi; \ + if [ ! -f "molecule/presets/k8s/$$PRESET.yml" ]; then \ + echo "❌ Ошибка: Пресет '$$PRESET' не найден!"; \ + echo "💡 Доступные пресеты:"; \ + ls -1 molecule/presets/k8s/*.yml 2>/dev/null | sed 's|molecule/presets/k8s/||g' | sed 's|\.yml||g' | sed 's/^/ - /' || echo " - k8s-minimal"; \ + exit 1; \ + fi; \ + CONTAINER_NAME=k8s-controller; \ + docker run -d --name $$CONTAINER_NAME --rm \ + -v "$(PWD):/workspace" -w /workspace \ + -v /var/run/docker.sock:/var/run/docker.sock \ + -u root \ + -e ANSIBLE_FORCE_COLOR=1 \ + -e MOLECULE_PRESET=$$PRESET \ + -e MOLECULE_EPHEMERAL_DIRECTORY=/tmp/molecule_workspace \ + $(DOCKER_K8S_IMAGE) \ + /bin/bash -c 'sleep infinity'; \ + echo "🚀 Запуск создания кластера..."; \ + docker exec $$CONTAINER_NAME bash -c "cd /workspace && python3 /workspace/scripts/create_k8s_cluster.py molecule/presets/k8s/$$PRESET.yml $$CONTAINER_NAME"; \ + echo "✅ Kind кластер создан"; \ + echo "💡 Для создания port-forward: make k8s portforward create"; \ + echo "💡 Для подключения используйте: make k8s kubeconfig"; \ + echo "💡 Для остановки используйте: make k8s stop";; \ + destroy) \ + echo "🗑️ Удаление Kind кластера и контейнеров..."; \ + PRESET_ARG="$(word 3, $(MAKECMDGOALS))"; \ + PRESET=$${PRESET_ARG:-k8s-minimal}; \ + CONTAINER_NAME=k8s-controller; \ + echo "🔌 Очистка port-forward..."; \ + python3 scripts/portforward.py clear || echo "⚠️ Не удалось очистить port-forward"; \ + if docker ps | grep -q $$CONTAINER_NAME; then \ + echo "🗑️ Удаление Kind кластеров..."; \ + docker exec $$CONTAINER_NAME bash -c "kind delete clusters --all" 2>/dev/null || true; \ + else \ + echo "⚠️ Контейнер $$CONTAINER_NAME не запущен"; \ + fi; \ + docker rm -f $$CONTAINER_NAME 2>/dev/null || true; \ + echo "🗑️ Удаление контейнеров из пресета..."; \ + if [ -f "molecule/presets/k8s/$$PRESET.yml" ]; then \ + if docker ps | grep -q $$CONTAINER_NAME; then \ + docker exec $$CONTAINER_NAME bash -c "python3 /workspace/scripts/delete_hosts.py /workspace/molecule/presets/k8s/$$PRESET.yml" 2>/dev/null || true; \ + else \ + python3 scripts/delete_hosts.py molecule/presets/k8s/$$PRESET.yml 2>/dev/null || true; \ + fi; \ + fi; \ + echo "✅ Удаление завершено";; \ + stop) \ + echo "🛑 Остановка Kind кластера..."; \ + PRESET_ARG="$(word 3, $(MAKECMDGOALS))"; \ + if [ -z "$$PRESET_ARG" ]; then \ + echo "❌ Ошибка: Укажите пресет"; \ + echo "💡 Пример: make k8s stop kubernetes"; \ + exit 1; \ + fi; \ + CONTAINER_NAME=k8s-controller; \ + if docker ps | grep -q $$CONTAINER_NAME; then \ + docker exec $$CONTAINER_NAME bash -c "kind get clusters | xargs -I {} kind stop cluster --name {}" 2>/dev/null || true; \ + echo "✅ Kind кластер остановлен"; \ + else \ + echo "⚠️ Контейнер $$CONTAINER_NAME не запущен"; \ + fi; \ + echo "💡 Кластер остановлен, но не удален"; \ + echo "💡 Для перезапуска: make k8s start $$PRESET_ARG"; \ + echo "💡 Для полного удаления: make k8s destroy $$PRESET_ARG";; \ + start) \ + echo "🚀 Запуск Kind кластера..."; \ + PRESET_ARG="$(word 3, $(MAKECMDGOALS))"; \ + if [ -z "$$PRESET_ARG" ]; then \ + echo "❌ Ошибка: Укажите пресет"; \ + echo "💡 Пример: make k8s start kubernetes"; \ + exit 1; \ + fi; \ + CONTAINER_NAME=k8s-controller; \ + if ! docker ps | grep -q $$CONTAINER_NAME; then \ + echo "❌ Контейнер $$CONTAINER_NAME не запущен"; \ + echo "💡 Запустите: make k8s create $$PRESET_ARG"; \ + exit 1; \ + fi; \ + docker exec $$CONTAINER_NAME bash -c "kind get clusters | xargs -I {} kind start cluster --name {}" 2>/dev/null || true; \ + echo "✅ Kind кластер запущен";; \ + status) \ + echo "📊 Детальный отчет о состоянии кластера..."; \ + PRESET_ARG="$(word 3, $(MAKECMDGOALS))"; \ + if [ -z "$$PRESET_ARG" ]; then \ + echo "❌ Ошибка: Укажите пресет"; \ + echo "💡 Пример: make k8s status kubernetes"; \ + exit 1; \ + fi; \ + CONTAINER_NAME=k8s-controller; \ + if docker ps | grep -q $$CONTAINER_NAME; then \ + python3 scripts/k8s_status.py; \ + else \ + echo "⚠️ Контейнер $$CONTAINER_NAME не запущен"; \ + echo "💡 Запустите: make k8s create $$PRESET_ARG"; \ + fi;; \ + config) \ + echo "📋 Получение kubeconfig..."; \ + PRESET_ARG="$(word 3, $(MAKECMDGOALS))"; \ + if [ -z "$$PRESET_ARG" ]; then \ + echo "❌ Ошибка: Укажите пресет"; \ + echo "💡 Пример: make k8s config kubernetes"; \ + exit 1; \ + fi; \ + CONTAINER_NAME=k8s-controller; \ + if ! docker ps | grep -q $$CONTAINER_NAME; then \ + echo "❌ Контейнер $$CONTAINER_NAME не запущен"; \ + echo "💡 Запустите: make k8s create $$PRESET_ARG"; \ + exit 1; \ + fi; \ + KUBECONFIG_FILE="$$(pwd)/kubeconfig"; \ + docker exec $$CONTAINER_NAME bash -c "kind get kubeconfig" > $$KUBECONFIG_FILE 2>/dev/null || true; \ + if [ -f $$KUBECONFIG_FILE ] && [ -s $$KUBECONFIG_FILE ]; then \ + echo "✅ kubeconfig сохранен в: $$KUBECONFIG_FILE"; \ + echo ""; \ + echo "💡 Для использования:"; \ + echo " export KUBECONFIG=$$KUBECONFIG_FILE"; \ + echo " kubectl get nodes"; \ + echo ""; \ + echo "💡 Или для однократного использования:"; \ + echo " kubectl --kubeconfig=$$KUBECONFIG_FILE get nodes"; \ + else \ + echo "❌ Не удалось получить kubeconfig"; \ + rm -f $$KUBECONFIG_FILE; \ + fi;; \ + nodes) \ + echo "🖥️ Просмотр узлов кластера..."; \ + PRESET_ARG="$(word 3, $(MAKECMDGOALS))"; \ + if [ -z "$$PRESET_ARG" ]; then \ + echo "❌ Ошибка: Укажите пресет"; \ + echo "💡 Пример: make k8s nodes kubernetes"; \ + exit 1; \ + fi; \ + CONTAINER_NAME=k8s-controller; \ + if ! docker ps | grep -q $$CONTAINER_NAME; then \ + echo "❌ Контейнер $$CONTAINER_NAME не запущен"; \ + echo "💡 Запустите: make k8s create $$PRESET_ARG"; \ + exit 1; \ + fi; \ + CLUSTER_NAME=$$(docker exec $$CONTAINER_NAME kind get clusters | head -1); \ + docker exec $$CONTAINER_NAME bash -c "CLUSTER_NAME=$$CLUSTER_NAME; kubectl --server=https://\$${CLUSTER_NAME}-control-plane:6443 --insecure-skip-tls-verify get nodes";; \ + shell) \ + echo "🐚 Открытие shell в контейнере..."; \ + PRESET_ARG="$(word 3, $(MAKECMDGOALS))"; \ + if [ -z "$$PRESET_ARG" ]; then \ + echo "❌ Ошибка: Укажите пресет"; \ + echo "💡 Пример: make k8s shell kubernetes"; \ + exit 1; \ + fi; \ + CONTAINER_NAME=k8s-controller; \ + if docker ps | grep -q $$CONTAINER_NAME; then \ + docker exec -it $$CONTAINER_NAME bash; \ + else \ + echo "❌ Контейнер $$CONTAINER_NAME не запущен"; \ + echo "💡 Запустите: make k8s create $$PRESET_ARG"; \ + fi;; \ + manifest) \ + echo "📄 Работа с манифестами..."; \ + MANIFEST_CMD="$(word 3, $(MAKECMDGOALS))"; \ + PRESET_ARG="$(word 4, $(MAKECMDGOALS))"; \ + MANIFEST_ARG="$(word 5, $(MAKECMDGOALS))"; \ + if [ -z "$$MANIFEST_CMD" ] || [ -z "$$PRESET_ARG" ] || [ -z "$$MANIFEST_ARG" ]; then \ + echo "❌ Ошибка: Укажите команду, пресет и путь к манифесту"; \ + echo "💡 Пример: make k8s manifest apply kubernetes https://example.com/manifest.yaml"; \ + exit 1; \ + fi; \ + CONTAINER_NAME=k8s-controller; \ + if ! docker ps | grep -q $$CONTAINER_NAME; then \ + echo "❌ Контейнер $$CONTAINER_NAME не запущен"; \ + echo "💡 Запустите: make k8s create $$PRESET_ARG"; \ + exit 1; \ + fi; \ + CLUSTER_NAME=$$(docker exec $$CONTAINER_NAME kind get clusters | head -1); \ + case "$$MANIFEST_CMD" in \ + apply) \ + echo "📥 Применение манифеста: $$MANIFEST_ARG"; \ + docker exec $$CONTAINER_NAME bash -c "CLUSTER_NAME=$$CLUSTER_NAME; kubectl --server=https://\$${CLUSTER_NAME}-control-plane:6443 --insecure-skip-tls-verify apply -f $$MANIFEST_ARG";; \ + delete) \ + echo "🗑️ Удаление ресурсов из манифеста: $$MANIFEST_ARG"; \ + docker exec $$CONTAINER_NAME bash -c "CLUSTER_NAME=$$CLUSTER_NAME; kubectl --server=https://\$${CLUSTER_NAME}-control-plane:6443 --insecure-skip-tls-verify delete -f $$MANIFEST_ARG";; \ + *) \ + echo "❌ Неизвестная команда: $$MANIFEST_CMD"; \ + echo "💡 Доступные команды: apply, delete"; \ + exit 1;; \ + esac;; \ + helm) \ + echo "📦 Работа с Helm..."; \ + HELM_CMD="$(word 3, $(MAKECMDGOALS))"; \ + PRESET_ARG="$(word 4, $(MAKECMDGOALS))"; \ + RELEASE_ARG="$(word 5, $(MAKECMDGOALS))"; \ + CHART_ARG="$(word 6, $(MAKECMDGOALS))"; \ + if [ -z "$$HELM_CMD" ] || [ -z "$$PRESET_ARG" ]; then \ + echo "❌ Ошибка: Укажите команду и пресет"; \ + echo "💡 Пример: make k8s helm list kubernetes"; \ + exit 1; \ + fi; \ + CONTAINER_NAME=k8s-controller; \ + if ! docker ps | grep -q $$CONTAINER_NAME; then \ + echo "❌ Контейнер $$CONTAINER_NAME не запущен"; \ + echo "💡 Запустите: make k8s create $$PRESET_ARG"; \ + exit 1; \ + fi; \ + CLUSTER_NAME=$$(docker exec $$CONTAINER_NAME kind get clusters | head -1); \ + case "$$HELM_CMD" in \ + apply) \ + if [ -z "$$RELEASE_ARG" ] || [ -z "$$CHART_ARG" ]; then \ + echo "❌ Ошибка: Укажите имя релиза и чарт"; \ + echo "💡 Пример: make k8s helm apply kubernetes my-release stable/nginx-ingress"; \ + exit 1; \ + fi; \ + echo "📦 Установка Helm чарта: $$CHART_ARG как $$RELEASE_ARG"; \ + docker exec $$CONTAINER_NAME bash -c "CLUSTER_NAME=$$CLUSTER_NAME; helm upgrade --install $$RELEASE_ARG $$CHART_ARG --kube-apiserver=https://\$${CLUSTER_NAME}-control-plane:6443 --kube-token=dummy --kube-context=dummy 2>&1 | grep -v '^WARNING' || true";; \ + delete) \ + if [ -z "$$RELEASE_ARG" ]; then \ + echo "❌ Ошибка: Укажите имя релиза"; \ + echo "💡 Пример: make k8s helm delete kubernetes my-release"; \ + exit 1; \ + fi; \ + echo "🗑️ Удаление Helm релиза: $$RELEASE_ARG"; \ + docker exec $$CONTAINER_NAME bash -c "CLUSTER_NAME=$$CLUSTER_NAME; helm uninstall $$RELEASE_ARG --kube-apiserver=https://\$${CLUSTER_NAME}-control-plane:6443 --kube-token=dummy --kube-context=dummy 2>&1 | grep -v '^WARNING' || true";; \ + update) \ + if [ -z "$$RELEASE_ARG" ] || [ -z "$$CHART_ARG" ]; then \ + echo "❌ Ошибка: Укажите имя релиза и чарт"; \ + echo "💡 Пример: make k8s helm update kubernetes my-release stable/nginx-ingress"; \ + exit 1; \ + fi; \ + echo "🔄 Обновление Helm релиза: $$RELEASE_ARG"; \ + docker exec $$CONTAINER_NAME bash -c "CLUSTER_NAME=$$CLUSTER_NAME; helm upgrade $$RELEASE_ARG $$CHART_ARG --kube-apiserver=https://\$${CLUSTER_NAME}-control-plane:6443 --kube-token=dummy --kube-context=dummy 2>&1 | grep -v '^WARNING' || true";; \ + rollback) \ + if [ -z "$$RELEASE_ARG" ]; then \ + echo "❌ Ошибка: Укажите имя релиза"; \ + echo "💡 Пример: make k8s helm rollback kubernetes my-release"; \ + exit 1; \ + fi; \ + echo "⏪ Откат Helm релиза: $$RELEASE_ARG"; \ + docker exec $$CONTAINER_NAME bash -c "CLUSTER_NAME=$$CLUSTER_NAME; helm rollback $$RELEASE_ARG --kube-apiserver=https://\$${CLUSTER_NAME}-control-plane:6443 --kube-token=dummy --kube-context=dummy 2>&1 | grep -v '^WARNING' || true";; \ + list) \ + echo "📋 Список Helm релизов:"; \ + docker exec $$CONTAINER_NAME bash -c "CLUSTER_NAME=$$CLUSTER_NAME; helm list --kube-apiserver=https://\$${CLUSTER_NAME}-control-plane:6443 --kube-token=dummy --kube-context=dummy --all-namespaces 2>&1 | grep -v '^WARNING' || true";; \ + status) \ + if [ -z "$$RELEASE_ARG" ]; then \ + echo "❌ Ошибка: Укажите имя релиза"; \ + echo "💡 Пример: make k8s helm status kubernetes my-release"; \ + exit 1; \ + fi; \ + echo "📊 Статус Helm релиза: $$RELEASE_ARG"; \ + docker exec $$CONTAINER_NAME bash -c "CLUSTER_NAME=$$CLUSTER_NAME; helm status $$RELEASE_ARG --kube-apiserver=https://\$${CLUSTER_NAME}-control-plane:6443 --kube-token=dummy --kube-context=dummy 2>&1 | grep -v '^WARNING' || true";; \ + *) \ + echo "❌ Неизвестная команда: $$HELM_CMD"; \ + echo "💡 Доступные команды: apply, delete, update, rollback, list, status"; \ + exit 1;; \ + esac;; \ + helmrepo) \ + echo "🏪 Работа с Helm репозиториями..."; \ + REPO_CMD="$(word 3, $(MAKECMDGOALS))"; \ + PRESET_ARG="$(word 4, $(MAKECMDGOALS))"; \ + NAME_ARG="$(word 5, $(MAKECMDGOALS))"; \ + URL_ARG="$(word 6, $(MAKECMDGOALS))"; \ + if [ -z "$$REPO_CMD" ] || [ -z "$$PRESET_ARG" ]; then \ + echo "❌ Ошибка: Укажите команду и пресет"; \ + echo "💡 Пример: make k8s helmrepo list kubernetes"; \ + exit 1; \ + fi; \ + CONTAINER_NAME=k8s-controller; \ + if ! docker ps | grep -q $$CONTAINER_NAME; then \ + echo "❌ Контейнер $$CONTAINER_NAME не запущен"; \ + echo "💡 Запустите: make k8s create $$PRESET_ARG"; \ + exit 1; \ + fi; \ + case "$$REPO_CMD" in \ + add) \ + if [ -z "$$NAME_ARG" ] || [ -z "$$URL_ARG" ]; then \ + echo "❌ Ошибка: Укажите имя и URL репозитория"; \ + echo "💡 Пример: make k8s helmrepo add kubernetes stable https://charts.helm.sh/stable"; \ + exit 1; \ + fi; \ + echo "➕ Добавление Helm репозитория: $$NAME_ARG"; \ + docker exec $$CONTAINER_NAME bash -c "helm repo add $$NAME_ARG $$URL_ARG 2>&1 | grep -v '^WARNING' || true; helm repo update";; \ + list) \ + echo "📋 Список Helm репозиториев:"; \ + docker exec $$CONTAINER_NAME bash -c "helm repo list 2>&1 | grep -v '^WARNING' || true";; \ + delete) \ + if [ -z "$$NAME_ARG" ]; then \ + echo "❌ Ошибка: Укажите имя репозитория"; \ + echo "💡 Пример: make k8s helmrepo delete kubernetes stable"; \ + exit 1; \ + fi; \ + echo "🗑️ Удаление Helm репозитория: $$NAME_ARG"; \ + docker exec $$CONTAINER_NAME bash -c "helm repo remove $$NAME_ARG 2>&1 | grep -v '^WARNING' || true";; \ + update) \ + echo "🔄 Обновление Helm репозиториев"; \ + docker exec $$CONTAINER_NAME bash -c "helm repo update 2>&1 | grep -v '^WARNING' || true";; \ + packages) \ + if [ -z "$$NAME_ARG" ]; then \ + echo "❌ Ошибка: Укажите имя репозитория"; \ + echo "💡 Пример: make k8s helmrepo packages kubernetes stable"; \ + exit 1; \ + fi; \ + echo "📦 Пакеты в репозитории: $$NAME_ARG"; \ + docker exec $$CONTAINER_NAME bash -c "helm search repo $$NAME_ARG 2>&1 | grep -v '^WARNING' || true";; \ + *) \ + echo "❌ Неизвестная команда: $$REPO_CMD"; \ + echo "💡 Доступные команды: add, list, delete, update, packages"; \ + exit 1;; \ + esac;; \ + portforward) \ + PORTFWD_CMD="$(word 3, $(MAKECMDGOALS))"; \ + PORT_ARG="$(word 4, $(MAKECMDGOALS))"; \ + if [ -z "$$PORTFWD_CMD" ]; then \ + echo "❌ Ошибка: Укажите команду"; \ + echo "💡 Пример: make k8s portforward create"; \ + exit 1; \ + fi; \ + case "$$PORTFWD_CMD" in \ + create) \ + echo "🔌 Создание port-forward..."; \ + python3 scripts/portforward.py create;; \ + list) \ + echo "📋 Список активных port-forward..."; \ + python3 scripts/portforward.py list;; \ + clear) \ + echo "🗑️ Очистка всех port-forward..."; \ + python3 scripts/portforward.py clear;; \ + recreate) \ + echo "🔄 Пересоздание port-forward..."; \ + python3 scripts/portforward.py recreate;; \ + delete) \ + if [ -z "$$PORT_ARG" ]; then \ + echo "❌ Ошибка: Укажите порт"; \ + echo "💡 Пример: make k8s portforward delete 3000"; \ + exit 1; \ + fi; \ + echo "🗑️ Удаление port-forward на порту $$PORT_ARG..."; \ + python3 scripts/portforward.py delete $$PORT_ARG;; \ + *) \ + echo "❌ Неизвестная команда: $$PORTFWD_CMD"; \ + echo "💡 Доступные команды: create, list, clear, recreate, delete"; \ + exit 1;; \ + esac;; \ + *) \ + echo "☸️ Доступные команды:"; \ + echo ""; \ + echo " make k8s create [preset] - создать Kind кластер"; \ + echo " 💡 Без параметра: используется k8s-minimal (без аддонов)"; \ + echo " 💡 С параметром: используется указанный пресет"; \ + echo " 💡 Кластер НЕ удаляется автоматически"; \ + echo ""; \ + echo " make k8s destroy [preset] - удалить Kind кластер полностью"; \ + echo " 💡 Удалит: кластер и контейнер ansible-controller"; \ + echo ""; \ + echo " make k8s stop [cluster] - остановить Kind кластер (без удаления)"; \ + echo " 💡 Можно указать имя кластера или остановить все"; \ + echo " 💡 Для перезапуска: make k8s start"; \ + echo ""; \ + echo " make k8s start [cluster] - запустить остановленный кластер"; \ + echo " 💡 Можно указать имя кластера или запустить все"; \ + echo ""; \ + echo " make k8s status [preset] - детальный отчет о состоянии кластера"; \ + echo " 💡 Показывает: узлы, pods, сервисы, Ingress, события, Helm релизы и т.д."; \ + echo " 💡 Требует: пресет"; \ + echo " 💡 Пример: make k8s status kubernetes"; \ + echo ""; \ + echo " make k8s config [cluster] - получить kubeconfig для подключения"; \ + echo " 💡 Сохраняет: kubeconfig в корне проекта"; \ + echo " 💡 Можно указать имя конкретного кластера"; \ + echo ""; \ + echo " make k8s nodes [preset] - показать узлы кластера"; \ + echo " 💡 Требует: пресет"; \ + echo " 💡 Пример: make k8s nodes kubernetes"; \ + echo ""; \ + echo " make k8s shell [preset] - открыть shell в контейнере"; \ + echo " 💡 Для: ручного управления kubectl/kind"; \ + echo " 💡 Пример: make k8s shell kubernetes"; \ + echo ""; \ + echo " make k8s manifest [cmd] [preset] [url] - работа с манифестами"; \ + echo " 💡 Команды: apply, delete"; \ + echo " 💡 Пример: make k8s manifest apply kubernetes https://example.com/deploy.yaml"; \ + echo ""; \ + echo " make k8s helm [cmd] [preset] [release] [chart] - работа с Helm"; \ + echo " 💡 Команды: apply, delete, update, rollback, list, status"; \ + echo " 💡 Пример: make k8s helm apply kubernetes nginx stable/nginx-ingress"; \ + echo ""; \ + echo " make k8s helmrepo [cmd] [preset] [name] [url] - работа с Helm репозиториями"; \ + echo " 💡 Команды: add, list, delete, update, packages"; \ + echo " 💡 Пример: make k8s helmrepo add kubernetes stable https://charts.helm.sh/stable"; \ + echo ""; \ + echo " make k8s portforward [cmd] - управление port-forward"; \ + echo " 💡 Команды: create, list, clear, recreate, delete [port]"; \ + echo " 💡 Пример: make k8s portforward create"; \ + echo ""; \ + echo "💡 Примеры:"; \ + echo " make k8s create # создать минимальный кластер"; \ + echo " make k8s create kubernetes # создать кластер с аддонами"; \ + echo " make k8s nodes kubernetes # показать узлы кластера"; \ + echo " make k8s config kubernetes # получить kubeconfig для кластера"; \ + echo " export KUBECONFIG=kubeconfig # использовать конфиг"; \ + echo " kubectl get nodes # проверить узлы"; \ + echo " make k8s manifest apply kubernetes https://example.com/manifest.yaml # установить манифест"; \ + echo " make k8s stop kubernetes # остановить кластер"; \ + echo " make k8s start kubernetes # запустить кластер"; \ + echo " make k8s destroy kubernetes # удалить кластер с пресетом kubernetes";; \ + esac + # ============================================================================= # СПРАВКА # ============================================================================= help: @echo "==========================================" - @echo "AnsibleLab - Универсальная система" + @echo "DevOpsLab - Универсальная система" @echo "тестирования Ansible ролей" @echo "==========================================" @echo "" @@ -1063,7 +1484,7 @@ help: @echo " make presets info - подробная информация о preset'е" @echo " make presets test - запустить тест с preset'ом" @echo "" - @echo "🖼️ СОБСТВЕННЫЕ ОБРАЗЫ (AnsibleLab):" + @echo "🖼️ СОБСТВЕННЫЕ ОБРАЗЫ (DevOpsLab):" @echo " make custom-images test [minimal|full|performance] - тест с собственными образами" @echo " make custom-images check - проверить наличие собственных образов" @echo " make custom-images build - собрать все образы для тестирования" @@ -1115,6 +1536,20 @@ help: @echo " make controller run - запустить ansible-controller" @echo " make controller stop - остановить ansible-controller" @echo "" + @echo "☸️ KUBERNETES (Kind кластеры):" + @echo " make k8s create [preset] - создать Kind кластер (по умолчанию: k8s-minimal)" + @echo " make k8s destroy [preset] - удалить Kind кластер" + @echo " make k8s start [preset] - запустить Kind кластер" + @echo " make k8s stop [preset] - остановить Kind кластер" + @echo " make k8s status [preset] - детальный отчет о состоянии кластера" + @echo " make k8s nodes [preset] - показать узлы кластера" + @echo " make k8s config [preset] - получить kubeconfig для подключения" + @echo " make k8s manifest [cmd] [preset] [url] - работа с манифестами (apply, delete)" + @echo " make k8s helm [cmd] [preset] [release] [chart] - работа с Helm" + @echo " make k8s helmrepo [cmd] [preset] [name] [url] - управление Helm репозиториями" + @echo " make k8s portforward [cmd] - управление port-forward (create, list, clear)" + @echo " make k8s shell [preset] - открыть shell в контейнере k8s" + @echo "" @echo "💡 ПРИМЕРЫ ИСПОЛЬЗОВАНИЯ:" @echo " make presets list # показать все preset'ы" @echo " make presets test PRESET=etcd-patroni # тест с etcd-patroni" @@ -1140,7 +1575,7 @@ help: custom-images: @case "$(word 2, $(MAKECMDGOALS))" in \ test) \ - echo "🧪 Тестирование с собственными образами AnsibleLab..."; \ + echo "🧪 Тестирование с собственными образами DevOpsLab..."; \ if [ -z "$(word 3, $(MAKECMDGOALS))" ]; then \ echo "💡 Использование: make custom-images test [minimal|full|performance]"; \ echo "💡 По умолчанию: minimal"; \ @@ -1168,7 +1603,7 @@ custom-images: echo ""; \ echo " 🔨 make custom-images build - собрать все образы для тестирования"; \ echo " 💡 Выполняет: make docker build"; \ - echo " 💡 Собирает: все образы AnsibleLab"; \ + echo " 💡 Собирает: все образы DevOpsLab"; \ echo ""; \ echo "💡 Пресеты для тестирования:"; \ echo " - custom-minimal.yml - минимальный тест (4 хоста)"; \ diff --git a/README.md b/README.md index 4cba800..fb43efc 100644 --- a/README.md +++ b/README.md @@ -2,20 +2,40 @@ **Автор:** Сергей Антропов **Сайт:** https://devops.org.ru -**Версия:** 2.0.0 +**Версия:** 3.0.0 ## 📋 Описание -DevOpsLab - это универсальная система для разработки, тестирования и развертывания Ansible ролей с использованием Docker, Molecule и preset конфигураций. Система поддерживает тестирование на различных ОС через Docker контейнеры. +DevOpsLab - это универсальная DevOps платформа для разработки, тестирования и развертывания инфраструктуры. Система объединяет Ansible роли, Docker контейнеры и Kubernetes кластеры в единую среду для автоматизации и управления инфраструктурой. + +**Ключевые компоненты:** +- **Ansible** - автоматизация конфигурации и развертывания +- **Docker** - контейнеризация для изоляции и переносимости +- **Molecule** - тестирование Ansible ролей +- **Kubernetes (Kind)** - локальные K8s кластеры для разработки +- **Multi-arch поддержка** - сборка для amd64 и arm64 архитектур ## ✨ Ключевые возможности +### 🔧 Ansible - **Тестирование ролей** через Molecule с Docker - **Preset система** для быстрого выбора окружений тестирования - **Мультиплатформенное тестирование** (Ubuntu, Debian, CentOS, AlmaLinux, RHEL и другие) - **Автоматическая проверка** синтаксиса Ansible ролей - **Управление секретами** через Ansible Vault -- **Готовые Docker образы** для разных ОС + +### 🐳 Docker +- **Готовые Docker образы** для разных ОС с поддержкой systemd +- **Multi-arch сборка** (amd64, arm64) +- **Автоматическая публикация** в Docker Hub +- **Контейнеры для тестирования** Ansible ролей + +### ☸️ Kubernetes +- **Kind кластеры** для локального тестирования +- **Автоматическая установка аддонов** (Istio, Prometheus, Grafana, Kiali, Ingress, Metrics Server) +- **Управление через Helm** и Kubernetes манифесты +- **Port-forward** для доступа к сервисам +- **Детальный мониторинг** состояния кластера ## 📁 Структура проекта @@ -31,22 +51,65 @@ DevOpsLab/ │ │ └── molecule.yml # Конфигурация Molecule │ └── presets/ # Preset конфигурации │ ├── default.yml # Стандартный preset -│ ├── minimal.yml # Минимальный preset │ ├── mytest.yml # Кастомный preset -│ ├── presets.yml # Основные preset'ы -│ └── examples/ # Примеры preset'ов -│ ├── all-images.yml # Все образы (16 хостов) -│ ├── multi-os.yml # Multi-OS тестирование -│ ├── performance.yml # Тест производительности -│ ├── security.yml # Тест безопасности -│ └── ... +│ ├── examples/ # Примеры preset'ов +│ │ ├── all-images.yml # Все образы (16 хостов) +│ │ ├── centos-all.yml # CentOS 7/8/9 +│ │ ├── debian-all.yml # Debian 9/10/11/12 +│ │ ├── ubuntu-all.yml # Ubuntu 20/22/24 +│ │ ├── multi-os.yml # Multi-OS тестирование +│ │ ├── performance.yml # Тест производительности +│ │ ├── security.yml # Тест безопасности +│ │ ├── minimal.yml # Минимальный preset +│ │ └── ... +│ └── k8s/ # Kubernetes preset'ы +│ ├── kubernetes.yml # Полный K8s кластер с аддонами +│ └── k8s-minimal.yml # Минимальный K8s кластер ├── roles/ # Ansible роли │ ├── docker/ # Роль установки Docker +│ │ ├── defaults/ # Переменные по умолчанию +│ │ ├── handlers/ # Обработчики +│ │ ├── meta/ # Метаданные +│ │ ├── tasks/ # Задачи +│ │ ├── templates/ # Шаблоны +│ │ ├── tests/ # Тесты +│ │ ├── vars/ # Переменные +│ │ ├── README.md +│ │ └── examples.yml │ ├── devops/ # Роль DevOps инструментов +│ │ ├── defaults/ +│ │ ├── files/ +│ │ ├── handlers/ +│ │ ├── meta/ +│ │ ├── tasks/ +│ │ ├── templates/ +│ │ ├── tests/ +│ │ ├── vars/ +│ │ ├── README.md +│ │ ├── QUICKSTART.md +│ │ ├── examples.yml +│ │ └── playbook.yml │ ├── ping/ # Роль для ping проверок +│ │ ├── defaults/ +│ │ ├── handlers/ +│ │ ├── meta/ +│ │ ├── tasks/ +│ │ ├── templates/ +│ │ ├── README.md +│ │ ├── QUICKSTART.md +│ │ └── playbook.yml │ └── deploy.yml # Playbook для развертывания ├── dockerfiles/ # Docker образы │ ├── ansible-controller/ # Ansible контроллер +│ │ ├── Dockerfile +│ │ ├── docker-compose.yml +│ │ ├── requirements.txt +│ │ └── requirements.yml +│ ├── k8s/ # Kubernetes образ (Kind, kubectl, Helm, Istio) +│ │ └── Dockerfile +│ ├── k8s-portforward/ # Port-forward контейнер (устаревший) +│ │ ├── Dockerfile +│ │ └── portforward-container.py │ ├── ubuntu20/ # Ubuntu 20.04 │ ├── ubuntu22/ # Ubuntu 22.04 │ ├── ubuntu24/ # Ubuntu 24.04 @@ -60,20 +123,53 @@ DevOpsLab/ │ ├── alma/ # AlmaLinux 8 │ ├── rocky/ # Rocky Linux 8 │ ├── rhel/ # RHEL 8 -│ ├── alt9/ # ALT Linux P9 +│ ├── alt-linux/ # ALT Linux P9 │ ├── astra-linux/ # Astra Linux 1.7 -│ └── redos/ # RED OS 9 +│ ├── redos/ # RED OS 9 +│ └── README.md ├── cicd/ # CI/CD конфигурации │ ├── azure-devops/ # Azure DevOps +│ │ └── azure-pipelines.yml │ ├── github/ # GitHub Actions +│ │ └── workflows.yml │ ├── gitlab/ # GitLab CI +│ │ ├── config.json +│ │ ├── docker-compose.yaml +│ │ └── runner/ +│ │ └── config.toml │ └── jenkins/ # Jenkins -├── vault/ # Зашифрованные секреты -├── inventory/ # Инвентори файлы +│ └── Jenkinsfile ├── scripts/ # Вспомогательные скрипты +│ ├── create_k8s_cluster.py # Создание K8s кластера +│ ├── delete_hosts.py # Удаление хостов +│ ├── k8s_status.py # Статус K8s кластера +│ ├── portforward.py # Управление port-forward +│ ├── generate-role-docs.sh # Генерация документации +│ ├── role-manager.sh # Управление ролями +│ ├── setup-cicd.sh # Настройка CI/CD +│ ├── test-custom-images.sh # Тестирование образов +│ └── update-playbooks.sh # Обновление playbook'ов ├── docs/ # Документация +│ ├── kubernetes-kind.md # Руководство по Kubernetes +│ ├── k8s-scripts.md # Описание K8s скриптов +│ ├── kubernetes-commands.md # Команды Kubernetes +│ ├── kubernetes-full-guide.md # Полное руководство K8s +│ ├── k8s-ingress-fix.md # Исправление Ingress +│ ├── getting-started.md # Быстрый старт +│ ├── molecule-guide.md # Руководство по Molecule +│ ├── creating-roles.md # Создание ролей +│ ├── linting-guide.md # Руководство по линтингу +│ ├── platform-support.md # Поддержка платформ +│ ├── monitoring.md # Мониторинг +│ └── ... +├── manifests/ # Kubernetes манифесты +│ └── test-grafana-ingress.yaml +├── vault/ # Зашифрованные секреты +│ └── secrets.yml +├── inventory/ # Инвентори файлы +│ └── hosts.ini ├── Makefile # Основные команды -└── requirements.yml # Ansible коллекции +└── README.md # Этот файл ``` ## 🚀 Быстрый старт @@ -109,6 +205,27 @@ make role lint docker make role lint ping ``` +### 4. Работа с Kubernetes + +```bash +# Создание Kind кластера с аддонами +make k8s create kubernetes + +# Статус кластера (детальный отчет) +make k8s status kubernetes + +# Создание port-forward для доступа к сервисам +make k8s portforward create + +# Установка Helm чарта +make k8s helm apply kubernetes nginx bitnami/nginx + +# Удаление кластера +make k8s destroy kubernetes +``` + +**Подробная документация:** [docs/kubernetes-kind.md](docs/kubernetes-kind.md) + ## 📚 Доступные роли ### Docker @@ -501,6 +618,54 @@ make custom-images # справка по собственным - **[docs/dockerfiles.md](docs/dockerfiles.md)** - Полная документация по Docker образам +### Kubernetes + +**Полная документация:** [docs/kubernetes-kind.md](docs/kubernetes-kind.md) + +DevOpsLab предоставляет полную поддержку локальных Kubernetes кластеров на базе Kind: + +#### Основные команды + +```bash +# Создание кластера с аддонами +make k8s create kubernetes + +# Детальный статус кластера +make k8s status kubernetes + +# Управление port-forward +make k8s portforward create +make k8s portforward list +make k8s portforward clear + +# Работа с Helm +make k8s helm apply kubernetes nginx bitnami/nginx +make k8s helm list kubernetes +make k8s helm delete kubernetes nginx + +# Работа с манифестами +make k8s manifest apply kubernetes https://example.com/app.yaml + +# Удаление кластера +make k8s destroy kubernetes +``` + +#### Доступные аддоны + +- **Ingress NGINX** - маршрутизация трафика +- **Metrics Server** - сбор метрик +- **Istio** - Service Mesh +- **Prometheus Stack** - мониторинг (Prometheus + Grafana) +- **Kiali** - визуализация Service Mesh + +#### Доступ к сервисам + +- **Grafana**: http://localhost:3000 (admin/admin) +- **Prometheus**: http://localhost:9090 +- **Kiali**: http://localhost:20001 +- **Ingress HTTP**: http://localhost:8081 +- **Ingress HTTPS**: https://localhost:8443 + ## 🐳 Docker образы Проект использует готовые Docker образы для различных ОС: @@ -620,6 +785,7 @@ MIT License - ✅ Управление секретами через Ansible Vault - ✅ Готовые Docker образы для разных ОС - ✅ CI/CD интеграция +- ✅ Kubernetes Kind кластеры для тестирования --- diff --git a/cicd/jenkins/Jenkinsfile b/cicd/jenkins/Jenkinsfile index 0a39be7..d6b03ef 100644 --- a/cicd/jenkins/Jenkinsfile +++ b/cicd/jenkins/Jenkinsfile @@ -1,4 +1,4 @@ -// Jenkins Pipeline для AnsibleLab +// Jenkins Pipeline для DevOpsLab // Автор: Сергей Антропов // Сайт: https://devops.org.ru diff --git a/dockerfiles/README.md b/dockerfiles/README.md index 2aaa03f..c34fcc1 100644 --- a/dockerfiles/README.md +++ b/dockerfiles/README.md @@ -2,7 +2,7 @@ **Автор:** Сергей Антропов **Сайт:** https://devops.org.ru -**Версия:** 2.0.0 +**Версия:** 3.0.0 ## 🐳 Обзор @@ -15,8 +15,14 @@ dockerfiles/ ├── ansible-controller/ # Ansible контроллер с предустановленными коллекциями │ ├── Dockerfile │ ├── docker-compose.yml -│ └── requirements.txt -├── alt9/ # ALT Linux P9 с systemd +│ ├── requirements.txt +│ └── requirements.yml +├── k8s/ # Kubernetes контроллер (Kind, kubectl, Helm, Istio) +│ └── Dockerfile +├── k8s-portforward/ # Port-forward контейнер (устаревший) +│ ├── Dockerfile +│ └── portforward-container.py +├── alt-linux/ # ALT Linux P9 с systemd │ └── Dockerfile ├── astra-linux/ # Astra Linux 1.7 с systemd │ └── Dockerfile @@ -48,7 +54,7 @@ dockerfiles/ │ └── Dockerfile ├── debian12/ # Debian 12 (bookworm) с systemd │ └── Dockerfile -└── README.md # Документация +└── README.md # Этот файл ``` ## 🚀 Доступные образы @@ -62,12 +68,11 @@ dockerfiles/ #### Компоненты: - **Ansible Core** с последними коллекциями - **Docker CLI** для работы с контейнерами -- **kubectl** для управления Kubernetes -- **Helm** для управления пакетами Kubernetes -- **Kind** для локального Kubernetes - **yq** для работы с YAML - **jq** для работы с JSON +**Примечание:** Kubernetes инструменты (kubectl, Helm, Kind, Istio) были перенесены в отдельный образ `k8s`. + #### Предустановленные коллекции: ```yaml collections: @@ -109,7 +114,40 @@ docker run --rm \ ansible-playbook site.yml ``` -### 2. Ubuntu +### 2. k8s + +**Базовый образ:** `ubuntu:22.04` +**Тег:** `inecs/ansible-lab:k8s-latest` +**Описание:** Kubernetes контроллер с инструментами для работы с Kubernetes, Helm, Istio и Kind кластерами + +#### Компоненты: +- **Docker CLI** (20.10.24) для работы с контейнерами +- **kubectl** (1.34.1) для управления Kubernetes +- **Helm** (latest) для управления пакетами Kubernetes +- **Kind** (0.30.0) для локальных Kubernetes кластеров +- **Istio CLI** (1.22.1) для управления Service Mesh +- **Python 3** с модулем yaml для выполнения скриптов + +#### Использование: +```bash +# Создание Kind кластера +docker run -it --rm \ + --name k8s-controller \ + --network kind \ + -v /var/run/docker.sock:/var/run/docker.sock:rw \ + inecs/ansible-lab:k8s-latest \ + kind create cluster --name lab + +# Выполнение kubectl команд +docker exec k8s-controller kubectl get nodes + +# Установка Helm релиза +docker exec k8s-controller helm install prometheus prometheus-community/kube-prometheus-stack +``` + +**Примечание:** Этот образ используется автоматически при выполнении `make k8s` команд. Контейнер запускается с именем `k8s-controller` и подключен к Docker daemon хоста. + +### 3. Ubuntu #### Ubuntu 20.04 (focal) @@ -157,7 +195,7 @@ docker run -d --privileged \ inecs/ansible-lab:ubuntu22 ``` -### 3. Debian +### 4. Debian #### Debian 9 (stretch) @@ -216,7 +254,7 @@ docker run -d --privileged \ inecs/ansible-lab:debian12 ``` -### 4. RHEL (Red Hat Enterprise Linux) +### 5. RHEL (Red Hat Enterprise Linux) **Базовый образ:** `registry.access.redhat.com/ubi8/ubi` **Тег:** `inecs/ansible-lab:rhel-latest` @@ -240,7 +278,7 @@ docker run -d --privileged \ inecs/ansible-lab:rhel-latest ``` -### 5. CentOS +### 6. CentOS #### CentOS 7 @@ -304,7 +342,7 @@ docker run -d --privileged \ inecs/ansible-lab:centos-latest ``` -### 6. alma +### 7. alma **Базовый образ:** `almalinux:8` **Тег:** `inecs/ansible-lab:alma-latest` @@ -341,7 +379,7 @@ docker run -d --privileged \ inecs/ansible-lab:alma-latest ``` -### 7. rocky +### 8. rocky **Базовый образ:** `rockylinux:8` **Тег:** `inecs/ansible-lab:rocky-latest` @@ -378,10 +416,10 @@ docker run -d --privileged \ inecs/ansible-lab:rocky-latest ``` -### 8. alt9 +### 9. alt-linux **Базовый образ:** `altlinux/p9` -**Тег:** `inecs/ansible-lab:alt9-latest` +**Тег:** `inecs/ansible-lab:alt-linux-latest` **Описание:** ALT Linux 9 с systemd и Docker #### Компоненты: @@ -408,14 +446,14 @@ systemctl set-default multi-user.target ```bash # Запуск ALT Linux контейнера docker run -d --privileged \ - --name alt9-test \ + --name alt-linux-test \ -v /sys/fs/cgroup:/sys/fs/cgroup:ro \ --tmpfs /run --tmpfs /run/lock \ --cap-add SYS_ADMIN \ - inecs/ansible-lab:alt9-latest + inecs/ansible-lab:alt-linux-latest ``` -### 9. astra-linux +### 10. astra-linux **Базовый образ:** `astralinux/astra-1.7` **Тег:** `inecs/ansible-lab:astra-linux-latest` @@ -452,7 +490,7 @@ docker run -d --privileged \ inecs/ansible-lab:astra-linux-latest ``` -### 10. redos +### 11. redos **Базовый образ:** `redos/redos:9` **Тег:** `inecs/ansible-lab:redos-latest` @@ -581,7 +619,7 @@ images: centos: "inecs/ansible-lab:centos-latest" alma: "inecs/ansible-lab:alma-latest" rocky: "inecs/ansible-lab:rocky-latest" - alt: "inecs/ansible-lab:alt9-latest" + alt: "inecs/ansible-lab:alt-linux-latest" astra: "inecs/ansible-lab:astra-linux-latest" redos: "inecs/ansible-lab:redos-latest" diff --git a/dockerfiles/k8s-portforward/Dockerfile b/dockerfiles/k8s-portforward/Dockerfile new file mode 100644 index 0000000..3f21cb7 --- /dev/null +++ b/dockerfiles/k8s-portforward/Dockerfile @@ -0,0 +1,43 @@ +# Kubernetes Port-Forward Container +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +ARG TARGETARCH + +FROM ubuntu:22.04 + +# Обновляем систему +RUN apt-get update && apt-get upgrade -y && apt-get clean + +# Устанавливаем базовые пакеты + socat для форвардинга портов +RUN apt-get install -y \ + wget \ + curl \ + bash \ + ca-certificates \ + python3 \ + python3-yaml \ + socat \ + netcat-openbsd \ + && apt-get clean + +# Устанавливаем kubectl +RUN if [ "${TARGETARCH}" = "amd64" ]; then \ + wget -O kubectl "https://dl.k8s.io/release/v1.34.1/bin/linux/amd64/kubectl"; \ + else \ + wget -O kubectl "https://dl.k8s.io/release/v1.34.1/bin/linux/arm64/kubectl"; \ + fi && \ + chmod +x kubectl && \ + mv kubectl /usr/local/bin/ + +# Создаем рабочий каталог +WORKDIR /portforward + +# Копируем скрипт порт-форвардинга +COPY portforward-container.py /portforward/portforward-container.py + +# Делаем скрипт исполняемым +RUN chmod +x /portforward/portforward-container.py + +# Команда по умолчанию +CMD ["python3", "/portforward/portforward-container.py"] diff --git a/dockerfiles/k8s-portforward/portforward-container.py b/dockerfiles/k8s-portforward/portforward-container.py new file mode 100755 index 0000000..3713077 --- /dev/null +++ b/dockerfiles/k8s-portforward/portforward-container.py @@ -0,0 +1,145 @@ +#!/usr/bin/env python3 +""" +Скрипт для работы внутри контейнера k8s-portforward +Автор: Сергей Антропов +Сайт: https://devops.org.ru +""" +import sys +import yaml +import subprocess +import time +import os +import signal +import json + +def run_kubectl_portforward(cluster_name, namespace, service, remote_port, local_port): + """Запускает kubectl port-forward внутри контейнера""" + cmd = [ + "kubectl", + f"--server=https://{cluster_name}-control-plane:6443", + "--insecure-skip-tls-verify", + "port-forward", + "-n", namespace, + service, + f"{local_port}:{remote_port}" + ] + + print(f"[portforward] Запуск: {' '.join(cmd)}") + process = subprocess.Popen( + cmd, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + text=True + ) + + return process + +def main(): + """Главная функция""" + # Загружаем preset + preset_file = "/workspace/molecule/presets/k8s/kubernetes.yml" + + if not os.path.exists(preset_file): + print(f"❌ Файл {preset_file} не найден") + print("💡 Убедитесь, что workspace подключен в контейнер") + sys.exit(1) + + with open(preset_file, 'r') as f: + preset = yaml.safe_load(f) + + cluster_name = preset['kind_clusters'][0]['name'] + addon_ports = preset['kind_clusters'][0].get('addon_ports', {}) + + print(f"🔌 Запуск порт-форвардинга для кластера: {cluster_name}") + + processes = [] + + # Ingress HTTP + if addon_ports.get('ingress_http'): + port = addon_ports['ingress_http'] + print(f" - Ingress HTTP: {port} -> ingress-nginx-controller:80") + proc = run_kubectl_portforward( + cluster_name, "ingress-nginx", + "svc/ingress-nginx-controller", 80, port + ) + processes.append(proc) + + # Ingress HTTPS + if addon_ports.get('ingress_https'): + port = addon_ports['ingress_https'] + print(f" - Ingress HTTPS: {port} -> ingress-nginx-controller:443") + proc = run_kubectl_portforward( + cluster_name, "ingress-nginx", + "svc/ingress-nginx-controller", 443, port + ) + processes.append(proc) + + # Prometheus + if addon_ports.get('prometheus'): + port = addon_ports['prometheus'] + print(f" - Prometheus: {port} -> monitoring-kube-prometheus-prometheus:9090") + proc = run_kubectl_portforward( + cluster_name, "monitoring", + "svc/monitoring-kube-prometheus-prometheus", 9090, port + ) + processes.append(proc) + + # Grafana + if addon_ports.get('grafana'): + port = addon_ports['grafana'] + print(f" - Grafana: {port} -> monitoring-grafana:80") + proc = run_kubectl_portforward( + cluster_name, "monitoring", + "svc/monitoring-grafana", 80, port + ) + processes.append(proc) + + # Kiali + if addon_ports.get('kiali'): + port = addon_ports['kiali'] + print(f" - Kiali: {port} -> kiali:20001") + proc = run_kubectl_portforward( + cluster_name, "istio-system", + "svc/kiali", 20001, port + ) + processes.append(proc) + + # Metrics Server + if addon_ports.get('metrics_server'): + port = addon_ports['metrics_server'] + print(f" - Metrics Server: {port} -> metrics-server:4443") + proc = run_kubectl_portforward( + cluster_name, "kube-system", + "svc/metrics-server", 4443, port + ) + processes.append(proc) + + print("✅ Все порты запущены. Ожидание завершения...") + print("💡 Контейнер будет работать, пока все port-forward активны") + + # Ожидание завершения процессов + try: + while True: + time.sleep(1) + # Проверяем, что все процессы еще работают + alive = [p for p in processes if p.poll() is None] + if not alive: + print("⚠️ Все port-forward завершились") + break + except KeyboardInterrupt: + print("\n🛑 Получен сигнал завершения...") + + # Завершаем все процессы + print("🗑️ Завершение port-forward...") + for proc in processes: + if proc.poll() is None: + proc.terminate() + try: + proc.wait(timeout=5) + except subprocess.TimeoutExpired: + proc.kill() + + print("✅ Завершено") + +if __name__ == "__main__": + main() diff --git a/dockerfiles/k8s/Dockerfile b/dockerfiles/k8s/Dockerfile new file mode 100644 index 0000000..34f7fba --- /dev/null +++ b/dockerfiles/k8s/Dockerfile @@ -0,0 +1,73 @@ +# Kubernetes Kind Container - Multi-Arch +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +ARG TARGETARCH + +FROM ubuntu:22.04 + +# Обновляем систему +RUN apt-get update && apt-get upgrade -y && apt-get clean + +# Устанавливаем базовые пакеты +RUN apt-get install -y \ + wget \ + curl \ + git \ + vim \ + bash \ + ca-certificates \ + python3 \ + python3-yaml \ + file \ + apt-transport-https \ + gnupg \ + lsb-release \ + && apt-get clean + +# Устанавливаем Docker CLI +RUN DOCKER_VERSION=20.10.24 && \ + if [ "${TARGETARCH}" = "amd64" ]; then \ + wget -O /tmp/docker-cli.tgz "https://download.docker.com/linux/static/stable/x86_64/docker-${DOCKER_VERSION}.tgz" && \ + tar -xz -C /tmp -f /tmp/docker-cli.tgz && \ + mv /tmp/docker/docker /usr/local/bin/ && \ + rm -rf /tmp/docker-cli.tgz /tmp/docker; \ + else \ + wget -O /tmp/docker-cli.tgz "https://download.docker.com/linux/static/stable/aarch64/docker-${DOCKER_VERSION}.tgz" && \ + tar -xz -C /tmp -f /tmp/docker-cli.tgz && \ + mv /tmp/docker/docker /usr/local/bin/ && \ + rm -rf /tmp/docker-cli.tgz /tmp/docker; \ + fi && \ + chmod +x /usr/local/bin/docker + +# Устанавливаем kubectl +RUN if [ "${TARGETARCH}" = "amd64" ]; then \ + wget -O kubectl "https://dl.k8s.io/release/v1.34.1/bin/linux/amd64/kubectl"; \ + else \ + wget -O kubectl "https://dl.k8s.io/release/v1.34.1/bin/linux/arm64/kubectl"; \ + fi && \ + chmod +x kubectl && \ + mv kubectl /usr/local/bin/ + +# Устанавливаем Helm +RUN wget https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 -O - | bash + +# Устанавливаем Kind v0.30.0 +RUN if [ "${TARGETARCH}" = "amd64" ]; then \ + wget -O /usr/local/bin/kind "https://github.com/kubernetes-sigs/kind/releases/download/v0.30.0/kind-linux-amd64"; \ + else \ + wget -O /usr/local/bin/kind "https://github.com/kubernetes-sigs/kind/releases/download/v0.30.0/kind-linux-arm64"; \ + fi && \ + chmod +x /usr/local/bin/kind && \ + ls -lh /usr/local/bin/kind && \ + file /usr/local/bin/kind + +# Устанавливаем Istio CLI +RUN ARCH=$(echo ${TARGETARCH} | sed 's/amd64/x86_64/; s/arm64/aarch64/') && \ + ISTIO_VERSION=1.22.1 && \ + wget -qO- https://istio.io/downloadIstio | ISTIO_VERSION=${ISTIO_VERSION} TARGET_ARCH=${ARCH} sh - && \ + mv istio-${ISTIO_VERSION}/bin/istioctl /usr/local/bin/ && \ + rm -rf istio-${ISTIO_VERSION} + +# Команда по умолчанию +CMD ["sleep", "infinity"] diff --git a/docs/creating-roles.md b/docs/creating-roles.md index 8c8d190..8475d8d 100644 --- a/docs/creating-roles.md +++ b/docs/creating-roles.md @@ -2,7 +2,7 @@ **Автор:** Сергей Антропов **Сайт:** https://devops.org.ru -**Версия:** 2.0.0 +**Версия:** 3.0.0 ## 🚀 Быстрый старт diff --git a/docs/dockerfiles.md b/docs/dockerfiles.md index 9f2b479..bc6fd18 100644 --- a/docs/dockerfiles.md +++ b/docs/dockerfiles.md @@ -2,7 +2,7 @@ **Автор:** Сергей Антропов **Сайт:** https://devops.org.ru -**Версия:** 2.0.0 +**Версия:** 3.0.0 ## 🐳 Обзор @@ -13,7 +13,16 @@ DevOpsLab использует предварительно собранные D ``` dockerfiles/ ├── ansible-controller/ # Ansible контроллер -├── alt9/ # ALT Linux P9 +│ ├── Dockerfile +│ ├── docker-compose.yml +│ ├── requirements.txt +│ └── requirements.yml +├── k8s/ # Kubernetes контроллер (Kind, kubectl, Helm, Istio) +│ └── Dockerfile +├── k8s-portforward/ # Port-forward контейнер (устаревший) +│ ├── Dockerfile +│ └── portforward-container.py +├── alt-linux/ # ALT Linux P9 ├── astra-linux/ # Astra Linux 1.7 ├── redos/ # RED OS 9 ├── rhel/ # Red Hat Enterprise Linux 8 @@ -28,7 +37,8 @@ dockerfiles/ ├── debian9/ # Debian 9 Stretch ├── debian10/ # Debian 10 Buster ├── debian11/ # Debian 11 Bullseye -└── debian12/ # Debian 12 Bookworm +├── debian12/ # Debian 12 Bookworm +└── README.md # Документация по Dockerfiles ``` ## 🚀 Доступные образы @@ -44,13 +54,12 @@ Ansible контроллер с предустановленными колле #### Компоненты: - Ansible Core с последними коллекциями - Docker CLI для работы с контейнерами -- kubectl для управления Kubernetes -- Helm для управления пакетами Kubernetes -- Kind для локального Kubernetes - yq для работы с YAML - jq для работы с JSON - Molecule для тестирования ролей +**Примечание:** Kubernetes инструменты (kubectl, Helm, Kind, Istio) были перенесены в отдельный образ `k8s`. + #### Предустановленные коллекции: ```yaml collections: @@ -82,6 +91,41 @@ docker run --rm \ ansible-playbook site.yml ``` +### k8s + +**Базовый образ:** `ubuntu:22.04` +**Теги:** `inecs/ansible-lab:k8s-latest` +**Платформы:** linux/amd64, linux/arm64 + +Kubernetes контроллер с инструментами для работы с Kubernetes, Helm, Istio и Kind кластерами. + +#### Компоненты: +- **Docker CLI** (20.10.24) для работы с контейнерами +- **kubectl** (1.34.1) для управления Kubernetes +- **Helm** (latest) для управления пакетами Kubernetes +- **Kind** (0.30.0) для локальных Kubernetes кластеров +- **Istio CLI** (1.22.1) для управления Service Mesh +- Python 3 с модулем yaml для выполнения скриптов + +#### Использование: +```bash +# Создание Kind кластера +docker run -it --rm \ + --name k8s-controller \ + --network kind \ + -v /var/run/docker.sock:/var/run/docker.sock:rw \ + inecs/ansible-lab:k8s-latest \ + kind create cluster --name lab + +# Выполнение kubectl команд +docker exec k8s-controller kubectl get nodes + +# Установка Helm релиза +docker exec k8s-controller helm install prometheus prometheus-community/kube-prometheus-stack +``` + +**Примечание:** Этот образ используется автоматически при выполнении `make k8s` команд. Контейнер запускается с именем `k8s-controller` и подключен к Docker daemon хоста. + ### Ubuntu **Базовые образы:** @@ -194,7 +238,7 @@ Red Hat Enterprise Linux 8 с systemd. ### ALT Linux **Базовый образ:** `altlinux/p9` -**Тег:** `inecs/ansible-lab:alt9-latest` +**Тег:** `inecs/ansible-lab:alt-linux-latest` **Платформы:** linux/amd64 (ограничение базового образа) ALT Linux P9 с systemd. @@ -348,18 +392,19 @@ docker run -d --privileged \ ## 📋 Матрица совместимости -| Образ | Платформы | systemd | Docker | Python 3 | -|-------|-----------|---------|--------|----------| -| ansible-controller | amd64, arm64 | ✅ | ✅ | ✅ | -| ubuntu20/22/24 | amd64, arm64 | ✅ | ✅ | ✅ | -| debian9/10/11/12 | amd64, arm64 | ✅ | ✅ | ✅ | -| centos7/8/9 | amd64, arm64 | ✅ | ✅ | ✅ | -| alma | amd64, arm64 | ✅ | ✅ | ✅ | -| rocky | amd64, arm64 | ✅ | ✅ | ✅ | -| rhel | amd64, arm64 | ✅ | ✅ | ✅ | -| alt9 | amd64 | ✅ | ✅ | ✅ | -| astra-linux | amd64 | ✅ | ✅ | ✅ | -| redos | amd64 | ✅ | ✅ | ✅ | +| Образ | Платформы | systemd | Docker | Python 3 | Kubernetes Tools | +|-------|-----------|---------|--------|----------|------------------| +| ansible-controller | amd64, arm64 | ✅ | ✅ | ✅ | ❌ | +| k8s | amd64, arm64 | ❌ | ✅ | ✅ | ✅ (kubectl, Helm, Kind, Istio) | +| ubuntu20/22/24 | amd64, arm64 | ✅ | ✅ | ✅ | ❌ | +| debian9/10/11/12 | amd64, arm64 | ✅ | ✅ | ✅ | ❌ | +| centos7/8/9 | amd64, arm64 | ✅ | ✅ | ✅ | ❌ | +| alma | amd64, arm64 | ✅ | ✅ | ✅ | ❌ | +| rocky | amd64, arm64 | ✅ | ✅ | ✅ | ❌ | +| rhel | amd64, arm64 | ✅ | ✅ | ✅ | ❌ | +| alt-linux | amd64 | ✅ | ✅ | ✅ | ❌ | +| astra-linux | amd64 | ✅ | ✅ | ✅ | ❌ | +| redos | amd64 | ✅ | ✅ | ✅ | ❌ | ## 🛠️ Управление образами diff --git a/docs/examples.md b/docs/examples.md index d5a26a5..6510278 100644 --- a/docs/examples.md +++ b/docs/examples.md @@ -2,7 +2,7 @@ **Автор:** Сергей Антропов **Сайт:** https://devops.org.ru -**Версия:** 2.0.0 +**Версия:** 3.0.0 ## Быстрый старт diff --git a/docs/getting-started.md b/docs/getting-started.md index 7b4131b..0d05742 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -2,7 +2,7 @@ **Автор:** Сергей Антропов **Сайт:** https://devops.org.ru -**Версия:** 2.0.0 +**Версия:** 3.0.0 ## 🚀 Установка и настройка diff --git a/docs/k8s-ingress-fix.md b/docs/k8s-ingress-fix.md new file mode 100644 index 0000000..076d2d4 --- /dev/null +++ b/docs/k8s-ingress-fix.md @@ -0,0 +1,110 @@ +# Исправление проблемы с Ingress + +## Проблема + +После создания Kubernetes кластера Ingress ресурсы не доступны по доменным именам. + +## Причина + +1. **extraPortMappings не добавлялись в конфигурацию Kind** - порты 80 и 443 не пробрасывались на host +2. **Записи в /etc/hosts не добавлялись автоматически** при применении манифестов + +## Решение + +### Вариант 1: Быстрое исправление (без пересоздания кластера) + +1. **Добавьте запись в `/etc/hosts` вручную:** + +```bash +echo "127.0.0.1 grafana.local #k8s" | sudo tee -a /etc/hosts +``` + +2. **Создайте port-forward для Ingress напрямую:** + +```bash +# Подключитесь к кластеру +export KUBECONFIG=$(docker exec k8s-controller cat /root/.kube/config) + +# Замените 0.0.0.0 на localhost в kubeconfig +export KUBECONFIG=$(echo "$KUBECONFIG" | sed 's/0\.0\.0\.0:6443/localhost:6443/g' > /tmp/kubeconfig-local.yaml && echo /tmp/kubeconfig-local.yaml) + +# Создайте port-forward для Ingress HTTP +kubectl port-forward -n ingress-nginx svc/ingress-nginx-controller 8081:80 & + +# Проверьте доступность +curl -H "Host: grafana.local" http://localhost:8081 +``` + +3. **Откройте в браузере:** + +``` +http://grafana.local:8081 +``` + +### Вариант 2: Пересоздание кластера (рекомендуется) + +Исправления уже внесены в код. Просто пересоздайте кластер: + +```bash +# Удалите старый кластер +make k8s destroy kubernetes + +# Создайте новый (с исправлениями) +make k8s create kubernetes + +# Примените манифест с Ingress +make k8s manifest apply kubernetes manifests/test-grafana-ingress.yaml + +# Запись в /etc/hosts добавится автоматически +# Проверьте +cat /etc/hosts | grep k8s + +# Откройте в браузере +open http://grafana.local:8081 +``` + +## Проверка + +```bash +# 1. Проверьте Ingress +docker exec k8s-controller kubectl --server=https://lab-control-plane:6443 --insecure-skip-tls-verify get ingress --all-namespaces + +# 2. Проверьте ports control-plane +docker port lab-control-plane + +# Должны быть: +# 6443/tcp -> 0.0.0.0:6443 +# 80/tcp -> 0.0.0.0:8081 <- после исправления +# 443/tcp -> 0.0.0.0:8443 <- после исправления + +# 3. Проверьте доступность +curl -H "Host: grafana.local" http://localhost:8081 +``` + +## Что было исправлено + +1. В `scripts/create_k8s_cluster.py` исправлена логика добавления `extraPortMappings` в конфигурацию Kind +2. Порты 80 и 443 теперь правильно пробрасываются на host (8081 и 8443) +3. Манифест Ingress можно применить и автоматически добавить запись в `/etc/hosts` + +## Дополнительно + +Если Ingress всё ещё не работает: + +1. **Проверьте статус подов Ingress Controller:** + +```bash +docker exec k8s-controller kubectl --server=https://lab-control-plane:6443 --insecure-skip-tls-verify get pods -n ingress-nginx +``` + +2. **Проверьте логи Ingress Controller:** + +```bash +docker exec k8s-controller kubectl --server=https://lab-control-plane:6443 --insecure-skip-tls-verify logs -n ingress-nginx -l app.kubernetes.io/component=controller +``` + +3. **Проверьте события:** + +```bash +docker exec k8s-controller kubectl --server=https://lab-control-plane:6443 --insecure-skip-tls-verify get events -n monitoring +``` diff --git a/docs/k8s-scripts.md b/docs/k8s-scripts.md new file mode 100644 index 0000000..a1f8c34 --- /dev/null +++ b/docs/k8s-scripts.md @@ -0,0 +1,232 @@ +# Скрипты управления Kubernetes + +**Автор:** Сергей Антропов +**Сайт:** https://devops.org.ru + +## Обзор + +В проекте используются несколько Python скриптов для автоматизации работы с Kubernetes кластерами на базе Kind. Все скрипты находятся в директории `scripts/`. + +## Скрипты + +### 1. `create_k8s_cluster.py` + +**Назначение:** Создание Kind кластера, установка аддонов и создание Docker контейнеров из пресета. + +**Принцип работы:** + +1. **Парсинг пресета:** Читает YAML файл пресета (например, `molecule/presets/k8s/kubernetes.yml`) + +2. **Создание Docker сети:** + - Проверяет наличие сети (по умолчанию `labnet`) + - Создает сеть если её нет + +3. **Создание Docker контейнеров:** + - Читает секцию `hosts` из пресета + - Для каждого хоста создает Docker контейнер с настройками из `systemd_defaults` + - Использует образы из секции `images` + +4. **Создание Kind кластера:** + - Генерирует конфигурацию Kind в формате YAML + - Настраивает `extraPortMappings` для Ingress портов + - Создает кластер через команду `kind create cluster` + +5. **Установка аддонов:** + - **Ingress NGINX:** Устанавливает ingress-nginx controller через kubectl apply + - **Metrics Server:** Устанавливает metrics-server с патчем для insecure TLS + - **Istio:** Устанавливает Istio через istioctl с профилем demo + - **Kiali:** Устанавливает Kiali через Helm (использует Helm chart) + - **Prometheus Stack:** Устанавливает Prometheus + Grafana через Helm (kube-prometheus-stack) + +6. **Подключение к сети Kind:** Подключает контейнер `k8s-controller` к сети `kind` для доступа к API серверу + +**Параметры:** +```bash +python3 scripts/create_k8s_cluster.py +``` + +**Пример:** +```bash +python3 scripts/create_k8s_cluster.py molecule/presets/k8s/kubernetes.yml k8s-controller +``` + +--- + +### 2. `delete_hosts.py` + +**Назначение:** Удаление Docker контейнеров, созданных из секции `hosts` пресета. + +**Принцип работы:** + +1. **Парсинг пресета:** Читает YAML файл пресета +2. **Получение списка хостов:** Извлекает секцию `hosts` +3. **Удаление контейнеров:** Для каждого хоста выполняет `docker rm -f ` + +**Параметры:** +```bash +python3 scripts/delete_hosts.py +``` + +**Пример:** +```bash +python3 scripts/delete_hosts.py molecule/presets/k8s/kubernetes.yml +``` + +--- + +### 3. `portforward.py` + +**Назначение:** Управление port-forward для доступа к сервисам Kubernetes извне кластера. + +**Принцип работы:** + +1. **Загрузка пресета:** Читает файл `molecule/presets/k8s/kubernetes.yml` + +2. **Получение kubeconfig:** + - Копирует kubeconfig из контейнера `k8s-controller` через `docker exec` + - Сохраняет во временный файл + +3. **Модификация kubeconfig:** + - Заменяет `server: https://0.0.0.0:6443` на `server: https://localhost:6443` + - Это необходимо для доступа с локальной машины + +4. **Создание port-forward:** + - Запускает `kubectl port-forward` для каждого сервиса из `addon_ports` + - Использует формат: `kubectl port-forward -n svc/ :` + - Управляет процессами через PID + +**Команды:** +- `create` - создает port-forward для всех сервисов +- `list` - показывает список активных портов +- `clear` - останавливает все port-forward процессы +- `recreate` - очищает и заново создает port-forward +- `delete ` - удаляет конкретный port-forward + +**Пример использования:** +```bash +python3 scripts/portforward.py create +python3 scripts/portforward.py list +python3 scripts/portforward.py delete 3000 +python3 scripts/portforward.py clear +``` + +**Важно:** Скрипт должен запускаться на локальной машине, где установлены `kubectl` и Python 3. + +--- + +### 4. `k8s_status.py` + +**Назначение:** Детальный отчет о состоянии Kubernetes кластера. + +**Принцип работы:** + +1. **Подключение к кластеру:** + - Получает имя кластера через `kind get clusters` + - Формирует адрес API сервера: `https://-control-plane:6443` + - Выполняет все kubectl команды через `docker exec k8s-controller` + +2. **Сбор информации:** + - **Общая информация:** версия Kubernetes + - **Узлы:** статус, ресурсы, описание каждого узла + - **Namespaces:** список всех namespace + - **Использование ресурсов:** метрики через metrics-server (если установлен) + - **Pods:** поды по каждому namespace + - **Deployments:** deployments по namespace + - **DaemonSets:** daemonsets по namespace + - **StatefulSets:** statefulsets по namespace + - **Services:** сервисы по namespace + - **Ingress:** ingress ресурсы + - **PVC:** PersistentVolumeClaims + - **События:** последние 20 событий по namespace + - **Helm релизы:** список установленных через Helm + +3. **Форматирование вывода:** + - Использует секции с разделителями + - Группирует информацию по namespace + - Показывает только непустые секции + +**Пример использования:** +```bash +python3 scripts/k8s_status.py +``` + +**Интеграция:** +- Автоматически вызывается командой `make k8s status [preset]` + +**Особенности:** +- Выполняет все команды внутри контейнера `k8s-controller` +- Использует прямой адрес control-plane для подключения +- Обходит проблемы с kubeconfig через `--insecure-skip-tls-verify` + +--- + +## Архитектура взаимодействия + +``` +┌─────────────────────────────────────────────────────┐ +│ Локальная машина │ +│ │ +│ Makefile → Python скрипты → Docker API │ +│ ↓ ↓ ↓ │ +│ make k8s scripts/*.py docker exec │ +└─────────────────────────────────────────────────────┘ + │ + ↓ +┌─────────────────────────────────────────────────────┐ +│ Docker контейнер │ +│ k8s-controller │ +│ ┌──────────────────────────────────────────┐ │ +│ │ kind, kubectl, helm, istioctl │ │ +│ └──────────────────────────────────────────┘ │ +└─────────────────────────────────────────────────────┘ + │ + ↓ +┌─────────────────────────────────────────────────────┐ +│ Docker сеть: kind │ +│ ┌──────────────────────────────────────────┐ │ +│ │ Kind Kubernetes Cluster │ │ +│ │ • Control Plane (6443) │ │ +│ │ • Worker Nodes │ │ +│ │ • Services (ClusterIP) │ │ +│ │ • Ingress │ │ +│ └──────────────────────────────────────────┘ │ +└─────────────────────────────────────────────────────┘ +``` + +## Общие принципы + +1. **Изоляция:** Все kubectl команды выполняются внутри контейнера `k8s-controller` +2. **Безопасность:** Используется `--insecure-skip-tls-verify` для обхода проблем с сертификатами +3. **Автоматизация:** Скрипты вызываются автоматически через Makefile +4. **Логгирование:** Все скрипты выводят подробную информацию о своих действиях + +## Требования + +- Python 3 (на локальной машине) +- kubectl (на локальной машине, для portforward.py) +- Docker +- Docker контейнер `k8s-controller` должен быть запущен + +## Отладка + +Если что-то не работает: + +1. **Проверьте контейнер:** + ```bash + docker ps | grep k8s-controller + ``` + +2. **Запустите скрипт вручную:** + ```bash + python3 scripts/k8s_status.py + ``` + +3. **Посмотрите логи:** + ```bash + docker logs k8s-controller + ``` + +4. **Проверьте кластер:** + ```bash + docker exec k8s-controller kubectl get nodes + ``` diff --git a/docs/kubernetes-commands.md b/docs/kubernetes-commands.md new file mode 100644 index 0000000..5ca5dfb --- /dev/null +++ b/docs/kubernetes-commands.md @@ -0,0 +1,395 @@ +# Команды для работы с Kubernetes + +Автор: Сергей Антропов +Сайт: https://devops.org.ru + +## Содержание + +- [Работа с манифестами](#работа-с-манифестами) +- [Работа с Helm](#работа-с-helm) +- [Работа с Helm репозиториями](#работа-с-helm-репозиториями) + +## Работа с манифестами + +Команды для применения, удаления и обновления манифестов YAML в кластере. + +### Синтаксис + +```bash +make k8s manifest [команда] [пресет] [URL_или_путь_к_файлу] +``` + +### Команды + +#### `apply` - Применение манифеста + +Применяет манифест YAML к кластеру. + +```bash +make k8s manifest apply kubernetes https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml +``` + +**Примеры:** +```bash +# Применение манифеста из URL +make k8s manifest apply kubernetes https://example.com/deploy.yaml + +# Применение локального манифеста +make k8s manifest apply kubernetes ./manifests/my-app.yaml +``` + +#### `delete` - Удаление ресурсов + +Удаляет ресурсы из кластера по манифесту. + +```bash +make k8s manifest delete kubernetes https://example.com/deploy.yaml +``` + +#### `update` - Обновление манифеста + +Обновляет ресурсы в кластере, используя манифест. + +```bash +make k8s manifest update kubernetes https://example.com/deploy.yaml +``` + +### Примеры использования + +```bash +# Установка NGINX Ingress Controller +make k8s manifest apply kubernetes https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml + +# Удаление ресурсов +make k8s manifest delete kubernetes https://example.com/deploy.yaml + +# Обновление конфигурации +make k8s manifest update kubernetes https://example.com/deploy.yaml --force +``` + +## Работа с Helm + +Команды для установки, обновления и управления Helm чартами в кластере. + +### Синтаксис + +```bash +make k8s helm [команда] [пресет] [релиз] [чант] +``` + +### Команды + +#### `apply` - Установка/обновление чарта + +Устанавливает новый релиз или обновляет существующий. + +```bash +make k8s helm apply kubernetes my-nginx nginx/nginx-ingress +``` + +**Параметры:** +- `пресет` - имя пресета кластера +- `релиз` - имя релиза (например: my-nginx) +- `чарт` - имя чарта (например: nginx/nginx-ingress) + +**Примеры:** +```bash +# Установка nginx-ingress +make k8s helm apply kubernetes nginx-ingress nginx/nginx-ingress + +# Установка с указанием репозитория +make k8s helm apply kubernetes prometheus prometheus-community/prometheus +``` + +#### `delete` - Удаление релиза + +Удаляет Helm релиз из кластера. + +```bash +make k8s helm delete kubernetes my-nginx +``` + +**Примеры:** +```bash +# Удаление релиза +make k8s helm delete kubernetes nginx-ingress + +# Удаление с флагом --keep-history +# (не поддерживается в текущей реализации) +``` + +#### `update` - Обновление релиза + +Обновляет существующий Helm релиз. + +```bash +make k8s helm update kubernetes my-nginx nginx/nginx-ingress +``` + +#### `rollback` - Откат релиза + +Откатывает релиз к предыдущей версии. + +```bash +make k8s helm rollback kubernetes my-nginx +``` + +**Примеры:** +```bash +# Откат к предыдущей ревизии +make k8s helm rollback kubernetes my-nginx + +# Откат к конкретной ревизии (не поддерживается в текущей реализации) +``` + +#### `list` - Список релизов + +Показывает список всех установленных Helm релизов. + +```bash +make k8s helm list kubernetes +``` + +**Пример вывода:** +``` +NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION +nginx-ingress default 1 2024-01-15 12:00:00.000000 +0000 UTC deployed nginx-ingress-0.1.0 1.0.0 +``` + +#### `status` - Статус релиза + +Показывает подробную информацию о статусе релиза. + +```bash +make k8s helm status kubernetes my-nginx +``` + +### Примеры использования + +```bash +# 1. Установка NGINX Ingress Controller +make k8s helm apply kubernetes nginx-ingress nginx/nginx-ingress + +# 2. Проверка статуса +make k8s helm status kubernetes nginx-ingress + +# 3. Обновление релиза +make k8s helm update kubernetes nginx-ingress nginx/nginx-ingress + +# 4. Просмотр списка релизов +make k8s helm list kubernetes + +# 5. Откат релиза +make k8s helm rollback kubernetes nginx-ingress + +# 6. Удаление релиза +make k8s helm delete kubernetes nginx-ingress +``` + +## Работа с Helm репозиториями + +Команды для управления Helm репозиториями. + +### Синтаксис + +```bash +make k8s helmrepo [команда] [пресет] [имя] [URL] +``` + +### Команды + +#### `add` - Добавление репозитория + +Добавляет новый Helm репозиторий. + +```bash +make k8s helmrepo add kubernetes stable https://charts.helm.sh/stable +``` + +**Примеры:** +```bash +# Добавление официального репозитория Helm +make k8s helmrepo add kubernetes stable https://charts.helm.sh/stable + +# Добавление репозитория Bitnami +make k8s helmrepo add kubernetes bitnami https://charts.bitnami.com/bitnami + +# Добавление репозитория NGINX +make k8s helmrepo add kubernetes nginx https://helm.nginx.com/stable + +# Добавление репозитория Prometheus +make k8s helmrepo add kubernetes prometheus-community https://prometheus-community.github.io/helm-charts + +# Добавление пользовательского репозитория +make k8s helmrepo add kubernetes my-repo https://charts.example.com +``` + +#### `list` - Список репозиториев + +Показывает список всех добавленных Helm репозиториев. + +```bash +make k8s helmrepo list kubernetes +``` + +**Пример вывода:** +``` +NAME URL +stable https://charts.helm.sh/stable +bitnami https://charts.bitnami.com/bitnami +nginx https://helm.nginx.com/stable +``` + +#### `delete` - Удаление репозитория + +Удаляет Helm репозиторий. + +```bash +make k8s helmrepo delete kubernetes stable +``` + +**Примеры:** +```bash +# Удаление репозитория +make k8s helmrepo delete kubernetes stable +``` + +#### `update` - Обновление репозиториев + +Обновляет информацию о всех Helm репозиториях. + +```bash +make k8s helmrepo update kubernetes +``` + +**Примеры:** +```bash +# Обновление всех репозиториев +make k8s helmrepo update kubernetes +``` + +#### `packages` - Список пакетов + +Показывает список пакетов в указанном репозитории. + +```bash +make k8s helmrepo packages kubernetes stable +``` + +**Примеры:** +```bash +# Просмотр пакетов в репозитории stable +make k8s helmrepo packages kubernetes stable + +# Просмотр пакетов в репозитории nginx +make k8s helmrepo packages kubernetes nginx + +# Поиск конкретного пакета +make k8s helmrepo packages kubernetes stable | grep nginx +``` + +### Примеры использования + +```bash +# 1. Добавление нескольких репозиториев +make k8s helmrepo add kubernetes stable https://charts.helm.sh/stable +make k8s helmrepo add kubernetes bitnami https://charts.bitnami.com/bitnami +make k8s helmrepo add kubernetes nginx https://helm.nginx.com/stable + +# 2. Просмотр списка репозиториев +make k8s helmrepo list kubernetes + +# 3. Обновление репозиториев +make k8s helmrepo update kubernetes + +# 4. Поиск пакетов в репозитории +make k8s helmrepo packages kubernetes stable + +# 5. Удаление репозитория +make k8s helmrepo delete kubernetes my-custom-repo + +# 6. Установка пакета из добавленного репозитория +make k8s helm apply kubernetes my-nginx nginx/nginx-ingress +``` + +## Полный рабочий пример + +```bash +# 1. Создание кластера +make k8s create kubernetes + +# 2. Добавление Helm репозиториев +make k8s helmrepo add kubernetes nginx https://helm.nginx.com/stable +make k8s helmrepo add kubernetes bitnami https://charts.bitnami.com/bitnami + +# 3. Обновление репозиториев +make k8s helmrepo update kubernetes + +# 4. Просмотр доступных пакетов +make k8s helmrepo packages kubernetes nginx + +# 5. Установка NGINX Ingress Controller +make k8s helm apply kubernetes nginx-ingress nginx/nginx-ingress + +# 6. Проверка статуса +make k8s helm status kubernetes nginx-ingress + +# 7. Просмотр списка релизов +make k8s helm list kubernetes + +# 8. Применение манифеста +make k8s manifest apply kubernetes https://example.com/deploy.yaml + +# 9. Откат релиза (если нужно) +make k8s helm rollback kubernetes nginx-ingress + +# 10. Удаление релиза +make k8s helm delete kubernetes nginx-ingress + +# 11. Удаление репозитория +make k8s helmrepo delete kubernetes nginx + +# 12. Удаление кластера +make k8s destroy kubernetes +``` + +## Обработка ошибок + +### Ошибка: Контейнер не запущен + +``` +❌ Контейнер k8s-kubernetes не запущен +💡 Запустите: make k8s create kubernetes +``` + +**Решение:** Запустите кластер перед выполнением команд. + +### Ошибка: Неизвестная команда + +``` +❌ Неизвестная команда: unknown +💡 Доступные команды: apply, delete, update +``` + +**Решение:** Используйте правильную команду из списка доступных. + +### Ошибка: Не указаны параметры + +``` +❌ Ошибка: Укажите имя релиза и чарт +💡 Пример: make k8s helm apply kubernetes my-release stable/nginx-ingress +``` + +**Решение:** Укажите все необходимые параметры команды. + +## Дополнительная информация + +- Все команды kubectl и helm выполняются внутри контейнера `k8s-[пресет]` +- Вам не нужно устанавливать kubectl или helm локально +- Подключение к кластеру происходит через имя узла control-plane +- Используется флаг `--insecure-skip-tls-verify` для обхода проблем с сертификатами + +## Автор + +Сергей Антропов +Сайт: https://devops.org.ru diff --git a/docs/kubernetes-full-guide.md b/docs/kubernetes-full-guide.md new file mode 100644 index 0000000..50f1607 --- /dev/null +++ b/docs/kubernetes-full-guide.md @@ -0,0 +1,906 @@ +# Полное руководство по работе с Kubernetes кластерами + +Автор: Сергей Антропов +Сайт: https://devops.org.ru + +## Содержание + +- [Введение](#введение) +- [Создание кластера](#создание-кластера) +- [Управление кластером](#управление-кластером) +- [Работа с манифестами](#работа-с-манифестами) +- [Работа с Helm](#работа-с-helm) +- [Настройка Ingress](#настройка-ingress) +- [Мониторинг и аддоны](#мониторинг-и-аддоны) +- [Service Mesh с Istio](#service-mesh-с-istio) +- [Примеры полных развертываний](#примеры-полных-развертываний) + +## Введение + +DevOpsLab предоставляет полную поддержку создания и управления локальными Kubernetes кластерами на основе Kind (Kubernetes in Docker). Kind позволяет запускать Kubernetes кластеры внутри Docker контейнеров, что идеально подходит для разработки, тестирования и обучения. + +### Основные возможности + +- Создание многоузловых Kubernetes кластеров +- Установка и управление Helm чартами +- Работа с манифестами YAML +- Настройка Ingress контроллеров +- Установка систем мониторинга (Prometheus, Grafana) +- Развертывание Service Mesh (Istio, Kiali) +- Изоляция сети и безопасность + +### Преимущества + +- Не требует установки локального Kubernetes +- Быстрое создание и удаление кластеров +- Поддержка многоузловых конфигураций +- Полная совместимость с production окружениями +- Контейнеризация всех инструментов + +## Создание кластера + +### Базовое создание + +Простое создание минимального кластера без дополнительных компонентов: + +```bash +make k8s create +``` + +Создаст кластер с пресетом `k8s-minimal` - один control-plane узел без дополнительных компонентов. + +### Создание полнофункционального кластера + +Создание кластера с предустановленными компонентами: + +```bash +make k8s create kubernetes +``` + +Этот пресет создает кластер со следующими компонентами: +- 1 control-plane узел +- 2 worker узла +- Ingress NGINX Controller +- Metrics Server +- Istio Service Mesh +- Kiali для визуализации Istio +- Prometheus Stack (Prometheus + Grafana) + +### Конфигурация пресета + +Пресеты находятся в `molecule/presets/k8s/`. Пример конфигурации: + +```yaml +kind_clusters: + - name: lab + workers: 2 + api_port: 6443 + addons: + ingress_nginx: true + metrics_server: true + istio: true + kiali: true + prometheus_stack: true + ingress_host_http_port: 8081 + ingress_host_https_port: 8443 + addon_ports: + prometheus: 9090 + grafana: 3000 + kiali: 20001 +``` + +### Проверка статуса кластера + +```bash +# Показать узлы кластера +make k8s nodes kubernetes + +# Вывод: +# NAME STATUS ROLES AGE VERSION +# lab-control-plane Ready control-plane 5m v1.34.0 +# lab-worker Ready 4m v1.34.0 +# lab-worker2 Ready 4m v1.34.0 + +# Показать подробный статус +make k8s status kubernetes +``` + +### Подключение к кластеру + +```bash +# Получить kubeconfig +make k8s config kubernetes + +# Использовать kubeconfig +export KUBECONFIG=$(pwd)/kubeconfig +kubectl get nodes +``` + +## Управление кластером + +### Остановка и запуск + +```bash +# Остановить кластер (без удаления) +make k8s stop kubernetes + +# Запустить остановленный кластер +make k8s start kubernetes + +# Перезапустить кластер +make k8s stop kubernetes && make k8s start kubernetes +``` + +### Удаление кластера + +```bash +# Полное удаление кластера и контейнера +make k8s destroy kubernetes +``` + +### Получение shell в контейнере + +```bash +# Открыть интерактивный shell +make k8s shell kubernetes + +# Теперь доступны все команды kubectl, helm, kind внутри контейнера +kubectl get nodes +helm list +kind get clusters +``` + +## Работа с манифестами + +### Применение манифеста + +Применение манифеста из URL: + +```bash +make k8s manifest apply kubernetes https://example.com/deploy.yaml +``` + +Применение локального манифеста: + +```bash +# Создайте файл example-deployment.yaml +cat > example-deployment.yaml < wordpress.yaml < app.yaml < + +# Просмотр логов с follow +kubectl --kubeconfig kubeconfig logs -f + +# Выполнить команду в поде +kubectl --kubeconfig kubeconfig exec -it -- /bin/sh + +# Описание ресурса +kubectl --kubeconfig kubeconfig describe pod +kubectl --kubeconfig kubeconfig describe service +``` + +### Масштабирование + +```bash +# Масштабировать Deployment +kubectl --kubeconfig kubeconfig scale deployment --replicas=5 + +# Автомасштабирование (требует metrics-server) +kubectl --kubeconfig kubeconfig autoscale deployment \ + --cpu-percent=70 --min=2 --max=10 +``` + +### Экспорт конфигурации + +```bash +# Экспортировать ресурс в YAML +kubectl --kubeconfig kubeconfig get deployment -o yaml > exported.yaml + +# Экспортировать все ресурсы namespace +kubectl --kubeconfig kubeconfig get all -n -o yaml > all-resources.yaml +``` + +## Безопасность + +### Использование Secrets + +```bash +# Создать Secret из файла +kubectl --kubeconfig kubeconfig create secret generic my-secret \ + --from-file=username=./username.txt \ + --from-file=password=./password.txt + +# Создать Secret из литерала +kubectl --kubeconfig kubeconfig create secret generic my-secret \ + --from-literal=username=admin \ + --from-literal=password=secret123 +``` + +### Network Policies + +Создайте файл `network-policy.yaml`: + +```yaml +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: test-network-policy + namespace: default +spec: + podSelector: + matchLabels: + role: db + policyTypes: + - Ingress + - Egress + ingress: + - from: + - podSelector: + matchLabels: + role: api + ports: + - protocol: TCP + port: 5432 + egress: + - to: + - podSelector: + matchLabels: + role: api + ports: + - protocol: TCP + port: 5432 +``` + +Примените: + +```bash +make k8s manifest apply kubernetes ./network-policy.yaml +``` + +## Заключение + +DevOpsLab предоставляет полный набор инструментов для работы с Kubernetes кластерами локально. Вы можете: + +- Создавать и управлять кластерами +- Устанавливать и настраивать приложения +- Работать с мониторингом и Service Mesh +- Тестировать перед развертыванием в production + +Все инструменты работают внутри Docker контейнеров, что обеспечивает изоляцию и переносимость. + +## Автор + +Сергей Антропов +Сайт: https://devops.org.ru diff --git a/docs/kubernetes-kind.md b/docs/kubernetes-kind.md new file mode 100644 index 0000000..de14e37 --- /dev/null +++ b/docs/kubernetes-kind.md @@ -0,0 +1,794 @@ +# Kubernetes Kind Кластеры + +**Автор:** Сергей Антропов +**Сайт:** https://devops.org.ru + +## Содержание + +- [Описание](#описание) +- [Требования к системе](#требования-к-системе) +- [Возможности](#возможности) +- [Быстрый старт](#быстрый-старт) +- [Команды управления](#команды-управления) +- [Работа с Helm](#работа-с-helm) +- [Работа с манифестами](#работа-с-манифестами) +- [Управление Ingress](#управление-ingress) +- [Проброс портов (Port-forward)](#проброс-портов-port-forward) +- [Мониторинг и логи](#мониторинг-и-логи) +- [Конфигурация](#конфигурация) +- [Архитектура](#архитектура) +- [Доступ к приложениям](#доступ-к-приложениям) +- [Кроссплатформенность](#кроссплатформенность) +- [Подробная документация по скриптам](#подробная-документация-по-скриптам) +- [Best Practices](#best-practices) +- [Troubleshooting](#troubleshooting) + +--- + +## Описание + +Проект поддерживает автоматическое создание и управление Kubernetes кластерами на базе [Kind](https://kind.sigs.k8s.io/) для тестирования в изолированной лабораторной среде. + +Kind позволяет создавать локальные Kubernetes кластеры внутри Docker контейнеров, что идеально подходит для разработки и тестирования без необходимости устанавливать полный Kubernetes. + +## Требования к системе + +### Обязательные требования + +1. **Docker** - для запуска Kind кластеров +2. **Python 3** - для управления port-forward +3. **kubectl** - для работы с кластером + +**Установка на macOS:** +```bash +brew install docker python3 kubectl +``` + +**Установка на Ubuntu/Debian:** +```bash +sudo apt update && sudo apt install -y docker.io python3 python3-pip kubectl +``` + +**Установка на CentOS/RHEL:** +```bash +sudo yum install -y docker python3 python3-pip kubectl +sudo systemctl start docker +sudo systemctl enable docker +``` + +### Проверка установки + +```bash +docker --version +python3 --version +kubectl version --client +``` + +### Docker группы + +На Linux добавьте пользователя в группу docker: +```bash +sudo usermod -aG docker $USER +# Выйдите и войдите заново +``` + +--- + +## Возможности + +- ✅ Создание Kind кластеров с настраиваемым количеством worker-узлов +- ✅ Автоматическая установка аддонов (Ingress NGINX, Metrics Server, Istio, Kiali, Prometheus Stack) +- ✅ **Автоматический port-forward** для доступа к сервисам +- ✅ Работа с Helm (установка, удаление, обновление, rollback) +- ✅ Работа с Kubernetes манифестами +- ✅ Управление Helm репозиториями +- ✅ Автоматическое управление `/etc/hosts` для Ingress +- ✅ Управление Docker контейнерами в лабораторной сети +- ✅ Интеграция с Istio Service Mesh +- ✅ Детальный отчет о состоянии кластера + +--- + +## Быстрый старт + +### 1. Создание кластера + +```bash +# Создание кластера с полным набором аддонов +make k8s create kubernetes +``` + +### 2. Проверка статуса + +```bash +# Детальный отчет о кластере +make k8s status kubernetes +``` + +### 3. Доступ к аддонам + +После создания кластера автоматически создаются port-forward: +- Grafana: http://localhost:3000 +- Prometheus: http://localhost:9090 +- Kiali: http://localhost:20001 + +### 4. Удаление кластера + +```bash +make k8s destroy kubernetes +``` + +--- + +## Команды управления + +### Создание кластера + +```bash +# Минимальный кластер (без аддонов) +make k8s create + +# Полный кластер с аддонами +make k8s create kubernetes + +# Пользовательский пресет +make k8s create my-custom-preset +``` + +**Что происходит:** +1. Создается контейнер `k8s-controller` с инструментами (Kind, kubectl, Helm, Istio CLI) +2. Создаются Docker контейнеры из раздела `hosts` (если есть) +3. Создается Kind кластер +4. Устанавливаются аддоны +5. Создается автоматический port-forward +6. Добавляются записи в `/etc/hosts` для Ingress + +### Управление жизненным циклом + +```bash +# Удаление кластера (с очисткой port-forward и /etc/hosts) +make k8s destroy [preset] + +# Остановка кластера (без удаления) +make k8s stop [preset] + +# Запуск остановленного кластера +make k8s start [preset] + +# Детальный отчет о состоянии +make k8s status [preset] + +# Показать узлы кластера +make k8s nodes [preset] +``` + +### Получение kubeconfig + +```bash +# Сохранить kubeconfig для подключения +make k8s config [preset] + +# Использовать конфиг +export KUBECONFIG=kubeconfig +kubectl get nodes +``` + +### Shell доступ + +```bash +# Открыть shell в контейнере k8s-controller +make k8s shell [preset] +``` + +--- + +## Работа с Helm + +Helm - это менеджер пакетов для Kubernetes. + +### Управление релизами + +```bash +# Установить чарт +make k8s helm apply kubernetes nginx stable/nginx-ingress + +# Обновить релиз +make k8s helm update kubernetes nginx stable/nginx-ingress + +# Откатить релиз +make k8s helm rollback kubernetes nginx + +# Посмотреть статус релиза +make k8s helm status kubernetes nginx + +# Удалить релиз +make k8s helm delete kubernetes nginx + +# Список всех релизов +make k8s helm list kubernetes +``` + +### Управление репозиториями + +```bash +# Добавить репозиторий +make k8s helmrepo add kubernetes stable https://charts.helm.sh/stable + +# Обновить репозиторий +make k8s helmrepo update kubernetes stable + +# Список репозиториев +make k8s helmrepo list kubernetes + +# Показать доступные чарты +make k8s helmrepo packages kubernetes stable + +# Удалить репозиторий +make k8s helmrepo delete kubernetes stable +``` + +### Пример: установка MySQL + +```bash +# Добавить репозиторий Bitnami +make k8s helmrepo add kubernetes bitnami https://charts.bitnami.com/bitnami + +# Установить MySQL +make k8s helm apply kubernetes mysql bitnami/mysql + +# Проверить статус +make k8s helm status kubernetes mysql +``` + +--- + +## Работа с манифестами + +Применение обычных Kubernetes манифестов (без Helm). + +```bash +# Применить манифест из URL +make k8s manifest apply kubernetes https://example.com/deploy.yaml + +# Применить манифест из файла +make k8s manifest apply kubernetes /path/to/manifest.yaml + +# Удалить манифест +make k8s manifest delete kubernetes https://example.com/deploy.yaml +``` + +### Пример: создание Deployment + +```yaml +# nginx-deployment.yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: nginx +spec: + replicas: 3 + selector: + matchLabels: + app: nginx + template: + metadata: + labels: + app: nginx + spec: + containers: + - name: nginx + image: nginx:latest + ports: + - containerPort: 80 +``` + +```bash +# Применить +make k8s manifest apply kubernetes ./nginx-deployment.yaml +``` + +--- + +## Управление Ingress + +### Доступ к приложениям через Ingress + +Для доступа к приложениям по доменным именам нужно вручную добавить записи в `/etc/hosts`: + +```bash +# Добавить запись в /etc/hosts +echo "127.0.0.1 grafana.local #k8s" | sudo tee -a /etc/hosts + +# Очистить DNS кеш macOS +sudo killall -HUP mDNSResponder +``` + +После этого приложение будет доступно по адресу: +``` +http://grafana.local:8081 +``` + +**Пример манифеста Ingress:** + +```yaml +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: grafana-ingress + namespace: monitoring +spec: + rules: + - host: grafana.local + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: monitoring-grafana + port: + number: 80 +``` + +**Важно:** +- Записи в `/etc/hosts` нужно добавлять вручную +- Используйте порт 8081 для HTTP и 8443 для HTTPS +- Для удаления записей используйте sudo + +--- + +## Проброс портов (Port-forward) + +Port-forward позволяет получить доступ к ClusterIP сервисам извне кластера. + +### Автоматический port-forward + +После создания кластера автоматически создаются порты: +- Ingress HTTP: `8081:80` +- Ingress HTTPS: `8443:443` +- Grafana: `3000:80` +- Prometheus: `9090:9090` +- Kiali: `20001:20001` + +### Управление вручную + +```bash +# Создать port-forward +make k8s portforward create + +# Список активных портов +make k8s portforward list + +# Удалить конкретный порт +make k8s portforward delete 3000 + +# Очистить все порты +make k8s portforward clear + +# Пересоздать порты +make k8s portforward recreate +``` + +### Ручной port-forward для своих сервисов + +```bash +# Подключиться к кластеру +export KUBECONFIG=$(docker exec k8s-controller cat /root/.kube/config) + +# Создать port-forward +kubectl port-forward -n default svc/my-service 8080:80 +``` + +--- + +## Мониторинг и логи + +### Детальный статус кластера + +```bash +make k8s status kubernetes +``` + +Показывает: +- Узлы кластера +- Namespaces +- Pods +- Services +- Ingress +- Deployments +- DaemonSets +- StatefulSets +- PVC +- События +- Helm релизы +- Использование ресурсов + +### Доступ к аддонам + +**Grafana:** +``` +URL: http://localhost:3000 +Login: admin +Password: admin +``` + +**Prometheus:** +``` +URL: http://localhost:9090 +``` + +**Kiali:** +``` +URL: http://localhost:20001 +Login: admin +Password: admin +``` + +### Логи контейнера + +```bash +# Логи k8s-controller +docker logs k8s-controller + +# Логи в реальном времени +docker logs -f k8s-controller +``` + +### Логи кластера + +```bash +# Логи конкретного pod +make k8s shell kubernetes +kubectl logs -n monitoring + +# Все логи в namespace +kubectl logs -n monitoring --all-containers=true --tail=100 +``` + +--- + +## Конфигурация + +### Пресеты + +Пресеты находятся в `molecule/presets/k8s/`: + +**kubernetes.yml** - полный набор аддонов: +- Ingress NGINX +- Metrics Server +- Istio +- Kiali +- Prometheus + Grafana + +### Структура пресета + +```yaml +k8s_cluster: + name: lab + nodes: 1 + +addons: + ingress: true + metrics_server: true + istio: true + kiali: true + prometheus_stack: true + +addon_ports: + ingress_http: 8081 + ingress_https: 8443 + prometheus: 9090 + grafana: 3000 + kiali: 20001 + metrics_server: 4443 + +hosts: + - name: test1 + image: centos8 + systemd_defaults: + container: true + +images: + centos8: + name: inecs/ansible-lab:centos8-latest +``` + +### Пользовательский пресет + +Создайте файл `molecule/presets/k8s/my-preset.yml`: + +```yaml +k8s_cluster: + name: my-cluster + nodes: 2 + +addons: + ingress: true + metrics_server: false + istio: false + kiali: false + prometheus_stack: false +``` + +Использование: +```bash +make k8s create my-preset +``` + +--- + +## Архитектура + +``` +┌─────────────────────────────────────────────────────┐ +│ Локальная машина │ +│ │ +│ ┌──────────────────────────────────────────────┐ │ +│ │ Makefile → Python скрипты → Docker API │ │ +│ │ kubectl (port-forward) │ │ +│ └──────────────────────────────────────────────┘ │ +└─────────────────────────────────────────────────────┘ + │ + ↓ +┌─────────────────────────────────────────────────────┐ +│ Docker: k8s-controller │ +│ ┌──────────────────────────────────────────────┐ │ +│ │ kind, kubectl, helm, istioctl │ │ +│ └──────────────────────────────────────────────┘ │ +└─────────────────────────────────────────────────────┘ + │ + ↓ +┌─────────────────────────────────────────────────────┐ +│ Docker сеть: kind │ +│ ┌──────────────────────────────────────────────┐ │ +│ │ Kind Kubernetes Cluster │ │ +│ │ • Control Plane (6443) │ │ +│ │ • Worker Nodes │ │ +│ │ • Services (ClusterIP) │ │ +│ │ • Ingress Controller │ │ +│ │ • Istio Service Mesh │ │ +│ └──────────────────────────────────────────────┘ │ +└─────────────────────────────────────────────────────┘ +``` + +### Компоненты + +1. **k8s-controller** - контейнер с инструментами управления +2. **Kind кластер** - Kubernetes кластер в Docker контейнерах +3. **Port-forward** - локальные процессы на хосте +4. **Ingress** - маршрутизация трафика внутрь кластера + +--- + +## Доступ к приложениям + +### Доступ через Ingress + +1. Создайте Ingress манифест +2. Примените через `make k8s manifest apply` +3. Запись автоматически добавится в `/etc/hosts` +4. Приложение доступно по доменному имени + +### Доступ через port-forward + +Для ClusterIP сервисов: +```bash +kubectl port-forward -n namespace svc/service-name 8080:80 +``` + +Доступ: http://localhost:8080 + +### Доступ внутри кластера + +Из другого pod: +```bash +kubectl exec -it pod-name -- curl http://service-name.namespace:80 +``` + +--- + +## Кроссплатформенность + +### Поддерживаемые платформы + +- **macOS (Intel & Apple Silicon)** - полная поддержка +- **Linux (amd64 & arm64)** - полная поддержка +- **Windows** - через WSL2 + +### Проблемы на разных платформах + +**Apple Silicon (M1/M2):** +- Используется ARM64 образы +- Автоматическое определение архитектуры + +**Linux:** +- Требуются права на Docker socket +- Возможны проблемы с selinux + +--- + +## Подробная документация по скриптам + +Для подробного описания работы всех скриптов управления Kubernetes смотрите: + +📖 [Документация по скриптам Kubernetes](k8s-scripts.md) + +Включает: +- Описание каждого скрипта +- Принцип работы +- Примеры использования +- Архитектура взаимодействия +- Отладка + +--- + +## Best Practices + +### 1. Используйте пресеты + +Не создавайте кластеры вручную, используйте пресеты для консистентности. + +### 2. Очищайте после работы + +```bash +# После тестирования +make k8s destroy kubernetes +``` + +### 3. Проверяйте статус + +```bash +# Регулярно проверяйте статус +make k8s status kubernetes +``` + +### 4. Используйте Helm для сложных приложений + +Для многослойных приложений лучше использовать Helm вместо сырых манифестов. + +### 5. Логируйте изменения + +Все изменения в кластере через `make k8s` автоматически логируются. + +--- + +## Troubleshooting + +### Кластер не создается + +**Проблема:** `kind create cluster` завершается с ошибкой + +**Решение:** +```bash +# Проверьте Docker +docker ps + +# Перезапустите Docker +sudo systemctl restart docker + +# Очистите старые кластеры +kind delete cluster --all +``` + +### Port-forward не работает + +**Проблема:** Невозможно подключиться к порту + +**Решение:** +```bash +# Проверьте процессы +make k8s portforward list + +# Пересоздайте порты +make k8s portforward recreate + +# Проверьте, что порт свободен +lsof -i :3000 +``` + +### kubectl не подключается + +**Проблема:** `kubectl get nodes` выдает ошибку + +**Решение:** +```bash +# Проверьте контейнер +docker ps | grep k8s-controller + +# Зайдите в контейнер +make k8s shell kubernetes + +# Проверьте кластер +kubectl get nodes + +# Если не работает, пересоздайте кластер +make k8s destroy kubernetes +make k8s create kubernetes +``` + +### Аддоны не устанавливаются + +**Проблема:** Grafana/Prometheus/Kiali не доступны + +**Решение:** +```bash +# Проверьте статус кластера +make k8s status kubernetes + +# Проверьте pods +make k8s shell kubernetes +kubectl get pods -n monitoring +kubectl logs -n monitoring + +# Пересоздайте кластер +make k8s destroy kubernetes +make k8s create kubernetes +``` + +### Ingress не работает + +**Проблема:** Доменные имена не резолвятся + +**Решение:** +```bash +# Проверьте Ingress +make k8s shell kubernetes +kubectl get ingress --all-namespaces + +# Добавьте запись в /etc/hosts вручную +echo "127.0.0.1 grafana.local #k8s" | sudo tee -a /etc/hosts + +# Очистите DNS кеш +sudo killall -HUP mDNSResponder + +# Проверьте доступность +curl http://grafana.local:8081 +``` + +### Helm чарты не устанавливаются + +**Проблема:** `helm install` завершается с ошибкой + +**Решение:** +```bash +# Проверьте репозитории +make k8s helmrepo list kubernetes + +# Обновите репозитории +make k8s helmrepo update kubernetes stable + +# Проверьте логи +make k8s shell kubernetes +kubectl logs -l app= +``` + +### Контейнер k8s-controller не запускается + +**Проблема:** `docker: Error response from daemon: ...` + +**Решение:** +```bash +# Проверьте образ +docker images | grep k8s + +# Пересоберите образ +make docker build-image IMAGE=k8s-amd64 +make docker build-image IMAGE=k8s-arm64 + +# Проверьте Docker +docker system prune -f +``` + +--- + +## Контакты + +- **Автор:** Сергей Антропов +- **Сайт:** https://devops.org.ru +- **GitHub:** https://github.com/your-repo + +--- + +## Лицензия + +MIT diff --git a/docs/monitoring.md b/docs/monitoring.md index 15ada55..2899e52 100644 --- a/docs/monitoring.md +++ b/docs/monitoring.md @@ -2,7 +2,7 @@ **Автор:** Сергей Антропов **Сайт:** https://devops.org.ru -**Версия:** 2.0.0 +**Версия:** 3.0.0 ## 🔍 Диагностика Docker diff --git a/docs/platform-support.md b/docs/platform-support.md index 6634307..34ce80a 100644 --- a/docs/platform-support.md +++ b/docs/platform-support.md @@ -2,7 +2,7 @@ **Автор:** Сергей Антропов **Сайт:** https://devops.org.ru -**Версия:** 2.0.0 +**Версия:** 3.0.0 ## Описание diff --git a/manifests/test-grafana-ingress.yaml b/manifests/test-grafana-ingress.yaml new file mode 100644 index 0000000..37122ca --- /dev/null +++ b/manifests/test-grafana-ingress.yaml @@ -0,0 +1,19 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: grafana-ingress + namespace: monitoring + annotations: + nginx.ingress.kubernetes.io/rewrite-target: / +spec: + rules: + - host: grafana.local + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: monitoring-grafana + port: + number: 80 diff --git a/molecule/default/create.yml b/molecule/default/create.yml index f919310..673b727 100644 --- a/molecule/default/create.yml +++ b/molecule/default/create.yml @@ -4,7 +4,8 @@ vars: # Получаем preset из переменной окружения или используем default preset_name: "{{ lookup('env', 'MOLECULE_PRESET') | default('default') }}" - preset_file: "/workspace/molecule/presets/{{ preset_name }}.yml" + # Проверяем сначала в папке k8s, затем в основной папке presets + preset_file: "{{ '/workspace/molecule/presets/k8s/' + preset_name + '.yml' if (preset_name in ['k8s-minimal', 'kubernetes', 'k8s-full'] or preset_name.startswith('k8s-')) else '/workspace/molecule/presets/' + preset_name + '.yml' }}" # Fallback значения если preset файл не найден docker_network: labnet @@ -31,6 +32,7 @@ - name: u1 family: debian groups: [test] + kind_clusters: [] tasks: # - name: Install required collections @@ -282,4 +284,4 @@ - Groups: {{ groups_map.keys() | list | join(', ') }} - Systemd nodes: {{ hosts | selectattr('type','undefined') | list | length }} - DinD nodes: {{ hosts | selectattr('type','defined') | selectattr('type','equalto','dind') | list | length }} - - DOoD nodes: {{ hosts | selectattr('type','defined') | selectattr('type','equalto','dood') | list | length }} \ No newline at end of file + - DOoD nodes: {{ hosts | selectattr('type','defined') | selectattr('type','equalto','dood') | list | length }} diff --git a/molecule/default/destroy.yml b/molecule/default/destroy.yml index f319182..587b37d 100644 --- a/molecule/default/destroy.yml +++ b/molecule/default/destroy.yml @@ -4,7 +4,8 @@ vars: # Получаем preset из переменной окружения или используем default preset_name: "{{ lookup('env', 'MOLECULE_PRESET') | default('default') }}" - preset_file: "/workspace/molecule/presets/{{ preset_name }}.yml" + # Проверяем сначала в папке k8s, затем в основной папке presets + preset_file: "{{ '/workspace/molecule/presets/k8s/' + preset_name + '.yml' if (preset_name in ['k8s-minimal', 'kubernetes', 'k8s-full'] or preset_name.startswith('k8s-')) else '/workspace/molecule/presets/' + preset_name + '.yml' }}" # Fallback значения если preset файл не найден docker_network: labnet @@ -12,6 +13,7 @@ - name: u1 family: debian groups: [test] + kind_clusters: [] tasks: - name: Load preset configuration @@ -80,4 +82,5 @@ 🧹 Cleanup Summary: - Removed containers: {{ hosts | length }} - Removed DinD volumes: {{ hosts | selectattr('type','defined') | selectattr('type','equalto','dind') | list | length }} - - Network: {{ docker_network }} \ No newline at end of file + - Network: {{ docker_network }} + - Removed kind clusters: {{ kind_clusters | default([]) | length }} \ No newline at end of file diff --git a/molecule/presets/examples/standart.yml b/molecule/presets/examples/standart.yml index df38870..f21624e 100644 --- a/molecule/presets/examples/standart.yml +++ b/molecule/presets/examples/standart.yml @@ -34,6 +34,20 @@ systemd_defaults: tmpfs: ["/run", "/run/lock"] capabilities: ["SYS_ADMIN"] +# Kind кластеры (опционально) +# kind_clusters: +# - name: lab +# workers: 2 +# api_port: 6443 +# addons: +# ingress_nginx: true +# metrics_server: true +# istio: true +# kiali: true +# prometheus_stack: true +# ingress_host_http_port: 8081 +# ingress_host_https_port: 8443 + hosts: # Стандартный набор - 3 хоста - name: u1 diff --git a/molecule/presets/k8s/k8s-minimal.yml b/molecule/presets/k8s/k8s-minimal.yml new file mode 100644 index 0000000..5408b26 --- /dev/null +++ b/molecule/presets/k8s/k8s-minimal.yml @@ -0,0 +1,42 @@ +--- +#description: Минимальный Kind кластер без аддонов +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +docker_network: labnet +generated_inventory: "{{ molecule_ephemeral_directory }}/inventory/hosts.ini" + +# systemd-ready образы +images: + alt: "inecs/ansible-lab:alt-linux-latest" + astra: "inecs/ansible-lab:astra-linux-latest" + rhel: "inecs/ansible-lab:rhel-latest" + centos7: "inecs/ansible-lab:centos7-latest" + centos8: "inecs/ansible-lab:centos8-latest" + centos9: "inecs/ansible-lab:centos9-latest" + alma: "inecs/ansible-lab:alma-latest" + rocky: "inecs/ansible-lab:rocky-latest" + redos: "inecs/ansible-lab:redos-latest" + ubuntu20: "inecs/ansible-lab:ubuntu20-latest" + ubuntu22: "inecs/ansible-lab:ubuntu22-latest" + ubuntu24: "inecs/ansible-lab:ubuntu24-latest" + debian9: "inecs/ansible-lab:debian9-latest" + debian10: "inecs/ansible-lab:debian10-latest" + debian11: "inecs/ansible-lab:debian11-latest" + debian12: "inecs/ansible-lab:debian12-latest" + +systemd_defaults: + privileged: true + command: "/sbin/init" + volumes: + - "/sys/fs/cgroup:/sys/fs/cgroup:rw" + tmpfs: ["/run", "/run/lock"] + capabilities: ["SYS_ADMIN"] + +# Минимальный Kind кластер без аддонов +kind_clusters: + - name: minimal + workers: 0 # Только control-plane + api_port: 6443 + +hosts: [] diff --git a/molecule/presets/k8s/kubernetes.yml b/molecule/presets/k8s/kubernetes.yml new file mode 100644 index 0000000..0284f48 --- /dev/null +++ b/molecule/presets/k8s/kubernetes.yml @@ -0,0 +1,66 @@ +--- +#description: Пресет для тестирования с Kubernetes Kind кластером +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +docker_network: labnet +generated_inventory: "{{ molecule_ephemeral_directory }}/inventory/hosts.ini" + +# systemd-ready образы +images: + alt: "inecs/ansible-lab:alt-linux-latest" + astra: "inecs/ansible-lab:astra-linux-latest" + rhel: "inecs/ansible-lab:rhel-latest" + centos7: "inecs/ansible-lab:centos7-latest" + centos8: "inecs/ansible-lab:centos8-latest" + centos9: "inecs/ansible-lab:centos9-latest" + alma: "inecs/ansible-lab:alma-latest" + rocky: "inecs/ansible-lab:rocky-latest" + redos: "inecs/ansible-lab:redos-latest" + ubuntu20: "inecs/ansible-lab:ubuntu20-latest" + ubuntu22: "inecs/ansible-lab:ubuntu22-latest" + ubuntu24: "inecs/ansible-lab:ubuntu24-latest" + debian9: "inecs/ansible-lab:debian9-latest" + debian10: "inecs/ansible-lab:debian10-latest" + debian11: "inecs/ansible-lab:debian11-latest" + debian12: "inecs/ansible-lab:debian12-latest" + +systemd_defaults: + privileged: true + command: "/sbin/init" + volumes: + - "/sys/fs/cgroup:/sys/fs/cgroup:rw" + tmpfs: ["/run", "/run/lock"] + capabilities: ["SYS_ADMIN"] + +# Kind кластеры с полным набором аддонов +kind_clusters: + - name: lab + workers: 2 + api_port: 6443 + addons: + ingress_nginx: true + metrics_server: true + istio: true + kiali: true + prometheus_stack: true + # Порты для доступа к аддонам извне + # Ingress HTTP: http://localhost:8081 + # Ingress HTTPS: https://localhost:8443 + # Prometheus: http://localhost:9090 + # Grafana: http://localhost:3000 (admin/admin) + # Kiali: http://localhost:20001 + # Metrics Server: http://localhost:4443 + addon_ports: + ingress_http: 8081 + ingress_https: 8443 + prometheus: 9090 + grafana: 3000 + kiali: 20001 + metrics_server: 4443 + +hosts: [] +# # Стандартный набор - 2 хоста для базового тестирования (стабильные ОС) +# - name: u1 +# family: ubuntu22 +# groups: [test, web] diff --git a/roles/devops/QUICKSTART.md b/roles/devops/QUICKSTART.md index ee40527..91583a2 100644 --- a/roles/devops/QUICKSTART.md +++ b/roles/devops/QUICKSTART.md @@ -2,7 +2,7 @@ **Автор:** Сергей Антропов **Сайт:** https://devops.org.ru -**Версия:** 2.0.0 +**Версия:** 3.0.0 ## Что делает роль diff --git a/roles/ping/QUICKSTART.md b/roles/ping/QUICKSTART.md index 2af14c3..6e367fd 100644 --- a/roles/ping/QUICKSTART.md +++ b/roles/ping/QUICKSTART.md @@ -2,7 +2,7 @@ **Автор:** Сергей Антропов **Сайт:** https://devops.org.ru -**Версия:** 2.0.0 +**Версия:** 3.0.0 ## Что делает роль? diff --git a/scripts/create_k8s_cluster.py b/scripts/create_k8s_cluster.py new file mode 100755 index 0000000..993a5a9 --- /dev/null +++ b/scripts/create_k8s_cluster.py @@ -0,0 +1,244 @@ +#!/usr/bin/env python3 +""" +Скрипт для создания Kind кластеров +Автор: Сергей Антропов +Сайт: https://devops.org.ru +""" +import sys +import yaml +import subprocess +import os + +def run_cmd(cmd): + """Выполнить команду""" + print(f"[run] {cmd}") + result = subprocess.run(cmd, shell=True, capture_output=True, text=True) + if result.returncode != 0: + print(f"[error] {result.stderr}") + sys.exit(1) + print(result.stdout) + return result.stdout + +def main(): + if len(sys.argv) < 3: + print("Usage: create_k8s_cluster.py ") + sys.exit(1) + + preset_file = sys.argv[1] + container_name = sys.argv[2] + + print(f"📋 Читаю пресет: {preset_file}") + with open(preset_file, 'r') as f: + preset = yaml.safe_load(f) + + # Создаем Docker сеть если её нет + docker_network = preset.get('docker_network', 'labnet') + print(f"\n🌐 Проверка Docker сети: {docker_network}") + result = subprocess.run(f"docker network ls --format '{{{{.Name}}}}' | grep -x {docker_network}", + shell=True, capture_output=True, text=True) + if not result.stdout.strip(): + print(f"📡 Создание Docker сети: {docker_network}") + run_cmd(f"docker network create {docker_network}") + else: + print(f"✅ Сеть {docker_network} уже существует") + + # Получаем конфигурацию для hosts + hosts = preset.get('hosts', []) + images = preset.get('images', {}) + systemd_defaults = preset.get('systemd_defaults', {}) + + # Создаем контейнеры если определены hosts + if hosts: + print(f"\n🐳 Создание контейнеров (всего: {len(hosts)})") + for host in hosts: + host_name = host['name'] + family = host['family'] + + # Проверяем существование контейнера + result = subprocess.run(f"docker ps -a --format '{{{{.Names}}}}' | grep -x {host_name}", + shell=True, capture_output=True, text=True) + if result.stdout.strip(): + print(f"⚠️ Контейнер '{host_name}' уже существует, удаляем старый") + run_cmd(f"docker rm -f {host_name}") + + # Получаем образ + image = images.get(family, f"inecs/ansible-lab:{family}-latest") + + # Формируем команду docker run + cmd_parts = [ + "docker run -d", + f"--name {host_name}", + f"--network {docker_network}", + "--restart=unless-stopped" + ] + + # Добавляем systemd настройки + if systemd_defaults.get('privileged'): + cmd_parts.append("--privileged") + + for vol in systemd_defaults.get('volumes', []): + cmd_parts.append(f"-v {vol}") + + for tmpfs in systemd_defaults.get('tmpfs', []): + cmd_parts.append(f"--tmpfs {tmpfs}") + + if systemd_defaults.get('capabilities'): + for cap in systemd_defaults['capabilities']: + cmd_parts.append(f"--cap-add {cap}") + + cmd_parts.append(image) + + # Добавляем command в конец если задан + if systemd_defaults.get('command'): + cmd_parts.append(systemd_defaults['command']) + + cmd = " ".join(cmd_parts) + print(f"🚀 Создание контейнера: {host_name}") + run_cmd(cmd) + print(f"✅ Контейнер '{host_name}' создан") + + kind_clusters = preset.get('kind_clusters', []) + if not kind_clusters: + print("\n⚠️ В пресете не определены kind кластеры") + print("✅ Создание контейнеров завершено") + sys.exit(0) + + os.makedirs("/ansible/.kind", exist_ok=True) + + for cluster in kind_clusters: + name = cluster['name'] + config_file = f"/ansible/.kind/{name}.yaml" + + print(f"\n☸️ Создание конфигурации для кластера: {name}") + + # Создаем конфигурацию Kind + config = { + 'kind': 'Cluster', + 'apiVersion': 'kind.x-k8s.io/v1alpha4', + 'nodes': [ + {'role': 'control-plane'} + ], + 'networking': { + 'apiServerAddress': '0.0.0.0', + 'apiServerPort': cluster.get('api_port', 0) + } + } + + # Добавляем extraPortMappings для всех портов из addon_ports + addon_ports = cluster.get('addon_ports', {}) + + # Ingress порты для проброса на host + if addon_ports.get('ingress_http') or addon_ports.get('ingress_https'): + # Добавляем extraPortMappings к control-plane узлу + if 'extraPortMappings' not in config['nodes'][0]: + config['nodes'][0]['extraPortMappings'] = [] + + if addon_ports.get('ingress_http'): + config['nodes'][0]['extraPortMappings'].append({ + 'containerPort': 80, + 'hostPort': addon_ports['ingress_http'], + 'protocol': 'TCP' + }) + if addon_ports.get('ingress_https'): + config['nodes'][0]['extraPortMappings'].append({ + 'containerPort': 443, + 'hostPort': addon_ports['ingress_https'], + 'protocol': 'TCP' + }) + + # Не добавляем extraPortMappings для портов аддонов - используем port-forward + + # Добавляем worker nodes + workers = cluster.get('workers', 0) + for i in range(workers): + config['nodes'].append({'role': 'worker'}) + + # Записываем конфигурацию + with open(config_file, 'w') as f: + yaml.dump(config, f) + + print(f"✅ Конфигурация сохранена: {config_file}") + + # Проверяем существование кластера + result = subprocess.run(f"kind get clusters", shell=True, capture_output=True, text=True) + existing = result.stdout.strip().split('\n') if result.returncode == 0 else [] + + if name in existing: + print(f"⚠️ Кластер '{name}' уже существует, пропускаю") + else: + print(f"🚀 Создание кластера: {name}") + run_cmd(f"kind create cluster --name {name} --config {config_file}") + + # Подключаем контейнер k8s-controller к сети kind + print(f"🔗 Подключение контейнера к сети kind...") + result = subprocess.run(f"docker network inspect kind", shell=True, capture_output=True, text=True) + if result.returncode == 0: + # Получаем имя контейнера из аргументов (второй аргумент) + controller_name = sys.argv[2] if len(sys.argv) > 2 else "k8s-controller" + result = subprocess.run(f"docker network connect kind {controller_name}", shell=True, capture_output=True, text=True) + if result.returncode == 0: + print(f"✅ Контейнер {controller_name} подключен к сети kind") + else: + print(f"⚠️ Не удалось подключить контейнер к сети kind: {result.stderr}") + else: + print(f"⚠️ Сеть kind не найдена") + + # Устанавливаем аддоны + addons = cluster.get('addons', {}) + if not addons: + continue + + print(f"\n📦 Установка аддонов для кластера: {name}") + + if addons.get('ingress_nginx'): + print(" - Installing ingress-nginx") + run_cmd(f"kubectl --server=https://{name}-control-plane:6443 --insecure-skip-tls-verify apply --validate=false -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml") + run_cmd(f"kubectl --server=https://{name}-control-plane:6443 --insecure-skip-tls-verify -n ingress-nginx rollout status deploy/ingress-nginx-controller --timeout=180s") + + if addons.get('metrics_server'): + print(" - Installing metrics-server") + run_cmd(f"kubectl --server=https://{name}-control-plane:6443 --insecure-skip-tls-verify apply --validate=false -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml") + patch_json = '{"spec":{"template":{"spec":{"containers":[{"name":"metrics-server","args":["--kubelet-insecure-tls","--kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname"]}]}}}}' + run_cmd(f"kubectl --server=https://{name}-control-plane:6443 --insecure-skip-tls-verify -n kube-system patch deploy metrics-server -p '{patch_json}'") + + if addons.get('istio'): + print(" - Installing Istio") + # Генерируем kubeconfig и заменяем 0.0.0.0 на IP control-plane узла + run_cmd(f"kind get kubeconfig --name {name} > /tmp/istio-kubeconfig-{name}.yaml") + # Получаем IP control-plane узла и заменяем в kubeconfig + result = subprocess.run(f"docker inspect {name}-control-plane --format='{{{{.NetworkSettings.Networks.kind.IPAddress}}}}'", + shell=True, capture_output=True, text=True) + if result.returncode == 0: + control_plane_ip = result.stdout.strip() + # Заменяем 0.0.0.0 на IP control-plane + subprocess.run(f"sed -i 's/0\\.0\\.0\\.0:6443/{control_plane_ip}:6443/g' /tmp/istio-kubeconfig-{name}.yaml", shell=True) + # Устанавливаем Istio используя kubeconfig + run_cmd(f"KUBECONFIG=/tmp/istio-kubeconfig-{name}.yaml istioctl install -y --set profile=demo") + run_cmd(f"kubectl --server=https://{name}-control-plane:6443 --insecure-skip-tls-verify -n istio-system rollout status deploy/istiod --timeout=180s") + run_cmd(f"kubectl --server=https://{name}-control-plane:6443 --insecure-skip-tls-verify -n istio-system rollout status deploy/istio-ingressgateway --timeout=180s") + + if addons.get('kiali'): + print(" - Installing Kiali") + subprocess.run(f"kubectl --server=https://{name}-control-plane:6443 --insecure-skip-tls-verify create ns istio-system", shell=True, capture_output=True) + # Добавляем Helm репозиторий Kiali + run_cmd(f"helm repo add kiali https://kiali.org/helm-charts") + run_cmd(f"helm repo update") + # Используем исправленный kubeconfig + run_cmd(f"KUBECONFIG=/tmp/istio-kubeconfig-{name}.yaml helm upgrade --install kiali-server kiali/kiali-server --namespace istio-system --set auth.strategy=anonymous --wait --timeout 180s") + + if addons.get('prometheus_stack'): + print(" - Installing Prometheus Stack") + # Добавляем Helm репозиторий Prometheus + subprocess.run(f"helm repo add prometheus-community https://prometheus-community.github.io/helm-charts", shell=True, capture_output=True) + subprocess.run(f"helm repo update", shell=True, capture_output=True) + subprocess.run(f"kubectl --server=https://{name}-control-plane:6443 --insecure-skip-tls-verify create ns monitoring", shell=True, capture_output=True) + # Используем исправленный kubeconfig + run_cmd(f"KUBECONFIG=/tmp/istio-kubeconfig-{name}.yaml helm upgrade --install monitoring prometheus-community/kube-prometheus-stack --namespace monitoring --set grafana.adminPassword=admin --set grafana.defaultDashboardsTimezone=browser --wait --timeout 600s") + run_cmd(f"kubectl --server=https://{name}-control-plane:6443 --insecure-skip-tls-verify -n monitoring rollout status deploy/monitoring-grafana --timeout=300s") + + print(f"✅ Кластер '{name}' готов!") + + print("\n🎉 Все кластеры созданы!") + +if __name__ == '__main__': + main() diff --git a/scripts/delete_hosts.py b/scripts/delete_hosts.py new file mode 100644 index 0000000..865dc1a --- /dev/null +++ b/scripts/delete_hosts.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python3 +""" +Скрипт для удаления контейнеров из секции hosts пресета +Автор: Сергей Антропов +Сайт: https://devops.org.ru +""" +import sys +import yaml +import subprocess + +def main(): + if len(sys.argv) < 2: + print("Usage: delete_hosts.py ") + sys.exit(1) + + preset_file = sys.argv[1] + + print(f"📋 Читаю пресет: {preset_file}") + with open(preset_file, 'r') as f: + preset = yaml.safe_load(f) + + hosts = preset.get('hosts', []) + if not hosts: + print("⚠️ В пресете нет контейнеров для удаления") + sys.exit(0) + + print(f"🗑️ Удаление контейнеров (всего: {len(hosts)})") + for host in hosts: + host_name = host['name'] + + # Проверяем существование контейнера + result = subprocess.run(f"docker ps -a --format '{{{{.Names}}}}' | grep -x {host_name}", + shell=True, capture_output=True, text=True) + if result.stdout.strip(): + print(f"🗑️ Удаление контейнера: {host_name}") + subprocess.run(f"docker rm -f {host_name}", shell=True, capture_output=True, text=True) + print(f"✅ Контейнер '{host_name}' удален") + else: + print(f"⚠️ Контейнер '{host_name}' не найден") + + print("✅ Удаление завершено") + +if __name__ == "__main__": + main() diff --git a/scripts/k8s_status.py b/scripts/k8s_status.py new file mode 100755 index 0000000..5c76c51 --- /dev/null +++ b/scripts/k8s_status.py @@ -0,0 +1,300 @@ +#!/usr/bin/env python3 +""" +Скрипт для детального отчета о состоянии Kubernetes кластера +Автор: Сергей Антропов +Сайт: https://devops.org.ru +""" +import sys +import subprocess +import json + +def get_cluster_name(): + """Получает имя кластера""" + result = subprocess.run("docker exec k8s-controller kind get clusters | head -1", shell=True, capture_output=True, text=True) + if result.returncode == 0: + return result.stdout.strip() + return None + +def run_kubectl_cmd(cmd): + """Выполняет команду kubectl внутри контейнера k8s-controller""" + cluster_name = get_cluster_name() + if cluster_name: + # Используем прямой адрес control-plane + server = f"https://{cluster_name}-control-plane:6443" + cmd_with_server = f"--server={server} --insecure-skip-tls-verify {cmd}" + else: + cmd_with_server = cmd + + full_cmd = f"docker exec k8s-controller kubectl {cmd_with_server}" + result = subprocess.run(full_cmd, shell=True, capture_output=True, text=True) + return result.stdout + +def print_section(title): + """Выводит заголовок секции""" + print(f"\n{'='*70}") + print(f" {title}") + print(f"{'='*70}\n") + +def print_subsection(title): + """Выводит подзаголовок""" + print(f"\n{'─'*70}") + print(f" {title}") + print(f"{'─'*70}\n") + +def get_cluster_info(): + """Получает информацию о кластере""" + print_section("📊 ОБЩАЯ ИНФОРМАЦИЯ О КЛАСТЕРЕ") + + # Версия Kubernetes + version = run_kubectl_cmd("version --short") + print(version) + +def get_nodes_status(): + """Получает статус узлов""" + print_section("🖥️ УЗЛЫ КЛАСТЕРА") + + nodes = run_kubectl_cmd("get nodes -o wide") + print(nodes) + + # Детальная информация о каждом узле + node_names = run_kubectl_cmd("get nodes -o jsonpath='{.items[*].metadata.name}'") + if node_names.strip(): + for node in node_names.strip().split(): + print_subsection(f"Узел: {node}") + node_info = run_kubectl_cmd(f"describe node {node}") + print(node_info) + +def get_namespaces(): + """Получает список namespace""" + print_section("📁 NAMESPACES") + + namespaces = run_kubectl_cmd("get namespaces") + print(namespaces) + +def get_pods_by_namespace(): + """Получает поды по namespace""" + print_section("🪟 PODS") + + # Получаем список namespace + namespaces_output = run_kubectl_cmd("get namespaces -o json") + try: + namespaces_data = json.loads(namespaces_output) + namespaces = [ns['metadata']['name'] for ns in namespaces_data['items']] + except: + namespaces = ['default', 'kube-system', 'kube-public', 'kube-node-lease'] + + for ns in namespaces: + print_subsection(f"Namespace: {ns}") + pods = run_kubectl_cmd(f"get pods -n {ns} -o wide") + if pods.strip(): + print(pods) + else: + print(" (пусто)") + +def get_services(): + """Получает сервисы""" + print_section("🔗 SERVICES") + + namespaces_output = run_kubectl_cmd("get namespaces -o json") + try: + namespaces_data = json.loads(namespaces_output) + namespaces = [ns['metadata']['name'] for ns in namespaces_data['items']] + except: + namespaces = ['default', 'kube-system', 'kube-public', 'kube-node-lease'] + + for ns in namespaces: + print_subsection(f"Namespace: {ns}") + services = run_kubectl_cmd(f"get services -n {ns}") + if services.strip(): + print(services) + else: + print(" (пусто)") + +def get_ingress(): + """Получает Ingress ресурсы""" + print_section("🌐 INGRESS") + + namespaces_output = run_kubectl_cmd("get namespaces -o json") + try: + namespaces_data = json.loads(namespaces_output) + namespaces = [ns['metadata']['name'] for ns in namespaces_data['items']] + except: + namespaces = ['default', 'kube-system', 'kube-public', 'kube-node-lease'] + + ingress_found = False + for ns in namespaces: + ingress = run_kubectl_cmd(f"get ingress -n {ns} 2>/dev/null") + if ingress.strip() and "No resources found" not in ingress: + ingress_found = True + print_subsection(f"Namespace: {ns}") + print(ingress) + + if not ingress_found: + print(" Ingress ресурсы не найдены") + +def get_pvcs(): + """Получает PersistentVolumeClaims""" + print_section("💾 VOLUMES (PVC)") + + namespaces_output = run_kubectl_cmd("get namespaces -o json") + try: + namespaces_data = json.loads(namespaces_output) + namespaces = [ns['metadata']['name'] for ns in namespaces_data['items']] + except: + namespaces = ['default', 'kube-system', 'kube-public', 'kube-node-lease'] + + pvc_found = False + for ns in namespaces: + pvcs = run_kubectl_cmd(f"get pvc -n {ns} 2>/dev/null") + if pvcs.strip() and "No resources found" not in pvcs: + pvc_found = True + print_subsection(f"Namespace: {ns}") + print(pvcs) + + if not pvc_found: + print(" PVC не найдены") + +def get_deployments(): + """Получает Deployments""" + print_section("🚀 DEPLOYMENTS") + + namespaces_output = run_kubectl_cmd("get namespaces -o json") + try: + namespaces_data = json.loads(namespaces_output) + namespaces = [ns['metadata']['name'] for ns in namespaces_data['items']] + except: + namespaces = ['default', 'kube-system', 'kube-public', 'kube-node-lease'] + + for ns in namespaces: + print_subsection(f"Namespace: {ns}") + deployments = run_kubectl_cmd(f"get deployments -n {ns}") + if deployments.strip(): + print(deployments) + else: + print(" (пусто)") + +def get_daemonsets(): + """Получает DaemonSets""" + print_section("🔧 DAEMONSETS") + + namespaces_output = run_kubectl_cmd("get namespaces -o json") + try: + namespaces_data = json.loads(namespaces_output) + namespaces = [ns['metadata']['name'] for ns in namespaces_data['items']] + except: + namespaces = ['default', 'kube-system', 'kube-public', 'kube-node-lease'] + + for ns in namespaces: + print_subsection(f"Namespace: {ns}") + daemonsets = run_kubectl_cmd(f"get daemonsets -n {ns}") + if daemonsets.strip(): + print(daemonsets) + else: + print(" (пусто)") + +def get_statefulsets(): + """Получает StatefulSets""" + print_section("🗄️ STATEFULSETS") + + namespaces_output = run_kubectl_cmd("get namespaces -o json") + try: + namespaces_data = json.loads(namespaces_output) + namespaces = [ns['metadata']['name'] for ns in namespaces_data['items']] + except: + namespaces = ['default', 'kube-system', 'kube-public', 'kube-node-lease'] + + statefulsets_found = False + for ns in namespaces: + statefulsets = run_kubectl_cmd(f"get statefulsets -n {ns} 2>/dev/null") + if statefulsets.strip() and "No resources found" not in statefulsets: + statefulsets_found = True + print_subsection(f"Namespace: {ns}") + print(statefulsets) + + if not statefulsets_found: + print(" StatefulSets не найдены") + +def get_events(): + """Получает события""" + print_section("📅 СОБЫТИЯ (EVENTS)") + + namespaces_output = run_kubectl_cmd("get namespaces -o json") + try: + namespaces_data = json.loads(namespaces_output) + namespaces = [ns['metadata']['name'] for ns in namespaces_data['items']] + except: + namespaces = ['default', 'kube-system', 'kube-public', 'kube-node-lease'] + + for ns in namespaces: + print_subsection(f"Namespace: {ns}") + events = run_kubectl_cmd(f"get events -n {ns} --sort-by='.lastTimestamp' | tail -20") + if events.strip(): + print(events) + else: + print(" (пусто)") + +def get_helm_releases(): + """Получает Helm релизы""" + print_section("📦 HELM RELEASES") + + helm_output = run_kubectl_cmd("helm list --all-namespaces 2>/dev/null") + if helm_output.strip(): + print(helm_output) + else: + print(" Helm релизы не найдены") + +def get_resource_usage(): + """Получает использование ресурсов""" + print_section("📈 ИСПОЛЬЗОВАНИЕ РЕСУРСОВ") + + try: + # Проверяем наличие metrics-server + top_nodes = run_kubectl_cmd("top nodes 2>/dev/null") + if top_nodes.strip(): + print_subsection("Узлы:") + print(top_nodes) + except: + print(" metrics-server не установлен или недоступен") + + try: + top_pods = run_kubectl_cmd("top pods --all-namespaces 2>/dev/null") + if top_pods.strip(): + print_subsection("Pods (топ-20):") + # Берем только первые 20 строк + lines = top_pods.strip().split('\n') + print('\n'.join(lines[:21])) # + заголовок + except: + pass + +def main(): + """Главная функция""" + # Проверяем доступность контейнера + result = subprocess.run("docker ps | grep k8s-controller", shell=True, capture_output=True, text=True) + if result.returncode != 0: + print("❌ Контейнер k8s-controller не запущен") + sys.exit(1) + + print("="*70) + print(" ДЕТАЛЬНЫЙ ОТЧЕТ О СОСТОЯНИИ KUBERNETES КЛАСТЕРА") + print("="*70) + + get_cluster_info() + get_nodes_status() + get_namespaces() + get_resource_usage() + get_pods_by_namespace() + get_deployments() + get_daemonsets() + get_statefulsets() + get_services() + get_ingress() + get_pvcs() + get_events() + get_helm_releases() + + print("\n" + "="*70) + print(" ОТЧЕТ ЗАВЕРШЕН") + print("="*70 + "\n") + +if __name__ == '__main__': + main() diff --git a/scripts/portforward.py b/scripts/portforward.py new file mode 100755 index 0000000..bf2d993 --- /dev/null +++ b/scripts/portforward.py @@ -0,0 +1,253 @@ +#!/usr/bin/env python3 +""" +Скрипт для управления port-forward для Kubernetes сервисов +Автор: Сергей Антропов +Сайт: https://devops.org.ru +""" +import sys +import yaml +import subprocess +import os +import signal +import time + +def get_cluster_name(): + """Получаем имя кластера из preset файла""" + preset_file = "molecule/presets/k8s/kubernetes.yml" + with open(preset_file, 'r') as f: + preset = yaml.safe_load(f) + return preset['kind_clusters'][0]['name'] + +def run_cmd(cmd): + """Выполняет команду и возвращает результат""" + print(f"[run] {cmd}") + result = subprocess.run(cmd, shell=True, capture_output=True, text=True) + if result.returncode != 0: + print(f"[error] {result.stderr}") + else: + print(result.stdout) + return result + +def get_portforward_pids(): + """Получает PID процессов port-forward""" + result = subprocess.run("ps aux | grep 'kubectl.*port-forward' | grep -v grep", shell=True, capture_output=True, text=True) + pids = [] + for line in result.stdout.split('\n'): + if line.strip(): + pids.append(int(line.split()[1])) + return pids + +def list_portforwards(): + """Показывает список всех активных port-forward""" + pids = get_portforward_pids() + if not pids: + print("❌ Нет активных port-forward") + return + + print("📋 Активные port-forward:") + result = subprocess.run("ps aux | grep 'kubectl.*port-forward' | grep -v grep", shell=True, capture_output=True, text=True) + for line in result.stdout.split('\n'): + if line.strip(): + print(f" {line}") + +def clear_portforwards(): + """Завершает все процессы port-forward""" + pids = get_portforward_pids() + if not pids: + print("❌ Нет активных port-forward") + return + + print(f"🗑️ Завершение {len(pids)} процессов port-forward...") + for pid in pids: + try: + os.kill(pid, signal.SIGTERM) + print(f"✅ Процесс {pid} завершен") + except ProcessLookupError: + print(f"⚠️ Процесс {pid} уже не существует") + + # Ждем завершения процессов + time.sleep(2) + + # Принудительно убиваем оставшиеся + remaining_pids = get_portforward_pids() + if remaining_pids: + print("⚠️ Принудительное завершение оставшихся процессов...") + for pid in remaining_pids: + try: + os.kill(pid, signal.SIGKILL) + print(f"✅ Процесс {pid} принудительно завершен") + except ProcessLookupError: + pass + +def create_portforwards(): + """Создает port-forward для всех сервисов из preset на локальном компьютере""" + # Загружаем preset + preset_file = "molecule/presets/k8s/kubernetes.yml" + with open(preset_file, 'r') as f: + preset = yaml.safe_load(f) + + cluster_name = preset['kind_clusters'][0]['name'] + addon_ports = preset['kind_clusters'][0].get('addon_ports', {}) + + # Получаем kubeconfig из контейнера k8s-controller + print(f"🔌 Создание port-forward для кластера: {cluster_name}") + print("📋 Получение kubeconfig из контейнера k8s-controller...") + + # Копируем kubeconfig из контейнера + result = subprocess.run( + f"docker exec k8s-controller kind get kubeconfig --name {cluster_name}", + shell=True, capture_output=True, text=True + ) + + if result.returncode != 0: + print(f"❌ Ошибка получения kubeconfig: {result.stderr}") + return + + # Сохраняем kubeconfig во временный файл + kubeconfig_file = "/tmp/kubeconfig-lab.yaml" + with open(kubeconfig_file, 'w') as f: + f.write(result.stdout) + + # Меняем server с 0.0.0.0 на localhost для локального доступа + subprocess.run(f"sed -i.bak 's|server: https://0.0.0.0:6443|server: https://localhost:6443|g' {kubeconfig_file}", shell=True) + + print("✅ Kubeconfig подготовлен") + + # Ingress HTTP (80) + if addon_ports.get('ingress_http'): + port = addon_ports['ingress_http'] + print(f" - Ingress HTTP: localhost:{port} -> ingress-nginx-controller:80") + subprocess.Popen([ + "kubectl", + f"--kubeconfig={kubeconfig_file}", + "port-forward", + "-n", "ingress-nginx", + "svc/ingress-nginx-controller", + f"{port}:80" + ], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + + # Ingress HTTPS (443) + if addon_ports.get('ingress_https'): + port = addon_ports['ingress_https'] + print(f" - Ingress HTTPS: localhost:{port} -> ingress-nginx-controller:443") + subprocess.Popen([ + "kubectl", + f"--kubeconfig={kubeconfig_file}", + "port-forward", + "-n", "ingress-nginx", + "svc/ingress-nginx-controller", + f"{port}:443" + ], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + + # Prometheus + if addon_ports.get('prometheus'): + port = addon_ports['prometheus'] + print(f" - Prometheus: localhost:{port} -> monitoring/monitoring-kube-prometheus-prometheus:9090") + subprocess.Popen([ + "kubectl", + f"--kubeconfig={kubeconfig_file}", + "port-forward", + "-n", "monitoring", + "svc/monitoring-kube-prometheus-prometheus", + f"{port}:9090" + ], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + + # Grafana + if addon_ports.get('grafana'): + port = addon_ports['grafana'] + print(f" - Grafana: localhost:{port} -> monitoring/monitoring-grafana:80") + subprocess.Popen([ + "kubectl", + f"--kubeconfig={kubeconfig_file}", + "port-forward", + "-n", "monitoring", + "svc/monitoring-grafana", + f"{port}:80" + ], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + + # Kiali + if addon_ports.get('kiali'): + port = addon_ports['kiali'] + print(f" - Kiali: localhost:{port} -> istio-system/kiali:20001") + subprocess.Popen([ + "kubectl", + f"--kubeconfig={kubeconfig_file}", + "port-forward", + "-n", "istio-system", + "svc/kiali", + f"{port}:20001" + ], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + + # Metrics Server + if addon_ports.get('metrics_server'): + port = addon_ports['metrics_server'] + print(f" - Metrics Server: localhost:{port} -> kube-system/metrics-server:4443") + subprocess.Popen([ + "kubectl", + f"--kubeconfig={kubeconfig_file}", + "port-forward", + "-n", "kube-system", + "svc/metrics-server", + f"{port}:4443" + ], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + + time.sleep(2) + print("✅ Port-forward создан") + list_portforwards() + +def delete_portforward(port): + """Удаляет port-forward для конкретного порта""" + pids = get_portforward_pids() + if not pids: + print(f"❌ Нет активных port-forward на порту {port}") + return + + # Находим процесс с нужным портом + result = subprocess.run(f"ps aux | grep 'kubectl.*port-forward.*:{port}' | grep -v grep", shell=True, capture_output=True, text=True) + if not result.stdout.strip(): + print(f"❌ Не найден port-forward на порту {port}") + return + + # Извлекаем PID + pid = int(result.stdout.split()[1]) + print(f"🗑️ Завершение port-forward на порту {port} (PID: {pid})...") + try: + os.kill(pid, signal.SIGTERM) + print(f"✅ Port-forward на порту {port} завершен") + except ProcessLookupError: + print(f"⚠️ Процесс {pid} уже не существует") + +def recreate_portforwards(): + """Пересоздает port-forward: удаляет существующие и создает заново""" + print("🔄 Пересоздание port-forward...") + clear_portforwards() + time.sleep(1) + create_portforwards() + +def main(): + if len(sys.argv) < 2: + print("Usage: portforward.py [port]") + sys.exit(1) + + command = sys.argv[1] + + if command == "create": + create_portforwards() + elif command == "list": + list_portforwards() + elif command == "clear": + clear_portforwards() + elif command == "recreate": + recreate_portforwards() + elif command == "delete": + if len(sys.argv) < 3: + print("Usage: portforward.py delete ") + sys.exit(1) + port = sys.argv[2] + delete_portforward(port) + else: + print(f"❌ Неизвестная команда: {command}") + sys.exit(1) + +if __name__ == "__main__": + main() diff --git a/scripts/setup-cicd.sh b/scripts/setup-cicd.sh index 3431114..7c92932 100755 --- a/scripts/setup-cicd.sh +++ b/scripts/setup-cicd.sh @@ -1,11 +1,11 @@ #!/bin/bash -# Автоматическая настройка CI/CD для AnsibleLab +# Автоматическая настройка CI/CD для DevOpsLab # Автор: Сергей Антропов # Сайт: https://devops.org.ru set -euo pipefail -echo "🔧 Настройка CI/CD для AnsibleLab..." +echo "🔧 Настройка CI/CD для DevOpsLab..." # Создание директории .github/workflows mkdir -p .github/workflows diff --git a/scripts/test-custom-images.sh b/scripts/test-custom-images.sh index a2c1f5b..cbe695b 100755 --- a/scripts/test-custom-images.sh +++ b/scripts/test-custom-images.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Скрипт для тестирования собственных образов AnsibleLab +# Скрипт для тестирования собственных образов DevOpsLab # Автор: Сергей Антропов # Сайт: https://devops.org.ru @@ -190,7 +190,7 @@ cleanup() { # Основная функция main() { - log "🚀 Тестирование собственных образов AnsibleLab" + log "🚀 Тестирование собственных образов DevOpsLab" echo "==========================================" # Проверки