DevOps & Infra/Kubernetes

[Kubernetes/helm] 쿠버네티스의 패키지 관리자 Helm 알아보기

턴태 2023. 11. 9. 00:38

헬름은 쿠버네티스를 위한 패키지 관리자다.

 

헬름을 이용하면 여러 유용한 패키지들을 손쉽게 설치할 수 있다. 예를 들어서, metalLB를 helm로도 설치할 수 있다. Kustomize와 비슷한 격이다.

 

공식 문서 한국어 번역도 깔끔하고, 상당히 친절해서 공식문서를 읽는 것이 좋을 것 같다. 아래 내용은 위 공식문서를 읽으며 정리한 내용이다.

설치

homebrew나 chocolatey 같은 패키지 매니저로도 설치할 수 있는데 헬름 프로젝트에서 공식적으로는 지원하지 않아서 스크립트로 설치하는 것을 추천한다고 한다.

curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3
chmod 700 get_helm.sh
./get_helm.sh

 

 

helm이 잘 설치 됐으면 helm version으로 확인할 수 있다.

주요 개념 3가지

chart는 헬름 패키지다. 이 패키지에는 쿠버네티스 클러스터 내에서 애플리케이션, 도구, 서비스를 구동하는데 필요한 모든 리소스 정의가 포함되어 있다. 쿠버네티스에서의 Homebrew 포뮬러, Apt dpkg, YUM RPM 파일과 같은 것으로 생각할 수 있다.

 

Repository는 차트를 모아두고 공유하는 장소이다. Perl의 CPAN 아카이브페도라 패키지 데이터베이스와 같은데, 쿠버네티스 패키지용이라고 보면 된다.

 

Release는 쿠버네티스 클러스터에서 구동되는 차트의 인스턴스이다. 일반적으로 하나의 차트는 동일한 클러스터내에 여러 번 설치될 수 있다. 설치될 때마다, 새로운 release 가 생성된다.

 

MySQL 차트의 경우 클러스터 내에 데이터베이스 2대를 구동하려면, 차트를 두번 설치하면 된다. 차례대로 각각 release 이름을 부과하고 다른 release를 사용한다.

 

헬름은 쿠버네티스 내부에 charts 를 설치하고, 각 설치에 대해 새로운 release 를 생성한다. 새로운 차트를 찾기 위해 헬름 차트 repositories 를 검색할 수 있다.

 

도커 허브에서 이미지(=> charts)를 찾고, 각 이미지 별로 컨테이너(=> release)를 생성하는 것과 같다.

helm search 차트 찾기

helm은 hub 혹은 repo에서 차트를 찾을 수 있다.

  • helm search hub 는 헬름 허브에서 헬름 차트를 검색한다. 헬름 차트가 있는 repository를 모두 검색한다.
  • helm search repo 는 로컬에 저장된 repository에서 검색한다. 미리 저장해 놓기 때문에 네트워크가 없더라도 검색이 가능하다. helm repo add 로 repository를 저장할 수 있다.
$ helm search hub postgres
URL                                                   CHART VERSION    APP VERSION    DESCRIPTION
https://artifacthub.io/packages/helm/romanow-he...    1.5.0            15             PostgreSQL is a powerful, open source object-re...
https://artifacthub.io/packages/helm/smo-helm-c...    6.0.0                           ONAP Postgres Server
https://artifacthub.io/packages/helm/account-se...    1.0.0            1.0.0          A Helm chart for Kubernetes for deployment post...
https://artifacthub.io/packages/helm/nicholaswi...    0.1.0            13.3           The World's Most Advanced Open Source Relationa...

 

레포지터리를 추가하면 기존에 추가했던 레포지터리에 있는 차트들을 가져온다.
테스트를 위해 bitnami 레포지터리를 추가했다. 아래 명령어로 추가할 수 있다.

helm repo add bitnami https://charts.bitnami.com/bitnami

 

