IBM Cloud Standard Imageの正しい取り方



今回はIBM Cloudの仮想サーバのちょっとネタです. 

Standard ImageはOSバックアップを取るための仕組みで、AWSで言うAMIを作成するのと同等です. 

Standard Imageの取り方はいろんなBlogで紹介されていますが、失敗例の情報が少ないので、経験上の注意事項と防止するための手順の一部を掲載します。

>**「正しい取り方」**じゃないところが見つかったら直してまいります.

---- 

## Standard Imageの取り方

**ポイント**

- 稼働中の場合はOSが停止します. 
- 仮想サーバ停止中でも取得できます. 

ブートディスクのみ取得する場合  

``` 
[guest@guest ~]$ slcli vs capture t01 -n backup-2018  --note "initial backup" 
```

2番目のディスクも含めて取得する場合  (オプション付加: --all True) 
```
[guest@guest ~]$ slcli vs capture t01 --all True -n backup-2018  --note "initial backup" 
```

> 2番目のディスクを含めるケースではブートディスクの一部として2番目のディスクを必要とするケースです. 
> 2番目のディスクがデータディスクであれば、含めないようにします. 

作成中はaction欄が"Check Cloud Image Transfer"などのように変化していきます. 


Standard Imageのリストに取得したイメージが表示されます. 
```
[guest@guest ~]$ slcli image list --private 
:.........:....................:........:............:.........:
:    id   :        name        :  type  : visibility : account :
:.........:....................:........:............:.........:
: 1900821 :        t01         : System :  Private   :  323xxx :
: 1900833 :        t02         : System :  Private   :  323xxx :
:.........:....................:........:............:.........:
```
取得するコマンドそのものは容易なので、簡単！と思うことでしょう. ( Cloudだから当たり前か ) 

---- 

## Standard Imageのリストア
OS Reload機能を使ってStandard Imageをリストアします. 

**ポイント**
  - rootパスワードはリセットされます. 
  - SSHキーもリセットされます. (必要でしたらリロード時にキーを指定します. オプション:-k) 

```
[guest@guest ~]$ slcli image list --private 
:.........:....................:........:............:.........:
:    id   :        name        :  type  : visibility : account :
:.........:....................:........:............:.........:
: 1900821 :        t01         : System :  Private   :  323xxx :
: 1900833 :        t02         : System :  Private   :  323xxx :
:.........:....................:........:............:.........:

[guest@guest ~]$ slcli vs reload --image 1900833 -k guest_rsa_key t01
This action cannot be undone! Type "52669399" or press Enter to abort: 52669399
[guest@guest ~]$
```

OSリロード中はaction欄が変動していきます.  

```
[guest@guest ~]$ slcli vs list 
:..........:..........:............:...............:............:...........................:
:    id    : hostname : primary_ip :   backend_ip  : datacenter :           action          :
:..........:..........:............:...............:............:...........................:
: 52669399 :   t01    :     -      : 10.133.173.68 :   tok02    : Register Physical license :
:..........:..........:............:...............:............:...........................:
```

OSリロードが完了するとaction欄の表示が消えます. 

```
[guest@guest ~]$ slcli vs list 
:..........:..........:............:...............:............:..............:
:    id    : hostname : primary_ip :   backend_ip  : datacenter :   action     :
:..........:..........:............:...............:............:...............
: 52669399 :   t01    :     -      : 10.133.173.68 :   tok02    :      -       :
:..........:..........:............:...............:............:..............:
```

---- 

## OSリストアに失敗するとどうなるの? 

よくある例では"Setup provision configuration" で停滞した後、リストア失敗となります. 

リストア中の仮想サーバの状態

```
[guest@guest ~]$ slcli vs list 
:..........:..........:............:...............:............:...............................:
:    id    : hostname : primary_ip :   backend_ip  : datacenter :             action            :
:..........:..........:............:...............:............:...............................:
: 52669399 :   t01    :     -      : 10.133.173.68 :   tok02    : Setup provision configuration :
:..........:..........:............:...............:............:...............................:
```
"Setup provision configuration"で停滞すると長い場合は数時間この状態が続きます. この状態ではキャンセルもできず、ひらすら待ちとなります.   
しばらく放置した後、再確認すると action欄が空白となり、「できた！」と思っても、pingにも応答しない,SSHもできない場合があります.  

```
[guest@guest ~]$ slcli vs list 
:..........:..........:............:...............:............:..............:
:    id    : hostname : primary_ip :   backend_ip  : datacenter :   action     :
:..........:..........:............:...............:............:...............
: 52669399 :   t01    :     -      : 10.133.173.68 :   tok02    :      -       :
:..........:..........:............:...............:............:..............:
```

