Kubernetesは自分にとって必要なのか

2020/08/27 07:12

Alex Hewson
DevOpsチームのスキルアップやプラットフォームの再構築を得意とする
この記事は、著者の許可を得て配信しています。
https://mbird.biz/writing/do-i-need-kubernetes.html

私がチームからよく聞かれる質問がこれです。「スタックをKubernetesでホストすべきか」というものです。技術の世界でKubernetesが話題になっていることを考えると、多くの人がそうすべきだと思い込んでいます。

私は数年間k8s(Kubernetes) を使って仕事をしてきました。非常に強力で複雑なプラットフォームを使うことも多々ありました。 ただ真実はもっと微妙だと思っています。

ここでは、その判断をした経緯を紐解いてみたいと思います。スタートアップや、自社製品のホスティングに責任を持つ、より広い組織内の自給自足のチームを対象とした記事となっています。また、大規模な組織の従来のIT部門の人々にも役に立つ記事になっていると思います。

何の役に立つのか?

Kubernetesは単なる「2018年の流行語」ではありません。これは安定しており拡張性の高いシステムで、よく考えられたプリミティブ(Pod, Service, Ingressなど)からアプリケーションのデプロイメントを構築することができます。アプリケーションがクラッシュすると、アプリケーションを再起動します。基盤となるマシンの全体が消えると、それらを置き換えようとします。多数のサービス(おそらくマイクロサービスアーキテクチャとして開発されたもの)を実行していて、効率性、レジリエンス、デプロイのためのストーリー性を求めている人にとっては、とても便利なツールです。

サービスに基本的なレジリエンス(復元力、回復力、弾力)を求めていますか?(もちろん求めていますよね) - デプロイメントで複数のレプリカを実行し、それらの間でトラフィックをバランスさせます。

ワークロードが「バースト的」な場合(API トラフィックが多いなどの場合)、必要なときに容量を増やすためにオートスケーリングを設定することで、これをベースに構築することができます。そしてお金の節約にもなります。ピーク時のキャパシティを常に支払うのではなく、ベースロード量を設定しておくことで、プラットフォームの動作を維持し、必要な時にはより多くのレプリカを起動させることができるのです。また、キューの長さをシステムにインポートすることができれば、キューベースのワークロードでもオートスケーリングが機能します。

コードが壊れるのが心配ですか? liveness/readiness probesをコンフィギュアすると、Kubernetesは障害が発生したときに自動的にサービスを再起動します。ハードウェアの障害についても同様で、ノードの半分を失ったクラスタが何事もなかったかのようにトラックを走らせ続けるのを見たことがあります。よくコンフィギュアされ、メンテナンスされたKubernetesクラスタは信じられないほどしっかりとしたものになります。もしリソースがあれば、chaos-monkeyのようなツールを使って、スタックが定期的な障害に耐えられるかどうかを確認してみるのもいいかもしれません。

KubernetesはCIワークフローと統合するための優れた機能を持っています。私が目にする最も一般的なパターンは、イメージをDockerレジストリにプッシュしてk8sクラスタを起動してロードするビルドです(理想的にはすべてのプロジェクトで標準化されています)。デプロイメントを変更して新しいタグを追加したり、新しいイメージにタグを指定してk8sを起動してすべてのポッドを再ロードしたりすることができます。ほとんどの場合(マイグレーションは全てを台無しにします)デプロイメントは完全に自動化されています。テストと機能フラグを信頼していれば100%自動化(Continuous Delivery=継続的デリバリー)にできますが、勇気のない人はビルド後に手動で承認することで痛みを和らげることができます。どちらにしても、開発者はKubernetesの専門家の助けを借りなくても、ほとんどのビルドをクラスタにリリースできるはずです。

CIと同様に、アプリケーションのロギングやモニタリングを標準化するのにも便利です。決してKubernetesに特有のことではありませんが、すべてのサービスに関するデータを同じ場所に集めたクラスタ全体のシステムを持つことで、デバッグの大変さを大幅に軽減することができます。私はfluentd を使って、アプリケーションからの json構造のロギング出力をAWS CloudWatchにパイプし、 Insightsを介してそれをクエリすることで、特に良い結果が得られたと感じています。

