Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Helm Chart デプロイ完全ガイド ── Kubernetes 環境準備から Ingress 公開・運用まで

Dify Enterprise を本番環境で運用する場合、Kubernetes + Helm Chart が推奨されるデプロイパスです。本記事では、クラスタの前提確認から helm install、Ingress 設定、動作検証、アップグレード・ロールバックまでを網羅的に解説します。

前提知識: Kubernetes の基本概念(Pod, Deployment, Service, PVC, Ingress)と kubectl の基本操作を理解していることを前提とします。Docker Compose 版を先に体験しておくと、サービス構成の理解がスムーズです。 → Docker Compose デプロイガイド


1. 前提条件

1.1 Kubernetes クラスタ要件

項目要件
Kubernetes バージョン1.24 以上
Helm バージョン3.14 以上
ノード数(推奨)3 ノード以上(本番)
ノードあたりの推奨スペック4 vCPU / 16 GB RAM 以上
StorageClass動的プロビジョニング対応の StorageClass が必要
Ingress Controllernginx-ingress または同等のコントローラが稼働中

1.2 外部リソース

Dify Enterprise の Helm Chart は、以下の外部リソースを事前に準備することを前提としています。本番環境ではマネージドサービスの利用を推奨します。

リソース用途推奨マネージドサービス例
PostgreSQLメインデータベースAmazon RDS, Cloud SQL, Azure Database for PostgreSQL
Redisキャッシュ・タスクキューAmazon ElastiCache, Cloud Memorystore, Azure Cache for Redis
オブジェクトストレージファイル・ドキュメント保存Amazon S3, Google Cloud Storage, Azure Blob Storage
ベクトルデータベースナレッジベースインデックスWeaviate Cloud, Qdrant Cloud, Zilliz (Milvus)

Note: Helm Chart 内にこれらのミドルウェアを同梱する構成も可能ですが、本番環境ではデータの永続性と運用性の観点からマネージドサービスの利用を推奨します。

1.3 ツールのバージョン確認

# Kubernetes バージョン確認
kubectl version --short

# Helm バージョン確認
helm version --short

# クラスタのノード状態確認
kubectl get nodes -o wide

# StorageClass の確認
kubectl get storageclass

# Ingress Controller の確認
kubectl get pods -n ingress-nginx

2. Namespace の設計

2.1 なぜ Namespace 設計が重要なのか

Dify Enterprise では License が Namespace に紐づく 仕様があります。つまり、Namespace を後から変更すると License の再アクティベーションが必要になる場合があります。最初の段階で慎重に設計してください。

2.2 推奨 Namespace 構成

# 開発環境
kubectl create namespace dify-dev

# ステージング環境
kubectl create namespace dify-staging

# 本番環境
kubectl create namespace dify-prod

2.3 Namespace 設計の指針

環境Namespace 名用途License
開発dify-dev機能検証、開発者テスト開発用 License
ステージングdify-stagingリリース前検証、負荷テストステージング用 License
本番dify-prodエンドユーザー向け本番運用本番用 License
# 以降の手順では本番環境を例に進めます
export NAMESPACE=dify-prod
kubectl config set-context --current --namespace=${NAMESPACE}

3. Helm リポジトリの追加

3.1 リポジトリ登録

# Dify の Helm リポジトリを追加
helm repo add dify https://helm.dify.ai

# リポジトリの更新
helm repo update

# 利用可能なバージョンの確認
helm search repo dify/dify --versions

Enterprise 版のプライベートリポジトリが提供されている場合は、そちらの URL に読み替えてください。

3.2 デフォルト values の確認

# デフォルトの values.yaml を確認(全設定項目の一覧)
helm show values dify/dify > values-default.yaml

# ファイルを開いて構造を把握
less values-default.yaml

デフォルト values を直接編集するのではなく、カスタム values ファイルを作成してオーバーライドする運用を推奨します。


4. values.yaml のカスタマイズ

4.1 カスタム values ファイルの作成

以下は、本番環境向けのカスタム values.yaml の構成例です。

# values-prod.yaml
# Dify Enterprise 本番環境設定

# ── グローバル設定 ──
global:
  # 外部からアクセスする URL
  host: "dify.example.com"
  enableTLS: true
  edition: "enterprise"
  # シークレットキー(必ず変更)
  secretKey: "sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

