Highly available and scalable Kubernetes on AWS for Kubernetes users 日本語版

本スライドは「Kubernetes Meetup Tokyo #3」の登壇資料です。

https://k8sjp.connpass.com/event/47525/

---

# Highly available and scalable Kubernetes on AWS

---

# TL;DR;

* 「高い**可用性**と**スケーラビリティ**を確保した**Kubernetes**クラスタを、**AWS**上で**本番運用**するにあたって得られた知見」を共有します :hearts:
* 「**コンテナベースのインフラ**を**AWS**で**本番運用**したい方」向けに話します
* KubernetesやAWSについてはある程度わかっている前提

---

# 自己紹介

twitter/github/slack.k8s.io: @mumoshu (むもしゅ)

* 数十人くらいの規模のWeb企業でインフラエンジニアとして働いています
* 半分仕事で、kube-awsというOSSの唯一のメンテナをしています

kube-aws: https://github.com/coreos/kube-aws

---

# アジェンダ 1/3

* Kubernetes on AWSの本番運用について
  * 何を実現したか
  * 困っていること
  * うまくいっていること
  * 今後のロードマップ
  * まとめ

---

# アジェンダ 2/3

* kube-awsについて
  * 何のためのツールか
  * 基本的な使い方
  * kube-aws機能リスト
  * kube-awsピンチ集
  * 今後のロードマップ
  * まとめ

---

# アジェンダ 3/3

* kube-awsメンテナ話
  * 困っていること
  * よかったこと

* まとめ

---

# Kubernetes on AWSの本番運用について

---

## 何を実現したか

---

### 何を実現したか 1/3

* 自社用のKubernetesクラスタをAWS上に構築
  * 高可用性
     * SPOFなし(Pod、ノードどちらのレベルでも)
  * 高スケーラビリティ
     * ノードは短時間で追加できる(Etcd除く)
  * 社内の他のサービスと通信可能

---

### 何を実現したか 2/3

* 運用負荷の軽減と分散
  * アプリの問題はログとkubectlがあれば(ほぼ)特定できるように
  * Kubernetesノードの追加、削除は自分以外でもできるように

---

### 何を実現したか 3/3

* 保守性を確保しつつコスト圧縮
  * 複数のコンテナが必要に応じてホストに相乗り
  * KubernetesのResource QoSで特定のコンテナが他のコンテナのパフォーマンスや安定性に影響を与えないように
  * Dockerを活用した自社PaaSのようなものを開発しなくても済んだ

---

## うまくいっていること

---

### うまくいっていること 1/6

* コンテナ、Podの監視に**Datadog**を利用
  * kube-dns、fluentdそれぞれ関連するメトリクスを見渡せるダッシュボード
* 分散ロギングのため**fluentd + GCP Stackdriver Loggin**gを利用
  * fluentdは時折OOMで落ちる以外はOK
  * StackdriverはCLI、Web UIでログをフィルタ付きでtailできて、ログをBigQueryに貯めることもできるう

---

### うまくいっていること 2/6

* init process (pid=0)に**s6-overlay**を採用
  * fluentd, logrotateなどのシステム用のPod

---

### うまくいっていること 3/6

既存サービスとの連携

* Kubernetes管理内サービスが、管理外の他のサービスと通信できるように
* 既存のVPCにKubernetes用のSubnetを新たに複数作成し、各ノードを配置(Multi-AZ)
* Route TableでSubnet間をつなぐ

---

### うまくいっていること 4/6

Kubernetes専任担当がいなくても(なんとか)回る運用

* アプリで使うコンテナイメージにはあえて制限を設けない
* ノード追加・削除はKubernetes担当でなくてもできるようにする
* kubectlは全員使えるようにする(スキル的にも権限的にも)

---

### うまくいっていること 5/6

H/Aとオートスケーリング対応の両立/cluster-autoscaler(CA)の落とし穴回避

* CAは「PendingになっているPodが動いているノード」の所属ASGの「サイズ調整」をする
* ASGが1aと1bの両方に割り当てられていると、サイズを増やしたときにどちらのAZにノードが追加されるかコントロールできない
* ASGをAZ毎につくって回避

---

### うまくいっていること 6/6

