はじめに

前回はマイクロサービスアーキテクチャのアプリケーション構築を支援する「Dapr」を使ってAKS上にアプリケーションを構築していく方法について説明しました。今回はKubernetesのアプリケーションをパッケージ化して管理・運用できるツールである「Helm」を使ったアプリケーションのデプロイ方法について説明していきます。

Helmを使ってKubernetesアプリケーションを構築しよう

Kubernetesを使ってアプリケーションを作成したりデプロイする際にはマニュフェストファイルの作成が必要です。アプリケーションの規模が大きくなってくると、マニュフェストファイルの量も膨大になり、管理やメンテナンスの負荷が高くなってしまいます。今回紹介するHelmを使用することで、これらの課題がどのように解消されるかを見ていきましょう。

Helmとは

Kubernetesでは、アプリケーションのあるべき姿を定義したマニュフェストファイルを使ってクラスタ上にアプリケーションをデプロイします。このマニュフェストファイルは、基本的にKubernetesにデプロイしたいアプリケーションの数だけ用意する必要があります。そのため、大規模なシステムになると膨大な量のマニュフェストファイルの管理やメンテナンスが課題となってきます。
Helmはこの様なKubernetesでのアプリケーション管理の複雑さの解消を手助けするツールです。Helmは公式サイトのトップに「The package manager for Kubernetes」と掲げている通り、Kubernetesのためのパッケージマネージャーです。 以下はHelmの概念図です。

  • Helmの概念図

    Helmの概念図

Helmには、「チャート」、「リリース」、「リポジトリ」という基礎となる3つの概念が存在します。

Helmチャート

Helmでは、チャートと呼ばれる単位でKubernetes上にデプロイされるアプリケーションのマニュフェストファイル群をパッケージ化して管理します。
チャートは、テンプレートファイルと呼ばれるKubernetesのマニュフェストファイルをテンプレート化したファイル群で構成されています。チャートを使ってKubernetes上にアプリケーションをデプロイする際は、テンプレートファイルに具体的な設定値を与える設定ファイルを用意します。Helmはテンプレートファイルと設定ファイルからKubernetesが認識できるマニュフェストファイルを生成してデプロイを行います。
またチャートは自作できる他、Helmリポジトリに公開されているチャートを利用することも可能です。例えば自作したチャートでHelmリポジトリに公開されている別のチャートを依存関係として定義すると、自作チャートをKubernetesクラスタにデプロイする際に依存するチャートの内容も同時にデプロイすることができるようになります。

Helmリリース

HelmチャートをKubernetes上にデプロイする行為をHelmリリースと呼びます。Helmリリースはリビジョンという通し番号で管理されます。チャートの設定値を更新して再度デプロイした場合などに新しいリビジョン番号でHelmリリースが行われます。以前のリビジョンのHelmリリースの情報は保存されるため、以前のリリース状態に戻す「ロールバック」といった操作も可能になります。

Helmリポジトリ

Helmチャートを公開して利用するためのリポジトリをHelmリポジトリと呼びます。自作したHelmチャートをHelmリポジトリに公開したり、公開されている別のチャートを使用することができます。Helm公式のHelmリポジトリである「https://charts.helm.sh/stable」の他にもリポジトリは多数存在しており、コミュニティが公開しているHelmチャートを使うことでKubernetesにデプロイするアプリケーション群をHelmで包括的に管理することができるようになります。

WebアプリケーションのHelmチャートを作ろう

ここからは実際にHelmを使ってWebアプリケーションをAKS上にデプロイしていきます。アプリケーション部分の説明を簡素化するために、これまでに作成してきたFlaskとRedisを使ったアクセスカウンターのWebアプリケーションを実装します。

コンテナ化するWebアプリケーションの実装

まずはAKS上で実行させたいアプリケーションの実装を行っていきます。任意のフォルダ上に「zerokara-aks-helm」というフォルダを作成します。さらにその中に「src」というフォルダを作成し「app.py」というファイルを作成します。

アクセスカウンターアプリの実装(zerokara-aks-helm/src/app.py)

# Flaskのインポート
from flask import Flask
# Redisのインポート
from redis import Redis
import os

# Flaskの使用
app = Flask(__name__)

# Redisの初期化
redis_server = os.environ['REDIS_SERVER']
redis = Redis(host=redis_server, port=6379)

# 公開するAPIの定義
@app.route('/')
def hello():
    count = redis.incr('hits')
    return 'Hello Helm! {}回目のアクセスです。\n'.format(count)

