社内のKubernetesクラスタ運用を効率化する基盤について

はじめに

こんにちは。
2022年の4月から、さくらインターネット株式会社に新卒入社し、7月よりSRE室という部署に配属されました、菅原大和(@drumato)と申します。

本記事では、7月の配属から今日(記事執筆時点では2022/10/31)にかけての3ヶ月間、社内のKubernetesクラスタ運用状況を調査し、現状の課題を明確にした上で、社内のKubernetesクラスタ運用状況を改善する基盤の設計と開発に取り組んできましたので、その内容をご紹介します。
その過程で得られた知見や、今後必要になってくるであろう、不足している機能についても合わせて共有します。
また、本プロジェクトの背景として、SRE室という部門の目的や今後実現したい世界観についてもお話しできればと思います。
本記事の全体を通して、技術的な側面よりもプロジェクトの背景や目的を重点的にお伝えします。

本プロジェクトの概要

本プロジェクトは社内のKubernetesクラスタ運用状況の調査と、基盤実装による改善を目的として発足されました。
プロジェクトのメンバーは現在2人で、現状以下のような分業が行われています。

私(菅原):プロジェクトの方針決定、設計と実装、テスト、導入、運用
稲垣さん(@hum_op_dev): 技術的知見の共有、社内への率先的な導入、ファーストユーザとしてのフィードバック

現在は完全にクローズドで開発されていますが、システム全体のうち、いくつかはOSSとして公開する可能性があり、現在検討中です。

本記事の執筆時点では、既に社内サービスとして公開している状態で、いくつかのエンジニアから利用していただき、フィードバックをいただいています。

本プロジェクトは発足されたばかりであり、開発/運用もほぼ私一人で行っているため、足りない機能もたくさん存在し、これからも開発を続けていく必要があります。

背景

SRE室の取り組み

SRE室は、2022年の7月に新設されたばかりの、比較的新しい部署です。一般的にEmbedded SREと呼ばれる、各プロダクトチームに所属するパターンと異なり、専門的な部門を組織している点が特徴です。

SRE室では、主にさくらインターネットが運用しているクラウドサービスの信頼性を高めるため、開発チーム、運用チームを巻き込み、SREプラクティスの実践によってお客様への価値提供が行えるまで、一気通貫のミッションを持って活動しています。

さくらインターネット全体のプロダクト数、エンジニア規模に対して、SRE室に在籍するメンバーはエンジニア5名と、かなり少なくなっていますが、人員を増やさずに、仕事をスケールさせる文化とメカニズムの導入をモチベーションに取り組んでいます。

それぞれのメンバーが独自のタスクを持って取り組んでいますが、私は学生時代からKubernetesに興味を持っていたことから、社内のKubernetes運用状況を調べてみることにしました。

社内のKubernetes利用事例

さくらインターネット社内では、いくつかのプロダクトチームがシステムの開発/運用にKubernetesを利用しています。各プロダクトチームは、さくらのクラウドや、物理インフラ上にそれぞれKubernetesクラスタを構築し、0からクラスタ運用を行っています。

現状、さくらインターネットでは、基本的に各プロダクトチームが独立してインフラを管理する方針を取っており、Kubernetesクラスタにおいても、それぞれのプロダクトが異なる要件を持っているため、このような状況となっていることが考えられます。

Kubernetesクラスタ運用知見の分散化

このような状況下で、Kubernetesクラスタを運用するチームのいくつかにヒアリングを行ったところ、Kubernetesに対する知見が豊富でないために、トラブルシューティングに時間がかかってしまったり、そもそもベストプラクティスを知っていないことから運用に困ってしまったりするという内容が挙がってきました。その一方で、Kubernetesクラスタの運用方針について非常に整理しているチームもありました。

ここまでで、今日におけるKubernetesクラスタの運用には専門的な知識・スキルが求められますが、現状、社内のクラスタ運用者間でそれらが共有されておらず、プロダクトチーム間で技術的ギャップが生まれていることが明らかになりました。

プロダクトチームから見たKubernetesクラスタの運用コスト

