Виртуальное приватное облако: работа с CoreOS и RancherOS

от автора

CoreOS

Недавно мы добавили в сервис «Виртуальное приватное облако» новый образ с операционной системой RancherOS и обновили образ CoreOS.

Эти операционные системы будут интересны пользователям, которым необходим инструмент для простого управления большим количеством приложений в контейнерах и использования различных систем кластеризации контейнеров — Kubernetes, Docker Swarm, Apache Mesos и других.

CoreOS и RancherOS отличаются от большинства популярных дистрибутивов Linux: они содержат лишь минимальный набор программного обеспечения для запуска приложений внутри контейнеров. В этих системах отсутствуют пакетные менеджеры и интерпретаторы различных языков программирования (Python, Ruby и других.).

Ниже мы рассмотрим специфику CoreOS и RancherOS, разберём особенности конфигурации сервисов etcd и fleet, а также приведём пример настройки кластера Docker Swarm на базе RancherOS.

CoreOS

Дистрибутив CoreOS разработан специально для быстрого и массового развертывания большого количества пользовательских приложений в изолированных контейнерах.

CoreOS содержит предустановленные инструменты для удобного управления множеством нод и контейнеров в кластере:

  • etcd — распределенное хранилище данных, которое используется нодами для получения информации о доступных сервисах в кластере, конфигурационным и временным файлам;
  • Docker — основная платформа для доставки и запуска приложений внутри контейнеров;
  • rkt — альтернатива Docker, разработанная создателями CoreOS;
  • fleet — распределенная система инициализации, позволяющая управлять множеством systemd-инстансов на отдельных нодах кластера и производить запуск необходимых сервисов на менее загруженных нодах.

Конфигурация

Основной метод изменения системных параметров ― это описание необходимых настроек при помощи декларативного языка YAML в конфигурационном файле cloud-config.yml. Этот файл используется утилитой Cloud-init для настройки системы.

Обратите внимание, что в CoreOS используется собственная реализация Cloud-init, конфигурационные файлы которой лишь частично совместимы с настройками для более распространенной версии Launchpad-cloud-init, используемой в большинстве обычных дистрибутивов для конфигурации системы в различных облачных сервисах, в том числе и в сервисе «Виртуальное приватное облако».

Приведем пример файла cloud-config.yml:

#cloud-config  # Set hostname hostname: "node01"  # Set ntp servers write_files:     - path: /etc/systemd/timesyncd.conf       content: |         [Time]         NTP=0.ru.pool.ntp.org 1.ru.pool.ntp.org  coreos:     units:     # Configure static network on eth0 interface     - name: iface-eth0.network       runtime: true       content: |         [Match]         Name=eth0          [Network]         DNS=188.93.16.19 	DNS=188.93.17.19 	DNS=109.234.159.91         Address=10.11.12.13/24         Gateway=10.11.12.1      # Change standard SSH port     - name: sshd.socket       command: restart       runtime: true       content: |         [Socket]         ListenStream=2345         FreeBind=true         Accept=yes 

При помощи заданных параметров утилита Cloud-init сменит хостнейм и стандартный порт 22 для сервиса SSH, настроит статическую сеть на интерфейсе eth0 и добавит ntp-серверы для синхронизации времени.

Подробнее о структуре конфигурационного файла cloud-config.yml можно прочитать в официальной документации.

При создании сервера из готового образа CoreOS в сервисе «Виртуальное приватное облако» вам не потребуется производить базовую настройку системы при помощи cloud-config.yml. Мы уже внесли необходимые изменения в образ, при помощи которых автоматически производится стандартная конфигурация сервера, в том числе настройка сетевых интерфейсов.

Доступ по SSH к серверу под управлением CoreOS изначально будет возможен только по ключу, указанному при создании сервера. Указанный ключ будет добавлен для пользователя core.

В дополнение к собственной версии cloud-init создатели CoreOS разработали утилиту Ignition. Этот инструмент дублирует возможности cloud-init и еще позволяет производить низкоуровневые настройки системы, — например, изменение таблиц разделов дисков и форматирование файловых систем. Это возможно благодаря тому, что Ignition начинает работать во время ранних этапов загрузки системы, в процессе запуска initramfs.

В Ignition для конфигурационных файлов используется формат JSON.

