<p>GitLab offers to manage a Kubernetes cluster, which includes (e.g.) creating the namespace, adding some tokens, etc. In GitLab CI jobs, one can directly use the <code>$KUBECONFIG</code> variable for contacting the cluster and e.g. creating deployments using helm. This works like a charm, as long as the GitLab project is public and therefore Docker images hosted by the GitLab project's image registry are publicly accessible.</p>
<p>However, when working with private projects, Kubernetes of course needs an <code>ImagePullSecret</code> to authenticate the GitLab's image registry to retreive the image. As far as I can see, GitLab does not automatically provide an <code>ImagePullSecret</code> for repository access.</p>
<p>Therefore, my question is: <strong>What is the best way to access the image repository of private GitLab repositories in a Kubernetes deployment in a GitLab managed deployment environment?</strong></p>
<p>In my opinion, these are the possibilities and <em>why they are not eligible/optimal</em>:</p>
<ul>
<li><strong>Permanent <code>ImagePullSecret</code> provided by GitLab</strong>: When doing a deployment on a GitLab managed Kubernetes cluster, GitLab provides <a href="https://docs.gitlab.com/ee/user/project/clusters/#deployment-variables" rel="nofollow noreferrer">a list of variables</a> to the deployment script (e.g. Helm Chart or <code>kubectl apply -f manifest.yml</code>). <em>As far as I can (not) see, there is a lot of stuff like ServiceAccounts and tokens etc., but no ImagePullSecret - and also no configuration option for enabling ImagePullSecret creation</em>.</li>
<li><strong>Using <code>$CI_JOB_TOKEN</code></strong>: When working with GitLab CI/CD, GitLab provides a variable named <code>$CI_JOB_TOKEN</code> which can be used for uploading Docker images to the registry during job execution. <em>This token expires after the job is done. It could be combined with <code>helm install --wait</code>, but when a rescheduling takes place to a new node which does not have the image yet, the token is expired and the node is not able to download the image anymore. Therefore, this only works right in the moment of deploying the app.</em></li>
<li><strong>Creating an ImagePullSecret manually and add it to the <code>Deployment</code> or the default <code>ServiceAccount</code></strong>: *This is a manual step, has to be repeated for each individual project and just sucks - we're trying to automate things/GitLab managed Kubernetes clusters is designed for avoiding any manual step.`</li>
<li><strong>Something else</strong> but I don't know about it.</li>
</ul>
<p>So, am I wrong in one of these points? Am I missing a eligible option in this listing?</p>
<p>Again: It's all about a seamless integration with the &quot;Managed Cluster&quot; features of GitLab. I know how to add tokens from GitLab as ImagePullSecrets in Kubernetes, but I want to know how to automate this with the Managed Cluster feature.</p>

<p>There is another way. You can bake the ImagePullSecret in your container runtime configuration. Docker, containerd or CRI-O (Whatever you are using)</p>
<p><strong>Docker</strong></p>
<ul>
<li><p>As root run <code>docker login &lt;your-private-registry-url&gt;</code>. Then a file <code>/root/.docker/config.json</code> should be created/updated. Stick that in all your Kubernetes node and make sure your kubelet runs as root (which typically does). <a href="https://github.com/kubernetes/kubernetes/issues/45487" rel="nofollow noreferrer">Some background info</a>.</p>
<p>The content of the file should look something like this:</p>
<pre class="lang-sh prettyprint-override"><code>{
      &quot;auths&quot;: {
          &quot;my-private-registry&quot;: {
              &quot;auth&quot;: &quot;xxxxxx&quot;
          }
      },
      &quot;HttpHeaders&quot;: {
          &quot;User-Agent&quot;: &quot;Docker-Client/18.09.2 (Linux)&quot;
      }
}
</code></pre>
</li>
</ul>
<p><strong>Containerd</strong></p>
<ul>
<li><a href="https://github.com/containerd/cri/issues/835#issuecomment-403652902" rel="nofollow noreferrer">Configure your <code>containerd.toml</code></a> file with something like this:
<pre><code>[plugins.cri.registry.auths]
  [plugins.cri.registry.auths.&quot;https://gcr.io&quot;]
    username = &quot;&quot;
    password = &quot;&quot;
    auth = &quot;&quot;
    identitytoken = &quot;&quot;
</code></pre>
</li>
</ul>
<p><strong>CRI-O</strong></p>
<ul>
<li>Specify the <code>global_auth_file</code> option in your <a href="https://github.com/cri-o/cri-o/blob/master/docs/crio.conf.5.md#crioimage-table" rel="nofollow noreferrer">crio.conf</a> file.</li>
</ul>
<p>✌️</p>
