cloud-initでOCI Computeの初期設定を済ませる

# cloud-initによるインスタンスのカスタマイズ
Computeインスタンス作成すると、初期状態ではタイムゾーンやロケールなどが日本向けに設定されていない。そのため手動で変更しなければならない。そんなときに便利なのがcloud-initである。cloud-initを使用すると、はじめから変更した状態でインスタンスを作成できる

### 今回設定すること
今回はcloud-initで以下の設定を行う。cloud-initの詳細は[公式ドキュメント](https://cloudinit.readthedocs.io/en/latest/topics/format.html)を参照のこと。

* ロケールの変更
* タイムゾーンの変更
* パッケージのアップデート
* 便利パッケージの追加

なお手動で設定する方法は、以下のエントリで紹介している。設定意図や確認方法の詳細は、こちらを参考にして欲しい。

* [OCI Compute払い出し直後にやること](https://qiita.com/yamada-hakase/items/e898ce08feb9497c81e3)

また、cloud-initの詳しい解説は以下のエントリを参照のこと。

* [cloud-initを使ったLinux OSの初期設定](https://qiita.com/yamada-hakase/items/40fa2cbb5ed669aaa85b)

### 対象環境
cloud-initのコードは、Linuxディストリビューションの種類やバージョンとは独立している。そのため6系でも7系でも同じコードを利用できる。試していないが、おそらくUbuntuでも。またWindowsでは、ほぼ同様の[cloudbase-init](https://cloudbase-init.readthedocs.io/en/latest/)が利用できる。

ただし本文の後半では、設定されていることをOracle Linux 7で確認している。6系のディストリビューションでの確認方法は 「[OCI Compute払い出し直後にやること](https://qiita.com/yamada-hakase/items/e898ce08feb9497c81e3)」を見て欲しい。

# Computeインスタンス作成時の指定方法
### 管理コンソールでComputeインスタンスページを選択

管理コンソールのComputeページで**[Create Instance]**をクリックして作成ページに移動する。一番下までスクロールすると**[Show Advanced Options]**があるのでクリックするとオプションが展開する。
![oci_advance1.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266049/dfb75539-2de4-d570-8dca-2e389d819be1.jpeg)

### User dataにcloud-initのコードを入力
表示された部分をさらに下にスクロールすると「User data」が表示される。**[Past cloud-init script]**にトグルすると、その下のテキストボックスに入力できるようになる。もしくは**[Choose cloud-init script file]**でファイルを指定できる。
![oci_advance2.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266049/c551b05c-b854-424e-6e26-2e0b3bc894e2.jpeg)
テキストボックスに以下のコードをコピーする。Oracle Linux 6と7で試したところ、まったく同じコードを利用できた。

```
#cloud-config
timezone: Asia/Tokyo
locale: ja_JP.utf8
package_upgrade: true
packages:
 - man-pages-ja
 - multitail
 - nmap
 - nc
 - tmux
 - tree
```

これで終了だ。あとは**[Create]**をクリックし作成を開始する。

<font color="red">**注意:YumリポジトリにアクセスできないNWではpackageを記述しない**
上記のサンプルではRPMパッケージのアップデートやインストールを行なっている。そのためYumリポジトリにアクセスできないネットワークでは、意図した通りに動作しない。
またNAT/Service Gatewayを設定していればプライベート・サブネットでも、Yumリポジトリにアクセスできる。しかし非常にセキュアな環境では、インターネットへのアクセスをプロキシ経由に限定することがある。そのようなときも払い出し直後の状態ではプロキシ設定が無いためYumに失敗する。
</font>

# 作成した環境を確認する

### タイムラグがあること理解する

今回テストした環境ではタイムラグがあり、起動直後にログインしたときはタイムゾーンはUTCのままだった。その後5分くらい経過したらJSTになっていた。

* はじめてyum updateを実行するときには、リポジトリとのメタデータ同期に時間がかかるにもかかわらず、インスタンス作成にかかる時間は通常と変わらなかった
* 起動直後は変わっていなかった
* 起動して5分後くらいには変わっていた

以上の事実を踏まえると、インスタンス作成が終わってから、cloud-initのコードが実行されると思われる。cloud-initでパッケージアップデートするときは確認作業をするまで5分程度待って欲しい。

タイムラグがある理由について調べたことを、下記の別エントリに記述した。興味のあるかたは読んで欲しい。

* 「[インスタンス作成時にUser Dataで指定した設定が遅れる理由](https://qiita.com/yamada-hakase/items/657fead978491e8db92f)」

### cloud-initが終了したことを知る方法

よく分からない時間を待つのはつらいだろう。cloud-initのログ```/var/log/cloud-init.log```で判別できる。

```
# tail -f /var/log/cloud-init.log
```

次のように``` finish: modules-final```の行が表示されれば終了している。

```
2019-05-16 13:04:25,343 - util.py[DEBUG]: Read 14 bytes from /proc/uptime
2019-05-16 13:04:25,343 - util.py[DEBUG]: cloud-init mode 'modules' took 0.208 seconds (0.21)
2019-05-16 13:04:25,344 - handlers.py[DEBUG]: finish: modules-final: SUCCESS: running modules for final
```

またOracle Linuxの場合、Kspliceが有効になっているため```yum update```に時間がかかる。topなどで確認してCPU使用率が10%を超えていれば「まだcloud-initは終わっていない」と考えていいだろう。Kspliceについては、近いうちに別エントリとして書く予定である。

```
★topの出力例
top - 13:02:50 up 3 min,  2 users,  load average: 1.27, 0.89, 0.39
Tasks: 136 total,   5 running,  76 sleeping,   0 stopped,   0 zombie
%Cpu(s): 50.9 us,  3.6 sy,  0.0 ni, 43.6 id,  1.5 wa,  0.0 hi,  0.0 si,  0.3 st
KiB Mem : 15117488 total, 12620128 free,   467276 used,  2030084 buff/cache
KiB Swap:  8388604 total,  8388604 free,        0 used. 14282896 avail Mem

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
15786 root      20   0    4632   1552   1272 R 100.0  0.0   0:07.13 gzip　★
15785 root      20   0    4484    708    632 R   7.6  0.0   0:00.35 cpio
 8554 root      20   0  162020   4556   3876 R   0.7  0.0   0:00.08 top
    1 root      20   0  128256   8400   5676 S   0.3  0.1   0:03.11 systemd
```

### 設定されていることを確認する

タイムゾーンを確認すると日本になっている。

```
$ timedatectl
      Local time: 火 2019-05-14 21:29:08 JST ★
  Universal time: 火 2019-05-14 12:29:08 UTC
        RTC time: 火 2019-05-14 12:29:08
       Time zone: Asia/Tokyo (JST, +0900)
     NTP enabled: yes
NTP synchronized: yes
 RTC in local TZ: no
      DST active: n/a
```

ロケールも変更されている。Keymapは通常は影響が無いのでよしとしよう。

```
$ localectl
   System Locale: LANG=ja_JP.utf8
       VC Keymap: us
      X11 Layout: us

$ cat /etc/locale.conf
LANG=ja_JP.utf8
```

インストールされているパッケージを調べると、cloud-initで指定したものがインストールされている。

```
$ rpm -qa --last |less
tree-1.6.0-10.el7.x86_64                      2019年05月14日 21時24分40秒
tmux-1.8-4.el7.x86_64                         2019年05月14日 21時24分40秒
multitail-6.4.2-1.el7.x86_64                  2019年05月14日 21時24分40秒
man-pages-ja-20130615-3.el7.noarch            2019年05月14日 21時24分40秒
nmap-6.40-16.el7.x86_64                       2019年05月14日 21時24分38秒
nmap-ncat-6.40-16.el7.x86_64                  2019年05月14日 21時24分37秒
python-jinja2-2.7.2-3.el7_6.noarch            2019年05月14日 21時22分14秒
kernel-3.10.0-957.12.1.el7.x86_64             2019年05月14日 21時22分10秒
sos-3.6-17.0.1.el7_6.noarch                   2019年05月14日 21時22分06秒
libgomp-4.8.5-36.0.1.el7_6.2.x86_64           2019年05月14日 21時22分05秒
python-perf-3.10.0-957.12.1.el7.x86_64        2019年05月14日 21時22分04秒
```

アップデート可能なパッケージがあるか調べてみると、こちらも表示されない。うまくいった！

```
$ sudo yum check-update
読み込んだプラグイン:langpacks, ulninfo
★何も表示されない★
```

# おわりに

カスタムイメージを作成すれば同じものを複製できる。またAnsibleやChefなどを使っても同様なことを実現できる。だけれど、とても手軽に使えるのがcloud-initの魅力だ。