Azure: CLI – пример создания SMB file share, Load Balancer и Linux VM с NGINX

Автор: | 17/07/2017
 

Задача – добавить новую группу ресурсов, которая бы включала в себя Load Balancer и две виртуальные машины с NGINX за ним.

Машины будут использовать единую файл-шару, в которую будут деплоиться обновлённые конфиги NGINX.

Ресурс группа будет включать в себя:

  1. Load Balancer
  2. две идентичные VM с NGINX
  3. Storage Account, который будет подключаться как Samba-share ресурс к обеим машинам в каталог /data/datanginx-conf.d.

Следующие действия:

  1. создать ресурс группу
  2. добавить в неё Load Balancer
  3. создать Storage Account, скопировать в него ключи
  4. создать одну VM с NGINX, примонтировать шару, проверить что всё работает
  5. подключить вторую вируталку


Подготовка

По возможности – делаем всё через Azure CLI (тут v1).

Load Balancer, сеть

Создаём группу ресурсов:

[simterm]

$ azure group create -n jm-akqa-gw-proxy-dev -l westeurope

[/simterm]

Создаём Load Balancer:

[simterm]

$ azure network lb create -g jm-akqa-gw-proxy-dev -n jm-akqa-gw-proxy-dev-lb -l westeurope

[/simterm]

Создаём Public IP:

[simterm]

$ azure network public-ip create --resource-group jm-akqa-gw-proxy-dev \
> --name jm-akqa-gw-proxy-dev-ip \
> --location westeurope \
> --domain-name-label jm-akqa-gw-proxy-dev-ip \
> --allocation-method Static

[/simterm]

Создаём сеть:

[simterm]

$ azure network vnet create --resource-group jm-akqa-gw-proxy-dev \
> --location westeurope \
> --name jm-akqa-gw-proxy-dev-vnet \
> --address-prefixes 10.0.0.0/24

[/simterm]

Примечание: тут Azure CLI сообщает об “ошибке” – “error:   Cannot read property ‘dnsServers’ of undefined”, но сеть создаётся. При этом в документации property ‘dnsServers’ указана как optional. Но вызывает ошибку… Azure…

И подсеть в ней:

[simterm]

$ azure network vnet subnet create --resource-group jm-akqa-gw-proxy-dev \
> --name jm-akqa-gw-proxy-dev-gws-subnet \
> --vnet-name jm-akqa-gw-proxy-dev-vnet \
> --address-prefix 10.0.0.0/28

[/simterm]

Подключаем IP к созданному LB:

[simterm]

$ azure network lb frontend-ip create --resource-group jm-akqa-gw-proxy-dev \
> --lb-name jm-akqa-gw-proxy-dev-lb \
> --name jm-akqa-gw-proxy-dev-feip \
> --public-ip-name jm-akqa-gw-proxy-dev-ip

[/simterm]

Добавляем backend IP pool:

[simterm]

$ azure network lb address-pool create --resource-group jm-akqa-gw-proxy-dev \
> --lb-name jm-akqa-gw-proxy-dev-lb \
> --name jm-akqa-gw-proxy-dev-beip

[/simterm]

Создаём правило проброса трафика с внешнего IP, порт 80, на бекенд, порт 80:

[simterm]

$ azure network lb rule create --resource-group jm-akqa-gw-proxy-dev \
> --lb-name jm-akqa-gw-proxy-dev-lb \
> --name http \
> --protocol tcp \
> --frontend-port 80 \
> --backend-port 80 \
> --frontend-ip-name jm-akqa-gw-proxy-dev-feip \
> --backend-address-pool-name jm-akqa-gw-proxy-dev-beip

[/simterm]

Аналогично – для 443:

[simterm]

$ azure network lb rule create -g jm-akqa-gw-proxy-dev -l jm-akqa-gw-proxy-dev-lb -n https -p tcp -f 443 -b 443 -t jm-akqa-gw-proxy-dev-feip -o jm-akqa-gw-proxy-dev-beip

[/simterm]

Добавляем Health probe, по которой LB будет определять “живые” машины в бекенде:

[simterm]

$ azure network lb probe create --resource-group jm-akqa-gw-proxy-dev \
> --lb-name jm-akqa-gw-proxy-dev-lb \
> --name http_health \
> --protocol tcp \
> --port 80

[/simterm]

Создаём NAT правило для проброса порта 2200 на внутренний интерфейс порт 22:

[simterm]

$ azure network lb inbound-nat-rule create --resource-group jm-akqa-gw-proxy-dev \
> --lb-name jm-akqa-gw-proxy-dev-lb \
> --name jm-akqa-gw-proxy-dev-nat-2200-22-gw1 \
> --protocol tcp \
> --frontend-port 2200 \
> --backend-port 22 \
> --frontend-ip-name jm-akqa-gw-proxy-dev-feip

[/simterm]

Создаём Network Interface:

[simterm]

