Slide 1

Slide 1 text

Kubernetesクラスタの ⾃動管理システムのつくりかた サイボウズ株式会社 池添 明宏 1 CloudNative Days Tokyo 2019 2019/07/22

Slide 2

Slide 2 text

⾃⼰紹介 • 池添 明宏 (Ikezoe Akihiro) • ソフトウェアエンジニア • 2016年にサイボウズに中途⼊社 • 運⽤本部所属 • ⾃作キーボードにハマりつつある 2 @zoetrope @zoetro

Slide 3

Slide 3 text

本⽇の発表内容 • Kubernetes クラスタの⾃動管理システムをつくった話 • 構築や運⽤を⾃動化する仕組み • Vault を利⽤した秘密情報の管理⽅法 • ⾼可⽤性を実現する仕組み 3

Slide 4

Slide 4 text

インフラ刷新プロジェクト Neco 4

Slide 5

Slide 5 text

インフラ刷新プロジェクト Neco とは • Cloud Native 技術を活⽤して、サイボウズの インフラを刷新するプロジェクト • ⾃社データセンターの1,000台規模のサーバー上 に Kubernetes クラスタを構築 • パブリッククラウドにも負けない最⾼の インフラを⽬指す 5

Slide 6

Slide 6 text

Neco が⽬指す最⾼のインフラ • ⾼可⽤、⾼信頼、⾼性能、セキュア、低コスト • 開発者には柔軟に利⽤できる使いやすい環境を提供 • ⼿作業やトイルを削減し運⽤者の負担を減らす 6 ⼀切の妥協なし︕

Slide 7

Slide 7 text

Neco の構成 7 3~5台の管理サーバー 1,000台規模のサーバー Kubernetes クラスタ マネージドサービス (ロードバランサー、モニタリング、データベースなど) サイボウズ製品のアプリケーションコンテナ App App App App App App App App App App App App 継続的デリバリー 管理 構築

Slide 8

Slide 8 text

Kubernetes クラスタ構築・運⽤の課題 • 1,000台のサーバーの構築・運⽤ • ⾼可⽤性の実現 • 機材の⾃動⼊れ替え • 秘密データの管理 8

Slide 9

Slide 9 text

課題を解決すべく 管理ツールを⾃作しよう 9

Slide 10

Slide 10 text

Kubernetes クラスタ⾃動管理システム CKE 10

Slide 11

Slide 11 text

CKE (Cybozu Container Engine) • Kubernetes クラスタの構築と運⽤を⾃動化するツール • https://github.com/cybozu-go/cke • 特徴 • 構築だけでなく運⽤まで⾃動化 • Declarative Configuration • バックエンドには etcd と Vault を利⽤ • Go ⾔語で開発 11

Slide 12

Slide 12 text

既存ツールとの⽐較 • Kubernetes クラスタの構築ツールは数多く存在するが、運⽤の⾃動化まで サポートするツールはあまり⾒当たらない。 • RKE (Rancher Kubernetes Engine) • Kubernetes is Everywhere • Declarative Configuration • 構築、バージョンアップ、ノードの増減 を⾃動化 • Ingress, CNI Plugin, DNS アドオン 12

Slide 13

Slide 13 text

RKE と CKE の機能の違い RKE v0.2.5 (Rancher) CKE v1.14.12 プログラムの形態 コマンドラインツール 常駐プログラム 対応コンテナランタイム Docker のみ Docker と CRI Runtime に対応 証明書の管理 ファイルに書き出して保存 Vault で管理 Secret リソースの暗号化 未対応 Vault を利⽤した暗号化に対応 apiserver のロードバラン サー nginx ⾃作軽量TCPリバースプロキシ(rivers) Kubernetes の拡張 API Aggregation API Aggregation, Scheduler Extender NodeLocal DNSCache 未対応 対応 Kubernetes リソースの管 理 Ingress, CNI Plugin, DNS などが選択利⽤ 可能 アドオンで任意のリソースも利⽤可能 DNS は CoreDNS を利⽤(固定) 任意のリソースを扱う仕組みあり Backup Disaster Recovery etcd のバックアップ(ローカル or S3) リカバリーコマンド etcd のバックアップ(PVに保存) Kubernetes バージョン 任意のバージョンが利⽤可能 CKEのバージョンと連動 コンテナイメージの変更 可能 利⽤コンテナイメージは固定