현재는 bitnami 레포지터리만 추가해뒀기 때문에, postgres를 레포지터리로 찾을 때 bitnami의 postgres 차트 검색 결과만 조회할 수 있다.

$ helm search repo postgres
NAME                     CHART VERSION    APP VERSION    DESCRIPTION
bitnami/postgresql       13.2.2           16.0.0         PostgreSQL (Postgres) is an open source object-...
bitnami/postgresql-ha    12.1.1           16.0.0         This PostgreSQL cluster solution includes the P...
bitnami/supabase         2.1.1            0.23.9         Supabase is an open source Firebase alternative...

 

검색어는 문자열 탐색 알고리즘이 사용되어서 일부만 검색해도 찾을 수 있다. post만 입력해도 postgresql을 가져온다.

$ helm search repo post
NAME                     CHART VERSION    APP VERSION    DESCRIPTION
bitnami/postgresql       13.2.2           16.0.0         PostgreSQL (Postgres) is an open source object-...
bitnami/postgresql-ha    12.1.1           16.0.0         This PostgreSQL cluster solution includes the P...
bitnami/supabase         2.1.1            0.23.9         Supabase is an open source Firebase alternative...

helm install 패키지 설치

릴리즈 이름과 설치하려는 차트 이름을 파라미터로 받는다. 릴리즈 이름을 자동으로 생성하려면 --generate-name 옵션을 사용한다.

$ helm install postgres bitnami/postgresql
NAME: postgres
LAST DEPLOYED: Wed Nov  8 19:44:20 2023
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
CHART NAME: postgresql
CHART VERSION: 13.2.2
APP VERSION: 16.0.0

** Please be patient while the chart is being deployed **

PostgreSQL can be accessed via port 5432 on the following DNS names from within your cluster:

    hello-world-postgresql.default.svc.cluster.local - Read/Write connection

To get the password for "postgres" run:

    export POSTGRES_PASSWORD=$(kubectl get secret --namespace default hello-world-postgresql -o jsonpath="{.data.postgres-password}" | base64 -d)

To connect to your database run the following command:

    kubectl run hello-world-postgresql-client --rm --tty -i --restart='Never' --namespace default --image docker.io/bitnami/postgresql:16.0.0-debian-11-r15 --env="PGPASSWORD=$POSTGRES_PASSWORD" \
      --command -- psql --host hello-world-postgresql -U postgres -d postgres -p 5432

    > NOTE: If you access the container using bash, make sure that you execute "/opt/bitnami/scripts/postgresql/entrypoint.sh /bin/bash" in order to avoid the error "psql: local user with ID 1001} does not exist"

To connect to your database from outside the cluster execute the following commands:

    kubectl port-forward --namespace default svc/hello-world-postgresql 5432:5432 &
    PGPASSWORD="$POSTGRES_PASSWORD" psql --host 127.0.0.1 -U postgres -d postgres -p 5432

WARNING: The configured password will be ignored on new installation in case when previous PostgreSQL release was deleted through the helm command. In that case, old PVC will have an old password, and setting it through helm won't take effect. Deleting persistent volumes (PVs) will solve the issue.

 

이후 잘 설치되었는지 확인하기 위해 검색했을 때, 아래처럼 릴리즈 이름 + 패키지명 조합의 스테이트풀셋으로 만들어진 것을 확인할 수 있었다.

$ kubectl get all -n default | grep "postgres"
pod/postgres-postgresql-0           1/1     Running   0               133m
service/postgres-postgresql      ClusterIP      10.97.34.46      <none>         5432/TCP         133m
service/postgres-postgresql-hl   ClusterIP      None             <none>         5432/TCP         133m
statefulset.apps/postgres-postgresql   1/1     133m

 

혹은 helm 에서도 helm status 릴리즈이름을 통해 상태를 추적하거나 구성정보를 확인할 수 있다.

$ helm status postgres
NAME: postgres
LAST DEPLOYED: Wed Nov  8 19:44:20 2023
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
CHART NAME: postgresql
CHART VERSION: 13.2.2
APP VERSION: 16.0.0

