Установка Oracle RAC под Docker =============================== Требования к системе -------------------- * 8 Гб оперативной памяти; * 150 Мб swap-памяти; * 50 Гб свободного места на жёстком диске под контейнеры; * 15 Гб места на отдельном разделе под ASM-диск; * Наличие пользователя с правами на администрирование Docker (в том числе на запуск привилегированных контейнеров) и выполнение `ip(8)`. Подготовка окружения -------------------- Данные инструкции были проверены на `Debian 4.8.7-1 (2016-11-13) x86_64 GNU/Linux`, с Docker версии `1.12.5, build 7392c3b`. ### Настройка DNS Для задания доменных имён будем использовать bind. Установим его: apt-get install bind9 Скопируем файлы `bind/named.conf.oracle` и `bind/db.16.172` в `/etc/bind`: cp bind/* /etc/bind Добавим запись о них в файл конфигурации `bind`: echo 'include "/etc/bind/named.conf.oracle";' | tee -a /etc/bind/named.conf Перезапустим `bind`: systemctl restart bind9 Исправим `/etc/resolv.conf` так, чтобы он обращался к `bind` и искал по заданной зоне: cp resolv.conf /etc/resolv.conf Проверим, что конфигурация применилась: host db1 # Ожидаемый результат: db1.oracle-lab.com has address 172.16.0.1 ### Установка Docker Добавим поддержку HTTPS в `apt`: apt-get install apt-transport-https Опишем репозиторий Docker'а: cp docker.list /etc/apt/sources.list.d/ Получим список пакетов из него: apt-get update Установим Docker: apt-get install docker-engine ### Настройка пользователя Настроим профиль пользователя, из-под которого будет осуществляться настройка. Создадим его: useradd -m -G docker -s /bin/bash stud Настроим ssh-соединение с контейнерами: mkdir -p ~stud/.ssh cp ssh-config ~stud/.ssh/config chown -R stud:stud ~stud/.ssh chmod 600 ~stud/.ssh Настройка сети -------------- ### Вариант 1 В качестве внешнего в терминах Oracle RAC сетевого интерфейса будем использовать мост `docker0`, автоматически создаваемый Docker'ом. Для задания шлюза и маски подсети этого интерфейса нужно изменить параметры запуска Docker так, чтобы среди них был `--bip=172.16.0.254/24`: sed -i 's;\(dockerd\);\1 --bip=172.16.0.254/24;' \ /lib/systemd/system/docker.service systemctl daemon-reload systemctl restart docker Для внутреннего подключения узлов Oracle RAC создадим новую сеть: docker network create --subnet 172.16.1.0/24 --gateway 172.16.1.254 priv При этом необходимо, чтобы контейнеры RAC не знали других сетевых интерфейсов. Это требование вызвано тем, что при повторном запуске контейнера Docker сохраняет MAC-адрес только интерфейса, подключенного к `docker0`. У остальных интерфейсов MAC-адреса могут меняться местами, как и, следовательно, их имена. Если же мы используем лишь один интерфейс, не являющийся `docker0`, у него нет возможности поменяться MAC-адресом с чем-то другим. Также важен порядок запуска контейнеров: указать IP-адрес в рамках данной маски подсети невозможно стандартными средствами, и контейнер при запуске принимает первый свободный адрес. ### Вариант 2 Впрочем, имеется решение, которое позволяет иметь несколько сетевых интерфейсов. Для этого сообщество разработало скрипт [pipework](https://raw.githubusercontent.com/jpetazzo/pipework/master/pipework). Если его вызывать каждый раз при запуске контейнера, имена интерфейсов задаются консистентно. Установим скрипт: mkdir -p /usr/local/bin wget -O /usr/local/bin/pipework \ https://raw.githubusercontent.com/jpetazzo/pipework/master/pipework chmod 755 /usr/local/bin/pipework В таком случае мы можем задать две сети: docker network create --subnet 172.16.0.0/24 --gateway 172.16.0.254 pub docker network create --subnet 172.16.1.0/24 --gateway 172.16.1.254 priv Тогда после остановки контейнера нужно выполнять функцию disconnect_node() { local num="$1" ip link delete "rac${num}-pub" ip link delete "rac${num}-priv" } После запуска контейнера нужно выполнять функцию connect_node() { local num=$1" disconnect_node "$num" || : pipework br-$(docker network ls -q -f NAME=pub) -i eth1 \ -l rac${num}-pub db${num} 172.16.0.${num}/24 && pipework br-$(docker network ls -q -f NAME=priv) -i eth2 \ -l rac${num}-priv db${num} 172.16.1.${num}/24 } На вход функциям подаётся номер (1 или 2) узла RAC. Обе функции требуют права на администрирование сети: либо установленных capabilities или SUID на `ip`, либо root-доступа. ### Выбор варианта В рамках этого руководства мы придерживаемся первого варианта как наиболее простого: не требуется усложнения операций запуска и остановки контейнера, а также прав на администрирование сети. Невозможность использовать дополнительные сетевые интерфейсы в рамках Docker мы находим несущественной. Более проблематичная необходимость запускать контейнеры в строгом порядке тоже разрешима. Для адаптации изложенных далее шагов ко второму варианту необходимо после `docker run` и `docker start` осуществлять `connect_node`, а в функции `init_node` не выполнять `docker connect`. Подготовка образа ----------------- _Здесь и далее все команды исполняются от пользователя stud_. Мы использовали `Dockerfile` на основе представленного у [Seth-Miller](https://github.com/Seth-Miller/12c-rac-docker). Существенные правки: * Не имеется отдельного пользователя `grid`; * Устанавливается пароль пользователя `root`; * Создано udev-правило для распознавания ASM-диска. В первую очередь нужно поправить udev-правило для распознавания диска ASM, подставив туда имя своего диска: sed -i 's/vdb/YOUR_DISK_NAME/' Dockerfile/99-asm-disks.rules Для инициализации образа требуется запустить docker build --tag rac_initial Dockerfile После завершения сборки, при условии наличия дистрибутива Oracle в `/PATH_TO_ORACLE`: init_node() { local num=$1 docker run \ --detach \ --privileged \ --dns=172.16.0.254 \ --name db$num \ --hostname db$num \ --volume /PATH_TO_ORACLE:/oracle \ --volume /sys/fs/cgroup:/sys/fs/cgroup:ro \ --storage-opt size=23G \ --shm-size 4196m \ rac_initial \ /usr/lib/systemd/systemd --system --unit=multi-user.target && docker network connect --ip=172.16.1.${num}/24 priv db$num } init_node 1 init_node 2 После этого узлы должны быть доступны для подключения через ssh. Для установления подключения без пароля между контейнерами: wget https://raw.githubusercontent.com/Seth-Miller/12c-rac-docker/master/fixssh.sh chmod 755 fixssh.sh ./fixssh.sh db1 db2 # Будут ошибки, связанные с отсутствием grid Для подключения без пароля к контейнерам снаружи: ssh-keygen -t rsa ssh-copy-id db1 ssh-copy-id db2