- 追加された行はこの色です。
- 削除された行はこの色です。
#author("2020-08-15T04:37:38+00:00","","")
#author("2020-08-15T07:35:16+00:00","","")
#mynavi(Azureメモ)
#setlinebreak(on);
* 目次 [#xaebdc2a]
#contents
- 関連
-- [[Azureメモ]]
-- [[Azure VM上にGrafanaをデプロイ]]
-- [[Azure VM上のGrafanaをカスタムドメインで公開]]
* 概要 [#cb2ae081]
#html(<div class="pl10">)
App Service は スケール等にも簡単に対応可能な為、アプリケーションの公開には非常に有用なサービスだが、
Grafana の様にデフォルトでローカルにデータを保存するようなアプリケーションの場合、「''スケール時や再起動時にデータを引き継ぐことが出来ない''」。
そこで、MySQL を使用して外部にデータを保存/利用する方法を記載する。
#html(</div>)
* 作成する環境 [#j6868bd3]
#html(<div class="pl10">)
下図のような環境を構築する。
#TODO
** なぜ MySQL を使用したのか [#o5c3f2ba]
#html(<div class="pl10">)
Azure App Service のアプリケーションで使用するファイルを外部化する方法として、Azure Files(ファイル共有) や Azure Disk 等があるが、
Azure Files(ファイル共有) で Grafana の内部データである SQLite のファイルを外部化(共有化)しようとしたが、これは出来なかった(※)。
※「Server shutdown" logger=server reason="Service init failed: Migration failed err: database is locked"」 となる。
※ Azure Disk は単純にコストの問題で採用を見送った。
調べてみると同様の事象は報告されており(※)、こちらでは AzureDisk を使用して回避したとの事だが、当記事では MySQL を使用して外部化する事とした。
※ https://github.com/kubernetes/kubernetes/issues/59755
#html(</div>)
** 仮想マシンについて [#xaba1f5a]
#html(<div class="pl10">)
仮想マシンには以下の環境を構築する。(docker-compose を使用して構築)
- Grafana に表示するグラフデータ用の InfluxDB
- Grafana自体のデータを保持する為の MySQL
#html(</div>)
* TODO [#kb48bb82]
#html(</div>)
* リソースの作成 [#s32d67cc]
#html(<div class="pl10">)
・Azure Files(ファイル共有)
・App Service
・docker
・Grafana
・MySQL関連の環境変数設定
・マウント設定(pluginsディレクトリ)
・仮想マシン
・docker
・MySQL、InfluxDB
・ポート開放(3306、8806)
いつも通りシェル化しておく。(最終的には ARM に移行)
#html(){{
<div id="tabs1">
<ul>
<li><a href="#tabs1-0">0_env.sh</a></li>
<li><a href="#tabs1-1">1_vm_resources.sh</a></li>
<li><a href="#tabs1-2">2_vm_setup.sh</a></li>
<li><a href="#tabs1-3">3_app_resources.sh</a></li>
</ul>
}}
// START tabs1-0
#html(<div id="tabs1-0">)
#mycode2(){{
#!/bin/bash
PREFIX=リソース名の頭に付ける接頭文字
subscriptionId=サブスクリプションID
region=japanwest
# リソースグループ
resourceGroup=${PREFIX}Resources
# 仮想ネットワーク
vnetName=${PREFIX}VNet
vnetPrefix=10.1.0.0/16
# セキュリティグループ名
nsgName=${vnetName}SecGrp
nsgPubRuleName=${nsgName}PubRule
# 仮想マシンを配置するサブネット
vmSubnetName=${PREFIX}VmSubnet
vmSubnetPrefix=10.1.1.0/24
# VNet統合用のサブネット
exSubnetName=${PREFIX}ExSubnet
exSubnetPrefix=10.1.2.0/24
# 仮想マシンの情報
vmName=${PREFIX}Vm
vmImage=UbuntuLTS
vmIpAddress=10.1.1.5
vmUser=sample
# App Service(Grafana)用
registryName=${PREFIX}registry
grafanaImageName=${PREFIX}-grafana
webappName=${PREFIX}-grafana
}}
#html(</div>)
// END tabs1-0
// START tabs1-1
#html(<div id="tabs1-1">)
#mycode2(){{
#!/bin/bash
# 設定の読み込み
source 0_env.sh
# リソース作成
if [ "$1" == "--create" ]; then
# リソースグループの作成
echo az group create
az group create --name $resourceGroup --location $region
# NSG(ネットワークセキュリティグループの)作成
echo az network nsg create
az network nsg create --resource-group $resourceGroup --name $nsgName
# InfluxDB接続用のNSGルール(Public) ※TODO: source-port-range は App Service 側の送信IPに合わせて絞っておいた方が良い
echo "az network nsg rule create(influxdb)"
az network nsg rule create \
--resource-group $resourceGroup --nsg-name $nsgName --name ${nsgPubRuleName}1\
--access Allow --protocol Tcp --direction Inbound --priority 100 \
--source-address-prefix Internet --source-port-range "*" --destination-port-range "8086"
# MySQL接続用のNSGルール(Public) ※TODO: source-port-range は App Service 側の送信IPに合わせて絞っておいた方が良い
echo "az network nsg rule create(mysql)"
az network nsg rule create \
--resource-group $resourceGroup --nsg-name $nsgName --name ${nsgPubRuleName}2 \
--access Allow --protocol Tcp --direction Inbound --priority 101 \
--source-address-prefix Internet --source-port-range "*" --destination-port-range "3306"
# 仮想ネットワーク 及び サブネット作成
echo az network vnet create
az network vnet create \
--name $vnetName --resource-group $resourceGroup \
--address-prefixes $vnetPrefix --network-security-group $nsgName \
--subnet-name $vmSubnetName --subnet-prefixes $vmSubnetPrefix
# 仮想マシンの作成
rm -rf ~/.ssh/id_rsa
rm -rf ~/.ssh/id_rsa.pub
echo az vm create
az vm create \
--resource-group $resourceGroup --name $vmName --image $vmImage --generate-ssh-keys \
--vnet-name $vnetName --subnet $vmSubnetName \
--private-ip-address $vmIpAddress --admin-username $vmUser \
--public-ip-address-dns-name `echo $vmName | tr '[A-Z]' '[a-z]'` \
--custom-data 2_vm_setup.sh
# ポート開放
echo "az vm open-port(3306)"
az vm open-port --resource-group $resourceGroup --name $vmName --port 3306 --priority 901
echo "az vm open-port(8086)"
az vm open-port --resource-group $resourceGroup --name $vmName --port 8086 --priority 902
# 生成されたSSH鍵を退避しておく
mkdir -p pem
if [ -e ~/.ssh/id_rsa ]; then
mv ~/.ssh/id_rsa ./pem/id_rsa_${vmName}
mv ~/.ssh/id_rsa.pub ./pem/id_rsa_${vmName}.pub
fi
fi
# リソース削除
if [ "$1" == "--delete" ]; then
echo az group delete
az group delete --name $resourceGroup
fi
}}
#html(</div>)
// END tabs1-1
// START tabs1-2
#html(<div id="tabs1-2">)
#mycode2(){{
#!/bin/bash
apt-get update
apt-get install -y apt-transport-https ca-certificates curl gnupg-agent software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
add-apt-repository \
"deb [arch=amd64] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) \
stable"
apt-get update
apt-get install -y docker-ce docker-ce-cli containerd.io
curl -L "https://github.com/docker/compose/releases/download/1.26.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
mkdir /tmp/influx_docker && cd /tmp/influx_docker
cat <<_EOCONF_ >influxdb.conf
[meta]
dir = "/var/lib/influxdb/meta"
[data]
dir = "/var/lib/influxdb/data"
engine = "tsm1"
wal-dir = "/var/lib/influxdb/wal"
[http]
enabled = true
flux-enabled = true
_EOCONF_
cat <<_EOYML_>docker-compose.yml
version: "3"
services:
influxdb:
image: influxdb:1.8
hostname: influxdb_for_grafana
container_name: influxdb_for_grafana
volumes:
- ./data/influxdb:/var/lib/influxdb
- ./influxdb.conf:/etc/influxdb/influxdb.conf
ports:
- "8086:8086"
mysql:
image: mysql:8.0.1
hostname: mysql_for_grafana
container_name: mysql_for_grafana
ports:
- "3306:3306"
environment:
MYSQL_DATABASE: grafana
MYSQL_USER: grafana
MYSQL_PASSWORD: grafana
MYSQL_ROOT_PASSWORD: admin
_EOYML_
mkdir -p data/influxdb
chmod 777 data/influxdb
# start influxdb
docker-compose up -d
# wait until influxdb starts
while [ true ]; do
sleep 10
x=`sudo docker exec -i influxdb_sample influx --execute "show databases" 2>&1`
if [ "$?" == "0" ]; then
break
fi
done
# create sample database and sample user.
docker exec -i influxdb_sample influx --execute "create database sampledb"
docker exec -i influxdb_sample influx --execute "create user sample with password 'sample' WITH ALL PRIVILEGES"
}}
#html(</div>)
// END tabs1-2
// START tabs1-3
#html(<div id="tabs1-3">)
#mycode2(){{
#!/bin/bash
# リソース名の読み込み
source 0_env.sh
# 一応リソースグループを分けておく
resourceGroup=${resourceGroup}2
# リソース作成
if [ "$1" == "--create" ]; then
# リソースグループの作成
echo "az group create ( $resourceGroup )"
az group create --name $resourceGroup --location $region
# コンテナレジストリ作成
echo "az acr create ( $registryName )"
az acr create -n $registryName -g $resourceGroup --sku standard --admin-enabled true
# レジストリユーザ名/パスワード取得
acr_credential="`az acr credential show --name $registryName -o table | tail -1`"
registryUser="`echo "$acr_credential" | awk '{print $1}'`"
registryPwd="`echo "$acr_credential" | awk '{print $2}'`"
cat <<_EO_DOCKERFILE_>Dockerfile
FROM grafana/grafana:7.1.1
# オリジナルプラグインのコピー等
COPY my_plungin/ /var/lib/grafana/plugins/my_plungin/
_EO_DOCKERFILE_
# DockerイメージをビルドしてACRに登録
echo "az acr build ( $grafanaImageName )"
az acr build --registry $registryName --image ${grafanaImageName} .
# App Service プラン作成 ( Standard プラン以上でないと VNet統合は使用できない )
echo "az appservice plan create ( ${webappName}-plan )"
az appservice plan create -n ${webappName}-plan -g $resourceGroup --is-linux --sku S1
cat <<_EOYML_>docker-compose.yml
version: "3.3"
services:
grafana:
image: ${registryName}.azurecr.io/${grafanaImageName}:latest
hostname: grafana_sample
container_name: grafana_sample
ports:
- "80:3000"
environment:
GF_SERVER_ROOT_URL: https://${webappName}.azurewebsites.net
GF_SECURITY_ADMIN_PASSWORD: admin
GF_DATABASE_TYPE: mysql
GF_DATABASE_HOST: ${vmIpAddress}:3306
GF_DATABASE_NAME: grafana
GF_DATABASE_USER: grafana
GF_DATABASE_PASSWORD: grafana
_EOYML_
# App Service アプリ作成(Grafana)
echo "az webapp create ( $webappName )"
az webapp create --resource-group $resourceGroup -p ${webappName}-plan \
-n $webappName --multicontainer-config-type compose \
--multicontainer-config-file docker-compose.yml \
--docker-registry-server-user ${registryUser} \
--docker-registry-server-password ${registryPwd}
# VNet統合用のサブネット
echo "az vnet subnet create"
az network vnet subnet create \
--name $exSubnetName \
--resource-group $resourceGroup \
--vnet-name $vnetName \
--address-prefixes $exSubnetPrefix
# VNet統合の作成
az webapp vnet-integration add \
--name $webappName \
--resource-group $resourceGroup \
--subnet $exSubnetName
--vnet $vnetName
# コンテナの構成/デプロイ(Grafana)
echo "configure web app from Azure Container Registry"
az webapp config container set \
--resource-group $resourceGroup --name $webappName \
--docker-registry-server-url http://${registryName}.azurecr.io \
--docker-registry-server-user ${registryUser} \
--docker-registry-server-password ${registryPwd}
echo "Application URL: https://${webappName}.azurewebsites.net"
fi
# リソース削除
if [ "$1" == "--delete" ]; then
echo "group delete ( $resourceGroup )"
az group delete --name $resourceGroup
fi
}}
#html(</div>)
// END tabs1-3
#html(</div>)
// END tabs1
#html(<script>$(function() { $("#tabs1").tabs(); });</script>)
** VM関連のリソースを作成 [#h492e87b]
#myterm2(){{
./1_vm_resources.sh --create
}}
** App Service のリソースを作成 [#c4e8cf3a]
#myterm2(){{
./3_app_resources.sh --create
}}
#html(</div>)
* 動作確認 [#n9269eef]
#html(<div class="pl10">)
#TODO
#html(</div>)