---
title: CFCRでデプロイしたKubernetes on AWSをSpot Instanceにする
tags: ["Kubo", "BOSH", "Kubernetes", "AWS", "CFCR"]
categories: ["Dev", "CaaS", "Kubernetes", "CFCR"]
date: 2018-06-03T12:43:47Z
updated: 2018-06-03T15:14:31Z
---

前記事で[Cloud Foundry Container Runtime 0.17.0をBOSH-wayでAWSにデプロイ](https://blog.ik.am/entries/453)しましたが、
クラスタをSpot InstanceにしてVM料金を3分の1くらいにします。

BOSHの[`vm_extensions`](http://bosh.io/docs/aws-cpi/#resource-pools)を使えば、BOSHでプロビジョニングしたVMにSpot Instanceの競り値を指定できます。


まずはBOSH DirectorがSpot Instanceを使えるように`${prefix}-bosh-director` IAMユーザーに次のIAM actionを追加してください。

* `ec2:RequestSpotInstances`
* `ec2:DescribeSpotInstanceRequests`
* `ec2:CancelSpotInstanceRequests`
* `iam:CreateServiceLinkedRole`

次にBastion serverにログイン。

```
./ssh-bastion.sh 
```

BOSH用の環境変数を読み込みます。

```
cd cfcr-manifests
source bosh-aws-env.sh
```

master vmに使用している`t2.micro`とworker vmに使用している`t2.medium`のSpot Instance価格はそれぞれ$0.0046、$0.0182で安定しています。

<img src="https://user-images.githubusercontent.com/106908/40886567-44261c4e-6775-11e8-85af-a315ea8fd2be.png" width="600">
<img src="https://user-images.githubusercontent.com/106908/40886563-3c0f0d04-6775-11e8-9476-6fe7b08fb32b.png" width="600">

念のため、$0.0047、$0.0183で入札するように`spot_bid_price`を設定する`vm_extensions`をCloud Configに追加するops-fileを作成します。

``` yaml
cat <<EOF > ops-files/cloud-config-spot-instance.yml 
- type: replace
  path: /vm_extensions?/-
  value:
    name: spot-instance-0.0047
    cloud_properties:
      spot_bid_price: 0.0047
      spot_ondemand_fallback: true

- type: replace
  path: /vm_extensions?/-
  value:
    name: spot-instance-0.0183
    cloud_properties:
      spot_bid_price: 0.0183
      spot_ondemand_fallback: true
EOF
```

`spot_ondemand_fallback`を`true`にしているので、Spot Instanceの価格が上がってAWSによってVMがシャットダウンされた場合にBOSH DirectorがOnDemand Instanceとして再作成してくれます。


`update-cloud-config.sh`に`cloud-config-spot-instance.yml`を追加して実行します。

``` bash
cat <<'EOF' > update-cloud-config.sh
#!/bin/bash
bosh update-cloud-config kubo-deployment/configurations/aws/cloud-config.yml \
    -o ops-files/cloud-config-rename-vm-types.yml \
    -o ops-files/cloud-config-small-vm-types.yml \
    -o ops-files/cloud-config-master-lb.yml \
    -o ops-files/cloud-config-spot-instance.yml \
    -v az=${zone} \
    -v master_iam_instance_profile=${prefix}-cfcr-master \
    -v worker_iam_instance_profile=${prefix}-cfcr-worker \
    -v internal_cidr=${private_subnet_ip_prefix}.0/24 \
    -v internal_gw=${private_subnet_ip_prefix}.1 \
    -v dns_recursor_ip=${private_subnet_ip_prefix}.1 \
    -v subnet_id=${private_subnet_id} \
    -v master_target_pool=${prefix}-cfcr-api
EOF

./update-cloud-config.sh
```

次にこれらの`vm_extensions`をKubernetesクラスタで使用するops-fileを作成します。

``` yaml
cat <<EOF > ops-files/kubernetes-spot-instance.yml 
- type: replace
  path: /instance_groups/name=master/vm_extensions?/-
  value: spot-instance-0.0047
- type: replace
  path: /instance_groups/name=worker/vm_extensions?/-
  value: spot-instance-0.0183
EOF
```

`deploy-kubernetes.sh`に`ops-files/kubernetes-spot-instance.yml`を追加して実行します。

``` bash
cat <<'EOF' > deploy-kubernetes.sh
#!/bin/bash
bosh deploy -d cfcr kubo-deployment/manifests/cfcr.yml \
    -o kubo-deployment/manifests/ops-files/misc/single-master.yml \
    -o kubo-deployment/manifests/ops-files/addons-spec.yml \
    -o kubo-deployment/manifests/ops-files/iaas/aws/lb.yml \
    -o kubo-deployment/manifests/ops-files/iaas/aws/cloud-provider.yml \
    -o ops-files/kubernetes-kubo-0.17.0.yml \
    -o ops-files/kubernetes-worker.yml \
    -o ops-files/kubernetes-master-lb.yml \
    -o ops-files/kubernetes-spot-instance.yml \
    --var-file addons-spec=<(for f in `ls specs/*.yml`;do cat $f;echo;echo "---";done) \
    -v kubernetes_cluster_tag=${kubernetes_cluster_tag} \
    -v kubernetes_master_host=${master_lb_ip_address} \
    --no-redact
EOF

./deploy-kubernetes.sh
```

EC2コンソールの"Spot Requests"で、Spot Instanceが作成されていることを確認してください。

![image](https://user-images.githubusercontent.com/106908/40886923-8949464c-677b-11e8-8ae4-542077c994ce.png)

うまくいかない場合はOnDemand Instanceになっているので、`bosh -d cfcr recreate master`または`bosh -d cfcr recreate worker`、失敗している方を実行してください。
