はじめまして、インプリムさんのPleasanter Loungeで開催されているNakano Tech Loungeのイベントの運営メンバーをしています、もちもちずきんと申します。
私は普段はSIerと事業会社でバックエンド開発やサーバー構築を行っているインフラ・バックエンドエンジニアです。Linuxユーザーグループである、東海道らぐやFediverse Linux Users Group、openSUSE ユーザー会などのコミュニティ活動への参加を趣味としており、多数出没しています。
今回は所属としては全くのインプリムさんの部外者でありながら、このアドベントカレンダーの執筆にお誘いをいただいたので、Pleasanterをk3sで構築してみようと思います。
はじめに
今回のこの記事ではインプリムさんの公式ドキュメントにも記載がなく、調べてみたところ前例もあまりない、PleasanterをKubernetesで動かしてみるという部分が趣旨になります。
おことわりとして、この記事に書いてある内容は
- 非公式の人間が書いています
- 実験的な内容を含むため、実用的・セキュリティ的にそのまま運用を推奨できるものではありません
- プロダクトの各名称及びバージョンは2025年12月19日現在のものを使用しています
ということを承知の上で読んでいただけると幸いです。
また、本記事で紹介する構成は、EKS や GKEいわゆるマネージドKubernetesサービスを使用した「クラウド前提の Kubernetes 運用」ではありません。すべてのノード、ストレージ、ネットワークを自前で管理する フルオンプレミス環境 を前提に、「社内システムとして止まりにくい構成」を検証します。
概要
kubernetes(k3s)を使用してHAなPleasanter環境を構築する
用意するものは以下です
- VM:4台(クラスタ用3台+Rancher用1台)
- Tailscaleアカウント
今回の構成
今回の登場人物です。ざっくりの構成とそれぞれ出てくる名前について説明します。
また、これはもしかしたら賛非が分かれるかもしれませんが、今回はつかえるものは使える限りhelmを使用して構築を行います。helmとはKubernetes用のパッケージマネージャで複雑なKubernetesの設定の管理を容易にします。
インフラ・ミドルウエア層
OS:openSUSE Leap Micro 6.2
OSは今回openSUSE Leap Micro 6.2を使用します。openSUSE Leap Microは高信頼性を謳う軽量Linuxディストリビューションです。
スナップショットでのOS管理などを特徴としており、今回のようなコンテナや仮想化の環境などに最適とされます。
Kubernetesディストリ:K3s
Kubernetesのディストリビューションは複数ありますが、今回は私の好みでRancher Labs によって開発され、現在は SUSE 傘下でメンテナンスされているK3sを使用したいと思います。
軽量なKubernetes。インストールが簡単で、メモリ使用量は半分、100MB未満のバイナリにすべてが収まります。
とあり、Go言語で実装されており、軽量かつ単一バイナリで動作することが売りです。
分散ブロックストレージ:Longhorn
今回永続ボリュームとして使用する分散ブロックストレージの実装はLonghornを使用します。エンタープライズ版は最近名前が変わりました。そっちはSUSE Storageと呼ばれているみたいです。
Webコンソール:Rancher
今回はお手軽構築の道具として、SUSEが開発しているRancherをk3sクラスタおよびlonghorn分散ストレージの管理用WebコンソールとしてRancherを使用します。
VPN・接続窓口:Tailscale
今回、VM間接続とクライアント⇔サービス間接続をTailscaleで接続・ルーティングします。TailscaleはWireGuardをベースにしたP2P型のVPNサービスです。クライアントはOSSで公開されていることなどが特徴的です。
アプリケーション層
Ingress:Traefik
TraefikはTraefik Labsによって開発されている、クラウドネイティブ環境向けに設計されたGoで実装されたリバースプロキシ・ロードバランサです。k3sにはデフォルトでIngress ControllerにTraefikが採用されています。今回はそれを使用します。
アプリケーション:implem/pleasanter:1.4.23.3
皆さんご存知、今回の主役、Pleasanterは株式会社インプリムさんがOSSで開発しているノーコード・ローコードツールです。
業種業界を問わず数多くの導入実績、140社以上の全国に広がるパートナーネットワーク、充実した学習コンテンツと安心のサポート体制。プリザンターが、あなたの企業のDXを成功に導きます。
今回は執筆時点で最新バージョンの1.4.23.3のdockerhubのイメージを使用します。
データベース:CloudNativePG 1.27.0 / PostgreSQL 16
CloudNative PGはPostgreSQLをKubernetes環境で動かす、オペレーターです。プライマリ・スタンバイでの運用、ストリーミングレプリケーション、自動フェイルオーバーなど、高可用性運用に対応しています。今回はCloudNative PGのバージョンを1.27.0を使用し、動かすPostgreSQLのバージョンは16を使用します。
1. k3s用VMの準備
(今回は私の自宅にあるサーバー環境でProxmox上でVMを作成しています)
今回は3台のVMで冗長化構成を組んで動かします。この手順は3台全てに行います。
1-1. openSUSE Leap Micro 6.2のインストール
https://get.opensuse.org/ja/leapmicro/6.2/ からご自身のマシンのCPUアーキテクチャにあったイメージやISOでインストールを行います。今回は「自己インストール型イメージ」でインストールをおこない
ちなみに今回はメインのアプリケーションであるPleasanterのコンテナイメージがAMD64かARM64で配布されているのでこの構成で使用できるCPUアーキテクチャは実質この二択になります。
1-2. OSのインストール
起動するとディスクのデータを全て消してインストールを始めていいか聞かれます。<Yes>でいきましょう。そしたらインストールが行われます。インストールが完了したら、再起動がかかり、rootパスワードやタイムゾーンなど、初期セットアップに必要な情報を求められます。それぞれの環境に合わせて回答していきましょう。
hostnameを見分けやすいようにユニークなものをつけておきましょう。今回はpleasanter-k3s-nにしてあります。
echo pleasanter-k3s-1 > /etc/hostname
のような形で設定します。
1-3. Tailscaleのインストール
今回ノード間接続に使用するTailscaleのインストールを行います。UbuntuやFedoraなどのディストリであれば
curl -fsSL https://tailscale.com/install.sh | sh
を実行するだけでインストールできるのですが、Leap Microはサポート対象外なので手動でインストールする必要があります。基本的には公式のガイドに沿っていればいいです。
今回は/usr/local/binにインストールを行います。
まず、Tailscaleのバイナリを取得するためのwgetコマンドをインストール・再起動します。
transactional-update pkg install wget
reboot
先程インストールしたwgetコマンドでTailscaleのバイナリを取得します。その時にマシンのアーキテクチャに合った最新バージョンを公式サイトから取得してください。
wget https://pkgs.tailscale.com/unstable/tailscale_1.93.56_amd64.tgz
tgzで圧縮されているので解凍し、ディレクトリに入ります。
tar xvf tailscale_1.93.56_amd64.tgz
cd tailscale_1.93.56_amd64
installコマンドでディレクトリにあるTailscaleのバイナリを/usr/local/binにインストールします。
install -m 0755 ./tailscale /usr/local/bin/tailscale
install -m 0755 ./tailscaled /usr/local/bin/tailscaled
また、このディレクトリの中にはsystemdの定義ファイルも入っていますので、それを/etc/systemd/systemに移動します。
cp ./systemd/* /etc/systemd/system
stateファイルについてもディレクトリを作って配置します
mkdir /var/lib/tailscale
cp tailscaled.state /var/lib/tailscale/
また/etc/defaultにtailscaleのenvを配置します。お好みのエディタで/etc/default/tailscaledに以下の内容を書いてください。
FLAGS=""
PORT="41641"
デフォルトのsystemd設定ファイルはバイナリのパスが異なるので、編集する必要があります。お好みのエディタで/etc/systemd/system/tailscaled.serviceを編集しましょう。以下のようにすると動くはずです。
- ExecStart=/usr/sbin/tailscaled --state=/var/lib/tailscale/tailscaled.state --socket=/run/tailscale/tailscaled.sock --port=${PORT} $FLAGS
- ExecStopPost=/usr/sbin/tailscaled --cleanup
+ ExecStart=/usr/local/bin/tailscaled --state=/var/lib/tailscale/tailscaled.state --socket=/run/tailscale/tailscaled.sock --port=${PORT} $FLAGS
+ ExecStopPost=/usr/local/bin/tailscaled --cleanup
そうしたら、デーモンのリロードをかけることで設定が読み込まれ、起動することができるようになるはずです。
systemctl daemon-reload
systemctl start tailscaled.service
そうしたら、tailscaleを起動・接続します。
tailscale up
ログイン用のURLが出てくるのでそこにアクセスし、認証を行うとTailscaleに接続されます
To authenticate, visit:
https://login.tailscale.com/a/xxxxxxxxxxxxx
1.4. k3sのインストール
k3sのインストールを行っていきます。こちらは公式のインストールスクリプトが使用できるのでそれを実行します。また、起動します。
1-4-1. 1台目
まずシングルノードとしてクラスタを構築します。今回ノード間接続はtailscaleにお任せするので、tailscaleのIPアドレスを確認しておきます。
ip a
2台目以降の接続用トークンを作っておきます。
openssl rand -hex 32
などでランダムな文字列を生成するのが良いでしょう。
tailscale0のIPアドレスが今回は100.70.242.62だったので、これを--tls-sanに書きます。Tailscaleでの接続の場合これを書かないと証明書のCAエラーが出てしまうので注意しましょう。
curl -sfL https://get.k3s.io | K3S_TOKEN={さっき作ったトークン} sh -s --tls-san 100.70.242.62 --cluster-init
systemctl enable --now k3s
起動しているか確認してみましょう
# k3s kubectl get no
NAME STATUS ROLES AGE VERSION
localhost.localdomain Ready control-plane,master 7s v1.33.6+k3s1
2つめ以降のノードで必要なトークンを控えておきます
cat /var/lib/rancher/k3s/server/node-token
1-4-2. 2台目以降
https://docs.k3s.io/datastore/ha-embedded#existing-single-node-clusters に従ってインストールスクリプトを使用して同様にインストールを行います。今回は3台ともコントロールプレーンとしての役割をもたせます。
--tls-sanには自分のマシンのTailscaleのIPアドレスを入れます。
curl -sfL https://get.k3s.io | K3S_TOKEN={1台目で控えたトークン} sh -s - server --server https://{1台目のIP}:6443 --tls-san {tailscale0のIP}
1-4-3. クラスタの確認
3台のうちのどれか一つでkubectl get noコマンドで確認を行うと、マルチノードのクラスタになっていることがわかります。
kubectl get no
NAME STATUS ROLES AGE VERSION
pleasanter-k3s-1 Ready control-plane,etcd,master 30m v1.33.6+k3s1
pleasanter-k3s-2 Ready control-plane,etcd,master 3m14s v1.33.6+k3s1
pleasanter-k3s-3 Ready control-plane,etcd,master 11s v1.33.6+k3s1
1-5. Longhornストレージの構築の準備
Longhornはopen-iscsiとiscsidが必要なため、インストールを行っておきます。
transactional-update pkg install open-iscsi nfs-client
reboot
systemctl enable --now iscsid
2. Rancher用VMの準備
Rancher用のVM準備に関しても1-1から1-3までは同じです。それぞれ実行してください。
2-1. Dockerのインストール
今回はRancherは簡単にDockerで実行します。transactional-updateでdockerをインストールします。
transactional-update pkg install docker
reboot
systemctl enable --now docker
2-2. Ranckerの起動
Rancherをdockerでインストール・起動します
docker run -d --restart=unless-stopped -p 80:80 -p 443:443 --privileged rancher/rancher
初期パスワードはログに出ているので確認しておきます
docker logs {コンテナID} 2>&1 | grep "Bootstrap Password:"
https://{IPアドレス} にアクセスすると、Rancherのページが表示されます。確認しておいた初期パスワードでログインし、パスワードを変更したら、Rancherのセットアップ完了です。
2-3. k3sクラスタをRancherに登録する
セットアップしたk3sクラスタをRancherに追加します。ちなみにデフォルトで表示されているのは、Rancherのノードに自動で作られたシングルノードクラスタです。
真ん中辺りにある「Import Existing」ボタンから追加します。
今回はオンプレなのでGenericを選択します
色々設定項目がありますが、今回はCluster Nameのみ設定します。今回は「pleasantertest」にしました
Createボタンを押すと、接続用のkubectlコマンドが表示されるので、コピーして3つのうちのどこかで実行します。実行が成功すると、クラスタが追加され、リソースの監視などができるようになります。
3. CloudNative PGによるPostgreSQLクラスタの構築
下準備は整いました。次にCloudNative PGをhelmを使用して構築します。
3-1. Rancherからリポジトリをロード
登録したクラスタを選択して、Apps>RepositoriesのCreateを押します。
リポジトリの追加画面で任意の名前とURLを入力します。今回は普通に名前をcnpgのものとlonghornのものを入れます。
CNPGのURL : https://cloudnative-pg.github.io/charts
LonghornのURL:https://charts.longhorn.io
正常に追加できると以下のようにActive表示になります。
3-2. Longhornのインストールとストレージの構築
同じ画面のままメニューをChartsに切り替えます。検索フォームに「longhorn」と入力すると、ヒットします。longhornをクリックします。
Install this versionからインストールを行います。
今回はデフォルト設定でそのままインストールします。
インストールが進む様子をログで確認しながらコーヒーでも飲みましょう。
インストールが完了すると、左のタブにLonghornが追加されているはずです。OverviewからLonghornをクリックするとLonghornのWeb管理画面にジャンプすることができます。
上のメニューのVolumeを選択し、CreateVolumeを選択します。
かっこいいダッシュボードが表示されたら作業完了です。
3-3. CloudNativePGのクラスタ構築
3-3-1. CloudNativePG Operatorのインストール
同じ画面のままメニューをChartsに切り替えます。検索フォームに「cloudnative pg」と入力すると、ヒットします。cloudnative-pgをクリックします。
問題なさそうであればInstall this versionをクリックします。
そうすると、NamespaceとNameを聞かれます。今回はNamespaceはdefaultのまま、Nameは空にしました。
また、コントロールも冗長化したいので最後のステップのyaml変更画面でreplicaCountを3に変更します。
Installを行うとオペレータがインストールされます。
3-3-2. CloudNativePG Clusterのインストール
同じ画面のままメニューをChartsに切り替えます。検索フォームに「cloudnative pg」と入力すると、ヒットします。clusterをクリックします。
Install this versionを押すと、NamespaceとNameを聞かれます。今回はNamespaceはdefaultのまま、Nameは空にしました。
また、コントロールも冗長化したいので最後のステップのyaml変更画面でstorage.storageClassを先程入れたlonghornに変更します。
ここでサーバー側でk8sのpodが作成されているか見てみましょう。
pleasanter-k3s-1:/home/yoheizuho # kubectl get po
NAME READY STATUS RESTARTS AGE
cloudnative-pg-0-1766048663-86857dbbc9-7msqb 1/1 Running 0 25m
cloudnative-pg-0-1766048663-86857dbbc9-dh2rr 1/1 Running 0 25m
cloudnative-pg-0-1766048663-86857dbbc9-r4fwh 1/1 Running 0 25m
cluster-0-1766049839-1 1/1 Running 0 5m55s
cluster-0-1766049839-2 1/1 Running 0 5m2s
cluster-0-1766049839-3 1/1 Running 0 4m25s
csi-attacher-b5547c89c-5jrzr 1/1 Running 0 25m
csi-attacher-b5547c89c-fcx2l 1/1 Running 0 25m
csi-attacher-b5547c89c-ndbkn 1/1 Running 0 25m
csi-provisioner-6d9fbbd668-c9ld5 1/1 Running 0 25m
csi-provisioner-6d9fbbd668-pknjq 1/1 Running 0 25m
csi-provisioner-6d9fbbd668-wmbng 1/1 Running 0 25m
csi-resizer-588c678f58-d99gb 1/1 Running 0 25m
csi-resizer-588c678f58-f7wgs 1/1 Running 0 25m
csi-resizer-588c678f58-sbwzw 1/1 Running 0 25m
csi-snapshotter-589f996dc-6szwp 1/1 Running 0 25m
csi-snapshotter-589f996dc-mlw7g 1/1 Running 0 25m
csi-snapshotter-589f996dc-vwv4b 1/1 Running 0 25m
engine-image-ei-3154f3aa-6jc2p 1/1 Running 0 26m
engine-image-ei-3154f3aa-pqvqx 1/1 Running 0 26m
engine-image-ei-3154f3aa-t78p5 1/1 Running 0 26m
instance-manager-38e4191462ab524cde79ff02ff1ab2a9 1/1 Running 0 26m
instance-manager-4977adb0b5c6229ebc590735b86ba78f 1/1 Running 0 26m
instance-manager-f4a600b4d74a706f48cb8fca0985b0ee 1/1 Running 0 26m
longhorn-csi-plugin-gzt9z 3/3 Running 0 25m
longhorn-csi-plugin-ktq5h 3/3 Running 0 25m
longhorn-csi-plugin-n8mdj 3/3 Running 0 25m
longhorn-driver-deployer-567c4b678b-hc88k 1/1 Running 0 27m
longhorn-manager-gxlqc 2/2 Running 0 27m
longhorn-manager-nr5zq 2/2 Running 0 27m
longhorn-manager-t8pxh 2/2 Running 0 27m
longhorn-ui-7974b7c999-hvlqk 1/1 Running 0 27m
longhorn-ui-7974b7c999-xcx8s 1/1 Running 0 27m
3-3-3. データベースの設定
PostgreSQLのオーナーユーザーのパスワードを変更します。Rancherのクラスタ管理画面からService Discovery > Servicesで構築したCloudNativePGのRW(ReadWrite)サービス(今回はmastodon-cnpg-cluster-rw )をクリックします。そうするとPodsにRWのPodが表示されているので、Nameをクリックします。Podの管理画面右上の︙からExecuteShellをクリックするとターミナルがブラウザ上に展開されます。
パスワードは適宜適切なものを使用してください。
postgres@cluster-0-1766049839-1:/$ psql
psql (16.11 (Debian 16.11-1.pgdg11+1))
Type "help" for help.
postgres=# ALTER ROLE postgres with password 'super_strong_pass';
ALTER ROLE
postgres=# quit;
4. Pleasanterのクラスタ構築
最後に皆さんお待ちかねPleasanterを構築します。以下のyamlファイルをサーバー上に作成します。今回は名前をpleasanter.yamlにしました。データベースのパスワードやホスト名は環境によって異なるので適宜変更してください。この設定では3つのレプリカを作ります。
データベースのRWのホスト名はRancherのServiceDiscovery > Servicesのなかから確認できます。自動で作られているならcluster-0-1766049839-rwのような名前です。
traefikで用いるホスト名も環境によって変更が必要です。今回はpleasanter.example.comになっています。
apiVersion: v1
kind: Secret
metadata:
name: pleasanter-db-secret
namespace: default
type: Opaque
stringData:
Implem_Pleasanter_Rds_PostgreSQL_SaConnectionString: "Host=cluster-0-1766049839-rw;Port=5432;Database=postgres;uid=postgres;pwd={上で設定したパスワード};"
Implem_Pleasanter_Rds_PostgreSQL_OwnerConnectionString: "Host=cluster-0-1766049839-rw;Port=5432;Database=#ServiceName#;uid=#ServiceName#_Owner;pwd={任意のパスワード};"
Implem_Pleasanter_Rds_PostgreSQL_UserConnectionString: "Host=cluster-0-1766049839-rw;Port=5432;Database=#ServiceName#;uid=#ServiceName#_User;pwd={任意のパスワード};"
---
apiVersion: v1
kind: ConfigMap
metadata:
name: pleasanter-config
namespace: default
data:
PORT: "8080"
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: pleasanter
namespace: default
spec:
replicas: 3
revisionHistoryLimit: 2
selector:
matchLabels:
app: pleasanter
template:
metadata:
labels:
app: pleasanter
spec:
containers:
- name: pleasanter
image: implem/pleasanter:1.4.23.3
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 8080
env:
- name: Implem.Pleasanter_Rds_PostgreSQL_SaConnectionString
valueFrom:
secretKeyRef:
name: pleasanter-db-secret
key: Implem_Pleasanter_Rds_PostgreSQL_SaConnectionString
- name: Implem.Pleasanter_Rds_PostgreSQL_OwnerConnectionString
valueFrom:
secretKeyRef:
name: pleasanter-db-secret
key: Implem_Pleasanter_Rds_PostgreSQL_OwnerConnectionString
- name: Implem.Pleasanter_Rds_PostgreSQL_UserConnectionString
valueFrom:
secretKeyRef:
name: pleasanter-db-secret
key: Implem_Pleasanter_Rds_PostgreSQL_UserConnectionString
readinessProbe:
tcpSocket:
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 2
failureThreshold: 6
livenessProbe:
tcpSocket:
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 2
failureThreshold: 6
resources:
requests:
cpu: 100m
memory: 256Mi
limits:
cpu: "2"
memory: 2Gi
---
apiVersion: v1
kind: Service
metadata:
name: pleasanter
namespace: default
spec:
type: ClusterIP
selector:
app: pleasanter
ports:
- name: http
port: 8080
targetPort: 8080
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: pleasanter
namespace: default
spec:
ingressClassName: traefik
rules:
- host: pleasanter.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: pleasanter
port:
number: 8080
kubectl applyと行きたいところですがCodeDefinerの実行を行います。ここのタイムゾーンなどの設定項目に関しては公式のDockerでのインストール手順と同じなので参照してください。
kubectl -n default run codedefiner-once --rm -it \
--image=implem/pleasanter:codedefiner \
--restart=Never \
--env=Implem.Pleasanter_Rds_PostgreSQL_SaConnectionString="Host=cluster-0-1766049839-rw;Port=5432;Database=postgres;uid=postgres;pwd={上で設定したパスワード};" \
--env=Implem.Pleasanter_Rds_PostgreSQL_OwnerConnectionString="Host=cluster-0-1766049839-rw;Port=5432;Database=#ServiceName#;uid=#ServiceName#_Owner;pwd={任意のパスワード};" \
--env=Implem.Pleasanter_Rds_PostgreSQL_UserConnectionString="Host=cluster-0-1766049839-rw;Port=5432;Database=#ServiceName#;uid=#ServiceName#_User;pwd={任意のパスワード};" \
-- _rds /l ja /z Asia/Tokyo
途中で
Type "y" (yes) if the license is correct, otherwise type "n" (no).
と聞かれるのでyを入力します。そうするとログが流れてCodeDefinerが走るはずです。
ホストでkubectlコマンドを用いてpodを起動させます。
kubectl apply -f pleasanter.yaml
kubectl get poで起動したpodを取得してみましょう。namespaceをpleasanterで作成したので指定しています。
pleasanter-k3s-1:/home/yoheizuho # kubectl get po
NAME READY STATUS RESTARTS AGE
cloudnative-pg-0-1766048663-86857dbbc9-7msqb 1/1 Running 0 116m
cloudnative-pg-0-1766048663-86857dbbc9-dh2rr 1/1 Running 0 116m
cloudnative-pg-0-1766048663-86857dbbc9-r4fwh 1/1 Running 0 116m
cluster-0-1766049839-1 1/1 Running 0 97m
cluster-0-1766049839-2 1/1 Running 0 96m
cluster-0-1766049839-3 1/1 Running 0 95m
csi-attacher-b5547c89c-5jrzr 1/1 Running 0 117m
csi-attacher-b5547c89c-fcx2l 1/1 Running 0 117m
csi-attacher-b5547c89c-ndbkn 1/1 Running 0 117m
csi-provisioner-6d9fbbd668-c9ld5 1/1 Running 0 117m
csi-provisioner-6d9fbbd668-pknjq 1/1 Running 0 117m
csi-provisioner-6d9fbbd668-wmbng 1/1 Running 0 117m
csi-resizer-588c678f58-d99gb 1/1 Running 0 117m
csi-resizer-588c678f58-f7wgs 1/1 Running 0 117m
csi-resizer-588c678f58-sbwzw 1/1 Running 0 117m
csi-snapshotter-589f996dc-6szwp 1/1 Running 0 117m
csi-snapshotter-589f996dc-mlw7g 1/1 Running 0 117m
csi-snapshotter-589f996dc-vwv4b 1/1 Running 0 117m
engine-image-ei-3154f3aa-6jc2p 1/1 Running 0 118m
engine-image-ei-3154f3aa-pqvqx 1/1 Running 0 118m
engine-image-ei-3154f3aa-t78p5 1/1 Running 0 118m
instance-manager-38e4191462ab524cde79ff02ff1ab2a9 1/1 Running 0 117m
instance-manager-4977adb0b5c6229ebc590735b86ba78f 1/1 Running 0 117m
instance-manager-f4a600b4d74a706f48cb8fca0985b0ee 1/1 Running 0 117m
longhorn-csi-plugin-gzt9z 3/3 Running 0 117m
longhorn-csi-plugin-ktq5h 3/3 Running 0 117m
longhorn-csi-plugin-n8mdj 3/3 Running 0 117m
longhorn-driver-deployer-567c4b678b-hc88k 1/1 Running 0 118m
longhorn-manager-gxlqc 2/2 Running 0 118m
longhorn-manager-nr5zq 2/2 Running 0 118m
longhorn-manager-t8pxh 2/2 Running 0 118m
longhorn-ui-7974b7c999-hvlqk 1/1 Running 0 118m
longhorn-ui-7974b7c999-xcx8s 1/1 Running 0 118m
pleasanter-6f6b4c769d-2pcvd 1/1 Running 0 5m4s
pleasanter-6f6b4c769d-8b6zt 1/1 Running 0 5m17s
pleasanter-6f6b4c769d-r2jv5 1/1 Running 0 4m52s
また、traefikで待ち受けがされているか確認してみましょう。
pleasanter-k3s-1:/home/yoheizuho # kubectl get ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
pleasanter traefik pleasanter.example.com 192.168.0.111,192.168.0.119,192.168.0.222 80 50m
pleasanter.example.comのホスト名で80ポートで公開されていることがわかります。(なぜかマシンのローカルIPになってしまっていますが💦)
5. ルーティングの設定
サーバーIPのAレコードでDNSラウンドロビンを行うのがいいですが、今回は公開していないので、/etc/hostsで運用します。
Cloudflaredを使うなどの方法もあります。
6. ブラウザで確認
これで構築の全ての工程が終わりました。設定したホスト名でブラウザでアクセスしてみましょう。
ログイン画面が表示されました🎉やったー成功です!!(実はめっちゃ失敗しながらここまできたのでめっちゃ嬉しい)
「ログインID: Administrator」、「初期パスワード: pleasanter」を入力します。 デフォルトのパスワードの変更が求められると思いますが、それを入力すると…
きましたね…長かった…(ここまで4日かかっている)
このあとのフェイルオーバーテストのためにも、なにかプロジェクトを作ってみましょう
ちゃんと作成されましたね。
7. フェイルオーバーのテスト
今回のテーマである冗長化、本当に効いているのかテストしてみましょう。
ServiceDiscoveryを見ると、RW=プライマリはcluster-0-1766049839-1というpodが担っており、ノードはpleasanter-k3s-2で動いているようです。
ということでpleasanter-k3s-2を落としてみます。
pleasanter-k3s-2:/home/yoheizuho # poweroff
少し待っているとpleasanter-k3s-3 にあるcluster-0-1766049839-2がRWに昇格しました。
マシンの性能不足だと思われますが、数分ダウンタイムが出てしまいましたが、無事参照が可能になりました。
それでは電源を落としたpleasanter-k3s-2を再度起こしてみましょう。
pleasanter-k3s-2:/home/yoheizuho # kubectl get no
NAME STATUS ROLES AGE VERSION
pleasanter-k3s-1 Ready control-plane,etcd,master 163m v1.33.6+k3s1
pleasanter-k3s-2 Ready control-plane,etcd,master 162m v1.33.6+k3s1
pleasanter-k3s-3 Ready control-plane,etcd,master 163m v1.33.6+k3s1
確認すると、k3sのクラスタには復帰しているようです。
障害時はここから復旧作業をもろもろ行っていく形になるでしょう。
まとめ
Pleasanterの環境をk3s+Longhorn+CNPGで冗長化をして、自動フェイルオーバーを行う構成で落ちない社内システムを作ってみようという趣旨で書かせてもらいました。
実際の結果はフェイルオーバーはして動いたものの、ダウンタイムが数分発生してしまう結果になりました。
HDDのサーバーに複数VMを作って実験をしたのでそのディスクIOとメモリ、CPUのスペック不足が影響していると思われます。
自分がお世話になっているサービスを前例があまりない構成で構築してみるのは結構楽しかったです。なにかに応用できれば良いな。閲覧くださり、ありがとうございました。





























