Skip to content

Instantly share code, notes, and snippets.

@juanjmerono
Last active January 20, 2021 19:09
Show Gist options
  • Save juanjmerono/9819e8754eb1cfc87f8c9ec571410b46 to your computer and use it in GitHub Desktop.
Save juanjmerono/9819e8754eb1cfc87f8c9ec571410b46 to your computer and use it in GitHub Desktop.
InstallFlux

PRIMEROS PASOS

https://toolkit.fluxcd.io/get-started/

1. Descarga el cliente flux y kubectl si no lo tienes...

https://kubernetes.io/es/docs/tasks/tools/install-kubectl/

https://github.com/fluxcd/flux2/releases

Instala ambos ejecutables en el path.

Sugerencia: Si tienes un cliente git mejor, porque modificar el repositorio desde el WebIDE es más pesado, para cambiar dos líneas si, para meter ficheros y carpetas enteras se puede hacer pero trabajo de chinos.

https://git-scm.com/downloads

2. Configura la conexión con el cluster

Accede a rancher y descarga el kubeconfig del cluster correspondiente y guardalo en ~/.kube/config.desa Esto genera un token en tu usuario (mira API & Keys)

2.1. Comprueba que todo funciona

$ kubectl --kubeconfig ~/.kube/config.desa get nodes
$ kubectl --kubeconfig ~/.kube/config.desa cluster-info

2.2. Puedes verificar que el cluster cumple los requisitos para funcionar con flux

$ flux --kubeconfig ~/.kube/config.desa check --pre

Ahora puedes renombrar config.desa como config para que por defecto TODO se ejecute en el cluster de desa.

$ kubectl get nodes
$ kubectl cluster-info

3. Ahora vamos a instalar flux en el cluster

Se va a crear los operadores y crd's necesarios de flux en el cluster al tiempo que se almacena lo creado en un repositorio de gitlab, por lo que vas a necesitar un token para acceder a gitlab con permisos para crear repositorios. Debes marcar todos los permisos al menos api, read/write repository y read registry.

$ export GITLAB_TOKEN=xxxxxx

Y ahora al lío...

$ flux bootstrap gitlab \
    --components-extra=image-reflector-controller,image-automation-controller \
    --hostname=gitlab.um.es \
    --owner=sistemas \
    --branch=master \
    --repository=flux-k8s-infra \
    --path=clusters/desarrollo \
    --token-auth

Si todo funciona ya está listo, a partir de ahora cualquier modificación de la configuración de flux la puedes hacer cambiando ficheros en el repositorio.

4. Clona el repositorio o accede desde el WebIDE de Gitlab

$ git clone https://gitlab.um.es/sistemas/flux-k8s-infra

Fin de la instalación

5. Incluir otro cluster

  • Repite el paso 2 para descargar el kubeconfig de rancher que corresponda al nuevo cluster destino.
  • Sustituye un config por otro para que por defecto kubectl y flux ataquen al nuevo cluster.
  • Asegúrate de tener la variable de entorno GITLAB_TOKEN para poder conectarte al repositorio.
  • Añade el nuevo cluster al repositorio existente.
$ flux bootstrap gitlab \
    --components-extra=image-reflector-controller,image-automation-controller \
    --hostname=gitlab.um.es \
    --owner=sistemas \
    --branch=master \
    --repository=flux-k8s-infra \
    --path=clusters/produccion

Si todo funciona ya está listo, a partir de ahora cualquier modificación de la configuración de flux para el nuevo cluster la puedes hacer cambiando ficheros en el repositorio.

INVESTIGA

Puedes ejecutar algunos comandos que te ayudarán a ver lo que ha pasado.

