別の名前空間にあるサービス


107

別の名前空間で実行されているポッドにリンクするサービスを、1つの名前空間で定義する方法を探しています。で実行されているポッド内のコンテナは、クラスタDNSでとして参照することで定義されたにnamespaceAアクセスできることを知っていますが、コンテナ内のコードでの場所を知る必要はありません。つまり、コードでルックアップして、それにアクセスできるようにします。serviceXnamespaceBserviceX.namespaceB.svc.cluster.localserviceXserviceX

Kubernetesのドキュメントでは、これが可能であることを示唆しています。セレクタなしでサービスを定義する理由の1つは、サービスを別の名前空間または別のクラスタのサービスにポイントしたいということです

それは私に私がすべきことを示唆しています:

  1. セレクタなしでserviceXサービスをで定義しますnamespaceA(選択したいPODがにないためnamespaceA)。
  2. でサービス(これもserviceX)を定義し、namespaceB次に
  3. namespaceA指すようserviceXにEndpointsオブジェクトを定義しnamespaceBます。

私が達成できなかったのは、この3番目のステップです。

まず、Endpointsオブジェクトを次のように定義してみました。

kind: Endpoints
apiVersion: v1
metadata:
  name: serviceX
  namespace: namespaceA
subsets:
  - addresses:
      - targetRef:
          kind: Service
          namespace: namespaceB
          name: serviceX
          apiVersion: v1
    ports:
      - name: http
        port: 3000

それは論理的なアプローチのようであり、明らかにそれが何のtargetRefためにあるのか。しかし、これによりipaddresses配列内のフィールドは必須であるというエラーが発生しました。だから、私の次の試みが固定CLUSTERIPアドレスを割り当てることだったserviceXnamespaceB、およびIPフィールドにいることを置く(ことに注意してくださいservice_cluster_ip_rangeとして構成され192.168.0.0/16、そして192.168.1.1ためCLUSTERIPとして割り当てられたserviceX中にnamespaceBserviceX中にnamespaceA自動で異なるCLUSTERIPを割り当てられた192.168.0.0/16サブネット) :

kind: Endpoints
apiVersion: v1
metadata:
  name: serviceX
  namespace: namespaceA
subsets:
  - addresses:
        - ip: 192.168.1.1
          targetRef:
            kind: Service
            namespace: namespaceB
            name: serviceX
            apiVersion: v1
    ports:
      - name: http
        port: 3000

それは受け入れられましたが、serviceXin へのアクセスnamespaceAはポッドに転送されませんでしたnamespaceB-彼らはタイムアウトしました。iptablesの設定を見ると、NATプレルーティングを2回実行する必要があったようです。

しかし、満足のいく解決策ではありません- -私は働いていた検索をした唯一のものは提供ポッドの実際のIPアドレスをルックアップするためにあるserviceX中でのnamespaceBそして内のエンドポイントのオブジェクトにそのアドレスを置きますnamespaceA。もちろん、ポッドのIPアドレスは時間とともに変化する可能性があるため、これは満足のいくものではありません。それが解決すべきサービスIPの問題です。

それで、あるネームスペースのサービスを別のネームスペースで実行されているサービスにポイントできるというドキュメントの約束のように思われるものを満たす方法はありますか?

なぜこれをしたいのかとコメントした人が質問しました-少なくとも私にとって意味のある使用例を以下に示します:

テナント間で共有できる共通のデータアクセス機能も含まれているマルチテナントシステムがあるとします。ここで、共通のAPIを持つこのデータアクセス関数にはさまざまなフレーバーがあり、パフォーマンス特性が異なると想像してください。一部のテナントはそのうちの1つにアクセスでき、他のテナントは別のテナントにアクセスできます。

各テナントのポッドは独自の名前空間で実行されますが、各ポッドはこれらの一般的なデータアクセスサービスの1つにアクセスする必要があり、サービスは別の名前空間にある必要があります(複数のテナントによってアクセスされるため)。ただし、より高性能なサービスにアクセスするためにサブスクリプションが変更された場合、テナントがコードを変更する必要はありません。

可能性のある解決策(それが機能したとしても、私が考えることができる最もクリーンな解決策)は、データアクセスサービスの各テナントの名前空間にサービス定義を含め、それぞれを適切なエンドポイント用に構成することです。このサービス定義は、各テナントが使用する資格がある適切なデータアクセスサービスを指すように構成されます。


名前空間のポイントは分離することなので、名前空間を移動する必要がある場合は、少なくともそれがどこにあるかを知る必要があります。
MrE、2016年

