Helm : The Kubernetes Package Manager

2018, Apr 13    

by 김대성(daeseong.kim@sk.com)

Update on 2019.07.30 새로운 블로그로 이전하였습니다

Intro

SK텔레콤의 클라우드 인프라 플랫폼 TACO는 지난 첫 포스트에서도 소개했지만 매우 다양한 오픈소스들로 이루어져 있습니다.

물론 그냥 가져다가 사용하는 것이 아니라 코드 기여 및 지속적인 미팅을 통해서 오픈소스 기술들을 내재화하고 있습니다.

이번 포스팅에서는 그 helm이라는 도구에 대해서 자세히 이야기해 보도록 하겠습니다.

helm은 kubernetes cluster에 어플리케이션을 배포하는 도구입니다. 그리고 TACO는 Openstack을 kubernetes위에 container 형태로 배포하기 위해서 openstack-helm 프로젝트를 사용하고 있는데 이 프로젝트가 Openstack의 배포를 위해서 사용하는 도구가 바로 helm입니다.

Helm 이란?

helm은 deis라는 회사에서 시작한 Helm Classic 프로젝트와 Google에서 진행되던 GCS Deployment Manager 프로젝트가 합해진 프로젝트입니다.

Helm Classic은 kubernetes에 어플리케이션을 올리고 관리하는 도구이고 GCS Deployment Manager는 kubernetes의 어머니격인 Google Cloud에 어플리케이션을 배포하고 관리하는 도구라서 서로의 목적이 같기 때문에 합해질 수 있었던 것 같습니다. 그렇게 deis와 google의 협업으로 진행되던 helm 프로젝트는 CNCF의 한 프로젝트로 완전히 오픈소스화가 되었습니다.

helm은 chart라는 개념으로 어플리케이션을 정의하고 관리합니다. 그리고 이를 이용해서 어플리케이션을 kubernetes 위에 배포하고 이렇게 배포된 어플리케이션을 관리합니다.

chart란 kubernetes에 올라갈 어플리케이션이 어떤 kubernetes 객체들로 구성되어 있는지, 어떤 설정값들을 사용하는지에 대한 정의가 담긴 정보의 집합이라 할 수 있습니다. 이번 포스팅에서는 helm 뿐만 아니라 chart의 구조에 대해서도 자세히 이야기해 볼 예정입니다.

Project Links

Helm 구조

helm은 client-server 구조로 설계되어 있습니다. 사용자를 위한 CLI인 client를 helm client라 부르고 server는 tiller라고 부릅니다. tiller는 보통kubernetes위에 pod으로 배포됩니다.

그리고 어플리케이션을 구성할 kubernetes 객체를 정의하는 manifest template 파일 및 설정 묶음을 chart라고 부릅니다. helm client를 통해서 chart를 kubernetes 위에 배포하면 배포된 어플리케이션을 release라고 부릅니다.

helm아키텍쳐 License: CC BY-NC-ND 4.0

아래 용어는 helm에서 가장 중요한 컨셉을 정의하는 용어들입니다.

  • helm client : 사용자를 위한 CLI client
  • tiller : helm server. 보통 kubernetes위에 pod 형태로 위치함
  • chart : 어플리케이션을 구성하는 kubernetes 객체 정의 및 설정 묶음
  • release : kubernetes 위에 배포된 어플리케이션

helm client는 gRPC 프로토콜을 이용해서 tiller와 통신합니다. 사용자가 chart를 배포하기 위해 helm install 명령어를 사용하면 helm client는 chart를 tiller에게 보냅니다. tiller는 받은 chart를 rendering해서 kubernetes 객체 정보를 정의하는 manifest 파일을 만듭니다. 그리고 이 manifest 파일을 kubernetes api를 통해서 kubernetes 위에 배포합니다.

또한 helm client는 local 혹은 원격에 존재하는 chart repository들을 관리합니다. helm을 설치하면 기본적으로 stable repository가 제공되고 여기엔 쉽게 배포해 볼 수 있는 다양한 어플리케이션들이 준비되어 있습니다.

