Skip to content
Published on

Helmアーキテクチャ内部分析: Helm 3の設計哲学と構造

Authors

1. Helm 3アーキテクチャ概要

1.1 Helm 2からHelm 3への変化

Helm 2ではクラスタ内にTillerというサーバーサイドコンポーネントが必要でした。Tillerはリリースの管理やチャートのデプロイを担当していましたが、深刻なセキュリティ上の問題がありました。

Tillerの問題点:

  • デフォルトでcluster-admin権限で実行
  • gRPCエンドポイントが認証なしで公開
  • マルチテナント環境で権限分離が不可能
  • RBACバイパスの原因

Helm 3ではTillerが完全に削除されました。Helm CLIがKubernetes APIサーバーと直接通信し、kubeconfigの認証情報をそのまま使用します。

1.2 クライアント専用アーキテクチャ

+------------------+       +---------------------+
|   Helm CLI       | ----> |  Kubernetes API     |
|  (クライアント)   |       |  Server             |
+------------------+       +---------------------+
        |                           |
        v                           v
  +-----------+              +-----------+
  | Chart     |              | Release   |
  | Repository|              | Storage   |
  +-----------+              | (Secrets) |
                             +-----------+

Helm 3のアーキテクチャはシンプルです:

  1. Helm CLI: チャートレンダリング、API呼び出し、リリース管理をすべてクライアントで実行
  2. Kubernetes API Server: リソースの作成/変更/削除の実際の実行
  3. Release Storage: リリースメタデータをSecretまたはConfigMapとして保存

1.3 セキュリティモデルの改善

# Helm 3はkubeconfigのコンテキストをそのまま使用
# RBACが自然に適用される
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: helm-deployer
  namespace: production
rules:
  - apiGroups: ['', 'apps', 'batch']
    resources: ['deployments', 'services', 'configmaps', 'secrets']
    verbs: ['get', 'list', 'create', 'update', 'patch', 'delete']

Helm 3ではユーザーのkubeconfigコンテキストがそのまま適用されるため、Kubernetes RBACによるきめ細かい権限制御が可能です。


2. リリースストレージ

2.1 Secretベースの保存

Helm 3はリリース情報をデフォルトでKubernetes Secretリソースに保存します。

# リリースSecretの照会
kubectl get secrets -l owner=helm -n default

# Secret名の形式: sh.helm.release.v1.RELEASE_NAME.vREVISION
# 例: sh.helm.release.v1.my-app.v1

各Secretには以下の情報がgzip圧縮 + base64エンコードされて保存されます:

  • チャートメタデータ(Chart.yamlの内容)
  • レンダリングされたマニフェスト
  • values(ユーザー提供値 + デフォルト値)
  • リリースステータス(deployed、failed、uninstalledなど)
  • リリースノート

2.2 ConfigMapベースの保存

Secretの代わりにConfigMapを使用することもできます:

# ConfigMapドライバの使用
export HELM_DRIVER=configmap
helm install my-app ./my-chart

2.3 ストレージドライバの比較

ドライバ長所短所
secret(デフォルト)etcd暗号化対応、RBACでアクセス制限Secretリソースサイズ制限(1MB)
configmapSecretアクセス権限不要データが平文で保存
sql大規模リリース管理外部DB必要、設定が複雑
memoryテスト用永続保存不可

3. チャート構造

3.1 基本ディレクトリ構造

my-chart/
  Chart.yaml          # チャートメタデータ(必須)
  Chart.lock          # 依存関係ロックファイル
  values.yaml         # デフォルト設定値(必須)
  values.schema.json  # valuesスキーマ検証
  charts/             # 依存関係チャート(サブチャート)
  crds/               # CRDマニフェスト
  templates/          # Goテンプレートファイル
    deployment.yaml
    service.yaml
    ingress.yaml
    _helpers.tpl      # 名前付きテンプレートヘルパー
    NOTES.txt         # リリースノートテンプレート
    tests/            # テストPod定義
      test-connection.yaml

3.2 Chart.yamlの詳細

apiVersion: v2 # Helm 3では必ずv2
name: my-application
description: A Helm chart for my application
type: application # applicationまたはlibrary
version: 1.2.3 # チャートバージョン(SemVer)
appVersion: '2.0.0' # アプリケーションバージョン
kubeVersion: '>=1.25.0' # サポートKubernetesバージョン範囲
home: https://example.com
sources:
  - https://github.com/example/my-app
maintainers:
  - name: developer
    email: dev@example.com
icon: https://example.com/icon.png
keywords:
  - app
  - web
dependencies:
  - name: postgresql
    version: '12.x.x'
    repository: 'https://charts.bitnami.com/bitnami'
    condition: postgresql.enabled
    tags:
      - database

3.3 CRDディレクトリ

crds/ディレクトリ内のファイルは特別な処理を受けます:

  • installの時のみ適用され、upgradeやrollbackでは無視されます
  • テンプレートレンダリングは適用されません(純粋なYAML)
  • uninstall時にも削除されません(データ保護)