Ниже представлен пример файла, при помощи которого Ignition отформатирует корневой раздел в Btrfs, и настроит систему с параметрами, аналогичными примеру выше для Cloud-init:

{     "ignition": { "version": "2.0.0" },     "storage": {         "filesystems": [{             "mount": {                 "device": "/dev/disk/by-label/ROOT",                 "format": "btrfs",                 "create": {                     "force": true,                     "options": [ "--label=ROOT" ]                 }             }         }],         "files": [{             "filesystem": "root",             "path": "/etc/systemd/timesyncd.conf",             "mode": 420,             "contents": { "source": "data:,%5BTime%5D%0ANTP=0.ru.pool.ntp.org%201.ru.pool.ntp.org%0A" }             },             {             "filesystem": "root",             "path": "/etc/hostname",             "mode": 420,             "contents": { "source": "data:,node01" }             }         ]     },     "networkd": {         "units": [{             "name": "iface-eth0.network",             "contents": "[Match]\nName=eth0\n\n[Network]\nDNS=188.93.16.19\nDNS=188.93.17.19\nDNS=109.234.159.91\nAddress=10.11.12.13/24\nGateway=10.11.12.1"         }]     },     "systemd": {         "units": [{             "name": "sshd.socket",             "command": "restart",             "runtime": true,             "contents": "[Socket]\nListenStream=2345\nFreeBind=true\nAccept=yes"         }]     } } 

Подробнее о всех возможностях Ignition можно узнать в официальной документации.

Пример настройки кластера CoreOS

Для этого примера нам потребуется заранее создать три сервера под управлением CoreOS в панели управления VPC со следующими параметрами:

CoreOS

После создания серверов потребуется discovery-url для сервиса etcd. Для этого мы можем воспользоваться публичным бесплатным сервисом discovery.etcd.io. Запустим на хосте node00 следующую команду:

core@node00 ~ $ curl -w "\n" 'https://discovery.etcd.io/new?size=3' https://discovery.etcd.io/ec42cfef0450bd8a99090ee3d3294493 

Добавим полученный URL и дополнительные параметры etcd в файл /usr/share/oem/cloud-config.yml на каждом сервере:

coreos:     etcd2:         discovery: https://discovery.etcd.io/ec42cfef0450bd8a99090ee3d3294493         advertise-client-urls: http://192.168.0.10:2379,http://192.168.0.10:4001         initial-advertise-peer-urls: http://192.168.0.10:2380         listen-client-urls: http://0.0.0.0:2379,http://0.0.0.0:4001         listen-peer-urls: http://192.168.0.10:2380      units:         - name: etcd2.service           command: start          - name: fleet.service           command: start 

Параметры в разделе etcd2 обозначают URL-адреса в формате protocol://address:port, которые необходимы для анонсирования ноды и обмена данными с другими членами кластера.

Раздел units позволяет управлять юнитами systemd в системе; в нашем случае он запустит юниты etc2d.service и fleet.service.

Для серверов node01 и node02 вам будет необходимо добавить аналогичные изменения в cloud-config.yml, изменив ip-адрес с 192.168.0.10 на 192.168.0.11 для сервера node01, и на адрес 192.168.0.12 для сервера node02.

После добавления новых настроек запустим утилиту Cloud-init на всех трех серверах (либо можно просто перезапустить эти серверы):

core@node00 ~ $ sudo coreos-cloudinit --from-file /usr/share/oem/cloud-config.yml 

Также проверим статус сервиса etcd:

core@node00 ~ $ etcdctl cluster-health member 3aaf91fd1172594e is healthy: got healthy result from http://192.168.0.11:2379 member 8cf40790248e1dcd is healthy: got healthy result from http://192.168.0.12:2379 member 96b61f40c082cd0b is healthy: got healthy result from http://192.168.0.10:2379 cluster is healthy 

Проверим доступность распределенного хранилища, добавим новую директорию (в терминологии etcd — ключ) со значением на сервере node00:

core@node00 ~ $ etcdctl set /common/cluster-name selectel-test-cluster selectel-test-cluster 

Затем убедимся, что наш новый ключ со значением доступен с любой другой ноды кластера:

core@node01 ~ $ etcdctl get common/cluster-name selectel-test-cluster 

