Skip to content

Commit f0ffc1b

Browse files
committed
wrote about hosting a private git repo
Signed-off-by: David Söderlund <[email protected]>
1 parent 5d7b417 commit f0ffc1b

11 files changed

+282
-0
lines changed
Lines changed: 282 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,282 @@
1+
---
2+
title: The Joy of Kubernetes 3 - Private Docker registry on NFS storage
3+
published: true
4+
---
5+
6+
# Welcome to the Joy of Kubernetes.
7+
8+
Hi everyone, so glad you could join us today and enjoy deploying some useful tools.
9+
10+
If you are painting along at home, this one might be an episode where you need to take some brave creative efforts.
11+
12+
The goal is to set up a private container registry on our kubernetes cluster using external storage.
13+
14+
- [Welcome to the Joy of Kubernetes.](#welcome-to-the-joy-of-kubernetes)
15+
- [Prerequisites 🎨](#prerequisites-)
16+
- [Argo CD](#argo-cd)
17+
- [Setting the scene, what our landscape will be](#setting-the-scene-what-our-landscape-will-be)
18+
- [Storage Classes: The colors on todays palette](#storage-classes-the-colors-on-todays-palette)
19+
- [NFS is not secure](#nfs-is-not-secure)
20+
- [Creation of the storage class](#creation-of-the-storage-class)
21+
- [Without Argo CD](#without-argo-cd)
22+
- [Persistent Volume Claims: Choosing the Perfect Canvas](#persistent-volume-claims-choosing-the-perfect-canvas)
23+
- [A private Docker Registry with helm: Bringing our masterpiece together](#a-private-docker-registry-with-helm-bringing-our-masterpiece-together)
24+
- [TLS and Ingress: Finishing touches](#tls-and-ingress-finishing-touches)
25+
- [Summary](#summary)
26+
- [Further things you can try](#further-things-you-can-try)
27+
- [Thank you for joining](#thank-you-for-joining)
28+
29+
## Prerequisites 🎨
30+
31+
- ~~A canvas, some brushes, and some paint~~ A kubernetes cluster and kubectl.
32+
- Optional, Argo CD with the application set creation from [the first post in the series](../he-joy-of-kubernetes-1-argocd-with-private-git-repo).
33+
- The ability to set up NFS storage, or some other storage class
34+
35+
### Argo CD
36+
37+
This is the structure that we will create today in our Argo CD gitops structure to get the required results splattered onto our canvas.
38+
39+
``` powershell
40+
mkdir gitops/joy-of-kubernetes-3
41+
mkdir gitops/joy-of-kubernetes-3/nfs
42+
mkdir gitops/joy-of-kubernetes-3/docker-registry
43+
mkdir gitops/joy-of-kubernetes-3/docker-registry-helm
44+
```
45+
46+
I went ahead and simplified the directories generator of our appset gitops/root-appset.yaml and applied that. This is hopefully the last time we will need to make changes to it in a while. Remember that we don't make mistakes, we just have happy little accidents. 😀
47+
48+
Instead of individual folders, each episode will have the same structure under gitops with one folder for each application neatly under its episode number.
49+
50+
The first app we made is renamed "hello" and put under episode 1.
51+
52+
![](../assets/2023-04-20-23-13-49.png)
53+
54+
This allows all apps to have names that make sense, but we can still search and filter by episodes.
55+
56+
![](../assets/2023-04-20-23-13-12.png)
57+
58+
## Setting the scene, what our landscape will be
59+
60+
The goal as we talked about is to have a private docker registry in kubernetes. This can be used to host images that we might want faster access to than loading from docker hub. Or simply images that we build ourselves but don't want to share with docker hub.
61+
62+
Once the installation is complete, we will take a look at connecting docker to our new registry with docker login. So we will need to generate ourselves a password in the [bcrypt format](https://en.wikipedia.org/wiki/Bcrypt).
63+
64+
Using the same registry container image that our installation in kubernetes will use, we can generate a bcrypt password with the htpasswd executable. I think this has been removed in later versions of the registry though. There are of course a million differnet ways you can generate this hash, but this one is elegant on top of docker and I like it. Let us know if you come up with a way that you would like to share!
65+
66+
``` bash
67+
docker run --entrypoint htpasswd registry:2.7.0 -Bbn youruser yourplaintextpassword
68+
```
69+
70+
![](../assets/2023-04-21-00-02-28.png)
71+
72+
## Storage Classes: The colors on todays palette
73+
74+
Storage classes in Kubernetes are like the various colors on our palette. They define different types of storage that we can use to create our masterpiece. These storage classes provide a way for administrators to describe the various storage options available within the cluster.
75+
76+
### NFS is not secure
77+
78+
For my painting today, I will be using the Network File System (NFS) as a storage class example. I added support for it on my NAS and created a shared folder.
79+
80+
![](../assets/2023-04-21-00-43-41.png)
81+
82+
I have restricted access to the hostnames of my nodes, this is about the extent to which you can protect this type of service outside of not allowing traffic to the shared network. So keep that in mind if you want to bring this beyond our artistic realm.
83+
84+
## Creation of the storage class
85+
86+
To create an NFS storage class, we'll use [this simple helm chart](https://kubernetes-sigs.github.io/nfs-subdir-external-provisioner/).
87+
88+
> gitops/joy-of-kubernetes-3/nfs/Chart.yaml
89+
90+
``` yaml
91+
apiVersion: v2
92+
name: nfs
93+
description: A happy little storage class installation
94+
type: application
95+
version: 0.1.0
96+
appVersion: "1.0"
97+
dependencies:
98+
- name: nfs-subdir-external-provisioner
99+
version: 4.0.18
100+
repository: https://kubernetes-sigs.github.io/nfs-subdir-external-provisioner/
101+
```
102+
103+
> gitops/joy-of-kubernetes-3/nfs/values.yaml
104+
105+
``` yaml
106+
nfs-subdir-external-provisioner:
107+
nfs:
108+
server: NAS # The IP or hostname of our NFS Server
109+
path: /volume2/ds-pi-nfs # Where we mounted our shared storage
110+
```
111+
112+
Once these files are pushed to git, an app named nfs with the label of episode 3 will show up. We can see that our configuration made its way into the deployment.
113+
114+
![](../assets/2023-04-20-23-28-47.png)
115+
116+
![](../assets/2023-04-20-23-26-35.png)
117+
118+
### Without Argo CD
119+
120+
If you want to use this helm chart but aren't following our gitops example, you can add it to your cluster this way.
121+
122+
``` powershell
123+
helm repo add nfs-subdir-external-provisioner https://kubernetes-sigs.github.io/nfs-subdir-external-provisioner/
124+
helm install nfs-subdir-external-provisioner nfs-subdir-external-provisioner/nfs-subdir-external-provisioner `
125+
--set nfs.server=NAS ` # The IP or hostname of our NFS Server
126+
--set nfs.path=/volume2/ds-pi-nfs # Where we mounted our shared storage
127+
```
128+
129+
With this storage class defined, we can now create our Persistent Volumes and Persistent Volume Claims that use this NFS storage.
130+
131+
132+
## Persistent Volume Claims: Choosing the Perfect Canvas
133+
Next, let's talk about Persistent Volume Claims (PVCs). PVCs are like choosing the perfect canvas for our painting. They allow our applications to request storage of a specific size and access mode.
134+
135+
Here's an example of a PVC that requests storage from our NFS storage class:
136+
137+
> gitops/joy-of-kubernetes-3/docker-registry/pvc.yaml
138+
139+
``` yaml
140+
apiVersion: v1
141+
kind: PersistentVolumeClaim
142+
metadata:
143+
name: docker-registry-pvc
144+
spec:
145+
accessModes:
146+
- ReadWriteOnce
147+
volumeMode: Filesystem
148+
resources:
149+
requests:
150+
storage: 100Gi
151+
storageClassName: nfs-client
152+
```
153+
154+
Our application can now use this PVC to store its data.
155+
156+
## A private Docker Registry with helm: Bringing our masterpiece together
157+
158+
When synchronizing the desired state from gitops into kubernetes using Argo CD we can use either plain manifests, helm charts, kustomize or kustomized helm. Since mixing helm charts and plain manifests doesn't work, we have split them up in two different directories.
159+
160+
> gitops/docker-registry-helm/Chart.yaml
161+
162+
``` yaml
163+
apiVersion: v2
164+
name: images
165+
description: A majestic container image hosting
166+
type: application
167+
version: 0.1.0
168+
appVersion: "1.0"
169+
dependencies:
170+
- name: docker-registry
171+
version: 2.2.2
172+
repository: https://helm.twun.io
173+
```
174+
175+
> gitops/docker-registry-helm/values.yaml
176+
177+
``` yaml
178+
images:
179+
replicaCount: 1
180+
persistence:
181+
enabled: true
182+
size: 100Gi
183+
deleteEnabled: true
184+
storageClass: nfs-client
185+
existingClaim: docker-registry-pvc
186+
secrets:
187+
htpasswd: youruser:your-bcrypt-hash
188+
```
189+
190+
## TLS and Ingress: Finishing touches
191+
I am so happy we have the cert-manager available to us from [the last episode](../2023-04-14-the-joy-of-kubernetes-2---let-us-encrypt.md).
192+
193+
This allows us to add highlights to our image container registry with TLS. Rather than ingress annotations we will perform the steps a bit differently today.
194+
195+
> gitops/joy-of-kubernetes-3/docker-registry/docker-registry-images-tls.yaml
196+
197+
``` yaml
198+
apiVersion: cert-manager.io/v1
199+
kind: Certificate
200+
metadata:
201+
name: images-tls
202+
spec:
203+
secretName: images-tls
204+
dnsNames:
205+
- images.k3s.dsoderlund.consulting
206+
duration: 2160h0m0s # 90d
207+
renewBefore: 360h0m0s # 15d
208+
privateKey:
209+
algorithm: RSA
210+
encoding: PKCS1
211+
size: 2048
212+
usages:
213+
- "digital signature"
214+
- "key encipherment"
215+
issuerRef:
216+
name: letsencrypt-prod
217+
kind: ClusterIssuer
218+
group: cert-manager.io
219+
```
220+
221+
Once pushed cert-manager will resolve a tls certificate for us.
222+
223+
![](../assets/2023-04-20-23-41-20.png)
224+
225+
While it is doing its thing, we will continue with the ingress route.
226+
227+
> gitops/joy-of-kubernetes-3/docker-registry/docker-registry-ingress-route.yaml
228+
229+
``` yaml
230+
kind: IngressRoute
231+
apiVersion: traefik.containo.us/v1alpha1
232+
metadata:
233+
name: docker-registry
234+
spec:
235+
entryPoints:
236+
- websecure
237+
routes:
238+
- match: Host(`images.k3s.dsoderlund.consulting`)
239+
kind: Rule
240+
services:
241+
- name: docker-registry-helm
242+
port: 5000
243+
tls:
244+
secretName: images-tls
245+
```
246+
247+
k3s which I use comes bundled with [traefik](https://github.com/traefik/traefik) which offers among other things ingress routes, allowing for some elegant mark up of traffic management.
248+
249+
The down side is that unlike ingress or a virtual service in istio, there is no pretty pictures getting drawn in Argo CD. But that is OK.
250+
251+
![](../assets/2023-04-21-00-28-44.png)
252+
253+
## Summary
254+
255+
By painting with storage classes, we can make peristent volume claims vibrant and allow us to build stateful applications that shine. Once such application is our own private container registry.
256+
257+
And there we have it friends, all this guy needs now is our signature. (Signing in, get it?)
258+
259+
``` bash
260+
docker login images.k3s.dsoderlund.consulting
261+
```
262+
263+
![](../assets/2023-04-21-00-15-44.png)
264+
265+
266+
## Further things you can try
267+
268+
Here is an example with the application from episode 1 to show that your registry is allowing you push images.
269+
270+
``` bash
271+
docker pull nginxdemos/hello:latest
272+
docker tag nginxdemos/hello:latest images.k3s.dsoderlund.consulting/nginxdemos/hello:latest
273+
docker push images.k3s.dsoderlund.consulting/nginxdemos/hello:latest
274+
```
275+
276+
![](../assets/2023-04-21-00-19-18.png)
277+
278+
You should now be able to explore pulling images from it with [pull secrets in kubernetes](https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/).
279+
280+
## Thank you for joining
281+
282+
That's all for now folks, I hope to see you again next week.
154 KB
Loading
55 KB
Loading
69.2 KB
Loading
39.9 KB
Loading
33.6 KB
Loading
11.7 KB
Loading
22.1 KB
Loading
55.3 KB
Loading
27.9 KB
Loading

0 commit comments

Comments
 (0)