Alcanzando las estrellas: Dominando a los operadores de Ansible para la gestión de aplicaciones en Kubernetes

Veremos cómo usar los roles publicados en Ansible Galaxy como operadores que administran aplicaciones en Kubernetes, y veamos cómo crear un operador que simplemente instale la aplicación y ajuste su comportamiento de manera flexible según el entorno.



Usaremos Ansible Operator y el módulo k8s para mostrar cómo usar Ansible para crear aplicaciones Kubernetes.

Ansible Operator es parte del Operator SDK y le permite formular las regulaciones operativas de la aplicación (cómo debe instalarse y mantenerse) en el lenguaje de roles y libros de jugadas de Ansible. El módulo k8s, a su vez, amplía la capacidad de administrar objetos en Kubernetes al crear tales roles y libros de jugadas.

Un operador se crea así simplemente así.

FROM quay.io/operator-framework/ansible-operator RUN ansible-galaxy install djzager.hello_world_k8s RUN echo $'--- \n\ - version: v1alpha1\n\ group: examples.djzager.io\n\ kind: HelloWorld\n\ role: /opt/ansible/roles/djzager.hello_world_k8s' > ${HOME}/watches.yaml 

Tecla de inicio


Primero, algunas palabras sobre el módulo k8s Ansible . Apareció en Ansible 2.6 y amplía las posibilidades de trabajar con objetos Kubernetes de Ansible y en cualquier distribución de Kubernetes, incluido Red Hat OpenShift. Ansible blog tenía una publicación separada sobre este módulo y el cliente dinámico de Python para Red Hat OpenShift . En nuestra opinión, trabajar con objetos Kubernetes a través de Ansible sin usar el módulo k8s está mal. El mecanismo del operador se creó originalmente para ejecutar aplicaciones en Kubernetes, y el SDK del operador proporciona herramientas para ensamblar, probar y empaquetar operadores. A su vez, se necesita Ansible Operator para establecer las regulaciones operativas de la aplicación en lenguaje Ansible. El flujo de trabajo correspondiente se organiza de manera bastante simple: primero hacemos operator-sdk new --type = Ansible para generar los archivos necesarios para el operador Ansible, luego pintamos Ansible, y finalmente hacemos operator-sdk build para construir la aplicación para trabajar en Kubernetes. Pero si ya tenemos un papel en Ansible Galaxy, que controla la aplicación en Kubernetes, las cosas se vuelven aún más fáciles. A continuación haremos lo siguiente:

  1. Creemos un rol Ansible para administrar la aplicación Hello World en Kubernetes, lo que nos ayudará a demostrar las capacidades del módulo k8s Ansible.
  2. Publicaremos este papel en Ansible Galaxy.

Entonces, ensamblemos el operador Ansible usando el rol publicado en Ansible Galaxy. ¿Por qué incluso crear un operador usando un rol de Ansible Galaxy? Hay dos razones:

  1. Para no repetir . Si ya hemos programado la función Ansible para administrar la aplicación Hello World y la hemos publicado en Ansible Galaxy, entonces es lógico usarla al crear el operador Ansible.
  2. Debido a la separación de responsabilidades . Queremos que el rol Hello World Ansible administre la aplicación del mismo nombre en Kubernetes y que la lógica operativa (operativa) permanezca dentro del operador. En nuestro ejemplo, la lógica operativa es extremadamente simple: simplemente llama al rol djzager.hello_world_k8s cada vez que crea o modifica un recurso personalizado HelloWorld. Sin embargo, en el futuro esta separación se volverá más significativa, por ejemplo, agregaremos validación a la aplicación Hello World a través del rol Ansible e implementaremos el control de estado de los recursos personalizados HelloWorld a través de la lógica del operador.

Hola Kubernetes, conoce a Ansible.


Que necesitamos


  1. Ansible: consulte la guía de instalación si no tiene Ansible instalado.
  2. Cliente de Python para OpenShift (opcional). Solo es necesario para el lanzamiento local. Las instrucciones de instalación están aquí .

