Self Learning Kubernetes: Helm (Pt. 2)

Self Learning Kubernetes: Helm (Pt. 2)
Helm homepage

Introduction

Kubernetes has a package management system called Helm which is similar to other technology package systems such as npm and nuget. With it you can package your Kubernetes application. Using helm allows for repeatable installations by Kubernetes administrators and it also helps simplify customizations to your installation via a values.yaml file.

Using Helm you can install projects and applications that others have written or that you yourself would write to share your application with others. Helm is an important piece of the puzzle as I want to self host an entire enterprise setup privately and free.


Paid/Public Tools being replaced by self hosted/private tools

These are the tools I'll be needing at a bare minimum in order to setup a CI/CD pipeline within my Kubernetes cluster as well as task tracking and organization of work. The infrastructure is self hosted but I can install OpenVPN on my PfSense router in order to allow trusted users to access my setup which will be important if I want to hire other developers.

An example of installing the package without using Helm

That's right, future me is writing to let you know that I initially didn't actually use Helm! I was still trying to understand the way Kubernetes worked and because of that, I wanted to do the deployment using Kubernetes resource files instead of Helm. I felt that I should understand what Helm was doing behind the scenes before actually using it and so I went about creating my own yaml files for use with kubectl which is a CLI tool used for management of the Kubernetes cluster. I did ultimately learn how to use Helm but at this stage in the game I was still trying to understand Kubernetes yaml files and thus I opted for creating my own PersistentVolumeClaim, Secret, Deployment, Service, and Ingress files.
I did use Helm for the installation of OpenProject and GitTea which will be documented in future posts.

Below you'll find my yaml files with the exception of the secret.yaml file since that contains the private key for my SSL cert. The SSL setup and DNS configuration will also be talked about more in depth in a future post as it involved setting up static ips, routes, a wildcard cert, and some other configuration.

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: registry-pvc
  namespace: registry
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi
  storageClassName: longhorn
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: registry
  name: registry
  namespace: registry
spec:
  replicas: 1
  selector:
    matchLabels:
      app: registry
  template:
    metadata:
      labels:
        app: registry
    spec:
      containers:
      - name: registry
        image: registry:2
        ports:
        - name: http
          containerPort: 5000
          protocol: TCP
        volumeMounts:
        - name: registry-data
          mountPath: /var/lib/registry
          subPath: registry
      volumes:
      - name: registry-data
        persistentVolumeClaim:
          claimName: registry-pvc
---
apiVersion: v1
kind: Service
metadata:
  name: registry-service
  namespace: registry
spec:
  selector:
    app: registry
  ports:
    - name: http
      port: 80
      targetPort: 5000
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: registry-ingress
  namespace: registry
  annotations:
    traefik.ingress.kubernetes.io/service.serversscheme: https
spec:
  ingressClassName: traefik
  tls:
  - hosts:
      - registry.sonicd007.com
    secretName: ssl-cert
  rules:
    - host: registry.sonicd007.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: registry-service
                port:
                  number: 80

registry.yaml

To install this on my cluster, I used kubectl apply – create-namespace registry -n registry -f registry.yaml

Just like that, the private docker registry was deployed and ready for me to build and send custom images to it!

Cool, but what about Helm?

I didn't use Helm for this particular application but if I were to go about doing this again I would definitely utilize Helm instead. I would have been able to have a values.yaml file with the particular values I needed and could have avoided maintaining these yaml files. It didn't really matter for this service but this is how the equivalent values.yaml file would've looked for a Helm install:

replicaCount: 1

image:
  repository: registry
  tag: "2"
  pullPolicy: IfNotPresent

service:
  type: ClusterIP
  port: 80
  targetPort: 5000

ingress:
  enabled: true
  ingressClassName: traefik
  annotations:
    traefik.ingress.kubernetes.io/service.serversscheme: https
  hosts:
    - host: registry.sonicd007.com
      paths:
        - path: /
          pathType: Prefix
  tls:
    - hosts:
        - registry.sonicd007.com
      secretName: ssl-cert

persistence:
  enabled: true
  accessMode: ReadWriteOnce
  size: 10Gi
  storageClass: longhorn
  existingClaim: registry-pvc
  mountPath: /var/lib/registry
  subPath: registry

The equivalent deployment specifying only the customized values

To deploy this, I could have used helm like so:

helm repo add twuni https://helm.twun.io
helm install twuni/docker-registry --namespace registry --create-namespace -f values.yaml

Either way, the registry at this point was now installed and ready for me to push custom images to it in a private manner.

Conclusion

While I initially began deploying applications to my cluster manually using kubectl and the CLI, the experience provided me with a foundational understanding of how Kubernetes deployments normally worked. With this knowledge, I now understood how helm works as the various Kubernetes template files located in a Helm package were regular Kubernetes yaml files with templating and variable injection. Helm not only simplifies the installation and management of Kubernetes applications but also allows for consistent and repeatable deployments across different environments. Moving forward, I will definitely leverage Helm more extensively to manage my Kubernetes resources, enabling easier updates, rollbacks, and customization through a centralized values.yaml file. This approach will be crucial as I continue to build out a robust, self-hosted enterprise setup.