最終的には、IBM Cloudのticketが起票され、OSリロードに失敗した通知を受けます. 

```
Subject: IBM Cloud チケット 58138729 - Updated - Custom Image Template Issues During Provisioning - IBM

お客様各位、

サブスクライブしているチケット上で更新が発生しました。
    アカウント ID : 323xxx
    チケット     : Custom Image Template Issues During Provisioning (58138729)
```

使用したStandard Imageはstatus: Inactiveに変化し、利用できない状態になります.   

```
[guest@guest ~]$ slcli image detail 1900833 
:....................:......................................:
:               name : value                                :
:....................:......................................:
:                 id : 1900833                              :
:  global_identifier : 8aaa41b8-5891-4a8b-9887-680846ef9418 :
:               name : t01                                  :
:             status : Inactive                             :
: active_transaction : -                                    :
<中略>
:         disk_space : 4.07G                                :
:        datacenters : tok02                                :
:....................:......................................:
```
***え? バックアップが無くなった!?***  なんてことになり、焦ります.  

status: Inactiveになったものは、ticketを起票してActiveにすることはできますが、イメージの編集ができませんので実質使えません...   
レスキューブートして問題判別したいと思っても、rootパスワードは参照できず、以前のパスワードも受け付けられません.  

```
[guest@guest ~]$ slcli vs credentials t01 
:..........:..........:
: username : password :
:..........:..........:
:..........:..........:
```

これを防ぐにはStandard Image取得時の手順で解決できます. 

---- 

### Standard Image取得時のチェックリスト

OSリロードやImage boot時に失敗しないためのチェックリストです.  

- OSリロード時の環境条件
   - [ ] 仮想マシンのOSとStandard ImageのOSの種類は一致していること
- 外部ディスク関連
   - [ ] 外部ディスクのマウントオプションに"nofail"を指定する(/etc/fstab) 
- サービス関連
   - [ ] IPアドレスにバインドしたサービスを無効化する
   - [ ] 外部ファイルシステムに依存したサービスを無効化する 
   - [ ] kdumpを無効化する
   - [ ] ホストFirewallを無効化する 
- [ ] rootユーザ認証関連
   - [ ] rootユーザのリモートログインを許可する
   - [ ] rootユーザのパスワード認証を許可する
- [ ] その他のハードニング解除
   - [ ] アンチウィルスやホストIPS/IDSを無効化する
- [ ] その他パッケージャー関連
   - [ ] 外部参照のyumリポジトリを無効化する

チェックリストにいろいろ書きましたが、じゃあどうやって確認するのか？なぜそれが必要なのか？というところをご説明します.  
 
#### 1) 外部ディスクのマウントオプションに"nofail"を指定する

外部ファイルシステム(Local/SAN/cifs/nfs)を自動マウントしたままの場合、ブート時にマウントできずProvisioningに失敗します.   
これを回避するためにマウントが失敗してもOSが起動するように"nofail"を指定します. 

またローカルファイルシステムの場合は、ブート時のfsckの対象外とするように設定しておきましょう. 

外部ディスクの識別方法はlsblkコマンドで確認します. 
デバイス名:/dev/xvda,/dev/xvdb,/dev/xvdh以外は外部ディスクです.  

この例では LVM: /dev/datavg/volume1が外部ディスクとなります. 

```
[guest@t01 ~]$ lsblk 
NAME               MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
xvda               202:0    0   25G  0 disk 
├─xvda1            202:1    0  256M  0 part /boot
└─xvda2            202:2    0 24.8G  0 part /
xvdb               202:16   0    2G  0 disk 
└─xvdb1            202:17   0    2G  0 part [SWAP]
xvdc               202:32   0   25G  0 disk 
└─xvdc1            202:33   0   25G  0 part 
  └─datavg-volume1 253:0    0   25G  0 lvm  
xvdh               202:112  0   64M  0 disk 

[guest@t01 ~]$ df -h
ファイルシス               サイズ  使用  残り 使用% マウント位置
/dev/xvda2                    25G  1.2G   22G    5% /
devtmpfs                     484M     0  484M    0% /dev
tmpfs                        494M     0  494M    0% /dev/shm
tmpfs                        494M  6.6M  487M    2% /run
tmpfs                        494M     0  494M    0% /sys/fs/cgroup
/dev/xvda1                   240M  121M  107M   54% /boot
tmpfs                         99M     0   99M    0% /run/user/0
/dev/mapper/datavg-volume1    25G   33M   25G    1% /ext/volume
```

/etc/fstabから外部ディスクのファイルシステムのマウントオプションを以下の内容で設定します. 
- nofailを指定し、マウントできない場合でもブート可能とします.  
- ブート時にfsckをしないようにします.  

