この記事はWeChatのパブリックアカウント「Xintai Cloud Service」から転載したもので、著者はZhu Xiangです。この記事を転載する場合は、Xintai Cloud Service公式アカウントまでご連絡ください。 私たちは 2017 年にバージョン 1.9.4 に基づいて最初の Kubernetes クラスターの構築を開始しました。現在、2 つのクラスターがあり、1 つはベアメタル RHEL VM 上で実行され、もう 1 つはパブリック クラウド AWS EC2 上で実行されています。 現在、当社の Kubernetes クラスターは、複数のデータセンターに分散された 400 台以上の仮想マシンで構成されています。このプラットフォームは、可用性の高いコア アプリケーションとシステムをホストし、約 400 万人のアクティブ ユーザーを抱える大規模なリアルタイム システムを管理します。 Kubernetes によって最終的には運用が容易になりましたが、プロセスは困難で、パラダイムシフトでした。私たちのスキルとツールが完全に変化しただけでなく、デザインと思考も完全に変化しました。チームとインフラストラクチャの品質とスキルを向上させるために、複数の新しいテクノロジーを導入し、多額の投資を行う必要がありました。 過去 3 年間を振り返ると、Kubernetes は 3 年間にわたって当社の本番環境で稼働しており、これがこの記事の焦点でもあります。 1. JavaベースのAPPコンテナ化の問題 マイクロサービスとコンテナ化に関しては、主にメモリ管理が扱いにくいという理由で、多くの人が Java を避ける傾向があります。しかし、今では状況が変わり、ここ数年で Java のコンテナ互換性は大幅に向上しました。結局のところ、現在のほとんどのシステムはミドルウェアとして Java プログラムである Apache Kafka を使用しており、Elasticsearch も通常は Java プログラム上で実行されます。 2017 年から 2018 年を振り返ると、Java 8 で実行されているアプリケーションがいくつかありました。これらのアプリケーションは、Docker などのコンテナー環境を理解するのに問題があり、ヒープ メモリの問題や奇妙なガベージ コレクションが原因でクラッシュすることがよくありました。これは、コンテナ化テクノロジーの中核となる Linux cgroup と名前空間を JVM がサポートできないことが原因であることがわかりました。 しかし、それ以来、Oracle はコンテナ空間における Java の互換性を継続的に改善してきました。 Java 8 のその後のパッチでも、これらの問題に対処するために、実験的な JVM フラグ XX:+UnlockExperimentalVMOptions と XX:+UseCGroupMemoryLimitForHeap が導入されました。 しかし、これらの改善にもかかわらず、Java は Python や Go などの同業言語と比べて、メモリ使用量と起動時間の遅さに関して依然として悪い評判があることは否定できません。これは主に JVM のメモリ管理によって発生します。 現在、Java を選択する必要がある場合は、バージョン 11 以上であることを確認します。十分なスペースを確保するために、Kubernetes のメモリ制限は JVM の最大ヒープ メモリ (-Xmx) より 1 GB 多くなります。つまり、JVM がヒープ メモリとして 8 GB を使用する場合、アプリケーションの Kubernetes リソース制限は 9 GB になります。こうすることで、アプリケーションはより健全になります。 2. Kubernetes のアップグレード アップグレードやパッチ適用などの Kubernetes ライフサイクル管理は、特にベアメタルまたは仮想マシン上に独自のクラスターを構築した場合には面倒になる可能性があります。アップグレードの場合、最も簡単な方法は、最新バージョンでクラスターを再構築し、古いクラスターから新しいクラスターにワークロードを移行することであることがわかりました。ノードのアップグレードは比較的複雑であり、結果は予測できません。 Kubernetes には、Kubernetes と連携して動作する複数のコンポーネントがあり、Kubernetes のアップグレードに合わせて調整する必要があります。 Docker から Calico や Flannel などの CNI プラグインまで、すべてを慎重に組み合わせて動作させる必要があります。 Kubespray、Kubeone、Kops、Kubeaws などのプロジェクトはメンテナンスが容易ですが、それぞれに欠点があり、汎用性はあまり高くありません。 RHEL VM 上で Kubespray を使用してクラスターを構築しました。 Kubespray は非常に優れており、Ansible 上での構築、新しいノードの追加と削除、バージョンのアップグレードなど、Kubernetes を本番環境で運用するために必要なほぼすべてのプレイブックが備わっています。ただし、アップグレード プレイブックには、マイナー バージョンをスキップできないようにする免責事項が付属しています。したがって、ターゲット バージョンに到達するには、すべての中間バージョンを通過する必要があります。つまり、Kubespray はバージョン間のアップグレードをサポートしていません。 上記からわかることは、Kubernetes の使用を計画している場合、またはすでに Kubernetes を使用している場合は、ライフサイクル管理を検討してくださいということです。クラスターの構築と実行は比較的簡単ですが、Kubernetes のライフサイクル管理は比較的複雑で、より多くのコンテンツが関係します。 3. ビルドとデプロイ ビルドおよびデプロイメント パイプライン全体を再設計する準備をします。私たちのビルド プロセスとデプロイメントは、Kubernetes をベースにするために完全な変革を経る必要がありました。 Jenkins パイプラインの大幅な再構築を行っただけでなく、Helm などの新しいツールも使用し、新しい git フローとビルド戦略、Docker イメージ タグ、バージョン管理された Helm チャートも開発しました。 コードを保守するだけでなく、Kubernetes デプロイメント ファイル、Docker ファイル、Docker イメージ、Helm Charts の戦略を保守し、これらすべてをリンクする方法も設計する必要があります。 何度か繰り返し検討した結果、次のデザインに決定しました。 アプリケーション コードとその Helm チャートは、別々の Git リポジトリに配置されます。これにより、個別にバージョン管理できるようになります。 次に、アプリケーション バージョンとともに Helm チャート バージョンを保存し、リリースを追跡するために使用します。たとえば、charts-1.1.0 は app-1.2.0 とともにデプロイされます。 Helm 値ファイルのみを変更すると、チャートのパッチ バージョンのみが変更されます。 (例: 1.1.0 から 1.1.1)。これらのリリースはすべて、各リポジトリのリリース ノート RELEASE.txt によって規定されています。 私たちは、コードを構築または変更する Apache Kafka や Redis などのシステム アプリケーションとは異なる方法で作業します。つまり、Docker タグは Helm チャート バージョン管理の一部にすぎないため、2 つの Git リポジトリは存在しません。 docker タグをアップグレードに変更する場合は、chart タグのメジャー バージョン番号を増やします。 4. 活発性と準備性のプローブ(諸刃の剣) Kubernetes の活性度と準備状況の検出は、システムの問題を自動的に解決するための優れた機能です。障害が発生した場合にコンテナを再起動し、不健全なインスタンスからトラフィックを迂回させることができます。ただし、特定の障害シナリオでは、これらのプローブは諸刃の剣となり、特にメッセージング ミドルウェアやデータベースなどのステートフル アプリケーションの場合、アプリケーションの起動と回復に影響する可能性があります。 私たちの Kafka システムが被害者です。 replicationFactor が 3、minInSyncReplica が 2 の 3 つのブローカーと 3 つの Zookeeper のステートフル クラスターを実行します。予期しないシステム障害またはクラッシュ後に Kafka が起動すると、問題が発生します。これにより、起動時に破損したインデックスを修復するための追加のスクリプトが実行され、そのプロセスは重大度に応じて 10 ~ 30 分かかることがあります。追加された時間により、活性状態は継続して失敗し、Kafka に再起動の強制終了信号が送信されます。これにより、Kafka はインデックスを変更できなくなり、完全に起動できなくなりました。 唯一の解決策は、コンテナの起動後にプローブを遅延するように initialDelaySeconds 活性プローブ設定を構成することです。しかし、もちろん問題は、これを説明するのが難しいということです。復元には最大 1 時間かかる場合もあるため、これを考慮して十分なスペースを確保する必要があります。ただし、 initialDelaySeconds を大きくするほど、起動失敗時に Kubernetes がコンテナを再起動するのに時間がかかるようになるため、回復が遅くなります。 したがって、最善のアプローチは、initialDelaySeconds フィールドの値を評価して、Kubernetes で求める回復力と、あらゆる障害条件 (ディスク障害、ネットワーク障害、システム クラッシュなど) 下でアプリケーションが正常に起動するまでにかかる時間のバランスをより適切に取ることです。 更新*: 最新バージョンを使用している場合、Kubernetes ではこの問題を解決するために「スタートアップ プローブ」と呼ばれる 3 番目のプローブ タイプが導入されました*](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/)*。アルファバージョン 1.16 およびベータバージョン 1.18 以降で利用可能です。 コンテナが起動する前に、起動プローブは準備状況と生存状況のチェックを無効にして、アプリケーションの起動が中断されないようにします。 5. 外部IP 外部 IP を使用してサービスを公開すると、カーネルの接続追跡メカニズムに大きな負荷がかかる可能性があることがわかりました。詳細に計画され、熟考されていなければ、規模が大きくなるとすぐに崩壊してしまいます。 私たちのクラスターは、Kubernetes 内のルーティング プロトコルとして Calico CNI と BGP 上で実行され、エッジ ルーターに接続することもできます。 Kubeproxy では、IP テーブル モードを使用します。私たちは Kubernetes で大規模なサービスをホストしており、これは外部 IP 経由で公開され、1 日に数百万件の接続を処理します。 SNAT の使用とソフトウェア定義ネットワークからのマスカレードのため、Kubernetes にはこれらすべての論理フローを追跡するメカニズムが必要です。これを行うには、カーネルの Conntrack および netfilter ツールを使用して、静的 IP への外部接続を管理し、それを内部サービス IP に変換して、最終的にポッド IP に変換します。転送プロセスはすべて、conntrack テーブルと IP テーブルを通じて完了します。 ただし、この conntrack テーブルには制限があります。この制限に達すると、Kubernetes クラスター (および基盤となる OS カーネル) は新しい接続を受け入れることができなくなります。 RHEL では、この方法で確認できます。
この問題を解決する方法の 1 つは、エッジ ルーターを使用して複数のノードを接続し、静的 IP への着信接続がクラスター全体に分散されるようにすることです。したがって、クラスターに多数のマシンがある場合は、累積的に大きな conntrack テーブルを作成して、多数の着信接続を処理できます。 2017 年に初めて確立されたとき、これはすべて困難なことでしたが、最近では 2019 年に Calico によって詳細に検討されました (https://www.projectcalico.org/when-linux-conntrack-is-no-longer-your-friend/)。 6. Kubernetes は本当に必要ですか? 3年経った今でも、私たちは毎日新しいことを発見し、学んでいます。 Kubernetes は複雑なプラットフォームであり、特に環境の構築と維持において独自の課題が伴います。設計、考え方、アーキテクチャが変わり、アーキテクチャの変革に対応するためにチームの能力を高めることが必要になります。 ただし、クラウドを使用していて、Kubernetes を「サービス」として使用できる場合は、「内部ネットワークの CIDR をどのように拡張するか」など、プラットフォームのメンテナンスに伴うオーバーヘッドの多くを軽減できます。または「Kubernetes のバージョンをアップグレードするにはどうすればよいですか?」 今日、私たちは、自分自身に最初に尋ねる必要がある質問は「Kubernetes は本当に必要ですか?」であることに気づきました。これにより、抱えている問題を評価し、Kubernetes がその問題を解決することがどれほど重要であるかを把握できます。 Kubernetes の変革は想像したほど単純でも安価でもありません。これに支払う価格は、本当に「あなたの」アプリとそれがプラットフォームをどのように活用するかを示すものでなければなりません。これらの条件が満たされれば、Kubernetes によって生産性が大幅に向上します。 覚えておいてください、テクノロジーのためのテクノロジーは無意味です。 元記事: https://medium.com/better-programming/3-years-of-Kubernetes-in-production-heres-what-we-learned-44e77e1749c8 |
<<: 2020 年に注目すべき 5 つのクラウド トレンド
>>: CDN をベースとしたエッジコンピューティング プラットフォームの設計と考察
12月10日の報道によると、わが国のインターネット相互接続は2012年に初期成果を達成し、ネットワー...
[要約] しかし、実際には、UC は Shenma Search に完全に切り替えるつもりはありませ...
この記事は、「Seller Digital Edition」編集長の招待を受けて、Taobaoストア...
2018年最もホットなプロジェクト:テレマーケティングロボットがあなたの参加を待っています広州でウェ...
Ramnodeは2010年に設立されました。以前はホスト猫が観察段階にあったため、リリースされていま...
[51CTO.com からのオリジナル記事]サーバーレスは、業界では仮想化技術とコンテナ技術に続く、...
長い間デザインをやってきたけれど、振り返ってデザインとは何なのかを考えることがある。私の理解では、デ...
新しいサイトの最適化計画は、これまでと同じように最適化できますか? 検索エンジンのみに最適化すること...
中国におけるクラウドコンピューティングは急速に発展している産業です。業界のプレイヤーたちは非常に激し...
Kubbur は毎年設立される新しい会社です。オフィスはアイスランドにあり、英国に登録されています。...
日本のインスタントメッセージング企業LINEの親会社ネイバーは水曜日、LINEが東京で新規株式公開(...
[編集者注] この記事の著者 @刘津legene モバイル インターネットの急速な発展に伴い、多くの...
外部リンクが王様で、内部リンクが最も重要だと言われています。では、ウェブサイトで内部リンクをうまく活...
みなさんこんにちは。私はインターネット金融業界のASO運用スペシャリストです。現在、2 つのアプリの...
今日になって初めて、私は長い間 SEO に関する記事を書いていないことに気づきました。しかし、それは...