Estoy tratando de configurar una canalización declarativa de Jenkins para usar dos agentes diferentes durante su ejecución. Los agentes son generados dinámicamente por el complemento de Kubernetes. En aras del argumento y la simplicidad, supongamos que quiero hacer esto:
En el Agente 1 (nombre de la nube: "ubuntu"):
En el Agente 2 (nombre de la nube: "fedora"):
El problema que tengo es que si uso una declaración de agente global:
pipeline { agent { kubernetes { cloud 'ubuntu' label "ubuntu-agent" containerTemplate { name 'support' image 'blenderfox/support' ttyEnabled true command 'cat' } } } ... }Entonces eso se usa en todas las etapas si no declaro un agente en cada una de las etapas.
Si uso agent none :
pipeline { agent none ... }Luego tengo que declarar una especificación de agente para cada etapa, por ejemplo:
stage ("apt update") { agent { kubernetes { cloud 'ubuntu' label "ubuntu-agent" containerTemplate { name 'support' image 'blenderfox/support' ttyEnabled true command 'cat' } } } steps { sh """ apt update """ } }Si bien esto funcionaría para mí porque puedo declarar por etapa qué agente quiero, el problema que causa este método es que genera un nuevo agente para cada etapa, lo que significa que el estado no se transfiere entre, por ejemplo, estos dos etapas:
stage ("apt-update") { agent { .... } steps { sh """ apt update """ } } stage ("apt-install") { agent { .... } steps { sh """ apt install -y .... """ } }¿Puedo reutilizar el mismo agente en todas las etapas? Por ejemplo, algo como esto:
stage ("provision agent") { agent { ... label "ubuntu-agent" ... } steps { sh """ echo "Provisioning agent" """ } } stage ("apt-update") { agent { label "ubuntu-agent" //reuse agent from previous stage } steps { sh """ apt update """ } } stage ("apt-install") { agent { label "ubuntu-agent" //reuse agent from previous stage } steps { sh """ apt install -y .... """ } }Encontré una solución. Muy hacky pero funciona:
pipeline { agent none stages { stage ("Provision dev agent") { agent { kubernetes { cloud 'dev-cloud' label "dev-agent-${env.BUILD_NUMBER}" slaveConnectTimeout 300 idleMinutes 5 yamlFile "jenkins-dev-agent.yaml" } } steps { sh """ ## Do any agent init steps here """ } } stage ("Do something on dev agent") { agent { kubernetes { label "dev-agent-${env.BUILD_NUMBER}" } } steps { sh """ ## Do something here """ } } stage ("Provision production agent") { agent { kubernetes { cloud 'prod-cloud' label "prod-agent-${env.BUILD_NUMBER}" slaveConnectTimeout 300 idleMinutes 5 yamlFile "jenkins-prod-agent.yaml" } } steps { sh """ ## Do any agent init steps here """ } } stage ("Do something on prod agent") { agent { kubernetes { label "prod-agent-${env.BUILD_NUMBER}" } } steps { sh """ ## Do something here """ } } } }Los yamls del agente varían, pero puedes hacer algo como esto:
spec: containers: - name: docker image: docker:18.06.1 command: ["tail", "-f", "/dev/null"] imagePullPolicy: Always volumeMounts: - name: docker mountPath: /var/run/docker.sock volumes: - hostPath: path: "/var/run/docker.sock" name: "docker"Y luego usa el agente así:
stage ("docker build") { agent { kubernetes { label "dev-agent-${env.BUILD_NUMBER}" } } steps { container('docker') { sh """ ## docker build.... """ } } }