$ flux get sources git (Ves flux-system apuntando a la rama máster de tu repo)
$ flux get ks (Ves flux-system apuntando a la rama máster de tu repo)
$ kubectl -n flux-system get pods (Ves los controllers de flux, source, helm, kustomize, notification y dos de image)
$ flux export sources git flux-system (Muestra el yaml asociado para copiarlo a otro repo por ejemplo)
$ flux suspend kustomization flux-system (Suspende la sincronización del propio flux)
$ flux resume kustomization flux-system (Reactiva la sincronización del propio flux)

SIGUIENTES PASOS

Hasta ahora lo que hemos instalado es ÚNICAMENTE FLUX, ahora habría que añadirle los sources de los desarrollos que queramos instalar. Todos los objetos creados en el namespace flux-system tienen su réplica en los yaml del repositorio, salvo el secret flux-system que se ha creado a partir de nuestro GITLAB_TOKEN y que le sirve a FLUX para estar al tanto de actualizaciones en el repositorio que deba ejecutar en el cluster.

1. Monitorización (OPCIONAL)

Este paso es opcional, se trata de componentes de monitorización del trabajo y performance del propio flux.

https://toolkit.fluxcd.io/guides/monitoring/

$ flux create source git monitoring \
    --interval=30m \
    --url=https://github.com/fluxcd/flux2 \
    --branch=main \
    --export > ./clusters/desarrollo/flux-system/gotk-monitoring.yaml
$ echo --- >> ./clusters/desarrollo/flux-system/gotk-monitoring.yaml
$ flux create kustomization monitoring \
    --interval=1h \
    --prune=true \
    --source=monitoring \
    --path="./manifests/monitoring" \
    --health-check="Deployment/prometheus.flux-system" \
    --health-check="Deployment/grafana.flux-system" \
    --export >> ./clusters/desarrollo/flux-system/gotk-monitoring.yaml

Ambos comandos escupen (--export) por consola los YAML adecuados para configurar el Git Repository y la Kustomization que provocará que flux los despliegue. Guarda la salida de ambos comandos en un fichero y añádelo al repositorio. Haz commit y push para que flux lo despliegue.

Una vez instalado puedes acceder a grafana haciendo port-forward ya que NO SE INSTALA INGRESS.

$ kubectl -n flux-system port-forward svc/grafana 3000:3000

2. Cifrado de secretos

Por defecto no se cifran los secretos por lo que NO se pueden incluir en el repositorio ya que el cifrado que usa K8s es Base64, completamente inseguro. Para cifrarlos se puede usar Sealed Secrets con sifrado asimétrico.

https://toolkit.fluxcd.io/guides/sealed-secrets/

https://github.com/bitnami-labs/sealed-secrets/releases

Debes instalar otro cliente de consola para poder cifrar los secretos e incluirlos en el repositorio cuando sea necesario.

Ahora obtén los yaml necesarios para desplegar el controller de Sealed Secrets, guárdalo en un fichero y añádelo al repositorio.

$ flux create source helm sealed-secrets \
    --interval=1h \
    --url=https://charts.helm.sh/stable/ \
    --export > ./clusters/desarrollo/flux-system/gotk-sealed-secrets.yaml
$ flux create helmrelease sealed-secrets \
    --interval=1h \
    --release-name=sealed-secrets \
    --target-namespace=flux-system \
    --source=HelmRepository/sealed-secrets \
    --chart=sealed-secrets \
    --chart-version="1.12.2" \
    --export >> ./clusters/desarrollo/flux-system/gotk-sealed-secrets.yaml

Incluye el nuevo fichero como recurso en el fichero ./clusters/desarrollo/flux-system/kustomization.yaml

$ git add .
$ git commit -m "Add sealed secrets"
$ git push origin master

Depués de añadirlo al repositorio se creará el controller y podrás descargarte la clave pública única para este cluster.

$ kubeseal --fetch-cert \
    --controller-name=sealed-secrets \
    --controller-namespace=flux-system > ./clusters/desarrollo/flux-system/pub-sealed-secrets.pem

Es posible que no funcione, puedes obtener el certificado de los logs:

