Skip to content

Instantly share code, notes, and snippets.

@ZAYEC77
Last active August 11, 2023 08:20
Show Gist options
  • Save ZAYEC77/eb95264192ceb51669f21e513df2a5e9 to your computer and use it in GitHub Desktop.
Save ZAYEC77/eb95264192ceb51669f21e513df2a5e9 to your computer and use it in GitHub Desktop.
Helm tutorial

Install helm

brew install helm
helm version

Configure autocomplete

source <(helm completion zsh)
source <(kubectl completion zsh)

Configure connection to cluster

export KUBECONFIG=$(pwd)/kubeconf.uu

Connect to cluster

kubectl config get-contexts

Set default namespace:

kubectl config set-context --current --namespace=<namespace>
kubectl config get-contexts

Create new chart

helm create mychart && cd mychart
  • Chart.yaml: This is the metadata of the chart.
  • values.yaml: The default values for the chart.
  • templates/: The directory containing template files that helm will combine with the values to generate Kubernetes manifest files.
  • charts/: A directory for chart dependencies.

Check templates

helm template .

run lint:

helm lint

Install package

helm install my-app . --debug
kubectl get all

Run tests

helm test my-app

More info: https://helm.sh/docs/topics/chart_tests/

Update values

sed -i "" 's/^  type: ClusterIP$/  type: LoadBalancer/' values.yaml

Upgrade chart

helm upgrade --install my-app . --debug
kubectl get all

Check notes:

export SERVICE_IP=$(kubectl get svc my-app-mychart --template "{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}")
echo http://$SERVICE_IP:80

Update templates

Add configmap

  • templates/web-content.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: web-content
data:
  index.html: |
{{ .Files.Get "files/index.html" | indent 4 }}
  • files/index.html
<!DOCTYPE html>
<html>
<head>
    <title>Welcome to My Website</title>
</head>
<body>
    <h1>Hello, Kubernetes!</h1>
    <p>This is a demo.</p>
</body>
</html>
  • update templates/deployment.yaml
...
spec:
  template:
    spec:
      ...
      containers:
        - name: {{ .Chart.Name }}
          ...
          volumeMounts:
            - name: html-volume
              mountPath: /usr/share/nginx/html
      volumes:
        - name: html-volume
          configMap:
            name: web-content
            items:
            - key: index.html
              path: index.html

Uninstall release

helm uninstall my-app

Create next chart

# back to parent folder
cd .. 
# create new chart
helm create webapp
# go to chart
cd webapp

