Pull to refresh
119.28
Rating
Badoo
Big Dating

Долго ли умеючи, или массовый запуск серверов с минимумом трудозатрат

Badoo corporate blogPuppet
В нашей первой статье, как и анонсировалось ранее, мы спешим поделиться своим опытом в таком редко обсуждаемом вопросе как быстрое развертывание сотен серверов в рамках высоко нагруженного проекта.

Как развернуть несколько сотен серверов в географически удаленном дата-центре при отсутствии физического доступа к оборудованию? Как компания Badoo решает такую задачу?
Мы расскажем вам об этом на следующем примере.

Ниже пойдет речь о самом первом этапе конфигурирования серверного оборудования; о том, как быстро и в срок мы выполнили конкретную задачу, а не о написании оптимальных скриптов. В случае, если данная тема покажется вам интересной, мы с удовольствием расскажем и об установке ОС на сервера и настройке рабочего окружения, в чём тоже имеются свои тонкости.

Итак, перед нами была поставлена задача развернуть несколько сотен новых серверов, только что прибывших в два наших дата-центра.

При успешном выполнении, на выходе мы должны получить:
  • описание всей «железной» составляющей по каждому серверу;
  • соответствие заказанного оборудования полученному (бывают случаи, что приходит не та конфигурация, которую заказывали);
  • готовые к установке ОС и ПО сервера (с обновленными версиями прошивок RAID, ROM и т.д., сконфигурированными RAID-массивами, без проблем с «железом»).
Информация, которой мы располагали:
  • сервера смонтированы в стойки/шкафы и включены;
  • известны заводские логины и пароли;
  • все сервера имеют IPMI-интерфейс (интерфейс управления);
  • на серверах отсутствуют какие-либо предустановки от производителя (в частности, не сконфигурирован RAID, не выставлены настройки энергопотребления);
  • все сервера подключены к сетевому оборудованию минимум двумя интерфейсами, находятся в заранее известном VLAN;
  • новые сервера получают свои IP-адреса динамически, соответственно, они доступны сразу после включения;
  • известно, сколько серверов каких конфигураций должно было быть в поставке.
Безусловно, не обошлось и без дополнительных сложностей. Во-первых, у наших инженеров не было физического доступа к серверам. Во-вторых, «железо» в поставке имело несколько различных конфигураций. И в третьих, все, что мы знали о наших серверах ― это фактически только их заводские логины и пароли.

Чаще всего, подобного рода задачи предлагают решать с помощью dd, PXE-сервера и rsync, постановки задач, привлекая сотрудников дата-центра. Но мы подошли к вопросу иначе.

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

Для выполнения поставленной задачи нам потребовалось:
  • несколько текстовых файлов, которые по окончании работ удаляются;
  • несколько совсем простых скриптов, использующих expect;
  • настроенный сервер сетевой загрузки (в нашем случае это xCAT);
  • настроенный и рабочий образ ОС (неважно какой, главное, чтобы в этот образ входили все нужные нам утилиты);
  • настроенная система инвентаризации оборудования (в нашем случае это glpi project).
Сначала нам требовалось узнать, какие IP адреса были получены нашими новыми серверами. Для этого мы сделали текстовый файл nodes с данными о логинах и паролях в формате

ILOHOSTNAME1	ILOPASSWORD1
ILOHOSTNAME2	ILOPASSWORD2

Эти данные мы получили с наклеек, имеющихся на каждом сервере, с помощью сканера штрих-кодов. Стандартный логин был известен заранее – Administrator. Пример наклейки:


Теперь можно было запускать команду, которая собирала нам соответствия hostname и IP:

for i in $(cat nodes | awk {'print $1'}); do j=$(cat nodes | grep $i | awk {'print $2'}); ssh DHCPD_SERVER_FQDN "sudo cat /var/log/messages | grep $i | tail -1 | sed 's/$/ '$j'/g'"; done

В результате мы получали строки наподобие приведенных ниже, складывали их в файл nodeswip:

