Helm チャート: Kubernetes パッケージ管理
Helm を使用した Kubernetes のデプロイメント
Helm は Kubernetes のアプリケーションのデプロイを革命的に変えてきました。伝統的なオペレーティングシステムでよく使われるパッケージ管理の概念を導入し、複雑なアプリケーションの管理を簡略化しました。
Kubernetes の採用が増えるにつれて、数十の YAML ファイルを管理する作業は困難になります。Helm Charts はこの問題を解決し、すべてのリソースをバージョン管理された、設定可能なパッケージにまとめます。
この素晴らしい画像は AI モデル Flux 1 dev によって生成されました。
Helm: Kubernetes のパッケージマネージャーの理解
Helm は Kubernetes にとって apt が Debian にとって、yum が RedHat にとって、Homebrew が macOS にとってのものです。Kubernetes アプリケーションを Charts にパッケージ化します。Charts は関連する Kubernetes リソースを記述するファイルのコレクションです。1つの Chart は、ウェブサーバー、データベース、キャッシュレイヤー、イングレスルール、モニタリングコンポーネントを含む、完全なアプリケーションスタックをデプロイできます。Kubernetes に初めて触れる方には、Kubernetes Cheatsheet が、開始に必要な基本的なコマンドと概念を提供します。
現代の DevOps において Helm が重要な理由
複雑性の削減: 20以上の YAML ファイルを管理する代わりに、カスタマイズ可能な値を持つ1つの Chart を管理します。
再現性: 開発、ステージング、プロダクション環境で環境固有の値の上書きにより、同じ構成をデプロイできます。これは、一貫性が重要となる複雑なマイクロサービスアーキテクチャのデプロイにおいて特に価値があります。
バージョン管理: Charts はバージョン管理され、ロールバックやアップグレードの追跡が容易になります。
コミュニティエコシステム: PostgreSQL、Redis、NGINX、Prometheus など、人気のあるアプリケーションの数千のプリビルドされた Charts が Artifact Hub(以前は Helm Hub)で利用可能です。
テンプレートの力: Go テンプレートにより、入力値に基づいて動的なリソース生成が可能となり、重複を減らします。
Helm のアーキテクチャとコアコンセプト
Helm 3 のアーキテクチャ
Helm 3 は、Helm 2 にあった問題のあるサーバーサイドコンポーネント Tiller を削除し、アーキテクチャを簡略化しました:
- Helm クライアント: Kubernetes API と直接やり取りする CLI ツール
- Chart: テンプレートとメタデータを含むパッケージ形式
- リリース: Kubernetes クラスター内で実行されている Chart のインスタンス
- リポジトリ: Charts の保存場所(HTTP サーバーまたは OCI レジストリ)
Helm Chart の主要なコンポーネント
my-app-chart/
├── Chart.yaml # Chart のメタデータとバージョン
├── values.yaml # デフォルトの設定値
├── charts/ # 依存する Charts
├── templates/ # Kubernetes リソーステンプレート
│ ├── deployment.yaml
│ ├── service.yaml
│ ├── ingress.yaml
│ ├── _helpers.tpl # テンプレートヘルパー
│ └── NOTES.txt # インストール後のノート
├── .helmignore # パッケージング時に無視するファイル
├── README.md
└── LICENSE
あなたの最初の Helm Chart の作成
新しい Chart の初期化
helm create my-application
cd my-application
これは、デプロイメント、サービス、イングレスのテンプレートの例が含まれたスターターチャートを生成します。
Chart.yaml: メタデータの定義
apiVersion: v2
name: my-application
description: プロダクション用のアプリケーションチャート
type: application
version: 1.0.0 # Chart バージョン
appVersion: "2.4.1" # アプリケーションのバージョン
maintainers:
- name: あなたのチーム
email: team@company.com
dependencies:
- name: postgresql
version: "12.x.x"
repository: "https://charts.bitnami.com/bitnami"
condition: postgresql.enabled
values.yaml: 設定管理
values.yaml ファイルは、ユーザーが上書きできるデフォルトの設定を定義します。このアプローチにより、テンプレートから設定を分離し、開発、ステージング、プロダクション環境を管理し、テンプレートファイルを変更せずにデプロイをカスタマイズできます。
replicaCount: 3
image:
repository: myapp/backend
tag: "1.0.0"
pullPolicy: IfNotPresent
service:
type: ClusterIP
port: 80
ingress:
enabled: true
className: "nginx"
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
hosts:
- host: myapp.example.com
paths:
- path: /
pathType: Prefix
resources:
limits:
cpu: 500m
memory: 512Mi
requests:
cpu: 250m
memory: 256Mi
autoscaling:
enabled: true
minReplicas: 3
maxReplicas: 10
targetCPUUtilizationPercentage: 80
テンプレート: 動的な Kubernetes マニフェスト
テンプレートは Go テンプレート構文を使用して、Kubernetes リソースを動的に生成します。これらのテンプレートは、単純なデプロイメントから、永続ストレージが必要なステートフルなアプリケーションの複雑なステートフルセットまで、あらゆる Kubernetes リソースタイプを生成できます。永続ストレージが必要な安定したアイデンティティを持つアプリケーションでは、ステートフルセットを使用する必要があります。これは、Kubernetes におけるステートフルセットと永続ストレージ のガイドで詳しく説明されています。
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "my-application.fullname" . }}
labels:
{{- include "my-application.labels" . | nindent 4 }}
spec:
{{- if not .Values.autoscaling.enabled }}
replicas: {{ .Values.replicaCount }}
{{- end }}
selector:
matchLabels:
{{- include "my-application.selectorLabels" . | nindent 6 }}
template:
metadata:
labels:
{{- include "my-application.selectorLabels" . | nindent 8 }}
spec:
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- containerPort: 8080
protocol: TCP
resources:
{{- toYaml .Values.resources | nindent 10 }}
テンプレートヘルパー (_helpers.tpl)
繰り返し使用するテンプレート関数を作成して、繰り返しを避けてください:
{{/*
チャートの名前を拡張します。
*/}}
{{- define "my-application.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
デフォルトの完全なアプリケーション名を作成します。
*/}}
{{- define "my-application.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{/*
共通ラベル
*/}}
{{- define "my-application.labels" -}}
helm.sh/chart: {{ include "my-application.chart" . }}
{{ include "my-application.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
Helm Chart の管理: インストールと運用
Chart のインストール
# リポジトリからインストール
helm install my-release bitnami/postgresql
# ローカルディレクトリからインストール
helm install my-app ./my-application
# カスタム値でインストール
helm install my-app ./my-application -f values-production.yaml
# インライン値の上書きでインストール
helm install my-app ./my-application \
--set replicaCount=5 \
--set image.tag=2.0.0
リリースのアップグレード
# 新しい値でアップグレード
helm upgrade my-app ./my-application -f values-production.yaml
# 失敗時に自動ロールバック
helm upgrade my-app ./my-application --atomic --timeout 5m
# リソースの強制更新
helm upgrade my-app ./my-application --force
ロールバックと履歴
# リリース履歴の表示
helm history my-app
# 以前のバージョンへのロールバック
helm rollback my-app
# 特定のリビジョンへのロールバック
helm rollback my-app 3
テストとデバッグ
# 生成されるマニフェストを確認するドライラン
helm install my-app ./my-application --dry-run --debug
# インストールせずにテンプレートのレンダリング
helm template my-app ./my-application
# チャートの問題をチェック
helm lint ./my-application
# テストハックでリリースをテスト
helm test my-app
Helm の高度な機能
チャートの依存関係
Helm Charts は他の Charts に依存でき、再利用可能なコンポーネントから複雑なアプリケーションを構成できます。これは、データベース、メッセージキュー、またはその他のサポートサービスが必要なマイクロサービスをデプロイする際に特に役立ちます。Chart.yaml で依存関係を定義します:
dependencies:
- name: redis
version: "17.x.x"
repository: "https://charts.bitnami.com/bitnami"
condition: redis.enabled
- name: postgresql
version: "12.x.x"
repository: "https://charts.bitnami.com/bitnami"
condition: postgresql.enabled
依存関係を更新します:
helm dependency update ./my-application
Helm フックによるライフサイクル管理
フックはリリースライフサイクルの特定の時点で実行されます:
apiVersion: batch/v1
kind: Job
metadata:
name: {{ include "my-application.fullname" . }}-db-migration
annotations:
"helm.sh/hook": pre-upgrade,pre-install
"helm.sh/hook-weight": "5"
"helm.sh/hook-delete-policy": before-hook-creation
spec:
template:
spec:
containers:
- name: db-migrate
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
command: ["python", "manage.py", "migrate"]
restartPolicy: Never
フックの種類には以下があります:
pre-install: リソースがインストールされる前post-install: すべてのリソースがインストールされた後pre-upgrade: アップグレードの前post-upgrade: アップグレードの後pre-delete: 削除の前post-delete: 削除の後pre-rollback: ロールバックの前post-rollback: ロールバックの後
条件付き論理とフロー制御
{{- if .Values.ingress.enabled }}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ include "my-application.fullname" . }}
{{- with .Values.ingress.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
{{- if .Values.ingress.className }}
ingressClassName: {{ .Values.ingress.className }}
{{- end }}
rules:
{{- range .Values.ingress.hosts }}
- host: {{ .host | quote }}
http:
paths:
{{- range .paths }}
- path: {{ .path }}
pathType: {{ .pathType }}
backend:
service:
name: {{ include "my-application.fullname" $ }}
port:
number: {{ $.Values.service.port }}
{{- end }}
{{- end }}
{{- end }}
OCI レジストリのサポート: 現代的なチャート配布
Helm 3.8 以降、OCI(Open Container Initiative)レジストリのサポートが安定しており、チャートをコンテナイメージと一緒に保存できるようになりました。
OCI レジストリへの公開
# レジストリにログイン
helm registry login registry.example.com
# チャートをパッケージ化
helm package ./my-application
# OCI レジストリにプッシュ
helm push my-application-1.0.0.tgz oci://registry.example.com/charts
# OCI レジストリからインストール
helm install my-app oci://registry.example.com/charts/my-application --version 1.0.0
OCI レジストリの利点
- 統一されたストレージ: チャートとイメージを1か所に保存
- 標準ツール: 既存のレジストリインフラを活用
- より良いセキュリティ: レジストリ認証とスキャンを活用
- シンプルな管理: 別のチャートリポジトリサーバーが不要
本番環境用 Helm Chart のベストプラクティス
1. 値構造とドキュメント化
すべての値をコメント付きでドキュメント化します:
# -- アプリケーションのレプリカ数
replicaCount: 3
# -- イメージ構成
image:
# -- イメージリポジトリ
repository: myapp/backend
# -- イメージプルポリシー
pullPolicy: IfNotPresent
# -- イメージタグ(デフォルトはチャートの appVersion)
tag: ""
2. リソース管理
常にリソースのリクエストと制限を設定します:
resources:
limits:
cpu: 1000m
memory: 1Gi
requests:
cpu: 500m
memory: 512Mi
3. セキュリティコンテキスト
コンテナのセキュリティコンテキストを定義します:
securityContext:
runAsNonRoot: true
runAsUser: 1000
fsGroup: 1000
capabilities:
drop:
- ALL
readOnlyRootFilesystem: true
4. ヘルスチェック
リビネスとレディネスプローブを含めます:
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
5. ConfigMap と Secret 管理
本番環境のデプロイでは、Secret の適切な管理が重要です。値ファイルにSecretを保存する代わりに、外部のSecretマネージャー(Sealed Secrets、External Secrets Operator、またはVault)を使用してください。これにより、データベースパスワード、APIキー、証明書などの機密情報が安全に処理されます:
envFrom:
- secretRef:
name: {{ include "my-application.fullname" . }}-secrets
- configMapRef:
name: {{ include "my-application.fullname" . }}-config
6. スキーマ検証
values.schema.json を作成してユーザー入力を検証します:
{
"$schema": "https://json-schema.org/draft-07/schema#",
"properties": {
"replicaCount": {
"type": "integer",
"minimum": 1
},
"image": {
"type": "object",
"properties": {
"repository": {
"type": "string"
},
"tag": {
"type": "string"
}
},
"required": ["repository"]
}
},
"required": ["image"]
}
7. NOTES.txt によるユーザーへのガイド
インストール後の指示を提供します:
1. アプリケーションのURLを取得するには、以下のコマンドを実行してください:
{{- if .Values.ingress.enabled }}
https://{{ (index .Values.ingress.hosts 0).host }}
{{- else if contains "NodePort" .Values.service.type }}
export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "my-application.fullname" . }})
export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
echo http://$NODE_IP:$NODE_PORT
{{- end }}
2. デプロイメントの監視:
kubectl --namespace {{ .Release.Namespace }} get pods -l "app.kubernetes.io/name={{ include "my-application.name" . }}"
Helm Chart のテストと CI/CD の統合
chart-testing (ct) によるチャートテスト
# chart-testing をインストール
brew install chart-testing
# チャートをリント
ct lint --config ct.yaml
# チャートをインストールしてテスト
ct install --config ct.yaml
GitHub Actions の例
name: Helm Chart CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
lint-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Helm をセットアップ
uses: azure/setup-helm@v3
with:
version: 3.12.0
- name: chart-testing をセットアップ
uses: helm/chart-testing-action@v2
- name: チャートをリント
run: ct lint --config ct.yaml
- name: kind クラスターを作成
uses: helm/kind-action@v1
- name: チャートをインストール
run: ct install --config ct.yaml
Helm と GitOps: ArgoCD と Flux
ArgoCD と Flux のような GitOps ツールは Helm Charts とシームレスに統合され、宣言型で自動化されたデプロイを可能にします。これらのツールは、Git リポジトリの変更を監視し、Helm リリースを自動的に同期します。これにより、継続的なデプロイが簡単になります。複雑なマイクロサービスアーキテクチャでは、Saga パターン などの分散トランザクションパターンが、Helm でデプロイされたサービス間の整合性を管理するために役立ちます。
ArgoCD アプリケーション
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: my-application
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/myorg/my-app-chart
targetRevision: main
path: charts/my-application
helm:
valueFiles:
- values-production.yaml
destination:
server: https://kubernetes.default.svc
namespace: production
syncPolicy:
automated:
prune: true
selfHeal: true
Flux HelmRelease
apiVersion: helm.toolkit.fluxcd.io/v2beta1
kind: HelmRelease
metadata:
name: my-application
namespace: flux-system
spec:
interval: 5m
chart:
spec:
chart: my-application
version: '1.x.x'
sourceRef:
kind: HelmRepository
name: my-charts
values:
replicaCount: 5
image:
tag: "2.0.0"
Helm の一般的な問題のトラブルシューティング
問題: 失敗したアップグレードが保留されている
# リリースのステータスを確認
helm list --all-namespaces
# リリースの詳細を取得
helm status my-app -n namespace
# 必要に応じて強制削除(注意が必要)
kubectl delete secret -n namespace -l owner=helm,name=my-app
問題: テンプレートレンダリングエラー
# テンプレートレンダリングをデバッグ
helm template my-app ./my-application --debug
# Kubernetes に対して検証
helm template my-app ./my-application | kubectl apply --dry-run=client -f -
問題: 値が適用されていない
# 合併された値を確認
helm get values my-app
# すべての計算済み値を表示
helm get values my-app --all
Helm エコシステムとツール
Helm エコシステムには、Kubernetes 技術と統合するための多くのツールが含まれています。サービス間通信、トラフィック管理、セキュリティポリシーなどの高度なネットワーキング機能が必要なアプリケーションをデプロイする際には、Istio と Linkerd によるサービスメッシュ を検討してください。これは Helm Charts を通じてデプロイおよび管理できます。
必須ツール
- Helmfile: Helm Charts をデプロイするための宣言型仕様
- Helm Diff: アップグレード前の変更をプレビュー
- Helm Secrets: SOPS で秘密を管理
- Nova: 過去の Helm Charts を見つける
- Pluto: 過去の Kubernetes API を検出
Helmfile の例
repositories:
- name: bitnami
url: https://charts.bitnami.com/bitnami
releases:
- name: postgresql
namespace: database
chart: bitnami/postgresql
version: 12.x.x
values:
- postgresql:
auth:
database: myapp
username: appuser
- name: my-app
namespace: production
chart: ./charts/my-application
values:
- values-production.yaml
needs:
- database/postgresql
Helm の未来
Helm エコシステムは継続的に進化しています:
- OCIネイティブ: OCIレジストリが標準となる完全な移行
- 改善されたセキュリティ: より良い秘密管理と署名機能
- パフォーマンス: 大規模なChartsのより高速なレンダリングとインストール
- WASMサポート: Chartプラグインと拡張のためのWebAssembly
- より良い検証: 検証とポリシー強制の強化
結論
Helm は Kubernetes パッケージ管理の事実上の標準となり、現代の DevOps プラクティスにおいて習得することが不可欠です。Chart の構造、テンプレート、値管理、ベストプラクティスを理解することで、保守性が高く、安全で、拡張性のある Kubernetes デプロイを実現できます。
シンプルな Charts から始め、ハックや依存関係などの高度な機能を徐々に導入し、GitOps ツールと統合して本番環境用のインフラを構築してください。Helm コミュニティは数千のプリビルドされた Charts を提供していますが、本当の力は、あなたの組織のニーズに合わせたカスタム Charts の作成にあります。ステートレスなアプリケーションや永続ストレージが必要なステートフルなワークロードをデプロイする際、Helm は Kubernetes リソース管理の複雑さを簡略化します。新しい Kubernetes クラスターを設定するチームは、Kubespray で Kubernetes をインストール または Kubernetes ディストリビューション である k3s または MicroK8s を開発環境に使用して検討してください。家庭用ラボや小規模なクラスターのニーズに合ったディストリビューションを評価する際には、Kubernetes ディストリビューションの包括的な比較 を参照してください。
有用なリンク
- 公式 Helm ドキュメント
- Artifact Hub - Helm Charts の発見
- Helm GitHub リポジトリ
- Helm ベストプラクティスガイド
- Chart Testing ツール
- Helmfile
- ArgoCD
- Flux CD
- Bitnami Charts リポジトリ
- Kubernetes Cheatsheet
- Kubespray で Kubernetes をインストール
- 3ノードの家庭用ラボ向け Kubernetes ディストリビューションの包括的な比較
- Kubernetes ディストリビューション - kubeadm、k3s、MicroK8s、Minikube、Talos Linux、RKE2 の概要
- Istio と Linkerd によるサービスメッシュ
- Kubernetes におけるステートフルセットと永続ストレージ
- マイクロサービスにおける Saga パターン