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 Controller | nginx-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) |
| Service | kubectl get svc | ClusterIP が割り当て済み |
| Ingress | kubectl get ingress | ADDRESS が割り当て済み |
| PVC | kubectl 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-run | helm 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 failed | TLS 設定不備 | 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 values | Git リポジトリ | 変更都度 |
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 デプロイについて、以下の流れで解説しました。
- 前提条件 – Kubernetes / Helm のバージョン要件と外部リソースの準備
- Namespace 設計 – License との紐づきを考慮した環境分離
- Helm リポジトリの追加 – Chart の取得と values の確認
- values.yaml のカスタマイズ – 外部 DB、ストレージ、Ingress の設定
- Secret 管理 – パスワード・認証情報の安全な取り扱い
- Helm Install – dry-run からインストール実行まで
- デプロイ後の検証 – Pod、Service、Ingress、PVC の確認
- アップグレードとロールバック – 安全な更新手順
- スケーリング – 手動スケールと HPA の設定
- 監視とログ – 運用時のログ確認とメトリクス収集
- トラブルシューティング – よくある問題と解決手順
Helm Chart による Kubernetes デプロイは、Docker Compose と比較して初期設定は複雑ですが、高可用性・自動スケーリング・ローリングアップデートなど、本番運用に必要な機能を全て活用できます。まずは開発環境で十分に検証し、ステージングを経て本番環境に展開してください。