Kubernetesを本番環境で使用した3年間の経験から学んだこと

Kubernetesを本番環境で使用した3年間の経験から学んだこと

[編集者注] Kubernetes の旅から得られた主な教訓。

私たちは 2017 年にバージョン 1.9.4 で最初の Kubernetes クラスターの作成を開始しました。クラスターは 2 つあり、1 つはベアメタル RHEL VM 上で実行され、もう 1 つは AWS EC2 上で実行されます。

現在、当社の Kubernetes インフラストラクチャは、複数のデータセンターに分散された 400 台以上の VM で構成されています。このプラットフォームは、約 4,000 万のアクティブ デバイスを備えた大規模なリアルタイム ネットワークを管理するための、可用性の高いミッション クリティカルなアプリケーションとシステムを多数ホストします。

[[416051]]

Kubernetes は最終的に私たちの生活を楽にしてくれましたが、それは困難なプロセスでした。完全に変化したのは、私たちのスキルやツールセットだけではありません。デザインや考え方も変化しました。私たちは複数の新しいテクノロジーを導入し、チームとインフラストラクチャの能力を拡張するために多額の投資をする必要がありました。

過去 3 年間に渡り Kubernetes を本番環境で使用してきた経験を振り返り、いくつかの重要な教訓をまとめました。

Javaアプリケーションの奇妙な問題

マイクロサービスとコンテナ化に関しては、主にメモリ管理の悪名が高いため、エンジニアは Java スタックを避ける傾向があります。しかし、状況は変わり、Java のコンテナ互換性は長年にわたって向上してきました。結局のところ、Apache Kafka や Elasticsearch などのユビキタス システムは Java 上で実行されます。

2017-18 年には、Java 8 バージョンで実行されるアプリケーションがいくつかありました。 Docker などのコンテナ環境を理解するのが困難な場合が多く、ヒープ メモリの問題や異常なガベージ コレクション メカニズムが原因でクラッシュすることがよくあります。これらはすべて、コンテナ化技術の中核である JVM と Linux の cgroup と名前空間の問題によって発生していることがわかりました。

しかし、その後も Oracle はコンテナ分野での Java の互換性の改善を続け、Java 8 のその後のパッチでもこれらの問題を解決するために実験的な JVM フラグ XX:+UnlockExperimentalVMOptions と XX:+UseCGroupMemoryLimitForHeap が導入されました。

しかし、これらの改善にもかかわらず、Java は Python や Go などの同業言語と比べて、メモリ使用量が多く、起動時間が遅いという評判が依然として悪いのは否定できません。これは主に、JVM のメモリ管理とクラス ローダーによって発生します。

ここで、Java を選択する必要がある場合は、Java 11 バージョン以上であることを確認します。 Kubernetes のメモリ制限は、JVM の最大ヒープ メモリ (-Xmx) に予約用の 1 GB を加えた値に基づいて構成されます。たとえば、JVM がヒープ メモリに 8 GB を使用する場合、そのアプリケーションに対する Kubernetes のリソース制限は 9 GB になります。これにより、アプリケーションはより安定します。

Kubernetes ライフサイクルのアップグレード

アップグレードや機能強化などの Kubernetes ライフサイクル管理は、特にクラスターがベアメタル デバイスまたは VM 上に構築されている場合は面倒になる可能性があります。アップグレードの場合、最も簡単な方法は、最新バージョンで新しいクラスターを立ち上げ、古いクラスターから新しいクラスターにワークロードを移行することだとわかりました。インプレース ノード アップグレードの労力と計画は価値がありません。

Kubernetes には、一緒にアップグレードする必要がある複数の可動部分があります。 Docker から Calico や Flannel などの CNI プラグインまで、動作させるには慎重に組み合わせる必要があります。 Kubespray、Kubeone、Kops、Kubeaws など、作業を容易にするツールはありますが、いずれも欠点があります。

Kubespray を使用して、RHEL 仮想マシン上にクラスターを構築します。 Kubespray は優れており、クラスターの設定、ノードの追加と削除、バージョンの更新など、Kubernetes を本番環境で運用するために必要なほぼすべてのプレイブックが備わっています。ただし、アップグレードのプレイブックには、マイナー バージョンをスキップできないようにする免責事項が付属しています。したがって、ターゲット バージョンのアップグレードを完了するには、すべての中間バージョンのアップグレードを実行する必要があります。

Kubernetes の使用を計画している場合、またはすでに使用している場合は、ライフサイクル アクティビティと、ソリューションでそれらに対処する方法について検討してください。クラスターの構築と実行は比較的簡単ですが、ライフサイクル管理は多くの可動部分を伴うまったく新しい問題です。

ビルドとデプロイ

ビルドとデプロイメントのパイプライン全体を再設計する準備をしましょう。 Kubernetes 環境に適応するために、ビルド プロセスとデプロイメントを完全に変革する必要がありました。リファクタリング作業には、Jenkins パイプラインだけでなく、Helm などの新しいツールの使用、新しい Git プロセスとビルド戦略への調整、Docker イメージのタグ付け、バージョン管理された Helm デプロイメント チャートも含まれます。

