Rancher を使ってCloudProviderを使ってみた(on AWS)

この記事は [エーピーコミュニケーションズ Advent Calendar 2018](https://qiita.com/advent-calendar/2018/ap-com) の 20 日目の記事となります。

# はじめに
今回は Kubernetes(k8s) の CloudProvider の実装を説明します。
そもそも CloudProvider とは各種クラウドで k8s を実装した際に、各リソース(Volume や Service)をクラウドのリソース(ELB や EBS)を使って実装することができる機能となっております。
社内研修の一環として k8s / Rancher について学習した際に、検証として CloudProvider について調査を行いました。
今回は AWS の EC2 上に Rancher を使って k8s 環境を構築し、構築したクラスターに対し CloudProvider の機能を実装、合わせて利用方法について説明したいと思います。

# サーバ構成

今回構築するサーバーの構成です。

* Rancher x 1
  * インスタンスタイプ：t3.medium
* Control & etcd x 1
  * インスタンスタイプ：t3.small
* Worker x 1
  * インスタンスタイプ：t3.small
* 共通
  * AMI：CentOS 7
  * docker：17.03.2
  * k8s：1.11
  * Rancher：2.1.1

※今回は rancher / k8s についてがメインとなりますので AWS の説明は省いております。
ご了承ください。

# 事前準備

## AWS ( IAM - 全般 )

事前に以下のポリシーが付与されている IAM アカウントを用意します。
用意したアカウントでインスタンスを構築します。

* PowerUserAccess
* IAM Role の参照、EC2インスタンスへの付与が出来る権限(iam:PassRole)

### AWS ( IAM - Role )

事前に以下のポリシーが適用されている Role を作成しておく。

- [Create an IAM Role and attach to the instances](https://rancher.com/docs/rancher/v2.x/en/cluster-provisioning/rke-clusters/options/cloud-providers/#create-an-iam-role-and-attach-to-the-instances)

# 構築

AWS 上に以下のインスタンスを構築していきます。

## AWS インスタンスの構築(3サーバ共通)

【ステップ 1】: Amazon マシンイメージ (AMI)：CentOS 7 (x86_64) - with Updates HVM
【ステップ 2】: インスタンスタイプの選択：サーバ構成のインスタンスタイプを指定
【ステップ 3】: インスタンスの詳細の設定：
　**・IAM ロール：事前に用意したロールを指定(今回は RancherRole という名前で用意しています)**
![img-01.jpg](https://qiita-image-store.s3.amazonaws.com/0/317159/de86775c-79c5-bfe8-2178-fb796fae4c00.jpeg)
【ステップ 4】: ストレージの追加：8 GiB / 汎用SSD ( gp2 )
【ステップ 5】: タグの追加
**・Key = kubernetes.io/cluster/CLUSTERID**
**・Value = owned**
※ CLUSTERIDは任意の識別子を付ける(3 台共同じ ID)
【ステップ 6】セキュリティグループを指定

**※IAM ロールの指定、およびタグの追加以外は基本的な EC2 の構築と変わりません。**

## VPC(Subnet) / SecurityGroup にタグを付与

以下のリソースにも EC2 インスタンスに付与したタグを付与する

* VPC(Subnet)
* SecurityGroup

付与するタグ
**・Key = kubernetes.io/cluster/CLUSTERID**
**・Value = owned**
※CLUSTERID は EC2 インスタンスに付与した識別子と同じ値を指定する

## Docker / Rancher 構築

Docker / Rancher の構築は弊社 T氏の以下記事を参考に構築します。
[Rancher2.0を使って超高速にkubernetesクラスタを構築した時のメモ](https://qiita.com/3364git/items/287fdf3685cebb4a7ce8)

## k8s クラスタ構築

k8s クラスタの構築も上記 T氏の記事を参考に構築します。

**【注意】**

クラスタを構築する際に以下を指定してください。

クラスタタイプ

* k8s サービスを利用せず、EC2 にインスタンスを構築して実装している為、クラスターのタイプで【 CUSTOM 】を指定してください。

 ![img-02.jpg](https://qiita-image-store.s3.amazonaws.com/0/317159/e9e6c146-a762-49c9-cf6f-7ebf98843449.jpeg)

クラスタオプション

* クラスターのオプションで左下の【 CloudProvider 】の項目において【 Amazon 】を指定してクラスターを作成してください。

![img-03.jpg](https://qiita-image-store.s3.amazonaws.com/0/317159/ada35887-bce1-f2af-4c5d-7803c69f1bc6.jpeg)

# CloudProvider を使ったリソース作成

## Service(LoadBalancer)

Rancher 管理画面から【ワークロード】⇒【YAML を インポート】より、以下で Deployment をデプロイしてみましょう。
※nginx の Pod と Service を定義しています。

```
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nginx
spec:
  selector:
    matchLabels:
      run: my-nginx
  replicas: 2
  template:
    metadata:
      labels:
        run: my-nginx
    spec:
      containers:
      - name: my-nginx
        image: nginx
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: my-nginx
  labels:
    run: my-nginx
spec:
  ports:
  - port: 80
    protocol: TCP
  selector:
    run: my-nginx
  type: LoadBalancer
```

実行後、AWS のコンソールを確認してみましょう。
ELB に一台 LoadBalancer が追加されております。
これは CloudProvider によって Service(LoadBalancer) で定義されたリソースを ELB で実装された形となります。

## PersistentVolume

PersistentVolume 作成前に PersistentVolume 作成用の StorageClass を作成します。

* クラスターの【ストレージ】⇒【ストレージクラス】から【クラスを追加】でストレージクラスを追加します
* 名前は任意で指定し、プロビジョナーを【Amazon EBS ディスク】を指定して作成します

![image.png](https://qiita-image-store.s3.amazonaws.com/0/317159/62ff804a-b905-0bb7-8bf4-b0924d93e74f.png)


それでは実際に PersistentVolume を作成してみましょう

* 各プロジェクト(名前空間)の【ワークロード】⇒【ボリューム】から【ボリューム追加】でボリュームを追加します
* 【ストレージクラス】を上記で作成した際のストレージクラス名を選択します
* 【容量】は適当に指定します(まずは 1GiB 程度から)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/317159/4ac30f64-0b3a-0e40-c150-1c09baf780db.png)

実行後、AWS のコンソールを確認してみましょう。
EBS に一つ Volume が追加されております。
これは CloudProvider によって PersistentVolume で定義されたリソースを EBS で実装された形となります。
まだ、どこにも割り振っていない為、available の状態が確認できると思います。

Service 同様、PersistentVolume でも nginx の Pod を作成し実際にVolumeをマウントさせてみましょう。

```
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nginx
spec:
  selector:
    matchLabels:
      run: my-nginx
  replicas: 2
  template:
    metadata:
      labels:
        run: my-nginx
    spec:
      containers:
      - name: my-nginx
        image: nginx
        ports:
        - containerPort: 80
        volumeMounts:
        - mountPath: /usr/share/nginx/html
          name: vol1
      volumes:
      - name: vol1
        persistentVolumeClaim:
          claimName: ###### <Volume名> ######
```

無事に Pod の作成、Volume のマウントが完了すると、EBS の available の状態から in-use の状態に変わったことが確認できると思います。

# まとめ

CloudProvider の実装・利用説明については以上となります。
PersistentVolume を利用する際に、NFS等の別の機構を用意する必要が無くなり、マネージドなリソースが利用できるのはメリットとはなりますが、HA や運用については別途検討が必要と考えています。
また、Service についてはマネージドな LB である ELB を利用でき、自動でアタッチしてくれることはメリットと考えています。
AWS での k8s 実装は EKS が主流となりそうですが、機構を学習するという面ではよい勉強になったと思っています。
AWS での k8s 実装の参考になれば幸いです。

# 参考サイト

* [Get Docker CE for CentOS](https://docs.docker.com/install/linux/docker-ce/centos/)
* [Node Requirements](https://rancher.com/docs/rancher/v2.x/en/installation/requirements/)
* [Selecting Cloud Providers](https://rancher.com/docs/rancher/v2.x/en/cluster-provisioning/rke-clusters/options/cloud-providers/)