2022年2月14日

DevOps

Kubernetesの間違い。よくある落とし穴を避けるための初級者向けガイド

初級者がやってしまいがちなKubernetesの間違いが多くあります。リストを作り、それらを回避するための解決策とヒントを添えました。

kubernetes mistakes - 1.webp

DevOpsは長い道のりを歩み、Kubernetesは急速にテクノロジー界を席巻しています。Kubernetesはオープンソースのコンテナオーケストレーターシステムで、コンテナ化されたアプリケーションのデプロイ、スケーリング、管理を自動化します。コンテナの分散クラスターを経済的かつ確実に管理するための強力なツールです。洗練されたツールと言われる一方で、正しく設定しないと問題を起こすこともあります。対処しないままでは、これらのKubernetesのミスが本番環境での障害につながります。

これらの落とし穴を回避するためには、基本的なアーキテクチャーとKubernetesの仕組みを理解することが不可欠です。このブログでは、Kubernetesのデプロイメントでよくある間違いやその仕組み、そしてそれらを修正する方法、または簡単なヒントで完全に回避する方法について説明します。


Kubernetesの基礎知識

kubernetes mistakes - 2.png

画像の出典はこちら kubernetes.io


 

Kubernetesは、コンテナオーケストレーションプラットフォームです。クラスター内のコンテナをAPIとコマンドラインツールで管理し、コンテナ型アプリケーションのデプロイ、スケーリング、管理を自動化します。Kubernetesのアーキテクチャーは、マスターと、複数のノードまたはワーカーノードで構成されています。マスターは、クラスターの状態やノードの活動を管理します。また、ワークロードを管理し、ノード上のコンテナをスケジュールし、コンテナに適切なリソースを割り当てます。ノードは物理マシンでも仮想マシンでも構いませんが、Kubernetesクラスターと連携するためには、いずれもDockerエンジンとkubeletサービスにアクセスする必要があります。さらに、ノード間でデータを転送するために、ノードは他のノードと接続する必要があります。

Kubernetesは宣言型構成モデルを採用しており、予測される変更と予測されない変更の両方に対して耐障害性のあるシステムを簡単に設計することができます。宣言型構成により、Kubernetesはコンテナとクラスター運用の根本的な複雑さを処理し、高可用性、拡張性、およびセキュリティーを備えたクラスターを簡単に構築することができます。

デプロイが複雑であればあるほど、これらのミスのいずれかを犯す可能性が高くなります。

ヘルスチェックを無視する

kubernetes mistakes - 3.png

画像の出典はこちら:Kaizenberglabs


Kubernetesにサービスをデプロイしている間、サービスを期待通りに稼働させるためにヘルスチェックは非常に重要です。全てが正常に動作しているかどうかを確認するには、Podの状態とKubernetesクラスタ全体の健全性を把握することが重要です。そのために、アプリやその中で動いているサービスの状態を知るためのstartupプローブ、livenessプローブ、readinessプローブがあります。startupプローブは、Podが正常に開始され、作成されることを確認します。livenessプローブは、アプリケーションが生きているかどうかをテストすることができます。readinessプローブは、アプリケーションがトラフィックを受け取る準備ができているかどうかを判断するために使用されます。

コンテナでホストファイルシステムをマウントする

コンテナでホストファイルシステムをマウントすることは、多くの失敗を招く一般的なアンチパターンです。まず、コンテナ内で作成または変更された全てのファイルは、外部からは見えないということを知っておくことが不可欠です。

コンテナでホストファイルシステムをマウントする主なユースケースは、データの永続化です。これを行う最も簡単な方法は、ホストのローカルディレクトリをコンテナのファイルシステム内のディレクトリーの1つとしてマウントすることです。この方法では、そのディレクトリーに書き込まれたものは全てホストマシンに永続化されます。しかし、ホストのファイルシステムをマウントすることは、結果を伴います。

複数のコンテナ間で状態を共有することはできません(つまり、2つの異なるディレクトリを2つの異なるホストにマウントすることはできません)。

ホストのファイルシステムを変更すると、他のコンテナから隠されます。

マウントされたディレクトリーの所有権とパーミッションを変更しないと、そのディレクトリーのファイルを管理できません。

これらの結果を避けるために、データの永続化のために必要な場合を除き、コンテナ内にホストのファイルシステムをマウントしないでください。

Latestタグの使用

Latestタグを実運用で使うとカオスになります。バージョンやその他の記述について十分に明確でないため、実運用で使用することはお勧めできません。さらに、物事が壊れたときに、どのバージョンのアプリが動作しているのか分からなくなるため、利用可能な状態に戻す必要があり、より混乱が生じます。従って、常に意味のあるDockerタグを使用するのがベストでしょう。多くの人は、Latestというタグは常に新しくプッシュされたバージョンのイメージを指していると考えていますが、そうではありません。デフォルトでは、イメージはLatestというタグを取得しますが、これは何の意味も持ちません。

誤ったKubernetesノードにサービスをデプロイする