* kube-awsの採用
  * kopsと迷った
     * kops = OS/Cloud-agnosticなKubernetesのCRUDツール
     * kube-aws = AWS/CoreOS specificな機能が沢山あるKubernetesのCRUD?ツール
  * Qiita: [Kubernetesのデプロイツールまとめ](http://qiita.com/mumoshu/items/72ae0f07a58a37626204)

---

## 困っていること

---

### 困っていること 1/3

EtcdのMulti-AZ構成のために3 AZ使いたいのに使えない

* 前提: EtcdはQuorumベースなので、ノード台数は1, 3, 5, ...のように増やす。Elasticsearchなどと一緒
* AWS Tokyoリージョンには3　AZあるが、各ユーザには基本的に2 AZしか開放されていない
* 1a:1台、 1b:2台のようにアンバランスに配置しているが、1bが仮に落ちたら終わり(H/A??)

---

### 困っていること 2/3

* コンテナのログローテートにlogrotateを採用したが…
  * よくよく考えると、ログローテートのタイミングでログを取りこぼしているはず
  * **kubernetesレポジトリにlogrotateの設定ファイルがある**からといって安心してはいけない

---

#### logrotateをおすすめしない背景 1/2

* Kubernetesはdockerのロギングドライバがjson-file前提
  * (試してないけど)例えばfluentdドライバにしたら、kubectl logsは動くの?
  * 参考: https://github.com/kubernetes/kubernetes/issues/15478

---

#### logrotateをおすすめしない背景 2/2

* copytruncateなしだと、ログローテート後にそのコンテナのログが一切出なくなる(DOckerの仕様)
  * [Add log rotation signal handling to docker daemon · Issue #7333 · docker/docker](https://github.com/docker/docker/issues/7333)
* copytruncateありだと、ログの流量が多いコンテナでは、ログローテート中に発生したログが消える(はず)
* 対策: Docker自体のログローテーション機能
  * https://github.com/coreos/kube-aws/issues/134

---

### 困っていること 3/3

* kube-dnsが不安定
  * 数日に一度、数podが落ちる
  * Deploymentなのでkube-dns自体は数分で自動復旧する
  * しかし、kube-dns復旧後も、他のアプリPodから名前解決が不安定になる(例:`java.lang.UnknownHostException`が出続ける)**ことがある**

---

## 今後のロードマップ

---

### 今後のロードマップ 1/3

スポットインスタンス活用

* 100%のEC2インスタンスをリザーブドやオンデマンドで構成する必要はない

---

### 今後のロードマップ 2/3

複雑なネットワークトポロジに対応

* Public/Private Subnetを混ぜられるようにする
* 連携先サービスの都合で固定IPを要求されるようなサービスに対応(NAT Gateway and/or EIP)
* 一部ノードだけをPrivate Subnetに配置

---

### 今後のロードマップ 3/3

RBAC(Role-Based Access Control)有効化

* 必要最小限のKubernetes API呼び出し権限を各Podに与えたい
* 課題: 「必要最小限の権限セット」というものがまだ存在しない
  * [RBAC feature should also provide minimally needed roles · Issue #230 · coreos/kube-aws](https://github.com/coreos/kube-aws/issues/230)

---

## まとめ

* Kubernetes on AWSを本番運用しています
* DNSとログローテートには注意
* スポットインスタンス活用、ノードのオートスケーリング、ネットワークトポロジ、RBACはまだツールのサポートが弱い
* Kubernetes自体は概ね安定して動いています

---

# kube-awsについて

---

## 何のためのツールか 1/2

* 一般的には「AWS上でKubernetesクラスタをCRUDするツール」
* 個人的には「良くも悪くも、AWS上にKubernetesクラスタを構築するためのCloudFormationスタックテンプレートを出力するツール」

---

## なんのためのツールか 2/2

cloud-config、CloudFormationでできること(かなり多い)はなんでもカスタマイズ可能

* あらゆるユーザの全ての要件に答えるツールは開発できない
* 代表的なユースケースはツールでサポートする
* kube-awsが対応できないことは、kube-awsがエクスポートした各ファイルを変更して各自やって!

---

## 基本的な使い方 1/3

Kubernetesクラスタをつくる

```
$ kube-aws init \
    --cluster-name ${KUBE_AWS_CLUSTER_NAME} \
    --external-dns-name ${EXTERNAL_DNS_NAME} \
    --region ${KUBE_AWS_REGION} \
    --availability-zone ${KUBE_AWS_AVAILABILITY_ZONE} \
    --key-name ${KUBE_AWS_KEY_NAME} \
    --kms-key-arn ${KUBE_AWS_KMS_KEY_ARN}
$ $EDITOR cluster.yaml
$ kube-aws render
$ kube-aws validate --s3-uri ${KUBE_AWS_S3_URI}
$ kube-aws up
$ kube-aws update
```

---

## 基本的な使い方 2/3

ノードプールを追加する

```
$ kube-aws node-pools init --node-pool-name $(nodepool_name) \
      --availability-zone ${KUBE_AWS_AVAILABILITY_ZONE} \
      --key-name ${KUBE_AWS_KEY_NAME} \
      --kms-key-arn ${KUBE_AWS_KMS_KEY_ARN}
$ $EDITOR node-pools/$(nodepool_name)/cluster.yaml
$ kube-aws node-pools render stack --node-pool-name $(nodepool_name)
$ kube-aws node-pools validate --node-pool-name $(nodepool_name) --s3-uri ${KUBE_AWS_S3_URI}
$ kube-aws node-pools up --node-pool-name $(nodepool_name) --s3-uri ${KUBE_AWS_S3_URI}
```

---

## 基本的な使い方 3/3

カスタマイズ

* `cluster.yaml` (Kubernetesクラスタ全体の設定)
* `userdata/cloud-config-{worker,controller,etcd}` (各ノード用にインストールするファイルやsystemd unitなど
* `credentials/*.pem` (各種TLS証明書)
* `stack-template.json` (CloudFormationスタックテンプレートテンプレート)

---

## kube-aws機能リスト

* 自動復旧: 落ちたノードは自動再作成(Etcd以外)
* Node Labels機能: 任意のNode Labelを自動付与できる。nodeSelectorに。
* Taints機能: 任意のTaintを自動付与できる。特定Pod専用にしたいノードに、Tolerationsと合わせて。
* Spot Fleet対応: AWSのSpot Fleetで可用性とコスト削減を両立。
* Calico対応: Network Policyの実装に。

---

## kube-awsピンチ集

---

### kube-awsピンチ集 1/2

* CloudFormationの上限に引っかかる
  * スタックテンプレートサイズ上限は50KB
  * 色々カスタマイズすると超えてしまう
  * S3に一旦アップロードすると上限が450KBに

---

### kube-awsピンチ集 2/2

* EC2 UserDataの上限に引っかかる
  * cloud-configなどに使うUserDataの上限は16KB
  * 色々カスタマイズすると超えてしまう
  * S3に一旦アップロードすると上限なし(?)に

---

## 今後のロードマップ

---

## 今後のロードマップ 1/3

cluster-autoscalerの設定自動化

* Auto Scaling Groupのサイズ変更するたびに、cluster-autoscalerの設定を変えて再起動しなければならない点を改善
* Issue
  * https://github.com/kubernetes/contrib/issues/2181
  * https://github.com/coreos/kube-aws/issues/148
* PR: https://github.com/kubernetes/contrib/pull/2226

---

## 今後のロードマップ 2/3

柔軟なネットワークトポロジ

* Private/Public Subnetの混在
* Internet/NAT Gatewayの柔軟な割当
* Issues
  * https://github.com/coreos/kube-aws/issues/44
  * https://github.com/coreos/kube-aws/issues/152

※半分くらいはkopsで既に実装されている

---

## 今後のロードマップ 3/3

複数のkube-awsクラスタをGitでバージョン管理

* 生成物を各企業の要件に応じてカスタマイズ
* クラスタ毎にGitブランチに
* kube-awsのバージョンを上げたら、デフォルトの生成物をmasterにpushして、各ブランチでコンフリクト解消
* Issue: https://github.com/coreos/kube-aws/issues/238

---

## kube-awsのまとめ

---

### kube-awsのまとめ

* 一般的には、KubernetesクラスタのCRUDツール
* Kubernetes on AWSの本番運用という観点からすると、「自由にカスタマイズ可能なKubernetesクラスタのテンプレートを出力するツール」

---

# kube-awsメンテナ話

---

## 困っていること

---

### 困っていること 1/2

* GitHub Issuesが質問サイトに
  * 色々聞いてみると、カスタマイズやAWSアカウントのリソース上限に引っかかっているだけ、ということも
* ユーザがt2.microを使おうとする
  * ※Kubernetes公式に非推奨です
* **Terraform**に対応してほしいという要望がくる
  * そういうときは**kops**をおすすめしてます :cry: 

---

### 困っていること 2/2

E2Eテストが大変

* 実KubernetesクラスタにConformance Testを実行する
* Conformance Test: 「Kubernetesが正常に動いている」といえる最小限の機能のテスト
* kube-awsでは機能追加するたびに行っている
* kopsのE2EテストはなんとKubernetes自体の自動ビルドに組み込まれている模様
* kube-awsもいれてーー

---

## よかったこと 1/2

* 他社のニーズから自社の将来のニーズを学べる
  * 例: EC2のUserData、CloudFormationのスタックテンプレートのサイズの上限に引っかかる
  * 基本的には自分で直さなければならないことに変わりはない。しかし、
  * 本番環境で問題が露呈する前に直せる（事が多くなる）のはメリット

---

## よかったこと 2/2

* 長期運用すると見えてくる課題に先に気付ける
  * 例: しばらく運用しているとノードのCPU利用率が100%になる問題
     * rktのバグを踏んでいた (https://github.com/coreos/rkt/issues/3181)

---

## 全体のまとめ

---

## 全体のまとめ

* 可用性、スケーラビリティを確保したKubernetesクラスタを、AWS上で本番運用しています
* コアな部分にOSSを採用して、メンテナになることで結果的に先んじて課題を解決することができました
* kube-awsぜひ使ってみてください

---

# Fin :bow: :clap: 

---

## kube-aws: https://github.com/coreos/kube-aws