Kubernetesを提供するプラットフォームの管理者

村田俊哉氏:今日は「プロダクションレディを目指した Kubernetes クラスタのアップグレード戦略」という内容で発表したいと思います。

アジェンダとしては、最初はKubernetesクラスタのアップグレード時に必要だと思っている作業についての紹介。それを踏まえて、プロダクションの環境下で、今はどのようにアップグレード戦略を練っているかについて話したいと思います。最後に、その戦略で弊社が実施している自動化の方法などを軽く紹介していく流れです。

本題に入る前に軽く自己紹介から。ゼットラボ株式会社というところでソフトウェアエンジニアとして働いている村田です。Kubernetesを触り始めて一応5年ぐらい経っていますが、まだまだKubernetesがわかっていないので、いろいろ勉強しています。

最初にバックグラウンドを話したほうが伝わると思うので、軽くお話させてください。ゼットラボ社は、ヤフー株式会社(以下ヤフー)の子会社です。ゼットラボ社はヤフーの次世代のインフラ基盤を設計・開発をする会社として、2015年に設立された会社です。今回の話はこのゼットラボ社が、ヤフーにKubernetesを導入して運用した話です。

ヤフーでは、現在300以上のKubernetesクラスタがあって、それをアップグレードしていく際に実施している内容になっています。自分の立場的に、Kubernetesの運用者というよりKubernetesを提供するプラットフォームの管理者という立場になるので、その視点での話になるかもしれないですが、ご了承ください。

今回の発表は一般的な内容と社内で実施している内容が入り乱れています。わかりにくいかなと思ったので、一般的な内容と社内での内容を色で分けたので、それを参考に見てもらえればと思います。

アップグレードに必要なもの

最初はKubernetesのアップグレードに必要だと思っている作業についての紹介から。必要な作業としてまとめると、次のような内容を考えています。まず準備として更新内容の調査、その更新内容が意図通りに動かせるか。また、その変更によって不具合などが発生しないかをちゃんと検証するということですね。

そのテストの結果とかを基に、アップグレード計画を考える。その計画を基にリリースノートみたいなものを作り、それを周知することを弊社はやっています。これで準備は完了するので、あとは実際にアップグレードの作業に入ります。それが終わり、必要であればストレージバージョンの更新とかマニフェストを更新する、といった感じです。

なおここでは、etcdのバックアップのような手順は入れていません。弊社の場合は、バックアップを定期的に取っているので、アップグレード前に別途実施しないので省いています。もしバックアップをする場合は、このアップグレード手順の事前に入れるといいです。

実際に各項目でどんなことをやるかを見ていきたいと思います。アップグレードの作業は、Kubernetesのリリースサイクルに合わせての実施が必要です。まず、リリースサイクルのサポートについて、一応おさらいから。Kubernetesのマイナーバージョンは、3ヶ月に1回、年に4回のサイクルでリリースをしています。

パッチバージョンについては、都度バグ修正とかで実施されているので、必要であれば実施されるという感じです。公式のサポート期間については、先ほどもあったように9ヶ月となっていて、基本的には最新3つのマイナーバージョンがサポートされています。現時点だと、昨日(発表日時点)リリースされた1.18と1.17と1.16の3つです。

そのため、このサポート期間内にKubernetesを利用したいと思う場合には、この定期的にアップグレードをしていく計画が必要になってきます。一応LTS版を作ろうという計画もあるみたいですが、まだワーキンググループ内で話している段階なので、LTS版についてはまだ具体的な話はなさそうです。

以上のことから、Kubernetesをプロダクションで使い続けていくには3ヶ月に1回程度の頻度でアップグレードを続けていくことが必要になります。

アップグレード前の調査

では、具体的にアップグレード時に実施していることを見ていきます。最初は変更点の調査から。

Kubernetesがリリースされると、公式のWeb上にChangeLogが作成されます。ChangLogにはMajor Themes、Known Issues、Urgent Upgrade Notes、Deprecations and Removals、Metrics Changes、API Changes、Notable Features、Other notable changesと、いろいろ含まれています。

とくにアップグレードのときに気にしないといけないのが、Urgent Upgrade NotesとRemovalsの2つですね。ここは注意して、自分たちの環境に影響があれば対応を考えていく必要があります。このChangLogを見て、変更点をチェックしていく必要がありますが、現在のKubernetesは巨大になっているのもあって、正直このChangLogを見て内容を読んだだけだと、わからないものはけっこう多いです。

細かくIssueをたどって見ていけばわかるものも多いんですが、やっぱり時間が掛かるので、弊社では複数人で担当のSIG(SpecialInterestGroup)を決めて細かいところを見ています。調べた内容は、Qiitaで公開していたりしますので、よかったら見てみてください。

基本的にはChangLogの調査だけでいいんですけど、巨大なのもあって、調査の漏れとかそういうのが発生して致命傷にならないように、パラメータの変更点やAPIの変更点については、別途にソースコードやAPIのレスポンスから取得した内容の差分を確認したりしています。APIの変更点は、APIサーバがどのAPIをサーブしているかを返すAPIがあるので、そこの差分を見て確認したりしています。

このリポジトリでスクリプト化して、そのまま取ってくるやつとかを公開しているので、興味がある人は見てみてください。

