Всем привет! Хочу поделиться с вами вариантом скрипта для создания экземпляров Nextcloud через Ansible в vCloudDirector. Заодно опишу процесс создания экземпляров Nextcloud. Возможно, у вас тоже бывают подобные задачи, — можете не изобретать ещё один велосипед, вот один из вариантов решения.
Для начала приведу схему инфраструктуры, в которой будут разворачиваться новые экземпляры Nextcloud.
Добавлю немного подробностей, чтобы картинка стала понятнее.
Все серверы в инфраструктуре — виртуальные, развёрнуты в Vmware Cloud Director (далее VCD). Они работают под управлением ОС Ubuntu 20.04. В качестве reverse proxy используется веб-сервер Nginx.
Новые разворачиваемые экземпляры Nextcloud представлены на схеме как Nextcloud Instances. В качестве сервера выполнения скрипта создания новых экземпляров Nextcloud используется Scripts. Этот сервер имеет ssh доступы по ключу на Nginx и все создаваемые экземпляры. Также Scripts может посылать API запросы к Vmware Cloud Director.
Для доступов к интернету используется NSX EDGE Gateway, а для разрешения доменных имён — публичный DNS сервер (он так и обозначен на схеме). Все экземпляры Nextcloud находятся в одном домене domainname.com. Вместо этого имени должен быть ваш домен. Также предполагается, что SSL сертификаты на домен domainname.com получены и добавлены на Nginx.
Скрипт создания новых экземпляров Nextcloud
Скрипт выполняется на виртуальном сервере Scripts. На нём установлен Ansible с модулем ansible-module-vcloud-director для работы с API VCD. Он состоит из главного скрипта на bash и отдельных скриптов для определённых действий на Ansible и Python. Вот их список:
create_instances_nextcloud.sh
create_vapp.yml
create_vm_in_vapp.yml
list_nics.yml
insert_txt.py
config_next.yml
config_nginx.yml
nextcloud_template_tls
Скрипт create_instances_nextcloud.sh выглядит так:
#!/bin/bash
ansible-playbook create_vapp.yml --extra-vars "orgname=$1"
ansible-playbook create_vm.yml --extra-vars "orgname=$1"
ip=$(ansible-playbook list_nics.yml --extra-vars "orgname=$1" 2>&1 | grep '"ip_address":' | grep -E -o '[0-9]{1,3}(\.[0-9]{1,3}){3}')
last_name_conf_next="nextcloud_tls"
name_config_next="$1$last_name_conf_next"
echo "[$1]" >> ansible_hosts
echo "$ip" >> ansible_hosts
cp nextcloud_template_tls "$name_config_next"
./insert_txt.py $1 $ip $name_config_next
last_domain_name_nextcloud="next.domainname.com"
domain_name_nextcloud="$1$last_domain_name_nextcloud"
scp $name_config_next root@192.168.4.3:/etc/nginx/sites-available
ansible-playbook config_nginx.yml --extra-vars "name_config_next=$name_config_next"
sleep 60
ansible-playbook config_next.yml --extra-vars "orgname=$1 ip=$ip domain_name_nextcloud=$domain_name_nextcloud password=$2"
Скрипт принимает два параметра:
Имя экземпляра Nextcloud. Является суффиксом к доменному имени next.domainname.com
Пароль пользователя admin в Nextcloud
Во второй строке скрипта используется ansible playbook create_vapp.yml. Он нужен для создания нового vApp в VCD. Приведу его содержание:
- name: vCloudDirectorAnsible
hosts: localhost
environment:
env_user: admin
env_password: password
env_host: vcd.domainname.ru ## VCD Instance URL
env_org: name_org ## VCD ORG to login
## env_api_version: PYVCLOUD_API_VERSION
env_verify_ssl_certs: false
tasks:
- name: create vapp
vcd_vapp:
vapp_name: "{{ orgname }}Nextcloud"
vdc: "name_VDC"
description: "name_VDC"
network: "name_network"
deploy: true
power_on: true
accept_all_eulas: false
state: "present"
Playbook принимает параметр “orgname”, что является суффиксом к названию нового экземпляра Nextcloud
В переменной “environment” задаются “credentials”, такие как:
env_user – имя пользователя с правами администратора организации
env_password – пароль пользователя
env_host – доменное имя VCD
env_org – название организации в VCD
Далее выполняется задача создания vapp. В переменной vcd_vapp вводятся данные, необходимые для нового vApp:
vapp_name – Название vApp с суффиксом названия экземпляра Nextcloud передаваемый в переменной orgname
vdc – название VDC где будет создаваться экземпляр Nextcloud
description – опиcание vApp (может быть любым)
network – имя сети которую необходимо подключить к vApp
power_on – включить vApp после создания
state – present означает что нужно создать vApp
Далее в скрипте create_instances_nextcloud.sh (3 строка) выполняется playbook create_vm.yml создания виртуальной машины в ранее созданном vApp. Создание виртуальной машины происходит из заранее подготовленного шаблона ВМ с Nextcloud. Вот содержание playbook:
- name: vCloudDirectorAnsible
hosts: localhost
environment:
env_user: name_admin
env_password: password
env_host: vcd.domainname.ru ## VCD Instance URL
env_org: name_VDC ## VCD ORG to login
## env_api_version: PYVCLOUD_API_VERSION
env_verify_ssl_certs: false
tasks:
- name: create vapp vm from catalog
vcd_vapp_vm:
target_vm_name: "{{ orgname }}Nextcloud"
target_vapp: "{{ orgname }}Nextcloud"
target_vdc: name_VDC
source_vdc: "name_source_VDC"
source_catalog_name: name_Catalog
source_template_name: template_name
source_vm_name: source_vm_name
hostname: "{{ orgname }}Nextcloud"
ip_allocation_mode: "POOL"
power_on: "true"
all_eulas_accepted: "true"
network: network_name
deploy: false
state: "present"
Playbook как и в предыдущем случае принимает один параметр: “orgname”.
Как и в предыдущем playbook в переменной “environment” указываются “credentials”. Далее создаётся задача создания виртуальной машины в vApp, где в переменной “vcd_vapp_vm” указываются следующие данные:
target_vm_name – имя создаваемой машины с суффиксом названия экземпляра Nextcloud, передаваемым через переменную orgname
target_vapp — название vApp, в котором будет создаваться ВМ, с суффиксом названия экземпляра Nextcloud передаваемым в переменной “orgname”
target_vdc – название VDC, в котором будет создаваться ВМ
source_catalog_name – имя каталога, в котором находится шаблон
source_template_name – имя шаблона с Nextcloud, который будет разворачиваться
source_vm_name – имя ВМ, которая находится в шаблоне
hostname – сетевое имя ВМ с суффиксом названия экземпляра Nextcloud, передаваемым через переменную “orgname”
ip_allocation_mode – способ назначения ip-адреса ВМ. Выбран способ static_ip_pool
power_on – включить или нет машину после создания. Выбрано “Да”.
network – имя сети, к которой необходимо подключить создаваемую ВМ. Имя сети совпадает с именем сети, которая подключается к vApp при его создании в прошлом playbook.
State – поставлена present. Это означает, что будет создаваться новая ВМ
На этом этапе выполнения вывод скрипта будет примерно таким:
После создания vApp и VM в нём, нам необходимо узнать ip-адрес, который получила новая ВМ и записать его в переменную “ip” командой в строке 4 скрипта create_instances_nextcloud.sh. Делается это при помощи playbook “list_nics.yml”. Вот его содержание:
- name: vCloudDirectorAnsible
hosts: localhost
environment:
env_user: name_admin
env_password: password
env_host: vcd.domainname.ru ## VCD Instance URL
env_org: name_org ## VCD ORG to login
## env_api_version: PYVCLOUD_API_VERSION
env_verify_ssl_certs: false
tasks:
- name: list vapp vm nics
vcd_vapp_vm:
target_vm_name: "{{ orgname }}Nextcloud"
target_vapp: "{{ orgname }}Nextcloud"
target_vdc: name_VDC
operation: "list_nics"
register: command_output
- debug:
var: command_output
Playbook принимает параметр “orgname”.
Как и в предыдущих playbook в переменной “environment” указываются “credentials” . Затем создаётся задача просмотра информации о интерфейсах. В переменной vcd_vapp_vm указываются:
target_vm_name – имя ВМ, информацию по которой хотим получить. Совпадает с именем ВМ, которые были указаны в предыдущих playbook.
target_vapp – имя vApp,в котором находится ВМ
target_vdc – имя VDC, в котором находится ВМ
operation – тип операции. Используется операция получения информации по интерфейсам "list_nics"
Далее выполняется подготовка конфигурационных файлов Nginx. Делается это путём редактирования единого шаблона конфигурации под именем nextcloud_template_tls. Этот шаблон был создан из конфигурации путём удаления строки “server_name <your-nc-domain>;” и “proxy_pass http://127.0.0.1:11000$request_uri; ”.
В строке 5 и 6 скрипта create_instances_nextcloud.sh задаётся имя конфигурационного файла Nginx для экземпляра Nextcloud. Затем добавляются строки в инвентарный файл Ansible для нового экземпляра Nextcloud в командах под строками 7 и 8 скрипта create_instances_nextcloud.sh.
В строке 9 копируется шаблон конфигурации Nginx nextcloud_template_tls под новым именем, которое хранится в переменной name_config_next. Затем при помощи скрипта на Python insert_txt.py вставляются нужные строки для нашего экземпляра Nextcloud. Вот содержание этого скрипта:
#!/usr/bin/python3.8
import sys
def insert(file, line, column, text):
ln, cn = line - 1, column - 1 # offset from human index to Python index
count = 0 # initial count of characters
with open(file, 'r+') as f: # open file for reading an writing
for idx, line in enumerate(f): # for all line in the file
if idx < ln: # before the given line
count += len(line) # read and count characters
elif idx == ln: # once at the line
f.seek(count + cn) # place cursor at the correct character location
remainder = f.read() # store all character afterwards
f.seek(count + cn) # move cursor back to the correct character location
f.write(text + remainder) # insert text and rewrite the remainder
return # You're finished!
if __name__ == "__main__":
nextcloud_domain_name='server_name ' + sys.argv[1] + 'next.domainname.com;'
directve_proxy_pass_next='proxy_pass https://' + sys.argv[2] + '$request_uri;'
template_nextcloud=sys.argv[3]
insert(template_nextcloud, 27, 5, nextcloud_domain_name)
insert(template_nextcloud, 30, 9, directve_proxy_pass_next)
Этот скрипт принимает 3 параметра:
Суффикс – суффикс имени нового экземпляра Nextcloud. Является суффиксом доменного имени next.domainname.com
IP адрес – ip-адрес нового экземпляра Nextcloud
Имя конфигурационного файла Nginx для Nextcloud
В итоге данный скрипт добавляет директивы “server_name” и “proxy_pass” в конфигурационный файл Nginx, где domainname.com — домен, в котором будет находиться ваш экземпляр Nextcloud.
Далее в строках 11, 12 скрипта create_instances_nextcloud.sh переменой domain_name_nextcloud присваивается доменное имя Nextcloud, где domainname.com — домен, в котором будет находиться ваш экземпляр Nextcloud.
В строке 13 скрипта create_instances_nextcloud.sh подготовленный конфигурационный файл копируется на Nginx по ssh при помощи команды scp.
В строке 14 задаётся конфигурация Nginx при помощи playbook config_nginx.yml. Вот его содержание:
- name: "Run a shell command on a remote host"
hosts: nginx*
tasks:
- name: create simvolic url
shell: |
ln -s /etc/nginx/sites-available/{{ name_config_next }} /etc/nginx/sites-enabled/{{ name_config_next }}
/etc/init.d/nginx reload
Playbook принимает один параметр “name_config_next”, что является именем конфигурационного файла, который мы подготавливали ранее.
В этом playbook удалённо выполняются команды по ssh на Nginx proxy. Например, команды создания символической ссылки в каталоге “sites-enabled” на конфигурационный файл, который мы скопировали ранее в каталог “sites-available”. После этого Nginx перечитывает конфигурацию командой “/etc/init.d/nginx reload”.
На этом этапе выполнения вывод скрипта будет примерно таким
В строке 15 скрипта create_instances_nextcloud.sh при помощи команды sleep ждём 60 секунд, пока машина загрузится.
В строке 16 скрипта create_instances_nextcloud.sh идёт конфигурация созданного экземпляра Nextcloud при помощи playbook config_next.yml. Вот его содержание:
- name: "Run a shell command on a remote host"
hosts: "{{ orgname }}"
tasks:
- name: congigure Nextcloud
shell: |
sudo -u www-data php /var/www/nextcloud/occ config:system:set trusted_domains 3 --value='{{ ip }}'
sudo -u www-data php /var/www/nextcloud/occ config:system:set trusted_domains 4 --value='{{ domain_name_nextcloud }}'
echo "{{ password }}" | sudo -u www-data php /var/www/nextcloud/occ user:resetpassword admin
systemctl restart apache2
Playbook принимает три параметра:
Суффикс имени экземпляра Nextcloud
IP-адрес экземпляра Nextcloud
Доменное имя экземпляра Nextcloud
Пароль пользователя admin который необходимо задать в Nextcloud
В этом playbook удалённо по ssh выполняются команды на новом экземпляре Nextcloud: добавляются доверенные домены в виде ip-адреса экземпляра Nextcloud и его доменного имени. Сбрасывается пароль пользователя администратора Nextcloud под именем admin. Затем перезагружается веб-сервер apache2.
На этом этапе выполнения скрипта вывод будет примерно таким
После выполнения скрипта create_instances_nextcloud.sh необходимо создать DNS записи для нашего экземпляра Nextcloud на DNS сервере. И всё, можно пользоваться Nextcloud.
Описанный алгоритм позволяет создать много экземпляров Nextcloud, используя скрипт create_instances_nextcloud.sh. Будет круто, если мой опыт вам поможет.