とことんDevOps | 日本仮想化技術が提供するDevOps技術情報メディア

DevOpsに関連する技術情報を幅広く提供していきます。

日本仮想化技術がお届けするとことんDevOpsでは、DevOpsに関する技術情報や、日々のDevOps業務の中での検証結果など、DevOpsのお役立ち情報をお届けします。
主なテーマ: DevOps、CI/CD、アジャイル開発、コンテナ開発など

開催予定の勉強会

各種SNSのフォローもよろしくお願いいたします。

Helmを使う

弊社Opsチームではアプリケーションの管理にHelmを使います。かんたんDevOpsでもHelmを使うことがありますが、導入して終わりというわけにもいかないので、簡単な使い方や、そもそもHelmって何ってなんなの?っという情報をここにまとめておきます。

そもそもHelmって?

helm.sh

HelmはKubernetesアプリケーションを管理するためのツールで、公式ページでは「Kubernetes用 パッケージマネージャー」を謳っています。チャートと呼ばれるKubernetesマニフェストのテンプレートを元にアプリケーションを管理することができます。パブリックに公開されているHelmチャートはArtifact HUBというWEBサイトや、コマンドラインから検索できます。使いたいチャートがあればHelmリポジトリとして登録することで、HelmからKubernetesにアプリケーションのインストールやアップグレード、アンインストールなどを簡単に行えるようになります。もちろん、公開されていなくても、ローカルや自分だけがアクセスできる場所にチャートを置けば、それを元に操作することが可能です。

Helmを使うと何がいいの?

メリットをいくつかまとめます。

  • Helmは動的にパラメータを埋め込むことができる
apiVersion: apps/v1
kind: Deployment
spec:
  replicas: {{ .Values.replicaCount }}

これはdeploymentを作るマニフェストの一部なんですが、replicasを見てください。{{ .Values.replicaCount }}という変数のようなものが定義されています。これはvalues.yamlというファイル内で定義されているreplicaCountに指定した値で置き換えられます。もしくはコマンドライン引数で--set replicaCount=3などとしても変更することが可能です。このようにマニフェストの値を変更することができるので、複数環境を1つのチャートで管理することが可能になります。

  • バージョン管理ができる

HelmチャートにはCHART VERSIONとAPP VERSIONがあります。CHART VERSIONはHelmチャート自体のバージョンです。Helmチャートに変更を加えた時にカウントアップします。APP VERSIONはアプリケーションのバージョンです。インストールやアップグレードの時にCHART VERSIONを指定することで、そのCHART VERSIONに紐づくアプリケーションをインストールすることが可能です。今どのバージョンで動いているのか、過去にどのバージョンが動いていたのか、いつアップグレードされたのかなどが簡単に確認できるので、障害が発生した時や、アップグレード計画を立てるときなどに役立つと思います。

  • Artifact HUBの存在

Helmを使っていない場合、公式のリポジトリからマニフェストをダウンロードし、自分の環境に必要な箇所を検索、修正してからデプロイするっということをしていました。しかし、Helmを使うと、チャートはArtifact HUBで公開されていて、各オプションの説明があり、外部から値の埋め込みができるので、前述した苦労から解放されます。

Helmええやん

いいことばかりではありません。デメリットもあります。

  • 学習コストがかかる

Helmチャートの実態はKubernetesマニフェストのテンプレートです。Kubernetesマニフェストを知っている必要もありますし、Helmチャートの書き方も学習する必要があります。

  • テンプレートが読みづらくなりがち

Helmを使っていると様々な値を外部から変更したくなるでしょう。しかし、やりすぎるとテンプレート内で何をしてるのかがわかりづらくなります。黒魔術にならないよう、あまり複雑なことはしないのがいいのかなっと思います。

  • 宣言的ではない

動的に値を埋め込めるので、まぁ、そうですよね。--setオプションで色々設定してしまうと、シェルのHistoryが消えると終わります。複数環境で1つのチャートを使う場合は、各環境用にvalues.yamlを用意しておいて--values /path/to/fileでオーバーライドしてあげるのでいいように思います。helmfileというツールを使うのもいいかもしれません。

実際に使ってみる

それではいよいよHelmを使っていきたいと思います。まずはKubernetes環境が必要になりますので、以下の過去記事を参考に導入を進めてみてください。ちなみに私は過去記事にはないのですがminikubeを使用しました。

devops-blog.virtualtech.jp

devops-blog.virtualtech.jp

devops-blog.virtualtech.jp

この記事のためにサンプルプロジェクトとコンテナイメージを公開しました。お使いください。

github.com

まずはリポジトリの登録です。helm-helloという名前でリポジトリを登録していきます。

helm repo add helm-hello https://virtualtech-devops.github.io/helm-hello

登録ができたら確認します。

helm repo list

以下のように出力されていれば成功です。

NAME            URL
...
helm-hello      https://virtualtech-devops.github.io/helm-hello

リポジトリに登録されているアプリケーションを確認してみます。

helm search repo
NAME                                            CHART VERSION   APP VERSION                             DESCRIPTION
...
helm-hello/hello                                1.1.0           v1.1.0                                  A Helm chart for Kubernetes
...

リポジトリを複数登録してる人は、全てのリポジトリが表示されて少し見づらいかもしれません。出力を絞り込んでみます。絞り込む時はhelm search repo [keyword]のように入力します。[keyword]はあいまい検索ができるので、単語やフレーズの一部を入力することでヒットしたものを表示することができます。

helm search repo helm-hello
NAME                    CHART VERSION   APP VERSION     DESCRIPTION
helm-hello/hello        1.1.0           1.0.0           A Helm chart for Kubernetes

