Developer Toolchain for Platform Engineering
はじめに
Kubernetes の登場以来、DevOps、コンテナ化、可観測性、マイクロサービス、サーバーレスなどの技術に代表されるクラウドネイティブは、アプリケーションアーキテクチャの新たなアップグレードをもたらしました。興味深いことに、これまでの技術の反復的な更新とは異なり、もともとは技術コミュニティ内での日常的な技術実践であったものが、数多くの業界のデジタルトランスフォーメーションという背景の下、パンデミックの継続的な影響と一部の伝統的な業界の技術自立政策という二重の影響を受けて、この技術イテレーションはほぼすべての IT 実践者が参加する一大イベントとなりました。しかし、急峻なラーニングカーブ、複雑な技術体系、そして一時的な基礎リソースの形態は、企業の情報システム構築における開発、構築、デリバリー、運用保守に多くの課題をもたらしました。これらの課題は、日々更新される技術スタックと、最前線のビジネス開発に集中することに慣れている開発者との間の矛盾をさらに深めました。この矛盾が、近年注目されているプラットフォームエンジニアリングというコンセプトの誕生に直接つながりました。
このコンセプトは、この矛盾点に着目し、「内部 R&D セルフサービスプラットフォーム」という概念を提唱しています。すなわち、「企業はプラットフォーム構築の形で一連のセルフサービスツールを開発者に提供し、各工程で直面するさまざまな技術的な問題の解決を支援すべきである」というものです。この提言は多くの開発者のニーズに合致し、このコンセプトが急速に注目を集めた理由の一つとなっています。コンセプトの背後には、より直接的な疑問が提起されました。このツールには何が含まれるべきなのか?
問題の全貌を明らかにする
2018 年初頭、EDAS の製品開発チームは、100 人規模の開発チームを持つ顧客を訪問しました。当時、その顧客はマイクロサービスの分割とクラウド移行を進めており、いくつかの新たな問題に直面していました。
・依存関係の問題により、ローカルで完全な環境を起動できず、開発が困難である。
・クラウド環境の呼び出し関係が複雑で、デバッグができない。
顧客が期待していたのは、ローカルで特定のインスタンスを起動し、クラウドからのトラフィックをローカルに転送でき、ローカルからクラウドへの転送も可能にすることで、マイクロサービスとクラウドのエンドツーエンドの共同デバッグを実現することでした。我々はこの問題に対する準備がなかったため、帰社後すぐに調査分析を開始し、水面下に隠れた氷山の全貌を徐々に明らかにしていきました。
顧客の要求は非常にシンプルで、ローカルでマイクロサービスアプリケーションを実行し、そのアプリケーションがクラウド上のマイクロサービスと相互に呼び出し可能にすることです。以下の図の通りです。
クラウド移行後、顧客のゲートウェイ、アプリケーション、メッセージキュー、キャッシュ、データベースなどのコンポーネントモジュールはすべてクラウドネットワーク内にデプロイされ、ローカルからは踏み台サーバー経由でしかアクセスできません。この状況では、ローカルノードを正常に起動すること(データベースなどの重要なコンポーネントに接続できないため)も、クラウドサービスと相互に呼び出すことも不可能です。クラウドネイティブアーキテクチャを採用した後、顧客はもはや以前のシンプルで効率的なローカル開発の方法に戻ることができなくなりました。
この問題は、この顧客だけが直面しているのでしょうか?いいえ、過去数年間にわたり多くの顧客と話をしましたが、皆同じ問題を抱えていました。しかし実際には、解決策が全くないわけではありません。最も直接的な方法は、プライベートネットワークを構築してローカルオフィスネットワークとクラウドネットワークを接続し、ネットワークの相互運用性を実現することです。しかし実際には、この方法には三つの大きな欠点があり、採用する顧客は多くありません。
・高コスト:専用回線ネットワークの構築への投資は非常に大きく、得られるメリットに対してコスト効率が悪いです。
・低いセキュリティ:ローカルネットワークをクラウドに接続することは、ローカルオフィスネットワークとクラウド本番ネットワークの両方に不安定性をもたらし、本質的にセキュリティドメインを拡大し、攻撃対象領域を広げることになります。
・複雑な運用保守:ネットワークの運用保守はかなり複雑です。スケーラビリティの高いクラウドネイティブアーキテクチャの下でローカルとクラウドのネットワークのバランスを取ることは、多くのネットワークエンジニアにとって悪夢です。ローカルとクラウドのネットワークを適切に計画し、両側のネットワークセグメントが競合しないようにする必要があります。同時に、双方向のネットワークルーティングとセキュリティポリシーは手動で管理する必要があり、複雑で労力がかかり、問題が発生しやすいものです。
これらの問題に対して、一部の企業は妥協的なアプローチを採用しています。クラウド上で一台のマシンを VPN サーバーとして用意し、ローカルからクラウドへの VPN リンクを構築する方法です。この解決策もネットワークの相互運用性を実現するためにネットワークルーティングの保守が必要です。さらに、OpenVPN は安価ですが不安定で、専用 VPN は高性能ですが高価です。二者択一となります。
これらの問題を認識した上で、我々は「道は長くとも道は道なり」の探求の旅に出ました。
端末 - クラウド相互接続:問題への最初の答え
当初、我々は二つの目標を設定しました。一つはローカルとクラウドのリンクを双方向に開放すること、もう一つはネットワークアーキテクチャに大幅な変更を加えないことです。
三か月の集中開発を経て、2018 年末にこのツールを完成させました。双方向通信をサポートし、すぐに使えるプラグイン形式で、Windows と macOS に対応しています。我々はこれを端末 - クラウド相互接続と名付け、その全体構成は以下の通りです。
端末 - クラウド相互接続プラグインは、マイクロサービス起動時にサイドカープロセスであるチャンネルサービスを起動します。チャンネルサービスはローカルマイクロサービスのトラフィックを受信し、踏み台サーバー経由でクラウド側のターゲットマイクロサービスに転送する役割を担います。以下で三つの重要なポイントをさらに詳しく説明します。
ローカルマイクロサービスの呼び出しをサイドカーに転送
Java のネイティブトラフィックプロキシ技術を使用します。起動時パラメーターを注入することで、ローカルマイクロサービスのトラフィックを SOCKS プロトコル経由でチャンネルサービスのサイドカーに転送できます。パラメーターの詳細については、Java Networking and Proxies を参照してください。
サイドカーからクラウドマイクロサービスへの呼び出し転送
実際、SSH 自体をデータ転送に利用でき、フォワードプロキシおよびリバースプロキシとして機能させることができます。SSH プロトコルは下位から上位に向かって、トランスポートレイヤー、認証レイヤー、接続レイヤーの三層に分かれています。
・トランスポートレイヤープロトコル:このレイヤーのプロトコルはセキュアな接続チャネルの確立を担当し、SSH セキュリティ全体の基盤となります。
・ユーザー認証プロトコル:このプロトコルはリモート認証を担当します。
・接続プロトコル:このレイヤーのプロトコルは SSH チャネルの多重化と情報交換を実現し、リモートコマンド実行やデータ転送など、さまざまな機能を実現できます。
SSH 接続プロトコルを使用して、チャンネルサービスサイドカーからクラウドマイクロサービスへの呼び出しを転送します。SSH の基盤原理は多少複雑ですが、上層部の使い方は比較的シンプルで、主要なプログラミング言語には基本的にすぐに使えるライブラリが用意されています。
クラウドマイクロサービスの呼び出しを踏み台サーバーに転送
ここでは、マイクロサービスの仕組みを利用して、踏み台サーバーの IP アドレスと特定のポートを、ローカルマイクロサービスのアドレス情報としてサービスレジストリに登録します。これにより、クラウド側のマイクロサービスから呼び出しがあった場合、レジストリ経由で踏み台サーバーが発見され、サービスリクエストが開始されます。SSH のデータ転送と組み合わせることで、ローカルマイクロサービスへの応答を実現できます。
百度千尋
端末 - クラウド相互接続ツールのリリース後、多くのお客様に歓迎されましたが、利用 過程で新たな問題に直面しました。
・NIO トラフィックプロキシの問題:Java Networking and Proxies のトラフィックプロキシパラメーターは BIO トラフィックにのみ有効で、NIO フレームワークには対応していません。この問題は非常に大きな影響を与えます。なぜなら、マイクロサービスアプリケーションは基本的に Java NIO フレームワークを直接的または間接的に使用しているからです。具体的でシンプルな例を挙げると、Netty 自体が Java NIO に基づいており、多くの人気ミドルウェアフレームワークが Netty を転送フレームワークとして使用しています。
・ドメイン名解決:ローカルマイクロサービスアプリケーションは、アクセス前にドメイン名解決を開始しますが、これらのドメイン名解決も Java のトラフィックプロキシではサポートされていません。つまり、ドメイン名がクラウド内でのみ解決可能な場合、呼び出し全体が失敗します。たとえば、Kubernetes 内のサービスドメイン名はクラスターノード上の DNS でしか解決できず、ローカルでは解決できないため、ローカルから Kubernetes サービスを呼び出すことができません。
これらの問題に対して、業界では通常コンテナを使用して解決しています(Telepresence など)。アプリケーションをコンテナ内で実行し、iptables と組み合わせてコンテナ内のトラフィック全体をインターセプトして転送します。この方法は有効であり、我々もサポートしています。全体のアーキテクチャは以下の通りです。
この構成は以前と似ていますが、ローカルにコンテナ技術が導入されている点が異なります。上の図では、docker network connect を使用してアプリケーションコンテナとサイドカーコンテナがネットワークスタックを共有できるようにし、チャンネルサービスが iptables を通じてローカルマイクロサービスプロセスのトラフィック(NIO と DNS トラフィックを含む)をインターセプトして転送できるようにしています。
プランは理想的ですが、現実は非常に厳しく、多くのお客様が利用できていません。その理由は、ローカル開発にコンテナという重い依存関係を導入する必要があるからです。ここには二つの問題があります。「重い」ということと、「依存関係」です。「重い」のは、ローカル開発マシンのコンピューティング能力が非常に限られているためです。Chrome、IDE、コミュニケーションソフトウェアなどのアプリケーションが、ローカルマシンのリソースの大半を占めていることが多く、そのような状況でローカルでコンテナを起動すると、クラッシュにつながることがよくあります。さらに、Windows や macOS などの主流オペレーティングシステムには Docker などのコンテナソフトウェアがプリインストールされていません。開発者がローカルに自分でインストールする必要がありますが、ネットワーク帯域幅などの理由により、インストール過程で多くの問題に直面します。
コンテナを使用する以外に、アプリケーションのトラフィックプロキシ問題を解決する方法はあるのでしょうか?ありますが、制約が非常に大きいです。たとえば、torsocks というツールはプロセスレベルで TCP と DNS トラフィックをインターセプトして転送できますが、Windows システムをサポートしていないという問題があります。macOS にも問題があります。torsocks は LD_PRELOAD/DYLD_INSERT_LIBRARIES の仕組みに基づいてシステムコールを書き換えてトラフィックをインターセプトしますが、macOS システム自体にシステム整合性保護があり、特定のシステムコールの書き換えを防ぐため、すべてのトラフィックをインターセプトできるわけではありません。
より良い解決策はないのだろうか?
灯火闌珊の処に人あり
直面していた問題を振り返ります。Java のネイティブトラフィックプロキシは NIO と DNS トラフィックの転送をサポートしていません。ここで非常に重要な情報があります——Java です。業界やオープンソースコミュニティのトラフィックインターセプト解決策は汎用性を追求する傾向があり、そのためにコンテナ依存を導入し、他方を失っています。
汎用性の追求に多くの問題があるならば、Java 言語に特化したより良い解決策はないでしょうか?答えはイエスです。Java は Agent バイトコード技術を通じて、上位層のコードを一切変更せずにアプリケーションのランタイム動作を動的に変更できます。たとえば、Pinpoint や SkyWalking などのリンクトレースツールは、バイトコードエージェントを注入することで非侵入型のリンク計装を実現しています。また、診断分野で人気の Arthas ツールも、バイトコード技術に基づいて Java プロセスの呼び出し追跡とプロファイリングを実現しています。
そこで、我々はバイトコード技術に基づく解決策の探求を始めました。探求の全過程は困難でありながらも興味深いものでした。マイクロサービスフレームワークレベルでは、SpringCloud、Dubbo、HSF、さらには gRPC などの主流フレームワークへの適応が必要です。コンポーネントレベルでは、マイクロサービス、データベース、メッセージキュー、タスクスケジューリング、キャッシュなどのコンポーネントをサポートする必要があります。JDK バージョンでは、JDK 1.7 から JDK 18 までのバージョンとの互換性が必要です。この過程で、我々は継続的にイテレーションと改善を重ね、顧客からポジティブなフィードバックを受け続け、ツールをますます完璧なものにしていきました。
1 年間の磨き上げを経て、ついにバイトコードベースの Java トラフィックプロキシ技術を開発しました。アーキテクチャは以下の通りです。
この解決策はバイトコードエージェントを導入するだけで、外部依存を導入しません。このプロキシエージェントはコンテナよりもはるかに軽量で、端末 - クラウド相互接続プラグインによって起動段階で自動的にプルおよび注入され、上位層からは認識されません。これで、ローカルマイクロサービスアプリケーションのトラフィックプロキシ問題をようやく解決できました。
高楼に独り登りて天涯の路を望む
ここ数年間、我々は地道に問題の発見と解決に取り組んできました。同時に、クラウドネイティブコミュニティも徐々に進化しています。同じく 2018 年に、Kubernetes コミュニティは Developing on Kubernetes という記事を公開し、さまざまな開発モードを非常によくまとめています。
remote はクラウドを意味し、local はローカルを意味します。cluster は K8s クラスター、dev は開発環境です。dev と cluster の位置の違いに応じて、全体は四つの開発モードに分類できます。
・Pure off-line:このモードは、K8s クラスターと開発環境の両方がローカルにあることを意味します。K3s、Minikube、EDAS Core(後ほど紹介します)がすべてこのモードに属し、ローカルで軽量開発クラスターを直接起動できます。
・Proxied:このモードは、K8s クラスターがクラウド上で動作し、開発環境がローカルにあり、プロキシを通じてクラウドクラスターとローカル開発環境を接続することを意味します。このモデルの典型は、コミュニティの Telepresence と EDAS の端末 - クラウド相互接続です。Telepresence は多言語対応の汎用性でやや優れており、Java においては EDAS の端末 - クラウド相互接続の方が使いやすいです。
・Live:このモードは、K8s クラスターがクラウド上で動作し、開発環境がローカルにあり、ローカルコードが CI/CD などの方法でクラウド側のアプリケーションを更新することを意味します。このモードは最も一般的なモードであり、同時に一般的に最も効率の低いモードでもあります。CI/CD 経由でデプロイする場合、コードを変更するたびに長時間のビルドとデプロイを経てクラスターで有効化する必要があります。開発中にデバッグのためにコードを継続的に変更する必要がある場合、この反復デプロイプロセスは非常に時間がかかります。
・Remote:このモードは、K8s クラスターと開発環境の両方がクラウド上にあることを意味します。Cloud IDE が典型例です。コードと実行環境の両方がクラウド上にあり、ブラウザまたは軽量エンドアプリケーションを通じてローカルでコードを編集します。実際、この方法は大多数の開発者に認められているわけではありません。ローカル IDE の体験は Cloud IDE よりも優れており、ローカル開発が依然として主流です。
Proxied モードにおいて、我々は端末 - クラウド相互接続をかなり磨き上げましたが、すべての問題を解決できるわけではありません。よくあるシナリオがあります。ローカルでの開発とデバッグは問題ないのに、デプロイすると問題が発生するというものです。この問題の根本原因は、ローカルの動作環境とクラウドクラスター内の動作環境が不一致であることで、この不一致がさまざまな問題を引き起こします。たとえば、ローカルで 2c4g のリソースを必要とする Java プロセスが正常に動作しても、クラウド上のクラスターでも同じく 2c4g の Pod を正常に割り当てられるとは限りません。現在のクラスターに余剰リソースがない可能性があるからです。
このような問題は非常に多く、一つずつ列挙することは不可能です。このことが、我々にこれらの問題をどのように解決するかをさらに考えさせるきっかけとなりました。半年間の研究、探求、開発を経て、我々は Cloud Native Development Kit(略称 CNKit)を開発し、これらの問題を解決すると同時に、クラウドネイティブアーキテクチャ下での開発、デバッグ、診断機能を提供します。
Cloud Native Development Kit
我々の問題解決のアプローチは明確です。環境の不一致問題を解決するには、環境そのものに戻るしかありません。クラウドネイティブ環境でアプリケーションを起動するのは一見単純に見えますが、実際には多くのステップを経る必要があります。アプリケーションは K8s のスケジューリング、Pod の初期化、サービスの起動を経て、ようやくアプリケーションの動作が完了します。この過程で、以下のような問題に遭遇する可能性があります。
これらの問題に対して、我々は解決策をまとめ、体系化しました。CNKit を使用して Pod を素早くレプリケーションし、その後反復的に開発、デプロイ、デバッグ、診断を行います。全体の機能は以下の通りです。
EDAS のフルリンクフロー制御と連携することで、CNKit は特定のルールに合致するデバッグトラフィックのみをレプリケーション Pod に流入させ、他の通常のトラフィックに影響を与えません。レプリケーション Pod に対しては、CNKit のすぐに使えるデプロイ、デバッグ、診断機能を使用でき、監査ベースのコマンドターミナルも利用できます。以下で、レプリケーション、デプロイ、デバッグ、診断の各機能について詳しく説明します。
レプリケーション
このレプリケーション Pod は、自分専用の一時的なワークスペースに相当します。ブラウザまたは IDE を通じて継続的にアプリケーションパッケージをデプロイし、デバッグと診断を実行できます。レプリケーション Pod は現在、以下の設定をサポートしています。
各設定項目の役割は以下の通りです。
・起動コマンド:Pod の起動コマンドです。デフォルトでは元のイメージの起動コマンドを使用しますが、反復デプロイやデバッグが必要な場合はカスタム起動コマンドが必要です。これは、本番環境では元のイメージの起動コマンドがアプリケーションプロセスを PID 1 として扱うことが多く、アプリケーションが終了または再起動すると Pod もそれに応じて解放されるためです。そのため、アプリケーションが終了しても Pod が解放されないよう、特別な起動コマンドを設定する必要があります。
・レプリケーションモード:Pod ベースのレプリケーション、または Deployment の spec からの作成をサポートします。
・ターゲットノード:Pod が実行されるクラスターノードです。デフォルトでは K8s のスケジューリングを通じて Pod を実行しますが、特定のクラスターノードを直接指定して Pod を実行することもできます。
・Pod ログ:Pod ログを標準出力にプリントするか、ファイルにリダイレクトするかを設定します。
・フロー制御:フルリンクフロー制御を通じて、特定のルールに合致するリクエストのみを Pod ノードに流入させます。
・診断オプション:アプリケーション起動時に tcpdump を即時実行してモニタリングすることや、JVM 例外ログの有効化、Liveness プローブの削除をワンクリックで行うことをサポートします。
これらの設定項目は、長年の EDAS カスタマーサポートの経験に基づいており、見た目は華やかではありませんが、非常に実用的です。「Liveness プローブの削除」を例に取ると、アプリケーション起動段階で例外が発生した場合、Liveness プローブが失敗し、K8s が Pod コンテナを直接終了して再起動します。Liveness の失敗、Pod コンテナの終了、そしてコンテナ再起動による Liveness の再失敗という無限ループに陥ってしまいます。Liveness プローブを削除すれば、Pod コンテナ内に入って原因を調査できます。
ここにもう一つ非常に興味深い設定項目があります。フルリンクフロー制御です。フルリンクフロー制御は EDAS のマイクロサービスガバナンスのキラー機能であり、マイクロサービスリンク全体のトラフィックを自在に制御できます。レプリケーション Pod に対して、自分自身のリクエストのみをこの Pod に流入させ、他のユーザーの呼び出しリクエストに影響を与えたくない場合があります。その場合、インターフェイス上で特定のフロー制御グループに参加するチェックを入れるだけでよく、使い方は非常にシンプルです。
デプロイ
元の課題を覚えていますか?クラウドネイティブアーキテクチャの下では、デプロイのたびに CI/CD、EDAS デプロイ、K8s スケジューリングを経てアプリケーションを起動する必要があります。このプロセスは長く、苦痛を伴います。さらに、問題調査時に特定のツールを一時的にインストールする必要がよくありますが、新しいアプリケーション Pod が起動されるたびに、必要なツールを再インストールする必要があります。
この問題に対して、我々は「一度コピーすれば何度でも使える」という戦略を推奨します。前述の通り、Pod をコピーして自分専用の「一時的なワークスペース」(本質的には Pod)を作成し、ブラウザまたは IDE からアプリケーションパッケージを一時的なワークスペースに直接デプロイして、デバッグと診断を実行できます。CI/CD ベースの開発プロセスと CNKit を使用した開発プロセスは以下のように大きく異なります。
CI/CD デプロイパスは本番環境に適しており、標準化されたプロセスを通じてオンラインビジネスの安定性を保証します。しかし同時に長いプロセスであり、開発段階ではメリットが明確ではなく、むしろ開発効率を低下させます。このような場合、CNKit のデプロイプロセスがよい補完となります。Pod をコピーするだけで、ブラウザまたは IDE から継続的にアプリケーションパッケージを更新し、コードをデバッグできます。
デバッグ
デバッグ(ここでは特にリモートデバッグを指します)は、アプリケーション開発プロセスにおいて非常に重要な要素です。デバッグができなければ、アプリケーション開発の効率は大幅に低下します。クラウドネイティブアーキテクチャの下では、アプリケーションのデバッグはそれほどシンプルではありませんが、実現は可能です。この点において、CNKit はデバッグプロセスを簡素化するだけでなく、フロー制御機能も提供します。
・プロセスの簡素化:ページ上で「デバッグを有効化」をクリックするだけで、CNKit が Pod 内のアプリケーションを再起動してデバッグポートを開きます。その後、ローカルで IDE から CNKit にワンクリックで接続し、ブレークポイントデバッグを開始できます。
・フロー制御:EDAS のフルリンクフロー制御と連携することで、CNKit は特定のリクエストのみをレプリケーション Pod に流入させ、ブレークポイントデバッグロジックをトリガーできます。
この二つのポイントを通じて、非常に便利にコードデバッグを完了できます。下図はシンプルな例です。商品センターを開発していて、上流が取引センター、下流がインベントリセンターの場合、CNKit を使用したデバッグの全体リンクは以下のようになります。
開発バージョンとしてマークされた商品センターがレプリケーション Pod ノードです。クラウド環境では、フルリンクフロー制御を通じて特定のトラフィックが Pod に転送され、開発者はローカルで CNKit プロキシを通じて Pod のデバッグポートに接続します。
実際、複数人で並行開発するサービスでは、各開発者が独自の開発バージョンノードを持つことができ、異なるフロー制御ルールを設定するだけで、互いに干渉せずに並行開発を進められます。
診断
問題を四つのフェーズに分けて診断します。K8s スケジューリング、アプリケーション起動、アプリケーション実行中、アプリケーション停止です。フェーズが異なれば、採用する診断方法も異なります。
K8s スケジューリング中は、主に生成される関連イベントに注目します。スケジューリング異常が発生した場合、K8s は関連する理由を示します。下図は正常なスケジューリング時の K8s イベントです。
スケジューリング異常(リソース不足によるスケジューリング失敗など)が発生した場合、K8s は対応するイベントを生成します。
アプリケーション起動フェーズでは、K8s イベントに加えて Pod ログも確認できます。Pod ログはアプリケーションによって生成され、より詳細な情報が含まれています。下図は Pod の標準出力ログのサンプルです。
さらに、アプリケーション起動フェーズではネットワークアクセスが多くなります。多くの場合、アプリケーション起動の失敗はネットワークリクエストの異常によって引き起こされます。そのため、CNKit は起動前に tcpdump を自動実行してネットワークリクエストを記録することをサポートしています。下図はアプリケーション起動時に自動キャプチャされた tcpdump データです。CNKit はテキスト形式と pcap 形式の二つの形式をサポートしています。下図はテキスト形式の tcpdump データです。
最後に、アプリケーションの実行中および停止時にも K8s イベント、Pod ログ、tcpdump を引き続き使用でき、さらに CNKit にワンクリックで統合された Arthas ツールも使用できます。ページ上で Arthas をワンクリック実行すると、CNKit が Arthas のインストールと実行を自動的に完了します。全体のインタラクションは以下の通りです。
ここまで、CNKit のレプリケーション、デプロイ、デバッグ、診断について一つずつ共有してきました。しかし、これらの機能に加えて、CNKit には監査 Webshell などの隠れた機能もあります。これらの機能は読者の皆様がゆっくり探求していただくものとし、ここでは詳しく述べません。
EDAS Core
端末 - クラウド相互接続と CNKit に加えて、我々は EDAS Core も公開しました。前述の Developing on Kubernetes の分類基準に従うと、端末 - クラウド相互接続は Proxied モード、CNKit は Live モード、EDAS Core は Pure off-line モードに属します。
EDAS 自体は有料の商用プロダクトです。アプリケーションホスティングとマイクロサービス管理のためのクラウドネイティブ PaaS プラットフォームであり、アプリケーション開発、デプロイ、モニタリング、運用保守などのフルスタックソリューションを提供し、サービスの動作環境を構築します。一方、EDAS Core は無料の軽量 EDAS カーネルバージョンで、同様の機能をサポートしていますが、商用機能を取り除き、サービス SLA とリアルタイム運用保守サポートを提供せず、開発フェーズでの使用に適しています。
EDAS Core は最小で 4 コア 8 GB のマシンリソースのみを必要とします。ローカルの PC 上でオフライン EDAS プラットフォームを実行し、マイクロサービスの開発を行うことができます。EDAS Core の全体アーキテクチャは以下の通りです。
以下に簡単に説明します。
・EDAS Core:EDAS アプリケーションホスティング機能を含み、Nacos のサービス登録と検出、Minio の永続ストレージをサポートします。Kind、K3s、Docker Desktop、K8s クラスター上で実行可能で、必要なリソースはわずか 4c8g です。
・開発者ツール:Jenkins プラグインによる継続的デプロイ、Terraform によるインフラストラクチャ管理、ACT によるローカル開発をサポートし、EDAS Open API および SDK と互換性があります。
・インストールメディア:Helm、OSS、ADP 経由での EDAS Core インストールをサポートします。
・K8s クラスター:この K8s クラスターは EDAS Core が管理するクラスターであり、マイクロサービスアプリケーションが実行されます(サービス管理用 OneAgent が自動的に注入されます)。
・サービス連携:水平方向のサービス連携において、EDAS Core は EDAS 商用アプリケーションとのワンクリック変換をサポートし、ARMS や SkyWalking などのリンクトレース製品と統合され、ACR を使用したイメージホスティングをサポートします。
以下は EDAS Core の実行画面です(旧 EDAS ユーザーにはおなじみの画面でしょう)。
現在、EDAS Core は社内ベータテスト中です。この機能をご利用になりたい場合は、Alibaba Cloud で EDAS 製品に関するサポートチケットを起票してご相談ください。
エピローグ
クラウドネイティブアーキテクチャとマイクロサービス開発はどちらも非常に人気の高い技術分野ですが、「クラウドネイティブアーキテクチャ下でのマイクロサービス開発」という命題は、国内ベンダーからはほとんど語られていません。マイクロサービスホスティング分野のパイオニアとして、EDAS は非常に早い時期からクラウドネイティブアーキテクチャのサポートに取り組み始め、新しいアーキテクチャ下でのマイクロサービス開発の動向に注目し続けてきました。
初期の端末 - クラウド相互接続モデルから、最近リリースされた Cloud Native Development Kit(CNKit)と EDAS Core に至るまで、EDAS はクラウドネイティブ技術の進化に伴う新たな課題を開発者の視点から考え続け、これらの問題を解決するためのツールとプロダクトを継続的に提供しています。
Kubernetes の登場以来、DevOps、コンテナ化、可観測性、マイクロサービス、サーバーレスなどの技術に代表されるクラウドネイティブは、アプリケーションアーキテクチャの新たなアップグレードをもたらしました。興味深いことに、これまでの技術の反復的な更新とは異なり、もともとは技術コミュニティ内での日常的な技術実践であったものが、数多くの業界のデジタルトランスフォーメーションという背景の下、パンデミックの継続的な影響と一部の伝統的な業界の技術自立政策という二重の影響を受けて、この技術イテレーションはほぼすべての IT 実践者が参加する一大イベントとなりました。しかし、急峻なラーニングカーブ、複雑な技術体系、そして一時的な基礎リソースの形態は、企業の情報システム構築における開発、構築、デリバリー、運用保守に多くの課題をもたらしました。これらの課題は、日々更新される技術スタックと、最前線のビジネス開発に集中することに慣れている開発者との間の矛盾をさらに深めました。この矛盾が、近年注目されているプラットフォームエンジニアリングというコンセプトの誕生に直接つながりました。
このコンセプトは、この矛盾点に着目し、「内部 R&D セルフサービスプラットフォーム」という概念を提唱しています。すなわち、「企業はプラットフォーム構築の形で一連のセルフサービスツールを開発者に提供し、各工程で直面するさまざまな技術的な問題の解決を支援すべきである」というものです。この提言は多くの開発者のニーズに合致し、このコンセプトが急速に注目を集めた理由の一つとなっています。コンセプトの背後には、より直接的な疑問が提起されました。このツールには何が含まれるべきなのか?
問題の全貌を明らかにする
2018 年初頭、EDAS の製品開発チームは、100 人規模の開発チームを持つ顧客を訪問しました。当時、その顧客はマイクロサービスの分割とクラウド移行を進めており、いくつかの新たな問題に直面していました。
・依存関係の問題により、ローカルで完全な環境を起動できず、開発が困難である。
・クラウド環境の呼び出し関係が複雑で、デバッグができない。
顧客が期待していたのは、ローカルで特定のインスタンスを起動し、クラウドからのトラフィックをローカルに転送でき、ローカルからクラウドへの転送も可能にすることで、マイクロサービスとクラウドのエンドツーエンドの共同デバッグを実現することでした。我々はこの問題に対する準備がなかったため、帰社後すぐに調査分析を開始し、水面下に隠れた氷山の全貌を徐々に明らかにしていきました。
顧客の要求は非常にシンプルで、ローカルでマイクロサービスアプリケーションを実行し、そのアプリケーションがクラウド上のマイクロサービスと相互に呼び出し可能にすることです。以下の図の通りです。
クラウド移行後、顧客のゲートウェイ、アプリケーション、メッセージキュー、キャッシュ、データベースなどのコンポーネントモジュールはすべてクラウドネットワーク内にデプロイされ、ローカルからは踏み台サーバー経由でしかアクセスできません。この状況では、ローカルノードを正常に起動すること(データベースなどの重要なコンポーネントに接続できないため)も、クラウドサービスと相互に呼び出すことも不可能です。クラウドネイティブアーキテクチャを採用した後、顧客はもはや以前のシンプルで効率的なローカル開発の方法に戻ることができなくなりました。
この問題は、この顧客だけが直面しているのでしょうか?いいえ、過去数年間にわたり多くの顧客と話をしましたが、皆同じ問題を抱えていました。しかし実際には、解決策が全くないわけではありません。最も直接的な方法は、プライベートネットワークを構築してローカルオフィスネットワークとクラウドネットワークを接続し、ネットワークの相互運用性を実現することです。しかし実際には、この方法には三つの大きな欠点があり、採用する顧客は多くありません。
・高コスト:専用回線ネットワークの構築への投資は非常に大きく、得られるメリットに対してコスト効率が悪いです。
・低いセキュリティ:ローカルネットワークをクラウドに接続することは、ローカルオフィスネットワークとクラウド本番ネットワークの両方に不安定性をもたらし、本質的にセキュリティドメインを拡大し、攻撃対象領域を広げることになります。
・複雑な運用保守:ネットワークの運用保守はかなり複雑です。スケーラビリティの高いクラウドネイティブアーキテクチャの下でローカルとクラウドのネットワークのバランスを取ることは、多くのネットワークエンジニアにとって悪夢です。ローカルとクラウドのネットワークを適切に計画し、両側のネットワークセグメントが競合しないようにする必要があります。同時に、双方向のネットワークルーティングとセキュリティポリシーは手動で管理する必要があり、複雑で労力がかかり、問題が発生しやすいものです。
これらの問題に対して、一部の企業は妥協的なアプローチを採用しています。クラウド上で一台のマシンを VPN サーバーとして用意し、ローカルからクラウドへの VPN リンクを構築する方法です。この解決策もネットワークの相互運用性を実現するためにネットワークルーティングの保守が必要です。さらに、OpenVPN は安価ですが不安定で、専用 VPN は高性能ですが高価です。二者択一となります。
これらの問題を認識した上で、我々は「道は長くとも道は道なり」の探求の旅に出ました。
端末 - クラウド相互接続:問題への最初の答え
当初、我々は二つの目標を設定しました。一つはローカルとクラウドのリンクを双方向に開放すること、もう一つはネットワークアーキテクチャに大幅な変更を加えないことです。
三か月の集中開発を経て、2018 年末にこのツールを完成させました。双方向通信をサポートし、すぐに使えるプラグイン形式で、Windows と macOS に対応しています。我々はこれを端末 - クラウド相互接続と名付け、その全体構成は以下の通りです。
端末 - クラウド相互接続プラグインは、マイクロサービス起動時にサイドカープロセスであるチャンネルサービスを起動します。チャンネルサービスはローカルマイクロサービスのトラフィックを受信し、踏み台サーバー経由でクラウド側のターゲットマイクロサービスに転送する役割を担います。以下で三つの重要なポイントをさらに詳しく説明します。
ローカルマイクロサービスの呼び出しをサイドカーに転送
Java のネイティブトラフィックプロキシ技術を使用します。起動時パラメーターを注入することで、ローカルマイクロサービスのトラフィックを SOCKS プロトコル経由でチャンネルサービスのサイドカーに転送できます。パラメーターの詳細については、Java Networking and Proxies を参照してください。
サイドカーからクラウドマイクロサービスへの呼び出し転送
実際、SSH 自体をデータ転送に利用でき、フォワードプロキシおよびリバースプロキシとして機能させることができます。SSH プロトコルは下位から上位に向かって、トランスポートレイヤー、認証レイヤー、接続レイヤーの三層に分かれています。
・トランスポートレイヤープロトコル:このレイヤーのプロトコルはセキュアな接続チャネルの確立を担当し、SSH セキュリティ全体の基盤となります。
・ユーザー認証プロトコル:このプロトコルはリモート認証を担当します。
・接続プロトコル:このレイヤーのプロトコルは SSH チャネルの多重化と情報交換を実現し、リモートコマンド実行やデータ転送など、さまざまな機能を実現できます。
SSH 接続プロトコルを使用して、チャンネルサービスサイドカーからクラウドマイクロサービスへの呼び出しを転送します。SSH の基盤原理は多少複雑ですが、上層部の使い方は比較的シンプルで、主要なプログラミング言語には基本的にすぐに使えるライブラリが用意されています。
クラウドマイクロサービスの呼び出しを踏み台サーバーに転送
ここでは、マイクロサービスの仕組みを利用して、踏み台サーバーの IP アドレスと特定のポートを、ローカルマイクロサービスのアドレス情報としてサービスレジストリに登録します。これにより、クラウド側のマイクロサービスから呼び出しがあった場合、レジストリ経由で踏み台サーバーが発見され、サービスリクエストが開始されます。SSH のデータ転送と組み合わせることで、ローカルマイクロサービスへの応答を実現できます。
百度千尋
端末 - クラウド相互接続ツールのリリース後、多くのお客様に歓迎されましたが、利用 過程で新たな問題に直面しました。
・NIO トラフィックプロキシの問題:Java Networking and Proxies のトラフィックプロキシパラメーターは BIO トラフィックにのみ有効で、NIO フレームワークには対応していません。この問題は非常に大きな影響を与えます。なぜなら、マイクロサービスアプリケーションは基本的に Java NIO フレームワークを直接的または間接的に使用しているからです。具体的でシンプルな例を挙げると、Netty 自体が Java NIO に基づいており、多くの人気ミドルウェアフレームワークが Netty を転送フレームワークとして使用しています。
・ドメイン名解決:ローカルマイクロサービスアプリケーションは、アクセス前にドメイン名解決を開始しますが、これらのドメイン名解決も Java のトラフィックプロキシではサポートされていません。つまり、ドメイン名がクラウド内でのみ解決可能な場合、呼び出し全体が失敗します。たとえば、Kubernetes 内のサービスドメイン名はクラスターノード上の DNS でしか解決できず、ローカルでは解決できないため、ローカルから Kubernetes サービスを呼び出すことができません。
これらの問題に対して、業界では通常コンテナを使用して解決しています(Telepresence など)。アプリケーションをコンテナ内で実行し、iptables と組み合わせてコンテナ内のトラフィック全体をインターセプトして転送します。この方法は有効であり、我々もサポートしています。全体のアーキテクチャは以下の通りです。
この構成は以前と似ていますが、ローカルにコンテナ技術が導入されている点が異なります。上の図では、docker network connect を使用してアプリケーションコンテナとサイドカーコンテナがネットワークスタックを共有できるようにし、チャンネルサービスが iptables を通じてローカルマイクロサービスプロセスのトラフィック(NIO と DNS トラフィックを含む)をインターセプトして転送できるようにしています。
プランは理想的ですが、現実は非常に厳しく、多くのお客様が利用できていません。その理由は、ローカル開発にコンテナという重い依存関係を導入する必要があるからです。ここには二つの問題があります。「重い」ということと、「依存関係」です。「重い」のは、ローカル開発マシンのコンピューティング能力が非常に限られているためです。Chrome、IDE、コミュニケーションソフトウェアなどのアプリケーションが、ローカルマシンのリソースの大半を占めていることが多く、そのような状況でローカルでコンテナを起動すると、クラッシュにつながることがよくあります。さらに、Windows や macOS などの主流オペレーティングシステムには Docker などのコンテナソフトウェアがプリインストールされていません。開発者がローカルに自分でインストールする必要がありますが、ネットワーク帯域幅などの理由により、インストール過程で多くの問題に直面します。
コンテナを使用する以外に、アプリケーションのトラフィックプロキシ問題を解決する方法はあるのでしょうか?ありますが、制約が非常に大きいです。たとえば、torsocks というツールはプロセスレベルで TCP と DNS トラフィックをインターセプトして転送できますが、Windows システムをサポートしていないという問題があります。macOS にも問題があります。torsocks は LD_PRELOAD/DYLD_INSERT_LIBRARIES の仕組みに基づいてシステムコールを書き換えてトラフィックをインターセプトしますが、macOS システム自体にシステム整合性保護があり、特定のシステムコールの書き換えを防ぐため、すべてのトラフィックをインターセプトできるわけではありません。
より良い解決策はないのだろうか?
灯火闌珊の処に人あり
直面していた問題を振り返ります。Java のネイティブトラフィックプロキシは NIO と DNS トラフィックの転送をサポートしていません。ここで非常に重要な情報があります——Java です。業界やオープンソースコミュニティのトラフィックインターセプト解決策は汎用性を追求する傾向があり、そのためにコンテナ依存を導入し、他方を失っています。
汎用性の追求に多くの問題があるならば、Java 言語に特化したより良い解決策はないでしょうか?答えはイエスです。Java は Agent バイトコード技術を通じて、上位層のコードを一切変更せずにアプリケーションのランタイム動作を動的に変更できます。たとえば、Pinpoint や SkyWalking などのリンクトレースツールは、バイトコードエージェントを注入することで非侵入型のリンク計装を実現しています。また、診断分野で人気の Arthas ツールも、バイトコード技術に基づいて Java プロセスの呼び出し追跡とプロファイリングを実現しています。
そこで、我々はバイトコード技術に基づく解決策の探求を始めました。探求の全過程は困難でありながらも興味深いものでした。マイクロサービスフレームワークレベルでは、SpringCloud、Dubbo、HSF、さらには gRPC などの主流フレームワークへの適応が必要です。コンポーネントレベルでは、マイクロサービス、データベース、メッセージキュー、タスクスケジューリング、キャッシュなどのコンポーネントをサポートする必要があります。JDK バージョンでは、JDK 1.7 から JDK 18 までのバージョンとの互換性が必要です。この過程で、我々は継続的にイテレーションと改善を重ね、顧客からポジティブなフィードバックを受け続け、ツールをますます完璧なものにしていきました。
1 年間の磨き上げを経て、ついにバイトコードベースの Java トラフィックプロキシ技術を開発しました。アーキテクチャは以下の通りです。
この解決策はバイトコードエージェントを導入するだけで、外部依存を導入しません。このプロキシエージェントはコンテナよりもはるかに軽量で、端末 - クラウド相互接続プラグインによって起動段階で自動的にプルおよび注入され、上位層からは認識されません。これで、ローカルマイクロサービスアプリケーションのトラフィックプロキシ問題をようやく解決できました。
高楼に独り登りて天涯の路を望む
ここ数年間、我々は地道に問題の発見と解決に取り組んできました。同時に、クラウドネイティブコミュニティも徐々に進化しています。同じく 2018 年に、Kubernetes コミュニティは Developing on Kubernetes という記事を公開し、さまざまな開発モードを非常によくまとめています。
remote はクラウドを意味し、local はローカルを意味します。cluster は K8s クラスター、dev は開発環境です。dev と cluster の位置の違いに応じて、全体は四つの開発モードに分類できます。
・Pure off-line:このモードは、K8s クラスターと開発環境の両方がローカルにあることを意味します。K3s、Minikube、EDAS Core(後ほど紹介します)がすべてこのモードに属し、ローカルで軽量開発クラスターを直接起動できます。
・Proxied:このモードは、K8s クラスターがクラウド上で動作し、開発環境がローカルにあり、プロキシを通じてクラウドクラスターとローカル開発環境を接続することを意味します。このモデルの典型は、コミュニティの Telepresence と EDAS の端末 - クラウド相互接続です。Telepresence は多言語対応の汎用性でやや優れており、Java においては EDAS の端末 - クラウド相互接続の方が使いやすいです。
・Live:このモードは、K8s クラスターがクラウド上で動作し、開発環境がローカルにあり、ローカルコードが CI/CD などの方法でクラウド側のアプリケーションを更新することを意味します。このモードは最も一般的なモードであり、同時に一般的に最も効率の低いモードでもあります。CI/CD 経由でデプロイする場合、コードを変更するたびに長時間のビルドとデプロイを経てクラスターで有効化する必要があります。開発中にデバッグのためにコードを継続的に変更する必要がある場合、この反復デプロイプロセスは非常に時間がかかります。
・Remote:このモードは、K8s クラスターと開発環境の両方がクラウド上にあることを意味します。Cloud IDE が典型例です。コードと実行環境の両方がクラウド上にあり、ブラウザまたは軽量エンドアプリケーションを通じてローカルでコードを編集します。実際、この方法は大多数の開発者に認められているわけではありません。ローカル IDE の体験は Cloud IDE よりも優れており、ローカル開発が依然として主流です。
Proxied モードにおいて、我々は端末 - クラウド相互接続をかなり磨き上げましたが、すべての問題を解決できるわけではありません。よくあるシナリオがあります。ローカルでの開発とデバッグは問題ないのに、デプロイすると問題が発生するというものです。この問題の根本原因は、ローカルの動作環境とクラウドクラスター内の動作環境が不一致であることで、この不一致がさまざまな問題を引き起こします。たとえば、ローカルで 2c4g のリソースを必要とする Java プロセスが正常に動作しても、クラウド上のクラスターでも同じく 2c4g の Pod を正常に割り当てられるとは限りません。現在のクラスターに余剰リソースがない可能性があるからです。
このような問題は非常に多く、一つずつ列挙することは不可能です。このことが、我々にこれらの問題をどのように解決するかをさらに考えさせるきっかけとなりました。半年間の研究、探求、開発を経て、我々は Cloud Native Development Kit(略称 CNKit)を開発し、これらの問題を解決すると同時に、クラウドネイティブアーキテクチャ下での開発、デバッグ、診断機能を提供します。
Cloud Native Development Kit
我々の問題解決のアプローチは明確です。環境の不一致問題を解決するには、環境そのものに戻るしかありません。クラウドネイティブ環境でアプリケーションを起動するのは一見単純に見えますが、実際には多くのステップを経る必要があります。アプリケーションは K8s のスケジューリング、Pod の初期化、サービスの起動を経て、ようやくアプリケーションの動作が完了します。この過程で、以下のような問題に遭遇する可能性があります。
これらの問題に対して、我々は解決策をまとめ、体系化しました。CNKit を使用して Pod を素早くレプリケーションし、その後反復的に開発、デプロイ、デバッグ、診断を行います。全体の機能は以下の通りです。
EDAS のフルリンクフロー制御と連携することで、CNKit は特定のルールに合致するデバッグトラフィックのみをレプリケーション Pod に流入させ、他の通常のトラフィックに影響を与えません。レプリケーション Pod に対しては、CNKit のすぐに使えるデプロイ、デバッグ、診断機能を使用でき、監査ベースのコマンドターミナルも利用できます。以下で、レプリケーション、デプロイ、デバッグ、診断の各機能について詳しく説明します。
レプリケーション
このレプリケーション Pod は、自分専用の一時的なワークスペースに相当します。ブラウザまたは IDE を通じて継続的にアプリケーションパッケージをデプロイし、デバッグと診断を実行できます。レプリケーション Pod は現在、以下の設定をサポートしています。
各設定項目の役割は以下の通りです。
・起動コマンド:Pod の起動コマンドです。デフォルトでは元のイメージの起動コマンドを使用しますが、反復デプロイやデバッグが必要な場合はカスタム起動コマンドが必要です。これは、本番環境では元のイメージの起動コマンドがアプリケーションプロセスを PID 1 として扱うことが多く、アプリケーションが終了または再起動すると Pod もそれに応じて解放されるためです。そのため、アプリケーションが終了しても Pod が解放されないよう、特別な起動コマンドを設定する必要があります。
・レプリケーションモード:Pod ベースのレプリケーション、または Deployment の spec からの作成をサポートします。
・ターゲットノード:Pod が実行されるクラスターノードです。デフォルトでは K8s のスケジューリングを通じて Pod を実行しますが、特定のクラスターノードを直接指定して Pod を実行することもできます。
・Pod ログ:Pod ログを標準出力にプリントするか、ファイルにリダイレクトするかを設定します。
・フロー制御:フルリンクフロー制御を通じて、特定のルールに合致するリクエストのみを Pod ノードに流入させます。
・診断オプション:アプリケーション起動時に tcpdump を即時実行してモニタリングすることや、JVM 例外ログの有効化、Liveness プローブの削除をワンクリックで行うことをサポートします。
これらの設定項目は、長年の EDAS カスタマーサポートの経験に基づいており、見た目は華やかではありませんが、非常に実用的です。「Liveness プローブの削除」を例に取ると、アプリケーション起動段階で例外が発生した場合、Liveness プローブが失敗し、K8s が Pod コンテナを直接終了して再起動します。Liveness の失敗、Pod コンテナの終了、そしてコンテナ再起動による Liveness の再失敗という無限ループに陥ってしまいます。Liveness プローブを削除すれば、Pod コンテナ内に入って原因を調査できます。
ここにもう一つ非常に興味深い設定項目があります。フルリンクフロー制御です。フルリンクフロー制御は EDAS のマイクロサービスガバナンスのキラー機能であり、マイクロサービスリンク全体のトラフィックを自在に制御できます。レプリケーション Pod に対して、自分自身のリクエストのみをこの Pod に流入させ、他のユーザーの呼び出しリクエストに影響を与えたくない場合があります。その場合、インターフェイス上で特定のフロー制御グループに参加するチェックを入れるだけでよく、使い方は非常にシンプルです。
デプロイ
元の課題を覚えていますか?クラウドネイティブアーキテクチャの下では、デプロイのたびに CI/CD、EDAS デプロイ、K8s スケジューリングを経てアプリケーションを起動する必要があります。このプロセスは長く、苦痛を伴います。さらに、問題調査時に特定のツールを一時的にインストールする必要がよくありますが、新しいアプリケーション Pod が起動されるたびに、必要なツールを再インストールする必要があります。
この問題に対して、我々は「一度コピーすれば何度でも使える」という戦略を推奨します。前述の通り、Pod をコピーして自分専用の「一時的なワークスペース」(本質的には Pod)を作成し、ブラウザまたは IDE からアプリケーションパッケージを一時的なワークスペースに直接デプロイして、デバッグと診断を実行できます。CI/CD ベースの開発プロセスと CNKit を使用した開発プロセスは以下のように大きく異なります。
CI/CD デプロイパスは本番環境に適しており、標準化されたプロセスを通じてオンラインビジネスの安定性を保証します。しかし同時に長いプロセスであり、開発段階ではメリットが明確ではなく、むしろ開発効率を低下させます。このような場合、CNKit のデプロイプロセスがよい補完となります。Pod をコピーするだけで、ブラウザまたは IDE から継続的にアプリケーションパッケージを更新し、コードをデバッグできます。
デバッグ
デバッグ(ここでは特にリモートデバッグを指します)は、アプリケーション開発プロセスにおいて非常に重要な要素です。デバッグができなければ、アプリケーション開発の効率は大幅に低下します。クラウドネイティブアーキテクチャの下では、アプリケーションのデバッグはそれほどシンプルではありませんが、実現は可能です。この点において、CNKit はデバッグプロセスを簡素化するだけでなく、フロー制御機能も提供します。
・プロセスの簡素化:ページ上で「デバッグを有効化」をクリックするだけで、CNKit が Pod 内のアプリケーションを再起動してデバッグポートを開きます。その後、ローカルで IDE から CNKit にワンクリックで接続し、ブレークポイントデバッグを開始できます。
・フロー制御:EDAS のフルリンクフロー制御と連携することで、CNKit は特定のリクエストのみをレプリケーション Pod に流入させ、ブレークポイントデバッグロジックをトリガーできます。
この二つのポイントを通じて、非常に便利にコードデバッグを完了できます。下図はシンプルな例です。商品センターを開発していて、上流が取引センター、下流がインベントリセンターの場合、CNKit を使用したデバッグの全体リンクは以下のようになります。
開発バージョンとしてマークされた商品センターがレプリケーション Pod ノードです。クラウド環境では、フルリンクフロー制御を通じて特定のトラフィックが Pod に転送され、開発者はローカルで CNKit プロキシを通じて Pod のデバッグポートに接続します。
実際、複数人で並行開発するサービスでは、各開発者が独自の開発バージョンノードを持つことができ、異なるフロー制御ルールを設定するだけで、互いに干渉せずに並行開発を進められます。
診断
問題を四つのフェーズに分けて診断します。K8s スケジューリング、アプリケーション起動、アプリケーション実行中、アプリケーション停止です。フェーズが異なれば、採用する診断方法も異なります。
K8s スケジューリング中は、主に生成される関連イベントに注目します。スケジューリング異常が発生した場合、K8s は関連する理由を示します。下図は正常なスケジューリング時の K8s イベントです。
スケジューリング異常(リソース不足によるスケジューリング失敗など)が発生した場合、K8s は対応するイベントを生成します。
アプリケーション起動フェーズでは、K8s イベントに加えて Pod ログも確認できます。Pod ログはアプリケーションによって生成され、より詳細な情報が含まれています。下図は Pod の標準出力ログのサンプルです。
さらに、アプリケーション起動フェーズではネットワークアクセスが多くなります。多くの場合、アプリケーション起動の失敗はネットワークリクエストの異常によって引き起こされます。そのため、CNKit は起動前に tcpdump を自動実行してネットワークリクエストを記録することをサポートしています。下図はアプリケーション起動時に自動キャプチャされた tcpdump データです。CNKit はテキスト形式と pcap 形式の二つの形式をサポートしています。下図はテキスト形式の tcpdump データです。
最後に、アプリケーションの実行中および停止時にも K8s イベント、Pod ログ、tcpdump を引き続き使用でき、さらに CNKit にワンクリックで統合された Arthas ツールも使用できます。ページ上で Arthas をワンクリック実行すると、CNKit が Arthas のインストールと実行を自動的に完了します。全体のインタラクションは以下の通りです。
ここまで、CNKit のレプリケーション、デプロイ、デバッグ、診断について一つずつ共有してきました。しかし、これらの機能に加えて、CNKit には監査 Webshell などの隠れた機能もあります。これらの機能は読者の皆様がゆっくり探求していただくものとし、ここでは詳しく述べません。
EDAS Core
端末 - クラウド相互接続と CNKit に加えて、我々は EDAS Core も公開しました。前述の Developing on Kubernetes の分類基準に従うと、端末 - クラウド相互接続は Proxied モード、CNKit は Live モード、EDAS Core は Pure off-line モードに属します。
EDAS 自体は有料の商用プロダクトです。アプリケーションホスティングとマイクロサービス管理のためのクラウドネイティブ PaaS プラットフォームであり、アプリケーション開発、デプロイ、モニタリング、運用保守などのフルスタックソリューションを提供し、サービスの動作環境を構築します。一方、EDAS Core は無料の軽量 EDAS カーネルバージョンで、同様の機能をサポートしていますが、商用機能を取り除き、サービス SLA とリアルタイム運用保守サポートを提供せず、開発フェーズでの使用に適しています。
EDAS Core は最小で 4 コア 8 GB のマシンリソースのみを必要とします。ローカルの PC 上でオフライン EDAS プラットフォームを実行し、マイクロサービスの開発を行うことができます。EDAS Core の全体アーキテクチャは以下の通りです。
以下に簡単に説明します。
・EDAS Core:EDAS アプリケーションホスティング機能を含み、Nacos のサービス登録と検出、Minio の永続ストレージをサポートします。Kind、K3s、Docker Desktop、K8s クラスター上で実行可能で、必要なリソースはわずか 4c8g です。
・開発者ツール:Jenkins プラグインによる継続的デプロイ、Terraform によるインフラストラクチャ管理、ACT によるローカル開発をサポートし、EDAS Open API および SDK と互換性があります。
・インストールメディア:Helm、OSS、ADP 経由での EDAS Core インストールをサポートします。
・K8s クラスター:この K8s クラスターは EDAS Core が管理するクラスターであり、マイクロサービスアプリケーションが実行されます(サービス管理用 OneAgent が自動的に注入されます)。
・サービス連携:水平方向のサービス連携において、EDAS Core は EDAS 商用アプリケーションとのワンクリック変換をサポートし、ARMS や SkyWalking などのリンクトレース製品と統合され、ACR を使用したイメージホスティングをサポートします。
以下は EDAS Core の実行画面です(旧 EDAS ユーザーにはおなじみの画面でしょう)。
現在、EDAS Core は社内ベータテスト中です。この機能をご利用になりたい場合は、Alibaba Cloud で EDAS 製品に関するサポートチケットを起票してご相談ください。
エピローグ
クラウドネイティブアーキテクチャとマイクロサービス開発はどちらも非常に人気の高い技術分野ですが、「クラウドネイティブアーキテクチャ下でのマイクロサービス開発」という命題は、国内ベンダーからはほとんど語られていません。マイクロサービスホスティング分野のパイオニアとして、EDAS は非常に早い時期からクラウドネイティブアーキテクチャのサポートに取り組み始め、新しいアーキテクチャ下でのマイクロサービス開発の動向に注目し続けてきました。
初期の端末 - クラウド相互接続モデルから、最近リリースされた Cloud Native Development Kit(CNKit)と EDAS Core に至るまで、EDAS はクラウドネイティブ技術の進化に伴う新たな課題を開発者の視点から考え続け、これらの問題を解決するためのツールとプロダクトを継続的に提供しています。
Related Articles
-
A detailed explanation of Hadoop core architecture HDFS
Knowledge Base Team
-
What Does IOT Mean
Knowledge Base Team
-
6 Optional Technologies for Data Storage
Knowledge Base Team
-
What Is Blockchain Technology
Knowledge Base Team
Explore More Special Offers
-
Short Message Service(SMS) & Mail Service
50,000 email package starts as low as USD 1.99, 120 short messages start at only USD 1.00
