Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Kubernetesクラスタの自動管理システムのつくりかた

Sponsored · Ship Features Fearlessly Turn features on and off without deploys. Used by thousands of Ruby developers.

 Kubernetesクラスタの自動管理システムのつくりかた

Avatar for Akihiro Ikezoe

Akihiro Ikezoe

July 22, 2019
Tweet

More Decks by Akihiro Ikezoe

Other Decks in Programming

Transcript

  1. ⾃⼰紹介 • 池添 明宏 (Ikezoe Akihiro) • ソフトウェアエンジニア • 2016年にサイボウズに中途⼊社

    • 運⽤本部所属 • ⾃作キーボードにハマりつつある 2 @zoetrope @zoetro
  2. CKE (Cybozu Container Engine) • Kubernetes クラスタの構築と運⽤を⾃動化するツール • https://github.com/cybozu-go/cke •

    特徴 • 構築だけでなく運⽤まで⾃動化 • Declarative Configuration • バックエンドには etcd と Vault を利⽤ • Go ⾔語で開発 11
  3. 既存ツールとの⽐較 • Kubernetes クラスタの構築ツールは数多く存在するが、運⽤の⾃動化まで サポートするツールはあまり⾒当たらない。 • RKE (Rancher Kubernetes Engine)

    • Kubernetes is Everywhere • Declarative Configuration • 構築、バージョンアップ、ノードの増減 を⾃動化 • Ingress, CNI Plugin, DNS アドオン 12
  4. 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のバージョンと連動 コンテナイメージの変更 可能 利⽤コンテナイメージは固定
  5. 16 管理サーバー サーバー サーバー CKE マスター ノード サーバー サーバー ワーカー

    ノード サーバー サーバー ワーカー ノード Kubernetesクラスタの構築
  6. Kubernetes クラスタの構築⽅法 17 管理サーバー CKE サーバー etcd kube- apiserver kube-

    scheduler kubelet SSH コンテナ を起動 証明書 を配布 証明書 発⾏ 秘密情報
  7. マスターノードとワーカーノード • マスターノード: • 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
  8. マスターノードを冗⻑構成にするには • etcd • 複数のメンバーでクラスタを構築する • kube-apiserver • 複数台をアクティブな状態で稼働させる •

    リクエストをロードバランスする • kube-scheduler, kube-controller-manager • いずれかのプロセスがリーダーとして動くよう設定 21
  9. 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
  10. etcd の接続問題も回避可能 • etcd は本来ロードバランサー不要だ が・・・ • 先頭のメンバーが落ちると、クライア ント接続できなくなる問題がある。 •

    https://github.com/etcd- io/etcd/issues/9949 24 Node Master Node Master Node Master Node etcd etcd etcd クライアント Node rivers クライアント localhost クライアント 接続失敗 問題なし
  11. 運⽤を⾃動化したい • 運⽤時にはいろいろなオペレーションが必要になる • クラスタの設定変更 • エラーで落ちたソフトウェアの再⽴ち上げ • 故障したサーバーの修理 •

    新しいサーバーの導⼊、古くなったサーバーの退役 • OSやソフトウェアのバージョンアップ • 理想の状態を宣⾔したら、あとはよしなにやってほしい︕ 26
  12. Declarative Configuration 27 • 期待するクラスタの状態を宣⾔ • 期待の状態と⼀致するように⾃律的に オペレーションを実施 • 運⽤者の⼿作業オペレーションは不要

    理想の状態を確認 現在のクラスタの 状態を取得 理想と現在の状態の 差分を⾒つける 理想の状態になるよ うにオペレーション を実施
  13. クラスタ構成の宣⾔ • 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
  14. オペレーション例: エラーの修復 29 node1 node2 node3 宣⾔ node1 node2 node3

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

    node4 node1 node2 node4 古くなったnode3を 新しいnode4と⼊れ替え node1 node2 node3 node4 CKE 実際のサーバーの状態 クラスタから削除 セットアップ
  16. クラスタ崩壊・データ損失の恐怖 32 メンバー数: 3 過半数: 2 メンバー数: 4 過半数: 3

    故障発⽣ エラー修復のため メンバーを追加 データ未同期 新メンバーの同期が完了するまで etcd クラスタに書き込みできない Kubernetes クラスタも機能停⽌︕
  17. CKE のオペレーション決定戦略 • 可能な限り⾃動的に修復を試みる • クラスタの機能停⽌やデータの損失を防⽌ • 各コンポーネントの再起動順序を考慮 • etcd

    のメンバー増減時は必ず過半数を保つ • 誤った宣⾔をした場合にはオペレーションを実施しない • オペレーション続⾏不可の場合には管理者に通知 33
  18. 秘密情報どうやって管理してますか︖ • 守るべき秘密がたくさんある • SSH鍵 • CA証明書の秘密鍵 • Kubernetes の

    Secret リソース • 外部サービスにアクセスするためのトークン • GitHub で管理することはできない • 適切なアクセス権管理が必要 35
  19. Vault の認証・認可 • 多様な認証⽅式に対応 • SSO, AppRole, Kubernetes 連携 •

    認証されたユーザーやアプリにポリ シーが適⽤される • ポリシーに応じて、アクセス可能な 秘密情報や証明書が制限される 37 CKE policy role_id secret_id login token token request リクエストの 権限チェック 秘密情報 証明書など
  20. コード例: ログイン処理 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()
  21. サーバー サーバー 証明書管理 39 管理サーバー CKE サーバー etcd kube- apiserver

    SSH 証明書を配布 証明書発⾏ kubectl ⽤の 証明書発⾏ CA証明書 CA証明書 の登録 管理者 開発者 10種類以上の証明書を 使い分ける 有効期限2時間
  22. コード例: 証明書の発⾏処理 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)
  23. Encrypting Secret Data at Rest 41 管理サーバー CKE Secret リソース

    作成 データ暗号化鍵(DEK)と DEKで暗号化したデータを 対にして保存する DEKを暗号化するための 鍵暗号化鍵(KEK)を保存 KEKの 設定
  24. CKE の HA 構成 • 3 〜 5 台の管理サーバーで冗⻑化 •

    etcd クラスタを構築 • Vault は etcd をバックエンドにし HA モードを有効化する • CKE はいずれか 1 つのプロセスが リーダーとして実⾏ 44 管理サーバー CKE 管理サーバー CKE 管理サーバー CKE リーダー
  25. コード例: リーダーエレクション 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())
  26. CKE を開発してみての感想 • つくるのは⼤変だった。なんやかんやで 1 年くらいかかった。 • チームメンバーは Kubernetes にかなり詳しくなった。

    • クラスタに必要な機能は望むまま。Scheduler Extender 対応とか etcd の不具合回避とか。 • 運⽤コストも⽬論⾒通り削減可能。 48
  27. Kubernetes の運⽤ • Kubernetes を⾃前で運⽤するのは⾮常に⼤変 • Kubernetes や多くの周辺ソフトウェアの深い理解 • ネットワーク、ストレージ、Linux

    カーネルの深い理解 • マネージド Kubernetes サービスの利⽤がおすすめ • ⾃前運⽤の場合は Rancher だけでなく CKE の利⽤も検討してみてくだ さい 49