では、セレクタを定義せずに、エンドポイントを定義することによって、あるネームスペースで定義されたサービスに別のネームスペースのサービスにアクセスするように指示できることを示唆している場合、ドキュメントはどういう意味ですか?これには確かに有効な使用例があります-その1つを質問に追加しました。ドキュメントは誤解を招くだけですか、それともまだ理解していない方法がありますか?
デビッドマッキンリー2016年

よくわかりません。私が知っているのは、fqdnを使用して複数の名前空間のサービスにアクセスすることです。私はこれを特にVPNで行います。1つのVPNポッドがあり、それからすべてのサービスを介して接続するからです。ただし、名前空間を理解し、fqdnを提供する必要があります。スラックチャンネルで質問することをお勧めします。
MrE、2016年

fqdnの使用は、私が現在使用しているソリューションです。ただし、必要がなければ、私のユースケースの方が適しています(現在は質問に追加されています)。
デビッドマッキンリー2016年

また、ドキュメンテーションが何を参照しているのかも不思議ですが、私のユースケースでは満足のいくソリューションとしてfqdnを使用できます。
Vincent De Smet 2016

回答:


221

私は同じ問題に遭遇し、静的IP構成を必要としない素敵な解決策を見つけました:

(あなたが述べたように)DNS名を介してサービスにアクセスできます:servicename.namespace.svc.cluster.local

そのDNS名を使用して、ローカルサービスを介して別の名前空間で参照できます。

kind: Service
apiVersion: v1
metadata:
  name: service-y
  namespace: namespace-a
spec:
  type: ExternalName
  externalName: service-x.namespace-b.svc.cluster.local
  ports:
  - port: 80

2
これは素晴らしいソリューションです!最初に質問したときに「ExternalName」タイプがサービスで使用可能であったかどうかはわかりませんが、現在サポートされており、問題はきちんと解決されています。ありがとう、ポール。
デビッドマッキンリー

1
これは機能しますか?私は疑う。これが本当にうまくいったかどうかは誰でも確認できますが、私にとってはうまくいきません。
debianmaster

2
はい、そうです。1つのポッドが別の名前空間のサービスと通信するために機能しますが、上りロードバランサーに対しては機能しません。
Paul

kubernetesのクラスター内CNAMEルックアップ修正したため、古いバージョンが機能しない可能性があります。
赵浩翔

1
これはkube-system名前空間のサービスでも機能しますか?
Nabheet

10

それを行うのはとても簡単です

ホストとして使用して解決したい場合

別の名前空間にあるサービスに他のAPIゲートウェイのアンバサダーを使用している場合は、常に以下を使用することをお勧めします。

            Use : <service name>
            Use : <service.name>.<namespace name>
            Not : <service.name>.<namespace name>.svc.cluster.local

それは次のようになります: servicename.namespacename.svc.cluster.local

これは、あなたが言及した名前空間内の特定のサービスにリクエストを送信します。

例:

kind: Service
apiVersion: v1
metadata:
  name: service
spec:
  type: ExternalName
  externalName: <servicename>.<namespace>.svc.cluster.local

ここで、<servicename>および<namespace>を適切な値に置き換えます。

Kubernetesでは、仮想環境を作成するために名前空間が使用されますが、すべてが相互に接続されています。


6
この回答が2年前に提供されたPaulの回答とどのように異なるのか説明していただけますか?
オリバー

2
@オリバーは違いはありませんが、特定の場所でサービス名と名前空間を置き換えるものを指定しました。彼は名前空間を使用していますが、私には混乱します。
Harsh Manvar

6
SOの便利なトリックは、回答にコメントを追加し、必要な説明を行うことです。
オリバー

4
これ.svc.cluster.localはデフォルトでサービスを内部的に解決するためにサポートされているため、これを最良のソリューションと呼びます。
DrKNa

1
私のためにも起きました。ありがとう
ビマルプラカシュ

0

これは、名前空間付きサービスよりも上位のレイヤーにサービスロードバランサーhttps://github.com/kubernetes/contrib/tree/master/service-loadbalancerなどの何かをデプロイすることで実現でき ます。単一の名前空間に制限する場合は、「-namespace = ns」引数を使用します(デフォルトではすべての名前空間に設定されています:https : //github.com/kubernetes/contrib/blob/master/service-loadbalancer/service_loadbalancer.go #L715)。これはL7ではうまく機能しますが、L4では少し面倒です。


3
このプロジェクトは現在非推奨になっています(2018年
Nicola Ben

1
@Prashanth B:それに応じて回答を更新してください!
chaosguru、
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.