На волне популярности Docker на Хабре, после участия в некоторых дискуссиях в комментариях относительно Docker, и в связи с недавней необходимостью настроить централизованную авторизацию для кластера Linux машин, я решил написать небольшую заметку. Здесь будет показан яркий, на мой взгляд, пример применения Docker'a для небольшой частной задачи.
Вот так, кстати, выглядит FreeIPA WebUI (официальное демо, временное демо у меня на сервере (подробности в комментариях)) (кликабельно):
Какие задачи я хотел решить при помощи FreeIPA:
- Иметь возможность создавать/изменять/удалять акаунты пользователей централизовано, а не на каждом отдельном сервере
- Централизованные плавила для sudo
- В последствии мы подключим к этой системе ещё и VPN авторизацию, а потом может и другие внутриофисные сервисы
Да, скорее всего FreeIPA в нашем случае это выстрел пушкой по воробьям, но с другой стороны — альтернатив что-то не видно. Я рассматривал такие варианты: NIS (по-моему он уже давно должен отправиться на отдых), OpenLDAP +… +… (не очень дружелюбно, да и FreeIPA в итоге под собой имеет LDAP, только нам не приходится с ним иметь дело напрямую), тут перечень заканчивается, я не нашёл ничего больше.
Итак, приступим!
Настройка сервера
Перечень используемых технологий:
- FreeIPA — открытый проект компании RedHat, который объединяет в себе множество других открытых проектов: 389 Directory Server, MIT Kerberos, NTP, DNS (bind), Dogtag certificate system, SSSD и другие. При этом у данного решения есть Web UI, CLI, XMLRPC, JSONRPC API и Python SDK.
- Dnsmasq — легковесный DNS сервер (позже я объясню зачем мне он нужен был в дополнение к bind, который используется в FreeIPA).
- Docker — open-source платформа, автоматизирующая развертывание приложений в легковесные, переносимые, самодостаточные контейнеры, которые могут без изменений переноситься между серверами. © Используем Docker и не волнуемся о vendor-lock
FreeIPA, в следствие того, что это продукт RedHat, естественно умеет хорошо разворачиваться на CentOS и Fedora и практически никак не разворачивается на других дистрибутивах. (прим. Я не особо задавался целью, поэтому может и есть где-то инструкции, но пакетов в Debian/Ubuntu для FreeIPA сервера нет, зато есть клиентский пакет freeipa-client
, но об этом потом.)
Меня этот факт ни разу не расстроил, а, наоборот, воодушевил! Это же идеальная задача для Docker, когда на серверах Debian/Ubuntu/Gentoo/etc. То есть я мог взять базовый образ Fedora, поставить там нужные пакеты, собрать всё в кучу и запустить, НО ещё более приятной новостью для меня стал официальный Docker образ freeipa-server (есть у них и клиент, но меня интересовал вариант с клиентом на Ubuntu, поэтому я запускал ubuntu образ в Docker и таким образом моделировал и быстро начинал с начала для отладки процесса «с нуля»).
Вообще, запуск freeipa-server не вызвал никаких проблем, всё в соответствии с документацией к образу Docker'a:
- Создаём директорию, которая будет монтироваться в образ для конфигов FreeIPA, которые нужно оставлять после перезапуска (в документации предлагается использовать
/var/lib/ipa-data/
, но я не люблю засорять систему, поэтому/opt/
):$ sudo mkdir -p /opt/dockers/freeipa-data
- Добавим файл с опциями, которые будут использоваться при инсталяции freeipa-server:
$ sudo tee /opt/dockers/freeipa-data/ipa-server-install-options --ds-password=The-directory-server-password --admin-password=The-admin-password
- Всё, запускаем (в доке не хватает проброса портов, хотя это и очевидно, что нужно сделать; стоит также отметить, что в доке написано, что нужно подключать раздел с префиксом
:Z:rw
, но у меня docker сказал, что не понимает что это такое, в гугле ничего вразумительного не нашёл, работает и без него; кто подскажет, что это?):$ docker run --name freeipa-server-test -it --rm --hostname freeipa.example.test --volume /opt/dockers/freeipa-data:/data --publish "443:443" --publish "389:389" --publish "636:636" --publish "88:88" --publish "88:88/udp" --publish "464:464" --publish "464:464/udp" adelton/freeipa-server
- После недолгой установки вам любезно предоставят
bash
— на этом установка и настройка FreeIPA Server по большому счёту завершена. Можете добавить freeipa.example.test себе в /etc/hosts, пройти на https://freeipa.example.test/, залогиниться под admin и создать пользователя.
FreeIPA у себя в образе поднял целый зоопарк служб, в том числе и bind (DNS), который настроил по своему усмотрению (магия, которую практически невозможно повторить на других DNS). Для клиентов FreeIPA ожидается, что они будут иметь доступ к этому DNS, который ещё умеет как-то хитро failover обрабатывать, только вот в случае как здесь — всё в одном образе Docker я не очень вижу пользу с такого failover. Однако, я не стал идти на перекор и учёл пожелания разработчиков FreeIPA (кстати, это особенность Kerberos, всё-таки FreeIPA — просто объединяет множество пакетов).
Так вот, к чему я про DNS? Мне нужен был DNS внутри кластера, но мне категорически не хотелось влезать в bind внутри FreeIPA контейнера. Поэтому я решил воспользоваться проверенным решением — Dnsmasq. На Docker Hub есть минималистичный образ Dnsmasq, основанный на Alpine Linux — 6МБ.
Вот как я его подготовил:
- Создал директорию для конфигов:
$ sudo mkdir -p /opt/dockers/dnsmasq.d
- Добавил туда конфиг dnsmasq:
$ sudo tee /opt/dockers/dnsmasq.d/dnsmasq.conf address=/freeipa.example.test/10.12.0.172 address=/server00.example.test/10.12.0.172 address=/server01.example.test/10.12.0.173 address=/server02.example.test/10.12.0.174
- Запускаем (DNS работает на 53/tcp и 53/udp портах, так что пробрасываем их, папку с конфигами):
$ docker run --name dnsmasq-test --rm --publish 53:53 --publish 53:53/udp --cap-add NET_ADMIN --volume /opt/dockers/dnsmasq.d:/etc/dnsmasq.d --entrypoint /bin/sh andyshinn/dnsmasq -c '/usr/sbin/dnsmasq -k -h --conf-dir /etc/dnsmasq.d/'
- Проверяем, что работает:
$ nslookup server00.example.test 127.0.0.1
Итого, у нас есть FreeIPA Server в одном контейнере и Dnsmasq в другом. Кстати, Dnsmasq, как можно было заметить, никак с bind DNS сервером FreeIPA ещё не взаимодействует.
Дальше я связал эти два сервиса в один docker-compose.yml
:
dnsmasq:
image: andyshinn/dnsmasq
ports:
- "53:53"
- "53:53/udp"
cap_add:
- NET_ADMIN
links:
- freeipa
volumes:
- "/opt/dockers/dnsmasq.d:/etc/dnsmasq.d"
entrypoint: ["/bin/sh", "-c", "/usr/sbin/dnsmasq -k -h --conf-dir /etc/dnsmasq.d/ -S /example.test/`getent hosts freeipa | cut -f1 -d' '`"]
freeipa:
image: adelton/freeipa-server
hostname: freeipa.example.test
ports:
- "443:443"
- "389:389"
- "636:636"
- "88:88"
- "88:88/udp"
- "464:464"
- "464:464/udp"
cap_add:
- NET_ADMIN
volumes:
- "/opt/dockers/freeipa-data:/data"
Можно заметить небольшую магию с дополнительной опцией к команде dnsmasq, эта опция будет перенаправлять запросы к *.example.test на bind DNS, уставновленный в freeipa контейнере.
Удобство Docker Compose в данном конкретном случае в том, что его конфиг всё-таки удобнее читать, чем bash-скрипт с docker run
. Да и лучше сразу делать хорошо. Сохраняем docker-compose.yml
и запускаем:
$ docker-compose up -d
C сервером, наконец, закончили.
Настройка клиентов
Тут у меня есть решение в 2 команды :)
- Нужно исправить /etc/hosts таким образом, чтобы первым в списке было полностью определённое имя домена (FQDN):
127.0.1.1 server00.example.test server00
- И теперь немного подредактировав вот эту команду (адрес Dnsmasq, имя домена, пароль admin'a в FreeIPA), можете её запустить:
$ sudo bash -c 'echo -e "nameserver 10.12.0.172nsearch example.testn# HEAD ENDn#" >> /etc/resolvconf/resolv.conf.d/head && service resolvconf restart && bash -c "cat > /usr/share/pam-configs/mkhomedir <<EOF Name: activate mkhomedir Default: yes Priority: 900 Session-Type: Additional Session: required pam_mkhomedir.so umask=0022 skel=/etc/skel EOF" && DEBIAN_FRONTEND=noninteractive apt-get install -y freeipa-client && ipa-client-install -U -N -p admin -w The-admin-password && service ssh restart'
Здесь добавится нужный DNS сервер, перегрузится resolveconf, добавится PAM-модуль для автоматического создания домашних директорий, установится freeipa-client, запустится установка ipa-client и после успешной установки перегрузится ssh.
Вот и всё, теперь на этом хосте можно делать su/sudo/ssh, где пользователя при самом первом входе заставят сменить пароль, а при первом входе на новом хосте для пользователя будет автоматически создана домашняя директория из /etc/skel
.
Выводы
Docker может упростить разворачивание сложных проектов в любой инфраструктуре. У Docker есть масса применений и это только одно из них.
В дальнейшем я, возможно, сподвигнусь написать о другом проекте, который интенсивно использует ограничения ресурсов, интегрированные в Docker (CPU, RAM).
Автор: frol