Skip to main content

Plataforma

Els serveis de plataforma que FluxCD desplega abans de qualsevol aplicació, nivell a nivell.

Nivell 1: xarxa​

Calico​

La CNI del clúster. Flux no la pot instal·lar (sense CNI no arrenca cap pod, ni tan sols els de Flux), així que la instal·la l'stack de Kubernetes en construir el clúster, i Flux adopta aquell Helm release.

Charttigera-operator, release calico a tigera-operator
Xarxa de pods172.16.0.0/16, IP-in-IP
Valorsinfrastructure/base/10-networking/controllers/calico/values.yaml

El HelmRelease té el mateix nom i namespace que la instal·lació inicial, de manera que Flux l'actualitza en lloc d'instal·lar-ne un de nou. A més, eliminar-lo de Git no desinstal·la Calico i Flux no és mai propietari del seu namespace.

perill

Calico no té rollback automàtic: tornar enrere la xarxa del clúster és una decisió manual. Si una actualització trenca la xarxa, Flux cau amb ella. L'API funciona a la xarxa del host, així que des d'un equip amb accés:

helm rollback calico -n tigera-operator
flux suspend helmrelease calico -n tigera-operator

Una versió menor nova requereix aplicar abans les seves CRDs a mà i comprovar que suporta la versió de Kubernetes del clúster.

MetalLB​

Sense balancejador del núvol, MetalLB dona als serveis LoadBalancer una adreça de la LAN i l'anuncia per ARP. Cada entorn té dos pools:

Entorningress (a mà)default (automàtic)
testing192.168.1.170 – .171192.168.1.172 – .179
production192.168.1.180 – .181192.168.1.182 – .189

Les dues adreces d'ingress estan reservades per a Traefik (intranet i extranet). Qualsevol altre servei rep la següent lliure de default.

warning

Aquests rangs han de quedar fora del DHCP, i dos clústers no han d'anunciar mai el mateix rang alhora.

Reloader​

Un pod llegeix els seus Secrets i ConfigMaps en arrencar. Reloader reinicia els workloads quan canvien, de manera que una contrasenya rotada a Git arriba a l'aplicació sense passos manuals. Només actua sobre els workloads que ho demanen:

metadata:
annotations:
reloader.stakater.com/auto: "true"

Metrics Server​

Recull l'ús actual de CPU i memòria de nodes i pods; és el que llegeix kubectl top. Fa servir --kubelet-insecure-tls perquè els kubelets fan servir els certificats autosignats de kubeadm. L'històric viu a la monitorització externa.

Nivell 2: ingress​

cert-manager​

Demana els certificats a Let's Encrypt, els desa com a Secrets i els renova 30 dies abans que caduquin. Un Ingress ho demana amb una anotació.

ClusterIssuerRepteÚs
letsencrypt-dnsDNS-01 amb l'API de CloudflareQualsevol nom, accessible des d'Internet o no
letsencrypt-httpHTTP-01 a través del Traefik extranetNoms publicats a Internet
letsencrypt-staging-dnsDNS-01 contra l'entorn de provesProvar la configuració sense gastar el límit de Let's Encrypt

A testing tot fa servir letsencrypt-dns. El token de Cloudflare (permís Zone › DNS › Edit) es desa xifrat:

sops infrastructure/testing/20-ingress/configs/cloudflare-api-token-secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: cloudflare-api-token-secret
namespace: cert-manager-system
stringData:
api-token: <token>

Traefik​

L'ingress controller. Hi ha dues instàncies separades, de manera que un servei pensat per a la LAN no es pugui publicar a Internet per error:

InstànciaIngressClassAccessible des detesting
traefik-intranetintranetLa LAN192.168.1.170
traefik-extranetextranetInternet, a través de Cloudflare (a producció)192.168.1.171

Totes dues tenen dues rèpliques en nodes diferents, redirigeixen HTTP a HTTPS, conserven la IP real del client i no tenen classe per defecte: un Ingress sense classe no el serveix cap. A testing cap no està publicada; les dues classes existeixen per replicar producció.

Publicar un servei:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app
annotations:
cert-manager.io/cluster-issuer: letsencrypt-dns
spec:
ingressClassName: intranet # o extranet
tls:
- hosts: [app.test.intranet.moon.cat]
secretName: app-tls
rules:
- host: app.test.intranet.moon.cat
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: app
port:
number: 80

