Telepresenceは7月に2つのメジャーリリースを8日間でリリースしました:14日に2.30、22日に2.31を。合わせて、2.xアーキテクチャ誕生以来最大の進化であり、振り返ってみると共通のテーマが浮かび上がります。長年Telepresenceが約束してきたすべての機能にはアスタリスクがついていました — 実際の組織で使おうとしたときに気づく制約です。任意のワークロードにアタッチできる(*ワークロードを変更する場合に限る)。トラフィックをノートPCにトンネリングできる(*Kubernetes APIサーバーを経由する全バイト)。チーム全員が利用可能(*traffic-managerに到達できる人なら誰でも)。開発環境は再現可能(*同僚やCIパイプラインが実行できないコマンドのwikiページとして)。

この2回のリリースでそれらのアスタリスクは撤廃されました。この記事では、それぞれの変更を — 単に何が変わったかだけでなく、なぜその形になったのかを — 振り返ります。ほとんどはホワイトボードから生まれたものではなく、長年の問題解決とコミュニティとの対話から生まれた設計です。

Telepresenceをご存じでない方へ:これはCNCFのツールで、ワークステーションをKubernetesクラスタのネットワークに接続し、作業中のサービスをローカル(IDEやデバッガーで、サブ秒の再ビルドで)実行しながら、クラスタにデプロイされたかのように振る舞わせ、周囲のサービスからライブトラフィックを受け取れるようにします。

Podに触れずにアタッチ

2.xアーキテクチャ誕生以来、ワークロードのトラフィックを受け取るにはTelepresenceがワークロードを変更する必要がありました。Podにtraffic-agentサイドカーをインジェクションし、Podテンプレートを書き換え、エージェント到着時に一度Podを再起動する必要がありました。

この設計は正当な理由に基づいていました。そしてその理由は今も有効です。サイドカーは非特権です。Pod自身のセキュリティコンテキスト内で動作し、他のコンテナと同じようにアドミッション・監査が可能で、管理者が開発者のRBACを厳しく制限できます。なぜならクラスタ側の機構が特権作業を行うからです。長寿命のチーム導入では健全なアーキテクチャであり、デフォルトのままです。

しかし周辺のエコシステムが変わりました。サイドカー設計当時、「Pod仕様の変更」は些細な出来事でした。今ではしばしばインシデントになります。GitOpsパイプラインはコミット済みマニフェストからの逸脱を検知し、一部のものは即座に元に戻すように設定されています。アドミッションポリシーはレビュー後のPod仕様の変更を拒否します。プラットフォームチームはプロダクト開発者が明示的に変更できないワークロードを所有しています。また、再起動が高コストなワークロードもあります — ウォームアップ時間が長いJVM、選出を行うステートフルサービス、実行中のバッチワーカーです。これらの環境ではサイドカーは単に不便ではなく、採用を阻害する要因でした。

2.30で新登場のnode-agentがその答えです。ワークロードにアタッチすると、traffic-managerはターゲットPodが稼働するノード上にnode-pinned Jobを作成します。そのエージェントは外部からPodのネットワーク名前空間に入り、そこからアタッチを処理します — サイドカーと同等のトラフィック再ルーティング、環境、ボリュームアクセスを提供しますが、Pod自体は変更されず、再起動もありません。その結果は直接的です:

  • アタッチ/デタッチが即時。 ロールアウト待ちや再起動スケジュールが不要。デタッチしてもワークロードに痕跡を残さない — ドリフト検知が検知するものは何もない、なぜならドリフト自体が存在しなかったからです。
  • 所有していないワークロードでも動作。 Pod仕様に触れないため、アドミッションコントローラーが拒否するものもなく、ポリシーが禁止する変更もありません。
  • すべてのレプリカをカバー。 traffic-managerはレプリカごとに1つのエージェントを作成し、Podの追加・削除に合わせて調整するため、スケールされたワークロードも正しくインターセプトできます。幸運な1レプリカだけをインターセプトするのではなく。
  • 複数開発者がエージェントを共有。 同一ワークロードにアタッチする2人は、同じnode-agentを再利用し、機構を積み重ねません。

