<p>I have been trying to setup Jenkins to utilize Kubernetes as in the tutorials.  I have everything working really well, but I have been trying to add some custom images using the Kubernetes Jenkins plugin.  It seems that any public images work just fine, but when I create an image and put it in my private Container Registry, the Jenkins slave fails miserably.  </p>

<p>I wanted to find out how best to utilize the images in my Container Registry within Jenkins.  I found this tutorial (<a href="https://cloud.google.com/solutions/jenkins-on-container-engine#customizing_the_docker_image" rel="nofollow noreferrer">https://cloud.google.com/solutions/jenkins-on-container-engine#customizing_the_docker_image</a>).  When I tried those steps by building the jenkins-slave image and pushing it to my repo, it did not work.  Every time it complains the slave is offline and is unable to be reached.</p>

<p>When a container build agent (old term was <code>slave</code>) shows as <em>Offline</em> within Jenkins, this usually means there was an error in the Jenkinsfile if using Pipeline, or there was a problem pulling the agent image container.</p>
<p>If you're using the Kubernetes Plugin, you'll see the error on the Kubernetes pod, and in the build logs in newer versions of the plugin. For docker plugin containers, the error may not be visible in the build log, but would be in the docker logs.</p>
<p>This is usually a problem of authentication or access for pulling the image from the registry.</p>
<p>If you're using the <strong><a href="https://plugins.jenkins.io/kubernetes/" rel="nofollow noreferrer">Jenkins Kubernetes plugin</a></strong>, the Pod YAML or Pod Template must contain the <a href="https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/" rel="nofollow noreferrer"><code>imagePullSecrets</code></a> for the Container Registry from which you wish to pull the container image from.</p>
<p><em>Jenkins Scripted Pipeline:</em></p>
<pre><code>node {
  podTemplate(cloud: 'kubernetes', containers: [
    containerTemplate(
      name: 'mine',
      image: 'my-image:v1.2',
      ttyEnabled: true,
    ),
  ], 
  imagePullSecrets: [ 'my-credentials-id' ]) {
    sh 'run command'
  }
}
</code></pre>
<p><em>Jenkins Declarative Pipeline:</em></p>
<pre><code>pipeline {
  agent {
    kubernetes {
      cloud 'kubernetes'
      defaultContainer 'mine'
      yaml '''
apiVersion: v1
kind: Pod
metadata:
  labels:
    build: my-app
spec:
  containers:
    - name: mine
      image: my-image:v1.2
      command:
        - cat
      tty: true
  imagePullSecrets:
    - name: my-image-pull-cred
    '''
    }
  }

  stages {
    stage('Run Build') {
      steps {
        sh 'mvn -version'
      }
    }
  }
}
</code></pre>
<p>If you're using the <strong><a href="https://plugins.jenkins.io/docker-plugin/" rel="nofollow noreferrer">Docker plugin</a></strong>, you'll need to define the docker agent <code>withRegistry</code> which allows you to pass a Jenkins credential for the registry from which you wish to pull the container image from.</p>
<p><em>Jenkins Scripted Pipeline:</em></p>
<pre><code>node {
  docker.withRegistry('https://my-registry.gcr.io', 'my-credentials-id') {
    docker.image('my-image:v1.2').inside {
      sh 'run command'
    }
  }
}
</code></pre>
<p><em>Jenkins Declarative Pipeline:</em></p>
<pre><code>pipeline {
  agent {
    docker {
      image 'my-image:v1.0'
      registryUrl 'https://my-registry.gcr.io'
      registryCredentialsId 'my-credentials-id'
    }
  }

  stages {
    stage('Build') {
      steps {
        sh 'run command'
      }
    }
  }
}
</code></pre>
