メインコンテンツまでスキップ

「Docker」タグの記事が9件件あります

全てのタグを見る

snake

Stable Diffusion web UIをDockerを使用してWindows上で動作させる方法についてまとめてあります。

前提条件

この投稿での環境についてです。必ずしも同様の環境である必要はありません。参考にしてください。

  • OS: Windows 11 Pro 22H2
  • CPU: Ryzen 7 5700X
  • GPU: Geforce RTX 3060
  • メモリ: 32GB
  • Docker、gitが導入可能、もしくは、すでに導入されている環境

当たり前ですが、Stable Diffusionが扱えるだけのスペックが整っている事が前提です。

Stable Diffusion web UI (AUTOMATIC1111 fork)について

AUTOMATIC1111さんがforkしたStable Diffusionです。webuiがついており、コマンドを使うことなくより簡単にStable Diffusionを扱えるようにします。私が知る限り、webuiから最も様々なことができるStable Diffusion forkです。

GitHub - AUTOMATIC1111/stable-diffusion-webui: Stable Diffusion web UI

何ができるかはドキュメントにまとめられています。

Features · AUTOMATIC1111/stable-diffusion-webui Wiki

Stable Diffusion WebUI Dockerについて

普通にStable Diffusionを動かそうとすると手間なので、今回はインストールの手間を減らすためにDockerを使用します。AbdBarhoが公開しているStable Diffusion WebUI Dockerを利用します。

Stable Diffusion WebUI Dockerでは、AUTOMATIC1111、hlky、lsteinのStable Diffusion forkを扱うことが可能です。今回はAUTOMATIC1111 forkを使用します。

GitHub - AbdBarho/stable-diffusion-webui-docker: Easy Docker setup for Stable Diffusion with user-friendly UI

セットアップ

Stable Diffusionのセットアップを始めます。人によっては、部分的にスキップ可能な箇所もあると思います。

(1) git for windowsのインストール

git for windowsをインストールしてください。インストール済みの場合は、無視していいです。

Git for Windows

詳細なインストール方法については解説しません。Downloadより.exeファイルをダウンロードし、手順に従うことでインストールが可能です。

(2) Docker Desktopのインストール

Docker Desktopをインストールしてください。インストール済みの場合は、無視していいです。

Docker Desktop - Docker

詳細なインストール方法については解説しません。Download Docker Desktopより.exeファイルをダウンロードし、手順に従うことでインストールが可能です。

(3) インストールの確認

正常にインストールが完了しており、Docker Desktopが起動状態であれば、Windows PowerShellから以下のコマンドを実行する事で、下記の結果を得ることができます。

Git for Windowsの確認

git -v でインストールされたバージョン情報を確認できます。インストールしたバージョンによって異なる結果が返ってきます。

git -v git version 2.38.1.windows.1

Docker for Desktopの確認

docker version でインストールされたバージョン情報を確認できます。インストールしたバージョンによって異なる結果が返ってきます。

docker version Client: Cloud integration: v1.0.29 Version: 20.10.20 API version: 1.41 Go version: go1.18.7 Git commit: 9fdeb9c Built: Tue Oct 18 18:28:44 2022 OS/Arch: windows/amd64 Context: default Experimental: true

Server: Docker Desktop 4.13.0 (89412) Engine: Version: 20.10.20 API version: 1.41 (minimum version 1.12) Go version: go1.18.7 Git commit: 03df974 Built: Tue Oct 18 18:18:35 2022 OS/Arch: linux/amd64 Experimental: false containerd: Version: 1.6.8 GitCommit: 9cd3357b7fd7218e4aec3eae239db1f68a5a6ec6 runc: Version: 1.1.4 GitCommit: v1.1.4-0-g5fd4c4d docker-init: Version: 0.19.0 GitCommit: de40ad0

もしもDockerの動作確認をしたい場合は、docker run hello-world コマンドでイメージからコンテナを作成してみてください。正常にコンテナを起動することができれば、以下のメッセージを得ることができます。

docker run hello-world Unable to find image 'hello-world:latest' locally latest: Pulling from library/hello-world 2db29710123e: Pull complete Digest: sha256:e18f0a777aefabe047a671ab3ec3eed05414477c951ab1a6f352a06974245fe7 Status: Downloaded newer image for hello-world:latest

Hello from Docker! This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:

  1. The Docker client contacted the Docker daemon.
  2. The Docker daemon pulled the "hello-world" image from the Docker Hub. (amd64)
  3. The Docker daemon created a new container from that image which runs the executable that produces the output you are currently reading.
  4. The Docker daemon streamed that output to the Docker client, which sent it to your terminal.

To try something more ambitious, you can run an Ubuntu container with: $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID: https://hub.docker.com/

For more examples and ideas, visit: https://docs.docker.com/get-started/

(4) Stable Diffusion WebUI Dockerをclone

Stable Diffusion WebUI Dockerをcloneします。以下のコマンドを実行してください。

git clone https://github.com/AbdBarho/stable-diffusion-webui-docker.git

現在いるディレクトリ上にstable-diffusion-webui-docker というディレクトリが作成され、その中に内容がダウンロードされます。

以降は、stable-diffusion-webui-docker で作業を行うので、ディレクトリへ移動します。移動するには、以下のコマンドを実行してください。

cd stable-diffusion-webui-docker

(5) モデルデータをダウンロード

Stable Diffusionが利用するモデルデータをダウンロードします。以下のコマンドを実行してください。

docker compose --profile download up --build

このコマンドにより、必要なモデル・ファイルがすべてダウンロードされ、整合性が検証されます。これらのデータは一度ダウンロードするのみで済みます。

ダウンロードされるデータは12GB近いので、十分な容量の確保と安定したインターネット接続が必要です。

かなり時間がかかりますので、待ちましょう。

(6) Stable Diffusion webUIの実行

以下のコマンドを実行することで、webUIを実行できます。

docker compose --profile auto up --build

最初の起動には時間がかかります。最初の起動でダウンロードされた内容などは、 data ディレクトリにキャッシュされるため、次回以降の起動は早くなります。インターネット接続速度によって異なりますが、初回起動には15分から1時間程度かかる場合があります。以降は、20秒程度です。

実行後は、http://localhost:7860/ からアクセスが可能です。

他のforkを使う場合

「docker compose --profile [ui] up --build」の[ui]を以下の文字列のいずれかに置き換えてください。

  • auto
  • hlky
  • lstein

autoはstable-diffusion-webui、hlkyはsygil-webui、lsteinはInvokeAI

GPUなしで動作させたい場合

「docker compose --profile auto-cpu up --build」を使って実行してください。

(7) 日本語化

Stable Diffusion webUIは有志によって日本語化が行われており、組み込まれています。

アクセスした先のSettingsより日本語化を行うことが可能です。 Settingsに移動した後に、下へスクロールすると「Localization (requires restart)」という項目があります。その中からja_JPを選択してください。 その後、Stable Diffusion webUIを再起動することで日本語化されます。再起動する場合、PowerShellからCtrl + Cで終了させてください。起動は(6)に従ってください。

snake

DockerのSwarm modeには、ルーティングメッシュと呼ばれる機能があります。この機能により、外部からのアクセスをロードバランシングすることができます。ルーティングメッシュにより、接続先のノード自身がタスクを実行していなくても、タスクが利用可能なノード上へリクエストを転送してくれるようになります。 Use swarm mode routing mesh

この機能は便利であり、Swarmを冗長構成にするのであれば、必要不可欠な機能の一つです。ただし、ルーティングメッシュが有効になっている場合、アクセス元のIPアドレスを取得できない可能性がある問題が存在しています。正確には取得できますが、接続元のIPアドレスではなく、アクセスを受け付けたノードのIPアドレスが取得されます。

最初に提示した画像を元に説明を行います。

仮に203.0.113.10から Node-03(192.168.10.102:8080)へアクセスがあったとします。Node-03上に利用可能なタスクがないため、全てのリクエストは利用可能なタスクの存在する異なるノードへ転送されます。そのためNode-01もしくはNode-02のnginx.1がアクセスを受けます。この時、アクセスを受けたnginx.1でアクセスログを確認すると、接続元のIPアドレスはNode-03のIPアドレスである192.168.10.102が記録されています。

という訳で、ルーティングメッシュによりリクエストが転送された場合、転送元のノードのIPアドレスが記録されてしまいます。

一般的に元のIPアドレスを取得場合、httpではX-Forwarded-Forと呼ばれるプロキシを通した際に元のIPアドレスを保持する仕組みを利用し、L4ではProxy Protocolと呼ばれるロードバランサを通した際に元のIPアドレスを保持する仕組みを利用します。

しかしながら、ルーティングメッシュによって転送されたリクエストは、X-Forwarded-ForやProxy Protocolが対応してないんですね。類する代替手段が用意されている訳でもないため、Docker Swarmのみで元のIPを取得することは不可能です。

