Slide 1

Slide 1 text

プライベートクラウドの サービス運⽤環境を K8sで改善する話 2019/11/26 Bonfire Backend #4

Slide 2

Slide 2 text

⾃⼰紹介 – 鶴⽥貴⼤ @dulltz – ログ基盤チーム(2017.09‒2017.12) – クラウド基盤刷新チーム(2018.01-) – 焚き⽕好き

Slide 3

Slide 3 text

cybozu.comというサービス – 提供期間 > 8年 – 契約社数 > 3万5千 – ユーザー数 > 130万

Slide 4

Slide 4 text

cybozu.comのインフラ

Slide 5

Slide 5 text

cybozu.com のインフラ – ⾃社製プライベートクラウドでサービス運⽤ – OpenStack は使っていない – ⾃社製プライベートクラウドにガタがきてる – 具体的な話は後述

Slide 6

Slide 6 text

cybozu.com のインフラ刷新 – つらいので2018年から刷新中 – Necoプロジェクト

Slide 7

Slide 7 text

インフラ刷新の進捗状況 – Done: 本番含め3データセンターでk8sクラスタ稼働中 – ⾃作k8s管理ツールCKEがCertifiedに Cybozu Kubernetes Engine - CNCF Cloud Native Interactive Landscape – WIP: Rook/Ceph – LVサポートのためにissue/PR出したり – WIP: サービス移⾏プロジェクトManeki – Cybozuにおける⼤規模インフラ基盤の移⾏プロジェクト Manekiの紹介 - Speaker Deck

Slide 8

Slide 8 text

刷新プロジェクトの⽬的 – 運⽤コストの低減 – 今回はこっちの話 – スケーラビリティの向上

Slide 9

Slide 9 text

運⽤に関する2017年当時の気持ち – 運⽤が⼤変 – もっと⾃動化したい – ⾃作過ぎる – もうちょっと標準的なしくみを取り⼊れたい

Slide 10

Slide 10 text

2017年後半の運⽤ツール – コンテナオーケストレーションツールが既に流⾏ – K8s – Apache Mesos – Docker Swarm

Slide 11

Slide 11 text

なぜK8sを選択? – K8sが圧倒的に流⾏っていた – K8s中⼼に発展しているエコシステムが強そう – 勝ち⾺に乗ろう

Slide 12

Slide 12 text

K8s導⼊の動機まとめ – 課題 増⼤する運⽤コストをなんとかしたい – なぜK8s? コンテナオーケストレーションツールの中で勢いが圧倒的だった

Slide 13

Slide 13 text

運⽤コスト下がった?

Slide 14

Slide 14 text

いい話1: OSアップグレード

Slide 15

Slide 15 text

旧基盤の環境 – Ubuntuを使⽤ – コンテナほぼ不使⽤ – ホストOSの環境がアプリケーションに影響

Slide 16

Slide 16 text

旧基盤 Ubuntuアップグレード – Ubuntu 14.04 から 16.04 へのアップグレード – 内蔵ミドルウェアの変更が サービス運⽤に影響ないかチェックする必要あり – Changelogを全部チェック – 実機で実験 – 不具合が現れたら原因調査、改修

Slide 17

Slide 17 text

ビッグバンリリースすぎた – もっと⼿軽にOSアップグレードしていきたい – 変更差分を⼩さくしたい

Slide 18

Slide 18 text

旧基盤のサービス退避 – サーバ停⽌にはその上のサービスの退避が伴う – ⼈⼒

Slide 19

Slide 19 text

新基盤ではすべてコンテナで – K8sを使う、つまりコンテナによるサービス運⽤にする – CoreOS Container Linux 採⽤

Slide 20

Slide 20 text

CoreOS Container Linux – コンテナを動かすための軽量OS – 内蔵ミドルウェアが少ない – ネットブートにかかる時間が短い

Slide 21

Slide 21 text

