Consejos y trucos de Kubernetes: sobre desarrollo local y telepresencia

Consejos y trucos de Kubernetes: sobre desarrollo local y telepresencia

Cada vez más nos preguntan sobre el desarrollo de microservicios en Kubernetes. Los desarrolladores, especialmente de lenguajes interpretados, quieren corregir rápidamente el código en su IDE favorito y ver el resultado sin esperar la compilación/implementación, simplemente presionando F5. Y cuando se trataba de una aplicación monolítica, bastaba con instalar localmente una base de datos y un servidor web (en Docker, VirtualBox...), y luego inmediatamente disfrutar del desarrollo. Con la división de monolitos en microservicios y la llegada de Kubernetes, con la aparición de dependencias entre sí, todo se volvió un poco más difícil. Cuantos más microservicios haya, más problemas. Para volver a disfrutar del desarrollo, es necesario levantar más de uno o dos contenedores Docker y, a veces, incluso más de una docena... En general, todo esto puede llevar bastante tiempo, ya que también es necesario mantenerlo actualizado. .

En diferentes momentos probamos diferentes soluciones al problema. Y empezaré por las soluciones acumuladas o simplemente “muletas”.

1. muletas

La mayoría de los IDE tienen la capacidad de editar código directamente en el servidor mediante FTP/SFTP. Este camino es muy obvio e inmediatamente decidimos utilizarlo. Su esencia se reduce a lo siguiente:

  1. En el grupo de entornos de desarrollo (dev/review), se lanza un contenedor adicional con acceso SSH y reenvía la clave SSH pública del desarrollador que confirmará/implementará la aplicación.
  2. En la etapa inicial (dentro del contenedor prepare-app) transferir el código a emptyDirpara tener acceso al código desde los contenedores de la aplicación y el servidor SSH.

Consejos y trucos de Kubernetes: sobre desarrollo local y telepresencia

Para comprender mejor la implementación técnica de dicho esquema, proporcionaré fragmentos de las configuraciones YAML involucradas en Kubernetes.

Configuraciones

1.1. valores.yaml

ssh_pub_key:
  vasya.pupkin: <ssh public key in base64> 

es vasya.pupkin es el valor de la variable ${GITLAB_USER_LOGIN}.

1.2. implementación.yaml

...
{{ if eq .Values.global.debug "yes" }}
      volumes:
      - name: ssh-pub-key
        secret:
          defaultMode: 0600
          secretName: {{ .Chart.Name }}-ssh-pub-key
      - name: app-data
        emptyDir: {}
      initContainers:
      - name: prepare-app
{{ tuple "backend" . | include "werf_container_image" | indent 8 }}
        volumeMounts:
        - name: app-data
          mountPath: /app-data
        command: ["bash", "-c", "cp -ar /app/* /app-data/" ]
{{ end }}
      containers:
{{ if eq .Values.global.debug "yes" }}
      - name: ssh
        image: corbinu/ssh-server
        volumeMounts:
        - name: ssh-pub-key
          readOnly: true
          mountPath: /root/.ssh/authorized_keys
          subPath: authorized_keys
        - name: app-data
          mountPath: /app
        ports:
        - name: ssh
          containerPort: 22
          protocol: TCP
{{ end }}
      - name: backend
        volumeMounts:
{{ if eq .Values.global.debug "yes" }}
        - name: app-data
          mountPath: /app
{{ end }}
        command: ["/usr/sbin/php-fpm7.2", "--fpm-config", "/etc/php/7.2/php-fpm.conf", "-F"]
...

1.3. secreto.yaml

{{ if eq .Values.global.debug "yes" }}
apiVersion: v1
kind: Secret
metadata:
  name: {{ .Chart.Name }}-ssh-pub-key
type: Opaque
data:
  authorized_keys: "{{ first (pluck .Values.global.username .Values.ssh_pub_key) }}"
{{ end }}

Toque final

Después de eso solo queda transferir variables requeridas gitlab-ci.yml:

dev:
  stage: deploy
  script:
   - type multiwerf && source <(multiwerf use 1.0 beta)
   - type werf && source <(werf ci-env gitlab --tagging-strategy tag-or-branch --verbose)
   - werf deploy
     --namespace ${CI_PROJECT_NAME}-stage
     --set "global.env=stage"
     --set "global.git_rev=${CI_COMMIT_SHA}"
     --set "global.debug=yes"
     --set "global.username=${GITLAB_USER_LOGIN}"
 tags:
   - build

Listo: el desarrollador que lanzó la implementación puede conectarse por el nombre del servicio (cómo otorgar acceso seguro al clúster, ya dijimos) desde su escritorio a través de SFTP y edite el código sin esperar a que se entregue al clúster.

Esta es una solución completamente funcional, pero desde el punto de vista de la implementación tiene desventajas obvias:

  • la necesidad de perfeccionar el gráfico de Helm, lo que dificulta su lectura en el futuro;
  • sólo puede ser utilizado por la persona que implementó el servicio;
  • debes recordar sincronizarlo con el directorio local con el código y enviarlo a Git.

2. Telepresencia

proyecto Telepresencia Se conoce desde hace bastante tiempo, pero nosotros, como dicen, "no logramos probarlo seriamente en la práctica". Sin embargo, la demanda ha hecho su trabajo y ahora estamos felices de compartir nuestra experiencia, que puede ser útil para los lectores de nuestro blog, especialmente porque todavía no ha habido otros materiales sobre Telepresencia en el centro.

