brew install helm
helm version
source <(helm completion zsh)
source <(kubectl completion zsh)
export KUBECONFIG=$(pwd)/kubeconf.uu
kubectl config get-contexts
Set default namespace:
kubectl config set-context --current --namespace=<namespace>
kubectl config get-contexts
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.
helm template .
run lint:
helm lint
helm install my-app . --debug
kubectl get all
helm test my-app
More info: https://helm.sh/docs/topics/chart_tests/
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
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
helm uninstall my-app
# 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
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: /
helm upgrade --install my-app . --debug
kubectl get all
export LOAD_BALANCER=$(kubectl get ingress my-app-webapp-ingress -o jsonpath="{.status.loadBalancer.ingress[0].hostname}")
echo "http://$LOAD_BALANCER"
dig $LOAD_BALANCER
helm uninstall my-app
helm install mongo oci://registry-1.docker.io/bitnamicharts/mongodb
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()
helm uninstall mongo
# 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
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
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"