|カラム    |説明                    |設定するべき値
|-------- |-------- |-------- 
| 1        | ブロックデバイス          |
| 2        | マウントポイント          |
| 3        | ファイルシステムタイプ     |
| 4        | マウントオプション        | "nofail"を追加します
| 5        | dump実行対象             | "0"(dump不要)を指定します
| 6        | ブート時のfsck順         | "0"(fsck不要)を指定します

/etc/fstabの例 

```
UUID=685c0159-c0b0-4c2b-b45b-550a962e4062 /                       ext3    defaults,noatime,noatime        1 1
UUID=f1c4ed45-98f5-4982-9a25-de08a52234dc /boot                   ext3    defaults,noatime,noatime        1 2
LABEL=SWAP-xvdb1 swap swap    defaults        0 0
/dev/datavg/volume1                       /ext/volume             xfs     defaults,noatime,nofail         0 0
```

#### 2) サービス関連
 - [ ] IPアドレスにバインドしたサービスは無効化する
 - [ ] 外部ファイルシステムに依存したサービスは無効化する 
 - [ ] kdumpは無効化する

tcp/udpのListenアドレスを確認し、localhostまたはALL以外の特定IP指定のdaemonが存在しないか確認します. 
以下の例では、DNSポート(53/tcp,53/udp)が特定IPに紐づいています.  
このようなサービスは停止するか、特定IPに紐つかないように設定します.  

```
[guest@t01 ~]$ ss -tuln
Netid State      Recv-Q Send-Q     Local Address:Port            Peer Address:Port              
udp   UNCONN     0      0                      *:53124                      *:*                  
udp   UNCONN     0      0                      *:18920                      *:*                  
udp   UNCONN     0      0                      *:68                         *:*                  
udp   UNCONN     0      0                      *:10000                      *:*                  
udp   UNCONN     0      0                      *:1812                       *:*                  
udp   UNCONN     0      0         10.133.173.68:53                          *:*                  
udp   UNCONN     0      0                      *:1813                       *:*                  
udp   UNCONN     0      0              127.0.0.1:323                        *:*                  
udp   UNCONN     0      0                     :::14322                     :::*                  
udp   UNCONN     0      0                     :::37001                     :::*                  
udp   UNCONN     0      0                     :::1812                      :::*                  
udp   UNCONN     0      0                     :::1813                      :::*                  
udp   UNCONN     0      0                    ::1:323                       :::*                  
tcp   LISTEN     0      50             127.0.0.1:3306                       *:*                  
tcp   LISTEN     0      128                    *:111                        *:*                  
tcp   LISTEN     0      128                    *:10000                      *:*                  
tcp   LISTEN     0      128                     :22                         *:*                  
tcp   LISTEN     0      128        10.133.173.68:53                         *:*                  
tcp   LISTEN     0      128                   :::111                       :::*                  
tcp   LISTEN     0      128                   :::22                        :::*
```

今回は特定サービスにひもづくDNSを無効化します. 


```
[guest@t01 ~]$ sudo systemctl disable named-chroot
```

kdumpもメモリ割り当ての少ない仮想サーバで起動する際にメモリ不足でfailする場合があります. こちらも無効化します. 

```
[guest@t01 ~]$ sudo systemctl disable kdump
```

最後に外部ディスク上のファイルシステムを必要とするサービスがあれば、それも無効化します.

```
[root@t01 ~]# fuser /ext/volume 
/ext/volume:          1145c
[root@t01 ~]# ps 1145
  PID TTY      STAT   TIME COMMAND
 1145 ?        Sl    55:31 /usr/libexec/mysqld --basedir=/usr --datadir=/ext/volume --plugin-dir=/usr/lib64/mysql/plugin --lo

[root@t01 ~]# systemctl disable maridb
Removed symlink /etc/systemd/system/multi-user.target.wants/mariadb.service.
```

その他チェックリスト記載の内容が満たされるかを確認していきます. 
バックアップの検証を行う時期では、この状態で一度OS再起動し、無効化したサービスが起動しないことなどを確認します. 

この状態からStandard Imageを取得すればOKです. 
リストアテストは時間単位の仮想サーバを注文してテスト、またはOS Reloadでテストします. 

### Standard Imageのリストアの事後作業

前述のように様々な設定を無効化するため、OSリロード時の事後処理はサービスの有効化等が必要です. 
Cloud Nativeにclout-init/provisioning scriptを使ったり、構成管理ツールのansible等を用いて自動化することが望ましいですね.  

### 最後に
個人の経験をまとめたものですので、実態にそぐわない場合がございます.  あらかじめご了承ください. 

間違いやご意見などありましたら、コメントお願いします.