# ── API サービス ──
api:
  replicaCount: 2
  resources:
    requests:
      cpu: "1"
      memory: "2Gi"
    limits:
      cpu: "2"
      memory: "4Gi"
  env:
    LOG_LEVEL: "INFO"

# ── Worker サービス ──
worker:
  replicaCount: 2
  resources:
    requests:
      cpu: "1"
      memory: "2Gi"
    limits:
      cpu: "2"
      memory: "4Gi"

# ── Web フロントエンド ──
web:
  replicaCount: 2
  resources:
    requests:
      cpu: "500m"
      memory: "512Mi"
    limits:
      cpu: "1"
      memory: "1Gi"

# ── Plugin Daemon ──
pluginDaemon:
  replicaCount: 1
  resources:
    requests:
      cpu: "500m"
      memory: "512Mi"
    limits:
      cpu: "1"
      memory: "1Gi"

4.2 外部データベースの設定

# values-prod.yaml(続き)

# ── PostgreSQL(外部マネージドサービス) ──
postgresql:
  # Chart 内蔵の PostgreSQL を無効化
  enabled: false

externalPostgresql:
  host: "dify-db.xxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com"
  port: 5432
  username: "dify"
  password: "your-secure-password"   # Secret 経由を推奨
  database: "dify"
  sslMode: "require"

# ── Redis(外部マネージドサービス) ──
redis:
  enabled: false

externalRedis:
  host: "dify-redis.xxxxxxxxxxxx.apne1.cache.amazonaws.com"
  port: 6379
  password: "your-secure-password"
  useTLS: true

4.3 ストレージ設定

# values-prod.yaml(続き)

# ── オブジェクトストレージ ──
storage:
  type: "s3"
  s3:
    endpoint: "https://s3.ap-northeast-1.amazonaws.com"
    bucketName: "dify-prod-storage"
    accessKey: "AKIAIOSFODNN7EXAMPLE"
    secretKey: "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
    region: "ap-northeast-1"

4.4 ベクトルデータベース設定

# values-prod.yaml(続き)

# ── ベクトルデータベース ──
vectorStore:
  type: "weaviate"    # weaviate | qdrant | milvus | pgvector

  weaviate:
    endpoint: "https://your-cluster.weaviate.network"
    apiKey: "your-weaviate-api-key"

  # Qdrant を使用する場合
  # qdrant:
  #   endpoint: "https://your-cluster.qdrant.io"
  #   apiKey: "your-qdrant-api-key"

4.5 Ingress 設定

# values-prod.yaml(続き)

# ── Ingress ──
ingress:
  enabled: true
  className: "nginx"
  annotations:
    cert-manager.io/cluster-issuer: "letsencrypt-prod"
    nginx.ingress.kubernetes.io/proxy-body-size: "100m"
    nginx.ingress.kubernetes.io/proxy-read-timeout: "300"
    nginx.ingress.kubernetes.io/proxy-send-timeout: "300"
  hosts:
    - host: "dify.example.com"
      paths:
        - path: /
          pathType: Prefix
  tls:
    - secretName: dify-tls
      hosts:
        - "dify.example.com"

4.6 永続化ボリューム設定

Chart 内蔵のミドルウェアを使用する場合(検証環境向け)は PVC の設定が必要です。

# 検証環境向け: Chart 内蔵ミドルウェア使用時
postgresql:
  enabled: true
  persistence:
    enabled: true
    storageClass: "gp3"
    size: "50Gi"

redis:
  enabled: true
  persistence:
    enabled: true
    storageClass: "gp3"
    size: "10Gi"

5. Secret の管理

5.1 Kubernetes Secret の作成

values.yaml にパスワードを直接記述するのではなく、Kubernetes Secret を使用することを推奨します。

# データベースパスワードの Secret
kubectl create secret generic dify-db-secret \
  --namespace=${NAMESPACE} \
  --from-literal=password='your-secure-db-password'

# Redis パスワードの Secret
kubectl create secret generic dify-redis-secret \
  --namespace=${NAMESPACE} \
  --from-literal=password='your-secure-redis-password'

# Dify シークレットキーの Secret
kubectl create secret generic dify-secret-key \
  --namespace=${NAMESPACE} \
  --from-literal=secretKey="$(openssl rand -base64 42)"