$ kubectl -n flux-system get pods | grep sealed
$ kubectl -n flux-system logs sealed-secrets-xxxxxx-xxxxxx

Puedes añadir esa clave pública al repositorio para que no necesites descargarla más y cualquiera SIN acceso directo al clúster pero con acceso al repositorio git pueda cifrar secretos destinados al mismo.

Más adelante cifraremos secretos tanto para los deployments como para otros controladores.

3. Actualizar Imágenes

Hay varios recursos que intervienen en este proceso:

  • Un repositorio (el registro docker que almacena las imágenes)
  • Una política (que determina cuándo hay que moverse de una versión a otra)
  • Un update (que provoca la actualización del repositorio para reflejar el cambio de versión)

De estos componentes el repositorio y la política tienen referencias a la imagen concreta por lo que no son comunes, sólo el update que siempre actualizará el mismo repositorio git de infraestructura es lo que vamos de forma común, así como las credenciales para acceder al registro docker.

$ flux create image update flux-system \
    --git-repo-ref=flux-system \
    --branch=main \
    --author-name=sistemas \
    --author-email=sistemasbot@users.noreply.gitlab.com \
    --commit-template="Image version update" \
    --interval 5m \
    --export > ./clusters/desarrollo/flux-system/gotk-image-automation.yaml

NOTA: Se puede hacer referencia al repo flux-system pero en mis pruebas no me ha funcionado al hacer update porque no tenía permisos para actualizar, el acceso SSH y HTTP utiliza diferentes estrategias. Por eso es posible que sea necesario incluir otro repositorio

Vamos a crear las credenciales para acceder al registro docker de gitlab. Para eso necesitamos un token, nos puede valer el mismo que creamos inicialmente que tenía permisos de lectura del registro.

$ kubectl create secret docker-registry registry-credentials \
    --docker-server=registry.um.es:443 \
    --docker-username=myuser   \
    --docker-password=mytoken \  
    --dry-run=client -o yaml > .secret-registry.yaml

IMPORTANTE: El secreto que acabas de crear NO ESTÁ CIFRADO, no debes hacer commit nunca de ese fichero.

$ kubeseal --scope=cluster-wide --format=yaml \
    --cert=clusters/desarrollo/flux-system/pub-sealed-secrets.pem \
    < .secret-registry.yaml > ./clusters/desarrollo/flux-system/gotk-registry-credentials.yaml

Ya tienes el secreto cifrado, borra el secreto sin cifrar !!

$ rm .secret-registry.yaml

Para evitar subir el secreto NO cifrado puedes añadir un fichero .gitignore incluyendo el patrón .secret* de modo que git lo ignore y nunca lo subas al repositorio.

4. Receptores y Notificaciones

Por el momento no tenemos ninguna de las dos cosas es algo que se puede configurar más adelante:

  • Receivers: Por el momento tenemos configurado TODO con estragia proactiva. Flux está consultando constantemente (en los intervalos que digamos) los cambios en el repositorio para sincronizarlos en el clúster. Se puede cambiar para que sea reactivo, es decir, cuando se ejecute un cambio en algún repositorio que se invoque a un webhook de flux para que ponga en marcha la reconciliación.
  • Notifications: En este caso se puede configurar para que cuando finalice la reconciliación se notifique a un webhook, por ejemplo rocketchat para indicar que se ha actualizado algo. Esto valdría para avisar a los desarrolladores de que sus cambios ya están actualizados en la infraestructura.

5. Buenas prácticas

Ahora vamos a instalar lo necesario para desplegar polaris que me permite visualizar un índice de calidad de buenas prácticas seguidas en los despliegues realizados en el clúster. Para hacerlo vamos a usar flux como si se tratase de una aplicación desarrollada por nosotros y vamos practicando.

6. Uso de recursos

Es interesante instalar Goldilocks https://goldilocks.docs.fairwinds.com/ que junto con VPA ofrece una ayuda ideal para establecer los valores adecuados de CPU y Memoria en base al funcionamiento de los pods.

