Как открыть сервис кубернетов для публики без жесткого кодирования для миньона IP?
У меня есть кластер кубернетов, работающий с 2 миньонами.
В настоящее время я предоставляю услугу в 2 этапа:
- Запустить контроллер репликации и pod
- Получить minion IP (используя
kubectl get minions
) и установить его как publicIPs для Сервиса.
Какова предлагаемая практика разоблачения услуги для общественности? Мой подход кажется неправильным, потому что я жестко кодирую IP-адреса отдельных миньонов IP-ов. Он также, кажется, обходит возможности балансировки нагрузки услуг кубернетов, поскольку клиентам приходилось напрямую обращаться к службам, работающим на отдельных миньонах.
Чтобы настроить контроллер репликации и модуль, я использую:
id: frontend-controller
kind: ReplicationController
apiVersion: v1beta1
desiredState:
replicas: 2
replicaSelector:
name: frontend-pod
podTemplate:
desiredState:
manifest:
version: v1beta1
id: frontend-pod
containers:
- name: sinatra-docker-demo
image: madisn/sinatra_docker_demo
ports:
- name: http-server
containerPort: 4567
labels:
name: frontend-pod
Чтобы настроить службу (после получения minion ip-s):
kind: Service
id: frontend-service
apiVersion: v1beta1
port: 8000
containerPort: http-server
selector:
name: frontend-pod
labels:
name: frontend
publicIPs: [10.245.1.3, 10.245.1.4]
Ответы
Ответ 1
Как я уже упоминал в комментарии выше, createExternalLoadBalancer - соответствующая абстракция, которую вы ищете, но, к сожалению, она еще не реализована для всех поставщиков облачных вычислений, и в частности для бродяг, которые вы используете локально.
Один из вариантов - использовать общедоступные IP-адреса для всех миньонов в вашем кластере для всех служб, которые вы хотите отключить. Трафик, предназначенный для службы, попадет на одного из миньонов, где он будет перехвачен процессом kube-proxy и перенаправлен на модуль, который соответствует селектору меток для службы. Это может привести к дополнительному переходу по сети (если вы приземлитесь на node, который не поддерживает локальную сеть), но для приложений, которые не очень чувствительны к задержке в сети, это, вероятно, не будет заметным.
Ответ 2
Как сказал Роберт в своем ответе, это то, что происходит, но, к сожалению, пока недоступно.
В настоящее время я запускаю кластер Kubernetes в нашей сети центров обработки данных. У меня есть 1 мастер и 3 миньона, которые работают на виртуальных сайтах CentOS 7 (vcenter). То, как я справлялся с этим, - создать выделенный сервер "kube-proxy". В основном я просто запускаю службу Kube-Proxy (вместе с Flannel для сети), а затем назначая "общедоступные" IP-адреса сетевому адаптеру, подключенному к этому серверу. Когда я говорю публично, я имею в виду адреса в нашей локальной сети центров обработки данных. Затем, когда я создаю службу, к которой я хотел бы получить доступ за пределами кластера, я просто установил значение publicIPs на один из доступных IP-адресов на сервере kube-proxy. Когда кто-то или что-то пытается подключиться к этой службе извне кластера, он попадет в прокси-сервер kube, а затем будет перенаправлен на соответствующий миньон.
Хотя это может показаться работой, это на самом деле похоже на то, что я ожидал бы, когда они придумают встроенное решение этой проблемы.
Ответ 3
Если вы используете локальный кластер, я использовал для этого службу на своих узлах kubernetes, используя директиву nodeport в определении вашего сервиса, а затем объединить robin с каждым node в вашем кластере с помощью HAproxy.
Здесь то, что обнажает узел, выглядит следующим образом:
apiVersion: v1
kind: Service
metadata:
name: nginx-s
labels:
name: nginx-s
spec:
type: NodePort
ports:
# must match the port your container is on in your replication controller
- port: 80
nodePort: 30000
selector:
name: nginx-s
Примечание. Указанное значение должно находиться в пределах заданного диапазона для портов node. (по умолчанию: 30000-32767)
Это предоставляет услугу на данном узлепорта на каждом node в вашем кластере. Затем я установил отдельную машину во внутренней сети, на которой запущен haproxy, и брандмауэр, доступный снаружи по указанным узлам (узлам), которые вы хотите открыть.
Если вы посмотрите на свою таблицу nat на одном из ваших хостов, вы можете увидеть, что она делает.
[email protected]:~# kubectl create -f nginx-s.yaml
You have exposed your service on an external port on all nodes in your
cluster. If you want to expose this service to the external internet, you may
need to set up firewall rules for the service port(s) (tcp:30000) to serve traffic.
See http://releases.k8s.io/HEAD/docs/user-guide/services-firewalls.md for more details.
services/nginx-s
[email protected]:~# iptables -L -t nat
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
KUBE-PORTALS-CONTAINER all -- anywhere anywhere /* handle ClusterIPs; NOTE: this must be before the NodePort rules */
DOCKER all -- anywhere anywhere ADDRTYPE match dst-type LOCAL
KUBE-NODEPORT-CONTAINER all -- anywhere anywhere ADDRTYPE match dst-type LOCAL /* handle service NodePorts; NOTE: this must be the last rule in the chain */
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
KUBE-PORTALS-HOST all -- anywhere anywhere /* handle ClusterIPs; NOTE: this must be before the NodePort rules */
DOCKER all -- anywhere !127.0.0.0/8 ADDRTYPE match dst-type LOCAL
KUBE-NODEPORT-HOST all -- anywhere anywhere ADDRTYPE match dst-type LOCAL /* handle service NodePorts; NOTE: this must be the last rule in the chain */
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
MASQUERADE all -- 172.17.0.0/16 anywhere
Chain DOCKER (2 references)
target prot opt source destination
RETURN all -- anywhere anywhere
Chain KUBE-NODEPORT-CONTAINER (1 references)
target prot opt source destination
REDIRECT tcp -- anywhere anywhere /* default/nginx-s: */ tcp dpt:30000 redir ports 42422
Chain KUBE-NODEPORT-HOST (1 references)
target prot opt source destination
DNAT tcp -- anywhere anywhere /* default/nginx-s: */ tcp dpt:30000 to:169.55.21.75:42422
Chain KUBE-PORTALS-CONTAINER (1 references)
target prot opt source destination
REDIRECT tcp -- anywhere 192.168.3.1 /* default/kubernetes: */ tcp dpt:https redir ports 51751
REDIRECT tcp -- anywhere 192.168.3.192 /* default/nginx-s: */ tcp dpt:http redir ports 42422
Chain KUBE-PORTALS-HOST (1 references)
target prot opt source destination
DNAT tcp -- anywhere 192.168.3.1 /* default/kubernetes: */ tcp dpt:https to:169.55.21.75:51751
DNAT tcp -- anywhere 192.168.3.192 /* default/nginx-s: */ tcp dpt:http to:169.55.21.75:42422
[email protected]:~#
В частности, эта строка
DNAT tcp -- anywhere anywhere /* default/nginx-s: */ tcp dpt:30000 to:169.55.21.75:42422
И, наконец, если вы посмотрите на netstat, вы увидите, что kube-proxy прослушивает и ждет эту службу на этом порту.
[email protected]:~# netstat -tupan | grep 42422
tcp6 0 0 :::42422 :::* LISTEN 20748/kube-proxy
[email protected]:~#
Kube-proxy будет прослушивать порт для каждой службы и выполнять трансляцию сетевых адресов в вашу виртуальную подсеть, в которой находятся ваши контейнеры. (Я думаю?) Я использовал фланель.
Для двух кластеров node эта конфигурация HAproxy может выглядеть примерно так:
listen sampleservice 0.0.0.0:80
mode http
stats enable
balance roundrobin
option httpclose
option forwardfor
server noname 10.120.216.196:30000 check
server noname 10.155.236.122:30000 check
option httpchk HEAD /index.html HTTP/1.0
И ваш сервис теперь доступен на порту 80 через HAproxy. Если какой-либо из ваших узлов опустится, контейнеры будут перемещены в другой node благодаря контроллерам репликации, а HAproxy будет перенаправляться только на ваши живые узлы.
Мне любопытно, какие методы использовали другие, что именно я придумал. Обычно я не отправляю сообщение о переполнении стека, поэтому извиняюсь, если я не следую соглашениям или правильному форматированию.
Ответ 4
Это для MrE. Мне не хватило места в области комментариев, чтобы опубликовать этот ответ, поэтому мне пришлось создать еще один ответ. Надеюсь, это поможет:
Мы действительно отошли от Кубернеса после публикации этого ответа. Если я правильно помню, хотя все, что мне действительно нужно было сделать, это запустить исполняемый файл kube-proxy на специализированной виртуальной машине CentOS. Вот что я сделал:
Сначала я удалил Firewalld и поместил iptables на место. Kube-proxy полагается на iptables для обработки NAT и перенаправления.
Во-вторых, вам необходимо установить фланель, чтобы вы могли иметь адаптер моста в той же сети, что и службы Docker, работающие на ваших миньонах.
Затем я назначил несколько IP-адресов локальному сетевому адаптеру, установленному на компьютере. Это будут IP-адреса, которые вы можете использовать при настройке службы. Это будут адреса, доступные вне вашего кластера.
Как только все будет позабочено, вы можете запустить службу прокси. Он подключится к Мастеру и возьмет IP-адрес для сети фланелевых мостов. Затем он будет синхронизировать все правила IPtables, и вы должны быть настроены. Каждый раз, когда добавляется новая служба, она создает правила прокси и реплицирует эти правила для всех миньонов (и вашего прокси). Пока вы указываете IP-адрес, доступный на вашем прокси-сервере, этот прокси-сервер пересылает весь трафик для этого IP-адреса на соответствующий миньон.
Надеюсь, это немного более ясно. Помните, хотя я не был частью проекта Kubernetes около 6 месяцев, поэтому я не уверен, что изменилось с тех пор, как я ушел. У них может даже быть функция, которая справляется с такими вещами. Если не надеюсь, это поможет вам позаботиться о нем.
Ответ 5
Вы можете использовать Ingress ресурс, чтобы внешние подключения извне кластера Kubernetes могли получить доступ к службам кластера.
Предполагая, что у вас уже установлен модуль Pod, теперь вам нужен ресурс службы, например:
apiVersion: v1
kind: Service
metadata:
name: frontend-service
labels:
tier: frontend
spec:
type: ClusterIP
selector:
name: frontend-pod
ports:
- name: http
protocol: TCP
# the port that will be exposed by this service
port: 8000
# port in a docker container; defaults to what "port" has set
targetPort: 8000
И вам нужен ресурс Ingress:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: frontend-ingress
spec:
rules:
- host: foo.bar.com
http:
paths:
- path: /
backend:
serviceName: frontend-service
# the targetPort from service (the port inside a container)
servicePort: 8000
Чтобы иметь возможность использовать ресурсы Ingress, вам понадобится