もうちょいコード化やりますか 3杯目 Packer~Chef

前回、Ubuntu ServerのVirtualBox(CUI)でVMを作成してBOX作成するという手順をやってみました。
次こそコード化!と宣言もしていたし、今度はPackerを利用してBOX作成してみようと思います。
収まりきらないので、上>中>3杯目と来てしまいました (*´Д`)

環境
Ubuntu Server14
Packer 0.7.2
VirtualBox 4.3.18
Vagrant 1.6.5

Packerのこと

PackerでISOイメージDLからインストール、インストール中のセットアップ、そしてインストール後の色々を自動でやってくれてVirtualboxのVagrant用のBOX作成までやってくれます。
AWSのインスタンスにも対応しているようですが、AWSって利用できるアプリケーションがめちゃ多いみたいで、それが利用者が増えるのに輪を書けているとよく思う。
利用者が増える→アプリが増える→使いやすくなる→利用者が増える。
と、倍々チャンス状態。
ちなみにVagrantはVmwareの他、さくらのクラウドにも使えるらしい。
Vagrant Sakura Provider

さて、PackerはJSONでできております。
JSONって最近まで知らなかったんですが、APIで知りました。
ここからすでに自動化ということでしでしな。

で、こいつはKickstartで使われるのと同じks.cfgと、それプラス、OSインストール後のセットアップスクリプトも併用できるprovisioner(仮)というファイルと連携が可能で、オートメーション化しているようです。

ks.cfgというと、昔々にインストールサーバーを立てまして、その時に作ったcfgファイルがあったなぁぁ~と、友達の友達はみな友達(古)という感じで色々と繋がってるんだな、うむ。と懐かしくも思ったけれど、deb用のものしか作ってなかったよ!(;^ω^)

薄い記憶はあまり当てにならないな・・・と、今回はCentOSのものが必要なので既存の/root/anaconda-ks.cfgを流用して作成しました。
後はprovisionersという、インスタンス作成後に実行するものでサッと見た感じ幾つかのスクリプトを走らせたりしているようですが、ここではYum updateとか必要なパッケージをインストールするくらいにしておかないと、のちほどChefでやる事がへっちゃうのでこの辺はできるだけ簡略化します。
今後、別のサーバーにChefでインストール後のセットアップをやってみたいので、Vagrantでいろいろやっちゃうと後から整合性を取るのが大変なのです。
多少はかぶっていても問題ないと思うけれどね。

さてPakcer.jsonとks.cfgですが、見よう見まねでこんな感じに出来上がりました。
何回か繰り返していらないとこを削ぎ落としていくとネット上にあるものとだいたい同じになってしまっていました (*´ω`)
最初はほぼコピーでも中身を見ながらならいいかなと。

階層(※事後です)

takeken@ubuntu:~/packer$ tree
.
├── Vagrantfile
├── builders
│   ├── ks.cfg
│   ├── ks.cfg.org
│   └── provisioner.sh
├── centos.json
├── crash.log
├── packer_cache
│   └── c69c3dbf72640e54c2b8a3117fc808535e32cdb06f11f586589f8d3524118c98.iso
└── vagrant
    └── CentOS-6.6-x86_64-minimal.box

そーす

/home/takeken/packer/cent.json

/home/takeken/packer/centos.json
{
  "builders": [
      {
      "type": "virtualbox-iso",
      "headless": true,
      "vm_name": "box",
      "boot_wait": "10s",
      "disk_size": "20000",
      "guest_os_type": "RedHat_64",
      "iso_checksum": "eb3c8be6ab668e6d83a118323a789e6c",
      "iso_checksum_type": "md5",
      "iso_url": "http://ftp.nara.wide.ad.jp/pub/Linux/centos/6.6/isos/x86_64/CentOS-6.6-x86_64-minimal.iso",
      "ssh_username": "vagrant",
      "ssh_password": "vagrant",
      "ssh_port": 22,
      "ssh_wait_timeout": "10000s",
      "shutdown_command": "echo '/sbin/halt -h -p' > shutdown.sh; echo 'vagrant'|sudo -S sh 'shutdown.sh'",
      "guest_additions_path": "VBoxGuestAdditions_{{.Version}}.iso",
      "virtualbox_version_file": ".vbox_version",
      "vboxmanage": [
          [ "modifyvm","{{.Name}}","--memory", "1024" ],
          [ "modifyvm","{{.Name}}","--cpus","1"]
      ],
      "http_directory": "./builders/",
      "boot_command":
          [ "<tab> text ks=http://{{ .HTTPIP }}:{{ .HTTPPort }}/ks.cfg<enter><wait>" ]
      }
    ],
  "provisioners": [
      {
      "type": "shell",
      "scripts": [ "./builders/provisioner.sh" ]
      }
    ],
  "post-processors": [
      {
        "type": "vagrant",
        "output": "./vagrant/CentOS-6.6-x86_64-minimal.box"
      }
    ]
}