# ヘルスチェック用のAPIの定義・・・①
@app.route('/health')
def health():
    try:
        redis.ping()
    except redis.exceptions.ConnectionError:
        return 'NG', 500
    return 'OK', 200

# アプリケーションの起動(外部公開できる状態で起動)
if __name__ == "__main__":
    app.run(host="0.0.0.0", port="5000", debug=True)

以前紹介したアクセスカウンタの実装に、ヘルスチェック用のAPIを新たに追加しました(①)。このAPIではRedisへの疎通が取れているかどうかをpingメソッドを使って確認し、Redisから応答があればHTTPステータスコード200を、Redisとの接続に失敗した場合はHTTPステータスコード500を返すようにしています。このヘルスチェックAPIは、後ほど説明するHelmが生成したDeployment用のテンプレートの中で使用していきます。

Pythonアプリの依存ライブラリの定義(zerokara-aks-helm/src/requirements.txt)
flask
redis

こちらも以前と同様に、Pythonが使用するライブラリである「flask」と「redis」をrequirements.txtに列挙します。

アプリケーションのビルドとACRへのプッシュ

アプリケーションの実装が完了したら、DockerイメージとしてビルドしてAzure Container Registry(ACR)へプッシュしていきます。

Webアプリケーション用のDockerfile(zerokara-aks-helm/src/Dockerfile)

# ベースイメージとしてpythonを使用する
FROM python:3.9-alpine

# アプリケーションの配置と依存関係のインストール
ADD . /code
WORKDIR /code
RUN pip install -r requirements.txt

# 公開するポートの指定
EXPOSE 5000

# 起動時のコマンドの指定
CMD ["python", "app.py"]

Dockerfileもこれまでと同様にpythonコンテナをベースイメージとしたコンテナとして定義をしていきます。
ここまで準備ができたら、Dockerイメージを作成してACRへプッシュをします。

DockerイメージのビルドとACRへのプッシュ

$ cd zerokara-aks-helm
$ az acr build --image zerokara-aks-helm:v1 --registry zerokara --file ./src/Dockerfile ./src

Azure CLIの「az acr build」コマンドを使用すると、Dockerイメージの作成とACRへのプッシュを一度に行うことができます。
「--image」オプションでイメージ名とタグ名を指定し、「--registry」オプションでイメージをプッシュするACRのレジストリ名を指定します。「--file」オプションでDockerファイルの保存場所を相対パスで指定します。
コマンドを実行すると、Dockerイメージのビルドが開始され、ビルドが完了すると続けてACRへのイメージのプッシュが開始されます。すべてが完了し、「successful」のログが出力されたらACRへのイメージプッシュまで成功となります。

Helm CLIのインストール

ここからはHelmのCLIツールを使った作業になります。Helm CLIはHelmの公式サイトからインストールすることが可能です。お使いのOSに合わせたインストール方法が提示されていますので、それに従ってインストールを実施します。 インストール完了後、ターミナルで「helm version」と入力してバージョン情報が出力されればインストールは成功です。

Helm CLIのバージョンチェック

$ helm version
version.BuildInfo{Version:"v3.10.2", GitCommit:"50f003e5ee8704ec937a756c646870227d7c8b58", GitTreeState:"clean", GoVersion:"go1.19.3"}

執筆時点では「v3.10.2」が最新版としてインストールされました。本記事はHelmのv3系を前提としているので、v3系がインストールされることを確認して下さい。

Helmチャートの生成

Helm CLIをインストールしたら、今回のアプリケーション用のHelmチャートを作成していきます。

Helmチャートの新規作成

$ helm create zerokara-aks-helm-front
Creating zerokara-aks-helm-front

「helm create」コマンドでHelmチャートを作成することができます。コマンドの引数としてチャート名を指定します。ここでは「zerokara-aks-helm-front」というチャート名を指定しています。
コマンドが成功すると、カレントディレクトリ上に指定したチャート名でディレクトリが作成されます。
このディレクトリの中にはHelmチャートとして公開するために必要なテンプレートファイル群が作成されています。

Helmチャートのディレクトリ構成

zerokara-aks-helm-front
  ├ charts
  │ ├ redis-x.x.x.tgz (後ほど追加される)
  │ └ xxx.tgz
  ├ templates
  │ ├ tests
  │ │ └ test-connection.yaml
  │ ├ _helpers.tpl
  │ ├ deployment.yaml
  │ ├ sevice.yaml
  │ └ xxx.yaml
  ├ ・・・中略
  ├ Chart.yaml
  └ values.yaml

