Al igual que cualquier otra solución, Helm, el administrador de paquetes de Kubernetes, tiene ventajas, desventajas y alcance, por lo que al usarlo, debe evaluar correctamente sus expectativas ...
Usamos Helm en nuestro arsenal de herramientas de laminación continua. Al momento de escribir, hay
más de mil aplicaciones en nuestros clústeres y alrededor de 4000 instalaciones de estas aplicaciones en diversas variaciones. Periódicamente encontramos problemas, pero en general estamos satisfechos con la solución, no tenemos tiempo de inactividad ni pérdida de datos.
El motivo principal para escribir este artículo es proporcionar al usuario una
evaluación objetiva de los principales problemas de Helm 2 sin conclusiones definitivas, así como el deseo de compartir experiencias y nuestras soluciones.
[ERROR] Después de la implementación, el estado de los recursos de liberación en el clúster no corresponde al gráfico Helm descrito
Al trabajar, Helm no tiene en cuenta el estado de los recursos de liberación en el clúster. Al reinstalar, el resultado está determinado solo por las configuraciones actuales y guardadas. Por lo tanto, el estado del recurso en el clúster y el registro de Helm es diferente, y Helm no tiene esto en cuenta.
Considere cómo se manifiesta este problema:
- La plantilla de recursos en el gráfico corresponde al estado X.
- El usuario instala el gráfico (Tiller guarda el estado del recurso X).
- A continuación, el usuario cambia manualmente el recurso en el clúster (el estado cambia de X a Y).
- Sin realizar ningún cambio, realiza la
helm upgrade
... Y el recurso todavía está en estado Y, aunque el usuario espera X.
Y eso no es todo. En algún momento, el usuario cambia la plantilla de recursos en el gráfico (nuevo estado W), luego tenemos dos escenarios después de la
helm upgrade
:
- La aplicación del parche XW está cayendo.
- Después de aplicar el parche, el recurso pasa al estado Z, que no corresponde al deseado.
Para evitar este problema, se propone organizar el trabajo con versiones de la siguiente manera:
nadie debe cambiar los recursos manualmente , Helm es la única herramienta para trabajar con los recursos de la versión. Idealmente, los cambios de gráficos se versionan en el repositorio de Git y se aplican
exclusivamente dentro del CD.
Si esta opción no es adecuada, puede
supervisar la sincronización de los estados de los recursos de la versión. La sincronización manual puede verse así:
- Descubrimos el estado de los recursos de lanzamiento a través de
helm get
. - Descubra el estado de los recursos en Kubernetes a través de
kubectl get
. - Si los recursos son diferentes, sincronizamos Helm con Kubernetes:
- Crea una rama separada.
- Actualización de los manifiestos de la tabla. Las plantillas deben coincidir con los estados de recursos en Kubernetes.
- Realizamos el despliegue. Sincronizamos el estado en el registro de Helm y el clúster.
- Después de eso, la rama se puede eliminar y continuar con el trabajo regular.
Al aplicar parches utilizando el
kubectl apply
, se ejecuta la llamada
fusión de 3 vías, es decir, Se tiene en cuenta el estado real del recurso actualizado. Puede ver el código del algoritmo
aquí y leer sobre esto
aquí .
Al momento de escribir, los desarrolladores de Helm están buscando formas de implementar la fusión de 3 vías en Helm 3. Con Helm 2, las cosas no son tan optimistas: la fusión de 3 vías no está planificada para implementarse, pero hay un RP para corregir la forma en que se crean los recursos: puede encontrar detalles o incluso participar como parte de la
cuestión relevante .
[ERROR] Error: no se encontró ningún RECURSO con el nombre NOMBRE
El problema se manifiesta si los
nuevos recursos se crean con éxito cuando se repite el despliegue, y el despliegue en sí mismo finalmente falla.
Nuevos recursos significan aquellos que no estaban en la última instalación de la tabla.
Si el despliegue falla, la versión se guarda en el registro marcado
FAILED , y durante la instalación, Helm se basa en el estado de la última versión
DESPLEGADA , que en este caso no sabe nada sobre los nuevos recursos. Como resultado, Helm intenta recrear estos recursos y falla con el error "no se encontró ningún RECURSO con el nombre NAME" (el error dice lo contrario, pero este es el problema). Parte del problema es que Helm no tiene en cuenta el estado de los recursos de liberación en el clúster al crear el parche, como se describe en la sección anterior.
Por ahora, la única solución es eliminar manualmente los nuevos recursos.
Para evitar tal estado, es posible eliminar automáticamente los nuevos recursos creados en la actualización / reversión actual si el comando finalmente falla. Después de una larga discusión con los desarrolladores de Helm, para los comandos de actualización / reversión, se agregó la opción
--cleanup-on-fail
, que activa la limpieza automática cuando falla la implementación. Nuestro
RP está en discusión, buscando la mejor solución.
A partir de la versión 2.13 de Helm, la opción
--atomic
aparece en los
--atomic
helm install/upgrade
, que activa la limpieza y la reversión durante una instalación fallida (para más detalles, consulte
PR ).
[ERROR] Error: reloj cerrado antes Hasta el tiempo de espera
El problema puede ocurrir cuando el enlace Helm se ejecuta durante demasiado tiempo (por ejemplo, durante las migraciones), aunque no se excedan los tiempos de espera especificados de
helm install/upgrade
de
helm install/upgrade
y
spec.activeDeadlineSeconds
trabajo correspondiente.
Este error es generado por el servidor API de Kubernetes mientras espera que se complete el trabajo de enlace. Helm no maneja este error y se bloquea inmediatamente, en lugar de volver a intentar la solicitud de espera.
Como solución, puede aumentar el tiempo de espera en api-server:
--min-request-timeout=xxx
en el archivo
/etc/kubernetes/manifests/kube-apiserver.yaml
.
[ERROR] Error: NO SE PUEDE ACTUALIZAR: "foo" no tiene lanzamientos implementados
Si falla la primera versión a través de la
helm install
, la
helm upgrade
posterior de
helm upgrade
devolverá un error similar.
Parece que la solución es bastante simple: necesita realizar manualmente la
helm delete --purge
después de una primera instalación fallida, pero esta acción manual interrumpe la automatización de CI / CD. Para no interrumpir la ejecución de comandos manuales, puede utilizar las funciones
werf para
implementar . Al usar werf, la versión problemática se volverá a crear automáticamente tras la reinstalación.
Además, comenzando con Helm 2.13, en los
helm upgrade --install
helm install
y
helm upgrade --install
simplemente especifique la opción
--atomic
y, después de una instalación fallida, la versión se eliminará automáticamente (consulte
PR para más detalles).
Autorollback
Helm carece de la opción
--autorollback
, que, cuando
--autorollback
, recordará la revisión exitosa actual (se eliminará si la última revisión no es exitosa) y, después de un intento de implementación fallido, regresará a la revisión guardada.
Dado que es crítico que el producto funcione sin interrupciones, es necesario buscar soluciones, la implementación debe ser predecible. Para minimizar la probabilidad de tiempo de inactividad del producto, a menudo se utiliza un
enfoque con varios circuitos (por ejemplo, etapas, qa y producción), que consiste en el despliegue secuencial en los circuitos. Con este enfoque, la mayoría de los problemas se solucionan antes de lanzarlos a la productividad y, junto con el autorolback, le permite lograr buenos resultados.
Para organizar el retroceso automático, puede usar el complemento
helm-monitor , que le permite vincular el retroceso a las métricas de Prometheus. Un buen artículo que describe este enfoque está disponible
aquí .
Para algunos de nuestros proyectos, se utiliza un enfoque bastante simple:
- Antes del despliegue, recordamos la revisión actual (creemos que en una situación normal, si la versión existe, entonces necesariamente está en el estado DESPLEGADO):
export _RELEASE_NAME=myrelease export _LAST_DEPLOYED_RELEASE=$(helm list -adr | \ grep $_RELEASE_NAME | grep DEPLOYED | head -n2 | awk '{print $2}')
- Ejecute instalar o actualizar:
helm install/upgrade ... || export _DEPLOY_FAILED=1
- Verificamos el estado de la implementación y hacemos la reversión al estado guardado:
if [ "$_DEPLOY_FAILED" == "1" ] && [ "x$_LAST_DEPLOYED_RELEASE" != "x" ] ; then helm rollback $_RELEASE_NAME $_LAST_DEPLOYED_RELEASE fi
- Terminamos la canalización con un error si la implementación no tuvo éxito:
if [ "$_DEPLOY_FAILED" == "1" ] ; then exit 1 ; fi
Nuevamente, comenzando con la versión 2.13 de Helm, cuando se llama a la
helm upgrade
Helm
helm upgrade
suficiente especificar la opción
--atomic
y luego de una instalación fallida, la reversión se realizará automáticamente (ver
PR para más detalles).
Esperando la disponibilidad de recursos de lanzamiento y comentarios al momento del lanzamiento
Según lo planeado, Helm debe monitorear la ejecución de las pruebas de vida y preparación correspondientes cuando se usa la opción
--wait
:
--wait if set, will wait until all Pods, PVCs, Services, and minimum number of Pods of a Deployment are in a ready state before marking the release as successful. It will wait for as long as --timeout
Esta función no funciona correctamente ahora: no todos los recursos y no todas las versiones de API son compatibles. Y el proceso de espera declarado en sí no satisface nuestras necesidades.
Al igual que con
kubectl wait
, no hay comentarios rápidos y no hay forma de regular este comportamiento. Si el despliegue falla, lo sabremos
solo después de un tiempo de espera . En caso de una instalación problemática, es necesario completar el proceso de implementación lo antes posible, voltear la tubería de CI / CD, revertir el lanzamiento a la versión de trabajo y proceder a la depuración.
Si la versión problemática se revierte y Helm no devuelve ninguna información durante el proceso de implementación, ¿de qué se trata la depuración? En el caso de
kubectl wait
puede organizar un proceso separado para mostrar registros, lo que requerirá liberar nombres de recursos. Cómo organizar una solución simple y funcional no está claro de inmediato. Y además de los registros de pod, puede contener información útil en el proceso de implementación, eventos de recursos ...
Nuestra
utilidad werf CI / CD puede implementar un gráfico Helm y monitorear la disponibilidad de recursos, así como mostrar información relacionada con el despliegue. Todos los datos se combinan en una sola secuencia y se envían al registro.
Esta lógica se realiza en una solución de
kubedog separada. Con la utilidad, puede suscribirse a un recurso y recibir eventos y registros, así como aprender sobre despliegues fallidos de manera oportuna. Es decir Como solución, después de llamar a
helm install/upgrade
sin la opción
--wait
, puede llamar a kubedog para cada recurso de lanzamiento.
Nuestro objetivo era crear una herramienta que proporcione toda la información necesaria para la depuración en la salida de la canalización de CI / CD. Lea más sobre la utilidad en
nuestro artículo reciente .
Quizás en Helm 3 algún día aparezca una solución similar, pero hasta ahora nuestro
problema está en un estado suspendido.
Seguridad cuando se usa helm init por defecto
De manera predeterminada, cuando se ejecuta el
helm init
, el componente del servidor se instala en el clúster con privilegios similares al superusuario, lo que puede tener consecuencias no deseadas cuando terceros acceden a él.
Para garantizar la seguridad del clúster, es necesario limitar las capacidades de Tiller, así como cuidar la conexión: la seguridad de la red a través de la cual se lleva a cabo la comunicación entre los componentes de Helm.
El primero se puede lograr mediante el uso del mecanismo estándar Ruber Kubernetes, que limitará las acciones del timón, y el segundo, mediante la configuración de SSL. Lea más en la documentación de Helm:
Asegurar su instalación de Helm .
Se cree que la presencia del componente del servidor, Tiller, es un grave error arquitectónico , literalmente un recurso extranjero con derechos de superusuario en el ecosistema de Kubernetes. En parte, estamos de acuerdo: la implementación es imperfecta, pero echemos un vistazo a esto desde el otro lado . Si interrumpe el proceso de implementación y elimina el cliente Helm, el sistema no permanecerá en un estado indefinido, es decir, Tiller traerá el estado de lanzamiento a válido. También es necesario comprender que a pesar del hecho de que Tiller se abandona en Helm 3, estas funciones serán de alguna manera realizadas por el controlador CRD.Martian Go Templates
Las plantillas Go tienen un umbral de entrada grande, pero la tecnología no tiene limitaciones en las capacidades y problemas con DRY. Los principios básicos, la sintaxis, las funciones y los operadores se analizan en nuestro
artículo anterior de la serie Helm.
Falta de secretos fuera de la caja
Es conveniente almacenar y mantener el código de la aplicación, la infraestructura y las plantillas de implementación cuando se encuentran en un solo lugar. Y los secretos no son la excepción.
Helm no admite secretos listos para usar, sin embargo, el complemento
helm-secrets está disponible, que es esencialmente una capa entre
sops , el administrador de secretos de Mozilla y Helm.
Cuando trabajamos con secretos, utilizamos nuestra propia solución implementada en
werf (
documentación sobre secretos ). De las características:
- Facilidad de implementación.
- Mantener un secreto en un archivo, no solo en YAML. Conveniente al almacenar certificados, llaves.
- Regeneración de secretos con una nueva clave.
- Implementación sin una clave secreta (cuando se utiliza werf). Puede ser útil para aquellos casos en que el desarrollador no tiene esta clave secreta, pero es necesario iniciar una implementación en una prueba o circuito local.
Conclusión
Helm 2 se posiciona como un producto estable, pero al mismo tiempo hay muchos errores que cuelgan en el limbo (¡algunos de ellos duran varios años!). En lugar de soluciones, o al menos parches, todos los esfuerzos se dedican al desarrollo de Helm 3.
A pesar del hecho de que MR y el problema pueden colgar durante meses (
aquí hay un ejemplo de cómo agregamos una
before-hook-creation policy
de anzuelos antes de anzuelos durante varios meses), aún puede participar en el desarrollo del proyecto. Todos los jueves hay una reunión de media hora de desarrolladores de Helm, donde puedes aprender sobre las prioridades y las instrucciones actuales del equipo, hacer preguntas y forzar tus propias mejores prácticas. Acerca de mete y otros canales de comunicación se escribe en detalle
aquí .
Si usar Helm o no depende de usted, por supuesto. Hoy nos adherimos a una posición tal que, a pesar de las deficiencias, Helm es una solución aceptable para el despliegue y es útil para que toda la comunidad participe en su desarrollo.
PS
Lea también en nuestro blog: