本スライドは「Kubernetes Meetup Tokyo #3」の登壇資料です。
Highly available and scalable Kubernetes on AWS
TL;DR;
- 「高い可用性とスケーラビリティを確保したKubernetesクラスタを、AWS上で本番運用するにあたって得られた知見」を共有します
- 「コンテナベースのインフラを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 Loggingを利用
- 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のデプロイツールまとめ
- kopsと迷った
困っていること
困っていること 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の仕様)
- copytruncateありだと、ログの流量が多いコンテナでは、ログローテート中に発生したログが消える(はず)
- 対策: Docker自体のログローテーション機能
困っていること 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に与えたい
- 課題: 「必要最小限の権限セット」というものがまだ存在しない
まとめ
- 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
- PR: https://github.com/kubernetes/contrib/pull/2226
今後のロードマップ 2/3
柔軟なネットワークトポロジ
- Private/Public Subnetの混在
- Internet/NAT Gatewayの柔軟な割当
- Issues
※半分くらいは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をおすすめしてます
- そういうときはkopsをおすすめしてます
困っていること 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)
- 例: しばらく運用しているとノードのCPU利用率が100%になる問題
全体のまとめ
全体のまとめ
- 可用性、スケーラビリティを確保したKubernetesクラスタを、AWS上で本番運用しています
- コアな部分にOSSを採用して、メンテナになることで結果的に先んじて課題を解決することができました
- kube-awsぜひ使ってみてください