跳到主要內容
節省工具箱Jason Tools
經驗分享

Graylog 的 MongoDB 5.0 升級 7.0

Jason Cheng 發布 瀏覽 1 次
Graylog 的 MongoDB 5.0 升級 7.0
本文目錄
  1. 環境與原則
  2. 升級前必讀的地雷
  3. 準備工作
  4. 第一階段:5.0 → 6.0
  5. 第二階段:6.0 → 7.0
  6. 第三階段:啟動 Graylog
  7. 復原方式
  8. 預估時間
  9. 升級完成檢查清單
  10. 結論
  11. 參考資料

這次要把一套 Graylog 從 6 升到 7,Graylog 7 需要 MongoDB 7.0,但這套環境的 MongoDB 還停在 5.0,而且是兩台組成的 replica set。MongoDB 不能跨版本直接跳,要 5.0 → 6.0 → 7.0 一版一版升,每一版都要升完程式、再調整 FCV(Feature Compatibility Version)。

過程中踩到幾個地雷,其中最麻煩的是 apt 顯示安裝成功,mongod 其實根本起不來。這篇把整理好的 SOP 記錄下來,也補上官方文件裡要注意的地方。

環境與原則

項目內容
作業系統Ubuntu 22.04
節點mongo1(192.168.10.41,PRIMARY)、mongo2(192.168.10.42,SECONDARY)
replica set 名稱rs0
升級路徑5.0 → 6.0 → 7.0

原則:

  • 兩台不能同時升:先升 SECONDARY,驗證正常後,PRIMARY 先 stepdown 交出角色再升
  • 每一版都要調 FCV:升完程式、整個 replica set 都正常之後,才把 FCV 調到新版本,再進行下一版的升級
  • 6.0 起用 mongosh:舊的 mongo 指令在 6.0 移除了
  • 7.0 的 setFCV 要加 confirm: true

注意:兩台組成的 replica set,停掉任何一台,剩下那台就會失去多數票,PRIMARY 會自動退成 SECONDARY,整個 replica set 變成無法寫入。所以這次是停掉 Graylog 做維護,不是不停機升級。要真正做到滾動升級不中斷,replica set 至少要有三個投票成員(或兩台加一個 arbiter)。

升級前必讀的地雷

地雷一:storage.journal.enabled 已移除

從 4.0 時代沿用下來的 /etc/mongod.conf,通常會有這段:

storage:
  journal:
    enabled: true

MongoDB 從 6.1 起 journaling 一律開啟,移除了 storage.journal.enabled 選項(以及 --journal、--nojournal 參數),7.0 也一樣。設定檔裡還有這段的話,mongod 會直接起不來:

Unrecognized option: storage.journal.enabled

6.0 還認得這個選項,所以 5.0 → 6.0 時不會出事,到 6.0 → 7.0 才會爆。升 7.0 之前務必先把它拿掉。

地雷二:apt install 成功不代表 mongod 有起來

apt install 過程中會試著重新啟動 mongod,就算 mongod 起不來,apt 本身還是可能顯示成功。每次安裝完一定要檢查 systemctl is-active mongod 和 mongod --version,不要跳過。

地雷三:stepdown 之後要確認角色真的換了

rs.stepDown() 回傳後不代表選舉已經完成,動手前先用 db.hello().isWritablePrimary 確認自己已經不是 PRIMARY。

準備工作

確認目前狀態(兩台)

lsb_release -a
mongod --version | head -1
systemctl is-active mongod
// mongosh 或 mongo 內執行
rs.status().members.forEach(m => print(m.name, m.stateStr, m.health))
rs.printSecondaryReplicationInfo()     // 確認 SECONDARY 沒有落後
db.adminCommand({ getParameter: 1, featureCompatibilityVersion: 1 })

注意:升級前 FCV 必須等於目前的版本。要升 6.0,FCV 要先是 5.0;要升 7.0,FCV 要先是 6.0。如果 5.0 的 FCV 還停在 4.4(從 4.4 升上來後忘了調),要先執行 db.adminCommand({ setFeatureCompatibilityVersion: "5.0" })。

開檔數限制

MongoDB 官方建議 nofile 至少 64000。用套件安裝的 mongod 是由 systemd 啟動,/etc/security/limits.conf 對它無效,實際的限制以 systemd unit 的 LimitNOFILE 為準(官方套件預設已設 64000)。確認方式:

cat /proc/$(pidof mongod)/limits | grep -i 'open files'

備份

在 PRIMARY 上做:

