Всем привет! Меня зовут Владислав, я руководитель направления развития пользовательских Linux-систем в Т-Банке. Мы работаем над проектом Linux Desktop.
Проект зародился во времена блокировки иностранного софта. Нам нужен был опенсорсный продукт, который никуда не исчезнет и на закроется. Но прежде чем развивать Linux Desktop, в компании нужно было выбрать систему управления конфигурациями, которая сможет выдержать больше 15 000 хостов. А еще построить инфраструктуру, которая будет отказоустойчивой и не рассыпаться, если один из ЦОДов упадет.
Расскажу, как мы создали инфраструктуру, которая контролирует системы безопасности, магазин приложений, конфигурации ядра и многое другое. А еще такая инфраструктура — запасной аэродром, если вдруг придется отказаться от западного вендора.
Требования к новой системе
Основная идея Linux Desktop в том, чтобы создать свой образ Linux на основе open-source-продуктов, который будет user-friendly для разработчиков и операторов колл-центра и при этом будет соответствовать строгим требованиям безопасности банка.
Мы размышляли, как управлять всем этим парком. Первое, что пришло в голову, — стандартные решения, такие как Ansible, Puppet, SaltStack, Chef. Вариантов много, и каждый из них по своему хорош, но сначала нужно определиться с нашими требованиями.
Мы старались сформулировать требования по аналогии с другими большими устоявшимися MDM-системами: SCCM, Jamf, Intune. Нам нужны:
-
Декларированный подход к управлению конфигурациями. Хотим видеть конечное решение конфигураций нашей системы, а не просто последовательное выполнение команд без финального результата.
-
Масштабируемость и отказоустойчивость — эти параметры обязательны.
-
Возможность сбора различных фактов о системе, потому что мы хотим вести статистику по всему парку, собирать информацию об установленных программах и другую интересную нам информацию.
-
Возможность задавать конкретные политики безопасности и обеспечивать их выполнение на всех управляемых нами устройствах, что критически важно в большой и сложной инфраструктуре.
-
Большое сообщество, которое следит за обновлениями и безопасностью.
Это плюс для любой системы: быстрый выпуск фиксов багов, много разных модулей для удобства управления. -
И нужно выбирать то, что нравится, потому что потом самим же с этим работать.
Выбор пал на Puppet, потому что он использует pull-модель и у него свой центр сертификации. Масштабируемость инфраструктуры может быть как горизонтальная, так и вертикальная, что очень удобно. А если рядом установить Foreman, получится полноценная система управления с графическим интерфейсом, и все это в последствии можно кастомизировать под себя.
Дальше нужно было подсчитать, сколько потребуется серверов, построить схему и настроить отказоустойчивость. Расчеты мы проводили просто: подняли сервер, настроили на нем Puppet-сервер, загрузили туда пару активных машин и начали снимать метрики с сервера.
Логичный вопрос: зачем выполнять такой расчет, если Puppet уже все посчитал сам? Доверяй, но проверяй. Тем более что не совсем понятно, как он поведет себя в нашей инфраструктуре.
Вот что получилось в наших расчетах.
Конфигурации серверов
hostname |
cpu |
ram |
Назначение сервера |
puppet-master.domain.ru |
4 |
8 Gb |
Puppet master |
puppet-server-01.domain.ru |
4 |
8 Gb |
Puppet server |
Тестирование нагрузки. Во время тестирования онлайн было 50—80 хостов, и всю нагрузку мы распределили на два сервера.
puppet-server-01.domain.ru: RAM 8 ГБ VCPUs 4
puppet-master.domain.ru: RAM 8 ГБ VCPUs 4
Возьмем среднюю нагрузку на сервер в 75 хостов.
Посчитаем CPU
avg CPU utilization
puppet-master.domain.ru(1,86) + puppet-server-01.domain.ru(0,92) / 2 = 1,39%
Получается, что средняя нагрузка на процессор составляет 1,39% от 4 VCPUs при онлайне в 37 хостов.
Считаем половину от 75, потому что происходит балансировка между нодами.
На 1000 хостов потребление будет примерно 1,5 VCPUs (все расчеты производятся с учетом уже написанных манифестов, модулей и фактов).
Из официальной документации видно, что минимальные требования — от 2 до 4 VCPUs на 1000 хостов.
Берем среднее значение 3 VCPUs на 1000 хостов.
Потом считаем memory
avg Memory utilization
puppet-master.domain.ru(56,21) + puppet-server-01.domain.ru(38,99) / 2 = 47,6%
Получается, что средняя нагрузка на оперативную память составляет 47,6% от 8 Gb при онлайне в 37 хостов.
Считаем половину от 75, потому что происходит балансировка между нодами.
С учетом того, что JAVA воркеры настроены стандартно, а пополнение хостов происходило постепенно, можно считать расчеты из официальной документации за основу.
На 1000 хостов потребление будет примерно 4—6 Gb. Все расчеты провели с учетом уже написанных манифестов, модулей и фактов.
Получаем, что конфигурация инфраструктуры выглядит так:
hostname |
cpu |
ram |
Назначение сервера |
puppet-server-01.domain.ru |
4 |
6 Gb |
Puppet server |
foreman.domain.ru |
4 |
6 Gb |
Foreman |
puppet-master.domain.ru |
4 |
6 Gb |
Puppet master |
puppet-proxy-01.domain.ru |
4 |
4 Gb |
Proxy |
puppet-ca.domain.ru |
4 |
6 Gb |
Puppet CA |
puppet-server-02.domain.ru |
4 |
6 Gb |
Puppet server |
puppet-proxy-02.domain.ru |
4 |
4 Gb |
Proxy |
Из расчетов видно, что нашей инфраструктуры хватит на 3000 хостов, и мы вынесли отдельно центр сертификации, чтобы не нагружать серверы. Правило хорошего тона — держать центр сертификации отдельно. Proxy-серверы мы настроили так, чтобы они распределяли запросы на подпись сертификатов и запросы на получение конфигураций.
После нехитрых манипуляций получаем вот такую схему:
Схема инфраструктуры
Ну а теперь, как говорится, следите за руками!
Агент обращается к кластеру Nginx, который выполняет балансировку на уровне L4 и просто перенаправляет запросы на первый или второй прокси-сервер. Прокси располагаются в разных ЦОДах для повышения отказоустойчивости, и мы настраиваем их на распределение запросов в CA и к Puppet-серверу.
CA мы вынесли и создали три независимых друг от друга сервера. При падении любого сервера агенты все равно будут обращаться к другим серверам и получать конфигурацию. Ну а саму конфигурацию мы, как положено, распространяем с помощью Git.
Foreman нужен для удобного управления системами, а для повышения отказоустойчивости мы еще развернули кластер баз данных.
Как все выглядело на практике
Расскажу, как сделать все так красиво. У нас уже был git, мы настроили ci/cd так, чтобы ранер собирал наши манифесты с git и пушил их на все puppet-серверы. При этом мы использовали ansible-контейнер.
Развернули все на Ubuntu 20.04 и настроили /etc/hosts на серверах.
Начали с puppet-серверов, центра сертификации и foreman — установили puppet на сервера:
-
puppet-master.domain.ru
-
puppet-server-01.domain.ru
-
puppet-server-02.domain.ru
-
puppet-ca.domain.ru
-
foreman.domain.ru
sudo apt-get -y install ca-certificates cd /tmp && wget https://apt.puppet.com/puppet7-release-focal.deb sudo apt-get install /tmp/puppet7-release-focal.deb sudo apt-get update sudo apt-get install puppetserver
Установка Puppet CA
1. Настраиваем puppet.conf. Редактируем /etc/puppetlabs/puppet/puppet.conf, указываем dns мастера и центра сертификации:
[main] ca_server = puppet-ca.domain.ru certname = puppet-ca.domain.ru server = puppet-master.domain.ru
2. Включаем центр сертификации. Редактируем /etc/puppetlabs/puppetserver/services.d/ca.cfg:
# To enable the CA service, leave the following line uncommented puppetlabs.services.ca.certificate-authority-service/certificate-authority-service # To disable the CA service, comment out the above line and uncomment the line below #puppetlabs.services.ca.certificate-authority-disabled-service/certificate-authority-disabled-service puppetlabs.trapperkeeper.services.watcher.filesystem-watch-service/filesystem-watch-service
3. Разрешаем подписывать сертификаты master-server:
cp /etc/puppetlabs/puppetserver/conf.d/ca.conf /etc/puppetlabs/puppetserver/conf.d/ca.conf.backup
Редактируем /etc/puppetlabs/puppetserver/conf.d/ca.conf. Такая конфигурация нужна для подписи сертификатов с альтернативными dns-именами. После подписания нод ее нужно вернуть в исходное состояние:
certificate-authority: { # allow CA to sign certificate requests that have subject alternative names. allow-subject-alt-names: true # allow CA to sign certificate requests that have authorization extensions. allow-authorization-extensions: true # enable the separate CRL for Puppet infrastructure nodes # enable-infra-crl: false }
4. Запускаем puppetserver:
sudo systemctl start puppetserver.service
Настройка puppet-master nod
1. Выключаем центр сертификации. Чтобы сервер не участвовал в управлении сертификатами, его нужно отключить.
Редактируем /etc/puppetlabs/puppetserver/services.d/ca.cfg:
# To enable the CA service, leave the following line uncommented #puppetlabs.services.ca.certificate-authority-service/certificate-authority-service # To disable the CA service, comment out the above line and uncomment the line below puppetlabs.services.ca.certificate-authority-disabled-service/certificate-authority-disabled-service puppetlabs.trapperkeeper.services.watcher.filesystem-watch-service/filesystem-watch-service
2. Настройка puppet.conf. Редактируем /etc/puppetlabs/puppet/puppet.conf. Тут нужно чуть-чуть пояснить: чтобы клиент ходил на балансировщик, мы добавили dns балансировщика тоже в dns_alt_names, просто если puppet agent не увидит dns балансировщика в сертификате, то он не пойдет к нему.
[main] dns_alt_names = puppet-master.domain.ru,puppet.domain.ru ca_server = puppet-ca.domain.ru certname = puppet-master.domain.ru server = puppet-master.domain.ru
3. Настройка puppet-nod. Привожу настройку сразу двух нод, потому что они идентичны.
Выключаем центр сертификации. Сервер нужно отключить, чтобы он не участвовал в управлении сертификатами.
Редактируем /etc/puppetlabs/puppetserver/services.d/ca.cfg:
# To enable the CA service, leave the following line uncommented #puppetlabs.services.ca.certificate-authority-service/certificate-authority-service # To disable the CA service, comment out the above line and uncomment the line below puppetlabs.services.ca.certificate-authority-disabled-service/certificate-authority-disabled-service puppetlabs.trapperkeeper.services.watcher.filesystem-watch-service/filesystem-watch-service
Настройка puppet.conf. Редактируем /etc/puppetlabs/puppet/puppet.conf. То же самое прописываем на второй ноде, только:
[main] dns_alt_names = puppet-master.domain.ru,puppet.domain.ru ca_server = puppet-ca.domain.ru certname = puppet-server-01.domain.ru server = puppet-master.domain.ru
4. Получение сертификатов. Запускаем на нодах puppet-master.domain.ru puppet-server-01.domain.ru puppet-server-02.domain.ru
sudo /opt/puppetlabs/bin/puppet agent -t --waitforcert 10
На ноде СА подписываем все сертификаты puppet-ca.domain.ru
#Проверяем, что сертификаты /opt/puppetlabs/bin/puppetserver ca sign --all #Подписываем все сертификаты /opt/puppetlabs/bin/puppetserver ca list --all
Теперь нужно отключить подпись сертификатов с dns_alt_names на puppet-ca.domain.ru
sudo systemctl restart puppetserver.service
Настройка Proxy Nods
Устанавливаем nginx:
sudo apt install nginx sudo nano /etc/nginx/nginx.conf
worker_rlimit_nofile 50000; user www-data; worker_processes auto; pid /run/nginx.pid; include /etc/nginx/modules-enabled/*.conf; events { worker_connections 10000; } http { sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; types_hash_max_size 2048; include /etc/nginx/mime.types; default_type application/octet-stream; ssl_protocols SSLv2 TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE ssl_prefer_server_ciphers on; access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log; include /etc/nginx/conf.d/*.conf; include /etc/nginx/sites-enabled/*; log_format pptsrv '[$time_local]-- ip_client:$remote_addr -> ip_server:$upstream_addr status:$status bytes_client:$bytes_sent'; log_format pptca '[$time_local]-- ip_client:$remote_addr -> ip_server:$upstream_addr status:$status bytes_client:$bytes_sent'; access_log /var/log/nginx/pptsrv-access.log pptsrv; access_log /var/log/nginx/pptsrv-access.log pptca; upstream pptsrv { zone pptsrv 4M; least_conn; server ip-server:8140; #puppet-master.domain.ru server ip-server:8140 weight=5; #puppet-server-01.domain.ru server ip-server:8140 weight=5; #puppet-server-02.domain.ru } upstream pptca { server ip-server:8140; #puppet-ca.domain.ru } server { listen 8140 ssl proxy_protocol; server_name puppet-proxy-01.domain.ru ssl_session_timeout 5m; ssl_certificate /etc/puppetlabs/puppet/ssl/certs/puppet-proxy-01.domain.ru.pem; ssl_certificate_key /etc/puppetlabs/puppet/ssl/private_keys/puppet-proxy-01.domain.ru.pem; ssl_client_certificate /etc/puppetlabs/puppet/ssl/certs/ca.pem; ssl_verify_client optional; ssl_crl /etc/puppetlabs/puppet/ssl/crl.pem; location /puppet/ { proxy_pass https://pptsrv; proxy_redirect off; proxy_ssl_server_name on; proxy_ssl_verify on; proxy_ssl_name puppet.domain.ru; #Тут указываем имя балансировщика. Это нужно для того, чтобы агент понимал, как ему ходить proxy_ssl_crl /etc/puppetlabs/puppet/ssl/crl.pem; proxy_ssl_trusted_certificate /etc/puppetlabs/puppet/ssl/certs/ca.pem; proxy_ssl_certificate /etc/puppetlabs/puppet/ssl/certs/puppet-proxy-01.domain.ru.pem; proxy_ssl_certificate_key /etc/puppetlabs/puppet/ssl/private_keys/puppet-proxy-01.domain.ru.pem; proxy_set_headerHost $http_host; proxy_set_headerX-Real-IP $remote_addr; proxy_set_headerX-Forwarded-For $proxy_add_x_forwarded_for; } location /puppet-ca/ { proxy_pass https://pptca; proxy_redirect off; proxy_set_headerHost $http_host; proxy_set_headerX-Real-IP $remote_addr; proxy_set_headerX-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_headerX-Client-Verify $ssl_client_verify; proxy_set_headerX-Client-DN $ssl_client_s_dn; proxy_set_headerX-SSL-Subject$ssl_client_s_dn; proxy_set_headerX-SSL-Issuer $ssl_client_i_dn; proxy_read_timeout 65; } } }
Мы добавили метод балансировки и вес для серверов. Чтобы проверить конфиг, можно использовать команду nginx -t, а чтобы применить конфиг без перезагрузки службы и сервера, используем команду nginx -s reload.
Настройка Foreman
Перед настройкой Foreman советую настроить базу данных, но об этом тут рассказывать не буду. Идем дальше по настройке.
Устанавливаем репозитории и установщик:
sudo wget https://deb.theforeman.org/foreman.asc -O /etc/apt/trusted.gpg.d/foreman.asc echo "deb http://deb.theforeman.org/ focal 3.10" | sudo tee /etc/apt/sources.list.d/foreman.list echo "deb http://deb.theforeman.org/ plugins 3.10" | sudo tee -a /etc/apt/sources.list.d/foreman.list sudo apt-get update && sudo apt-get -y install foreman-installer puppet-agent
Настраиваем Noda Foreman. Устанавливаем puppet-agent.
Редактируем конфигурацию /etc/puppetlabs/puppet/puppet.conf:
[main] ca_server = puppet-ca.domain.ru certname = foreman.domain.ru server = puppet-master.domain.ru
Установка Foreman отдельно от puppet servers:
foreman-installer \ --puppet-server=false \ --foreman-proxy-puppet=false \ --foreman-proxy-puppetca=false \ --foreman-db-manage=false \ --foreman-db-host=name host DB \ --foreman-db-database=name DB \ --foreman-db-username=name user DB \ --foreman-db-password=pass user DB
Для настройки базы данных:
foreman-rake db:migrate foreman-rake db:seed foreman-rake apipie:cache:index
Noda Puppet-server. После установки Foreman nod нужно запомнить для подключения puppet-server:
-foreman-proxy-oauth-consumer-key -foreman-proxy-oauth-consumer-secret
Команда выполняется на foreman nod, чтобы получись oauth для получения foreman-proxy-oauth-consumer-key и foreman-proxy-oauth-consumer-secret:
sudo cat /etc/foreman-installer/scenarios.d/foreman-answers.yaml | grep oauth_consumer
Дальше запускаем установку на Puppet-server:
foreman-installer \ --no-enable-foreman \ --no-enable-foreman-plugin-puppet \ --no-enable-foreman-cli \ --no-enable-foreman-cli-puppet \ --enable-puppet \ --puppet-server-ca=false \ --puppet-server-foreman-url=https://foreman.domain.ru \ --enable-foreman-proxy \ --foreman-proxy-puppetca=false \ --foreman-proxy-foreman-base-url=https://foreman.domain.ru \ --foreman-proxy-trusted-hosts=foreman.domain.ru \ --foreman-proxy-oauth-consumer-key=***********************\ --foreman-proxy-oauth-consumer-secret=********************
Обратите внимание, что эта нода ставится без СА
По такой схеме настраивается master и slave server.
6.4 Noda Puppet-CA-server.
Устанавливаем прокси с СА:
foreman-installer \ --no-enable-foreman \ --no-enable-foreman-plugin-puppet \ --no-enable-foreman-cli \ --no-enable-foreman-cli-puppet \ --enable-puppet \ --puppet-server-ca=true \ --puppet-server-foreman-url=https://foreman.domain.ru \ --enable-foreman-proxy \ --foreman-proxy-puppetca=true \ --foreman-proxy-foreman-base-url=https://foreman.domain.ru \ --foreman-proxy-trusted-hosts=foreman.domain.ru \ --foreman-proxy-oauth-consumer-key=**************************\ --foreman-proxy-oauth-consumer-secret=**************************
После установки получите логин и пароль для входа, переходим на https://foreman.domain.ru, логинимся и получаем готовый сервис для работы.
А в итоге
Мы получили отказоустойчивую инфраструктуру, готовую выдержать до 3000 агентов с возможностью масштабирования. Это могут быть как серверы, так и мобильные рабочие станции, контроль распространения манифестов через git, удобное управление парком через Foreman, полный функционал puppet с управлением сертификатами, гибким написанием манифестов и множеством модулей от комьюнити.
P.S.
Кстати, puppet может управлять не только Linux, но и Windows-системами )
ссылка на оригинал статьи https://habr.com/ru/articles/865328/
Добавить комментарий