Практически все знают, что такое Kubernetes Service, но не все могут быть в курсе, что такое Endpoint, так как обычно он работает “за кулисами”, и мы его не видим, аналогично тому, как мы пользуемся Deployment, но редко видим ReplicaSet-ы.
Содержание
Kubernetes Service
Итак, Service – это абстракция Kubernetes, которая, используя labels, выбирает поды, на которые следует перенаправлять трафик, см. Kubernetes: ClusterIP vs NodePort vs LoadBalancer, Services и Ingress — обзор, примеры и Kubernetes: Service, балансировка нагрузки, kube-proxy и iptables:
apiVersion: v1 kind: Service metadata: name: my-service spec: selector: app: MyApp ports: - protocol: TCP port: 80 targetPort: 9376
Как только в кластере появляется новый под, лейблы которого совпадают с селектором Сервиса, в данном примере app=MyApp
– Service начнёт роутить трафик на него.
Реализуется это путём добавления IP-адреса пода в список Endpoints, который используется Сервисом.
Создадим простейший пример:
--- apiVersion: v1 kind: Pod metadata: name: nginx-pod labels: app: nginx spec: containers: - name: nginx-container image: nginx ports: - name: web containerPort: 80 protocol: TCP --- apiVersion: v1 kind: Service metadata: name: nginx-svc spec: selector: app: nginx ports: - protocol: TCP port: 80 targetPort: 80
Тут создаётся под с NGINX, и для него – Сервис с дефолтным типом ClusterIP
.
Создаём их:
Проверяем Сервис:
Kubernetes Endpoints
Теперь рассмотрим этот Сервис детальнее:
В конце мы собственно и видим Endpoints этого сервиса – IP-адрес пода.
Проверим под:
Вот и наш IP.
А теперь проверим ендпоинты, которые являются отдельными объектами API-сервера – Endpoints, и с которыми можно работать так же, как с Services и Pods:
Если мы добавим ещё один под с той же лейблой, в Deployment или просто опишем вторым объектом – он будет добавлен в этот же Ендпоинт:
--- apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deploy labels: app: nginx spec: replicas: 2 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx-container image: nginx ports: - name: web containerPort: 80 protocol: TCP --- apiVersion: v1 kind: Service metadata: name: nginx-svc spec: selector: app: nginx ports: - protocol: TCP port: 80 targetPort: 80
Создаём:
И проверяем ендпоинт:
Тут у нас остался старый под 10.21.56.143:80, и появилось два новых, которые указаны в replicas
нашего деплоймента.
Найдём из используя --selector
– аналогично Сервис ищет поды для добавления в Ендпоинты:
Custom Endpoint
Кроме ендпоинтов подов, мы можем создать кастомный ендпоинт, который будет слать трафик на любой ресурс.
К примеру, опишем такой сервис:
kind: Service apiVersion: v1 metadata: name: external-svc spec: ports: - name: web protocol: TCP port: 80 targetPort: 80
Обратите внимание, что тут мы не описываем selector
.
К нему описываем Endpoints:
kind: Endpoints apiVersion: v1 metadata: name: external-svc subsets: - addresses: - ip: 139.59.205.180 ports: - port: 80 name: web
Тут:
name
: должно быть таким же, как у Serviceaddresses
: адрес, на который шлём трафик, в этом примере – IP адрес сервера в DigitalOcean, на котором работает блог rtfm.co.ua, можно указать несколько – тогда Service будет выполнять load balancing между ними, как описано в Kubernetes: Service, балансировка нагрузки, kube-proxy и iptablesports.port
иports.name
такие же, как у Service
Создаём:
Проверяем Service и его Endpoints:
Запускаем для проверки под:
Устанавливаем в нём curl
:
И проверяем по имени сервиса:
Или по его FQDN:
externalName
Другой вариант для доступа к внешним ресурсам – использовать Service с типом externalName
:
--- apiVersion: v1 kind: Service metadata: name: rtfm-service spec: ports: - port: 80 type: ExternalName externalName: rtfm.co.ua
Применяем, и проверяем:
Готово.