Create Registry in Cluster
Define Local Storage
> vi localStorage.yml
apiVersion: v1 kind: PersistentVolume metadata: name: local-storage spec: capacity: storage: 10Gi # volumeMode field requires BlockVolume Alpha feature gate to be enabled. volumeMode: Filesystem accessModes: - ReadWriteOnce persistentVolumeReclaimPolicy: Delete storageClassName: local-storage local: path: /var/k8s/LOCAL_STORAGE nodeAffinity: required: nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/hostname operator: In values: - k8sworker1 - k8sworker2 - k8sworker3 - docker-for-desktop --- kind: PersistentVolumeClaim apiVersion: v1 metadata: name: local-storage-claim spec: storageClassName: local-storage accessModes: - ReadWriteOnce resources: requests: storage: 3Gi
For running on a docker for desktop cluster, you will probably need to update the path to a folder under the users home directory.
ie.
path: /Users/john.mehan/k8s/LOCAL_STORAGE
Apply the yml file
kubectl apply -f localStorage.yml
On each of the worker nodes, create the folder specified in 'path'.
ssh k8sworker1
sudo mkdir -p /var/k8s/LOCAL_STORAGE
Repeat for all worker nodes.
Create Password File
We will generate a password file to use with our registry. The default username password will be test/testpw.
vi htpasswdGenerator.yml
apiVersion: v1 kind: Pod metadata: name: htpasswd-generator spec: containers: - name: htpasswd-generator image: registry:2 command: ["/usr/bin/htpasswd"] args: ["-Bcb", "/auth/htpasswd", "test", "testpw"] volumeMounts: - mountPath: /auth name: local-vol subPath: registry/auth affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/hostname operator: In values: - k8sworker2 - docker-for-desktop volumes: - name: local-vol persistentVolumeClaim: claimName: local-storage-claim restartPolicy: OnFailure
kubectl apply -f htpasswdGenerator.yml
Create SSL Certificate
Create CSR
We are using CFSSL to generate the Certificate Signing Request.
Install CFSSL on your mac using the following command:
brew install cfssl
Create script to create CSR:
vi createCSR.sh
cat <<EOF | cfssl genkey - | cfssljson -bare server { "hosts": [ "registry-ext.default.svc.cluster.local", "registry.default.svc.cluster.local", "registry.default.pod.cluster.local" ], "CN": "registry.default.pod.cluster.local", "key": { "algo": "ecdsa", "size": 256 } } EOF
Run script:
./createCSR
This will generate two files:
- server-key.pem
- server.csr
Submit CSR to Kubernetes Cluster for Approval
Login to the master node
Create script to submit CSR
vi submitCSR.sh
cat <<EOF | kubectl apply -f - apiVersion: certificates.k8s.io/v1beta1 kind: CertificateSigningRequest metadata: name: registry.default spec: groups: - system:authenticated request: $(cat server.csr | base64 | tr -d '\n') usages: - digital signature - key encipherment - server auth EOF kubectl get csr
Run the script:
./submitCSR.sh
certificatesigningrequest.certificates.k8s.io/registry.default created
Approve CSR
kubectl certificate approve registry.default
kubectl get csr
NAME AGE REQUESTOR CONDITION registry.default 30s kubernetes-admin Approved,Issued
Get Signed Certificate
kubectl get csr registry.default -o jsonpath='{.status.certificate}' | base64 --decode > server.crt
Create Secret for SSL Certificate
kubectl create secret generic registry-ssl --from-file=./server.crt --from-file=./server-key.pem
kubectl get secrets
NAME TYPE DATA AGE registry-ssl Opaque 2 32s
Create Registry Pod and Service
We will create our registry and tie it to node k8sworker2. See nodeSelector in following registry.yml
vi registry.yml
apiVersion: v1 kind: Pod metadata: name: registry labels: app: registry spec: containers: - name: registry image: registry:2 env: - name: REGISTRY_AUTH value: htpasswd - name: REGISTRY_AUTH_HTPASSWD_REALM value: "Registry Realm" - name: REGISTRY_AUTH_HTPASSWD_PATH value: /auth/htpasswd - name: REGISTRY_HTTP_ADDR value: 0.0.0.0:5000 - name: REGISTRY_HTTP_TLS_CERTIFICATE value: /ssl/server.crt - name: REGISTRY_HTTP_TLS_KEY value: /ssl/server-key.pem ports: - containerPort: 5000 volumeMounts: - mountPath: /auth name: local-vol subPath: registry/auth - mountPath: /var/lib/registry name: local-vol subPath: registry/data - mountPath: /ssl name: registry-ssl readOnly: true affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/hostname operator: In values: - k8sworker2 - docker-for-desktop volumes: - name: local-vol persistentVolumeClaim: claimName: local-storage-claim - name: registry-ssl secret: secretName: registry-ssl --- apiVersion: v1 kind: Service metadata: name: registry-ext spec: type: NodePort selector: app: registry ports: - port: 5000 nodePort: 30500 name: registry-ext
kubectl apply -f registry.yml
Verify that the registry was successfully installed by issuing the following command:
curl -k --user test:testpw https://<HOST_OR_IP>:30500/v2/_catalog
{"repositories":[]}
Create a secret in the Cluster for the Registry
Create a secret in the cluster that holds your authorization token
kubectl create secret docker-registry regcred --docker-server='https://127.0.0.1:30500/' --docker-username='test' --docker-password='testpw' --docker-email='test@irdeto.com'
Feed the Registry
From user machine, revise the docker daemon file.
On Mac:
vi ~/.docker/daemon.json
{ "debug" : true, "experimental" : false, "insecure-registries" : ["172.20.233.181:30500"] }
Add an entry for insecure-registries for your cluster registry.
docker tag <image> <node_ip>:30500/<image>
docker push <node_ip>:30500/<image>
example:
docker tag nginx-jmehan:latest 172.20.233.181:30500/nginx-jmehan:latest
docker push 172.20.233.181:30500/nginx-jmehan:latest
Verify that the registry was successfully installed by issuing the following command:
curl -k --user test:testpw https://172.20.233.181:30500/v2/_catalog
{"repositories":["nginx-jmehan"]}
Revise deployment.yaml files
Add imagePullSecrets section to your deployment yaml files:
imagePullSecrets:
- name: regcred
example:
apiVersion: v1 kind: Pod metadata: name: sample labels: app: sample spec: containers: - name: sample image: 127.0.0.1:30500/nginx-jmehan:latest ports: - containerPort: 80 imagePullSecrets: - name: regcred
Test that you can pull from the cluster registry
Create a custom docker image
mkdir html
vi html/index.html
<html> <body> <h1>Hello from John</h1> </body> </html>
vi Dockerfile
FROM nginx COPY html /usr/share/nginx/html
docker build -t nginx-jmehan .
Sending build context to Docker daemon 5.632kB Step 1/2 : FROM nginx ---> 7042885a156a Step 2/2 : COPY html /usr/share/nginx/html ---> Using cache ---> b284da22e8cb Successfully built b284da22e8cb Successfully tagged nginx-jmehan:latest
Push the Custom Image to the new Registry
docker tag nginx-jmehan:latest 172.20.233.181:30500/nginx-jmehan:latest
docker push 172.20.233.181:30500/nginx-jmehan:latest
Verify that it is in the registry
curl -k --user test:testpw https://172.20.233.181:30500/v2/_catalog
{"repositories":["nginx-jmehan"]}
Configure a node that uses the new image
vi sample.yml
apiVersion: v1 kind: Pod metadata: name: sample labels: app: sample spec: containers: - name: sample image: 127.0.0.1:30500/nginx-jmehan:latest ports: - containerPort: 80 imagePullSecrets: - name: regcred --- apiVersion: v1 kind: Service metadata: name: sample spec: type: NodePort selector: app: sample ports: - port: 80 nodePort: 30080 name: sample
kubectl apply -f sample.yml
Navigate to http://localhost:30080/ to see our new pod.
Troubleshooting
Start a ubuntu pod
kubectl run -it --image=ubuntu:latest bash
From bash shell of new pod:
apt-get update
apt-get install curl
curl -k --user test:testpw https://registry:5000/v2/_catalog
{"repositories":["nginx-jmehan"]}
References
Reference | URL |
---|---|
Deploy a registry server | https://docs.docker.com/registry/deploying/ |
Configuring a registry | https://docs.docker.com/registry/configuration/ |
Manage TLS Certificates in a Cluster | https://kubernetes.io/docs/tasks/tls/managing-tls-in-a-cluster/#requesting-a-certificate |
Docker registry:2 Setup with TLS, Basic Auth, and persistent data | https://medium.com/@ManagedKube/docker-registry-2-setup-with-tls-basic-auth-and-persistent-data-8b98a2a73eec |
Docker Login | https://docs.docker.com/engine/reference/commandline/login/ |
Using a Private Registry | https://kubernetes.io/docs/concepts/containers/images/#using-a-private-registry |
Define a Command and Arguments for a Container | https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/ |
In Cluster Docker Registy with TLS | https://medium.com/@jmarhee/in-cluster-docker-registry-with-tls-on-kubernetes-758eecfe8254 |