Press "Enter" to skip to content

C贸mo instalar Jenkins en Kubernetes

Hace poco a solicitud de un cliente tuve que realizar la instalaci贸n de Jenkins sobre un cl煤ster de Kubernetes EKS (AWS), y de esta manera poder aprovechar las caracter铆sticas de alta disponibilidad, escalamiento horizontal, inicio de agentes a demanda, etc. que brinda Kubernetes.

Luego de revisar la diversa documentaci贸n existente y de realizar varias pruebas de concepto, encontr茅 que a parte del despliegue del cl煤ster en s铆, eran necesarios otros componentes que permitieran el correcto funcionamiento de una aplicaci贸n en K8s (Jenkins en este caso).

En el presente proyecto, he tratado de describir este proceso de la manera m谩s detallada posible. Aunque puede parecer tedioso en un inicio, una vez comprendidos los conceptos replicar el procedimiento no debe tomarnos m谩s de unos cuantos minutos.

Si bien este procedimiento ha sido desarrollado pensado en el despliegue de Jenkins, puede adaptarse f谩cilmente a cualquier tipo de aplicaci贸n conteinerizada, o simplemente para el despliegue correcto de un cl煤ster Kubernetes sobre AWS.

馃敯 Requerimientos Iniciales

馃寜 Arquitectura Jenkins sobre Kubernetes

A continuaci贸n se muestra la arquitectura de componentes de la aplicaci贸n Jenkins sobre un cl煤ster de Kubernetes EKS (AWS).

kubernetes aws eks cluster jenkins
Arquitectura Jenkins sobre un Cl煤ster de Kubernetes

En el diagrama se puede apreciar lo siguiente:

  • Los recursos utilizados por Jenkins (pods, services, pvc, serviceAccount, ingress, etc. ) ir谩n desplegados en su propio namespace, aisl谩ndolos de otros servicios / aplicaciones ya existentes en el cl煤ster.
  • El deployment de Jenkins puede implementarse en uno o m谩s pods brindando alta disponibilidad y escalamiento horizontal.
  • Los agentes Jenkins se levantan a demanda como pods y existen s贸lo durante el tiempo de ejecuci贸n del pipeline, luego de que 茅ste finaliza el pod se destruye autom谩ticamente y se liberan los recursos.
  • Si en un futuro el cl煤ster se queda sin recursos de CPU / memoria, simplemente deben agregarse m谩s nodos Kubernetes tipo Worker al cl煤ster.
  • Los nodos tipo Worker en EKS por defecto usan el sistema operativo Amazon Linux 2.
  • El servicio de Jenkins ser谩 expuesto p煤blicamente a trav茅s de un ingress, el cual a su vez est谩 enlazado con un Application Load Balancer (ALB). Es a trav茅s de este ALB que podremos acceder a nuestra aplicaci贸n desde Internet.

馃彈锔 Despliegue de un Cl煤ster Kubernetes en AWS EKS

鈿欙笍 Desplegando el cl煤ster con eksctl

En mi experiencia, la manera m谩s f谩cil para desplegar un cl煤ster Kubernetes (EKS) en AWS es usando la herramienta eksctl.

Eksctl nos crear谩 de manera autom谩tica las plantillas de CloudFormation que desplegar谩n los recursos solicitados en AWS.

Teniendo eksctl correctamente instalado y configurado, ejecutar el siguiente comando en una terminal:

eksctl create cluster --name "my-cluster" --region "us-east-1" --zones "us-east-1a,us-east-1b" --version 1.24 --node-type "t2.small" --nodes 2 --nodes-min 1 --nodes-max 2 --with-oidc --alb-ingress-access --spot