この問題はすでに把握されており、issueは立ち上げられています。しかし、2016年から開かれ続けており、すぐに解決される問題ではない気がします。

Unable to retrieve user’s IP address in docker swarm mode · Issue #25526 · moby/moby

Proxy Protocolのサポートも同様にissueは立ち上がっているものの、すぐに解決される問題ではなさそうです。

Proxy Protocol support in Swarm ingress · Issue #39465 · moby/moby

対処法1

この問題に対する対処法として、ルーティングメッシュの無効化があります。しかし、Overlay Networkの利点を失うことになる点は注意してください。

Docker-composeの場合、long syntaxでポートを以下のように指定することでルーティングメッシュを無効化することができます。

  • target: 80 published: 80 protocol: tcp mode: host
  • target: 53 published: 53 protocol: udp mode: host

modeを省略した場合、もしくは、ingressを設定した場合はルーティングメッシュが有効になります。

Docker Swarmを使う意味がよく分からなくなりますが、クラスタの外側にHAProxyのようなロードバランサを設置してあげることで、ルーティングメッシュみたいなことはできるようになります。

対処法2

docker-ingress-routing-daemonなるものを利用することで、元のIPアドレスを取得できるようになるらしいですが、使ったことがないので詳しいことはよく分かりません。少なくとも、私は複雑になり過ぎるので使おうと思いませんでした。

GitHub - newsnowlabs/docker-ingress-routing-daemon: Docker swarm daemon that modifies ingress mesh routing to expose true client IPs to service containers

snake

lucaslorentz/caddy-docker-proxy で発生するエラー「Service is not in same network as caddy」に対する解決策です。

前提

Docker Swarmでlucaslorentz/caddy-docker-proxy をデプロイし、各種コンテナへのリバースプロキシ用のラベルを適切に設定されている状態。

特に他にエラーが見られず設定に問題がないのにも関わらずエラーが発生する場合。

エラー内容

エラーは以下の通りです。

"msg":"Failed to get ingress networks" "error":"Cannot find container id in cgroups" "msg":"Service is not in same network as caddy"

修正方法

環境変数の CADDY_INGRESS_NETWORKS に属するネットワークを設定する。

例えば、externalの public ネットワークに参加しており、 public に属するコンテナへプロキシを行う場合は、 CADDY_INGRESS_NETWORKS=public と環境変数を設定する必要がある。

docker-compose.yml 例

version: "3.7" services: caddy: image: lucaslorentz/caddy-docker-proxy:ci-alpine ports:

  • 80:80
  • 443:443 environment:
  • CADDY_INGRESS_NETWORKS=public networks:
  • public volumes:
  • /var/run/docker.sock:/var/run/docker.sock
  • caddy_data:/data restart: unless-stopped

networks: public: external: true

volumes: caddy_data:

snake

Docker Engineが標準的に提供するオーケストラレーションツールであるDocker Swarmについて、マネージャーノードはいくつが良いのかが分からなかったので、簡単に調べました。それについてちょっとだけまとめておきます。基本的に語っていることは公式のドキュメントと大差ありませんので、より詳細で正確な情報を知りたい場合は、公式ドキュメントをご確認ください。

Docker Documentation

※この投稿で言う「Docker Swarm」は、Docker Engineに標準的に組み込まれているSwarm modeを指しています。

Docker SwarmのマネージャーノードはRaftコンセンサスアルゴリズム(分散合意アルゴリズム)によって状態管理が行われます。通常、このアルゴリズムについて詳しく理解する必要はありませんが、概要を理解することでマネージャーノードの数を決定する役に立ちます。

マネージャーノードの数とパフォーマンス

Docker Swarmでクラスターに追加できるマネージャーノード数には、制限がなく、追加しようと思えばいくらでも追加することができます。基本的な考え方として、マネージャーノードの数が多ければ多いほど、障害耐性が強くなります。しかし、ほとんどの場合でマネージャーノードの増加はパフォーマンスの悪化を引き起こします。これは単純にノードの追加・削除といった処理を多数のノードで行う必要があるためです。数が増えればその分パフォーマンスが悪化します。

マネージャーノードとquorum

Docker Swarmでマネージャーノードが何らかのタスクを実行する際には、quorumと呼ばれるものが必要です。quorumは分散システムでよく利用されるものであり、処理の整合性を保つために使われます。Docker Swarmでは、このquorumが全マネージャーノードの半数を超過する必要があります。これは単純な議決のように考えることができ、参加者の半数を超過した数が賛同しなければ、実行することができません。

注意点:quorumは全マネージャーノードの半数を超過している必要があります。6ノード存在する場合、半数の3の超過、つまり4以上のquorumが必要です。

では、以上を踏まえてquorumが常に半数以上確保できる環境を考えてみます。

マネージャーノードが1つである場合、1つのマネージャーノードが必要です。もしマネージャーノードが1つダウンした場合、クラスターではタスクが実行できなくなります。この場合、必要なquorumが1となる為、1つでもダウンすると必要quorumに達しません。

マネージャーノードが2つである場合、2つのマネージャーノードが必要です。もしマネージャーノードが1つダウンした場合、クラスターではタスクが実行できなくなります。この場合、必要なquorumが2となる為、1つでもダウンすると必要quorumに達しません。

マネージャーノードが3つである場合、3つのマネージャーノードが必要です。もしマネージャーノードが1つダウンした場合、クラスターでのタスクが実行可能です。この場合、必要なquorumが2となる為、1つのダウンまでは許容されます。2つダウンした場合は、必要quorumに達しません。

マネージャーノードが4つである場合、4つのマネージャーノードが必要です。もしマネージャーノードが1つダウンした場合、クラスターでのタスクが実行可能です。この場合、必要なquorumが3となる為、1つのダウンまでは許容されます。2つダウンした場合は、必要quorumに達しません。

同様の考え方でそれ以上の数の場合でも考えていくことができます。

quorumについて、以下に簡単にまとめます。

Docker Swarmでは:

  • 最大 (N-1)/2 までの障害が許容されます。
  • クラスターでのタスク実行には (N/2)+1 ノードのquorumが必要です。

マネージャーノードの耐障害性

これまでの内容を踏まえ、マネージャーノードの耐障害性について考えていきます。

以下はマネージャーノード数が1~9の場合に必要なquorumと、ダウンが許容されるノード数を表にまとめたものです。表は、「Administer and maintain a swarm of Docker Engines | Docker Documentation」から引用しています。 マネージャーノード数quorum許容値110220321431532642743853954 マネージャーノード数が偶数(2, 4, 6, 8~)である場合、耐障害性に対するメリットはありません。例えば、マネージャーノード数が 4 である場合 2ノード 以上がダウンすると、quorumが足らなくなります。しかし、マネージャーノード数が 3 である場合も同様に 2ノード 以上のダウンでquorumが足らなくなります。マネージャーノード数が 3 もしくは 4 の場合のどちらであっても、ダウンが許容されるノード数は 1 です。

そのためマネージャーノード数は奇数(1, 3, 5, 7, 9)であることが、望ましいです。

適切なマネージャーノード数

最後に適切なマネージャーノード数について考えます。とはいえども、ここまで流れで読んできていれば、何となく分かっているかもしれません。

クラスターの耐障害性を確保するために、マネージャーノードが複数であることは必要です。Docker Swarmでは、マネージャーノードがなければクラスターでタスクの実行が不可能になるためです。

  • 通常、クラスターを構築する場合、マネージャーノード数 3 は目指すべき最低限のラインです。
  • クラスターが中規模である場合は、マネージャーノード数 5 を目指すべきです。
  • クラスターが大規模である場合は、マネージャーノード数 7 を目指すべきです。

中規模は数百のノードである場合を指し、大規模は数千のノードである場合を指します。この規模感のノード数は、殆どの場合エンタープライズなので、個人で検証することは難しいです。そのため明確な根拠を出すことができません。

では、上記よりも更にクラスターの規模が大規模であり、マネージャーノードが不足していると感じている場合は、マネージャーノード数を 9 にするべきでしょうか。この場合は、増やすべきではないという答えになります。

Dockerの公式ドキュメントでは、次のように言及されています。

Docker recommends a maximum of seven manager nodes for a swarm.

Important Note: Adding more managers does NOT mean increased scalability or higher performance. In general, the opposite is true.

How nodes work | Docker Documentation 雑に翻訳すると以下のようになります。

Dockerでは、Swarmに対して最大7のマネージャーノードが推奨されています。 注意:マネージャーノードを追加しても、スケーラビリティーの向上やパフォーマンスの向上には繋がりません。通常、その逆が起こります。

一切の効果がないと断言することは私にはできませんが、少なくとも公式ドキュメントで非推奨である旨が明示されています。

参考

Administer and maintain a swarm of Docker Engines

How nodes work

Pros and Cons of running all Docker Swarm nodes as Managers?

How to handle when leader node goes down in docker swarm

snake