mkdir -p /var/backups/mongo
mongodump --host 192.168.10.41:27017 --out /var/backups/mongo/backup-$(date +%Y%m%d-%H%M%S)
ls -la /var/backups/mongo/

# 設定檔也備份
cp /etc/mongod.conf /var/backups/mongo/mongod.conf.$(hostname)

有開帳號驗證的話,加上 -u、--authenticationDatabase admin。如果是虛擬機,升級前另外做一份快照,回復最快。

停止 Graylog

# 兩台都停
systemctl stop graylog-server

第一階段:5.0 → 6.0

加入 6.0 套件庫(兩台)

wget -qO - https://www.mongodb.org/static/pgp/server-6.0.asc | \
    gpg --dearmor -o /usr/share/keyrings/mongodb-server-6.0.gpg

echo "deb [ arch=amd64,arm64 signed-by=/usr/share/keyrings/mongodb-server-6.0.gpg ] https://repo.mongodb.org/apt/ubuntu jammy/mongodb-org/6.0 multiverse" \
    | tee /etc/apt/sources.list.d/mongodb-org-6.0.list

# 停用 5.0 套件庫
sed -i 's/^deb/# deb/' /etc/apt/sources.list.d/mongodb-org-5.0.list

apt update
apt list --upgradable 2>/dev/null | grep mongo

apt-key 已經不建議使用,這裡改用 signed-by 指定金鑰檔。

如果之前有用 apt-mark hold 鎖住版本(建議要鎖,避免日常更新時意外升級),升級前要先解開:

apt-mark showhold
apt-mark unhold mongodb-org mongodb-org-server mongodb-org-mongos mongodb-org-tools

升級 SECONDARY(mongo2)

systemctl stop mongod
apt install -y mongodb-org
systemctl start mongod
sleep 10

# 必做驗證
systemctl is-active mongod      # 預期 active
mongod --version | head -1      # 預期 db version v6.0.x

# 失敗的話查原因
journalctl -u mongod --no-pager -n 30

mongodb-org 是整組的中繼套件,會一併升級 server、mongos、tools,並裝上 mongosh。

確認 replica set

mongosh --host 192.168.10.41 --eval 'rs.status().members.forEach(m => print(m.name, m.stateStr))'

兩個成員都要是 PRIMARY 或 SECONDARY,不能有 (not reachable/healthy)。

PRIMARY stepdown 後升級(mongo1)

# 交出 PRIMARY
mongosh --host 192.168.10.41 --eval 'rs.stepDown(60)'

# 確認已經不是 PRIMARY
mongosh --host 192.168.10.41 --quiet --eval 'db.hello().isWritablePrimary'    # 預期 false

systemctl stop mongod
apt install -y mongodb-org
systemctl start mongod
sleep 10

systemctl is-active mongod
mongod --version | head -1      # 預期 v6.0.x

設定 FCV 為 6.0

到目前的 PRIMARY(stepdown 後應該是 mongo2)執行:

mongosh --host 192.168.10.42 --eval 'db.adminCommand({ setFeatureCompatibilityVersion: "6.0" })'
mongosh --host 192.168.10.42 --eval 'db.adminCommand({ getParameter: 1, featureCompatibilityVersion: 1 })'

確認是 6.0 才能繼續。這時候先不要啟動 Graylog,等升到 7.0 再說。

第二階段:6.0 → 7.0

移除 storage.journal.enabled(兩台,必做)

在安裝 7.0 之前完成,否則 apt 安裝時重新啟動 mongod 就會失敗。

# 先看現況
grep -n -A2 'journal' /etc/mongod.conf

# 備份
cp /etc/mongod.conf /etc/mongod.conf.bak-$(date +%Y%m%d-%H%M%S)

用編輯器把 journal: 與底下的 enabled: true 兩行刪掉,改完 storage 區段應該只剩:

storage:
  dbPath: /var/lib/mongodb
# 確認沒有 journal 設定了
grep -n 'journal' /etc/mongod.conf || echo "OK:沒有 journal 設定"

設定檔是 YAML,縮排錯了 mongod 一樣起不來,建議手動編輯,改完再確認一次。

加入 7.0 套件庫(兩台)

wget -qO - https://www.mongodb.org/static/pgp/server-7.0.asc | \
    gpg --dearmor -o /usr/share/keyrings/mongodb-server-7.0.gpg

echo "deb [ arch=amd64,arm64 signed-by=/usr/share/keyrings/mongodb-server-7.0.gpg ] https://repo.mongodb.org/apt/ubuntu jammy/mongodb-org/7.0 multiverse" \
    | tee /etc/apt/sources.list.d/mongodb-org-7.0.list

