AR ホームベーカリー

オイラのアウトプット用ホームベーカリー!

MongoDB の単体運用環境で雑にレプリカを作成する

本番がレプリカ環境なので、ローカルも同じ様にレプリカ構築したい場合があると思われる。 (mongoid の option に replica_set: rs1 とか書く時)

MongoDB は複数プロセスやホストを用意しなくても雑にレプリカを用意できる。

コンフィグの用意

レプリケーションの名前を設定する。

/etc/mongo/mongod.conf

macOSbrew 経由で入れたら /opt/homebrew/etc/mongod.conf あたり。

...

net:
  bindIp: 127.0.0.1
  ipv6: false
replication:
    replSetName: "rs0"

レプリケーションを作成する

コンフィグを用意したら mongod を起動して、 mongosh なりでログインします。

ログイン後、 rs.initiate を実行することで作成できます。

[root@localhost ~]# systemctl start mongod
[root@localhost ~]# mongosh

mongosh> rs.initiate({_id:"rs0",members:[{_id: 0,host:"127.0.0.1:27017"}]})

できました、以上! 本番では使うなよ!

参考?

qiita.com

master を main にしたら PR が全部クローズされた

バカバカバカ! Github のバカ!

どうして

適当にググったけど Github 公式でやりかたを解説しているページが見つからなかったので、そのへんの人が解説しているのを参考に。

izanagi-portfolio-site.com

git branch -m master main
git push origin main
git push origin :master

改名したあと master ブランチが削除されるので、まあ PR も自動で以降されるんだろうと思っていたら、全部「master 削除されたからクローズするわwwwww」となっており。

あーはん?

改めてググりなおしたら、大正義クラスメソッドくんが「ちゃんと変更しないとダメだし、Github 上からブランチ削除すれば警告出るよ」と書いていて、おおもう……。

dev.classmethod.jp

どうする

クローズされた PR 、あとから merge 先のブランチつけかえは出来ないようなので、全部再作成です……。

Your configuration specifies to merge with the ref 'refs/heads/master'

ちなみに上記の改名作業を実施したあと、 git pull したら怒られた。 見ているのはずっと remote の master とのことっぽい。

❯ git pull
Your configuration specifies to merge with the ref 'refs/heads/master'
from the remote, but no such ref was fetched.

senseiengineer.com

こちらに書いてあるとおり、 fetch して master への参照外して、 改めて main 参照してやればよい。

❯ git fetch
❯ git branch --unset-upstream
❯ git branch -u origin/main

❯ git pull
Already up to date.

以上、高い勉強代だったぜ……