** Please be patient while the chart is being deployed **

PostgreSQL can be accessed via port 5432 on the following DNS names from within your cluster:

    hello-world-postgresql.default.svc.cluster.local - Read/Write connection

To get the password for "postgres" run:

    export POSTGRES_PASSWORD=$(kubectl get secret --namespace default hello-world-postgresql -o jsonpath="{.data.postgres-password}" | base64 -d)

To connect to your database run the following command:

    kubectl run hello-world-postgresql-client --rm --tty -i --restart='Never' --namespace default --image docker.io/bitnami/postgresql:16.0.0-debian-11-r15 --env="PGPASSWORD=$POSTGRES_PASSWORD" \
      --command -- psql --host hello-world-postgresql -U postgres -d postgres -p 5432

    > NOTE: If you access the container using bash, make sure that you execute "/opt/bitnami/scripts/postgresql/entrypoint.sh /bin/bash" in order to avoid the error "psql: local user with ID 1001} does not exist"

To connect to your database from outside the cluster execute the following commands:

    kubectl port-forward --namespace default svc/hello-world-postgresql 5432:5432 &
    PGPASSWORD="$POSTGRES_PASSWORD" psql --host 127.0.0.1 -U postgres -d postgres -p 5432

WARNING: The configured password will be ignored on new installation in case when previous PostgreSQL release was deleted through the helm command. In that case, old PVC will have an old password, and setting it through helm won't take effect. Deleting persistent volumes (PVs) will solve the issue.

 

혹은 helm list 로도 현재 설치된 릴리즈를 확인할 수 있다.

$ helm list
NAME        NAMESPACE    REVISION    UPDATED                                 STATUS    CHART                APP VERSION
postgres    default      1           2023-11-08 20:21:43.438662 +0900 KST    failed    postgresql-13.2.2    16.0.0

차트 커스터마이징

패키지를 본격적으로 설치하기 전에 차트를 커스터마이징할 수 있다. 구성할 수 있는 옵션은 helm show values 차트명을 통해 확인할 수 있다.

$ helm show values bitnami/postgresql
# Copyright VMware, Inc.
# SPDX-License-Identifier: APACHE-2.0

## @section Global parameters
## Please, note that this will override the parameters, including dependencies, configured to use the global value
##
global:
  ## @param global.imageRegistry Global Docker image registry
  ##
  imageRegistry: ""
  ## @param global.imagePullSecrets Global Docker registry secret names as an array
  ## e.g.
  ## imagePullSecrets:
  ##   - myRegistryKeySecretName
  ##
  imagePullSecrets: []
  ## @param global.storageClass Global StorageClass for Persistent Volume(s)
  ##
  storageClass: ""
  ...

 

그러면 yaml 파일에 지정된 형식을 오버라이드하여 원하는 설정을 부여할 수 있다.

auth:
  ## @param auth.enablePostgresUser Assign a password to the "postgres" admin user. Otherwise, remote access will be blocked for this user
  ##
  enablePostgresUser: true
  ## @param auth.postgresPassword Password for the "postgres" admin user. Ignored if `auth.existingSecret` is provided
  ##
  postgresPassword: ""
  ## @param auth.username Name for a custom user to create
  ##
  username: ""
  ## @param auth.password Password for the custom user to create. Ignored if `auth.existingSecret` is provided
  ##
  password: ""
  ## @param auth.database Name for a custom database to create
  ##
  database: ""
  ## @param auth.replicationUsername Name of the replication user
  ##
  replicationUsername: repl_user

# 아래처럼 yaml 파일을 만들었으나, 잘 적용이 안 돼서 기존 yaml 형식으로 작성해보니까 잘 적용 됐다.
$ echo '{auth.username: "iseongtae", auth.password: "root1234", auth.database: "testdb"}' > config.yaml
$ helm install -f config.yaml postgresql bitnami/postgresql

 

