首页 > 解决方案 > 如何阻止从 kubernates 中的其他命名空间到 db pod & service (DNS) 的流量?

问题描述

我在 2 个命名空间中创建了 2 个租户(tenant1,tenant2),tenant1-namespace,tenant2-namespace

每个租户都有 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 db,而不是在其他命名空间中。

但问题是,使用 DNS 限定的服务名称(app-name.namespace-name.svc.cluster.local)它允许访问彼此的 db pod(命名空间tenant1-namespace 中的 grafana-app 可以通过以下方式访问其他tenant2-namespace 中的 postgres dbpostgres-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: []

标签: postgresqlkubernetesgoogle-kubernetes-enginekubernetes-helmkubernetes-ingress

解决方案


  • 您的NetworkPolicy对象是正确的,我用它们创建了一个示例,并将在下面演示。

  • 如果您仍然可以使用 FQDN访问其他命名空间上的服务,则您的集群NetworkPolicy可能没有完全启用

运行gcloud container clusters describe "CLUSTER_NAME" --zone "ZONE"并查找这两个片段:

  • 在描述的开头,它显示是否在 Master 级别启用了 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

再生产:

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

默认情况下,pod 是非隔离的;他们接受来自任何来源的流量。

Pod 通过选择它们的 NetworkPolicy 变得孤立。一旦命名空间中有任何 NetworkPolicy 选择特定 pod,该 pod 将拒绝任何 NetworkPolicy 不允许的任何连接。(命名空间中未被任何 NetworkPolicy 选择的其他 pod 将继续接受所有流量。)

网络策略不冲突;它们是添加剂。如果任何一个或多个策略选择了一个 pod,则该 pod 被限制在这些策略的入口/出口规则的联合所允许的范围内。因此,评估顺序不会影响策略结果。

  • 然后我们将在两个命名空间上应用规则,因为规则的范围是它分配给的命名空间:
$ 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
  • 现在进行最终测试,我将登录并尝试grafana-app在两个命名空间中访问并检查输出:tenant1postgres-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 阻止了对后端 pod 的访问。

如果在对 Master 和 Nodes 启用 NetworkPolicy 进行仔细检查后,您仍然面临同样的问题,请在评论中告诉我,我们可以进一步挖掘。


推荐阅读