Jenkins en Kubernetes Engine

En este artículo, se presentan las prácticas recomendadas para usar Jenkins con Google Kubernetes Engine. A fin de implementar esta solución, consulta cómo configurar Jenkins en Kubernetes Engine.

Jenkins es un servidor de automatización de código abierto que te permite organizar de manera flexible tus canalizaciones de compilación, de prueba y de implementación. Kubernetes Engine es una versión alojada de Kubernetes, un administrador de clústeres y un sistema de organización para contenedores eficaz.

Cuando necesitas configurar una canalización de entrega continua (EC), la implementación de Jenkins en Kubernetes Engine proporciona beneficios importantes en comparación con una implementación estándar basada en VM.

  • Cuando se usan contenedores en el proceso de compilación, un host virtual puede ejecutar trabajos en diferentes sistemas operativos.

  • Kubernetes Engine proporciona ejecutores de compilación efímeros, lo que permite que cada compilación se ejecute en un entorno limpio idéntico a las compilaciones anteriores.

    • Como parte del carácter efímero de los ejecutores de compilación, el clúster de Kubernetes Engine solo se usa cuando las compilaciones se ejecutan de forma activa, lo que deja recursos disponibles para otras tareas del clúster, como los trabajos de procesamiento por lotes.

    • Compila el lanzamiento de ejecutores en segundos.

  • Kubernetes Engine aprovecha el balanceador de cargas global de Google para dirigir el tráfico web a tu instancia. El balanceador de cargas administra la finalización de SSL y proporciona una dirección IP global que enruta los usuarios al frontend web en una de las rutas más rápidas desde el punto de presencia más cercano a tus usuarios, a través de la red troncal de Google.

Para obtener más información sobre Jenkins en Kubernetes Engine, mira la charla de Next 2018 en YouTube:

Los informes Estado de DevOps identificaron las capacidades que impulsan el rendimiento de la entrega de software. En este tema, encontrarás ayuda para las siguientes funciones:

Implementa el controlador de Jenkins con Helm

Usa Helm para implementar Jenkins desde el repositorio de gráficos. Helm es un administrador de paquetes que puedes usar para configurar y, luego, implementar apps de Kubernetes.

En la siguiente imagen, se describe la arquitectura para implementar Jenkins en un clúster de Kubernetes de varios nodos.

Arquitectura de Jenkins y Kubernetes

Implementa el controlador de Jenkins en un espacio de nombres independiente en el clúster de Kubernetes. Los espacios de nombres permiten crear cuotas para la implementación de Jenkins y, también, separar Jenkins de forma lógica de otras implementaciones dentro del clúster.

Crea servicios de Jenkins

Jenkins proporciona dos servicios a los que el clúster necesita acceder. Implementa estos servicios por separado para que se puedan administrar y nombrar de manera individual.

  • Un servicio de NodePort expuesto de forma externa en el puerto 8080 que permite que los Pods y los usuarios externos accedan a la interfaz de usuario de Jenkins. Este tipo de servicio puede obtener un balanceo de cargas a través de un balanceador de cargas de HTTP

  • Un servicio de ClusterIP interno privado en el puerto 50000 que los ejecutores de Jenkins usan para comunicarse con el controlador de Jenkins desde el interior del clúster

En las siguientes secciones, se muestran ejemplos de definiciones de servicios. (El controlador se llama master en las definiciones).

---
  kind: Service
  apiVersion: v1
  metadata:
    name: jenkins-ui
    namespace: jenkins
  spec:
    type: NodePort
    selector:
      app: master
    ports:
      - protocol: TCP
        port: 8080
        targetPort: 8080
        name: ui
---
  kind: Service
  apiVersion: v1
  metadata:
    name: jenkins-discovery
    namespace: jenkins
  spec:
    selector:
      app: master
    ports:
      - protocol: TCP
        port: 50000
        targetPort: 50000
        name: slaves

Crea la implementación de Jenkins

Implementa el controlador de Jenkins como una implementación con un recuento de réplicas de 1. Esto garantiza que se ejecute un solo controlador de Jenkins en el clúster en todo momento. Si el Pod del controlador de Jenkins se apaga o el nodo en el que se ejecuta se cierra, Kubernetes reinicia el Pod en otra ubicación del clúster.

Es importante configurar solicitudes y límites como parte de la implementación de Helm, de modo que el contenedor tenga garantizada una cierta cantidad de recursos de CPU y memoria dentro del clúster antes de que se programe. De lo contrario, el controlador podría fallar debido a la falta de CPU o memoria.