예를 들어서, postgres를 설치하면서 유저와 데이터베이스를 생성할 수 있다.

 

실제로 statefulset pod를 뽑아보니 환경변수가 잘 적용이 되어 있다. secret도 같은 방법으로 뽑아내어 base64 디코딩했을 때 원했던 비밀번호가 적용되어 있었다.

$ kubectl get pod postgres-postgresql-0 -o yaml

...
  containers:
  - env:
    - name: BITNAMI_DEBUG
      value: "false"
    - name: POSTGRESQL_PORT_NUMBER
      value: "5432"
    - name: POSTGRESQL_VOLUME_DIR
      value: /bitnami/postgresql
    - name: PGDATA
      value: /bitnami/postgresql/data
    - name: POSTGRES_USER
      value: iseongtae # 오버라이드한 username
    - name: POSTGRES_PASSWORD
      valueFrom:
        secretKeyRef:
          key: password
          name: postgres-postgresql
    - name: POSTGRES_POSTGRES_PASSWORD
      valueFrom:
        secretKeyRef:
          key: postgres-password
          name: postgres-postgresql
    - name: POSTGRES_DATABASE
      value: testdb # 오버라이드한 database
...

 

옵션에 값을 전달하는 방법은 위 방식을 포함하여 총 두 개가 있다.

  • --values(= -f): 여러 번 지정할 수 있지만, 가장 오른쪽에 있는 파일이 우선시된다.
  • --set: 명령줄에서 지정한다. 키=값 쌍으로 오버라이드할 수 있다.

둘 다 사용하면, --set 값은 더 높은 우선순위를 가진 --values 으로 병합된다. --set에 명시된 오버라이드 사항들은 컨피그맵(ConfigMap)으로 보관된다. helm get values 릴리즈이름로 해당 릴리스에 대한 --set 설정값들을 조회할 수 있다. --set 설정값들은 helm upgrade를 실행할 때 --reset-values를 명시하여 제거할 수 있다.

 

콤마를 찍어 여러 개의 값을 넣을 수도 있다.

--set a=1,b=2
a: 1
b: 2

 

--set에서 nested된 값은 키.키=값으로 표현할 수 있다.

--set key.key=value
key:
  key: value

 

중괄호를 사용하여 리스트로 표현할 수도 있다.

--set key={value1, value2, value3}
key:
  - value1
  - value2
  - value3

 

인덱스 문법을 사용하여 설정할 수도 있다.

--set key[0].firstKey=value
key:
  - firstKey: value

 

특수문자를 위한 이스케이프도 지원한다.

--set key=value1\,value2 # 이스케이프를 사용하지 않으면, 두 개의 값으로 인식 및 에러
key: "value1,value2"
--set nodeSelector."kubernetes\.io/role"=master
nodeSelector:
  kubernetes.io/role: master

 

