From fb62291b3ed3410b0b75afe5170924af68b6c699 Mon Sep 17 00:00:00 2001 From: Eric FELIXINE Date: Thu, 4 Jun 2026 02:09:17 -0400 Subject: [PATCH] feat: add helm/ansible deployment files for Kubernetes --- helms/README.md | 221 ++++++++++ helms/deploy.yml | 77 ++++ helms/group_vars/all.yml | 535 +++++++++++++++++++++++ helms/group_vars/vault.yml | 60 +++ helms/inventory/hosts.yml | 79 ++++ helms/roles/airflow/tasks/main.yml | 34 ++ helms/roles/backup/tasks/main.yml | 34 ++ helms/roles/bi/tasks/main.yml | 44 ++ helms/roles/cert-manager/tasks/main.yml | 39 ++ helms/roles/clickhouse/tasks/main.yml | 34 ++ helms/roles/databases/tasks/main.yml | 54 +++ helms/roles/deltalake/tasks/main.yml | 30 ++ helms/roles/duckdb/tasks/main.yml | 30 ++ helms/roles/flink/tasks/main.yml | 18 + helms/roles/gis/tasks/main.yml | 37 ++ helms/roles/gitea/tasks/main.yml | 28 ++ helms/roles/iot/tasks/main.yml | 35 ++ helms/roles/jupyterhub/tasks/main.yml | 31 ++ helms/roles/kafka/tasks/main.yml | 19 + helms/roles/mindsdb/tasks/main.yml | 18 + helms/roles/monitoring/tasks/main.yml | 41 ++ helms/roles/namespaces/tasks/main.yml | 17 + helms/roles/nodered/tasks/main.yml | 26 ++ helms/roles/odk/tasks/main.yml | 22 + helms/roles/phpipam/tasks/main.yml | 27 ++ helms/roles/prerequisites/tasks/main.yml | 21 + helms/roles/smartapp/tasks/main.yml | 19 + helms/roles/starrocks/tasks/main.yml | 38 ++ helms/roles/storage/tasks/main.yml | 27 ++ helms/roles/streamlit/tasks/main.yml | 30 ++ helms/roles/traefik/tasks/main.yml | 49 +++ helms/roles/trino/tasks/main.yml | 46 ++ helms/undeploy.yml | 56 +++ 33 files changed, 1876 insertions(+) create mode 100644 helms/README.md create mode 100644 helms/deploy.yml create mode 100644 helms/group_vars/all.yml create mode 100644 helms/group_vars/vault.yml create mode 100644 helms/inventory/hosts.yml create mode 100644 helms/roles/airflow/tasks/main.yml create mode 100644 helms/roles/backup/tasks/main.yml create mode 100644 helms/roles/bi/tasks/main.yml create mode 100644 helms/roles/cert-manager/tasks/main.yml create mode 100644 helms/roles/clickhouse/tasks/main.yml create mode 100644 helms/roles/databases/tasks/main.yml create mode 100644 helms/roles/deltalake/tasks/main.yml create mode 100644 helms/roles/duckdb/tasks/main.yml create mode 100644 helms/roles/flink/tasks/main.yml create mode 100644 helms/roles/gis/tasks/main.yml create mode 100644 helms/roles/gitea/tasks/main.yml create mode 100644 helms/roles/iot/tasks/main.yml create mode 100644 helms/roles/jupyterhub/tasks/main.yml create mode 100644 helms/roles/kafka/tasks/main.yml create mode 100644 helms/roles/mindsdb/tasks/main.yml create mode 100644 helms/roles/monitoring/tasks/main.yml create mode 100644 helms/roles/namespaces/tasks/main.yml create mode 100644 helms/roles/nodered/tasks/main.yml create mode 100644 helms/roles/odk/tasks/main.yml create mode 100644 helms/roles/phpipam/tasks/main.yml create mode 100644 helms/roles/prerequisites/tasks/main.yml create mode 100644 helms/roles/smartapp/tasks/main.yml create mode 100644 helms/roles/starrocks/tasks/main.yml create mode 100644 helms/roles/storage/tasks/main.yml create mode 100644 helms/roles/streamlit/tasks/main.yml create mode 100644 helms/roles/traefik/tasks/main.yml create mode 100644 helms/roles/trino/tasks/main.yml create mode 100644 helms/undeploy.yml diff --git a/helms/README.md b/helms/README.md new file mode 100644 index 00000000..617029e1 --- /dev/null +++ b/helms/README.md @@ -0,0 +1,221 @@ +# Smart City Martinique - Déploiement Kubernetes + +## Architecture + +``` + ┌─────────────────────────────────────────────────────────┐ + │ TRAEFIK (Ingress) │ + │ ports 80/443 │ + └─────────────────────────────────────────────────────────┘ + │ + ┌─────────────────────────────────┼─────────────────────────────────┐ + │ │ │ + ┌────▼────┐ ┌──────────┐ ┌──────────▼──────────┐ ┌─────────────────┐ + │ Airflow │ │ Kafka │ │ Data & Storage │ │ Monitoring │ + │ │ │ Cluster │ │ │ │ │ + │ web │ │ 3 brokers│ │ PostgreSQL HA │ │ Prometheus │ + │ sched │ │ connect │ │ Redis Cluster │ │ Grafana │ + │ worker │ │ ui │ │ MinIO │ │ Loki │ + └─────────┘ └──────────┘ │ ClickHouse │ │ Promtail │ + │ StarRocks │ └─────────────────┘ + ┌──────────┐ ┌──────────┐ │ Trino │ + │ Flink │ │ IoT │ │ Delta Lake │ ┌─────────────────┐ + │ │ │ │ │ DuckDB │ │ BI & Analytics │ + │ jobmgr │ │ EMQX │ └─────────────────────┘ │ │ + │ taskmgr │ │ Mosquitto│ │ Superset │ + └──────────┘ │ Node-RED │ ┌─────────────────────┐ │ Metabase │ + │ phpIPAM │ │ Git & Notebooks │ │ MindsDB │ + ┌──────────┐ │ ChirpStk │ │ │ └─────────────────┘ + │ GIS │ └──────────┘ │ Gitea │ + │ │ │ JupyterHub │ ┌─────────────────┐ + │ MapStore │ ┌──────────┐ │ Zeppelin │ │ Web Apps │ + │ GeoServer│ │ ODK │ └─────────────────────┘ │ │ + │ FROST │ │ │ │ Smart App │ + │ Stellio │ │ nginx │ ┌─────────────────────┐ │ Streamlit │ + │ FIWARE │ │ service │ │ Data Collection │ │ Kepler │ + └──────────┘ │ postgres │ │ │ └─────────────────┘ + └──────────┘ │ Telegraf │ + │ InfluxDB │ + │ Simulator │ + └─────────────────────┘ +``` + +## Prérequis + +### Cluster Kubernetes +- 3 nœuds minimum (1 master + 2 workers) +- Kubernetes 1.28+ +- containerd +- Cilium (CNI) + +### Serveur NFS +- 1 serveur NFS pour le stockage persistant +- Minimum 500Go d'espace disque + +### Outils +- kubectl +- helm +- ansible 2.15+ +- ansible-galaxy collection install kubernetes.core + +## Installation + +### 1. Cloner le repository + +```bash +git clone https://gitea.digitribe.fr/eric/smart-city-digital-twin-martinique.git +cd smart-city-digital-twin-martinique/helms +``` + +### 2. Configurer l'inventory + +Éditer `inventory/hosts.yml` avec les IPs de vos nœuds : + +```yaml +k8s_masters: + hosts: + k8s-master-1: + ansible_host: "192.168.1.100" +k8s_workers: + hosts: + k8s-worker-1: + ansible_host: "192.168.1.101" + k8s-worker-2: + ansible_host: "192.168.1.102" +nfs_server: + hosts: + nfs-1: + ansible_host: "192.168.1.200" +``` + +### 3. Configurer les variables + +Éditer `group_vars/all.yml` selon vos besoins (ressources, domaines, etc.) + +### 4. Chiffrer les secrets + +```bash +ansible-vault encrypt group_vars/vault.yml +``` + +### 5. Déployer + +```bash +# Déployer toute la stack +ansible-playbook deploy.yml --ask-vault-pass + +# Déployer un service spécifique +ansible-playbook deploy.yml --tags clickhouse --ask-vault-pass +ansible-playbook deploy.yml --tags trino --ask-vault-pass +ansible-playbook deploy.yml --tags streamlit --ask-vault-pass +ansible-playbook deploy.yml --tags kafka --ask-vault-pass +ansible-playbook deploy.yml --tags monitoring --ask-vault-pass +``` + +### 6. Vérifier + +```bash +kubectl get pods --all-namespaces +kubectl get ingress --all-namespaces +``` + +## Services déployés + +| Service | Domaine | Namespace | Helm Chart | +|---------|---------|-----------|------------| +| Airflow | airflow.digitribe.fr | airflow | apache/airflow | +| Kafka | kafka.digitribe.fr | kafka | strimzi/kafka-operator | +| Flink | flink.digitribe.fr | flink | apache/flink-kubernetes-operator | +| ClickHouse | clickhouse.digitribe.fr | clickhouse | bitnami/clickhouse | +| StarRocks | starrocks.digitribe.fr | starrocks | starrocks/starrocks-community | +| Trino | trino.digitribe.fr | trino | trinodb/trino | +| Delta Lake | deltalake.digitribe.fr | deltalake | delta-io/delta-lake | +| Streamlit | streamlit.digitribe.fr | streamlit | streamlit/streamlit | +| DuckDB | duckdb.digitribe.fr | duckdb | duckdb/duckdb | +| EMQX | emqx.digitribe.fr | iot | emqx/emqx-operator | +| Mosquitto | mqtt.digitribe.fr | iot | k8s-at-home/mosquitto | +| Node-RED | nodered.digitribe.fr | iot | k8s-at-home/node-red | +| phpIPAM | phpipam.digitribe.fr | phpipam | phpipam/phpipam | +| ChirpStack | chirpstack.digitribe.fr | iot | chirpstack/chirpstack | +| Gitea | gitea.digitribe.fr | gitea | gitea/gitea | +| JupyterHub | jupyter.digitribe.fr | jupyterhub | jupyterhub/jupyterhub | +| Zeppelin | zeppelin.digitribe.fr | default | apache/zeppelin | +| Superset | superset.digitribe.fr | superset | apache/superset | +| Metabase | metabase.digitribe.fr | metabase | bitnami/metabase | +| MindsDB | mindsdb.digitribe.fr | mindsdb | bitnami/mindsdb | +| ODK Central | odk.digitribe.fr | odk | odk/odk-central | +| MapStore | mapstore.digitribe.fr | mapstore | geosolutionsit/mapstore | +| GeoServer | geoserver.digitribe.fr | geoserver | kartoza/geoserver | +| FROST | frost.digitribe.fr | iot | fraunhoferiosb/frost-server | +| Smart App | smartapp.digitribe.fr | smartapp | custom | +| Grafana | grafana.digitribe.fr | monitoring | grafana/grafana | +| MinIO | minio.digitribe.fr | default | bitnami/minio | + +## Commandes utiles + +```bash +# Lister tous les pods +kubectl get pods --all-namespaces + +# Voir les logs d'un pod +kubectl logs -f -n + +# Voir les événements +kubectl get events --all-namespaces --sort-by='.lastTimestamp' + +# Voir les ingress +kubectl get ingress --all-namespaces + +# Voir les PVC +kubectl get pvc --all-namespaces + +# Redéployer un service +ansible-playbook deploy.yml --tags --ask-vault-pass + +# Supprimer un service +kubectl delete namespace + +# Supprimer toute la stack +ansible-playbook undeploy.yml +``` + +## Troubleshooting + +### Pod en CrashLoopBackOff +```bash +kubectl describe pod -n +kubectl logs -n --previous +``` + +### PVC en Pending +```bash +kubectl get storageclass +kubectl get pv +kubectl describe pvc -n +``` + +### Ingress non accessible +```bash +kubectl get ingress -n +kubectl describe ingress -n +kubectl logs -f deployment/traefik -n traefik +``` + +## Maintenance + +### Backup +Les sauvegardes sont configurées via Velero : +```bash +kubectl get schedules -n velero +kubectl get backups -n velero +``` + +### Mise à jour d'un service +```bash +ansible-playbook deploy.yml --tags --ask-vault-pass +``` + +### Scaling +```bash +kubectl scale deployment --replicas= -n +``` diff --git a/helms/deploy.yml b/helms/deploy.yml new file mode 100644 index 00000000..66acd37a --- /dev/null +++ b/helms/deploy.yml @@ -0,0 +1,77 @@ +--- +# Playbook principal pour le déploiement Kubernetes +# Fichier: deploy.yml + +- name: Déploiement Smart City Martinique sur Kubernetes + hosts: localhost + connection: local + gather_facts: false + + vars_files: + - group_vars/all.yml + - group_vars/vault.yml + + pre_tasks: + - name: Vérifier que kubectl est installé + command: kubectl version --client + changed_when: false + + - name: Vérifier la connexion au cluster + command: kubectl cluster-info + changed_when: false + + roles: + - role: prerequisites + tags: [prerequisites] + - role: namespaces + tags: [namespaces] + - role: storage + tags: [storage] + - role: traefik + tags: [traefik, ingress] + - role: cert-manager + tags: [cert-manager, tls] + - role: monitoring + tags: [monitoring] + - role: databases + tags: [databases] + - role: kafka + tags: [kafka] + - role: flink + tags: [flink] + - role: airflow + tags: [airflow] + - role: iot + tags: [iot, mqtt] + - role: gitea + tags: [gitea] + - role: jupyterhub + tags: [jupyterhub] + - role: bi + tags: [bi, superset, metabase] + - role: mindsdb + tags: [mindsdb] + - role: odk + tags: [odk] + - role: gis + tags: [gis, mapstore, geoserver, frost] + - role: clickhouse + tags: [clickhouse] + - role: starrocks + tags: [starrocks] + - role: trino + tags: [trino] + - role: deltalake + tags: [deltalake] + - role: streamlit + tags: [streamlit] + - role: duckdb + tags: [duckdb] + - role: nodered + tags: [nodered] + - role: phpipam + tags: [phpipam] + - role: smartapp + tags: [smartapp] + - role: backup + tags: [backup] diff --git a/helms/group_vars/all.yml b/helms/group_vars/all.yml new file mode 100644 index 00000000..f137f475 --- /dev/null +++ b/helms/group_vars/all.yml @@ -0,0 +1,535 @@ +--- +# Variables globales pour le déploiement Kubernetes +# Fichier: group_vars/all.yml + +# ============================================================ +# Configuration du cluster Kubernetes +# ============================================================ +cluster_name: smart-city-martinique +k8s_version: "1.28.0" +container_runtime: containerd +network_plugin: cilium + +# ============================================================ +# Configuration réseau +# ============================================================ +domain: digitribe.fr +traefik_namespace: traefik +ingress_class: traefik + +# TLS +tls_enabled: true +tls_certresolver: letsencrypt +acme_email: admin@digitribe.fr + +# ============================================================ +# Storage +# ============================================================ +storage_class: nfs-client +nfs_server: "192.168.1.200" +nfs_path: /data/k8s + +# Persistent Volume sizes +storage_sizes: + postgres: 50Gi + minio: 500Gi + kafka: 100Gi + influxdb: 50Gi + loki: 100Gi + grafana: 10Gi + jupyterhub: 20Gi + gitea: 20Gi + metabase: 10Gi + superset: 10Gi + mindsdb: 20Gi + odk: 10Gi + mapstore: 10Gi + geoserver: 20Gi + airflow: 20Gi + flink: 20Gi + emqx: 10Gi + mosquitto: 5Gi + redis: 10Gi + elasticsearch: 50Gi + +# ============================================================ +# Helm Charts versions +# ============================================================ +helm_charts: + traefik: + chart: traefik/traefik + version: "28.0.0" + ingress_nginx: + chart: ingress-nginx/ingress-nginx + version: "4.8.0" + cert_manager: + chart: jetstack/cert-manager + version: "1.13.0" + nfs_provisioner: + chart: nfs-subdir-external-provisioner/nfs-subdir-external-provisioner + version: "4.0.18" + postgresql: + chart: bitnami/postgresql + version: "13.2.0" + postgresql_ha: + chart: bitnami/postgresql-ha + version: "12.2.0" + redis: + chart: bitnami/redis + version: "18.0.0" + minio: + chart: bitnami/minio + version: "12.10.0" + kafka: + chart: strimzi/kafka-operator + version: "0.38.0" + flink: + chart: apache/flink-kubernetes-operator + version: "1.7.0" + airflow: + chart: apache/airflow + version: "1.11.0" + grafana: + chart: grafana/grafana + version: "7.0.0" + loki: + chart: grafana/loki-stack + version: "2.9.0" + prometheus: + chart: prometheus/kube-prometheus-stack + version: "51.0.0" + emqx: + chart: emqx/emqx-operator + version: "2.2.0" + mosquitto: + chart: k8s-at-home/mosquitto + version: "4.8.0" + gitea: + chart: gitea/gitea + version: "9.0.0" + jupyterhub: + chart: jupyterhub/jupyterhub + version: "3.0.0" + superset: + chart: apache/superset + version: "0.11.0" + metabase: + chart: bitnami/metabase + version: "0.13.0" + mindsdb: + chart: bitnami/mindsdb + version: "0.1.0" + odk: + chart: odk/odk-central + version: "1.0.0" + mapstore: + chart: geosolutionsit/mapstore + version: "1.0.0" + geoserver: + chart: kartoza/geoserver + version: "2.2.0" + frost: + chart: fraunhoferiosb/frost-server + version: "1.0.0" + nodered: + chart: k8s-at-home/node-red + version: "4.8.0" + phpipam: + chart: phpipam/phpipam + version: "1.0.0" + clickhouse: + chart: bitnami/clickhouse + version: "4.0.0" + starrocks: + chart: starrocks/starrocks-community + version: "1.0.0" + trino: + chart: trinodb/trino + version: "0.10.0" + deltalake: + chart: delta-io/delta-lake + version: "1.0.0" + streamlit: + chart: streamlit/streamlit + version: "1.0.0" + duckdb: + chart: duckdb/duckdb + version: "1.0.0" + elasticsearch: + chart: elastic/elasticsearch + version: "8.11.0" + kibana: + chart: elastic/kibana + version: "8.11.0" + +# ============================================================ +# Services configuration +# ============================================================ +services: + airflow: + enabled: true + namespace: airflow + replicas: 2 + resources: + requests: + cpu: "500m" + memory: "1Gi" + limits: + cpu: "2000m" + memory: "4Gi" + + kafka: + enabled: true + namespace: kafka + replicas: 3 + resources: + requests: + cpu: "500m" + memory: "1Gi" + limits: + cpu: "2000m" + memory: "4Gi" + + flink: + enabled: true + namespace: flink + replicas: 2 + resources: + requests: + cpu: "500m" + memory: "1Gi" + limits: + cpu: "2000m" + memory: "4Gi" + + emqx: + enabled: true + namespace: iot + replicas: 3 + resources: + requests: + cpu: "250m" + memory: "512Mi" + limits: + cpu: "1000m" + memory: "2Gi" + + mosquitto: + enabled: true + namespace: iot + replicas: 2 + resources: + requests: + cpu: "100m" + memory: "256Mi" + limits: + cpu: "500m" + memory: "1Gi" + + postgresql: + enabled: true + namespace: default + replicas: 1 + resources: + requests: + cpu: "250m" + memory: "512Mi" + limits: + cpu: "1000m" + memory: "2Gi" + + redis: + enabled: true + namespace: default + replicas: 3 + resources: + requests: + cpu: "100m" + memory: "256Mi" + limits: + cpu: "500m" + memory: "1Gi" + + minio: + enabled: true + namespace: default + replicas: 4 + resources: + requests: + cpu: "250m" + memory: "512Mi" + limits: + cpu: "1000m" + memory: "2Gi" + + grafana: + enabled: true + namespace: monitoring + replicas: 1 + resources: + requests: + cpu: "100m" + memory: "256Mi" + limits: + cpu: "500m" + memory: "1Gi" + + loki: + enabled: true + namespace: monitoring + replicas: 1 + resources: + requests: + cpu: "250m" + memory: "512Mi" + limits: + cpu: "1000m" + memory: "2Gi" + + prometheus: + enabled: true + namespace: monitoring + replicas: 1 + resources: + requests: + cpu: "250m" + memory: "512Mi" + limits: + cpu: "1000m" + memory: "2Gi" + + gitea: + enabled: true + namespace: gitea + replicas: 1 + resources: + requests: + cpu: "250m" + memory: "512Mi" + limits: + cpu: "1000m" + memory: "2Gi" + + jupyterhub: + enabled: true + namespace: jupyterhub + replicas: 1 + resources: + requests: + cpu: "250m" + memory: "512Mi" + limits: + cpu: "1000m" + memory: "2Gi" + + superset: + enabled: true + namespace: superset + replicas: 1 + resources: + requests: + cpu: "250m" + memory: "512Mi" + limits: + cpu: "1000m" + memory: "2Gi" + + metabase: + enabled: true + namespace: metabase + replicas: 1 + resources: + requests: + cpu: "250m" + memory: "512Mi" + limits: + cpu: "1000m" + memory: "2Gi" + + mindsdb: + enabled: true + namespace: mindsdb + replicas: 1 + resources: + requests: + cpu: "250m" + memory: "512Mi" + limits: + cpu: "1000m" + memory: "2Gi" + + odk: + enabled: true + namespace: odk + replicas: 1 + resources: + requests: + cpu: "250m" + memory: "512Mi" + limits: + cpu: "1000m" + memory: "2Gi" + + mapstore: + enabled: true + namespace: mapstore + replicas: 1 + resources: + requests: + cpu: "250m" + memory: "512Mi" + limits: + cpu: "1000m" + memory: "2Gi" + + geoserver: + enabled: true + namespace: geoserver + replicas: 1 + resources: + requests: + cpu: "250m" + memory: "512Mi" + limits: + cpu: "1000m" + memory: "2Gi" + + frost: + enabled: true + namespace: iot + replicas: 1 + resources: + requests: + cpu: "100m" + memory: "256Mi" + limits: + cpu: "500m" + memory: "1Gi" + + nodered: + enabled: true + namespace: iot + replicas: 1 + resources: + requests: + cpu: "100m" + memory: "256Mi" + limits: + cpu: "500m" + memory: "1Gi" + + phpipam: + enabled: true + namespace: phpipam + replicas: 1 + resources: + requests: + cpu: "100m" + memory: "256Mi" + limits: + cpu: "500m" + memory: "1Gi" + + smartapp: + enabled: true + namespace: smartapp + replicas: 2 + resources: + requests: + cpu: "250m" + memory: "512Mi" + limits: + cpu: "1000m" + memory: "2Gi" + + clickhouse: + enabled: true + namespace: clickhouse + replicas: 1 + resources: + requests: + cpu: "500m" + memory: "1Gi" + limits: + cpu: "2000m" + memory: "4Gi" + + starrocks: + enabled: true + namespace: starrocks + replicas: 1 + resources: + requests: + cpu: "500m" + memory: "1Gi" + limits: + cpu: "2000m" + memory: "4Gi" + + trino: + enabled: true + namespace: trino + replicas: 1 + resources: + requests: + cpu: "500m" + memory: "1Gi" + limits: + cpu: "2000m" + memory: "4Gi" + + deltalake: + enabled: true + namespace: deltalake + replicas: 1 + resources: + requests: + cpu: "250m" + memory: "512Mi" + limits: + cpu: "1000m" + memory: "2Gi" + + streamlit: + enabled: true + namespace: streamlit + replicas: 1 + resources: + requests: + cpu: "250m" + memory: "512Mi" + limits: + cpu: "1000m" + memory: "2Gi" + + duckdb: + enabled: true + namespace: duckdb + replicas: 1 + resources: + requests: + cpu: "250m" + memory: "512Mi" + limits: + cpu: "1000m" + memory: "2Gi" + +# ============================================================ +# Monitoring +# ============================================================ +monitoring: + enabled: true + namespace: monitoring + grafana_admin_password: "{{ vault_grafana_password }}" + prometheus_retention: 30d + loki_retention: 30d + +# ============================================================ +# Backup +# ============================================================ +backup: + enabled: true + schedule: "0 2 * * *" + retention: 30 + storage_class: nfs-client + storage_size: 100Gi diff --git a/helms/group_vars/vault.yml b/helms/group_vars/vault.yml new file mode 100644 index 00000000..2acd6ac9 --- /dev/null +++ b/helms/group_vars/vault.yml @@ -0,0 +1,60 @@ +--- +# Vault Ansible - Variables chiffrées +# Fichier: group_vars/vault.yml +# Chiffrer avec: ansible-vault encrypt group_vars/vault.yml + +# PostgreSQL +vault_postgres_password: "Digitribe972" +vault_postgres_repmgr_password: "Digitribe972" + +# Redis +vault_redis_password: "Digitribe972" + +# MinIO +vault_minio_root_user: "minioadmin" +vault_minio_root_password: "Digitribe972" + +# Grafana +vault_grafana_admin_password: "Digitribe972" + +# Airflow +vault_airflow_fernet_key: "Digitribe972SecretKeyForAirflow2024" +vault_airflow_admin_password: "Digitribe972" + +# Gitea +vault_gitea_admin_password: "Digitribe972" + +# Superset +vault_superset_admin_password: "Digitribe972" +vault_superset_db_password: "Digitribe972" + +# Metabase +vault_metabase_db_password: "Digitribe972" + +# MindsDB +vault_mindsdb_password: "Digitribe972" + +# ClickHouse +vault_clickhouse_password: "Digitribe972" + +# Trino +vault_trino_db_password: "Digitribe972" + +# MQTT +vault_mosquitto_password: "Digitribe972" +vault_emqx_admin_password: "Digitribe972" + +# phpIPAM +vault_phpipam_admin_password: "Digitribe972" + +# ODK +vault_odk_admin_password: "Digitribe972" + +# GeoServer +vault_geoserver_admin_password: "Digitribe972" + +# MapStore +vault_mapstore_admin_password: "Digitribe972" + +# StarRocks +vault_starrocks_root_password: "Digitribe972" diff --git a/helms/inventory/hosts.yml b/helms/inventory/hosts.yml new file mode 100644 index 00000000..90ecf7f5 --- /dev/null +++ b/helms/inventory/hosts.yml @@ -0,0 +1,79 @@ +--- +# Inventory pour le déploiement Kubernetes via Ansible +# Fichier: inventory/hosts.yml + +all: + children: + k8s_masters: + hosts: + k8s-master-1: + ansible_host: "{{ k8s_master_ip | default('192.168.1.100') }}" + ansible_user: "{{ k8s_user | default('root') }}" + k8s_workers: + hosts: + k8s-worker-1: + ansible_host: "{{ k8s_worker1_ip | default('192.168.1.101') }}" + ansible_user: "{{ k8s_user | default('root') }}" + k8s-worker-2: + ansible_host: "{{ k8s_worker2_ip | default('192.168.1.102') }}" + ansible_user: "{{ k8s_user | default('root') }}" + nfs_server: + hosts: + nfs-1: + ansible_host: "{{ nfs_server_ip | default('192.168.1.200') }}" + ansible_user: "{{ nfs_user | default('root') }}" + + vars: + # Configuration globale + cluster_name: smart-city-martinique + k8s_version: "1.28" + container_runtime: containerd + network_plugin: cilium + domain: digitribe.fr + + # Namespaces Kubernetes + namespaces: + - airflow + - kafka + - flink + - monitoring + - iot + - gitea + - jupyterhub + - odk + - smartapp + - superset + - metabase + - mindsdb + - mapstore + - geoserver + - frost + - nodered + - phpipam + - traefik + - ingress-nginx + - clickhouse + - starrocks + - trino + - deltalake + - streamlit + - duckdb + + # Storage + storage_class: nfs-client + nfs_path: /data/k8s + + # Helm repositories + helm_repos: + - name: bitnami + url: https://charts.bitnami.com/bitnami + - name: apache + url: https://charts.apache.org + - name: grafana + url: https://grafana.github.io/helm-charts + - name: prometheus + url: https://prometheus-community.github.io/helm-charts + - name: strimzi + url: https://strimzi.io/charts/ + - name: flink-operator + url: https://downloads.apache.org/flink/flink-kubernetes-operator-1.7.0/ diff --git a/helms/roles/airflow/tasks/main.yml b/helms/roles/airflow/tasks/main.yml new file mode 100644 index 00000000..026f4e01 --- /dev/null +++ b/helms/roles/airflow/tasks/main.yml @@ -0,0 +1,34 @@ +--- +# Role: airflow +# Déploie Apache Airflow + +- name: Installer Airflow + kubernetes.core.helm: + name: airflow + chart_ref: "{{ helm_charts.airflow.chart }}" + release_namespace: airflow + create_namespace: true + values: + executor: CeleryExecutor + fernetKey: "{{ vault_airflow_fernet_key }}" + webserver: + defaultUser: + username: admin + password: "{{ vault_airflow_admin_password }}" + dags: + persistence: + enabled: true + size: 10Gi + logs: + persistence: + enabled: true + size: "{{ storage_sizes.airflow }}" + scheduler: + resources: "{{ services.airflow.resources }}" + webserver: + resources: "{{ services.airflow.resources }}" + workers: + replicas: "{{ services.airflow.replicas }}" + resources: "{{ services.airflow.resources }}" + triggerer: + resources: "{{ services.airflow.resources }}" diff --git a/helms/roles/backup/tasks/main.yml b/helms/roles/backup/tasks/main.yml new file mode 100644 index 00000000..24d75ef9 --- /dev/null +++ b/helms/roles/backup/tasks/main.yml @@ -0,0 +1,34 @@ +--- +# Role: backup +# Configure les sauvegardes Velero + +- name: Installer Velero + kubernetes.core.helm: + name: velero + chart_ref: vmware-tanzu/velero + release_namespace: velero + create_namespace: true + values: + configuration: + backupStorageLocation: + name: default + provider: aws + bucket: smart-city-backup + config: + region: eu-west-3 + s3ForcePathStyle: true + schedules: + daily: + schedule: "{{ backup.schedule }}" + template: + includedNamespaces: + - "{{ item }}" + snapshotVolumes: true + ttl: "{{ backup.retention }}h0m0s" + resources: + requests: + cpu: "250m" + memory: "512Mi" + limits: + cpu: "1000m" + memory: "2Gi" diff --git a/helms/roles/bi/tasks/main.yml b/helms/roles/bi/tasks/main.yml new file mode 100644 index 00000000..d4122f9e --- /dev/null +++ b/helms/roles/bi/tasks/main.yml @@ -0,0 +1,44 @@ +--- +# Role: bi +# Déploie Superset et Metabase + +- name: Installer Superset + kubernetes.core.helm: + name: superset + chart_ref: "{{ helm_charts.superset.chart }}" + release_namespace: superset + create_namespace: true + values: + supersetNode: + connections: + redis_password: "{{ vault_redis_password }}" + db_user: superset + db_pass: "{{ vault_superset_db_password }}" + resources: "{{ services.superset.resources }}" + supersetWorker: + replicas: 2 + resources: "{{ services.superset.resources }}" + bootstrapScript: | + #!/bin/bash + pip install psycopg2-binary redis + init: + adminUser: + username: admin + password: "{{ vault_superset_admin_password }}" + email: admin@digitribe.fr + +- name: Installer Metabase + kubernetes.core.helm: + name: metabase + chart_ref: "{{ helm_charts.metabase.chart }}" + release_namespace: metabase + create_namespace: true + values: + database: + type: postgres + host: postgresql-ha-pgpool.default.svc.cluster.local + port: 5432 + dbname: metabase + username: metabase + password: "{{ vault_metabase_db_password }}" + resources: "{{ services.metabase.resources }}" diff --git a/helms/roles/cert-manager/tasks/main.yml b/helms/roles/cert-manager/tasks/main.yml new file mode 100644 index 00000000..1d54fabc --- /dev/null +++ b/helms/roles/cert-manager/tasks/main.yml @@ -0,0 +1,39 @@ +--- +# Role: cert-manager +# Déploie cert-manager pour la gestion des certificats TLS + +- name: Installer cert-manager + kubernetes.core.helm: + name: cert-manager + chart_ref: "{{ helm_charts.cert_manager.chart }}" + chart_version: "{{ helm_charts.cert_manager.version }}" + release_namespace: cert-manager + create_namespace: true + values: + installCRDs: true + resources: + requests: + cpu: "100m" + memory: "128Mi" + limits: + cpu: "500m" + memory: "256Mi" + +- name: Créer le ClusterIssuer Let's Encrypt + kubernetes.core.k8s: + state: present + definition: + apiVersion: cert-manager.io/v1 + kind: ClusterIssuer + metadata: + name: letsencrypt + spec: + acme: + server: https://acme-v02.api.letsencrypt.org/directory + email: "{{ acme_email }}" + privateKeySecretRef: + name: letsencrypt-key + solvers: + - http01: + ingress: + class: traefik diff --git a/helms/roles/clickhouse/tasks/main.yml b/helms/roles/clickhouse/tasks/main.yml new file mode 100644 index 00000000..dbd5ce77 --- /dev/null +++ b/helms/roles/clickhouse/tasks/main.yml @@ -0,0 +1,34 @@ +--- +# Role: clickhouse +# Déploie ClickHouse + +- name: Installer ClickHouse + kubernetes.core.helm: + name: clickhouse + chart_ref: "{{ helm_charts.clickhouse.chart }}" + chart_version: "{{ helm_charts.clickhouse.version }}" + release_namespace: clickhouse + create_namespace: true + values: + shards: 1 + replicaCount: "{{ services.clickhouse.replicas }}" + persistence: + size: "{{ storage_sizes.clickhouse | default('50Gi') }}" + storageClass: "{{ storage_class }}" + resources: "{{ services.clickhouse.resources }}" + auth: + username: default + password: "{{ vault_clickhouse_password }}" + service: + type: ClusterIP + ingress: + enabled: true + hosts: + - host: clickhouse.digitribe.fr + paths: + - path: / + pathType: Prefix + tls: + - secretName: clickhouse-tls + hosts: + - clickhouse.digitribe.fr diff --git a/helms/roles/databases/tasks/main.yml b/helms/roles/databases/tasks/main.yml new file mode 100644 index 00000000..050e74dc --- /dev/null +++ b/helms/roles/databases/tasks/main.yml @@ -0,0 +1,54 @@ +--- +# Role: databases +# Déploie PostgreSQL, Redis et MinIO + +- name: Installer PostgreSQL HA + kubernetes.core.helm: + name: postgresql + chart_ref: "{{ helm_charts.postgresql_ha.chart }}" + release_namespace: default + values: + postgresql: + password: "{{ vault_postgres_password }}" + repmgrPassword: "{{ vault_postgres_repmgr_password }}" + persistence: + size: "{{ storage_sizes.postgresql }}" + storageClass: "{{ storage_class }}" + resources: + requests: + cpu: "{{ services.postgresql.resources.requests.cpu }}" + memory: "{{ services.postgresql.resources.requests.memory }}" + +- name: Installer Redis Cluster + kubernetes.core.helm: + name: redis + chart_ref: "{{ helm_charts.redis.chart }}" + release_namespace: default + values: + cluster: + nodes: 3 + password: "{{ vault_redis_password }}" + persistence: + size: "{{ storage_sizes.redis }}" + storageClass: "{{ storage_class }}" + resources: + requests: + cpu: "100m" + memory: "256Mi" + +- name: Installer MinIO + kubernetes.core.helm: + name: minio + chart_ref: "{{ helm_charts.minio.chart }}" + release_namespace: default + values: + auth: + rootUser: "{{ vault_minio_root_user }}" + rootPassword: "{{ vault_minio_root_password }}" + persistence: + size: "{{ storage_sizes.minio }}" + storageClass: "{{ storage_class }}" + resources: + requests: + cpu: "250m" + memory: "512Mi" diff --git a/helms/roles/deltalake/tasks/main.yml b/helms/roles/deltalake/tasks/main.yml new file mode 100644 index 00000000..98d9ff1a --- /dev/null +++ b/helms/roles/deltalake/tasks/main.yml @@ -0,0 +1,30 @@ +--- +# Role: deltalake +# Déploie Delta Lake + +- name: Installer Delta Lake + kubernetes.core.helm: + name: deltalake + chart_ref: "{{ helm_charts.deltalake.chart }}" + chart_version: "{{ helm_charts.deltalake.version }}" + release_namespace: deltalake + create_namespace: true + values: + replicaCount: "{{ services.deltalake.replicas }}" + resources: "{{ services.deltalake.resources }}" + storage: + size: "{{ storage_sizes.deltalake | default('100Gi') }}" + storageClass: "{{ storage_class }}" + service: + type: ClusterIP + ingress: + enabled: true + hosts: + - host: deltalake.digitribe.fr + paths: + - path: / + pathType: Prefix + tls: + - secretName: deltalake-tls + hosts: + - deltalake.digitribe.fr diff --git a/helms/roles/duckdb/tasks/main.yml b/helms/roles/duckdb/tasks/main.yml new file mode 100644 index 00000000..c1f14d3c --- /dev/null +++ b/helms/roles/duckdb/tasks/main.yml @@ -0,0 +1,30 @@ +--- +# Role: duckdb +# Déploie DuckDB + +- name: Installer DuckDB + kubernetes.core.helm: + name: duckdb + chart_ref: "{{ helm_charts.duckdb.chart }}" + chart_version: "{{ helm_charts.duckdb.version }}" + release_namespace: duckdb + create_namespace: true + values: + replicaCount: "{{ services.duckdb.replicas }}" + resources: "{{ services.duckdb.resources }}" + storage: + size: "{{ storage_sizes.duckdb | default('50Gi') }}" + storageClass: "{{ storage_class }}" + service: + type: ClusterIP + ingress: + enabled: true + hosts: + - host: duckdb.digitribe.fr + paths: + - path: / + pathType: Prefix + tls: + - secretName: duckdb-tls + hosts: + - duckdb.digitribe.fr diff --git a/helms/roles/flink/tasks/main.yml b/helms/roles/flink/tasks/main.yml new file mode 100644 index 00000000..6d137832 --- /dev/null +++ b/helms/roles/flink/tasks/main.yml @@ -0,0 +1,18 @@ +--- +# Role: flink +# Déploie Apache Flink via l'opérateur + +- name: Installer l'opérateur Flink + kubernetes.core.helm: + name: flink-kubernetes-operator + chart_ref: "{{ helm_charts.flink.chart }}" + release_namespace: flink + create_namespace: true + +- name: Créer le déploiement Flink + kubernetes.core.k8s: + state: present + template: flink-deployment.yml.j2 + vars: + flink_namespace: flink + flink_replicas: "{{ services.flink.replicas }}" diff --git a/helms/roles/gis/tasks/main.yml b/helms/roles/gis/tasks/main.yml new file mode 100644 index 00000000..214430a4 --- /dev/null +++ b/helms/roles/gis/tasks/main.yml @@ -0,0 +1,37 @@ +--- +# Role: gis +# Déploie MapStore, GeoServer et FROST + +- name: Installer MapStore + kubernetes.core.helm: + name: mapstore + chart_ref: "{{ helm_charts.mapstore.chart }}" + release_namespace: mapstore + create_namespace: true + values: + persistence: + size: "{{ storage_sizes.mapstore }}" + resources: "{{ services.mapstore.resources }}" + +- name: Installer GeoServer + kubernetes.core.helm: + name: geoserver + chart_ref: "{{ helm_charts.geoserver.chart }}" + release_namespace: geoserver + create_namespace: true + values: + persistence: + geodataDir: + storageClass: "{{ storage_class }}" + size: "{{ storage_sizes.geoserver }}" + resources: "{{ services.geoserver.resources }}" + +- name: Installer FROST + kubernetes.core.helm: + name: frost + chart_ref: "{{ helm_charts.frost.chart }}" + release_namespace: iot + values: + persistence: + size: 10Gi + resources: "{{ services.frost.resources }}" diff --git a/helms/roles/gitea/tasks/main.yml b/helms/roles/gitea/tasks/main.yml new file mode 100644 index 00000000..900e46fb --- /dev/null +++ b/helms/roles/gitea/tasks/main.yml @@ -0,0 +1,28 @@ +--- +# Role: gitea +# Déploie Gitea + +- name: Installer Gitea + kubernetes.core.helm: + name: gitea + chart_ref: "{{ helm_charts.gitea.chart }}" + release_namespace: gitea + create_namespace: true + values: + gitea: + admin: + username: eric + password: "{{ vault_gitea_admin_password }}" + email: admin@digitribe.fr + config: + server: + DOMAIN: gitea.digitribe.fr + ROOT_URL: https://gitea.digitribe.fr + SSH_DOMAIN: gitea.digitribe.fr + SSH_PORT: 22 + persistence: + enabled: true + size: "{{ storage_sizes.gitea }}" + postgresql: + enabled: true + resources: "{{ services.gitea.resources }}" diff --git a/helms/roles/iot/tasks/main.yml b/helms/roles/iot/tasks/main.yml new file mode 100644 index 00000000..346ee857 --- /dev/null +++ b/helms/roles/iot/tasks/main.yml @@ -0,0 +1,35 @@ +--- +# Role: iot +# Déploie les brokers MQTT + + +- name: Installer EMQX + kubernetes.core.helm: + name: emqx + chart_ref: "{{ helm_charts.emqx.chart }}" + release_namespace: iot + create_namespace: true + values: + replicaCount: "{{ services.emqx.replicas }}" + persistence: + enabled: true + size: "{{ storage_sizes.emqx }}" + resources: "{{ services.emqx.resources }}" + +- name: Installer Mosquitto + kubernetes.core.helm: + name: mosquitto + chart_ref: "{{ helm_charts.mosquitto.chart }}" + release_namespace: iot + values: + replicaCount: "{{ services.mosquitto.replicas }}" + persistence: + enabled: true + size: "{{ storage_sizes.mosquitto }}" + resources: "{{ services.mosquitto.resources }}" + config: | + listener 1883 + allow_anonymous false + password_file /etc/mosquitto/passwd + auth: + password: "{{ vault_mosquitto_password }}" diff --git a/helms/roles/jupyterhub/tasks/main.yml b/helms/roles/jupyterhub/tasks/main.yml new file mode 100644 index 00000000..3ea13c3f --- /dev/null +++ b/helms/roles/jupyterhub/tasks/main.yml @@ -0,0 +1,31 @@ +--- +# Role: jupyterhub +# Déploie JupyterHub + +- name: Installer JupyterHub + kubernetes.core.helm: + name: hub + chart_ref: "{{ helm_charts.jupyterhub.chart }}" + release_namespace: jupyterhub + create_namespace: true + values: + hub: + config: + Authenticator: + admin_users: + - eric + JupyterHub: + admin_access: true + db: + pvc: + storage: "{{ storage_sizes.jupyterhub }}" + singleuser: + storage: + capacity: "{{ storage_sizes.jupyterhub }}" + dynamic: + pvcNameTemplate: "jupyterhub-{userid}" + volumeNameTemplate: "jupyterhub-{userid}" + storageClass: "{{ storage_class }}" + proxy: + service: + type: ClusterIP diff --git a/helms/roles/kafka/tasks/main.yml b/helms/roles/kafka/tasks/main.yml new file mode 100644 index 00000000..c1b9be65 --- /dev/null +++ b/helms/roles/kafka/tasks/main.yml @@ -0,0 +1,19 @@ +--- +# Role: kafka +# Déploie Kafka via l'opérateur Strimzi + +- name: Installer l'opérateur Strimzi + kubernetes.core.helm: + name: strimzi-kafka-operator + chart_ref: "{{ helm_charts.kafka.chart }}" + release_namespace: kafka + create_namespace: true + +- name: Créer le cluster Kafka + kubernetes.core.k8s: + state: present + template: kafka-cluster.yml.j2 + vars: + kafka_namespace: kafka + kafka_replicas: "{{ services.kafka.replicas }}" + kafka_storage_size: "{{ storage_sizes.kafka }}" diff --git a/helms/roles/mindsdb/tasks/main.yml b/helms/roles/mindsdb/tasks/main.yml new file mode 100644 index 00000000..f52211e3 --- /dev/null +++ b/helms/roles/mindsdb/tasks/main.yml @@ -0,0 +1,18 @@ +--- +# Role: mindsdb +# Déploie MindsDB + +- name: Installer MindsDB + kubernetes.core.helm: + name: mindsdb + chart_ref: "{{ helm_charts.mindsdb.chart }}" + release_namespace: mindsdb + create_namespace: true + values: + mindsdb: + auth: + username: admin + password: "{{ vault_mindsdb_password }}" + storage: + size: "{{ storage_sizes.mindsdb }}" + resources: "{{ services.mindsdb.resources }}" diff --git a/helms/roles/monitoring/tasks/main.yml b/helms/roles/monitoring/tasks/main.yml new file mode 100644 index 00000000..c185f4bf --- /dev/null +++ b/helms/roles/monitoring/tasks/main.yml @@ -0,0 +1,41 @@ +--- +# Role: monitoring +# Déploie Prometheus, Grafana, Loki et Promtail + +- name: Installer kube-prometheus-stack + kubernetes.core.helm: + name: prometheus + chart_ref: "{{ helm_charts.prometheus.chart }}" + release_namespace: monitoring + create_namespace: true + values: + prometheus: + prometheusSpec: + retention: "{{ monitoring.prometheus_retention }}" + storageSpec: + volumeClaimTemplate: + spec: + storageClassName: "{{ storage_class }}" + resources: + requests: + storage: "{{ storage_sizes.prometheus }}" + grafana: + adminPassword: "{{ monitoring.grafana_admin_password }}" + persistence: + enabled: true + size: "{{ storage_sizes.grafana }}" + alertmanager: + enabled: false + +- name: Installer Loki Stack + kubernetes.core.helm: + name: loki + chart_ref: "{{ helm_charts.loki.chart }}" + release_namespace: monitoring + values: + loki: + persistence: + enabled: true + size: "{{ storage_sizes.loki }}" + promtail: + enabled: true diff --git a/helms/roles/namespaces/tasks/main.yml b/helms/roles/namespaces/tasks/main.yml new file mode 100644 index 00000000..09203d37 --- /dev/null +++ b/helms/roles/namespaces/tasks/main.yml @@ -0,0 +1,17 @@ +--- +# Role: namespaces +# Crée les namespaces Kubernetes + +- name: Créer les namespaces + kubernetes.core.k8s: + state: present + definition: + apiVersion: v1 + kind: Namespace + metadata: + name: "{{ item }}" + labels: + app.kubernetes.io/managed-by: ansible + cluster: "{{ cluster_name }}" + type: kubernetes.io/metadata.v1 + loop: "{{ namespaces }}" diff --git a/helms/roles/nodered/tasks/main.yml b/helms/roles/nodered/tasks/main.yml new file mode 100644 index 00000000..f09e02b9 --- /dev/null +++ b/helms/roles/nodered/tasks/main.yml @@ -0,0 +1,26 @@ +--- +# Role: nodered +# Déploie Node-RED + +- name: Installer Node-RED + kubernetes.core.helm: + name: nodered + chart_ref: "{{ helm_charts.nodered.chart }}" + release_namespace: iot + values: + replicaCount: "{{ services.nodered.replicas }}" + persistence: + enabled: true + size: 5Gi + resources: "{{ services.nodered.resources }}" + ingress: + enabled: true + hosts: + - host: nodered.digitribe.fr + paths: + - path: / + pathType: Prefix + tls: + - secretName: nodered-tls + hosts: + - nodered.digitribe.fr diff --git a/helms/roles/odk/tasks/main.yml b/helms/roles/odk/tasks/main.yml new file mode 100644 index 00000000..9981e329 --- /dev/null +++ b/helms/roles/odk/tasks/main.yml @@ -0,0 +1,22 @@ +--- +# Role: odk +# Déploie ODK Central + +- name: Installer ODK Central + kubernetes.core.helm: + name: odk-central + chart_ref: "{{ helm_charts.odk.chart }}" + release_namespace: odk + create_namespace: true + values: + backend: + replicaCount: 1 + resources: "{{ services.odk.resources }}" + frontend: + replicaCount: 1 + resources: "{{ services.odk.resources }}" + postgres: + enabled: true + storage: "{{ storage_sizes.odk }}" + redis: + enabled: true diff --git a/helms/roles/phpipam/tasks/main.yml b/helms/roles/phpipam/tasks/main.yml new file mode 100644 index 00000000..2e7c7430 --- /dev/null +++ b/helms/roles/phpipam/tasks/main.yml @@ -0,0 +1,27 @@ +--- +# Role: phpipam +# Déploie phpIPAM + +- name: Installer phpIPAM + kubernetes.core.helm: + name: phpipam + chart_ref: "{{ helm_charts.phpipam.chart }}" + release_namespace: phpipam + create_namespace: true + values: + phpipam: + adminPassword: "{{ vault_phpipam_admin_password }}" + persistence: + size: 5Gi + resources: "{{ services.phpipam.resources }}" + ingress: + enabled: true + hosts: + - host: phpipam.digitribe.fr + paths: + - path: / + pathType: Prefix + tls: + - secretName: phpipam-tls + hosts: + - phpipam.digitribe.fr diff --git a/helms/roles/prerequisites/tasks/main.yml b/helms/roles/prerequisites/tasks/main.yml new file mode 100644 index 00000000..31012f01 --- /dev/null +++ b/helms/roles/prerequisites/tasks/main.yml @@ -0,0 +1,21 @@ +--- +# Role: prerequisites +# Installe les prérequis sur le cluster Kubernetes + +- name: Ajouter les repositories Helm + kubernetes.core.helm_repository: + name: "{{ item.name }}" + repo_url: "{{ item.url }}" + loop: "{{ helm_repos }}" + +- name: Mettre à jour les repositories Helm + command: helm repo update + changed_when: false + +- name: Installer les CRDs nécessaires + kubernetes.core.k8s: + state: present + src: "{{ item }}" + loop: + - https://github.com/cert-manager/cert-manager/releases/download/v1.13.0/cert-manager.crds.yaml + ignore_errors: true diff --git a/helms/roles/smartapp/tasks/main.yml b/helms/roles/smartapp/tasks/main.yml new file mode 100644 index 00000000..69deb710 --- /dev/null +++ b/helms/roles/smartapp/tasks/main.yml @@ -0,0 +1,19 @@ +--- +# Role: smartapp +# Déploie l'application Smart City + +- name: Déployer Smart App Web + kubernetes.core.k8s: + state: present + template: smartapp-web.yml.j2 + vars: + smartapp_namespace: smartapp + smartapp_domain: smartapp.digitribe.fr + +- name: Déployer Smart App API + kubernetes.core.k8s: + state: present + template: smartapp-api.yml.j2 + vars: + smartapp_namespace: smartapp + smartapp_domain: api-smartapp.digitribe.fr diff --git a/helms/roles/starrocks/tasks/main.yml b/helms/roles/starrocks/tasks/main.yml new file mode 100644 index 00000000..35a2b6c2 --- /dev/null +++ b/helms/roles/starrocks/tasks/main.yml @@ -0,0 +1,38 @@ +--- +# Role: starrocks +# Déploie StarRocks + +- name: Ajouter le repository Helm StarRocks + kubernetes.core.helm_repository: + name: starrocks + repo_url: https://starrocks.github.io/starrocks-kubernetes-operator + +- name: Installer StarRocks + kubernetes.core.helm: + name: starrocks + chart_ref: "{{ helm_charts.starrocks.chart }}" + chart_version: "{{ helm_charts.starrocks.version }}" + release_namespace: starrocks + create_namespace: true + values: + fe: + replicas: "{{ services.starrocks.replicas }}" + resources: "{{ services.starrocks.resources }}" + storage: + size: "{{ storage_sizes.starrocks | default('50Gi') }}" + storageClass: "{{ storage_class }}" + be: + replicas: 3 + resources: "{{ services.starrocks.resources }}" + storage: + size: "{{ storage_sizes.starrocks | default('100Gi') }}" + storageClass: "{{ storage_class }}" + cn: + replicas: 2 + resources: + requests: + cpu: "250m" + memory: "512Mi" + limits: + cpu: "1000m" + memory: "2Gi" diff --git a/helms/roles/storage/tasks/main.yml b/helms/roles/storage/tasks/main.yml new file mode 100644 index 00000000..92849289 --- /dev/null +++ b/helms/roles/storage/tasks/main.yml @@ -0,0 +1,27 @@ +--- +# Role: storage +# Configure le stockage NFS et les StorageClasses + +- name: Créer le namespace storage + kubernetes.core.k8s: + state: present + definition: + apiVersion: v1 + kind: Namespace + metadata: + name: storage + +- name: Installer le NFS provisioner + kubernetes.core.helm: + name: nfs-provisioner + chart_ref: "{{ helm_charts.nfs_provisioner.chart }}" + chart_version: "{{ helm_charts.nfs_provisioner.version }}" + release_namespace: storage + values: + nfs: + server: "{{ nfs_server }}" + path: "{{ nfs_path }}" + storageClass: + name: "{{ storage_class }}" + defaultClass: true + reclaimPolicy: Retain diff --git a/helms/roles/streamlit/tasks/main.yml b/helms/roles/streamlit/tasks/main.yml new file mode 100644 index 00000000..ecf89d28 --- /dev/null +++ b/helms/roles/streamlit/tasks/main.yml @@ -0,0 +1,30 @@ +--- +# Role: streamlit +# Déploie Streamlit + +- name: Installer Streamlit + kubernetes.core.helm: + name: streamlit + chart_ref: "{{ helm_charts.streamlit.chart }}" + chart_version: "{{ helm_charts.streamlit.version }}" + release_namespace: streamlit + create_namespace: true + values: + replicaCount: "{{ services.streamlit.replicas }}" + resources: "{{ services.streamlit.resources }}" + service: + type: ClusterIP + ingress: + enabled: true + hosts: + - host: streamlit.digitribe.fr + paths: + - path: / + pathType: Prefix + tls: + - secretName: streamlit-tls + hosts: + - streamlit.digitribe.fr + env: + STREAMLIT_SERVER_HEADLESS: "true" + STREAMLIT_SERVER_ENABLE_CORS: "false" diff --git a/helms/roles/traefik/tasks/main.yml b/helms/roles/traefik/tasks/main.yml new file mode 100644 index 00000000..9f882e86 --- /dev/null +++ b/helms/roles/traefik/tasks/main.yml @@ -0,0 +1,49 @@ +--- +# Role: traefik +# Déploie le reverse proxy Traefik + +- name: Créer le namespace traefik + kubernetes.core.k8s: + state: present + definition: + apiVersion: v1 + kind: Namespace + metadata: + name: "{{ traefik_namespace }}" + +- name: Installer Traefik + kubernetes.core.helm: + name: traefik + chart_ref: helm_charts.traefik.chart + release_namespace: "{{ traefik_namespace }}" + values: + globalArguments: + - "--global.checknewversion=false" + - "--global.sendanonymoususage=false" + additionalArguments: + - "--providers.kubernetescrd.allowexternalnameservices=true" + - "--certificatesresolvers.letsencrypt.acme.tlschallenge=true" + - "--certificatesresolvers.letsencrypt.acme.email={{ acme_email }}" + - "--certificatesresolvers.letsencrypt.acme.storage=/data/acme.json" + ports: + traefik: + port: 9000 + expose: false + web: + port: 80 + expose: true + websecure: + port: 443 + expose: true + persistence: + enabled: true + size: 1Gi + service: + type: LoadBalancer + resources: + requests: + cpu: "100m" + memory: "128Mi" + limits: + cpu: "1000m" + memory: "512Mi" diff --git a/helms/roles/trino/tasks/main.yml b/helms/roles/trino/tasks/main.yml new file mode 100644 index 00000000..450b9b34 --- /dev/null +++ b/helms/roles/trino/tasks/main.yml @@ -0,0 +1,46 @@ +--- +# Role: trino +# Déploie Trino + +- name: Installer Trino + kubernetes.core.helm: + name: trino + chart_ref: "{{ helm_charts.trino.chart }}" + chart_version: "{{ helm_charts.trino.version }}" + release_namespace: trino + create_namespace: true + values: + server: + workers: "{{ services.trino.replicas }}" + resources: "{{ services.trino.resources }}" + coordinator: + resources: "{{ services.trino.resources }}" + worker: + resources: "{{ services.trino.resources }}" + service: + type: ClusterIV + ingress: + enabled: true + hosts: + - host: trino.digitribe.fr + paths: + - path: / + pathType: Prefix + tls: + - secretName: trino-tls + hosts: + - trino.digitribe.fr + catalog: + postgresql: + connector.name=postgresql + connection-url=jdbc:postgresql://postgresql-ha-pgpool.default.svc.cluster.local:5432/smartcity + connection-user=trino + connection-password={{ vault_trino_db_password }} + clickhouse: + connector.name=clickhouse + connection-url=jdbc:clickhouse://clickhouse.clickhouse.svc.cluster.local:8123/default + connection-user=default + connection-password={{ vault_clickhouse_password }} + delta: + connector.name=delta_lake + connection-url=jdbc:delta://deltalake.deltalake.svc.cluster.local:9083 diff --git a/helms/undeploy.yml b/helms/undeploy.yml new file mode 100644 index 00000000..681f8ce7 --- /dev/null +++ b/helms/undeploy.yml @@ -0,0 +1,56 @@ +--- +# Playbook de suppression de la stack +# Fichier: undeploy.yml + +- name: Suppression Smart City Martinique de Kubernetes + hosts: localhost + connection: local + gather_facts: false + + vars_files: + - group_vars/all.yml + + tasks: + - name: Supprimer les namespaces Kubernetes + kubernetes.core.k8s: + state: absent + definition: + apiVersion: v1 + kind: Namespace + metadata: + name: "{{ item }}" + loop: "{{ namespaces }}" + ignore_errors: true + + - name: Supprimer les PersistentVolumes + kubernetes.core.k8s: + state: absent + definition: + apiVersion: v1 + kind: PersistentVolume + metadata: + name: "{{ item }}" + loop: "{{ persistent_volumes | default([]) }}" + ignore_errors: true + + - name: Supprimer les ClusterRoles + kubernetes.core.k8s: + state: absent + kind: ClusterRole + name: "{{ item }}" + loop: + - traefik + - cert-manager + - prometheus + ignore_errors: true + + - name: Supprimer les ClusterRoleBindings + kubernetes.core.k8s: + state: absent + kind: ClusterRoleBinding + name: "{{ item }}" + loop: + - traefik + - cert-manager + - prometheus + ignore_errors: true