쿠버네티스 교육

06. Kube 교육 - Helm 이용한 Application 배포

Jerry_이정훈 2021. 6. 4. 16:37
728x90

실습

실무에서 아래의 작업을 위해 필요한 Helm 관련 내용을 정리해 보았습니다.

  • Helm 이용하여 Redis Helm Chart를 다운로드 하세요
  • values.yml 수정하여 StorageClass, AuthPassword 등을 수정하세요 
  • 각 변수가 어떤 YAML 파일에 적용되는지 확인해 보세요 
  • Helm Redis 설치해 보세요
  • auth.Password 변수 변경하고 Helm Chart 업데이트 하세요 

물론, 위 실습을 이미 하실 수 있는 정도면 아래 생략하셔도 됩니다 ^^

 

Why Helm?

Kube 관련 일하다 보면 YAML 파일을 참으로 많이 만들게 됩니다. 그럴 때 과연 이게 보안과 고가용성 측면에서 제대로 작성한건지 궁금할 때가 많습니다. Application이 돌아는 가는 것 같은데 이게 Best-Practice인지 확신이 없는 거죠. 그리고 Deploy, Service, ConfigMap 등 여러 YAML 파일이 필요하고 수정된 버전도 같이 관리해야 하는데 여러 사람들(+ 과거의 나)과 같이 관리하는게 참 어렵습니다. 이 때 사용하기 편한 도구가 바로 Helm 입니다. 


Helm은 쿠버네티스 어플리케이션을 패키지 형태로 손쉽게 관리할 수 있도록 도와주는 도구입니다. CentOS에서 YUM이 어플리케이션에서 사용하는 여러 라이브러리를 하나의 통일된 패키지로 관리 하듯이 Kube Helm은 어플리케이션에서 사용하는 여러 object를 단일 패키지 형태로 관리 합니다.

 

그리고 해당 Helm 파일을 여러 사람들이 사용할 수 있도록 인터넷에 공개해 놓은 게 많습니다. (artifacthub.io) 그 중 많은 사람들이 사용하는 Helm 파일을 이용하시면 보안과 안정성 측면에서 Best-Practice 기반인 경우가 많습니다. Kube 환경에서 Application  YAML 파일은 Helm으로 관리하는 것이 거의 준 표준이 되었습니다.

 

그럼, Redis 설치 Hands-on으로 Helm 상세 내용을 확인하겠습니다.

 

Helm Application 검색 

설치하려는 어플리케이션을 구글에서 helm chart 로 검색하시면 됩니다. 

주로 어플리케이션 공식 helm chart 또는 Bitnami Helm 사용합니다. (Bitnami 짱인 경우가 많았습니다.)

 

Redis Helm Chart 다운로드

먼저 Helm Repo를 추가 합니다. (yum repo 추가와 동일합니다.)

[spkr@erdia22 32.redis (spkn02:nginx)]$ helm repo add bitnami https://charts.bitnami.com/bitnami
"bitnami" has been added to your repositories

Redis 설치 시 공식 홈페이지 가이드는 옵션 수정 없이 바로 install 명령어를 사용합니다. 하지만 그렇게 하지 마시고 먼저, 설치 관련 패키지 File을 다운로드(pull) 하여 옵션을 수정하고 설치하시는 것을 권고 합니다. 파일 다운로드는 docker 등과 동일하게 익숙한 pull 명령어를 사용합니다. 다운로드 받는 디렉토리 위치도 Redis로 지정하는 걸 권고합니다. 

[spkr@erdia22 ~ (spkn02:redis)]$ helm pull bitnami/redis

[spkr@erdia22 32.redis (spkn02:nginx)]$ ls -lrt
total 148
-rw-r--r-- 1 spkr spkr 64224 Nov 11  2020 redis-11.3.4.tgz
drwxr-xr-x 5 spkr spkr  4096 Nov 13  2020 redis-11.3.4
drwxr-xr-x 6 spkr spkr  4096 Mar 17 10:59 redis-12.8.3
-rw-r--r-- 1 spkr spkr 77191 May 24 07:41 redis-14.1.0.tgz

