前に Qiita で「[Debian] chef/Serverspec のためだけに CoreOSのDockerを構成する [Wheezy] – Qiita」を書いたのを、「MarsEdit 3」で、どんだけうまくできるかどうかのテストです。
手抜きじゃないんです。
流行に従って、Dockerを使い始めている最近です。どうせなら、CoreOS使ってやろうとCoreOS+Dockerで、chef/Serverspecの開発環境を作るに至ったのわけだけれども、systemd を初めて触ったり、/etc 配下をみてもサッパリ意味が分からなかったり、構成変更どうやったらいいのか、まるで宇宙に取り残された気分になりました。
そんな宇宙に取り残された状態でもNet上に散らばった情報をまとめていって、なんとか自分で満足のいくCoreOS+Docker環境が完成しました。
ので、自分のためだけに書き残しておきます。
目次
CoreOSをインストールしよう
CDブートからCoreOSをインストールする方法を選択します。この1週間で10回以上はインストールしていますが、全てこの方法でクリーンインストールを繰り返しています。しかし、cloud-config.ymlという素敵な構成ファイルのお陰で、何度やりなおしても苦痛がないので助かっています。ホント素晴らしい。
さて、まずはメディアを準備しましょう。
ブートCDを準備する
Booting CoreOS from an ISO より好きなメディアを落としてきましょう、どうせイメージはネットからダウンロードしてインストールするので、どれでもいい気がします(個人的見解)。
仮想環境でも実機でもどこでもいいので、ISOのまま使うか、CDに焼くかは皆さんのお好み次第です。私は Proxmoxの仮想環境に入れてます。
起動するだけなら、ディスクサイズは2GBと必要ないでしょう。とは言え、イメージをおいたりするので、20-40GB と自分がどれだけのイメージを準備するかによって割り当てましょう。
我が家では、外部NFSをマウントしたりして、共有やデータの外部保管も実現してるので、16GBと少なめです。イメージ一つだけですしね。
cloud-config.yml を準備する
インストールする前に、まず設定ファイルを準備しておきます。面倒ごとは先にする主義です。実現してないけど。
内容はコレだ(ババン)長い
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | #cloud-config hostname: docker01.oshiire.to coreos: units: - name: etcd.service command: stop - name: fleet.service command: stop - name: docker-tcp.socket command: start enable: yes content: | [Unit] Description=Docker Socket for the Remote API [Socket] ListenStream=0.0.0.0:2375 Service=docker.service BindIPv6Only=both [Install] WantedBy=sockets.target - name: enable-docker-tcp.service command: start content: | [Unit] Description=Enable Docker Socket for Remote API [Service] type=oneshot ExecStart=/usr/bin/systemctl enable docker-tcp.socket - name: timezone.service command: start content: | [Unit] Description=timezone [Service] Type=oneshot RemainAfterExit=yes ExecStart=/usr/bin/ln -sf ../usr/share/zoneinfo/Japan /etc/localtime - name: 10-static.network runtime: no content: | [Match] Name=ens* [Network] Address=... Gateway=... DNS=... - name: rpc-statd.service command: start - name: home.mount command: start content: | [Unit] Description=Home Directory on NFS Before=rpc-statd.service Conflicts=umount.target [Mount] What=...:/mnt/home Where=/home Options=rw,rsize=4096,wsize=4096,hard,intr,async,nodev,nosuid Type=nfs update: reboot-strategy: best-effort users: - name: core passwd: ... groups: - sudo - docker ssh-authorized-keys: - ssh-rsa AAAA.....== |
拡張子から分かるとおり、YAMLで記述されています。
個人的に見られたくない部分は「…」としています。主に書き換え必須な部分はそこだろうと当たりをつけてください。また、indent はスペースでないとダメらしいです。こわいですね。
さて、自分のために、全部説明書きを、残すんです(川平風)
#cloud-config
1 | #cloud-config |
おまじないです。絶対に入れておいてください。ないと死にます。
hostname
1 | hostname: docker01.oshiire.to |
家庭内で使っているホスト名なので、外から叩いても何も起きません。とりあえず、好きにつけてください。名前解決できるようにしておけるものが望ましいです。
coreos: units:
systemd で処理されるメインの部分です。
name: ごとに各daemon や service が割り当てられていると判断しました。(systemdがよく分かってない)
1 2 | coreos: units: |
おまじないです。忘れずに書きましょう。
1 2 3 4 | - name: etcd.service command: stop - name: fleet.service command: stop |
etcd と fleet を使わないと心に誓った想いがここに現れています。
CoreOSとしては etcd/fleet がメインみたいなので、勝手に起動するように設定されそうなので先に排除しました。今回は Docker に絞ったのでこんな感じにしてます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | - name: docker-tcp.socket command: start enable: yes content: | [Unit] Description=Docker Socket for the Remote API [Socket] ListenStream=0.0.0.0:2375 Service=docker.service BindIPv6Only=both [Install] WantedBy=sockets.target - name: enable-docker-tcp.service command: start content: | [Unit] Description=Enable Docker Socket for Remote API [Service] type=oneshot ExecStart=/usr/bin/systemctl enable docker-tcp.socket |
メイン部分の Docker 起動部分ですね。Docker プロセス自体は勝手に起動されてくるようなんですが、remote APIが使えないので、寂しすぎるので tcp socket サービスを入れて、外部からも docker コマンド を使えるようにしています。
ListenStream=0.0.0.0:2375 部分がキーポイントです。ListenするIPアドレスとポートを指定できます。このケースだと、IPv4 で割り当てられた全I/F から 2375/tcp ポートで待ち受けることを示してます。
timezone.service
どこからかパクってきました。最低です。
ここは日本であることを示して、Timezoneを設定してます。時刻は正しく表示してもらいたいですもんね!
1 2 3 4 5 6 7 8 9 | - name: timezone.service command: start content: | [Unit] Description=timezone [Service] Type=oneshot RemainAfterExit=yes ExecStart=/usr/bin/ln -sf ../usr/share/zoneinfo/Japan /etc/localtime |
10-static.network
数字始まりでなにやら異質な部分ですが、ネットワーク設定部分です。
1 2 3 4 5 6 7 8 9 10 | - name: 10-static.network runtime: no content: | [Match] Name=ens* [Network] Address=... Gateway=... DNS=... |
[Network] 以下の Address=xxx.xxx.xxx.xxx/xx にIPアドレスを、Gateway=xxx.xxx.xxx.xxx に Default gatewayアドレスを、DNS=xxx.xxx.xxx.xxx に DNSサーバのIPアドレスを指定します。DNSが複数あるときは、もう1行 DNS=… を追加すれば良さそうです。
home.mount
我が家では慣習的に /home を nfsマウントして運用している手前、nfs マウントを追加しています。お好みですが、なかなか情報が無かったので、systemd の書き方探してきて、自分なりにアレンジしました。オレカッコイイ。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | - name: rpc-statd.service command: start - name: home.mount command: start content: | [Unit] Description=Home Directory on NFS Before=rpc-statd.service Conflicts=umount.target [Mount] What=...:/mnt/home Where=/home Options=rw,rsize=4096,wsize=4096,hard,intr,async,nodev,nosuid Type=nfs |
nfs の lock サービスを使いたいので、rpc-statd を起動するようにしています。最初の2行がそれですね。
systemd の慣習として、xxx.mount の xxx はマウント先を書くようなので、今回は home.mount としています。要するに好きにしろってコトです。
[Unit] 以下には、先に rpc-statd.service が起動していて欲しい、と言うことと、umount.target の仲間にして下さいと言うことで Conflicts を指定してます。詳しいことはよく分かりません。
[Mount] には、/etc/fstab に書いているようなことを記載します。
What は、マウント元です。…はマウント元のサーバ名またはIPアドレスで、: をはさんでディレクトリを示します。この例だと /mnt/home がマウント元のディレクトリですね。
Where は、このCoreOSでマウントする先になります。先にも説明したとおり、home を共有しているので、/homeとしています。この場合、CoreOS のホームディレクトリが /home 配下になりますので、その辺はうまいことやりましょう。
Options は、nfsのマウントオプションです。うちはこんな感じです。
Type には、マウントタイプを指定します。nfs じゃなくて smbfs や ext4 なども指定できますので、適宜読みかえましょう。
update
CoreOS はアップデートを見つけると勝手に更新して、勝手に再起動します。素敵ですね。
その時の再起動方針を指定します。
1 2 | update: reboot-strategy: best-effort |
Using Cloud-Config の update セクションに詳しいので、そちらを見てください。
なお、ぱくってくるとこんなコト書いてあります。
One of “reboot”, “etcd-lock”, “best-effort” or “off” for controlling when reboots are issued after an update is performed.
- reboot: Reboot immediately after an update is applied.
- etcd-lock: Reboot after first taking a distributed lock in etcd, this > guarantees that only one host will reboot concurrently and that the cluster will remain available during the update.
- best-effort – If etcd is running, “etcd-lock”, otherwise simply “reboot”.
- off – Disable rebooting after updates are applied (not recommended).
いつでもすぐに再起動して欲しければreboot、再起動して欲しくなければoff、なんだからよく分からなければbest-effort、etcd 使ってる人は etcd-lockとbest-effortあたりで悩んでください。
users
長かった(個人的に)…。最後に usersです。CoreOSで利用するユーザをここに指定します。書かないとログインで困ります。
1 2 3 4 5 6 7 8 | users: - name: core passwd: ... groups: - sudo - docker ssh-authorized-keys: - ssh-rsa AAAA.....== |
name 欄にユーザ名を記載します
passwd には、Using Cloud-Config の Generating a password hash セクションにある方法で password のハッシュを作って、それを記載します。
1 2 3 4 5 6 7 8 9 10 11 | # On Debian/Ubuntu (via the package "whois") mkpasswd --method=SHA-512 --rounds=4096 # OpenSSL (note: this will only make md5crypt. While better than antext it should not be considered fully secure) openssl passwd -1 # Python (change password and salt values) python -c "import crypt, getpass, pwd; print crypt.crypt('password', '$6$SALT$')" # Perl (change password and salt values) perl -e 'print crypt("password","$6$SALT$") . "n"' |
groups には所属グループを記載しますが、sudo に入れとかないとむせび泣くと思います
ssh-authorized-keys には、ssh の公開鍵をそのままぺたっと貼り付けます。我が家ではRSA鍵使ってるので、ssh-rsa から始まるあれが貼り付けてあります。これがそのまま ~/.ssh/authorized_keys になります。
長かった…。
インストールしよう!
の前に、コンソールで、上記 cloud-config.yml を入力するのは至難の業なので、次の順に進めていきます。
- core ユーザにパスワードをつける
- IPアドレスを知る
- 自由の利くクライアントから ssh ログインする
- cloud-config.yml をコピペするか、scp でコピーする
- インストールコマンドを打つ
1. core ユーザにパスワードをつける
起動した CoreOSでおもむろに次のコマンドを打ちましょう。
1 | sudo passwd core |
パスワードは好きにつけてください
2. IPアドレスを知る
1 | ip -f inet addr |
実は Enterキーを押しても IPアドレス分かります。何故こんなコトするかというと、dhcp で勝手に拾ってくるからです。dhcp ない人は諦めてください(やり方知らない)。
3. 自由の利くクライアントから ssh ログインする
先の二つの経験を元に
1 | ssh core@[ipアドレス] |
でどうぞ。~/.ssh/known_hosts が汚されたくない人は、-o “StrictHostKeyChecking no” つけてください。コレによる影響は多少は気にしたほうがいいです。
4. cloud-config.yml をコピペするか、scp でコピーする
多分 vi できますので、vi ~/cloud-config.yml したり、scp ./cloud-config.yml core@xxx.xxx.xxx.xxx:~/ で、先ほどの cloud-config.yml をなんとかしましょう。
5. インストールコマンドを打つ
最後です。これを打てばインストールできます。上記の設定で。素敵。
1 | sudo coreos-install -d /dev/sda -C stable -c ~/cloud-config.yml -V 493.0.0 |
各オプションは次の通り
-d 導入先のディスクを指定します。
-C 導入する CoreOS のチャネルを指定します。stable(安定版) beta(β版) alpha(開発最新版) とあり、安定志向の人はstableを、最新版がとにかく使いたい人はalphaを、引っ込み思案で優柔不安なあなたはbetaを指定しましょう。
-c 大文字と小文字に注意。これまでがんばって作り上げたcloud-config.ymlファイルを指定します。
-V 導入するバージョンを指定します。個人的には指定した方が良いと思いますが、各チャネルの最新バージョンはRelease Channelsで確認できますので、ここを見ながら指定しましょう。
再起動
導入完了の合図がきたら、あとは再起動するのみです。
おめでとうございます、CoreOSの導入はここで完了です!
長かったなー。とお思いでしょうが、コレでは終わりません。大変です。
Debian用の chef/serverspec 用 Dockerイメージを準備する
なんだよ、フツーに docker build すればいいんだろと思われるかも知れませんが、実はちょっと注意事項があるんです。
私の Dockerfile をご覧に入れましょう。大盤振る舞いです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | FROM debian:wheezy MAINTAINER sho kisaragi <sho@oshiire.to> RUN echo "deb http://ftp.jp.debian.org/debian/ wheezy main" > /etc/apt/sources.list RUN echo "deb http://security.debian.org/ wheezy/updates main" >> /etc/apt/sources.list RUN echo "deb http://ftp.jp.debian.org/debian/ wheezy-updates main" >> /etc/apt/sources.list RUN apt-get update RUN apt-get install -y ca-certificates dialog locales openssh-server sudo curl rsync net-tools --no-install-recommends RUN apt-get upgrade -y && apt-get clean RUN mkdir /var/run/sshd RUN groupadd --gid 1000 chef RUN useradd --uid 1000 --gid 1000 -m chef RUN mkdir -p /home/chef/.ssh RUN chmod 0700 /home/chef/.ssh RUN chown chef.chef /home/chef/.ssh RUN echo 'chef ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers.d/chef ADD id_rsa.pub /home/chef/.ssh/authorized_keys RUN chmod 0400 /home/chef/.ssh/authorized_keys RUN chown chef.chef /home/chef/.ssh/authorized_keys RUN echo "#!/bin/shnexit 0" > /usr/sbin/policy-rc.d RUN curl -L https://www.opscode.com/chef/install.sh | sudo bash EXPOSE 22 CMD ["/usr/sbin/sshd", "-D"] |
何の変哲もない気がします。流れとしては、chefを実行するために必要なパッケージを入れることと、専用のユーザを準備しているだけに見えます。
残念、そうはいかないのです。
invoke-rc.d: policy-rc.d denied execution of start の罠
なんとなく docker上で chefを運用していると、invoke-rc.d: policy-rc.d denied execution of start. に巡り会い、service が起動できない自体に巡り会うことがあります。その理由は Docker, Openstack, policy-rc.d, mysqld にもある通り、systemd 化された CoreOSのために、policy-rc.d コマンドが exit 101 を強制的に返すことによる影響を受けるためです。分かっていればいいわけですが、地味にいやな気持ちになるので、Dockerfile 内に次の 1行を入れています。
1 | RUN echo "#!/bin/shnexit 0" > /usr/sbin/policy-rc.d |
これでいいのか的な対応ですが、いいんです(川平風)
ここまでやって、やっと 「debian向けchef/serverspec開発用環境 on CoreOS」の完成です。
文章は無駄に長いですが、やってみると 5分で終わります。是非どうぞ。