Amazonのブラックフライデーセールで安く売られていた6 TBの外付けHDDを購入したので、それにラズパイをくっつけて簡単お家クラウドを作りました。

この組み合わせの話、擦られすぎて書く意味がよく分かりませんが、こんな事やったよという報告程度に見て頂ければと思います。特別なにか尖ったことをするわけではないので、別にこのサイト以外の内容を見ながら、やっても同じ結果を得られるかと思います。

環境

基盤:Raspberry Pi 3 Model B+(以下、ラズパイ)

ストレージ:32GB SDカード

Team microSDHCカード 32GB UHS-1 U1 Switch動作確認済み 読込み最大100MB/s 日本国内10年保証 SD変換アダプター付属 正規品

ストレージ:外付け6TB HDD

【Amazon.co.jp限定】バッファロー 外付けハードディスク 6TB テレビ録画/PC/PS4/4K対応 バッファロー製nasne™対応 静音&コンパクト 日本製 故障予測 みまもり合図 HD-AD6U3

OS:Ubuntu Server 20.04 LTS

(Dockerで動かすのでDebianでもCentOSでも動かせます)

必要なもの:Docker、Docker-compose、やる気、モチベーション

前提

外部からサーバーへアクセスできる環境は整っているという前提で話をしています。例えばポート開放やリバースプロキシ、サーバーのIPアドレスなどは全て設定されているものとみなしています。

OSのインストール

ラズパイで動かすので、まずはOSをインストールします。OSさえインストールされればやり方はお好みですが、今回はRaspberry Pi公式が出しているRaspberry Pi Imagerを利用します。

ダウンロードは下記URLから行えます。

Raspberry Pi OS – Raspberry Pi

下記画像の「Download for Windows」をクリックすることでWindows版をダウンロードできます。macOSやUbuntuをお使いの場合は、下に表示されているリンクをクリックしてください。 インストール後起動すると、下記画像のようなウィンドウが立ち上がります。 ここまで来たら後は簡単です。「CHOOSE OS」でOSを選択してください。今回はUbuntu Serverを選択しますが、もしもこだわりがあれば他のOSを選択してもらっても構いません。ただしその場合、この投稿の手順ではできないかも知れないです。 OS選択後「CHOOSE STORAGE」でPCに刺したマイクロSDカードを選択して「WRITE」でOSを書き込みます。

ここもHDDからブートしたり、ネットワークからごちゃごちゃやったりできたりできなかったりするらしいのですが、今回は面倒なのでやらないというのと、個人的に別用途でも利用するのでSDに書き込んでおきます。

書き込みが終わったら、後はラズパイにマイクロSDカードを挿して、起動させるだけです。

起動後Raspberry Piにモニターとキーボードが接続されている場合は、画面に表示されます。そうでない場合、かつ、Raspberry Pi ImagerのCHOOSE OSでカスタム .imgなどを使用していない限り、初期段階からSSHが有効になっているので、ローカルIPを探し接続してください。

接続後パスワードの設定や必要に応じてユーザーの作成などを行ってください。パスワードの設定は必要ですが、ユーザー作成などの環境面はお好みです。

環境が整ったら、アップデートを行ってください。

Ubuntuの場合、以下の通りです。

$ sudo apt -y update $ sudo apt -y upgrade

時間がかかるのでお茶でも飲みながらゆっくり待ちましょう。

アップデートが完了したらOSの準備が整いました。

Docker、Docker Composeのインストール

初めにDockerインストールしていきます。これは公式ドキュメントに沿ってインストールしていけばいいです。下記は実行するコマンドです。

$ sudo apt install
ca-certificates
curl
gnupg
lsb-release $ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg $ echo
"deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null $ sudo apt update $ sudo apt install docker-ce docker-ce-cli containerd.io

Install Docker Engine on Ubuntu

次にDocker Composeをインストールしていきます。こちらについても公式ドキュメントに沿ってインストールしていけばいいです。下記は実行するコマンドです。

$ sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose $ sudo chmod +x /usr/local/bin/docker-compose

Install Docker Compose

インストール完了後、必要に応じてインストールの確認をしてください。

Nextcloudのインストール

インストールとは言ってもDockerで動かすので、 docker-compose.yml を作成して記述するだけです。

docker-compose.ymlの例は以下の通りです。

version: '3'

services: db: image: mariadb:10.5 command: --transaction-isolation=READ-COMMITTED --binlog-format=ROW restart: always volumes:

  • db:/var/lib/mysql environment:
  • MYSQL_ROOT_PASSWORD=ChangeMe env_file:
  • db.env