[spkr@erdia22 32.redis (spkn02:nginx)]$ tar xvfz redis-14.1.0.tgz
redis/Chart.yaml
(이하 생략) 

향후 히스토리 관리에 용이하도록 디렉토리 이름을 버전이름(14.1.0)으로 지정합니다. 

[spkr@erdia22 32.redis (spkn02:nginx)]$ mv redis redis-14.1.0

[spkr@erdia22 32.redis (spkn02:nginx)]$ cd redis-14.1.0/
[spkr@erdia22 redis-14.1.0 (spkn02:nginx)]$ ls -lrt
total 168
-rw-r--r-- 1 spkr spkr 57138 Apr 23 19:00 values.yaml
-rw-r--r-- 1 spkr spkr  4199 Apr 23 19:00 values.schema.json
-rw-r--r-- 1 spkr spkr 79773 Apr 23 19:00 README.md
-rw-r--r-- 1 spkr spkr   767 Apr 23 19:00 Chart.yaml
-rw-r--r-- 1 spkr spkr   219 Apr 23 19:00 Chart.lock
drwxr-xr-x 5 spkr spkr  4096 May 24 07:43 templates
drwxr-xr-x 2 spkr spkr  4096 May 24 07:43 img
drwxr-xr-x 2 spkr spkr  4096 May 24 07:43 ci
drwxr-xr-x 3 spkr spkr  4096 May 24 07:43 charts

Redis 설치

기본 포함되는 value.yml에 옵션을 설정합니다. 원본 value 파일과 구분을 위하여 신규 my-value.yml을 하나 더 copy 합니다. 

[spkr@erdia22 redis-14.1.0 (spkn02:nginx)]$ cp values.yaml my-values.yml

편의를 위하여 VSCode로 해당 파일(my-values.yml) 수정 합니다. (되도록 vi 사용 안 하시는게 정신 건강에 이롭습니다. )

 개별 환경에 맞게 적절히 수정합니다. 아래는 제가 수정한 내역입니다.

  global.storageClass: openebs-hostpath
  image.pullPolicy: Always
  auth.password: "P@ssw0rd"
  resources:
    requests:
      memory: 1Gi
      cpu: "0.5"
    limits:
      memory: 4Gi
      cpu: "2"

향후 원본 파일과 변경 내역 확인 시 아래와 같이 VSCode Compare Selected 통하여 편리하게 비교합니다. 

 아래와 같이 변경된 내역만 Highlight 됩니다. 

설치 전 Redis Namespace 생성하고 해당 namespace로 변경합니다.

[spkr@erdia22 redis-14.1.0 (spkn02:nginx)]$ k create ns redis
namespace/redis created

k[spkr@erdia22 redis-14.1.0 (spkn02:nginx)]$ kns redis
Context "spkn02" modified.
Active namespace is "redis".

그럼, Helm redis 설치 하겠습니다. 

[spkr@erdia22 redis-14.1.0 (spkn02:redis)]$ helm install redis -f my-values.yml .
NAME: redis
LAST DEPLOYED: Mon May 24 07:56:24 2021
NAMESPACE: redis
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
** Please be patient while the chart is being deployed **

Redis(TM) can be accessed on the following DNS names from within your cluster:

    redis-master.redis.svc.cluster.local for read/write operations (port 6379)
    redis-replicas.redis.svc.cluster.local for read-only operations (port 6379)



To get your password run:

    export REDIS_PASSWORD=$(kubectl get secret --namespace redis redis -o jsonpath="{.data.redis-password}" | base64 --decode)

To connect to your Redis(TM) server:

1. Run a Redis(TM) pod that you can use as a client:

   kubectl run --namespace redis redis-client --restart='Never'  --env REDIS_PASSWORD=$REDIS_PASSWORD  --image docker.io/bitnami/redis:6.2.2-debian-10-r3 --command -- sleep infinity

   Use the following command to attach to the pod:

   kubectl exec --tty -i redis-client \
   --namespace redis -- bash