トレードオフもメリットと同様に明確に述べるべきです:node-agentは特権Jobとして実行されます。外部から他Podのネットワーク名前空間に入る操作は本質的に特権操作だからです。これを回避する巧妙な方法はありません。未変更のPodにアタッチするツールはどこかでこのコストを支払います。選べるのはどこで特権を実行するか — 開発者が実行するものではなく、traffic-managerがオンデマンドで作成する短命のnode-pinned Jobです。agent-modesガイドでは、サイドカーとnode-agentの選択方法を説明しています。両方正しく、クラスタによって使い分けるからです。

nodeレベルのエージェント経由で未変更のワークロードにアタッチすることがmirrordに似ているように聞こえるなら、その通りです — mirrordはそのアプローチで構築されており、優れた方法です。2.30でTelepresenceは両方のスタイルを提供します。2つのツールはアーキテクチャが大きく異なります — Telepresenceはワークステーション全体をネットワークレベルで接続し、mirrordは単一プロセスをsyscallレベルでリンクします — そしてそれぞれがより適した場面を公平に比較した比較ページを公開しています。

traffic-managerが呼び出し元を認識

2.31はセキュリティリリースであり、遅ればせながらのものです。対処する不都合な真実:これまでtraffic-managerは呼び出し元を信頼していました。そのgRPCエンドポイントに到達できる人なら誰でも、セッションを作成し、他クライアントのアタッチメントに作用し、トラフィックをルーティングできました — 自分が誰であるかを証明することなく。2つのHigh重大度勧告GHSA-j8j4-rw65-56r6GHSA-6j3h-rp73-6rvfは、これが実際に可能にしたことを具体的に説明しています:クラスタ内の任意のPodがtraffic-agentを装い、サービスのトラフィックをインターセプトでき、アクティブなクライアントセッションはIDを知るだけで誰でも乗っ取れる。

ツールがどのようにしてこの状態になったのか?歴史的に:Telepresenceは、クラスタ自体が信頼されたものとして扱われる開発ツールとして成長しました。到達可能性が境界でした。その前提は数年前に通用しなくなりました — クラスタはマルチテナントで、ワークロードは半信頼であり、「クラスタ内のものは何でも他と通信できる」という性質こそ、ゼロトラストアーキテクチャが排除しようとしているものです。修正は、既存のインストールを一切壊さずに、IDを持たなかったプロトコルにIDを後付けする必要がありました。その制約がすべてを形作りました。

最初の設計判断:新しい認証情報システムを発明しない。クラスタにはすでに存在します。クライアントはkubeconfig認証情報が解決するbearerトークン(静的トークン、トークンファイル、またはexec認証情報プラグインの出力)を転送し、traffic-managerはKubernetesのTokenReviewで検証します。クライアントが提示するIDは、クラスタが割り当てるIDそのものです。新たにプロビジョニング・ローテーション・漏洩のリスクはありません。traffic-agentはprojectedでaudience-boundなServiceAccountトークンで認証し、であるかだけでなくどのPodであるかを証明します — agentのなりすましという穴を具体的に塞ぎます。

認証の上に、クラスタがすでに理解している概念に基づく2つの認可ルールがあります:

  • セッションは作成したIDに紐づく。 呼び出し元は他クライアントやエージェントのセッションに作用できなくなります — 他者のインターセプトの確認、他者のアタッチメントの解除、または自分が実行していないPodを代表した発言。
  • インターセプトの作成にはRBACが必要。 具体的には、呼び出し元のKubernetes IDがターゲット名前空間でpods/portforward権限を持つ必要があり、SubjectAccessReviewで確認されます。この権限は意図的に選択されました:kubectl port-forwardがすでに必要とするものであり、インターセプトは能力の観点でport-forwardです。新しいポリシー言語も、Telepresence固有のロール設計も不要。クラスタのRBACがすでにPodへのトラフィック転送を許可する人を定義しているなら、それはインターセプトの許可も定義していることになります。