Jul  1 10:31:23 local@DHCPD_SERVER dhcpd: DHCPACK on 10.10.10.213 to 9c:8e:99:19:3a:68 (ILOUSE125NDBF) via 10.10.10.1 W3G554L7
Jul  1 10:31:35 local@DHCPD_SERVER dhcpd: DHCPACK on 10.10.10.210 to 9c:8e:99:19:b6:aa (ILOUSE125NDBA) via 10.10.10.1 BJCP691P
Jul  1 10:31:47 local@DHCPD_SERVER dhcpd: DHCPACK on 10.10.10.211 to 9c:8e:99:19:58:7c (ILOUSE125NDBG) via 10.10.10.1 67MG91SV

Теперь нам требовалось создать стандартного пользователя с набором доступных ему прав на всех IPMI интерфейсах новых серверов. Здесь же нужно было получить MAC адреса net и mgm интерфейсов для дальнейшей структуризации. Для этого мы выполнили команду

for i in $(cat nodeswip | awk {'print $8'}); do j=$(grep $i nodeswip|awk {'print $14'}); expect expwip.sh $i $j | grep Port1NIC_MACAddress; done;

где sh-скрипт expwip.sh выглядел следующим образом:

#!/usr/bin/expect
set timeout 600  
set ip [lindex $argv 0]
set pass [lindex $argv 1]
spawn ssh Administrator@$ip
set answ "$pass"
set comm1 "create /map1/accounts1 username=deployer password=PASSWORD name=deployer group=admin,config,oemhp_vm,oemhp_power,oemhp_rc"
expect "Administrator@$ip's password:"
send "$answ\r"
expect "</>hpiLO->"
send "$comm1\r"
expect "</>hpiLO->"
send "show /system1/network1/Integrated_NICs\r"
expect "</>hpiLO->"
send "exit\r"
expect eof

Полученный список MAC-адресов net интерфейсов наших серверов добавлялся в табличный редактор, что позволяло нам видеть все соответствия.

Затем мы выполняли действия по формированию конфига для DHCP-сервера, после чего отправляли сервера в netboot. После этого нам нужно было отправить IPMI-интерфейсы в перезагрузку для того, чтобы они заняли намеченные для них адреса. Это делалось с помощью команды

expect reset_ilo.sh $i $j

где $i – это адрес сервера, полученый ранее, $j – это заводской пароль администратора

Скрипт reset_ilo.sh выглядел так:

#!/usr/bin/expect
set timeout 600  
set ip [lindex $argv 0]
set pass [lindex $argv 1]
spawn ssh Administrator@$ip
set answ "$pass"
set comm1 "reset /map1"
expect "Administrator@$ip's password:"
send "$answ\r"
expect "</>hpiLO->"
send "$comm1\r"
expect eof

Далее мы переходили к автоматическому формированию RAID-массивов, обновлению всех возможных версий firmware на «железе», получению исчерпывающей информации по компоновке серверов в удобном виде. Все эти операции выполнялись при сетевой загрузке.

Сначала стартовал init-скрипт, который «готовил» RAID-массив:

LD=`/usr/sbin/hpacucli ctrl slot=0 logicaldrive all show|awk '$0 ~ /RAID 5/ || /RAID 0/ || /RAID 1/ {print $1" "$2}'`

LD=${LD:-NULL}

if [ "$LD" != "NULL" ]; then /usr/sbin/hpacucli ctrl slot=0 $LD delete forced; fi
/usr/sbin/hpacucli ctrl slot=0 create type=ld drives=`/usr/sbin/hpacucli ctrl slot=0 physicaldrive all show|awk '$1 ~ /physicaldrive/{split($2,arr,":");print $2}'|tr "\n" ","|sed 's/,$//'` raid=1+0
if [ `/usr/sbin/hpacucli ctrl slot=0 physicaldrive all show | grep physicaldrive | wc -l` -gt 1 ]; then r=`/usr/sbin/hpacucli ctrl slot=0 physicaldrive all show | grep physicaldrive | wc -l`; let t=$r%2; if [ $t -ne 0 ]; then let tl=$r-1; /usr/sbin/hpacucli ctrl slot=0 create type=ld drives=`/usr/sbin/hpacucli ctrl slot=0 physicaldrive all show|grep physicaldrive | head -$tl|awk '$1 ~ /physicaldrive/{split($2,arr,":");print $2}'|tr "\n" ","|sed 's/,$//'` raid=1+0; /usr/sbin/hpacucli ctrl slot=0  array all add spares=`/usr/sbin/hpacucli ctrl slot=0 physicaldrive all show|grep physicaldrive | tail -1|awk '$1 ~ /physicaldrive/{split($2,arr,":");print $2}'|tr "\n" ","|sed 's/,$//'`; fi; fi