最後に、ホスティングレイヤー(つまり、高価な EC2 インスタンスに可能な限り多くのアプリケーションを詰め込むこと)と、開発者がソフトウェアのデプロイに費やす時間を短縮することで、効率性が向上し、より大きな効果を発揮します。コンピュータよりも人間の方がコストがかかるので、ほとんどの組織にとっては、これらのうちの2番目が最大のメリットになります。しかし、Kubernetesは万能ではありません。私は、美しく効率的なクラスタをいくつか見てきましたが、効率の悪い燃費の悪い大型車のようなものもあります。Kubernetesを正しく使うことに投資してこそ、Kubernetesのコストを節約することができるのだ。

Kubernetesが一番役に立つのはどんな場面か?

まず、自分の作業量(ワークロード)を考えてみましょう。どのようなアプリケーションを実行する必要がありますか?それらはどのようにお互いに、そして外の世界と対話しているのでしょうか?経験から言うと、以下の属性があなたのスタックに適していると思います。

  • 大まかに言えば、マイクロサービスアーキテクチャを理解できていますか?もし1つのアプリケーションしか持っていないのであれば、Kubernetesの価値はほとんどありません。アプリケーションをKubernetesにデプロイするにはDocker化する必要があります。どんなプロジェクトでも初日にこれから始めるとサービスの間の境界線を考えることにつながると思います。
  • あなたのサービスはHTTP(s)(おそらく、2020年でしょうか)を介してお互いに、そして外部の世界に公開されていますか?これはk8sのモデルにうまくフィットしますし、通常のingressコントローラのいずれかを使用してそれらを前面に出すことができます。
  • あなたのアプリケーションは、ロードバランスに適していますか?ローカルな状態を持たず(PostgreSQLやRedisなどを使用し)、既知のエンドポイントを介した通信、高速なスタートアップ/シャットダウンが可能です。クラスタ内にRedisキャッシュのような短命な状態を保持できないわけではありませんが、多くの場合、クラウドプロバイダが提供するboxed servicesを利用した方が良いでしょう。
  • また、Kubernetesは、バッチ処理( Job コントローラを介したもの)や長持ちするキューコンシューマのようなヘッドレスアプリケーションにも適しています。
  • メモリ(とCPU)の使用量は予測可能ですか?Kubernetesはアプリケーションを同じ物理マシン上でホストしようとするので、もしそのうちの1つが壊れてRAMを消費してしまうと、他のワークロードがランダムにキルされてしまう可能性があります。私の経験上、これがKubernetesクラスタの不安定性の最大の原因です。もしアプリケーションのリソース使用量を把握していれば、resources.requestsと resources.limitsを宣言することで、必要なメモリを常に確保し、悪者にならないことを保証することができます。

逆にここでは使わない方がいいと思うワークロードをいくつか紹介します。

  • 静的なウェブサイト。通常、コンテンツを Nginx 由来のイメージに焼き付け、クラスタの ingress コントローラを介してエクスポーズします。これは静的なコンテンツをホストするには最も適していない方法です。Nginxの小さなコピーをメンテナンスする必要があり、効率が悪く、ネットワークレベルではレジリエンスやパフォーマンスが劣ります。確かにCDNの後ろに置くこともできますが、もしそうするのであれば、クラウドサービスにコンテンツをホストさせるのはどうでしょうか?
  • 信頼されていないコードをホストする。これは、顧客から提供されたアプリケーションや、WordpressやNPMの怪しいライブラリなど、セキュリティ上の問題を抱えたサードパーティのコードを意味します。デフォルトでは、ワークロードを分離するための Kubernetes の機能はあまり優れていません。ネットワークアクセスをコントロールするためにCalicoのようなものを追加することはできますが、それは簡単に台無しにしてしまいますし、セキュリティモデルは常にコンテナランタイムに100%依存することになります。このためのデフォルト (Linux の cgroups をベースにした Docker) は、侵害されたアプリケーションに対して巨大な攻撃範囲を提供しています。 クラスタが実行されているコードベースがハッキングされた場合、攻撃者はクラスタの残りの部分へのアクセスをエスカレートさせるのは難しいことではありません。cgroups に代わるものとして興味深い研究が行われていますが (例: Kata Containers)、一般のユーザに推奨できるほど主流ではありません。
  • ワークロードが合わない場合は、Kubernetes に組み込むオプションがあるかもしれませんが (例えば、 ボリューム を長期間持続する状態に使うことができます)、問題を回避するためのエンジニアリングに多くの時間を費やすことになるでしょう。これらの問題の多くはいずれにしても悪いプラクティスなので、スタックから完全に切り離して設計した方がリソースの時間を有効に使えるかもしれません。

どんな難題でも解決してくれる魔法のツールではない