NginxProxyManager を動かす (RockyLinux 8 で

公式に書いてあるとおりの手順で、まずは動く環境を作ります。

nginxproxymanager.com

Docker

Docker CommunityEdition インストール

$ sudo yum install -y yum-utils device-mapper-persistent-data lvm2
$ sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

$ sudo dnf install docker-ce

docs.docker.jp

Docker バージョン確認

$ docker -v
Docker version 23.0.1, build a5ee5b1
ユーザグループ Docker に追加する?

毎回 sudo するのも面倒なので、運用するユーザグループに追加しようと思いましたが、やってみた所ダメでした。

$ sudo usermod -aG docker user

$ sudo systemctl start docker
$ docker run hello-world
docker: permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Post "http://%2Fvar%2Frun%2Fdocker.sock/v1.24/containers/create": dial unix /var/run/docker.sock: connect: permission denied.
See 'docker run --help'.

sock ファイルを chgrp するとか chmod で権限を大きくする、みたいな話が出てきたのですが、前者はともかく後者は……という感じだったので、Socket ファイルを確認してみます。

$ ls -lha /var/run/docker.sock
srw-rw---- 1 root docker 0  2月 20 22:32 /var/run/docker.sock

うーん?

まあここで詰まるのは本意じゃないので、毎回 sudo すればいいか。

hello-world して動作確認する

うごきましたね。

$ sudo docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
2db29710123e: Pull complete
Digest: sha256:6e8b6f026e0b9c419ea0fd02d3905dd0952ad1feea67543f525c73a0a790fefb
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/
hello-world イメージを削除する

動作確認したかっただけなので、 hello-world イメージは削除しましょ。

$ sudo docker ps -a
CONTAINER ID   IMAGE         COMMAND    CREATED         STATUS                     PORTS     NAMES
97908c7b341c   hello-world   "/hello"   3 minutes ago   Exited (0) 3 minutes ago             peaceful_nash

$ sudo docker stop 97908c7b341c
97908c7b341c

$ sudo docker images
REPOSITORY    TAG       IMAGE ID       CREATED         SIZE
hello-world   latest    feb5d9fea6a5   17 months ago   13.3kB

$ sudo docker rmi feb5d9fea6a5
Error response from daemon: conflict: unable to delete feb5d9fea6a5 (must be forced) - image is being used by stopped container 97908c7b341c
#=> 複数のタグがついているので削除できないので、削除を強制する必要がある
$ sudo docker rmi -f feb5d9fea6a5
Untagged: hello-world:latest
Untagged: hello-world@sha256:6e8b6f026e0b9c419ea0fd02d3905dd0952ad1feea67543f525c73a0a790fefb
Deleted: sha256:feb5d9fea6a5e9606aa995e879d862b825965ba48de054caab5ef356dc6b3412

これでよし

Docker-compose

インストール

dnf install docker-ce した時に一緒に入っていた模様。

$ sudo dnf install docker-compose-plugin
メタデータの期限切れの最終確認: 0:56:41 時間前の 20230220220434秒 に実施しました。
パッケージ docker-compose-plugin-2.16.0-1.el8.x86_64 は既にインストールされています。
依存関係が解決しました。
行うべきことはありません。
完了しました!

バージョン確認

大丈夫そうですね。

$ docker compose version
Docker Compose version v2.16.0

NginxProxyManager インストール

ポート開放

firewalld の確認

firewalld 動作しております (アプライアンスがネットワークの先頭にいるので切ってもいいヤツ) 。

$ systemctl status firewalld
● firewalld.service - firewalld - dynamic firewall daemon
   Loaded: loaded (/usr/lib/systemd/system/firewalld.service; enabled; vendor preset: enabled)
   Active: active (running) since Tue 2023-02-21 06:48:16 JST; 7h left
     Docs: man:firewalld(1)
 Main PID: 839 (firewalld)
    Tasks: 3 (limit: 23263)
   Memory: 36.7M
   CGroup: /system.slice/firewalld.service
           └─839 /usr/libexec/platform-python -s /usr/sbin/firewalld --nofork --nopid

現状のルール確認

適用する zone を指定しないといけなくて、以外と面倒なんですよね。 今回は public に開放するサービス (port) を追加すれば良いようです。

$ sudo firewall-cmd --list-all
public (active)
  target: default
  icmp-block-inversion: no
  interfaces: ens3 ens4
  sources:
  services: cockpit dhcpv6-client ssh
  ports:
  protocols:
  forward: no
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:

ポート開放と設定有効化

--add-port したのち、 --reload でプロセスに設定再読み込みを行わせます。

$ sudo firewall-cmd --add-port=80/tcp --zone=public --permanent
success
$ sudo firewall-cmd --add-port=81/tcp --zone=public --permanent
success
$ sudo firewall-cmd --add-port=443/tcp --zone=public --permanent
success

$ sudo firewall-cmd --reload
success

ポート開放結果を確認する

ports: 80/tcp 81/tcp 443/tcp と追加されているのがわかりますね。 サービス名 http, https で指定しても良さそうですが、 NginxProxyManager の管理ポートである :81 は直接指定するしかなさそう。

$ sudo firewall-cmd --list-all
public (active)
  target: default
  icmp-block-inversion: no
  interfaces: ens3 ens4
  sources:
  services: cockpit dhcpv6-client ssh
  ports: 80/tcp 81/tcp 443/tcp
  protocols:
  forward: no
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:

Docker-compose 用 yml ファイルの準備

Docker-compose で利用する yml ファイルを準備します。

$ mkdir ~/nginx-proxy-manager; cd $_
$ vi ./docker-compose.yml
~/nginx-proxy-manager/docker-compose.yml
version: '3'
services:
  app:
    image: 'jc21/nginx-proxy-manager:latest'
    restart: unless-stopped
    ports:
      - '80:80'
      - '81:81'
      - '443:443'
    volumes:
      - ./data:/data
      - ./letsencrypt:/etc/letsencrypt

起動する

docker compose の plugin を使っているので以下のコマンドで起動します。

$ sudo docker compose up -d
[+] Running 33/33
 ⠿ app Pulled                                                                                                                                      22.8s
   ⠿ 4500a762c546 Pull complete                                                                                                                     2.2s
   ⠿ 2064244d4a45 Pull complete                                                                                                                     2.3s
   ⠿ 84215fabca57 Pull complete                                                                                                                     4.0s
   ⠿ b76f93d918a0 Pull complete                                                                                                                     4.1s
   ⠿ df317c467603 Pull complete                                                                                                                     4.2s
   ⠿ 83b1b9be61d5 Pull complete                                                                                                                     4.4s
   ⠿ 60d6f63fc4c0 Pull complete                                                                                                                     4.6s
   ⠿ a4d97773651a Pull complete                                                                                                                     7.9s
   ⠿ c06eb9e1dc9a Pull complete                                                                                                                     8.0s
   ⠿ a8167af86067 Pull complete                                                                                                                     8.1s
   ⠿ cd05bb490889 Pull complete                                                                                                                     8.6s
   ⠿ 723aeecfd151 Pull complete                                                                                                                     8.7s
   ⠿ 916e1ca435ed Pull complete                                                                                                                     9.2s
   ⠿ dae2831773a8 Pull complete                                                                                                                     9.3s
   ⠿ e87a4fe7a100 Pull complete                                                                                                                    10.1s
   ⠿ 458ba1ceb1d0 Pull complete                                                                                                                    10.5s
   ⠿ 368cd5f2b4c1 Pull complete                                                                                                                    10.6s
   ⠿ eac612b2d600 Pull complete                                                                                                                    14.3s
   ⠿ 5886c916a6d2 Pull complete                                                                                                                    14.3s
   ⠿ 20ee015b172f Pull complete                                                                                                                    14.4s
   ⠿ a50f24615148 Pull complete                                                                                                                    14.5s
   ⠿ 2ba8bdc1cb2e Pull complete                                                                                                                    14.6s
   ⠿ 8738d43676e1 Pull complete                                                                                                                    14.7s
   ⠿ aa813c6ef05a Pull complete                                                                                                                    14.8s
   ⠿ 003e6980c1b6 Pull complete                                                                                                                    14.9s
   ⠿ fb68e75b2b7a Pull complete                                                                                                                    15.1s
   ⠿ b98d05b8f325 Pull complete                                                                                                                    15.2s
   ⠿ 4f4fb700ef54 Pull complete                                                                                                                    15.3s
   ⠿ 748b5c7c86e2 Pull complete                                                                                                                    18.7s
   ⠿ 04aec91b6cb4 Pull complete                                                                                                                    18.8s
   ⠿ d854886c6c95 Pull complete                                                                                                                    18.9s
   ⠿ a046a4de3325 Pull complete                                                                                                                    19.1s
[+] Running 2/2
 ⠿ Network nginx-proxy-manager_default  Created                                                                                                     0.3s
 ⠿ Container nginx-proxy-manager-app-1  Started                                                                                                     1.7s

確認する

公式だと AdminUI にいけ、と書いているんですが、作った環境は 80 以外潰している (ならなんで開放した) という感じなので、publicUI な port 80 にアクセスしてみます。

うぇるかめ!

大丈夫そうですね、お疲れ様でした。

ログインする

IPアドレス:81 でアクセスすると管理画面が見えます。 こちらに初期設定されている情報でログインしましょう。

Email Address Password
admin@example.com changeme

nginxproxymanager.com

初回ログインすると、管理者のメールアドレス・パスワードを変更するように求められます。 素直に変更しておきましょう。

以下はパスワード変更する際の様子です、この前にメールアドレスの変更もあるんだけどスクリーンショット取得するの忘れた。

パスワード変更画面

このあとは

AdminUI からログインして設定をしていけば良いでしょう。 時間ができたら次回!

追記:ホストを登録する時の条件

インスタンス作成と同時に作業していたら、いつまで待っても host を追加できなくて悩んでいたのだけど、どうも追加する対象にヘルスチェック送ってオッケーな状態じゃないと登録できないっぽい。

RockyLinux 8.5 を 8.7 にアップグレードする

Hypervisor が AHV(Nutanix) なので、9.1 の ISO 登録したんだけど、 L7 にする予定だった IP を持ってるインスタンスが RockyLinux 8.5 だったのでめんどくさくて 8 系列で使うことにした。

EOL までにはこの Hypervisor も死ぬじゃろ。

アップグレードするコマンド

[root@localhost ~]# dnf -y upgrade --refresh

これでしまいや。

終わった後

お作法として reboot して ssytem-release を確認する。

[user@localhost ~]$ cat /etc/system-release
Rocky Linux release 8.7 (Green Obsidian)

[user@localhost ~]$ sudo dnf -y upgrade --refresh
Rocky Linux 8 - AppStream                                                                                                 10 kB/s | 4.8 kB     00:00
Rocky Linux 8 - BaseOS                                                                                                   8.8 kB/s | 4.3 kB     00:00
Rocky Linux 8 - Extras                                                                                                   6.3 kB/s | 3.1 kB     00:00
依存関係が解決しました。
行うべきことはありません。
完了しました!

8.9 になると思ってたけど 8.7 で打ち止めだった。 まあいいか。

EOL

endoflife.date

めっちゃ壊れた時

upgrade だっけ? と思って調べていたら、めっちゃ壊れてしまったとこから復旧している先人を偶然見つけてしまった。 (fedora だけど

kernhack.hatenablog.com

はえー、そんな状態でも復旧できるんだ、と知見があった。

ワイならイメージバックアップ無いなら問答無用で再インストールするなあ。

AppleSillicon 環境で Lima + Docker on MongoDB を動かす際に気をつけること

基本的に 5.x, 6.0.x は現状動かないので、メンテナンスされている 4.4.x を使うか、 どうしても 6.0.x を利用したい場合は brew からインストールして使いましょう。

ナンデ!?

docker pull 時に Docker 自体が利用環境に応じて最適なアーキテクチャを選んでくれる。 M1, M2 は ARM 系列なんだけど lima で動かしているとだいたい x86_64 の Docker が起動しているはず。 いざこの状態で docker pull すると mongoDB が起動しない。

hub.docker.com

例えばこの記事を書いてる時点では 6.0.4 が最新なんだけど、 pull してきた後に起動すると以下のように怒られる。

❯ docker run -v /tmp/lima:/data -p 27017:27017 mongo:6.0.4

WARNING: MongoDB 5.0+ requires a CPU with AVX support, and your current system does not appear to have that!
  see https://jira.mongodb.org/browse/SERVER-54407
  see also https://www.mongodb.com/community/forums/t/mongodb-5-0-cpu-intel-g4650-compatibility/116610/2
  see also https://github.com/docker-library/mongo/issues/485#issuecomment-891991814

これは docker を動かす lima のバックエンドである qemu が AVX をサポートしていないから、らしい。

公式にも色々書いてあるけど Rosetta2 の有無で動作が変わる、例えば brew 経由でバイナリインストールしたら Docker なくても動くよね実際動くし、と言及がある。

www.mongodb.com

At the moment, running natively on Apple M1 is referring to using Rosetta 2 without Docker (for example, installing the macOS x86_64 binaries via brew 48). The macOS packages are working fine for me on M1 with Rosetta 2 installed.

現時点では、Apple M1 でネイティブに実行するということは、Rosetta 2 を Docker なしで使用することを指しています (たとえば、brew 48 を介して macOS x86_64 バイナリをインストールします)。 macOS パッケージは、Rosetta 2 がインストールされた M1 で正常に動作しています。

で、なんで M1 + Lima (x86_64) の Docker で動かないかと言うと以下とのこと。

This discussion was originally about someone trying to run the Linux x86_64 binaries in Docker on M1, which will be problematic because of the requirement for AVX support in MongoDB 5.0 packages for Linux x86_64 39. The solution for the original question would be to either install MongoDB 4.4 packages on Linux (since those are not optimised for AVX) or to build MongoDB 5.x from source 22 with an older x86_64 CPU architecture target.

この議論はもともと、M1 上の Docker で Linux x86_64 バイナリを実行しようとしている人に関するものでした。これは、Linux x86_64 の MongoDB 5.0 パッケージでの AVX サポートの要件のために問題となるでしょう 39. 元の質問に対する解決策は、MongoDB をインストールすることです。 Linux 上の 4.4 パッケージ (これらは AVX 用に最適化されていないため)、または古い x86_64 CPU アーキテクチャ ターゲットを使用してソース 22 から MongoDB 5.x をビルドします。

まあやっぱり AVX が問題なんだワ、とのこと。

じゃあ aarch なり arm64 を選んだらどうなんの、と思ったら以下との事。

Building the MongoDB server with ARM64/aarch64 support for MacOS (SERVER-50115 106) is currently blocked pending resolution of a SpiderMonkey JavaScript engine upgrade (SERVER-42427 61).

MacOS 用の ARM64/aarch64 サポートを備えた MongoDB サーバーの構築 (SERVER-50115 106) は、SpiderMonkey JavaScript エンジンのアップグレード (SERVER-42427 61) の解決が保留されているため、現在ブロックされています。

ということで

結構前の記載だったんだけど、なんか先行きよくないのと結構詰まってしまったので自分向けに。

実際データベースアダプタとかで接続してて、 v4.x と v6.0.x 系でコンフィグ変更せずにいけるとかなら、M1 (ARM) 系は 4.x、それ以外は 6.0.x とか思い切ってバージョン違いにしてもいいかもしれない。

実際僕がメンテナンスしているプロジェクトでは、開発環境は 4.x で統一して、本番環境は 6.0.4 を使うことにした(少しでもパフォーマンス稼ぎたい要件が出てきたので)。

macOS に MongoDB 6.0 (community) のインストール

インストール

基本的に公式のドキュメントを参考にすればオッケー。

※ homebrew が利用可能な状態にしておきましょう。

www.mongodb.com

tap を設定する

brew tap mongodb/brew

formula を読み込む

brew update

インストールする

brew install mongodb-community@6.0
インストールされる様子

config もそうだけど、 brew services が馴染みなくてよく忘れるんだよなあ。

==> Installing mongodb/brew/mongodb-community
==> Caveats
To start mongodb/brew/mongodb-community now and restart at login:
  brew services start mongodb/brew/mongodb-community
Or, if you don't want/need a background service you can just run:
  mongod --config /opt/homebrew/etc/mongod.conf
==> Summary
🍺  /opt/homebrew/Cellar/mongodb-community/6.0.4: 10 files, 199.9MB, built in 2 seconds
==> Running `brew cleanup mongodb-community`...
Disable this behaviour by setting HOMEBREW_NO_INSTALL_CLEANUP.
Hide these hints with HOMEBREW_NO_ENV_HINTS (see `man brew`).
Removing: /opt/homebrew/Cellar/mongodb-community/6.0.1... (10 files, 199.6MB)
==> Caveats
==> mongodb-community
To start mongodb/brew/mongodb-community now and restart at login:
  brew services start mongodb/brew/mongodb-community
Or, if you don't want/need a background service you can just run:
  mongod --config /opt/homebrew/etc/mongod.conf

RHEL9 世代での SELinux

Red Hat は、SELinux を永続的に無効にする代わりに、Permissive モードを使用することを強く推奨します。Permissive モードの詳細は Permissive モードへの変更 を参照してください。

access.redhat.com

とのことなので、無効化するくらいなら Permissive にしてくれやとのこと。

そもそも SELinux 無効化するの、設定は意味不明だし煩雑だし、いざやってみるとミドルウェア・アプリケーションが対応してない、みたいな地獄でみんな設定するのが嫌になるのが大本な気がするんだよな。

IDS みたいにもっとうっすらと存在してて、動的にカジュアルに扱えればなあ、と思うけど、SELinux 初心者過ぎて今どきは全部課題をクリアしているのかもしれない。