Отлично, etcd функционирует, и мы можем приступать к использованию сервиса fleet.

В нашем примере мы будем использовать fleet для запуска Nginx в изолированном контейнере Docker. Для начала создадим systemd-юнит /etc/systemd/system/nginx.service:

[Unit] Description=Nginx Test Service  [Service] EnvironmentFile=/etc/environment ExecStartPre=/usr/bin/docker pull nginx ExecStart=/usr/bin/docker run --rm --name nginx -p 80:80 nginx ExecStop=/usr/bin/docker kill nginx  [X-Fleet] Conflicts=nginx.service 

Параметр Conflicts в секции X-Fleet запрещает запускать два и более сервиса Nginx на одной ноде, что позволит «размазать» нагрузку на кластер и повысить доступность сервиса. Дополнительные параметры X-Fleet, которые можно использовать внутри юнитов systemd описаны в документации fleet.

Остальные секции в файле являются стандартными для systemd, вы можете ознакомиться с ними например в небольшой вводной инструкции от CoreOS.

Запустим новый юнит nginx.service в нашем кластере при помощи fleetctl:

core@node00 ~ $ fleetctl start /etc/systemd/system/nginx.service Unit nginx.service inactive Unit nginx.service launched on 1ad018e0.../192.168.0.11 

После этого мы можем увидеть наличие Nginx в списке юнитов на любой ноде кластера:

core@node02 ~ $ fleetctl list-units UNIT		    MACHINE				        ACTIVE	SUB nginx.service	1ad018e0.../192.168.0.11	active	running 

core@node02 ~ $ fleetctl list-unit-files UNIT		    HASH	DSTATE		STATE		TARGET nginx.service	 0c112c1	launched	launched	1ad018e0.../192.168.0.11 

Как мы видим, контейнер с Nginx запустился на сервере с ip-адресом 192.168.0.11, которому соответствует сервер node01.

Мы можем отключить или полностью удалить сервер node01, после чего fleet автоматически перенесет Nginx на другую доступную ноду.

Etcd сообщит о недоступности члена при проверке статуса кластера:

core@node00 ~ $ etcdctl cluster-health failed to check the health of member 3aaf91fd1172594e on http://192.168.0.11:2379: Get http://192.168.0.11:2379/health: dial tcp 192.168.0.11:2379: i/o timeout failed to check the health of member 3aaf91fd1172594e on http://192.168.0.11:4001: Get http://192.168.0.11:4001/health: dial tcp 192.168.0.11:4001: i/o timeout member 3aaf91fd1172594e is unreachable: [http://192.168.0.11:2379 http://192.168.0.11:4001] are all unreachable member 8cf40790248e1dcd is healthy: got healthy result from http://192.168.0.12:2379 member 96b61f40c082cd0b is healthy: got healthy result from http://192.168.0.10:2379 cluster is healthy 

Но как мы видим, статус сервиса Nginx в норме, он запустился на другой рабочей ноде:

core@node00 ~ $ fleetctl list-units UNIT		    MACHINE				        ACTIVE	SUB nginx.service	4a1ff11c.../192.168.0.10	active	running 

Мы разобрали элементарный пример конфигурации кластера etcd + Docker + fleet на базе CoreOS. В следующем разделе мы рассмотрим другой дистрибутив — RancherOS, который основан на CoreOS и также предназначен для активного использования контейнеров.

RancherOS

Дистрибутив RancherOS представляет собой форк CoreOS. Отличительная особенность этой системы заключается в том, что в контейнерах запускаются не только пользовательские приложения, но и все системные сервисы. Более того, в RancherOS Docker имеет PID = 1, поэтому запускается сразу после ядра системы.

Операционная система содержит два Docker-инстанса; один из них является системным, в нём запускаются контейнеры udev, acpid, syslog, ntp и другие базовые сервисы, необходимые для работы системы. Системный Docker-инстанс заменяет собой традиционные системы инициализации (systemd, Upstart, SysV), присутствующих в обычных дистрибутивах Linux.

Второй Docker-инстанс используется для запуска пользовательских приложений и представляет собой специальный контейнер, запущенный внутри системного Docker’а.

Такое разделение обеспечивает защиту системных контейнеров от некорректных действий пользователя.

RancherOS

