Как мне настроить доступ к нескольким узлам с помощью одной службы в кубернетах?
Я пытаюсь настроить доступ к модулям на нескольких узлах с помощью одного Service yaml. Все стручки имеют одинаковые ярлыки (скажем,label:app
), но распределены между несколькими узлами, а не на одном узле.
Насколько мне известно, я могу настроить службу для перенаправления доступа к модулю через NodePort, например:
spec:
type: NodePort
selector:
label:app
ports:
targetPort: 5000
nodePort: 30000
где доступ к порту 30000 на узле перенаправляет на порт 5000 на модуле.
Если у меня есть модули на нескольких узлах, есть ли способ, которым клиент может получить доступ к одной конечной точке, например к самой Службе, чтобы получить любой модуль в циклическом режиме? Или клиенту нужно получить доступ к набору модулей на определенном узле, используя IP-адрес этого узла, как вxx.xx.xx.xx:30000
?
2 ответа
Хотя LoadBalancer - безусловно рекомендуемое решение (особенно в облачной среде), стоит отметить, что NodePort также имеет возможности балансировки нагрузки.
Тот факт, что вы получаете доступ к своему NodePort
Обслуживание на конкретном узле не означает, что вы можете получить доступ только таким образом Pods
которые были запланированы на этом конкретном узле.
Как вы можете прочитать в NodePort
Услуги по спецификации:
Каждый узел передает этот порт (один и тот же номер порта на каждом узле) в ваш
Service
.
Итак, получив доступ к порту 30080
на одном конкретном узле ваш запрос не идет напрямую на какой-то случайный Pod
, запланированный на этом узле. Он проксируется наService
объект, который является абстракцией, охватывающей все узлы. И это, наверное, ключевой момент здесь, поскольку вашNodePort
Сервис никаким образом не привязан к узлу, IP-адрес которого вы используете для доступа к своим модулям.
Следовательно NodePort
Сервис может направлять клиентские запросы ко всем подам в кластере, используя простой алгоритм циклического перебора.
Вы можете легко проверить это, используя следующие Deployment
:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
initContainers:
- name: init-myservice
image: nginx:1.14.2
command: ['sh', '-c', "echo $MY_NODE_NAME > /usr/share/nginx/html/index.html"]
env:
- name: MY_NODE_NAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
volumeMounts:
- mountPath: /usr/share/nginx/html
name: cache-volume
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
volumeMounts:
- mountPath: /usr/share/nginx/html
name: cache-volume
volumes:
- name: cache-volume
emptyDir: {}
Это позволит вам проверить, на какой узел будет направлен ваш HTTP-запрос. Вам может потребоваться немного масштабировать этоDeployment
чтобы убедиться, что используются все узлы:
kubectl scale deployment nginx-deployment --replicas=9
Затем убедитесь, что ваши поды запланированы на разных узлах:
kubectl get pods -o wide
Перечислите все свои узлы:
kubectl get nodes -o wide
и выберите IP-адрес узла, который вы хотите использовать для доступа к своим модулям.
Теперь вы можете выставить Deployment
запустив:
kubectl expose deployment nginx-deployment --type NodePort --port 80 --target-port 80
или если вы хотите указать номер порта самостоятельно, например, как 30080
, примените следующие NodePort
Определение услуги как kubectl expose
не позволяет указать точный nodePort
ценность:
apiVersion: v1
kind: Service
metadata:
name: nginx-deployment
spec:
type: NodePort
selector:
app: nginx
ports:
- port: 80
targetPort: 80
nodePort: 30080
Затем попробуйте получить доступ к своим модулям через NodePort
Сервис с использованием IP ранее выбранного узла. Возможно, вам придется попробовать как обычный, так и частный режим / режим инкогнито или даже другой браузер (простое обновление может не работать), но в конечном итоге вы увидите, что разные запросы попадают в модули, запланированные на разных узлах.
Имейте в виду, что если вы решите использовать NodePort
вы не сможете использовать хорошо известные порты. На самом деле это может быть даже возможно, поскольку вы можете изменить диапазон портов по умолчанию (30000-32767
) на что-то вроде 1-1024
в конфигурации kube-apiserver с помощью--service-node-port-range
вариант, но его не рекомендуется, так как это может привести к некоторым неожиданным проблемам.
Если вы ищете единую точку входа в службу приложения и она работает в облачной инфраструктуре, вы можете использовать службу балансировки нагрузки (вместо порта узла), которая назначит внешний IP-адрес для вашей службы, который можно использовать для доступа к вашей службе из внешняя система.
spec:
ports:
- name: httpsPort
port: 443
protocol: TCP
targetPort: 443
selector:
label: app
type: LoadBalancer
Если у вас есть несколько сервисов в одном кластере, к которым необходимо получить доступ из внешней системы, вы можете использовать Ingress.
Спасибо Кируба