2番目の設計判断はロールアウトについてであり、技術的観察と同様に社会学的観察を反映しています:既存のインストールを破壊するセキュリティアップグレードはインストールされない。 延期され、ピン留めされ、不満が溜まる — 適用されないセキュリティ修正は誰も守りません。したがって、強制はHelm値1つで3つの設定によりオプトイン方式です。permissive(デフォルト)はすべてのトークンを検証し、すべての認可判断をログに記録しますが、何も拒否しません:アップグレードはユーザーにとって何も変わらず、ログは強制が行ったであろうことを正確に示します。enforcingは拒否を有効にします。(disabledは旧動作を本当に望むインストール向けに存在します。)意図した道筋は設計上地味です:アップグレードし、クライアントとエージェントの群れが追いつくのを待ち、permissiveログが静かになるまで観察し、スイッチを切り替える。古いクライアントはpermissive managerに対して動作し続け、2.31クライアントは古いmanagerに対して動作し続けます — 群れが最新になる必要があるのは最後のステップだけです。

各kubeconfig認証情報タイプが提供するものの詳細を含む完全な情報は、新しいauthentication referenceに記載されています。

QUIC:APIサーバーをデータパスから除外

ワークステーションとクラスタ間のトンネルトラフィックは、歴史的に単一のport-forwarded gRPC接続を通っていました。この設計の大きな利点は、どこでも動作することです。Kubernetes APIサーバーに到達できればport-forwardでき、port-forwardできればTelepresenceは動作します — LoadBalancerも、開いたポートも、ファイアウォールとの交渉も不要。

しかしその代償を見てみましょう。port-forwardはAPIサーバー接続に乗るため、トンネルされた開発トラフィックの全バイト — サービスが受信するすべてのリクエスト、上流へのすべてのコール — がクラスタのコントロールプレーンを通過します。APIサーバーはクラスタが持つ最も重要で最も競合するコンポーネントであり、データプレーンになることを意図されていませんでした。単一の開発者にとっては負荷はノイズに過ぎませんが、組織全体でTelepresenceを実行するプラットフォームチームにとっては測定可能であり、まさに間違ったコンポーネントに費やされています。

単一接続は開発者にも害を及ぼします。1つのgRPC接続は1つのTCPストリームであり、すべてのフローを1つのTCPストリームに多重化すると、規模に応じてTCPの最悪の性質 — head-of-line blocking — を得ることになります。パケットが失われると、TCPは再送が到着するまでその後ろのすべてを保留します — パイプを共有しただけに過ぎない無関係のフローに属するバイトも含めて。クリーンなネットワークでは気づきません。損失のあるネットワーク — ホテルのWi-Fi、調子が悪いVPNコンセントレータ、混雑したラストマイル — では、すべてのフローが定期的に他フローの不運に代償を払い、トンネルは原因を特定しにくい不思議な遅延を感じます。

2.31のオプトインQUICトランスポートは、両方を同時に解決します。クライアントはtraffic-managerが公開するQUICエンドポイントに直接接続するため、トンネルトラフィックはAPIサーバーを完全にバイパスします — コントロールプレーンはコントロールプレーンの仕事に戻ります。そしてQUICは各ストリームに独立した損失回復を提供するため、失われたパケットはその属するフローのみを停止させます。ベンチマークは両方を裏付けています:1–3%の入力パケット損失時、小さなリクエストのテールレイテンシは共有gRPCトンネル経由でQUIC経由より1.7–1.8倍高くなり — 小さなリクエストのテールレイテンシこそがインタラクティブな開発の体感そのものです — 利得は損失のあるネットワークに限定されません:複数のベンチマーク形状で、直接QUICパスは数倍高速でした。

なぜオプトインか?gRPCトンネルを普遍的にする性質は、QUICが持てないものだからです。QUICエンドポイントはUDPサービスとして到達可能である必要があります — LoadBalancerまたはNodePort — これは管理者の判断であり、すべてのクラスタが提供できるわけではありません。したがってtraffic-managerはquicTunnel.enabledが設定されたときにQUICを公開し、クライアントは到達可能な場合に新しいトンネル接続を自動的にアップグレードし、gRPCはデフォルトかつ常時利用可能なフォールバックのままです。telepresence statusは実際に得られたトランスポートを教えてくれます — 推測の必要はありません。

開発環境がファイルに

Kubernetesが勝利したのは単一のアイデアの力です:望む状態を記述し、コントローラーに実現させる。しかしクラスタネイティブ開発のワークステーション側は、命令型に留まり続けています — このクラスタに接続し、あのサービスをこれらの9つのフラグでインターセプトし、ローカルサーバーを起動し、明日も繰り返す。そして新しいチームメンバーのオンボーディングは、2四半期前に正確だったwikiページを指し示すこと。

