DUICUO

Alibaba のオープンソースで強力な Kubernetes ローカル デバッグ ツール、Kt-Connect のユーザー ガイド。

背景

  • 注:開発中のローカルデバッグの変更点について説明しているため、背景説明は少し長くなります。面倒だと感じる場合は、読み飛ばしても問題ありません。

2019

当時、私の会社には Java アプリケーションが 2 つしかなく、どちらも Tomcat Servlet コンテナで実行されていました。

当時はローカルデバッグをどのように行っていましたか?開発者はMySQLとTomcatを自分のコンピュータにインストールし、そこでテストを実行していました。バックエンド開発者が互いに干渉することなく、好きなように変更できるという利点がありました。アプリ開発者はバックエンドのラップトップに直接接続してデバッグしていました。デプロイメントには、開発者が手動でJARファイルをコンパイルし、クラウドサーバーにアップロードする必要がありました。基本的には間に合わせの作業で、作業は完了していましたが、それだけでした。

2020

2020年までに、当社はCentOSサーバーを購入し、MySQLとTomcatをインストールし、キャッシュにはRedis、メッセージキューにはRabbitMQを使用し、独立したテスト環境を構築しました。また、アプリケーションのパッケージ化とデプロイを自動化するためにJenkinsを導入し、これは大きな進歩でした。少なくとも、アプリケーションを自分でパッケージ化する必要がなくなったのです。

では、現時点でローカルでデバッグするにはどうすればよいでしょうか?少なくとも、MySQLを自分のコンピュータにインストールする必要はなくなりました。その後、フレームワークがSpringMVCとStruts2からSpring Bootに変更され、外部のTomcatも削除できるようになりました。バックエンド開発者は、Spring Bootをローカルで実行する際に、サーバーのMySQLに直接接続してデバッグできます。また、アプリはバックエンド開発者のラップトップに接続する必要がなくなり、比較的安定したデバッグ環境が提供されます。ただし、異なるバックエンド間でデータベース構造を更新する場合、他のバックエンドへの影響を避けるために互換性を維持する必要があります。

2021

事業の拡大に伴い、バックエンドフレームワークはSpring BootからSpring Cloudスイートへと進化し、アプリケーション実行環境はLinux上で直接実行されていたものからDockerイメージを介したデプロイへと移行しました。また、様々なミドルウェアもDockerイメージを採用しました。製品ラインの増加に伴い、単一の開発ブランチではニーズを満たせなくなったため、新たなバックエンドコードブランチが作成され、開発・テスト環境も追加されました。

この段階では、アプリ側のローカルデバッグはそれほど変わりません。唯一の違いは、異なるバックエンド環境に接続するために異なるドメインを使用する点です。しかし、バックエンド開発者にとっては話は別です。ローカルデバッグを行うたびに、EurekaインスタンスとConfig Serverをコンピューター上で実行する必要があります。デバッグ対象のマイクロサービスに多くの依存関係がある場合は、大量のメモリが不可欠です。

2022

事業量は拡大を続け、製品チームのメンバー数も増え、需要は山のように積み重なっていきました。2つのブランチではもはや十分ではなく、3つ目のブランチが作成されましたが、それでも十分ではありませんでした。新しいブランチのランタイム環境が追加されるたびに、バックエンド開発チームも、多数の環境とサードパーティプラットフォームのコールバックを構成する必要があり、苦労しました。動的なスケーリングを可能にするために、Spring Cloudエコシステムは進化を続け、ZuulゲートウェイとEurekaを放棄してSpring Cloud Kubernetesを採用し、ランタイム環境をKubernetesに完全に統合しました。この間、同社は開発とテスト用に別のサーバーを購入し、メモリ、CPU、ディスク容量がいっぱいになりました。

Kubernetesの登場により、バックエンド開発者はローカルコンピュータからLinuxサーバー上の様々なミドルウェアに自由に接続できなくなりました。新しいブランチ環境の各PODには新しいIPアドレスが割り当てられ、以前のようにバックエンド接続用に特定のミドルウェアポートを開くことはできなくなりました。これほど多くの環境を設定しなければならないとしたら、運用エンジニアは一日中何もすることがなくなってしまうでしょう。

これが、本日ご紹介するkt-connectツールの登場です。このツールを使うと、バックエンド開発者はプロキシ経由でKubernetes内の名前空間にある様々なブランチ環境(すべてのサービス)にアクセスできます。デバッグが必要なサービスだけを起動すれば良いため、CPUとメモリの使用量を大幅に削減できます。

選択

ローカルデバッグのために K8S 環境にアクセスするためのプロキシを選択するためのツールがオンラインでいくつか利用可能です。

1. ポート転送