Empecemos Primero, crea un esqueleto de roles usando ansible-galaxy:

 # I like clear names on projects. # In meta/main.yml I will make role_name: hello-world-k8s $ ansible-galaxy init ansible-role-hello-world-k8s 

Inmediatamente después de crear una nueva función Ansible, estableceremos todos los valores predeterminados para documentar al mismo tiempo sus parámetros de configuración válidos. Además, nuestro ejemplo de Hello World no es particularmente complicado a este respecto. Así es como se ve nuestro archivo por defecto / main.yml:

 --- # NOTE: meta.name(space) comes from CR metadata when run with Ansible Operator # deploy/crds has an example CR for reference name: "{{ meta.name | default('hello-world') }}" namespace: "{{ meta.namespace | default('hello-world') }}" image: docker.io/ansibleplaybookbundle/hello-world:latest # To uninstall from the cluster # state: absent state: present # The size of the hello-world deployment size: 1 

Una vez establecidos los valores predeterminados, es necesario decidir qué hará el rol. La aplicación Hello World tendrá que hacer lo siguiente:

  1. Obtenga información sobre las API disponibles en el clúster.
  2. Cree varias plantillas y asegúrese de que estén presentes o ausentes en el clúster.

Por lo tanto, nuestro archivo tareas / main.yml se ve así:

 --- - name: "Get information about the cluster" set_fact: api_groups: "{{ lookup('k8s', cluster_info='api_groups') }}" - name: 'Set hello-world objects state={{ state }}' k8s: state: '{{ state }}' definition: "{{ lookup('template', item.name) | from_yaml }}" when: item.api_exists | default(True) loop: - name: deployment.yml.j2 - name: service.yml.j2 - name: route.yml.j2 api_exists: "{{ True if 'route.openshift.io' in api_groups else False }}" 

Antes de pasar a las plantillas, preste atención a esta línea en el archivo de tareas:

 api_exists: "{{ True if 'route.openshift.io' in api_groups else False }}" 

Usando set_fact, obtenemos una lista de todas las API disponibles en el clúster para que podamos generar plantillas de forma selectiva dependiendo de si hay una API allí, en este caso, route.openshift.io. De manera predeterminada, en el clúster Kubernetes de OpenShift, las Rutas no están disponibles y no las necesitamos, por lo tanto, solo trabajamos con el objeto Ruta cuando hay route.openshift.io en el clúster.

No solo podemos administrar objetos de forma selectiva en el clúster dependiendo de la disponibilidad de ciertas API, sino también usar las plantillas Jinja2 para usar OpenShift DeploymentConfig en nuestra plantilla de implementación si el clúster tiene la API apps.openshift.io. Así es como se ve nuestro archivo templates / despliegue.yml.j2:

 --- {% if 'apps.openshift.io' in api_groups %} apiVersion: apps.openshift.io/v1 kind: DeploymentConfig {% else %} apiVersion: apps/v1 kind: Deployment {% endif %} metadata: name: {{ name }} namespace: {{ namespace }} labels: app: {{ name }} service: {{ name }} spec: replicas: {{ size }} {% if 'apps.openshift.io' in api_groups %} selector: app: {{ name }} service: {{ name }} {% else %} selector: matchLabels: app: {{ name }} service: {{ name }} {% endif %} template: metadata: labels: app: {{ name }} service: {{ name }} spec: containers: - image: {{ image }} name: hello-world ports: - containerPort: 8080 protocol: TCP 

Plantillas de archivo / service.yml.j2:

 --- apiVersion: v1 kind: Service metadata: name: {{ name }} namespace: {{ namespace }} labels: app: {{ name }} service: {{ name }} spec: ports: - name: web port: 8080 protocol: TCP targetPort: 8080 selector: app: {{ name }} service: {{ name }} 