もう一点、ヒアリングを行った際に出てきた話題として、各プロダクトチームにとって、Kubernetesクラスタを独自に構築し運用するコストが高いと認識されていることが挙げられました。

これは、いくつかのプロダクトチームにとっては、CNIプラグインの選定や各種アドオンの利用方法等を検討するモチベーションがそこまで高くない、平たく言うと使いやすいKubernetesがあり、その上にアプリを乗せることのみ意識したいという意見から来るものでした。

さくらインターネットの各プロダクトチームは職能横断的に構成されているので、インフラエンジニアが在籍するチームも存在しますが、チームによってはKubernetesの自由度が高すぎることで、運用に影響を与えているのかもしれないと考えました。

目的

これらの背景や現状から、解決するべき問題点を列挙し、実現したい世界観を具体的にしていきました。

さくらインターネット社内のKubernetes利用例増加

プロダクトの本番環境としてでないとしても、社内でKubernetesが利用される、または利用が検討される事例が増えることで、社内のコンテナアプリケーションに対する関心向上や、運用改善が見込めると考えました。

さくらインターネットはパブリッククラウド、そしてその他のクラウドサービスを提供しているため、クラウド技術に対するキャッチアップのモチベーションは非常に高く存在します。

今日において、Kubernetesとクラウド技術は切っても切り離せない関係にあるため、社内のKubernetesに対する関心向上や、ナレッジの共有が行われることは非常に重要です。

Kubernetes利用をサポートする

すでにKubernetesを利用しているプロダクトチームや、Kubernetesを利用したいが採用ハードルの高さから保留しているチームに対して、Kubernetesクラスタの運用をサポートする仕組みを提供することが必要だと考えました。

ここで「サポート」という言葉を用いているのは、決してKubernetesクラスタ運用をSRE室が「代行」するのではないことを強調するためです。

SREがシステムの構築と運用に責任を持つパターン自体は、他組織でも見られる一般的なパターンですが、さくらインターネット社内の状況を鑑みると、今後想定される本システムを利用するプロダクトチームの数に対し、現状のSRE室、特にこのプロジェクトに参加しているメンバーは非常に少ないため、このようなコンセプトを採用しました。

SRE室としてはあくまでも、「人員を増やさずに、仕事をスケールさせる文化とメカニズムの導入」が活動の前提にあるべきだと考えているので、プロダクトチームの意図や目指す世界観を実現しやすい基盤を提供し、それを利用してもらいつつも、各プロダクトの運用はチームにハンドルを握ってもらうことを期待しています。

Kubernetesの運用知見を集中的に管理する

これは何らかの仕組み自体だけではなく、その外側であるSRE室自体のアプローチも含めた内容になりますが、Kubernetesを利用したいエンジニアにとって、意思決定の参考になるような情報が揃っていたり、あるいは揃えられるような前提条件が成り立っている(e.g., 相談しやすい場所がある)必要があると考えます。

社内Kubernetes基盤の設計と実装

ここまでの背景から、プロダクトチームにとって扱いやすいKubernetesクラスタを提供する基盤システムを設計し、実装に取り組んでいくことにしました。本記事では、基盤の仕組みについて詳細に解説することはせず、この基盤を運用する上での考え方を重点的に共有します。

以下の図は、本システムのユースケースを簡略化した様子です。

後ほどご紹介しますが、Grafanaは基盤システム側で提供されている、共通のメトリクス等を可視化するためのものです。今日において、Kubernetesクラスタの監視は必須要件となっていることを考えると、ユーザクラスタそれぞれでGrafanaを構築する必要がないようにするべきだと考え、このようにしています。

クラスタ仕様の変更には、クラスタノードのスケールアウトやスケールインが含まれます。現状、スケールアウトは動作検証が完了していますが、スケールインについては未検証です。

基盤運用者は現在私一人となっています。本ユースケース図において、運用者が行わなければならない手作業をできるだけ減らしつつ、プロダクトチームにとって最適な抽象化が行われたインタフェースを提供することが求められます。

社内Kubernetes基盤の仕組み

ここからは、現在開発されているKubernetes基盤の仕組みを解説していきます。
現在、Kubernetes基盤は、以下のような技術スタックで実装されています。PrometheusやGrafana等、ここに列挙しているもの以外も利用していますが、それについては「基盤の運用効率化」のセクションで扱います。