Так как Docker-инстанс в RancherOS представляет собой обычное Docker-окружение, то мы можем использовать стандартный набор команд Docker для управления как пользовательскими так и системными контейнерами.

# проверка версии Docker [rancher@rancher-os ~]$ docker --version Docker version 1.12.1, build 23cf638 

# установка нового контейнера из Docker Hub [rancher@rancher-os ~]$ docker run -d nginx Unable to find image 'nginx:latest' locally latest: Pulling from library/nginx …  Status: Downloaded newer image for nginx:latest 

# просмотр списка запущенных контейнеров [rancher@rancher-os ~]$ docker ps CONTAINER ID        IMAGE               COMMAND                  CREATED              STATUS              PORTS               NAMES 2ec5126e8dd5        nginx               "nginx -g 'daemon off"   About a minute ago   Up About a minute   80/tcp, 443/tcp     sad_fermat 

Для доступа к системным контейнерам необходимо использовать команду system-docker вместе с утилитой sudo.

Просмотреть список запущенных базовых сервисов операционной системы можно с помощью команды:

[rancher@rancher-os ~]$ sudo system-docker ps CONTAINER ID        IMAGE                       COMMAND                  CREATED             STATUS              PORTS               NAMES a566d0c7cc4c        rancher/os-docker:1.12.1    "/usr/bin/user-docker"   8 minutes ago       Up 8 minutes                            docker 8697a04e90a4        rancher/os-console:v0.6.1   "/usr/bin/ros entrypo"   8 minutes ago       Up 8 minutes                            console c8c337282aaa        rancher/os-base:v0.6.1      "/usr/bin/ros entrypo"   8 minutes ago       Up 8 minutes                            network 1e55244fc99c        rancher/os-base:v0.6.1      "/usr/bin/ros entrypo"   8 minutes ago       Up 8 minutes                            ntp fd6a03fdb28f        rancher/os-udev:v0.6.1      "/usr/bin/ros entrypo"   8 minutes ago       Up 8 minutes                            udev 7e9e50c28651        rancher/os-acpid:v0.6.1     "/usr/bin/ros entrypo"   8 minutes ago       Up 8 minutes                            acpid 5fec48b060f2        rancher/os-syslog:v0.6.1    "/usr/bin/ros entrypo"   8 minutes ago       Up 8 minutes                            syslog 

Перезапуск системного контейнера осуществляется так:

[rancher@rancher-os ~]$ sudo system-docker restart ntp 

Конфигурация

Основным инструментом автоматической конфигурации системы является собственная имплементация cloud-init, который был разделен на две отдельные утилиты: cloud-init-execute и cloud-init-save. По аналогии с другими реализациями cloud-init, версия RancherOS использует декларативный язык YAML, однако cloud-config.yml для другого дистрибутива не будет совместим с RancherOS.

Все возможные директивы конфигурационного файла описаны в официальной документации docs.rancher.com/os.

Системные сервисы используют параметры, полученные из файлов, в описанной ниже последовательности (каждый последующий файл из указанного списка перезаписывает предыдущие параметры, если они совпадают):

  • /usr/share/ros/os-config.yml — настройки системы по умолчанию;
  • /usr/share/ros/oem/oem-config.yml — в нашем случае это файл, позволяющий производить автоматическую конфигурацию статических настроек сети, в соответствии с параметрами из панели управления VPC;
  • YAML-файлы в директории /var/lib/rancher/conf/cloud-config.d/;
  • /var/lib/rancher/conf/cloud-config.yml — файл, хранящий значения, установленные утилитой ros, о которой мы расскажем далее;
  • параметры ядра, начинающиеся с ключевого слова «rancher»;
  • /var/lib/rancher/conf/metadata — метаданные из используемого облачного сервиса, добавленные утилитой cloud-init-save.

Вы можете изменять конфигурацию системы при при помощи утилиты ros, после чего новые параметры будут отображаться в файле /var/lib/rancher/conf/cloud-config.yml:

[rancher@rancher-os ~]$ sudo ros config set rancher.network.dns.nameservers "['188.93.16.19','188.93.17.19', '109.234.159.91']" 

[rancher@rancher-os ~]$ sudo cat /var/lib/rancher/conf/cloud-config.yml rancher:     network:         dns:             nameservers:               - 188.93.16.19               - 188.93.17.19               - 109.234.159.91 

