Служба, розташована в іншому просторі імен


108

Я намагався знайти спосіб визначення служби в одному просторі імен, який посилається на Pod, який працює в іншому просторі імен. Я знаю, що контейнери в Pod, що працює в, namespaceAможуть отримати доступ до serviceXвизначеного namespaceB, посилаючись на нього в кластері DNS як serviceX.namespaceB.svc.cluster.local, але я б краще не мав коду всередині контейнера, щоб знати про місцезнаходження serviceX. Тобто я хочу, щоб код просто шукав, serviceXа потім мав доступ до нього.

Документація Kubernetes говорить про те, що це можливо. Це говорить про те, що одна з причин того, що ви б визначили службу без селектора, полягає в тому, що ви хочете вказати свою послугу на службу в іншому просторі імен або на іншому кластері .

Це підказує мені, що я повинен:

  1. Визначте serviceXпослугу в namespaceAбез селектора (оскільки ПОД, який я хочу вибрати, не входить namespaceA).
  2. Визначте послугу (яку я також зателефонував serviceX) у namespaceB, а потім
  3. Визначити об'єкт в Endpoints namespaceAдо точки , щоб serviceXв namespaceB.

Саме цей третій крок я не зміг здійснити.

Спочатку я спробував визначити об’єкт Кінцевих точок таким чином:

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було. Але це призвело до помилки, сказавши, що ipполе в addressesмасиві є обов'язковим. Отже, моя наступна спроба була призначити фіксований адресу ClusterIP , щоб serviceXв namespaceB, і покласти , що в поле IP (зверніть увагу , що service_cluster_ip_rangeналаштована як 192.168.0.0/16і 192.168.1.1був призначений в якості ClusterIP для serviceXв namespaceB, serviceXв 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не переадресували до Pod namespaceB-, вони вичерпалися. Дивлячись на налаштування iptables, схоже, що для цього потрібно було б зробити попереднє маршрутизацію NAT двічі.

Єдиним , що я знайшов , що працювало - але не є задовільним рішенням - це для пошуку фактичного IP - адреси Pod , що забезпечує serviceXв namespaceBі помістити цю адресу в об'єкті Endpoints в namespaceA. Звичайно, це не задовільно, тому що IP-адреса Pod може змінитися з часом. Ось цю проблему IP-адреси служб вирішувати.

Отже, чи є спосіб виконати те, що здається обіцянкою документації, що я можу вказати службу в одному просторі імен на службу, що працює в іншому просторі імен?

Коментолог запитав, чому ви хочете це зробити - ось випадок використання, який має для мене сенс, принаймні:

Скажімо, у вас є система багатоорендарів, яка також включає загальну функцію доступу до даних, якою можна ділитися між орендарями. Тепер уявіть, що ця функція доступу до даних має різні смаки із загальними API, але різними характеристиками. Деякі орендарі отримують доступ до одного з них, інші орендарі мають доступ до іншого.

Кожні орендарі працюють у власних просторах імен, але кожен повинен отримати доступ до однієї з цих загальних служб доступу до даних, яка обов'язково буде знаходитися в іншому просторі імен (оскільки до неї звертаються кілька орендарів). Але ви не хочете, щоб орендар повинен змінити свій код, якщо підписка зміниться, щоб отримати доступ до високоефективної послуги.

Потенційним рішенням (найчистішим, про яке я можу придумати, якби воно працювало) є включення визначення служби у простір імен кожного орендаря для служби доступу до даних, з кожним з яких налаштовано для відповідної кінцевої точки. Це визначення послуги було б налаштовано так, щоб вказувати на належну послугу доступу до даних, яку кожен орендар має право використовувати.


сенс просторів імен полягає в ізоляції, тому я думаю, якщо вам потрібно перейти через простори імен, вам потрібно знати хоча б де він знаходиться!
ГРЕ

Отже, що означає документація, коли вона пропонує вам направити службу, визначену в одному просторі імен, для доступу до служби в іншому просторі імен, не визначаючи селектор, а шляхом імплікації, що визначає кінцеву точку? Для цього, безумовно, є дійсні випадки використання - один із них я додав до питання. Чи документація просто вводить в оману, чи є спосіб зробити це, що я ще не з'ясував?
Девід МакКінлі

я не впевнений, вибач. Що я знаю, це те, що я отримую доступ до служб у кількох просторах імен, використовуючи їх fqdn. Це я роблю особливо з vpn, оскільки у мене є 1 vpn стручок і я підключаюся через усі сервіси з нього. однак вам потрібно знати простір імен та надати fqdn. Я б запропонував вам запитати на слабкому каналі.
MrE

Використання fqdn - це рішення, яке я зараз використовую. Хоча мій випадок використання краще подавати, (якщо тепер додано питання), якщо це не було б необхідним.
Девід МакКінлі

Мені також цікаво, на що йдеться і в документації, проте я можу використовувати fqdn як задовільне рішення для мого випадку використання.
Вінсент Де Смет

Відповіді:


223

Я наткнувся на ту саму проблему і знайшов приємне рішення, яке не потребує статичної конфігурації 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
Так. Він працює для одного стручка для спілкування зі службою в іншому просторі імен, але не для врівноважувача навантаження.
Пол,

через виправлення кубернетів у кластері пошуку CNAME , стара версія може не працювати.
赵浩翔

1
Чи / має це працювати і для служб у просторі імен kube-системи?
Набхет

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>на відповідне значення.

У Кубернетах простори імен використовуються для створення віртуального середовища, але всі вони з'єднуються між собою.


6
Чи можете ви пояснити, чим ця відповідь відрізняється від наказу Павла майже на 2 роки раніше?
Олівер

2
@Oliver немає різниці, але я тільки що вказав, що замінити ім'я служби та простір імен у якому конкретному місці. в той час як він використовував простір імен, так мені це бентежить.
Суворий Манвар

7
Зручна хитрість щодо SO - додати коментар до відповіді та зробити необхідне уточнення.
Олівер

4
Я б назвав це найкращим рішенням, оскільки .svc.cluster.localвоно за замовчуванням підтримується для вирішення послуги внутрішньо.
DrKNa

1
прокинувся і для мене. велике спасибі
Vimal Пракаш

0

Цього можна досягти, розгорнувши щось на більш високому рівні, ніж Служби з розширенням імен, як-от сервіс loadbalancer 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)
Нікола Бен

1
@Prashanth B: Чи можете ви відповідно оновити свою відповідь!
хаосгуру
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.