Merge branch 'main' of https://git.pigreco66.it/gitadmin/italiadatacenter
This commit is contained in:
@@ -0,0 +1,21 @@
|
|||||||
|
# Dockerfile di esempio — containerizza un flow esportato da Langflow
|
||||||
|
# come Python app standalone, da usare nel percorso BYO (Esempio B).
|
||||||
|
|
||||||
|
FROM python:3.11-slim
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# requirements.txt generato/estratto insieme all'export del flow
|
||||||
|
# (langflow, langgraph-checkpointer-kagent, e le dipendenze del tuo flow)
|
||||||
|
COPY requirements.txt .
|
||||||
|
RUN pip install --no-cache-dir -r requirements.txt
|
||||||
|
|
||||||
|
# Codice esportato dal builder low-code + eventuali customizzazioni
|
||||||
|
# del developer (es. integrazione kagentCheckpointer se usi LangGraph)
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
# L'agente deve esporre un endpoint compatibile A2A sulla porta
|
||||||
|
# dichiarata in byo.deployment.port dell'Agent CR
|
||||||
|
EXPOSE 8080
|
||||||
|
|
||||||
|
CMD ["python", "agent_server.py"]
|
||||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,7 @@
|
|||||||
|
# crea secret con langflow-secrets-setup.sh
|
||||||
|
|
||||||
|
|
||||||
|
# Poi installa con i valori personalizzati
|
||||||
|
helm install langflow-ide langflow/langflow-ide \
|
||||||
|
-f langflow-values.yaml \
|
||||||
|
-n langflow-team-alpha --create-namespace
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
# HTTPRoute (Gateway API) per Langflow IDE
|
||||||
|
# Presuppone un Gateway nginx già esistente nel cluster (nginx Gateway
|
||||||
|
# Fabric), referenziato come parentRef qui sotto.
|
||||||
|
|
||||||
|
apiVersion: gateway.networking.k8s.io/v1
|
||||||
|
kind: HTTPRoute
|
||||||
|
metadata:
|
||||||
|
name: langflow-team-alpha
|
||||||
|
namespace: langflow-team-alpha
|
||||||
|
spec:
|
||||||
|
parentRefs:
|
||||||
|
- name: nginx-gateway # nome del Gateway condiviso — verifica con:
|
||||||
|
namespace: nginx-gateway # kubectl get gateway -A
|
||||||
|
sectionName: https # nome del listener HTTPS sul Gateway
|
||||||
|
|
||||||
|
hostnames:
|
||||||
|
- "langflow-team-alpha.pigreco66.it"
|
||||||
|
|
||||||
|
rules:
|
||||||
|
# UI/editor visuale (frontend) — porta 8080 come da doc Langflow
|
||||||
|
- matches:
|
||||||
|
- path:
|
||||||
|
type: PathPrefix
|
||||||
|
value: /
|
||||||
|
backendRefs:
|
||||||
|
- name: langflow-ide-frontend # verifica nome esatto: kubectl get svc -n langflow-team-alpha
|
||||||
|
port: 8080
|
||||||
|
|
||||||
|
# API backend, se vuoi esporla separatamente (es. per invocazione
|
||||||
|
# programmatica di un flow senza passare dall'editor) — porta 7860
|
||||||
|
- matches:
|
||||||
|
- path:
|
||||||
|
type: PathPrefix
|
||||||
|
value: /api
|
||||||
|
backendRefs:
|
||||||
|
- name: langflow-ide-backend # verifica nome esatto: kubectl get svc -n langflow-team-alpha
|
||||||
|
port: 7860
|
||||||
|
---
|
||||||
|
# TLS: con Gateway API il certificato si referenzia sul Gateway stesso
|
||||||
|
# (non sull'HTTPRoute). Se il Gateway condiviso non ha già un listener
|
||||||
|
# per questo hostname, serve aggiungerlo lì, es.:
|
||||||
|
#
|
||||||
|
# apiVersion: gateway.networking.k8s.io/v1
|
||||||
|
# kind: Gateway
|
||||||
|
# metadata:
|
||||||
|
# name: nginx-gateway
|
||||||
|
# namespace: nginx-gateway
|
||||||
|
# spec:
|
||||||
|
# gatewayClassName: nginx
|
||||||
|
# listeners:
|
||||||
|
# - name: https
|
||||||
|
# protocol: HTTPS
|
||||||
|
# port: 443
|
||||||
|
# hostname: "*.pigreco66.it"
|
||||||
|
# tls:
|
||||||
|
# mode: Terminate
|
||||||
|
# certificateRefs:
|
||||||
|
# - name: wildcard-pigreco66-it-tls
|
||||||
|
# allowedRoutes:
|
||||||
|
# namespaces:
|
||||||
|
# from: All
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
# Creazione dei Secret richiesti da langflow-values.yaml
|
||||||
|
# Namespace di esempio: langflow-team-alpha (adatta al tuo tenant)
|
||||||
|
|
||||||
|
# 1. Secret connessione database Postgres
|
||||||
|
kubectl create secret generic langflow-db-secret \
|
||||||
|
-n langflow-team-alpha \
|
||||||
|
--from-literal=connection-string="postgresql://user:pass@host:5432/langflow"
|
||||||
|
|
||||||
|
# 2. Secret credenziali admin (superuser Langflow)
|
||||||
|
kubectl create secret generic langflow-admin-secret \
|
||||||
|
-n langflow-team-alpha \
|
||||||
|
--from-literal=username="admin" \
|
||||||
|
--from-literal=password="<password-sicura>"
|
||||||
|
|
||||||
|
# 3. Secret credenziali LLM — STESSO Secret già usato per kagent nel
|
||||||
|
# golden path di onboarding-team: se lo hai già creato per kagent
|
||||||
|
# in questo namespace, questo passaggio è già fatto, verifica solo
|
||||||
|
# che contenga le chiavi coi nomi attesi (vedi sotto).
|
||||||
|
#
|
||||||
|
# Se non esiste ancora, crealo così (aggiungi/rimuovi provider a
|
||||||
|
# seconda di cosa serve al team):
|
||||||
|
kubectl create secret generic llm-credentials \
|
||||||
|
-n langflow-team-alpha \
|
||||||
|
--from-literal=openai-api-key="sk-..." \
|
||||||
|
--from-literal=anthropic-api-key="sk-ant-..."
|
||||||
|
|
||||||
|
# Se il Secret esiste già (es. creato per kagent) e vuoi solo
|
||||||
|
# aggiungere/aggiornare una chiave senza ricrearlo da zero:
|
||||||
|
kubectl patch secret llm-credentials -n langflow-team-alpha \
|
||||||
|
--type=json \
|
||||||
|
-p='[{"op":"add","path":"/data/openai-api-key","value":"'$(echo -n "sk-..." | base64)'"}]'
|
||||||
|
|
||||||
|
# 4. Verifica che tutti i Secret siano presenti prima di installare/
|
||||||
|
# aggiornare la release Helm
|
||||||
|
kubectl get secrets -n langflow-team-alpha
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
# values.yaml — Langflow IDE, personalizzato per un namespace-tenant
|
||||||
|
# Uso: helm install langflow-ide langflow/langflow-ide -f values.yaml -n <namespace>
|
||||||
|
|
||||||
|
langflow:
|
||||||
|
backend:
|
||||||
|
image:
|
||||||
|
repository: langflowai/langflow
|
||||||
|
tag: "1.10.0" # fissa una versione esplicita, evita 'latest' in produzione
|
||||||
|
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 250m
|
||||||
|
memory: 512Mi
|
||||||
|
limits:
|
||||||
|
cpu: "1"
|
||||||
|
memory: 2Gi
|
||||||
|
|
||||||
|
# Variabili LLM/DB — usa Secret, mai valori in chiaro qui
|
||||||
|
env:
|
||||||
|
- name: LANGFLOW_DATABASE_URL
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: langflow-db-secret
|
||||||
|
key: connection-string
|
||||||
|
- name: LANGFLOW_SUPERUSER
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: langflow-admin-secret
|
||||||
|
key: username
|
||||||
|
- name: LANGFLOW_SUPERUSER_PASSWORD
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: langflow-admin-secret
|
||||||
|
key: password
|
||||||
|
# Rimuove automaticamente eventuali API key salvate nei flow prima
|
||||||
|
# di persisterli a DB — best practice di sicurezza, seconda linea
|
||||||
|
# di difesa oltre alle Global Variable qui sotto
|
||||||
|
- name: LANGFLOW_REMOVE_API_KEYS
|
||||||
|
value: "true"
|
||||||
|
|
||||||
|
# --- Pre-caricamento credenziali LLM come Global Variable ---
|
||||||
|
# Riusa lo stesso Secret 'llm-credentials' già previsto per kagent
|
||||||
|
# in fase di onboarding del team (vedi golden path Backstage).
|
||||||
|
# I developer trovano le chiavi già pronte nel dropdown Global
|
||||||
|
# Variable, senza mai vederne il valore reale.
|
||||||
|
- name: LANGFLOW_STORE_ENVIRONMENT_VARIABLES
|
||||||
|
value: "true"
|
||||||
|
- name: LANGFLOW_VARIABLES_TO_GET_FROM_ENVIRONMENT
|
||||||
|
value: "OPENAI_API_KEY,ANTHROPIC_API_KEY"
|
||||||
|
- name: OPENAI_API_KEY
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: llm-credentials
|
||||||
|
key: openai-api-key
|
||||||
|
optional: true # non tutti i team useranno tutti i provider
|
||||||
|
- name: ANTHROPIC_API_KEY
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: llm-credentials
|
||||||
|
key: anthropic-api-key
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
frontend:
|
||||||
|
image:
|
||||||
|
repository: langflowai/langflow
|
||||||
|
tag: "1.10.0"
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 256Mi
|
||||||
|
limits:
|
||||||
|
cpu: 500m
|
||||||
|
memory: 512Mi
|
||||||
|
|
||||||
|
# Ingress classico DISABILITATO — l'esposizione avviene via Gateway API
|
||||||
|
# (nginx Gateway Fabric), vedi manifest separato langflow-httproute.yaml
|
||||||
|
ingress:
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
# Il Service del frontend resta ClusterIP (default del chart), sarà
|
||||||
|
# l'HTTPRoute a instradare il traffico dal Gateway verso questo Service
|
||||||
|
|
||||||
|
# Persistenza dei flow salvati (altrimenti persi al riavvio del pod)
|
||||||
|
persistence:
|
||||||
|
enabled: true
|
||||||
|
size: 5Gi
|
||||||
|
storageClassName: standard # adatta alla tua StorageClass
|
||||||
@@ -0,0 +1,166 @@
|
|||||||
|
# =====================================================================
|
||||||
|
# ESEMPIO A — Agent dichiarativo nativo (kagent esegue direttamente)
|
||||||
|
# Caso d'uso: flow Langflow/Flowise semplice — un LLM + un paio di tool,
|
||||||
|
# nessuna logica custom complessa. Tradotto 1:1 in prompt + tool MCP.
|
||||||
|
# =====================================================================
|
||||||
|
apiVersion: kagent.dev/v1alpha2
|
||||||
|
kind: Agent
|
||||||
|
metadata:
|
||||||
|
name: k8s-troubleshooter
|
||||||
|
namespace: team-alpha
|
||||||
|
spec:
|
||||||
|
description: Agente di troubleshooting Kubernetes
|
||||||
|
type: Declarative
|
||||||
|
declarative:
|
||||||
|
modelConfig: gpt4o-config
|
||||||
|
systemMessage: |
|
||||||
|
Sei un agente di troubleshooting per Kubernetes...
|
||||||
|
a2aConfig:
|
||||||
|
skills:
|
||||||
|
- id: diagnose-pod-issue
|
||||||
|
name: Diagnose Pod Issue
|
||||||
|
description: Investiga problemi su pod/servizi Kubernetes
|
||||||
|
inputModes: ["text"]
|
||||||
|
outputModes: ["text"]
|
||||||
|
tags: ["kubernetes"]
|
||||||
|
tools:
|
||||||
|
- type: McpServer
|
||||||
|
mcpServer:
|
||||||
|
name: kagent-tool-server
|
||||||
|
kind: RemoteMCPServer
|
||||||
|
toolNames:
|
||||||
|
- k8s_get_pods
|
||||||
|
- k8s_describe_pod
|
||||||
|
- k8s_get_logs
|
||||||
|
---
|
||||||
|
apiVersion: kagent.dev/v1alpha1
|
||||||
|
kind: ModelConfig
|
||||||
|
metadata:
|
||||||
|
name: gpt4o-config
|
||||||
|
namespace: team-alpha
|
||||||
|
spec:
|
||||||
|
provider: OpenAI
|
||||||
|
model: gpt-4o
|
||||||
|
apiKeySecretRef:
|
||||||
|
name: llm-credentials
|
||||||
|
key: openai-api-key
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# invocazione
|
||||||
|
Le 4 modalità di invocazione
|
||||||
|
1. Dashboard kagent (per gli utenti umani, uso interattivo)
|
||||||
|
bash
|
||||||
|
kagent dashboard
|
||||||
|
|
||||||
|
Apre una UI web dove cerchi k8s-troubleshooter nella lista e chatti direttamente — il modo più immediato per un developer che vuole testare l'agente senza altri strumenti.
|
||||||
|
|
||||||
|
2. CLI kagent (per script, pipeline, debug da terminale)
|
||||||
|
bash
|
||||||
|
kagent invoke --agent k8s-troubleshooter -n team-alpha \
|
||||||
|
--task "Il pod payment-service-7d9f in default sta crashando, investiga"
|
||||||
|
3. Chiamata diretta via A2A REST (per integrazione da altri sistemi/servizi)
|
||||||
|
|
||||||
|
Ogni Agent espone un endpoint A2A standard, con un "agent card" che ne descrive le capability:
|
||||||
|
|
||||||
|
bash
|
||||||
|
kubectl port-forward -n kagent svc/kagent-service 8083:8083
|
||||||
|
|
||||||
|
# scopri le capability dell'agente
|
||||||
|
curl localhost:8083/api/a2a/team-alpha/k8s-troubleshooter/.well-known/agent.json
|
||||||
|
|
||||||
|
# invocalo
|
||||||
|
curl -X POST localhost:8083/api/a2a/team-alpha/k8s-troubleshooter/ \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"task": "Perché il pod payment-service sta in CrashLoopBackOff?"}'
|
||||||
|
|
||||||
|
Questa è la via che useresti se, ad esempio, un tuo servizio interno (o un'automazione CI/CD) deve invocare l'agente programmaticamente.
|
||||||
|
|
||||||
|
4. Canali chat (Slack/Teams/Discord/Telegram) — via AgentHarness CRD
|
||||||
|
|
||||||
|
Se vuoi che i developer interroghino l'agente direttamente da Slack invece che aprire la dashboard, kagent ha una CRD dedicata (AgentHarness) che fa da ponte:
|
||||||
|
|
||||||
|
yaml
|
||||||
|
apiVersion: kagent.dev/v1alpha2
|
||||||
|
kind: AgentHarness
|
||||||
|
metadata:
|
||||||
|
name: k8s-troubleshooter-slack
|
||||||
|
namespace: kagent
|
||||||
|
spec:
|
||||||
|
backend: hermes
|
||||||
|
modelConfigRef: default-model-config
|
||||||
|
channels:
|
||||||
|
- name: platform
|
||||||
|
type: slack
|
||||||
|
slack:
|
||||||
|
botToken:
|
||||||
|
valueFrom: {type: Secret, name: slack-tokens, key: bot-token}
|
||||||
|
appToken:
|
||||||
|
valueFrom: {type: Secret, name: slack-tokens, key: app-token}
|
||||||
|
|
||||||
|
Poi in Slack: /mykagent perché il pod X sta crashando? — il bot inoltra la richiesta all'agente via A2A e posta la risposta nel canale. Interessante per un'IDP perché è il canale più naturale per i developer, senza dover imparare dashboard o CLI dedicate.
|
||||||
|
|
||||||
|
# =====================================================================
|
||||||
|
# ESEMPIO B — Agent BYO (Bring Your Own), container esportato da
|
||||||
|
# Langflow/Flowise dopo containerizzazione custom.
|
||||||
|
# Caso d'uso: flow complesso con logica di stato/loop che il developer
|
||||||
|
# ha personalizzato oltre quello che il builder low-code esporta,
|
||||||
|
# quindi ha bisogno di pieno controllo del codice.
|
||||||
|
# =====================================================================
|
||||||
|
apiVersion: kagent.dev/v1alpha1
|
||||||
|
kind: Agent
|
||||||
|
metadata:
|
||||||
|
name: currency-exchange-agent
|
||||||
|
namespace: team-alpha
|
||||||
|
spec:
|
||||||
|
type: BYO
|
||||||
|
byo:
|
||||||
|
deployment:
|
||||||
|
image: ghcr.io/team-alpha/langflow-currency-agent:latest
|
||||||
|
workingDir: /app
|
||||||
|
env:
|
||||||
|
- name: GOOGLE_API_KEY
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: llm-credentials
|
||||||
|
key: gemini-api-key
|
||||||
|
port: 8080 # porta su cui l'agente espone l'endpoint A2A
|
||||||
|
|
||||||
|
# Nota: kagent invoca questo agente via protocollo A2A, trattandolo
|
||||||
|
# come black box — nessuna decomposizione in prompt/tool separati,
|
||||||
|
# perché la logica vive interamente dentro l'immagine.
|
||||||
|
|
||||||
|
|
||||||
|
## Esempio Agent di Orchestrazione
|
||||||
|
apiVersion: kagent.dev/v1alpha2
|
||||||
|
kind: Agent
|
||||||
|
metadata:
|
||||||
|
name: incident-commander
|
||||||
|
namespace: team-alpha
|
||||||
|
spec:
|
||||||
|
type: Declarative
|
||||||
|
declarative:
|
||||||
|
systemMessage: |
|
||||||
|
Sei il coordinatore per la gestione incidenti. Quando ricevi una
|
||||||
|
segnalazione, decidi quali specialisti coinvolgere: se riguarda
|
||||||
|
pod/servizi K8s, delega al k8s-troubleshooter; se servono i log,
|
||||||
|
delega al log-analyzer. Puoi chiamare entrambi in sequenza se
|
||||||
|
il problema lo richiede.
|
||||||
|
modelConfig: gpt4o-config
|
||||||
|
tools:
|
||||||
|
- type: McpServer
|
||||||
|
mcpServer:
|
||||||
|
name: kagent-tool-server
|
||||||
|
toolNames: ["k8s_get_events"]
|
||||||
|
|
||||||
|
# Sotto-agenti esposti come "tool" — la scelta di chiamarli
|
||||||
|
# è dell'LLM di incident-commander, non di kagent
|
||||||
|
- type: Agent
|
||||||
|
agent:
|
||||||
|
name: k8s-troubleshooter
|
||||||
|
namespace: team-alpha
|
||||||
|
- type: Agent
|
||||||
|
agent:
|
||||||
|
name: log-analyzer
|
||||||
|
namespace: team-alpha
|
||||||
@@ -619,6 +619,11 @@ spec:
|
|||||||
EOF
|
EOF
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
COMANDO - applica alert
|
COMANDO - applica alert
|
||||||
```bash
|
```bash
|
||||||
kubectl apply -f blackbox-http-alerts.yaml
|
kubectl apply -f blackbox-http-alerts.yaml
|
||||||
@@ -631,8 +636,119 @@ kubectl describe prometheusrule blackbox-http-alerts -n monitoring
|
|||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
10. TEST MANUALE BLACKBOX EXPORTER
|
10. CONFIGURA ALERTMANAGER - INVIO EMAIL SU FAIL DI UN SERVIZIO
|
||||||
=================================
|
================================================================
|
||||||
|
|
||||||
|
Obiettivo:
|
||||||
|
- inviare una email a un indirizzo specifico quando la probe di un
|
||||||
|
servizio specifico (serviceX) fallisce (alert BlackboxHttpProbeFailed).
|
||||||
|
|
||||||
|
FILE - blackbox-email-alert.yaml
|
||||||
|
|
||||||
|
Descrizione:
|
||||||
|
- crea un receiver email dedicato al servizio da monitorare;
|
||||||
|
- instrada verso quel receiver solo gli alert che riguardano il
|
||||||
|
target specifico, identificato tramite il label instance.
|
||||||
|
|
||||||
|
NOTA - credenziali SMTP
|
||||||
|
Se il server SMTP richiede autenticazione, crea prima un Secret con
|
||||||
|
la password:
|
||||||
|
|
||||||
|
COMANDO - crea secret con password SMTP
|
||||||
|
```bash
|
||||||
|
kubectl create secret generic alertmanager-smtp \
|
||||||
|
-n monitoring --from-literal=password='<SMTP_PASSWORD>'
|
||||||
|
```
|
||||||
|
|
||||||
|
COMANDO - crea blackbox-email-alert.yaml
|
||||||
|
```bash
|
||||||
|
cat > blackbox-email-alert.yaml <<'EOF'
|
||||||
|
apiVersion: monitoring.coreos.com/v1alpha1
|
||||||
|
kind: AlertmanagerConfig
|
||||||
|
metadata:
|
||||||
|
name: blackbox-email-routing
|
||||||
|
namespace: monitoring
|
||||||
|
labels:
|
||||||
|
release: kube-prometheus-stack
|
||||||
|
spec:
|
||||||
|
route:
|
||||||
|
groupBy: ["alertname", "instance"]
|
||||||
|
groupWait: 30s
|
||||||
|
groupInterval: 5m
|
||||||
|
repeatInterval: 1h
|
||||||
|
receiver: "email-default"
|
||||||
|
routes:
|
||||||
|
- matchers:
|
||||||
|
- name: alertname
|
||||||
|
value: BlackboxHttpProbeFailed
|
||||||
|
matchType: "="
|
||||||
|
- name: instance
|
||||||
|
value: "<SERVIZIO_X_URL_O_HOST>"
|
||||||
|
matchType: "="
|
||||||
|
receiver: "email-servizioX"
|
||||||
|
|
||||||
|
receivers:
|
||||||
|
- name: "email-default"
|
||||||
|
emailConfigs: []
|
||||||
|
|
||||||
|
- name: "email-servizioX"
|
||||||
|
emailConfigs:
|
||||||
|
- to: "<INDIRIZZO_X>"
|
||||||
|
from: "<SMTP_FROM>"
|
||||||
|
smarthost: "<SMTP_HOST>:<SMTP_PORT>"
|
||||||
|
authUsername: "<SMTP_USER>"
|
||||||
|
authPassword:
|
||||||
|
name: alertmanager-smtp
|
||||||
|
key: password
|
||||||
|
requireTLS: true
|
||||||
|
sendResolved: true
|
||||||
|
headers:
|
||||||
|
subject: "[ALERT] Servizio X non raggiungibile"
|
||||||
|
html: |
|
||||||
|
<p>Il servizio <b>{{ "{{" }} .CommonLabels.instance {{ "}}" }}</b> non risponde.</p>
|
||||||
|
<p>{{ "{{" }} .CommonAnnotations.description {{ "}}" }}</p>
|
||||||
|
EOF
|
||||||
|
```
|
||||||
|
|
||||||
|
Da personalizzare:
|
||||||
|
- <SERVIZIO_X_URL_O_HOST>: valore del label instance della probe da
|
||||||
|
monitorare (es. http://my-service.my-namespace.svc.cluster.local:8080/health);
|
||||||
|
- <INDIRIZZO_X>: indirizzo email destinatario;
|
||||||
|
- <SMTP_HOST>, <SMTP_PORT>: server SMTP (es. smtp.gmail.com:587);
|
||||||
|
- <SMTP_FROM>: mittente email;
|
||||||
|
- <SMTP_USER>: utente SMTP, se richiesta autenticazione.
|
||||||
|
|
||||||
|
COMANDO - applica la configurazione
|
||||||
|
```bash
|
||||||
|
kubectl apply -f blackbox-email-alert.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
COMANDO - verifica AlertmanagerConfig
|
||||||
|
```bash
|
||||||
|
kubectl get alertmanagerconfig -n monitoring
|
||||||
|
kubectl describe alertmanagerconfig blackbox-email-routing -n monitoring
|
||||||
|
```
|
||||||
|
|
||||||
|
NOTA - matcher su instance vs job
|
||||||
|
Se vuoi far scattare l'email per TUTTI i target di una Probe (job)
|
||||||
|
invece che per un singolo servizio, sostituisci il matcher su
|
||||||
|
`instance` con:
|
||||||
|
```yaml
|
||||||
|
- name: job
|
||||||
|
value: "http-services-probe"
|
||||||
|
matchType: "="
|
||||||
|
```
|
||||||
|
|
||||||
|
COMANDO - verifica alert in Alertmanager
|
||||||
|
```bash
|
||||||
|
kubectl port-forward -n monitoring svc/kube-prometheus-stack-alertmanager 9093
|
||||||
|
# -> http://localhost:9093, controlla che l'alert BlackboxHttpProbeFailed
|
||||||
|
# per il servizio X sia instradato sul receiver email-servizioX
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
11. TEST MANUALE BLACKBOX EXPORTER
|
||||||
|
==================================
|
||||||
|
|
||||||
COMANDO - port-forward blackbox-exporter
|
COMANDO - port-forward blackbox-exporter
|
||||||
```bash
|
```bash
|
||||||
@@ -651,7 +767,7 @@ probe_http_status_code 200
|
|||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
11. TROUBLESHOOTING
|
12. TROUBLESHOOTING
|
||||||
===================
|
===================
|
||||||
|
|
||||||
CASO - Prometheus non vede la Probe
|
CASO - Prometheus non vede la Probe
|
||||||
@@ -700,7 +816,7 @@ Azioni consigliate:
|
|||||||
- aggiungere un modulo dedicato in blackbox-values.yaml se serve una configurazione HTTP specifica.
|
- aggiungere un modulo dedicato in blackbox-values.yaml se serve una configurazione HTTP specifica.
|
||||||
|
|
||||||
|
|
||||||
12. ORDINE DI ESECUZIONE CONSIGLIATO
|
13. ORDINE DI ESECUZIONE CONSIGLIATO
|
||||||
====================================
|
====================================
|
||||||
|
|
||||||
COMANDO - sequenza completa
|
COMANDO - sequenza completa
|
||||||
@@ -727,7 +843,7 @@ blackbox-http-alerts.yaml
|
|||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
13. NOTE PER DEV, QA E PROD
|
14. NOTE PER DEV, QA E PROD
|
||||||
===========================
|
===========================
|
||||||
|
|
||||||
Per separare gli ambienti e semplificare dashboard e alert, usa Probe distinte:
|
Per separare gli ambienti e semplificare dashboard e alert, usa Probe distinte:
|
||||||
|
|||||||
@@ -0,0 +1,75 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Aggiunge un hostname a spec.template.spec.hostAliases del Deployment blackbox.
|
||||||
|
#
|
||||||
|
# Uso:
|
||||||
|
# ./add-hostalias.sh <hostname> <deployment_name> <deployment_namespace>
|
||||||
|
#
|
||||||
|
# Esempio:
|
||||||
|
# ./add-hostalias.sh idcidcp.pigreco66.it cert-manager cert-manager
|
||||||
|
#
|
||||||
|
|
||||||
|
DEPLOYMENT_NAME="${2:-}"
|
||||||
|
DEPLOYMENT_NS="${3:-}"
|
||||||
|
TARGET_IP="10.43.37.118"
|
||||||
|
HOSTNAME_VAL="${1:-}"
|
||||||
|
|
||||||
|
if [[ -z "$HOSTNAME_VAL" ]]; then
|
||||||
|
echo "Uso: $0 <hostname>" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! command -v kubectl >/dev/null 2>&1; then
|
||||||
|
echo "Errore: kubectl non trovato nel PATH" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! command -v jq >/dev/null 2>&1; then
|
||||||
|
echo "Errore: jq non trovato nel PATH" >&2
|
||||||
|
echo "Installa jq e riprova." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Idempotenza: controlla solo il blocco hostAliases associato a TARGET_IP.
|
||||||
|
EXISTING_HOSTNAMES="$(kubectl get deployment "$DEPLOYMENT_NAME" -n "$DEPLOYMENT_NS" -o jsonpath="{.spec.template.spec.hostAliases[?(@.ip=='${TARGET_IP}')].hostnames[*]}" 2>/dev/null || true)"
|
||||||
|
if echo " $EXISTING_HOSTNAMES " | grep -Fq " $HOSTNAME_VAL "; then
|
||||||
|
echo "Hostname '$HOSTNAME_VAL' gia presente per IP ${TARGET_IP} in ${DEPLOYMENT_NS}/${DEPLOYMENT_NAME}. Nessuna modifica."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
DEPLOY_JSON="$(kubectl get deployment "$DEPLOYMENT_NAME" -n "$DEPLOYMENT_NS" -o json)"
|
||||||
|
|
||||||
|
UPDATED_HOST_ALIASES="$({
|
||||||
|
echo "$DEPLOY_JSON" | jq -c --arg ip "$TARGET_IP" --arg hostname "$HOSTNAME_VAL" '
|
||||||
|
(.spec.template.spec.hostAliases //= [])
|
||||||
|
| if any(.spec.template.spec.hostAliases[]?; .ip == $ip) then
|
||||||
|
.spec.template.spec.hostAliases |= map(
|
||||||
|
if .ip == $ip then
|
||||||
|
if ((.hostnames // []) | index($hostname)) then
|
||||||
|
.
|
||||||
|
else
|
||||||
|
.hostnames = ((.hostnames // []) + [$hostname])
|
||||||
|
end
|
||||||
|
else
|
||||||
|
.
|
||||||
|
end
|
||||||
|
)
|
||||||
|
else
|
||||||
|
.spec.template.spec.hostAliases += [{"ip": $ip, "hostnames": [$hostname]}]
|
||||||
|
end
|
||||||
|
| .spec.template.spec.hostAliases
|
||||||
|
'
|
||||||
|
} )"
|
||||||
|
|
||||||
|
PATCH_PAYLOAD="$(jq -cn --argjson hostAliases "$UPDATED_HOST_ALIASES" '{spec:{template:{spec:{hostAliases:$hostAliases}}}}')"
|
||||||
|
|
||||||
|
kubectl patch deployment "$DEPLOYMENT_NAME" \
|
||||||
|
-n "$DEPLOYMENT_NS" \
|
||||||
|
--type=merge \
|
||||||
|
-p "$PATCH_PAYLOAD" >/dev/null
|
||||||
|
|
||||||
|
echo "Hostname aggiunto con successo."
|
||||||
|
echo " Deployment: ${DEPLOYMENT_NS}/${DEPLOYMENT_NAME}"
|
||||||
|
echo " IP : ${TARGET_IP}"
|
||||||
|
echo " Hostname : ${HOSTNAME_VAL}"
|
||||||
@@ -45,11 +45,13 @@ fi
|
|||||||
|
|
||||||
# Se l'hostname non e nel dominio *.italiadatacenter.com, aggiungilo anche a cert-manager hostAliases.
|
# Se l'hostname non e nel dominio *.italiadatacenter.com, aggiungilo anche a cert-manager hostAliases.
|
||||||
if [[ "$host_no_port" != *.italiadatacenter.com ]]; then
|
if [[ "$host_no_port" != *.italiadatacenter.com ]]; then
|
||||||
HOSTALIAS_SCRIPT="/root/work/pipeline/add-cert-manager-hostalias.sh"
|
HOSTALIAS_SCRIPT="/root/work/pipeline/add-hostalias.sh"
|
||||||
if [[ -x "$HOSTALIAS_SCRIPT" ]]; then
|
if [[ -x "$HOSTALIAS_SCRIPT" ]]; then
|
||||||
"$HOSTALIAS_SCRIPT" "$host_no_port"
|
"$HOSTALIAS_SCRIPT" "$host_no_port" "cert-manager" "cert-manager"
|
||||||
|
"$HOSTALIAS_SCRIPT" "$host_no_port" "blackbox-exporter" "monitoring"
|
||||||
elif [[ -f "$HOSTALIAS_SCRIPT" ]]; then
|
elif [[ -f "$HOSTALIAS_SCRIPT" ]]; then
|
||||||
bash "$HOSTALIAS_SCRIPT" "$host_no_port"
|
bash "$HOSTALIAS_SCRIPT" "$host_no_port" "cert-manager" "cert-manager"
|
||||||
|
bash "$HOSTALIAS_SCRIPT" "$host_no_port" "blackbox-exporter" "monitoring"
|
||||||
else
|
else
|
||||||
echo "Errore: script non trovato: $HOSTALIAS_SCRIPT" >&2
|
echo "Errore: script non trovato: $HOSTALIAS_SCRIPT" >&2
|
||||||
exit 1
|
exit 1
|
||||||
|
|||||||
Reference in New Issue
Block a user