$ azure network nic create --resource-group jm-akqa-gw-proxy-dev \
> --location westeurope \
> --name jm-akqa-gw-proxy-dev-gw1-nic \
> --subnet-name jm-akqa-gw-proxy-dev-gws-subnet \
> --subnet-vnet-name jm-akqa-gw-proxy-dev-vnet \
> --lb-address-pool-ids /subscriptions/0a4f2b9c-***-***-***-40b17ef8c3ab/resourceGroups/jm-akqa-gw-proxy-dev/providers/Microsoft.Network/loadbalancers/jm-akqa-gw-proxy-dev-lb/backendAddressPools/jm-akqa-gw-proxy-dev-beip \
> --lb-inbound-nat-rule-ids /subscriptions/0a4f2b9c-***-***-***-40b17ef8c3ab/resourceGroups/jm-akqa-gw-proxy-dev/providers/Microsoft.Network/loadBalancers/jm-akqa-gw-proxy-dev-lb/inboundNatRules/jm-akqa-gw-proxy-dev-nat-2200-22-gw1

[/simterm]

На этом сеть и балансировщик нагрузки готовы.

Виртуальная машина для NGINX

Запускаем виртуальную машину:

[simterm]

$ azure vm create --resource-group jm-akqa-gw-proxy-dev \
> --location westeurope \
> --name jm-akqa-gw-proxy-dev-gw1 \
> --vnet-name jm-akqa-gw-proxy-dev-vnet \
> --vnet-subnet-name jm-akqa-gw-proxy-dev-gws-subnet \
> --nic-name jm-akqa-gw-proxy-dev-gw1-nic \
> --os-type Linux \
> --image-urn Canonical:UbuntuServer:16.04-LTS:latest \
> --admin-username jadmin --admin-password p@ssw0rd \
> --vm-size Standard_F1s
info:    Executing command vm create
+ Looking up the VM "jm-akqa-gw-proxy-dev-gw1"                                 
info:    Using the VM Size "Standard_F1s"
info:    The [OS, Data] Disk or image configuration requires storage account
+ Retrieving storage accounts                                                  
info:    Could not find any storage accounts in the region "westeurope", trying to create new one
+ Creating storage account "cli21b60a27a12fbe731***" in "westeurope"          
+ Looking up the storage account cli21b60a27a12fbe731***                      
+ Looking up the NIC "jm-akqa-gw-proxy-dev-gw1-nic"                            
info:    Found an existing NIC "jm-akqa-gw-proxy-dev-gw1-nic"
info:    Found an IP configuration with virtual network subnet id "/subscriptions/0a4f2b9c-***-***-***-40b17ef8c3ab/resourceGroups/jm-akqa-gw-proxy-dev/providers/Microsoft.Network/virtualNetworks/jm-akqa-gw-proxy-dev-vnet/subnets/jm-akqa-gw-proxy-dev-gws-subnet" in the NIC "jm-akqa-gw-proxy-dev-gw1-nic"
info:    This is an NIC without publicIP configured
info:    The storage URI 'https://cli21b60a27a12fbe731***.blob.core.windows.net/' will be used for boot diagnostics settings, and it can be overwritten by the parameter input of '--boot-diagnostics-storage-uri'.
+ Creating VM "jm-akqa-gw-proxy-dev-gw1"                                       
info:    vm create command OK

[/simterm]

Проверяем:

[simterm]

$ ssh -p 2200 jageradmin@52.***.***.82                                                                                                                                                                
...
jadmin@jm-akqa-gw-proxy-dev-gw1:~$

[/simterm]

Готово.

По теме:

https://docs.microsoft.com/en-us/azure/load-balancer/load-balancer-get-started-ilb-arm-cli

https://docs.microsoft.com/en-us/azure/virtual-network/virtual-networks-create-vnet-arm-pportal

https://docs.microsoft.com/en-us/azure/load-balancer/load-balancer-get-started-internet-arm-cli

https://docs.microsoft.com/en-us/azure/virtual-machines/linux/sizes-compute

https://docs.microsoft.com/en-us/azure/virtual-machines/linux/cli-ps-findimage

https://docs.microsoft.com/en-us/azure/virtual-network/virtual-networks-overview

Azure File share

Далее требуется создать data-диск, которые будут использоваться в роли файловых шар для конфигов NGINX на обеих машинах.

Создаём Storage account:

[simterm]

$ azure storage account create --resource-group jm-akqa-gw-proxy-dev \
> --location westeurope \
> --sku-name GRS \
> --kind storage \                                                                                                                                                                                                                            
> gwproxystorage

[/simterm]

Проверяем:

[simterm]

