Running a docker registry (v2) on Kubernetes is well documented as an addon to Kubernetes.
That setup, however, involves proxying the registry as localhost
on each Kubernetes node. While this simplifies pulling on nodes (no insecure registry issue, as it is localhost), this makes building and pushing outside the Kubernetes cluster unnecessarily complex and hacky (you need to kubectl port-forward
to access the registry, and you also must build your images with the tag like localhost:5000/repository/image:version
.) Moreover, it is based on Persistent Volume storage.
For a better docker registry setup, we wanted two things:
- S3 backed registry so that storage is managed better.
- Proper service for registry so that push and pull are more sane, and image tags are proper. We would like to push and pull from local workstation and our CI boxes. Also, at any time we can move to a different hosting solution for our private registry without have to retag and push images.
For S3 storage, we can utilize the ability to override all the configuration for the registry via environment variables. Our ReplicationController
looks like the following:
apiVersion: v1
kind: ReplicationController
metadata:
name: kube-registry-v0
namespace: kube-system
labels:
k8s-app: kube-registry
version: v0
kubernetes.io/cluster-service: "true"
spec:
replicas: 1
selector:
k8s-app: kube-registry
version: v0
template:
metadata:
labels:
k8s-app: kube-registry
version: v0
kubernetes.io/cluster-service: "true"
spec:
containers:
- name: registry
image: registry:2.2.1
env:
- name: REGISTRY_HTTP_ADDR
value: :5000
- name: REGISTRY_STORAGE
value: S3
- name: REGISTRY_STORAGE_S3_ACCESSKEY
value: <access_key>
- name: REGISTRY_STORAGE_S3_SECRETKEY
value: <secret_key>
- name: REGISTRY_STORAGE_S3_REGION
value: us-east-1
- name: REGISTRY_STORAGE_S3_BUCKET
value: <S3_bucket>
- name: REGISTRY_STORAGE_S3_ENCRYPT
value: "true"
- name: REGISTRY_STORAGE_S3_SECURE
value: "true"
- name: REGISTRY_STORAGE_S3_V4AUTH
value: "true"
- name: REGISTRY_STORAGE_S3_CHUNKSIZE
value: "5242880"
- name: REGISTRY_HTTP_SECRET
value: "<secret>"
ports:
- containerPort: 5000
name: registry
protocol: TCP
It is important to set REGISTRY_STORAGE
to S3
so that the default storage configuration is overridden. If this is not done, you will get an error regarding multiple storage drivers. REGISTRY_HTTP_SECRET
has been added so that load balancing across multiple pods will work, when needed. Rest of the settings are pretty standard for a S3 backed registry, as per the docs.
We have a service that looks like below (For context, our Kubernetes cluster is on AWS, and has AWS aware features enabled):
apiVersion: v1
kind: Service
metadata:
name: kube-registry
namespace: kube-system
labels:
k8s-app: kube-registry
kubernetes.io/cluster-service: "true"
kubernetes.io/name: "KubeRegistry"
spec:
selector:
k8s-app: kube-registry
type: LoadBalancer
ports:
- name: registry
port: 80
targetPort: 5000
protocol: TCP
We have a nice Route53 alias for the resulting ELB so that we can push and pull like we would to any other private registry. With the DNS name and S3 storage, moving away from Kubernetes for the registry is trivial too.
Improvements: Obviously, we are running an insecure registry at the moment. That’s something on our TODO list of things to fix. Currently, our CoreOS nodes, local workstations and CI boxes have Docker service running with the --insecure-registry
flag.