Пространство имен белого списка "kube-system" с использованием NetworkPolicy
У меня есть мультитенантный кластер, где мультитенантность достигается через пространства имен. Каждый арендатор имеет свое собственное пространство имен. Стручки от арендатора не могут общаться с другими арендаторами. Тем не менее, некоторые модули в каждом арендаторе должны предоставлять доступ к Интернету, используя Ingress.
Это я, как далеко я получил (я использую Калико):
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: tenant1-isolate-namespace
namespace: tenant1
spec:
policyTypes:
- Ingress
podSelector: {} # Select all pods in this namespace
ingress:
- from:
- namespaceSelector:
matchLabels:
name: tenant1 # white list current namespace
Развернуто для каждого пространства имен (tenant1
, tenant2
,...), это ограничивает связь между модулями в их пространстве имен. Тем не менее, это предотвращает стручки от kube-system
пространство имен для общения со стручками в этом пространстве имен.
Тем не менее kube-system
Пространство имен не имеет никаких меток по умолчанию, поэтому я не могу специально указать белый список этого пространства имен.
Я нашел (грязный) обходной путь для этой проблемы, вручную назначив ему метку:
kubectl label namespace/kube-system permission=talk-to-all
И добавление правила белого списка в сетевую политику:
...
- from:
- namespaceSelector:
matchLabels:
permission: talk-to-all # allow namespaces that have the "talk-to-all privilege"
Есть ли лучшее решение, не давая вручную kube-system
этикетка?
Редактировать: я пытался дополнительно добавить правило "ИЛИ", чтобы разрешить общение с модулями с меткой "app=nginx-ingress", но без удачи:
- from
...
- podSelector:
matchLabels:
app: nginx-ingress # Allow pods that have the app=nginx-ingress label
4 ответа
NamespaceSelector предназначен для соответствия пространствам имен только по меткам. Нет возможности выбрать пространство имен по имени.
PodSelector может выбирать модули только в одном пространстве имен с объектом NetworkPolicy. Для объектов, расположенных в разных пространствах имен, возможен только выбор всего пространства имен.
Вот пример реализации Политики сети Kubernetes:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: test-network-policy
namespace: default
spec:
podSelector:
matchLabels:
role: db
policyTypes:
- Ingress
- Egress
ingress:
- from:
- ipBlock:
cidr: 172.17.0.0/16
except:
- 172.17.1.0/24
- namespaceSelector:
matchLabels:
project: myproject
- podSelector:
matchLabels:
role: frontend
ports:
- protocol: TCP
port: 6379
egress:
- to:
- ipBlock:
cidr: 10.0.0.0/24
ports:
- protocol: TCP
port: 5978
Перейдите по этой ссылке, чтобы прочитать хорошее объяснение всей концепции сетевой политики, или по этой ссылке, чтобы посмотреть лекцию.
apiVersion: projectcalico.org/v3
Calico API дает вам больше возможностей для написания правил NetworkPolicy, так что в какой-то момент вы можете достичь своей цели с меньшими усилиями и умопомрачительным умом.
Например, используя реализацию сетевой политики Calico, вы можете:
- установить действие для правила (Allow, Deny, Log, Pass),
- использовать отрицательное соответствие (протокол, notProtocol, селектор, notSelector),
- применить более сложные селекторы меток (имеет (k), k не в {'v1', 'v2'}),
- объединить селекторы с оператором &&,
- использовать диапазон портов (порты: [8080, "1234:5678", "named-port"]),
- сопоставлять стручки в других пространствах имен.
Но, тем не менее, вы можете сопоставлять пространства имен только по меткам.
Подумайте о прочтении документации Calico для деталей.
Вот пример реализации Сетевой Политики Calico:
apiVersion: projectcalico.org/v3
kind: NetworkPolicy
metadata:
name: allow-tcp-6379
namespace: production
spec:
selector: role == 'database'
types:
- Ingress
- Egress
ingress:
- action: Allow
protocol: TCP
source:
selector: role == 'frontend'
destination:
ports:
- 6379
egress:
- action: Allow
В самом деле, tenant1
стручкам потребуется доступ к kube-dns
в kube-system
пространство имен конкретно.
Один подход без необходимости kube-system
Пространство имен, которое будет помечено, является следующей политикой. Хотя kube-dns
может быть в любом пространстве имен с таким подходом, поэтому он может не подойти для вас.
---
# Default deny all ingress & egress policy, except allow kube-dns
# All traffic except this must be explicity allowed.
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: default-deny-all-except-kube-dns
namespace: tenant1
spec:
podSelector: {}
egress:
- to:
- podSelector:
matchLabels:
k8s-app: kube-dns
- ports:
- protocol: UDP
port: 53
policyTypes:
- Ingress
- Egress
Затем вам также потребуется "разрешить все в рамках политики пространства имен" следующим образом:
---
# Allow intra namespace traffic for development purposes only.
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: allow-intra-namespace
namespace: tenant1
spec:
podSelector:
matchLabels:
ingress:
- from:
- podSelector: {}
egress:
- to:
- podSelector: {}
policyTypes:
- Ingress
- Egress
Наконец, вы захотите добавить определенные политики, такие как правило входа. Было бы лучше заменить allow-intra-namespace
политика с конкретными правилами, чтобы удовлетворить отдельные стручки, которые ваши tenant1
может сделать.
Они были адаптированы с этого сайта: https://github.com/ahmetb/kubernetes-network-policy-recipes
Я на k3os с фланелевым CNI по умолчанию. Он имеет метку по умолчанию в пространстве имен kube-system:
$ kubectl describe ns kube-system
Name: kube-system
Labels: kubernetes.io/metadata.name=kube-system
Annotations: <none>
Status: Active
Это работает для меня:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: kube-system
Вот мой полный yaml, который разрешает весь внешний трафик и kube-dns в пространстве имен kube-system для выхода:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-egress
spec:
podSelector: {}
policyTypes:
- Egress
egress:
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: kube-system
podSelector:
matchLabels:
k8s-app: kube-dns
ports:
- port: 53
protocol: UDP
- to:
- ipBlock:
cidr: 0.0.0.0/0
except:
- 10.0.0.0/8
- 172.16.0.0/12
- 192.168.0.0/16
Если я правильно понял, вы используете бязь. Просто используйте их пример о том, как реализовать default-deny, не нарушая связи kube-dns. Найдено здесь
apiVersion: projectcalico.org/v3
kind: GlobalNetworkPolicy
metadata:
name: deny-app-policy
spec:
namespaceSelector: has(projectcalico.org/name) && projectcalico.org/name not in {"kube-system", "calico-system"}
types:
- Ingress
- Egress
egress:
# allow all namespaces to communicate to DNS pods
- action: Allow
protocol: UDP
destination:
selector: 'k8s-app == "kube-dns"'
ports:
- 53