Bootstrap
El nivel 0 instala Flux y lo que todos los demás niveles necesitan. Es el único punto con pasos manuales.
Requisitos
brew install helm kubectl fluxcd/tap/flux sops age
Acceso de administrador al clúster (el kubeconfig que entrega el stack de Kubernetes) y una CNI funcionando. El stack ya deja Calico instalado.
Flux Operator
Flux se instala con el Flux Operator: el operador es un Helm release, y Flux se describe con un recurso FluxInstance que el operador convierte en los controladores de Flux y mantiene actualizado.
helm install flux-operator oci://ghcr.io/controlplaneio-fluxcd/charts/flux-operator \
--version 0.61.0 \
--namespace flux-system --create-namespace \
--wait
helm list -n flux-system # flux-operator, deployed
kubectl -n flux-system get pods # flux-operator-... 1/1 Running
Una vez conectado, FluxCD adopta este mismo Helm release (mismo nombre y namespace) y lo actualiza desde el repositorio como cualquier otro componente.
Secrets con SOPS
Los secrets se guardan en el repositorio cifrados con SOPS y una clave age por entorno. Flux los descifra dentro del clúster.
El repositorio es público. Subir un fichero sin cifrar no tiene fácil solución: Git lo recordará para siempre.
Generar la clave del entorno y guardarla en el clúster (la clave del secret debe terminar en .agekey):
age-keygen -o testing.agekey
# Public key: age1...
kubectl -n flux-system create secret generic sops-age \
--from-file=age.agekey=testing.agekey
La clave privada solo debe existir en el clúster y en un almacén seguro. Para editar secrets desde el equipo, se añade también donde la busca SOPS:
mkdir -p "$HOME/Library/Application Support/sops/age"
cat testing.agekey >> "$HOME/Library/Application Support/sops/age/keys.txt"
rm testing.agekey
La clave pública va en .sops.yaml, en la regla de su entorno. Con ella, sops elige la clave según la ruta del fichero y cifra únicamente data y stringData:
creation_rules:
- path_regex: ^(clusters|infrastructure|apps)/testing/.*\.yaml$
encrypted_regex: ^(data|stringData)$
age: age1...
Trabajar con secrets:
sops <fichero> # crear o editar; el texto plano nunca toca el disco
sops -e -i <fichero> # cifrar un fichero existente
sops -d <fichero> # leerlo
Un fichero está listo para subir cuando sus valores empiezan por ENC[AES256_GCM, y termina con un bloque sops:.
Notificaciones en Slack
Flux informa en Slack de lo que cambia y lo que falla: recursos creados o modificados, instalaciones y actualizaciones de Helm, actualizaciones del propio Flux y cualquier error. Los eventos rutinarios se descartan.
En la app de Slack, en Incoming Webhooks, crear un webhook para el canal del entorno y guardarlo cifrado:
sops infrastructure/testing/00-bootstrap/configs/slack-token.yaml
apiVersion: v1
kind: Secret
metadata:
name: slack-token
namespace: flux-system
stringData:
address: https://hooks.slack.com/services/...
La URL del webhook es una credencial: cualquiera que la tenga puede escribir en el canal.
Conectar el clúster
Toda la conexión es un fichero, clusters/<entorno>/flux-instance.yaml. Define la versión de Flux, sus controladores y, en el bloque sync, qué repositorio, rama y carpeta sigue el clúster:
apiVersion: fluxcd.controlplane.io/v1
kind: FluxInstance
metadata:
name: flux
namespace: flux-system
spec:
distribution:
version: "2.9.x"
registry: ghcr.io/fluxcd
components:
- source-controller
- kustomize-controller
- helm-controller
- notification-controller
cluster:
type: kubernetes
networkPolicy: true
sync:
kind: GitRepository
url: https://gitlab.com/reiizumi/fluxcd-thor-network.git
ref: refs/heads/main
path: clusters/testing
interval: 168h
Se aplica una única vez a mano. Es el momento en el que el clúster queda ligado al repositorio:
kubectl apply -f clusters/testing/flux-instance.yaml
kubectl -n flux-system wait fluxinstance/flux --for=condition=Ready --timeout=5m
El operador despliega los controladores de Flux y crea un GitRepository y una Kustomization que aplican todo lo que hay en la ruta. Como el propio flux-instance.yaml está en esa ruta, a partir de aquí Flux lee su propia definición de Git: cambiar Flux es un commit, no un comando.
Flux solo necesita acceso de lectura. El repositorio es público, así que se clona de forma anónima por HTTPS: no hay token que crear, guardar ni rotar, ni nada que configurar en GitLab. Si el repositorio pasara a ser privado, bastaría con un deploy token con el scope read_repository referenciado como pullSecret en el bloque sync.
Validar:
kubectl -n flux-system get fluxinstance # flux True Reconciliation finished
flux check # all checks passed
flux get sources git -n flux-system # main@sha1:<último commit>
flux get kustomizations -n flux-system # Applied revision: main@sha1:<último commit>
Flux revisa el repositorio cada 7 días. Para aplicar un cambio al momento:
flux reconcile kustomization flux-system --with-source
Actualizaciones
- Flux: los parches de
2.9.xlos aplica el operador automáticamente. Una versión menor es un cambio enspec.distribution.versiondelflux-instance.yaml. - Flux Operator: los parches de
0.61.xson automáticos. Una versión menor es un cambio en surepository.yaml.
Rotaci ón
- Webhook: crear uno nuevo en Slack, sustituir
addressconsops, subir y borrar el antiguo. - Clave age: generar una nueva, cambiar la pública en
.sops.yaml, ejecutarsops updatekeysen cada secret del entorno, subir y sustituir el secretsops-age. Lo cifrado antes sigue legible con la clave antigua en el historial, así que, si una clave se compromete, hay que rotar también las credenciales.