<p>Currently, running a private Docker registry (Artifactory) on an internal network that uses a self signed certificate for authentication.</p>

<p>When Kubernetes starts up a new node, it is unable to auth with the private Docker registry because this new node does not have the self signed certificate. </p>

<p>Any help would be much appreciated. Thanks!</p>

jjNford
<p>The simplest solution I found after an extensive search is suggested in this guide by CoreOS : <a href="https://github.com/coreos/tectonic-docs/blob/master/Documentation/admin/add-registry-cert.md" rel="nofollow noreferrer">https://github.com/coreos/tectonic-docs/blob/master/Documentation/admin/add-registry-cert.md</a></p>
<p>It consists to create a secret that contains your certificate and a DaemonSet to populate it to <code>/etc/docker/certs.d/my-private-insecure-registry.com/ca.crt</code> on all the nodes of your cluster.</p>
<p>I think this answers your question because, when adding a new node, the DaemonSet is automatically executed on it.</p>
<p>I give the detailed solution below but all the credits goes to Kyle Brown (kbrwn) for his very cool guide (cf. link above).</p>
<h1>Detailed solution for Kubernetes 1.16 to 1.23</h1>
<p>Lets suppose that your certificate is a file named <code>ca.crt</code> in your working directory. Create a secret from this file content :</p>
<pre class="lang-bash prettyprint-override"><code>kubectl create secret generic registry-ca --namespace kube-system --from-file=registry-ca=./ca.crt
</code></pre>
<p>Then, use the following DaemonSet that mounts the certificate as the file <code>/home/core/registry-ca</code> and copy it to the desired location : <code>/etc/docker/certs.d/reg.example.com/ca.crt</code>.</p>
<p>Simply replace <code>my-private-insecure-registry.com</code> with the hostname of your container registry.</p>
<pre class="lang-yaml prettyprint-override"><code>apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: registry-ca
  namespace: kube-system
  labels:
    k8s-app: registry-ca
spec:
  selector:
    matchLabels:
      name: registry-ca
  template:
    metadata:
      labels:
        name: registry-ca
    spec:
      containers:
      - name: registry-ca
        image: busybox
        command: [ 'sh' ]
        args: [ '-c', 'cp /home/core/registry-ca /etc/docker/certs.d/my-private-insecure-registry.com/ca.crt &amp;&amp; exec tail -f /dev/null' ]
        volumeMounts:
        - name: etc-docker
          mountPath: /etc/docker/certs.d/my-private-insecure-registry.com
        - name: ca-cert
          mountPath: /home/core
      terminationGracePeriodSeconds: 30
      volumes:
      - name: etc-docker
        hostPath:
          path: /etc/docker/certs.d/my-private-insecure-registry.com
      - name: ca-cert
        secret:
          secretName: registry-ca
</code></pre>
<p>Save the file as <code>registry-ca-ds.yaml</code> and then create the DaemonSet :</p>
<pre class="lang-bash prettyprint-override"><code>kubectl create -f registry-ca-ds.yaml
</code></pre>
<p>You can now check that your application correctly pulls from your private self-signed registry.</p>
<p>As mentioned, the certificate will be added to new nodes' docker in an automatic fashion by the <code>registry-ca</code> DaemonSet. If you want to avoid this, simply delete the DaemonSet :</p>
<pre class="lang-bash prettyprint-override"><code>kubectl delete ds registry-ca --namespace kube-system
</code></pre>
<p>I think this is more secure than setting the <code>insecure-registries</code> flag of the docker daemon. Also, it is resilient to new nodes.</p>
<h1>Known limitations</h1>
<h2>Solution for Kubernetes 1.24+ (edit 2023)</h2>
<p>The Kubernetes project is removing built-in support for the Docker runtime in Kubernetes version 1.24 and later (<a href="https://cloud.google.com/kubernetes-engine/docs/deprecations/docker-containerd" rel="nofollow noreferrer">source</a>).
Therefore, these solutions doesn't work for Kubernetes 1.24+ clusters that should use Containerd instead of Docker.
As explained in <a href="https://stackoverflow.com/a/72216347/5498624">Moly's answer</a>, Containerd doesn't support yet adding certificates without restarting so a different approach using a privileged container is recommended for those clusters.</p>
<p>Please, see <a href="https://stackoverflow.com/a/72216347/5498624">Moly's answer</a> for detailed explanation and code.</p>
<h2>Registries with specific ports (edit 2021)</h2>
<p>According to these Kubernetes answers (<a href="https://github.com/kubernetes/kubernetes/issues/83781#issuecomment-542767227" rel="nofollow noreferrer">here</a> and <a href="https://github.com/kubernetes/kubernetes/issues/93479#issuecomment-664656885" rel="nofollow noreferrer">here</a>) to related github issues, a Kubernetes volume path cannot contain a colon. Therefore, this solution is not valid for registries that communicate securely with a self-signed certificate on specific ports (for example 5000).</p>
<p>In such case, please see <a href="https://stackoverflow.com/a/68552211/5498624">Gary Plattenburg's answer</a> to create the directory in the shell command instead of using Kubernetes to handle it during the mount.</p>
