Включение внешних сервисов в контекст Kubernetes
Речь о создании объекта Service, за которым стоит не под, а внешний по отношению к кластеру Kubernetes сервер.
Приём позволяет сделать по крайней мере две полезные вещи:
подключить внешний сервис к Prometheus с использованием Kubernetes SD;
создать для внешнего сервиса запись во внутреннем DNS Kubernetes.
Собственно приём заключается в создании headless сервиса без селектора и соответствующего объекта Endpoints.
Отсутствие селектора отключает управление объектом Endpoints, связанным с сервисом. Значение clusterIP: None отключает создание сервисного IP. Как следствие, внутренняя запись DNS для сервиса будет указывать сразу на адреса конечных точек входа и трафик будет направляться на конечный сервер без трансляции адресов назначения.
Пусть у нас есть кластер Kubernetes, в котором установлен Prometheus со включенным Kubernetes SD. Мы установили внешний сервер Redis с адресом 10.1.0.27, на котором подняты node_exporter, собственно Redis и redis_exporter.
Для подключения сервера к Prometheus создадим следующие ресурсы:
---
apiVersion: v1
kind: Service
metadata:
name: external-redis-exporter
labels:
to-see: in-prometheus
annotations:
prometheus.io/scrape: "true"
spec:
clusterIP: None
type: ClusterIP
---
apiVersion: v1
kind: Endpoints
metadata:
name: external-redis-exporter
subsets:
- addresses:
- ip: 10.1.0.27
ports:
- name: node-exporter
port: 9100
protocol: TCP
- name: redis-exporter
port: 9121
protocol: TCP
Объект Endpoints связывается с соответствующим Service по metadata.name.
Заглянув в Status -> Targets в интерфейсе Prometheus, наблюдаем в списке kubernetes-service-endpoints
Обратите внимание, что, хотя адреса для мониторинга берутся из объекта Endpoints, метки для метрик берутся из Service.
Пример приведён в синтетическом виде. В реальности для такой инсталляции Redis лучше на сервер поставить только node_exporter, а redis_exporter установить в Kubernetes. При этом для Redis можно создать отдельный Service, после чего к нему можно будет подключаться, используя внутреннее имя DNS.
Список объектов будет выглядеть так:
---
apiVersion: v1
kind: Service
metadata:
name: external-redis
spec:
clusterIP: None
type: ClusterIP
---
apiVersion: v1
kind: Endpoints
metadata:
name: external-redis
subsets:
- addresses:
- ip: 10.1.0.27
ports:
- name: redis
port: 6379
protocol: TCP
---
apiVersion: v1
kind: Service
metadata:
name: external-redis-node
spec:
clusterIP: None
type: ClusterIP
---
apiVersion: v1
kind: Endpoints
metadata:
name: external-redis-node
subsets:
- addresses:
- ip: 10.1.0.27
ports:
- name: node-exporter
port: 9100
protocol: TCP
redis_exporter устанавливается и настраивается отдельно, при этом в качестве адреса сервера Redis теперь можно использовать external-redis:6379 (в том же namespace, что и Service). Имя будет разрешаться в адрес, указанный в Endpoints.
И ещё о профитах. Продолжая рассматривать пример с Redis, можно предположить три возможных вида инсталляции сервера:
изначальный пример с Redis на отдельном внешнем сервере,
Redis, установленный внутри Kubernetes,
облачное managed решение.
Предложенная схема с выделенным Service и redis_exporter, установленным в Kubernetes, позволит менять реализации сервера, не меняя схемы настроек клиентов.