Помимо изменения конфигурации системных сервисов утилита ros также используется для управления версиями операционной системы, версиями Docker, настройкой TLS и SELinux.

При использовании готового образа RancherOS в сервисе «Виртуальное приватное облако» вам нет необходимости настраивать базовые параметры системы (конфигурацию сетевых интерфейсов и т.п.)

После установки сервер будет доступен по выбранному вами IP-адресу в панели управления VPC. Вы сможете подключиться к серверу, используя протокол SSH, однако аутентификация изначально будет возможна только по ключу, указанному при создании сервера. Этот ключ будет добавлен для пользователя rancher.

Управление версиями

Чтобы узнать текущую версию операционной системы, используйте команду:

[rancher@rancher-os ~]$ sudo ros os version v0.6.1 

А для проверки всех доступных релизов:

[rancher@rancher-os ~]$ sudo ros os list rancher/os:v0.4.0 remote rancher/os:v0.4.1 remote rancher/os:v0.4.2 remote rancher/os:v0.4.3 remote rancher/os:v0.4.4 remote rancher/os:v0.4.5 remote rancher/os:v0.5.0 remote rancher/os:v0.6.0 remote rancher/os:v0.6.1 remote 

Вы можете установить последнюю стабильную версию системы при помощи команды sudo ros os upgrade, либо выбрать требуемую версию, указав параметр -i:

[rancher@rancher-os ~]$ sudo ros os upgrade -i rancher/os:v0.5.0 

Так как указанная нами версия 0.5.0 старше, чем установленная 0.6.1, то вместо обновления системы произойдет даунгрейд

Управлять версией Docker не менее просто. Приведём несколько примеров:

#просмотр доступных версий [rancher@rancher-os ~]$ sudo ros engine list disabled docker-1.10.3 disabled docker-1.11.2 current  docker-1.12.1 

#установка версии 1.11.2 [rancher@rancher-os ~]$ sudo ros engine switch docker-1.11.2 INFO[0000] Project [os]: Starting project INFO[0000] [0/19] [docker]: Starting … INFO[0010] Recreating docker INFO[0010] [1/19] [docker]: Started 

Кластер Docker Swarm на RancherOS

В Docker 1.12 появились интегрированные инструменты для управления кластером контейнеров Docker Swarm, благодаря чему настроить готовый кластер стало гораздо проще.

В нашем примере мы будем использовать готовый образ RancherOS в сервисе «Виртуальное приватное облако». В нём используется Docker версии 1.12.1.

Нам понадобится создать три сервера со следующими параметрами:

pr-3225-02

Для начала нам необходимо инициализировать создание кластера Docker Swarm, для этого на ноде manager0 выполним следующую команду:

[rancher@manager0 ~]$ docker swarm init --advertise-addr 192.168.0.100 Swarm initialized: current node (8gf95qb6l61v5s6561qx5vfy6) is now a manager.  To add a worker to this swarm, run the following command:      docker swarm join \         --token SWMTKN-1-0hlhela57gsvxzoaqol70n2b9wos6qlu3ukriry3pcxyb9j2k6-0n1if4hkvdvmrpbb7f3clx1yg \         192.168.0.100:2377  To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.

Как вы можете заметить из появившейся подсказки, на нодах worker0 и worker1 вам необходимо выполнить команду:

docker swarm join \     --token SWMTKN-1-0hlhela57gsvxzoaqol70n2b9wos6qlu3ukriry3pcxyb9j2k6-0n1if4hkvdvmrpbb7f3clx1yg \     192.168.0.100:2377 

Проверим статус нод кластера, для этого на manager0 запустим команду:

[rancher@manager0 ~]$ docker node ls ID                           HOSTNAME  STATUS  AVAILABILITY  MANAGER STATUS 366euocei01dw3ay66uwzb3pv    worker0   Ready   Active 67pt4fo5gi13cxkphtfzfbfbo    worker1   Ready   Active 8gf95qb6l61v5s6561qx5vfy6 *  manager0  Ready   Active        Leader 

Docker Swarm готов к использованию!