El registre DNS del nom ha d'apuntar a l'adreça de la instància escollida. A Sora, es crea com a àlies a la xarxa d'Horizon.

Observabilitat​

Dins del clúster no es guarda res. Un únic col·lector, Grafana Alloy, recull mètriques, logs i traces i els envia a la màquina de monitorització. Tot porta l'etiqueta cluster (tanya a testing).

SenyalOrigenCom se selecciona
Mètriqueskubelet, cAdvisor, kube-state-metricsSempre
MètriquesWorkloads que les exposenAnotació k8s.grafana.com/scrape: "true"
LogsPodsEtiqueta monitoring/logs: "true"
Logskubelet.service i crio.service de cada nodeSempre
Logs, traces i mètriquesAplicacions amb OpenTelemetryEl que enviïn

Les mètriques de CPU, memòria i disc de cada node no es recullen aquí: les publica el Node Exporter de cada VM, que continua informant encara que Kubernetes estigui caigut.

Les aplicacions envien OTLP per HTTP al receptor del clúster, sense credencials:

OTEL_EXPORTER_OTLP_ENDPOINT=http://k8s-monitoring-alloy-receiver.monitoring-system.svc:4318
OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf
tip

Una aplicació amb SDK d'OpenTelemetry envia els seus logs per OpenTelemetry i no porta l'etiqueta monitoring/logs; amb totes dues, cada línia es guarda dues vegades. L'etiqueta és per al que no té OpenTelemetry (Traefik, cert-manager, Keycloak, ...).

Les credencials d'enviament són les sortides del treball traefik de l'stack de monitorització, desades xifrades:

sops infrastructure/testing/30-observability/configs/monitoring-ingest.yaml
apiVersion: v1
kind: Secret
metadata:
name: monitoring-ingest
namespace: monitoring-system
stringData:
username: <usuari d'ingesta>
password: <contrasenya d'ingesta>

Per comprovar què arriba, a Grafana › Explore: up{cluster="tanya"} == 0 a Prometheus (targets caiguts) o {cluster="tanya", namespace="traefik-system"} a Loki.

Keycloak​

El proveïdor d'identitat: les aplicacions hi deleguen el login mitjançant OpenID Connect. S'instal·la amb el Keycloak Operator oficial, seguint els tags del seu repositori.

testing
Hostnameauth.test.lb.moon.cat
Ingressextranet, certificat de letsencrypt-dns
Base de dadeskeycloak a mio-akiyama.horizon.moon.cat:6432 (PgBouncer)

FluxCD gestiona l'operador, el servidor, la seva base de dades, el seu nom i el seu ingress. El que hi ha dins (realms, clients, usuaris, ...) ho configura Horizon. La base de dades comença buida i Keycloak crea les seves taules en arrencar; es crea abans amb l'acció Create User de l'stack de PostgreSQL, i les seves credencials es desen xifrades:

sops infrastructure/testing/40-identity/configs/keycloak-pg-auth.yaml
apiVersion: v1
kind: Secret
metadata:
name: keycloak-pg-auth
namespace: keycloak-system
stringData:
username: keycloak
password: <contrasenya>

A la primera arrencada, l'operador crea un administrador temporal al secret keycloak-initial-admin, que és el que es fa servir per connectar Horizon.

Tema moon​

La pàgina de login fa servir el tema moon, desat al repositori i muntat sobre la imatge oficial: sense imatge pròpia ni volums. Mostra una imatge de fons al costat de la targeta de login, s'adapta a PC, tauleta i mòbil, segueix el mode clar o fosc del navegador i, a testing, afegeix una cinta TESTING ENVIRONMENT. Només estén el tema de Keycloak, sense sobreescriure plantilles, perquè les seves actualitzacions continuïn funcionant. Cada realm l'escull com a tema de login des d'Horizon.

Validar:

kubectl -n keycloak-system get pods # keycloak-operator-…, keycloak-0 Running
curl -s https://auth.test.lb.moon.cat/realms/master/.well-known/openid-configuration | jq -r .issuer
# https://auth.test.lb.moon.cat/realms/master

L'issuer ha de ser exactament el nom públic per https. Qualsevol altra cosa vol dir que el hostname o les capçaleres del proxy són incorrectes, i els logins fallaran.