Недавно мне пришлось обновить сетевую политику для одной из наших служб. Перед внедрением изменений я захотел протестировать их с помощью Minikube, чтобы удостовериться, что ничего не испорчу.
В этой заметке описаны шаги, которые были мною выполнены для проведения теста.
Прежде чем мы начнем, давайте определим несколько терминов.
Что такое сетевая политика?
Сетевые политики — это ориентированная на приложения конструкция, которая позволяет вам определять, как поду разрешено взаимодействовать с различными сетевыми "сущностями" через сеть. Сетевые политики применяются к соединению с подом на одном или обоих концах и не относятся к другим соединениям.
В чем разница между Ingress и Egress?
Egress относится к трафику, исходящему из пода/сети/сущности.
Ingress относится к трафику, входящему в под/сеть/сущность.
Что мы тестируем?
Служба, которую я хотел обновить, имела NetworkPolicy, запрещающую подключение ко всему, что находится за пределами ее пространства имен. Обновление заключалось в разрешении соединения с еще одним пространством имен, на определенном порту; чтобы Prometheus мог скрейпить метрики.
Настройка minikube
Запустите minikube с сетевым плагином
cni
и calico cni:
minikube start --network-plugin=cni --cni=calico
Проверьте установку Calico:
kubectl get pods -n kube-system -l k8s-app=calico-node
NAME READY STATUS RESTARTS AGE
calico-node-9ln25 1/1 Running 0 54s
Проверка работы сетевых политик
Запустите nginx Под с метками
app=web
и раскройте его на порту 80:
kubectl run web --image=nginx --labels="app=web" --expose --port=80
Дождитесь, пока под будет запущен:
kubectl get pods web
NAME READY STATUS RESTARTS AGE
web 1/1 Running 0 2m19s
Запустите временный Под и сделайте запрос к сервису
web
:
kubectl run --rm -i -t --image=alpine test-$RANDOM -- sh
/ # wget -qO- http://web
Сохраните следующий манифест в
web-deny-all.yaml
, затем примените к кластеру:
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: web-deny-all
spec:
podSelector:
matchLabels:
app: web
ingress: []
Снова запустите тестовый контейнер и попробуйте сделать запрос к веб:
kubectl run --rm -i -t --image=alpine test-$RANDOM -- sh
/ # wget -qO- --timeout=2 http://web
Если все работает как надо, вы должны получить сообщение wget: download timed out error
:
Очистка:
kubectl delete pod web
kubectl delete service web
kubectl delete networkpolicy web-deny-all
Настройка теста
Ранее я упоминал, что обновление, которое я тестировал, должно было перейти от политики NetworkPolicy, которая запрещает соединение с чем-либо за пределами своего пространства имен => разрешить соединение с еще одним пространством имен, на определенном порту, без разрыва соединения внутри пространства имен.
Запретить весь трафик из других пространств имен
Запуск веб-службы в пространстве имен
default
:
kubectl run web --namespace=default --image=nginx --labels="app=web" --expose --port=80
Сохраните следующий манифест в
deny-from-other-namespaces.yaml
и примените к кластеру
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
namespace: default
name: deny-from-other-namespaces
spec:
podSelector:
matchLabels:
ingress:
- from:
- podSelector: {}
kubectl apply -f /tmp/deny-from-other-namespaces.yaml
networkpolicy.networking.k8s.io/deny-from-other-namespaces created
Создайте пространство имен
foo
:
kubectl create namespace foo
Запросите
web
сервис из пространства именfoo
:
kubectl run test-$RANDOM --namespace=foo --rm -i -t --image=alpine -- sh
/ # wget -qO- --timeout=2 http://web.default
Если все работает как надо, вы должны получить сообщение wget: download timed out error
.
Запросите
web
сервис из пространства именdefault
:
kubectl run test-$RANDOM --namespace=default --rm -i -t --image=alpine -- sh
/ # wget -qO- --timeout=2 http://web.default
Если все работает как надо, вы должны были получить HTML-ответ, вместо таймаута.
Очистка:
kubectl delete networkpolicy deny-from-other-namespaces
Разрешение доступа из пространства имен foo на определенном порту
Теперь у нас есть локальная среда, настроенная для репликации того, что сейчас развернуто, и мы можем протестировать наши новые изменения.
Создайте пространство имен
bar
:
kubectl create namespace bar
Создайте метку для пространства имен
bar
:
kubectl label namespace/bar purpose=allow
Запустите piserver под, называемый
apiserver
:
kubectl run piserver --image=ahmet/app-on-two-ports --labels="app=apiserver"
Предоставьте под как сервис, маппируя
8000
с8001
, а5000
с5001
:
kubectl create service clusterip apiserver \
--tcp 8001:8000 \
--tcp 5001:5000
Сохраните следующий манифест в
allow-from-bar.yaml
и примените к кластеру:
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
namespace: default
name: allow-from-bar
spec:
podSelector:
matchLabels:
app: apiserver
ingress:
- from:
- podSelector: {}
- from:
- namespaceSelector:
matchLabels:
purpose: "allow"
ports:
- port: 5000
protocol: TCP
Запросите службу
apiserver
из пространства именbar
(доступ должен быть предоставлен к порту 5000, но не 8000):
kubectl run test-$RANDOM --namespace=bar --rm -i -t --image=alpine -- sh
/ # wget -qO- --timeout=2 http://apiserver.default:8001
/ # wget -qO- --timeout=2 http://apiserver.default:5001/metrics
Если все работает как надо, первый запрос к http://apiserver.default:8001
должен вернуть ошибку таймаута, а второй запрос к http://apiserver.default:5001/metrics
должен вернуть список метрик.
Запросите
web
сервис из пространства именfoo
(доступ не должен предоставляться ни к одному из портов):
kubectl run test-$RANDOM --namespace=foo --rm -i -t --image=alpine -- sh
/ # wget -qO- --timeout=2 http://apiserver.default:8001
/ # wget -qO- --timeout=2 http://apiserver.default:5001/metrics
Если все работает как надо, оба запроса должны вернуть ошибку тайм-аута.
Запрос
web
сервиса из пространства именdefault
(доступ должен быть предоставлен к портам 5000 и 8000).
kubectl run test-$RANDOM --namespace=default --rm -i -t --image=alpine -- sh
/ # wget -qO- --timeout=2 http://apiserver.default:8001
/ # wget -qO- --timeout=2 http://apiserver.default:5001/metrics
Если все работает как надо, первый запрос к http://apiserver.default:8001
должен вернуть Hello from HTTP server
, а второй запрос к http://apiserver.default:5001/metrics
должен вернуть список метрик.
Это доказывает, что обновление NetworkPolicy
работает так, как ожидалось.
Всех желающих приглашаем на открытое занятие «Из каких частей состоит Kubernetes». На вебинаре мы узнаем, из каких основных и вспомогательных компонентов состоит kubernetes кластер, рассмотрим, за что отвечает каждый из них и как они взаимодействуют между собой.