コードだけでなく、Kubernetes デプロイメント ファイル、Dockerfile、Docker イメージ、Helm チャートも維持し、それらすべてを接続する新しい方法を考案するための戦略が必要になります。

数回の繰り返しを経て、次のデザインに落ち着きました。

  • アプリケーション コードと対応する Helm チャートは異なる Git リポジトリに保存されるため、バージョンを個別に管理できます。
  • リリースを追跡するために、アプリケーション バージョンを含むチャート バージョンの組み合わせを保持します。たとえば、app-1.2.0 は charts-1.1.0 とともにデプロイされます。 Helm 値ファイルのみが変更された場合は、チャートのパッチ バージョンのみが変更されます (たとえば、1.1.0 から 1.1.1 へ)。これらのバージョン番号はすべて、各リポジトリ内のリリース ノート ファイル RELEASE.txt によって決定されます。
  • Apache Kafka や Redis などのシステム アプリケーションは、コードをビルドしたり変更したりする必要がないため、動作が異なります。つまり、Docker タグは Helm チャート バージョン管理の一部であるため、2 つの Git リポジトリを使用する必要はありません。アップグレードにより Docker タグを変更する場合は、チャート タグ内のメジャー バージョン番号もアップグレードします。 ### 生存性プローブと準備性プローブ(これは諸刃の剣です)

Kubernetes の準備プローブと生存プローブは、システムの問題を自動的に解決するための優れた機能です。障害発生時にコンテナを再起動し、異常なインスタンスからトラフィックをリダイレクトできます。しかし、特定の障害条件下では、これらのプローブは諸刃の剣となり、アプリケーション、特にメッセージング プラットフォームやデータベースなどのステートフル アプリケーションの起動と回復に影響を及ぼします。

私たちの Kafka システムはこの問題の被害者でした。 replicationFactor: 3、minInSyncReplica: 2 で 3 Broker 3 ZooKeeper ステートフル クラスターを実行しました。予期しないシステム障害とクラッシュの後に Kafka が起動したときに問題が発生しました。これにより、起動時に破損したインデックスを修復するための追加のスクリプトが実行され、プログラムの重大度に応じて 10 ~ 30 分かかることがあります。この余分な起動時間により、活性プローブは失敗し続け、Kafka を再起動させる Kill シグナルがトリガーされます。これにより、Kafka がインデックスを修復して完全に起動できなくなります。

唯一の解決策は、コンテナの起動後に評価を遅らせるために、サバイバル プローブ検出で initialDelaySeconds 構成を構成することです。しかし、問題は、特定の値を想定することが難しいことです。回復プロセスには最大 1 時間かかる場合があり、これを考慮して十分なスペースを確保する必要があります。ただし、initialDelaySeconds 値が大きいほど、起動に失敗したときに Kubernetes がコンテナの起動を完了するまでに時間がかかるため、サービスの回復が遅くなります。

したがって、妥協策としては、Kubernetes で求める回復力と、あらゆる障害状況 (ディスク障害、ネットワーク障害、システム クラッシュなど) 下でアプリケーションが正常に起動するまでにかかる時間のバランスをより適切に取る initialDelaySeconds フィールドの値を評価することです。

新しいバージョンの Kubernetes を使用している場合は、3 番目のプローブ タイプである「スタートアップ プローブ」を使用できます。コンテナの起動プロセスが中断されないよう、コンテナが正常に起動する前に、生存性および準備状況のプローブを無効にします。

外部IP露出を利用する

静的な外部 IP を使用してサービスを公開すると、カーネルの接続追跡メカニズムに大きな負担がかかることがわかりました。慎重に計画しなければ、大規模な崩壊が起きる恐れがあります。

私たちのクラスターは Calico CNI を使用し、エッジ ルーターとピアリングしながら Kubernetes のルーティング プロトコルとして BGP を使用します。 Kube-proxy では、IPTables モードを使用します。私たちは、外部 IP 経由で公開され、1 日に数百万件のリクエストを処理する大規模なサービスを Kubernetes でホストしました。 SDN からのすべての SNAT とマスカレードにより、Kubernetes にはこれらすべての論理フローを追跡するメカニズムが必要になります。これを実現するために、カーネル内でConntrackを使用する。

そして、これらの外部接続を静的 IP に管理するための netfilter ツールが、内部サービス IP に変換され、さらに Pod IP に変換されます。これらはすべて、conntrack テーブルと IPTables を通じて実現されます。

ただし、conntrack テーブルには制限があり、制限がトリガーされると、Kubernetes クラスター (OS カーネルの下) は新しい接続を受け入れることができなくなります。 RHEL システムでは、次のコマンドを実行して確認できます。

  1. $ sysctl net.netfilter.nf_conntrack_count net.netfilter.nf_conntrack_maxnet.netfilter.nf_conntrack_count = 167012  
  2. ネット.netfilter.nf_conntrack_max = 262144

この問題の解決策としては、複数のノードをエッジ ルーターでピアリングして、静的 IP への接続をクラスター全体に分散させるというものがあります。したがって、クラスターに多数のマシンがある場合は、累積的に、大量の着信接続を処理するための大きな conntrack テーブルが存在するように見えます。