/home/takeken/packer/builders/ks.cfg
ほとんどのサイトがKeyboard US なので、問題あるのかなと思いましたが、JP106でも全然問題ないようです。

install
cdrom
lang en_US.UTF-8
keyboard jp106
network --bootproto=dhcp
rootpw vagrant
firewall --enabled --service=ssh
authconfig --enableshadow --passalgo=sha512
selinux --disabled
timezone Asia/Tokyo
bootloader --location=mbr --append="crashkernel=auto rhgb quiet"

text
skipx
zerombr

clearpart --all --initlabel
autopart

auth  --useshadow  --enablemd5
firstboot --disabled
reboot

%packages --ignoremissing
@core
bzip2
kernel-devel
kernel-headers
-ipw2100-firmware
-ipw2200-firmware
-ivtv-firmware
%end

%post
/usr/bin/yum -y install sudo
/usr/sbin/groupadd -g 501 vagrant
/usr/sbin/useradd vagrant -u 501 -g vagrant -G wheel
echo "vagrant"|passwd --stdin vagrant
echo "vagrant        ALL=(ALL)       NOPASSWD: ALL" >> /etc/sudoers.d/vagrant
chmod 0440 /etc/sudoers.d/vagrant
%end

/home/takeken/packer/builders/provisioner.sh

#!/bin/sh

## base install
sudo yum -y update
sudo rpm -i http://ftp.riken.jp/Linux/fedora/epel/6/x86_64/epel-release-6-8.noarch.rpm
sudo yum -y install gcc make kernel-devel-`uname -r` zlib-devel openssl-devel readline-devel perl wget
sudo yum -y install curl bind-utils git jman ntp openssh-clients rsync sysstat vim dkms
sudo sed -i "s/^.*requiretty/#Defaults requiretty/" /etc/sudoers
sudo sed -i "s/#UseDNS yes/UseDNS no/" /etc/ssh/sshd_config
sudo sed -i "s/SELINUX=enforcing/SELINUX=disabled/" /etc/selinux/config

## vboxguest install
VBOX_VERSION=$(cat /home/vagrant/.vbox_version)
sudo cd /tmp
sudo mount -o loop /home/vagrant/VBoxGuestAdditions_$VBOX_VERSION.iso /mnt
sudo sh /mnt/VBoxLinuxAdditions.run --nox11
sudo rm -rf /home/vagrant/VBoxGuestAdditions_*.iso
echo "Vboxguest conplete!"

## user create
mkdir -pm 700 /home/vagrant/.ssh
wget --no-check-certificate 'https://raw.github.com/mitchellh/vagrant/master/keys/vagrant.pub' -O /home/vagrant/.ssh/authorized_keys
chmod 0600 /home/vagrant/.ssh/authorized_keys
chown -R vagrant:vagrant /home/vagrant/.ssh

ではPacker build。

$ packer build -only=virtualbox-iso centos.json
 Build 'virtualbox-iso' finished.

Vagrant ファイルを作成。

VAGRANTFILE_API_VERSION = "2"
BOX_NAME = "cenb"
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
    config.vm.box = BOX_NAME
    config.vm.box_url = "./vagrant/CentOS-6.6-x86_64-minimal.box"
    config.vm.network "public_network", ip: "192.168.24.120"
    config.vm.provider "virtualbox" do |vb|
       vb.name = BOX_NAME
       vb.customize ["modifyvm", :id, "--memory", "1024"]
       vb.customize ["modifyvm", :id, "--cpus", "1"]
    end
end

BOXとVagrantfileが出来上がったので、Vagrant upで立ち上げてみようと思います。
たしかにコマンドを叩いて作っていくよりも楽だわね。
コードならコードを修正すればいいので、コードで保守ができるというのは実際やってみると身に染みてきます。
出来上がるまでのプロセスがまるで違うからね。

$ vagrant up
takeken@ubuntu:~/packer$ vagrant ssh
Last login: Sat Nov 15 21:12:50 2014 from 10.0.2.2
[vagrant@localhost ~]$ id
uid=501(vagrant) gid=501(vagrant) 所属グループ=501(vagrant),10(wheel)