Slide 14

Slide 14 text

なぜ既存のツールを利⽤しなかったのか • Rancher (RKE) は、様々な環境に簡単に Kubernetes クラスタを構築で きる素晴らしいツール • しかし、⼀部要件にマッチしなかった • ⾃作することで Kubernetes クラスタの運⽤ノウハウ蓄積を狙った 14

Slide 15

Slide 15 text

CKE の基本動作 15

Slide 16

Slide 16 text

16 管理サーバー サーバー サーバー CKE マスター ノード サーバー サーバー ワーカー ノード サーバー サーバー ワーカー ノード Kubernetesクラスタの構築

Slide 17

Slide 17 text

Kubernetes クラスタの構築⽅法 17 管理サーバー CKE サーバー etcd kube- apiserver kube- scheduler kubelet SSH コンテナ を起動 証明書 を配布 証明書 発⾏ 秘密情報

Slide 18

Slide 18 text

マスターノードとワーカーノード • マスターノード: • Kubernetes クラスタを管理する役割のノード。3〜5台程度。 • ワーカーノード: • アプリケーションコンテナを実⾏する役割のノード。 • マスターノード以外はすべてワーカーノードとして構築。1,000台規模。 18 マスターノード etcd kube- apiserver kube- scheduler kube- controller- manager rivers etcd-rivers kube- proxy kubelet ワーカーノード kube- proxy kubelet rivers etcd-rivers

Slide 19

Slide 19 text

Kubernetes リソースの適⽤ 19 管理サーバー CKE Kubernetesクラスタに最低限必要な リソースを適⽤していく CoreDNS unbound CNI Plugin squid Role Role Binding Service Account Pod Security Policy Service Config Maps

Slide 20

Slide 20 text

マスターノードの冗⻑化 20

Slide 21

Slide 21 text

マスターノードを冗⻑構成にするには • etcd • 複数のメンバーでクラスタを構築する • kube-apiserver • 複数台をアクティブな状態で稼働させる • リクエストをロードバランスする • kube-scheduler, kube-controller-manager • いずれかのプロセスがリーダーとして動くよう設定 21

Slide 22

Slide 22 text

apiserver のロードバランシング • kube-apiserver を冗⻑化するた めにロードバランサーが必要 • オンプレ環境では、⾼可⽤な ロードバランサーを⽤意するの が⼤変 22 22 Worker Node Master Node Master Node Master Node LB apiserver apiserver apiserver kubelet kube- proxy Worker Node kubelet kube- proxy

Slide 23

Slide 23 text

rivers: 軽量 TCP リバースプロキシ 23 Worker Node Master Node Master Node Master Node rivers apiserver apiserver apiserver kubelet kube- proxy Worker Node rivers kubelet kube- proxy • rivers を各ノード上に配置 • kubelet から localhost 指定 • CKE は rivers の設定を変更して接 続先アドレスを更新 localhost localhost

Slide 24

Slide 24 text

etcd の接続問題も回避可能 • etcd は本来ロードバランサー不要だ が・・・ • 先頭のメンバーが落ちると、クライア ント接続できなくなる問題がある。 • https://github.com/etcd- io/etcd/issues/9949 24 Node Master Node Master Node Master Node etcd etcd etcd クライアント Node rivers クライアント localhost クライアント 接続失敗 問題なし

Slide 25

Slide 25 text

運⽤の⾃動化 25

Slide 26

Slide 26 text

運⽤を⾃動化したい • 運⽤時にはいろいろなオペレーションが必要になる • クラスタの設定変更 • エラーで落ちたソフトウェアの再⽴ち上げ • 故障したサーバーの修理 • 新しいサーバーの導⼊、古くなったサーバーの退役 • OSやソフトウェアのバージョンアップ • 理想の状態を宣⾔したら、あとはよしなにやってほしい︕ 26

Slide 27

Slide 27 text

