과거에 ESXi - xsibackup 와 관련된 글을 포스팅한 적이 있다.
당시에는 ESXi 6.7에 xsibackup 을 도입하여 사용하였다. 최근 ESXi 8.0 U2로 업그레이드를 하면서 기존 xsibackup이 동작하지 않는 이슈가 발생하였고, 그래서 최신 버전의 xsibakcup (XSIBACKUP-DC FREE 1.7.1.1)을 다운 받아서 돌려 보았으나 두 가지 문제점이 발생하였다.
첫 번째로 --backup 옵션을 사용할 경우 xsibkacup 솔루션의 고유 포맷으로 백업 파일이 저장된다. (xsibackup으로 --restore 복구를 한다면 별다른 이슈는 없을 것이다.)
두 번째로 본인의 경우 vmdk와 vmx 파일을 다른 서버나 스토리지에 복사본을 두고 ESXi 서버가 장애 발생 시 다른 하이퍼바이저(vmware workstation 등)에 해당 이미지 파일로 vm을 구동하려는 계획을 가지고 있다. 그런데 고유 포맷이라면 계획대로 되기 쉽지 않다. 그래서 --replica 옵션(xsibackup-classic의 backup 옵션과 유사하게 vm 파일들이 copy 되는 방식)을 사용해 봤는데 무슨 이유에서 인지 파일 복사 도중 일부 파일을 찾지 못하고 에러가 발생된다.
이러한 이유로 xsibakcup 사용을 당분간 보류하고, 백업 스크립트를 하나 작성하여 사용 중이다. 이 포스트는 그 내용을 설명하고 있다.
목차
스크립트 작성
영구적으로 저장될 수 있는 적절한 공간에 아래와 같이 스크립트 작성
[root@localhost:~] vi /vmfs/volumes/HDD02/_apps/vm-live_clone.sh
#!/bin/sh
##### Variable - Modify it to an appropriate value. #####
VM_NAME=myvm
SOURCE_DIR=/vmfs/volumes/NVME01/$VM_NAME
TARGET_DIR=/vmfs/volumes/NFS02/$VM_NAME
STOR_DAYS=30
#########################################################
CUR_TIME=$(date +%Y%m%d_%H%M)
DATETIME_OF_BACKUP=$(date +%Y-%m-%d-%T)
VM_ID=$(vim-cmd vmsvc/getallvms 2>/dev/null | grep "${VM_NAME}" | awk '{print $1}')
alias cp='cp'
CLEAN_OLD_BK_AND_MKDIR () {
find $TARGET_DIR -mindepth 1 -mtime +"$STOR_DAYS" -exec rm -rf {} \;
mkdir -p $TARGET_DIR/$CUR_TIME
}
CLEAN_SNAP () {
SNAP_NUM=$(vim-cmd vmsvc/get.snapshotinfo $VM_ID | egrep "description = \"Snapshot created by Backup Script\"" -A 1 | grep -v description | awk -F '= ' '{print $2}' | sed '/^$/d;s/,//g' | sort -r)
for i in $SNAP_NUM
do vim-cmd vmsvc/snapshot.remove $VM_ID $i
done
}
UNLIVE_CP () {
CUR_TIME=$(date +%Y%m%d_%H%M_unlive_cp)
vim-cmd vmsvc/power.shutdown `vim-cmd vmsvc/getallvms | grep $VM_NAME | awk '{print $1}'`
sleep 5
alias cp='cp'
VM_STATUS=$(vim-cmd vmsvc/power.getstate `vim-cmd vmsvc/getallvms | grep $VM_NAME | awk '{print $1}'` | grep Powered | awk '{print $NF}')
if [ "$VM_STATUS" = "off" ]; then
CLEAN_OLD_BK_AND_MKDIR;
cp -rp $SOURCE_DIR/* $TARGET_DIR/$CUR_TIME
else
vim-cmd vmsvc/power.off `vim-cmd vmsvc/getallvms | grep $VM_NAME | awk '{print $1}'`
sleep 3
CLEAN_OLD_BK_AND_MKDIR;
cp -rp $SOURCE_DIR/* $TARGET_DIR/$CUR_TIME
fi
vim-cmd vmsvc/power.on `vim-cmd vmsvc/getallvms | grep $VM_NAME | awk '{print $1}'`
}
CLEAN_SNAP;
if [ "$1" = "--unlive" ]; then
UNLIVE_CP;
exit 0
fi
CLEAN_OLD_BK_AND_MKDIR;
cp -rp /vmfs/volumes/NVME01/$VM_NAME/${VM_NAME}.nvram $TARGET_DIR/$CUR_TIME
cp -rp /vmfs/volumes/NVME01/$VM_NAME/${VM_NAME}.vmsd $TARGET_DIR/$CUR_TIME
vim-cmd vmsvc/snapshot.create ${VM_ID} "${VM_NAME} ${DATETIME_OF_BACKUP}" 'Snapshot created by Backup Script' 1 1
CHK_SNAP=$?
## If take a snap shot succeed, then copy the vmdk by live.
if [ $CHK_SNAP = 0 ]; then
CLEAN_OLD_BK_AND_MKDIR;
vmkfstools -i $SOURCE_DIR/${VM_NAME}.vmdk $TARGET_DIR/$CUR_TIME/${VM_NAME}.vmdk
CHK_THIN_CP=$?
fi
CLEAN_SNAP;
cp -rp /vmfs/volumes/NVME01/$VM_NAME/${VM_NAME}.vmx $TARGET_DIR/$CUR_TIME
## If copy the vmdk failed, then copy vmdk by unlive.
if [ ! $CHK_SNAP = 0 ] || [ ! $CHK_THIN_CP = 0 ]; then
UNLIIVE_CP;
fi
exit 0
-> VM_NAME, SOURCE_DIR, TARGET_DIR, STOR_DAYS 변수 값을 적절히 수정한다.
동작 설명 :
1) snap 샷 생성 후 vm clone (이때 STOR_DAY(30)일이 넘은 기존 백업본은 삭제.)
2) snap 샷 정리
(* --unlive 옵션을 주고 실행 시 vm을 내리고 cp 수행)
위 실패 시 아래처럼 offline copy 진행
1) myvm을 shutdown(또는 power off)
2) vm 이미지 파일들을 target directory에 복사 (이때 STOR_DAY(14)일이 넘은 기존 백업본은 삭제.)
3) myvm power on
(*참고: vm을 라이브(vm온라인상태) 복제하기 위해서는 snapshot을 찍고 진행해야 한다. 이 때 vm이 위치한 datastore의 용량이 부족하면 snapshot 생성에 실패할 수 있다. 그런 경우나 thin copy가 실패되면 vm을 shutdown 하여 오프라인 상태로 만들고 cp 명령으로 복사하도록 스크립트를 짰다.)
실행 권한 설정 및 테스트 구동
[root@localhost:~] esxcli system settings advanced set -o /User/execInstalledOnly -i 0
[root@localhost:~] chmod 700 /vmfs/volumes/HDD02/_apps/vm-live_clone.sh
[root@localhost:~] cd /vmfs/volumes/HDD02/_apps
[root@localhost:~] ./vm-live_clone.sh
또는
[root@localhost:~] ./vm-live_clone.sh --unlive (--unlive 옵션 적용 시 vm을 shutdown/poweroff 후 수행)
esxcli 명령으로 execInstalledOnly를 세팅하는 이유는 허가되지 않은 영역에서 스크립트나 바이너리를 실행할 수 있도록 하기 위함.
Enabled(1, default) 상태에서는 실행 시 Operation not permitted 오류 발생됨.
cron job 등록
- 현재 런닝 중인 상태에서 cron 적용을 위한 설정
[root@localhost:~] vi /var/spool/cron/crontabs/root
00 19 * * 6 /vmfs/volumes/HDD02/_apps/vm-live_clone.sh
00 18 1 * * /vmfs/volumes/HDD02/_apps/vm-live_clone.sh --unlive
- cron에 즉시 반영 시키고자 cron 데몬 재시작
[root@localhost:~] cat /var/run/crond.pid
[root@localhost:~] /bin/kill $(cat /var/run/crond.pid)
[root@localhost:~] /usr/lib/vmware/busybox/bin/busybox crond
[root@localhost:~] cat /var/run/crond.pid
- 부팅 시 cron 적용을 위해 초기 스크립트에 적용 (적절한 라인에 삽입)
[root@localhost:~] vi /etc/rc.local.d/local.sh
/bin/echo "00 19 * * 6 /vmfs/volumes/HDD02/_apps/vm-live_clone.sh" >> /var/spool/cron/crontabs/root
/bin/echo "00 17 1 * * /vmfs/volumes/HDD02/_apps/vm-live_clone.sh --unlive" >> /var/spool/cron/crontabs/root
-> 토요일 19시 00분(UTC기준. KST 기준으로는 일요일 새벽 04시 00분)에 vm-live_clone.sh를 수행
-> 매달 1일, 18시 00분(UTC기준. KST 기준으로는 일요일 새벽 02시 00분)에 vm-live_clone.sh --unlive 를 수행
스크립트 중지
cron에 의해 vm-live_clone.sh가 구동 중일 때 kill 시키고자 할 때는 아래와 같이 수행한다.
[root@localhost:~] /bin/kill $(ps | egrep '\ vmkfstools\ ' | awk '{print $1}')
[root@localhost:~] /bin/kill $(ps | egrep '\ cp\ ' | awk '{print $1}')
.
이 백업은 온라인 백업이며, vm이 한가한 주말 새벽 시간대에 백업이 동작 되도록 cron job에 등록하여 사용중이다.
VM Restore의 경우 esxi 또는 VMware-Workstation / player에 넣고 돌리면 그대로 올라온다.