commit 1f6e65ab7d956fb290769e991c487d6db9a8ff87 Author: tsvetkov Date: Fri Feb 27 09:42:48 2026 +0000 Upload the ansible playbook for the elk k8s stack diff --git a/ansible/inventory/hosts.yml b/ansible/inventory/hosts.yml new file mode 100644 index 0000000..02feddb --- /dev/null +++ b/ansible/inventory/hosts.yml @@ -0,0 +1,36 @@ +all: + hosts: + localhost: + ansible_connection: local + ansible_python_interpreter: /usr/bin/python3 + + vars: + # --- Project paths --- + project_dir: "{{ playbook_dir }}/.." + k8s_manifests_dir: "{{ project_dir }}/k8s" + scripts_dir: "{{ project_dir }}/scripts" + certs_dir: "{{ project_dir }}/certs" + + # --- Minikube --- + minikube_cpus: 4 + minikube_memory: 8192 + minikube_disk_size: "40g" + minikube_driver: docker + + # --- Domain --- + domain: elk.local + + # --- ELK versions --- + elk_version: "8.17.0" + nginx_version: "1.27" + authentik_version: "2024.12" + mysql_version: "8.4" + + # --- Passwords (override in vault for production) --- + elastic_password: "ElasticP@ss2024!" + kibana_system_password: "KibanaP@ss2024!" + mysql_root_password: "rootpassword" + logstash_mysql_password: "logstash_password" + authentik_pg_password: "AuthPgP@ss2024!" + authentik_secret_key: "Sup3rS3cretK3yForAuth3nt1k2024ThatIsLongEnough!" + authentik_bootstrap_password: "AdminP@ss2024!" diff --git a/ansible/playbooks/deploy.yml b/ansible/playbooks/deploy.yml new file mode 100644 index 0000000..62e6bdb --- /dev/null +++ b/ansible/playbooks/deploy.yml @@ -0,0 +1,351 @@ +--- +# ============================================================================= +# ELK Stack on Kubernetes (Minikube) — Main Deployment Playbook +# ============================================================================= +# Usage: +# ansible-playbook -i inventory/hosts.yml playbooks/deploy.yml +# +# Tags: +# --tags prereqs Install system dependencies +# --tags certs Generate TLS certificates +# --tags minikube Start/configure Minikube +# --tags namespaces Create K8s namespaces +# --tags secrets Create TLS secrets in K8s +# --tags mysql Deploy MySQL +# --tags elasticsearch Deploy Elasticsearch +# --tags es-setup Run Elasticsearch post-setup +# --tags kibana Deploy Kibana +# --tags logstash Deploy Logstash +# --tags nginx Deploy NGINX proxy +# --tags authentik Deploy Authentik SSO +# --tags dns Configure /etc/hosts +# ============================================================================= + +- name: Deploy ELK Stack on Kubernetes + hosts: localhost + connection: local + gather_facts: true + + tasks: + # ======================================================================= + # PHASE 1 — Prerequisites + # ======================================================================= + - name: Install system prerequisites + tags: [prereqs] + block: + - name: Update apt cache + become: true + ansible.builtin.apt: + update_cache: true + cache_valid_time: 3600 + + - name: Install required packages + become: true + ansible.builtin.apt: + name: + - curl + - apt-transport-https + - ca-certificates + - gnupg + - lsb-release + - openssl + - docker.io + - conntrack + state: present + + - name: Ensure Docker service is running + become: true + ansible.builtin.systemd: + name: docker + state: started + enabled: true + + - name: Add current user to docker group + become: true + ansible.builtin.user: + name: "{{ ansible_user_id }}" + groups: docker + append: true + + - name: Install kubectl + become: true + ansible.builtin.shell: | + if ! command -v kubectl &>/dev/null; then + curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" + install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl + rm -f kubectl + fi + args: + creates: /usr/local/bin/kubectl + + - name: Install minikube + become: true + ansible.builtin.shell: | + if ! command -v minikube &>/dev/null; then + curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64 + install minikube-linux-amd64 /usr/local/bin/minikube + rm -f minikube-linux-amd64 + fi + args: + creates: /usr/local/bin/minikube + + # ======================================================================= + # PHASE 2 — TLS Certificates + # ======================================================================= + - name: Generate TLS certificates + tags: [certs] + block: + - name: Create certs directory + ansible.builtin.file: + path: "{{ certs_dir }}" + state: directory + mode: "0755" + + - name: Run certificate generation script + ansible.builtin.command: + cmd: bash "{{ scripts_dir }}/generate-certs.sh" "{{ certs_dir }}" + creates: "{{ certs_dir }}/ca.crt" + + # ======================================================================= + # PHASE 3 — Minikube + # ======================================================================= + - name: Start and configure Minikube + tags: [minikube] + block: + - name: Check if Minikube is running + ansible.builtin.command: minikube status --format='{{.Host}}' + register: minikube_status + ignore_errors: true + changed_when: false + + - name: Start Minikube + ansible.builtin.command: > + minikube start + --cpus={{ minikube_cpus }} + --memory={{ minikube_memory }} + --disk-size={{ minikube_disk_size }} + --driver={{ minikube_driver }} + --addons=default-storageclass,storage-provisioner + when: minikube_status.rc != 0 or 'Running' not in minikube_status.stdout + + - name: Enable ingress addon + ansible.builtin.command: minikube addons enable ingress + changed_when: false + + # ======================================================================= + # PHASE 4 — Kubernetes Namespaces + # ======================================================================= + - name: Create Kubernetes namespaces + tags: [namespaces] + ansible.builtin.command: kubectl apply -f "{{ k8s_manifests_dir }}/namespaces/namespaces.yaml" + changed_when: false + + # ======================================================================= + # PHASE 5 — TLS Secrets in Kubernetes + # ======================================================================= + - name: Create TLS secrets + tags: [secrets] + block: + - name: Delete existing elk-certificates secret (if any) + ansible.builtin.command: kubectl delete secret elk-certificates -n elk --ignore-not-found + changed_when: false + + - name: Create elk-certificates secret in elk namespace + ansible.builtin.command: > + kubectl create secret generic elk-certificates -n elk + --from-file=ca.crt={{ certs_dir }}/ca.crt + --from-file=ca.key={{ certs_dir }}/ca.key + --from-file=elasticsearch.crt={{ certs_dir }}/elasticsearch.crt + --from-file=elasticsearch.key={{ certs_dir }}/elasticsearch.key + --from-file=elasticsearch.p12={{ certs_dir }}/elasticsearch.p12 + --from-file=http.p12={{ certs_dir }}/elastic-http.p12 + --from-file=kibana.crt={{ certs_dir }}/kibana.crt + --from-file=kibana.key={{ certs_dir }}/kibana.key + --from-file=logstash.crt={{ certs_dir }}/logstash.crt + --from-file=logstash.key={{ certs_dir }}/logstash.key + --from-file=nginx.crt={{ certs_dir }}/nginx.crt + --from-file=nginx.key={{ certs_dir }}/nginx.key + --from-file=authentik.crt={{ certs_dir }}/authentik.crt + --from-file=authentik.key={{ certs_dir }}/authentik.key + + # ======================================================================= + # PHASE 6 — MySQL (database namespace) + # ======================================================================= + - name: Deploy MySQL + tags: [mysql] + block: + - name: Apply MySQL manifests + ansible.builtin.command: kubectl apply -f "{{ k8s_manifests_dir }}/mysql/" + changed_when: false + + - name: Wait for MySQL to be ready + ansible.builtin.command: > + kubectl wait --for=condition=ready pod -l app=mysql + -n database --timeout=180s + changed_when: false + + # ======================================================================= + # PHASE 7 — Elasticsearch + # ======================================================================= + - name: Deploy Elasticsearch + tags: [elasticsearch] + block: + - name: Apply Elasticsearch manifests + ansible.builtin.command: kubectl apply -f "{{ k8s_manifests_dir }}/elasticsearch/elasticsearch.yaml" + changed_when: false + + - name: Wait for Elasticsearch to be ready + ansible.builtin.command: > + kubectl wait --for=condition=ready pod -l app=elasticsearch + -n elk --timeout=300s + changed_when: false + + # ======================================================================= + # PHASE 8 — Elasticsearch post-setup + # ======================================================================= + - name: Run Elasticsearch setup job + tags: [es-setup] + block: + - name: Delete previous setup job (if any) + ansible.builtin.command: kubectl delete job elasticsearch-setup -n elk --ignore-not-found + changed_when: false + + - name: Apply setup job + ansible.builtin.command: kubectl apply -f "{{ k8s_manifests_dir }}/elasticsearch/setup-job.yaml" + changed_when: false + + - name: Wait for setup job completion + ansible.builtin.command: > + kubectl wait --for=condition=complete job/elasticsearch-setup + -n elk --timeout=120s + changed_when: false + + # ======================================================================= + # PHASE 9 — Authentik SSO + # ======================================================================= + - name: Deploy Authentik SSO + tags: [authentik] + block: + - name: Apply Authentik manifests + ansible.builtin.command: kubectl apply -f "{{ k8s_manifests_dir }}/authentik/" + changed_when: false + + - name: Wait for Authentik PostgreSQL + ansible.builtin.command: > + kubectl wait --for=condition=ready pod -l app=authentik-postgresql + -n elk --timeout=120s + changed_when: false + + - name: Wait for Authentik Redis + ansible.builtin.command: > + kubectl wait --for=condition=ready pod -l app=authentik-redis + -n elk --timeout=60s + changed_when: false + + - name: Wait for Authentik Server + ansible.builtin.command: > + kubectl wait --for=condition=ready pod -l app=authentik-server + -n elk --timeout=180s + changed_when: false + + # ======================================================================= + # PHASE 10 — Kibana + # ======================================================================= + - name: Deploy Kibana + tags: [kibana] + block: + - name: Apply Kibana manifests + ansible.builtin.command: kubectl apply -f "{{ k8s_manifests_dir }}/kibana/" + changed_when: false + + - name: Wait for Kibana to be ready + ansible.builtin.command: > + kubectl wait --for=condition=ready pod -l app=kibana + -n elk --timeout=300s + changed_when: false + + # ======================================================================= + # PHASE 11 — Logstash + # ======================================================================= + - name: Deploy Logstash + tags: [logstash] + block: + - name: Apply Logstash manifests + ansible.builtin.command: kubectl apply -f "{{ k8s_manifests_dir }}/logstash/" + changed_when: false + + - name: Wait for Logstash to be ready + ansible.builtin.command: > + kubectl wait --for=condition=ready pod -l app=logstash + -n elk --timeout=180s + changed_when: false + + # ======================================================================= + # PHASE 12 — NGINX Proxy + # ======================================================================= + - name: Deploy NGINX reverse proxy + tags: [nginx] + block: + - name: Apply NGINX manifests + ansible.builtin.command: kubectl apply -f "{{ k8s_manifests_dir }}/nginx/" + changed_when: false + + - name: Wait for NGINX to be ready + ansible.builtin.command: > + kubectl wait --for=condition=ready pod -l app=nginx + -n elk --timeout=60s + changed_when: false + + # ======================================================================= + # PHASE 13 — DNS / /etc/hosts + # ======================================================================= + - name: Configure local DNS + tags: [dns] + block: + - name: Get Minikube IP + ansible.builtin.command: minikube ip + register: minikube_ip + changed_when: false + + - name: Add kibana.elk.local to /etc/hosts + become: true + ansible.builtin.lineinfile: + path: /etc/hosts + regexp: '.*kibana\.elk\.local.*' + line: "{{ minikube_ip.stdout }} kibana.elk.local authentik.elk.local" + state: present + + # ======================================================================= + # FINAL — Summary + # ======================================================================= + - name: Deployment summary + tags: [always] + block: + - name: Get Minikube IP for summary + ansible.builtin.command: minikube ip + register: minikube_ip_final + changed_when: false + ignore_errors: true + + - name: Print access information + ansible.builtin.debug: + msg: | + ╔══════════════════════════════════════════════════════════════╗ + ║ ELK Stack Deployment Complete! ║ + ╠══════════════════════════════════════════════════════════════╣ + ║ ║ + ║ Minikube IP: {{ minikube_ip_final.stdout | default('N/A') }} + ║ ║ + ║ Kibana (NGINX proxy): ║ + ║ https://kibana.elk.local:30443 ║ + ║ User: elastic / ElasticP@ss2024! ║ + ║ ║ + ║ Authentik Admin: ║ + ║ https://authentik.elk.local:30944 ║ + ║ User: akadmin / AdminP@ss2024! ║ + ║ ║ + ║ Elasticsearch: ║ + ║ kubectl port-forward svc/elasticsearch 9200:9200 -n elk ║ + ║ User: elastic / ElasticP@ss2024! ║ + ║ ║ + ╚══════════════════════════════════════════════════════════════╝ diff --git a/ansible/playbooks/teardown.yml b/ansible/playbooks/teardown.yml new file mode 100644 index 0000000..b7768bc --- /dev/null +++ b/ansible/playbooks/teardown.yml @@ -0,0 +1,38 @@ +--- +# ============================================================================= +# Teardown Playbook — Remove the entire ELK stack deployment +# ============================================================================= +# Usage: +# ansible-playbook -i inventory/hosts.yml playbooks/teardown.yml +# ============================================================================= + +- name: Teardown ELK Stack + hosts: localhost + connection: local + gather_facts: false + + tasks: + - name: Delete elk namespace (removes all ELK resources) + ansible.builtin.command: kubectl delete namespace elk --ignore-not-found --timeout=120s + changed_when: false + + - name: Delete database namespace (removes MySQL) + ansible.builtin.command: kubectl delete namespace database --ignore-not-found --timeout=120s + changed_when: false + + - name: Remove /etc/hosts entries + become: true + ansible.builtin.lineinfile: + path: /etc/hosts + regexp: '.*kibana\.elk\.local.*' + state: absent + + - name: Optionally stop Minikube + ansible.builtin.command: minikube stop + ignore_errors: true + changed_when: false + when: stop_minikube | default(false) | bool + + - name: Print teardown complete + ansible.builtin.debug: + msg: "ELK stack teardown complete. Run with -e stop_minikube=true to also stop Minikube."