新基盤の継続的インテグレーション – OSのブートストラップ、アップグレードを⾃動テスト化 – Nested VM上に仮想的なデータセンター環境を構築 – VM構築ユーティリティを開発 cybozu-go/placemat – 毎⽇CIで試験しておいて、常にOSアップグレード可能な状態に

Slide 22

Slide 22 text

新基盤のOSアップグレードはこれだけ 1. 対象ノードをdrain 2. サーバーを再起動 3. 対象ノードのuncordon

Slide 23

Slide 23 text

OSアップグレード楽になった – k8sノードはコンテナさえ動けばOKなのでコンテナ⽤軽量OSが 使える。内蔵ミドルウェアが少なくアップグレードも⽐較的楽 – Container Linux 最⾼ – サービス退避はk8sのスケジューリング機能で楽できる

Slide 24

Slide 24 text

いい話2: サービスのデプロイ

Slide 25

Slide 25 text

旧基盤のサービスデプロイ – 宣⾔的なオペレーションが書けない – スクリプト実⾏の順番を厳密に守る必要がある – ⼿順書が⻑く複雑になりがち

Slide 26

Slide 26 text

旧基盤のサービスデプロイ – 継続的デリバリが⼀部しかできていない

Slide 27

Slide 27 text

旧基盤のサービスデプロイ – 開発チームから渡ってきたアーカイブファイルを SREチームがデプロイ – 運⽤コストが⼀部のチームに集中しがち

Slide 28

Slide 28 text

どうしてこうなった 旧基盤は – 理想状態への収束を⾏えるようなアーキテクチャになってない – マルチテナンシーという概念が薄い – 本番デプロイできるようになるにはadmin並の権限が必要

Slide 29

Slide 29 text

新基盤では宣⾔的なオペレーション – K8sのYAML適⽤ – ⻑い⼿順書からの脱却 – 必要に応じてカスタムコントローラも導⼊

Slide 30

Slide 30 text

新基盤ではサクッと継続的デリバリ – GitOps – Argo CDを使⽤中 – Kustomizeで構成管理 – 各ツールの使い⽅は他のチームにも布教

Slide 31

Slide 31 text

新基盤ではどのチームもデプロイできる – 各チーム(=テナント)に適切な権限を割り当てることで、 基盤チーム以外でもk8sのリソースを触れるように

Slide 32

Slide 32 text

テナントの権限 – アプリをデプロイできるようにする – うっかり他のテナントを邪魔してしまわないようにする

Slide 33

Slide 33 text

新基盤のマルチテナンシー – いわゆるソフトマルチテナンシー – 単⼀のk8sクラスタですべてのテナントを賄う – RBAC, Admission Controller, NetworkPolicy などを利⽤ – 時間余ったら最後に詳しく話します(資料の最後の⽅参照)

Slide 34

Slide 34 text

サービスデプロイ良くなった – 基盤チーム以外がデプロイできるようになった – GitOpsでCDできるようになった – マルチテナンシー周りはまだまだ固まっていないので、 これからも改善していく

Slide 35

Slide 35 text

いい話3: 開発環境

Slide 36

Slide 36 text

旧基盤の開発環境 – 本番と同型のクラスタを共同利⽤ – うっかり壊すと他の⼈に迷惑かけてしまう

Slide 37

Slide 37 text

新基盤はk8s – 各⼈ごとに⽤意可能なK8sはいろいろある – Minikube – microk8s – Kind – GKE

Slide 38

Slide 38 text

新基盤の開発環境はKindで – ⾃作CSIプラグインなど、⾃社仕様のk8sクラスタで動かすミド ルウェアを動かすようにカスタマイズ

Slide 39

Slide 39 text

開発環境よくなった – 開発環境を松⽵梅で⽤意 – Kind環境 – ローカルPCで動く – Nested VM環境 – GCEインスタンスで動く – K8sの下回りのミドルウェアやネットワーク構成が本番と同じ – 実機環境 – どうしても実機が必要なとき使う

Slide 40

Slide 40 text

いい話4: いろいろ

Slide 41

Slide 41 text

