Включение внешних сервисов в контекст 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, позволит менять реализации сервера, не меняя схемы настроек клиентов.