# S3 認証情報の Secret
kubectl create secret generic dify-s3-secret \
  --namespace=${NAMESPACE} \
  --from-literal=accessKey='AKIAIOSFODNN7EXAMPLE' \
  --from-literal=secretKey='wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY'

5.2 values.yaml での Secret 参照

# Secret を参照する values.yaml の記述例
externalPostgresql:
  host: "dify-db.xxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com"
  port: 5432
  username: "dify"
  database: "dify"
  existingSecret: "dify-db-secret"
  existingSecretPasswordKey: "password"

6. Helm Install の実行

6.1 Dry-run による事前確認

# テンプレートのレンダリング結果を確認(実際にはデプロイしない)
helm template dify dify/dify \
  --namespace=${NAMESPACE} \
  -f values-prod.yaml > rendered.yaml

# レンダリング結果を確認
less rendered.yaml

# dry-run で Kubernetes API への送信をシミュレート
helm install dify dify/dify \
  --namespace=${NAMESPACE} \
  -f values-prod.yaml \
  --dry-run

6.2 インストールの実行

# Helm Chart のインストール
helm upgrade --install dify dify/dify \
  --namespace=${NAMESPACE} \
  -f values-prod.yaml \
  --wait \
  --timeout 10m

helm upgrade --install は冪等性があり、初回はインストール、2 回目以降はアップグレードとして動作します。

6.3 インストール状態の確認

# Helm リリースの確認
helm list --namespace=${NAMESPACE}

# リリースの詳細確認
helm status dify --namespace=${NAMESPACE}

# 適用された values の確認
helm get values dify --namespace=${NAMESPACE}

7. デプロイ後の検証

7.1 Pod の状態確認

# 全 Pod の状態を確認
kubectl get pods --namespace=${NAMESPACE} -o wide

# 期待される出力例
# NAME                          READY   STATUS    RESTARTS   AGE   NODE
# dify-api-xxxxxxxxxx-xxxxx     1/1     Running   0          5m    node-1
# dify-api-xxxxxxxxxx-yyyyy     1/1     Running   0          5m    node-2
# dify-worker-xxxxxxxxxx-xxxxx  1/1     Running   0          5m    node-1
# dify-worker-xxxxxxxxxx-yyyyy  1/1     Running   0          5m    node-3
# dify-web-xxxxxxxxxx-xxxxx     1/1     Running   0          5m    node-2
# dify-web-xxxxxxxxxx-yyyyy     1/1     Running   0          5m    node-3

# Pod が Running にならない場合
kubectl describe pod <pod-name> --namespace=${NAMESPACE}
kubectl logs <pod-name> --namespace=${NAMESPACE}

7.2 Service と Ingress の確認

# Service の確認
kubectl get svc --namespace=${NAMESPACE}

# Ingress の確認
kubectl get ingress --namespace=${NAMESPACE}

# Ingress の詳細(割り当てられた IP / ホスト名を確認)
kubectl describe ingress dify --namespace=${NAMESPACE}

7.3 PVC の確認

# 永続化ボリュームの状態確認
kubectl get pvc --namespace=${NAMESPACE}

# 全 PVC が Bound であることを確認
# NAME                STATUS   VOLUME         CAPACITY   STORAGECLASS
# dify-postgresql-0   Bound    pvc-xxxxxxxx   50Gi       gp3
# dify-redis-0        Bound    pvc-yyyyyyyy   10Gi       gp3

7.4 DNS とアクセス確認