По умолчанию новые сервисы будут запускаться на всех нодах кластера. Подкорректируем данные настройки таким образом, чтобы все сервисы запускались на нодах worker0 и worker1, а нода manager0 выполняла только управляющую роль.

Для внесения этих параметров изменим «доступность» ноды manager0:

[rancher@manager0 ~]$ docker node update --availability drain manager0 

Запустим сервис с контейнером Nginx:

[rancher@manager0 ~]$ docker service create --name webserver --replicas 1 --publish 80:80 nginx 

В ответ мы получим идентификатор сервиса:

av1qvj32mz8vwkwihf0lauiz8 

Изначально количество реплик будет равно 0, а единственная задача, относящаяся к этому сервису, будет находится в статусе «Preparing»:

[rancher@manager0 ~]$ docker service ls ID            NAME       REPLICAS  IMAGE  COMMAND av1qvj32mz8v  webserver  0/1       nginx 

[rancher@manager0 ~]$ docker service ps webserver ID                         NAME         IMAGE  NODE     DESIRED STATE  CURRENT STATE                 ERROR cjxkza3qzx5m73bgbls0r26m6  webserver.1  nginx  worker1  Running        Preparing about a minute ago 

Через несколько секунд необходимый образ Nginx будет автоматически скачан из Docker Hub, после чего статус сервиса изменится на «Running»:

[rancher@manager0 ~]$ docker service ls ID            NAME       REPLICAS  IMAGE  COMMAND av1qvj32mz8v  webserver  1/1       nginx 

[rancher@manager0 ~]$ docker service ps webserver ID                         NAME         IMAGE  NODE     DESIRED STATE  CURRENT STATE          ERROR cjxkza3qzx5m73bgbls0r26m6  webserver.1  nginx  worker1  Running        Running 8 minutes ago 

Как мы видим, сервис запустился на ноде worker1 (значение в столбце «NODE»). Отключим эту ноду через панель управления VPC и снова проверим статус сервиса webserver:

[rancher@manager0 ~]$ docker service ps webserver ID                         NAME             IMAGE  NODE     DESIRED STATE  CURRENT STATE             ERROR 5lwf4z54p74qtoopuilshw204  webserver.1      nginx  worker0  Running        Preparing 32 seconds ago cjxkza3qzx5m73bgbls0r26m6   \_ webserver.1  nginx  worker1  Shutdown       Running 16 minutes ago 

Статус сервиса изменился на «Preparing», Docker Swarm пытается перенести сервис на другую рабочую ноду worker0, задержка связана с тем, что перед запуском на ноду worker0 должен быть добавлен образ Nginx из Docker Hub.

После автоматического добавления образа сервис webserver успешно запустится на ноде worker0:

[rancher@manager0 ~]$ docker service ps webserver ID                         NAME             IMAGE  NODE     DESIRED STATE  CURRENT STATE               ERROR 5lwf4z54p74qtoopuilshw204  webserver.1      nginx  worker0  Running        Running about a minute ago cjxkza3qzx5m73bgbls0r26m6   \_ webserver.1  nginx  worker1  Shutdown       Running 19 minutes ago 

Чтобы избежать простоя при переносе сервиса с упавшей ноды, мы можем увеличить количество реплик этого сервиса.

Выполним команду (не забудьте включить ноду worker1 обратно):

[rancher@manager0 ~]$ docker service update --replicas 2 webserver 

Сервис начнет реплицироваться на вторую ноду worker1:

[rancher@manager0 ~]$ docker service ps webserver ID                         NAME             IMAGE  NODE     DESIRED STATE  CURRENT STATE            ERROR 5lwf4z54p74qtoopuilshw204  webserver.1      nginx  worker0  Running        Running 11 minutes ago cjxkza3qzx5m73bgbls0r26m6   \_ webserver.1  nginx  worker1  Shutdown       Complete 6 minutes ago f3o7icke69zw83ag92ywol0dr  webserver.2      nginx  worker1  Running        Preparing 2 seconds ago 

Заключение

В этой статье мы проделали обзор дистрибутивов Linux, предназначенных для быстрого развертывания и удобного управления кластером из изолированных контейнеров.

Будем рады, если вы поделитесь собственным опытом использования CoreOS, RancherOS и подобных им операционных систем.

ссылка на оригинал статьи https://habrahabr.ru/post/315930/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *