Upload the ansible playbook for the elk k8s stack
This commit is contained in:
36
ansible/inventory/hosts.yml
Normal file
36
ansible/inventory/hosts.yml
Normal file
@@ -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!"
|
||||||
351
ansible/playbooks/deploy.yml
Normal file
351
ansible/playbooks/deploy.yml
Normal file
@@ -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! ║
|
||||||
|
║ ║
|
||||||
|
╚══════════════════════════════════════════════════════════════╝
|
||||||
38
ansible/playbooks/teardown.yml
Normal file
38
ansible/playbooks/teardown.yml
Normal file
@@ -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."
|
||||||
Reference in New Issue
Block a user