redis: image: redis:alpine restart: always

app: image: nextcloud:apache restart: always ports:

  • 80:80 volumes:
  • nextcloud:/var/www/html environment:
  • MYSQL_HOST=db
  • REDIS_HOST=redis env_file:
  • db.env depends_on:
  • db
  • redis

cron: image: nextcloud:apache restart: always volumes:

  • nextcloud:/var/www/html entrypoint: /cron.sh depends_on:
  • db
  • redis

volumes: db: nextcloud:

記述後、ファイルを保存してください。

ディレクトリで以下のコマンドを実行することで、Nextcloudが立ち上がります。

$ sudo docker-compose up -d

起動後、IPやドメインを使ってウェブサイトへアクセスし、指示に従ってインストールしてください。

これで完了です。自分で使いたいように他の設定をいじったりしてください。

NextCloudをRaspberry Pi 3 B+で運用してみて

結論だけ言います。動作が遅い、たまに完全に固まる。だけど、基本的にほっておけば処理は終わってるので、個人宅のファイルサーバー程度使うのであれば、何ら問題ないです。

快適に複数ユーザーであれこれ色々使いたいのであれば、Raspberry Pi 4を使うか、もっとスペックを持ったPCに入れるのが良い気がしますね。

snake

Twitchで配信をしながら、勉強しつつ10時間かけてクラスタ構築とクラスタへの移行を行いました。

クラスタを構築したのは良いもののデータベースを実行してるメインサーバが吹き飛んだので、やってからこの記事を書くまで時間が経過しました。

サーバが吹き飛んだことに関するIQ3まとめについては下記の投稿を見てください。

サーバーがカーネルパニック起こしたと思ったらハードウェアごと吹き飛んだ件

なぜクラスタを構築したのか?

大きく2つの理由があります。

1つ目は学習目的です。クラスタに関して興味深くQiitaやZennその他様々な記事を目にしていましたが、いままで一度も構築したことがありませんでした。そこでやってみようと考えました。好奇心的なところが強いです。そもそもとして、私が自宅にサーバを持っている理由が学習目的なので、こういう感じで結構色々気軽にやってたりします。

2つ目は複数台管理が面倒くさかったです。クラスタ構築して運用できれば、個別にSSHでいちいちつないで細かく設定する必要がなくなるので、かなり管理の手間が減ると思いました。実際、楽になりました。初期に色々設定するという面ではかなり手間はありますが、そこさえ乗り越えれば楽です。

上記の2つの理由からクラスタ構築を自宅サーバ群で行いました。

自宅サーバ群について

サーバ群なんて言っていますが、今回のクラスタ構築では3台のみで考えました。今後追加することも一応考慮しています。

1台目

データベースやゲームサーバー、その他諸々一番色々やっているサーバ。スペックもメモリも一番ある。

ストレージは、SSDにOS、HDD2枚にそれぞれバックアップと本番の運用データが乗ってます。

OSはUbuntu Server 20.04、もともとはCentOSで運用していましたがCentOS 8でなくなるということでDebian系に乗り換えました。Ubuntuを選択した理由は、割と安定しながらも、バージョンを比較的新しいのを使ってくれるからです。後は最近のOSSとかがUbuntuで動かすことを想定して作ってることが多かったりするなんて理由もあります。あまり細かいことは考えてません。

2台目及び3台目

Raspberry Pi 3 Model B+です。

どちらもTeam GroupのSDカード32GBを指してあります。

OSはUbuntu Server 20.04です。

基本的にデータを保持せず、サービスをDockerなどで動かしているだけです。このウェブサイトのウェブサーバーもラズパイで動作しています。データはデータベースやNASなどに放り込んであります。

後日、外部HDDをつなげてNAS化する計画がありますが、それはおいおいの話なので、ストレージは無いものとして扱います。

3台目以降

現在はありませんが、今後追加する可能性があるという事を考慮して構築しました。まだ扱いを考えていますが、クラウドのクラスタを自宅サーバのクラスタと混ぜてしまってもいいかなと考えているので、そういった可能性も考慮しつつ作ります。

オーケストレーションに何を使うのか

クラスタ構築で重要なオーケストレーションシステムをどのように選んだのかという話です。

最も有名なオーケストレーションシステムの1つとして、k8s(Kubernetes)があると思います。Googleが設計したやつで、デファクトスタンダードの立ち位置にあるオーケストレーションシステムです。

