Packer + Ansible on Windows 10でKubernetes 1.10のクラスタ on VirtualBoxを全自動構築
Sun, Jun 17, 2018
Kubernetes docker ansible packer msys2Table of Contents
「Kubernetes 1.10のクラスタを全手動で構築するのをAnsibleで全自動化した」の続きで、さらにPackerを組み合わせて、VM作成まで自動化した話。
AnsibleをWindows(MSYS2)で動かした話でもある。
書いたPackerテンプレートはGitHubに置いた。
Packerとは
Packerは、様々な種類のVMを構築できるツール。 VagrantとかTerraformとかを開発しているHashiCorpが開発している。
テンプレートと呼ばれるビルド定義をJSONファイルに書いて、ビルド、プロビジョニング、ポストプロセスを実行して、アーティファクトと呼ばれるビルドの成果物を生成する。
ビルドのステップでは、VMを作成して、ハードウェア構成を設定したり、OSをインストールしたりする。
以下のような環境でVMを作れる。
- VirtualBox
- Hyper-V
- VMware Workstation
- VMware vSphere Hypervisor
- Docker
- AWS EC2
プロビジョニングのステップでは、ビルドで作ったVMのOS上で指定された操作を実行し、ソフトウェアのインストールなどのセットアップ処理をする。
プロビジョニングには以下のようなツールを使える。
- Shell
- PowerShell
- Ansible
- Chef
- Puppet
プロビジョニングが終わるとアーティファクト(VMイメージファイルや、AWS EC2のAMI IDとか)が出力される。
ポストプロセスのステップでは、アーティファクトを入力として何らかの処理をして、最終的なアーティファクトを生成する。
ポストプロセスでは以下のような処理を実行できる。
- アーカイブ
- VagrantBox生成
- AWS EC2へのインポート
- Docker push
PackerはGoで書かれていてビルド済みのバイナリが配布されているので、ダウンロードページから落として PATHの通ったところに置くだけでインストールできる。
今回はPacker 1.2.4のWindows版をインストールした。
Packerのテンプレート概要
Packerのテンプレートにはビルド、プロビジョニング、ポストプロセスの定義を複数かけて、複数環境のVM生成を1ファイルで定義できる。
テンプレートには以下のプロパティを書く。
- builders: ビルドの定義のリスト。
description
: テンプレートの説明。min_packer_version
: Packer の最低バージョン指定。- post-processors: ポストプロセスの定義のリスト。
- provisioners: プロビジョニングの定義のリスト。
- variables: テンプレート内で使う変数の定義。
_comment
: コメントなどを書くためのプロパティ。実際はアンダースコアで始まればなんでもいい。JSON オブジェクトのルートレベルのみで使える。
これらのうち、必須なのはbuildersだけ。
一つのビルド定義には一つのcommunicatorを紐づける。 communicatorはビルド時にVMにつなぐための設定。 基本はSSHだけど、WinRMとかもある。
やりたいこと
Windows 10上でPackerとAnsibleを動かして、VirtualBoxのVMをOracle Linux 7.4で作って、Kubernetes 1.10をインストールしたい。 Windowsでやりたいのは、単にベアメタルのLinuxの環境が無いからってのもあるし、いずれHyper-VのVMも作りたいからってのもある。
PackerはGo製で普通にWindowsで動くからいいけど、問題はAnsibleがPython製のくせにWindowsのPythonでは動かないこと。 AnsibleはWSLでは動くけど、VirtualBoxとかHyper-VはWindows上で動くから、PackerはWindows上で動かさないといけないはずで、そうなるとPackerから呼ばれるAnsibleもWindows上で動かさないといけない気がする。 のでWSLではだめな気がするし、そもそも実はWindows 7でも同じことやりたいのでWSLは無し。
要はWindows上でLinuxのPythonを使ってAnsibleを動かしたい。 ならばCygwinかMSYS2+MinGW-w64かGit Bashか。
ここにAnsibleはCygwinでもGit Bashでも動かすの難しいと書いてあって、逆にMSYS2でAnsible動かした記事はあったので、安直にMSYS2でやることにした。
MSYS2インストール
MSYS2は、公式サイトからx86_64のインストーラ(msys2-x86_64-20180531.exe)をダウンロードして実行して普通にインストールしただけ。
Ansibleインストール
MSYS2でのパッケージ管理にはpacmanを使う。
何はともあれPythonを入れる。3系でいい。
MSYS2 MSYS
のショートカット(MSYS2 MinGW 64-bit
じゃだめ)からターミナルを開いて、
$ pacman -S python
で、Python 3.6.2が入った。
次に、Ansible(の依存)のビルドに必要なパッケージを入れる。
$ pacman -S gcc
$ pacman -S make
$ pacman -S libffi-devel
$ pacman -S openssl-devel
さらに、AnsibleからのSSH接続で(鍵ではなくて)パスワードを使う場合に必要なパッケージも入れる。
$ pacman -S sshpass
sshpassの依存としてopensshも入った。
Ansibleはpipでインストールするんだけど、pacmanで入れたPython 3にはpipが付いてなかったので、別途入れる。
$ curl https://bootstrap.pypa.io/get-pip.py -LO
$ python get-pip.py
(ちょっと古いけどpipはpacman python3-pip
でも入る。)
で、ようやくAnsibleインストール。
$ export CFLAGS=-I/usr/lib/libffi-3.2.1/include
$ pip install ansible
依存するPyNaClのビルドに20分くらいかかるのでゆっくり待つと、インストール完了するはず。
今回はAnsible 2.5.4がインストールされた。
AnsibleでJinja2のipaddrフィルターを使うために、もう一つPyPiパッケージ入れる。
$ pip install netaddr
Packerテンプレート作成
ビルドは、OSインストールメディアのISOファイルを使うVirtualBoxのビルダであるvirtualbox-isoを指定して書いた。
OSのインストールは、Boot Commandをテンプレートに書くことで、インストーラのGUIを操作してやることもできるけど、RHEL系ならKickstartを使うのが楽。
Kickstartの定義ファイルは、普通に手動でOSをインストールした後、/root/anaconda-ks.cfg
を採取して、必要に応じて編集して作る。
今回作ったのはこれで、このスレを参考に、Minimalインストールから、Wifiのファームウェアとか要らないのを抜いてる。
プロビジョニングは、「Kubernetes 1.10のクラスタを全手動で構築するのをAnsibleで全自動化した」ときのPlaybookを実行するやつを公式マニュアル見ながら適当に書いて、ポストプロセスも適当に書いて、できたのがこれ。
ansible_env_vars
でANSIBLE_SSH_ARGS
に-o ControlMaster=no
を入れているのは、この問題に対応するため。
ビルド実行
MSYS2 MSYS
のショートカットからターミナルを開いて、Packerを実行してみたら以下のエラー。
$ packer build -var-file=variables.json k8s_single_node_cluster-vb.json
bash: packer: コマンドが見つかりません
WindowsのPathが通ったところにPackerバイナリを置いておいてもMSYS2からは見えない。
のでpackerバイナリのフルパス(今回はC:\Users\kaitoy\Desktop\bin\
にインストールしてたのでそのパス)を指定してやる。
$ /c/Users/kaitoy/Desktop/bin/packer.exe build -var-file=variables.json k8s_single_node_cluster-vb.json
k8s-single-node-cluster output will be in this color.
1 error(s) occurred:
* Error running "ansible-playbook --version": exec: "ansible-playbook": executable file not found in %PATH%
と、今度は、ansible-playbookが無いと言われる。 ansible-playbookはansibleパッケージに入っていて/usr/bin/にインストールされているんだけど、Windows界で動いているPackerからはLinuxのPATHが見えないので、見つけられない。
さらに、AnsibleのPlaybookのパスなど、Packerが妙な気を利かせてWindowsのフルパスにしてansible-playbookに渡してくれちゃうので、それをLinuxなパスに変換してやる必要がある。
ということで、以下のようなラッパスクリプトを書いて、カレントディレクトリに置くことにした。
@echo off
setlocal enabledelayedexpansion
for %%f in (%*) do (
if !key_file! == 1 (
rem The value of ansible_ssh_private_key_file is the path to
rem a key file in Windows TMP directory from MSYS2 point of view.
set arg=/%tmp:\=/%
set arg=!arg::=!
set args=!args!=!arg!/%%~nxf
set key_file=0
) else if %%~xf == .yml (
rem Convert the passed Playbook path to relative one.
set arg=%%f
set arg=!arg:%CD%=!
set arg=!arg:\=/!
set args=!args! !arg:~1!
) else (
rem Add other args as they are
set args=!args! %%f
)
if %%f == ansible_ssh_private_key_file (
rem The next arg will be the value of ansible_ssh_private_key_file
set key_file=1
)
)
echo args: %args%
C:\msys64\usr\bin\python C:\msys64\usr\bin\ansible-playbook -v %args%
以上でちゃんと実行できるようになった。
まとめると、
- Windows 10に、
- VirtualBox 5.1.28をインストールして、
- Packer 1.2.4のWindows版をインストールして、
- MSYS2をインストールして、
MSYS2 MSYS
のターミナルでPython 3.6.2とAnsible 2.5.4とか(とGit)をインストールして、以下を実行すればいい。
$ git clone --recursive https://github.com/kaitoy/packer-k8s.git $ cd packer-k8s $ /c/Users/kaitoy/Desktop/bin/packer.exe build -var-file=variables.json k8s_single_node_cluster-vb.json
packer.exe build
に-debug
を渡すと、内部の処理ステップごとに停止するようになり、デバッグしやすい。
一回実行したらゴミができて、次回実行時にエラーになるので、以下でクリーンアップする必要がある。
$ rm -rf /tmp/ansible
$ rm -f ~/.ssh/known_hosts
因みに、上記known_hostsを消し忘れると以下のようなエラーになる。
k8s-single-node-cluster: fatal: [k8s_master]: UNREACHABLE! => {"changed": false, "msg": "Failed to connect to the host via ssh: @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\r\n@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @\r\n@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\r\nIT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!\r\nSomeone could be eavesdropping on you right now (man-in-the-middle attack)!\r\nIt is also possible that a host key has just been changed.\r\nThe fingerprint for the ECDSA key sent by the remote host is\nSHA256:JNs/ZY38VpIuBE3QEzLHyLFGYe+Qg+bEWi8BOzgSNc0.\r\nPlease contact your system administrator.\r\nAdd correct host key in /home/kaitoy/.ssh/known_hosts to get rid of this message.\r\nOffending ECDSA key in /home/kaitoy/.ssh/known_hosts:1\r\nPassword authentication is disabled to avoid man-in-the-middle attacks.\r\nKeyboard-interactive authentication is disabled to avoid man-in-the-middle attacks.\r\[email protected]: Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password).\r\n", "unreachable": true}