Advanced
Тема интерфейса

Обзор

Эта статья полезна?
Язык статьи: Русский
Показать оригинал
Страница переведена автоматически и может содержать неточности. Рекомендуем сверяться с английской версией.

Прямой доступ к Pod

После создания pod могут возникнуть следующие проблемы, если вы напрямую обращаетесь к pod:

  • Pod может быть удалён и пересоздан в любой момент контроллером, например Deployment, и результат доступа к pod становится непредсказуемым.
  • IP‑адрес pod выделяется только после его запуска. До запуска pod IP‑адрес неизвестен.
  • Приложение обычно состоит из нескольких pod, которые запускают один и тот же образ. Обращение к pod по отдельности не эффективно.

Например, приложение использует Deployments для создания фронтенда и бэкенда. Фронтенд вызывает бэкенд для вычислений, как показано в Рисунок 1. Три pod работают в бэкенде, они независимы и заменяемы. Когда pod бэкенда пересоздаётся, ему назначается новый IP‑адрес, о котором фронтенд‑pod не знает.

Рисунок 1 Доступ между pod


Использование сервисов для доступа к Pod

Сервисы Kubernetes используются для решения описанных выше проблем доступа к pod. Сервис имеет фиксированный IP‑адрес. (Когда создаётся кластер CCE, задаётся блок Service CIDR, который используется для распределения IP‑адресов сервисам.) Сервис перенаправляет запросы, обращённые к сервису, к pod’ам на основе меток и одновременно выполняет балансировку нагрузки для этих pod’ов.

В приведённом выше примере к сервису добавлен frontend pod для доступа к backend pod’ам. Таким образом, frontend pod не должен знать о изменениях в backend pod’ах, как показано в Рисунок 2.

Рисунок 2 Доступ к pod’ам через сервис


Типы сервисов

Kubernetes позволяет указать сервис требуемого типа. Значения и действия различных типов сервисов перечислены ниже:

  • ClusterIP

    Сервисы ClusterIP позволяют рабочим нагрузкам в одном кластере использовать внутренние доменные имена кластера для доступа друг к другу.

  • NodePort

    Сервис доступен по IP‑адресу каждого узла на статическом порту (NodePort). Автоматически создаётся ClusterIP Service, к которому будет перенаправлять NodePort Service. Запрашивая <NodeIP>:<NodePort>, вы можете получить доступ к NodePort Service извне кластера.

  • LoadBalancer

    LoadBalancer Services могут получать доступ к рабочим нагрузкам из публичной сети через балансировщик нагрузки, который надёжнее доступа на основе EIP. LoadBalancer Services рекомендуется использовать для доступа к рабочим нагрузкам из внешнего кластера.

  • DNAT

    Шлюз DNAT переводит адреса узлов кластера и позволяет нескольким узлам кластера использовать общий EIP. DNAT Services обеспечивают более высокую надёжность по сравнению с NodePort Services, использующими EIP. Вам не нужно привязывать EIP к отдельному узлу, и запросы могут распределяться к рабочей нагрузке даже если один из узлов выходит из строя.

externalTrafficPolicy (Service Affinity)

Для NodePort и LoadBalancer Service запросы сначала отправляются на node port, затем на Service, и в конце на pod, обслуживающий Service. Обслуживающий pod может находиться не на узле, получающем запросы. По умолчанию backend workload может быть доступен с любого node IP address и service port. Если pod не находится на узле, получающем запрос, запрос будет перенаправлен на узел, где расположен pod, что может привести к потере производительности.

Эта externalTrafficPolicy параметр в Service используется для определения, может ли внешний трафик быть направлен к локальным узлам или к конечным точкам по всему кластеру. The following is an example:

apiVersion: v1
kind: Service
metadata:
name: nginx-nodeport
spec:
externalTrafficPolicy: Local
ports:
- name: service
nodePort: 30000
port: 80
protocol: TCP
targetPort: 80
selector:
app: nginx
type: NodePort

Если значение externalTrafficPolicy равен Local, запросы, отправленные с Node IP address:Service port будут перенаправлены только к pod на локальном узле. Если узел не имеет pod, запросы приостанавливаются.

Если значение externalTrafficPolicy является Кластер, запросы пересылаются внутри кластера, и бэкенд‑нагрузка может быть доступна с любого IP‑адреса узла и порта сервиса.

Если externalTrafficPolicy не установлено, значение по умолчанию Кластер будет использоваться.

При создании NodePort в консоли CCE вы можете настроить этот параметр с помощью Привязка сервиса опции.

В следующей таблице сравниваются два варианта externalTrafficPolicy.

Table 1 Сравнение двух типов привязки сервиса

Измерение

externalTrafficPolicy (Привязка сервиса)

Уровень кластера (Кластер)

Уровень узла (Локальный)

Сценарий применения