Declarative Configuration 27 • 期待するクラスタの状態を宣⾔ • 期待の状態と⼀致するように⾃律的に オペレーションを実施 • 運⽤者の⼿作業オペレーションは不要 理想の状態を確認 現在のクラスタの 状態を取得 理想と現在の状態の 差分を⾒つける 理想の状態になるよ うにオペレーション を実施

Slide 28

Slide 28 text

クラスタ構成の宣⾔ • YAML形式で宣⾔ • ノードの指定は必須 • オプションで設定変更も可能 28 name: my-cluster nodes: - name: node-1 address: 10.0.0.101 control_plane: true user: cybozu labels: "cke.cybozu.com/role": "master" - name: node-2 address: 10.0.0.102 user: cybozu labels: "cke.cybozu.com/role": "worker" - name: node-3 address: 10.0.0.103 user: cybozu labels: "cke.cybozu.com/role": "worker" service_subnet: 10.68.0.0/16 pod_subnet: 10.64.0.0/14 options: kubelet: domain: cybozu.cluster kube-api: extra_args: - --enable-admission-plugins=PodSecurityPolicy

Slide 29

Slide 29 text

オペレーション例: エラーの修復 29 node1 node2 node3 宣⾔ node1 node2 node3 node1 node2 node3 node1 node2 CKE 実際のサーバーの状態 プロセスを再起動して 修復を試みる node3 エラーが発⽣してプロセスが終了

Slide 30

Slide 30 text

オペレーション例: サーバーの⼊れ替え 30 node1 node2 node3 宣⾔ node1 node2 node3 node4 node1 node2 node4 古くなったnode3を 新しいnode4と⼊れ替え node1 node2 node3 node4 CKE 実際のサーバーの状態 クラスタから削除 セットアップ

Slide 31

Slide 31 text

Kubernetes クラスタ運⽤の難しさ • Kubernetes クラスタはステートフル • 単純に理想と現実の差分を修正するだけではうまくいかない • Kubernetes クラスタが動作を停⽌したり、最悪の場合はデー タを失うことになる 31

Slide 32

Slide 32 text

クラスタ崩壊・データ損失の恐怖 32 メンバー数: 3 過半数: 2 メンバー数: 4 過半数: 3 故障発⽣ エラー修復のため メンバーを追加 データ未同期 新メンバーの同期が完了するまで etcd クラスタに書き込みできない Kubernetes クラスタも機能停⽌︕

Slide 33

Slide 33 text

CKE のオペレーション決定戦略 • 可能な限り⾃動的に修復を試みる • クラスタの機能停⽌やデータの損失を防⽌ • 各コンポーネントの再起動順序を考慮 • etcd のメンバー増減時は必ず過半数を保つ • 誤った宣⾔をした場合にはオペレーションを実施しない • オペレーション続⾏不可の場合には管理者に通知 33

Slide 34

Slide 34 text

秘密情報の管理 34

Slide 35

Slide 35 text

秘密情報どうやって管理してますか︖ • 守るべき秘密がたくさんある • SSH鍵 • CA証明書の秘密鍵 • Kubernetes の Secret リソース • 外部サービスにアクセスするためのトークン • GitHub で管理することはできない • 適切なアクセス権管理が必要 35

Slide 36

Slide 36 text

Vault • HashiCorp社の秘密情報管理ソフトウェア • CKE での利⽤⽤途 • SSH鍵などの秘密情報の管理 • CA証明書の管理、各種証明書の発⾏ • Kubernetes Secret リソースの暗号化 36

Slide 37

Slide 37 text

Vault の認証・認可 • 多様な認証⽅式に対応 • SSO, AppRole, Kubernetes 連携 • 認証されたユーザーやアプリにポリ シーが適⽤される • ポリシーに応じて、アクセス可能な 秘密情報や証明書が制限される 37 CKE policy role_id secret_id login token token request リクエストの 権限チェック 秘密情報 証明書など

Slide 38

Slide 38 text

コード例: ログイン処理 38 // ログイン処理(トークンの取得) secret, err := client.Logical().Write("auth/approle/login", map[string]interface{}{ "role_id": "/* ロールID */", "secret_id": "/* シークレットID */", }) client.SetToken(secret.Auth.ClientToken) // トークンの定期的な更新 renewer, err := client.NewRenewer(&RenewerInput{ Secret: secret, }) go renewer.Renew() defer renewer.Stop()

