こんにちは。tubone24 です。
Dify にはセルフホステッド版が存在しております。
github.com
こちらをAzure Kubernetes Service (AKS) 上に構築する手順についてまとめていきます。
手順の概略
本手順はdouban/charts dify を用いてDifyの動作に必要なサービス郡をAKS 上に作ります。
基本的にHelmを用いて一式が立ち上がりますが、パブリックアクセスでDifyにアクセスしたいため、
パブリックアクセス用にイングレスをLoadBarancer タイプに紐づける形で新規作成する手順が追加されております。
事前準備
開発環境整備
Mac などのローカル環境から構築手順を実施する場合はこちらの手順を実施し、環境を作成してください。
Azure Cloud Shell を使って構築も可能ですが、その場合はAzure CLI , Helm , kubectl がすでにインストール済みのため、こちらの手順は不要となります。
Homebrew がインストール済みのMac の場合、次のコマンドでインストール可能です。
# 開発ツール一式をインストール
brew install helm
brew install azure-cli
brew install kubectl
# Azureにコマンドラインでログイン
az login
az account set --subscription ${サブスクリプションID}
Azureの設定更新
下記コマンドはサブスクリプション の操作権限以上がないと実行できないので、リソースグループの共同所有者では実施できません。
Azureのアカウント管理者にて実施をお願いします。
Aレコードが登録可能なドメイン を取得しておく
このあとの手順で作成するAKS のLoadbarancerのExternal-IPをAレコードに設定する手順を実施するため
douban/charts dify のHelmをそのまま実行しただけでは、デプロイしたサービス一式が外部(パブリック)からできるイングレスを持たない形で立ち上がってきてしまうのでパブリックアクセス可能な http_application_routing
を組み込んだAKS クラスタ ーを事前に作ることでパブリックアクセスが可能となります。
AKS クラスタ ー作成は次のコマンドを実施します。
az aks create --resource-group ${リソースグループID} --name ${クラスター名} --node-count 1 --enable-addons http_application_routing --generate-ssh-keys
AKS クラスタ ーの作成には数分かかります。
また、後の手順でkubectlが打てるようにAKS が作成できたタイミングでget-credentialsを実行します。
az aks get-credentials --resource-group ${リソースグループID} --name ${クラスター名}
ACRの作成・インポート
各サービスが使うDifyのDockerイメージをAzure Container Registry にインポートしておきます。
あらかじめ https://github.com/langgenius/dify/releases を参照し、最新のイメージのタグを控えておきます。(本手順作成の2024/9/16時点ではv0.8.2でした)
# ACRの作成
az acr create --resource-group ${リソースグループID} --name ${acr名} --sku Basic
# ACRに各イメージをインポート
az acr import --name ${acr名} --source docker.io/langgenius/dify-web --image dify-web:latest
az acr import --name ${acr名} --source docker.io/langgenius/dify-api--image dify-api:latest
Helmでサービスをデプロイ
douban/charts dify を使いDifyのサービスをデプロイしていきます。
基本的にはdouban公式の手順に則って進めていきます。
values.ymlを作成
Helmコマンドに渡すvalues.yaml
を作成します。
FixMeの箇所を実際の値に置き換えて使用してください。
global :
host : "dify.example.com"
enableTLS : false
image :
tag : "0.8.2"
extraBackendEnvs :
- name : SECRET_KEY
value : "testdify"
- name : LOG_LEVEL
value : "DEBUG"
- name : VECTOR_STORE
value : "milvus"
ingress :
enabled : true
className : "nginx"
minio :
embedded : true
Helmレポジトリの取得と更新
Helmコマンドを用いて、doubanのHelmレポジトリを取得します。
helm repo add douban https://douban.github.io/charts/
helm update
Helmでサービスをデプロイ
先ほど作成したvalues.yaml
をhelmコマンドで指定して実行します。
helm upgrade dify douban/dify -f values.yaml --install --debug
しばらくすると、AKS 上Defaultのnamespaceに次のサービスが立ち上がってきます。
(AzureポータルのKubernetes サービスのサービスとイングレス
から確認可能です。)
kubectlでも確認が可能です。
すべてのサービスが登録されていることを確認します。
kubectl get services -n default
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
dify-api-svc ClusterIP 10.0.234.25 <none> 80/TCP 96m
dify-frontend ClusterIP 10.0.115.89 <none> 80/TCP 96m
dify-minio ClusterIP 10.0.186.110 <none> 9000/TCP,9001/TCP 96m
dify-postgresql ClusterIP 10.0.219.74 <none> 5432/TCP 96m
dify-postgresql-hl ClusterIP None <none> 5432/TCP 96m
dify-redis-headless ClusterIP None <none> 6379/TCP 96m
dify-redis-master ClusterIP 10.0.226.40 <none> 6379/TCP 96m
dify-sandbox ClusterIP 10.0.35.3 <none> 80/TCP 96m
kubernetes ClusterIP 10.0.0.1 <none> 443/TCP 102m
また、各podの稼働状況も確認しておきます。
手順が問題なく実行できていれば、すべてのpodがRunningになっているはずです。
もしRunningになっていない場合は、サブスクリプション のリソースプロバイダーの登録状況や、ACRイメージのアクセス周りが問題と思われますのでご確認ください。
kubectl get pods -n default
NAME READY STATUS RESTARTS AGE
dify-api-6d6d5bbbb5-zlbdg 1/1 Running 0 61m
dify-frontend-5f5d7fdddd-qcpvc 1/1 Running 0 61m
dify-minio-56b7d4779d-wzd6t 1/1 Running 0 97m
dify-postgresql-0 1/1 Running 0 97m
dify-redis-master-0 1/1 Running 0 97m
dify-sandbox-7bf987566c-f664s 1/1 Running 0 97m
dify-worker-68476c7dcc-7tmzc 1/1 Running 0 61m
doubanのHelm chartを実行すると、nginxでイングレスも作成されます。
ただし、こちらのイングレスは利用せず、別途AKS クラスタ ーを作成したときに用意したhttp_application_routing
のLoadBalancerと紐づける別のイングレスを利用します。
Difyが利用するPostgreSQL にDBマイグレーション を実施します。
API サーバーが立っているPodでexecでDBマイグレーション コマンドを実行すればOKです。
あらかじめAPI サーバーのpod名を確認し、execコマンドを実行しましょう。
kubectl get pods -n default
NAME READY STATUS RESTARTS AGE
dify-api-6d6d5bbbb5-zlbdg 1/1 Running 0 61m
dify-frontend-5f5d7fdddd-qcpvc 1/1 Running 0 61m
dify-minio-56b7d4779d-wzd6t 1/1 Running 0 97m
dify-postgresql-0 1/1 Running 0 97m
dify-redis-master-0 1/1 Running 0 97m
dify-sandbox-7bf987566c-f664s 1/1 Running 0 97m
dify-worker-68476c7dcc-7tmzc 1/1 Running 0 61m
ここではdify-api -6d6d5bbbb5-zlbdgという名前のPodなのでこちらのpod上でDBのマイグレーション スクリプト を実行します。
実際の手順ではpod名はget pods コマンドの結果を下に変更してください。
kubectl exec -it dify-api-6d6d5bbbb5-zlbdg -- flask db upgrade
Load barancerの更新
先ほどAKS クラスタ ーを作成した際にhttp_application_routing
で作成済みのLoadBarancerをdifyのイングレスとして組み込みます。
dify-ingress .yaml を作成し、先ほど作成したhttp_application_routing
に各サービスを紐づけて更新します。
(もちろん、Helmコマンドで作成済みのイングレスを更新する形でも構いませんが、その場合kubectl applyが打てるように kubectl.kubernetes.io/last-applied-configuration
を追加したYAML を作成済みのイングレスのYAML 定義に追加する形で作成します。)
apiVersion : networking.k8s.io/v1
kind : Ingress
metadata :
name : dify-ingress
annotations :
kubernetes.io/ingress.class : addon-http-application-routing
spec :
rules :
- http :
paths :
- path : /
pathType : Prefix
backend :
service :
name : dify-frontend
port :
number : 80
- path : /console/api
pathType : Prefix
backend :
service :
name : dify-api-svc
port :
number : 80
- path : /api
pathType : Prefix
backend :
service :
name : dify-api-svc
port :
number : 80
- path : /v1
pathType : Prefix
backend :
service :
name : dify-api-svc
port :
number : 80
- path : /files
pathType : Prefix
backend :
service :
name : dify-api-svc
port :
number : 80
kubectl applyでイングレスを更新します。
kubectl apply -f dify-ingress.yaml
暫く待つと、LoadBarancerのExternal-IPアドレス 経由でDifyにアクセスできるようになります。
kubectl get ingress -n default
を実行し、dify-ingress のAddressにアクセスすると、Difyのログイン画面が表示されるはずです。
ただし、この時点でサインインやインストールはできません。
なぜならDifyのフロントエンド(Next.js)がAPI サーバーへアクセスするドメイン を上記のIPアドレス でなく、values.yaml に指定したglobal.hostの値を利用するためです。
💡
本手順ではAレコードの利用可能なドメイン の取得方法についてはご案内いたしません。
また、LetsEncryptサービスによるSSL 化のための証明書の紐づけも実施してませんのでHTTPS でアクセスしたい場合は別途AKS 上でcert-manager を構築するなど実施をお願いします。
利用しているDNS サービスでAレコードを作成します。
作成したAレコードの値にはLoadBarancerのExternal-IPを指定します。
再度ドメイン でアクセスする
無事全部の設定が問題なく完了していればこの時点で http://ドメイン/install
にアクセスすることで管理者アカウントを作成可能になります。
もし、/install
にアクセスした際にInternal server error などが出るようであれば、
作成したイングレスの設定もしくは、DBマイグレーション が正しくできてない可能性があるので、再度確認してください。