Y finalmente, el archivo templates / route.yml.j2:

 --- apiVersion: route.openshift.io/v1 kind: Route metadata: name: {{ name }} namespace: {{ namespace }} labels: app: {{ name }} service: {{ name }} spec: port: targetPort: web to: kind: Service name: {{ name }} 

Omitimos el archivo meta / main.yml, pero se puede encontrar aquí .

Como resultado, tenemos la función Ansible de administrar la aplicación Hello World en Kubernetes, y podemos usar las API disponibles en el clúster. En otras palabras, el módulo k8s y el cliente dinámico simplifican el trabajo con objetos en Kubernetes. Esperamos que con el ejemplo de este rol, podamos mostrar el potencial de Ansible al trabajar con Kubernetes.

Hola Galaxy, conoce a Kubernetes


Ansible Galaxy tiene muchos roles para configurar servidores y administrar aplicaciones, pero no hay tantos roles para administrar aplicaciones de Kubernetes, por lo que haremos una pequeña contribución.

Después de publicar nuestro papel en GitHub , todo lo que quedaba era:

  1. Inicie sesión en Ansible Galaxy para dar acceso a nuestros repositorios en GitHub.
  2. Importa nuestro papel.

Eso es todo, ahora nuestro rol hello_world_k8s está disponible públicamente en Ansible Galaxy, aquí .

Hola operador de Ansible, Meet Galaxy


Si estudia cuidadosamente nuestro proyecto Hello World en GitHub , notará que agregamos algunas cosas allí que son necesarias para crear el operador Ansible, a saber:

  1. Un archivo de Watches que asigna recursos personalizados de Kubernetes a roles o libros de jugadas de Ansible.
  2. Dockerfile para construir nuestro operador.
  3. Implemente el directorio con los objetos de Kubernetes necesarios para ejecutar nuestro operador.

Si necesita aprender más sobre cómo construir sus propias declaraciones de Ansible, use la Guía del usuario . Pero dado que prometimos construir un operador Ansible usando el rol publicado en Ansible Galaxy, todo lo que realmente necesitamos es un Dockerfile:

 FROM quay.io/operator-framework/ansible-operator RUN ansible-galaxy install djzager.hello_world_k8s RUN echo $'--- \n\ - version: v1alpha1\n\ group: examples.djzager.io\n\ kind: HelloWorld\n\ role: /opt/ansible/roles/djzager.hello_world_k8s' > ${HOME}/watches.yaml 

Ahora recogemos el operador:

 $ docker build -t hello-world-operator -f Dockerfile . Sending build context to Docker daemon 157.2 kB Step 1/3 : FROM quay.io/operator-framework/ansible-operator latest: Pulling from operator-framework/ansible-operator Digest: sha256:1156066a05fb1e1dd5d4286085518e5ce15acabfff10a8145eef8da088475db3 Status: Downloaded newer image for quay.io/water-hole/ansible-operator:latest ---> 39cc1d19649d Step 2/3 : RUN ansible-galaxy install djzager.hello_world_k8s ---> Running in 83ba8c21f233 - downloading role 'hello_world_k8s', owned by djzager - downloading role from https://github.com/djzager/ansible-role-hello-world-k8s/archive/master.tar.gz - extracting djzager.hello_world_k8s to /opt/ansible/roles/djzager.hello_world_k8s - djzager.hello_world_k8s (master) was installed successfully Removing intermediate container 83ba8c21f233 ---> 2f303b45576c Step 3/3 : RUN echo $'--- \n- version: v1alpha1\n group: examples.djzager.io\n kind: HelloWorld\n role: /opt/ansible/roles/djzager.hello_world_k8s' > ${HOME}/watches.yaml ---> Running in cced495a9cb4 Removing intermediate container cced495a9cb4 ---> 5827bc3c1ca3 Successfully built 5827bc3c1ca3 Successfully tagged hello-world-operator:latest 