サービス公開+証明書発⾏を⾃動化 – カスタムリソースを1つ作成するだけで AレコードとTLS証明書が⾃動で作成される コンポーネント – Contour – Cert-manager – External-DNS – Contour-plus

Slide 42

Slide 42 text

処理の流れ Contour⽤カス タムリソースを 作成する • ユーザが作成 Certificateと DNSEndpoint が作成される • contour-plus TLS証明書と Aレコードが 作成される • cert-manager • external-dns

Slide 43

Slide 43 text

多機能踏台サーバが使える – Teleport – K8sへのアクセスを管理できる – GitHubを使ったSSOで権限制御ができる – ターミナルの⼊出⼒を録画できる – TeleportでKubernetesクラスタへのユーザーアクセスを管理する - Cybozu Inside Out

Slide 44

Slide 44 text

既存ツールの組み合わせで⾊々できる – エコシステムが盛り上がっているツールを選んだメリット – 勝ち⾺にのって良かった感

Slide 45

Slide 45 text

まとめ

Slide 46

Slide 46 text

運⽤コストは下がった? – これまで⾯倒だったことが楽になった – OSアップグレード – サービスデプロイ – 開発環境 – その他⾊々 – ⾃分たちで全部作らなくても既存ツールの組み合わせで いい感じにできるように – ただしk8sの運⽤・アップグレードという新タスクも発⽣

Slide 47

Slide 47 text

おわり – まだまだ模索中 – 他社の知⾒を教えて下さい

Slide 48

Slide 48 text

新基盤のマルチテナンシーについて詳細 – 1クラスタk8sですべてのテナントを賄う – Soft multi-tenancy

Slide 49

Slide 49 text

RBAC – テナントのスコープをnamespaceで切る – 基盤チームの namespace はテナントからは⾒えない – Custer-wide リソースをテナントは作成できない

Slide 50

Slide 50 text

Admission Controller – 認証より後のフェーズで ユーザーからのAPIリクエストを受け⼊れるか制御する機構

Slide 51

Slide 51 text

今有効にしてるadmission controller https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#is-there-a-recommended- set-of-admission-controllers-to-use を参考に – NamespaceLifecycle – LimitRanger – ServiceAccount – Priority – DefaultTolerationSeconds – DefaultStorageClass – PersistentVolumeClaimResize – MutatingAdmissionWebhook – ValidatingAdmissionWebhook – ResourceQuota – StorageObjectInUseProtection – NodeRestriction – PodSecurityPolicy

Slide 52

Slide 52 text

PodSecurityPolicy – クラスタ全体でPodのセキュリティ設定を制御するポリシー – 特権コンテナの拒否、hostのリソース使⽤の拒否などができる – 運⽤⽅針:デフォルトのポリシーでは権限をある程度限定してお き、必要に応じて緩和するよう上書きする – PSPは今後GAにならないらしい。そのうち⾒直す必要ありそう

Slide 53

Slide 53 text

デフォルトのPSP spec: privileged: false allowPrivilegeEscalation: false requiredDropCapabilities: - ALL volumes: - 'configMap' - 'emptyDir' - 'projected' - 'secret' - 'downwardAPI’ - 'persistentVolumeClaim' hostNetwork: false hostIPC: false hostPID: false runAsUser: rule: 'MustRunAsNonRoot' seLinux: rule: 'RunAsAny' supplementalGroups: rule: 'MustRunAs' ranges: - min: 1 max: 65535 fsGroup: rule: 'MustRunAs' ranges: - min: 1 max: 65535 readOnlyRootFilesystem: true • 以下を不許可 • すべてのCapability • ホストのプロセス/ネットワーク/ファ イルシステムへのアクセス • rootによる実⾏を禁⽌ • ルートファイルシステムは read-only

Slide 54

Slide 54 text

緩和したPSP spec: privileged: false allowPrivilegeEscalation: false requiredDropCapabilities: - ALL volumes: - 'configMap' - 'emptyDir' - 'projected' - 'secret' - 'downwardAPI’ - 'persistentVolumeClaim’ hostNetwork: true hostPorts: - max: 7472 min: 7472 hostIPC: false hostPID: false runAsUser: rule: 'MustRunAsNonRoot' seLinux: rule: 'RunAsAny' supplementalGroups: rule: 'MustRunAs' ranges: - min: 1 max: 65535 fsGroup: rule: 'MustRunAs' ranges: - min: 1 max: 65535 readOnlyRootFilesystem: true Metallb(ロードバランサー実装)のPSP • ホストネットワークの使⽤を許可

Slide 55

Slide 55 text

ResourceQuota, LimitRange – ResourceQuota – Namespaceごとに使⽤可能なリソース(CPU,RAM)の総量を設定 – LimitRange – Pod,PVCなどに割り当てるリソースの最⼩値/最⼤値を設定 – 基盤チームは無制限 – テナントにはクラスタを壊さない程度の制限を設定 – 具体的な数値は相談しながら調整

Slide 56

Slide 56 text

NetworkPolicy – Admission Controllerではない – ラベルセレクタが使えるファイヤウォール – Calicoの拡張NetworkPolicyを使っている – 基盤チームが優先順位の⾼いポリシーを作っておく

Slide 57

Slide 57 text

基本: GlobalNetworkSetを定義 – データセンターで使うサブネットを役割ごとに定義し、ラベル を付与しておく – k8sクラスタ内部のサブネット – BMCのサブネット – 機材のサブネット – 踏み台サーバのサブネット

Slide 58

Slide 58 text

基本: 外部への通信を許可 apiVersion: crd.projectcalico.org/v1 kind: GlobalNetworkPolicy metadata: name: egress-all-allow spec: order: 10000.0 types: - Egress egress: - action: Allow

Slide 59

Slide 59 text

基本: 内部への通信を遮断 apiVersion: crd.projectcalico.org/v1 kind: GlobalNetworkPolicy metadata: name: ingress-all-deny spec: order: 10000.0 types: - Ingress ingress: - action: Deny

Slide 60

Slide 60 text

クラスタ内からのアクセスを許可 apiVersion: crd.projectcalico.org/v1 kind: GlobalNetworkPolicy metadata: name: ingress-cluster-allow spec: order: 9900.0 types: - Ingress ingress: - action: Allow source: selector: role == 'cluster'

Slide 61

Slide 61 text

Admission Webhook – APIサーバへのリクエストのバリデーション/ミューテーション を⾃作するための機構 – Necoではテナントが優先順位の⾼すぎるNetworkPolicyを作れ ないようにしている – 以前はGatekeeperとOpenPolicyAgentを使って実装していたが、 それは⽌めてcontroller-runtimeで作り直した

Slide 62

Slide 62 text

Admission Webhook 例 – テナントが優先順位の⾼すぎるNetworkPolicyを作れないよう にする – 以前はGatekeeperとOpenPolicyAgentを使って実装していたが、 ⼀旦⽌めてcontroller-runtimeで作り直した – *KubeConNA2019だとGatekeeperすごい流⾏ってました

Slide 63

Slide 63 text

テナントのやりたいことにAdmin権限が 必要な時はどうする? ケースバイケースで対応中 ミドルウェアレイヤーでなんとかなったりもする

Slide 64

Slide 64 text

「CRDやオペレーターを追加したい」 – 基盤チームで管理する – テナントには基盤チームの提供する1サービスとして提供 – 例: Elastic Cloud on Kubernetes

Slide 65

Slide 65 text

「ArgoCD使いたい」 – ArgoCD⾃体は基盤チームが管理 – ArgoCDの参照するGitソースは各テナントが管理 – ArgoCD⾃体に独⾃RBAC機能があるので、 テナントのApplicationリソースの同期/閲覧権限だけテナント に渡したり

Slide 66

Slide 66 text

「基盤チームのPrometheusのデータを 使いたい」 – kube-state-metricsなどがテナントから⾒えない – 基盤チームのPrometheusのFederation APIに アクセスしてもらうことで対応