## 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 Code: https://github.com/Kubernetes/helm
- Charts Code: https://github.com/Kubernetes/Charts
- Documentation: https://docs.helm.sh
Helm 구조
helm은 client-server 구조로 설계되어 있습니다.
사용자를 위한 CLI인 client를 helm client라 부르고 server는 tiller라고 부릅니다.
tiller는 보통kubernetes위에 pod으로 배포됩니다.
그리고 어플리케이션을 구성할 kubernetes 객체를 정의하는 manifest template 파일 및 설정 묶음을 chart라고 부릅니다.
helm client를 통해서 chart를 kubernetes 위에 배포하면 배포된 어플리케이션을 release라고 부릅니다.
아래 용어는 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가 제공되고 여기엔 쉽게 배포해 볼 수 있는 다양한 어플리케이션들이 준비되어 있습니다.
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을 설치하는 부분입니다.
Using Helm
helm client가 동작하려면 tiller와 통신할 수 있어야 합니다.
helm client는 kubernetes proxy 기능을 통해서 tiller와 통신하는데 그러기 위해서는 kubernetes config파일의 위치를 알고 있어야 합니다.
helm client는 kubectl과 마찬가지로 아래 위치에서 config파일을 찾습니다.
helm init
helm client를 통해서 tiller를 설치하는 명령어 입니다. –upgrade 옵션을 통해서 이미 설치된 tiller의 버젼을 올리는 것도 가능합니다.
helm repo
chart repository 목록을 등록하고 조회하고 삭제할 수 있습니다.
helm serve
helm repository sevice process를 실행합니다.
helm search
helm repo list에 보이는 repository에 등록되어 있는 chart를 조회할 수 있습니다. helm 설치 직후엔 stable 이라는 기본 repository가 제공되는 것을 확인 할 수 있습니다.
helm install
chart repository에 등록된 chart를 이용해서 kubernetes cluster에 어플리케이션을 배포하는 명령어입니다. 아래 명령어는 helm install 명령어를 통해서 stable repository에 등록된 mariadb를 kubernetes위에 배포하는 예제입니다.
helm lint
chart의 문법을 체크하는 명령어 입니다. chart 개발시에 자주 사용하는 명령어로 chart 내에 존재하는 yaml들의 indent 및 문법이 잘못되어 있거나 kubernetes 객체를 정의하는 template 언어의 문법이 잘못되어 있는 것을 미리 체크해 볼 수 있습니다. 아래 예는 stable/drupal chart를 받아서 deployment.yaml 파일의 코드를 임의로 삭제하고 helm lint를 한 결과입니다.
helm list
배포된 release 목록을 조회하는 명령어입니다.
helm history
배포된 release의 배포 이력을 조회하는 명령어입니다.
helm fetch
repository에 등록된 chart를 tar ball형태로 다운받을 수 있는 명령어 입니다.
다운 받은 tarball의 압축을 풀면 chart의 구성을 확인해 볼 수 있습니다.
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을 선언해야 합니다.
Chart
helm은 chart라고 부르는 패키지 포멧을 사용해서 어플리케이션을 배포합니다.
chart란 kubernetes의 객체들을 정의하는 파일들과 그 설정값들의 집합입니다.
지금부터는 chart의 구조를 자세히 살펴보고 chart를 구성하는 각 파일들의 내용을 알아보도록 하겠습니다.
Chart 구조
chart는 어플리케이션 이름인 디렉토리 아래에 다양한 파일들로 구성되어 있습니다.
즉, wordpress 어플리케이션을 배포하는 chart의 디렉토리 이름은 wordpress입니다.
아래는 wordpress 라는 chart의 구조를 보여줍니다.
chart는 반드시 위의 파일 및 디렉토리 이름들로 구성되어야 하며 다른 파일 및 디렉토리 이름들은 무시됩니다.
또한 해당 chart가 의존성이 없으면 charts 디렉토리가 필요 없습니다.
Chart.yaml
Chart.yaml 파일은 명세서 역할을 하는 파일입니다.
그 내용은 아래와 같습니다.
만약에 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파일에 정의하면 됩니다.
위의 예에서 name 및 version 항목에는 chart의 이름 및 버젼을 적어야 하고, repository 항목에는 해당 chart가 저장되어 있는 저장소의 주소를 적어야 합니다.
물론 helm repo list 명령어를 통해서 볼 수 있는 repository여야 하고, 등록된 주소가 없다면 helm repo add 명령어로 repository를 등록해 주어야 합니다.
위와 같이 의존성이 정의된 chart에 helm dep up 명령어를 사용하면 아래와 같은 결과를 볼 수 있습니다.
(chart 이름은 foochart라고 하겠습니다.)
그렇다면 의존 관계가 정의된 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 파일로 완성됩니다.
- Go Template Language : https://golang.org/pkg/text/template/
- Sprig Library : https://github.com/Masterminds/sprig
template 파일은 아래 예제와 같은 형태로 구성되어 있습니다.
위의 예제를 보면 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 파일을 넘겨줄 수 있습니다.
즉 value를 정의하는 방법은 총 3가지 방법이 존재합니다.
- chart 내의 values.yaml 파일에 미리 정의하는 방법
- helm install –values 옵션에 values 파일을 만들어서 넘겨주는 방법
- 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로 선언하면 됩니다.
위와 같이 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 명령의 예로 확인해 보도록 하겠습니다.
- 사용자가 helm install foo 명령을 실행합니다.
- chart가 tiller에게 전달됩니다.
- tiller가 chart를 검증한 후, template을 rendering을 해서 kubernetes manifest를 생성합니다.
- tiller가 어플리케이션을 구성하는 manifest들을 kubernetes에 전달합니다.
- tiller가 release 이름을 비롯한 정보들은 client에 반환합니다.
- client가 실행을 종료합니다.
위의 install 생명주기에서 helm은 pre-install과 post-install hook을 제공합니다.
만약에 사용자가 두가지 hook을 모두 선언하면 아래와 같은 과정이 추가됩니다.
- 사용자가 helm install foo 명령을 실행합니다.
- chart가 tiller에게 전달됩니다.
- tiller가 chart를 검증한 후, template을 rendering을 해서 kubernetes manifest를 생성합니다.
- tiller는 pre-install hook을 가중치와 이름으로 asc 정렬해서 합니다.
- 그리고 tiller는 hook으로 정의된 객체를 kubernetes에 전달합니다.
- tiller는 hook들이 “Ready” 상태가 될때까지 기다립니다.
- tiller가 어플리케이션을 구성하는 manifest들을 kubernetes에 전달합니다.
- 만약 helm install 명령시에 –wait 옵션이 선언되어 있다면 모든 객체가 생성 완료 될때까지 기다리며 post-install hook을 실행하지 않습니다.
- tiller가 post-install hook으로 정의된 객체를 kubernetes에 전달합니다.
- tiller는 post-install hook들이 “Ready” 상태가 될때까지 기다립니다.
- tiller가 release 이름을 비롯한 정보들은 client에 반환합니다.
- client가 실행을 종료합니다.
위에서 hook이 “Ready” 상태가 된다는 이야기는 hook으로 동작하는 kubernetes 객체의 종류에 따라 조금 달라지지만 많이 사용되는 Job 객체의 경우에는 Job이 성공적으로 완료되는 시점을 의미합니다.
여기서 중요한 것은 hook으로 동작한 kubernetes 객체는 release와 함께 관리되지 않는다는 것입니다.
즉, helm delete명령으로 release를 삭제해도 hook으로 생성된 객체는 삭제되지 않습니다.
해당 객체들이 삭제되길 원한다면 pre-delete나 post-delete hook을 구현해서 삭제해 주거나 "helm.sh/hook-delete-policy" annotation을 hook template에 선언해야 합니다.
아래는 alpine 이미지를 배포하는 chart에 post-install로 sleep 10 하는 hook의 구현 예제입니다.
마무리
지금까지 helm이 무엇인지 알아보고 helm이 어플리케이션을 kubernetes cluster 위에 배포하는 단위인 chart에 대해 알아봤습니다.
chart를 이루는 주요 구성 요소인 template과 values를 알아보고 chart 의존성에 대한 개념과 hook 기능에 대해서도 알아보았습니다.
위의 내용을 충분히 숙지한다면 openstack-helm 프로젝트의 openstack chart들의 구성이 쉽게 눈에 들어올 것 같습니다.
helm은 이제 kubernetes cluster에 어플리케이션을 배포하는 정식 도구가 되어가고 있습니다.
위의 포스팅을 통해서 helm을 조금이라도 이해할 수 있길 바랍니다.
또한 taco-script를 받아서 직접 설치해 보시면 TACO가 어떻게 helm chart들을 사용하고 있는지 확인해 보실 수 있을 것입니다.
'쿠버네티스 기타' 카테고리의 다른 글
How ALB Ingress Controller works? | AWS ALB Ingress Controller | kubernetes Ingress controller - ALB 인그레스 아키텍처 (0) | 2020.11.02 |
---|---|
Fargate on EKS 구현 (0) | 2020.10.28 |
AWS Fargate on EKS 실전 사용하기 (0) | 2020.10.27 |
Helm (헬름) 설치하기 (0) | 2020.10.14 |
Helm 차트 란? | NGINX를 사용한 Helm Kubernetes 데모 (0) | 2020.10.14 |
댓글