前述のように、Ingress、NodePort、LoadBalancerなどのツールを使用してトラフィックを特定のポートに転送すると、運用・保守担当者の作業負荷が増加し、ブランチ環境の自動作成と再利用が容易になりません。これは、少数のポートを公開する必要があるシナリオにのみ適しています。

2. VPN

Kubernetesの各名前空間にVPNサービスを実行するPODを設置することで、バックエンド開発用ラップトップはVPNクライアントを介して指定された名前空間に接続し、クラスター内の様々なサービスに正常にアクセスして解決できるため、基本的に日常的な要件を満たすことができます。ただし、各名前空間でそれぞれ独自のVPNサービスが実行されていることが欠点です。

3. テレプレゼンス

検索中にこのプロキシツールを発見しました。中国語と英語の技術記事のほぼ90%で、このツールの使用が推奨されています。これは非常に強力で、VPNのプロキシ機能(名前空間内のすべてのサービスへのアクセスを許可する機能)だけでなく、特定のサービスからローカルマシンへのトラフィックをブロックするルールを指定する機能も備えています。つまり、ローカルマシンは外部サービスを提供する通常のPOD(ポータブルプロバイダー)としても機能するということです。基本的な設計原理は次のとおりです。

研究開発に使用するローカルコンピュータで以下のコマンドを実行します。

  • テレプレゼンス helm インストール --kubeconfig .\kubeconfig テレプレゼンス接続 ---kubeconfig .\kubeconfig

Kubernetesクラスターに「ambassador」という名前空間が自動的に作成され、トラフィック管理用のトラフィックマネージャーPodがデプロイされます。ローカル開発用ラップトップでは、2つのデーモンサービスが起動します。1つは「ルートデーモン」と呼ばれ、双方向プロキシチャネルを確立し、ローカルコンピューターとKubernetesクラスター間のトラフィックを管理するために使用されます。もう1つは「ユーザーデーモン」と呼ばれ、Traffic Managerとの通信、ブロッキングルールの設定、ログイン後のAmbassador Cloudとの通信を担当します。

インターセプトルールを設定すると、インターセプトされたポッドにトラフィックエージェントがインストールされます。公式ドキュメントによると、これはKubernetesクラスターのサイドカーモードに似ており、注入されたポッドへのトラフィックをインターセプトし、すべてのトラフィックをトラフィックマネージャー経由で再ルーティングします。

  • Traffic Agent は、インターセプトを容易にするサイドカーコンテナです。インターセプトが最初に開始されると、Traffic Agent コンテナがワークロードのポッドに挿入されます。

強力な機能を備えているものの、現在のバージョン2.5では、ブロッキング機能やURLプレビュー機能を使用するには、商用クラウドプラットフォームであるAmbassador Cloudへの登録とログインが必要です(注:オンラインの技術記事ではなぜこのことに触れられていないのか分かりませんが、テスト中はクラウドプラットフォームへのログインが必要でした)。さらに、ブロッキングルールの設定はクラウドプラットフォームのウェブページから行う必要があります。ネットワーク要件に加え、セキュリティとデータ漏洩の潜在的なリスクも許容できないため、このツールの使用を断念せざるを得ませんでした。

もう一つの欠点として、旧バージョンの使用後に自動作成された名前空間やPod、インターセプトエージェント(Telepresenceのアンインストール)をクリーンアップする機能がなくなったことが挙げられます。バージョン2.5では、この機能はコマンドパラメータから完全に削除されました。つまり、使用後に環境をクリーンアップした状態に保ちたい場合、運用・保守担当者にクリーンアップを依頼する必要があり、非常に面倒で、強迫性障害の患者にとっては頭が痛くなるほどで​​す。

4. ktコネクト

幸いなことに、オープンソースコミュニティはTelepresenceに似たツール、kt-connect(バージョンv0.3.6)を発見しました(ちなみに、Kubernetesのバージョンは1.24です)。インターネット接続やアカウントログインは不要で、コマンド実行後に自動的にクリーンアップされます。これはAlibabaのツールで、KPI主導のオープンソースプロジェクトかどうかは分かりませんが、少なくとも今のところ、このツールには非常に満足しています。

原理

Telepresenceに似ていますが、Telepresenceとは異なり、kt-connectは指定された接続の名前空間内に単一の自己使用Podを作成し、kt-connect-shadowイメージをデプロイします。Telepresenceと比較して、kt-connectはより洗練され拡張されたモードを提供し、4つの主要なモードに分かれています。

1. 接続モード

 ktctl.exe 接続--kubeconfig .\kubeconfig --namespace feature-N --debug