Slide 39

Slide 39 text

サーバー サーバー 証明書管理 39 管理サーバー CKE サーバー etcd kube- apiserver SSH 証明書を配布 証明書発⾏ kubectl ⽤の 証明書発⾏ CA証明書 CA証明書 の登録 管理者 開発者 10種類以上の証明書を 使い分ける 有効期限2時間

Slide 40

Slide 40 text

コード例: 証明書の発⾏処理 40 secret, err := client.Logical().Write( // Kubernetes⽤CA証明書でkubelet⽤のクライアント証明書を発⾏ "cke/ca-kubrenetes/issue/kubelet", map[string]interface{}{ "common_name": "system:node:node-1", "alt_names": "localhost,node-1", "ip_sans": "127.0.0.1,192.168.30.101", "exclude_cn_from_sans": "true", }) crt := secret.Data["certificate"].(string) key := secret.Data["private_key"].(string)

Slide 41

Slide 41 text

Encrypting Secret Data at Rest 41 管理サーバー CKE Secret リソース 作成 データ暗号化鍵(DEK)と DEKで暗号化したデータを 対にして保存する DEKを暗号化するための 鍵暗号化鍵(KEK)を保存 KEKの 設定

Slide 42

Slide 42 text

クラスタ管理システムの冗⻑化 42

Slide 43

Slide 43 text

43 High Availability 管理サーバー CKE Kubernetesクラスタの管理 SPOF クラスタ管理システムも冗⻑化しないと意味がない

Slide 44

Slide 44 text

CKE の HA 構成 • 3 〜 5 台の管理サーバーで冗⻑化 • etcd クラスタを構築 • Vault は etcd をバックエンドにし HA モードを有効化する • CKE はいずれか 1 つのプロセスが リーダーとして実⾏ 44 管理サーバー CKE 管理サーバー CKE 管理サーバー CKE リーダー

Slide 45

Slide 45 text

分散システム構築のお供に etcd • etcd は強い⼀貫性モデルの分散キーバリューストア • 分散システムを構築するために必要な機能が豊富 • トランザクション • リーダーエレクション • キーバリューの変更監視 • キーバリューの有効期限設定 45

Slide 46

Slide 46 text

コード例: リーダーエレクション 46 s, err := concurrency.NewSession(client) defer s.Close() e := concurrency.NewElection(s, "the election name") // リーダーに選出されると⾮エラーが返る。 // リーダー選出まではブロックされる。 err = e.Campaign(context.TODO(), "this process name") /* リーダーとしての処理を実⾏する */ // 処理が終了したらリーダーを辞任 defer e.Resign(context.TODO())

Slide 47

Slide 47 text

まとめ 47

Slide 48

Slide 48 text

CKE を開発してみての感想 • つくるのは⼤変だった。なんやかんやで 1 年くらいかかった。 • チームメンバーは Kubernetes にかなり詳しくなった。 • クラスタに必要な機能は望むまま。Scheduler Extender 対応とか etcd の不具合回避とか。 • 運⽤コストも⽬論⾒通り削減可能。 48

Slide 49

Slide 49 text

Kubernetes の運⽤ • Kubernetes を⾃前で運⽤するのは⾮常に⼤変 • Kubernetes や多くの周辺ソフトウェアの深い理解 • ネットワーク、ストレージ、Linux カーネルの深い理解 • マネージド Kubernetes サービスの利⽤がおすすめ • ⾃前運⽤の場合は Rancher だけでなく CKE の利⽤も検討してみてくだ さい 49

Slide 50

Slide 50 text

CKE の今後 • 基本機能の実装は完了 • 運⽤を開始して信頼度を⾼めていく • ドキュメントやチュートリアルの整備 50

Slide 51

Slide 51 text

Neco プロジェクトの公開情報 • ブログ • https://blog.cybozu.io/archive/category/Neco • スライド • https://tech.cybozu.io/slides/tags/neco/ • ソースコード • https://github.com/cybozu • https://github.com/cybozu-go 51