如何阻止来自 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

复制:

  • 我将创建一个简单的示例,我将为租户 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: []

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 后您仍然遇到同样的问题,请在评论中告诉我,我们可以进一步挖掘。