helm-helloはリポジトリ名、helloはリポジトリに含まれているアプリケーション名です。今回使っているリポジトリでいうとココから確認できます。

--versionsオプションをつけることで、リポジトリに登録されている全てのバージョンが確認できます。

helm search repo helm-hello --versions
NAME                    CHART VERSION   APP VERSION     DESCRIPTION
helm-hello/hello        1.1.0           v1.1.0          A Helm chart for Kubernetes
helm-hello/hello        1.0.0           v1.0.0          A Helm chart for Kubernetes

CHART VERSIONとAPP VERSIONはズレることがよくあります。これはチャートとアプリのライフサイクルが違うのに起因します。アプリがアップデートされればチャートも変更されるのですが、チャートを変更してもアプリのバージョンは上がりません。もしくは、元々アプリがリリースされていて、後からチャートが追加された、最初なので0.1.0にしょう、などです。インストールしたいアプリのバージョンは必ずAPP VERSIONを確認しましょう。

もし思ったようなバージョンが出てこなかった場合は以下のコマンドでリポジトリをアップデートしてみてください。

helm repo update

今まで使っていたhelm searchですが、Artifact HUBから検索することも可能です。

helm search hub

Artifact HUBにある全てのパッケージが出てきますので、適当にKeywordで絞り込んで使ってみてください。

それでは実際にデプロイしてみます。

helm install helm-hello helm-hello/hello --namespace helm-hello --create-namespace

今回はhelm installを使いましたが、helm upgrade --installとしてもインストールできます。後者の場合、インストールされていなければインストールを、インストール済みであればアップグレードをという動きをします。ちなみに私はupgradeをよく使います。

インストール後、以下のように出力されたと思います。

NAME: helm-hello
LAST DEPLOYED: Mon Aug 29 16:50:34 2022
NAMESPACE: helm-hello
STATUS: deployed
REVISION: 1
NOTES:
1. Get the application URL by running these commands:
  export POD_NAME=$(kubectl get pods --namespace helm-hello -l "app.kubernetes.io/name=hello,app.kubernetes.io/instance=helm-hello" -o jsonpath="{.items[0].metadata.name}")
  export CONTAINER_PORT=$(kubectl get pod --namespace helm-hello $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
  echo "Visit http://127.0.0.1:8080 to use your application"
  kubectl --namespace helm-hello port-forward $POD_NAME 8080:$CONTAINER_PORT

NOTESの欄に色々書いてあります。これはアプリケーション固有の情報で、全てのチャートでこの出力があるわけではありません。しかし、有用な情報が書いてあることがありますので、一応目を通しておくことをおすすめします。

後から取得することも可能です。

helm get notes --namespace helm-hello helm-hello

今回はNOTESにアクセス方法が記載されています。以下の手順を行うことでブラウザからアプリにアクセスできるようになります。

export POD_NAME=$(kubectl get pods --namespace helm-hello -l "app.kubernetes.io/name=hello,app.kubernetes.io/instance=helm-hello" -o jsonpath="{.items[0].metadata.name}")
export CONTAINER_PORT=$(kubectl get pod --namespace helm-hello $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
kubectl --namespace helm-hello port-forward $POD_NAME 8080:$CONTAINER_PORT

以下のように待ち受け状態になったら、ブラウザからhttp://127.0.0.1:8080にアクセスしてみてください。hello helm wordが表示されたと思います。

Forwarding from 127.0.0.1:8080 -> 80
Forwarding from [::1]:8080 -> 80

続いて何がインストールされたのかを見てみましょう。

helm list --namespace helm-hello
NAME            NAMESPACE       REVISION        UPDATED                                 STATUS          CHART           APP VERSION
helm-hello      helm-hello      1               2022-08-29 17:03:59.478781 +0900 JST    deployed        hello-1.1.0     v1.1.0

いつインストールされて、CHARTとAPPがどのバージョンがデプロイされたかが確認できます。

インストールされたマニフェストは以下で確認できます。

helm get manifest --namespace helm-hello helm-hello

helm installした時にバージョンを指定しなかったのでlatestがインストールされました。次はバージョンを指定してインストールしてみましょう。今回はすでにアプリがインストール済みなのでupgradeを使います。

helm upgrade helm-hello helm-hello/hello --namespace helm-hello --create-namespace --version 1.0.0

もう一度 helm listを実行してみてください、REVISIONが進み、CHARTとAPP VERSIONがダウングレードされたと思います。NOTESの通り再度ポートフォワードを設定し、ブラウザからアクセスしてみましょう。hello worldに表示が変わったと思います。

次に操作履歴を見てみます。

helm history --namespace helm-hello helm-hello
REVISION        UPDATED                         STATUS          CHART           APP VERSION     DESCRIPTION     
1               Tue Aug 30 09:12:56 2022        superseded      hello-1.1.0     v1.1.0          Install complete
2               Tue Aug 30 09:13:20 2022        deployed        hello-1.0.0     v1.0.0          Upgrade complete

いつインストールやアップグレードがされたか、その時のバージョン情報などを確認することができます。STATUSがdeployedになっているものが現在デプロイされているアプリケーションで、helm listで確認したときのリビジョンと一致していると思います。

それでは最後にアンインストールをして終わります。

helm uninstall --namespace helm-hello helm-hello

まとめ

Helmについて簡単にまとめました。今回紹介したサブコマンドは、私が運用中によく使うものです。紹介したもの以外にも、静的解析やロールバックなど、様々なサブコマンドが用意されています。どれも運用に役立つコマンドなので、色々触ってみてください。