[華語, cmn-Hant-TW]
之前在這篇有提到 snapshot 管理主要是用在 backup 上,塞東西到備份伺服器上最簡單的方式就是 rsync,之前主要是用 rsyncd,但是 rsyncd 有幾個問題,首先是傳輸未加密,如果經過公共網路區間有點不安全;再來就是各台備份的設定檔不小心弄成一樣的話,會很搞笑的不小心同步到另一台機器用的備份區域 (可以用鎖 IP 來處理,不過浮動 IP 的機器就麻煩了)。所以後來就研究了一下有沒有適當解,結果發現比較簡單的方式還是用 rsync + ssh,然後透過 ssh authorized_keys 的機制達到不用輸入密碼的效果,機器端的指令長這樣
export BACKUP_ARGS="-avHS --ignore-errors" rsync $BACKUP_ARGS -e "/usr/bin/ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o LogLevel=ERROR -o SendEnv=BACKUP_ARGS -i $KEY" / $USER@$HOST: |
其中 -o 參數除了 SendEnv 外,都是為了避免加入 known_hosts 提示用的,不加也無妨,$BACKUP_ARGS 是 rsync 的參數,這個例子就是常見的 -avHS 以及 –ignore-errors,$USER 是使用者,為了方便通常都是 root,然後 $HOST 則是備份伺服器的位置,$KEY 的話則是由 ssh-keygen 產生出來 .key 檔的位置,另外隨附的 .pub 要把他貼到備份伺服器端 $USER 家目錄下的 .ssh/authorized_keys 裡面,然後在 ssh-rsa 前面加上command指令,長得像這樣
command="/usr/local/bin/rsync --server $BACKUP_ARGS . /backup/318" ssh-rsa AAAA...c87 root@ck49th318 |
透過 rsync 的 –server 參數就可以在伺服器接收檔案了,以這行來講,最後的 /backup/318 會確保所有傳進來的東西都會被丟到 /backup/318 去,又因為 authorized_key 存的是每台機器各別產生的 key,我們可以從 key 很清楚的得知這次連線是從哪來機器連過來的,搭配 command 指令就可以直接隔離各台機器,保證他們不會被塞到一樣的地方。不過這種方式的缺點是沒辦法處理像是 /usr /usr/local /usr/local/bin 這樣的階層,所以要備份的時候,最好一次到位直接備份 / 然後再用 rsync 的排除機制跳過不需要的目錄。
另外要注意的是 $BACKUP_ARGS 在機器下的指令和備份伺服器 command 裡的指令最好一致,某些參數兩邊不一樣會造成錯誤,像在機器上跑 rsync –dry-run 但備份伺服器沒有 –dry-run 指令的話,就可能會出現這種錯誤
Invalid packet at end of run (3984) [sender] rsync error: protocol incompatibility (code 2) at main.c(691) [sender=3.0.9] |
但是每次參數一改就要兩邊改也是很煩,這就是為什麼機器端需要 -o SendEnv 了,這個參數能在送指令的時候順便把 $BACKUP_ARGS 傳過去,當然備份伺服器的 sshd 也要願意吃這個參數才行,這個在 sshd_config 裡面設。除了這個要設定外,還要放寬讓 root 可以透過 ssh 登入,不過為了安全起見不開放密碼登入,也就是一定要用 key 登入。配合這兩個需求 /etc/ssh/sshd_config 要加這兩行
PermitRootLogin without-password AcceptEnv BACKUP_ARGS |
其中 PermitRootLogin 還可以更進一步設成 forced-commands-only,更安全些。
UPDATE 2014-01-15:
後來發現其實 rsync 有內附一個叫 rrsync 的 script 可以幫忙處理這個問題,也不用傳環境變數給 ssh 了,只要 authorized_keys 裡面改成這樣即可 command=”/usr/local/bin/rrsync /backup/318″ ssh-rsa AAAA…c87 root@ck49th318″
rrsync 請自己放到想放的地方,另外這是一個 perl script,所以 perl 跟會用到的 module 要先裝好就是