root@taco-aio:~# helm search
NAME                                 	CHART VERSION	APP VERSION                 	DESCRIPTION                                       
stable/acs-engine-autoscaler         	2.1.4        	2.1.1                       	Scales worker nodes within agent pools            
stable/aerospike                     	0.1.7        	v3.14.1.2                   	A helm chart for Aerospike in Kubernetes          
stable/anchore-engine                	0.1.5        	0.1.9                       	Anchore container analysis and policy evaluatio...
stable/artifactory                   	7.1.0        	5.9.1                       	Universal Repository Manager supporting all maj...
stable/artifactory-ha                	0.1.5        	5.9.1                       	Universal Repository Manager supporting all maj...
stable/aws-cluster-autoscaler        	0.3.3        	                            	Scales worker nodes within autoscaling groups.    
stable/bitcoind                      	0.1.3        	0.15.1                      	Bitcoin is an innovative payment network and a ...
stable/buildkite                     	0.2.2        	3                           	Agent for Buildkite                               
stable/burrow                        	0.4.3        	0.17.1                      	Burrow is a permissionable smart contract machine 
stable/centrifugo                    	2.0.1        	1.7.3                       	Centrifugo is a real-time messaging server.       
stable/cert-manager                  	0.2.8        	0.2.4                       	A helm chart for cert-manager                     
stable/chaoskube                     	0.7.0        	0.8.0                       	Chaoskube periodically kills random pods in you...
stable/chartmuseum                   	1.2.0        	0.5.1                       	helm Chart Repository with support for Amazon S...
stable/chronograf                    	0.4.3        	1.3                         	Open-source web application written in Go and R...
stable/cluster-autoscaler            	0.5.3        	1.1.0                       	Scales worker nodes within autoscaling groups.    
stable/cockroachdb                   	1.0.4        	2.0.0                       	CockroachDB is a scalable, survivable, strongly...
stable/concourse                     	1.2.3        	3.10.0                      	Concourse is a simple and scalable CI system.     
stable/consul                        	1.3.5        	1.0.0                       	Highly available and distributed service discov...
stable/coredns                       	0.9.0        	1.0.6                       	CoreDNS is a DNS server that chains plugins and...
stable/coscale                       	0.2.1        	3.9.1                       	CoScale Agent                                     
stable/dask                          	1.0.2        	0.17.1                      	Distributed computation in Python with task sch...
stable/dask-distributed              	2.0.2        	                            	DEPRECATED: Distributed computation in Python     
stable/datadog                       	0.11.2       	6.1.2                       	DataDog Agent                                     
stable/dex                           	0.1.0        	2.10.0                      	CoreOS Dex                                        
stable/docker-registry               	1.1.1        	2.6.2                       	A helm chart for Docker Registry                  
stable/dokuwiki                      	1.0.1        	0.20170219.201708232029     	DokuWiki is a standards-compliant, simple to us...
stable/drupal                        	0.11.15      	8.5.1                       	One of the most versatile open source content m...
stable/elastalert                    	0.1.3        	0.1.29                      	ElastAlert is a simple framework for alerting o...
stable/elasticsearch-exporter        	0.1.3        	1.0.2                       	Elasticsearch stats exporter for Prometheus       
stable/etcd-operator                 	0.7.5        	0.7.0                       	CoreOS etcd-operator helm chart for Kubernetes    
stable/ethereum                      	0.1.1        	v1.7.3                      	private Ethereum network helm chart for Kubernetes
stable/external-dns                  	0.5.4        	0.4.8                       	Configure external DNS servers (AWS Route53, Go...
stable/factorio                      	0.3.1        	0.14.22                     	Factorio dedicated server.                        
stable/filebeat                      	0.2.0        	6.2.3                       	A helm chart to collect Kubernetes logs with fi...
stable/fluent-bit                    	0.4.0        	0.12.15                     	Fast and Lightweight Log/Data Forwarder for Lin...
...

Installing Helm

helm을 직접 사용해보려면 일단 kubernetes가 설치된 환경이 있어야 합니다. 그리고 그 위에 helm을 설치해야 합니다.

CentOS, Ubuntu 또는 Redhat OS가 설치된 환경이 이미 있다면 taco-scripts를 통해서 쉽게 kubernetes 및 helm을 설치할 수 있습니다.

참고링크 : https://github.com/sktelecom-oslab/taco-scripts

위의 링크에서 020-install-k8s.sh 까지 스크립트를 진행하면 kubernetes 및 helm이 설치되는 것을 볼 수 있습니다.

020-install-k8s.sh 스크립트 중 아래 라인이 helm을 설치하는 부분입니다.

curl https://raw.githubusercontent.com/kubernetes/helm/master/scripts/get | cat > /tmp/helm_script.sh \
&& chmod 755 /tmp/helm_script.sh && /tmp/helm_script.sh --version v2.8.2

helm init --upgrade

helm 프로젝트는 helm을 쉽게 설치할 수 있는 스크립트를 github에 이미 제공하고 있고 위의 taco-script 코드는 이를 curl로 다운받아서 version을 명시 후 설치해주는 코드입니다.

helm은 아래와 같이 client와 server를 설치합니다.

  1. helm client를 local에 설치
  2. tiller server를 kubernetes cluster 위에 설치

그리고 helm init 명령어는 위의 2번에 해당하는 tiller를 설치하는 명령어입니다. –upgrade 옵션은 이미 tiller가 설치되어 있다면 버젼을 체크해서 상위 버젼으로 upgrade를 하는 옵션입니다.

helm init 명령어가 어떤 형식의 manifest 파일을 만들어서 tiller를 kubernetes cluster 위에 베포하는지 보고 싶다면 helm init --output yaml 또는 helm init --output json 같은 명령어를 통해 확인해 볼 수 있습니다.

root@taco-aio:~# helm init --output yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: helm
    name: tiller
  name: tiller-deploy
  namespace: kube-system
spec:
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: helm
        name: tiller
    spec:
      containers:
      - env:
        - name: TILLER_NAMESPACE
          value: kube-system
        - name: TILLER_HISTORY_MAX
          value: "0"
        image: gcr.io/kubernetes-helm/tiller:v2.8.2
        imagePullPolicy: IfNotPresent
        livenessProbe:
          httpGet:
            path: /liveness
            port: 44135
          initialDelaySeconds: 1
          timeoutSeconds: 1
        name: tiller
        ports:
        - containerPort: 44134
          name: tiller
        - containerPort: 44135
          name: http
        readinessProbe:
          httpGet:
            path: /readiness
            port: 44135
          initialDelaySeconds: 1
          timeoutSeconds: 1
        resources: {}
status: {}

Using Helm

helm client가 동작하려면 tiller와 통신할 수 있어야 합니다. helm client는 kubernetes proxy 기능을 통해서 tiller와 통신하는데 그러기 위해서는 kubernetes config파일의 위치를 알고 있어야 합니다. helm client는 kubectl과 마찬가지로 아래 위치에서 config파일을 찾습니다.

$HOME/.kube/config

v2.8.2 기준으로 helm은 아래와 같은 기능들을 제공합니다.

Usage:
  helm [command]

Available Commands:
  completion  Generate autocompletions script for the specified shell (bash or zsh)
  create      create a new chart with the given name
  delete      given a release name, delete the release from Kubernetes
  dependency  manage a chart\'s dependencies
  fetch       download a chart from a repository and (optionally) unpack it in local directory
  get         download a named release
  history     fetch release history
  home        displays the location of HELM_HOME
  init        initialize helm on both client and server
  inspect     inspect a chart
  install     install a chart archive
  lint        examines a chart for possible issues
  list        list releases
  package     package a chart directory into a chart archive
  plugin      add, list, or remove helm plugins
  repo        add, list, remove, update, and index chart repositories
  reset       uninstalls Tiller from a cluster
  rollback    roll back a release to a previous revision
  search      search for a keyword in charts
  serve       start a local http web server
  status      displays the status of the named release
  template    locally render templates
  test        test a release
  upgrade     upgrade a release
  verify      verify that a chart at the given path has been signed and is valid
  version     print the client/server version information

그 중 몇몇 중요한 명령어를 확인해 보겠습니다.

helm init

helm client를 통해서 tiller를 설치하는 명령어 입니다. –upgrade 옵션을 통해서 이미 설치된 tiller의 버젼을 올리는 것도 가능합니다.

helm repo

chart repository 목록을 등록하고 조회하고 삭제할 수 있습니다.

helm repo list : 조회
helm repo add localhost http://localhost:8879/charts : localhost라는 이름의 chart repository 등록
helm repo remove localhost : localhost라는 이름의 chart repository 삭제

위의 helm repo add 명령어로 localhost repository를 등록하고 싶다면 먼저 localhost 에 helm serve 명령을 통해서 local chart repository service가 실행되고 있어야 합니다.

helm serve

helm repository sevice process를 실행합니다.

helm serve . &

helm repo list에 보이는 repository에 등록되어 있는 chart를 조회할 수  있습니다. helm 설치 직후엔 stable 이라는 기본 repository가 제공되는 것을 확인 할 수 있습니다.

helm install

chart repository에 등록된 chart를 이용해서 kubernetes cluster에 어플리케이션을 배포하는 명령어입니다. 아래 명령어는 helm install 명령어를 통해서 stable repository에 등록된 mariadb를 kubernetes위에 배포하는 예제입니다.

helm install --name mariadb-test --set persistence.enabled=false \
  --set mariadbRootPassword=password,mariadbUser=taco,mariadbPassword=password,mariadbDatabase=database \
    stable/mariadb

chart를 실제로 배포하지 않고 tiller rendering 결과만 보고 싶다면 helm install --debug --dry-run 옵션을 사용하면 됩니다.

helm lint

chart의 문법을 체크하는 명령어 입니다. chart 개발시에 자주 사용하는 명령어로 chart 내에 존재하는 yaml들의 indent 및 문법이 잘못되어 있거나 kubernetes 객체를 정의하는 template 언어의 문법이 잘못되어 있는 것을 미리 체크해 볼 수 있습니다. 아래 예는 stable/drupal chart를 받아서 deployment.yaml 파일의 코드를 임의로 삭제하고 helm lint를 한 결과입니다.

root@taco-aio:~/tmp/drupal# helm lint
==> Linting .
[ERROR] templates/: parse error in "drupal/templates/deployment.yaml": template: drupal/templates/deployment.yaml:26: unexpected 

Error: 1 chart(s) linted, 1 chart(s) failed

helm list

배포된 release 목록을 조회하는 명령어입니다.

root@taco-aio:~# helm list
NAME            REVISION        UPDATED                         STATUS          CHART           NAMESPACE
my-release      1               Mon Apr 16 05:23:09 2018        DEPLOYED        drupal-0.11.15  default  

helm history

배포된 release의 배포 이력을 조회하는 명령어입니다.

root@taco-aio:~# helm history my-release
REVISION        UPDATED                         STATUS          CHART           DESCRIPTION     
1               Mon Apr 16 05:23:09 2018        DEPLOYED        drupal-0.11.15  Install complete

helm fetch

repository에 등록된 chart를 tar ball형태로 다운받을 수 있는 명령어 입니다. 다운 받은 tarball의 압축을 풀면 chart의 구성을 확인해 볼 수 있습니다.

root@taco-aio:~/taco# helm fetch stable/mariadb
root@taco-aio:~/taco# ls
mariadb-3.0.3.tgz
root@taco-aio:~/taco# tar zxvf mariadb-3.0.3.tgz 
mariadb/Chart.yaml
mariadb/values.yaml
mariadb/templates/NOTES.txt
mariadb/templates/_helpers.tpl
mariadb/templates/configmap.yaml
mariadb/templates/deployment.yaml
mariadb/templates/pvc.yaml
mariadb/templates/secrets.yaml
mariadb/templates/svc.yaml
mariadb/templates/test-runner.yaml
mariadb/templates/tests.yaml
mariadb/.helmignore
mariadb/OWNERS
mariadb/README.md

helm get

배포된 release의 kunernetes 객체 정보(manifest)를 조회하는 명령어입니다.

helm status

배포된 release의 kubernetes 객체 상태를 조회하는 명령어입니다.

helm delete

배포된 release는 helm delete 명령어를 통해 삭제할 수 있습니다. 완전히 삭제하려면 –purge 옵션을 사용해야 합니다.

helm test

어플리케이션이 잘 배포되었는지 검증하기 위해 테스트를 하는 명령어입니다. helm test 명령어를 사용하려면 테스트를 실행할 kubernetes 객체가 chart에 이미 구현되어 있어야 합니다. 해당 kubernetes 객체가 test를 위한 객체라고 template에 아래와 같이 annotation을 선언해야 합니다.

metadata:
  annotations:
    "helm.sh/hook": test-success

Chart

helm은 chart라고 부르는 패키지 포멧을 사용해서 어플리케이션을 배포합니다. chart란 kubernetes의 객체들을 정의하는 파일들과 그 설정값들의 집합입니다. 지금부터는 chart의 구조를 자세히 살펴보고 chart를 구성하는 각 파일들의 내용을 알아보도록 하겠습니다.

Chart 구조

chart는 어플리케이션 이름인 디렉토리 아래에 다양한 파일들로 구성되어 있습니다. 즉, wordpress 어플리케이션을 배포하는 chart의 디렉토리 이름은 wordpress입니다.

아래는 wordpress 라는 chart의 구조를 보여줍니다.

wordpress/
  Chart.yaml          # Chart에 대한 정보를 적어놓는 YAML 파일 (필수)
  LICENSE             # 라이센스에 대한 내용을 적어 놓는 텍스트 파일 (옵션)
  README.md           # 사용자가 읽을 수 있는 README 파일 (옵션)
  requirements.yaml   # Chart간 의존성이 있을 경우 이를 리스트 형태로 정의하는 파일 (옵션)
  values.yaml         # Chart 내에서 어플리케이션에 필요한 설정값들이 모여 있는 파일 (필수)
  charts/             # Chart가 다른 Chart에 의존성이 있을 경우 다른 의존하는 Chart들이 위치하는 디렉토리 (옵션)
  templates/          # kubernetes 객체를 정의하는 manifest template 파일들이 위치하는 디렉토리 (필수)
                      # gotpl로 구현된 template들이어야 하며 values.yaml의 값들과 합해져서 manifest 파일을 rendering함
  templates/NOTES.txt # chart 사용 방법을 설명해 놓은 텍스트 파일 (옵션)

chart는 반드시 위의 파일 및 디렉토리 이름들로 구성되어야 하며 다른 파일 및 디렉토리 이름들은 무시됩니다. 또한 해당 chart가 의존성이 없으면 charts 디렉토리가 필요 없습니다.

Chart.yaml

Chart.yaml 파일은 명세서 역할을 하는 파일입니다. 그 내용은 아래와 같습니다.

name: Chart 이름 (필수)
version: SemVer 2 형식으로 정의된 Chart 버젼 (필수)
description: 한줄 설명 (옵션)
keywords:
  - 키워드 리스트. Chart 검색 시 이 키워드로 검색된다. (옵션)
home: 프로젝트 홈페이지 주소 (옵션)
sources:
  - 공개된 프로젝트 소스 코드 주소 (옵션)
maintainers: # (옵션)
  - name: 개발/관리자 이름 (각 개발/관리자 별 필수)
    email: 개발/관리자 이메일 주소 (각 개발/관리자 별 옵션)
    url: 개발/관리자 홈페이지 (각 개발/관리자 별 옵션)
engine: gotpl # template 엔진 이름 정의 (옵션, 기본값은 gotpl)
icon: 아이콘 이미지를 사용할 경우 이미지 파일의 주소 (옵션).
appVersion: 해당 Chart가 배포할 어플리케이션의 버젼 정보 (옵션).
deprecated: 해 Chart의 deprecated 유무 (옵션, boolean값임)
tillerVersion: 해당 Chart를 지원하는 tiller 버젼의 범위를 지정함. 예를 들어 ">2.0.0" (옵션)

만약에 chart 디렉토리 이름이 wordpress이고 Charts.yaml파일의 version에 1.2.0로 정의되어 있다면 helm package 명령어로 패키지를 만들면 wordpress-1.2.0.tgz 로 패키지가 만들어집니다.

Dependency

chart가 다른 chart들과 의존 관계가 있는 경우 requirements.yaml 파일에는 다른 chart에 대한 의존 관계를 정의할 수 있습니다. requirements.yaml파일에 의존 관계를 가지는 다른 chart들을 정의해 놓고 helm dependency update(helm dep up) 명령어를 사용하면 helm은 requirements.yaml 파일을 읽어서 파일에 정의된 chart들을 charts/ 디렉토리 안에 넣습니다. 사용자가 직접 의존하는 패키지들을 charts/ 디렉토리 안에 넣어둘 수 도 있습니다.

예를 들어 apache와 mysql chart에 의존성이 있는 어플리케이션이라면 아래와 같이 requirements.yaml파일에 정의하면 됩니다.

dependencies:
  - name: apache
    version: 1.2.3
    repository: http://example.com/charts
  - name: mysql
    version: 3.2.1
    repository: http://another.example.com/charts

위의 예에서 name 및 version 항목에는 chart의 이름 및 버젼을 적어야 하고, repository 항목에는 해당 chart가 저장되어 있는 저장소의 주소를 적어야 합니다. 물론 helm repo list 명령어를 통해서 볼 수 있는 repository여야 하고, 등록된 주소가 없다면 helm repo add 명령어로 repository를 등록해 주어야 합니다.

위와 같이 의존성이 정의된 chart에 helm dep up 명령어를 사용하면 아래와 같은 결과를 볼 수 있습니다. (chart 이름은 foochart라고 하겠습니다.)

$ helm dep up foochart
Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "local" chart repository
...Successfully got an update from the "stable" chart repository
...Successfully got an update from the "example" chart repository
...Successfully got an update from the "another" chart repository
Update Complete. Happy helming!
Saving 2 charts
Downloading apache from repo http://example.com/charts
Downloading mysql from repo http://another.example.com/charts

그리고 위와 같이 helm dep up을 사용하고나서 charts/ 디렉토리 아래를 보면 다음과 같은 결과를 볼 수 있습니다.

charts/
  apache-1.2.3.tgz
  mysql-3.2.1.tgz

그렇다면 의존 관계가 정의된 chart를 helm install 명령으로 배포하면 어떤 일이 벌어질까요? chart A와 chart B로 예를 들어 보겠습니다.

chart A의 requirement.yaml 파일엔 chart B가 정의되어 있기 때문에 A는 B에 의존합니다.

chart A는 아래와 같은 kubernetes 객체를 생성합니다.

  • namespace “A-Namespace”
  • statefulset “A-StatefulSet”
  • service “A-Service”

chart B는 아래와 같은 kubernetes 객체를 생성합니다.

  • namespace “B-Namespace”
  • replicaset “B-ReplicaSet”
  • service “B-Service”

그럴 경우 chart A를 배포할 경우 아래과 같은 순서로 kubernetes 객체가 생성됩니다.

  • B-Namespace
  • A-Namespace
  • B-Service
  • A-Service
  • B-ReplicaSet
  • A-StatefulSet

즉, 객체를 생성하는 순서는

  • 두 chart를 하나의 set로 합치고
  • 의존하는 chart의 객체가 먼저 생성되며
  • kubernetes 객체의 순서는 아래 code에 의해서 정렬됩니다.

tiller 객체 sorting code : https://github.com/kubernetes/helm/blob/master/pkg/tiller/kind_sorter.go#L26

Template Files

helm은 kubernetes 객체를 정의하는 template들을 go template language를 통해서 구현합니다. 그리고 몇몇 go template 함수를 추가로 사용하기 위해 Sprig library를 사용합니다. go template 함수 및 사용법은 다음 기회에 포스팅해 보겠습니다.

helm은 모든 template 파일들을 templates/ 디렉토리 아래에 저장합니다. 그리고 template이 tiller에 의해 rendering되는 시점에 values.yaml 파일 안에 들어있는 값들과 합쳐져서 kubernetes 객체를 정의하는 manifest 파일로 완성됩니다.

template 파일은 아래 예제와 같은 형태로 구성되어 있습니다.

apiVersion: v1
kind: ReplicationController
metadata:
  name: deis-database
  namespace: deis
  labels:
    heritage: deis
spec:
  replicas: 1
  selector:
    app: deis-database
  template:
    metadata:
      labels:
        app: deis-database
    spec:
      serviceAccount: deis-database
      containers:
        - name: deis-database
          image: /postgres:
          imagePullPolicy: 
          ports:
            - containerPort: 5432
          env:
            - name: DATABASE_STORAGE
              value: 

위의 예제를 보면 replication controller라는 kubernetes 객체를 생성하기 위한 template 파일임을 알 수 있고 4개의 value를 사용하고 있습니다. 그 template value 값들은 values.yaml 파일에 아래와 같이 명시되어 있다고 추측해 볼 수 있습니다.

  • imageRegistry: docker 이미지 저장소
  • dockerTag: 사용하고자 하는 docker 이미지의 tag
  • pullPolicy: docker 이미지를 download하는 규칙 설정
  • storage: 사용하고자 하는 백앤드 스토리지. values.yaml에 값이 없으면 기본값으로 minio를 사용하겠다는 의미

values.yaml

values.yaml 파일은 chart의 변수값들을 정의할 수 있는 파일입니다. chart내에 미리 정의된 values.yaml파일을 만들어 둘 수도 있고 따로 만들어서 helm install --values 의 파라미터로 넘겨줄 수도 있습니다. 위의 deis-database template 예제의 경우 아래와 같은 myval.yaml 파일을 만들어서 helm install --values=myval.yaml deis-database 명령어로 value 파일을 넘겨줄 수 있습니다.

imageRegistry: "quay.io/deis"
dockerTag: "latest"
pullPolicy: "Always"
storage: "s3"

즉 value를 정의하는 방법은 총 3가지 방법이 존재합니다.

  1. chart 내의 values.yaml 파일에 미리 정의하는 방법
  2. helm install –values 옵션에 values 파일을 만들어서 넘겨주는 방법
  3. helm install –set 옵션으로 value 값을 하나 하나 넘겨주는 방법

이렇게 정의된 value들은 template 안에서 키워드로 접근 할 수 있습니다.

Predefined Values

helm에는 아래와 같은 변수들이 미리 선언되어 있어서 따로 선언하지 않아도 바로 사용할 수 있습니다.

  • Release.Name: 배포된 release의 이름
  • Release.Time: release가 최근 update된 시간
  • Release.Namespace: release가 속한 namespace 이름
  • Release.Service: release를 배포한 서비스명. 우리는 tiller로 배포했으므로 이 값은 Tiller
  • Release.IsUpgrade: 현재 release가 upgrade/rollback 중이면 이 값이 true
  • Release.IsInstall: 현재 release가 install 중이면 이 값이 true
  • Release.Revision: 첫 install시 1로 세팅. upgrade가 수행될때마다 1씩 증가함
  • Chart: Chart.yaml 파일 내용
  • Capabilities: kubernetes 관련 정보를 얻어 올 수 있응 객체. , 등을 확인 할 수 있음

value 값들의 범위

chart가 의존 관계를 가질 경우 각 chart에 정의된 value들 또한 사용 범위가 정의됩니다.

예를 들어 wordpress chart가 mysql, apache chart들을 의존한다면 wordpress chart에선 mysql 및 apache chart의 value 값들을 정의하고 사용할 수 있지만 mysql 및 apache chart는 불가능합니다.

만약에 하위 chart에서 상위 chart의 value 값들을 사용하고 싶다면 상위 chart의 values.yaml에 global로 선언하면 됩니다.

global:
  app: MyWordPress

위와 같이 wordpress chart의 values.yaml에 선언한다면 mysql, apache chart에서도 app값을 사용할 수 있습니다.

Hooks

helm은 chart가 install/upgrade/rollback/delete되는 생명주기의 중간에 개입할 수 있는 기능을 제공하고 이를 hook이라고 부릅니다.

hook을 사용하면 다음 예와 같은 구현이 가능해 집니다.

  • chart install 시 먼저 configMap이나 Secret을 로드
  • database를 upgrade하기 전에 자동으로 database를 backup하는 job 실행
  • release 삭제 시 삭제 작업 전에 사전 작업을 job으로 정의

hook은 일반적인 kubernetes 객체를 정의하는 template과 같은 형태로 구현되며 template에 hook임을 선언하는 annotation을 정의하면 선언된 hook의 종류에 따라 그 시점에 동작합니다. 즉, 어떤 kubernetes 객체도 hook으로 활용될 수 있지만 많은 경우 Job 객체가 hook으로 사용됩니다.

Hook의 종류

  • pre-install: template이 tiller에 의해 rendering된 직후지만 아직 kubernetes에 객체를 생성하기 전에 실행
  • post-install: 모든 객체가 kubernetes 위에 배포된 후 실행
  • pre-delete: delete 요청이 들어왔지만 tiller가 kubernetes에 delete요청을 전달하기 전에 실행
  • post-delete: kubernetes상의 모든 객체가 삭제된 이후에 실행
  • pre-upgrade: upgrade 요청 후 tiller가 template을 rendering은 했지만 아직 kubernetes에 요청하기 전에 실행
  • post-upgrade: 모든 자원의 upgrade가 끝난 후 실행
  • pre-rollback: rollback 요청 후 tiller가 template을 rendering은 했지만 아직 kubernetes에 요청하기 전에 실행
  • post-rollback: 모든 자원의 rollbacl이 끝난 후 실행

Hook과 Release의 생명주기

그럼 hook이 chart가 배포되는 생명주기에 어떻게 관여하여 동작하는지 helm install 명령의 예로 확인해 보도록 하겠습니다.

  1. 사용자가 helm install foo 명령을 실행합니다.
  2. chart가 tiller에게 전달됩니다.
  3. tiller가 chart를 검증한 후, template을 rendering을 해서 kubernetes manifest를 생성합니다.
  4. tiller가 어플리케이션을 구성하는 manifest들을 kubernetes에 전달합니다.
  5. tiller가 release 이름을 비롯한 정보들은 client에 반환합니다.
  6. client가 실행을 종료합니다.

위의 install 생명주기에서 helm은 pre-install과 post-install hook을 제공합니다. 만약에 사용자가 두가지 hook을 모두 선언하면 아래와 같은 과정이 추가됩니다.

  1. 사용자가 helm install foo 명령을 실행합니다.
  2. chart가 tiller에게 전달됩니다.
  3. tiller가 chart를 검증한 후, template을 rendering을 해서 kubernetes manifest를 생성합니다.
  4. tiller는 pre-install hook을 가중치와 이름으로 asc 정렬해서 합니다.
  5. 그리고 tiller는 hook으로 정의된 객체를 kubernetes에 전달합니다.
  6. tiller는 hook들이 “Ready” 상태가 될때까지 기다립니다.
  7. tiller가 어플리케이션을 구성하는 manifest들을 kubernetes에 전달합니다.
  8. 만약 helm install 명령시에 –wait 옵션이 선언되어 있다면 모든 객체가 생성 완료 될때까지 기다리며 post-install hook을 실행하지 않습니다.
  9. tiller가 post-install hook으로 정의된 객체를 kubernetes에 전달합니다.
  10. tiller는 post-install hook들이 “Ready” 상태가 될때까지 기다립니다.
  11. tiller가 release 이름을 비롯한 정보들은 client에 반환합니다.
  12. client가 실행을 종료합니다.

위에서 hook이 “Ready” 상태가 된다는 이야기는 hook으로 동작하는 kubernetes 객체의 종류에 따라 조금 달라지지만 많이 사용되는 Job 객체의 경우에는 Job이 성공적으로 완료되는 시점을 의미합니다.

여기서 중요한 것은 hook으로 동작한 kubernetes 객체는 release와 함께 관리되지 않는다는 것입니다. 즉, helm delete명령으로 release를 삭제해도 hook으로 생성된 객체는 삭제되지 않습니다. 해당 객체들이 삭제되길 원한다면 pre-deletepost-delete hook을 구현해서 삭제해 주거나 "helm.sh/hook-delete-policy" annotation을 hook template에 선언해야 합니다.

아래는 alpine 이미지를 배포하는 chart에 post-install로 sleep 10 하는 hook의 구현 예제입니다.

apiVersion: batch/v1
kind: Job
metadata:
  name: ""
  labels:
    heritage: 
    release: 
    chart: "-"
  annotations:
    # This is what defines this resource as a hook. Without this line, the
    # job is considered part of the release.
    "helm.sh/hook": post-install
    "helm.sh/hook-weight": "-5"
    "helm.sh/hook-delete-policy": hook-succeeded
spec:
  template:
    metadata:
      name: ""
      labels:
        heritage: 
        release: 
        chart: "-"
    spec:
      restartPolicy: Never
      containers:
      - name: post-install-job
        image: "alpine:3.3"
        command: ["/bin/sleep",""]

마무리

지금까지 helm이 무엇인지 알아보고 helm이 어플리케이션을 kubernetes cluster 위에 배포하는 단위인 chart에 대해 알아봤습니다. chart를 이루는 주요 구성 요소인 template과 values를 알아보고 chart 의존성에 대한 개념과 hook 기능에 대해서도 알아보았습니다. 위의 내용을 충분히 숙지한다면 openstack-helm 프로젝트의 openstack chart들의 구성이 쉽게 눈에 들어올 것 같습니다.

helm은 이제 kubernetes cluster에 어플리케이션을 배포하는 정식 도구가 되어가고 있습니다. 위의 포스팅을 통해서 helm을 조금이라도 이해할 수 있길 바랍니다.

또한 taco-script를 받아서 직접 설치해 보시면 TACO가 어떻게 helm chart들을 사용하고 있는지 확인해 보실 수 있을 것입니다.

감사합니다.