2. Connect using the Redis(TM) CLI:
   redis-cli -h redis-master -a $REDIS_PASSWORD
   redis-cli -h redis-replicas -a $REDIS_PASSWORD

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

    kubectl port-forward --namespace redis svc/redis-master 6379:6379 &
    redis-cli -h 127.0.0.1 -p 6379 -a $REDIS_PASSWORD

설치 중 에러가 발생하지 않으면 아래와 같이 생성 중인 POD 확인이 가능합니다.

[spkr@erdia22 ~ (spkn02:redis)]$ kgp
NAME               READY   STATUS              RESTARTS   AGE   IP             NODE    NOMINATED NODE   READINESS GATES
redis-master-0     2/2     Running             0          58s   10.233.92.52   node3   <none>           <none>
redis-replicas-0   2/2     Running             0          58s   10.233.90.78   node1   <none>           <none>
redis-replicas-1   0/2     ContainerCreating   0          10s   <none>         node2   <none>           <none>

설치된 리스트는 Helm ls 명령어로 확인 가능합니다. 

[spkr@erdia22 ~ (spkn02:redis)]$ helm ls
NAME    NAMESPACE       REVISION        UPDATED                                 STATUS          CHART           APP VERSION
redis   redis           1               2021-05-24 07:56:24.9468242 +0900 KST   deployed        redis-14.1.0    6.2.2

이제, Redis 설치가 완료 되었습니다. pod, service, statefulset 등이 설치 되었습니다. (Helm에서 설치한 RBAC, Service 등 전체 Object 리스트를 알 수 있으면 좋겠는데, 아쉽게도 저는 찾지 못하였습니다. Helm2에서는 설치 시 리스트가 나왔는데, Helm3에서는 안 나오네요. 문성주 님께서 template 방법을 알려 주셨습니다.) 

[spkr@erdia22 redis-14.1.0 (spkn02:redis)]$ k get all
NAME                   READY   STATUS    RESTARTS   AGE
pod/redis-master-0     2/2     Running   0          10m
pod/redis-replicas-0   2/2     Running   0          10m
pod/redis-replicas-1   2/2     Running   0          9m16s
pod/redis-replicas-2   2/2     Running   0          8m34s

NAME                     TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
service/redis-headless   ClusterIP   None            <none>        6379/TCP   10m
service/redis-master     ClusterIP   10.233.49.120   <none>        6379/TCP   10m
service/redis-metrics    ClusterIP   10.233.4.107    <none>        9121/TCP   10m
service/redis-replicas   ClusterIP   10.233.61.108   <none>        6379/TCP   10m

NAME                              READY   AGE
statefulset.apps/redis-master     1/1     10m
statefulset.apps/redis-replicas   3/3     10m

Helm으로 설치한 전체 Object list를 helm template 명령어로 확인 가능합니다. 너무 많고 길어서 불편하기는 하지만 전체 상세 리스트는 아래와 같이 확인이 가능합니다. 

[spkr@erdia22 diamanti-k8s-bootcamp (spkn02:redis)]$ helm template bitnami/redis |more
---
# Source: redis/templates/serviceaccount.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: RELEASE-NAME-redis
  namespace: "redis"
  labels:
    app.kubernetes.io/name: redis
    helm.sh/chart: redis-14.2.0
    app.kubernetes.io/instance: RELEASE-NAME
    app.kubernetes.io/managed-by: Helm
---
# Source: redis/templates/secret.yaml
apiVersion: v1
kind: Secret
metadata:
(이하 생략)

Helm 변수 업데이트

실 운영 중 변수 설정을 변경해야 하는 경우가 있습니다. my-values.yml 파일에서 해당 변수를 수정 후  Helm upgrade를 실행 합니다. 

 

예를 들어 보안 상의 이유로 redis port 를 변경하는 경우 아래와 같이 수정 합니다.

master.containerPort: 16379
replica.containerPort: 16379
service.containerPort: 16379

