如何阻止来自 kubernetes 中其他命名空间的 db pod 和服务(DNS)的流量?
How to block traffic to db pod & service (DNS) from other namespaces in kubernates?
我在 2 个命名空间 tenant1-namespace,tenant2-namespace 中创建了 2 个租户 (tenant1,tenant2)
每个租户都有 db pod 及其服务
如何隔离 db pods/service 即如何限制 pod/service 从他的命名空间访问其他租户 db pods ?
我已经为每个租户使用了服务帐户并应用了网络策略,以便隔离命名空间。
kubectl get svc --all-namespaces
tenant1-namespace grafana-app LoadBalancer 10.64.7.233 104.x.x.x 3000:31271/TCP 92m
tenant1-namespace postgres-app NodePort 10.64.2.80 <none> 5432:31679/TCP 92m
tenant2-namespace grafana-app LoadBalancer 10.64.14.38 35.x.x.x 3000:32226/TCP 92m
tenant2-namespace postgres-app NodePort 10.64.2.143 <none> 5432:31912/TCP 92m
所以
我想限制 grafana-app 只在他的命名空间中使用他的 postgres 数据库,而不是在其他命名空间中。
但问题是使用 DNS 限定服务名称 (app-name.namespace-name.svc.cluster.local
)
它允许相互访问 db pods(命名空间 tenant1-namespace 中的 grafana-app 可以通过 postgres-app.tenant2-namespace.svc.cluster.local
访问其他 tenant2-namespace 中的 postgres db
更新:网络政策
1)
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: deny-from-other-namespaces
spec:
podSelector:
matchLabels:
ingress:
- from:
- podSelector: {}
2)
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: web-allow-external
spec:
podSelector:
matchLabels:
app: grafana-app
ingress:
- from: []
您的 NetworkPolicy
对象是正确的,我用它们创建了一个示例并将在下面演示。
如果您仍然可以使用 FQDN 访问另一个命名空间上的服务,您的 NetworkPolicy
可能未在集群上完全启用。
运行 gcloud container clusters describe "CLUSTER_NAME" --zone "ZONE"
并查找以下两个片段:
- 在描述的开头,如果 NetworkPolicy 插件已启用在大师级别,它应该是这样的:
addonsConfig:
networkPolicyConfig: {}
- 在描述的中间,您可以找到是否在节点 上启用了 NetworkPolicy。它应该是这样的:
name: cluster-1
network: default
networkConfig:
network: projects/myproject/global/networks/default
subnetwork: projects/myproject/regions/us-central1/subnetworks/default
networkPolicy:
enabled: true
provider: CALICO
- 如果以上任何一项不同,请在此处查看:How to Enable Network Policy in GKE
复制:
- 我将创建一个简单的示例,我将为租户 1 使用
gcr.io/google-samples/hello-app:1.0
图像,为租户 2 使用 gcr.io/google-samples/hello-app:2.0
,因此查看它的连接位置更简单,但我将使用名称您的环境:
$ kubectl create namespace tenant1
namespace/tenant1 created
$ kubectl create namespace tenant2
namespace/tenant2 created
$ kubectl run -n tenant1 grafana-app --generator=run-pod/v1 --image=gcr.io/google-samples/hello-app:1.0
pod/grafana-app created
$ kubectl run -n tenant1 postgres-app --generator=run-pod/v1 --image=gcr.io/google-samples/hello-app:1.0
pod/postgres-app created
$ kubectl run -n tenant2 grafana-app --generator=run-pod/v1 --image=gcr.io/google-samples/hello-app:2.0
pod/grafana-app created
$ kubectl run -n tenant2 postgres-app --generator=run-pod/v1 --image=gcr.io/google-samples/hello-app:2.0
pod/postgres-app created
$ kubectl expose pod -n tenant1 grafana-app --port=8080 --type=LoadBalancer
service/grafana-app exposed
$ kubectl expose pod -n tenant1 postgres-app --port=8080 --type=NodePort
service/postgres-app exposed
$ kubectl expose pod -n tenant2 grafana-app --port=8080 --type=LoadBalancer
service/grafana-app exposed
$ kubectl expose pod -n tenant2 postgres-app --port=8080 --type=NodePort
service/postgres-app exposed
$ kubectl get all -o wide -n tenant1
NAME READY STATUS RESTARTS AGE IP NODE
pod/grafana-app 1/1 Running 0 100m 10.48.2.4 gke-cluster-114-default-pool-e5df7e35-ez7s
pod/postgres-app 1/1 Running 0 100m 10.48.0.6 gke-cluster-114-default-pool-e5df7e35-c68o
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
service/grafana-app LoadBalancer 10.1.23.39 34.72.118.149 8080:31604/TCP 77m run=grafana-app
service/postgres-app NodePort 10.1.20.92 <none> 8080:31033/TCP 77m run=postgres-app
$ kubectl get all -o wide -n tenant2
NAME READY STATUS RESTARTS AGE IP NODE
pod/grafana-app 1/1 Running 0 76m 10.48.4.8 gke-cluster-114-default-pool-e5df7e35-ol8n
pod/postgres-app 1/1 Running 0 100m 10.48.4.5 gke-cluster-114-default-pool-e5df7e35-ol8n
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
service/grafana-app LoadBalancer 10.1.17.50 104.154.135.69 8080:30534/TCP 76m run=grafana-app
service/postgres-app NodePort 10.1.29.215 <none> 8080:31667/TCP 77m run=postgres-app
- 现在,让我们部署您的两条规则:第一个阻止来自命名空间外部的所有流量,第二个允许从命名空间外部进入
grafana-app
:
$ cat default-deny-other-ns.yaml
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: deny-from-other-namespaces
spec:
podSelector:
matchLabels:
ingress:
- from:
- podSelector: {}
$ cat allow-grafana-ingress.yaml
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: web-allow-external
spec:
podSelector:
matchLabels:
run: grafana-app
ingress:
- from: []
- 让我们回顾一下Network Policy Isolation的规则:
By default, pods are non-isolated; they accept traffic from any source.
Pods become isolated by having a NetworkPolicy that selects them. Once there is any NetworkPolicy in a namespace selecting a particular pod, that pod will reject any connections that are not allowed by any NetworkPolicy. (Other pods in the namespace that are not selected by any NetworkPolicy will continue to accept all traffic.)
Network policies do not conflict; they are additive. If any policy or policies select a pod, the pod is restricted to what is allowed by the union of those policies' ingress/egress rules. Thus, order of evaluation does not affect the policy result.
- 然后我们将在两个命名空间上应用规则,因为规则的范围是它分配给的命名空间:
$ kubectl apply -n tenant1 -f default-deny-other-ns.yaml
networkpolicy.networking.k8s.io/deny-from-other-namespaces created
$ kubectl apply -n tenant2 -f default-deny-other-ns.yaml
networkpolicy.networking.k8s.io/deny-from-other-namespaces created
$ kubectl apply -n tenant1 -f allow-grafana-ingress.yaml
networkpolicy.networking.k8s.io/web-allow-external created
$ kubectl apply -n tenant2 -f allow-grafana-ingress.yaml
networkpolicy.networking.k8s.io/web-allow-external created
- 现在进行最终测试,我将在
tenant1
中登录 grafana-app
并尝试访问两个命名空间中的 postgres-app
并检查输出:
$ kubectl exec -n tenant1 -it grafana-app -- /bin/sh
/ ### POSTGRES SAME NAMESPACE ###
/ # wget -O- postgres-app:8080
Connecting to postgres-app:8080 (10.1.20.92:8080)
Hello, world!
Version: 1.0.0
Hostname: postgres-app
/ ### GRAFANA OTHER NAMESPACE ###
/ # wget -O- --timeout=1 http://grafana-app.tenant2.svc.cluster.local:8080
Connecting to grafana-app.tenant2.svc.cluster.local:8080 (10.1.17.50:8080)
Hello, world!
Version: 2.0.0
Hostname: grafana-app
/ ### POSTGRES OTHER NAMESPACE ###
/ # wget -O- --timeout=1 http://postgres-app.tenant2.svc.cluster.local:8080
Connecting to postgres-app.tenant2.svc.cluster.local:8080 (10.1.29.215:8080)
wget: download timed out
- 可以看到DNS解析了,但是networkpolicy阻止了对后端的访问pods。
如果仔细检查主节点和节点上启用了 NetworkPolicy 后您仍然遇到同样的问题,请在评论中告诉我,我们可以进一步挖掘。
我在 2 个命名空间 tenant1-namespace,tenant2-namespace 中创建了 2 个租户 (tenant1,tenant2)
每个租户都有 db pod 及其服务
如何隔离 db pods/service 即如何限制 pod/service 从他的命名空间访问其他租户 db pods ?
我已经为每个租户使用了服务帐户并应用了网络策略,以便隔离命名空间。
kubectl get svc --all-namespaces
tenant1-namespace grafana-app LoadBalancer 10.64.7.233 104.x.x.x 3000:31271/TCP 92m
tenant1-namespace postgres-app NodePort 10.64.2.80 <none> 5432:31679/TCP 92m
tenant2-namespace grafana-app LoadBalancer 10.64.14.38 35.x.x.x 3000:32226/TCP 92m
tenant2-namespace postgres-app NodePort 10.64.2.143 <none> 5432:31912/TCP 92m
所以
我想限制 grafana-app 只在他的命名空间中使用他的 postgres 数据库,而不是在其他命名空间中。
但问题是使用 DNS 限定服务名称 (app-name.namespace-name.svc.cluster.local
)
它允许相互访问 db pods(命名空间 tenant1-namespace 中的 grafana-app 可以通过 postgres-app.tenant2-namespace.svc.cluster.local
更新:网络政策
1)
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: deny-from-other-namespaces
spec:
podSelector:
matchLabels:
ingress:
- from:
- podSelector: {}
2)
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: web-allow-external
spec:
podSelector:
matchLabels:
app: grafana-app
ingress:
- from: []
您的
NetworkPolicy
对象是正确的,我用它们创建了一个示例并将在下面演示。如果您仍然可以使用 FQDN 访问另一个命名空间上的服务,您的
NetworkPolicy
可能未在集群上完全启用。
运行 gcloud container clusters describe "CLUSTER_NAME" --zone "ZONE"
并查找以下两个片段:
- 在描述的开头,如果 NetworkPolicy 插件已启用在大师级别,它应该是这样的:
addonsConfig:
networkPolicyConfig: {}
- 在描述的中间,您可以找到是否在节点 上启用了 NetworkPolicy。它应该是这样的:
name: cluster-1
network: default
networkConfig:
network: projects/myproject/global/networks/default
subnetwork: projects/myproject/regions/us-central1/subnetworks/default
networkPolicy:
enabled: true
provider: CALICO
- 如果以上任何一项不同,请在此处查看:How to Enable Network Policy in GKE
复制:
- 我将创建一个简单的示例,我将为租户 1 使用
gcr.io/google-samples/hello-app:1.0
图像,为租户 2 使用gcr.io/google-samples/hello-app:2.0
,因此查看它的连接位置更简单,但我将使用名称您的环境:
$ kubectl create namespace tenant1
namespace/tenant1 created
$ kubectl create namespace tenant2
namespace/tenant2 created
$ kubectl run -n tenant1 grafana-app --generator=run-pod/v1 --image=gcr.io/google-samples/hello-app:1.0
pod/grafana-app created
$ kubectl run -n tenant1 postgres-app --generator=run-pod/v1 --image=gcr.io/google-samples/hello-app:1.0
pod/postgres-app created
$ kubectl run -n tenant2 grafana-app --generator=run-pod/v1 --image=gcr.io/google-samples/hello-app:2.0
pod/grafana-app created
$ kubectl run -n tenant2 postgres-app --generator=run-pod/v1 --image=gcr.io/google-samples/hello-app:2.0
pod/postgres-app created
$ kubectl expose pod -n tenant1 grafana-app --port=8080 --type=LoadBalancer
service/grafana-app exposed
$ kubectl expose pod -n tenant1 postgres-app --port=8080 --type=NodePort
service/postgres-app exposed
$ kubectl expose pod -n tenant2 grafana-app --port=8080 --type=LoadBalancer
service/grafana-app exposed
$ kubectl expose pod -n tenant2 postgres-app --port=8080 --type=NodePort
service/postgres-app exposed
$ kubectl get all -o wide -n tenant1
NAME READY STATUS RESTARTS AGE IP NODE
pod/grafana-app 1/1 Running 0 100m 10.48.2.4 gke-cluster-114-default-pool-e5df7e35-ez7s
pod/postgres-app 1/1 Running 0 100m 10.48.0.6 gke-cluster-114-default-pool-e5df7e35-c68o
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
service/grafana-app LoadBalancer 10.1.23.39 34.72.118.149 8080:31604/TCP 77m run=grafana-app
service/postgres-app NodePort 10.1.20.92 <none> 8080:31033/TCP 77m run=postgres-app
$ kubectl get all -o wide -n tenant2
NAME READY STATUS RESTARTS AGE IP NODE
pod/grafana-app 1/1 Running 0 76m 10.48.4.8 gke-cluster-114-default-pool-e5df7e35-ol8n
pod/postgres-app 1/1 Running 0 100m 10.48.4.5 gke-cluster-114-default-pool-e5df7e35-ol8n
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
service/grafana-app LoadBalancer 10.1.17.50 104.154.135.69 8080:30534/TCP 76m run=grafana-app
service/postgres-app NodePort 10.1.29.215 <none> 8080:31667/TCP 77m run=postgres-app
- 现在,让我们部署您的两条规则:第一个阻止来自命名空间外部的所有流量,第二个允许从命名空间外部进入
grafana-app
:
$ cat default-deny-other-ns.yaml
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: deny-from-other-namespaces
spec:
podSelector:
matchLabels:
ingress:
- from:
- podSelector: {}
$ cat allow-grafana-ingress.yaml
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: web-allow-external
spec:
podSelector:
matchLabels:
run: grafana-app
ingress:
- from: []
- 让我们回顾一下Network Policy Isolation的规则:
By default, pods are non-isolated; they accept traffic from any source.
Pods become isolated by having a NetworkPolicy that selects them. Once there is any NetworkPolicy in a namespace selecting a particular pod, that pod will reject any connections that are not allowed by any NetworkPolicy. (Other pods in the namespace that are not selected by any NetworkPolicy will continue to accept all traffic.)
Network policies do not conflict; they are additive. If any policy or policies select a pod, the pod is restricted to what is allowed by the union of those policies' ingress/egress rules. Thus, order of evaluation does not affect the policy result.
- 然后我们将在两个命名空间上应用规则,因为规则的范围是它分配给的命名空间:
$ kubectl apply -n tenant1 -f default-deny-other-ns.yaml
networkpolicy.networking.k8s.io/deny-from-other-namespaces created
$ kubectl apply -n tenant2 -f default-deny-other-ns.yaml
networkpolicy.networking.k8s.io/deny-from-other-namespaces created
$ kubectl apply -n tenant1 -f allow-grafana-ingress.yaml
networkpolicy.networking.k8s.io/web-allow-external created
$ kubectl apply -n tenant2 -f allow-grafana-ingress.yaml
networkpolicy.networking.k8s.io/web-allow-external created
- 现在进行最终测试,我将在
tenant1
中登录grafana-app
并尝试访问两个命名空间中的postgres-app
并检查输出:
$ kubectl exec -n tenant1 -it grafana-app -- /bin/sh
/ ### POSTGRES SAME NAMESPACE ###
/ # wget -O- postgres-app:8080
Connecting to postgres-app:8080 (10.1.20.92:8080)
Hello, world!
Version: 1.0.0
Hostname: postgres-app
/ ### GRAFANA OTHER NAMESPACE ###
/ # wget -O- --timeout=1 http://grafana-app.tenant2.svc.cluster.local:8080
Connecting to grafana-app.tenant2.svc.cluster.local:8080 (10.1.17.50:8080)
Hello, world!
Version: 2.0.0
Hostname: grafana-app
/ ### POSTGRES OTHER NAMESPACE ###
/ # wget -O- --timeout=1 http://postgres-app.tenant2.svc.cluster.local:8080
Connecting to postgres-app.tenant2.svc.cluster.local:8080 (10.1.29.215:8080)
wget: download timed out
- 可以看到DNS解析了,但是networkpolicy阻止了对后端的访问pods。
如果仔细检查主节点和节点上启用了 NetworkPolicy 后您仍然遇到同样的问题,请在评论中告诉我,我们可以进一步挖掘。