$ azure storage account show -g jm-gw-proxy-dev gwproxystorage
info:    Executing command storage account show
+ Getting storage account                                                      
data:    Name: gwproxystorage
data:    Url: /subscriptions/0a4f2b9c-***-***-***-40b17ef8c3ab/resourceGroups/jm-akqa-gw-proxy-dev/providers/Microsoft.Storage/storageAccounts/gwproxystorage
data:    Type: Microsoft.Storage/storageAccounts
data:    SKU Name: Standard_GRS
data:    SKU Tier: Standard
data:    Kind: Storage
data:    Resource Group: jm-akqa-gw-proxy-dev
data:    Location: westeurope
data:    Provisioning State: Succeeded
data:    Primary Location: westeurope
data:    Primary Status: available
data:    Secondary Location: northeurope
data:    Creation Time: Fri, 14 Jul 2017 12:41:15 GMT
data:    Primary Endpoints: blob https://gwproxystorage.blob.core.windows.net/
data:    Primary Endpoints: queue https://gwproxystorage.queue.core.windows.net/
data:    Primary Endpoints: table https://gwproxystorage.table.core.windows.net/
data:    Primary Endpoints: file https://wproxystorage.file.core.windows.net/
info:    storage account show command OK

[/simterm]

Создаём файл-шару:

[simterm]

$ azure storage share create gwproxydata \
> --account-name gwproxystorage \
> --account-key  F5M***yZg== \
> 
info:    Executing command storage share create
+ Creating storage file share gwproxydata                                      
+ Getting Storage share information                                            
data:    {
data:        name: 'gwproxydata',
data:        metadata: {},
data:        etag: '"0x8D4CCEDCBBCBBF7"',
data:        lastModified: 'Mon, 17 Jul 2017 08:28:26 GMT',
data:        requestId: 'f05a9307-001a-004b-64d6-feb922000000',
data:        quota: '5120',
data:        shareUsage: '0'
data:    }
info:    storage share create command OK

[/simterm]

Создаём в этой шаре каталог для файлов NGINX с именем datanginx-conf.d:

[simterm]

$ azure storage directory create --share gwproxydata \
> --path datanginx-conf.d  \
> --account-name gwproxystorage \
> --account-key  F5M***yZg==
info:    Executing command storage directory create
+ Creating storage file directory 'datanginx-conf.d' in share gwproxydata      
info:    Directory datanginx-conf.d has been created successfully
data:    {
data:        name: 'datanginx-conf.d',
data:        etag: '"0x8D4CCEE3CAA3033"',
data:        lastModified: 'Mon, 17 Jul 2017 08:31:35 GMT',
data:        requestId: '3b4b92d7-001a-0009-6dd7-fe00a2000000'
data:    }
info:    storage directory create command OK

[/simterm]

Подключаем на сервер gw1 c NGINX, устанавливаем cifs-utils:

[simterm]

root@jm-akqa-gw-proxy-dev-gw1:~# apt update && apt install cifs-utils
...
cifs-utils is already the newest version (2:6.4-1ubuntu1.1).

[/simterm]

Создаём каталог:

[simterm]

root@jm-akqa-gw-proxy-dev-gw1:~# mkdir -p /data

[/simterm]

Монтируем шару:

[simterm]

root@jm-akqa-gw-proxy-dev-gw1:~# mount -t cifs //gwproxystorage.file.core.windows.net/gwproxydata /data -o vers=3.0,username=gwproxystorage,password=F5M***yZg==,dir_mode=0755,file_mode=0644

[/simterm]

Проверяем:

[simterm]

root@jm-akqa-gw-proxy-dev-gw1:~# ls -l /data/
total 0
drwxr-xr-x 2 root root 0 Jul 17 08:31 datanginx-conf.d

[/simterm]

Готово.

По теме:

https://docs.microsoft.com/en-us/azure/virtual-machines/linux/mount-azure-file-storage-on-linux-using-smb

https://docs.microsoft.com/en-us/azure/storage/storage-blob-storage-tiers

https://medium.com/@wimcoekaerts/creating-an-azure-file-share-and-mounting-it-in-your-linux-instance-2d011fbacdbc

https://docs.microsoft.com/en-us/azure/storage/storage-how-to-use-files-linux

NGINX

Следующим шагом – устанавливаем NGINX, и подключаем к нему каталог /data/datanginx-conf.d/:

[simterm]

root@jm-akqa-gw-proxy-dev-gw1:~# apt install nginx -y

[/simterm]

В файл /etc/nginx/nginx.conf в блок http {} добавляем:

...
 include /data/datanginx-conf.d/*.conf;
...

Проверяем:

[simterm]

root@jm-akqa-gw-proxy-dev-gw1:~# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

[/simterm]

Добавляем тестовый файл конфигурации /data/datanginx-conf.d/jm-akqa-gw-proxy-dev.domain.ms.conf:

[simterm]

server {
    server_name jm-akqa-gw-proxy-dev.domain.ms;
    
    access_log /var/log/nginx/jm-akqa-gw-proxy-dev.domain.ms-access.log;
    error_log /var/log/nginx/jm-akqa-gw-proxy-dev.domain.ms-error.log;

    root /usr/share/nginx/html;
        
}

[/simterm]

Проверяем NGINX, перечитываем конфиги:

[simterm]

root@jm-akqa-gw-proxy-dev-gw1:~# nginx  -t && service nginx reload
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

[/simterm]

Проверяем по URL:

[simterm]

$ curl jm-akqa-gw-proxy-dev.domain.ms
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

[/simterm]

Готово.