設定ファイル *Container Linux Configurations* の書き方例

## 前書き ##

[前回の記事][prev]では *Ignition* ファイルに変換するツール `Container Linux Config Transpiler（ct）` の導入について説明しました。

今回は変換元ファイルである *Container Linux Configurations* について備忘録を残しておきます。
公式サイトにある[Examples][example]の焼き直しですが、自分なりに試してみた結果として残しておこうかと。

残念ながらコンテナサービスとか *Kubernetes* の設定とかはありません。
まだまだ勉強中なので、すみません。

* テスト環境

    |システム |バージョン |
    |---|---|
    |Windows10 Pro x64 |1709 |
    |Vagrant |2.0.4 |
    |VirtualBox |5.2.10r122406 |
    |CoreOS(Vagrant)| 1772.0.0 |


## Container Linux Configurations ##

**YMAL書式** で書かれた設定ファイルになります。

構造化データを読みやすく表現するマークアップ言語らしいです。
が、ここでは詳しく説明しません（書ければいいんですよ）ので、気になった方は自分で調べてみてください。
（参考： [YAMLとは何か？ - いつもRailsの設定ファイルで出てくるやつの正体](https://qiita.com/Yama-to/items/587544993fb62610528a)）


## 設定例 ##

設定例のコード本文は [こちらの *GitHubGist*](https://gist.github.com/akiakishitai/cdc14e34d6e7d869143e89c870d3fb74) にも載せています。

注意点としまして、

* 各設定項目のインデントを適切に行う
    * インデントが書式に従っていない場合、エラーが発生（後述）
* `ct` コマンドを使って設定を検証する
    * 導入してない方は [前回の記事][prev] を参考にしてください
* *Vagrant* で作成した *CoreOS* で実際に試す際は、`config.ign` というファイル名で配置する

    ```bash:git-bash
    ct < cl-config.yml > config.ign
    ```

### ユーザ設定 ###

* ユーザのパスワードはハッシュ化して記載
  * セキュリティ上はパスワード設定しない（＝無効化）で、SSH公開鍵認証のみが推奨されます
* パスワードなし `sudo` を使いたい場合は `sudo` グループに所属させる
* `rkt` グループに所属させようとするとエラー

```yml:clc-sample-user.yml
passwd:
  users:
    - name: core
      password_hash: "$6$container-linux$Lo4rHvEin..."
      ssh_authorized_keys:
        - "ssh-rsa AAAAC3NzaC1l..."
    - name: hoge
      ssh_authorized_keys:
        - "ssh-rsa AAAAC3NzaC1l..."
      home_dir: /home/hoge
      no_create_home: false
      groups:
        - sudo
        - docker
      shell: /bin/bash
```

|項目 |概要 |
|---|---|
|name |ユーザー名 |
|password_hash |ハッシュ化パスワード |
|ssh_authorized_keys |SSHログイン用公開鍵 |
|home_dir |ユーザーのホームディレクトリ |
|no_create_home |ホームディレクトリ作成しない/する(bool値) |
|groups |ユーザーが所属するグループ |
|shell |ログインシェル |


#### ハッシュ化パスワードの作成 ####

[Examples の Generating a password hash][example]項目とおりにやればいいのですが、
*Python 2.7* の場合はそのままだとエラーが出るため、修正した次のコマンドで作成できます。

 ```bash
python -c "import crypt,random,string; print(crypt.crypt(raw_input('clear-text password: '), '\$6\$' + ''.join([random.choice(string.ascii_letters + string.digits) for _ in range(16)])))"
```


### ファイル作成 ###

単にファイル作成なら[Example#Storage and files](https://coreos.com/os/docs/1758.0.0/clc-examples.html#storage-and-files)の通りにやればできます。

ローカルファイルをコピーして渡したい場合は、
1. `local` でファイルパスを指定（相対パス）
2. `ct` コマンドで変換するときに `-files-dir` オプションでディレクトリパスを指定

という手順になります。
`local` で指定するファイルパスは `-files-dir` オプションで渡すディレクトリパスからの相対パスになります。

```yml:clc-sample-files.yml
storage:
  files:
    - path: /opt/test/hoge_clone.txt
      filesystem: root
      contents:
        local: ./hoge.txt
      mode: 0644
```

```bash:git-bash
ct -files-dir /path/to/local/hoge_dir < cl-sample-files.yml
```

|項目 |概要 |
|---|---|
|path |作成するファイルパス |
|filesystem |とりあえず `root` にしておけば問題ない |
|local |コピーするローカルファイルの相対パス<br>`ct` コマンドの `-files-dir` オプションで渡すディレクトリからの相対 |
|mode |ファイルのパーミッション設定 |


### systemdサービスの作成 ###

デフォルトではTimezoneがUTCなので日本時間JSTに変更する `service` を作成してみます。
`systemd` サービスの作成・書き方については [Systemd入門(4) - serviceタイプUnitの設定ファイル][service] を参考にさせていただきました。

* 複数行の文字列を設定するため、 `contents` で `|` を指定

```yml:clc-sample-timezone.yml
systemd:
  units:
    - name: timezone2jst.service
      enabled: true
      contents: |
        [Unit]
        Description=Change timezone to JST.
        [Service]
        Type=oneshot
        ExecStart=/usr/bin/timedatectl set-timezone Asia/Tokyo
        [Install]
        WantedBy=multi-user.target
```

|項目 |概要 |
|---|---|
|name |サービス名 |
|enabled |自動起動の設定(bool値) |


### ネットワーク設定 ###

固定アドレスを設定する例になります。
（仮想環境ではうまく設定できないかもしれません...）

```yml:clc-sample-network.yml
networkd:
  units:
    - name: 10-static.network
      contents: |
        [Match]
        Name=eth0
        [Network]
        Address=192.168.2.20/24
        Gateway=192.168.2.1
        DNS=8.8.8.8
```

|項目 |概要 |
|---|---|
|name |ネットワーク設定ファイル名 |
|`Name=<DEVICE>` |ネットワーク・インタフェースの指定 |
|`Address=xxx.xxx.xxx.xxx/PREFIX` |固定IPアドレス / プレフィックス |
|`Gateway` |ゲートウェイアドレス |
|`DNS` |ネームサーバのアドレス |


## エラーとか ##

### *error: yaml: line XX: could not find expected ':'* ###

`:` が必要ないところ（例えばファイルの内容を書いている場所）で起きる場合があります。
その場合はインデントが適切に入力されていないことが原因です。

インデントし忘れで長いことはまってました……。


### *Iginition* が適用されない ###

Ignition は **初回起動時のみ** に適用されます。
つまり **インストール直後の1回目の起動時のみ** が適用されるタイミングです。

初回起動時の状態に戻す方法もありますが（参考： [Container Linux を初回起動時の状態にする](https://blog.summerwind.jp/posts/20180307/)）、
*Vagrant* を使った仮想環境ならばさくっと破棄するのが早いです。

```bash:git-bash
vagrant destroy && vagrant up
```


## あとがき ##

以上で *Container Linux Configurations* の基本的な書き方はできるはずです。
*etcd* とか *flannel* とかの設定は特別に用意されてるみたいですが、試せれてないので許して……。

公式の [Examples][example] を雑に焼き直した程度ですが、ちょっとでも参考になれば幸いです。



## 参考 ##

* [Examples | Container Linux Documentation][example]
* [Configuration Specification | Container Linux Documentation][config-spec]
* [Systemd入門(4) - serviceタイプUnitの設定ファイル][service]

[prev]:https://qiita.com/akiakishitai/items/27b805f5e4d0da19e5bb
[example]:https://coreos.com/os/docs/latest/clc-examples.html
[config-spec]:https://coreos.com/os/docs/latest/configuration.html
[service]:http://enakai00.hatenablog.com/entry/20130917/1379374797
[timezone]:https://coreos.com/os/docs/latest/configuring-date-and-timezone.html