はじめに
Nutanix Advent Calender 2024のための記事のパート2です。クリスマス過ぎてしまった。
前回NKPでKubernetesクラスタをデプロイしたので、そこにDifyをデプロイしていきます。
DifyをKubernetes上で(そこそこちゃんとした構成で)動かす
Difyはクラウドサービス(SaaS)として提供されているものと、ローカルインストールできるオープンソースのコミュニティ版があります。
ドキュメントではDocker Composeによるコミュニティ版のデプロイ方法が説明されていますが、これはお手軽にパソコンで動かしてみる程度のものであり、ちゃんと使おうと思うとバックエンドのサービスも含めてしっかり構成する必要があります。
そこでKubernetesを使うわけですが、コミュニティ有志がhelmチャートを公開してくれています。ここではこちらを使います。
Docker Composeでデプロイする場合は、Difyがバックエンドで使う
- RDB(postgresql)
- NoSQL(redis)
- オブジェクトストレージ(minio)
- ベクターストア(weaviate)
もコンテナとしてデプロイされます。が、それだけだとスケーラビリティや可用性は考慮されておらず、とりあえず動くという最小構成です。
上記のhelmチャートを利用してKubernetes上で展開すると、READMEに書かれているように、これらのバックエンドサービスを外部化することができます。
特にオンプレのデータを活用したRAGというユースケースを考慮すると、オブジェクトストレージとベクターストアにはスケーラビリティ・アベイラビリティ・セキュリティが求められますので、ここでは
- オブジェクトストレージ: Nutanix Objectsを利用
- ベクターストア: Kubernetes上にMilvusを展開
とします。もちろんRDBにNutanix Database Service(NDB)を使ってもよい(ていうか使ってほしい)のですが、そこはまあやるだけなので今回はパスします。
Nutanix Objectsのセットアップ
やってみればわかるので細かく説明はしませんが、以下の流れです。
-
Create Object Store
でオブジェクトストレージのVMを作成
こんな感じでウィザードぽちぽちしていけば作れます。 -
Create Bucket
でバケットを作成
名前つけて作るだけです。Dify用(アップロードした生データなどを格納)のdify
というバケットと、後述するMilvus(ベクターストア)用のMilvus
というバケットを作りました。 - ユーザーを作ってアクセスキーを発行し、作成したバケットに紐づけ
Milvusのデプロイ
オープンソースのベクターストア(ベクトルDBという呼び方の方が一般的かもしれませんが、個人的には「DB」という概念とはなんか違う感じがするのでVector Storeという呼び方が好みです)であるMilvusは、それ自体かなりマイクロサービス・分散アーキテクチャになっています。
Milvusには公式のHelmチャートが用意されているので、そちらを使ってデプロイします。
前回ai-demo
というKubernetesクラスタを作成したので、そこにデプロイします。以下、Kubeconfigの向き先はこのai-demo
クラスタです。
余談ですが、 複数のK8sクラスタに対して作業を行う際、Kubeconfigがどのクラスタを向いているか混乱しがちなので、私はkubectxを使っています。
https://github.com/ahmetb/kubectx
まず、Helmチャートのvalues.yaml をダウンロードして、以下を編集します。
デフォルトではオブジェクトストレージとしてminioが展開されますが、今回はNutanix Objectsを使うので不要です。
minio:
enabled: false
Nutanix Objectsを利用するための設定をします。S3用の項目があるので、以下のように編集します。
###################################
# External S3
# - these configs are only used when `externalS3.enabled` is true
###################################
externalS3:
enabled: true
host: "<Object StorageのIPアドレス>"
port: "80"
accessKey: "<バケットに割り当てたユーザーのアクセスキー>"
secretKey: "<バケットに割り当てたユーザーのシークレットキー>"
useSSL: false
bucketName: "milvus"
rootPath: ""
useIAM: false
cloudProvider: "aws"
iamEndpoint: ""
あとはこのvalues.yamlを指定してデプロイするだけです。
$ helm repo add milvus https://zilliztech.github.io/milvus-helm/
$ helm repo update
$ kubectl create ns milvus
$ helm install -n milvus my-release milvus/milvus -f values.yaml
問題がなければ5分ぐらいで上がってくると思います。
$ kubectl -n milvus get pod
NAME READY STATUS RESTARTS AGE
my-release-etcd-0 1/1 Running 0 74s
my-release-etcd-1 1/1 Running 0 2m47s
my-release-etcd-2 1/1 Running 0 4m12s
my-release-milvus-datanode-86486d7d7-jmgpk 1/1 Running 0 4m14s
my-release-milvus-indexnode-d48945776-mljwj 1/1 Running 0 4m14s
my-release-milvus-mixcoord-69d65f8449-q48m8 1/1 Running 0 4m13s
my-release-milvus-proxy-5bd5584b4c-d9445 1/1 Running 0 4m14s
my-release-milvus-querynode-76878878bb-4wxhr 1/1 Running 0 4m14s
my-release-pulsarv3-bookie-0 1/1 Running 0 18m
my-release-pulsarv3-bookie-1 1/1 Running 0 18m
my-release-pulsarv3-bookie-2 1/1 Running 0 18m
my-release-pulsarv3-broker-0 1/1 Running 0 18m
my-release-pulsarv3-broker-1 1/1 Running 0 18m
my-release-pulsarv3-proxy-0 1/1 Running 0 18m
my-release-pulsarv3-proxy-1 1/1 Running 0 18m
my-release-pulsarv3-recovery-0 1/1 Running 0 18m
my-release-pulsarv3-zookeeper-0 1/1 Running 0 18m
my-release-pulsarv3-zookeeper-1 1/1 Running 0 18m
my-release-pulsarv3-zookeeper-2 1/1 Running 0 18m
Ingressを作る
NKPにはTreafikが標準で入っていて、これをIngressコントローラーとして使うことができます。
が、NKP独特のKommanderというアプリケーション管理の仕組みがあり、TraefikのIngressはKommander管理下のアプリケーションで使用することが想定されています。NKPの管理画面(Dashboard)もそのひとつです。
私は個人的にそういうOpinionatedなのがちょっと気持ち悪いので、ここでは普通に ingress-nginx
を入れて使うことにします。
コマンド一発
helm upgrade --install ingress-nginx ingress-nginx \
--repo https://kubernetes.github.io/ingress-nginx \
--namespace ingress-nginx --create-namespace
Difyをデプロイする
前述したようにHelmチャートを使用してデプロイしますので、values.yaml
ファイルを作ります。
global:
# Ingressが解釈するホスト名。ingress-nginxのExternal IPでDNSに登録しておくか、クライアントのhostsに書いておく
host: "aidemo.japansa.local"
enableTLS: false
storagetype: "s3"
image:
# Set to the latest version of dify
# Check the version here: https://github.com/langgenius/dify/releases
# If not set, Using the default value in Chart.yaml
tag: "0.6.15"
extraBackendEnvs:
- name: SECRET_KEY
value: <なんか生成したやつ>
- name: LOG_LEVEL
value: "DEBUG"
# ベクターストアとしてmilvusを使用
# ClusterIPでアクセスするので、kubectl -n milvus get svcでmy-release-milvusのClusterIPを確認しておく
# ユーザー・パスワードはデフォルトを書いてるけど良い子はまねしないでね
- name: VECTOR_STORE
value: "milvus"
- name: MILVUS_HOST
value: "10.100.58.48"
- name: MILVUS_PORT
value: "19530"
- name: MILVUS_USER
value: "root"
- name: MILVUS_PASSWORD
value: "Milvus"
# Nutanix Objectsをオブジェクトストレージとして使用。バケットとキーはあらかじめ作っておく
- name: S3_ENDPOINT
value: "http://<Object StoreのIP>"
- name: S3_BUCKET_NAME
value: "dify"
- name: S3_ACCESS_KEY
value: "<バケットに割り当てたユーザーのアクセスキー>"
- name: S3_SECRET_KEY
value: "<バケットに割り当てたユーザーのシークレットキー>"
# ユーザー登録時のメール認証のためのSMTPサーバー
- name: MAIL_TYPE
value: "smtp"
- name: SMTP_SERVER
value: "<SMTPサーバーのIP>"
- name: SMTP_PORT
value: "587"
# ingressのクラスを指定。NKPではデフォルトでkommander-traefikというクラスが使用できるが、ここでは別途nginx-ingressを導入して使用している
ingress:
enabled: true
className: "nginx"
# オブジェクトストレージはNutanix Objectsを使用するのでminioは無効化
minio:
embedded: false
# DB(Postgresql)はNDBを使用してHA構成としてもよいが、ここでは組み込みPostgresを使用
postgresql:
embedded: true
で、デプロイ
$ helm repo add douban https://douban.github.io/charts/
$ kubectl create ns dify
$ helm upgrade -n dify dify douban/dify -f values.yaml --install --debug
問題なければ2~3分で上がってくると思います。
$ kubectl -n dify get pod
NAME READY STATUS RESTARTS AGE
dify-api-64df859d74-jt6t6 1/1 Running 0 2m6s
dify-frontend-775dc4c99c-q8z8v 1/1 Running 0 2m6s
dify-postgresql-0 1/1 Running 0 2m6s
dify-redis-master-0 1/1 Running 0 2m6s
dify-sandbox-5c6bdcdb9c-kj6lh 1/1 Running 0 2m6s
dify-worker-c96bf9cf8-qhvgt 1/1 Running 0 2m6s
DBをアップグレードしろって書いてあるのでやっておきます。
$ kubectl -n dify exec -it dify-api-64df859d74-jt6t6 -- flask db upgrade
$ kubectl -n dify exec -it dify-worker-c96bf9cf8-qhvgt -- flask db upgrade
で、登録したホスト名にブラウザからアクセスすると初期設定画面が出ます。
管理者ユーザーを登録してログインすると、DifyのUIが開きます。ぱちぱちぱち。
つづく。