# Ingress の EXTERNAL-IP を取得
INGRESS_IP=$(kubectl get ingress dify --namespace=${NAMESPACE} \
  -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
echo "Ingress IP: ${INGRESS_IP}"

# DNS が設定されるまでの間、/etc/hosts で一時的に名前解決
# sudo sh -c "echo '${INGRESS_IP} dify.example.com' >> /etc/hosts"

# ヘルスチェック
curl -sk https://dify.example.com/v1/health

# ブラウザでアクセス
# https://dify.example.com

7.5 包括的な動作確認チェックリスト

# 以下のコマンドで全リソースの状態を一括確認
kubectl get all,ingress,pvc,secret --namespace=${NAMESPACE}
確認項目コマンド / 方法期待結果
Pod 全体kubectl get pods全て Running (1/1)
Servicekubectl get svcClusterIP が割り当て済み
Ingresskubectl get ingressADDRESS が割り当て済み
PVCkubectl get pvc全て Bound
API ヘルスcurl /v1/health{"status": "ok"}
UI アクセスブラウザで URL初期セットアップ画面が表示
DB 接続api Pod のログ接続エラーなし
Redis 接続worker Pod のログ接続エラーなし

8. アップグレードとロールバック

8.1 アップグレード

# リポジトリを最新化
helm repo update

# 新バージョンの確認
helm search repo dify/dify --versions

# values.yaml を更新した後にアップグレード
helm upgrade dify dify/dify \
  --namespace=${NAMESPACE} \
  -f values-prod.yaml \
  --wait \
  --timeout 10m

# 特定バージョンを指定してアップグレード
helm upgrade dify dify/dify \
  --namespace=${NAMESPACE} \
  -f values-prod.yaml \
  --version 1.2.3 \
  --wait

8.2 アップグレード前のチェックリスト

ステップコマンド目的
1. 現在のバージョン確認helm list -n ${NAMESPACE}現在のリリース情報
2. 変更内容の確認helm diff upgrade dify dify/dify -f values-prod.yaml差分の事前確認(helm-diff プラグイン)
3. DB バックアップマネージドサービスのスナップショットデータ保護
4. dry-runhelm upgrade --dry-run ...テンプレート確認
5. 実行helm upgrade ...アップグレード実行
6. 検証kubectl get pods, curl /health正常動作確認

8.3 ロールバック

# リリース履歴の確認
helm history dify --namespace=${NAMESPACE}

# 1 つ前のリビジョンにロールバック
helm rollback dify --namespace=${NAMESPACE}

# 特定のリビジョンにロールバック
helm rollback dify 3 --namespace=${NAMESPACE}

# ロールバック後の確認
kubectl get pods --namespace=${NAMESPACE}
helm status dify --namespace=${NAMESPACE}

9. スケーリング

9.1 手動スケーリング

# values.yaml を変更して適用
# api:
#   replicaCount: 4

helm upgrade dify dify/dify \
  --namespace=${NAMESPACE} \
  -f values-prod.yaml

# または kubectl で直接スケール(一時的な対応)
kubectl scale deployment dify-api --replicas=4 --namespace=${NAMESPACE}

9.2 HPA(Horizontal Pod Autoscaler)の設定

# values-prod.yaml に追加
api:
  autoscaling:
    enabled: true
    minReplicas: 2
    maxReplicas: 10
    targetCPUUtilizationPercentage: 70
    targetMemoryUtilizationPercentage: 80

worker:
  autoscaling:
    enabled: true
    minReplicas: 2
    maxReplicas: 8
    targetCPUUtilizationPercentage: 70
# HPA の状態確認
kubectl get hpa --namespace=${NAMESPACE}

# HPA の詳細確認
kubectl describe hpa dify-api --namespace=${NAMESPACE}

10. 監視とログ

10.1 Pod ログの確認

# API サーバーのログ
kubectl logs -f deployment/dify-api --namespace=${NAMESPACE}

# Worker のログ
kubectl logs -f deployment/dify-worker --namespace=${NAMESPACE}

# 複数 Pod のログを同時に確認(stern を使用)
# brew install stern  (macOS)
stern dify-api --namespace=${NAMESPACE}
stern dify-worker --namespace=${NAMESPACE}

10.2 リソース使用状況

# Pod のリソース使用量(metrics-server が必要)
kubectl top pods --namespace=${NAMESPACE}

# ノードのリソース使用量
kubectl top nodes

10.3 Prometheus / Grafana 連携

本番環境では Prometheus + Grafana によるメトリクス監視を推奨します。

# values-prod.yaml に追加
api:
  podAnnotations:
    prometheus.io/scrape: "true"
    prometheus.io/port: "5001"
    prometheus.io/path: "/metrics"

11. トラブルシューティング

11.1 Pod が起動しない(Pending)

# Pod の詳細を確認
kubectl describe pod <pod-name> --namespace=${NAMESPACE}

# よくある原因:
# - リソース不足 → ノードの追加またはリソースリクエストの削減
# - PVC がバインドされない → StorageClass の確認
# - イメージ Pull 失敗 → imagePullSecrets の確認

11.2 Pod が CrashLoopBackOff

# コンテナのログを確認
kubectl logs <pod-name> --namespace=${NAMESPACE} --previous

# よくある原因:
# - データベース接続失敗 → externalPostgresql の設定確認
# - Redis 接続失敗 → externalRedis の設定確認
# - SECRET_KEY が未設定 → values.yaml の global.secretKey 確認

11.3 Ingress にアクセスできない

# Ingress Controller のログ
kubectl logs -f deployment/ingress-nginx-controller -n ingress-nginx

# Ingress リソースの確認
kubectl describe ingress dify --namespace=${NAMESPACE}

# バックエンド Service のエンドポイント確認
kubectl get endpoints --namespace=${NAMESPACE}

# よくある原因:
# - Ingress Controller が未インストール
# - className の不一致
# - TLS Secret が存在しない

11.4 ナレッジベースが動作しない

# Worker のログを確認
kubectl logs -f deployment/dify-worker --namespace=${NAMESPACE}

# ベクトルデータベースへの接続確認
kubectl exec -it deployment/dify-api --namespace=${NAMESPACE} -- \
  curl -s http://weaviate-endpoint:8080/v1/.well-known/ready

# よくある原因:
# - ベクトルデータベースの接続情報が不正
# - Worker がダウンしている

11.5 よくあるエラーと対処法

エラー原因対処法
ImagePullBackOffレジストリ認証失敗imagePullSecrets を設定
Pending (PVC)StorageClass なしkubectl get sc で確認、作成
CrashLoopBackOff設定エラーkubectl logs --previous でログ確認
502 Bad Gatewayバックエンド未起動Pod の状態と Service の Endpoints 確認
certificate verify failedTLS 設定不備cert-manager のログと Secret 確認

12. 本番運用のベストプラクティス

12.1 values.yaml の Git 管理

# values ファイルを Git で管理
mkdir -p dify-helm-config
cd dify-helm-config
git init

# 環境ごとの values ファイル
# values-dev.yaml
# values-staging.yaml
# values-prod.yaml

# Secret 値は values に含めず、Kubernetes Secret で管理
# .gitignore に機密情報を含むファイルを追加
echo "values-*-secrets.yaml" >> .gitignore

12.2 バックアップ戦略

対象方法頻度
PostgreSQLマネージドサービスの自動バックアップ + 手動スナップショット日次自動 + リリース前手動
Redisマネージドサービスの自動バックアップ日次自動
オブジェクトストレージバージョニング + クロスリージョンレプリケーションリアルタイム
ベクトルデータベーススナップショット週次
Helm valuesGit リポジトリ変更都度

12.3 Namespace と License の関係

graph LR
    subgraph "Kubernetes クラスタ"
        NS1[dify-dev<br/>namespace]
        NS2[dify-staging<br/>namespace]
        NS3[dify-prod<br/>namespace]
    end

    L1[開発 License] --> NS1
    L2[ステージング License] --> NS2
    L3[本番 License] --> NS3

    style L1 fill:#e1f5fe
    style L2 fill:#fff3e0
    style L3 fill:#e8f5e9

重要な注意点:

  • License は Namespace に紐づくため、Namespace 名を変更すると再アクティベーションが必要
  • 1 つの License で複数の Namespace にデプロイすることはできない
  • License の有効期限・シート数は Dify Enterprise の契約に依存

まとめ

本記事では、Dify Enterprise の Helm Chart デプロイについて、以下の流れで解説しました。

  1. 前提条件 – Kubernetes / Helm のバージョン要件と外部リソースの準備
  2. Namespace 設計 – License との紐づきを考慮した環境分離
  3. Helm リポジトリの追加 – Chart の取得と values の確認
  4. values.yaml のカスタマイズ – 外部 DB、ストレージ、Ingress の設定
  5. Secret 管理 – パスワード・認証情報の安全な取り扱い
  6. Helm Install – dry-run からインストール実行まで
  7. デプロイ後の検証 – Pod、Service、Ingress、PVC の確認
  8. アップグレードとロールバック – 安全な更新手順
  9. スケーリング – 手動スケールと HPA の設定
  10. 監視とログ – 運用時のログ確認とメトリクス収集
  11. トラブルシューティング – よくある問題と解決手順

Helm Chart による Kubernetes デプロイは、Docker Compose と比較して初期設定は複雑ですが、高可用性・自動スケーリング・ローリングアップデートなど、本番運用に必要な機能を全て活用できます。まずは開発環境で十分に検証し、ステージングを経て本番環境に展開してください。


参考資料