Open40

OpenWebUI × OpenAI API のAIチャットボットを ECS × Fargate 環境で動かす

sakisaki

まずlocalでやってみる
docker run -d -p 3000:8080 -e OPENAI_API_KEY=[secret_key] -v open-webui:/app/backend/data --name open-webui --restart always ghcr.io/open-webui/open-webui:main

http://localhost:3000/ にアクセス
WebUIが起動

sakisaki

AWSに乗せる前に、認証周りやデータがどう保管されてるか把握しておきたい

sakisaki

volumeは起動時のテンプレオプションで指定していた
open-webui というvolumeが存在しなければ作る
-v open-webui:/app/backend/data

sakisaki

2人目のアカウントを作ると
open_webui.apps.webui.models.authsinsert_new_authが動いている様子
特にメールの送信などはしないので、ID, Password認証みたいなものか。

1人目が管理者になり、2人目以降は管理者の承認が必要なようだ
管理者の承認待ち表示

sakisaki

管理者アカウントでログインし、http://localhost:3000/admin にアクセスすると管理画面になる
管理画面

sakisaki

「役割」の「保留中」を押すと「ユーザー」に切り替わる。
何度か押すと管理者にしたり保留中に戻したりもできる。

sakisaki

insert_new_auth ではUsersテーブルにemailやpassword情報をinsertしている
デフォだとSQLiteが使われている

sakisaki

SQLiteのデータは/app/backend/data/webui.dbに保存されている

sakisaki

取り出して見てみる
% docker cp open-webui:/app/backend/data/webui.db .
webui.db を DB Browser for SQLiteで開く

emailとpassword(暗号化済み)の対応はauthテーブルに、その他のユーザー情報はuserテーブルに記録されている

sakisaki

とりあえず、WebUI単独で最低限認証が行えることがわかったのでこのままAWSで稼働させてみる

sakisaki

まずECS clusterを作成
cluster名とtagは適当につけ、インフラストラクチャはFargateを選択

sakisaki

ECS taskを作っていく

インフラストラクチャの要件

起動タイプはFargate、CPUとメモリは最弱にしてみる

コンテナ

イメージURIはghcr.io/open-webui/open-webui:main
ポートマッピングは8080
※ Fargateのネットワークモードはawsvpcのみであり、これはDocker組み込みネットワークを経由せず直接外部と通信する。hostポートはランダムなものが自動で割り当てられるので、containerポートだけ指定する。
https://ameblo.jp/bakery-diary/entry-12798511245.html
https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definition_parameters.html#container_definitions

ストレージ

ユーザーなどのデータはこのコンテナ内のSQLiteに保存されるので、ボリュームを新規作成してアタッチする

sakisaki

ECS サービスも作ったが、タスク作成におけるDocker Imageのpullに失敗した。
VPC subnetがインターネットに接続していないからっぽい。
VPCにIGWをアタッチする

sakisaki

う〜ん、だるいので大人しくPublicIP割り当てするか

sakisaki

public IPオプション+IGWでやってるがERR_CONNECTION_REFUSEDになる。
続きは後日

sakisaki

SGのインバウンドルールを変更したらERR_CONNECTION_REFUSED から ERR_CONNECTION_TIMED_OUT に変わった
Fargateのスペック上げてみる

sakisaki

public subnetのインバウンドで8080を開放する必要があった(ブラウザから:8080をつけてアクセスする)

sakisaki

https://repost.aws/ja/knowledge-center/ecs-fargate-static-elastic-ip-address

ロードバランサーは、ターゲットグループ内のターゲット間でトラフィックを分散します。ターゲットグループが Amazon ECS サービスに関連付けられている場合、Amazon ECS はターゲットグループにコンテナを自動的に登録および登録解除します。Amazon ECS がターゲットの登録を処理するので、ターゲットグループにターゲットを手動で追加する必要はありません。

sakisaki

https化したいのでドメイン登録する
お名前.comで1年無料で取ろうと思ったけどなんかいろいろダークパターンで微妙な印象だったのでRoute53で金払って取る

sakisaki
  • Route53でドメイン取得
  • Route53でホストゾーン -> レコード作成 -> ElasticIPのIPアドレスを登録
  • AWS Certificate Manager で Route53で取ったドメイン名に証明書を設定
sakisaki

NLBだけだとHTTPS化できないので、やっぱALB × マルチAZ VPCで諸々やり直す

sakisaki
  • 「VPC"など"を作成」から、AZ2つ、パブリックサブネット2つ、プライベートサブネットなしで作る
  • IGWをVPCにアタッチする
  • パブリックサブネットのルートテーブルに、0.0.0.0 -> IGW へのルートを追加
  • あとなんか毎回GitHubから公式imageをpullしてくるの変な気がしたのでECRに保存しておく
    • M1 MacでpullしたimageをECRに単にpushすると、CPUアーキテクチャの違いからFargateで動かない
    • docker pull のオプションで platform linux/x86_64 を指定
  • ECSのタスク定義を作っておく(DockerImageのURIをさっきpushしたECRのものにする)
  • ECS用のTGをつくる(ターゲットタイプはIP。ただIP設定不要)
  • ALB作成 SGはインバウンド/アウトバウンドともHTTPSのanywhere
  • ECSのサービスをパブリックサブネット内で作成
    • ECS用のSGでインバウンド8080を許可(ソースはALBのSG)
  • ECSのサービスとその中のタスクが立ち上がる

ElasticIPはいらない(ALBに割り当てられない)
Route53のレコード作成で、Aレコードの転送先エイリアスとしてALBを選択

sakisaki

503になっている
どこでエラーが返ってるのか調べないとだが、ALB→TG(ECS)部分な気がする
ECSのTGはポート80や443ではなく、8080を指定するのか?

sakisaki

ECSのサービスを作るときにALBの設定ができた(ECS Serviceにロードバランサーが紐づく)

sakisaki

ALBのリソースマップ
TG -> ターゲット(ECS Service)が「異常」

ターゲットがunhealthyなのがだめなのか

ECS Service作り直す。SGがうまく設定できていなかったかも
ALB用SGからのport 8080を受け付ける

ヘルスチェック猶予期間も300秒にしてみる

sakisaki

なんかタスクがECRへのタイムアウトらしきエラーで起動しなくなった。
なんで?

AmazonEC2ContainerRegistryReadOnly のポリシーを ecsTaskExecutionRole に許可してみる
https://note.shiftinc.jp/n/nf456dd5900df

sakisaki

やっぱ違うな。timeoutだもんな。一回policyは外す

sakisaki

https://qiita.com/inoue2355/items/13b7c1406028d76a0b28

起動Taskをパブリックサブネットに配置して直接InternetGateWay経由で外に
アクセスしてECRからイメージを取得する方法。
注意点としてはSerivceを構築する際に「パブリックIPの自動割り当て」を
「Enable」にして起動TaskにパブリックIPを割り振る必要がある。

あ〜やっぱり?

sakisaki

あとは料金削減のための手段を考える
ただCPUは低すぎるかも

正直一人でやるならChatGPTに課金したほうがいいからterraformingしたら消すかも

あとECSのタスク作り直したらボリュームが作り直されてるのかユーザー情報が消えてる

sakisaki

いろいろやった結果、ChatbotUIのSelfHosted版あるやん!これでええやん!