# clean template folder
rm -rf templates/*
rm values.yaml

Update templates

  • templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ .Release.Name }}-webapp
spec:
  replicas: {{ .Values.replicaCount }}
  selector:
    matchLabels:
      app: webapp
  template:
    metadata:
      labels:
        app: webapp
    spec:
      containers:
      - name: webapp
        image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
        ports:
          - name: http
            containerPort: {{ .Values.service.port }}
            protocol: TCP
        livenessProbe:
          httpGet:
            path: /
            port: http
        readinessProbe:
          httpGet:
            path: /
            port: http
  • templates/service.yaml
apiVersion: v1
kind: Service
metadata:
  name: {{ .Release.Name }}-webapp
spec:
  type: {{ .Values.service.type }}
  ports:
    - port: {{ .Values.service.port }}
      targetPort: http
      protocol: TCP
      name: http
  selector:
    app: webapp
  • templates/ingress.yaml
{{- if .Values.ingress.enabled -}}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: {{ .Release.Name }}-webapp-ingress
  annotations:
    kubernetes.io/ingress.class: alb
    alb.ingress.kubernetes.io/scheme: internet-facing
spec:
  rules:
  - host: {{ .Values.ingress.host }}
    http:
      paths:
      - path: {{ .Values.ingress.path | default "/" }}
        pathType: Prefix
        backend:
          service:
            name: {{ .Release.Name }}-webapp
            port:
              number: {{ .Values.service.port }}

{{- end }}
  • values.yaml
image:
  repository: karpovych/express-hello-world
  tag: 5

replicaCount: 1

service: 
  port: 3000
  type: NodePort

ingress:
  enabled: true
  host: mywebapp.example.com
  path: /

Install chart

helm upgrade --install my-app . --debug
kubectl get all

Check access

export LOAD_BALANCER=$(kubectl get ingress my-app-webapp-ingress -o jsonpath="{.status.loadBalancer.ingress[0].hostname}")
echo "http://$LOAD_BALANCER"
dig $LOAD_BALANCER

Uninstall chart

helm uninstall my-app

Install MongoDB chart

helm install mongo oci://registry-1.docker.io/bitnamicharts/mongodb

Connect to mongo

Run pod with mongosh

export MONGODB_ROOT_PASSWORD=$(kubectl get secret mongo-mongodb -o jsonpath="{.data.mongodb-root-password}" | base64 -d)

kubectl run mongo-mongodb-client --rm --tty -i --restart='Never' --env="MONGODB_ROOT_PASSWORD=$MONGODB_ROOT_PASSWORD" --image docker.io/bitnami/mongodb:6.0.8-debian-11-r12 --command -- bash

Connect to mongodb and create data

mongosh admin --host "mongo-mongodb" --authenticationDatabase admin -u root -p $MONGODB_ROOT_PASSWORD
use testDB

db.testCollection.insertMany([
    { name: "John Doe", age: 30, profession: "Engineer" },
    { name: "Jane Smith", age: 25, profession: "Designer" },
    { name: "Bob Johnson", age: 35, profession: "Manager" }
])

db.testCollection.find().pretty()

Uninstall chart

helm uninstall mongo

Create umbrella chart

# back to parent folder
cd .. 

# create new chart and go to folder
helm create umbrella-chart && cd umbrella-chart

# clean up folder
rm -rf templates/* && rm values.yaml

Update files

  • umbrella-chart/Chart.yaml
...
dependencies:
  - name: mongodb
    version: "13.16.x"
    repository: https://charts.bitnami.com/bitnami
  - name: webapp
    version: "0.1.0"
    repository: file://../webapp
  • umbrella-chart/values.yaml
webapp:
  image:
    tag: 7
  service:
    port: 3000
  ingress:
    enabled: false
  • webapp/templates/deployment.yaml
...
spec:
  template:
    spec:
      containers:
      ...
      - name: webapp
        envFrom:
          - secretRef:
              name: {{ .Release.Name }}-mongodb
        env:
          - name: MONGO_USER
            value: 'root'
          - name: MONGO_HOST
            value: '{{ .Release.Name }}-mongodb'
          - name: MONGO_PORT
            value: '27017'
          - name: MONGO_PASSWORD
            valueFrom:
              secretKeyRef:
                name: {{ .Release.Name }}-mongodb
                key: mongodb-root-password
          - name: MONGO_URL
            value: "mongodb://$(MONGO_USER):$(MONGO_PASSWORD)@$(MONGO_HOST):$(MONGO_PORT)"
  • umbrella-chart/templates/ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: {{ .Release.Name }}-ingress
  annotations:
    kubernetes.io/ingress.class: alb
    alb.ingress.kubernetes.io/scheme: internet-facing
spec:
  rules:
    - http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: {{ .Release.Name }}-webapp
                port:
                  number: {{ .Values.webapp.service.port }}

Build dependencies:

helm dependency build

Install chart:

helm upgrade --install my-app . --debug
kubectl get all

Connect to mongo

Run pod with mongosh

export MONGODB_ROOT_PASSWORD=$(kubectl get secret my-app-mongodb -o jsonpath="{.data.mongodb-root-password}" | base64 -d)

kubectl run mongo-mongodb-client --rm --tty -i --restart='Never' --env="MONGODB_ROOT_PASSWORD=$MONGODB_ROOT_PASSWORD" --image docker.io/bitnami/mongodb:6.0.8-debian-11-r12 --command -- bash
mongosh admin --host "my-app-mongodb" --authenticationDatabase admin -u root -p $MONGODB_ROOT_PASSWORD
use testDB

db.testCollection.insertMany([
    { name: "John Doe", age: 30, profession: "Engineer" },
    { name: "Jane Smith", age: 25, profession: "Designer" },
    { name: "Bob Johnson", age: 35, profession: "Manager" }
])

Check website:

export LOAD_BALANCER=$(kubectl get ingress my-app-ingress -o jsonpath="{.status.loadBalancer.ingress[0].hostname}")
echo "http://$LOAD_BALANCER"

curl "http://$LOAD_BALANCER/mongodb"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment