diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 00000000..73f69e09
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
+# Editor-based HTTP Client requests
+/httpRequests/
diff --git a/.idea/manabie-com.github.io.iml b/.idea/manabie-com.github.io.iml
new file mode 100644
index 00000000..c956989b
--- /dev/null
+++ b/.idea/manabie-com.github.io.iml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 00000000..38e774eb
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 00000000..6b9c29fa
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/.helmignore b/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/.helmignore
new file mode 100644
index 00000000..0e8a0eb3
--- /dev/null
+++ b/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/.helmignore
@@ -0,0 +1,23 @@
+# Patterns to ignore when building packages.
+# This supports shell glob matching, relative path matching, and
+# negation (prefixed with !). Only one pattern per line.
+.DS_Store
+# Common VCS dirs
+.git/
+.gitignore
+.bzr/
+.bzrignore
+.hg/
+.hgignore
+.svn/
+# Common backup files
+*.swp
+*.bak
+*.tmp
+*.orig
+*~
+# Various IDEs
+.project
+.idea/
+*.tmproj
+.vscode/
diff --git a/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/Chart.lock b/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/Chart.lock
new file mode 100644
index 00000000..c3831f6d
--- /dev/null
+++ b/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/Chart.lock
@@ -0,0 +1,9 @@
+dependencies:
+- name: another-nginx
+ repository: file://../another-nginx
+ version: 0.1.0
+- name: mynginx
+ repository: file://../mynginx
+ version: 0.1.0
+digest: sha256:7fd5f319b4ae8a45e97f6b9806022d226b785149297a9487acc2a7551cddeff1
+generated: "2021-12-15T15:14:37.612073449+07:00"
diff --git a/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/Chart.yaml b/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/Chart.yaml
new file mode 100644
index 00000000..e6397f70
--- /dev/null
+++ b/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/Chart.yaml
@@ -0,0 +1,24 @@
+apiVersion: v2
+name: all-in-one
+description: A Helm chart for Kubernetes
+
+# A chart can be either an 'application' or a 'library' chart.
+#
+# Application charts are a collection of templates that can be packaged into versioned archives
+# to be deployed.
+#
+# Library charts provide useful utilities or functions for the chart developer. They're included as
+# a dependency of application charts to inject those utilities and functions into the rendering
+# pipeline. Library charts do not define any templates and therefore cannot be deployed.
+type: application
+
+# This is the chart version. This version number should be incremented each time you make changes
+# to the chart and its templates, including the app version.
+# Versions are expected to follow Semantic Versioning (https://semver.org/)
+version: 0.1.0
+
+# This is the version number of the application being deployed. This version number should be
+# incremented each time you make changes to the application. Versions are not expected to
+# follow Semantic Versioning. They should reflect the version the application is using.
+# It is recommended to use it with quotes.
+appVersion: "1.16.0"
\ No newline at end of file
diff --git a/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/another-nginx/.helmignore b/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/another-nginx/.helmignore
new file mode 100644
index 00000000..0e8a0eb3
--- /dev/null
+++ b/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/another-nginx/.helmignore
@@ -0,0 +1,23 @@
+# Patterns to ignore when building packages.
+# This supports shell glob matching, relative path matching, and
+# negation (prefixed with !). Only one pattern per line.
+.DS_Store
+# Common VCS dirs
+.git/
+.gitignore
+.bzr/
+.bzrignore
+.hg/
+.hgignore
+.svn/
+# Common backup files
+*.swp
+*.bak
+*.tmp
+*.orig
+*~
+# Various IDEs
+.project
+.idea/
+*.tmproj
+.vscode/
diff --git a/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/another-nginx/Chart.lock b/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/another-nginx/Chart.lock
new file mode 100644
index 00000000..bbd95ad6
--- /dev/null
+++ b/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/another-nginx/Chart.lock
@@ -0,0 +1,6 @@
+dependencies:
+- name: metrics
+ repository: file://../metrics
+ version: 0.1.0
+digest: sha256:3f0b5d9bb4d3c1b47dc84f7ca7be1492ac9d3d8a1a8f4ac7fb19e4a998d3dd15
+generated: "2021-12-15T15:11:32.246451292+07:00"
diff --git a/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/another-nginx/Chart.yaml b/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/another-nginx/Chart.yaml
new file mode 100644
index 00000000..4703e9fe
--- /dev/null
+++ b/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/another-nginx/Chart.yaml
@@ -0,0 +1,28 @@
+apiVersion: v2
+name: another-nginx
+description: A Helm chart for Kubernetes
+
+# A chart can be either an 'application' or a 'library' chart.
+#
+# Application charts are a collection of templates that can be packaged into versioned archives
+# to be deployed.
+#
+# Library charts provide useful utilities or functions for the chart developer. They're included as
+# a dependency of application charts to inject those utilities and functions into the rendering
+# pipeline. Library charts do not define any templates and therefore cannot be deployed.
+type: application
+
+# This is the chart version. This version number should be incremented each time you make changes
+# to the chart and its templates, including the app version.
+# Versions are expected to follow Semantic Versioning (https://semver.org/)
+version: 0.1.0
+
+# This is the version number of the application being deployed. This version number should be
+# incremented each time you make changes to the application. Versions are not expected to
+# follow Semantic Versioning. They should reflect the version the application is using.
+# It is recommended to use it with quotes.
+appVersion: "1.16.0"
+dependencies:
+- name: metrics
+ version: 0.1.0
+ repository: file://../../metrics
\ No newline at end of file
diff --git a/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/another-nginx/charts/metrics-0.1.0.tgz b/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/another-nginx/charts/metrics-0.1.0.tgz
new file mode 100644
index 00000000..77f72b88
Binary files /dev/null and b/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/another-nginx/charts/metrics-0.1.0.tgz differ
diff --git a/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/another-nginx/templates/NOTES.txt b/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/another-nginx/templates/NOTES.txt
new file mode 100644
index 00000000..a02afbdf
--- /dev/null
+++ b/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/another-nginx/templates/NOTES.txt
@@ -0,0 +1,22 @@
+1. Get the application URL by running these commands:
+{{- if .Values.ingress.enabled }}
+{{- range $host := .Values.ingress.hosts }}
+ {{- range .paths }}
+ http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }}
+ {{- end }}
+{{- end }}
+{{- else if contains "NodePort" .Values.service.type }}
+ export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "another-nginx.fullname" . }})
+ export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
+ echo http://$NODE_IP:$NODE_PORT
+{{- else if contains "LoadBalancer" .Values.service.type }}
+ NOTE: It may take a few minutes for the LoadBalancer IP to be available.
+ You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "another-nginx.fullname" . }}'
+ export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "another-nginx.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
+ echo http://$SERVICE_IP:{{ .Values.service.port }}
+{{- else if contains "ClusterIP" .Values.service.type }}
+ export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "another-nginx.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
+ export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
+ echo "Visit http://127.0.0.1:8080 to use your application"
+ kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT
+{{- end }}
diff --git a/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/another-nginx/templates/_helpers.tpl b/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/another-nginx/templates/_helpers.tpl
new file mode 100644
index 00000000..a18ef8b5
--- /dev/null
+++ b/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/another-nginx/templates/_helpers.tpl
@@ -0,0 +1,62 @@
+{{/*
+Expand the name of the chart.
+*/}}
+{{- define "another-nginx.name" -}}
+{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
+{{- end }}
+
+{{/*
+Create a default fully qualified app name.
+We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
+If release name contains chart name it will be used as a full name.
+*/}}
+{{- define "another-nginx.fullname" -}}
+{{- if .Values.fullnameOverride }}
+{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
+{{- else }}
+{{- $name := default .Chart.Name .Values.nameOverride }}
+{{- if contains $name .Release.Name }}
+{{- .Release.Name | trunc 63 | trimSuffix "-" }}
+{{- else }}
+{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
+{{- end }}
+{{- end }}
+{{- end }}
+
+{{/*
+Create chart name and version as used by the chart label.
+*/}}
+{{- define "another-nginx.chart" -}}
+{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
+{{- end }}
+
+{{/*
+Common labels
+*/}}
+{{- define "another-nginx.labels" -}}
+helm.sh/chart: {{ include "another-nginx.chart" . }}
+{{ include "another-nginx.selectorLabels" . }}
+{{- if .Chart.AppVersion }}
+app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
+{{- end }}
+app.kubernetes.io/managed-by: {{ .Release.Service }}
+{{- end }}
+
+{{/*
+Selector labels
+*/}}
+{{- define "another-nginx.selectorLabels" -}}
+app.kubernetes.io/name: {{ include "another-nginx.name" . }}
+app.kubernetes.io/instance: {{ .Release.Name }}
+{{- end }}
+
+{{/*
+Create the name of the service account to use
+*/}}
+{{- define "another-nginx.serviceAccountName" -}}
+{{- if .Values.serviceAccount.create }}
+{{- default (include "another-nginx.fullname" .) .Values.serviceAccount.name }}
+{{- else }}
+{{- default "default" .Values.serviceAccount.name }}
+{{- end }}
+{{- end }}
diff --git a/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/another-nginx/templates/configmap.yaml b/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/another-nginx/templates/configmap.yaml
new file mode 100644
index 00000000..c5442cba
--- /dev/null
+++ b/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/another-nginx/templates/configmap.yaml
@@ -0,0 +1 @@
+{{ include "metrics.configmap.tpl" . }}
\ No newline at end of file
diff --git a/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/another-nginx/templates/deployment.yaml b/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/another-nginx/templates/deployment.yaml
new file mode 100644
index 00000000..57035957
--- /dev/null
+++ b/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/another-nginx/templates/deployment.yaml
@@ -0,0 +1,66 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: {{ include "another-nginx.fullname" . }}
+ labels:
+ {{- include "another-nginx.labels" . | nindent 4 }}
+spec:
+ {{- if not .Values.autoscaling.enabled }}
+ replicas: {{ .Values.replicaCount }}
+ {{- end }}
+ selector:
+ matchLabels:
+ {{- include "another-nginx.selectorLabels" . | nindent 6 }}
+ template:
+ metadata:
+ {{- with .Values.podAnnotations }}
+ annotations:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ labels:
+ {{- include "another-nginx.selectorLabels" . | nindent 8 }}
+ spec:
+ {{- with .Values.imagePullSecrets }}
+ imagePullSecrets:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ serviceAccountName: {{ include "another-nginx.serviceAccountName" . }}
+ securityContext:
+ {{- toYaml .Values.podSecurityContext | nindent 8 }}
+ volumes:
+ - {{ include "metrics.volume.tpl" . | nindent 8 }}
+ containers:
+ - name: {{ .Chart.Name }}
+ securityContext:
+ {{- toYaml .Values.securityContext | nindent 12 }}
+ image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
+ imagePullPolicy: {{ .Values.image.pullPolicy }}
+ ports:
+ - name: http
+ containerPort: 80
+ protocol: TCP
+ livenessProbe:
+ httpGet:
+ path: /
+ port: http
+ readinessProbe:
+ httpGet:
+ path: /
+ port: http
+ resources:
+ {{- toYaml .Values.resources | nindent 12 }}
+ volumeMounts:
+ - {{- include "metrics.volume-mount.tpl" . | nindent 12 }}
+ - {{- include "metrics.container.tpl" . | nindent 10 }}
+ {{- with .Values.nodeSelector }}
+ nodeSelector:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.affinity }}
+ affinity:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.tolerations }}
+ tolerations:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
diff --git a/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/another-nginx/templates/hpa.yaml b/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/another-nginx/templates/hpa.yaml
new file mode 100644
index 00000000..519726a2
--- /dev/null
+++ b/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/another-nginx/templates/hpa.yaml
@@ -0,0 +1,28 @@
+{{- if .Values.autoscaling.enabled }}
+apiVersion: autoscaling/v2beta1
+kind: HorizontalPodAutoscaler
+metadata:
+ name: {{ include "another-nginx.fullname" . }}
+ labels:
+ {{- include "another-nginx.labels" . | nindent 4 }}
+spec:
+ scaleTargetRef:
+ apiVersion: apps/v1
+ kind: Deployment
+ name: {{ include "another-nginx.fullname" . }}
+ minReplicas: {{ .Values.autoscaling.minReplicas }}
+ maxReplicas: {{ .Values.autoscaling.maxReplicas }}
+ metrics:
+ {{- if .Values.autoscaling.targetCPUUtilizationPercentage }}
+ - type: Resource
+ resource:
+ name: cpu
+ targetAverageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }}
+ {{- end }}
+ {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }}
+ - type: Resource
+ resource:
+ name: memory
+ targetAverageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }}
+ {{- end }}
+{{- end }}
diff --git a/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/another-nginx/templates/ingress.yaml b/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/another-nginx/templates/ingress.yaml
new file mode 100644
index 00000000..415ec8bd
--- /dev/null
+++ b/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/another-nginx/templates/ingress.yaml
@@ -0,0 +1,41 @@
+{{- if .Values.ingress.enabled -}}
+{{- $fullName := include "another-nginx.fullname" . -}}
+{{- $svcPort := .Values.service.port -}}
+{{- if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}}
+apiVersion: networking.k8s.io/v1beta1
+{{- else -}}
+apiVersion: extensions/v1beta1
+{{- end }}
+kind: Ingress
+metadata:
+ name: {{ $fullName }}
+ labels:
+ {{- include "another-nginx.labels" . | nindent 4 }}
+ {{- with .Values.ingress.annotations }}
+ annotations:
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+spec:
+ {{- if .Values.ingress.tls }}
+ tls:
+ {{- range .Values.ingress.tls }}
+ - hosts:
+ {{- range .hosts }}
+ - {{ . | quote }}
+ {{- end }}
+ secretName: {{ .secretName }}
+ {{- end }}
+ {{- end }}
+ rules:
+ {{- range .Values.ingress.hosts }}
+ - host: {{ .host | quote }}
+ http:
+ paths:
+ {{- range .paths }}
+ - path: {{ .path }}
+ backend:
+ serviceName: {{ $fullName }}
+ servicePort: {{ $svcPort }}
+ {{- end }}
+ {{- end }}
+ {{- end }}
diff --git a/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/another-nginx/templates/service.yaml b/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/another-nginx/templates/service.yaml
new file mode 100644
index 00000000..7c8aa38b
--- /dev/null
+++ b/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/another-nginx/templates/service.yaml
@@ -0,0 +1,19 @@
+apiVersion: v1
+kind: Service
+metadata:
+ name: {{ include "another-nginx.fullname" . }}
+ labels:
+ {{- include "another-nginx.labels" . | nindent 4 }}
+spec:
+ type: {{ .Values.service.type }}
+ ports:
+ - port: {{ .Values.service.port }}
+ targetPort: http
+ protocol: TCP
+ name: http
+ - port: 9113
+ targetPort: exporter
+ protocol: TCP
+ name: exporter
+ selector:
+ {{- include "another-nginx.selectorLabels" . | nindent 4 }}
diff --git a/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/another-nginx/templates/serviceaccount.yaml b/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/another-nginx/templates/serviceaccount.yaml
new file mode 100644
index 00000000..9e7b4454
--- /dev/null
+++ b/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/another-nginx/templates/serviceaccount.yaml
@@ -0,0 +1,12 @@
+{{- if .Values.serviceAccount.create -}}
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: {{ include "another-nginx.serviceAccountName" . }}
+ labels:
+ {{- include "another-nginx.labels" . | nindent 4 }}
+ {{- with .Values.serviceAccount.annotations }}
+ annotations:
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+{{- end }}
diff --git a/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/another-nginx/templates/tests/test-connection.yaml b/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/another-nginx/templates/tests/test-connection.yaml
new file mode 100644
index 00000000..ec2cb0a6
--- /dev/null
+++ b/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/another-nginx/templates/tests/test-connection.yaml
@@ -0,0 +1,15 @@
+apiVersion: v1
+kind: Pod
+metadata:
+ name: "{{ include "another-nginx.fullname" . }}-test-connection"
+ labels:
+ {{- include "another-nginx.labels" . | nindent 4 }}
+ annotations:
+ "helm.sh/hook": test
+spec:
+ containers:
+ - name: wget
+ image: busybox
+ command: ['wget']
+ args: ['{{ include "another-nginx.fullname" . }}:{{ .Values.service.port }}']
+ restartPolicy: Never
diff --git a/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/another-nginx/values.yaml b/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/another-nginx/values.yaml
new file mode 100644
index 00000000..e8220c52
--- /dev/null
+++ b/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/another-nginx/values.yaml
@@ -0,0 +1,83 @@
+# Default values for another-nginx.
+# This is a YAML-formatted file.
+# Declare variables to be passed into your templates.
+
+replicaCount: 1
+
+image:
+ repository: nginx
+ pullPolicy: IfNotPresent
+ # Overrides the image tag whose default is the chart appVersion.
+ tag: ""
+
+imagePullSecrets: []
+nameOverride: "another-nginx"
+fullnameOverride: "another-nginx"
+
+serviceAccount:
+ # Specifies whether a service account should be created
+ create: true
+ # Annotations to add to the service account
+ annotations: {}
+ # The name of the service account to use.
+ # If not set and create is true, a name is generated using the fullname template
+ name: ""
+
+podAnnotations: {}
+
+podSecurityContext: {}
+ # fsGroup: 2000
+
+securityContext: {}
+ # capabilities:
+ # drop:
+ # - ALL
+ # readOnlyRootFilesystem: true
+ # runAsNonRoot: true
+ # runAsUser: 1000
+
+service:
+ type: ClusterIP
+ port: 80
+
+ingress:
+ enabled: false
+ annotations: {}
+ # kubernetes.io/ingress.class: nginx
+ # kubernetes.io/tls-acme: "true"
+ hosts:
+ - host: chart-example.local
+ paths:
+ - path: /
+ backend:
+ serviceName: chart-example.local
+ servicePort: 80
+ tls: []
+ # - secretName: chart-example-tls
+ # hosts:
+ # - chart-example.local
+
+resources: {}
+ # We usually recommend not to specify default resources and to leave this as a conscious
+ # choice for the user. This also increases chances charts run on environments with little
+ # resources, such as Minikube. If you do want to specify resources, uncomment the following
+ # lines, adjust them as necessary, and remove the curly braces after 'resources:'.
+ # limits:
+ # cpu: 100m
+ # memory: 128Mi
+ # requests:
+ # cpu: 100m
+ # memory: 128Mi
+
+autoscaling:
+ enabled: false
+ minReplicas: 1
+ maxReplicas: 100
+ targetCPUUtilizationPercentage: 80
+ # targetMemoryUtilizationPercentage: 80
+
+nodeSelector: {}
+
+tolerations: []
+
+affinity: {}
diff --git a/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/mynginx/.helmignore b/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/mynginx/.helmignore
new file mode 100644
index 00000000..0e8a0eb3
--- /dev/null
+++ b/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/mynginx/.helmignore
@@ -0,0 +1,23 @@
+# Patterns to ignore when building packages.
+# This supports shell glob matching, relative path matching, and
+# negation (prefixed with !). Only one pattern per line.
+.DS_Store
+# Common VCS dirs
+.git/
+.gitignore
+.bzr/
+.bzrignore
+.hg/
+.hgignore
+.svn/
+# Common backup files
+*.swp
+*.bak
+*.tmp
+*.orig
+*~
+# Various IDEs
+.project
+.idea/
+*.tmproj
+.vscode/
diff --git a/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/mynginx/Chart.lock b/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/mynginx/Chart.lock
new file mode 100644
index 00000000..1bfffe54
--- /dev/null
+++ b/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/mynginx/Chart.lock
@@ -0,0 +1,6 @@
+dependencies:
+- name: metrics
+ repository: file://../metrics
+ version: 0.1.0
+digest: sha256:3f0b5d9bb4d3c1b47dc84f7ca7be1492ac9d3d8a1a8f4ac7fb19e4a998d3dd15
+generated: "2021-12-15T14:59:05.768841877+07:00"
diff --git a/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/mynginx/Chart.yaml b/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/mynginx/Chart.yaml
new file mode 100644
index 00000000..68e05db8
--- /dev/null
+++ b/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/mynginx/Chart.yaml
@@ -0,0 +1,28 @@
+apiVersion: v2
+name: mynginx
+description: A Helm chart for Kubernetes
+
+# A chart can be either an 'application' or a 'library' chart.
+#
+# Application charts are a collection of templates that can be packaged into versioned archives
+# to be deployed.
+#
+# Library charts provide useful utilities or functions for the chart developer. They're included as
+# a dependency of application charts to inject those utilities and functions into the rendering
+# pipeline. Library charts do not define any templates and therefore cannot be deployed.
+type: application
+
+# This is the chart version. This version number should be incremented each time you make changes
+# to the chart and its templates, including the app version.
+# Versions are expected to follow Semantic Versioning (https://semver.org/)
+version: 0.1.0
+
+# This is the version number of the application being deployed. This version number should be
+# incremented each time you make changes to the application. Versions are not expected to
+# follow Semantic Versioning. They should reflect the version the application is using.
+# It is recommended to use it with quotes.
+appVersion: "1.16.0"
+dependencies:
+- name: metrics
+ version: 0.1.0
+ repository: file://../../metrics
\ No newline at end of file
diff --git a/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/mynginx/charts/metrics-0.1.0.tgz b/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/mynginx/charts/metrics-0.1.0.tgz
new file mode 100644
index 00000000..121f355c
Binary files /dev/null and b/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/mynginx/charts/metrics-0.1.0.tgz differ
diff --git a/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/mynginx/templates/NOTES.txt b/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/mynginx/templates/NOTES.txt
new file mode 100644
index 00000000..112f1756
--- /dev/null
+++ b/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/mynginx/templates/NOTES.txt
@@ -0,0 +1,22 @@
+1. Get the application URL by running these commands:
+{{- if .Values.ingress.enabled }}
+{{- range $host := .Values.ingress.hosts }}
+ {{- range .paths }}
+ http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }}
+ {{- end }}
+{{- end }}
+{{- else if contains "NodePort" .Values.service.type }}
+ export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "mynginx.fullname" . }})
+ export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
+ echo http://$NODE_IP:$NODE_PORT
+{{- else if contains "LoadBalancer" .Values.service.type }}
+ NOTE: It may take a few minutes for the LoadBalancer IP to be available.
+ You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "mynginx.fullname" . }}'
+ export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "mynginx.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
+ echo http://$SERVICE_IP:{{ .Values.service.port }}
+{{- else if contains "ClusterIP" .Values.service.type }}
+ export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "mynginx.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
+ export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
+ echo "Visit http://127.0.0.1:8080 to use your application"
+ kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT
+{{- end }}
diff --git a/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/mynginx/templates/_helpers.tpl b/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/mynginx/templates/_helpers.tpl
new file mode 100644
index 00000000..a818ac9d
--- /dev/null
+++ b/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/mynginx/templates/_helpers.tpl
@@ -0,0 +1,62 @@
+{{/*
+Expand the name of the chart.
+*/}}
+{{- define "mynginx.name" -}}
+{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
+{{- end }}
+
+{{/*
+Create a default fully qualified app name.
+We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
+If release name contains chart name it will be used as a full name.
+*/}}
+{{- define "mynginx.fullname" -}}
+{{- if .Values.fullnameOverride }}
+{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
+{{- else }}
+{{- $name := default .Chart.Name .Values.nameOverride }}
+{{- if contains $name .Release.Name }}
+{{- .Release.Name | trunc 63 | trimSuffix "-" }}
+{{- else }}
+{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
+{{- end }}
+{{- end }}
+{{- end }}
+
+{{/*
+Create chart name and version as used by the chart label.
+*/}}
+{{- define "mynginx.chart" -}}
+{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
+{{- end }}
+
+{{/*
+Common labels
+*/}}
+{{- define "mynginx.labels" -}}
+helm.sh/chart: {{ include "mynginx.chart" . }}
+{{ include "mynginx.selectorLabels" . }}
+{{- if .Chart.AppVersion }}
+app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
+{{- end }}
+app.kubernetes.io/managed-by: {{ .Release.Service }}
+{{- end }}
+
+{{/*
+Selector labels
+*/}}
+{{- define "mynginx.selectorLabels" -}}
+app.kubernetes.io/name: {{ include "mynginx.name" . }}
+app.kubernetes.io/instance: {{ .Release.Name }}
+{{- end }}
+
+{{/*
+Create the name of the service account to use
+*/}}
+{{- define "mynginx.serviceAccountName" -}}
+{{- if .Values.serviceAccount.create }}
+{{- default (include "mynginx.fullname" .) .Values.serviceAccount.name }}
+{{- else }}
+{{- default "default" .Values.serviceAccount.name }}
+{{- end }}
+{{- end }}
diff --git a/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/mynginx/templates/configmap.yaml b/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/mynginx/templates/configmap.yaml
new file mode 100644
index 00000000..c5442cba
--- /dev/null
+++ b/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/mynginx/templates/configmap.yaml
@@ -0,0 +1 @@
+{{ include "metrics.configmap.tpl" . }}
\ No newline at end of file
diff --git a/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/mynginx/templates/deployment.yaml b/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/mynginx/templates/deployment.yaml
new file mode 100644
index 00000000..c5eed0cc
--- /dev/null
+++ b/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/mynginx/templates/deployment.yaml
@@ -0,0 +1,66 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: {{ include "mynginx.fullname" . }}
+ labels:
+ {{- include "mynginx.labels" . | nindent 4 }}
+spec:
+ {{- if not .Values.autoscaling.enabled }}
+ replicas: {{ .Values.replicaCount }}
+ {{- end }}
+ selector:
+ matchLabels:
+ {{- include "mynginx.selectorLabels" . | nindent 6 }}
+ template:
+ metadata:
+ {{- with .Values.podAnnotations }}
+ annotations:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ labels:
+ {{- include "mynginx.selectorLabels" . | nindent 8 }}
+ spec:
+ {{- with .Values.imagePullSecrets }}
+ imagePullSecrets:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ serviceAccountName: {{ include "mynginx.serviceAccountName" . }}
+ securityContext:
+ {{- toYaml .Values.podSecurityContext | nindent 8 }}
+ volumes:
+ - {{ include "metrics.volume.tpl" . | nindent 8 }}
+ containers:
+ - name: {{ .Chart.Name }}
+ securityContext:
+ {{- toYaml .Values.securityContext | nindent 12 }}
+ image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
+ imagePullPolicy: {{ .Values.image.pullPolicy }}
+ ports:
+ - name: http
+ containerPort: 80
+ protocol: TCP
+ livenessProbe:
+ httpGet:
+ path: /
+ port: http
+ readinessProbe:
+ httpGet:
+ path: /
+ port: http
+ resources:
+ {{- toYaml .Values.resources | nindent 12 }}
+ volumeMounts:
+ - {{- include "metrics.volume-mount.tpl" . | nindent 12 }}
+ - {{- include "metrics.container.tpl" . | nindent 10 }}
+ {{- with .Values.nodeSelector }}
+ nodeSelector:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.affinity }}
+ affinity:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.tolerations }}
+ tolerations:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
diff --git a/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/mynginx/templates/hpa.yaml b/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/mynginx/templates/hpa.yaml
new file mode 100644
index 00000000..2a6237bb
--- /dev/null
+++ b/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/mynginx/templates/hpa.yaml
@@ -0,0 +1,28 @@
+{{- if .Values.autoscaling.enabled }}
+apiVersion: autoscaling/v2beta1
+kind: HorizontalPodAutoscaler
+metadata:
+ name: {{ include "mynginx.fullname" . }}
+ labels:
+ {{- include "mynginx.labels" . | nindent 4 }}
+spec:
+ scaleTargetRef:
+ apiVersion: apps/v1
+ kind: Deployment
+ name: {{ include "mynginx.fullname" . }}
+ minReplicas: {{ .Values.autoscaling.minReplicas }}
+ maxReplicas: {{ .Values.autoscaling.maxReplicas }}
+ metrics:
+ {{- if .Values.autoscaling.targetCPUUtilizationPercentage }}
+ - type: Resource
+ resource:
+ name: cpu
+ targetAverageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }}
+ {{- end }}
+ {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }}
+ - type: Resource
+ resource:
+ name: memory
+ targetAverageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }}
+ {{- end }}
+{{- end }}
diff --git a/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/mynginx/templates/ingress.yaml b/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/mynginx/templates/ingress.yaml
new file mode 100644
index 00000000..db38df6c
--- /dev/null
+++ b/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/mynginx/templates/ingress.yaml
@@ -0,0 +1,41 @@
+{{- if .Values.ingress.enabled -}}
+{{- $fullName := include "mynginx.fullname" . -}}
+{{- $svcPort := .Values.service.port -}}
+{{- if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}}
+apiVersion: networking.k8s.io/v1beta1
+{{- else -}}
+apiVersion: extensions/v1beta1
+{{- end }}
+kind: Ingress
+metadata:
+ name: {{ $fullName }}
+ labels:
+ {{- include "mynginx.labels" . | nindent 4 }}
+ {{- with .Values.ingress.annotations }}
+ annotations:
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+spec:
+ {{- if .Values.ingress.tls }}
+ tls:
+ {{- range .Values.ingress.tls }}
+ - hosts:
+ {{- range .hosts }}
+ - {{ . | quote }}
+ {{- end }}
+ secretName: {{ .secretName }}
+ {{- end }}
+ {{- end }}
+ rules:
+ {{- range .Values.ingress.hosts }}
+ - host: {{ .host | quote }}
+ http:
+ paths:
+ {{- range .paths }}
+ - path: {{ .path }}
+ backend:
+ serviceName: {{ $fullName }}
+ servicePort: {{ $svcPort }}
+ {{- end }}
+ {{- end }}
+ {{- end }}
diff --git a/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/mynginx/templates/service.yaml b/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/mynginx/templates/service.yaml
new file mode 100644
index 00000000..27deca39
--- /dev/null
+++ b/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/mynginx/templates/service.yaml
@@ -0,0 +1,19 @@
+apiVersion: v1
+kind: Service
+metadata:
+ name: {{ include "mynginx.fullname" . }}
+ labels:
+ {{- include "mynginx.labels" . | nindent 4 }}
+spec:
+ type: {{ .Values.service.type }}
+ ports:
+ - port: {{ .Values.service.port }}
+ targetPort: http
+ protocol: TCP
+ name: http
+ - port: 9113
+ targetPort: exporter
+ protocol: TCP
+ name: exporter
+ selector:
+ {{- include "mynginx.selectorLabels" . | nindent 4 }}
diff --git a/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/mynginx/templates/serviceaccount.yaml b/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/mynginx/templates/serviceaccount.yaml
new file mode 100644
index 00000000..bbd4de56
--- /dev/null
+++ b/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/mynginx/templates/serviceaccount.yaml
@@ -0,0 +1,12 @@
+{{- if .Values.serviceAccount.create -}}
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: {{ include "mynginx.serviceAccountName" . }}
+ labels:
+ {{- include "mynginx.labels" . | nindent 4 }}
+ {{- with .Values.serviceAccount.annotations }}
+ annotations:
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+{{- end }}
diff --git a/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/mynginx/templates/tests/test-connection.yaml b/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/mynginx/templates/tests/test-connection.yaml
new file mode 100644
index 00000000..30eb6dba
--- /dev/null
+++ b/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/mynginx/templates/tests/test-connection.yaml
@@ -0,0 +1,15 @@
+apiVersion: v1
+kind: Pod
+metadata:
+ name: "{{ include "mynginx.fullname" . }}-test-connection"
+ labels:
+ {{- include "mynginx.labels" . | nindent 4 }}
+ annotations:
+ "helm.sh/hook": test
+spec:
+ containers:
+ - name: wget
+ image: busybox
+ command: ['wget']
+ args: ['{{ include "mynginx.fullname" . }}:{{ .Values.service.port }}']
+ restartPolicy: Never
diff --git a/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/mynginx/values.yaml b/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/mynginx/values.yaml
new file mode 100644
index 00000000..3cb1a525
--- /dev/null
+++ b/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/charts/mynginx/values.yaml
@@ -0,0 +1,83 @@
+# Default values for mynginx.
+# This is a YAML-formatted file.
+# Declare variables to be passed into your templates.
+
+replicaCount: 1
+
+image:
+ repository: nginx
+ pullPolicy: IfNotPresent
+ # Overrides the image tag whose default is the chart appVersion.
+ tag: ""
+
+imagePullSecrets: []
+nameOverride: "mynginx"
+fullnameOverride: "mynginx"
+
+serviceAccount:
+ # Specifies whether a service account should be created
+ create: true
+ # Annotations to add to the service account
+ annotations: {}
+ # The name of the service account to use.
+ # If not set and create is true, a name is generated using the fullname template
+ name: ""
+
+podAnnotations: {}
+
+podSecurityContext: {}
+ # fsGroup: 2000
+
+securityContext: {}
+ # capabilities:
+ # drop:
+ # - ALL
+ # readOnlyRootFilesystem: true
+ # runAsNonRoot: true
+ # runAsUser: 1000
+
+service:
+ type: ClusterIP
+ port: 80
+
+ingress:
+ enabled: false
+ annotations: {}
+ # kubernetes.io/ingress.class: nginx
+ # kubernetes.io/tls-acme: "true"
+ hosts:
+ - host: chart-example.local
+ paths:
+ - path: /
+ backend:
+ serviceName: chart-example.local
+ servicePort: 80
+ tls: []
+ # - secretName: chart-example-tls
+ # hosts:
+ # - chart-example.local
+
+resources: {}
+ # We usually recommend not to specify default resources and to leave this as a conscious
+ # choice for the user. This also increases chances charts run on environments with little
+ # resources, such as Minikube. If you do want to specify resources, uncomment the following
+ # lines, adjust them as necessary, and remove the curly braces after 'resources:'.
+ # limits:
+ # cpu: 100m
+ # memory: 128Mi
+ # requests:
+ # cpu: 100m
+ # memory: 128Mi
+
+autoscaling:
+ enabled: false
+ minReplicas: 1
+ maxReplicas: 100
+ targetCPUUtilizationPercentage: 80
+ # targetMemoryUtilizationPercentage: 80
+
+nodeSelector: {}
+
+tolerations: []
+
+affinity: {}
diff --git a/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/values.yaml b/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/values.yaml
new file mode 100644
index 00000000..d284959b
--- /dev/null
+++ b/content/posts/deploying-application-on-k8s-with-helm/examples/all-in-one/values.yaml
@@ -0,0 +1,83 @@
+# Default values for all-in-one.
+# This is a YAML-formatted file.
+# Declare variables to be passed into your templates.
+
+replicaCount: 1
+
+image:
+ repository: nginx
+ pullPolicy: IfNotPresent
+ # Overrides the image tag whose default is the chart appVersion.
+ tag: ""
+
+imagePullSecrets: []
+nameOverride: ""
+fullnameOverride: ""
+
+serviceAccount:
+ # Specifies whether a service account should be created
+ create: true
+ # Annotations to add to the service account
+ annotations: {}
+ # The name of the service account to use.
+ # If not set and create is true, a name is generated using the fullname template
+ name: ""
+
+podAnnotations: {}
+
+podSecurityContext: {}
+ # fsGroup: 2000
+
+securityContext: {}
+ # capabilities:
+ # drop:
+ # - ALL
+ # readOnlyRootFilesystem: true
+ # runAsNonRoot: true
+ # runAsUser: 1000
+
+service:
+ type: ClusterIP
+ port: 80
+
+ingress:
+ enabled: false
+ annotations: {}
+ # kubernetes.io/ingress.class: nginx
+ # kubernetes.io/tls-acme: "true"
+ hosts:
+ - host: chart-example.local
+ paths:
+ - path: /
+ backend:
+ serviceName: chart-example.local
+ servicePort: 80
+ tls: []
+ # - secretName: chart-example-tls
+ # hosts:
+ # - chart-example.local
+
+resources: {}
+ # We usually recommend not to specify default resources and to leave this as a conscious
+ # choice for the user. This also increases chances charts run on environments with little
+ # resources, such as Minikube. If you do want to specify resources, uncomment the following
+ # lines, adjust them as necessary, and remove the curly braces after 'resources:'.
+ # limits:
+ # cpu: 100m
+ # memory: 128Mi
+ # requests:
+ # cpu: 100m
+ # memory: 128Mi
+
+autoscaling:
+ enabled: false
+ minReplicas: 1
+ maxReplicas: 100
+ targetCPUUtilizationPercentage: 80
+ # targetMemoryUtilizationPercentage: 80
+
+nodeSelector: {}
+
+tolerations: []
+
+affinity: {}
diff --git a/content/posts/deploying-application-on-k8s-with-helm/examples/another-nginx/.helmignore b/content/posts/deploying-application-on-k8s-with-helm/examples/another-nginx/.helmignore
new file mode 100644
index 00000000..0e8a0eb3
--- /dev/null
+++ b/content/posts/deploying-application-on-k8s-with-helm/examples/another-nginx/.helmignore
@@ -0,0 +1,23 @@
+# Patterns to ignore when building packages.
+# This supports shell glob matching, relative path matching, and
+# negation (prefixed with !). Only one pattern per line.
+.DS_Store
+# Common VCS dirs
+.git/
+.gitignore
+.bzr/
+.bzrignore
+.hg/
+.hgignore
+.svn/
+# Common backup files
+*.swp
+*.bak
+*.tmp
+*.orig
+*~
+# Various IDEs
+.project
+.idea/
+*.tmproj
+.vscode/
diff --git a/content/posts/deploying-application-on-k8s-with-helm/examples/another-nginx/Chart.lock b/content/posts/deploying-application-on-k8s-with-helm/examples/another-nginx/Chart.lock
new file mode 100644
index 00000000..bbd95ad6
--- /dev/null
+++ b/content/posts/deploying-application-on-k8s-with-helm/examples/another-nginx/Chart.lock
@@ -0,0 +1,6 @@
+dependencies:
+- name: metrics
+ repository: file://../metrics
+ version: 0.1.0
+digest: sha256:3f0b5d9bb4d3c1b47dc84f7ca7be1492ac9d3d8a1a8f4ac7fb19e4a998d3dd15
+generated: "2021-12-15T15:11:32.246451292+07:00"
diff --git a/content/posts/deploying-application-on-k8s-with-helm/examples/another-nginx/Chart.yaml b/content/posts/deploying-application-on-k8s-with-helm/examples/another-nginx/Chart.yaml
new file mode 100644
index 00000000..9f676488
--- /dev/null
+++ b/content/posts/deploying-application-on-k8s-with-helm/examples/another-nginx/Chart.yaml
@@ -0,0 +1,28 @@
+apiVersion: v2
+name: another-nginx
+description: A Helm chart for Kubernetes
+
+# A chart can be either an 'application' or a 'library' chart.
+#
+# Application charts are a collection of templates that can be packaged into versioned archives
+# to be deployed.
+#
+# Library charts provide useful utilities or functions for the chart developer. They're included as
+# a dependency of application charts to inject those utilities and functions into the rendering
+# pipeline. Library charts do not define any templates and therefore cannot be deployed.
+type: application
+
+# This is the chart version. This version number should be incremented each time you make changes
+# to the chart and its templates, including the app version.
+# Versions are expected to follow Semantic Versioning (https://semver.org/)
+version: 0.1.0
+
+# This is the version number of the application being deployed. This version number should be
+# incremented each time you make changes to the application. Versions are not expected to
+# follow Semantic Versioning. They should reflect the version the application is using.
+# It is recommended to use it with quotes.
+appVersion: "1.16.0"
+dependencies:
+- name: metrics
+ version: 0.1.0
+ repository: file://../metrics
\ No newline at end of file
diff --git a/content/posts/deploying-application-on-k8s-with-helm/examples/another-nginx/charts/metrics-0.1.0.tgz b/content/posts/deploying-application-on-k8s-with-helm/examples/another-nginx/charts/metrics-0.1.0.tgz
new file mode 100644
index 00000000..77f72b88
Binary files /dev/null and b/content/posts/deploying-application-on-k8s-with-helm/examples/another-nginx/charts/metrics-0.1.0.tgz differ
diff --git a/content/posts/deploying-application-on-k8s-with-helm/examples/another-nginx/templates/NOTES.txt b/content/posts/deploying-application-on-k8s-with-helm/examples/another-nginx/templates/NOTES.txt
new file mode 100644
index 00000000..a02afbdf
--- /dev/null
+++ b/content/posts/deploying-application-on-k8s-with-helm/examples/another-nginx/templates/NOTES.txt
@@ -0,0 +1,22 @@
+1. Get the application URL by running these commands:
+{{- if .Values.ingress.enabled }}
+{{- range $host := .Values.ingress.hosts }}
+ {{- range .paths }}
+ http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }}
+ {{- end }}
+{{- end }}
+{{- else if contains "NodePort" .Values.service.type }}
+ export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "another-nginx.fullname" . }})
+ export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
+ echo http://$NODE_IP:$NODE_PORT
+{{- else if contains "LoadBalancer" .Values.service.type }}
+ NOTE: It may take a few minutes for the LoadBalancer IP to be available.
+ You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "another-nginx.fullname" . }}'
+ export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "another-nginx.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
+ echo http://$SERVICE_IP:{{ .Values.service.port }}
+{{- else if contains "ClusterIP" .Values.service.type }}
+ export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "another-nginx.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
+ export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
+ echo "Visit http://127.0.0.1:8080 to use your application"
+ kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT
+{{- end }}
diff --git a/content/posts/deploying-application-on-k8s-with-helm/examples/another-nginx/templates/_helpers.tpl b/content/posts/deploying-application-on-k8s-with-helm/examples/another-nginx/templates/_helpers.tpl
new file mode 100644
index 00000000..a18ef8b5
--- /dev/null
+++ b/content/posts/deploying-application-on-k8s-with-helm/examples/another-nginx/templates/_helpers.tpl
@@ -0,0 +1,62 @@
+{{/*
+Expand the name of the chart.
+*/}}
+{{- define "another-nginx.name" -}}
+{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
+{{- end }}
+
+{{/*
+Create a default fully qualified app name.
+We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
+If release name contains chart name it will be used as a full name.
+*/}}
+{{- define "another-nginx.fullname" -}}
+{{- if .Values.fullnameOverride }}
+{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
+{{- else }}
+{{- $name := default .Chart.Name .Values.nameOverride }}
+{{- if contains $name .Release.Name }}
+{{- .Release.Name | trunc 63 | trimSuffix "-" }}
+{{- else }}
+{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
+{{- end }}
+{{- end }}
+{{- end }}
+
+{{/*
+Create chart name and version as used by the chart label.
+*/}}
+{{- define "another-nginx.chart" -}}
+{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
+{{- end }}
+
+{{/*
+Common labels
+*/}}
+{{- define "another-nginx.labels" -}}
+helm.sh/chart: {{ include "another-nginx.chart" . }}
+{{ include "another-nginx.selectorLabels" . }}
+{{- if .Chart.AppVersion }}
+app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
+{{- end }}
+app.kubernetes.io/managed-by: {{ .Release.Service }}
+{{- end }}
+
+{{/*
+Selector labels
+*/}}
+{{- define "another-nginx.selectorLabels" -}}
+app.kubernetes.io/name: {{ include "another-nginx.name" . }}
+app.kubernetes.io/instance: {{ .Release.Name }}
+{{- end }}
+
+{{/*
+Create the name of the service account to use
+*/}}
+{{- define "another-nginx.serviceAccountName" -}}
+{{- if .Values.serviceAccount.create }}
+{{- default (include "another-nginx.fullname" .) .Values.serviceAccount.name }}
+{{- else }}
+{{- default "default" .Values.serviceAccount.name }}
+{{- end }}
+{{- end }}
diff --git a/content/posts/deploying-application-on-k8s-with-helm/examples/another-nginx/templates/configmap.yaml b/content/posts/deploying-application-on-k8s-with-helm/examples/another-nginx/templates/configmap.yaml
new file mode 100644
index 00000000..c5442cba
--- /dev/null
+++ b/content/posts/deploying-application-on-k8s-with-helm/examples/another-nginx/templates/configmap.yaml
@@ -0,0 +1 @@
+{{ include "metrics.configmap.tpl" . }}
\ No newline at end of file
diff --git a/content/posts/deploying-application-on-k8s-with-helm/examples/another-nginx/templates/deployment.yaml b/content/posts/deploying-application-on-k8s-with-helm/examples/another-nginx/templates/deployment.yaml
new file mode 100644
index 00000000..57035957
--- /dev/null
+++ b/content/posts/deploying-application-on-k8s-with-helm/examples/another-nginx/templates/deployment.yaml
@@ -0,0 +1,66 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: {{ include "another-nginx.fullname" . }}
+ labels:
+ {{- include "another-nginx.labels" . | nindent 4 }}
+spec:
+ {{- if not .Values.autoscaling.enabled }}
+ replicas: {{ .Values.replicaCount }}
+ {{- end }}
+ selector:
+ matchLabels:
+ {{- include "another-nginx.selectorLabels" . | nindent 6 }}
+ template:
+ metadata:
+ {{- with .Values.podAnnotations }}
+ annotations:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ labels:
+ {{- include "another-nginx.selectorLabels" . | nindent 8 }}
+ spec:
+ {{- with .Values.imagePullSecrets }}
+ imagePullSecrets:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ serviceAccountName: {{ include "another-nginx.serviceAccountName" . }}
+ securityContext:
+ {{- toYaml .Values.podSecurityContext | nindent 8 }}
+ volumes:
+ - {{ include "metrics.volume.tpl" . | nindent 8 }}
+ containers:
+ - name: {{ .Chart.Name }}
+ securityContext:
+ {{- toYaml .Values.securityContext | nindent 12 }}
+ image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
+ imagePullPolicy: {{ .Values.image.pullPolicy }}
+ ports:
+ - name: http
+ containerPort: 80
+ protocol: TCP
+ livenessProbe:
+ httpGet:
+ path: /
+ port: http
+ readinessProbe:
+ httpGet:
+ path: /
+ port: http
+ resources:
+ {{- toYaml .Values.resources | nindent 12 }}
+ volumeMounts:
+ - {{- include "metrics.volume-mount.tpl" . | nindent 12 }}
+ - {{- include "metrics.container.tpl" . | nindent 10 }}
+ {{- with .Values.nodeSelector }}
+ nodeSelector:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.affinity }}
+ affinity:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.tolerations }}
+ tolerations:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
diff --git a/content/posts/deploying-application-on-k8s-with-helm/examples/another-nginx/templates/hpa.yaml b/content/posts/deploying-application-on-k8s-with-helm/examples/another-nginx/templates/hpa.yaml
new file mode 100644
index 00000000..519726a2
--- /dev/null
+++ b/content/posts/deploying-application-on-k8s-with-helm/examples/another-nginx/templates/hpa.yaml
@@ -0,0 +1,28 @@
+{{- if .Values.autoscaling.enabled }}
+apiVersion: autoscaling/v2beta1
+kind: HorizontalPodAutoscaler
+metadata:
+ name: {{ include "another-nginx.fullname" . }}
+ labels:
+ {{- include "another-nginx.labels" . | nindent 4 }}
+spec:
+ scaleTargetRef:
+ apiVersion: apps/v1
+ kind: Deployment
+ name: {{ include "another-nginx.fullname" . }}
+ minReplicas: {{ .Values.autoscaling.minReplicas }}
+ maxReplicas: {{ .Values.autoscaling.maxReplicas }}
+ metrics:
+ {{- if .Values.autoscaling.targetCPUUtilizationPercentage }}
+ - type: Resource
+ resource:
+ name: cpu
+ targetAverageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }}
+ {{- end }}
+ {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }}
+ - type: Resource
+ resource:
+ name: memory
+ targetAverageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }}
+ {{- end }}
+{{- end }}
diff --git a/content/posts/deploying-application-on-k8s-with-helm/examples/another-nginx/templates/ingress.yaml b/content/posts/deploying-application-on-k8s-with-helm/examples/another-nginx/templates/ingress.yaml
new file mode 100644
index 00000000..415ec8bd
--- /dev/null
+++ b/content/posts/deploying-application-on-k8s-with-helm/examples/another-nginx/templates/ingress.yaml
@@ -0,0 +1,41 @@
+{{- if .Values.ingress.enabled -}}
+{{- $fullName := include "another-nginx.fullname" . -}}
+{{- $svcPort := .Values.service.port -}}
+{{- if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}}
+apiVersion: networking.k8s.io/v1beta1
+{{- else -}}
+apiVersion: extensions/v1beta1
+{{- end }}
+kind: Ingress
+metadata:
+ name: {{ $fullName }}
+ labels:
+ {{- include "another-nginx.labels" . | nindent 4 }}
+ {{- with .Values.ingress.annotations }}
+ annotations:
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+spec:
+ {{- if .Values.ingress.tls }}
+ tls:
+ {{- range .Values.ingress.tls }}
+ - hosts:
+ {{- range .hosts }}
+ - {{ . | quote }}
+ {{- end }}
+ secretName: {{ .secretName }}
+ {{- end }}
+ {{- end }}
+ rules:
+ {{- range .Values.ingress.hosts }}
+ - host: {{ .host | quote }}
+ http:
+ paths:
+ {{- range .paths }}
+ - path: {{ .path }}
+ backend:
+ serviceName: {{ $fullName }}
+ servicePort: {{ $svcPort }}
+ {{- end }}
+ {{- end }}
+ {{- end }}
diff --git a/content/posts/deploying-application-on-k8s-with-helm/examples/another-nginx/templates/service.yaml b/content/posts/deploying-application-on-k8s-with-helm/examples/another-nginx/templates/service.yaml
new file mode 100644
index 00000000..7c8aa38b
--- /dev/null
+++ b/content/posts/deploying-application-on-k8s-with-helm/examples/another-nginx/templates/service.yaml
@@ -0,0 +1,19 @@
+apiVersion: v1
+kind: Service
+metadata:
+ name: {{ include "another-nginx.fullname" . }}
+ labels:
+ {{- include "another-nginx.labels" . | nindent 4 }}
+spec:
+ type: {{ .Values.service.type }}
+ ports:
+ - port: {{ .Values.service.port }}
+ targetPort: http
+ protocol: TCP
+ name: http
+ - port: 9113
+ targetPort: exporter
+ protocol: TCP
+ name: exporter
+ selector:
+ {{- include "another-nginx.selectorLabels" . | nindent 4 }}
diff --git a/content/posts/deploying-application-on-k8s-with-helm/examples/another-nginx/templates/serviceaccount.yaml b/content/posts/deploying-application-on-k8s-with-helm/examples/another-nginx/templates/serviceaccount.yaml
new file mode 100644
index 00000000..9e7b4454
--- /dev/null
+++ b/content/posts/deploying-application-on-k8s-with-helm/examples/another-nginx/templates/serviceaccount.yaml
@@ -0,0 +1,12 @@
+{{- if .Values.serviceAccount.create -}}
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: {{ include "another-nginx.serviceAccountName" . }}
+ labels:
+ {{- include "another-nginx.labels" . | nindent 4 }}
+ {{- with .Values.serviceAccount.annotations }}
+ annotations:
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+{{- end }}
diff --git a/content/posts/deploying-application-on-k8s-with-helm/examples/another-nginx/templates/tests/test-connection.yaml b/content/posts/deploying-application-on-k8s-with-helm/examples/another-nginx/templates/tests/test-connection.yaml
new file mode 100644
index 00000000..ec2cb0a6
--- /dev/null
+++ b/content/posts/deploying-application-on-k8s-with-helm/examples/another-nginx/templates/tests/test-connection.yaml
@@ -0,0 +1,15 @@
+apiVersion: v1
+kind: Pod
+metadata:
+ name: "{{ include "another-nginx.fullname" . }}-test-connection"
+ labels:
+ {{- include "another-nginx.labels" . | nindent 4 }}
+ annotations:
+ "helm.sh/hook": test
+spec:
+ containers:
+ - name: wget
+ image: busybox
+ command: ['wget']
+ args: ['{{ include "another-nginx.fullname" . }}:{{ .Values.service.port }}']
+ restartPolicy: Never
diff --git a/content/posts/deploying-application-on-k8s-with-helm/examples/another-nginx/values.yaml b/content/posts/deploying-application-on-k8s-with-helm/examples/another-nginx/values.yaml
new file mode 100644
index 00000000..9aeea586
--- /dev/null
+++ b/content/posts/deploying-application-on-k8s-with-helm/examples/another-nginx/values.yaml
@@ -0,0 +1,83 @@
+# Default values for another-nginx.
+# This is a YAML-formatted file.
+# Declare variables to be passed into your templates.
+
+replicaCount: 1
+
+image:
+ repository: nginx
+ pullPolicy: IfNotPresent
+ # Overrides the image tag whose default is the chart appVersion.
+ tag: ""
+
+imagePullSecrets: []
+nameOverride: ""
+fullnameOverride: ""
+
+serviceAccount:
+ # Specifies whether a service account should be created
+ create: true
+ # Annotations to add to the service account
+ annotations: {}
+ # The name of the service account to use.
+ # If not set and create is true, a name is generated using the fullname template
+ name: ""
+
+podAnnotations: {}
+
+podSecurityContext: {}
+ # fsGroup: 2000
+
+securityContext: {}
+ # capabilities:
+ # drop:
+ # - ALL
+ # readOnlyRootFilesystem: true
+ # runAsNonRoot: true
+ # runAsUser: 1000
+
+service:
+ type: ClusterIP
+ port: 80
+
+ingress:
+ enabled: false
+ annotations: {}
+ # kubernetes.io/ingress.class: nginx
+ # kubernetes.io/tls-acme: "true"
+ hosts:
+ - host: chart-example.local
+ paths:
+ - path: /
+ backend:
+ serviceName: chart-example.local
+ servicePort: 80
+ tls: []
+ # - secretName: chart-example-tls
+ # hosts:
+ # - chart-example.local
+
+resources: {}
+ # We usually recommend not to specify default resources and to leave this as a conscious
+ # choice for the user. This also increases chances charts run on environments with little
+ # resources, such as Minikube. If you do want to specify resources, uncomment the following
+ # lines, adjust them as necessary, and remove the curly braces after 'resources:'.
+ # limits:
+ # cpu: 100m
+ # memory: 128Mi
+ # requests:
+ # cpu: 100m
+ # memory: 128Mi
+
+autoscaling:
+ enabled: false
+ minReplicas: 1
+ maxReplicas: 100
+ targetCPUUtilizationPercentage: 80
+ # targetMemoryUtilizationPercentage: 80
+
+nodeSelector: {}
+
+tolerations: []
+
+affinity: {}
diff --git a/content/posts/deploying-application-on-k8s-with-helm/examples/metrics/.helmignore b/content/posts/deploying-application-on-k8s-with-helm/examples/metrics/.helmignore
new file mode 100644
index 00000000..0e8a0eb3
--- /dev/null
+++ b/content/posts/deploying-application-on-k8s-with-helm/examples/metrics/.helmignore
@@ -0,0 +1,23 @@
+# Patterns to ignore when building packages.
+# This supports shell glob matching, relative path matching, and
+# negation (prefixed with !). Only one pattern per line.
+.DS_Store
+# Common VCS dirs
+.git/
+.gitignore
+.bzr/
+.bzrignore
+.hg/
+.hgignore
+.svn/
+# Common backup files
+*.swp
+*.bak
+*.tmp
+*.orig
+*~
+# Various IDEs
+.project
+.idea/
+*.tmproj
+.vscode/
diff --git a/content/posts/deploying-application-on-k8s-with-helm/examples/metrics/Chart.yaml b/content/posts/deploying-application-on-k8s-with-helm/examples/metrics/Chart.yaml
new file mode 100644
index 00000000..086e7d83
--- /dev/null
+++ b/content/posts/deploying-application-on-k8s-with-helm/examples/metrics/Chart.yaml
@@ -0,0 +1,24 @@
+apiVersion: v2
+name: metrics
+description: A Helm chart for Kubernetes
+
+# A chart can be either an 'application' or a 'library' chart.
+#
+# Application charts are a collection of templates that can be packaged into versioned archives
+# to be deployed.
+#
+# Library charts provide useful utilities or functions for the chart developer. They're included as
+# a dependency of application charts to inject those utilities and functions into the rendering
+# pipeline. Library charts do not define any templates and therefore cannot be deployed.
+type: library
+
+# This is the chart version. This version number should be incremented each time you make changes
+# to the chart and its templates, including the app version.
+# Versions are expected to follow Semantic Versioning (https://semver.org/)
+version: 0.1.0
+
+# This is the version number of the application being deployed. This version number should be
+# incremented each time you make changes to the application. Versions are not expected to
+# follow Semantic Versioning. They should reflect the version the application is using.
+# It is recommended to use it with quotes.
+appVersion: "1.16.0"
diff --git a/content/posts/deploying-application-on-k8s-with-helm/examples/metrics/templates/_metrics.yaml b/content/posts/deploying-application-on-k8s-with-helm/examples/metrics/templates/_metrics.yaml
new file mode 100644
index 00000000..23bde80f
--- /dev/null
+++ b/content/posts/deploying-application-on-k8s-with-helm/examples/metrics/templates/_metrics.yaml
@@ -0,0 +1,44 @@
+{{- define "metrics.volume.tpl" -}}
+name: {{ .Chart.Name }}-config
+configMap:
+ name: {{ .Chart.Name }}
+ items:
+ - key: nginx.conf
+ path: nginx.conf
+{{- end -}}
+
+{{- define "metrics.volume-mount.tpl" -}}
+name: {{ .Chart.Name }}-config
+mountPath: /etc/nginx/conf.d/nginx.conf
+subPath: nginx.conf
+{{- end -}}
+
+{{- define "metrics.container.tpl" -}}
+name: {{ .Chart.Name }}-exporter
+image: nginx/nginx-prometheus-exporter:0.9.0
+imagePullPolicy: {{ .Values.image.pullPolicy }}
+ports:
+ - name: exporter
+ containerPort: 9113
+ protocol: TCP
+args:
+ - -nginx.scrape-uri=http://localhost:8080/stub_status
+resources:
+ {{- toYaml .Values.resources | nindent 12 }}
+{{- end -}}
+
+{{- define "metrics.configmap.tpl" -}}
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: {{ .Chart.Name }}
+data:
+ nginx.conf: |
+ server {
+ listen 8080;
+ server_name localhost;
+ location /stub_status {
+ stub_status;
+ }
+ }
+{{- end -}}
\ No newline at end of file
diff --git a/content/posts/deploying-application-on-k8s-with-helm/examples/mynginx/.helmignore b/content/posts/deploying-application-on-k8s-with-helm/examples/mynginx/.helmignore
new file mode 100644
index 00000000..0e8a0eb3
--- /dev/null
+++ b/content/posts/deploying-application-on-k8s-with-helm/examples/mynginx/.helmignore
@@ -0,0 +1,23 @@
+# Patterns to ignore when building packages.
+# This supports shell glob matching, relative path matching, and
+# negation (prefixed with !). Only one pattern per line.
+.DS_Store
+# Common VCS dirs
+.git/
+.gitignore
+.bzr/
+.bzrignore
+.hg/
+.hgignore
+.svn/
+# Common backup files
+*.swp
+*.bak
+*.tmp
+*.orig
+*~
+# Various IDEs
+.project
+.idea/
+*.tmproj
+.vscode/
diff --git a/content/posts/deploying-application-on-k8s-with-helm/examples/mynginx/Chart.lock b/content/posts/deploying-application-on-k8s-with-helm/examples/mynginx/Chart.lock
new file mode 100644
index 00000000..1bfffe54
--- /dev/null
+++ b/content/posts/deploying-application-on-k8s-with-helm/examples/mynginx/Chart.lock
@@ -0,0 +1,6 @@
+dependencies:
+- name: metrics
+ repository: file://../metrics
+ version: 0.1.0
+digest: sha256:3f0b5d9bb4d3c1b47dc84f7ca7be1492ac9d3d8a1a8f4ac7fb19e4a998d3dd15
+generated: "2021-12-15T14:59:05.768841877+07:00"
diff --git a/content/posts/deploying-application-on-k8s-with-helm/examples/mynginx/Chart.yaml b/content/posts/deploying-application-on-k8s-with-helm/examples/mynginx/Chart.yaml
new file mode 100644
index 00000000..2533045f
--- /dev/null
+++ b/content/posts/deploying-application-on-k8s-with-helm/examples/mynginx/Chart.yaml
@@ -0,0 +1,28 @@
+apiVersion: v2
+name: mynginx
+description: A Helm chart for Kubernetes
+
+# A chart can be either an 'application' or a 'library' chart.
+#
+# Application charts are a collection of templates that can be packaged into versioned archives
+# to be deployed.
+#
+# Library charts provide useful utilities or functions for the chart developer. They're included as
+# a dependency of application charts to inject those utilities and functions into the rendering
+# pipeline. Library charts do not define any templates and therefore cannot be deployed.
+type: application
+
+# This is the chart version. This version number should be incremented each time you make changes
+# to the chart and its templates, including the app version.
+# Versions are expected to follow Semantic Versioning (https://semver.org/)
+version: 0.1.0
+
+# This is the version number of the application being deployed. This version number should be
+# incremented each time you make changes to the application. Versions are not expected to
+# follow Semantic Versioning. They should reflect the version the application is using.
+# It is recommended to use it with quotes.
+appVersion: "1.16.0"
+dependencies:
+- name: metrics
+ version: 0.1.0
+ repository: file://../metrics
\ No newline at end of file
diff --git a/content/posts/deploying-application-on-k8s-with-helm/examples/mynginx/charts/metrics-0.1.0.tgz b/content/posts/deploying-application-on-k8s-with-helm/examples/mynginx/charts/metrics-0.1.0.tgz
new file mode 100644
index 00000000..121f355c
Binary files /dev/null and b/content/posts/deploying-application-on-k8s-with-helm/examples/mynginx/charts/metrics-0.1.0.tgz differ
diff --git a/content/posts/deploying-application-on-k8s-with-helm/examples/mynginx/templates/NOTES.txt b/content/posts/deploying-application-on-k8s-with-helm/examples/mynginx/templates/NOTES.txt
new file mode 100644
index 00000000..112f1756
--- /dev/null
+++ b/content/posts/deploying-application-on-k8s-with-helm/examples/mynginx/templates/NOTES.txt
@@ -0,0 +1,22 @@
+1. Get the application URL by running these commands:
+{{- if .Values.ingress.enabled }}
+{{- range $host := .Values.ingress.hosts }}
+ {{- range .paths }}
+ http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }}
+ {{- end }}
+{{- end }}
+{{- else if contains "NodePort" .Values.service.type }}
+ export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "mynginx.fullname" . }})
+ export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
+ echo http://$NODE_IP:$NODE_PORT
+{{- else if contains "LoadBalancer" .Values.service.type }}
+ NOTE: It may take a few minutes for the LoadBalancer IP to be available.
+ You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "mynginx.fullname" . }}'
+ export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "mynginx.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
+ echo http://$SERVICE_IP:{{ .Values.service.port }}
+{{- else if contains "ClusterIP" .Values.service.type }}
+ export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "mynginx.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
+ export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
+ echo "Visit http://127.0.0.1:8080 to use your application"
+ kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT
+{{- end }}
diff --git a/content/posts/deploying-application-on-k8s-with-helm/examples/mynginx/templates/_helpers.tpl b/content/posts/deploying-application-on-k8s-with-helm/examples/mynginx/templates/_helpers.tpl
new file mode 100644
index 00000000..a818ac9d
--- /dev/null
+++ b/content/posts/deploying-application-on-k8s-with-helm/examples/mynginx/templates/_helpers.tpl
@@ -0,0 +1,62 @@
+{{/*
+Expand the name of the chart.
+*/}}
+{{- define "mynginx.name" -}}
+{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
+{{- end }}
+
+{{/*
+Create a default fully qualified app name.
+We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
+If release name contains chart name it will be used as a full name.
+*/}}
+{{- define "mynginx.fullname" -}}
+{{- if .Values.fullnameOverride }}
+{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
+{{- else }}
+{{- $name := default .Chart.Name .Values.nameOverride }}
+{{- if contains $name .Release.Name }}
+{{- .Release.Name | trunc 63 | trimSuffix "-" }}
+{{- else }}
+{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
+{{- end }}
+{{- end }}
+{{- end }}
+
+{{/*
+Create chart name and version as used by the chart label.
+*/}}
+{{- define "mynginx.chart" -}}
+{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
+{{- end }}
+
+{{/*
+Common labels
+*/}}
+{{- define "mynginx.labels" -}}
+helm.sh/chart: {{ include "mynginx.chart" . }}
+{{ include "mynginx.selectorLabels" . }}
+{{- if .Chart.AppVersion }}
+app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
+{{- end }}
+app.kubernetes.io/managed-by: {{ .Release.Service }}
+{{- end }}
+
+{{/*
+Selector labels
+*/}}
+{{- define "mynginx.selectorLabels" -}}
+app.kubernetes.io/name: {{ include "mynginx.name" . }}
+app.kubernetes.io/instance: {{ .Release.Name }}
+{{- end }}
+
+{{/*
+Create the name of the service account to use
+*/}}
+{{- define "mynginx.serviceAccountName" -}}
+{{- if .Values.serviceAccount.create }}
+{{- default (include "mynginx.fullname" .) .Values.serviceAccount.name }}
+{{- else }}
+{{- default "default" .Values.serviceAccount.name }}
+{{- end }}
+{{- end }}
diff --git a/content/posts/deploying-application-on-k8s-with-helm/examples/mynginx/templates/configmap.yaml b/content/posts/deploying-application-on-k8s-with-helm/examples/mynginx/templates/configmap.yaml
new file mode 100644
index 00000000..c5442cba
--- /dev/null
+++ b/content/posts/deploying-application-on-k8s-with-helm/examples/mynginx/templates/configmap.yaml
@@ -0,0 +1 @@
+{{ include "metrics.configmap.tpl" . }}
\ No newline at end of file
diff --git a/content/posts/deploying-application-on-k8s-with-helm/examples/mynginx/templates/deployment.yaml b/content/posts/deploying-application-on-k8s-with-helm/examples/mynginx/templates/deployment.yaml
new file mode 100644
index 00000000..c5eed0cc
--- /dev/null
+++ b/content/posts/deploying-application-on-k8s-with-helm/examples/mynginx/templates/deployment.yaml
@@ -0,0 +1,66 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: {{ include "mynginx.fullname" . }}
+ labels:
+ {{- include "mynginx.labels" . | nindent 4 }}
+spec:
+ {{- if not .Values.autoscaling.enabled }}
+ replicas: {{ .Values.replicaCount }}
+ {{- end }}
+ selector:
+ matchLabels:
+ {{- include "mynginx.selectorLabels" . | nindent 6 }}
+ template:
+ metadata:
+ {{- with .Values.podAnnotations }}
+ annotations:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ labels:
+ {{- include "mynginx.selectorLabels" . | nindent 8 }}
+ spec:
+ {{- with .Values.imagePullSecrets }}
+ imagePullSecrets:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ serviceAccountName: {{ include "mynginx.serviceAccountName" . }}
+ securityContext:
+ {{- toYaml .Values.podSecurityContext | nindent 8 }}
+ volumes:
+ - {{ include "metrics.volume.tpl" . | nindent 8 }}
+ containers:
+ - name: {{ .Chart.Name }}
+ securityContext:
+ {{- toYaml .Values.securityContext | nindent 12 }}
+ image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
+ imagePullPolicy: {{ .Values.image.pullPolicy }}
+ ports:
+ - name: http
+ containerPort: 80
+ protocol: TCP
+ livenessProbe:
+ httpGet:
+ path: /
+ port: http
+ readinessProbe:
+ httpGet:
+ path: /
+ port: http
+ resources:
+ {{- toYaml .Values.resources | nindent 12 }}
+ volumeMounts:
+ - {{- include "metrics.volume-mount.tpl" . | nindent 12 }}
+ - {{- include "metrics.container.tpl" . | nindent 10 }}
+ {{- with .Values.nodeSelector }}
+ nodeSelector:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.affinity }}
+ affinity:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.tolerations }}
+ tolerations:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
diff --git a/content/posts/deploying-application-on-k8s-with-helm/examples/mynginx/templates/hpa.yaml b/content/posts/deploying-application-on-k8s-with-helm/examples/mynginx/templates/hpa.yaml
new file mode 100644
index 00000000..2a6237bb
--- /dev/null
+++ b/content/posts/deploying-application-on-k8s-with-helm/examples/mynginx/templates/hpa.yaml
@@ -0,0 +1,28 @@
+{{- if .Values.autoscaling.enabled }}
+apiVersion: autoscaling/v2beta1
+kind: HorizontalPodAutoscaler
+metadata:
+ name: {{ include "mynginx.fullname" . }}
+ labels:
+ {{- include "mynginx.labels" . | nindent 4 }}
+spec:
+ scaleTargetRef:
+ apiVersion: apps/v1
+ kind: Deployment
+ name: {{ include "mynginx.fullname" . }}
+ minReplicas: {{ .Values.autoscaling.minReplicas }}
+ maxReplicas: {{ .Values.autoscaling.maxReplicas }}
+ metrics:
+ {{- if .Values.autoscaling.targetCPUUtilizationPercentage }}
+ - type: Resource
+ resource:
+ name: cpu
+ targetAverageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }}
+ {{- end }}
+ {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }}
+ - type: Resource
+ resource:
+ name: memory
+ targetAverageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }}
+ {{- end }}
+{{- end }}
diff --git a/content/posts/deploying-application-on-k8s-with-helm/examples/mynginx/templates/ingress.yaml b/content/posts/deploying-application-on-k8s-with-helm/examples/mynginx/templates/ingress.yaml
new file mode 100644
index 00000000..db38df6c
--- /dev/null
+++ b/content/posts/deploying-application-on-k8s-with-helm/examples/mynginx/templates/ingress.yaml
@@ -0,0 +1,41 @@
+{{- if .Values.ingress.enabled -}}
+{{- $fullName := include "mynginx.fullname" . -}}
+{{- $svcPort := .Values.service.port -}}
+{{- if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}}
+apiVersion: networking.k8s.io/v1beta1
+{{- else -}}
+apiVersion: extensions/v1beta1
+{{- end }}
+kind: Ingress
+metadata:
+ name: {{ $fullName }}
+ labels:
+ {{- include "mynginx.labels" . | nindent 4 }}
+ {{- with .Values.ingress.annotations }}
+ annotations:
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+spec:
+ {{- if .Values.ingress.tls }}
+ tls:
+ {{- range .Values.ingress.tls }}
+ - hosts:
+ {{- range .hosts }}
+ - {{ . | quote }}
+ {{- end }}
+ secretName: {{ .secretName }}
+ {{- end }}
+ {{- end }}
+ rules:
+ {{- range .Values.ingress.hosts }}
+ - host: {{ .host | quote }}
+ http:
+ paths:
+ {{- range .paths }}
+ - path: {{ .path }}
+ backend:
+ serviceName: {{ $fullName }}
+ servicePort: {{ $svcPort }}
+ {{- end }}
+ {{- end }}
+ {{- end }}
diff --git a/content/posts/deploying-application-on-k8s-with-helm/examples/mynginx/templates/service.yaml b/content/posts/deploying-application-on-k8s-with-helm/examples/mynginx/templates/service.yaml
new file mode 100644
index 00000000..27deca39
--- /dev/null
+++ b/content/posts/deploying-application-on-k8s-with-helm/examples/mynginx/templates/service.yaml
@@ -0,0 +1,19 @@
+apiVersion: v1
+kind: Service
+metadata:
+ name: {{ include "mynginx.fullname" . }}
+ labels:
+ {{- include "mynginx.labels" . | nindent 4 }}
+spec:
+ type: {{ .Values.service.type }}
+ ports:
+ - port: {{ .Values.service.port }}
+ targetPort: http
+ protocol: TCP
+ name: http
+ - port: 9113
+ targetPort: exporter
+ protocol: TCP
+ name: exporter
+ selector:
+ {{- include "mynginx.selectorLabels" . | nindent 4 }}
diff --git a/content/posts/deploying-application-on-k8s-with-helm/examples/mynginx/templates/serviceaccount.yaml b/content/posts/deploying-application-on-k8s-with-helm/examples/mynginx/templates/serviceaccount.yaml
new file mode 100644
index 00000000..bbd4de56
--- /dev/null
+++ b/content/posts/deploying-application-on-k8s-with-helm/examples/mynginx/templates/serviceaccount.yaml
@@ -0,0 +1,12 @@
+{{- if .Values.serviceAccount.create -}}
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: {{ include "mynginx.serviceAccountName" . }}
+ labels:
+ {{- include "mynginx.labels" . | nindent 4 }}
+ {{- with .Values.serviceAccount.annotations }}
+ annotations:
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+{{- end }}
diff --git a/content/posts/deploying-application-on-k8s-with-helm/examples/mynginx/templates/tests/test-connection.yaml b/content/posts/deploying-application-on-k8s-with-helm/examples/mynginx/templates/tests/test-connection.yaml
new file mode 100644
index 00000000..30eb6dba
--- /dev/null
+++ b/content/posts/deploying-application-on-k8s-with-helm/examples/mynginx/templates/tests/test-connection.yaml
@@ -0,0 +1,15 @@
+apiVersion: v1
+kind: Pod
+metadata:
+ name: "{{ include "mynginx.fullname" . }}-test-connection"
+ labels:
+ {{- include "mynginx.labels" . | nindent 4 }}
+ annotations:
+ "helm.sh/hook": test
+spec:
+ containers:
+ - name: wget
+ image: busybox
+ command: ['wget']
+ args: ['{{ include "mynginx.fullname" . }}:{{ .Values.service.port }}']
+ restartPolicy: Never
diff --git a/content/posts/deploying-application-on-k8s-with-helm/examples/mynginx/values.yaml b/content/posts/deploying-application-on-k8s-with-helm/examples/mynginx/values.yaml
new file mode 100644
index 00000000..04aad0a6
--- /dev/null
+++ b/content/posts/deploying-application-on-k8s-with-helm/examples/mynginx/values.yaml
@@ -0,0 +1,83 @@
+# Default values for mynginx.
+# This is a YAML-formatted file.
+# Declare variables to be passed into your templates.
+
+replicaCount: 1
+
+image:
+ repository: nginx
+ pullPolicy: IfNotPresent
+ # Overrides the image tag whose default is the chart appVersion.
+ tag: ""
+
+imagePullSecrets: []
+nameOverride: ""
+fullnameOverride: ""
+
+serviceAccount:
+ # Specifies whether a service account should be created
+ create: true
+ # Annotations to add to the service account
+ annotations: {}
+ # The name of the service account to use.
+ # If not set and create is true, a name is generated using the fullname template
+ name: ""
+
+podAnnotations: {}
+
+podSecurityContext: {}
+ # fsGroup: 2000
+
+securityContext: {}
+ # capabilities:
+ # drop:
+ # - ALL
+ # readOnlyRootFilesystem: true
+ # runAsNonRoot: true
+ # runAsUser: 1000
+
+service:
+ type: ClusterIP
+ port: 80
+
+ingress:
+ enabled: false
+ annotations: {}
+ # kubernetes.io/ingress.class: nginx
+ # kubernetes.io/tls-acme: "true"
+ hosts:
+ - host: chart-example.local
+ paths:
+ - path: /
+ backend:
+ serviceName: chart-example.local
+ servicePort: 80
+ tls: []
+ # - secretName: chart-example-tls
+ # hosts:
+ # - chart-example.local
+
+resources: {}
+ # We usually recommend not to specify default resources and to leave this as a conscious
+ # choice for the user. This also increases chances charts run on environments with little
+ # resources, such as Minikube. If you do want to specify resources, uncomment the following
+ # lines, adjust them as necessary, and remove the curly braces after 'resources:'.
+ # limits:
+ # cpu: 100m
+ # memory: 128Mi
+ # requests:
+ # cpu: 100m
+ # memory: 128Mi
+
+autoscaling:
+ enabled: false
+ minReplicas: 1
+ maxReplicas: 100
+ targetCPUUtilizationPercentage: 80
+ # targetMemoryUtilizationPercentage: 80
+
+nodeSelector: {}
+
+tolerations: []
+
+affinity: {}
diff --git a/content/posts/deploying-application-on-k8s-with-helm/index.md b/content/posts/deploying-application-on-k8s-with-helm/index.md
new file mode 100644
index 00000000..bf66ee65
--- /dev/null
+++ b/content/posts/deploying-application-on-k8s-with-helm/index.md
@@ -0,0 +1,431 @@
++++
+date = "2021-12-15T14:28:23+07:00"
+author = "sanglh"
+description = "How to work with helm chart and something about helm subchart/dependency feature"
+title = "Deploying application on Kubenetes with Helm"
+categories = ["DevSecOps", "Helm", "K8S"]
+tags = ["k8s", "helm", "kubernetes"]
++++
+
+## Why do we need to use helm chart?
+
+Working with k8s, we have many k8s resources: ConfigMap, Secret, Service, Deployment, Pod,... K8s resources can be created by creating the yaml file, and use command kubectl apply -f . For example, we create a file with name is deployment.yaml:
+
+```yaml
+
+ apiVersion: apps/v1
+ kind: Deployment
+ metadata:
+ name: nginx-deployment
+ spec:
+ replicas: 2
+ selector:
+ matchLabels:
+ app: nginx-deployment
+ template:
+ metadata:
+ labels:
+ app: nginx-deployment
+ spec:
+ containers:
+ - name: nginx-deployment
+ image: nginx
+ ports:
+ - containerPort: 8080
+
+```
+To create the k8s deployment, we use the command:
+```bash
+
+ kubectl apply -f deployment.yaml
+
+```
+
+With each resource, we can create a file (deployment.yaml, service.yaml, configmap.yaml, secret.yaml,...) and use the kubectl command to apply them. But we have a problem. If we work with microservices and we have multiple services => the number of yaml files is very large, and makes it difficult for us to manage them.
+
+We need a solution to manage all of them in a common template => Helm can solve this problem
+
+Before going to next part, you need to download and install minikube on your local device.
+
+## Introduction to helm chart
+**Helm is a tool that streamlines installing and managing Kubernetes applications.** To work with helm charts, we need to install the helm command. This link is about how to install: https://helm.sh/docs/intro/install
+
+I will introduce you to the structure of the helm chart. To create a chart, we can use my example command:
+```bash
+
+ helm create mynginx
+
+```
+That command will create a mynginx folder. Let's take a look in the mynginx folder where we have some folders and files:
+- charts: this folder will contain another subchart which our chart will depend on. I will talk more about that subchart in the next section
+- templates: this folder contains yaml files about the k8s resource. We can add more, remove or modify the files in this folder
+- Chart.yaml: this file is the description about the chart information
+- _helpers.tpl: this file defines some yaml key-value which we can import to yaml files in templates folders
+
+Let take a look about the file template/deployments.yaml:
+
+```yaml
+
+ apiVersion: apps/v1
+ kind: Deployment
+ metadata:
+ name: {{ include "mynginx.fullname" . }}
+ labels:
+ {{- include "mynginx.labels" . | nindent 4 }}
+ spec:
+ {{- if not .Values.autoscaling.enabled }}
+ replicas: {{ .Values.replicaCount }}
+ {{- end }}
+ selector:
+ matchLabels:
+ {{- include "mynginx.selectorLabels" . | nindent 6 }}
+ template:
+ metadata:
+ {{- with .Values.podAnnotations }}
+ annotations:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ labels:
+ {{- include "mynginx.selectorLabels" . | nindent 8 }}
+ spec:
+ {{- with .Values.imagePullSecrets }}
+ imagePullSecrets:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ serviceAccountName: {{ include "mynginx.serviceAccountName" . }}
+ securityContext:
+ {{- toYaml .Values.podSecurityContext | nindent 8 }}
+ containers:
+ - name: {{ .Chart.Name }}
+ securityContext:
+ {{- toYaml .Values.securityContext | nindent 12 }}
+ image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
+ imagePullPolicy: {{ .Values.image.pullPolicy }}
+ ..........................................................
+
+```
+
+This yaml file looks like the template of k8s resource, except we see alot of this {{ }} syntax. The statement in {{ }} can be a value, operator, expression, etc. Let me explain some popular uses:
+
+- {{ include … }}: this syntax helps us to import the yaml template that is defined in file **_helpers.tpl**
+- {{ .Values.<key> }}: gets the **value** at the position **key** of files values.yaml and fill that value to the k8s template yaml file
+- {{ -if <expression > }} <some yaml line> {{- end }}: if the expression returns true, the <some yaml line> will be added to the template file
+- {{ with .Values.key }} {{- toYaml . }} {{- end }}, {{- toYaml .Values.key }}: get the **value** at the position **key** of files **values.yaml** and convert it to yaml format.
+- indent <n>: indents the content with n tabs
+- nindent <n>: same with indent but the yaml code is created in the new line
+
+Look at the **_helper.tpl**, there are some basic things we need to know:
+```yaml
+
+ {{- define "mynginx.name" -}}
+ {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
+ {{- end }}
+
+```
+This script is about the value of **mynginx.name**. The first thing is the **default** operator. The value of **.Chart.Name** is defined in file **Chart.yaml**. If the value of key nameOverride in file values.yaml is not empty, it is chosen, if not, .Chart.Name is chosen. Trunc 63 is the function to get the first 63 characters and trimSuffix “-” in here is used to remove all the characters “-” at the end of the string. You can read more about helm chart function at here: https://helm.sh/docs/chart_template_guide/function_list/
+
+``` yaml
+
+ {{- define "mynginx.selectorLabels" -}}
+ app.kubernetes.io/name: {{ include "mynginx.name" . }}
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ {{- end }}
+
+```
+This script defines the template of “mynginx.selectorLabels”. This returns some yaml code. **{{ .Release.Name }}** is the value which we pass in the helm install command. I will introduce the helm command install now.
+
+## Install/Upgrade helm chart
+To install all the services that are defined in the helm chart into k8s cluster, we use helm install/upgrade command. The format I usually use to install/upgrade is:
+
+```bash
+
+ helm upgrade --install \
+ --create-namespace --namespace= “specific namespace to install service” \
+ --values “path to the values file” \
+ --set== \
+ --set== \
+ ......
+ --set==
+
+```
+
+- The <ReleaseName> will become the value of {{ .Release.Name }} in file **_heplers.tpl** I mentioned above
+- “path to the values file": The default values for the helm chart are defined in file values.yaml. But if we want to use value from another file, we can specify the path to that file by using --values flag
+- --set=<key>=<value>: in the case the value is dynamic, we can set value for the key by using --set flag
+
+
+With current chart, you can apply and create nginx service by running (make sure to install and start minikube in your local device)
+
+```bash
+
+ helm upgrade --install mynginx ./mynginx
+
+```
+
+Now you can run: _kubectl get deployment_
+
+``` bash
+
+ NAME READY UP-TO-DATE AVAILABLE AGE
+ mynginx 1/1 1 1 3m29s
+
+```
+
+And _kubectl get service_
+
+``` bash
+
+ NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
+ kubernetes ClusterIP 10.96.0.1 443/TCP 9m36s
+ mynginx ClusterIP 10.107.22.190 80/TCP 4m15s
+
+```
+
+You can see that all things are created for you.
+
+More about helm install command, you can refer at: https://helm.sh/docs/helm/helm_install/
+
+## Helm subchart and global values
+We have two use-case that need to use this feature of helm:
+- To import some template that common and dynamic by value of each helm chart
+- To install all of our microservices in one helm command.
+
+### Import some template that common and dynamic by value of each helm chart
+
+Imagine that you have many nginx apps and you need to monitor them. The solution is you can use a sidecar container for each app.
+For monitoring nginx, each services you need add some config like this:
+- A config map for file nginx.conf
+- Some yaml code for mapping the config map into volume of container
+- Some yaml code for create sidecar container with image nginx/nginx-prometheus-exporter:0.9.0
+
+The code above is repeated for each service. So we can create a helm chart with the type “library" and import it to each service.
+
+You can follow these steps:
+
+- Create an library helm, I named it is “metrics"
+
+```bash
+
+ helm create metrics
+
+```
+- In file Chart.yaml, change type from **application** to **library**
+- In the metrics/template folder, you delete all files and create a file _metrics.yaml with the content:
+```yaml
+
+ {{- define "metrics.volume.tpl" -}}
+ name: {{ .Chart.Name }}-config
+ configMap:
+ name: {{ .Release.Name }}
+ items:
+ - key: nginx.conf
+ path: nginx.conf
+ {{- end -}}
+
+ {{- define "metrics.volume-mount.tpl" -}}
+ name: {{ .Chart.Name }}-config
+ mountPath: /etc/nginx/conf.d/nginx.conf
+ subPath: nginx.conf
+ {{- end -}}
+
+ {{- define "metrics.container.tpl" -}}
+ name: {{ .Chart.Name }}-exporter
+ image: nginx/nginx-prometheus-exporter:0.9.0
+ imagePullPolicy: {{ .Values.image.pullPolicy }}
+ ports:
+ - name: exporter
+ containerPort: 9113
+ protocol: TCP
+ args:
+ - -nginx.scrape-uri=http://localhost:8080/stub_status
+ resources:
+ {{- toYaml .Values.resources | nindent 12 }}
+ {{- end -}}
+
+ {{- define "metrics.configmap.tpl" -}}
+ apiVersion: v1
+ kind: ConfigMap
+ metadata:
+ name: {{ .Chart.Name }}
+ data:
+ nginx.conf: |
+ server {
+ listen 8080;
+ server_name localhost;
+ location /stub_status {
+ stub_status;
+ }
+ }
+ {{- end -}}
+
+```
+- Go to folder mynginx, and add this block to file Chart.yaml:
+
+```yaml
+
+ dependencies:
+ - name: metrics
+ version: 0.1.0
+ repository: file://../metrics
+
+```
+- Run the command: helm dependency update
+After you run the command, it will create the .tgz file in charts folder
+- Now we need to add config for file nginx.conf by using configmap. Create configmap.yaml file in templates folder and just import the template from subchart:
+
+```yaml
+
+ {{ include "metrics.configmap.tpl" . }}
+
+```
+- In the templates/deployment.yaml, import volume template, volume mount template and sidecar container template like this:
+
+```yaml
+
+ apiVersion: apps/v1
+ kind: Deployment
+ spec:
+ …
+ template:
+ spec:
+ volumes:
+ - {{ include "metrics.volume.tpl" . | nindent 8 }}
+ containers:
+ - name: {{ .Chart.Name }}
+ ....
+ volumeMounts:
+ - {{- include "metrics.volume-mount.tpl" . | nindent 12 }}
+ - {{- include "metrics.container.tpl" . | nindent 10 }}
+
+```
+- Expose port 9113 in the service.yaml:
+
+```yaml
+
+ - port: 9113
+ targetPort: exporter
+ protocol: TCP
+ name: exporter
+
+```
+- Now we can upgrade helm chart:
+
+```bash
+
+ helm upgrade --install mynginx ./mynginx
+
+```
+- Check the service by run __kubectl get services__
+
+```bash
+
+ NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
+ kubernetes ClusterIP 10.96.0.1 443/TCP 6m31s
+ mynginx ClusterIP 10.106.193.81 80/TCP,9113/TCP 2m59s
+
+```
+
+Now you have the prometheus exporter working at port 9113. You can run: __kubectl port-forward svc/mynginx 9113:9113__ and call to localhost:9113/metrics to get metrics data
+```bash
+
+ sanglh@sanglh-G5-5500:~$ curl localhost:9113/metrics
+ # HELP nginx_connections_accepted Accepted client connections
+ # TYPE nginx_connections_accepted counter
+ nginx_connections_accepted 6123
+ # HELP nginx_connections_active Active client connections
+ # TYPE nginx_connections_active gauge
+ nginx_connections_active 1
+ # HELP nginx_connections_handled Handled client connections
+ # TYPE nginx_connections_handled counter
+ nginx_connections_handled 6123
+ # HELP nginx_connections_reading Connections where NGINX is reading the request header
+ # TYPE nginx_connections_reading gauge
+ nginx_connections_reading 0
+ # HELP nginx_connections_waiting Idle client connections
+ # TYPE nginx_connections_waiting gauge
+ nginx_connections_waiting 0
+ # HELP nginx_connections_writing Connections where NGINX is writing the response back to the client
+ # TYPE nginx_connections_writing gauge
+ nginx_connections_writing 1
+ # HELP nginx_http_requests_total Total http requests
+ # TYPE nginx_http_requests_total counter
+ nginx_http_requests_total 6124
+ # HELP nginx_up Status of the last metric scrape
+ # TYPE nginx_up gauge
+ nginx_up 1
+ # HELP nginxexporter_build_info Exporter build information
+ # TYPE nginxexporter_build_info gauge
+ nginxexporter_build_info{commit="5f88afbd906baae02edfbab4f5715e06d88538a0",date="2021-03-22T20:16:09Z",version="0.9.0"} 1
+
+```
+
+### Install all of our microservices in one helm command
+
+Currently each service has 1 helm chart. So that if you have N service, you need to run N command. Imaging that if you want to deploy all in one command, you can do with 2 ways:
+
+- create many of deployment, service, configmap,... template in one helm chart
+- use subchart
+
+
+In this blog I will use subchart. I created another chart with the name “another-nginx". You can read at … And I created the chart name “all-in-one".
+
+You can add dependencies into all-in-one/Chart.yaml like this and run helm dependency update:
+
+```yaml
+
+ dependencies:
+ - name: another-nginx
+ version: 0.1.0
+ repository: file://../another-nginx
+ - name: mynginx
+ version: 0.1.0
+ repository: file://../mynginx
+
+```
+
+But this way is only effective when dependencies are stable. When you update something in another-nginx or mynginx, you need to run helm dependency update to update the chart all-in-one. So the efficient way we can do is copy mynginx and another nginx folder to all-in-one/charts. When you run helm upgrade --install all-in-one ./all-in-one, it will return the same result with using helm dependency.
+
+Check the deployment result by run __kubectl get deploy__:
+
+```bash
+
+ NAME READY UP-TO-DATE AVAILABLE AGE
+ all-in-one-another-nginx 1/1 1 1 3m51s
+ all-in-one-mynginx 1/1 1 1 3m51s
+
+```
+
+You can see the deployment name contains “all-in-one”. You can remove the “all-in-one” prefix by change the nameOverride and fullnameOverride in file values.yaml of all-in-one/chart/another-nginx and all-in-one/chart/mynginx to these name:
+
+- File all-in-one/charts/mynginx/values.yaml
+
+```yaml
+
+ nameOverride: "mynginx"
+ fullnameOverride: "mynginx"
+
+```
+- File all-in-one/charts/another-nginx/values.yaml
+
+```yaml
+
+ nameOverride: "another-nginx"
+ fullnameOverride: "another-nginx"
+
+```
+
+Save file and run __helm upgrade --install all-in-one ./all-in-one__ again. After that recheck deploy and you can see the name is changed:
+
+```bash
+
+ NAME READY UP-TO-DATE AVAILABLE AGE
+ another-nginx 1/1 1 1 13s
+ mynginx 1/1 1 1 15s
+
+```
+
+The final thing you need to know about helm subchart is Global Chart Values. This helps us so much to control the value of each subchart or common value of the all-in-one chart. Read more at: https://helm.sh/docs/chart_template_guide/subcharts_and_globals/
+
+
+The source code for this blog is posted at:
+https://github.com/manabie-com/manabie-com.github.io/tree/main/content/posts/introduce-about-helm-chart
\ No newline at end of file
diff --git a/data/authors/sanglh.json b/data/authors/sanglh.json
new file mode 100644
index 00000000..d6189fcb
--- /dev/null
+++ b/data/authors/sanglh.json
@@ -0,0 +1,6 @@
+{
+ "name": "sanglh",
+ "social": {
+ "linkedin": "https://www.linkedin.com/in/lhsanghcmus/"
+ }
+}
\ No newline at end of file