完走&完成しました!
やっと納得いけたのでChefに進みます。
長かった。

Vagrantファイルの生成はVagrant initで可能で、そこから修正を加えるので、そこだけ手動なのが少し気に入らないですが、他にいい方法も思いつかないので今は先に進みましょう。

 

Chefのこと

まずはホスト側で必要なものをそろえる。

takeken@ubuntu:~$ gem list | grep berk
berkshelf (3.2.1)
takeken@ubuntu:~$ gem list | grep knife
knife-solo (0.4.2)
takeken@ubuntu:~$ gem list | grep chef
chef (11.16.4)
takeken@ubuntu:~$ ruby -v
ruby 1.9.3p484 (2013-11-22 revision 43786) [x86_64-linux]

リポジトリを作成

takeken@ubuntu:~$ knife solo init chef-repo
WARNING: No knife configuration file found
Creating kitchen...
Creating knife.rb in kitchen...
Creating cupboards...
Setting up Berkshelf...
takeken@ubuntu:~/chef-repo$ ls -l
合計 28
-rw-rw-r-- 1 takeken takeken   14 11月 15 22:43 Berksfile
drwxrwxr-x 3 takeken takeken 4096 11月 15 22:46 cookbooks
drwxrwxr-x 2 takeken takeken 4096 11月 15 22:43 data_bags
drwxrwxr-x 2 takeken takeken 4096 11月 15 22:43 environments
drwxrwxr-x 2 takeken takeken 4096 11月 15 22:43 nodes
drwxrwxr-x 2 takeken takeken 4096 11月 15 22:43 roles
drwxrwxr-x 2 takeken takeken 4096 11月 15 22:43 site-cookbooks

まずはHello worldのレシピをば

takeken@ubuntu:~/chef-repo$ knife cookbook create hello -o cookbooks
takeken@ubuntu:~/chef-repo$ vim cookbooks/hello/recipes/default.rb

実行してみますと

takeken@ubuntu:~/chef-repo$ knife solo cook cenb -o hello
Compiling Cookbooks...
Converging 1 resources
Recipe: hello::default
  * log[Hello, World!!] action write

でましたー(*’ω’*)

とりあえず何か作ってみようと思ったものの、何も思い浮かばず。
ひとまずhttpdとmysqlのインストールが定番ですが参考書を見ながらじっくり作っていきます。

次に進む前にちょいとコマンドの整理

knife solo init リポジトリ名 : リポジトリを作成。
knife solo prepare ホスト名 : 対象ホストにChefをインストール
knife solo cook ホスト名 -o リポジトリ名 : 対象ホストにリポジトリをアップ、Chef-soloを実行する。
knife solo bootstrap ホスト名 : 上の2個を実行する。

 

Chefでhttpdとmysqlのインストール

まずリポジトリを作成。

$ knife solo init httpd-mysql

クックブックを作成します。

~/httpd-mysql$ knife cookbook create httpd-mysql -o site-cookbooks

レシピを書く。

~/httpd-mysql$ vi site-cookbooks/httpd-mysql/recipes/default.rb

Chef-solo Knife-solo を実行する。というのが一連の流れのようです。

~/httpd-mysql$ knife solo cook cenb -o httpd-mysql
package "httpd" do
        action :install
end

package "mysql" do
        action :install
end

中身は上の6行だけですが、実行してみます。

~/httpd-mysql$ knife solo cook cenb -o httpd-mysql

例によってテスト駆動というものにするならServerspecとかで確認するのが良いのでしょうが、今の段階では手動で確認します。

~/httpd-mysql$ ssh cenb
Last login: Sun Nov 16 10:41:43 2014 from 10.0.2.2
[vagrant@localhost ~]$ httpd -v
Server version: Apache/2.2.15 (Unix)
Server built:   Oct 16 2014 14:48:21
[vagrant@localhost ~]$ mysql -V
mysql  Ver 14.14 Distrib 5.1.73, for redhat-linux-gnu (x86_64) using readline 5.1

OKですね。このVMにはすでにうちのDHCP(CTU)からセグメント内のIPを割り振っているので、httpdを起動すればWindows機からもアクセスできるはずですが、今はアクセスできないようです。
では、そこでserviceを叩くのをぐっと堪えて、Chefでやってみようのコーナー。
本来ならそれぞれ別のクックブックを作ってNodeのjsonファイルに実行するListを記述するようですが、まだ小さいので1個に書いています。