DESPLEGAR APLICACIONES

Para desplegar aplicaciones necesitas declarar un source en el que estarán los manifiestos de la aplicación y una kustomization que determinará el despliegue concreto para un entorno concreto. Puesto que el repositorio source va a ser el mismo para todos (el que hemos creado) vamos a declararlo de forma general para todo el mundo y así todas las kustomizations usarán el mismo.

$ flux create source git deployments-source \
    --url https://gitlab.um.es/sistemas/flux-k8s-infra \
    --branch master \
    --secret-ref deployments-credentials \
    --export > ./clusters/desarrollo/flux-system/gotk-deployments-source.yaml

Necesitamos unas credenciales para obtener acceso al repositorio mediante https por lo que vamos a configurarlas usando Sealed Secrets. Son las mismas credenciales que ya hemos hecho antes pero en otro formato:

$ kubectl create secret generic deployments-credentials \
    --from-literal=username=myuser \
    --from-literal=password=mytoken \  
    --dry-run=client -o yaml > .secret-deployments.yaml

IMPORTANTE: El secreto que acabas de crear NO ESTÁ CIFRADO, no debes hacer commit nunca de ese fichero. Si ya has configurado el .gitignore no corres peligro (a menos que accedan a tu pc).

$ kubeseal --scope=cluster-wide --format=yaml \
    --cert=clusters/desarrollo/flux-system/pub-sealed-secrets.pem \
    < .secret-deployments.yaml \
    > ./clusters/desarrollo/flux-system/gotk-deployments-credentials.yaml

Ya tienes el secreto cifrado, borra el secreto sin cifrar !!

$ rm .secret-deployments.yaml

Ahora vamos a definir la kustomization del aplicativo concreto y lo vamos a colocar en una carpeta para tenerlas localizadas. Por un lado estará la kustomization y en el mismo repositorio pero en otra carpeta los manifiestos de la aplicación.

$ flux create kustomization polaris \
    --source=deployments-source \
    --path="./deployments/polaris/" \
    --prune=true \
    --interval=10m \
    --validation=client \
    --health-check="Deployment/polaris.polaris-dashboard" \
    --health-check-timeout=3m
    --export > ./clusters/desarrollo/applications/polaris/polaris.yaml

Hemos apuntado la kustomization a una carpeta dentro de nuestro repositorio por lo que ahora hay que crearla y poner en ella el yaml de kustomization de la aplicación o si son varios.

Descarga el yaml de polaris: https://github.com/fairwindsops/polaris/releases/latest/download/dashboard.yaml

Guarda el fichero en el directorio referenciado por la kustomization: ./deployments/polaris/

1. Buenas prácticas

Ahora vamos a añadir un pipeline al repositorio para que se analizen los yaml incluidos en él, en busca de malas prácticas. EN caso de detectar malas prácticas el pipeline fallará y eso permitirá controlar que los despliegues que se hagan sean lo más correctos que sea posible.

Incluye el fichero .gitlab-ci.yml en la raíz del repositorio y súbelo al repositorio.

build-manifest:
  stage: build
  image: nekottyo/kustomize-kubeval
  script:
    - mkdir -p build
    - kustomize create --autodetect --recursive
    - kustomize build . > manifest.yaml
  artifacts:
    name: k8s-manifests
    paths:
    - manifest.yaml
    expire_in: 1 day

validate-manifest:
  stage: test
  image: docker:latest
  services:
    - docker:dind
  script:
    - docker run --rm -v ${PWD}:/project zegl/kube-score score manifest.yaml

Incluye en .gitignore los ficheros temporales que se utilizan durante el pipeline:

.secret*
/kustomization.yaml
/manifest.yaml

Ahora el pipeline hará un análisis de código estático en busca de errores sintácticos o de malas prácticas en la definición de manifiestos kubernetes. Solo queda respetar los consejos que nos vayan dando.

