LoginSignup
19

More than 5 years have passed since last update.

[Debian] chef/Serverspec のためだけに CoreOSのDockerを構成する [Wheezy]

Last updated at Posted at 2014-12-06

流行に従って、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 を準備する

インストールする前に、まず設定ファイルを準備しておきます。面倒ごとは先にする主義です。実現してないけど。

内容はコレだ(ババン)長い

cloud-config.yml
#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

cloud-config.yml
#cloud-config

おまじないです。絶対に入れておいてください。ないと死にます。

hostname

cloud-config.yml
hostname: docker01.oshiire.to

家庭内で使っているホスト名なので、外から叩いても何も起きません。とりあえず、好きにつけてください。名前解決できるようにしておけるものが望ましいです。

coreos: units:

systemd で処理されるメインの部分です。
name: ごとに各daemon や service が割り当てられていると判断しました。(systemdがよく分かってない)

cloud-config.yml
coreos:
  units:

おまじないです。忘れずに書きましょう。

cloud-config.yml
    - name: etcd.service
      command: stop
    - name: fleet.service
      command: stop

etcd と fleet を使わないと心に誓った想いがここに現れています。
CoreOSとしては etcd/fleet がメインみたいなので、勝手に起動するように設定されそうなので先に排除しました。今回は Docker に絞ったのでこんな感じにしてます。

cloud-config.yml
    - 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を設定してます。時刻は正しく表示してもらいたいですもんね!

cloud-config.yml
    - 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

数字始まりでなにやら異質な部分ですが、ネットワーク設定部分です。

cloud-config.yml
    - 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 の書き方探してきて、自分なりにアレンジしました。オレカッコイイ。

cloud-config.yml
    - 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.mountxxx はマウント先を書くようなので、今回は 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 はアップデートを見つけると勝手に更新して、勝手に再起動します。素敵ですね。
その時の再起動方針を指定します。

cloud-config.yml
  update:
    reboot-strategy: best-effort

Using Cloud-Configupdate セクションに詳しいので、そちらを見てください。
なお、ぱくってくるとこんなコト書いてあります。

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-lockbest-effortあたりで悩んでください。

users

長かった(個人的に)...。最後に usersです。CoreOSで利用するユーザをここに指定します。書かないとログインで困ります。

cloud-config.yml
users:
  - name: core
    passwd: ...
    groups:
      - sudo
      - docker
    ssh-authorized-keys:
      - ssh-rsa AAAA.....==

name 欄にユーザ名を記載します
passwd には、Using Cloud-ConfigGenerating a password hash セクションにある方法で password のハッシュを作って、それを記載します。

commands
# 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 を入力するのは至難の業なので、次の順に進めていきます。

  1. core ユーザにパスワードをつける
  2. IPアドレスを知る
  3. 自由の利くクライアントから ssh ログインする
  4. cloud-config.yml をコピペするか、scp でコピーする
  5. インストールコマンドを打つ

1. core ユーザにパスワードをつける

起動した CoreOSでおもむろに次のコマンドを打ちましょう。

CoreOS
sudo passwd core

パスワードは好きにつけてください

2. IPアドレスを知る

CoreOS
ip -f inet addr

実は Enterキーを押しても IPアドレス分かります。何故こんなコトするかというと、dhcp で勝手に拾ってくるからです。dhcp ない人は諦めてください(やり方知らない)。

3. 自由の利くクライアントから ssh ログインする

先の二つの経験を元に

ssh
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. インストールコマンドを打つ

最後です。これを打てばインストールできます。上記の設定で。素敵。

CoreOS
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 をご覧に入れましょう。大盤振る舞いです。

Dockerfile
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/sh\nexit 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行を入れています。

Dockerfile
RUN echo "#!/bin/sh\nexit 0" > /usr/sbin/policy-rc.d

これでいいのか的な対応ですが、いいんです(川平風)

ここまでやって、やっと 「debian向けchef/serverspec開発用環境 on CoreOS」の完成です。
文章は無駄に長いですが、やってみると 5分で終わります。是非どうぞ。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
19