どもです。インフラ池田(@mikeda)です。
今日は『NaviPlusではどういうふうにサーバ構築作業をしているのか』について話します。
※編集長注:以下は記事執筆時点のものです。将来的に弊社がこの手順を使用することを保証するものではありません。
まずNaviPlusでは今のところクラウドは利用していないので、
サーバ構築は基本的に以下のどっちかになります。
- 物理サーバ
- KVMのゲスト
OSはCentOSの6系です。
作業は以下の技術を使って自動化しています。
- PXE Boot + kickstart
- chef-solo
それではさっそく、ザックリとした実際の構築手順から。
構築手順
物理サーバとVMに分けて説明します。
事前にローカルDNSの登録と、chefのnode定義の作成だけやっておきます。
物理サーバ
まずは物理サーバの構築手順です。
以下の作業は並列実行可能、 またiLO/iDRAC等を使ってリモートでコンソールが取得できればオフィスからでも実行可能です。
PXE Boot + kickstartでOSインストール
サーバをPXEブートさせます。
HPサーバ、DELLサーバであれば起動中にF12を押せばOKです。
そうするとモニターにこんな画面が表示されるので、
======================== Select kickstart setting ======================== 1. CentOS-6 2. CentOS-6 KVM HOST 9. CentOS-6 Installer boot:
数字を入力してほおっておくとOSのインストールと初期設定が完了します。
1が通常サーバ、
2がKVMホスト(パーティションの切り方を変えてます)、
9は手動インストール(kickstartなしでインストーラが起動)です。
ネットワーク設定
初回起動時はネットワーク設定がDHCPになってるので、設定スクリプトを使って設定します。
# sh /tmp/nw_setting.sh test01 192.168.1.1 # reboot
bonding設定もこのスクリプトでやっちゃってます。
※VMのホストサーバの場合は、さらにブリッジ設定とLVM設定を実施します。
chef-solo実行
管理ユーザでログインし、chef-soloを実行します。
$ sudo chef-solo -c ~/chef/solo.rb -j ~/chef/nodes/`hostname`.json
で完了です。
VM
続いてVM(KVMゲスト)の構築手順です
virt-install + kickstartでOSインストール
VM構築スクリプトを使ってVMを作成します。
# ./vm_create.sh test01 192.168.1.101 1/2
これだけでOSのインストールと初期設定、NW設定が完了します。
chef-solo実行
ここからは物理サーバと同じです。
管理ユーザでログインし、chef-soloを実行、
$ sudo chef-solo -c ~/chef/solo.rb -j ~/chef/nodes/`hostname`.json
で完了。
以上で手順の説明は終わりです。
サーバ構築環境について
以降はサーバ構築環境の細かい設定などを説明していきます。
基本的に管理サーバが1台あって、そこに一通りの機能を突っ込んでいます。
- PXE Boot(要するにDHCPとTFTP)
- インストール用のOSイメージの公開
- ローカルyumレポジトリの管理と公開
- ソースコード、SSL証明書などのファイル置き場
PXE Boot + kickstart
PXE boot、kickstartの細かい説明は割愛します。
PXE bootの設定はこんな感じです。
$ cat /var/lib/tftpboot/boot.msg ======================== Select kickstart setting ======================== 1. CentOS-6 2. CentOS-6 KVM HOST 9. CentOS-6 Installer $ cat /var/lib/tftpboot/pxelinux.cfg/default prompt 1 display boot.msg # CentOS-6 label 1 kernel /centos6-x86_64/vmlinuz append ksdevice=eth0 ks=http://192.168.1.100/ks/centos6.cfg initrd=/centos6-x86_64/initrd.img noipv6 biosdevname=0 # CentOS-6 KVM HOST label 2 kernel /centos6-x86_64/vmlinuz append ksdevice=eth0 ks=http://192.168.1.100/ks/centos6_kvmhost.cfg initrd=/centos6-x86_64/initrd.img noipv6 biosdevname=0 # CentOS-6 installer label 9 kernel /centos6-x86_64/vmlinuz append initrd=/centos6-x86_64/initrd.img noipv6 biosdevname=0
kickstartファイルはこんな感じ
install text url --url=http://192.168.1.100/mrepo/centos6-x86_64/disc1/ lang ja_JP.UTF-8 keyboard jp106 network --onboot yes --device eth0 --bootproto dhcp --noipv6 rootpw --iscrypted XXXXXXXXXXXXXXXXXXXXXX firewall --service=ssh authconfig --enableshadow --passalgo=sha512 selinux --enforcing timezone Asia/Tokyo reboot zerombr bootloader --location=mbr --driveorder=sda --append=" biosdevname=0" clearpart --all --initlabel --drives=sda part /boot --fstype ext4 --size=300 --ondisk=sda part swap --size=2048 part / --fstype ext4 --size=1 --grow %packages @base @core @debugging @development @japanese-support @performance @server-policy sgpio systemtap-client %pre #/bin/sh /usr/bin/wget http://192.168.1.100/setup/os_setup.sh -O /tmp/os_setup.sh %post %include /tmp/os_setup.sh
DVDからインストールしたサーバの/root/anaconda-ks.cfgをちょっといじっただけですね。
- OSイメージの場所をDVDからHTTP経由に変更
- rebootつけてインストール完了後に勝手にリブート
- ディスク初期化で止まらないように、zerombrとかclearpartのinitlabelオプションつける
- biosdevname=0を指定して、新し目のDELLサーバもNICの名前がethXになるように
- OSの初期設定スクリプトをダウンロード&実行
※DVDから手動インストールしても同じ状態にできるように、kickstartでは特殊なことはやらないようにしてます
OSの初期設定スクリプトではこんなことをやっています。
- sshd設定調整
- SELinux無効化
- yumレポジトリ設定(既存を全削除してローカルyumレポジトリにむける)
- カーネルパラメータの調整
- 不要サービスの停止
- ネットワーク設定スクリプトのダウンロード。VMの場合は実行までやっちゃう。
- 管理ユーザの作成と設定
- ユーザ作成
- SSHの鍵配置
- sudoers設定
- git設定
- chefのgitレポジトリをclone
- chef-solo実行環境を導入
要するに『管理ユーザでログインしてchef-soloが実行できる状態』にします。
chef-solo
特に言うことがないw
githubで管理、各サーバに展開してます。
パッケージ管理
ミドルウェア系のパッケージ管理について話しておきます。
RPMはローカルレポジトリからyum installします。
ローカルレポジトリにはCentOS標準レポジトリのミラー、EPELのミラー、オリジナルのyumレポジトリ(外部から入手したもの、自分で作ったものを追加)があります。
外部から直接アクセスのあるReverseProxy用のApacheやAPP用のRubyなど、セキュリティや機能の面でバージョンを細かく更新したいものはソースインストールしています。
RPMの自作は管理が面倒なのであまりやっていません。
サーバ構築に必要なRPMやソースコードは全て管理サーバ上に配置されていて、外部からのファイル取得はありません(gemやpearのようなものは除いて)。
外部yumレポジトリなどを使っていると以下の問題が発生するためです。
- 依存パッケージも含めた完全なバージョンの固定化が難しい
- ファイルが消えちゃうことがある
ローカルyumレポジトリの構築にはmrepoを使っています。
構築手順はとっても簡単です。
ここからmrepoの0.8.8をダウンロード&インストールして、コンフィグをこんな感じに作成
# cat /etc/mrepo.conf [main] srcdir = /var/mrepo wwwdir = /var/www/mrepo confdir = /etc/mrepo.conf.d arch = x86_64 createrepo-options = --checksum sha --pretty --database --update mailto = root@localhost smtp-server = localhost # cat /etc/mrepo.conf.d/centos6.conf [centos6] name = CentOS $release ($arch) release = 6 arch = x86_64 metadata = repomd repoview ### ISO images iso = CentOS-6.4-x86_64-bin-DVD?.iso ### Additional repositories updates = rsync://ftp.riken.jp/centos/$release/updates/$arch/Packages/ fasttrack = rsync://ftp.riken.jp/centos/$release/fasttrack/$arch/Packages/ centosplus = rsync://ftp.riken.jp/centos/$release/centosplus/$arch/Packages/ extras = rsync://ftp.riken.jp/centos/$release/extras/$arch/Packages/ contrib = rsync://ftp.riken.jp/centos/$release/contrib/$arch/Packages/ ### EPEL repositories epel = rsync://ftp.jaist.ac.jp/pub/Linux/Fedora/epel/$release/$arch/ ### Original repositories naviplus = file:///naviplus/rpm/centos/$release/$arch/naviplus/
/var/mrepo/iso/にCentOS6のISOファイルを置いて
# ls /var/mrepo/iso/ CentOS-6.4-x86_64-bin-DVD1.iso CentOS-6.4-x86_64-bin-DVD2.iso
そしてレポジトリの更新を実行
# mrepo -ugvv
これだけで(あとはapacheのgracefulくらい)ここまでやってくれます。
- ISOファイルをインストール用にマウントして公開
- yumレポジトリを作成して公開
- OSイメージからbaseとなるyumレポジトリを作成
- update、extras等の標準レポジトリのミラーを作成
- EPELのミラーを作成
- 指定ディレクトリからrpmを探してオリジナルのyumレポジトリを作成
EPELレポジトリだけを再同期したければこんなコマンドを実行します
# mrepo -ugvv -r epel centos6-x86_64
オリジナルのyumレポジトリにパッケージを追加したい場合は、rpmをコンフィグで指定したディレクトリ以下に配置、更新コマンドを実行するだけでOKです。
# ls /naviplus/rpm/centos/6/x86_64/naviplus/td/ td-agent-1.1.18-0.x86_64.rpm td-libyaml-0.1.4-1.x86_64.rpm # mrepo -ugvv -r naviplus centos6-x86_64
作成したレポジトリは、yum設定をこんな感じにすれば使えます。
[base-local] name=CentOS-$releasever - Base baseurl=http://192.168.1.100/mrepo/centos$releasever-$basearch/RPMS.os/ gpgcheck=0 #released updates [updates-local] name=CentOS-$releasever - Updates baseurl=http://192.168.1.100/mrepo/centos$releasever-$basearch/RPMS.updates/ gpgcheck=0 ... [epel-local] name=Extra Packages for Enterprise Linux $releasever - $basearch baseurl=http://192.168.1.100/mrepo/centos$releasever-$basearch/RPMS.epel/ gpgcheck=0 enabled=1 [naviplus] name=CentOS-$releasever - Naviplus baseurl=http://192.168.1.100/mrepo/centos$releasever-$basearch/RPMS.naviplus/ gpgcheck=0 enabled=1
mrepoは便利なツールですが、情報が少ないしメンテされてなさそうなので、あんまオススメできないかもw
VMのインストールスクリプト
これもちょっとだけ話をしておきます。
ちなみにKVMのホストは、物理運用サーバを流用したそこそこスペックの1Uサーバがけっこう多いです。
その場合のサーバスペックはこのくらいです。
- 論理CPUコア数 : 24(6コア×2のHT)
- メモリ: 32G
- HDD : 300G
冗長化前提のサービス用VMはVM移動などを考慮して細かいリソース調整はせず、
各リソースを1/2、1/4、1/8した固定サイズのVMを使うようにしています。
※開発サーバや管理系のサーバは、それ用のホストに必要なだけリソースを確保してVMを作成してます。
最初の手順にあった1/2っていうのは、1/2サイズってことでした。
# ./vm_create.sh test01 192.168.1.101 1/2
このスクリプトの中身はこんな感じです。
#!/bin/bash HOSTNAME=$1 IP=$2 VM_SIZE=$3 LOCATION="http://192.168.1.100/mrepo/centos6-x86_64/disc1/" LV=/dev/vm_vg/lv_${HOSTNAME} case "$VM_SIZE" in "1/8") VCPUS=3 RAM=3584 DISK=32 ;; "1/4") VCPUS=6 RAM=7168 DISK=64 ;; "1/2") VCPUS=12 RAM=14336 DISK=128 ;; *) echo "undefined size" exit ;; esac if [ -b $LV ];then echo 'LV is already exists' exit fi lvcreate -L ${DISK}G -n lv_${HOSTNAME} vm_vg virt-install \ --name $HOSTNAME \ --ram $RAM \ --vcpus=$VCPUS \ --disk path=${LV} \ --os-variant=rhel6 \ --hvm \ --nographics \ --accelerate \ -w bridge:br0 \ --location="${LOCATION}" \ --extra-args="ks=http://192.168.1.100/ks/ks_kvm.php?cfg=centos6.cfg__${HOSTNAME}__${IP} console=tty0 console=ttyS0,115200n8"
VMのイメージはファイルじゃなくてLVMボリュームを使っています。
ファイルのほうが取り回しは楽なのですが、KVM徹底入門の平さん に「安定性とパフォーマンスの面でLVMのほうがオススメ」と言われたのでそうしてます。
(自分じゃ細かい検証してません!サーセンw)
kickstartファイルは動的に生成しています。
$ curl -g 'http://192.168.1.100/ks/ks_kvm.php?cfg=centos6.cfg__test01__192.168.1.101' install text url --url=http://192.168.1.100/mrepo/centos6-x86_64/disc1/ lang ja_JP.UTF-8 keyboard jp106 network --device eth0 --bootproto static --onboot yes --noipv6 --ip 192.168.1.101 --netmask 255.255.255.0 --gateway 192.168.1.1 --nameserver 192.168.1.2 --hostname test01 ...
といっても今のところ元kickstartファイルの、networkやデバイスを書き換えてるだけです。
<?php list($cfg, $hostname, $ip) = explode("__", $_GET["cfg"]); switch (preg_replace('/\.\d+$/', '', $ip)) { case "192.168.0": $netmask = '255.255.255.0'; $gateway = '192.168.0.1'; $nameserver = '192.168.0.2'; break; case "192.168.1": $netmask = '255.255.255.0'; $gateway = '192.168.1.1'; $nameserver = '192.168.1.2'; break; } $ks_config = file_get_contents("$cfg"); $ks_config = preg_replace( "/^network.*/m", "network --device eth0 --bootproto static --onboot yes --noipv6 " . "--ip $ip --netmask $netmask --gateway $gateway " . "--nameserver $nameserver " . "--hostname $hostname", $ks_config ); $ks_config = preg_replace( "/=sda/", "=vda", $ks_config); $ks_config = preg_replace( "/^bootloader.*/m", 'bootloader --location=mbr --driveorder=vda --append="console=ttyS0,115200n8"', $ks_config ); echo $ks_config; ?>
ちょっとこのスクリプト適当すぎだな・・・
まとめ
というわけで、NaviPlusのサーバ構築手順と使っている技術についての話でした!
PXE Bootやkickstart、ローカルyumレポジトリはcobblerを使ってかっこ良くテンプレート管理する手もあります。
ただサーバベンダやOS構成の種類が限られる場合、cobblerはちょっと大げさ過ぎる気がして使ってません。
構築時間はどのくらいですかね。
OSインストール中、chef-solo実行中は他の作業してるので、特にVMだと実際の作業時間はほとんどないです。
ここはもう、クラウドだろうがオンプレミスだろうがこのぐらいは当たり前になってきてる気はします。
もし1桁台の構築台数で『サーバ構築は丸1日以上かかります』とかって状態であれば、何か非効率的なことをしていると思います。
サーバ構築の速度と精度は高いに越したことはないです(もちろんどこまでやるかは状況によりけりです)。
工数削減はもちろんそうですが、加えて『作業』のコストとリスクを下げることは『改善』のコストとリスクを下げることになるからです。
『こうすればもっとよくなるのに』を簡単に実現できるように、環境を整備しましょう!
なんかいろいろ端折ってるので、わからないこと/気になることあったらTwitterで聞いて下さいw
ピンバック: NaviPlusの開発環境 | NaviPlus Engineers' Blog