kubernetes

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

参考