Этот режим применяется в сценариях, когда высокая производительность не требуется и адрес IP клиента не нужно сохранять. Этот режим обеспечивает более сбалансированную нагрузку на каждый узел в кластере.

Этот режим применяется в сценариях, когда требуется высокая производительность и необходимо сохранять адрес IP клиента. Однако трафик перенаправляется только на узел, где находится контейнер, и трансляция адреса IP не выполняется.

Режим доступа

IP-адреса и порты доступа всех узлов в кластере могут обращаться к рабочей нагрузке, связанной с Service.

Только IP-адрес и порт доступа узла, на котором размещена нагрузка, могут обращаться к нагрузке, связанной с Service.

Получение исходного IP-адреса клиента

Исходный IP-адрес клиента не может быть получен.

Исходный IP-адрес клиента может быть получен.

Производительность доступа

Доступ к сервису может привести к потере производительности из‑за перенаправления маршрута, и следующий прыжок для пакета данных может быть другим узлом.

Доступ к сервису не приводит к потере производительности из‑за перенаправления маршрута.

Балансировка нагрузки

Распространение трафика обладает хорошей общей балансировкой нагрузки.

Существует потенциальный риск несбалансированного распространения трафика.

Другой особый случай

Нет

В разных моделях сетей контейнеров и режимах переадресации сервисов доступ к сервисам из кластера может завершиться неудачей. Подробности см Почему сервис не может быть доступен изнутри кластера.

Почему сервис не может быть доступен изнутри кластера

Если привязка сервиса к сервису задана на уровне узла, то есть значение externalTrafficPolicy равно Локальный, служба может быть недоступна изнутри кластера (конкретно, узлы или контейнеры). Информация, похожая на следующую, отображается:

upstream connect error or disconnect/reset before headers. reset reason: connection failure
Or
curl: (7) Failed to connect to 192.168.10.36 port 900: Connection refused

Типично, что балансировщик нагрузки в кластере недоступен. Причина следующая: Когда Kubernetes создает Service, kube-proxy добавляет адрес доступа к балансировщику нагрузки как внешний IP‑адрес (External‑IP, как показано в выводе следующей команды) в iptables или IPVS. Если клиент внутри кластера инициирует запрос к доступу к балансировщику нагрузки, адрес считается внешним IP‑адресом Service, и запрос напрямую переадресуется kube-proxy без прохождения через балансировщик нагрузки за пределами кластера.

# kubectl get svc nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx LoadBalancer 10.247.76.156 123.**.**.**,192.168.0.133 80:32146/TCP 37s

Когда значение externalTrafficPolicy равно Local, сбои доступа в различных моделях сетей контейнеров и режимах переадресации службы следующие:

Note
  • Для многоподовой нагрузки убедитесь, что все pod доступны. В противном случае существует вероятность, что доступ к нагрузке завершится с ошибкой.
  • In a CCE Turbo cluster that utilizes Cloud Native Network 2.0, node-level affinity is supported only when the Service backend is connected to a hostNetwork pod.
  • The table lists only the scenarios where the access may fail. Other scenarios that are not listed in the table indicate that the access is normal.

Service Type Released on the Server

Access Type

Request Initiation Location on the Client

Tunnel Network Cluster (IPVS)

VPC Network Cluster (IPVS)

Tunnel Network Cluster (iptables)

VPC Network Cluster (iptables)

NodePort Service

Public/Private network

Same node as the service pod

Access the IP address and NodePort on the node where the server is located: The access is successful.

Access the IP address and NodePort on a node other than the node where the server is located: The access failed.

Access the IP address and NodePort on the node where the server is located: The access is successful.

Access the IP address and NodePort on a node other than the node where the server is located: The access failed.

Access the IP address and NodePort on the node where the server is located: The access is successful.

Access the IP address and NodePort on a node other than the node where the server is located: The access failed.

Access the IP address and NodePort on the node where the server is located: The access is successful.

Access the IP address and NodePort on a node other than the node where the server is located: The access failed.

Different nodes from the service pod

Access the IP address and NodePort on the node where the server is located: The access is successful.

Access the IP address and NodePort on a node other than the node where the server is located: The access failed.

Access the IP address and NodePort on the node where the server is located: The access is successful.

Получить доступ к IP-адресу и NodePort на узле, отличном от узла, где расположен сервер: Доступ не удался.

Доступ выполнен успешно.

Доступ выполнен успешно.

Другие контейнеры на том же узле, что и pod сервиса

Получить доступ к IP-адресу и NodePort на узле, где расположен сервер: Доступ выполнен успешно.

Получить доступ к IP-адресу и NodePort на узле, отличном от узла, где расположен сервер: Доступ не удался.

Доступ не удался.

Получить доступ к IP-адресу и NodePort на узле, где расположен сервер: Доступ выполнен успешно.

Получить доступ к IP-адресу и NodePort на узле, отличном от узла, где расположен сервер: Доступ не удался.

Доступ не удался.

Другие контейнеры на разных узлах от pod сервиса