$ cat site-cookbooks/httpd-mysql/recipes/default.rb
# httpdをインストール
package "httpd" do
        action :install
end

# httpdを起動する
service "httpd" do
        action [ :enable, :start ]
end

# mysqlをインストール
package "mysql" do
        action :install
end

# iptablesを都合上Stop
service "iptables" do
        action [ :disable, :stop ]
end

では、アクセスできるか確認してみます。
Win機なのでCurlもTelnetも入っていないので、術はブラウザのみですが、スクリーンショットを載せると邪魔なので、アクセスできたという事で終了。
自分にはウェルカムページが見えています \(゜ロ\)(/ロ゜)/

続いて、設定ファイルをChefでやりたいと思います。

Chefで設定ファイルを設定する

先ほどインストールしたhttpdの設定ファイル、httpd.confを設定してみます。
デフォルトのhttpd.confを用意して、templatesディレクトリに用意します。

~/httpd-mysql$ cp httpd.conf site-cookbooks/httpd-mysql/templates/default/httpd.conf.erb

現時点ではそのまま設置する事にするので、servertokenをonからoffに変えました。

レシピにtemplateリソースを追記します。

site-cookbooks/httpd-mysql/recipes/default.rb
# httpd.confを変更
template "httpd.conf" do
        path "/etc/httpd/conf/httpd.conf"
        owner "apache"
        group "apache"
        mode 0644
        notifies :reload, 'service[httpd]'
end

ではクックしてみて、実際にゲストで確認してみます。

takeken@ubuntu:~/httpd-mysql$ knife solo cook cenb -o httpd-mysql

所有者はapacheになり、ServerTokenはオフになっていました。
ばっちりです。

[vagrant@localhost ~]$ grep -i servertoken /etc/httpd/conf/httpd.conf
ServerTokens off
[vagrant@localhost ~]$ ls -l /etc/httpd/conf/httpd.conf
-rw-r--r-- 1 apache apache 34419 11月 16 12:52 2014 /etc/httpd/conf/httpd.conf

こうしたちょっとだけの作業だと、コードでやるのは少々めんどくささを感じますが、先の大きな事の一歩なので今は我慢なのです。

設定ファイルの設定方法は、設定したhttpd.confをまるまるゲストのhttpd.confを置く方法でやりましたが、少し別の方法があるのでまた今度やってみます。

 

レシピを増やそう

では次ですが、今回Vagrantで行ったことがいくつかあります。

  • epelリポジトリの追加
  • 必要なパッケージのインストール
  • インストーラーで追加したユーザーの設定
  • SElinuxの無効化

などなどですが、Vagrant以外のサーバーにChefで設定したいと思うので、まずはそれらもChefでできるようにしてみます。

Base用に作成したクックブック

~/httpd-mysql$ knife cookbook create base -o site-cookbooks

node/cenb.jsonを記述。外部Cookbookも使っています。

"run_list": [
 "yum",
 "recipe[selinux::disabled]",
 "recipe[base]",
 "recipe[httpd-mysql]"
 ],

Templateはsudoersのみです。
中身をここに載せるのは主旨が異なるので載せないですが、基本的な設定ファイルになっています。

site-cookbooks/base/templates/default/sudoers.erb

