備份神器restic必須搭配restic-browser
windows畢竟還是主流,所以在windows上設定restic備份之後,事後要提取還原,windows系統上必須搭配好用的GUI軟體,因此我推薦 https://github.com/emuell/restic-browser
windows畢竟還是主流,所以在windows上設定restic備份之後,事後要提取還原,windows系統上必須搭配好用的GUI軟體,因此我推薦 https://github.com/emuell/restic-browser
幾天前我想把nextcloud 25.0.11 升級到 26.0.5 ,這麼多年來從18版一路高歌升到25版,都沒遇到問題,這次卻栽了無法升級,原因卡在資料庫那段,這問題似乎無解,在不想等待的情況下,我決定還原回去。
2023/9/22 發現我25.0.11升級會出錯,官方馬上釋出25.0.12 ,但我升級還是失敗,原來資料庫mariadb 10.3.2版本有問題,我直接docker pull mariadb:10.3 後面不接了,這樣就從25->26能升級成功
還原步驟:
我先將restic 所備份最新版nextcloud備份的snapshot掛載起來,接著停用目前的資料庫(mariadb 10.3.2 多個容器共用);再將nextcloud的相關volume、資料庫還原,結果失敗,失敗原因不明,docker看log也看不出來,web登入出現「Nextcloud the server was unable to complete your request」錯誤,真真急死人;後來爬文,歸納問題可能有三種:目錄權限沒設定好、資料庫問題與ldap無法連線。
不屈不撓檢查才發現原來是我偷懶,當初所有容器所用到的資料庫都統一讓唯一的資料庫容器管理,現在要還原,我停止資料庫容器後,只有還原其中nextcloud的資料庫,其他資料庫不還原,導致重新啟動資料庫容器時,nextcloud資料庫居然有一些資料表損毀(ENGINE=InnoDB)。
好在損毀的資料表是oc_authtoken,只要重建就好了,但是重建失敗,mysql會說該資料表已在,但是query時,mysql又說沒有該資料表,網上有位苦命工程師說建資料表時,遇到這情形,請改用ENGINE=MyISAM格式就能成功,我照著做之後,nextcloud又恢復往日雄風還原成功,但重建的資料表MyISAM跟其他使用InnoDB的資料表格格不入,以後要找一天將資料庫修復才行。
這故事告訴我們,還原資料庫容器要全部都還原,不可只還原其中一部分資料庫。
CREATE TABLE `oc_authtoken` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `uid` varchar(64) COLLATE utf8_bin NOT NULL DEFAULT '', `login_name` varchar(64) COLLATE utf8_bin NOT NULL DEFAULT '', `password` longtext COLLATE utf8_bin, `name` longtext COLLATE utf8_bin NOT NULL, `token` varchar(200) COLLATE utf8_bin NOT NULL DEFAULT '', `type` smallint(5) unsigned NOT NULL DEFAULT '0', `remember` smallint(5) unsigned NOT NULL DEFAULT '0', `last_activity` int(10) unsigned NOT NULL DEFAULT '0', `last_check` int(10) unsigned NOT NULL DEFAULT '0', `scope` longtext COLLATE utf8_bin, `expires` int(10) unsigned DEFAULT NULL, `private_key` longtext COLLATE utf8_bin, `public_key` longtext COLLATE utf8_bin, `version` smallint(5) unsigned NOT NULL DEFAULT '1', `password_invalid` tinyint(1) NOT NULL DEFAULT '0', PRIMARY KEY (`id`), UNIQUE KEY `authtoken_token_index` (`token`), KEY `authtoken_last_activity_idx` (`last_activity`), KEY `authtoken_uid_index` (`uid`), KEY `authtoken_version_index` (`version`) ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
以上重建table失敗
CREATE TABLE `oc_authtoken` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `uid` varchar(64) COLLATE utf8_bin NOT NULL DEFAULT '', `login_name` varchar(64) COLLATE utf8_bin NOT NULL DEFAULT '', `password` longtext COLLATE utf8_bin, `name` longtext COLLATE utf8_bin NOT NULL, `token` varchar(200) COLLATE utf8_bin NOT NULL DEFAULT '', `type` smallint(5) unsigned NOT NULL DEFAULT '0', `remember` smallint(5) unsigned NOT NULL DEFAULT '0', `last_activity` int(10) unsigned NOT NULL DEFAULT '0', `last_check` int(10) unsigned NOT NULL DEFAULT '0', `scope` longtext COLLATE utf8_bin, `expires` int(10) unsigned DEFAULT NULL, `private_key` longtext COLLATE utf8_bin, `public_key` longtext COLLATE utf8_bin, `version` smallint(5) unsigned NOT NULL DEFAULT '1', `password_invalid` tinyint(1) NOT NULL DEFAULT '0', PRIMARY KEY (`id`), UNIQUE KEY `authtoken_token_index` (`token`), KEY `authtoken_last_activity_idx` (`last_activity`), KEY `authtoken_uid_index` (`uid`), KEY `authtoken_version_index` (`version`) ) ENGINE=MyISAM AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
改成MyISAM就成功重建table
因為要減少備份snapshots數量, 因此執行forget + prune 瘦身指令
restic forget --keep-last 3 --prune -r <repository>
但是出現某某snapshots中有某些 pack missing 錯誤
some pack files are missing from the repository, getting their blobs from the repository index: [c3622b51e9c118521af211cd3a98f580f5902824b6b665e62d61061acedbe71d]
很慘, 於是只好找一下該 pack, 看看是哪些檔案不見
restic find --pack c3622b51e9c118521af211cd3a98f580f5902824b6b665e62d61061acedbe71d -r <repository>
最後終於找到某些snapshots遺失哪些檔案, 但依舊無法解決問題, 現主時只好忍痛直接將有問題的snapshots移除,等以後再研究解決方案
restic -r <repository> forget <snapshot id>
2023/2/8 後續
—
儘管forget該snapshots, 以為成功了.
但是再次執行備份,還是出現這個pack missing錯誤.
於是爬文, 發現必須先刪除相關packs , 再重跑以下步驟:
restic rebuild-index
restic backup –force
restic prune
詳細處理方式請查看 https://feeding.cloud.geek.nz/posts/removing-corrupted-data-pack-restic-backup/ 或是我下載好該網頁內容
我已經使用 restic 做離線備份半年了 , 效果還不錯, 但是遇到掛載nfs的資料, 效率就有點差了,
當然備份效率差的原因之一, 是我暴力備份docker or podman 裡面storage 資料, 那邊檔案超級多, 又是透過 nfs 方式備份, 就算restic 每次只做差異性, 還是很慢.
後來想想, 我的虛擬伺服器 proxmox ve 也有遇到掛載nfs效率問題, 解法就是使用soft link, 所以自己使用mount指令掛載nfs應該也是可以改用soft方式, 以下列出一些心得
mount -t cifs -o username=xxx,password=xxx,domain=yyy,ro,cache=loose ...
mount -t nfs -o ro,soft ...
#查看
nfsstat -m
前陣子發現restic備份的好處, 尤其拿來當離線備份.
IT同事進行離線備份時, 有意無意被老闆路過, 看到滿滿備份畫面咻咻跑來跑去, 充滿了儀式感.
老闆開心, IT同仁也有成就感.
restic指令備份, 不夠自動化, 為了讓IT同事做少少的工作, 又讓IT同事與其他路過的同事覺得好專業, 因此寫了簡單的restic backup script , 可以協助掛載來源目錄, 掛載後,進行restic備份.
檔案請到這裡下載, 下載後請看readme.md檔案
服務器端啟用nfs server
yum install nfs-utils
## 分享目錄
mkdir -p /mnt/docker
vi etc/exports
=================
#只讀ro, 10.192.130.4可使用
/mnt/docker 10.192.130.4(ro,sync,no_root_squash,no_all_squash)
#讀寫rw, 10.192.130.0/24網段可使用
/mnt/docker 10.192.130.0/24(rw,sync,no_root_squash,no_all_squash)
=================
#啟用
firewall-cmd --zone=public --add-service=nfs --permanent
## rockylinux
#firewall-cmd --add-service={nfs,nfs3,mountd,rpc-bind} --permanent
firewall-cmd --reload
systemctl enable nfs
systemctl start nfs
## rockylinux
#systemctl enable nfs-server rpcbind
#systemctl start nfs-server rpcbind
#查看狀態(windows,linux通用)
showmount -e localhost
用戶端(linux)
mount -t nfs <server ip>:/mnt/docker <本地要掛載的目錄>
或是
mount -t nfs4 <server ip>:/mnt/docker <本地要掛載的目錄>
用戶端(windows)
mount -o anon \\ip\mount_path z:
使用情境是依不同系統 , 建立多個備份倉, 一個倉別若要備份不同目錄, 可用tag區分.
備份倉盡量用簡單的方式, 當然也可以掛載sftp ,或是 rclone.
要備份的目錄, 盡量用掛載的, 變成一個目錄, rclone是個好選擇
備份後,執行保留策略(7天或是30天), 備份可以從目錄, 也可以從stdin ,
還原就比較沒甚麼好談的
至於密碼, 我覺得用環境變數就好了, 用檔案存密碼, 我覺得指令看起來好複雜
export RESTIC_PASSWORD=123456
restic -r <備份倉目錄> init
#Linux
export RESTIC_PASSWORD=123456
restic -r <備份倉目錄> backup <想要備份的目錄> --cleanup-cache --verbose --verbose >> restic.log 2>&1
#windows powershell
$Env:RESTIC_PASSWORD='password'
restic -r <備份倉目錄> backup <想要備份的目錄> | Out-File C:\temp\files.log -Encoding UTF8
export RESTIC_PASSWORD=123456
mysqldump -u root -p<密碼> --all-databases -h <主機ip> | restic --repo <備份倉目錄> backup --stdin --stdin-filename all.sql
restic -r <備份倉目錄> backup <想要備份的目錄> --tag:名稱 --cleanup-cache --verbose --verbose >> restic.log 2>&1
export RESTIC_PASSWORD=123456
restic -r <備份倉目錄> snapshots
export RESTIC_PASSWORD=123456
restic -r <備份倉目錄> restore <snapshots id> --target <要還原的目錄>
export RESTIC_PASSWORD=123456
restic -r <備份倉目錄> forget --prune --keep-daily 7
restic -r <備份倉目錄> forget --prune --keep-last 7
docker run restic/restic 參數
## 例如
docker run restic/restic version
#例如建立repository
docker run -v /root:/root restic/restic --repo /root/repo --password-file=/root/password init
export GODEBUG=asyncpreemptoff=1
docker run -v /root:/root restic/restic --repo /root/repo --password-file=/root/password backup /root/a