Skip to main content

Helm チャート開発のベストプラクティス 2025

Helm は Kubernetes のパッケージマネージャーとして、アプリケーションのデプロイを再現可能かつ管理しやすくする標準ツールです。しかし、チャートの品質はプロジェクトの運用コストに直結します。テンプレートの過度な抽象化、テスト不足、セキュリティの見落としは、本番環境で深刻な問題を引き起こします。Kubo では Helm チャートを活用した宣言的デプロイを標準パターンとして採用しており、本記事のベストプラクティスは Kubo 環境にそのまま適用できます。

チャート構造とディレクトリ設計

Helm チャートの品質は、構造設計の段階で決まります。Helm 公式ドキュメントと実践から導かれたベストプラクティスを紹介します。

標準的なチャート構造

text
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 ファイルを分離し、デプロイ時に明示的に指定します。

bash
# 開発環境
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 に抽出し、テンプレート関数として再利用します。

yaml
{{/* _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 開発ガイドは「すべての条件分岐、関数、パラメータは認知的オーバーヘッドを増やす」と警告しています。

悪い例: 不要な抽象化

yaml
{{- if .Values.deployment.enabled }}
{{- if .Values.deployment.strategy.enabled }}
strategy:
  type: {{ .Values.deployment.strategy.type | default "RollingUpdate" }}
{{- end }}
{{- end }}

良い例: シンプルで必要十分

yaml
strategy:
  type: {{ .Values.strategy | default "RollingUpdate" }}

現在の要件を満たすシンプルなテンプレートを書き、将来の仮想的な要件のために複雑化させないことが重要です。

ライブラリチャートの活用

組織内で複数のチャートがある場合、Bitnami Common Chart のようなライブラリチャートに共通テンプレートを集約します。ライブラリチャートはリソースを直接デプロイせず、テンプレートヘルパーのみを提供します。

yaml
# 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 と静的検証

bash
# Helm 組み込みの lint
helm lint ./my-app --values values-production.yaml

# Chart Testing による厳密な lint
ct lint --chart-dirs charts/ --all

レイヤー 2: ユニットテスト(helm-unittest)

yaml
# 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: テンプレートレンダリング検証

bash
# テンプレートを YAML にレンダリングして検証
helm template my-app ./my-app -f values-production.yaml | kubeval --strict

レイヤー 4: 統合テスト(helm test)

Helm の chart test 機能を使い、デプロイ後の実環境テストを実行します。

yaml
# 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
bash
helm test my-release

OCI レジストリとチャート配布

Helm 3.8 以降、OCI(Open Container Initiative)レジストリがチャート配布の推奨メカニズムとなっています。コンテナイメージと同じレジストリでチャートを管理でき、運用の一元化が可能です。

OCI レジストリへのプッシュ

bash
# パッケージング
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 レジストリからのインストール

bash
helm install my-app oci://ghcr.io/your-org/charts/my-app --version 1.0.0

ci-cd パイプラインでの自動公開

yaml
# 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 準拠のレジストリが統合されており、チャートの公開と管理がシームレスに行えます。

セキュリティとリソース管理

リソース制限の適切な設定

yaml
# values.yaml
resources:
  requests:
    cpu: 100m
    memory: 128Mi
  limits:
    cpu: 500m
    memory: 512Mi

環境ごとにリソース値を調整します。開発環境では最小限に、本番ではトラフィックに応じた適切な値を設定します。

セキュリティコンテキスト

yaml
securityContext:
  runAsNonRoot: true
  runAsUser: 1000
  readOnlyRootFilesystem: true
  allowPrivilegeEscalation: false
  capabilities:
    drop:
      - ALL

シークレットの外部化

テンプレート内で Kubernetes Secrets を参照しつつ、シークレットデータ自体は External Secrets OperatorSealed Secrets で管理します。

脆弱性スキャン

bash
# Trivy によるチャートと参照イメージのスキャン
trivy config ./my-app/
trivy image my-registry/my-app:v1.0.0

# Kubescape による設定スキャン
kubescape scan framework nsa ./my-app/

TrivyKubescape を CI パイプラインに統合し、デプロイ前にセキュリティ問題を検出します。

まとめ: Kubo で Helm チャートを最大限に活用する

Helm チャートの品質は、Kubernetes 運用の成功を左右します。DRY と YAGNI のバランス、多層テスト戦略、OCI レジストリによる配布、セキュリティベストプラクティスを組み合わせることで、保守しやすく安全なチャートを開発できます。

Kubo は Helm チャートによる宣言的デプロイを標準パターンとしてサポートしており、ArgoCD や FluxCD との連携も組み込まれています。Captain.AI がチャートの品質分析やテンプレート最適化を AI で支援し、開発者の生産性を最大化します。Helm チャート開発の改善に取り組みたい方は、ぜひお問い合わせください。

← Back to all posts