先ほどの話はKubernetes本体なんですけど、Kubernetesクラスタを動作させるためにはそれ以外のコンポーネントも多くあります。例えばOS自体やコンテナランタイム、CNIプラグイン。それ以外にもCoreDNSのアドオンなど、いろいろなものがあるので、それらも併せて更新していく必要があります。

これらのコンポーネントを、コンポーネントごとにリリースする度にチェックするのは大変です。しかし、定期的に見直す機会というのを作らないと、放置されてしまいます。弊社の場合だと、Kubernetesのマイナーバージョンに合わせて、それ以外のコンポーネントも更新するようにしています。

例えばコンテナランタイムやCNI、その他のコンポーネントはOSイメージにまとめてアップグレード。アドオンは、アドオン一式をコンテナにまとめてアップグレードしています。ちなみにこの話は、マイナーバージョンなどの新機能を追加するときの話です。修正があれば、パッチをまとめて流し、必要があればアップグレードしていくことをやっています。

確認のテスト

これまでが調査で、次はこの内容が実際に動作するかを確認テストします。KubernetesはConformance testを公開しているので、それを実行すれば、Kubernetesの機能が正しく動作されているか確認が可能です。Conformance testを実行するためのツールとして、Sonobuoyというのがあるので、これを使えば簡単に実施できます。

また弊社の場合は、当時の使い勝手と更新タイミングの問題などから、今は公式リポジトリにあるテストを独自にビルドして実行。あとはこのConformance test以外にも、アップグレードテストやアドオンのe2eテストだったりといったことを実施しています。これらは、弊社では自動テストにして、基本的に毎日動作させて問題ないかを都度確認しています。

それ以外にも、あとは長期稼働試験として常時検証クラスタを動かしていて、メモリリークに代表されるリソースのリークを検知できるような状態を取ったりもしています。

これらのテストをして、アップグレードは問題ないなと判断できたら、アップグレード計画を作っていきます。

テストで反映した内容を基に、これらの4つの項目を精査して問題があれば、上の計画に組み込むという感じです。弊社の場合、1.10ぐらいから本番稼働して、アップグレードさせてます。今のところ、クラスタの停止を伴うようなアップグレードには遭遇していなくて、APIまわりの変更に伴う、マニフェストの変更を周知するとか、そのぐらいになっているのが現状です。

ただ、今後CNIの変更とか無停止のアップグレードができない場合が、もちろんあり得るので、その場合に備えて引っ越しを含めた計画も考えています。

計画が決まったら、弊社の場合はリリースノートというかたちでヤフーのKubernetesを実際に利用している方向けに、周知のためのドキュメントを作っています。内容は、主にアップグレード前後に実施すべき内容があるかどうか。変更点の中でユーザーに影響がある場合は、それを記載しています。

過去にあった例だと、例えばPodPreemptionを導入するときは、ユーザーに影響がけっこうあるので、それを周知したり。あとは1.16でextensions/v1beta1のデプロイメント系のリソースが廃止になったんですけど、そういうのを周知したりとかもしています。ここでは廃止予定となった時点で、早めに周知して移行の推進を促したりとか。

それ以外にも、マニフェストのlinterを提供していて、廃止予定に入った時点で、そのlinterで警告を出すようにするといった施策も実施しています。そのおかげもあってか、この1.16の移行のときには、とくに混乱もなくスムーズに移行ができたと聞きました。

これで準備が終わったので、次からは実際のアップグレード作業の話です。

実施時の注意点

クラスタのバージョンアップ作業は、具体的にはこのような流れで進めています。具体的な手順については環境によって異なるので、今日話してもあまり有益じゃありません。なので、実施時の注意事項を中心に話していきます。

まず、マスターからアップグレードするという話を先ほど言いました。Kubernetesのコンポーネント間はバージョンの依存関係にポリシーが決まっています。それを満たすようにアップグレードするには、マスターから埋めていくのが一般的です。詳しくはこのURLにあるドキュメントに公開されているので、興味のある方は見てみてください。

ここにはKubernetesが、いくつ上までサポートするのかといったことが書かれています。注意すべきなのが、動作させたままアップグレードするには、アップグレード中もその依存関係を満たした状態でアップグレードすることです。

例えば、すべてのマスターが最新版になる前にノードのアップグレードを開始してしまったりすると、一時的にマスターよりも高いノードができてしまったりすることがあります。そういう状態にならないために、アップグレードは注意して実施しなければなりません。

あと、マスターでマイナーバージョンをスキップするのはサポート外です。そのため1.15を1.17に上げるみたいなマイナーバージョンをスキップしたアップグレードは、動作保証外になるので1つずつ上げていく必要があります。

ノードに関しては、2個下のマイナーバージョンまでは一応サポートをしているらしいので、1.15から1.17に上げることもできるようです。永続的にその状態で動かすのは非推奨と明記されているので、可能であれば止めたほうがいいと思います。

アップグレードを実施したあとは、ストレージバージョンの更新が必要です。このストレージバージョンとは、簡単に言うとetcdに保存されているリソースのスキーマのバージョンみたいなもの。これを更新せずに、そのAPIサーバがetcdに保存されているリソースをデコードできない状態になると、APIサーバがそのリソースを読み取れなくなって、エラーになる問題が発生してしまいます。

あとはetcdですね。etcdもKubernetesのバージョンごとに推奨バージョンが明記されるようになっています。それを見て、それに合わせてバージョンをアップグレードしていくといいでしょう。