Azure上にあるVMのデータはAzureのblobに投げたらいいかなと思ってやってみた小ネタ。
azコマンド入れるところはマケプレのimageから起動したVMだと要らないようでしたがオレオレイメージだと必要だと思われます。
(ローカルから使えるようにしたいということでなければポータルの>_
というマークをクリックするとCloudShellというコンソールっぽいのが画面下の方に上がってきてazコマンド使えたりterraform使えたりします。GCPも似たのがあったような。)
スクリプト
以下はjenkinsHOMEのバックアップをローカルで取りAzureのストレージに転送するjenkinsジョブ(シェルの実行)です。
(1世代だけ。ストレージアカウントは要るのですがazコマンド用のログインは要らないようでした。)
# /bin/bash -e
TMPDIR=/tmp
TARFILE='jenkins-bkup.tar.gz'
EXCLUDE='exclude.txt'
test -e ${TMPDIR}/${EXCLUDE} || cat <<_EOD_ > ${TMPDIR}/${EXCLUDE}
workspace
workspace/[0-9a-zA-Z\/\.-]*
backup
_EOD_
cd $JENKINS_HOME
test -e ${TMPDIR}/${TARFILE} && mv -f ${TMPDIR}/${TARFILE} ${TMPDIR}/${TARFILE}.1
tar czf ${TMPDIR}/${TARFILE} --exclude-from=${TMPDIR}/${EXCLUDE} .
export AZURE_STORAGE_ACCOUNT=${myaccount}
export AZURE_STORAGE_ACCESS_KEY=${AZURE_STORAGE_ACCESS_KEY}
export container_name=backup
export blob_name=${TARFILE}
export file_to_upload=${TMPDIR}/${TARFILE}
AZ_CMD=/usr/bin/az
ContainerExists=`${AZ_CMD} storage container exists --account-name ${AZURE_STORAGE_ACCOUNT} \
--account-key ${AZURE_STORAGE_ACCESS_KEY} --name $container_name --output tsv`
if [ "${ContainerExists}" = "False" ];then
echo "Creating the container..."
${AZ_CMD} storage container create --name $container_name \
--account-name ${AZURE_STORAGE_ACCOUNT} --account-key ${AZURE_STORAGE_ACCESS_KEY}
fi
echo "Uploading the file..."
${AZ_CMD} storage blob upload --container-name $container_name --file $file_to_upload --name $blob_name \
--account-name ${AZURE_STORAGE_ACCOUNT} --account-key ${AZURE_STORAGE_ACCESS_KEY}
echo "Listing the blobs..."
${AZ_CMD} storage blob list --container-name $container_name --output table \
--account-name ${AZURE_STORAGE_ACCOUNT} --account-key ${AZURE_STORAGE_ACCESS_KEY}
echo "Done"
シェル内で定義されてない変数はmask-passwords-pluginというジョブ毎に設定できる別のプラグインで別途設定してます。
実行ログは切り回し実装しなくてよく標準出力にだしとけばjenkinsが拾って記録してくれます。
サーバにログインせずブラウザから実行ログを後から追いやすく地味に便利です。
名前を統一できない複数ファイルを扱い古いものを消す運用するスクリプト例↓
(めんどくさかったのでrsyncの--deleteオプションみたいなことができてほしい気持ちでいっぱいです)
# /bin/bash -e
#
## set localhost's variables.
BK_DIR=/var/opt/gitlab/backups
LOG=/opt/log/bk.log
# log redirect.
exec >> ${LOG}
exec 2>&1
## daily backup.
echo "$(/bin/date +%Y%m%d.%H%M%S) daily backup start."
/opt/gitlab/bin/gitlab-rake gitlab:backup:create
echo "$(/bin/date +%Y%m%d.%H%M%S) daily backup end."
## remove old backups.
find ${BK_DIR} -name "*.tar.gz" -ctime +1 -type f -exec rm -f {} \;
## set azure variables.
export AZURE_STORAGE_ACCOUNT={{ azure_storage_account }}
AZURE_STORAGE_ACCESS_KEY='{{ azure_storage_access_key }}'
export AZURE_STORAGE_ACCESS_KEY=${AZURE_STORAGE_ACCESS_KEY}
export container_name={{ azure_container_name }}
AZ_CMD=/usr/bin/az
## if not exist container, create it.
ContainerExists=`${AZ_CMD} storage container exists --account-name ${AZURE_STORAGE_ACCOUNT} \
--account-key ${AZURE_STORAGE_ACCESS_KEY} --name ${container_name} --output tsv`
if [ "${ContainerExists}" = "False" ];then
echo "Creating the container..."
${AZ_CMD} storage container create --name ${container_name} \
--account-name ${AZURE_STORAGE_ACCOUNT} --account-key ${AZURE_STORAGE_ACCESS_KEY}
fi
## commpressed and upload backup files to azure blob.
### commpressed
cd ${BK_DIR}
test -f ${BK_DIR}/*.tar
result=$(echo $?)
if [ ${result} == 1 ];then
echo "un commpressed backup files is not exists."
exit 0
fi
### rename
placetag='lan'
find ${BK_DIR} -name "*_gitlab_*" | sed "p;s/_gitlab_/_gitlab-${placetag}_/g" | xargs -n2 mv
### upload to azure blob
bkupfiles=$(ls -1 ${BK_DIR}/*.tar)
for bkupfile in ${bkupfiles}
do
gzip ${bkupfile}
export blob_name=$(basename ${bkupfile}.gz)
export file_to_upload=${bkupfile}.gz
echo "Uploading the file...${bkupfile}.gz."
${AZ_CMD} storage blob upload --container-name ${container_name} \
--file ${file_to_upload} --name ${blob_name} \
--account-name ${AZURE_STORAGE_ACCOUNT} --account-key ${AZURE_STORAGE_ACCESS_KEY}
done
## get list of uploaded backup files.
echo "Listing the blobs..."
uploaded_list=$(
${AZ_CMD} storage blob list --container-name ${container_name} --output tsv \
--account-name ${AZURE_STORAGE_ACCOUNT} --account-key ${AZURE_STORAGE_ACCESS_KEY} \
--query '[].{Name: name, Lastmodified: properties.lastModified}'|grep gitlab| \
sed -e 's/[",]//g' -e 's/\t/,/g'
)
## limit check and delete old backup files.
numofgeneration="3"
days_ago=$(/bin/date -d "${numofgeneration} days ago" +%Y-%m-%d'T'%H:%M'Z')
days_ago_unixtime=$(/bin/date -d "${numofgeneration} days ago" +%s)
today_unixtime=$(/bin/date +%s)
retention_limit=$(echo ${today_unixtime} - ${days_ago_unixtime}|bc)
for filedata in ${uploaded_list}
do
uploadedfile=$(echo ${filedata} |awk -F , '{print $1}')
lastmodified=$(echo ${filedata} |awk -F , '{print $2}')
lastmodified_conv=$(echo ${lastmodified}|sed -e 's/T/ /g' -e 's/+00:00//g' -e 's/$/ UTC/g')
lastmodified_unixtime=$(/bin/date -d "${lastmodified_conv}" +%s)
diff_seconds=$(echo ${today_unixtime} - ${lastmodified_unixtime}|bc)
if [ ${retention_limit} -gt ${diff_seconds} ];then
echo "${uploadedfile} is still newer than expiration date."
continue
fi
echo "Delete old backup files. ${filedata}"
${AZ_CMD} storage blob delete --container-name ${container_name} --output table \
--name ${uploadedfile} --if-unmodified-since ${days_ago} \
--account-name ${AZURE_STORAGE_ACCOUNT} --account-key ${AZURE_STORAGE_ACCESS_KEY}
done
echo "$(/bin/date +%Y%m%d.%H%M%S) Done."
## rotate logs.
find /opt/log -name bk.log -size +5M -exec mv bk.log{,.$(/bin/date +%Y%m%d)} \;
find /opt/log -name "bk.log.*" -atime +365 -delete
exit 0
とりあえず三日(numofgenerationで指定)より前のファイルを消す仕様です。
(unixtimeに変換して引き算してif分岐で判定して旧くなければループの次に移るのでazによる古くねーよエラーはでない)
Ansibleタスク
azコマンドも入れるansibleのタスクファイルを一応書いた。
(Debian向けはマニュアルに丁寧に書いてあったので一応書いただけでテストしてないけどsyntaxエラーは出てない)
---
# tasks file for azure
#
- block:
- name: check azure-cli yum repo
shell: yum repolist azure-cli|grep repolist|awk '{print $2}'
register: res_exist_azclirepo_yum
- name: install az yum repository gpg key.
command: rpm --import https://packages.microsoft.com/keys/microsoft.asc
- name: copy yum repository file
copy:
src: azure-cli.repo
dest: /etc/yum.repos.d/azure-cli.repo
- name: yum install azure-cli
yum:
name: azure-cli
state: present
when:
- res_exist_azclirepo_yum == '0'
- ansible_os_family == 'RedHat'
- block:
- name: check azure-cli apt repo
command: ls /etc/apt/sources.list.d/azure-cli.list
register: res_exist_azclirepo_apt
ignore_errors: ture
- name: copy apt source list
copy:
src: azure-cli.list
dest: /etc/apt/sources.list.d/azure-cli.list
- name: install azure-cli apt-key
apt_key:
id: 417A0893
keyserver: packages.microsoft.com
state: present
- name: apt install azure-cli
apt:
name: "{{ item }}"
state: present
with_items:
- apt-transport-https
- azure-cli
when:
- res_exist_azclirepo_apt != ''
- ansible_os_family == 'Debian'
- block:
- name: copy backup script for azureblob
template:
src: backup.sh-gitlab-azureblob
dest: /opt/bin/backup.sh
no_log: True
- name: set cron job for backup to azureblob
cron:
name: "gitlab backup(send to remote storage)"
user: 'root'
job: '/opt/bin/backup.sh'
minute: '0'
hour: '3'
weekday: '0'
when: use_azureblob_bkup_script == 'yes'
上記はローカルにcron登録する感じのタスクでweekday 0になってるので日曜しか作動しないですがローカル用は別にとっててシステムの重要度に応じてクラウドストレージに向けてはまあ通信料もあるし毎日じゃなくてもいいかな、という思想によります。
参考
Using the Azure CLI 2.0 with Azure Storage | Microsoft Docs
Amazon S3, Google Cloud Storageなど各種オブジェクトストレージの料金比較まとめ (2017/04/30) - Qiita
az blob delete --help
az blob list --help
JMESPath Tutorial — JMESPath
Azure CLI 2.0 のインストール | Microsoft Docs
Azure Storage アカウント キーの漏洩対策 - Qiita