このモードでは、kt-connect は VPN のように動作し、ローカル コンピューターが接続された名前空間内のすべてのサービスにアクセスできるようになりますが、クラスター内の他のサービスには統合されず、他のサービスからのトラフィックはローカル コンピューターに転送されません。

  • 注1:Telepresenceと同様に、すべてのkt-connectコマンドには--kubeconfigを含める必要があります。これは、KubernetesクラスターのAPIサーバーに正しく接続するための十分な権限と機能を確保するためです。多くの記事ではこの点についてほとんど触れられていません。Kubernetesクラスターの権限が制限されている場合、または開発チームと同じネットワーク上にない場合は、運用チームから提供された十分な権限を持つkubeconfigファイルを使用して接続する必要があります。
  • 注 2: ポート転送の設定に失敗しました local:28344 -> pod kt-connect-shadow-gseak:53 error="接続のアップグレードエラー: リクエストの送信エラー: Post "https://10.0.8.101:8443/api/v1/namespaces/feature-N/pods/kt-connect-shadow-gseak/portforward": dial tcp 10.0.8.101:8443: connectex: 到達不可能なホストへのソケット操作が試行されました。",

上記のエラーが発生した場合、kt-connect のルーティングバグの可能性があります。ローカルコンピュータのルーティングと API サーバーへの新規追加ルートが競合している可能性があります。パラメータ --excludeIps 10.0.8.101/32 を追加すると問題が解決するはずです。ネットワークセグメントの競合が多い場合は、ネットワークセグメントの範囲を拡張してください(例: --excludeIps 10.0.8.0/24)。詳細は issue-302 をご覧ください。

 ktctl.exe 接続--kubeconfig .\kubeconfig --namespace feature-N --excludeIps 10 .0.8.101/32 --debug

2. 交換モード

 ktctl.exe exchange serviceA --kubeconfig .\kubeconfig --namespace feature-N --expose 12001 --debug

このモードは、指定されたサービスへのすべてのトラフィックを傍受し、開発用コンピュータのポートに転送するTelepresenceのインターセプトモードに似ています。このモードを使用すると、環境内のアクセス要求を直接デバッグできます。

具体的な原則は、サービス内の Pod を serviceA-kt-exchange という名前の Pod に置き換えることです。

  • 注1:Exchangeモードではトラフィックの方向は一方向であり、ローカルコンピュータから開始されたリクエストはプロキシされません。K8Sクラスターとローカルコンピュータが同じネットワークセグメント上にない場合は、別のコマンドラインを開いてConnectモードを実行し、ローカルサービスがK8Sクラスター内の他のサービスに正常に接続できることを確認する必要があります。問題番号216を参照してください。
  • 注2:Exchangeモードは、サービスをインターセプトすることでトラフィックを転送します。クラスターリクエストがPodクラスに直接解決されるなど、サービスを経由しない場合、インターセプトに失敗する可能性があります(Meshモードでも同様です)。そのため、問題が発生した場合は、Kubernetesクラスター内のルーティング状況を運用チームに確認することを忘れないでください。

3. メッシュモード

 kctl.exe メッシュ サービスA --kubeconfig .\kubeconfig --namespace feature-N --expose 12001 --debug

コマンドを実行すると、出力ログに次のようなテキストが表示されます。

午後2時30分INF ヘッダー「VERSION: xxxxx」サービスにアクセスできるようになりました

このモードでは、ローカルコンピューター上のサービスとKubernetesクラスター内の同じサービスが同時にリクエストに応答します。ただし、指定されたHTTPリクエストヘッダーVERSION: xxxxを持つリクエストのみがローカルコンピューターに転送されます。Exchangeモードと比較して、これにより他のサービスは正常に動作し続けることができ、開発者はローカルデバッグを実行できます。VERSIONヘッダーの値は毎回動的に生成されます。この値を固定するには、--versionMarkパラメータを使用して指定します。例えば、値をtest-versionに固定するには、コマンドは以下のようになります。

 kctl.exe メッシュ サービスA --kubeconfig .\kubeconfig --namespace feature-N --expose 12001 --debug --versionMarkテスト バージョン

具体的な手順は、serviceA の Pod を、リクエストヘッダーに基づいてトラフィックのプロキシと転送を行う serviceA-kt-router のルートイメージに置き換えることです。さらに、通常オンラインで実行されている serviceA である serviceA-kt-stuntman サービスが生成されます。また、ローカルコンピュータへのトラフィックのプロキシを行う serviceA-kt-mesh-xxxxx サービスも生成されます。

4. プレビューモード

 kctl.exe プレビュー サービスB --kubeconfig .\kubeconfig --namespace feature-N --expose 12001


Kubernetes クラスターで実行中のサービスを必要とする Exchange モードや Mesh モードとは異なり、プレビュー モードでは、ローカル コンピューターで実行されているプログラムをまったく新しいサービスとして Kubernetes クラスターにデプロイできるため、新しいサービスの開発、デバッグ、プレビューに非常に便利です。