k8sは技術トレンドですし、扱えたらなんかカッケー!とは思いますが、ここは現実的な事を考えましょう。まずk8sはプロダクション環境で使われることが多く、そこで使うことを想定した作りとなっています。実際Googleさんとか色々な企業は数千ノードをk8sとかで扱っているとか...

しかし私は一般家庭、プロダクション環境ではないのです。もちろん数千ノードなんて扱うことは有りません。現在稼働させてるサーバーをオンプレ・クラウド合わせてもいいとこ10数個です。まず20ノードを超えることは有りません。ということはそこまで高性能である必要も無ければ、プロダクション環境に対応できるだけのスケールアウト可能なシステムである必要もありません。

k8sが無いとすると次に挙がってくるオーケストレーションシステムといえば、Docker Swarmです。これはDocker-ce自体に統合されているものなので、追加のインストールなどは必要なく、Docker engineが使えれば利用可能です。

補足ですが、「Docker Swarm 終了」や「Docker Swarm サポート終了」といったサジェストが出てきて、その旨の記述をするブログが散見されますが、終わったのは、Docker-Swarm-Mode-As-A-Serviceです。Docker Swarmが完全に削除されたわけではなく、開発が終了したわけではないです。

Is Docker Swarm Mode EOL?

これ以外に利用されるオーケストレーションとしてGKEやECS、OpenShift、Rancherなどなど色々ありますが、他のは情報少なかったり、クラウドでやること想定されてたりなので、考えないこととします。後は単純に導入の手間とコストに見合わないです。

Kubernetes vs Docker Swarm

少なくとも私が自宅サーバ群でクラスタ構築するにあたり、どちらが良いのか。実際に検証したわけではありませんが、ある記事を見つけたのでそちらの情報を参照します。

[和訳]Docker SwarmとKubernetesの比較 #docker - クリエーションライン株式会社

ここでは技術コンサルタントのJeff NickoloffとDockerが契約して、パフォーマンス評価をした結果の和訳が掲載されています。

中身はここでは解説しないので、簡単に呼んで頂くとして、重要な2つのパフォーマンス評価項目とその結果に注目します。

評価項目は「コンテナの起動にかかる時間」と「高負荷状態での応答性」です。後者のような状態になることは想定してないし、プロダクションでもないので最悪time outしてもいいかなぐらいの気持ちではいますが、良いに越したことは有りません。

結果だけ書くと、コンテナの起動にかかる時間はDocker Swarmの方が5倍早く、クラスターの負荷率がほぼ100%であったとき、Kubernetesはクラスターの形成状態が10%~100%に到達するまで、Docker Swarmの98倍の時間がかかっています。

できることの幅は間違いなくk8sの方が良いです。ただしk8sは純粋に複雑なんです。ちょっとしたことをやるためにも色々やる必要があります。大規模なサービスを厳格に動かす場合、おそらくk8sは向いているでしょうが、自宅でちょっとクラスタを動かすぐらいであれば、複雑でパフォーマンスが出ないk8sよりもDocker Swarmの方が良いという結論になりました。

これは私の結論なので、自分で作る場合はぜひ自分で選択してほしいですが、少なくとも少ないサーバー台数で、1人でシンプルに物事を進めたいのであれば、Docker Swarmの方が向いていると思います。

WebUI

さて一人で管理していくとなると、WebUIがあったほうが楽ですし、やりやすいです。全部CUIでやれという意見も理解はしますが、人間なのでGUIに甘えたいです。

ここに関しては割とすぐに決まりました。というかだいぶ前からクラスタ構築のための構想は頭で練っていて、もともとこれでいいでしょって感じで決めていました。

選ばれたのはPortainerでした。

Container Management | Kubernetes GUI | Docker Swarm GUI | Portainer

Dockerの WebUIで一番有名なのが、Portainerだと思いますね。なぜこれを選んだか話もしたいんですが、いうほど掘れる話題無いです。軽量で簡単に動かせて手間かからないのが、Portainerぐらいで他のWebUI系はパッとしなかった。

クラスタ構築してどうなったのか

まだ結果は出ていません。現状大きな問題はなく順調に動いており、快適といえば快適という感じになっています。その一方、クラスタである必要はないと思うこともあります。今後の課題です。

また、時間が足りなかったりメンテナンスにそこそこな時間を割かなくてはいけないという点から、一部コンテナはStackとしてデプロイできていないです。さらには新たな問題点も見つけているので、今後の課題が積み重なっています。色々勉強しながら、ベストプラクティスを模索していきたいと思います。

今後、ちょこちょことこういう問題あった!解決した!といった系の投稿を小出ししていこうと思います。