El volumen local de Jenkins almacena archivos de configuración XML y los archivos JAR de complementos que conforman tu configuración. Estos datos se almacenan en un disco persistente administrado por el clúster de GKE y se conservarán en los reinicios de Jenkins. Para cambiar el tamaño del disco persistente, edita el valor Persistence.Size cuando instales Jenkins con Helm.

Conéctate a Jenkins

Una vez creado el Pod de Jenkins, puedes crear un extremo de balanceador de cargas para conectarte desde el exterior de Cloud Platform. Considera las siguientes prácticas recomendadas:

  • Usa un recurso Ingress de Kubernetes para obtener un balanceador de cargas L7 fácil de configurar con una finalización de SSL.

  • Proporciona certificados SSL para el balanceador de cargas mediante el uso de los secretos de Kubernetes. Usa los valores tls.cert y tls.key, y haz referencia a ellos en la configuración del recurso Ingress.

Configura Jenkins

Protege Jenkins

Después de conectarte a Jenkins por primera vez, es importante que lo protejas de inmediato. Puedes seguir el instructivo de configuración de seguridad estándar de Jenkins para ver un procedimiento simple que aprovecha una base de datos de usuarios interna. Esta configuración no requiere infraestructura adicional y permite bloquear usuarios anónimos.

Instala complementos

Puedes instalar los siguientes complementos para mejorar las interacciones entre Jenkins y Kubernetes Engine.

  • El complemento de Kubernetes permite usar cuentas de servicio de Kubernetes para la autenticación y crear parámetros de configuración de ejecutores etiquetados con diferentes imágenes base. El complemento crea un Pod cuando se necesita un ejecutor y lo destruye cuando un trabajo finaliza.

  • El complemento Google Authenticated Source permite el uso de las credenciales de las cuentas de servicio cuando se accede a los servicios de Cloud Platform, como Cloud Source Repositories.

Para agregar complementos adicionales mediante el gráfico de Helm, edita la lista de complementos en el archivo de valores que pasas a los comandos de instalación o actualización de Helm.

Personaliza la imagen de Docker del agente de Jenkins

Cuando creas una plantilla de Pods, puedes proporcionar una imagen de Docker existente o puedes crear una personalizada que tenga instaladas la mayoría de las dependencias del tiempo de compilación. El uso de una imagen personalizada puede reducir el tiempo de compilación general y crear entornos de compilación más coherentes.

La imagen de Docker personalizada debe instalar y configurar el agente entrante de JPLP de Jenkins. El agente de JNLP es un software que se comunica con el controlador de Jenkins a fin de coordinar la ejecución de los trabajos de Jenkins y para informar el estado de los trabajos.

Una opción es agregar FROM jenkins/inbound-agent a la configuración de la imagen. Por ejemplo, si el proceso de compilación de la aplicación depende del entorno de ejecución de Go, puedes crear el siguiente Dockerfile para extender la imagen existente con tus propias dependencias y artefactos de compilación.

FROM jenkins/inbound-agent
RUN apt-get update && apt-get install -y golang

Luego, compila y sube la imagen al repositorio de Container Registry del proyecto mediante la ejecución de los siguientes comandos.

docker build -t gcr.io/[PROJECT]/my-jenkins-image .
gcloud auth configure-docker
docker push gcr.io/[PROJECT]/my-jenkins-image

Cuando creas una plantilla de Pods, puedes configurar el campo de la imagen de Docker como la siguiente string, en la que [PROJECT] se reemplaza por el nombre del proyecto y [IMAGE_NAME] se reemplaza por el nombre de la imagen.

gcr.io/[PROJECT]/[IMAGE_NAME]

En el ejemplo anterior, se garantiza que el entorno de ejecución del lenguaje Go esté preinstalado cuando comience el trabajo de Jenkins.

Compila imágenes de Docker en Jenkins

Cloud Build se puede usar desde los trabajos de Jenkins para compilar imágenes de Docker sin necesidad de alojar tu propio daemon de Docker. El trabajo de Jenkins debe tener credenciales de cuentas de servicio disponibles a las que se les haya otorgado la función cloudbuild.builds.editor.

Para obtener un ejemplo de un archivo de canalización de Jenkins, consulta el siguiente repositorio de GitHub.

Kaniko es otra opción para los usuarios que desean compilar contenedores dentro de sus clústeres. Kaniko no requiere un daemon de Docker para compilar y enviar imágenes a un registro remoto.

Para ver un ejemplo del uso de Kaniko en Jenkins, consulta el siguiente repositorio de GitHub.

Próximos pasos