En resumen, todo resultó no ser tan aterrador. Colocamos todas las acciones que requieren ejecución por parte del desarrollador en un archivo de texto de gráfico Helm llamado NOTES.txt. Por lo tanto, después de implementar el servicio en Kubernetes, el desarrollador ve instrucciones para iniciar el entorno de desarrollo local en el registro de trabajos de GitLab:

!!! Разработка сервиса локально, в составе Kubernetes !!!

* Настройка окружения
* * Должен быть доступ до кластера через VPN
* * На локальном ПК установлен kubectl ( https://kubernetes.io/docs/tasks/tools/install-kubectl/ )
* * Получить config-файл для kubectl (скопировать в ~/.kube/config)
* * На локальном ПК установлен telepresence ( https://www.telepresence.io/reference/install )
* * Должен быть установлен Docker
* * Необходим доступ уровня reporter или выше к репозиторию https://gitlab.site.com/group/app
* * Необходимо залогинится в registry с логином/паролем от GitLab (делается один раз):

#########################################################################
docker login registry.site.com
#########################################################################

* Запуск окружения

#########################################################################
telepresence --namespace {{ .Values.global.env }} --swap-deployment {{ .Chart.Name  }}:backend --mount=/tmp/app --docker-run -v `pwd`:/app -v /tmp/app/var/run/secrets:/var/run/secrets -ti registry.site.com/group/app/backend:v8
#########################################################################

No nos detendremos en detalle en los pasos descritos en esta instrucción... con excepción del último. ¿Qué sucede durante el lanzamiento de Telepresencia?

Trabajar con telepresencia

Al inicio (usando el último comando especificado en las instrucciones anteriores), configuramos:

  • espacio de nombres en el que se ejecuta el microservicio;
  • nombres de la implementación y el contenedor que queremos penetrar.

Los argumentos restantes son opcionales. Si nuestro servicio interactúa con y para la API de Kubernetes Cuenta de servicio creada, necesitamos montar certificados/tokens en nuestro escritorio. Para hacer esto, use la opción --mount=true (o --mount=/dst_path), que montará la raíz (/) del contenedor de Kubernetes en nuestro escritorio. Después de esto, podemos (dependiendo del sistema operativo y de cómo se inicia la aplicación) utilizar las “claves” del clúster.

Primero, veamos la opción más universal para ejecutar una aplicación: en un contenedor Docker. Para ello usaremos la clave --docker-run y monte el directorio con el código en el contenedor: -v `pwd`:/app

Tenga en cuenta que esto supone que se ejecuta desde el directorio del proyecto. El código de la aplicación se montará en el directorio. /app en un contenedor

Siguiente: -v /tmp/app/var/run/secrets:/var/run/secrets — para montar el directorio con el certificado/token en un contenedor.

A esta opción le sigue finalmente la imagen en la que se ejecutará la aplicación. NB: Al crear una imagen, debe especificar CMD o ENTRYPOINT!

¿Qué pasará exactamente a continuación?

  • En Kubernetes, para la implementación especificada, el número de réplicas se cambiará a 0. En su lugar, se lanzará una nueva implementación, con un contenedor sustituto. backend.
  • Se lanzarán 2 contenedores en el escritorio: el primero con Telepresencia (proxy solicitudes desde/hacia Kubernetes), el segundo con la aplicación en desarrollo.
  • Si ejecutamos la ejecución en el contenedor con la aplicación, todas las variables ENV transferidas por Helm durante la implementación estarán disponibles para nosotros y todos los servicios también estarán disponibles. Ya sólo queda editar el código en tu IDE favorito y disfrutar del resultado.
  • Al final del trabajo, solo necesita cerrar el terminal en el que se está ejecutando Telepresence (terminar la sesión con Ctrl+C): los contenedores Docker se detendrán en el escritorio y en Kubernetes todo volverá a su estado inicial. Todo lo que queda es confirmar, emitir el MR y transferirlo para revisar/fusionar/… (dependiendo de sus flujos de trabajo).

Si no queremos ejecutar la aplicación en un contenedor Docker (por ejemplo, no desarrollamos en PHP, sino en Go, y aun así la compilamos localmente), iniciar Telepresence será aún más sencillo:

telepresence --namespace {{ .Values.global.env }} --swap-deployment {{ .Chart.Name  }}:backend --mount=true

Si la aplicación accede a la API de Kubernetes, deberá montar el directorio de claves (https://www.telepresence.io/howto/volumes). Hay una utilidad para Linux. prueba:

proot -b $TELEPRESENCE_ROOT/var/run/secrets/:/var/run/secrets bash

Después de iniciar Telepresencia sin la opción --docker-run Todas las variables de entorno estarán disponibles en la terminal actual, por lo que la aplicación debe iniciarse en ella.

NB: Cuando utilice, por ejemplo, PHP, debe recordar desactivar varios op_cache, apc y otros aceleradores para el desarrollo; de lo contrario, editar el código no conducirá al resultado deseado.

resultados

El desarrollo local con Kubernetes es un problema cuya solución crece en proporción a la difusión de esta plataforma. Al recibir solicitudes relevantes de los desarrolladores (de nuestros clientes), comenzamos a resolverlas con los primeros medios disponibles, que, sin embargo, no dieron resultado a largo plazo. Afortunadamente, esto se ha vuelto obvio no solo ahora y no solo para nosotros, por lo que ya han aparecido en el mundo medios más adecuados, y la Telepresencia es el más famoso de ellos (por cierto, también existe patín de Google). Nuestra experiencia con su uso aún no es tan buena, pero ya nos da motivos para recomendarlo a nuestros “colegas de taller”: ¡pruébalo!

PS

Otros de la serie de consejos y trucos del K8:

Fuente: habr.com

Añadir un comentario