Сервис типа LoadBalancer по умолчанию принимает запросы с любых адресов, для которых настроена маршрутизация до внешнего IP балансировщика. Чтобы ограничить доступ к приложению определёнными клиентами, в поле spec.loadBalancerSourceRanges сервиса задаётся список разрешённых IP-адресов или подсетей в формате CIDR.
Балансировщик пробрасывает к подам только трафик с разрешённых адресов. Соединения с остальных адресов отбрасываются на уровне сети: приложение их не видит, а клиент вместо ответа от приложения получает таймаут соединения.
Ограничим доступ к сервису LoadBalancer одним IP-адресом, проверим работу ограничения с двух внешних виртуальных машин и снимем его.
Перед началом работы вам понадобится:
Кластер Kubernetes в NetAngels
Установленная утилита kubectl с настроенным доступом (конфигурационный файл кластера)
Две внешние виртуальные машины с публичными IP-адресами: адрес одной будет добавлен в список разрешённых, со второй будет проверяться, что доступ с неразрешённого адреса запрещён
Запустим веб-сервер nginx в двух экземплярах и создадим для него сервис типа LoadBalancer без ограничений:
kubectl apply -f - <<EOF
---
apiVersion: v1
kind: Namespace
metadata:
name: nginx
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
namespace: nginx
labels:
app: nginx
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx
namespace: nginx
spec:
selector:
app: nginx
ports:
- port: 80
targetPort: 80
protocol: TCP
type: LoadBalancer
externalTrafficPolicy: Local
EOF
namespace/nginx created
deployment.apps/nginx created
service/nginx created
Проверим готовность сервиса командой describe — когда балансировщику назначат внешний адрес, он появится в поле LoadBalancer Ingress:
kubectl describe service nginx -n nginx
Name: nginx
Namespace: nginx
Labels: <none>
Annotations: <none>
Selector: app=nginx
Type: LoadBalancer
IP Family Policy: SingleStack
IP Families: IPv4
IP: 10.96.38.1
IPs: 10.96.38.1
LoadBalancer Ingress: 80.87.99.128 (VIP)
Port: <unset> 80/TCP
TargetPort: 80/TCP
NodePort: <unset> 30243/TCP
Endpoints: 10.244.226.80:80,10.244.226.81:80
Session Affinity: None
External Traffic Policy: Local
Internal Traffic Policy: Cluster
HealthCheck NodePort: 30918
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal EnsuringLoadBalancer 15s service-controller Ensuring load balancer
Normal EnsuredLoadBalancer 8s service-controller Ensured load balancer
Внешний адрес 80.87.99.128 назначен, сервис готов.
Отметим, что IP-адрес 80.87.99.128 это адрес выданный балансировщику в демонстрационном кластере. При выполнении инструкций из статьи замените его на адрес балансировщика выданный вашему сервису, а адреса тестовых виртуальных машин — на адреса своих виртуальных машин.
Проверим также статус подов и сервиса:
kubectl get pods,svc -n nginx
NAME READY STATUS RESTARTS AGE
pod/nginx-96b9d695-65g5h 1/1 Running 0 16s
pod/nginx-96b9d695-m9pvk 1/1 Running 0 16s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/nginx LoadBalancer 10.96.38.1 80.87.99.128 80:30243/TCP 16s
Запустим curl с первой виртуальной машины:
curl -s http://80.87.99.128/
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, nginx is successfully installed and working.
Further configuration is required for the web server, reverse proxy,
API gateway, load balancer, content cache, or other features.</p>
<p>For online documentation and support please refer to
<a href="https://nginx.org/">nginx.org</a>.<br/>
To engage with the community please visit
<a href="https://community.nginx.org/">community.nginx.org</a>.<br/>
For enterprise grade support, professional services, additional
security features and capabilities please refer to
<a href="https://f5.com/nginx">f5.com/nginx</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
Пока поле loadBalancerSourceRanges не задано, доступ открыт с любого адреса: со второй виртуальной машины будет получена та же страница.
Добавим в сервис поле loadBalancerSourceRanges со списком разрешённых источников. Значения задаются в формате CIDR: <адрес>/<маска>. Укажем адрес первой виртуальной машины:
kubectl -n nginx patch service nginx -p '{"spec": {"loadBalancerSourceRanges": ["<IP первой виртуальной машины>/32"]}}'
service/nginx patched
Поле можно задать и сразу в манифесте сервиса — тогда балансировщик будет создан с ограничениями с самого начала.
Изменения на балансировщике применяются асинхронно. При начале изменения в событиях сервиса появляется Ensuring load balancer, а после применения новых настроек — Ensured load balancer. Состояние проверяем командой describe:
kubectl describe service nginx -n nginx | tail -9
External Traffic Policy: Local
Internal Traffic Policy: Cluster
HealthCheck NodePort: 30918
LoadBalancer Source Ranges: 80.87.106.224/32
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal EnsuringLoadBalancer 29s (x2 over 110s) service-controller Ensuring load balancer
Normal EnsuredLoadBalancer 28s (x2 over 103s) service-controller Ensured load balancer
Событие Ensured load balancer говорит о том, что новые настройки на балансировщике применены, и можно переходить к проверке.
Два момента, которые важно учитывать:
Ограничение действует только для обращения через внешний адрес балансировщика. Трафик, который идёт в обход балансировщика — например, по ClusterIP внутри кластера, — не затрагивается.
Соединения с неразрешённых адресов отбрасываются балансировщиком: клиенту не приходит ни ответа от приложения, ни ошибки HTTP — он видит лишь таймаут соединения.
С первой виртуальной машины, чей адрес указан в loadBalancerSourceRanges, сервис по-прежнему доступен:
curl -s -o /dev/null -w '%{http_code}\n' --max-time 10 http://80.87.99.128/
200
Со второй виртуальной машины, не указанной в списке, соединение не устанавливается:
curl -sS --max-time 10 http://80.87.99.128/
curl: (28) Connection timed out after 10002 milliseconds
Балансировщик не пробрасывает трафик с неразрешённого адреса, поэтому соединение не устанавливается и curl завершает работу с ошибкой таймаута.
Уберём ограничения, установив поле в пустое значение:
kubectl -n nginx patch service nginx -p '{"spec": {"loadBalancerSourceRanges": null}}'
service/nginx patched
Поле станет пустым списком, и балансировщик снова начнёт принимать соединения со всех адресов. Дождёмся нового события Ensured load balancer в выводе kubectl describe service nginx -n nginx и проверим доступ со второй виртуальной машины:
curl -s -o /dev/null -w '%{http_code}\n' --max-time 10 http://80.87.99.128/
200
Удалим неймспейс вместе с сервисом, деплоем и подами:
kubectl delete ns nginx
namespace "nginx" deleted