Недавно мне пришлось обновить сетевую политику для одной из наших служб. Перед внедрением изменений я захотел протестировать их с помощью 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 кластер, рассмотрим, за что отвечает каждый из них и как они взаимодействуют между собой.

Комментарии (0)