Kubernetesは複雑なシステムであり、初級者が犯しがちなミスの1つは、間違ったノードにサービスをデプロイしてしまうことです。Kubernetesでは、ノードはマスターノードとワーカーノードのどちらかです。Kubernetesの全てのジョブには、コントローラとスケジューラがあります。コントローラーはマスターノード上で動作し、スケジューラーはワーカーノード上で動作する。マスターノードの主な機能は、対応するワーカーとの同期と、ボリューム、ネットワーク、永続データストレージなどのクラスタレベルのリソースを管理することです。

ワーカーノードは、マスターから割り当てられたタスクのみを実行します。つまり、間違ったノードにサービスをデプロイすると、正しく動作しない、あるいはまったく動作しない可能性があるということです。また、新しいコンテナの起動には予想以上に時間がかかります。なぜなら、コンテナは、他の何かを起動する前に、利用可能なスケジューラがタスクを割り当てるのを待つ必要があるからです。

これを避けるには、デプロイする前に、サービスがどのタイプのノードで実行されているか(マスターまたはワーカー)を常に把握しておく必要があります。また、コンテナを起動する前に、Podが通信する必要のあるクラスター内の他のPodにアクセスできるかどうかを確認する必要があります。


デプロイメントモデルを採用していない

アプリケーションのデプロイは開発者にとって困難な作業ですが、Kubernetesは数多くのデプロイ技術によってそれを容易にしています。アプリケーションの可用性を維持し、新しいソフトウェアのデプロイ中に起こりうるダウンタイムによってユーザーが影響を受けないようにするために、Kubernetesはブルーグリーン、カナリア、ローリングといったデプロイメント戦略を使用することを推奨しています。

kubernetes mistakes - 4.png

ローリングデプロイメントは、Kubernetesによるデフォルトの戦略で、前バージョンの古いPodを新しいバージョンのPodにゆっくりと置き換えていくものです。

ブルーグリーンデプロイメントでは、ブルーとグリーンの両方のバージョンが同時にデプロイされますが、一度にアクティブでライブになるのは1つのバージョンだけです。ブルーを古いバージョン、グリーンを新しいバージョンと考えることにしましょう。そして、最新バージョン(グリーン)が全ての要件を満たした場合、古いバージョンのトラフィックは新しいバージョンに(ブルーからグリーンへ)転用されます。

カナリアデプロイメントは、A/Bテストやダークローンチを実施する際に使用されます。ブルーグリーンアプローチに似ていますが、よりコントロールされています。この戦略では、バージョンAからバージョンBへのゆっくりとした動きのあるトラフィックを見ることができます。炭鉱のカナリアをイメージしてください。

デプロイメントが重複している

Kubernetesで最もよくある間違いの1つは、デプロイメント戦略が重複している場合です。これは、同じ状態のレプリカを複数作成し、異なるクラスターに並行してデプロイした場合に起こります。

これは何を意味するのでしょうか?基本的に、これは、1つのクラスターがダウンした場合、他のクラスターはあなたのデプロイのための要求を処理し続けることを意味します。しかし、それらが回復したとき(またはそれらを追加したとき)、両方のレプリカがリクエストを処理し、2セットのレプリカが実行されているため、リクエストは2倍になります。これは、基盤となるホストのCPUとメモリをオーバーサブスクライブする可能性があるため、悪い知らせとなることがあります。この誤りを修正するには、HeadlessサービスやDaemonセットなどのサービス タイプを使用し、常に1つのバージョンのデプロイメントのみが実行されるようにすることをお勧めします。

本番環境で1種類のコンテナ(ステートレス)のみ使用している

当初、コンテナとコンテナ化はステートレスアプリケーションのために設計されましたが、その後、ステートフルアプリケーションをサポートするために多くの取り組みが行われました。Kubernetesがコンテナ化を可能にし、最新のデータ駆動型アプリケーションをサポートしたことで、ステートフルアプリケーションを採用することが重要になりました。

開発者が犯しがちな間違いの1つは、ステートフルとステートレスの両方のコンテナを使用すべき本番環境において、1種類のコンテナ(通常はステートレス)しか使用していないことです。多くの人は、全てのコンテナが同じであると誤解していますが、コンテナには大きな違いがあります。ステートフルコンテナでは、ディスクのような永続的なストレージにデータを保存できるため、データが失われることはありません。これに対し、ステートレスコンテナは、起動している間はデータを保持しますが、その後は(バックアップを行わない限り)永遠に失われます。従って、ステートフルとステートレスの両方のコンテナを利用するのは良い方法です。

監視とログの要件を考慮せずにアプリケーションを展開する

モニタリングとログの必要性を考慮しないと、悲惨なことになりかねません。この見落としがあると、開発者は自分のコードやアプリケーションが本番環境でどのように動作しているかを確認することができません。

