Helm은 간단히 말하면 쿠버네티스 리소스를 패키지로 관리하는 툴이다. Helm을 사용하면 쿠버네티스 리소스를 배포하고 버저닝 할 수 있다. 예를 들어, 새로운 버전의 도커이미지로 쿠버네티스의 deployment를 새로 배포한다고 할 때 deployment 관련 매니페스트에 별도의 코드 변경을 가하지 않고 Helm을 이용하여 새로운 버전의 deployment를 배포할 수 있으며, 리비전도 남기기 때문에 필요 시 롤백도 할 수 있다.
Helm을 사용하기 전에 아래 3가지 개념에 대해 먼저 알아야 한다. (더 자세한 내용은 여기 참고.)
1. 차트(chart)
차트는 쿠버네티스 리소스 집합을 나타내는 파일들을 패키지로 묶은 단위다. 차트는 파드(pod)로만 구성되어 있을 수도 있고 service, configmap 등의 복잡한 오브젝트들로 구성되어 있을 수도 있다.
2. 리퍼지토리(repository)
차트를 저장하고 관리하는 곳으로, Helm이 동작하는 서버의 디스크가 될 수도 있고 AWS의 S3 버킷이 될 수도 있다. 여러 사람들이 같은 템플릿을 관리한다면 리퍼지토리가 필요하다.
3. 릴리즈(release)
쿠버네티스 클러스터에서 차트가 실행된 상태의 단위다. 같은 클러스터에 있는 1개의 차트에서 여러 개의 릴리즈를 생성할 수 있다.
2. Helm 설치하기
리눅스 서버에 Helm을 설치하고 실행해보자. 리눅스 버전은 Ubuntu 18.04 이다.
Helm의 깃헙 리퍼지토리에서 바이너리 파일 Linux amd64를 다운로드 한다. v.3.x.x 부터는 Helm을 초기화할 때 사용하는 helm init 명령어를 지원하지 않으므로 2.16.6버전으로 설치했다.
$ wget https://get.helm.sh/helm-v2.16.6-linux-amd64.tar.gz
$ tar -xzvf helm-v2.16.6-linux-amd64.tar.gz
$ ls
helm-v2.16.6-linux-amd64.tar.gz linux-amd64
$ sudo mv linux-amd64/helm /usr/local/bin/helm
$ helm
The Kubernetes package manager
To begin working with Helm, run the 'helm init' command:
$ helm init
This will install Tiller to your running Kubernetes cluster.
It will also set up any necessary local configuration.
...
3. Tiller를 위한 role & service account 생성하기
Tiller는 쿠버네티스 클러스터 내부에 설치되어 Helm 클라이언트와 통신하는 API 서버라고 보면 된다. Tiller가 차트를 가지고 쿠버네티스 클러스터에 deployment, service와 같은 리소스를 생성/삭제하려면 그와 관련된 권한이 필요하다. Tiller가 권한을 가지려면
Role 오브젝트를 생성한다.
Role을 부여할 ServiceAccount를 생성한다.
생성한 Role과 ServiceAccount를 RoleBinding 오브젝트를 통해 연결한다.
Helm을 초기화할 때 ServiceAccount를 넘겨준다.
쿠버네티스에서 권한은 롤과 클러스터 롤로 구분한다.
role
특정 네임스페이스에 속하는 오브젝트들에 대한 권한을 정의할 때 사용한다.
cluster role
클러스터 단위의 권한을 정의할 때 사용한다. 네임스페이스에 속하지 않는 오브젝트들에 대한 권한 뿐만 아니라 클러스터 전반에 걸친 기능에 대한 권한이 필요할 때 클러스터 롤을 부여한다.
클러스터 롤은 쿠버네티스 컴포넌트가 사용하는 권한도 포함되기 때문에 꽤 많은 수의 클러스터 롤이 미리 생성되어 있다. 쿠버네티스에서 관리자 권한으로 모든 기능을 사용할 수 있는 cluster-admin이라는 롤이 그 예다. cluster-admin 을 helm-chart-account라는 서비스 어카운트에 부여해보자.
account.yaml이라는 매니페스트를 생성했다.
apiVersion:v1kind:ServiceAccountmetadata:name:helm-chart-accountnamespace:kube-system---apiVersion:rbac.authorization.k8s.io/v1kind:ClusterRoleBindingmetadata:name:cluster-rolebindingsubjects:# 권한을 부여할 대상은 ServiceAccount 이다. - kind:ServiceAccount# helm-chart-account 라는 이름의 서비스 어카운트에 권한을 부여한다.name:helm-chart-accountnamespace:kube-systemroleRef:apiGroup:rbac.authorization.k8s.io# cluster-admin 이라는 이름의 클러스터 롤을 대상에게 부여한다.kind:ClusterRolename:cluster-admin
위 매니페스트를 적용한다.
$ kubectl apply -f account.yaml
serviceaccount/helm-chart-account created
clusterrolebinding.rbac.authorization.k8s.io/cluster-rolebinding created
생성한 서비스 어카운트로 service 오브젝트를 조회해보자. --as 옵션은 쿠버네티스 명령어를 실행할 때 어떤 인증방식과 식별을 사용할 것인지 지정한다. helm-chart-account 라는 서비스 어카운트가 kube-system 네임스페이스에서 소속되었으므로 system:serviceaccount:kube-system:helm-chart-account 라는 값을 넘겨줬다.
$ kubectl get svc --as system:serviceaccount:kube-system:helm-chart-account
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 7d8h
service-app NodePort 10.104.73.103 <none> 8080:30080/TCP 3h48m
Helm을 초기화한다.
$ helm init --service-account helm-chart-account
4. 차트 생성하고 템플릿 바인딩하기
차트를 생성할 때는 아래의 명령어를 실행한다.
$ helm create chart <차트 이름>
my-helm-chart 라는 이름의 차트를 생성하면 아래와 같은 구조의 디렉토리와 파일이 생성된다.
my-helm-chart
Chart.yaml # A YAML file containing information about the chart
LICENSE # OPTIONAL: A plain text file containing the license for the chart
README.md # OPTIONAL: A human-readable README file
values.yaml # The default configuration values for this chart
values.schema.json # OPTIONAL: A JSON Schema for imposing a structure on the values.yaml file
charts/ # A directory containing any charts upon which this chart depends.
crds/ # Custom Resource Definitions
templates/ # A directory of templates that, when combined with values,
# will generate valid Kubernetes manifest files.
templates/NOTES.txt # OPTIONAL: A plain text file containing short usage notes
file
usage
Chart.yaml
차트에 대한 기본적인 정보를 기재한다. (작성자, 차트 이름, 버전 등)
values.yaml
클러스터의 리소스 관련 config, 템플릿에 들어갈 동적인 값 등을 기재한다.
templates
values.yaml에 정의된 속성들을 바인딩 할 템플릿들의 디렉토리.
한가지 예시를 들어보겠다. flask-gunicorn:0.0.1이라는 도커이미지로 deployment를 생성하는 매니페스트 deployment.yaml이 있다고 하자.
플라스크 애플리케이션 서버 코드에 변경이 있어서 도커이미지에 0.0.2라는 새로운 버전이 생겼다면 매니페스트의 template.spec.containers.image를 kde6260/flask-gunicorn:0.0.2로 직접 고쳐야 한다. 하지만 Helm을 사용하면 직접 고치지 않아도 된다.
values.yaml에 아래 내용을 추가했다.
deployment:flaskGunicorn:# use --set option when deploying new version of imageimage:kde6260/flask-gunicorn:0.0.1
values.yaml에 정의된 속성을 템플릿에 바인딩할 때는 {{ .Values.< 속성 이름> }}과 같은 형식을 사용한다.
Helm의 values.yaml에 있는 속성을 위처럼 템플릿에 바인딩 시킨 뒤 (이미지 이름을 고정시키지 않고 동적으로 바인딩하므로 앞으로 템플릿이라고 하겠다.)helm upgrade ... --set deployment.flaskGunicorn.image=kde6260/flask-gunicorn:0.0.2 를 실행하면 파일에 코드를 직접 수정하지 않고 deployment를 배포할 수 있다. (helm upgrade ... --set=... 에 대해서는 뒤에서 다룬다.)
단, deployment.yaml은 $ helm create chart my-helm-chart를 통해 생성된 my-helm-chart/templates 디렉토리에 있어야 한다.
이제 생성한 차트를 리퍼지토리에 등록해보자.
5. chartmuseum으로 리퍼지토리 생성하기
Helm은 기본적으로 리퍼지토리 2개를 가지고 있다. 모든 리퍼지토리를 조회하려면 아래의 명령어를 실행한다.
$ helm repo list
NAME URL
stable https://kubernetes-charts.storage.googleapis.com
local http://127.0.0.1:8879/charts
팀원들과 차트를 공유하고 관리하려면 원격에 위치한 리퍼지토리가 필요할 것이다. chartmuseum은 원격으로 공유가능한 리퍼지토리를 생성하고 차트를 생성/수정/삭제하는 API를 제공한다.