Kubernetesはどんな難題でも解決してくれる魔法のツールではありません。アプリケーションをホスティングする際の複雑さを、うまく設計された独自のレイヤーに移行させるのには役立ちますが、それだけでは問題は解消されません。常にプラットフォームの安全性を確保し、維持する必要があります。

クラスタを平均的なワークロードに有用なものにするためには、さまざまなアドオンが必要になります。アドオンの中にはほとんどの人が使っているものもあれば、ニッチなものもあります。例としては、(ingress controllercert-manage、十分な容量がない場合にノードを追加するための cluster-autoscaler などが挙げられます。環境の主要な機能を操作するオーダーメイドのソフトウェアをカスタマイズすることで、クラスターをユニークで独自なものにし、そのように管理する必要があります。また、定期的に更新する必要があり、品質が疑わしい場合もあります。Helm やTerraformのようなコンフィグレーション管理ツールは必須です。クラスタを手でいじるのは危険ですし、デクレラティブな設定がなければ、まったく同じように別のものを起動することはできません。私はこれが、より成熟したクラスタを運用したり、置き換えたりする際に、問題が尽きることがないのを見てきました。

Kubernetes上で重要なスタックを実行する場合、常にある程度のキュレーションが必要になります。誰でも好きなものを好きなように、クラスタにデプロイさせれば、混乱を招くだけです。そうなると、何十個もの(もっと悪いことには1個の)ネームスペースに散らばった、名前の合わないアプリケーションが溢れるだけです。おめでとうございます!!古いスパゲッティインフラストラクチャを、新しい味のスパゲッティインフラストラクチャに置き換えました。もっとかっこいいお皿に乗っていますよ。

私が見てきたKubernetesの実装で最も成功しているのは、インフラストラクチャの専門家が開発者と協力して、ワークロードがしっかりとコンフィギュアされ、標準化され、互いに保護され、通信パターンが設定されている場合です。彼らはインフラストラクチャ上でアプリケーションの初期設定を行い、うまくいけばビルド/リリースシステムに接続して、開発チームが自力で新しいバージョンのコードを出荷できるようにします。多くの点で、これはあなたの組織のより広い文化を反映しています。もし、エンジニアリングがコミュニケーションの悪さと不明確な責任の入り混じった悪い単なる野放しの場であるならば、あなたのホスティング環境はそれを反映します。最悪の場合、信頼性が低く、メンテナンス性がなく、コストのかかるという最悪の事態を招くことになります。

所有コスト

大規模なアプリケーションを実行しているのであれば、Kubernetesを利用することで多くのコストを節約することができます。オートスケーリング(クラスタとレプリカセットの両方)や、スポットインスタンスのプール(EC2)やプリエンプティブVM(Google)などの機能を見ていきましょう。大規模な環境では、これだけで意思決定ができるかもしれません。

優れたツールのエコシステムは、どんなエンジニアでもアプリケーションをテストするためのどうでもいいクラスタを立ち上げるのを助けるために存在しています。でも、その点が素晴らしいところです。学習曲線は緩やかに始まりますが、コミットメントの大きさに気づかないうちに、簡単にKubernetesが本番環境に忍び寄り、あなたのビジネスの重要な部分になってしまいます。Kubernetesには複雑な障害モードがあり、それを最大限に活用するには多くの専門的なスキルが必要です。経験の浅い開発チームに急いでクラスタを構築させるのは災難のもとです( Kopsを使うのはよくあるアンチパターンですよね)。それでも数か月は上手くいくでしょう。しかし、もし大きく変える必要が出てきた場合、クラスタを再設定したり、コンセンサス障害のトラブルシューティングをしたりすると、最悪の事態に陥ります。

k8sクラスタをゼロから構築するのは、自分のカーネルをコンパイルするようなものです。物事がどのように動くのかを学ぶためには最適ですが、本番環境のアプリケーションを実行するには全くもって最悪の方法です。その代わりに、 AWS EKSやGoogleの GKEのような箱物のソリューションを使うべきでしょう。私よりもはるかに賢い人たちは、月数百ドルを支払わないといけないとしてもこれらを正しく動作させるために膨大な時間を投資していますし、その努力も理には適っています。

箱入りのKubernetesディストリビューションを使うにしても、専門的なスキルが必要になります。コントロールプレーンはAmazonの問題ですが、遅かれ早かれノード上で不明瞭なバグを引き起こすことになるでしょう。しかも大抵あなたのビジネスが最も忙しいときにバグが起きるのです。システムを実行するためにリソースをコミットし、そのためにお金を払っても構わないと覚悟しなければなりません。Kubernetesのリリースサイクルは短いので、少なくとも年に一度はクラスタをアップグレードする必要があります。そのAPIに定期的に変更を加えることで、それは簡単な作業になる可能性があります。あなたが実行しているどのようなアドオンもメンテナンスが必要になります。小規模で軽量な要件のショップであればパートタイムのリソースでも良いでしょうが、午前4時の時点ですべてのコンテナが不明瞭なスレッドエラーで爆発している場合は、誰かに頼る必要があるでしょう。

これらのことから、Kubernetesを効果的に利用するためには、サイズ/複雑さのしきい値レベルが存在すると考えています。少数(<5)のシンプルで需要の少ないサービスを運用しているのであれば、気にすることはないかもしれません。Kubernetesが本当にその力を発揮するのは、管理するデプロイの複雑さやダイナミックなワークロードが多い環境、あるいは、Kubernetesを効果的に使うための閾値があるような環境だと考えています。管理しなければならないデプロイの複雑さや動的なワークロードが多い環境や、ツールを標準化することで複雑さやコストを大幅に削減できるような環境では、この機能が本当に役立つでしょう。

ではどうすればいいのか?

読者の皆さんは2,000語の小論文の結論に期待しているかもしれませんが、答えは「状況による」です。もしあなたがまだ建築図を持っていないのであれば、あなたのアーキテクチャの図を描くとよいでしょう。

もし数を増やすことを想定していないサービスが少ししかないのであれば、技術スタックをホスティングするより簡単で安価な方法があるかもしれません。 AWS ECS (特に Fargateとの連携)、APIやバッチジョブを Lambdas /  Cloud Functionsとして書き換えたり、Herokuのようなシンプルな PaaS プロバイダーでアプリケーションをホスティングしたりする方法もります。また、古臭い方法だと思うかもしれませんが、メンテナンスの行き届いたいくつかのLinuxボックス上でシンプルでトラフィックの少ないアプリケーションを実行することで得られる価値と堅牢性も無視できません。

セキュリティやコンプライアンスの要件も判断に影響を与える可能性があります。ワークロードをオンプレミスでホストすることが義務づけられている場合、大きな運用上のオーバーヘッドが発生する可能性がありますし、Kubernetesの使用しない方がいいとは言いませんが、従来のソリューションの方があなたに合っているかもしれません。アドオンのセットを使用する必要があるけれど、コンプライアンス上、実行するすべてのソフトウェアを吟味する必要がある場合、その努力はあまり現実的とは言えないかもしれません。

Kubernetesが必要ないのにKubernetesが必要だと思い込んで、多くのリソースを注ぎ込むことになってしまったスタートアップ起業を私は今までたくさん見てきました。あなたがKubernetesを必要としているかどうか、そしてそれをうまく実装するための余裕があるかどうか、今一度慎重に考えてみてください。あなたの要件がコミットメントを正当化するものであれば、それを目指してください。そうでない場合は、将来的にKubernetesに移行する可能性があることを考慮し、それを技術的な決定に反映させることで、選択肢を広げておくことが大切です。起業初日からDockerでアプリケーションを実行し(これはdocker-compose では本番環境と同様に開発者にとっても価値があります)、ローカルの状態を保存させる前に慎重に考えてください。

一方で、今後の成長余地を測ることも重要です。今の時点で、シンプルなサービスが2、3つしかないのであれば、おそらくk8は必要ないでしょう。しかし、それらのサービスが数十にまで増えるのであれば、組織は今から複雑さを管理するためのスキルを身につけるべきなのかもしれません。複葉機(複葉飛行機、旧式の飛行機 2枚羽根で一方が他方の上にある飛行機)で十分なのにボーイング747を作りたいとは思わないでしょうし、300人の乗客がゲートで待機している場合、ソッピースキャメル(イギリスの戦闘機)は全く役に立ちません。

要約すると、インフラストラクチャの決定は、一般的にソフトウェア・アーキテクチャの選択の関数だということです。インフラを後回しにせず、必要なものが多ければ多いほど所有コストが高くなることを忘れないでください。必要であれば複雑なシステムに投資するのは構いませんが、その前にコミットメントについてよく考えてみる必要があります。

appstore
googleplay
会員登録
URLからPICKする

会員登録して、もっと便利に利用しよう

  • 1.

    記事をストックできる
    気になる記事をPickして、いつでも読み返すことができます。
  • 2.

    新着ニュースをカスタマイズできます
    好きなニュースフィードをフォローすると、新着ニュースが受け取れます。