レシピはこんな感じです。っていうかどんどん日記が長くなってしまうので、ぼちぼちgithubとか使った方がいいな(´・ω・`)

$ cat site-cookbooks/base/recipes/default.rb
 #
 # Cookbook Name:: base
 # Recipe:: default
 #
 # Copyright 2014, YOUR_COMPANY_NAME
 #
 # All rights reserved - Do Not Redistribute
 #
 # 外部cookbookを利用してepelをインストール
 yum_repository 'epel' do
 description 'Extra Packages for Enterprise Linux'
 url 'http://ftp.riken.jp/Linux/fedora/epel/6/x86_64/epel-release-6-8.noarch.rpm'
 gpgkey  'http://ftp.riken.jp/Linux/fedora/epel/RPM-GPG-KEY-EPEL-6'
 action :create
 end
 # 基本的なパッケージをインストール
 %w{ gcc make kernel-devel zlib-devel openssl-devel readline-devel perl wget curl bind-utils git ntp openssh-clients rsync sysstat vim }.each do |p|
 package p do
 action :install
 end
 end
 # 外部cookbookを利用してselinuxを無効
 selinux_state "SELinux Disabled" do
 action :disabled
 end

 # 作業ユーザー作成
 # passwd は openssl passwd -1でOK
 user "takeken" do
 comment "takeken"
 home "/home/takeken"
 shell "/bin/bash"
 password "$1$Sdk6GWI3$8wCs/GirgmAfyjEd3K8rp/"
 supports :manage_home => true
 action [:create, :manage]
 end
 #
 group "wheel" do
 action :modify
 members [ 'takeken' ]
 append true
 end
 #
 template "sudoers" do
 owner "root"
 group "root"
 path "/etc/sudoers"
 mode "0440"
 source "sudoers.erb"
 end

ユーザー名はVagrantではなくtakekenになっていますが、これでVagrantで行ったことはほぼChefでもOKになっているはずです。

テストにVagrant経由ではなくて、直接sshでログインしてみます。

takeken@ubuntu:~/httpd-mysql$ ssh takeken@192.168.24.120
takeken@192.168.24.120's password:
[takeken@localhost ~]$ sudo -s
[root@localhost takeken]# exit

うむ。何の問題もないですね。

ではでは

 

Vagrant以外のサーバーにChefを実行する

今まではVagrant+Virtualboxのゲストに対して行っていましたがChefのいいところは他のサーバーに対してもOKなところです。
VagrantはAWSにも使えたり、大規模なプラットフォームに対しても有効ですが、個人ではそこまでいらなかったりします。

さくらのVPS+Chefでググると色々でてくるように、VPS等では効果が高いはずです。
まずはWindows機にVMwareから新規にOSを入れて試してみますか。
即消すつもりなのでちょっとめんどくさいけれど(*´ω`*)

~/httpd-mysql$ knife solo prepare root@192.168.24.64

rootでログインしているのでやたらとパスワードを聞かれるけど、とりあえず終了。
jsonが形成されるので編集します。

nodes/192.168.24.64.json

{
  "user": {
    "name": "root",
    "password" : "$1$wJVOjlmk$NdQ/FUU6EMVT394jhuS/I."
  },
  "run_list": [
    "yum",
    "recipe[selinux::disabled]",
    "recipe[base]",
    "recipe[httpd-mysql]"
  ],
  "automatic": {
    "ipaddress": "192.168.24.64"
  }
}

ではクッキングです。

~/httpd-mysql$ knife solo cook root@192.168.24.64

何度かエラーが出てリポジトリの参照先を変えたりしたけれど、なんとか完走できた。
新ユーザーでも問題なくログインできた。

takeken@192.168.24.64's password:
Last login: Sun Nov 16 19:07:32 2014 from 192.168.24.58
[takeken@localhost ~]$

ただエラーが出ているのでもう1回OS再インストールして試してみませう。
iptablesが無効なのでこのままだとVPSとかじゃ使えない。
修正が必要だえ。

2回目は1回で済むようにbootstrapで。

takeken@ubuntu:~/httpd-mysql$ knife solo bootstrap root@192.168.24.64
Running handlers complete
Chef Client finished, 32/42 resources updated in 134.788715791 seconds

おお、1回でセットアップ完了です。
これでいつでも同じ環境が作れて、ここから環境を広げていけばよいと。

では次回に~。

次回はiptablesの設定と、設定テンプレートの設定を別の方法で試してみます。

参考書籍

サーバ/インフラ徹底攻略 技術評論社
Chef実践入門 吉羽龍太郎/安藤祐介/伊藤直也/菅井佑太朗/並河裕貴 著 技術評論社

参考サイト

Packer-Ubuntu 14.04 を Vagrant に準備する seizans

PackerでVagrant用のBoxを作成したときのメモ ryurock

PackerでVagrantで使うVirtualBox用のboxを生成する | Fusic Developers Weblog:

my-packer-template-files/template.json at master ·
hnakamur/my-packer-template-files · GitHub:

Packerを使ってVagrant Boxを作ってみた – technica:

CentOSのインストールをkickstartで自動化しよう – Qiita:tukiyo3

さくらVPSの初期設定をChef Soloでやってみた〜サードパーティcookbookの使い方〜
| tsuchikazu blog:

ChefでApahceとPHPをソースインストールするレシピを書いてみた – 初めてのシステムと日記:

apache2.4のrecipeを書いてみた – Qiita:k-motoyan

Vagrant と Chef でユーザー作成の自動化をしてみる | girigiribauer.com:

ChefでさくらVPSの環境構築を自動化する – tkr’s blog:

さくらのクラウドを Vagrant up した – ナチュラル @rch850:

Similar Posts:


Leave a Reply

Your email address will not be published. Required fields are marked *