作成されたチャートのディレクトリ直下には「Chart.yaml」と「values.yaml」というファイルがあります。
Chart.yamlはチャート全体に関する情報を記述するファイルです。また依存するチャートの情報を記述することで、Helmリポジトリから別のチャートをダウンロードすることができるようになります。
values.yamlはチャートの設定ファイルです。このファイルにKubernetesへのデプロイ時に要求する具体的な設定値を入力していきます。
chartsディレクトリは依存する別のチャートが保存されるディレクトリです。先述のChart.yamlに記述した依存チャートが、Helmリポジトリからダウンロードされてこのディレクトリtgz形式で保存されます。
templatesディレクトリにはKubernetesのマニュフェストファイルのテンプレートファイル群がYAMLファイルとして存在します。deployment.yamlやservice.yamlは、それぞれKubernetesリソースであるDeploymentやServiceをデプロイするために使用するテンプレートファイルです。
_helpers.tplはチャート内で再利用したいテンプレートの内容をヘルパーとして定義できるスクリプトファイルです。
templatesディレクトリ内にあるtestsディレクトリは名前の通りチャートのテストを行う際に利用します。testsディレクトリにテスト用のテンプレートファイルを配置し、それをKubernetes上にデプロイすることでテストを行う仕組みです。

Chart.yamlの編集

「helm create」コマンドでHelmチャートのファイル群が作成されたら必要に応じて内容を編集していきます。各ファイルをKubernetesにデプロイしたいアプリケーションの構成に沿ったものに変更します。
まずは「Chart.yaml」ファイルを編集します。

Helmチャートの定義ファイルの編集(zerokara-aks-helm-front/Chart.yaml)

apiVersion: v2
name: zerokara-aks-helm-front
description: A Helm chart for Kubernetes

# dependenciesのブロックを追加・・・①
dependencies:
  - name: redis
    version: 17.3.13
    repository: https://charts.bitnami.com/bitnami

・・・以下略

先述の通り「Chart.yaml」はこのHelmチャート全体に関係する内容を記述するファイルです。HelmチャートはKubernetesにデプロイするアプリケーションをパッケージ化したものですので、複数のHelmチャートを組み合わせて使用することも可能です。
今回作成したWebアプリケーションはアクセスカウントの保存先DBとしてRedisを使用するため、RedisもKubernetesクラスター上にデプロイする必要があります。このようにアプリケーションが別のアプリケーションに依存している場合、Chart.yaml内に「dependencies」ブロックを記述することで依存アプリケーションのHelmチャートを参照することができるようになります(①)。今回使用するRedisのHelmチャートはbitnamiが公開しているリポジトリ上にあるチャートを参照するように記述しています。

Chart.yamlにRedisへの依存関係を記述したら、ファイルを保存して以下のhelmコマンドを実行します。

Helmチャートの依存関係の更新

$ helm dependency update zerokara-aks-helm-front
Getting updates for unmanaged Helm repositories...
...Successfully got an update from the "https://charts.bitnami.com/bitnami" chart repository
Saving 1 charts
Downloading redis from repo https://charts.bitnami.com/bitnami
Deleting outdated charts

「helm dependency update」コマンドを実行すると、Chart.yamlの「dependencies」ブロックに記述されているHelmチャートをHelmリポジトリからダウンロードします。コマンドが成功すると、「charts」ディレクトリ内に依存するHelmチャートがtgz形式でダウンロードされます。これにより、現在作成しているWebアプリケーション用のHelmチャートをKubernetesにデプロイする際に、Redisのチャートのデプロイも同時に行ってくれるようになります。

まとめ

今回はKubernetes向けのパッケージマネージャーであるHelmの概要およびHelmチャートの新規作成方法について説明しました。次回はいくつかのテンプレートファイルの内容を編集して、実装したWebアプリケーションをAKSにデプロイできるように調整していきます。

WINGSプロジェクト 秋葉龍一著/山田祥寛監修
<WINGSプロジェクトについて>テクニカル執筆プロジェクト(代表山田祥寛)。海外記事の翻訳から、主にWeb開発分野の書籍・雑誌/Web記事の執筆、講演等を幅広く手がける。一緒に執筆をできる有志を募集中