この質問は、私たちが2017年に事業を開始した当時、非常に困惑していましたが、最近では、Calico が 2019 年にこの問題に関する詳細な調査レポートを公開しました。そのレポートには、「conntrack がもはやあなたの味方ではない理由」という適切なタイトルが付けられています。

自己分析の質問: Kubernetes は絶対に必要ですか?

3年経った今でも、私たちは毎日新しいことを発見し、学び続けています。これは、特に環境の構築と維持のオーバーヘッドなど、独自の問題を抱えた複雑なプラットフォームです。設計、考え方、アーキテクチャが変わり、変革の要求を満たすためにチームのスキルと規模を拡大する必要があります。

ただし、クラウド上で Kubernetes を「サービス」として利用できる場合は、「社内ネットワークの CIDR を拡張するにはどうすればよいか」といったプラットフォームのメンテナンス作業に伴うオーバーヘッドのほとんどを軽減できます。または「Kubernetes のバージョンをアップグレードするにはどうすればよいですか?」

さて、自分自身に最初に尋ねるべき質問は「Kubernetes は絶対に必要ですか?」であることがわかりました。これは、問題と Kubernetes がそれをどの程度解決できるかを評価するのに役立ちます。

Kubernetes の変革は簡単ではありません。支払う価格は、使用事例を正当化するものであり、プラットフォームに実際にプラスの影響を与えることができるものでなければなりません。答えが「はい」であれば、Kubernetes は生産性を大幅に向上させることができると言えます。

覚えておいてください。テクノロジーをテクノロジーのために使用しても意味がありません。

<<:  Canalys: アマゾン、マイクロソフト、グーグルがクラウドサービス市場の60%を占める

>>:  Red HatとNutanixが協力してオープンハイブリッドマルチクラウドソリューションを提供

推薦する

ホームページサイトがそもそも存在しない場合の詳細な解決策

私とコミュニケーションを取るとき、多くのウェブマスターの友人は、ウェブサイトのドメインのホームページ...

情報フロー配信に必要な5つの段階!ゲーム業界の優れたケーススタディを添付します〜

2017年、伝説や童話のゲームはトラフィックの購入に多額の費用を費やし、素材は高度に均質化され、ゲー...

vaicdn: 登録不要/実名CDN、高速、広帯域幅、高防御、攻撃によるレイテンシへの影響なし

vaicdn はどのようにして登録や実名登録なしで高速かつ防御力の高い CDN を提供するのでしょう...

Crowdfunding.com の出版パートナー、Lai Yiu Fai 氏: クラウドファンディングに適した製品はどれですか?

[要約] 彼は、クラウドファンディングに適した製品には 3 つのタイプがあると考えています。1 つ目...

ユーザーエクスペリエンスに影響を与える4つの要素

検索エンジンにウェブサイトを評価してもらいたいなら、まずウェブサイトのユーザーエクスペリエンスを向上...

Redmi 人気の裏にある真実: 並外れたマーケティングが鍵

Xiaomiの携帯電話は2011年11月に発売されて以来、中国でますます人気が高まっており、その優れ...

SEO最適化ウェブサイト:サイト内キーワードレイアウトスキルの共有

SEO 担当者にとって、最適化されたウェブサイトを運営することは基本的な仕事の 1 つです。SEO ...

racknerd: サンノゼディストリビューション、AMD Ryzen9 3900X+DDR4+NVMe シリーズ、VPS は年間 14 ドルから

racknerd がロサンゼルス、ダラス、シカゴ、ニューヨーク、シアトルのデータセンターで AMD ...

特別なサイトレイアウトを構築するにはどうすればいいですか?

私たちがやりたいサイト内レイアウトは、一般的に言われているサイト内内部リンクレイアウトではなく、別の...

外部リンク構築の3つのステップに従うことでトラフィックが急増します

外部リンクを構築する方法はたくさんありますが、方法がいくつあっても、その方法には制限があります。外部...

英雄たちは年老いており、かつての王たちは「死んだ」

ノキア、モトローラ、ブラックベリー、コダック、ベストバイ…これらの有名なかつての業界大手は、激しい市...

hostodo-$5/2g メモリ/200g ハードディスク/4 コア/2IP/G ポート/ロサンゼルス

Hostodo は、大容量ハードドライブ、大容量トラフィック、十分なメモリを備えた、高構成の低価格 ...

cheapwindowsvps-7USD/1.15GB RAM/45GB SSD/2TB データ/G ポート/Windows 2003

cheapwindowsvps と ssdvps は同じ会社のものです。私の記憶が正しければ、おそら...

ウェブマスターネットワークからの毎日のレポート:Alipay が重大な抜け穴を暴露、360 リクエストは拒否される

1. Qihoo 360がテンセントを提訴:360の要求はすべて却下された新浪科技は3月28日朝、市...

hostyun: 中秋節 VPS イベント、全品 12% オフ、すべてのハイエンド ライン、オプションには香港/韓国/日本/米国/ロシアが含まれます

Hostyunは特別な中秋節イベントを開始しました: (1) すべてのデータセンターのすべてのVPS...