The simplest solution I found after an extensive search is suggested in this guide by CoreOS : https://github.com/coreos/tectonic-docs/blob/master/Documentation/admin/add-registry-cert.md
It consists to create a secret that contains your certificate and a DaemonSet to populate it to /etc/docker/certs.d/my-private-insecure-registry.com/ca.crt
on all the nodes of your cluster.
I think this answers your question because, when adding a new node, the DaemonSet is automatically executed on it.
I give the detailed solution below but all the credits goes to Kyle Brown (kbrwn) for his very cool guide (cf. link above).
Detailed solution for Kubernetes 1.16 to 1.23
Lets suppose that your certificate is a file named ca.crt
in your working directory. Create a secret from this file content :
kubectl create secret generic registry-ca --namespace kube-system --from-file=registry-ca=./ca.crt
Then, use the following DaemonSet that mounts the certificate as the file /home/core/registry-ca
and copy it to the desired location : /etc/docker/certs.d/reg.example.com/ca.crt
.
Simply replace my-private-insecure-registry.com
with the hostname of your container registry.
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 && 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
Save the file as registry-ca-ds.yaml
and then create the DaemonSet :
kubectl create -f registry-ca-ds.yaml
You can now check that your application correctly pulls from your private self-signed registry.
As mentioned, the certificate will be added to new nodes' docker in an automatic fashion by the registry-ca
DaemonSet. If you want to avoid this, simply delete the DaemonSet :
kubectl delete ds registry-ca --namespace kube-system
I think this is more secure than setting the insecure-registries
flag of the docker daemon. Also, it is resilient to new nodes.
Known limitations
Solution for Kubernetes 1.24+ (edit 2023)
The Kubernetes project is removing built-in support for the Docker runtime in Kubernetes version 1.24 and later (source).
Therefore, these solutions doesn't work for Kubernetes 1.24+ clusters that should use Containerd instead of Docker.
As explained in Moly's answer, Containerd doesn't support yet adding certificates without restarting so a different approach using a privileged container is recommended for those clusters.
Please, see Moly's answer for detailed explanation and code.
Registries with specific ports (edit 2021)
According to these Kubernetes answers (here and here) 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).
In such case, please see Gary Plattenburg's answer to create the directory in the shell command instead of using Kubernetes to handle it during the mount.
insecure-registries
the preferred approach should be to install the CA correctly on the host. This is a good option though if you just want EKS Managed Node Groups to work with AWS provided AMIs with minimum amount of modifications. Please note for Artifactory you need to provide the full long path to the registry, my-local.artifactory.mydomain.com not just artifactory.mydomain.com – Sello