2. Una aplicación real

Vamos a desplegar una aplicación real de las desarrolladas en ATICA. La pequeña prueba con polaris no ha puesto sobre la mesa la necesidad de hacer un deployment cuya imagen se encuentre en un registro privado ni el uso de configmaps o secretos. Tampoco pone sobre la mesa el uso de kustomize para definir el despliegue de una misma aplicación en diferentes namespaces del mismo cluster (diferentes entornos).

Además también hay que crear el repositorio y la política de actualización de imágenes. Vamos a crear los objetos necesarios para gestionar una aplicación desarrollada en nuestro repositorio que desplegaremos en dos entornos desa y test:

$ flux create kustomization portal-desa \
    --source=deployments-source \
    --path="./deployments/aulavirtual/portal-servicios/desa" \
    --prune=true \
    --interval=10m \
    --validation=client \
    --health-check="Deployment/portal-api-deployment.portal-svc-desa" \
    --health-check-timeout=3m \
    --export > ./clusters/desarrollo/applications/portal-servicios/portal-desa.yaml
$ flux create kustomization portal-test \
    --source=deployments-source \
    --path="./deployments/aulavirtual/portal-servicios/test" \
    --prune=true \
    --interval=10m \
    --validation=client \
    --health-check="Deployment/portal-api-deployment.portal-svc-test" \
    --health-check-timeout=3m \
    --export > ./clusters/desarrollo/applications/portal-servicios/portal-test.yaml

Ahora vamos a declarar las imágenes que podemos querer actualizar dentro de este despliegue:

$ flux create image repository portal-api-image-repository 
    --image registry.um.es:443/aulavirtual/portal-api
    --interval 1m 
    --secret-ref registry-credentials 
    --export > ./clusters/desarrollo/applications/portal-servicios/portal-api-image-repo.yaml
$ flux create image repository portal-ui-image-repository 
    --image registry.um.es:443/aulavirtual/portal-ui
    --interval 1m 
    --secret-ref registry-credentials 
    --export > ./clusters/desarrollo/applications/portal-servicios/portal-ui-image-repo.yaml

Y ahora la política de selección que dependerá de los entornos que queramos desplegar:

$ flux create image policy portal-api-desa-policy 
    --image-ref portal-api-image-repository
    --semver ">=1.0.0 <10.0.0" 
    --export > ./clusters/desarrollo/applications/portal-servicios/portal-desa-image-policies.yaml
$ echo --- >> ./clusters/desarrollo/applications/portal-servicios/portal-desa-image-policies.yaml
$ flux create image policy portal-ui-desa-policy 
    --image-ref portal-ui-image-repository
    --semver ">=1.0.0 <2.0.0" 
    --export >> ./clusters/desarrollo/applications/portal-servicios/portal-desa-image-policies.yaml
$ flux create image policy portal-api-test-policy 
    --image-ref portal-api-image-repository
    --semver ">=10.0.0 <20.0.0" 
    --export > ./clusters/desarrollo/applications/portal-servicios/portal-test-image-policies.yaml
$ echo --- >> ./clusters/desarrollo/applications/portal-servicios/portal-test-image-policies.yaml
$ flux create image policy portal-ui-test-policy 
    --image-ref portal-ui-image-repository
    --semver ">=10.0.0 <20.0.0" 
    --export > ./clusters/desarrollo/applications/portal-servicios/portal-test-image-policies.yaml

Nos faltan todos los manifiestos de la aplicación en si misma, que debería ubicarse en la carpeta definida en las kustomizations, incluyendo la kustomization concreta para desa y test en cada caso.

CONCLUSIONES

Para el mantenimiento del repositorio y la inclusión de más aplicaciones es más sencillo copiar los manifiestos de las aplicaciones que ya haya incluídas antes que añadir cada uno de los recursos con comandos flux.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment