: Kubernetes의 템플릿 파일들의 집합을 관리하는 오픈소스 패키지 매니저 툴.
⇒ 이를 위해, 애플리케이션 배포에 필요한 템플릿들을 “Charts”로 묶고, 동적으로 설정값을 변경하여 손쉽게 배포를 할 수 있는 “Helm”이 등장
⇒ Charts 배포를 통해 외부에서도 손쉽게 Kubernetes 클러스터에 애플리케이션을 배포할 수 있게 됨.
Helm의 기본 구조는 V2와 V3가 상이하다.
Helm Repository의 Chart를 관리한다. 즉, 로컬 서버에 차트를 만들거나 차트 저장소의 릴리즈들을 관리할 때 필요한 요청을 한다.
Kubernetes Cluster의 Api Server와 직접 통신하여, Client의 요청을 받아 Api Server에 전달하여 실제로 요청을 처리한다. Client와는 gRPC를 통해 통신한다.
mysql의 차트를 예시로 한번 구조를 살펴보면 다음과 같다.
├── Chart.lock
├── Chart.yaml
├── README.md
├── charts
│ └── common
│ ├── Chart.yaml
│ ├── README.md
│ ...
│ └── values.yaml
├── templates
│ ├── NOTES.txt
│ ├── _helpers.tpl
│ ├── extra-list.yaml
│ ├── metrics-svc.yaml
│ ├── networkpolicy.yaml
│ ├── primary
│ │ ├── configmap.yaml
│ │ ├── initialization-configmap.yaml
│ │ ├── pdb.yaml
│ │ ├── startdb-configmap.yaml
│ │ ├── statefulset.yaml
│ │ ├── svc-headless.yaml
│ │ └── svc.yaml
...
├── values.schema.json
└── values.yaml
위의 예시에서 눈여겨볼 파일은 values.yaml
과 templates
다.
templates 폴더안에는 Kubernetes에서 애플리케이션을 배포하기 위한 Yaml 파일들이 담겨있다. 즉, Deployment나 Service 등, 여러 오브젝트들의 선언 파일들이 들어있다고 생각하면 된다. 이를 templates
폴더에 담은 것이나 같다.
허나, 우리가 흔히 아는 Yaml과는 조금 다른 값이 채워져 있는 것을 볼 수 있다. statefulset
의 파일을 보도록 하자.
apiVersion: {{ include "common.capabilities.statefulset.apiVersion" . }}
kind: StatefulSet
metadata:
name: {{ include "mysql.primary.fullname" . }}
namespace: {{ include "common.names.namespace" . | quote }}
labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }}
app.kubernetes.io/component: primary
{{- if .Values.commonAnnotations }}
annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }}
{{- end }}
spec:
replicas: 1
podManagementPolicy: {{ .Values.primary.podManagementPolicy | quote }}
{{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.primary.podLabels .Values.commonLabels ) "context" . ) }}
selector:
보다시피, {{ }} 형식으로 동적으로 값이 들어갈 수 있는 부분이 있다. 이 부분을 잘 보면, Values 에서 값을 가져오는 것을 볼 수 있는데, Helm은 이처럼 정적인 파일인 template에, values.yaml을 통해 동적으로 값을 삽입할 수 있도록 했다.
💡 즉, Helm은 정적인 template에 동적인 설정 값 (Value)로 오브젝트들을 패키지 형태로 관리한다.위에서 설명한 정적인 파일 template에, 설정 값을 삽입하는 구성요소가 바로 values.yaml이다.
global:
imageRegistry: ""
## E.g.
## imagePullSecrets:
## - myRegistryKeySecretName
##
imagePullSecrets: []
storageClass: ""
## @section Common parameters
##
## @param kubeVersion Force target Kubernetes version (using Helm capabilities if not set)
##
kubeVersion: ""
## @param nameOverride String to partially override common.names.fullname template (will maintain the release name)
##
nameOverride: ""
## @param fullnameOverride String to fully override common.names.fullname template
##
fullnameOverride:
다음은 mysql 차트의 values.yaml의 일부다. 이처럼, 커스터마이징 하고 싶은 설정값을 채움으로써 배포 환경이나 의도에 맞게 패키지를 세부적으로 설정할 수 있다.
특이한 점은, values.yaml은 정적인 template 파일에 동적으로 설정값을 삽입하는 구성요소다 보니, Override하고 싶은 필드만 명시해도 정상적으로 패키지를 배포할 수 있다.
예를 들어, mysql의 service를 ClusterIP가 아닌 NodePort로 배포하고 싶으면 단순히 해당 필드만 명시하면 된다.
service:
type: NodePort
nodePorts:
mysql: 30200
그 후, 다음 명령어를 입력함으로써 설정값을 적용하면 된다.
$ helm install --values custom_values.yaml mysql stable/mysql
또는
$ helm install -f custom_values.yaml mysql stable/mysql
helm repo add stable https://charts.helm.sh/stable
위의 명령어는 helm 차트 원격 레포지토리 중, stable 버전이 게시되어 있는 레포지토리를 추가하여, stable
이라는 이름으로 레포지토리를 저장하는 작업이다.
$ helm repo list
NAME URL
prometheus-community https://prometheus-community.github.io/helm-charts
grafana https://grafana.github.io/helm-charts
traefik https://traefik.github.io/charts
sonarqube https://SonarSource.github.io/helm-chart-sonarqube
bitnami https://charts.bitnami.com/bitnami
apache-airflow https://airflow.apache.org
mongodb https://mongodb.github.io/helm-charts
jetstack https://charts.jetstack.io
elastic https://helm.elastic.co
gitlab https://charts.gitlab.io
stable https://charts.helm.sh/stable
이를 통해, helm 레포지토리가 추가되어 해당 레포지토리에 게시되어 있는 Chart들을 선택할 수 있다.
$ helm search repo stable
NAME CHART VERSION APP VERSION DESCRIPTION
stable/acs-engine-autoscaler 2.2.2 2.1.1 DEPRECATED Scales worker nodes within agent pools
stable/aerospike 0.3.5 v4.5.0.5 DEPRECATED A Helm chart for Aerospike in Kubern...
stable/airflow 7.13.3 1.10.12 DEPRECATED - please use: https://github.com/air...
stable/ambassador 5.3.2 0.86.1 DEPRECATED A Helm chart for Datawire Ambassador
stable/anchore-engine 1.7.0 0.7.3 Anchore container analysis and policy evaluatio...
stable/apm-server 2.1.7 7.0.0 DEPRECATED The server receives data from the El...
stable/ark 4.2.2 0.10.2 DEPRECATED A Helm chart for ark
stable/artifactory 7.3.2 6.1.0 DEPRECATED Universal Repository Manager support...
stable/artifactory-ha 0.4.2 6.2.0 DEPRECATED Universal Repository Manager support...
stable/atlantis 3.12.4 v0.14.0 DEPRECATED A Helm chart for Atlantis https://ww...
...
저장한 레포지토리들의 차트를 최신화하려면 helm repo update
를 통해 최신화할 수 있다.
$ helm repo update
Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "apache-airflow" chart repository
...Successfully got an update from the "sonarqube" chart repository
...Successfully got an update from the "elastic" chart repository
...Successfully got an update from the "traefik" chart repository
...Successfully got an update from the "grafana" chart repository
...Successfully got an update from the "prometheus-community" chart repository
...Successfully got an update from the "gitlab" chart repository
...Successfully got an update from the "stable" chart repository
...Successfully got an update from the "mongodb" chart repository
...Successfully got an update from the "jetstack" chart repository
...Successfully got an update from the "bitnami" chart repository
Update Complete. ⎈Happy Helming!⎈
현재 홈서버의 Kubernetes는 Helm을 사용하지 않고, 기존 template으로 설정한 상태이다. 따라서 데이터를 미리 백업하고 재설치를 진행한다.
$ mysqldump -u root -p --all-databases > mysql_backup.sql
그 후, helm search repo mysql
을 통해 가능한 mysql의 버전을 확인한다.
$ helm search repo mysql
NAME CHART VERSION APP VERSION DESCRIPTION
bitnami/mysql 9.18.0 8.0.36 MySQL is a fast, reliable, scalable, and easy t...
prometheus-community/prometheus-mysql-exporter 2.4.0 v0.15.1 A Helm chart for prometheus mysql exporter with...
stable/mysql 1.6.9 5.7.30 DEPRECATED - Fast, reliable, scalable, and easy...
stable/mysqldump 2.6.2 2.4.1 DEPRECATED! - A Helm chart to help backup MySQL...
stable/prometheus-mysql-exporter 0.7.1 v0.11.0 DEPRECATED A Helm chart for prometheus mysql ex...
bitnami/phpmyadmin 14.2.0 5.2.1 phpMyAdmin is a free software tool written in P...
stable/percona 1.2.3 5.7.26 DEPRECATED - free, fully compatible, enhanced, ...
stable/percona-xtradb-cluster 1.0.8 5.7.19 DEPRECATED - free, fully compatible, enhanced, ...
stable/phpmyadmin 4.3.5 5.0.1 DEPRECATED phpMyAdmin is an mysql administratio...
bitnami/mariadb 15.2.0 11.2.2 MariaDB is an open source, community-developed ...
bitnami/mariadb-galera 11.2.0 11.2.2 MariaDB Galera is a multi-primary database clus...
stable/gcloud-sqlproxy 0.6.1 1.11 DEPRECATED Google Cloud SQL Proxy
stable/mariadb 7.3.14 10.3.22 DEPRECATED Fast, reliable, scalable, and easy t...
이 중에서 stable/mysql
버전은 DEPRECATED 되었다고 표시하므로, 최신 버전인 bitnami/mysql
을 설치한다.
$ helm install -f values.yaml mysql bitnami/mysql
NAME: mysql
LAST DEPLOYED: Wed Jan 24 15:34:12 2024
NAMESPACE: mysql
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
CHART NAME: mysql
CHART VERSION: 9.18.0
APP VERSION: 8.0.36
** Please be patient while the chart is being deployed **
Tip:
Watch the deployment status using the command: kubectl get pods -w --namespace mysql
...
$ kc get po
kNAME READY STATUS RESTARTS AGE
mysql-0 0/1 CrashLoopBackOff 6 (90s ago) 8m11s
$ kc logs -f mysql-0
mysql 15:40:54.04 INFO ==>
mysql 15:40:54.04 INFO ==> Welcome to the Bitnami mysql container
mysql 15:40:54.04 INFO ==> Subscribe to project updates by watching https://github.com/bitnami/containers
mysql 15:40:54.05 INFO ==> Submit issues and feature requests at https://github.com/bitnami/containers/issues
mysql 15:40:54.05 INFO ==>
mysql 15:40:54.06 INFO ==> ** Starting MySQL setup **
mysql 15:40:54.09 INFO ==> Validating settings in MYSQL_*/MARIADB_* env vars
mysql 15:40:54.11 INFO ==> Initializing mysql database
mkdir: cannot create directory '/bitnami/mysql/data': Permission denied
cannot create directory '/bitnami/mysql/data': Permission denied
의 오류를 해결하기 위해 volumePermission을 true로 설정하고, root user와 password도 설정한다.
$ vi values.yaml
volumePermissions:
enabled: true
auth:
rootPassword: "~~~~"
다음 명령어를 실행하여 Mysql을 설치한다.
$ helm install -f values.yaml mysql bitnami/mysql
#만일 이미 설치되어 있다면
$ helm upgrade --install -f values.yaml mysql bitnami/mysql
NAME: mysql
LAST DEPLOYED: Wed Jan 24 16:39:25 2024
NAMESPACE: mysql
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
CHART NAME: mysql
CHART VERSION: 9.18.0
APP VERSION: 8.0.36
** Please be patient while the chart is being deployed **
Tip:
...
$ kc get all
NAME READY STATUS RESTARTS AGE
pod/mysql-0 1/1 Running 0 3m52s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/mysql ClusterIP 10.104.132.205 <none> 3306/TCP 3m52s
service/mysql-headless ClusterIP None <none> 3306/TCP 3m52s
NAME READY AGE
statefulset.apps/mysql 1/1 3m52s
그 후, 파드 내부로 들어가서 데이터를 복구한다.
$ mysql -u root -p < mysql_backup.sql
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| boj_bot_db |
| diareat |
| family_app_db |
| gstagram |
| hackerthon |
| information_schema |
| my_database |
| mysql |
| performance_schema |
| sys |
+--------------------+
10 rows in set (0.02 sec)
잘 복구된 것을 볼 수 있다.
Helm으로 Node Server를 만들기 위해서는 먼저 Helm을 통해 기본 구조의 차트를 만들어야 한다.
$ helm create node_server
$ tree node_server
node_server
├── Chart.yaml
├── charts
├── templates
│ ├── NOTES.txt
│ ├── _helpers.tpl
│ ├── deployment.yaml
│ ├── hpa.yaml
│ ├── ingress.yaml
│ ├── service.yaml
│ ├── serviceaccount.yaml
│ └── tests
│ └── test-connection.yaml
└── values.yaml
다음과 같이 기본적인 구조의 Chart가 생성된다.
그 후, template 형식에 맞게 기존의 Manifest 파일들을 수정해주어야 한다.
다음은 기존의 Manifest 파일 중, Deployment와 Service의 Spec이 명시된 Yaml이다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: node-server
namespace: node-server
spec:
replicas: 2
selector:
matchLabels:
app: node-server
template:
metadata:
labels:
app: node-server
spec:
containers:
- name: node-server
image: public.ecr.aws/l2c3u0x6/node_server:latest
imagePullPolicy: IfNotPresent
resources:
requests:
memory: "512Mi"
cpu: "0.2"
limits:
memory: "2Gi"
cpu: "1"
ports:
- containerPort: 3000
envFrom:
- configMapRef:
name: node-server-configmap
---
apiVersion: v1
kind: Service
metadata:
name: interview
namespace: interview
spec:
selector:
app: interview
ports:
- port: 80
targetPort: 3000
protocol: TCP
nodePort: 30300
type: NodePort
Helm에서 동적으로 설정값을 넣기 위해서는 Template의 필드의 값 부분을 Go Template
을 이용하여 대체해야 한다.
Manifest 파일을 Go Template에 맞게 수정하기 위해, 천천히 단계적으로 접근해보자.
그 전에 Helm에 내장된, 즉, 사전에 정의된 필드를 알면 좀 더 작성하기 쉽다.
Release
: 패키지의 릴리즈 자체를 의미한다.Release.Name
: 릴리즈 이름Release.Namespace
: 릴리즈될 네임스페이스Release.Revision
: 릴리즈의 리비전 번호. 설치시 1이고, Upgrade 또는 Rollback시 번호가 증가한다.Values
: values.yaml
을 통해 전달될 설정 값을 의미한다.Chart
: Chart.yaml
을 통해 전달될 값을 의미한다.Capabilites
: 쿠버네티스 클러스터가 지원하는 기능에 대한 정보를 제공한다.Template
: 현재 실행 중인 템플릿의 정보를 포함한다.Name
: 현재 템플릿에 대한 전체 파일 경로BasePath
: 현재 템플릿에 대한 디렉토리 경로helm을 통해 템플릿을 정의할 때, 재활용 가능한 필드를 미리 템플릿 조각 (.tpl
)에 정의한 후, 이를 사용할 때 Include 문을 사용한다.
예를 들어,
{{- define "example.labels" -}}
app.kubernetes.io/name: {{ include "example.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end -}}
이러한 템플릿 조각 파일 (example.tpl
)을 정의했다면, 다음과 같이 재활용 할 수 있다.
metadata:
labels:
{{- include "example.lables" . | nindent 4}}
즉, 이는 아래의 내용과 동일하다. 여기서 nindent 4란 들여쓰기를 4번 하라는 뜻이다. Yaml파일은 들여쓰기에 매우 민감하기 때문에, 필드를 맞추기 위해서 들여쓰기 횟수를 명시해야 한다.
metadata:
labels:
app.kubernetes.io/name: {{ include "example.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
우선, Deployment의 name
부터 시작해보겠다. 보통 helm install
을 통해 패키지를 설치하고자 할 때는 다음과 같은 양식을 따른다.
helm install <설치하는 Package에 붙일 이름> <차트 명칭>
이 때, <설치하는 Package에 붙일 이름>
이 곧 애플리케이션의 이름이 되며, 이는 곧 metadata.name
의 값이 되므로, 이를 대체해야 한다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "node-server.fullname" . }}
...
{{ include "node-server.fullname" . }}
은 템플릿 조각 _helpers.tpl
에서 Chart에 명시되어 있는 이름과 같다. Chart.yaml에는 해당 패키지의 기본 metadata (이름, 버전)등이 명시되어 있으므로, 이를 일관되게 사용하기 위해 include를 통해 name을 주입했다.
apiVersion: apps/v1
kind: Deployment
metatdata:
name: {{ include "node-server.fullname" . }}
namepsace: {{ .Release.Namespace | quote }}
{{ .Release.Namespace | quote }}
의 경우는 사용자가 helm 패키지를 설치할 때 명시하는 Namespace를 지칭하며, helm v3부터는 패키지 설치시 Namespace를 지정해야 한다는 원칙에 따라 .Release.Namespace 를 그대로 사용했다. 또한 | quote
를 통해 쌍따옴표를 붙여 String으로 인식하도록 했다.
Go 템플릿은 조건절을 지원하기도 한다. 즉, 조건절에 따라 해당 필드를 포함할 수도, 포함하지 않을 수도 있다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "node-server.fullname" . }}
namepsace: {{ .Release.Namespace | quote }}
spec:
replicas: 2 ##
이 Replicas를 Autoscaling 옵션이 false 일 경우에만 필드에 포함하도록 바꾸면 다음과 같다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "node-server.fullname" . }}
namepsace: {{ .Release.Namespace | quote }}
spec:
{{- if not .Values.autoscaling.enabled }}
replicas: {{ .Values.replicaCount }}
{{- end }}
{{- if not .Values.autoscaling.enabled }}
의 뜻은 values.yaml에서 autoscaling 필드의 하위 필드 enabled가 false일 때만 해당 필드를 사용하겠다는 뜻이 된다. 즉, values.yaml에서,
namespace: interview
autoscaling:
enabled: false
minReplicas: 1
maxReplicas: 3
targetCPUUtilizationPercentage: 50
targetMemoryUtilizationPercentage: 50
replicaCount: 2
다음과 같이 enabled: false
일 때만 replicas의 수를 명시하겠다는 뜻이다. 만일 true
이면 replicas
필드에 값이 기입된다.
위에서 사용한 방법으로 나머지 필드를 모두 채우면 다음과 같은 모습이 된다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "node-server.fullname" . }}
namepsace: {{ .Release.Namespace | quote }}
spec:
{{- if not .Values.autoscaling.enabled }}
replicas: {{ .Values.replicaCount }
{{- end }}
selector:
matchLabels:
app: {{ .Values.labels.app }}
template:
metadata:
labels:
app: {{ .Values.labels.app }}
이제 남은 필드는 컨테이너의 spec 필드다.
spec:
containers:
- name: node_server
image: public.ecr.aws/l2c3u0x6/node_server:latest
imagePullPolicy: Always
resources:
requests:
memory: "512Mi"
cpu: "0.2"
limits:
memory: "128Mi"
cpu: "500m"
ports:
- containerPort: 3000
우선, Containers의 name
필드는 Chart.yaml에 적힌 Name을 사용할 것이다.
spec:
containers:
- name: {{ Chart.Name }}
또한, 이미지의 경로 역시 하드코딩하는 것은 적절하지 않으므로, values.yaml에서 동적으로 불러오도록한다.
spec:
containers:
- name: {{ Chart.Name }}
image: {{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}
여기서 {{ .Values.image.tag | default .Chart.Appversion }}
중 default
는 말 그대로 기본값을 설정하는 것이다. 즉, image.tag가 명시되지 않으면 Chart.yaml의 Appversion을 사용하겠다는 것이다.
values.yaml은 다음과 같이 생성된다.
autoscaling:
enabled: false
minReplicas: 1
maxReplicas: 3
targetCPUUtilizationPercentage: 50
targetMemoryUtilizationPercentage: 50
replicaCount: 2
image:
repository: public.ecr.aws/l2c3u0x6/node_server
tag: latest
이제 어느정도 감을 잡았으니, 나머지 필드를 포함하여 전체 템플릿 파일을 생성하면 다음과 같다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "node-server.fullname" . }}
namespace: {{ .Release.Namespace | quote }}
spec:
{{- if not .Values.autoscaling.enabled }}
replicas: {{ .Values.replicaCount }}
{{- end }}
selector:
matchLabels:
app: {{ .Values.labels.app }}
template:
metadata:
labels:
app: {{ .Values.labels.app }}
spec:
containers:
- name: {{ .Chart.Name }}
image: {{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}
imagePullPolicy: {{ .Values.image.imagePullPolicy }}
resources:
requests:
memory: {{ .Values.resources.requests.memory }}
cpu: {{ .Values.resources.requests.cpu }}
limits:
memory: {{ .Values.resources.limits.memory }}
cpu: {{ .Values.resources.limits.cpu }}
ports:
- containerPort: {{ .Values.args.port }}
envFrom:
- configMapRef:
name: {{ include "node-server.fullname" . }}
이에 따른 values.yaml은 다음과 같다.
autoscaling:
enabled: false
minReplicas: 1
maxReplicas: 3
targetCPUUtilizationPercentage: 50
targetMemoryUtilizationPercentage: 50
replicaCount: 2
labels:
app: node_server
image:
repository: public.ecr.aws/l2c3u0x6/node_server
tag: latest
imagePullPolicy: IfNotPresent
resources:
requests:
memory: "256Mi"
cpu: "0.2"
limits:
memory: "512Mi"
cpu: "0.8"
args:
port: 3000
마찬가지로 Service도 바꿔보도록 하자.
apiVersion: v1
kind: Service
metadata:
name: {{ include "node-server.fullname" . }}
namespace: {{ .Release.Namespace | quote }}
spec:
selector:
app: {{ .Values.labels.app }}
ports:
- port: {{ .Values.service.port }}
targetPort: {{ .Values.service.targetPort }}
protocol: {{ .Values.service.protocol }}
nodePort: 30300
type: NodePort
이제 Service Type이 걸린다. 종류에 따라 변경하려면 어떻게 해야 할까? 위에서 사용한 조건절을 이용하면 다음과 같다.
apiVersion: v1
kind: Service
metadata:
name: {{ include "node-server.fullname" . }}
namespace: {{ .Release.Namespace | quote }}
spec:
selector:
app: {{ .Values.labels.app }}
ports:
- port: {{ .Values.service.port }}
targetPort: {{ .Values.service.targetPort }}
protocol: {{ .Values.service.protocol }}
{{- if eq .Values.service.type "NodePort" }}
nodePort: {{ .Values.service.nodePort }}
{{- end }}
type: {{ .Values.service.type }}
nodePort
필드를 사용하는 Service Type은 NodePort
Service 밖에 없다. 따라서, 만일 Service Type이 NodePort
가 아니라면 해당 필드를 비활성화 시켜야 하므로, 조건절을 통해 필드를 선택적으로 활성화 시키는 것이다.
지금까지 values.yaml은 다음과 같다.
autoscaling:
enabled: false
minReplicas: 1
maxReplicas: 3
targetCPUUtilizationPercentage: 50
targetMemoryUtilizationPercentage: 50
replicaCount: 2
labels:
app: node_server
image:
repository: public.ecr.aws/l2c3u0x6/node_server
tag: latest
imagePullPolicy: IfNotPresent
resources:
requests:
memory: "256Mi"
cpu: "0.2"
limits:
memory: "512Mi"
cpu: "0.8"
args:
port: 3000
service:
port: 80
targetPort: 3000
protocol: TCP
nodePort: 30300
type: ClusterIP
ingress:
enabled: true
마지막으로, 웹서버가 DB에 접근할 수 있도록, 컨피그맵 또한 Go template 형식에 맞게 수정한다.
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "node-server.fullname" . }}
namespace: {{ .Release.Namespace | quote }}
data:
DB_HOST: {{ .Values.configMap.DB_HOST | quote }}
DB_USER: {{ .Values.configMap.DB_USER | quote }}
DB_PASSWORD: {{ .Values.configMap.DB_PASSWORD | quote }}
DB_NAME: {{ .Values.configMap.DB_NAME | quote }}
여기서 “quote”란 값의 양 끝에 쌍따옴표 “를 붙이는 명령어를 의미한다.
최종 YAML 파일은 다음과 같다.
autoscaling:
enabled: false
minReplicas: 1
maxReplicas: 3
targetCPUUtilizationPercentage: 50
targetMemoryUtilizationPercentage: 50
replicaCount: 2
labels:
app: node-server
image:
repository: public.ecr.aws/l2c3u0x6/node_server
tag: latest
imagePullPolicy: Always
resources:
requests:
memory: "256Mi"
cpu: "0.2"
limits:
memory: "1Gi"
cpu: "1"
args:
port: 3000
service:
port: 80
targetPort: 3000
protocol: TCP
nodePort: 30300
type: NodePort
ingress:
enabled: false
configMap:
DB_HOST: ...
DB_USER: ...
DB_PASSWORD: ...
DB_NAME: ...
최종 차트 구조는 다음과 같다.
tree
.
├── Chart.yaml
├── charts
├── templates
│ ├── NOTES.txt
│ ├── _helpers.tpl
│ ├── configmap.yaml
│ ├── deployment.yaml
│ ├── hpa.yaml
│ ├── ingress.yaml
│ ├── service.yaml
│ └── tests
│ └── test-connection.yaml
└── values.yaml
배포하기 전, helm에서 패키지들을 배포하기 위해서는 .tgz 형식으로 패키지를 묶어야 한다.
그전에 먼저 다음 명령어를 실행하여, helm 차트가 제대로 실행이 되는지 확인한다.
$ helm upgrade -i node-server ./node-server --dry-run --debug
history.go:56: [debug] getting history for release node-server
Release "node-server" does not exist. Installing it now.
install.go:214: [debug] Original chart version: ""
install.go:231: [debug] CHART PATH: /home/synoti21/interview/node-server
NAME: node-server
LAST DEPLOYED: Thu Jan 25 15:35:21 2024
NAMESPACE: node-server
STATUS: pending-install
REVISION: 1
USER-SUPPLIED VALUES:
{}
COMPUTED VALUES:
args:
...
검사를 해보니 잘 실행되는 것을 확인할 수 있다. 따라서 다음 명령어를 통해 패키지 압축파일을 생성한다.
$ helm package node-server
$ ls
node-server node-server-0.1.0.tgz
실제로 로컬 서버에 배포를 해보자.
$ helm install node-server ./node-server -n node-server
NAME: node-server
LAST DEPLOYED: Thu Jan 25 17:45:43 2024
NAMESPACE: node-server
STATUS: deployed
REVISION: 1
NOTES:
1. Get the application URL by running these commands:
export NODE_PORT=$(kubectl get --namespace node-server -o jsonpath="{.spec.ports[0].nodePort}" services node-server)
export NODE_IP=$(kubectl get nodes --namespace node-server -o jsonpath="{.items[0].status.addresses[0].address}")
echo http://$NODE_IP:$NODE_PORT
$ kc get all
NAME READY STATUS RESTARTS AGE
pod/node-server-5fb7588fc4-2kdqc 1/1 Running 0 2m46s
pod/node-server-5fb7588fc4-84xhm 1/1 Running 0 2m46s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/node-server NodePort 10.105.1.165 <none> 80:30300/TCP 2m46s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/node-server 2/2 2 2 2m46s
NAME DESIRED CURRENT READY AGE
replicaset.apps/node-server-5fb7588fc4 2 2 2 2m46s
잘 작동하는 것을 볼 수 있다!