В прошлой статье, я рассказывал о том, как можно быстро развернуть тестовую среду при помощи DevStack. В этой публикации я расскажу как развернуть своё «облако» OpenStack на двух машинах (Controller, Compute) в комплектации:
- Keystone
- Glance
- Nova
- Neutron
- Cinder
- Horizon
В общем-то эта система позволит нам запускать множество виртуальных машин (сколько позволит памяти и CPU на compute), создавать виртуальные сети, создавать виртуальные диски и подключать их к VM, ну и конечно управлять всем этим через удобный дашборд.
Осторожно! Много «портянок» со списком команд и конфигами!
Сразу скажу:
- Теоретически, я мог забыть что-то дописать или недоправить в конфигах, забыть, что нужно перезапустить какой-то сервис или ещё что-то.
- Публикация не клонирует, но берёт свои корни из официальной документации, которая есть здесь (англ.)
- Цель написания всего этого, чтобы был какой-то более-менее читабельный ман по OpenStack на русском языке. Не претендую, что получилось это у меня, но надеюсь это побудит кого-то сделать лучше. Так же, готов принять во внимание комментарии о необходимых правках публикации, дабы она стала более удобочитабельной.
Не надо бездумно «копипастить». Это, конечно, поможет установить OpenStack-среду по данному руководству, но не научит использовать это знание в полевых условиях.
Что будем использовать?
- Controller i3-540/8Gb/2x120Gb + 2x500Gb/2NIC
- Compute i7-2600/32Gb/2x500Gb/1NIC
ОС: Ubuntu 14.04 (Можно использовать CentOS, но руководство будет основано на Ubuntu).
Редакция OpenStack: Kilo
Подготовка
Сеть
В оригинальном руководстве используется 4 сети:
Management — 10.0.0.0/24 — VLAN 10
Tunnel — 10.0.1.0/24 — VLAN 11
Storage — 10.0.2.0/24 — VLAN 12
External — 192.168.1.0/24
External-сеть в нашем случае смотрит куда-нибудь в домашнюю сеть, но по большому счёту этот интерфейс может смотреть и во «всемирную паутину» — всё зависит от того, для чего разворачиваете облако.
Будет очень неплохо иметь работоспособный dns-server. Я использовал dnsmasq.
# cat /etc/hosts
10.0.0.11 controller
10.0.0.31 compute1
Настраиваем интерфейсы
# cat /etc/network/interfaces
auto p2p1.10
iface p2p1.10 inet static
address 10.0.0.11
netmask 255.255.255.0
gateway 10.0.0.1
dns-nameservers 10.0.0.1
auto p2p1.11
iface p2p1.11 inet static
address 10.0.1.11
netmask 255.255.255.0
auto p2p1.12
iface p2p1.12 inet static
address 10.0.2.11
netmask 255.255.255.0
# Интерфейс для внешней сети
auto p3p1
iface p3p1 inet manual
up ip link set dev $IFACE up
down ip link set dev $IFACE down
# cat /etc/network/interfaces
auto p2p1.10
iface p2p1.10 inet static
address 10.0.0.31
netmask 255.255.255.0
gateway 10.0.0.1
dns-nameservers 10.0.0.1
auto p2p1.11
iface p2p1.11 inet static
address 10.0.1.31
netmask 255.255.255.0
auto p2p1.12
iface p2p1.12 inet static
address 10.0.2.31
netmask 255.255.255.0
Проверяем, чтобы обе машины видели друг друга и ходили в сеть.
NTP
На контроллере:
# apt-get install ntp -y
# cat /etc/ntp.conf
server ntp.oceantelecom.ru iburst
restrict -4 default kod notrap nomodify
restrict -6 default kod notrap nomodify
# service ntp stop
# ntpdate ntp.oceantelecom.ru
# service ntp start
На вычислительной ноде:
# apt-get install ntp -y
# cat /etc/ntp.conf
server controller iburst
# service ntp stop
# ntpdate controller
# service ntp start
Репозиторий Kilo
# apt-get install ubuntu-cloud-keyring
# echo "deb http://ubuntu-cloud.archive.canonical.com/ubuntu" "trusty-updates/kilo main" > /etc/apt/sources.list.d/cloudarchive-kilo.list
Kilo довольно молодой выпуск — апрель 2015 года. Больше всего в этом релизе мне понравился русский язык в интерфейсе Horizon.
Более подробно можно почитать тут.
Обновляемся:
# apt-get update && apt-get dist-upgrade -y
SQL + RabbitMQ
В роли SQL сервера может быть MySQL, PostgreSQL, Oracle или любой другой, который поддерживается SQLAlchemy. Мы будем устанавливать MariaDB как и в официальном мануале.
# apt-get install mariadb-server python-mysqldb -y
# cat /etc/mysql/conf.d/mysqld_openstack.cnf
[mysqld]
bind-address = 10.0.0.11
default-storage-engine = innodb
innodb_file_per_table
collation-server = utf8_general_ci
init-connect = 'SET NAMES utf8'
character-set-server = utf8
# service mysql restart
# mysql_secure_installation
Если есть лишние HDD с хорошей производительностью, то файлы БД можно положить на него и это не будет лишним, если вы планируете развивать стенд вычислительными нодами.
Ну и конечно же RabbitMQ:
# apt-get install rabbitmq-server
# rabbitmq-plugins enable rabbitmq_management
# service rabbitmq-server restart
Мы устанавливаем рээбита и запускаем административную WebGUI, для удобства слежения за очередями.
Создаём пользователя и устанавливаем права ему:
rabbitmqctl add_user openstack RABBIT_PASS
rabbitmqctl set_permissions openstack ".*" ".*" ".*"
Keystone
Keystone — центр авторизации для OpenStack. Все авторизации проходят через него. Данные Keystone хранит в SQL-БД, но использует так же и memcache.
Подготовим БД:
# mysql -u root -p
CREATE DATABASE keystone;
GRANT ALL PRIVILEGES ON keystone.* TO 'keystone'@'localhost' IDENTIFIED BY 'KEYSTONE_DBPASS';
GRANT ALL PRIVILEGES ON keystone.* TO 'keystone'@'%' IDENTIFIED BY 'KEYSTONE_DBPASS';
Естественно, не забудьте подставить свой пароль, как и везде.
Отключаем автозагрузку keystone сервиса и устанавливаем все необходимые компоненты:
# echo "manual" > /etc/init/keystone.override
# apt-get install keystone python-openstackclient apache2 libapache2-mod-wsgi memcached python-memcache
В конфиге /etc/keystone/keystone.conf прописываем следующие строки:
[DEFAULT]
admin_token = ADMIN_TOKEN
[database]
connection = mysql://keystone:KEYSTONE_DBPASS@controller/keystone
[memcache]
servers = localhost:11211
[token]
provider = keystone.token.providers.uuid.Provider
driver = keystone.token.persistence.backends.memcache.Token
[revoke]
driver = keystone.contrib.revoke.backends.sql.Revoke
ADMIN_TOKEN генерим при помощи "openssl rand -hex 16".
Синхронизируем локальную БД с SQL сервером
# su -s /bin/sh -c "keystone-manage db_sync" keystone
Настраиваем апач:
# cat /etc/apache2/apache2.conf
...
ServerName controller
...
# cat /etc/apache2/sites-available/wsgi-keystone.conf
Listen 5000
Listen 35357
<VirtualHost *:5000>
WSGIDaemonProcess keystone-public processes=5 threads=1 user=keystone display-name=%{GROUP}
WSGIProcessGroup keystone-public
WSGIScriptAlias / /var/www/cgi-bin/keystone/main
WSGIApplicationGroup %{GLOBAL}
WSGIPassAuthorization On
<IfVersion >= 2.4>
ErrorLogFormat "%{cu}t %M"
</IfVersion>
LogLevel info
ErrorLog /var/log/apache2/keystone-error.log
CustomLog /var/log/apache2/keystone-access.log combined
</VirtualHost>
<VirtualHost *:35357>
WSGIDaemonProcess keystone-admin processes=5 threads=1 user=keystone display-name=%{GROUP}
WSGIProcessGroup keystone-admin
WSGIScriptAlias / /var/www/cgi-bin/keystone/admin
WSGIApplicationGroup %{GLOBAL}
WSGIPassAuthorization On
<IfVersion >= 2.4>
ErrorLogFormat "%{cu}t %M"
</IfVersion>
LogLevel info
ErrorLog /var/log/apache2/keystone-error.log
CustomLog /var/log/apache2/keystone-access.log combined
</VirtualHost>
# ln -s /etc/apache2/sites-available/wsgi-keystone.conf /etc/apache2/sites-enabled
# mkdir -p /var/www/cgi-bin/keystone
# curl http://git.openstack.org/cgit/openstack/keystone/plain/httpd/keystone.py?h=stable/kilo | tee /var/www/cgi-bin/keystone/main /var/www/cgi-bin/keystone/admin
# chown -R keystone:keystone /var/www/cgi-bin/keystone
# chmod 755 /var/www/cgi-bin/keystone/*
# service apache2 restart
# rm -f /var/lib/keystone/keystone.db
Мы меняем ServerName на имя нашего контроллера.
Рабочие скрипты мы берём с репозитория openstack.
Настроим endpoint`ы. Вообщем-то именно благодаря endpoint`ам openstack будет знать где и какой сервис работает.
Добавим переменные окружения, для того чтобы не указывать их каждый раз в параметрах keystone:
# export OS_TOKEN=ADMIN_TOKEN
# export OS_URL=http://controller:35357/v2.0
Теперь создаём сервис:
# openstack service create --name keystone --description "OpenStack Identity" identity
Ну и создаём API endpoint:
# openstack endpoint create --publicurl http://controller:5000/v2.0 --internalurl http://controller:5000/v2.0 --adminurl http://controller:35357/v2.0 --region RegionOne identity
RegionOne можно поменять на любое удобочитаемое имя. Я буду использовать его, чтобы не «заморачиваться».
Создаём проекты, пользователей и роли.
Будем продолжать делать по официальному ману, так что всё так же: админ и демо
# openstack project create --description "Admin Project" admin
# openstack user create --password-prompt admin
# openstack role create admin
# openstack role add --project admin --user admin admin
Пароль для админа придумайте сами. По порядку: создали проект «Admin Project», пользователя и роль admin, и соединяем проект и пользователя с ролью.
Теперь создаём проектservice:
# openstack project create --description "Service Project" service
По аналогии с admin`ом создаём demo:
# openstack project create --description "Demo Project" demo
# openstack user create --password-prompt demo
# openstack role create user
# openstack role add --project demo --user demo user
Создадим скрипты окружения:
# cat admin-openrc.sh
export OS_PROJECT_DOMAIN_ID=default
export OS_USER_DOMAIN_ID=default
export OS_PROJECT_NAME=admin
export OS_TENANT_NAME=admin
export OS_USERNAME=admin
export OS_PASSWORD=ADMIN_PASS
export OS_AUTH_URL=http://controller:35357/v3
export OS_IMAGE_API_VERSION=2
export OS_VOLUME_API_VERSION=2
# cat demo-openrc.sh
export OS_PROJECT_DOMAIN_ID=default
export OS_USER_DOMAIN_ID=default
export OS_PROJECT_NAME=demo
export OS_TENANT_NAME=demo
export OS_USERNAME=demo
export OS_PASSWORD=DEMO_PASS
export OS_AUTH_URL=http://controller:5000/v3
export OS_IMAGE_API_VERSION=2
export OS_VOLUME_API_VERSION=2
Собственно:
# source admin-openrc.sh
На этом настройка сервиса keystone закончена.
Glance
Glance — это инструмент OpenStack для хранения шаблонов (образов) виртуальных машин. Образы могут храниться в Swift, в собственном хранилище Glance`а, но и где-то ещё — главное чтобы этот образ можно было получить по http.
Начнём как всегда с mysql:
# mysql -u root -p
CREATE DATABASE glance;
GRANT ALL PRIVILEGES ON glance.* TO 'glance'@'localhost' IDENTIFIED BY 'GLANCE_DBPASS';
GRANT ALL PRIVILEGES ON glance.* TO 'glance'@'%' IDENTIFIED BY 'GLANCE_DBPASS';
Создадим в keystone информацию о будущем сервисе:
# openstack user create --password-prompt glance
# openstack role add --project service --user glance admin
# openstack service create --name glance --description "OpenStack Image service" image
# openstack endpoint create --publicurl http://controller:9292 --internalurl http://controller:9292 --adminurl http://controller:9292 --region RegionOne image
Мы создаём пользователя glance и подключаем его к роли admin, т.к. все сервисы будут работать именно от этой роли, мы создаём сервис glance, задаём endpoint.
Теперь приступим к установке:
# apt-get install glance python-glanceclient
и настройке:
# cat /etc/glance/glance-api.conf
[DEFAULT]
...
notification_driver = noop
[database]
connection = mysql://glance:GLANCE_DBPASS@controller/glance
[keystone_authtoken]
auth_uri = http://controller:5000
auth_url = http://controller:35357
auth_plugin = password
project_domain_id = default
user_domain_id = default
project_name = service
username = glance
password = GLANCE_PASS
[paste_deploy]
flavor = keystone
[glance_store]
default_store = file
filesystem_store_datadir = /var/lib/glance/images/
Что бы ни было в секции [keystone_authtoken] — это нужно удалить. GLANCE_PASS — пароль от пользователя glance в keystone. filesystem_store_datadir это путь к хранилищу, где будут лежать наши образы. Рекомендую подмонтировать к этой директории или рейд-массив или надёжное сетевое хранилище, чтобы случайно не потерять все наши образы из-за отказа диска.
В /etc/glance/glance-registry.conf дублируем ту же информацию из секций database, keystone_authtoken, paste_deploy, DEFAULT.
Синхронизируем БД:
# su -s /bin/sh -c "glance-manage db_sync" glance
Перезапускаем сервисы и удаляем локальную БД:
# service glance-registry restart
# service glance-api restart
# rm -f /var/lib/glance/glance.sqlite
В официальном мануале загружается cirros, который в общем-то нам не нужен, так что мы загрузим образ Ubuntu:
# mkdir /tmp/images
# wget -P /tmp/images http://cloud-images.ubuntu.com/releases/14.04.2/release/ubuntu-14.04-server-cloudimg-amd64-disk1.img
# glance image-create --name "Ubuntu-Server-14.04.02-x86_64" --file /tmp/images/ubuntu-14.04-server-cloudimg-amd64-disk1.img --disk-format qcow2 --container-format bare --visibility public --progress
# rm -r /tmp/images
Можно сразу залить все нужные нам образы, но думаю дождёмся момента, когда у нас появится Dashboard.
Целом — наш сервис Glance готов.
Nova
Nova — основная часть IaaS в OpenStack. Собственно благодаря Nova создаются виртуальные машины автоматически. Nova может взаимодействовать с KVM, Xen, Hyper-V, VMware и кажется Ironic (честно говоря не совсем понимаю как это работает). Мы будем использовать KVM, для других гипервизоров конфиги будут отличаться.
Контроллер
Опять начинаем с БД:
# mysql -u root -p
CREATE DATABASE nova;
GRANT ALL PRIVILEGES ON nova.* TO 'nova'@'localhost' IDENTIFIED BY 'NOVA_DBPASS';
GRANT ALL PRIVILEGES ON nova.* TO 'nova'@'%' IDENTIFIED BY 'NOVA_DBPASS';
Добавляем информацию в keystone:
# openstack user create --password-prompt nova
# openstack role add --project service --user nova admin
# openstack service create --name nova --description "OpenStack Compute" compute
# openstack endpoint create --publicurl http://controller:8774/v2/%\(tenant_id\)s --internalurl http://controller:8774/v2/%\(tenant_id\)s --adminurl http://controller:8774/v2/%\(tenant_id\)s --region RegionOne compute
Устанавливаем необходимые пакеты:
# apt-get install nova-api nova-cert nova-conductor nova-consoleauth nova-novncproxy nova-scheduler python-novaclient
[DEFAULT]
...
rpc_backend = rabbit
auth_strategy = keystone
my_ip = 10.0.0.11
vncserver_listen = 10.0.0.11
vncserver_proxyclient_address = 10.0.0.11
[database]
connection = mysql://nova:NOVA_DBPASS@controller/nova
[oslo_messaging_rabbit]
rabbit_host = controller
rabbit_userid = openstack
rabbit_password = RABBIT_PASS
[keystone_authtoken]
auth_uri = http://controller:5000
auth_url = http://controller:35357
auth_plugin = password
project_domain_id = default
user_domain_id = default
project_name = service
username = nova
password = NOVA_PASS
[glance]
host = controller
[oslo_concurrency]
lock_path = /var/lib/nova/tmp
Синхронизируем БД, перезапускаем сервисы и удаляем локальную БД.
# su -s /bin/sh -c "nova-manage db sync" nova
# service nova-api restart
# service nova-cert restart
# service nova-consoleauth restart
# service nova-scheduler restart
# service nova-conductor restart
# service nova-novncproxy restart
# rm -f /var/lib/nova/nova.sqlite
Вычислительный узел
Теперь мы наконец начнём работать с вычислительным узлом. Все описанные действия справедливы для каждого вычислительного узла в нашей системе.
# apt-get install nova-compute sysfsutils
[DEFAULT]
...
verbose = True
rpc_backend = rabbit
auth_strategy = keystone
my_ip = 10.0.0.31 #MANAGEMENT_INTERFACE_IP_ADDRESS
vnc_enabled = True
vncserver_listen = 0.0.0.0
vncserver_proxyclient_address = 10.0.0.31 #MANAGEMENT_INTERFACE_IP_ADDRESS
novncproxy_base_url = http://controller:6080/vnc_auto.html
[oslo_messaging_rabbit]
rabbit_host = controller
rabbit_userid = openstack
rabbit_password = RABBIT_PASS
[keystone_authtoken]
auth_uri = http://controller:5000
auth_url = http://controller:35357
auth_plugin = password
project_domain_id = default
user_domain_id = default
project_name = service
username = nova
password = NOVA_PASS
[glance]
host = controller
[oslo_concurrency]
lock_path = /var/lib/nova/tmp
[libvirt]
virt_type = kvm
MANAGEMENT_INTERFACE_IP_ADDRESS это адрес вычислительного узла из VLAN 10.
В novncproxy_base_url controller должен соответствовать тому адресу, через который будет возможность обратиться через Web-browser. Иначе вы не сможете воспользоваться vnc-консолью из Horizon.
Перезапускаем сервис и удаляем локальную копию БД:
# service nova-compute restart
# rm -f /var/lib/nova/nova.sqlite
Проверяем всё ли правильно работает:
# nova service-list
+----+------------------+------------+----------+---------+-------+----------------------------+-----------------+
| Id | Binary | Host | Zone | Status | State | Updated_at | Disabled Reason |
+----+------------------+------------+----------+---------+-------+----------------------------+-----------------+
| 1 | nova-conductor | controller | internal | enabled | up | 2014-09-16T23:54:02.000000 | - |
| 2 | nova-consoleauth | controller | internal | enabled | up | 2014-09-16T23:54:04.000000 | - |
| 3 | nova-scheduler | controller | internal | enabled | up | 2014-09-16T23:54:07.000000 | - |
| 4 | nova-cert | controller | internal | enabled | up | 2014-09-16T23:54:00.000000 | - |
| 5 | nova-compute | compute1 | nova | enabled | up | 2014-09-16T23:54:06.000000 | - |
+----+------------------+------------+----------+---------+-------+----------------------------+-----------------+
5ая строчка говорит о том, что мы всё правильно сделали.
Мы сделали самое главное — теперь у нас есть IaaS.
Neutron
Neutron это сервис предоставляющий сеть как услуга (NaaS). Вообще официальная документация немного другое определение даёт, но так думаю будет понятнее. Nova-networking объявлен как устаревший в новых версиях OpenStack, поэтому его мы использовать не будем. Да и функционал у neutron значительно шире.
Контроллер
Мы устанавливаем ядро сети на контроллере, хотя в мануале используется 3я нода. Если вычислительных нод будет достаточно много (>10) и/или сетевая нагрузка будет достаточно высокая, то лучше вынести Network-сервер на отдельную ноду.
Как всегда начнём с БД
# mysql -u root -p
CREATE DATABASE neutron;
GRANT ALL PRIVILEGES ON neutron.* TO 'neutron'@'localhost' IDENTIFIED BY 'NEUTRON_DBPASS';
GRANT ALL PRIVILEGES ON neutron.* TO 'neutron'@'%' IDENTIFIED BY 'NEUTRON_DBPASS';
Keystone:
# openstack user create --password-prompt neutron
# openstack role add --project service --user neutron admin
# openstack service create --name neutron --description "OpenStack Networking" network
# openstack endpoint create --publicurl http://controller:9696 --adminurl http://controller:9696 --internalurl http://controller:9696 --region RegionOne network
Устанавливаем необходимые компоненты:
# apt-get install neutron-server neutron-plugin-ml2 python-neutronclient neutron-plugin-openvswitch-agent neutron-l3-agent neutron-dhcp-agent neutron-metadata-agent
Так же необходимо подправить /etc/sysctl.conf
# cat /etc/sysctl.conf
net.ipv4.ip_forward=1
net.ipv4.conf.all.rp_filter=0
net.ipv4.conf.default.rp_filter=0
# sysctl -p
[DEFAULT]
...
rpc_backend = rabbit
auth_strategy = keystone
core_plugin = ml2
service_plugins = router
allow_overlapping_ips = True
notify_nova_on_port_status_changes = True
notify_nova_on_port_data_changes = True
nova_url = http://controller:8774/v2
[oslo_messaging_rabbit]
rabbit_host = controller
rabbit_userid = openstack
rabbit_password = RABBIT_PASS
[database]
connection = mysql://neutron:NEUTRON_DBPASS@controller/neutron
[keystone_authtoken]
auth_uri = http://controller:5000
auth_url = http://controller:35357
auth_plugin = password
project_domain_id = default
user_domain_id = default
project_name = service
username = neutron
password = NEUTRON_PASS
[nova]
auth_url = http://controller:35357
auth_plugin = password
project_domain_id = default
user_domain_id = default
region_name = RegionOne
project_name = service
username = nova
password = NOVA_PASS
Редактируя конфиг не следует ничего оттуда удалять, кроме закомментированных строк.
[ml2]
type_drivers = flat,vlan,gre,vxlan
tenant_network_types = gre
mechanism_drivers = openvswitch
[ml2_type_gre]
tunnel_id_ranges = 1000:2000
[ml2_type_flat]
flat_networks = external
[securitygroup]
enable_security_group = True
enable_ipset = True
firewall_driver = neutron.agent.linux.iptables_firewall.OVSHybridIptablesFirewallDriver
[ovs]
local_ip = 10.0.1.11 #INSTANCE_TUNNELS_INTERFACE_IP_ADDRESS
bridge_mappings = external:br-ex
[agent]
tunnel_types = gre
[DEFAULT]
interface_driver = neutron.agent.linux.interface.OVSInterfaceDriver
external_network_bridge =
router_delete_namespaces = True
[DEFAULT]
interface_driver = neutron.agent.linux.interface.OVSInterfaceDriver
dhcp_driver = neutron.agent.linux.dhcp.Dnsmasq
dhcp_delete_namespaces = True
dnsmasq_config_file = /etc/neutron/dnsmasq-neutron.conf
dhcp-option-force=26,1454
В официальной документации эта настройка использовалась для сетевых устройств без поддержки jumbo frames, но в целом там можно прописать практически любые настройки для dnsmasq.
Убиваем все процессы dnsmasq
# pkill dnsmasq
[DEFAULT]
auth_uri = http://controller:5000
auth_url = http://controller:35357
auth_region = RegionOne
auth_plugin = password
project_domain_id = default
user_domain_id = default
project_name = service
username = neutron
password = NEUTRON_PASS
nova_metadata_ip = controller
metadata_proxy_shared_secret = METADATA_SECRET
[DEFAULT]
...
network_api_class = nova.network.neutronv2.api.API
security_group_api = neutron
linuxnet_interface_driver = nova.network.linux_net.LinuxOVSInterfaceDriver
firewall_driver = nova.virt.firewall.NoopFirewallDriver
[neutron]
url = http://controller:9696
auth_strategy = keystone
admin_auth_url = http://controller:35357/v2.0
admin_tenant_name = service
admin_username = neutron
admin_password = NEUTRON_PASS
service_metadata_proxy = True
metadata_proxy_shared_secret = METADATA_SECRET
METADATA_SECRET это так же набор символов от 10 до 16 символов
Из nova.conf не удаляем ничего, только добавляем.
Синхронизируем БД и перезапускаем сервисы:
# su -s /bin/sh -c "neutron-db-manage --config-file /etc/neutron/neutron.conf --config-file /etc/neutron/plugins/ml2/ml2_conf.ini upgrade head" neutron
# service nova-api restart
# service neutron-server restart
# service openvswitch-switch restart
Создаём мост и связываем его с external-интерфейсом
# ovs-vsctl add-br br-ex
# ovs-vsctl add-port br-ex p3p1
Перезапускаем интерфейсы
# service neutron-plugin-openvswitch-agent restart
# service neutron-l3-agent restart
# service neutron-dhcp-agent restart
# service neutron-metadata-agent restart
Вычислительный узел
Без комментариев.
# cat /etc/sysctl.conf
net.ipv4.conf.all.rp_filter=0
net.ipv4.conf.default.rp_filter=0
net.bridge.bridge-nf-call-iptables=1
net.bridge.bridge-nf-call-ip6tables=1
# sysctl -p
# apt-get install neutron-plugin-ml2 neutron-plugin-openvswitch-agent
[DEFAULT]
...
rpc_backend = rabbit
auth_strategy = keystone
core_plugin = ml2
service_plugins = router
allow_overlapping_ips = True
[oslo_messaging_rabbit]
rabbit_host = controller
rabbit_userid = openstack
rabbit_password = RABBIT_PASS
[keystone_authtoken]
auth_uri = http://controller:5000
auth_url = http://controller:35357
auth_plugin = password
project_domain_id = default
user_domain_id = default
project_name = service
username = neutron
password = NEUTRON_PASS
[ml2]
type_drivers = flat,vlan,gre,vxlan
tenant_network_types = gre
mechanism_drivers = openvswitch
[ml2_type_gre]
tunnel_id_ranges = 1000:2000
[ml2_type_flat]
flat_networks = external
[securitygroup]
enable_security_group = True
enable_ipset = True
firewall_driver = neutron.agent.linux.iptables_firewall.OVSHybridIptablesFirewallDriver
[ovs]
local_ip = 10.0.1.31 #INSTANCE_TUNNELS_INTERFACE_IP_ADDRESS
bridge_mappings = external:br-ex
[agent]
tunnel_types = gre
Перезапускаем openvswitch
# service openvswitch-switch restart
Добавляем строчки в /etc/nova/nova.conf
[DEFAULT]
...
network_api_class = nova.network.neutronv2.api.API
security_group_api = neutron
linuxnet_interface_driver = nova.network.linux_net.LinuxOVSInterfaceDriver
firewall_driver = nova.virt.firewall.NoopFirewallDriver
[neutron]
url = http://controller:9696
auth_strategy = keystone
admin_auth_url = http://controller:35357/v2.0
admin_tenant_name = service
admin_username = neutron
admin_password = NEUTRON_PASS
Перезапускаем сервисы:
# service nova-compute restart
# service neutron-plugin-openvswitch-agent restart
Если я ничего не забыл упомянуть, то должно получиться так:
# neutron agent-list
+--------------------------------------+--------------------+----------+-------+----------------+---------------------------+
| id | agent_type | host | alive | admin_state_up | binary |
+--------------------------------------+--------------------+----------+-------+----------------+---------------------------+
| 30275801-e17a-41e4-8f53-9db63544f689 | Metadata agent | network | :-) | True | neutron-metadata-agent |
| 4bd8c50e-7bad-4f3b-955d-67658a491a15 | Open vSwitch agent | network | :-) | True | neutron-openvswitch-agent |
| 756e5bba-b70f-4715-b80e-e37f59803d20 | L3 agent | network | :-) | True | neutron-l3-agent |
| 9c45473c-6d6d-4f94-8df1-ebd0b6838d5f | DHCP agent | network | :-) | True | neutron-dhcp-agent |
| a5a49051-05eb-4b4f-bfc7-d36235fe9131 | Open vSwitch agent | compute1 | :-) | True | neutron-openvswitch-agent |
+--------------------------------------+--------------------+----------+-------+----------------+---------------------------+
Сети
Сейчас мы сделаем начальную заготовку наших сетей. Мы создадим одну внешнюю сеть и одну внутреннюю.
Создаём виртуальную сеть:
# neutron net-create ext-net --router:external --provider:physical_network external --provider:network_type flat
Настраиваем нашу внешнюю подсеть:
# neutron subnet-create ext-net 192.168.1.0/24 --name ext-subnet --allocation-pool start=192.168.1.100,end=192.168.1.200 --disable-dhcp --gateway 192.168.1.1
Наша внешняя сеть 192.168.1.0/24 и маршрутизатор выпускающий в интернет 192.168.1.1. Внешние адреса для нашего облака будут выдаваться из диапазона 192.168.1.101-200.
Далее мы будем создавать внутреннюю сеть для проекта demo, поэтому следует загрузить переменные для demo-юзера:
# source demo-openrc.sh
Теперь создаём виртуальную внутреннюю сеть:
# neutron net-create demo-net
# neutron subnet-create demo-net 172.16.1.0/24 --name demo-subnet --gateway 172.168.1.1
Понятно, что наша виртуальная сеть будет 172.16.1.0/24 и все инстансы из неё будут получать в качестве маршрутизатора 172.168.1.1.
Вопрос: что это за маршрутизатор?
Ответ: это виртуальный маршрутизатор.
«Фишка» в том, что в Neutron можно строить виртуальные сети с достаточно большим количеством подсетей, а значит для них необходим виртуальный маршрутизатор. Каждый виртуальный маршрутизатор можно добавлять порты в любую из доступных виртуальных и внешних сетей. И это действительно «сильно»! Мы назначаем маршрутизаторам только только доступ к сетям, а всеми правилами firewall мы управляем из групп безопасности. Более того! Мы можем создать виртуальную машину с программным маршрутизатором, настроить интерфейсы во все необходимые сети и управлять доступом через него (я пробовал использовать Mikrotik).
В общем, Neutron даёт простор фантазии.
Создаём виртуальный маршрутизатор, назначаем ему интерфейс в demo-subnet и присоединяем его к внешней сети:
# neutron router-create demo-router
# neutron router-interface-add demo-router demo-subnet
# neutron router-gateway-set demo-router ext-net
Теперь из внешней сети должен пинговаться наш виртуальный маршрутизатор:
# ping 192.168.1.100
PING 192.168.1.100 (192.168.1.100) 56(84) bytes of data.
64 bytes from 192.168.1.100: icmp_req=1 ttl=64 time=0.619 ms
64 bytes from 192.168.1.100: icmp_req=2 ttl=64 time=0.189 ms
64 bytes from 192.168.1.100: icmp_req=3 ttl=64 time=0.165 ms
64 bytes from 192.168.1.100: icmp_req=4 ttl=64 time=0.216 ms
...
В целом, у нас уже есть работоспособное облако с сетью.
Cinder (Блочное хранилище)
Cinder — сервис предоставляющий возможность управлять блочными устройствами (виртуальными дисками), присоединять их к виртуальным инстансам. Виртуальные диски могут быть и загрузочными. Это может быть очень удобно для переноса VM на другой вычислительный инстанс.
БД:
# mysql -u root -p
CREATE DATABASE cinder;
GRANT ALL PRIVILEGES ON cinder.* TO 'cinder'@'localhost' IDENTIFIED BY 'CINDER_DBPASS';
GRANT ALL PRIVILEGES ON cinder.* TO 'cinder'@'%' IDENTIFIED BY 'CINDER_DBPASS';
Keystone:
# openstack user create --password-prompt cinder
# openstack role add --project service --user cinder admin
# openstack service create --name cinder --description "OpenStack Block Storage" volume
# openstack service create --name cinderv2 --description "OpenStack Block Storage" volumev2
# openstack endpoint create --publicurl http://controller:8776/v2/%\(tenant_id\)s --internalurl http://controller:8776/v2/%\(tenant_id\)s --adminurl http://controller:8776/v2/%\(tenant_id\)s --region RegionOne volume
# openstack endpoint create --publicurl http://controller:8776/v2/%\(tenant_id\)s --internalurl http://controller:8776/v2/%\(tenant_id\)s --adminurl http://controller:8776/v2/%\(tenant_id\)s --region RegionOne volumev2
Установка необходимых пакетов:
# apt-get install cinder-api cinder-scheduler python-cinderclient
Поправим конфиг:
[DEFAULT]
...
rpc_backend = rabbit
auth_strategy = keystone
my_ip = 10.0.0.11
[oslo_messaging_rabbit]
rabbit_host = controller
rabbit_userid = openstack
rabbit_password = RABBIT_PASS
[database]
connection = mysql://cinder:CINDER_DBPASS@controller/cinder
[keystone_authtoken]
auth_uri = http://controller:5000
auth_url = http://controller:35357
auth_plugin = password
project_domain_id = default
user_domain_id = default
project_name = service
username = cinder
password = CINDER_PASS
[oslo_concurrency]
lock_path = /var/lock/cinder
Далее синхронизируем БД и перезапускаем сервисы:
# su -s /bin/sh -c "cinder-manage db sync" cinder
# service cinder-scheduler restart
# service cinder-api restart
Т.к. наш контроллер будет так же и хранилищем, то следующие действия так же проводим на нём.
Устанавливаем необходимые пакеты:
# apt-get install qemu lvm2
Помните я упоминал в конфигурации про два 500Гб диска? Мы из них сделаем RAID 1 (уж это описывать я не буду). Чисто технически, мы могли бы просто создать lvm-раздел из двух физических дисков, но такой вариант плох тем, что у нас не HA-проект и падение одного из дисков может быть критичным. Разбирать как создать RAID-массив я не буду, это легко гуглится. Будем считать, что наш рейд называется /dev/md1:
# pvcreate /dev/md1
# vgcreate cinder-volumes /dev/md1
Мы создали физическое LVM-устройство и создали lvm-группу cinder-volumes.
Далее правим /etc/lvm/lvm.conf.
Находим (или добавляем) туда такую строку:
devices {
...
filter = [ "a/md1/", "r/.*/"]
Будем считать, что кроме как на рейд-разделе у нас ничего связанного с lvm нет. Если рабочий раздел так же развёрнут на lvm, то следует его добавить. Например, если наша система развёрнута на /dev/md0 и поверх неё развёрнут lvm, то наш конфиг будет выглядеть так:
devices {
...
filter = [ "a/md0/", "a/md1/", "r/.*/"]
В целом, думаю для тех, кто сталкивался с lvm это не должно быть сложно.
Устанавливаем необходимые пакеты:
# apt-get install cinder-volume python-mysqldb
добавляем в конфиг:
[DEFAULT]
...
enabled_backends = lvm
glance_host = controller
[lvm]
volume_driver = cinder.volume.drivers.lvm.LVMVolumeDriver
volume_group = cinder-volumes
iscsi_protocol = iscsi
iscsi_helper = tgtadm
И перезапускаем сервисы:
# service tgt restart
# service cinder-scheduler restart
# service cinder-api restart
# service cinder-volume restart
Horizon (dashboard)
Horizon — дашбоард для OpenStack, написан на Python 2.7, движком является Django. Из него ведётся полное управление всей средой OpenStack: управление пользователями/проектами/ролями, управление образами, виртуальными дисками, инстансами, сетями и т.д.
Установка
# apt-get install openstack-dashboard
Установку можно производить на отдельном сервере с доступом к Controller-ноде, но мы установим на контроллере.
Поправим конфиг /etc/openstack-dashboard/local_settings.py:
...
OPENSTACK_HOST = "controller"
...
ALLOWED_HOSTS = '*'
...
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
'LOCATION': '127.0.0.1:11211',
}
}
...
OPENSTACK_KEYSTONE_DEFAULT_ROLE = "user"
...
TIME_ZONE = "Asia/Vladivostok"
...
TIME_ZONE — ваш часовой пояс может быть (и скорее всего будет) другой. Тут найдёте свой.
Перезапускаем Апач:
# service apache2 reload
Теперь можно заходить на controller/horizon. В предыдущей моей публикации можно посмотреть скрины дашборда. В ubuntu дополнительно устанавливается пакет openstack-dashboard-ubuntu-theme, который добавляет некоторые ссылки с намёком на Juju. Если захочется вернуть оригинальную версию, то можно просто удалить пакет.
Так же можно в профиле пользователя выбрать язык интерфейса Русский, то изрядно облегчит работу Developer`ам.
Готово!
Публикация получилась весьма громоздкая, но не хотелось разделять.
Надеюсь статья поможет кому-либо.
В следующей публикации (если мою карму не закидают «помидорами») буду описывать примитивную установку Chef-сервера и простого рецепта.
Комментарии (10)
legioner
14.07.2015 13:03Все это прекрасно, но в случае общего хранилища в SAN приходится его пилить и раздавать по частям — clvm+gfs2 под ubuntu неявно требуют cman, последняя версия которого была в 12.04
onegreyonewhite Автор
15.07.2015 04:42Я не совсем вас понял, причём здесь SAN-хранилище?
legioner
15.07.2015 07:54Простите, конкретно здесь не причем. Мне нужно было выговориться из-за угроханного в пустую месяца в попытках запустить openstack с общим SAN-хранилищем
onegreyonewhite Автор
15.07.2015 08:10Да вам не за что извиняться. Я просто так и не понял что конкретно вы имели в виду:
Вы полностью отказались от HDD на серверах с OpenStack
Вы хотели разместить виртуальные диски Cinder`а в хранилище SAN
Что-то ещё
?
Можете чуть подробнее рассказать?legioner
17.07.2015 07:07По плану конфигурация должна была получиться следующая:
1) диски серверов использовать только под систему
2) отказаться от Cinder/Ceph/etc.
3) вместо этого использовать общее хранилище SAN с clvm+gfs2, чтобы не терять драгоценное место на отказоустойчивости, пусть даже ценой «ручного» failover и миграции с одной compute node'ы на другую
но как у я уже сказал в первом комменте — все уперлось в отсутствие cman под ubuntu свежее 12.04onegreyonewhite Автор
17.07.2015 08:09А чем не устроил Cinder?
Я почему спрашиваю, потому что мне больше нравится использовать OpenStack «из коробки» (как впрочем и многие продукты).
А выбор Ubuntu в качестве примера был взят только потому, что:
Большинство «новичков» используют Ubuntu как дистрибутив для ознакомления с Linux, соответственно для них это будет немного ближе.
На CentOS установка RabbitMQ производится более чем в одну команду. А это может быть камнем преткновения для некоторых из пользователей. Не хотелось на этом акцентировать внимание.
Под рукой были образы только Ubuntu Server и CentOS 7 (который с GUI`ёвым установщиком). Собственно мышки под рукой не оказалось. Вот так вот просто это определило судьбу моего тестового стенда.legioner
17.07.2015 12:26Да, надо немного пояснить. Наличии были 6 серверов HP BL460c Gen8 одинаковой начинки и подключением к SAN. Выделять из этого небольшого количества storage-only ноды для Cinder/Ceph слишком расточительно, т.к требует минимум две ноды для отказоустойчивости и дополнительно выходной объем хранилища уменьшается в 2 раза. Последнее — лишнее, т.к. хранилище в SAN само обеспечивает отказоустойчивость.
Поэтому хотелось сделать универсальные compute ноды, а хранилище отдавать целиком каждой ноде — эдакий аналог VmWare-кластера, где ноды равноправны и vmfs поддерживает работу в кластере.onegreyonewhite Автор
19.07.2015 07:00Идея интересная. А на чём в итоге развернули? На RHEL/CentOS?
legioner
20.07.2015 07:49Ничего не вышло. clvm+gfs2 неявно требуют cman (cluster manager от RH), который последний раз был в 12.04. В итоге пришлось поставить отдельные kvm на машины и разрезать хранилище на 6 частей. Без HA, failover и централизованного управления.
Arahnid
Спасибо, интересно.
Буду ждать след. публикацию