また本記事では、Cluster APIやコントローラアルゴリズムの詳細な解説については行わないものとします。

コンポーネント開発元使用技術説明
Cluster APIKubernetesコミュニティGoKubernetesコミュニティが開発・メンテナンスしている、Kubernetesクラスタのライフサイクルを管理することを目的としたプラグインと拡張インタフェースの実装
さくらのクラウド用Cluster APIプロバイダ独自GoCluster APIの拡張インタフェースを満たすように実装された、kubebuilderで開発されているKubernetes Operator

さくらのクラウドが提供しているAPIを利用し、IaaSリソースの管理を行うコントローラ
マニフェスト作成ツール独自Vite + React + TypeScriptクラスタ用マニフェストを作成するWeb UI
ユーザはYAMLを1から書かず、必要な情報をWebフォームに入力することでマニフェストを作成できる

以下に示すのは、クラスタ作成の流れについて、コンポーネントの関心ごとにまとめた図になります。ここで、Workload Clusterはプロダクトチームに提供するKubernetesクラスタ、Management ClusterはWorkload Clusterを管理するコントローラやシステムをデプロイするKubernetesクラスタです。

図に使用しているロゴは、以下のリンクより引用しました。
GitHub: https://github.com/logos
ArgoCD: https://github.com/argoproj/argo-cd/blob/master/docs/assets/argo.png
Kubernetes: https://github.com/kubernetes/community/blob/master/icons/png/control_plane_components/labeled/c-m-256.png

まず、プロダクトチームは用意したReactアプリによって、クラスタ仕様を記述したマニフェストファイル作成します。その後、マニフェストファイルをGitHub Enterpriseリポジトリにプッシュします。作成されたPRは基盤運用者によってレビューされ、承認された場合はマージされます。

本来、クラスタ作成はカジュアルに行ってよい作業なので、承認プロセスを必要としない設計も有効ですが、全クラスタを同じリポジトリで管理しており、不必要なトラブルを避けるために、基盤運用者のPR承認プロセスを設けています。仮に、承認プロセスに時間がかかってしまったとしても、KinD等の縮小環境を対象に、整備作業を行っておくことはでき、SREにおけるアンチパターンとしてのゲートキーパには該当しない想定です。

続いて、Management Clusterで動作するArgoCDは、クラスタリポジトリに対するAuto Syncを設定しています。これにより、クラスタに対応するカスタムリソースが自動作成され、それに対応するカスタムコントローラが動作します。これは、Cluster APIが提供するインタフェースを満たすCluster API Infrastructure Providerとして実装されています。

カスタムコントローラはさくらのクラウドにおけるIaaSリソースを管理するものです。例えばクラスタノードはサーバリソースとしてデプロイされますが、これに対応する形で、SacloudServerというカスタムリソースが存在します。

Infrastructure Providerに対し、Cluster API側のコントローラはcloud-initを格納したSecretを提供しています。これによって、作成したクラスタノードに対しKubeadmの実行コマンドが渡され、クラスタとしての準備が完了します。

作成されたクラスタでNodeListを取得する様子を以下に示します。ここで、サンプルクラスタのNodeはStatus Readyになっていますが、実際にはユーザ自身がCNIプラグインを選定し、インストールすることで初めてこの状態になります。

foo@sample-cluster-1-control-plane-xxxxx:~$ kubectl get nodes
NAME                                 STATUS ROLES         AGE VERSION
sample-cluster-1-control-plane-xxxxx Ready  control-plane 10d v1.25.3
sample-cluster-1-control-plane-yyyyy Ready  control-plane 10d v1.25.3
sample-cluster-1-control-plane-zzzzz Ready  control-plane 10d v1.25.3
sample-cluster-1-worker-xxxxx        Ready                10d v1.25.3
sample-cluster-1-worker-yyyyy        Ready                10d v1.25.3
sample-cluster-1-worker-zzzzz        Ready                10d v1.25.3

基盤の運用効率化

