Posted at

Kubernetes: パッケージマネージャHelm

More than 1 year has passed since last update.

Kubernetes Helmを試してみました。下記はv2.0.0-alpha.5で時点での情報です。


Kubernetes Helmとは

Kubernetes Helm(以降Helm)とはKubernetesのパッケージマネージャーです。HelmはKubernetesのSIG-Appsで開発がされています。パッケージはChart(s)と呼ばれ、公式でレポジトリkubernetes/chartsが用意されています。Kubernetesクラスタに側にはtillerと呼ばれるデプロイ用のコンポーネントを配置して使用します。

用語
意味
役割

helm
船のかじ
yum, aptに相当するパッケージマネージャー。Linux, OSXのバイナリが用意されている

chart
海図
deb, rpmに相当するパッケージ。Kubernetesのマニフェストのテンプレートをまとめたもの

tiller
舵柄
デプロイを担うサーバーコンポーネント


公式レポジトリ

公式レポジトリではstableincubatorの2つに分けて管理されています。kubernetes/chartsのstableの説明によると下記のポリシーで運用されています。


  • データ永続化の方法が提供される

  • アプリケーションのアップグレードがサポートされる

  • アプリケーション設定のカスタマイズを許可する

  • セキュアなデフォルト設定を持つ

  • Kubernetesのアルファ機能を利用しない

公式レポジトリ以外に任意のレポジトリを使用することも可能です。なお、現在は下記のパッケージが提供されています。


Stable


Incubator


旧Helm、DeploymentManagerとの関係

Kubernetes HelmはHelm Classic(旧Helm)というプロジェクトと、Kubernetesチームが開発するdeployment-manager(dm)という2つのツールが統合されたものです。Integrate helm and dm #171によると、ハッカソンでこの2つを統合すると決めたらしく、レポジトリ名も"deployment-manager"から"helm"に変更されました。現在のKubernetes Helmも主にDeis(Engine Yard)のエンジニアが開発しています。参考: Kubernetes HelmのContributors


Helmを試してみる


Helmのインストール

Helmのクライアント(helmコマンド)のインストールを行います。Homebrew Caskのformulaが用意されてますが、最新のバージョン(v2.0.0-alpha.5)を使いたかったので、releasesからダウンロードしPATHの通った場所にhelmバイナリを配置しました。

$ export HELM_OS=darwin && wget https://storage.googleapis.com/kubernetes-helm/helm-v2.0.0-alpha.5-$HELM_OS-amd64.tar.gz && tar -zxvf helm-v2.0.0-alpha.5-$HELM_OS-amd64.tar.gz && cd $HELM_OS-amd64

下記のコマンドでクラスタの初期化を行います。初期化ではkubernetesクラスタにサーバーコンポーネント(tiller)のデプロイを行うため、kubectlの接続先設定もされている必要があります。

$ helm init

Creating /Users/tkusumi/.helm
Creating /Users/tkusumi/.helm/repository
Creating /Users/tkusumi/.helm/repository/cache
Creating /Users/tkusumi/.helm/repository/local
Creating /Users/tkusumi/.helm/repository/repositories.yaml
Creating /Users/tkusumi/.helm/repository/local/index.yaml
$HELM_HOME has been configured at $HOME/.helm.

Tiller (the helm server side component) has been installed into your Kubernetes Cluster.
Happy Helming!

下記のようにサーバーコンポーネントのtillerがkubernetesクラスタのkube-systemネームスペースにデプロイされます。

$ kubectl get pods --all-namespaces | grep tiller

kube-system tiller-deploy-637859184-v6za1 1/1 Running 0 1m

helm versionでクライアント、サーバーのバージョンを確認できます。

$ helm version

Client: &version.Version{SemVer:"v2.0.0-alpha.5", GitCommit:"36ec1901ebd68ae976fa8ef332ca5ed44598fc24", GitTreeState:"clean"}
Server: &version.Version{SemVer:"v2.0.0-alpha.5", GitCommit:"4de5c4aa578ed9ca173aff472f00d2167ec59a88", GitTreeState:"dirty"}

参考


Helmでパッケージをインストールする

helm searchでstableパッケージの一覧が取得できます。(2.0.0-Alpha.5からの機能)

$ helm search

NAME VERSION DESCRIPTION
stable/drupal 0.3.2 One of the most versatile open source content m...
stable/jenkins 0.1.0 A Jenkins Helm chart for Kubernetes.
stable/mariadb 0.5.0 Chart for MariaDB
stable/mysql 0.1.0 Chart for MySQL
stable/redmine 0.3.1 A flexible project management web application.
stable/wordpress 0.3.0 Web publishing platform for building blogs and ...

helm install PACKAGE_NAMEでパッケージのインストールを行います。ここではJenkinsをインストールしてみます。インストール時にパッケージごとの設定を指定することができます。指定可能な値は各パッケージのREADMEにかかれています。参考: JenkinsのREADME

$ helm install stable/jenkins

Fetched stable/jenkins to jenkins-0.1.0.tgz
viable-robin
Last Deployed: Tue Oct 11 13:57:50 2016
Namespace: default
Status: DEPLOYED

~省略~

Notes:
Getting Started:

1. Get your 'admin' user password by running:
printf $(printf '\%o' `kubectl get secret --namespace default viable-robin-jenkins -o jsonpath="{.data.jenkins-admin-password[*]}"`);echo