sed -i 's/^deb/# deb/' /etc/apt/sources.list.d/mongodb-org-6.0.list

apt update
apt list --upgradable 2>/dev/null | grep mongo

升級 SECONDARY(這時是 mongo1)

剛才 stepdown 過,角色已經對調,先確認誰是 SECONDARY 再動手:

mongosh --quiet --eval 'db.hello().isWritablePrimary'    # 在要升級的那台,預期 false

systemctl stop mongod
apt install -y mongodb-org
systemctl start mongod
sleep 10

systemctl is-active mongod      # 預期 active
mongod --version | head -1      # 預期 v7.0.x

如果 is-active 回 failed,九成是 journal 設定沒拿掉,用 journalctl -u mongod -n 30 確認。

確認 replica set

mongosh --host 192.168.10.41 --eval 'rs.status().members.forEach(m => print(m.name, m.stateStr))'

PRIMARY stepdown 後升級(這時是 mongo2)

mongosh --quiet --eval 'db.hello().isWritablePrimary'    # 預期 true,確認是 PRIMARY
mongosh --quiet --eval 'rs.stepDown(60)'
mongosh --quiet --eval 'db.hello().isWritablePrimary'    # 預期 false

systemctl stop mongod
apt install -y mongodb-org
systemctl start mongod
sleep 10

systemctl is-active mongod
mongod --version | head -1      # 預期 v7.0.x

設定 FCV 為 7.0

連到目前的 PRIMARY:

db.adminCommand({ setFeatureCompatibilityVersion: "7.0", confirm: true })
db.adminCommand({ getParameter: 1, featureCompatibilityVersion: 1 })   // 預期 "7.0"

從 7.0 起 setFCV 一定要加 confirm: true,沒加會直接回錯誤,這是官方刻意的設計,提醒你調整 FCV 之後要降版會比較麻煩。

鎖定版本

apt-mark hold mongodb-org mongodb-org-server mongodb-org-mongos mongodb-org-tools mongodb-mongosh

第三階段:啟動 Graylog

# 兩台都做
systemctl start graylog-server
sleep 30
journalctl -u graylog-server --no-pager -n 30
curl -s http://localhost:9000/api/system/lbstatus      # 預期 ALIVE

server.conf 裡的 mongodb_uri 如果有寫 replicaSet=rs0 和兩台主機,就不用改。

復原方式

每個階段之間都可以停在當時的版本,真的出問題時:

從備份還原

# 兩台的 Graylog 先停
systemctl stop graylog-server

# 在 PRIMARY 還原,replica set 會自動同步到 SECONDARY
mongorestore --host 192.168.10.41 --drop /var/backups/mongo/backup-YYYYMMDD-HHMMSS

注意:FCV 調到 7.0 之後要降版,官方程序比較繁瑣(要先把 FCV 降回 6.0,再換回 6.0 的程式),而且部分 7.0 才有的資料格式必須先處理。如果升級後很快就發現問題,用升級前的虛擬機快照或備份回復通常比較快。所以我才會在每個階段都先確認一切正常,再調 FCV。

預估時間

階段時間
備份10 分鐘
5.0 → 6.015~20 分鐘
6.0 → 7.015~20 分鐘
驗證與啟動 Graylog10 分鐘
總計約 1 小時

資料量越大,備份與 mongod 啟動檢查的時間會越長,Graylog 的 MongoDB 只存設定與中繼資料,通常很快。

升級完成檢查清單

  • 兩台的 mongod --version 都是 7.0.x
  • rs.status() 兩個成員都正常(一台 PRIMARY、一台 SECONDARY)
  • FCV 是 7.0
  • 兩台的 graylog-server 都是 active
  • Graylog 網頁介面可以登入
  • 原有的 stream、input、看板、使用者都還在
  • 新訊息能正常寫入(看 input 的流量)

結論

MongoDB 升級最怕的是「以為成功了」:apt 回傳成功、指令沒報錯,結果 mongod 其實沒起來。我的習慣是每一步都驗證:is-active、--version、rs.status(),三個都對了才往下走。

另外兩台的 replica set 其實並不理想,停一台就整組不能寫入。這次升級完之後,也建議加一台 arbiter 或第三個成員,下次維護才能真的不停機。

參考資料

Jason Cheng

Jason Cheng

企業開源技術顧問,專注架構規劃與實務導入

關於作者 →

延伸閱讀