2.31で新登場のtelepresence apply -f dev.yamlは、宣言型モデルをワークステーションにもたらします。マニフェストはオプションの接続と一連のアタッチメント — intercept、replace、ingest、またはwiretap — を記述し、それぞれにフラグと、オプションでアタッチメント中に実行するローカルコマンド(開発サーバーなど)を指定できます。アタッチメントが準備できたときに起動し、破棄されたときに停止します。Applyはべき等です:すでにマニフェストに一致するものはそのままにし、逸脱したものは再作成し、--dry-runは何か触ることなく計画を表示します。telepresence delete -fは状態全体を破棄します。

実務上の変化は機能リストが示唆する以上に大きいです。チームの標準的な開発セットアップは部族知からリポジトリ内のファイルになり — バージョン管理され、レビューされ、新人にもベテランにも同一になります。「このサービスでどうやってセットアップするの?」はtelepresence apply -f dev.yamlになり、答えは全員のマシンで同じです。

次なるもの:クラスタの知識をツールに移動

上記の機能はTelepresenceをより強力にします。次のイニシアチブは異なる問題を攻撃します:最初の1時間。

クラスタに実際に適合するtraffic-managerのインストールには、そのクラスタに関する質問に答える必要があります。QUICエンドポイントを公開でき、LoadBalancerにするべきかNodePortにするべきか?node-agentはクラスタのアドミッションポリシーを通過するか?mutating webhookを作成でき、APIサーバーはそれに到達できるか?インストールはクラスタ全体か、名前空間にスコープするか、どの名前空間か?すでに何かがインストールされており、健康か?今日、それらの答えはリファレンスドキュメントと試行錯誤の中にあり、Telepresenceを採用する価値があるかどうかを評価する人にとって実質的なコストです — これらの質問に最も精通している人々は、ドキュメントを最も必要としない人々です。

次回リリースのいずれかで予定されているtelepresence setupコマンドは、その知識をツールに移動します。クラスタを読み取り専用で調査します — インストール権限、QUICの実行可能性、node-agentのアドミッション(実際のポリシーエンジンを動作させるサーバーサイドのdry-runカナリア付き)、webhookの到達可能性、名前空間の規模、既存インストールとその健全性、さらにはワークステーションのローカルネットワークとのルーティング競合まで。次に、調査で残された質問のみを尋ね、完全に設定されたHelmインストールを検証・作成・適用します。注目すべき設計判断:ワークステーションを一切変更しないため、繰り返し実行しても安全で、読み取り専用で実行しても安全。書き出すvaluesファイルは通常のHelm valuesドキュメントなので、GitOpsの外ではなく中に収まる。既存インストールのdoctorとしても機能する。クラスタ権限がない場合、管理者への項目別ハンドオフを生成し、行き止まりにならない。

ありがとう、OpenAI

これらすべては資金提供されたメンテナの時間なしには起こりません。そしてそれは具体的に述べる価値があります。node-agentやゼロから作る認証レイヤのような機能は、数ヶ月規模の弧です:設計、実装、セキュリティレビュー、ドキュメント、そしてハードニングの長い尾。この規模の作業は、夕方や週末には収まりません — 持続可能ではなく、セキュリティレイヤが要求する品質でもありません。

OpenAIはTelepresenceプロジェクトをスポンサーしています。これらの特定の機能ではありません — 機能の方向性は付いていません — プロジェクト自体への持続的な支援です。それこそが、メンテナがこの規模の作業に取り組む余裕を与える種類のスポンサーシップであり、この2回のリリースはその直接の結果です。ありがとうございます。

Telepresence OSSはApache 2.0ライセンスの下のCNCFプロジェクトです。この記事で説明したものはすべて無償です — 席も、有料ティアも、機能ゲートもありません。組織が価値を得ているなら、恩返しの最善の方法はコントリビューションスポンサーシップで、メンテナンスと開発に直接資金提供します。

はじめに

クイックスタートは約10分で完了します。変更の完全なリストはリリースノートに記載されており、質問や実践例はGitHub DiscussionsまたはCNCF Slackの#telepresence-ossでお待ちしています。

この記事は元々telepresence.ioに掲載されました。