«Всю разработку — в контейнеры» — с этой фразы началось мое увлекательное путешествие в мир Docker. Попытки угодить требованиям разработчиков привели к выбору OpenShift Origin. Однако, завести полноценный кластер, как оказалось, задача нетривиальная. Во время постройки контейнерной инфраструктуры я пытался найти что-нибудь по теме, в том числе на Хабре, и не находил, как это ни странно. Поэтому ниже я попробую описать весь базовый процесс установки и постараюсь уберечь вас от граблей, по которым фактически гулял.
Приступим:
Все инфраструктурные объекты представляют собой набор выделенных ВМ с разным набором ресурсов. Минимальные аппаратные требования изложены здесь. Подразумевается, что между ВМ траффик ходит свободно и без ограничений. Если это не так, то здесь можно посмотреть какие порты должны быть открыты.
На момент установки этого кластера я использовал:
Итак, предположим, что у нас есть домен вида habra.cloud, которым мы активно пользуемся для наших инфраструктурных нужд.
Добавим записи типа «А» для всех хостов нашего кластера и выделим поддомен apps.habra.cloud для будущих сервисов в нашем облаке.
После добавления получим картину вида:
Для зоны apps.habra.cloud вывод будет следующим:
Мы настроили DNS — нужно сконфигурировать сетевые адаптеры и имена NFS-сервера и ноды кластера.
Надолго останавливаться на этом не будем, т.к. информации по этому поводу вагон и маленькая тележка. Заострю внимание лишь на нескольких моментах:
С хостами и сетью разобрались. Следующим этапом установим docker на все ноды кластера и настроим docker-storage.
В файл /etc/sysconfig/docker в раздел OPTIONS добавим:
Далее, в соответствии с этим мануалом создадим docker-storage.
Я рекомендую воспользоваться опцией «B», чтобы можно было им управлять с помощью нативного LVM. Также, необходимо учесть, что именно в этот storage OpenShift будет копировать docker-образы из любых docker registry. При этом, OpenShift не удаляет старые и незадействованные docker-образы. Поэтому, я рекомендую делать docker-storage объемом не менее 30-50ГБ на каждой ноде. Остальное — в зависимости от ваших потребностей.
Как это сделал я:
Хорошо, docker установлен и работоспособен. Настроим SELinux как того требует OpenShift.
Идем дальше, к NFS-серверу. Так как клиентов мы уже установили и даже настроили специально для этого SELinux, остался пустяк — подготовить NFS-сервер.
В данной статье, дабы она не разрослась до огромных размеров, предполагается, что NFS-сервер у вас уже вовсю работает. Если это не так, то вот неплохая статья на эту тему.
Добавлю, что мой NFS-сервер смотрит на каталог /nfs/ и я буду отталкиваться от этого.
Отлично, теперь мы сможем подключиться клиентом к этому каталогу.
В случае, если Ansible у вас уже где-то установлен, как у меня, следует выполнять действия именно на нем. В случае, если вы хотите использовать для этого Master, то тоже самое нужно будет выполнить и для него.
Итак, первое — Ansible должен знать наши ВМ по hostname. Значит, либо правим /etc/hosts, либо, что гораздо правильнее, натравливаем нашу ВМ на наш DNS-сервер любым доступным нам способом (в случае использования Master это делать не нужно, так как уже все готово).
Теперь необходимо растиражировать наш публичный SSH-ключ на ноды кластера, чтобы Ansible мог без проблем подключаться к ним.
При этом у меня уже были готовы пары ключей. Если это не так, то следует воспользоваться утилитой ssh-keygen и создать собственную пару.
Пришло время для самого главного — правки inventory файла для Ansible с нужными параметрами.
Подробно про переменные OpenShift в Ansible можно почитать тут
Осталась самая малость — качаем свежий архив с необходимыми ролями OpenShift для Ansible (нужен установленный git-client):
Важное замечание. Если вы, как и я, деплоитесь на ВМ — я бы рекомендовал пользоваться снапшотами. Если что-то пойдет не так, то при установке будет гораздо проще изменить что-то в первоначальном варианте настроек, чем проходить через долгий и нудный дэбаг.
Приступим к лакомке — установим наконец-то OpenShift Origin на наши ноды. Следующая команда подразумевает, что вы находитесь в том же каталоге, где и ваш inventory-файл.
Примечание: на текущий момент, последняя версия OpenShift Origin (1.4) playbook для Ansible корректно работает с Ansible версии 2.2.0.0. При обновлении до версии 1.4 мне пришлось откатить Ansible чтобы все встало корректно.
Установка длится около 20 минут. По результатам не должно быть фэйлов.
На Master`е запросим статус нод и получим вывод:
Если картина такая, откроем браузер и пройдем по URL: https://master.habra.cloud:8443/console
Уже можно логиниться под любым пользователем.
Однако, радость будет не полной.
Для полного счастья нам нужно выполнить еще несколько действий. Во-первых продеплоить router и private docker-registry. Во-вторых, модифицировать docker-registry таким образом, чтобы он располагался на нашем NFS-сервере.
Инсталлятор по-умолчанию создает задания на деплой router и registry в namespace default. Но при этом, деплой произойдет только в том случае, если статус Master`а будет Schedulable.
Это означает, что роутер уже готов. И наши будущие сервисы уже смогут отвечать на их DNS-имена. Так как мы уже создали необходимые каталоги на NFS-сервере, осталось указать на них OpenShift`у.
Почти готово, немного докрутим DNS на Master`e.
Готово! Кластер работает.
В конце хотелось бы сказать, что это только начало большого пути. В процессе эксплуатации всплывает очень много нестыковок и недоработок. Не все контейнеры и даже не все сервисы из шаблонов будут работать. Под большинство задач, с которыми я сталкивался мне приходилось либо дорабатывать шаблоны грубым напильником, либо создавать свои. Но все же, насколько приятнее оперировать готовыми сервисами!
Спасибо за внимание.
Комментарии и дополнения приветствуются.
Приступим:
Подготовка окружения
Все инфраструктурные объекты представляют собой набор выделенных ВМ с разным набором ресурсов. Минимальные аппаратные требования изложены здесь. Подразумевается, что между ВМ траффик ходит свободно и без ограничений. Если это не так, то здесь можно посмотреть какие порты должны быть открыты.
На момент установки этого кластера я использовал:
- Три полноценных ВМ для самого кластера (CentOS 7.2);
- Одна ВМ с каталогом пользователей и DNS-сервером (Windows Server 2012);
- Одна ВМ с NFS-сервером для централизованного хранения данных (CentOS 7.2);
- ВМ с Ansible на борту.
Итак, предположим, что у нас есть домен вида habra.cloud, которым мы активно пользуемся для наших инфраструктурных нужд.
Добавим записи типа «А» для всех хостов нашего кластера и выделим поддомен apps.habra.cloud для будущих сервисов в нашем облаке.
После добавления получим картину вида:
Name Type Data apps
(same as parent folder) Start of Authority (SOA) [16], dc-infra.habra.cloud,
(same as parent folder) Name Server (NS) 172.28.246.50.
ansible Host (A) 172.28.247.200
master Host (A) 172.28.247.211
nfs Host (A) 172.28.247.51
node01 Host (A) 172.28.247.212
node02 Host (A) 172.28.247.213
Для зоны apps.habra.cloud вывод будет следующим:
Name Type Data Timestamp
* Host (A) 172.28.247.211 static
Мы настроили DNS — нужно сконфигурировать сетевые адаптеры и имена NFS-сервера и ноды кластера.
Надолго останавливаться на этом не будем, т.к. информации по этому поводу вагон и маленькая тележка. Заострю внимание лишь на нескольких моментах:
- Во-первых, все настройки следует выполнять через NetworkManager, т.к. иначе Ansible проигнорирует ваши настройки DNS и специфичных маршрутов, если они есть.
- Во-вторых, нужно обязательно указать ваш DNS-сервер в качестве primary DNS server, при этом ваши хосты должны отвечать на полные DNS-имена, указанные на DNS-сервере. Например, для мастер-ноды OpenShift вывод должен быть таким:
root@master# hostname
master.habra.cloud
- В-третьих — в качестве search-доменов вы должны указать еще несколько, чтобы не было проблем с разрешением имен между подами и контейнерами. Для понимания, приведу часть моего файла /etc/resolv.conf:
root@OpenShiftCluster# cat /etc/resolv.conf
# Generated by NetworkManager
search habra.cloud default.svc.cluster.local svc.cluster.local cloud.local default.svc svc local
nameserver 172.28.246.50
С хостами и сетью разобрались. Следующим этапом установим docker на все ноды кластера и настроим docker-storage.
root@OpenShiftCluster# yum -y install docker
В файл /etc/sysconfig/docker в раздел OPTIONS добавим:
OPTIONS='--selinux-enabled --insecure-registry 172.30.0.0/16'
Далее, в соответствии с этим мануалом создадим docker-storage.
Я рекомендую воспользоваться опцией «B», чтобы можно было им управлять с помощью нативного LVM. Также, необходимо учесть, что именно в этот storage OpenShift будет копировать docker-образы из любых docker registry. При этом, OpenShift не удаляет старые и незадействованные docker-образы. Поэтому, я рекомендую делать docker-storage объемом не менее 30-50ГБ на каждой ноде. Остальное — в зависимости от ваших потребностей.
Как это сделал я:
- Разметим fdisk`ом /dev/sdb под формат LVM, затем создадим PV и VG:
root@OpenShiftCluster# fdisk /dev/sdb
n
t
8e
w
root@OpenShiftCluster# pvcreate /dev/sdb1
root@OpenShiftCluster# vgcreate docker-vg /dev/sdb1
- Поправим /etc/sysconfig/docker-storage-setup. Листинг /etc/sysconfig/docker-storage-setup прилагается:
# Edit this file to override any configuration options specified in
# /usr/lib/docker-storage-setup/docker-storage-setup.
#
# For more details refer to "man docker-storage-setup"
VG=docker-vg
- Запустим процедуру создания docker-storage:
root@OpenShiftCluster# docker-storage-setup
- Выполним рекомендации из мануала после создания docker-storage:
root@OpenShiftCluster# systemctl is-active docker
- Если docker еще не был запущен на хосте:
root@OpenShiftCluster# systemctl enable docker
root@OpenShiftCluster# systemctl start docker
- Если Docker уже запущен (процедура уничтожит все контейнеры и образы):
root@OpenShiftCluster# systemctl stop docker
root@OpenShiftCluster# rm -rf /var/lib/docker/*
root@OpenShiftCluster# systemctl restart docker
Хорошо, docker установлен и работоспособен. Настроим SELinux как того требует OpenShift.
- Сначала выставим параметр SELINUXTYPE=targeted в файле
/etc/selinux/config:
# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
# enforcing - SELinux security policy is enforced.
# permissive - SELinux prints warnings instead of enforcing.
# disabled - No SELinux policy is loaded.
SELINUX=enforcing
# SELINUXTYPE= can take one of these three values:
# targeted - Targeted processes are protected,
# minimum - Modification of targeted policy. Only selected processes are protected.
# mls - Multi Level Security protection.
SELINUXTYPE=targeted
- И, так как подразумевается работа с NFS, выполним пару команд:
root@OpenShiftCluster# setsebool -P virt_use_nfs 1
root@OpenShiftCluster# setsebool -P virt_sandbox_use_nfs 1
- Доустановим оставшиеся необходимые
компоненты:
root@OpenShiftCluster# yum install -y wget git net-tools bind-utils iptables-services bridge-utils bash-completion nfs-utils nfs-utils-lib
root@OpenShiftCluster# yum update
root@OpenShiftCluster# yum -y install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
root@OpenShiftCluster# sed -i -e "s/^enabled=1/enabled=0/" /etc/yum.repos.d/epel.repo
root@OpenShiftCluster# yum -y --enablerepo=epel install pyOpenSSL
- В моем случае Ansible установлен на отдельном сервере, но если вы хотите, можно его использовать на Master, в таком случае, последняя команда будет выглядеть так:
root@master# yum -y --enablerepo=epel install ansible pyOpenSSL
Идем дальше, к NFS-серверу. Так как клиентов мы уже установили и даже настроили специально для этого SELinux, остался пустяк — подготовить NFS-сервер.
В данной статье, дабы она не разрослась до огромных размеров, предполагается, что NFS-сервер у вас уже вовсю работает. Если это не так, то вот неплохая статья на эту тему.
Добавлю, что мой NFS-сервер смотрит на каталог /nfs/ и я буду отталкиваться от этого.
- Приготовим папки на NFS сервере для будущего private docker registry:
root@nfs# mkdir -R /nfs/infrastructure/registry
root@nfs# chmod 755 /nfs/infrastructure
root@nfs# chmod 755 /nfs/infrastructure/registry
root@nfs# chown nfsnobody:nfsnobody /nfs/infrastructure
root@nfs# chown nfsnobody:nfsnobody /nfs/infrastructure/registry
- Модифицируем файл /etc/exports — добавляем туда:
/nfs/infrastructure/registry *(rw,sync,root_squash,no_subtree_check,no_wdelay)
- выполняем:
root@nfs# exportfs -a
Отлично, теперь мы сможем подключиться клиентом к этому каталогу.
Готовим Ansible и его inventory.
В случае, если Ansible у вас уже где-то установлен, как у меня, следует выполнять действия именно на нем. В случае, если вы хотите использовать для этого Master, то тоже самое нужно будет выполнить и для него.
Итак, первое — Ansible должен знать наши ВМ по hostname. Значит, либо правим /etc/hosts, либо, что гораздо правильнее, натравливаем нашу ВМ на наш DNS-сервер любым доступным нам способом (в случае использования Master это делать не нужно, так как уже все готово).
Теперь необходимо растиражировать наш публичный SSH-ключ на ноды кластера, чтобы Ansible мог без проблем подключаться к ним.
root@ansible# for host in master.habra.cloud node01.habra.cloud node02.habra.cloud; do ssh-copy-id -i ~/.ssh/id_rsa.pub $host; done
При этом у меня уже были готовы пары ключей. Если это не так, то следует воспользоваться утилитой ssh-keygen и создать собственную пару.
Пришло время для самого главного — правки inventory файла для Ansible с нужными параметрами.
Мой файл Inventory:
root@ansible# cat inventory
[OSEv3:children]
masters
nodes
[masters]
master.habra.cloud
[nodes]
master.habra.cloud openshift_schedulable=false openshift_node_labels="{'region': 'infra', 'zone': 'default'}"
node01.habra.cloud openshift_node_labels="{'region': 'primary', 'zone': 'firstzone'}"
node02.habra.cloud openshift_node_labels="{'region': 'primary', 'zone': 'secondzone'}"
[OSEv3:vars]
ansible_ssh_user=root
openshift_master_default_subdomain=apps.habra.cloud
containerized=false
deployment_type=origin
Подробно про переменные OpenShift в Ansible можно почитать тут
Осталась самая малость — качаем свежий архив с необходимыми ролями OpenShift для Ansible (нужен установленный git-client):
root@ansible# git clone https://github.com/openshift/openshift-ansible
Важное замечание. Если вы, как и я, деплоитесь на ВМ — я бы рекомендовал пользоваться снапшотами. Если что-то пойдет не так, то при установке будет гораздо проще изменить что-то в первоначальном варианте настроек, чем проходить через долгий и нудный дэбаг.
Приступим к лакомке — установим наконец-то OpenShift Origin на наши ноды. Следующая команда подразумевает, что вы находитесь в том же каталоге, где и ваш inventory-файл.
Примечание: на текущий момент, последняя версия OpenShift Origin (1.4) playbook для Ansible корректно работает с Ansible версии 2.2.0.0. При обновлении до версии 1.4 мне пришлось откатить Ansible чтобы все встало корректно.
root@ansible# ansible-playbook -i ./inventory openshift-ansible/playbooks/byo/config.yml
Установка длится около 20 минут. По результатам не должно быть фэйлов.
Первичная настройка
На Master`е запросим статус нод и получим вывод:
root@master# oc get nodes
NAME STATUS AGE
master.habra.cloud Ready,SchedulingDisabled 1d
node01.habra.cloud Ready 1d
node02.habra.cloud Ready 1d
Если картина такая, откроем браузер и пройдем по URL: https://master.habra.cloud:8443/console
Уже можно логиниться под любым пользователем.
Однако, радость будет не полной.
Для полного счастья нам нужно выполнить еще несколько действий. Во-первых продеплоить router и private docker-registry. Во-вторых, модифицировать docker-registry таким образом, чтобы он располагался на нашем NFS-сервере.
- Поехали — деплоим router и private docker-registry:
root@master# oadm manage-node master.habra.cloud --schedulable=true
root@master# oc get nodes
NAME STATUS AGE
master.habra.cloud Ready 1d
node1.habra.cloud Ready 1d
node2.habra.cloud Ready 1d
Инсталлятор по-умолчанию создает задания на деплой router и registry в namespace default. Но при этом, деплой произойдет только в том случае, если статус Master`а будет Schedulable.
Проверим как идет деплой:
root@master# oc project default
root@master# oc get all
NAME REVISION DESIRED CURRENT TRIGGERED BY
dc/docker-registry 4 1 1 config
dc/router 3 1 1 config
NAME DESIRED CURRENT READY AGE
rc/docker-registry-1 0 0 0 1d
rc/router-1 1 1 1 1d
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
svc/docker-registry 172.30.7.135 <none> 5000/TCP 1d
svc/kubernetes 172.30.0.1 <none> 443/TCP,53/UDP,53/TCP 1d
svc/router 172.30.79.17 <none> 80/TCP,443/TCP,1936/TCP 1d
NAME READY STATUS RESTARTS AGE
po/docker-registry-1-ayuuo 1/1 Running 11 1d
po/router-1-lzewh 1/1 Running 8 1d
Это означает, что роутер уже готов. И наши будущие сервисы уже смогут отвечать на их DNS-имена. Так как мы уже создали необходимые каталоги на NFS-сервере, осталось указать на них OpenShift`у.
- На Master`е создадим файл nfs-pv.yaml со следующим содержимым:
nfs-pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: registrypv
spec:
capacity:
storage: 20Gi
accessModes:
- ReadWriteOnce
nfs:
path: /nfs/infrastructure/registry
server: nfs.habra.cloud
persistentVolumeReclaimPolicy: Recycle
- Создадим еще один файл nfs-claim1.yaml:
nfs-claim1.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: registry-claim1
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 20Gi
- Теперь создадим PV:
root@master# oc create -f nfs-pv.yaml
- и проверим результат:
root@master# oc get pv
NAME CAPACITY ACCESSMODES RECLAIMPOLICY STATUS ...
registrypv 20Gi RWO Recycle Available
- Также поступим с pvc:
Persistent Volume Claim
root@master# oc create -f nfs-claim1.yaml
root@master# oc get pvc
NAME STATUS VOLUME CAPACITY ACCESSMODES AGE
registry-claim1 Bound registrypv 20Gi RWO 1d
- Модифицируем наш deploymentconfig для docker-registry, чтобы он смотрел на наш nfs-claim1:
root@master# oc volume deploymentconfigs/docker-registry --add --name=registry-storage -t pvc --claim-name=registry-claim1 --overwrite
- Убеждаемся, что редеплой прошел:
root@master# oc get pods
NAME READY STATUS RESTARTS AGE
docker-registry-2-sdfhk 1/1 Running 1 1d
Почти готово, немного докрутим DNS на Master`e.
- Добавляем следующие строки в
/etc/dnsmasq.conf:
# Reverse DNS record for master
host-record=master.habra.cloud,172.28.247.211
# Wildcard DNS for OpenShift Applications - Points to Router
server=/habra.cloud/172.28.246.50
address=/apps.habra.cloud/172.28.247.211
server=/apps.habra.cloud/172.28.246.50
# Forward .local queries to SkyDNS
server=/local/127.0.0.1#8053
# Forward reverse queries for service network to SkyDNS.
# This is for default OpenShift SDN - change as needed.
server=/17.30.172.in-addr.arpa/127.0.0.1#8053
# Forward .habra.cloud queries to DC
server=/habra.cloud/172.28.246.50#53
- Правим /etc/origin/master/master-config.yaml в разделе dnsConfig должно стать так:
dnsConfig:
bindAddress: 0.0.0.0:8053
- Рестартим dnsmasq и master-node:
root@master# service dnsmasq restart
root@master# service origin-master restart
Готово! Кластер работает.
Заключение
В конце хотелось бы сказать, что это только начало большого пути. В процессе эксплуатации всплывает очень много нестыковок и недоработок. Не все контейнеры и даже не все сервисы из шаблонов будут работать. Под большинство задач, с которыми я сталкивался мне приходилось либо дорабатывать шаблоны грубым напильником, либо создавать свои. Но все же, насколько приятнее оперировать готовыми сервисами!
Спасибо за внимание.
Литература и иточники
Комментарии и дополнения приветствуются.
Поделиться с друзьями
Комментарии (8)
biziwalker
18.03.2017 08:01Самое интересное в очень голодном openshift на ресурсы со временем работы. Такое ощущение что там повсюду memory leak.
servarius
18.03.2017 12:07У меня пока там не очень много приложений крутится. Не замечал. Но обращу внимание, спасибо. У Вас есть готовое решение как с этим справится?
biziwalker
18.03.2017 22:18К сожалению решений нет, кроме как соответствовать минимальным требованиям в виде 2 ядер с 16 гб оперативы для мастер узла. Подробнее в документации написано для каких узлов какие требования и как расчитывать. Как по мне, так это слишком много для минимальных требований
servarius
19.03.2017 15:49На то они и минимальные требования. Для посмотреть и разработки есть вариант из Getting Started в готовом контейнере.
msolovyev
Спасибо, очень доходчиво!
servarius
Не за что, обращайтесь ;)