ユースケース図で示したとおり、Kubernetes基盤に必要な機能は、クラスタを作成する機能だけではありません。クラスタに対するヘルスチェック機能や、Grafanaダッシュボードの提供等が含まれます。

また、これからクラスタ数が増大することを想定して、基盤の運用負荷を下げる取り組みを実施する必要があります。

最後に、クラスタは作成するまでが終わりではなく、そのクラスタが安定して動作するまでの信頼性を担保する必要があるため、それに向けた取り組みをご紹介します。

ArgoCDの運用

クラスタ作成の仕組みで説明したとおり、基盤システムではArgoCDを導入してクラスタ作成を半自動化していますが、その様子をユーザが確認できるようになっています。それ以外にも、基盤を構成するシステムのデプロイをArgoCDで管理しています。ここでは、本システムにおける、現状のArgoCDの運用方法についてお話します。

ArgoCDをインストールすると、argocd-cmというConfigMapが作成されます。このリソースに変更を加えると、ArgoCD上のユーザアカウントを管理できるようになっています。

https://argo-cd.readthedocs.io/en/stable/operator-manual/user-management/#create-new-user

apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-cm
  namespace: argocd
data:
  accounts.foo: login
  accounts.bar: login

また、argocd-cmと同じように、ArgoCD ProjectやArgoCD Applicationについても、コアリソース、またはArgoCDの提供するカスタムリソースを設定することで宣言的に管理することができます

Kubernetes基盤としては、プロダクトチームのそれぞれに対しArgoCD Projectを作成し、そのProject以下にArgoCD Appを作成する必要があります。

現状は、クラスタ作成PRのマージ後、基盤運用者の方でArgoCDマニフェストについて管理しているリポジトリに変更を加え、ユーザの作成とProjectの作成、ユーザに対する新規Projectの権限付与、新規クラスタ用のApp作成を行っています。これは今後、クラスタ作成にトリガーして自動的に行えるようにできないか検討しています。

また、新規に作成されたユーザの初期パスワードはAdminユーザと同じものになっているため、クラスタ作成後にArgoCD CLIから変更する必要があります。この作業を自動化するために、argocd-cmの内容をwatchして、それに対応する初期パスワードを生成し、ArgoCD CLIを叩いて変更した後、それを格納したSecretを作成するようなGoプログラムを運用しています。

Prometheus OperatorとAPI外形監視

Kubernetes基盤としては、Workload Clusterが健常に動作し続けること、そして、Kubernetes基盤自体の信頼性を担保するために、様々な監視項目を設計しています。例えば、先述したユースケースから、以下のような監視項目を想定できます。

  • クラスタ作成の可用性
  • Workload ClusterのAPIサーバの可用性
  • クラスタのスケールイン/アウト
  • Management Clusterのキャパシティ
    • 単一のManagement ClusterでどれだけのWorkload Clusterを収容できるか
  • Management/Workload Clusterの接続性

その中でも、比較的すぐに取り組めて効果の高い指標に、Workload Clusterのkube-apiserverに対する外形監視 が挙げられます。参考にした取り組みとして、Yahoo! JAPANさんの資料を共有します。

Cluster APIの機能の一つに、各Workload Clusterに接続するためのkubeconfigを格納したSecretを作成してくれる、というものがあります。私はこれを利用して、それぞれのWorkload ClusterでAPIサーバがホストするVIPに向けて、/readyz エンドポイントの外形監視を定期的に行うようなヘルスチェッカを自前実装しました。

以下のようなカスタムリソースを作成すると、Management Cluster側に外形監視用のDeploymentが作成され、定期的にAPIリクエストを送信するようになります。また、Deployment側は本リソースに対するアクセス権を持っており、APIリクエストの実行結果は.statusに書き込まれていきます。

apiVersion: healthcheck.example.com/v1beta1
kind: WorkloadClusterHealthCheck
metadata:
  name: sample-cluster-1-api-health-check
spec:
  clusterName: sample-cluster-1
  containerImage: privateregistry/checker
  intervalSeconds: 60
status:
  checks: 14716                                   # チェックのトータルカウント
  errors: 25                                      # 通信失敗等、プログラム上のエラー
  failures: 0                                     # リクエストは成功したが、ヘルスチェックに失敗した場合
  pods:
  - name: sample-cluster-1-api-health-check-xxxxx
    phase: Running

コントローラ側ではこの.statusをもとにPrometheusのカスタムメトリクスを公開し、Grafanaでダッシュボードを作成しています。

https://book.kubebuilder.io/reference/metrics.html

Kubernetes基盤側ではGrafanaダッシュボードを運用していますが、kube-prometheusを利用することで、Prometheusを含めた仕組みをすぐに利用できます。

https://github.com/prometheus-operator/kube-prometheus

最後に、Management ClusterとWorkload ClusterでPrometheus Federation機能を利用する方針を検討しています。Workload Cluster側で外部メトリクスストレージを用意せず、メトリクスの長期保存を行えるようにするのが目的です。

SealedSecret

各Workload Clusterに関するマニフェストはGitで管理されていますが、カスタムコントローラのリコンサイル時に、各Workload Clusterで用意したさくらのクラウドAPIトークンを使い分ける必要があります。これは、プロダクトチームごとに異なるクラウドアカウントを利用しており、そのクラウドアカウント以下にリソースを作成する必要があることに起因します。

本プロジェクトでは、これをGitの管理下に置くために、SealedSecretを利用しています。

https://sealed-secrets.netlify.app/

今後の展望

本プロジェクトはまだまだ発展途上であり、これからも機能追加や運用改善に取り組み続ける必要があります。ここでは、今後実現したい内容の一部についてご紹介します。

SLO測定の本格実施とslothの導入

最低限の仕組みとして、API外形監視を実現していますが、先述したように、Kubernetes基盤としては他にも様々なユーザシナリオが想定され、それらに対する可用性も計測するモチベーションが強く存在します。

これらを実現した上で、その計測やアラートルールをプラクティカルに管理する方法として、slothの導入を検討しています。slothは、Prometheus環境で利用できる高機能なSLOジェネレータであり、PromQLを利用してSLI/SLOを記述し、Slackアラート等をうまく管理することができます。

https://sloth.dev/

kube-vipの継続的な検証

オンプレKubernetesクラスタの運用にとってネックとなるのが、Service Type LoadBalancerと、APIサーバの冗長化構成の実現方法です。現在、Workload ClusterにはStatic Podでkube-vipをデプロイしており、それによってAPIサーバの冗長化を実現しています。

https://kube-vip.io/

kube-vipはAPIサーバの冗長化以外にも、Service Type LoadBalancerやIPVSを利用したコントロールプレーンのロードバランシングを提供しています。また、Static PodではなくDaemonSetでデプロイすることで管理しやすくなるため、そちらも合わせて検討しています。

SAKURA Kubernetes Operator Groupの発足

記事冒頭でも説明したように、本プロジェクトは社内のKubernetesクラスタ運用状況を改善するために発足されました。

SRE室としては、Kubernetes基盤を実装して提供するだけでなく、各プロダクトチームの運用状況をヒアリングし続け、改善し続けるところまで責任を持つ必要があります。

現在、さくらインターネット社内のKubernetesクラスタ運用者間でコミュニケーションを行い、定期的に知見共有を行う場を設けるための取り組みを実施中です。

まとめ

本日は、

  • 社内のKubernetesクラスタ運用状況調査
  • 現状の課題感
  • 社内のKubernetesクラスタ運用を効率化する基盤の設計と運用

についてご紹介しました。これからもプロジェクトを継続して進行し、社内にKubernetesの運用プラクティスが広まる活動を続けていきます。

余談ですが、新卒で入社し、配属されてからの3ヶ月間で、プロジェクトの設計から課題感の調査、方針整理、実装と動作検証、ユーザへの導入、フィードバックまで、広範的な業務を行う経験ができたのは、とても貴重な経験でした。これからもこのイテレーションを回しつつ、本質的なエンジニアリングができるスキルの習得と実践に取り組み続けます。

採用

さくらインターネット株式会社では、継続してエンジニア採用に力を入れています。ご興味のある方は、下記採用ページをご覧ください。

さくらインターネット 採用情報