Submariner Lighthouseにおける組み込み型CoreDNS設計の深掘り

![Submariner Lighthouse Image Apr 15 2025.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/7565/c986ff41-78fe-4601-b952-a27e740bfffe.png)


## 背景：マルチクラスタ環境のDNS課題とLighthouseの登場

Kubernetesでは各クラスタ内部のサービス名前解決はCoreDNS（またはkube-dns）によって行われます。しかし、クラスタをまたいだサービスディスカバリ（マルチクラスタサービス）は標準ではサポートされておらず、クラスタ間でサービス名による通信を実現するには新たな仕組みが必要でした ([Multicluster Service Discovery in OpenShift (Part 1)](https://www.redhat.com/en/blog/multicluster-service-discovery-in-openshift#:~:text=The%20core%20Submariner%20component%20connects,of%20services%20via%20their%20name))。そこで登場したのがSubmarinerプロジェクトの**Lighthouse**です。Lighthouseはマルチクラスタ環境におけるサービスディスカバリを提供し、複数クラスタを接続するSubmarinerと連携して動作します ([Multicluster Service Discovery in OpenShift (Part 1)](https://www.redhat.com/en/blog/multicluster-service-discovery-in-openshift#:~:text=There%20are%20several%20bespoke%20implementations,that%20are%20connected%20by%20Submariner)) ([Service Discovery :: Submariner k8s project documentation website](https://submariner.io/getting-started/architecture/service-discovery/#:~:text=The%20Lighthouse%20project%20provides%20DNS,Cluster%20Service%20APIs))。特に、Kubernetesコミュニティで標準化が進められている**Multi-Cluster Services (MCS) API**を実装し、`<サービス名>.<ネームスペース>.svc.clusterset.local`というドメイン名で他クラスタのサービスを解決できるように設計されています ([Service Discovery :: Submariner k8s project documentation website](https://submariner.io/getting-started/architecture/service-discovery/#:~:text=Lighthouse%20DNS%20Server))。

このサービスディスカバリを実現する上で鍵となるのが**Lighthouse DNSサーバー**です。Lighthouseは各クラスタに独自のDNSサーバーをデプロイし、このDNSサーバーがマルチクラスタ用ドメイン（デフォルトでは`clusterset.local`）に対する名前解決を担当します ([Service Discovery :: Submariner k8s project documentation website](https://submariner.io/getting-started/architecture/service-discovery/#:~:text=The%20Lighthouse%20DNS%20server%20runs,record%20and%20an%20SRV%20record))。クラスタ内の既存CoreDNSは、`clusterset.local`向けのクエリをすべてLighthouseのDNSサーバーにフォワード（転送）するよう設定されます ([Service Discovery :: Submariner k8s project documentation website](https://submariner.io/getting-started/architecture/service-discovery/#:~:text=The%20Lighthouse%20DNS%20server%20runs,record%20and%20an%20SRV%20record))。これにより、クライアントPodが他クラスタのサービス名（例: `myservice.myns.svc.clusterset.local`）を引いたとき、まず自クラスタのCoreDNSがそのドメインを認識してLighthouse DNSに問い合わせ、そのLighthouse DNSがグローバルなサービス情報に基づいて回答を返す、という流れが実現されます。

 ([Service Discovery :: Submariner k8s project documentation website](https://submariner.io/getting-started/architecture/service-discovery/))このアーキテクチャにより、従来のクラスタ内DNSでは不可能だったクロスクラスタのサービス名前解決がシームレスに行えるようになりました ([Service Discovery :: Submariner k8s project documentation website](https://submariner.io/getting-started/architecture/service-discovery/#:~:text=The%20workflow%20is%20as%20follows%3A))。上のシーケンス図はその流れを示しています。フロントエンドPodからの`clusterset.local`ドメインに対するDNSクエリは、まずクラスタ内のCoreDNSに届きます。CoreDNSは当該ドメインを権威ゾーンとして持っていないため、設定されたとおりLighthouseのDNSサーバーへフォワードします。Lighthouse DNSサーバーは事前に同期されたServiceImport情報を用いて名前解決を試み、該当サービスのクラスタIP（またはエンドポイントのIPアドレス）を見つければAレコードとして返答します ([Service Discovery :: Submariner k8s project documentation website](https://submariner.io/getting-started/architecture/service-discovery/#:~:text=%60clusterset.local%60.%20,NXDomain%20error%20will%20be%20returned))（見つからなければNXDOMAINを返します）。クエリ元のCoreDNSはその返答を受け取り、元のPodに回答する仕組みです。

## 一般的なCoreDNSプラグイン方式との違い

LighthouseによるDNS解決のアプローチは、単にCoreDNSのプラグインとして機能を追加する方法とは一線を画しています。通常、CoreDNSに新機能（例えばマルチクラスタの名前解決）を追加する場合は、CoreDNSのプラグインを実装し、クラスタ内のCoreDNSにそのプラグインを組み込んで動作させる方法が考えられます ([ lighthouse ](https://coredns.io/explugins/lighthouse/#:~:text=Lighthouse%20plugin%20allows%20Cross%20Cluster,Kubernetes%20clusters%20connected%20by%20Submariner))。実際、LighthouseにもCoreDNSプラグインとしてのコード（`lighthouse`プラグイン）が存在し、CoreDNSの外部プラグインとして登録されています ([ lighthouse ](https://coredns.io/explugins/lighthouse/#:~:text=lighthouse%3Agithub.com%2Fsubmariner)) ([ lighthouse ](https://coredns.io/explugins/lighthouse/#:~:text=If%20the%20default%20Kubernetes%20plugin,that%20this%20IP%20is%20reachable))。このプラグインは、本来クラスタ内のCoreDNSに組み込まれ、Kubernetesプラグインで解決できなかった場合にフォールバックして他クラスタのサービス情報を引くものとして設計されています ([ lighthouse ](https://coredns.io/explugins/lighthouse/#:~:text=Lighthouse%20plugin%20allows%20Cross%20Cluster,Kubernetes%20clusters%20connected%20by%20Submariner))。

しかし、Submariner Lighthouseは**このプラグインを既存のCoreDNSプロセスに入れるのではなく、独自にCoreDNSプロセスごと内包したDNSサーバーとして動作**させています ([Service Discovery :: Submariner k8s project documentation website](https://submariner.io/getting-started/architecture/service-discovery/#:~:text=The%20Lighthouse%20DNS%20server%20runs,record%20and%20an%20SRV%20record))。言い換えれば、LighthouseはCoreDNSの実行バイナリを内部に取り込み、自前で起動・運用することで、クラスタ内DNSと分離された**組み込み型のDNSサーバー（Embedded DNS Server）**を提供しています。クラスタ側ではCoreDNSの設定を一部変更し（後述のようにConfigMapのstubドメインやフォワーダー設定を追加）、`clusterset.local`ドメインの問い合わせだけをLighthouseに委ねるようにするだけで済みます ([Multicluster Service Discovery in OpenShift (Part 1)](https://www.redhat.com/en/blog/multicluster-service-discovery-in-openshift#:~:text=Lighthouse%20provides%20cross,service%20information))。クラスタDNS自体にLighthouse専用のプラグインを組み込む必要はないため、**Kubernetesのディストリビューションやバージョンに依存せず**導入しやすいという特徴があります ([Multicluster Service Discovery in OpenShift (Part 1)](https://www.redhat.com/en/blog/multicluster-service-discovery-in-openshift#:~:text=Lighthouse%20provides%20cross,service%20information))。

## CoreDNSを内包する設計の背景と動機

なぜLighthouseはこのような設計を採用したのでしょうか？ 背景には以下のような動機や要件がありました。

- **他クラスタ向けドメインの処理を分離したい:** マルチクラスタ用のドメイン（clusterset.local）の解決ロジックは、各クラスタ固有のサービス名前解決（cluster.local ドメイン）とは異なる特殊な処理です。これを既存CoreDNSに組み込まず外部に切り離すことで、**クラスタ内DNSへの影響を最小限に抑える**狙いがあります ([Multicluster Service Discovery in OpenShift (Part 1)](https://www.redhat.com/en/blog/multicluster-service-discovery-in-openshift#:~:text=Lighthouse%20provides%20cross,service%20information))。仮にマルチクラスタ用の機能に不具合があっても、クラスタ内の通常のDNSには影響を与えません。

- **インストールと互換性の容易さ:** CoreDNSプラグイン方式を取る場合、クラスタ内のCoreDNSにプラグインを組み込むために**カスタムビルド**したCoreDNSバイナリやイメージを用意したり、ConfigMapに複雑な設定（プラグインの有効化設定）を追加する必要があります。これはクラスターの種類やマネージドサービス（例えばOpenShiftやAKSなど）によっては難しい場合があります。LighthouseではCoreDNSを内包した独自コンテナ（Lighthouse DNSサーバ）を提供し、**既存CoreDNSには単純なフォワード設定を挟むだけ**で導入できるようにしました ([Service Discovery :: Submariner k8s project documentation website](https://submariner.io/getting-started/architecture/service-discovery/#:~:text=The%20Lighthouse%20DNS%20server%20runs,record%20and%20an%20SRV%20record))。例えばOpenShiftではDNS Operator経由でstubドメイン設定を追加し、AKSでは`coredns-custom` ConfigMapを用いるなど、環境に応じてフォワード設定を自動調整する工夫がなされています ([CoreDNS in AKS uses two configmaps.  the lighthouse forwarding domain needs added to coredns-custom · Issue #1046 · submariner-io/submariner-operator · GitHub](https://github.com/submariner-io/submariner-operator/issues/1046#:~:text=Lighthouse%20makes%20changes%20to%20,configmap%20by%20overwriting%20any%20changes))。

- **標準APIへの対応と将来性:** KubernetesのマルチクラスタサービスAPI（MCS）はまだ発展途上でしたが、Lighthouseはそれを先取りして独自実装していました ([Multicluster Service Discovery in OpenShift (Part 1)](https://www.redhat.com/en/blog/multicluster-service-discovery-in-openshift#:~:text=There%20is%20a%20proposal%20in,and%20using%20the%20standard%20APIs))。将来的に標準APIが成熟しても、LighthouseのDNSサーバー部分を切り替えることで対応しやすいように、**プロジェクト内で完全に制御できるDNSプロセス**としておくメリットがあります。CoreDNSプラグインとしてではなく独立サーバーにしておけば、Lighthouse側の実装を自由に変えても既存クラスタDNSとのインターフェース（フォワード設定）さえ維持すれば互換性を保てます。

- **あらゆるCNIプラグイン・環境との互換性:** Submariner/Lighthouseはネットワーク実装やクラスタ環境に依存しないことを重視しています ([submariner-io/lighthouse: DNS service discovery across ... - GitHub](https://github.com/submariner-io/lighthouse#:~:text=GitHub%20github,))。組み込み型DNSサーバーは、クラスタ内DNS実装がCoreDNSでもkube-dnsでも関係なく利用できます。極端な場合、クラスタがCoreDNSを使っていなくても、`clusterset.local`向け問い合わせを外部DNSに転送できればLighthouseを利用できるわけです。この柔軟性はプラグイン方式より高いと言えます。

以上の理由から、Lighthouseは**CoreDNSそのものを内部に取り込む**という大胆な設計を選択しました。このアプローチにより、各クラスタにLighthouse専用のDNSサーバー（CoreDNSベース）が立ち上がり、クラスタ内DNSと協調してマルチクラスタの名前解決を実現しています ([Service Discovery :: Submariner k8s project documentation website](https://submariner.io/getting-started/architecture/service-discovery/#:~:text=The%20Lighthouse%20DNS%20server%20runs,record%20and%20an%20SRV%20record))。

## `main.go`と関連コードの構造：CoreDNS埋め込みの実装

Lighthouseのソースコード（`submariner-io/lighthouse`リポジトリ）を見ると、この組み込み型DNSサーバーの実装詳細が伺えます。特に `coredns/main.go` がエントリポイントとなっており、ここでCoreDNSの初期化と起動処理を行っています ([lighthouse/coredns/main.go at devel · submariner-io/lighthouse · GitHub](https://github.com/submariner-io/lighthouse/blob/devel/coredns/main.go#:~:text=package%20main))。このファイルを覗くと、まず目につくのがCoreDNS本体や各種プラグインをimportする記述です ([lighthouse/coredns/main.go at devel · submariner-io/lighthouse · GitHub](https://github.com/submariner-io/lighthouse/blob/devel/coredns/main.go#:~:text=_%20)) ([lighthouse/coredns/main.go at devel · submariner-io/lighthouse · GitHub](https://github.com/submariner-io/lighthouse/blob/devel/coredns/main.go#:~:text=_%20))。例えば`github.com/coredns/coredns/coremain`（CoreDNSのメインループ）や`github.com/coredns/coredns/plugin/...`（さまざまな標準プラグイン）などがimportされており、Lighthouse独自のプラグインとして`github.com/submariner-io/lighthouse/coredns/plugin`もimportされています ([lighthouse/coredns/main.go at devel · submariner-io/lighthouse · GitHub](https://github.com/submariner-io/lighthouse/blob/devel/coredns/main.go#:~:text=%22github.com%2Fsubmariner))。これらは空白import（`_ "..."`）によって実行時にプラグインが登録される形になっています。さらにコード中にはCoreDNSの公式ドキュメントへのコメントもあり、**外部のGoコードと一緒にCoreDNSをビルドする手法**について触れられています ([lighthouse/coredns/main.go at devel · submariner-io/lighthouse · GitHub](https://github.com/submariner-io/lighthouse/blob/devel/coredns/main.go#:~:text=%2F%2F%20build%20with%20external%20golang,source%20code))（CoreDNSではビルド時にプラグインの有効/無効を切り替える仕組みがあり、それを活用していることが示唆されています）。

次に、`main.go`内で**プラグインの実行順序（ディレクティブ順）**を定義している部分があります。`dnsserver.Directives = [...]`という配列に、`metadata`, `log`, `kubernetes`等と並んで`lighthouse`が含まれています ([lighthouse/coredns/main.go at devel · submariner-io/lighthouse · GitHub](https://github.com/submariner-io/lighthouse/blob/devel/coredns/main.go#:~:text=))。これにより、CoreDNSのプラグインチェーンの適切な位置にLighthouseプラグインが組み込まれるようになっています。興味深いのは、このディレクティブ一覧に**通常の`kubernetes`プラグインが含まれていない**点です（代わりに`k8s_external`はあります）。これは、LighthouseのDNSサーバー自体は各クラスタ内のKubernetes Service（cluster.localドメイン）の解決は行わず、あくまでclusterset.localドメインに特化するためです。クラスタ内のサービス解決は引き続き既存のCoreDNS（kubernetesプラグイン）が担当し、Lighthouse側では不要という割り切りになっています。この構成により、LighthouseのCoreDNSは**`clusterset.local`に関する問い合わせだけを処理するシンプルな権威DNSサーバー**として振る舞います。

`main.go`のエントリポイントである`main()`関数では、まずSubmariner共通のログ初期化処理（kzerologの設定）が行われ、`coremain.Run()`が呼ばれています ([lighthouse/coredns/main.go at devel · submariner-io/lighthouse · GitHub](https://github.com/submariner-io/lighthouse/blob/devel/coredns/main.go#:~:text=kzerolog))。`coremain.Run()`はCoreDNS本家のメインループを実行する関数で、これにより実質的にCoreDNSサーバーが起動します。つまり、LighthouseのDNSサーバーは**CoreDNSのライブラリを用いて起動している**ことになります。

まとめると、Lighthouseの`main.go`は**CoreDNSの埋め込み版起動スクリプト**となっており、CoreDNS本体＋必要なプラグイン群＋Lighthouseプラグインをまとめて初期化し、そのままDNSサーバープロセスとして走らせています。この実装により、LighthouseはCoreDNSの機能拡張でありながら、**独立したプロセス**としてクラスタ内にデプロイできる形になっています。

また、Lighthouseのコードベースには`plugin/`ディレクトリの他に`resolver/`や`loadbalancer/`といったディレクトリも見られます ([lighthouse/coredns at devel · submariner-io/lighthouse · GitHub](https://github.com/submariner-io/lighthouse/tree/devel/coredns#:~:text=resolver))。これらはDNS解決の具体的なロジックや、複数候補からのIP選択アルゴリズム（例えば複数クラスタに同じサービスがある場合のラウンドロビンなど）を実装している部分と思われます。実際、Lighthouseプラグインは単にServiceImportリソースを引くだけでなく、**内部に「アドレスキャッシュ」**を持ち、複数クラスタから集約したサービス情報を保持・検索する役割を果たしています ([Service Discovery :: Submariner k8s project documentation website](https://submariner.io/getting-started/architecture/service-discovery/#:~:text=The%20Lighthouse%20DNS%20server%20runs,record%20and%20an%20SRV%20record))。このキャッシュはおそらくLighthouse Agent（後述）によって継続的に更新されるか、もしくはDNSサーバー自体がKubernetes APIをウォッチしてServiceImport/EndpointSliceの変更を取り込むことで実現されています。CoreDNSのkubernetesプラグインがServiceやEndpointを監視してDNSレコードを動的に管理するのと同様に、LighthouseプラグインもServiceImport/EndpointSliceを監視して対応するDNSレコード（エントリ）を管理していると考えられます。これにより、新たなサービスエクスポートや削除があった場合でもリアルタイムにDNS応答を調整できる仕組みになっています。

## LighthouseのDNS解決：マルチクラスタ環境への対応

Lighthouse DNSサーバーは、**各クラスタのLighthouse Agentから集約されたサービス情報**をもとに名前解決を行います。Lighthouse Agentは各クラスタにデプロイされ、サービスのエクスポート/インポート情報をBroker経由で他クラスタと同期するコンポーネントです ([Service Discovery :: Submariner k8s project documentation website](https://submariner.io/getting-started/architecture/service-discovery/#:~:text=The%20Lighthouse%20Agent%20runs%20in,from%20other%20clusters%20is%20imported)) ([Service Discovery :: Submariner k8s project documentation website](https://submariner.io/getting-started/architecture/service-discovery/#:~:text=,it%20in%20the%20local%20cluster))。具体的には、あるクラスタでServiceExportが作成されると、Broker上に対応するServiceImportとEndpointSliceが生成され、他のクラスタのAgentがそれを検知して自クラスタ内にServiceImport/EndpointSliceを作成します ([Service Discovery :: Submariner k8s project documentation website](https://submariner.io/getting-started/architecture/service-discovery/#:~:text=,it%20in%20the%20local%20cluster))。この結果、**各クラスタには、全参加クラスタのサービス情報を表すServiceImport/EndpointSliceリソースが集まる**ことになります。

LighthouseのDNSサーバー（CoreDNSプラグイン）は、この集約されたServiceImport/EndpointSlice情報を**「アドレスキャッシュ」**として保持し、問い合わせに応答します ([Service Discovery :: Submariner k8s project documentation website](https://submariner.io/getting-started/architecture/service-discovery/#:~:text=The%20Lighthouse%20DNS%20server%20runs,record%20and%20an%20SRV%20record))。例えば、`myservice.myns.svc.clusterset.local`という名前のAレコード問い合わせが来た場合、Lighthouseプラグインは内部のキャッシュから`myns`名前空間の`myservice`に該当するエントリを探します。そこに登録されているIPアドレス（クラスタIPもしくはエンドポイントIPの集合）を取り出し、DNS応答として返します ([Service Discovery :: Submariner k8s project documentation website](https://submariner.io/getting-started/architecture/service-discovery/#:~:text=%60clusterset.local%60.%20,NXDomain%20error%20will%20be%20returned))。

**ローカルクラスタ優先度:** もし同じサービスが複数のクラスタで提供されていた場合、Lighthouseは**クエリを発してきたクラスタ自身のエンドポイントを優先**する戦略を取ります ([Service Discovery :: Submariner k8s project documentation website](https://submariner.io/getting-started/architecture/service-discovery/#:~:text=using%20an%20A%20record%20and,an%20SRV%20record))。公式ドキュメントによれば、「単一のサービスが複数クラスタにデプロイされている場合、Lighthouse DNSサーバーはまずローカルクラスタを優先し、それからラウンドロビンで他のリモートクラスタのIPを返す」動作をします ([Service Discovery :: Submariner k8s project documentation website](https://submariner.io/getting-started/architecture/service-discovery/#:~:text=using%20an%20A%20record%20and,an%20SRV%20record))。つまり、同じ名前のサービスが自クラスタにも存在すればそのIPを返し、もし自クラスタには無いが他に2つのクラスタで提供されていれば、その2つを交互に返すような挙動です。これにより、**可能な限り通信をローカルに留めて遅延を最小化**しつつ、他クラスタにもフェイルオーバーできるようになっています（例えば自クラスタのサービスがダウンしている場合はリモートのIPが返る）。

**対応するDNSレコード種類:** Lighthouse DNSサーバーは通常のAレコードによる名前解決に加え、SRVレコードのクエリにも対応しています ([Service Discovery :: Submariner k8s project documentation website](https://submariner.io/getting-started/architecture/service-discovery/#:~:text=The%20Lighthouse%20DNS%20server%20runs,record%20and%20an%20SRV%20record))。SRVレコード対応により、サービスディスカバリ時にポート番号や複数エンドポイントの存在を問い合わせることも可能です。おそらく`_<svc-name>._<protocol>.<ns>.svc.clusterset.local`のような形式でSRVクエリを受けると、ServiceImport内の全エンドポイントを列挙したSRV回答を返す実装になっていると推測されます。この機能はマルチクラスタ環境でロードバランシングやサービスヘルスチェックを行う際に役立つでしょう。

以上のように、Lighthouseは**マルチクラスタAPI (ServiceImport/ServiceExport, EndpointSlice)**を駆使して各クラスタにグローバルサービスのレコードを行き渡らせ、それをDNSで引けるようにしています ([Service Discovery :: Submariner k8s project documentation website](https://submariner.io/getting-started/architecture/service-discovery/#:~:text=The%20Lighthouse%20DNS%20server%20runs,record%20and%20an%20SRV%20record))。この仕組みは、ユーザから見ると各クラスタがあたかも一つの「スーパークラスタ」を形成しているかのようにサービス名前解決ができる点で非常に強力です。

 ([Service Discovery :: Submariner k8s project documentation website](https://submariner.io/getting-started/architecture/service-discovery/))上の図はLighthouseの全体アーキテクチャを示したものです。左側（west.mydomain）と右側（east.mydomain）にそれぞれクラスタがあり、中央にBroker（サービス情報を共有するK8s APIサーバ）が存在しています。各クラスタにはLighthouse Agentがいて、サービスのExport/Importに応じBrokerと通信しながらServiceImport CRDやEndpointSliceを作成・更新しています ([Service Discovery :: Submariner k8s project documentation website](https://submariner.io/getting-started/architecture/service-discovery/#:~:text=The%20Lighthouse%20Agent%20runs%20in,from%20other%20clusters%20is%20imported)) ([Service Discovery :: Submariner k8s project documentation website](https://submariner.io/getting-started/architecture/service-discovery/#:~:text=,it%20in%20the%20local%20cluster))。クラスタ内にはCoreDNS（既存のkube-dns）が動作しており、通常の`cluster.local`ドメインを解決するとともに、フォワーダーを介して`clusterset.local`のクエリをLighthouse CoreDNSに転送します ([Service Discovery :: Submariner k8s project documentation website](https://submariner.io/getting-started/architecture/service-discovery/#:~:text=The%20Lighthouse%20DNS%20server%20runs,record%20and%20an%20SRV%20record))（図中のCoreDNSの「Forwarding」プラグイン）。Lighthouse CoreDNS（図では各クラスタ内の"Lighthouse Plugin"を含むCoreDNS）が受け取ったクエリは、自身のキャッシュ内（ServiceImport由来のデータ）を検索し回答を返します ([Service Discovery :: Submariner k8s project documentation website](https://submariner.io/getting-started/architecture/service-discovery/#:~:text=%60clusterset.local%60.%20,NXDomain%20error%20will%20be%20returned))。このようにAgentとDNSサーバーが連携し、Submarinerによるクロスクラスタネットワーク上でサービス名解決を実現しているのです。

## 組み込みDNSサーバー方式の利点

LighthouseがCoreDNS内蔵型のDNSサーバー方式を採用したことで得られる主な利点をまとめます。

- **クラスタDNSへの最小限の変更:** 各クラスタのDNS(ConfigMap)には、`clusterset.local`ドメインをLighthouseにフォワードする設定を追加するだけで済みます ([Service Discovery :: Submariner k8s project documentation website](https://submariner.io/getting-started/architecture/service-discovery/#:~:text=The%20Lighthouse%20DNS%20server%20runs,record%20and%20an%20SRV%20record))。既存のCoreDNSのプラグイン構成やバイナリ自体を差し替える必要がありません。これにより、**クラスタのアップグレードや設定管理に与えるインパクトが小さい**です。例えばManagedなKubernetes（AKSやGKE、OpenShift等）では、クラスタDNSを自由に差し替えられない場合がありますが、Lighthouseであれば許可された範囲内のConfigMap変更のみで機能を導入できます ([CoreDNS in AKS uses two configmaps.  the lighthouse forwarding domain needs added to coredns-custom · Issue #1046 · submariner-io/submariner-operator · GitHub](https://github.com/submariner-io/submariner-operator/issues/1046#:~:text=Lighthouse%20makes%20changes%20to%20,configmap%20by%20overwriting%20any%20changes))。

- **実装の独立性と柔軟性:** LighthouseチームはDNSサーバー実装を自前で抱えることで、**CoreDNS本体の更新サイクルから独立して開発**できます。新しい機能追加やバグ修正もLighthouse側のコードベースで完結でき、必要に応じてCoreDNSのバージョンアップを取り込むことも自由です（実際、importでCoreDNSをライブラリとして取り込んでいるため、依存バージョンを上げればCoreDNSの改良を享受できます）。逆に、安定しているCoreDNS部分は変更せずLighthouse独自ロジックだけを調整する、といった選択も可能で、**制御権が自分たちにある**点は大きな利点です。

- **異なる環境でのポータビリティ:** この方式は**あらゆるKubernetesディストリビューションで動作**します。CoreDNSプラグイン方式だと、クラスタがCoreDNS以外（古いkube-dnsなど）だった場合に対応できませんが、Lighthouse独立サーバー方式ならフォワードできるDNS実装であれば構いません。事実、Lighthouseは「どのCNI（Container Network Interface）プラグインとも互換性があるソリューション」であり ([submariner-io/lighthouse: DNS service discovery across ... - GitHub](https://github.com/submariner-io/lighthouse#:~:text=GitHub%20github,))、ネットワーク層やDNS実装の違いに影響されず利用できます。これはマルチクラスタという異質な環境をまたぐユースケースでは重要な要素です。

- **障害分離と安定性:** Lighthouse DNSが仮にダウンしても、クラスタ内の通常DNS（cluster.local解決）は影響を受けません。障害が**マルチクラスタ部分に閉じる**ため、最悪の場合でも各クラスタは独立動作を保てます。またLighthouse DNS自体もDeploymentで冗長化（複数レプリカ）したり、CoreDNSのヘルスチェックプラグインを有効化して健全性監視を行うなど、安定稼働のための工夫ができます ([lighthouse/coredns/main.go at devel · submariner-io/lighthouse · GitHub](https://github.com/submariner-io/lighthouse/blob/devel/coredns/main.go#:~:text=)) ([lighthouse/coredns/main.go at devel · submariner-io/lighthouse · GitHub](https://github.com/submariner-io/lighthouse/blob/devel/coredns/main.go#:~:text=))。こうした冗長化やスケーリングも、クラスタ内DNSとは別個に調整できるため柔軟性があります。

- **性能面の考慮:** 一見、DNSクエリがクラスタDNSからLighthouse DNSへと**一段階増える**ためオーバーヘッドが心配されるかもしれません。しかし実際にはCoreDNSのフォワード処理は非常に軽量で、同一クラスタ内の通信なので遅延もごくわずかです。またCoreDNSにはキャッシュ機能もあり、Lighthouse側でも`cache`プラグインが有効になっています ([lighthouse/coredns/main.go at devel · submariner-io/lighthouse · GitHub](https://github.com/submariner-io/lighthouse/blob/devel/coredns/main.go#:~:text=_%20)) ([lighthouse/coredns/main.go at devel · submariner-io/lighthouse · GitHub](https://github.com/submariner-io/lighthouse/blob/devel/coredns/main.go#:~:text=))。そのため、繰り返し問い合わせる場合はキャッシュヒットして応答が高速化されますし、不要なBroker問い合わせやAPIアクセスも削減されます。むしろプラグインをクラスタDNS内に組み込んで毎回他クラスタのデータ参照をするより、Lighthouse DNSで一度引いて結果をキャッシュし、クラスタDNSもその結果をキャッシュするといった**二段キャッシュ**の形になるため、全体的なスループットは十分高く保てるでしょう。

- **ログ・メトリクスの分離:** Lighthouse DNSサーバーは独立しているため、**マルチクラスタ関連のDNSクエリログやメトリクスを個別に収集**できます。CoreDNSの標準メトリクス（Prometheus）プラグインも有効にできますし ([lighthouse/coredns/main.go at devel · submariner-io/lighthouse · GitHub](https://github.com/submariner-io/lighthouse/blob/devel/coredns/main.go#:~:text=))、Lighthouseプラグイン特有の統計（どのクラスタのIPを返したか等）を取ることもできます。サービスメッシュ的な観点で各クラスタ間のトラフィック分布を測定する場合にも、Lighthouse DNSを観察すれば把握できるという利点があります。

以上のように、組み込み型のCoreDNSサーバー方式は、マルチクラスタDNSという特殊な要件に柔軟かつ安定して応えるための合理的な解決策と言えます。

## 制約やトレードオフ、開発・運用上の注意点

一方で、この設計にはいくつかのトレードオフや注意すべき点も存在します。

- **追加コンポーネントの管理:** 各クラスタにLighthouse AgentとLighthouse DNSサーバーという2つのコンポーネントを動かす必要があり、システム全体として見ると構成がやや複雑になります。特にDNS周りでは、**クラスタDNSのConfigMap変更**と**Lighthouse DNSデプロイ**がセットで正しく行われないと機能しません。運用時には、Lighthouse DNSが正しく起動しているか、またCoreDNSのフォワード設定が失われていないか（クラスタアップグレード時に上書きされる等）を監視・確認する必要があります ([CoreDNS in AKS uses two configmaps.  the lighthouse forwarding domain needs added to coredns-custom · Issue #1046 · submariner-io/submariner-operator · GitHub](https://github.com/submariner-io/submariner-operator/issues/1046#:~:text=Lighthouse%20makes%20changes%20to%20,configmap%20by%20overwriting%20any%20changes))。Submariner Operatorが自動でこれらを設定してくれますが、ユーザーはそれを認識しておくべきです。

- **CoreDNSアップデートへの追随:** Lighthouseは内部に特定バージョンのCoreDNSを取り込んでビルドしています。そのため、CoreDNS本体にセキュリティアップデートや重要な不具合修正があった場合、Lighthouse側でも依存バージョンを上げて新しいコンテナイメージをリリースする必要があります。クラスタ管理者は、Submariner/Lighthouseのアップグレードも通じてCoreDNSの更新を適用する形になります。これはCoreDNSプラグインを直接使っている場合も同様ではありますが、**独自ビルドの場合はアップストリームから自動で最新にならない**点は意識すべきです。

- **DNSフォワードの単一点障害:** クラスタDNSからLighthouse DNSへの転送設定が誤っていたり、Lighthouse DNSサーバーがダウンしていると、`clusterset.local`名前解決は失敗してしまいます（フォワード先が無い場合、クラスタDNSはその問い合わせを外部DNSに投げてNXDOMAINになるだけです）。そのため、Lighthouse DNSは冗長化（複数レプリカ＋CoreDNSの`forward`プラグインで複数先指定）や高可用性を確保することが望ましいです。運用上はLighthouse DNS用のServiceをClusterIPではなく**Headless Service＋各PodのHostPort**で提供してローカルに動かしたり、あるいはDeploymentでなくDaemonSetにして各ノード上のDNS問い合わせをローカル処理させる、などの工夫も考えられます（これらは高度な最適化例ですが、要はフォワード先のLighthouse DNSを信頼できるよう冗長にすることがポイントです）。

- **プラグイン開発の難易度:** CoreDNSのプラグインとしてLighthouseを実装する際、当初はCoreDNSプロジェクトへの外部プラグイン追加提案もなされました ([New Plugin: Lighthouse for multi cluster service discovery with Submariner · Issue #3410 · coredns/coredns · GitHub](https://github.com/coredns/coredns/issues/3410#:~:text=Issue))。しかしマルチクラスタ特有のロジックや他コンポーネント（Lighthouse Agentとの協調）が必要なことから、CoreDNS本体とは独立に開発を進める判断がなされています。プラグイン自体のコードはLighthouseリポジトリ内で管理されていますが、それでもCoreDNSのPlugin APIや挙動を理解しつつ、Kubernetes APIから情報を取得して応答を生成するという**高度な実装**が求められます。Go言語に精通したエンジニアであっても、KubernetesのCRDやCoreDNSの仕組みに跨る知識が必要で、開発・デバッグには相応の手間がかかったことでしょう。しかしその分、Lighthouseプラグインの実装はシンプルに保たれており（ServiceImportからIPを引くだけという意味で）、それ以外の難しい部分はAgent側に任せる設計になっています。

- **将来的な統合の可能性:** KubernetesのマルチクラスタサービスAPIが普及し、各ベンダーがネイティブに対応するようになれば、Lighthouseの必要性は薄れる可能性があります。しかし現時点（2025年）でもマルチクラスタDNS解決の標準実装は確立されておらず、Lighthouseは実運用で貴重なソリューションとなっています。そのため、しばらくはLighthouse独自DNSを維持・発展させていく必要があるでしょう。開発者向けには、コードを追いやすいようにモジュールが分割されており、CoreDNSプラグイン部分も単独でテスト可能に実装されているはずです。運用者向けには、Submarinerのバージョンアップにより自動でCoreDNS設定が調整されるケース（例: RKE2環境でのConfigMap検出 ([CoreDNS in AKS uses two configmaps.  the lighthouse forwarding domain needs added to coredns-custom · Issue #1046 · submariner-io/submariner-operator · GitHub](https://github.com/submariner-io/submariner-operator/issues/1046#:~:text=Lighthouse%20makes%20changes%20to%20,configmap%20by%20overwriting%20any%20changes))）もあるため、**リリースノートやドキュメントの注意事項**を定期的に確認することが推奨されます。

## おわりに：Lighthouseの設計思想とその価値

Submariner LighthouseのCoreDNS組み込み型DNSサーバーの設計は、マルチクラスタ環境という新たな領域の課題に取り組む中で生まれた、ユニークかつ実践的なアプローチです。CoreDNSをプラグインとしてではなくプロセスごと抱え込むことで、システムの柔軟性と安定性を確保しながら、ユーザーにはシームレスなサービスディスカバリ体験を提供しています。

Go言語で実装されたこの仕組みは、Goの持つモジュール性やパッケージ結合のしやすさを存分に活かしたものと言えるでしょう。CoreDNSという信頼性の高いDNSサーバーを土台にしつつ、その拡張を自前でコントロールすることで、イノベーションと安定運用のバランスを取っています。

マルチクラスタが当たり前になりつつある今日、Lighthouseのような取り組みから学べることは多くあります。既存ソフトウェアをただ利用するのではなく、必要に応じて**組み込んでしまう**という発想は、エンジニアリング上の一つの大胆な解決策です。それによって生まれる利点と負担を正しく見極め、システム全体で最適なアーキテクチャを選択したLighthouseは、マルチクラスタ時代のDNSソリューションとして興味深い成功例と言えるでしょう。

**参考文献・情報源:**

- Submariner/Lighthouse 公式ドキュメント（アーキテクチャとサービスディスカバリ） ([Service Discovery :: Submariner k8s project documentation website](https://submariner.io/getting-started/architecture/service-discovery/#:~:text=The%20Lighthouse%20DNS%20server%20runs,record%20and%20an%20SRV%20record)) ([Service Discovery :: Submariner k8s project documentation website](https://submariner.io/getting-started/architecture/service-discovery/#:~:text=using%20an%20A%20record%20and,an%20SRV%20record)) ([Service Discovery :: Submariner k8s project documentation website](https://submariner.io/getting-started/architecture/service-discovery/#:~:text=The%20workflow%20is%20as%20follows%3A))  
- CoreDNS公式ブログ（プラグインのビルド手法） ([lighthouse/coredns/main.go at devel · submariner-io/lighthouse · GitHub](https://github.com/submariner-io/lighthouse/blob/devel/coredns/main.go#:~:text=%2F%2F%20build%20with%20external%20golang,source%20code))  
- Lighthouse リポジトリのソースコード (`coredns/main.go` 他) ([lighthouse/coredns/main.go at devel · submariner-io/lighthouse · GitHub](https://github.com/submariner-io/lighthouse/blob/devel/coredns/main.go#:~:text=)) ([lighthouse/coredns/main.go at devel · submariner-io/lighthouse · GitHub](https://github.com/submariner-io/lighthouse/blob/devel/coredns/main.go#:~:text=kzerolog))  
- Red Hat Blog: *"Multicluster Service Discovery in OpenShift"* （Lighthouseの概念解説） ([Multicluster Service Discovery in OpenShift (Part 1)](https://www.redhat.com/en/blog/multicluster-service-discovery-in-openshift#:~:text=Lighthouse%20provides%20cross,service%20information))  
- Submariner Issue/PR議論（CoreDNS ConfigMap調整など運用上の知見） ([CoreDNS in AKS uses two configmaps.  the lighthouse forwarding domain needs added to coredns-custom · Issue #1046 · submariner-io/submariner-operator · GitHub](https://github.com/submariner-io/submariner-operator/issues/1046#:~:text=Lighthouse%20makes%20changes%20to%20,configmap%20by%20overwriting%20any%20changes))