---
title: Cloud Foundry Container Runtime 0.17.0 (Kubernetes on BOSH)をBOSH-wayでAWSにデプロイ
tags: ["Kubo", "BOSH", "Kubernetes", "AWS", "CFCR", "PKS"]
categories: ["Dev", "CaaS", "Kubernetes", "CFCR"]
date: 2018-05-31T18:44:02Z
updated: 2018-07-07T15:23:23Z
---

**ℹ️ 本記事の作成方法はMulti-AZに対応していません。Multi-AZ対応版は[こちら](https://github.com/making/cfcr-aws/tree/v0.17.0)です。**

本記事は[こちら](https://blog.ik.am/entries/451)のv0.17.0版です。
**0.16.0から0.17.0にアップデートする方法**は[こちら](https://blog.ik.am/entries/452)を参照してください。

**目次**

[Cloud Foundry Container Runtime](https://docs-cfcr.cfapps.io/)(CFCR)を使ってKubernetesを[BOSH](https://bosh.io)でAWSにデプロイします。

CFCRはかつてKubo(Kubernetes on BOSH)と言われていましたが、renameされました。
この記事で一度環境を作れば、今後は(Breaking Changeがない限り)簡単にバージョンアップに追従できるはずです。

<!-- toc -->

### CFCRのdeploy

[Official Document](https://docs-cfcr.cfapps.io/installing/)のインストール方法は手作業が混じっているのとBOSHの操作を隠蔽してしまっており、BOSHユーザーには扱いづらい内容になっているので、
素直なBOSH wayでデプロイできるようにカスタマイズしました。またTerraformテンプレートも[オフィシャルのもの](https://github.com/cloudfoundry-incubator/kubo-deployment/tree/master/docs/terraform/aws)に加えてドキュメントの手作業部分も追加しました。

#### TerraformでAWS環境をPaving

まずはBOSHおよびKuberneteに必要なAWS環境をPaving(舗装)します。ここでは[Terraform](https://www.terraform.io/)を使います。

[カスタマイズ済みTerraformテンプレート](https://github.com/making/cfcr-aws)を取得してください。

```bash
git clone https://github.com/making/cfcr-aws.git
cd cfcr-aws/terraform
```

`terraform.tfvars`に変数を定義します。`access_key`と`secret_key`はTerraform実行用のIAMユーザーで`AdministratorAccess` Roleを持ったものを設定してください。

```bash
cat <<EOF > terraform.tfvars
prefix                   = "demo"
access_key               = "abcdef"
secret_key               = "foobar"
region                   = "ap-northeast-1"
zone                     = "ap-northeast-1a"
vpc_cidr                 = "10.0.0.0/16"
public_subnet_ip_prefix  = "10.0.1"
private_subnet_ip_prefix = "10.0.2"
EOF
```

次のコマンドでTerraformを実行してください。

```
terraform init
terraform plan -out plan
terraform apply plan
```

次の図のような環境ができました。

![image](https://user-images.githubusercontent.com/106908/40372551-eb314806-5e1f-11e8-97df-d665b321c33a.png)


#### Bastionサーバーへlogin

次に舗装された環境上でBOSHのプロビジョングを行いますが、作業はBastion(踏み台)サーバー上で行います。

```bash
cat terraform.tfstate | jq -r '.modules[0].resources["tls_private_key.deployer"].primary.attributes.private_key_pem' > deployer.pem
chmod 600 deployer.pem
export BASTION_IP=`cat terraform.tfstate | jq -r '.modules[0].outputs["bosh_bastion_ip"].value'`

echo "ssh -o StrictHostKeyChecking=no -i $(pwd)/deployer.pem ubuntu@${BASTION_IP}" > ssh-bastion.sh
chmod +x ssh-bastion.sh
```

次のスクリプトを実行してBastionサーバーにsshログインしてください。

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

#### BOSHのprovisioning

BOSH(BOSH Director)を[bosh-deployment](https://github.com/cloudfoundry/bosh-deployment)を使ってProvisioningします。
合わせて[kubo-deployment](https://github.com/cloudfoundry-incubator/kubo-deployment)も取得し、一旦Git管理します。

```bash
mkdir cfcr-manifests
cd cfcr-manifests
git init
git submodule add https://github.com/cloudfoundry/bosh-deployment.git
git submodule add https://github.com/cloudfoundry-incubator/kubo-deployment.git
cd kubo-deployment
git checkout v0.17.0
cd ..
git add -A
git commit -m "import CFCR v0.17.0"
```

YAMLの差分ファイル(ops-file)は`ops-files`ディレクトリで管理します。

```bash
mkdir -p ops-files
```

BOSH DirectorのVMサイズを小さめの`t2.small`にするops-fileを作成します。

```yaml
cat <<EOF > ops-files/director-size-aws.yml
- type: replace
  path: /resource_pools/name=vms/cloud_properties/instance_type
  value: t2.small
EOF
```

BOSHをprovisioningするスクリプトを作成します。各種環境変数はTerraformでBastionサーバーに設定済みです。

```bash
cat <<'EOF' > deploy-bosh.sh
#!/bin/bash
bosh create-env bosh-deployment/bosh.yml \
    -o bosh-deployment/aws/cpi.yml \
    -o bosh-deployment/uaa.yml \
    -o bosh-deployment/credhub.yml \
    -o bosh-deployment/jumpbox-user.yml \
    -o bosh-deployment/local-dns.yml \
    -o ops-files/director-size-aws.yml \
    -o kubo-deployment/configurations/generic/dns-addresses.yml \
    -o kubo-deployment/configurations/generic/bosh-admin-client.yml \
    -o kubo-deployment/manifests/ops-files/iaas/aws/bosh/tags.yml \
    -v director_name=bosh-aws \
    -v internal_cidr=${private_subnet_ip_prefix}.0/24 \
    -v internal_gw=${private_subnet_ip_prefix}.1 \
    -v internal_ip=${private_subnet_ip_prefix}.252 \
    -v access_key_id=${AWS_ACCESS_KEY_ID} \
    -v secret_access_key=${AWS_SECRET_ACCESS_KEY} \
    -v region=${region} \
    -v az=${zone} \
    -v default_key_name=${default_key_name} \
    -v default_security_groups=[${default_security_groups}] \
    --var-file private_key=${HOME}/deployer.pem \
    -v subnet_id=${private_subnet_id} \
    --vars-store=bosh-aws-creds.yml \
    --state bosh-aws-state.json
EOF
chmod +x deploy-bosh.sh
```

スクリプトを実行してBOSH Directorを作成してください。

```bash
./deploy-bosh.sh
```
次の図のような環境ができました。

![image](https://user-images.githubusercontent.com/106908/40372434-a36b332e-5e1f-11e8-90e0-7ea768bb2b2f.png)

BOSH Directorをアップデートしたい場合は`bosh-deployment`を`git pull`して`./deploy-bosh.sh`を再実行すれば良いです。

#### BOSH Directorの設定

BOSH Directorにアクセスするための設定を行い、BOSH Directorにログインします。

```bash
cat <<'EOF' > bosh-aws-env.sh
export BOSH_CLIENT=admin  
export BOSH_CLIENT_SECRET=$(bosh int ./bosh-aws-creds.yml --path /admin_password)
export BOSH_CA_CERT=$(bosh int ./bosh-aws-creds.yml --path /director_ssl/ca)
export BOSH_ENVIRONMENT=${private_subnet_ip_prefix}.252
EOF
chmod +x bosh-aws-env.sh
```

次のコマンドを実行してください。

```bash
source bosh-aws-env.sh
```

`bosh env`と`bosh login`を確認してください。

```
$ bosh env
Using environment '10.0.2.252' as client 'admin'

Name      bosh-aws  
UUID      7feb01e4-0eee-4eae-a735-8e3183428087  
Version   265.2.0 (00000000)  
CPI       aws_cpi  
Features  compiled_package_cache: disabled  
          config_server: enabled  
          dns: disabled  
          snapshots: disabled  
User      admin  

Succeeded
```

```
$ bosh login
Successfully authenticated with UAA

Succeeded
```

#### Stemcellのupload

BOSHが作成するVMのテンプレートイメージであるStemcellをアップロードします。

```
STEMCELL_VERSION=$(bosh int kubo-deployment/manifests/cfcr.yml --path /stemcells/0/version)
bosh upload-stemcell https://s3.amazonaws.com/bosh-aws-light-stemcells/light-bosh-stemcell-${STEMCELL_VERSION}-aws-xen-hvm-ubuntu-trusty-go_agent.tgz
```


#### Cloud Configのupdate

BOSH DirectorにIaaSの環境上を設定するためのCloud Configを作成します。

Cloud Configのテンプレートは[Officialのもの](https://github.com/cloudfoundry-incubator/kubo-deployment/blob/v0.17.0/configurations/aws/cloud-config.yml)を使いますが、`vm_type`名がなぜか[`cfcr.yml`](https://github.com/cloudfoundry-incubator/kubo-deployment/blob/v0.17.0/manifests/cfcr.yml)で使われている値と違うため、renameするためのops-fileを作成します...

```yaml
cat <<EOF > ops-files/cloud-config-rename-vm-types.yml
- type: replace
  path: /vm_types/name=master/name
  value: small
- type: replace
  path: /vm_types/name=worker/name
  value: small-highmem
- type: replace
  path: /compilation/vm_type
  value: small-highmem
EOF
```

`instance_type`を小さくします。

```yaml
cat <<EOF > ops-files/cloud-config-small-vm-types.yml
- type: replace
  path: /vm_types/name=minimal/cloud_properties/instance_type
  value: t2.micro
- type: replace
  path: /vm_types/name=small/cloud_properties/instance_type
  value: t2.micro
- type: replace
  path: /vm_types/name=small-highmem/cloud_properties/instance_type
  value: t2.medium
EOF
```

Master APIにLoadBalancerをアタッチするための`vm_extensions`を作成します。

```yaml
cat <<EOF > ops-files/cloud-config-master-lb.yml
- type: replace
  path: /vm_extensions?/-
  value:
    name: master-lb
    cloud_properties:
      elbs:
      - ((master_target_pool))
EOF
```

Cloud Configをupdateするためのスクリプトを作成します。

```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 \
    -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
chmod +x update-cloud-config.sh
```

次のコマンドを実行してください。

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

#### Kubernetesクラスタのデプロイ


Kubernetesのデプロイは[OfficialのManifest](https://github.com/cloudfoundry-incubator/kubo-deployment/blob/v0.17.0/manifests)をベースに差分をops-fileで適用する形で行います。


CFCR 0.17.0を使うops-fileを作成します。

```yaml
cat <<EOF > ops-files/kubernetes-kubo-0.17.0.yml
- type: replace
  path: /releases/name=kubo?
  value:
    name: kubo
    version: 0.17.0
    url: https://bosh.io/d/github.com/cloudfoundry-incubator/kubo-release?v=0.17.0
    sha1: 0ab676b9f6f5363377498e93487e8ba31622768e
EOF
```

Workerのインスタンス数を1に減らすops-fileを作成します。(Workerを増やしたい場合はこの値を変えてください)

```yaml
cat <<EOF > ops-files/kubernetes-worker.yml
- type: replace
  path: /instance_groups/name=worker/instances
  value: 1
EOF
```

MasterにLBをアタッチするための`vm_extensions`と、MasterのTLS証明書のSANにELBのDNS名を追加するops-fileを作成します。

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

- type: replace
  path: /variables/name=tls-kubernetes/options/alternative_names/-
  value: ((kubernetes_master_host))
EOF
```

デプロイ時に追加で登録したいAddonは`specs`ディレクトリ以下で管理します。

```bash
mkdir -p specs
```

EBS用のStorageClassをデフォルトとして登録するSpecを作成します。

```yaml
cat <<EOF > specs/aws-storage-class.yml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: standard
  annotations:
    storageclass.beta.kubernetes.io/is-default-class: "true"
  labels:
    kubernetes.io/cluster-service: "true"
    addonmanager.kubernetes.io/mode: EnsureExists
provisioner: kubernetes.io/aws-ebs
parameters:
  type: gp2
EOF
```

Kubrnetesをデプロイするスクリプトを作成します。

```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 \
    --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
chmod +x deploy-kubernetes.sh
```

次のコマンドを実行してデプロイしてください。(途中で`y`を入力する必要があります。)

```bash
./deploy-kubernetes.sh
```

次の図のような環境ができました。

![image](https://user-images.githubusercontent.com/106908/40374599-59ebcdb2-5e24-11e8-8631-af8ef0c5f39d.png)

`bosh vms`、`bosh instances --ps`を実行してVM一覧、プロセス一覧を確認してください。

```
$ bosh -d cfcr vms
Using environment '10.0.2.252' as client 'admin'

Task 13. Done

Deployment 'cfcr'

Instance                                     Process State  AZ  IPs       VM CID               VM Type        Active  
master/bc14d482-2481-4cd4-ab61-f8998959befe  running        z1  10.0.2.4  i-07b65c52ed5de9bfa  small          -  
worker/9a57034a-99a5-48cb-9db0-59841e083a8c  running        z1  10.0.2.5  i-0cadb8a54cec35909  small-highmem  -  
```

```
$ bosh -d cfcr instances --ps
Using environment '10.0.2.252' as client 'admin'

Task 14. Done

Deployment 'cfcr'

Instance                                           Process                  Process State  AZ  IPs  
apply-addons/70988ada-d3b8-4015-b2a7-de93ebd21e92  -                        -              z1  -  
master/bc14d482-2481-4cd4-ab61-f8998959befe        -                        running        z1  10.0.2.4  
~                                                  bosh-dns                 running        -   -  
~                                                  bosh-dns-healthcheck     running        -   -  
~                                                  bosh-dns-resolvconf      running        -   -  
~                                                  etcd                     running        -   -  
~                                                  flanneld                 running        -   -  
~                                                  kube-apiserver           running        -   -  
~                                                  kube-controller-manager  running        -   -  
~                                                  kube-scheduler           running        -   -  
worker/9a57034a-99a5-48cb-9db0-59841e083a8c        -                        running        z1  10.0.2.5  
~                                                  bosh-dns                 running        -   -  
~                                                  bosh-dns-healthcheck     running        -   -  
~                                                  bosh-dns-resolvconf      running        -   -  
~                                                  docker                   running        -   -  
~                                                  flanneld                 running        -   -  
~                                                  kube-proxy               running        -   -  
~                                                  kubelet                  running        -   -  

18 instances
```

CFCRがアップデートされた場合は、Breaking Changeがなければ`kubo-deployment`を`git pull`して、`./deploy-kubernetes.sh`を実行すれば良いです。

#### Addonのdeploy

KubeDNS, Kubenetes DashboardなどのAddonはerrandでデプロイされます。次のコマンドを実行してください。

```bash
bosh -d cfcr run-errand apply-addons
```

#### CredHubへのログイン

Kubernetesクラスタに関するCredentials情報はBOSH Director VM内のCredHubに保存されています。
TLS証明書やAdminのパスワードを取得するにはCredHubにアクセスする必要があります。

CredHubにログインするためのスクリプトを作成します。

```bash
cat <<'EOF' > credhub-login.sh
#!/bin/bash
credhub login \
        -s ${BOSH_ENVIRONMENT}:8844 \
        --client-name=credhub-admin \
        --client-secret=$(bosh int ./bosh-aws-creds.yml --path /credhub_admin_client_secret) \
        --ca-cert <(bosh int ./bosh-aws-creds.yml --path /uaa_ssl/ca) \
        --ca-cert <(bosh int ./bosh-aws-creds.yml --path /credhub_ca/ca)
EOF
chmod +x credhub-login.sh
```

スクリプトを実行してCredHubにログインしてください。

```bash
./credhub-login.sh
```

CredHubへのアクセストークンは1時間で切れるので、有効期限が切れたら再度ログインしてください。

#### Kubernetesへアクセス

AdminのパスワードをCredHubから取得します。

```bash
admin_password=$(credhub get -n /bosh-aws/cfcr/kubo-admin-password | bosh int - --path=/value)
```

Master APIのTLS CA証明書を取得します。

```bash
tmp_ca_file="$(mktemp)"
credhub get -n /bosh-aws/cfcr/tls-kubernetes | bosh int - --path=/value/ca > "${tmp_ca_file}"
```

`kubectl`のContextを設定します。

```bash
cluster_name="cfcr-aws"
user_name="admin-aws"
context_name="cfcr-aws"

kubectl config set-cluster "${cluster_name}" \
  --server="https://${master_lb_ip_address}:8443" \
  --certificate-authority="${tmp_ca_file}" \
  --embed-certs=true

kubectl config set-credentials "${user_name}" --token="${admin_password}"

kubectl config set-context "${context_name}" --cluster="${cluster_name}" --user="${user_name}"

kubectl config use-context "${context_name}"
```

`kubectl cluster-info`でクラスタ情報を確認してください。

```
$ kubectl cluster-info
Kubernetes master is running at https://demo-cfcr-api-658626716.ap-northeast-1.elb.amazonaws.com:8443
Heapster is running at https://demo-cfcr-api-658626716.ap-northeast-1.elb.amazonaws.com:8443/api/v1/namespaces/kube-system/services/heapster/proxy
KubeDNS is running at https://demo-cfcr-api-658626716.ap-northeast-1.elb.amazonaws.com:8443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
monitoring-influxdb is running at https://demo-cfcr-api-658626716.ap-northeast-1.elb.amazonaws.com:8443/api/v1/namespaces/kube-system/services/monitoring-influxdb/proxy
```

Master APIはInternet FacingなELBにアタッチされているので、`~/.kube/config`の内容はBastionサーバー以外でも利用可能です。


最終的にこの記事で使用するEC2インスタンスは次の通りです。

![image](https://user-images.githubusercontent.com/106908/40376301-f97e7fa6-5e28-11e8-99cf-e40fd3a309ff.png)


### クラスタのスケールアウト

Workerを2インスタンス、Masterを3インスタンスにスケールアウトしましょう。

```yaml
cat <<EOF > ops-files/kubernetes-worker.yml
- type: replace
  path: /instance_groups/name=worker/instances
  value: 2
EOF
```

```bash
cat <<'EOF' > deploy-kubernetes.sh
#!/bin/bash
bosh deploy -d cfcr kubo-deployment/manifests/cfcr.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 \
    --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 
```

`bosh vms`でVM一覧を確認。

```
$ bosh -d cfcr vms
Using environment '10.0.2.252' as client 'admin'

Task 61. Done

Deployment 'cfcr'

Instance                                     Process State  AZ  IPs       VM CID               VM Type        Active  
master/485d11d9-6390-40d7-97dd-b6f92b3148c6  running        z2  10.0.2.7  i-0f6a5ceca5c869797  small          -  
master/7e776fbe-ea80-499c-b1d6-9f1aa8af29bc  running        z3  10.0.2.8  i-01ef1a2a6b0e38f84  small          -  
master/bc14d482-2481-4cd4-ab61-f8998959befe  running        z1  10.0.2.4  i-0e0c6b90f7b2ee10d  small          -  
worker/9a57034a-99a5-48cb-9db0-59841e083a8c  running        z1  10.0.2.5  i-03d3204bfe5f4ba1f  small-highmem  -  
worker/ac71f182-ce0b-4c6d-8811-2605c3248121  running        z2  10.0.2.9  i-0412554a975042d05  small-highmem  -  

5 vms

Succeeded
```

EC2コンソールは次のようになります。

![image](https://user-images.githubusercontent.com/106908/40799521-c1c855c4-6548-11e8-9745-4abadb9680b4.png)

### CFCRのdestroy

使い終わった環境は削除します。

#### Kubernetesクラスタの削除

Kubernetesを次のコマンド削除します。
なお、KubernetesがprovisioningしたService用のELBやPersistentVolume用のEBSはBOSH管理外なので、`kubectl`コマンドで事前に削除してください。

```bash
bosh -d cfcr delete-deployment
bosh -n clean-up --all
```

#### BOSH Directorの削除

BOSH Directorを次のコマンドで削除します。

```bash
eval "$(sed 's/create-env/delete-env/' deploy-bosh.sh)"
```

#### AWS環境の削除

AWS環境を次のコマンドで削除します。

```bash
terraform destroy
```


### Pivotal Container Serviceについて

CFCRを使えばBOSHを用いてKubernetesを簡単にデプロイでき、スケールアウト、アップデート、自動復旧も容易です。
CFCRはOSSですが、これのエンタープライズ版に相当するのが[Pivotal Container Service(PKS)](https://pivotal.io/platform/pivotal-container-service)です。

PKSでは、Kubernetesクラスタを一つ一つ手でインストールするのではなく、PKS ControllerというAPIサーバーがこの記事の内容を実行してKubernetesクラスタを作成してくれます。

PKSユーザーは

```
pks create-cluster my-k8s --external-hostname my-k8s.example.com --plan small --num-nodes 3
```

というコマンドを実行すれば、クラスタが作成されます。

次の図のようになります。

![image](https://user-images.githubusercontent.com/106908/40376882-7350c66c-5e2a-11e8-81bb-a1f4209e078b.png)

CFCRのKubernetesクラスタをオンデマンドで作成するのがPKSです。

あとはCNI実装としての[NSX-T](https://docs.vmware.com/jp/VMware-NSX-T/index.html)連携や[Habor](https://vmware.github.io/harbor/) Docker Registry連携などもあります。
1.0ではIaaSとしてvSphereとGCPのみサポートされていますが、他のIaaSも順次対応予定です。

このブログでも今後PKSのインストールについて扱いたいと思います。

興味のある方は[ドキュメント](https://docs.pivotal.io/runtimes/pks/)を参照しつつ、[@making](https://twitter.com/making)にも声をかけてみてください。