2. Get the Jenkins URL to visit by running these commands in the same shell:
**** NOTE: It may take a few minutes for the LoadBalancer IP to be available. ****
**** You can watch the status of by running 'kubectl get svc -w viable-robin-jenkins' ****
export SERVICE_IP=$(kubectl get svc --namespace default viable-robin-jenkins -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
echo http://$SERVICE_IP:8080/login

3. Login with the password from step 1 and the username: admin

For more information on running Jenkins on Kubernetes, visit:
https://cloud.google.com/solutions/jenkins-on-container-engine

Jenkinsにアクセスする手順が表示されるので手順の通りアクセスし、正しくJenkinsがインストールされたことを確認します。

image

下記のようにJenkinsのPodが配置されました。

$ kubectl get pods

NAME READY STATUS RESTARTS AGE
viable-robin-jenkins-4218656479-dvu4v 1/1 Running 0 4m

helm listコマンドでデプロイされた一覧を確認することができます。

$ helm list

NAME REVISION UPDATED STATUS CHART
viable-robin 1 Tue Oct 11 13:57:50 2016 DEPLOYED jenkins-0.1.0


パッケージ(Charts)を試しに作ってみる

https://github.com/kubernetes/helm/blob/master/docs/charts.md

ここではサンプルに任意の文字列を設定できるnginxのパッケージ(Charts)を作ります。

helm createというコマンドで雛形を生成します。

$ helm create helloworld

Creating helloworld

下記の構成でファイルが作られます。

helloworld/

Chart.yaml # chartの情報を記載するyaml
values.yaml # chartのデフォルト設定
charts/ # chartの依存を含めるディレクトリ
templates/ # マニフェストファイルのテンプレートを配置するディレクトリ

templates/以下にkubernetesのマニフェストファイルのテンプレートを配置します。ここでは下記のマニフェストのテンプレートを配置しました。テンプレートはGoのtext/template形式で記述します。.Valuesというのが任意に設定する情報です。


hello-deployment.yaml

apiVersion: extensions/v1beta1

kind: Deployment
metadata:
# 本来は{{.Release.Name}}などを使ってユニークにする必要がある
name: "hello-nginx"
labels:
spec:
# 任意のレプリカ数を設定できる
replicas: {{.Values.replicaCount}}
template:
metadata:
labels:
app: "hello-nginx"
spec:
containers:
- image: nginx:1.11.4
name: nginx
ports:
- containerPort: 80
command:
- /bin/bash
- -c
# 任意の値をindex.htmlで表示
- 'echo "<h1>{{.Values.message}}</h1>" > /usr/share/nginx/html/index.html; /usr/sbin/nginx -g "daemon off;"'


hello-svc.yaml

apiVersion: v1

kind: Service
metadata:
name: hello-nginx
labels:
spec:
ports:
- port: 80
name: http
targetPort: 80
selector:
app: "hello-nginx"
type: LoadBalancer

values.yamlに初期値を記載しておきます。


values.yaml

replicaCount: 2

message: hello world!

helm lintという構文チェックツールが付属していおり、構文エラーをチェックすることができます。

$ helm lint helloworld

==> Linting helloworld
[ERROR] templates/: render error in "helloworld/templates/hello-deployment.yaml": template: helloworld/templates/hello-deployment.yaml:14:24: executing "helloworld/templates/hello-deployment.yaml" at <{{template "fullname...>: template "fullname" not defined

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

構文に問題がなければパッケージ(tgzファイル)を作成します。

$ helm package helloworld

パッケージされたhelloworld-0.1.0.tgzが作成されました。下記の用にインストールができます。テンプレートの変数は--setフラグでカンマ区切りのkey=value形式、または--valuesフラグでyaml形式で指定することができます。

$ helm install --set 'message=It works!,replicaCount=3' helloworld-0.1.0.tgz

right-quail
Last Deployed: Tue Oct 11 16:19:10 2016
Namespace: default
Status: DEPLOYED

Resources:
==> extensions/Deployment
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
hello-nginx 3 3 3 0 0s

==> v1/Service
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
hello-nginx 10.187.251.4 <pending> 80/TCP 0s

ロードバランサのEXTERNAL-IPを確認してブラウザでアクセスします。

$ kubectl get svc hello-nginx

NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
hello-nginx 10.187.251.4 104.155.129.166 80/TCP 53s

image

既存のChartを見ると、他にもラベルなどの設定がいろいろとあるので、実際に作る際は既存のものを参考にするとよいと思います。例えばRelease.Name(指定しないとランダムで付けられる)のような事前に定義された変数があり、これらを使ってユニークなnameを設定したりする必要があります。


その他にChartでできること

Chartsのドキュメントによると他にChartsで下記のことができるようです。


依存関係

Chartの依存関係をcharts/ディレクトリへのコピーまたはrequirements.yamlによる定義で表現することができます。これにより自動的に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


フック

パッケージインストール、削除、アップグレード時にフックする機能が提供されています。例えばシークレットを動的に作ることや、アップグレード前にDBのバックアップを取るなどの用途に利用できます。下記のフックポイントが用意されています。


  • pre-install

  • post-install

  • pre-delete

  • post-delete

  • pre-upgrade

  • post-upgrade

フックの処理はKubernetesのBatch Jobとして定義し、下記のようにアノテーションでフックポイントを指定できます。カンマ区切りで複数していすることもできます。

  annotations:

"helm.sh/hook": post-install


参考