Vamos a explicar las principales opciones de la l铆nea de comandos anterior:

  • –name: El nombre que llevar谩 el cl煤ster, en este caso my-cluster.
  • –region: La regi贸n AWS sobre la que se desplegar谩 el cl煤ster, nosotros usaremos us-east-1.
  • –zones: Las zonas de disponibilidad (subnets) dentro de la regi贸n sobre las que funcionar谩 el cl煤ster. Para nuestro caso y por simplicidad s贸lo seleccionamos 2, pero pueden ser m谩s.
  • –version: La versi贸n de Kubernetes a utilizar.
  • –node-type: El tipo de instancia que se utilizar谩 para desplegar los nodos. En nuestro ejemplo usaremos t2.small.
  • –nodes, –nodes-min, –nodes-max: N煤mero de nodos inicial, m铆nimo y m谩ximo que tendr谩 el cl煤ster
  • –spot (Opcional): Desplegar谩 las instancias EC2 como tipo spot ahorrando costos. No usar esta opci贸n en despliegues para producci贸n.

Al ejecutar esta l铆nea de comando, veremos una salida como la siguiente:

14:38:34  eksctl version 0.122.0
14:38:34  using region us-east-1
14:38:34  subnets for us-east-1a - public:192.168.0.0/19 private:192.168.64.0/19
14:38:34  subnets for us-east-1b - public:192.168.32.0/19 private:192.168.96.0/19
14:38:34  nodegroup "ng-0e78de48" will use "" [AmazonLinux2/1.24]
14:38:34  using Kubernetes version 1.24
14:38:34  creating EKS cluster "my-cluster" in "us-east-1" region with managed nodes
14:38:34  will create 2 separate CloudFormation stacks for cluster itself and the initial managed nodegroup
14:38:34  if you encounter any issues, check CloudFormation console or try 'eksctl utils describe-stacks --region=us-east-1 --cluster=my-cluster'
14:38:34  Kubernetes API endpoint access will use default of {publicAccess=true, privateAccess=false} for cluster "my-cluster" in "us-east-1"
.
.
14:57:04  waiting for CloudFormation stack "eksctl-my-cluster-nodegroup-ng-0e78de48"
14:57:04  waiting for the control plane to become ready
14:57:05 [鉁擼  saved kubeconfig as "C:\\Users\\John\\.kube\\config"
14:57:05  no tasks
14:57:05 [鉁擼  all EKS cluster resources for "my-cluster" have been created
14:57:06  nodegroup "ng-0e78de48" has 2 node(s)
14:57:06  node "ip-192-168-32-202.ec2.internal" is ready
14:57:06  node "ip-192-168-5-170.ec2.internal" is ready
14:57:06  waiting for at least 1 node(s) to become ready in "ng-0e78de48"
14:57:10  kubectl command should work with "C:\\Users\\John\\.kube\\config", try 'kubectl get nodes'
14:57:10 [鉁擼  EKS cluster "my-cluster" in "us-east-1" region is ready

Al terminar el despliegue, vamos a la consola de AWS y verificamos que nuestro cl煤ster EKS se haya desplegado correctamente:

Cl煤ster AWS EKS Kubernetes
Cl煤ster EKS reci茅n desplegado

馃敆 Configurando la conexi贸n al cl煤ster Kubernetes

Para acceder a nuestro nuevo cl煤ster, ya sea por l铆nea de comandos eksctl o de manera gr谩fica usando Lens, debemos actualizar nuestro archivo local de configuraci贸n de Kubernetes (~/.kube/config) con la informaci贸n correspondiente de conexi贸n. Para ello ejecutamos el siguiente comando:

aws eks update-kubeconfig --region "us-east-1" --name "my-cluster"
Updated context arn:aws:eks:us-east-1:680655248338:cluster/my-cluster in C:\Users\John\.kube\config

En el par谩metro –region colocamos la regi贸n en la cual desplegamos nuestro cl煤ster, y en –name el nombre del mismo.

A continuaci贸n verificamos que podamos conectarnos correctamente al cl煤ster usando kubectl:

kubectl cluster-info
Kubernetes control plane is running at https://******.gr7.us-east-1.eks.amazonaws.com
CoreDNS is running at https://******.gr7.us-east-1.eks.amazonaws.com/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
kubectl get nodes
NAME                             STATUS   ROLES    AGE    VERSION
ip-192-168-32-202.ec2.internal   Ready    <none>   113m   v1.24.7-eks-fb459a0
ip-192-168-5-170.ec2.internal    Ready    <none>   113m   v1.24.7-eks-fb459a0

Para el caso de Lens, una nueva conexi贸n aparecer谩 en la lista de cl煤steres disponibles:

EKS K8s Lens
Accediendo al cl煤ster Kubernetes usando Lens

馃捊 Instalaci贸n del controlador Amazon EBS CSI

Para poder aprovisionar vol煤menes de almacenamiento (unidades de disco) en nuestro cl煤ster, es necesario que instalemos un controlador de almacenamiento.

Para AWS EKS instalaremos el controlador Amazon EBS CSI (Elastic Block Store Container Storage Interface). Este driver nos permitir谩 crear y eliminar din谩micamente vol煤menes EBS (Elastic Block Store) para ser utilizados por las aplicaciones en nuestro cl煤ster.

馃懆鈥嶐煉 Creaci贸n del rol de IAM

Primero debemos crear el rol de IAM con el cual se ejecutar谩 el controlador EBS CSI en el cl煤ster. Para ello, en el siguiente comando reemplazamos my-cluster por el nombre de nuestro cl煤ster y lo ejecutamos:

eksctl create iamserviceaccount \
  --name ebs-csi-controller-sa \
  --namespace kube-system \
  --cluster my-cluster \
  --attach-policy-arn arn:aws:iam::aws:policy/service-role/AmazonEBSCSIDriverPolicy \
  --approve \
  --role-only \
  --role-name AmazonEKS_EBS_CSI_DriverRole

Verificamos que el comando termine de ejecutarse correctamente:

17:35:34  1 existing iamserviceaccount(s) (kube-system/aws-node) will be excluded
17:35:34  1 iamserviceaccount (kube-system/ebs-csi-controller-sa) was included (based on the include/exclude rules)
17:35:34  serviceaccounts that exist in Kubernetes will be excluded, use --override-existing-serviceaccounts to override
17:35:34  1 task: { create IAM role for serviceaccount "kube-system/ebs-csi-controller-sa" }
17:35:34  building iamserviceaccount stack "eksctl-my-cluster-addon-iamserviceaccount-kube-system-ebs-csi-controller-sa"
17:35:34  deploying stack "eksctl-my-cluster-addon-iamserviceaccount-kube-system-ebs-csi-controller-sa"
17:35:34  waiting for CloudFormation stack "eksctl-my-cluster-addon-iamserviceaccount-kube-system-ebs-csi-controller-sa"

馃獩 Instalaci贸n del controlador usando eksctl o AWS CLI

Ahora realizaremos la instalaci贸n del controlador en s铆. En el siguiente comando, reemplazamos my-cluster por el nombre de nuestro cl煤ster y el valor de 111122223333 por nuestro identificador de cuenta de AWS:

eksctl create addon --name aws-ebs-csi-driver --cluster my-cluster --service-account-role-arn arn:aws:iam::111122223333:role/AmazonEKS_EBS_CSI_DriverRole

Tambi茅n podemos realizar la misma tarea usando AWS CLI:

aws eks create-addon --cluster-name my-cluster --addon-name aws-ebs-csi-driver --service-account-role-arn arn:aws:iam::111122223333:role/AmazonEKS_EBS_CSI_DriverRole

Verificamos que el driver haya terminado de instalarse correctamente:

2023-01-08 11:53:31 [鈩筣  Kubernetes version "1.24" in use by cluster "my-cluster"
2023-01-08 11:53:32 [鈩筣  using provided ServiceAccountRoleARN "arn:aws:iam::680655248338:role/AmazonEKS_EBS_CSI_DriverRole"
2023-01-08 11:53:32 [鈩筣  creating addon
AWS EKS EBS CSI Driver
Driver Amazon EBS CSI instal谩ndose

馃搳 Instalaci贸n de Prometheus para el monitoreo del cl煤ster

Para el monitoreo b谩sico del estado de nuestro cl煤ster, instalaremos la aplicaci贸n Prometheus. Esto lo realizaremos usando el comando helm.

Primero agregamos el repositorio de charts de Prometheus y actualizamos nuestra cach茅 local:

helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update

Instalamos el chart de Prometheus:

helm install prometheus prometheus-community/prometheus

Una vez Prometheus est茅 instalado, podremos ver en los widgets de monitoreo de Lens informaci贸n de uso de recursos como CPU, memoria, etc.:

consumo cpu memoria kubernetes prometheus
Widgets de consumo de CPU y Memoria del Cl煤ster despu茅s de instalar Prometheus
kubernetes lens prometheus 2
Consumo de CPU y Memoria por Nodo despu茅s de instalar Prometheus

馃寪 Instalaci贸n del controlador AWS Load Balancer

Para poder publicar nuestros servicios en Kubernetes y as铆 est茅n disponibles en Internet, es necesario contar con un controlador que mapee estos servicios con un balanceador de carga correspondiente al proveedor de cloud que estemos utilizando.

Para el caso de AWS es necesario instalar el AWS Load Balancer Controller. Este controlador nos permitir谩 mapear un ingress o servicio de Kubernetes a un Application Load Balancer (ALB) o Network Load Balancer (NLB), seg煤n sea el caso.

馃懆鈥嶐煉 Creaci贸n de la pol铆tica y rol de IAM

Primero creamos la pol铆tica que utilizar谩 el rol. Ejecutamos:

curl -o iam_policy.json https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.4.4/docs/install/iam_policy.json
aws iam create-policy --policy-name AWSLoadBalancerControllerIAMPolicy --policy-document file://iam_policy.json

Creamos el rol IAM y Service Account con el cual se ejecutar谩 el controlador a instalar. Reemplazamos my-cluster con el nombre de nuestro cl煤ster y el valor de 111122223333 lo reemplazamos por nuestro identificador de cuenta de AWS. Ejecutamos:

eksctl create iamserviceaccount \
  --cluster=my-cluster \
  --namespace=kube-system \
  --name=aws-load-balancer-controller \
  --role-name "AmazonEKSLoadBalancerControllerRole" \
  --attach-policy-arn=arn:aws:iam::111122223333:policy/AWSLoadBalancerControllerIAMPolicy \
  --approve

馃獩 Instalaci贸n del controlador con Helm

Instalaremos el controlador usando helm. Primero agregamos el Helm chart correspondiente y actualizamos:

helm repo add eks https://aws.github.io/eks-charts
helm repo update

En el siguiente comando, reemplazamos my-cluster con el nombre de nuestro cl煤ster, los valores 602401143452 y us-east-1 debes reemplazarlos con los valores correspondientes a tu caso seg煤n el siguiente cuadro. Ejecutamos el comando y verificamos que termine correctamente.

helm install aws-load-balancer-controller eks/aws-load-balancer-controller \
  -n kube-system \
  --set clusterName=my-cluster \
  --set serviceAccount.create=false \
  --set serviceAccount.name=aws-load-balancer-controller \
  --set image.repository=602401143452.dkr.ecr.us-east-1.amazonaws.com/amazon/aws-load-balancer-controller

馃殌 Despliegue de Jenkins en Kubernetes

Ya tenemos nuestro cl煤ster Kubernetes ejecut谩ndose y con todos los plugins necesarios, as铆 que ya podemos proceder a instalar Jenkins.

Si a煤n no lo haz hecho, clona el repositorio de c贸digo en GitHub correspondiente al presente art铆culo:

git clone https://github.com/jruizcampos/jenkins-k8s.git

馃敥 Creando los recursos de Jenkins en Kubernetes

Ubicados en la carpeta del repositorio clonado, ejecutamos los siguientes comandos. Creamos el namespace, Service Account y volumen necesarios:

kubectl apply -f namespace.yaml
kubectl apply -f serviceAccount.yaml
kubectl apply -f volume.yaml

Creamos el deployment de Jenkins y su servicio de acceso correspondiente:

kubectl apply -f deployment.yaml
kubectl apply -f service.yaml

鈿 Configurando el Ingress y Load Balancer en AWS

Para configurar el ingress en Kubernetes, necesitamos la lista de subnets p煤blicas configuradas en nuestro cl煤ster EKS. Para ello, desde la consola de AWS vamos al servicio de VPC, seleccionamos Subnets y filtramos las redes por 芦public芦. Copiamos los Subnet ID encontrados:

EKS Cluster Subnets
Listando las subnets p煤blicas del Cl煤ster EKS

Editamos el archivo ingress.yaml y buscamos la secci贸n alb.ingress.kubernetes.io/subnets, a continuaci贸n actualizamos los valores con la lista de Subnet ID‘s obtenida en el paso anterior:

  alb.ingress.kubernetes.io/subnets: subnet-0ce7fbd629a3db193,subnet-0c4b6807f56cbd85d

Procedemos a crear el ingress:

kubectl apply -f ingress.yaml
ingress.networking.k8s.io/jenkins-ingress created

Luego de unos minutos, verificamos que el load balancer correspondiente se haya creado en AWS. Vamos a la consola EC2 de AWS y seleccionamos Load Balancers. El load balancer creado debe ser del tipo application (ALB):

Application Load Balancer for EKS
Application Load Balancer creado por el ingress desplegado (archivo ingress.yaml)

馃寧 Comprobando el acceso a Jenkins

En el Load Balancer creado en el paso anterior verificamos su DNS name, lo copiamos y pegamos en la barra de direcciones de nuestro navegador web y accedemos:

Jenkins DNS Name
Accediendo a Jenkins mediante el DNS Name del Load Balancer

Se nos pedir谩 la clave de administrador inicial generada durante el momento de la instalaci贸n. Para obtener esta clave, debemos inspeccionar los logs del pod de despliegue de Jenkins.

Primero listamos los pods ejecut谩ndose actualmente en el namespace devops-tools:

kubectl get pods -n devops-tools
NAME                       READY   STATUS    RESTARTS   AGE
jenkins-5ddc766476-ll82g   1/1     Running   0          88m

Una vez identificado el pod, obtenemos las 煤ltimas 20 l铆neas de su log de ejecuci贸n:

kubectl logs jenkins-5ddc766476-ll82g --tail 20 -n devops-tools

En el fragmento de log mostrado, se puede apreciar claramente la clave generada:

*************************************************************
*************************************************************

Jenkins initial setup is required. An admin user has been created and a password generated.
Please use the following password to proceed to installation:

a14f39190fa44226af623ce9560b0d7b

This may also be found at: /var/jenkins_home/secrets/initialAdminPassword

*************************************************************
*************************************************************

Ingresamos esta clave en la p谩gina de inicio de Jenkins, instalamos la lista de plugins recomendados y creamos un usuario administrador:

Jenkins install suggested plugins
Instalaci贸n de plugins recomendados de Jenkins

Configuramos la URL de acceso a nuestra instancia e ingresamos a la consola de Jenkins:

Jenkins URL de acceso
Configurando la URL de acceso a Jenkins
Jenkins first run
Consola de Jenkins reci茅n instalado

0 0 votos
Calificaci贸n del art铆culo
Suscribirse
Notificar de
guest
0 Comentarios
Inline Feedbacks
View all comments
error: Contenido protegido!
0
D茅janos tus comentarios!x
()
x