В результате мы получали 1+0 или «зеркало». Затем выполнялся запуск агента, который отправлял информацию о «железе» в нашу систему инвентаризации. Мы используем fusion inventory agent, в настройках которого не меняли ничего, кроме адреса сервера сбора информации. Результат виден в интерфейсе Fusion Inventory:


Последним запускался скрипт, который обновлял все firmware на «железе». Для этого использовались несколько классов в puppet, которые выполнялись на новых серверах. Ниже приведен пример класса, который «смотрит» на текущую конфигурацию сервера и, в случае необходимости, обновляет версию прошивки RAID-контроллера до требуемой. По такому же сценарию выполнялись и остальные обновления прошивок «железа».

class hp_raid_update_rom {
        exec { "updateraid":
                command => "wget -P /tmp/ http://WEBSERVER/install/soft/firmware/hp/raid/5_12/CP015960.scexe; wget -P /tmp/ http://WEBSERVER/install/soft/update_hp_raid_firmware_512.sh; chmod +x /tmp/CP015960.scexe; chmod +x /tmp/update_hp_raid_firmware_512.sh; /tmp/update_hp_raid_firmware_512.sh; echo '5.12' > /tmp/firmware_raid",
                onlyif => "/usr/bin/test `/sbin/lspci | grep -i 'Hewlett-Packard Company Smart Array G6' | wc -l` != '0' && /usr/bin/test `/usr/sbin/hpacucli ctrl all show detail | grep -i firmware | awk {'print \$3'}` != '5.12' && ( [ ! -f /tmp/firmware_raid ] || [ `cat /tmp/firmware_raid` != '5.12' ])",
                path => "/usr/bin:/bin",
                require => Exec["remove_report_file", "remove_empty_report_file"],
        }
        exec { "remove_report_file":
                command => "/bin/rm /tmp/firmware_raid",
                onlyif => "[ -f /tmp/firmware_raid ] && [ `cat /tmp/firmware_raid` == `/usr/sbin/hpacucli ctrl all show detail | grep -i firmware | awk {'print \$3'}` ]",
                path => "/usr/bin:/bin",
        }
        exec { "remove_empty_report_file":
                command => "/bin/rm /tmp/firmware_raid",
                onlyif => "[ -f /tmp/firmware_raid ] && [ `cat /tmp/firmware_raid | wc -l` == '0' ]",
                path => "/usr/bin:/bin",
        }
}

Таким образом, мы решили поставленную задачу, используя лишь собственные ресурсы. Все наши машины были готовы к установке боевой ОС, установке ПО и началу обслуживания пользователей Badoo.

Все вышеизложенное описывает лишь подготовительный этап настройки оборудования, за рамками статьи остались вопросы установки ОС и конфигурирования рабочего окружения. Если вас интересует данная тема, мы с удовольствием подготовим материал о хСАТ и puppet и поделимся нашими способами решения специфических задач с помощью этих инструментов.

Ваши предложения, вопросы и замечания по вышеизложенному вы можете смело оставлять в комментариях ― мы всегда открыты для диалога!

Компания Badoo
Tags:badooбадуxcatglpipuppetdeploybadoo.comexpecthpilo
Hubs: Badoo corporate blog Puppet
Total votes 71: ↑58 and ↓13+45
Views20K

Top of the last 24 hours

Information

Founded
2006
Location
Россия
Website
badoo.com
Employees
501–1,000 employees
Registered
Representative
Yuliya Telezhkina

Habr blog