Servicios
Organización
Lo ideal sería desplegar la infraestructura en un orden lógico y después los servicios normales, pero esto no es realista debido a las dependencias cruzadas. Así que toca usar un orden más aceptable y no tan lógico.
Normalmente querremos monitorizar el sistema desde el inicio, pero Grafana requiere de Ingress y Prometheus, Ingress requiere MetalLB, Prometheus requiere Longhorn, el cual requiere de Ingress. 🤯
Aprovechando el sistema de dependencias de FluxCD, he dividido los servicios de infraestructura en diferentes niveles. Cuando uno termina de desplegar, empieza el siguiente. Al terminar, despliega las aplicaciones propias:
- level1: Internal networking (MetalLB, CNPG Operator, Email Relay)
- level2: External networking (Ingress, Cert-Manager)
- level3: Volumes (Longhorn) y FluxCD UI (Weave GitOps)
- level4: Monitoring (Prometheus, Grafana, Grafana Loki)
- level5: Identity Provider (Keycloak)
- apps: Thor services: DocuMoon, Toranku, Kirin y Shizen
Sora está diseñado para unificar y desplegar las bases de datos en PostgreSQL. Esto permite tener auto-escalado (réplicas son de solo lectura y pueden cambiar su rol a máster si este se cae), reducir la carga de peticiones DNS, unificar procesos de copias de seguridad y disponer de una base de datos propia para cada servicio. Para ello, CNPG es ideal.
Ideal, porque las copias de seguridad explotan continuamente, no tienes notificaciones "de per se", el volumen de WAL se sobrecarga de serie (requiere ciertos ajustes y aun así 🔥) lanzando el PostgreSQL a la basura, como WAL es un volumen, a Longhorn no le gusta y explota, los nodos se caen por sobrecarga, a Longhorn también le toca la moral si le tocas los nodos. y una larga lista de motivos por los que es MALA idea añadir la base de datos dentro del clúster. ¿He dicho ya que el Helm oficial es Alpha y cada cambio MENOR añade más bugs que el anterior y además es incompatible?
Tras muchos intentos, Sora tiene esto disponible, pero se desvía hacia la base de datos externa. Quizás algún día lo vuelva a intentar.
Estructura de carpetas
Siguiendo el MonoRepo, el repositorio se organiza con 3 carpetas raíz:
- clusters: Cada entorno tiene su carpeta que hace referencia al resto. Simplemente dispone de los
yaml
básicos para llamar a sus carpetas correspondientes. - infrastructure: Dispone de los datos para todos los niveles y se encarga de desplegar los servicios de plataforma.
- apps: Tras desplegar la plataforma, se despliegan los servicios configurados en esta carpeta.
FluxCD se gestiona mediante IaC hacia un repositorio de Git. Mi repositorio original puede ser utilizado de base para construir uno propio, ajustando todo aquello que se requiera para cada red.
Clusters
FluxCD revisa periódicamente la información en una carpeta especifica de un repositorio Git, es por ello que cada entorno tiene su propia carpeta, donde guardará sus datos básicos, y también donde definimos la información de qué carpetas debe leer y el orden para las dependencias.
La configuración apunta a una carpeta donde tendremos nuestros yaml
. En esta, FluxCD construye la carpeta flux-system
con sus datos.
Desplegar un entorno nuevo significa copiar la carpeta de otro entorno y ajustar los path
que apuntan al resto de carpetas.
Prácticamente todos los ficheros en esta carpeta son iguales, así que me centraré a explicar uno de ellos:
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: infra-level2-controllers
namespace: flux-system
spec:
dependsOn:
- name: infra-level1-configs
interval: 24h
retryInterval: 5m
timeout: 5m
sourceRef:
kind: GitRepository
name: flux-system
path: ./infrastructure/production/level2/controllers
prune: true
wait: true
decryption:
provider: sops
secretRef:
name: sops-age
---
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: infra-level2-configs
namespace: flux-system
spec:
dependsOn:
- name: infra-level2-controllers
interval: 24h
retryInterval: 5m
timeout: 5m
sourceRef:
kind: GitRepository
name: flux-system
path: ./infrastructure/production/level2/configs
prune: true
wait: true
decryption:
provider: sops
secretRef:
name: sops-age
Como veremos, cada carpeta de nivel de infraestructura dispone de 2 carpetas: controllers
y configs
.
Este fichero asocia las dependencias para que configs
espere a su controllers
, mientras esta espera al configs
del nivel anterior.
A parte de esto, espera 24h antes de volver a revisar si hay cambios, intenta aplicar los cambios en 5 minutos, destruye los servicios en caso de que este fichero se elimine y se utiliza SOPS con Age para cualquier fichero encriptado.
La parte más importante es el path
que indica dónde está la información que será utilizada para su entorno y uso.
Infraestructure
Comparte con apps
las carpetas raíz:
- base: Tiene la información principal para desplegar los servicios.
- testing o production: Cada entorno dispone de los datos para apuntar a su
base
, añadiendo sobrescritura según el entorno.
Tanto el base
como la carpeta de cada entorno tienen una carpeta para cada nivel, dentro otras para controllers
y configs
, tal como se ha visto en la sección anterior.
controllers
define los datos para desplegar el servicio, mientras configs
añaden información específica para configurar un servicio que solo puede ser configurado tras confirmar que se ha desplegado. No todos los niveles tienen configuración añadida.
Algunos servicios despliegan CRDs que deben ser configurados posteriormente, configs
suele encargarse de ello.
A su vez, el base/controllers
tiene una carpeta para cada servicio. Los de entorno simplemente apuntan a la carpeta principal.
Estos serán explicados dentro de cada sección.
Apps
Similar al anterior, cada servicio tiene su propia carpeta, y serán explicados en sus secciones.