こんにちは。tubone24です。
Difyにはセルフホステッド版が存在しております。
こちらを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のアカウント管理者にて実施をお願いします。
AKSクラスターの作成
douban/charts difyのHelmをそのまま実行しただけでは、デプロイしたサービス一式が外部(パブリック)からできるイングレスを持たない形で立ち上がってきてしまうのでパブリックアクセス可能な http_application_routing
を組み込んだ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" # FixMe: 実際に利用可能なドメインを指定 enableTLS: false image: tag: "0.8.2" # FixMe最新バージョンに更新 extraBackendEnvs: - name: SECRET_KEY value: "testdify" # FixMe: 必ず推測困難な文字列にしてください - 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 サービスのサービスとイングレス
から確認可能です。)
- dify-sandbox
- dify-redis-master
- dify-redis-headless
- dify-postgresql-hl
- dify-postgresql
- dify-minio
- dify-frontend
- dify-api-svc
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と紐づける別のイングレスを利用します。
DBマイグレーション
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の値を利用するためです。
DNSの更新
利用しているDNSサービスでAレコードを作成します。 作成したAレコードの値にはLoadBarancerのExternal-IPを指定します。
再度ドメインでアクセスする
無事全部の設定が問題なく完了していればこの時点で http://ドメイン/install
にアクセスすることで管理者アカウントを作成可能になります。
もし、/install
にアクセスした際にInternal server errorなどが出るようであれば、
作成したイングレスの設定もしくは、DBマイグレーションが正しくできてない可能性があるので、再度確認してください。