Получить доступ к IP-адресу и NodePort на узле, где расположен сервер: Доступ выполнен успешно.

Доступ к IP‑адресу и NodePort на узле, отличном от узла, где расположен сервер: Доступ не удался.

Доступ к IP‑адресу и NodePort на узле, где расположен сервер: Доступ выполнен успешно.

Доступ к IP‑адресу и NodePort на узле, отличном от узла, где расположен сервер: Доступ не удался.

Доступ к IP‑адресу и NodePort на узле, где расположен сервер: Доступ выполнен успешно.

Доступ к IP‑адресу и NodePort на узле, отличном от узла, где расположен сервер: Доступ не удался.

Доступ к IP‑адресу и NodePort на узле, где расположен сервер: Доступ выполнен успешно.

Доступ к IP‑адресу и NodePort на узле, отличном от узла, где расположен сервер: Доступ не удался.

LoadBalancer Service с выделенным балансировщиком нагрузки

Приватная сеть

Тот же узел, что и pod сервиса

Доступ не удался.

Доступ не удался.

Доступ не выполнен.

Доступ не выполнен.

Другие контейнеры на том же узле, что и service pod.

Доступ не выполнен.

Доступ не выполнен.

Доступ не выполнен.

Доступ не выполнен.

Служба шлюза DNAT.

Публичная сеть.

Тот же узел, что и service pod.

Доступ не выполнен.

Доступ не выполнен.

Доступ не выполнен.

Доступ не выполнен.

Разные узлы от service pod.

Доступ не выполнен.

Доступ не выполнен.

Доступ не выполнен.

Доступ не выполнен.

Другие контейнеры на том же узле, что и service pod.

Доступ не удался.

Доступ не удался.

Доступ не удался.

Доступ не удался.

Другие контейнеры на разных узлах от сервисного pod

Доступ не удался.

Доступ не удался.

Доступ не удался.

Доступ не удался.

Служба LoadBalancer, использующая выделенный балансировщик нагрузки (Local) для взаимосвязи с NGINX Ingress Controller

Приватная сеть

Тот же узел, что и pod cceaddon-nginx-ingress-controller

Доступ не удался.

Доступ не удался.

Доступ не удался.

Доступ не удался.

Другие контейнеры на том же узле, что и pod cceaddon-nginx-ingress-controller

Доступ не удался.

Доступ не удался.

Доступ не удался.

Доступ не удался.

Для решения этой проблемы можно использовать следующие методы:

  • (Рекомендуется) В кластере используйте службу ClusterIP или доменное имя службы для доступа.
  • Установите externalTrafficPolicy службы на Кластер, что означает привязку службы на уровне кластера. Обратите внимание, что это влияет на постоянство исходного адреса.
    apiVersion: v1
    kind: Service
    metadata:
    annotations:
    kubernetes.io/elb.class: union
    kubernetes.io/elb.autocreate: '{"type":"public","bandwidth_name":"cce-bandwidth","bandwidth_chargemode":"bandwidth","bandwidth_size":5,"bandwidth_sharetype":"PER","eip_type":"5_bgp","name":"james"}'
    labels:
    app: nginx
    name: nginx
    spec:
    externalTrafficPolicy: Cluster
    ports:
    - name: service0
    port: 80
    protocol: TCP
    targetPort: 80
    selector:
    app: nginx
    type: LoadBalancer
  • Используя функцию pass-through службы, kube-proxy обходится, когда для доступа используется адрес ELB. Сначала обращаются к балансировщику нагрузки ELB, затем к рабочей нагрузке. Для получения подробностей см. Настройка сетевого pass-through для службы LoadBalancer.
    Note
    • В стандартном кластере CCE после настройки passthrough‑сетей для выделенного балансировщика нагрузки приватный IP‑адрес балансировщика нельзя получить с узла, где находится pod нагрузки, или из других контейнеров на том же узле
    • Passthrough networking не поддерживается для кластеров версии и более ранних
    • В режиме сети IPVS настройки passthrough служб, подключенных к одному и тому же балансировщику нагрузки, должны быть одинаковыми
    • Если используется привязанность службы уровня узла (local), kubernetes.io/elb.pass-through автоматически устанавливается в onlyLocal для включения pass-through.
    apiVersion: v1
    kind: Service
    metadata:
    annotations:
    kubernetes.io/elb.pass-through: "true"
    kubernetes.io/elb.class: union
    kubernetes.io/elb.autocreate: '{"type":"public","bandwidth_name":"cce-bandwidth","bandwidth_chargemode":"bandwidth","bandwidth_size":5,"bandwidth_sharetype":"PER","eip_type":"5_bgp","name":"james"}'
    labels:
    app: nginx
    name: nginx
    spec:
    externalTrafficPolicy: Local
    ports:
    - name: service0
    port: 80
    protocol: TCP
    targetPort: 80
    selector:
    app: nginx
    type: LoadBalancer