차트 저장소 외에 설치할 수 있는 방법들은 다음과 같다.

  • 차트 저장소 (위에서 살펴본 것)
  • 로컬 차트 압축파일 (helm install foo foo-0.1.1.tgz)
  • 압축해제된 차트 디렉토리 (helm install foo path/to/foo)
  • 완전한 URL (helm install foo https://example.com/charts/foo-1.2.3.tgz)

helm upgrade, helm rollback 릴리즈 업그레이드 및 롤백

새로운 버전의 차트가 릴리즈 되었거나, 릴리즈 구성을 변경하고자 할 때 helm upgrade를 통해 변경할 수 있다. 업그레이드는 현존하는 릴리스를 가지고, 사용자가 입력한 정보에 따라 업그레이드한다. 쿠버네티스의 apply 처럼 바뀐 사항에 대해서만 변경이 진행된다.

helm upgrade -f config.yml postgres bitnami/postgres

 

위에서 postgres 릴리즈의 차트가 업그레이드되며, 새로 오버라이드 한 yaml 파일도 적용된다. helm get values 릴리즈이름를 통해 설정한 옵션/구성이 잘 적용되었는지 확인해볼 수 있다.

 

또한, 릴리즈가 오타나 내부 구성의 오류로 원하는 동작을 하지 않을 수 있다. 디플로이먼트처럼 릴리즈도 마찬가지로 롤백을 유용하게 사용할 수 있다.

helm rollback 릴리즈이름 리비전

 

증분 리비전을 사용하므로 1씩 증가한다. 어떤 리비전들이 있는지는 history로 확인할 수 있다.

helm history 릴리즈이름

기타 옵션들

설치하거나 업그레이드, 롤백 시 유용한 옵션들이 있다.

  • --timeout: 쿠버네티스 명령어가 완료되기를 기다리는 값으로 기본값은 5분(5m0s)이다.
    $ helm install postgres bitnami/postgresql --timeout 1m
    NAME: postgres
    LAST DEPLOYED: Wed Nov  8 20:20:20 2023
    NAMESPACE: default
    STATUS: deployed
    REVISION: 1
    TEST SUITE: None
    NOTES:
    CHART NAME: postgresql
    CHART VERSION: 13.2.2
    APP VERSION: 16.0.0
  • --wait: 쿠버네티스 오브젝트들이 모두 준비상태가 되었을 때까지 기다린다. timeout으로 설정한 값까지 기다리고 그 이후로는 릴리즈가 FAILED로 기록된다.

helm uninstall 릴리즈 삭제

helm uninstall 릴리즈이름으로 릴리즈를 삭제할 수 있다.

 

성공적으로 삭제되었는지는 helm list로도 확인할 수 있다.

 

그리고 helm uninstall --keep-history을 사용하면 삭제 기록도 확인할 수 있다. helm list --uninstalled는 사용하면, --keep-history 플래그로 언인스톨된 릴리스들만 볼 수 있다. --all을 사용하면 실패/삭제된 릴리즈를 포함한 모든 릴리즈를 가져올 수 있다.

삭제된 릴리즈는 롤백이 불가능하다.

helm repo 레포지터리 작업하기

helm repo list 를 통해 현재 저장된 레포지터리를 조회할 수 있다.

$ helm repo list
NAME       URL
bitnami    https://charts.bitnami.com/bitnami

helm repo add 레포지터리명 레포지터리주소로 레포지터리를 저장할 수도 있다.

$ helm repo add prometheus
"prometheus" has been added to your repositories

$ helm repo list
NAME          URL
bitnami       https://charts.bitnami.com/bitnami
prometheus    https://prometheus-community.github.io/helm-charts

helm repo update로 레포지터리를 업데이트할 수 있고 helm repo remove 레포지터리명으로 삭제할 수 있다.

차트 만들기

차트 개발 가이드는 개발하는 방법을 설명한다. 하지만 helm create 명령어를 사용하여 빠르게 시작해볼 수 있다:

$ helm create my-first-chart
Creating my-first-chart

 

 

이렇게 디렉터리와 함께 차트가 생성된다. 차트를 모두 편집했다면 helm lint [경로]로 형식에 맞췄는지 검증할 수도 있다.

의도적으로 잘못 작성하면 위처럼 에러를 잡아준다.

 

배포를 하기 위해서 helm package 패키지명 으로 패키징할 수 있다. helm create의 인자로 넣었던 패키지명을 인수로 넣는다.

$ helm package my-first-chart
Successfully packaged chart and saved it to: /Users/iseongtae/my-first-chart-0.1.0.tgz

 

위에서 기재한 방법대로 압축파일로 패키지를 설치하면 끝이다.

helm install my-first-chart ./my-first-chart-0.1.0.tgz

 

정리하며

구성 옵션을 변경하는 부분이 가장 중요하면서도 가장 껄끄러웠다. 막상 yaml 파일을 만들고 적용시켜도 잘 적용되었는지 제대로 확인이 되지 않고, 각 패키지마다 옵션들을 잘 숙지하고 있어야 하기 때문이다. 뭔가 쉬우면서도 어렵다!