大きなアウトプットしようとすると、時間ばかりが経過して何日も投稿しない日が続くのでね...

snake

CMSのGhostをDockerで利用する場合のdocker-compose.yml例

Ghost: Turn your audience into a business

データベースは、外部のものを利用することを想定

version: '3.1'

services:

ghost:
image: ghost:alpine
container_name: ghost
restart: always
ports:
- 80:2368
environment:
database__client: mysql
database__connection__host: [DB_HOST]
database__connection__user: [DB_USER]
database__connection__password: [DB_PASSWORD]
database__connection__database: [DB_DATABASE]
url: https://example.com
mail__transport: SMTP
mail__options__host: [MAIL_HOST]
mail__options__port: [MAIL_PORT]
mail__options__auth__user: [MAIL_USER]
mail__options__auth__pass: [MAIL_PASSWORD]
mail__from: [MAIL_FROM]
volumes:
- ./content:/var/lib/ghost/content

データベース

DB_HOST: データベースのホスト名
DB_USER: データベースのユーザー名
DB_PASSWORD: データベースのパスワード
DB_DATABASE: データベース名

メール

MAIL_HOST: メールサーバーのホスト名
MAIL_PORT: メールサーバーのポート番号
MAIL_USER: メールサーバーのユーザー名
MAIL_PASSWORD: メールサーバーのパスワード
MAIL_FROM: 送信用のメールアドレス

snake

OSS「Kanboard」をDockerで利用する場合のdocker-compose.yml例

Kanban Project Management Software - Kanboard

データベースに、外部のデータベースを利用することを想定

version: '2' services: kanboard: image: kanboard/kanboard:latest ports:

  • "80:80"
  • "443:443" environment: DATABASE_URL: [DB_DRIVER]://[DB_USER]:[DB_PASSWORD]@[DB_ADDRESS]:[DB_PORT]/[DB_DATABASE] volumes:
  • kanboard_data:/var/www/app/data
  • kanboard_plugins:/var/www/app/plugins
  • kanboard_ssl:/etc/nginx/ssl volumes: kanboard_data: kanboard_plugins: kanboard_ssl:

DATABASE_URL

DB_DRIVER: 利用するデータベース、デフォルトではSQLiteを利用。次から選択: postgres, mysql, sqlite

DB_USER: データベースのユーザー名

DB_PASSWORD: データベースのパスワード

DB_ADDRESS: データベースのアドレス

DB_PORT: データベースのポート

DB_DATABASE: データベースのデータベース名


environmentを記述しない場合、sqliteを使用します。ボリューム「kanboard_data」にデータを保存。

snake

最近ノートパソコンが異常に重いと思ってタスクマネージャー眺めていたら、Vmmemなるプロセスがメモリを食いつぶしていました。

Vmmemってなんぞやって事で物知りのGoogle先生に聞いてみたら、どうやらWindowsでLinux動かす為のWindows Subsystem for Linux 2(WSL2)のプロセスみたいなんですよ。

でもWindowsに普通に入ってるシステムがメモリを食いつぶすなんて問題、普通であれば考えにくいので、もう少し調べたら「WSL 2 consumes massive amounts of RAM and doesn't return it」というGitHub issueが出てきました。

WSL 2 consumes massive amounts of RAM and doesn’t return it · Issue #4166 · microsoft/WSL

ほっとくとメモリ食いつぶすよっていう問題です。予想に反して、普通に問題でした。

私はDocker for Desktopを使っていて、WSL2をアンインストールすれば問題解決!みたいにはならないので解決方法も探したら、下記のQiitaの記事が出てきました。

WSL2によるホストのメモリ枯渇を防ぐための暫定対処 - Qiita

記事内で示されている対処法は、メモリサイズを固定して利用するメモリ量に制限かけるというものです。

一応、下記にやり方を示しておきます。

%USERPROFILE%に.wslconfigを作成する。

%USERPROFILE%C:\User\ユーザー名のこと。分からなければ、WindowsキーとRキーを同時押しして %USERPROFILE%を実行して表示された場所がそこです。

そこに.qslconfigを作ったらメモ帳か何かで開いて下記を記述してください。

[wsl2]
memory=2GB
swap=0

memoryが利用可能なメモリ量、swapがスワップメモリ量です。swapはお好みで、memoryは自分のパソコンのメモリとご相談ください。

WindowsにDocker for Desktop入れたらメモリが食いつぶされて枯渇していると悩んでいる方は、以上の解決策を試してみて下さい。