Telepresenceをやめてmirrordに乗り換えた話
エスマットでは、コンテナ基盤としてAWS EKSを採用しています。開発者はマイクロサービスの開発・デバッグを行う際に開発用の共通クラスターにTelepresenceを使い開発中のサービスのみを入れ替えて動作検証をおこなっていました。
しかし、Telepresence v2.21以降、OSS版ではpersonal interceptorが削除されたため複数開発者が共通クラスターにTelepresenceで同時に接続することができなくなりました。そのため、代替方法を探す必要が発生しました。いくつかの候補を検討した結果、最終的にmirrordを採用することにしました。
この記事では、Telepresenceからmirrordに移行した経緯を解説します。また、mirrordを実際にどのような設定で運用しているかを紹介します。
Telepresenceとmirrordの比較
私たちのチームが直面していた課題は明確でした。Telepresence OSS版では複数開発者が同一クラスターで同時に開発できないという制限です。この課題を解決するには、以下の2つの選択肢がありました。
- Telepresence有償版(Blackbird)への移行
- mirrord有償版の採用
どちらも有償版が必要という条件は同じでしたが、最終的にmirrordを選択しました。
mirrordを選んだ3つの理由
-
VPNを使わないことによる安定性と軽快さ
- Telepresenceが採用するVPNベースの接続は、ネットワーク設定を書き換えるため他のVPNソフトと競合して動作が不安定になりやすかった
- mirrordのシステムコール横取り方式はオーバーヘッドが少なく効率的
- 実際の開発作業で、Telepresenceよりも安定していて、レスポンスも速いと体感
-
目的に特化したシンプルさ
- Blackbirdはマイクロサービスの統合開発環境として設計されており、多機能
- 私たちが必要としていた「開発中のサービスの部分的な置き換え」以外の機能も多く、調査時にノイズが多い
- mirrordは必要な機能に特化しており、シンプルで分かりやすい
-
実際に動作した
- Blackbirdは正式版がリリースされた直後で私たちの環境ではランタイムエラーが発生し、そもそも利用できない状態だった(2025年4月時点)
- mirrordは実際にfrontend/BFFサービスで動作検証が完了できた
どうやって動くのか?
mirrordは、VPNを使わずにシステムコールを横取りする仕組みで動作します。ローカルプロセスがファイルを読もうとしたり、ネットワーク通信をしようとすると、その呼び出しをmirrordが捕まえて、Kubernetes上のPodに転送します。
この仕組みにより、VPNもroot権限も不要で、まるでPod内で動いているかのようにローカルプロセスが振る舞います。
設定手順
mirrordのセットアップは、以下の2ステップになります。
- ローカルPCへのCLIのインストール
- Kubernetes クラスターへmirrod operatorをインストール
CLIのインストール
Mac OSを使っている場合、brewコマンドでインストールできます。
brew install metalbear-co/mirrord/mirrord
mirrord operatorのインストール
公式のHelmからインストールする方法が簡単です。
helm repo add metalbear https://metalbear-co.github.io/charts
curl https://raw.githubusercontent.com/metalbear-co/charts/main/mirrord-operator/values.yaml --output values.yaml
helm install -f values.yaml mirrord-operator metalbear/mirrord-operator
動作確認
CLIとoperatorのインストールが完了したら、targetlessモードを使ってクラスタ内部のネットワークに接続できることを確認します。以下の例では、クラスター内部のAPIにcurlコマンドでアクセスを試みています。
$ mirrord exec curl -- -v http://my-service.default.svc.cluster.local:5000/healthcheck
New mirrord version available: 3.153.0. To update, run: `"curl -fsSL https://raw.githubusercontent.com/metalbear-co/mirrord/main/scripts/install.sh | bash"`.
To disable version checks, set env variable MIRRORD_CHECK_VERSION to 'false'.
* Running command: curl -v http://my-service.default.svc.cluster.local:5000/healthcheck
* mirrord will run without a target, no configuration file was loaded
* mirrord will run without the mirrord Operator
* env: all remote environment variables will be fetched
* fs: file operations will default to read from the remote
* incoming: incoming traffic will be be mirrored
* outgoing: forwarding is enabled on TCP and UDP
* dns: DNS will be resolved remotely
* internal proxy: logs will be written to /var/folders/v7/c267687s10sg2b95vj455kjc0000gp/T/mirrord-intproxy-1754140810-QSjAubE.log
⠚ mirrord exec
✓ update to 3.153.0 available
✓ ready to launch process
✓ layer extracted
✓ operator not found
✓ agent pod created
✓ pod is ready
✓ arm64 layer library extracted
✓ config summary * Host my-service.default.svc.cluster.local:5000 was resolved.
* IPv6: (none)
* IPv4: 10.100.55.190
* Trying 10.100.55.190:5000...
* Connected to my-service.default.svc.cluster.local (10.100.55.190) port 5000
> GET /healthcheck HTTP/1.1
> Host: my-service.default.svc.cluster.local:5000
> User-Agent: curl/8.7.1
> Accept: */*
>
* Request completely sent off
< HTTP/1.1 200 OK
< Content-Type: application/json; charset=utf-8
< Date: Sat, 02 Aug 2025 13:20:26 GMT
< Content-Length: 2
<
* Connection #0 to host my-service.default.svc.cluster.local left intact
{}
このコマンドの実行で以下の確認ができます。
- クラスタ内部のDNS解決が機能している(
.cluster.local
ドメインが解決される) - Service経由でPodにアクセスできている
- ローカルのcurlコマンドがクラスタ内部のネットワークで実行されている
例:複数開発者がフロントエンド開発をする場合
複数開発者がフロントエンド開発をする場合を例にmirrordの設定を説明します。この構成では、各開発者がBFFをmirrord経由で実行します。
BFFを起動するコマンドは以下の通りです。
mirrord exec -t deployment/bff -f ./mirrord.config.json npm run dev
この実行例では、クラスター上の deployment/bff
が npm run dev
で起動したプロセスによって置き換えられます。詳細な設定は mirrord.config.json
に記載されています。
mirrordの詳細設定
mirrord.config.json
の設定内容は以下の通りです。
{
"feature": {
"env": true,
"network": {
"dns": true,
"outgoing": {
"tcp": true,
"udp": true
},
"incoming": {
"mode": "steal",
"http_filter": {
"header_filter": "^X-Dev-User: {{ get_env(name=\"USER\", default=\"unknown\") }}$"
}
}
}
}
}
各設定の意味:
-
env: true
: Pod の環境変数をローカルで使用 -
dns: true
: クラスタ内の DNS 解決を有効化 -
mode: "steal"
: トラフィックを完全にローカルにリダイレクト -
header_filter
: 開発者ごとにトラフィックを分離
なぜheader_filterが必要なのか?
mode: "steal"
を設定すると、BFFへのトラフィックがすべてローカルPCに転送されてしまいます。これでは複数の開発者が同時に作業できません。
そこでheader_filter
を使います。この設定により、特定のHTTPヘッダー(X-Dev-User)を持つリクエストだけが自分のローカルPCに転送されるようになります。
例:
- 開発者Aliceのリクエスト(
X-Dev-User: alice
)→ AliceのローカルPCへ - 開発者Bobのリクエスト(
X-Dev-User: bob
)→ BobのローカルPCへ - ヘッダーなしのリクエスト → クラスター内のBFFが処理
フロントエンドでの設定
開発者を識別するヘッダを自動的に付与するようにします。
// 開発環境でのみ有効
if (process.env.NODE_ENV === 'development') {
axios.defaults.headers.common['X-Dev-User'] = process.env.USER;
}
おわりに
Telepresenceからmirrordへの移行は、当初は「仕方なく」始めた作業でした。しかし、実際に使ってみると、mirrordの方が優れている点が多いことに気づきました。
移行後の成果
開発効率の向上
- VPNの接続待ちやエラーに悩まされることがなくなった
- レスポンスが速くなり、開発のリズムが良くなった
チーム開発の改善
- 複数開発者が同時に作業しても競合しない
- HTTPヘッダーによる明確なトラフィック分離
運用中の課題と今後の展望
現在、frontend/BFFだけでなくバックエンドサービスでもmirrordを活用しています。ただし、運用していく中で課題も見えてきました。
発生している課題
- mirrord operatorがスタックして動作しなくなることがある
- 現在は
kubectl rollout restart
で対応しているが、根本的な解決には至っていない - 今後のバージョンアップで安定性が向上することを期待
それでも、これらの課題を差し引いても、mirrordがもたらす開発効率の向上は大きく、現時点では最適な選択だと確信しています。Blackbirdが安定版になった際には再評価も検討する予定です。
もしTelepresence OSS版の制限で困っている方がいれば、ぜひmirrordを試してみてください。きっと期待以上の開発体験が得られるはずです。
参考リンク

IoT重量計スマートマットを活用した在庫管理・発注自動化DXソリューション「SmartMat Cloud」を運営しています。一緒に働く仲間を募集しています。 s-mat.co.jp/recruit
Discussion