Está claro que para usar este operador, necesita el contenido del directorio de implementación de nuestro proyecto para crear una cuenta de servicio, rol y enlace de roles, definición de recursos personalizados, así como para implementar el propio operador. Y después de implementar el operador, deberá crear un recurso personalizado para obtener una instancia de la aplicación Hello World:

 apiVersion: examples.djzager.io/v1alpha1 kind: HelloWorld metadata: name: example-helloworld namespace: default spec: size: 3 

Ámbitos del operador: espacio de nombres y clúster


Un poco más arriba, ya sugerimos explorar nuestro directorio de implementación y buscar los objetos de Kubernetes necesarios para iniciar el operador. Hay tres cosas que limitan el alcance del operador al administrar recursos personalizados con el espacio de nombres en el que se implementa el operador, a saber:

  1. La variable de entorno WATCH_NAMESPACE en el archivo operator.yaml que le dice al operador dónde buscar recursos personalizados
  2. role.yaml
  3. enlace de roles

Esta limitación es ciertamente útil en el desarrollo de operadores. Pero si quisiéramos que nuestra aplicación fuera accesible para todos los usuarios del clúster, necesitaríamos la ayuda de un administrador. Tendría que hacer lo siguiente:

  1. Cree ClusterRole en lugar de Role.
  2. Cree una declaración de ServiceAccount en el espacio de nombres donde se desplegará la declaración.
  3. Cree un ClusterRoleBinding que asociará una ServiceAccount de un espacio de nombres particular con un ClusterRole.
  4. Expanda la declaración con una variable de entorno WATCH_NAMESPACE indefinida (es decir, "").

Si hace todas estas cosas, el resto de los usuarios del clúster podrán implementar instancias de nuestra aplicación Hello World. Si está interesado en este tema, le recomendamos que estudie el Administrador del ciclo de vida del operador (parte del marco del operador).

Star trek


Mostramos cómo crear un rol Ansible para controlar una aplicación en Kubernetes, publicar este rol en Ansible Galaxy y usarlo en el operador Ansible. Esperamos que ahora:

  1. Utilizará el módulo k8s Ansible .
  2. Comience a publicar sus roles para administrar aplicaciones Kubernetes en Ansible Galaxy .
  3. Interesarse en el SDK del operador y suscribirse a nuestro boletín del Marco del operador .

Nuestra aplicación Hello World se hizo extremadamente simple intencionalmente, pero hay cosas que pueden ayudar a que sea aún más confiable, y aquí hay algunas:

  1. Uso del SDK del operador : no lo hicimos intencionalmente en nuestro ejemplo para enfatizar lo fácil que es cambiar del rol Ansible al operador. Pero es mejor seguir usando esta función con el SDK (es decir, operator-sdk new), además, es posible que necesite esto en los próximos pasos.
  2. Validación: en nuestra versión actual, el usuario puede crear un CR con el tamaño: abc, lo que inevitablemente conducirá a un error en la etapa de implementación. Por lo tanto, es mejor detectar errores en la etapa de especificación, y no después de que comience el trabajo.
  3. Ciclo de vida: en ejemplos más complejos, puede ser la misma actualización de versión. En escenarios como el nuestro, donde solo hay una versión de la aplicación Hello World, podríamos determinar si la imagen de un contenedor en funcionamiento está desactualizada comparándola con las imágenes disponibles en el registro del contenedor correspondiente y actualizar las instancias en ejecución si es necesario.
  4. Pruebas: Molecule es muy útil al desarrollar y probar roles de Ansible.
  5. Operator Lifecycle Manager es un juego de herramientas para la gestión de operadores. La integración con él ayudará a instalar y actualizar nuestro operador.
  6. Estado: podríamos activar el subrecurso de estado en nuestro Hello World CRD y usar el módulo k8s_status, que es parte de la imagen del Operador Ansible, para incluir información de estado en el recurso personalizado.

Source: https://habr.com/ru/post/440188/


All Articles