この間違いを避けるために、開発者はアプリケーションをKubernetes上にデプロイする前に、監視システムとログ集約サーバーをセットアップする必要があります。これらのシステムを導入すれば、アプリケーションのパフォーマンスを測定し、より良いパフォーマンスを得るために最適化する必要がある変更を確認することが可能になります。

サードパーティーのソリューションを使用せず、Kubernetes自体が提供するサービスやツールだけを使用する場合、ベンダーロックインが発生する可能性があります。例えば、Dockerやrktコンテナではなく、CRIコンテナランタイムインターフェイスを使用してコンテナをデプロイするような場合です。また、多くの開発者は、クラスターの容量が十分でなかったり、アプリケーションをデプロイする時間帯を間違えたりして、カオス状態に陥ります。

セキュリティー設定をしていない状態でアプリケーションを展開する

アプリケーションをデプロイする際には、常にセキュリティーに配慮する必要があります。では、セキュリティーに関して最も考慮すべきことは何でしょうか?例えば、クラスタの外からアクセスできるエンドポイントを使用する、secretsを保護していない、特権コンテナなどを安全に実行する方法を考慮しない、などです。

Kubernetesのセキュリティーは、Kubernetesのデプロイメントに不可欠な部分です。セキュリティーの課題は以下の通りです。

● 承認。Kubernetesクラスター内のリソースへのアクセスを制御するためには、認証と承認が不可欠です。

● ネットワーキング。Kubernetesのネットワーキングでは、オーバーレイネットワークとサービスエンドポイントを管理し、コンテナ間のトラフィックがクラスター内で安全にルーティングされるようにします。

● ストレージ。クラスター内のストレージの保護は、不正なユーザーやプロセスによってデータがアクセスされないようにすることと、データを保護することで成り立っています。

Kubernetes APIサーバーは、保存されている全ての情報へのアクセスを提供するRESTインターフェイスを備えています。つまり、ユーザーはAPIにHTTPリクエストを送信するだけで、APIに保存されているあらゆる情報にアクセスすることができます。このデータを未認証のユーザーから保護するには、ユーザー名/パスワードやトークンベース認証などのサポートされている方法を使用して、APIサーバーの認証を設定する必要があります。

kubernetes mistakes - 5.png

クラスターそのものだけでなく、クラスター上の秘密や設定も保護することが重要です。クラスターを脆弱性から保護するには、クラスター上で一連のセキュリティー制御を構成する必要があります。そのような堅牢なセキュリティー制御の1つが、RBAC(ロールベースのアクセス制御)を使用してKubernetesクラスターを保護することです。ユーザーに割り当てられたロールに基づいてリソースへのアクセスを制限することで、Kubernetesクラスターを保護するために使用することができます。これらのロールは、adminまたはoperatorとして構成することができます。adminロールは完全なアクセス権を持ち、operatorロールはクラスター内のリソースに対して制限された権限を持ちます。このようにすることで、クラスターにアクセスする人を制御・管理することができるのです。

蛇足ですが、Harnessはきめ細かいRBAC機能を備えています。Harness Software Delivery Platformにおけるユーザーとロールの管理について説明した記事もありますので、ご興味があればご覧ください。

リソース消費量の制限を設けない

もし、リソースの使用量や請求額が急増しているようであれば、どのサービスが必要で、どのサービスが不要かを判断し、コントロールする必要があります。1つの方法は、アプリケーションに対してストレステストを行うことです。  

そして、コンテナのCPUとメモリに上限を設けるとよいでしょう。Kubernetesは、リソース活用のカテゴリーで「リクエスト」と「リミット」を定義しています。リクエストはアプリケーションが実行するために必要な最低限のリソースを表し、リミットは最大リソースを定義しています。リソースを制御しないということは、アプリケーションを監視していないということでもあります。リソース制限をデプロイメントYAMLで指定することができるのです。


kubernetes mistakes - 6.png

Harness Cloud Cost Management(CCM)は、毎月の支出を削減するためのリソース最適化の機会を示すことで、Kubernetesクラスターに対する提案を行います。推奨事項は、ワークロードのCPUとメモリの過去の使用率を分析することによって計算されます。この実装では、ヒストグラム法を使用して推奨値を計算します。

結論

Kubernetesは素晴らしいものですが、その学習曲線は時に困難なものになることがあります。私たちは、開発者がKubernetes運用で問題に直面していることを知っていました。そこで、Kubernetesのデプロイメントで効率的に作業できるように、よくある間違いや落とし穴を、それらを回避するヒントとともにリストアップしました。さらに、これらの間違いは、Kubernetesとのやりとりに細心の注意を払い、デプロイされたサービスとのやりとりの違いを理解することで回避することができます。

アプリケーションを稼働させる前に、十分な注意を払うようにしてください。また、全ての管理を支援する必要がある場合は、Harnessを試して出荷完了しましょう


この記事はHarness社のウェブサイトで公開されているものをDigital Stacksが日本語に訳したものです。無断複製を禁じます。原文はこちらです。

Harnessに関するお問い合わせはお気軽にお寄せください。

お問い合わせ