Implementar AWX en GKE – Parte 2 (prod-ready)

En el post anterior Implementar AWX en GKE vimos como realizar una implementación basica de AWX en un Cluster de GKE utilizando la version 2.11.0 con Helm.

Ahora vamos a realizar una implementación production-ready. Vamos a asginar a nuestro deployment:

  • Utilizaremos la versión 2.17.0 del Operador de AWX.
  • Storage persistente (standard-rwo) en GKE.
  • Solucionaremos: 1. Bug de Ingress en GKE y 2. Bug de AccesType en PV de los Pods de Task y Web.
  • Ademas solucionaremos el Bug de permisos de acceso para escritura de datos en el PVC para el pod de Postgres.

Clonar repositorio

Primero debemos descargar el ultimo release disponible del Operator. A la fecha de este post, el ultimo release disponible es el 2.17.0. Para esto ejecutaremos los siguientes comandos:

git clone https://github.com/ansible/awx-operator/tree/2.17.0 awx-operator.2.17.0
cd .\awx-operator.2.17.0\
git checkout tags/2.17.0 -b release-2.17.0
code .

Esto nos asegurará tener los archivos disponibles a la versión del Release.

Editar Ingress jinja template

Basado en el este Issue del repositorio Oficial del Operador de AWX.

          - path: '{{ (ingress_path + '/*').replace("//","/") }}'

Este paso es importante ya que nos asegura que el manifiesto generado por el Operador del K8s Ingress (HTTPs Load Balancer en GKE) quede finalmente con un Path correcto.

Crear custom Operator Container

Ahora debemos crear y almacenar nuestra custom image del Operador en un Artifact Registry privado.

Crear GCP Artifact Registry

Ahora debemos crear un Artifact Registry en GCP para guardar nuestra imagen. Ejecutaremos el siguiente gcloud command:

gcloud artifacts repositories create awx_repo \
    --repository-format=docker \
    --location=us-east4 --description="AWX Containers Repo" \
    --project=multicloudstech-gke

Ahora debemos autenticar Docker con gcloud para poder pushear las imagenes a este repo, ejecutando el siguiente comando:

gcloud auth configure-docker us-east4-docker.pkg.dev 

Docker Build

Ahora realizaremos el build de nuestra propia imagen de Docker del AWX-Operator. Para esto, luego de haber modificado el Jinja2 File del Ingress, realizar el Docker Build:

docker build -t us-east4-docker.pkg.dev/multicloudstech-gke/awx-repo/awx-operator:2.17.0 . --no-cache

Podremos verificar la imagen construida:

Docker Push

Ahora realizaremos el push de la imagen creada a nuestro artifact registry. Ejecutaremos el siguiente comando:

docker push us-east4-docker.pkg.dev/multicloudstech-gke/awx-repo/awx-operator:2.17.0

Verificamos que la imagen fue pusheada exitosamente:

Configurar AWX Artifact Registry Login

Ahora debemos asignar los permisos necesarios a nuestra cuenta de servicio de nuestros nodos de Kubernetes para leer/pull images desde Artifact Registry. Para esto asignaremos el rol de Artifact Registry Reader la Service Account asignada a los nodos de GKE.

Crear AWX Operator Yaml

Ahora, utilizando las cualidades de Make, realizaremos la creación del Manifiesto de AWX Operator. Ejecutaremos el siguiente comando (en linux):

make gen-resources | tee awx-operator.yaml

Se creará el archivo para desplegar nuestro Operador:

Cambios al YAML del Operator

Ahora debemos realizar algunos cambios a nuestro manifiesto.

Image Pull Secret

En la linea 2860, debemos comentar la linea de Image Pull Secret.

Ahora reemplazaremos en la linea 2832, cambiando la imagen por defecto del Operador por la nueva que acabamos de crear.

Desplegar AWX Operator

Realizaremos el primer paso de despliegue, aplicaremos el manifiesto inicial del Operador. Para esto, ejecutaremos el siguiente comando:

kubectl apply -f .\awx-operator.yaml -n awx

Aquí veremos que se crean todos los recursos relacionados con el Namespace, los CRD, RBAC permissions, K8s Service Accounts, ConfigMaps, el Servicio del Operador y el Deployment.

Ahora podemos ver que nuestro Operador esta desplegado:

Desplegar recurso AWX

Ahora sí, con nuestro Operador desplegado y funcionando podemos realizar el despliegue de AWX. Para esto debemos generar nuestro manifiesto, pero antes un prerrequisito…

Prerrequisito

Primero debemos asegurarnos:

  • HTTPs Load Balancing este habilitado en GKE.
  • Crear una IP estática reservada para el ingress.
  • Disponer de un certificado para configurar en el ingress

Crear Secret para el certificado

En este caso, disponemos de un certificado creado con Let’s Encrypt. Vamos a guardarlo como secret en Kubernetes, utiilzando el siguiente comando:

kubectl create secret tls awx-multiclouds-tech-cert --cert=C:\Users\Mateo\AppData\Local\Posh-ACME\LE_PROD\1629371947\awx.multiclouds.tech\cert.cer  --key=C:\Users\Mateo\AppData\Local\Posh-ACME\LE_PROD\1629371947\awx.multiclouds.tech\cert.key -n awx

Crear manifiesto de recurso AWX

Ahora realizaremos la implementación de nuestro CRD. Para esto crearemos el siguiente manifiesto:

---
apiVersion: awx.ansible.com/v1beta1
kind: AWX
metadata:
  name: ansible-awx
  namespace: awx
spec:
  service_type: nodeport
  postgres_storage_class: standard-rwo
  projects_persistence: true
  projects_storage_access_mode: ReadWriteOnce 
  ingress_type: ingress
  ingress_path: /
  ingress_path_type: ImplementationSpecific
  hostname: awx.multiclouds.tech
  ingress_tls_secret: awx-multiclouds-tech-cert
  ingress_annotations: |
    kubernetes.io/ingress.global-static-ip-name: <<< IP ADDRESS NAME >>>
    cloud.google.com/backend-config: '{"ports": {"80":"awx-backendconfig"}}'
  service_annotations: |
    cloud.google.com/backend-config: '{"ports": {"80":"awx-backendconfig"}}'
    cloud.google.com/neg: '{"ingress": true}'
  • Recordar asignar el nombre de la reserva de IP address realizada en GCP en la 18.
  • Es importante tener en cuenta que podes recibir un error si cambias el parametro projects_storage_access_mode.

Implementar AWX

Realizaremos el Apply de nuestro manifiesto ejecutando el siguiente commando:

kubectl apply -f .\awx-deploy.yaml -n awx

Ahora podremos revisar el status de nuestros Pods:

kubectl get pods -n awx -w

Si vemos los logs del pod, verificamos que:

El contenedor de Postgres no puede escribirr data al PVC:

Solucionar Postgres “mkdir: cannot create directory ‘/var/lib/pgsql/data/userdata’: Permission denied”

Para solucionar este error debemos generar un pod temporar para inspecionar el PVC y asignar permisos al usuario 26 que es el que postgres utiliza por default.

Vamos a crear el siguiente manificesto para un PVC-Inspector pod, a través del cual asignaremos los permisos al PVC.

apiVersion: v1
kind: Pod
metadata:
  name: pvc-inspector
  namespace: awx
spec:
  containers:
  - image: busybox
    name: pvc-inspector
    command: ["tail"]
    args: ["-f", "/dev/null"]
    volumeMounts:
    - mountPath: /pvc
      name: pvc-mount
  volumes:
  - name: pvc-mount
    persistentVolumeClaim:
      claimName: postgres-15-ansible-awx-postgres-15-0

Aplicamos el manifest:

kubectl apply -f .\pvc-inspector.yaml -n awx

Una vez creado ingresamos al pod:

kubectl exec -it pvc-inspector -n awx -- /bin/sh

Asignamos el siguiente permiso:

chown -R 26:26 /pvc/data/

Al realizar esto el pod de postgres debería pasar al estado “Running”. Si no lo hace de manera automatica, podemos eleiminarlo y se volverá a crear gracias al autohealing de nuestro deployment.

Luego continuará el deploy hasta tener todos los pods funcionando:

En este sentido, podemos ver que el Ingress no está tomando correctamente la ip address designada en el awx-deploy.yaml.

Solucionar problematica del Ingress

Como vimos en el punto anterior, el ingress no está funcionando correctamente. Ya que se está creando el HTTP Load Balancer que esperamos en GCP:

Utlizando el comando de kubctl describe, podemos ver el error arrojado:

kubectl describe ingress ansible-awx-ingress -n awx 

Para solucionar esto vamos a crear el BackendConfig, generando el siguiente manifiesto:

apiVersion: cloud.google.com/v1
kind: BackendConfig
metadata:
  name: awx-backendconfig
  namespace: awx

Realizamos el Apply del backend-config file:

kubectl apply -f .\backend-config.yaml -n awx

Al configurarlo podemos verificar que un HTTPs Load Balancer es creado en GCP:

Luego de un momento, Kubernetes se da cuenta del cambio y realiza la correcta configuración del Ingress:

Así ahora podemos ver como podemos ingresar correctamente a nuestro Cluster 🙂


Posted

in

, , , , ,

by

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.