# crds/my-crd.yaml
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  name: myresources.example.com
spec:
  group: example.com
  versions:
    - name: v1
      served: true
      storage: true
      schema:
        openAPIV3Schema:
          type: object
          properties:
            spec:
              type: object
  scope: Namespaced
  names:
    plural: myresources
    singular: myresource
    kind: MyResource

4. テンプレートエンジンの基礎

4.1 Goテンプレートの基本構文

HelmはGoのtext/templateパッケージをベースとし、Sprigライブラリの関数を追加で提供します。

# templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: { { include "my-chart.fullname" . } }
  labels: { { - include "my-chart.labels" . | nindent 4 } }
spec:
  replicas: { { .Values.replicaCount } }
  selector:
    matchLabels: { { - include "my-chart.selectorLabels" . | nindent 6 } }
  template:
    metadata:
      labels: { { - include "my-chart.selectorLabels" . | nindent 8 } }
    spec:
      containers:
        - name: { { .Chart.Name } }
          image: '{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}'
          ports:
            - containerPort: { { .Values.service.port } }

4.2 ビルトインオブジェクト

Helmテンプレートで使用可能な主要なビルトインオブジェクト:

オブジェクト説明
.Releaseリリース情報(Name、Namespace、Revision、IsUpgrade、IsInstall)
.Valuesvalues.yamlとユーザー提供値のマージ結果
.ChartChart.yamlの内容
.Capabilitiesクラスタ能力情報(APIバージョン、Kubernetesバージョン)
.Template現在のテンプレート情報(Name、BasePath)
.Filesチャート内ファイルへのアクセス
# .Releaseオブジェクトの活用例
metadata:
  annotations:
    helm.sh/release-name: {{ .Release.Name }}
    helm.sh/release-namespace: {{ .Release.Namespace }}
    helm.sh/revision: {{ .Release.Revision | quote }}

# .Capabilitiesの活用例
{{- if .Capabilities.APIVersions.Has "networking.k8s.io/v1" }}
apiVersion: networking.k8s.io/v1
{{- else }}
apiVersion: networking.k8s.io/v1beta1
{{- end }}

4.3 Sprig関数の例

# 文字列関数
name: {{ .Values.name | upper }}           # 大文字変換
name: {{ .Values.name | lower }}           # 小文字変換
name: {{ .Values.name | title }}           # タイトルケース
name: {{ .Values.name | trim }}            # 空白除去
name: {{ .Values.name | trunc 63 }}        # 63文字に切り詰め

# デフォルト値
image: {{ .Values.image.tag | default "latest" }}

# 条件付き必須値
name: {{ required "A name is required" .Values.name }}

# エンコーディング
data: {{ .Values.secret | b64enc }}

# 日付
timestamp: {{ now | date "2006-01-02T15:04:05Z07:00" }}

5. 依存関係管理

5.1 Chart.yamlでの依存関係宣言

# Chart.yaml
dependencies:
  - name: redis
    version: '17.x.x'
    repository: 'https://charts.bitnami.com/bitnami'
    condition: redis.enabled
    tags:
      - cache
  - name: postgresql
    version: '12.x.x'
    repository: 'https://charts.bitnami.com/bitnami'
    condition: postgresql.enabled
    tags:
      - database

5.2 Chart.lockファイル

# 依存関係のダウンロードとロックファイルの生成
helm dependency update ./my-chart

# 既存のChart.lockから正確なバージョンでビルド
helm dependency build ./my-chart

5.3 conditionとtags

condition: 特定の値がtrueの場合のみサブチャートを有効化

# values.yaml
redis:
  enabled: true
postgresql:
  enabled: false # PostgreSQLサブチャートを無効化

tags: タググループ単位でサブチャートを有効化/無効化

# values.yaml
tags:
  cache: true # cacheタグのすべての依存関係を有効化
  database: false # databaseタグのすべての依存関係を無効化

conditionはtagsより優先順位が高いです。

5.4 グローバル値

# values.yaml
global:
  imageRegistry: myregistry.io
  imagePullSecrets:
    - name: my-pull-secret
  storageClass: fast-ssd

global以下の値はすべてのサブチャートからアクセス可能です。


6. OCIレジストリサポート

6.1 OCIベースのチャート管理

Helm 3.8からOCIレジストリサポートがGA(Generally Available)です:

# レジストリにログイン
helm registry login registry.example.com

# チャートをOCIアーティファクトとしてパッケージングとプッシュ
helm package ./my-chart
helm push my-chart-1.0.0.tgz oci://registry.example.com/charts

# OCIレジストリからチャートをインストール
helm install my-release oci://registry.example.com/charts/my-chart --version 1.0.0

7. まとめ

Helm 3のアーキテクチャはセキュリティシンプルさ拡張性を核心的な設計原則としています:

  1. Tiller削除: クラスタ内サーバーコンポーネントなしでCLIのみで動作
  2. RBACネイティブ: kubeconfigベースの認証/認可でKubernetes RBACと自然に統合
  3. SecretベースのRelease Storage: etcd暗号化サポート、リリース履歴管理
  4. 構造化されたチャート: Chart.yaml、values.yaml、templates/などの明確な関心の分離
  5. OCIレジストリサポート: コンテナイメージと同じインフラでチャート管理

次の記事では、Helmテンプレートエンジンの内部動作をさらに深く分析します。