Helm에 적용하기 위해서는 기존 Helm chart를 삭제하는 것이 아니고(제가 한 1년 이렇게 했던 것 같습니다. ㅎㅎ) upgrade 명령어로 가능합니다.

[spkr@erdia22 redis-14.1.0 (spkn02:redis)]$ helm  upgrade redis -f my-values.yml .
Release "redis" has been upgraded. Happy Helming!
(생략)

기존 pod가 순서대로 삭제(rolling update)되고 신규 pod가 차례로 생성됩니다.

[spkr@erdia22 redis-14.1.0 (spkn02:redis)]$ kgp
NAME               READY   STATUS    RESTARTS   AGE   IP             NODE    NOMINATED NODE   READINESS GATES
redis-master-0     1/2     Running   0          14s   10.233.92.56   node3   <none>           <none>
redis-replicas-0   2/2     Running   0          20m   10.233.90.78   node1   <none>           <none>
redis-replicas-1   1/2     Running   0          19m   10.233.96.66   node2   <none>           <none>
redis-replicas-2   1/2     Running   0          14s   10.233.92.55   node3   <none>           <none>

작업이 완료되면 새로운 pod가 정상적으로 실행 됩니다.

[spkr@erdia22 redis-14.1.0 (spkn02:redis)]$ kgp
NAME               READY   STATUS    RESTARTS   AGE     IP             NODE    NOMINATED NODE   READINESS GATES
redis-master-0     2/2     Running   0          2m44s   10.233.92.57   node3   <none>           <none>
redis-replicas-0   2/2     Running   0          3m8s    10.233.90.79   node1   <none>           <none>
redis-replicas-1   2/2     Running   0          2m56s   10.233.96.67   node2   <none>           <none>
redis-replicas-2   2/2     Running   0          2m20s   10.233.92.58   node3   <none>           <none>

Helm 변수 설정

그럼, values.yml 파일 변수가 실제 YAML 파일에 어떻게 적용되는지 확인해 보겠습니다.

먼저, my-values.yml 파일의 master.containerPort: 변수를 6379 to 16379 변경합니다.

해당 변수는 Redis  Helm 차트 파일의 redis-14.10.0.templates.master.statefulset.yaml 파일에 적용됩니다. statefulset.yaml 파일을 열어서 확인해 보겠습니다. 

파일에서 master.containerPort 로 검색하시면 아래와 같이 해당 변수가 YAML 어떤 부문에 적용되는지 확인 가능합니다. 

위 부문이 실제 YAML 파일 생성 시 적용되는 부문 입니다. 위와 같이 my-values.yml 파일 내 각 변수가 개별 object yaml(service.yml, psp.yml 등) 파일에 적용됩니다.  

 

추가로 resources 변수 사례를 확인해 보겠습니다. 

statefulset.yml 파일에서 resources 변수 이름으로 검색하시면 아래와 같이 해당 내역 확인 가능합니다.

resources 아래 변수 내역이 전체 줄 변경 + 들여쓰기(indent) 되어 저장됩니다. 

 

실제 YAML 파일에서 확인해 보겠습니다.

[spkr@erdia22 redis-14.1.0 (spkn02:redis)]$ k get sts redis-master -o yaml | k neat
(이하 생략)
        resources:
          limits:
            cpu: "2"
            memory: 4Gi
          requests:
            cpu: 500m
            memory: 1Gi

위와 같이 정상적으로 적용됩니다. 다른 모든 변수 파일도 동일 형식 입니다.

 

Helm 삭제 

그럼, 마지막으로 Helm Chart 삭제해 보겠습니다. 삭제는 delete 명령어로 쉽게 가능합니다.  

[spkr@erdia22 ~ (spkn02:redis)]$ helm delete redis
release "redis" uninstalled

이상 간단하게 Helm에 대하여 알아 보았습니다. Helm은 정말 유용하게 많이 사용하고 있으니 꼭 알아 두셔야 합니다. (Kube 전체 어플리케이션은 Helm으로 관리합니다.)

 

반응형