Helm は Kubernetes のパッケージマネージャーとして、アプリケーションのデプロイを再現可能かつ管理しやすくする標準ツールです。しかし、チャートの品質はプロジェクトの運用コストに直結します。テンプレートの過度な抽象化、テスト不足、セキュリティの見落としは、本番環境で深刻な問題を引き起こします。Kubo では Helm チャートを活用した宣言的デプロイを標準パターンとして採用しており、本記事のベストプラクティスは Kubo 環境にそのまま適用できます。
チャート構造とディレクトリ設計
Helm チャートの品質は、構造設計の段階で決まります。Helm 公式ドキュメントと実践から導かれたベストプラクティスを紹介します。
標準的なチャート構造
my-app/
├── Chart.yaml # チャートのメタデータ
├── Chart.lock # 依存関係のロックファイル
├── values.yaml # デフォルト設定値
├── values-dev.yaml # 開発環境のオーバーライド
├── values-staging.yaml # ステージング環境のオーバーライド
├── values-production.yaml # 本番環境のオーバーライド
├── templates/
│ ├── _helpers.tpl # 共通テンプレートヘルパー
│ ├── deployment.yaml
│ ├── service.yaml
│ ├── ingress.yaml
│ ├── hpa.yaml
│ ├── serviceaccount.yaml
│ ├── configmap.yaml
│ └── tests/
│ └── test-connection.yaml
├── charts/ # サブチャート(依存関係)
└── .helmignore
環境別 values ファイルの分離
Carlos Neto のブログが指摘するように、単一の values.yaml で全環境を管理しようとすると、ファイルが肥大化して管理不能になります。環境ごとに values ファイルを分離し、デプロイ時に明示的に指定します。
# 開発環境
helm upgrade --install my-app ./my-app -f values.yaml -f values-dev.yaml
# 本番環境
helm upgrade --install my-app ./my-app -f values.yaml -f values-production.yaml
values.yaml にはデフォルト値を定義し、環境固有ファイルではオーバーライドが必要な値のみを記述します。これにより各ファイルが小さく保たれ、差分が明確になります。
テンプレート設計の原則: DRY と YAGNI
Helm テンプレートの品質を左右する 2 つの重要な原則があります。
DRY(Don't Repeat Yourself)
マニフェストの重複はエラーの温床です。共通パターンは _helpers.tpl に抽出し、テンプレート関数として再利用します。
{{/* _helpers.tpl */}}
{{- define "my-app.labels" -}}
app.kubernetes.io/name: {{ include "my-app.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
helm.sh/chart: {{ include "my-app.chart" . }}
{{- end }}
{{- define "my-app.selectorLabels" -}}
app.kubernetes.io/name: {{ include "my-app.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
YAGNI(You Aren't Gonna Need It)
テンプレートの過度な抽象化は最大のアンチパターンです。実践的な Helm 開発ガイドは「すべての条件分岐、関数、パラメータは認知的オーバーヘッドを増やす」と警告しています。
悪い例: 不要な抽象化
{{- if .Values.deployment.enabled }}
{{- if .Values.deployment.strategy.enabled }}
strategy:
type: {{ .Values.deployment.strategy.type | default "RollingUpdate" }}
{{- end }}
{{- end }}
良い例: シンプルで必要十分
strategy:
type: {{ .Values.strategy | default "RollingUpdate" }}
現在の要件を満たすシンプルなテンプレートを書き、将来の仮想的な要件のために複雑化させないことが重要です。
ライブラリチャートの活用
組織内で複数のチャートがある場合、Bitnami Common Chart のようなライブラリチャートに共通テンプレートを集約します。ライブラリチャートはリソースを直接デプロイせず、テンプレートヘルパーのみを提供します。
# Chart.yaml
dependencies:
- name: common
version: 2.x.x
repository: https://charts.bitnami.com/bitnami
Captain.AI は、テンプレートの品質分析や最適化提案も AI で支援します。
テスト戦略: 品質を担保する多層アプローチ
Helm チャートのテストは、ci-cd パイプラインの信頼性に直結します。Chart Testing(ct)ツールと helm-unittest を組み合わせた多層テストを実装しましょう。
レイヤー 1: Lint と静的検証
# Helm 組み込みの lint
helm lint ./my-app --values values-production.yaml
# Chart Testing による厳密な lint
ct lint --chart-dirs charts/ --all
レイヤー 2: ユニットテスト(helm-unittest)
# tests/deployment_test.yaml
suite: Deployment Tests
templates:
- deployment.yaml
tests:
- it: should set correct replicas
set:
replicaCount: 5
asserts:
- equal:
path: spec.replicas
value: 5
- it: should have resource limits
asserts:
- isNotEmpty:
path: spec.template.spec.containers[0].resources.limits
- it: should use correct image
set:
image.repository: my-registry/my-app
image.tag: "v1.0.0"
asserts:
- equal:
path: spec.template.spec.containers[0].image
value: "my-registry/my-app:v1.0.0"
レイヤー 3: テンプレートレンダリング検証
# テンプレートを YAML にレンダリングして検証
helm template my-app ./my-app -f values-production.yaml | kubeval --strict
レイヤー 4: 統合テスト(helm test)
Helm の chart test 機能を使い、デプロイ後の実環境テストを実行します。
# templates/tests/test-connection.yaml
apiVersion: v1
kind: Pod
metadata:
name: "{{ include "my-app.fullname" . }}-test"
annotations:
"helm.sh/hook": test
spec:
containers:
- name: curl-test
image: curlimages/curl:latest
command: ['curl', '--fail', 'http://{{ include "my-app.fullname" . }}:{{ .Values.service.port }}']
restartPolicy: Never
helm test my-release
OCI レジストリとチャート配布
Helm 3.8 以降、OCI(Open Container Initiative)レジストリがチャート配布の推奨メカニズムとなっています。コンテナイメージと同じレジストリでチャートを管理でき、運用の一元化が可能です。
OCI レジストリへのプッシュ
# パッケージング
helm package ./my-app
# レジストリにログイン
helm registry login ghcr.io -u $GITHUB_USER -p $GITHUB_TOKEN
# プッシュ
helm push my-app-1.0.0.tgz oci://ghcr.io/your-org/charts
OCI レジストリからのインストール
helm install my-app oci://ghcr.io/your-org/charts/my-app --version 1.0.0
ci-cd パイプラインでの自動公開
# GitHub Actions 例
- name: Publish Helm Chart
run: |
helm package ./charts/my-app --version ${{ github.ref_name }}
helm push my-app-${{ github.ref_name }}.tgz \
oci://ghcr.io/${{ github.repository_owner }}/charts
Kubo では OCI 準拠のレジストリが統合されており、チャートの公開と管理がシームレスに行えます。
セキュリティとリソース管理
リソース制限の適切な設定
# values.yaml
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 512Mi
環境ごとにリソース値を調整します。開発環境では最小限に、本番ではトラフィックに応じた適切な値を設定します。
セキュリティコンテキスト
securityContext:
runAsNonRoot: true
runAsUser: 1000
readOnlyRootFilesystem: true
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
シークレットの外部化
テンプレート内で Kubernetes Secrets を参照しつつ、シークレットデータ自体は External Secrets Operator や Sealed Secrets で管理します。
脆弱性スキャン
# Trivy によるチャートと参照イメージのスキャン
trivy config ./my-app/
trivy image my-registry/my-app:v1.0.0
# Kubescape による設定スキャン
kubescape scan framework nsa ./my-app/
Trivy と Kubescape を CI パイプラインに統合し、デプロイ前にセキュリティ問題を検出します。
まとめ: Kubo で Helm チャートを最大限に活用する
Helm チャートの品質は、Kubernetes 運用の成功を左右します。DRY と YAGNI のバランス、多層テスト戦略、OCI レジストリによる配布、セキュリティベストプラクティスを組み合わせることで、保守しやすく安全なチャートを開発できます。
Kubo は Helm チャートによる宣言的デプロイを標準パターンとしてサポートしており、ArgoCD や FluxCD との連携も組み込まれています。Captain.AI がチャートの品質分析やテンプレート最適化を AI で支援し、開発者の生産性を最大化します。Helm チャート開発の改善に取り組みたい方は、ぜひお問い合わせください。