postgresql - 如何阻止从 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: []
解决方案
您的
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
- 如果上述任何一项不同,请在此处查看:如何在 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的规则:
默认情况下,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
在两个命名空间中访问并检查输出:tenant1
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 阻止了对后端 pod 的访问。
如果在对 Master 和 Nodes 启用 NetworkPolicy 进行仔细检查后,您仍然面临同样的问题,请在评论中告诉我,我们可以进一步挖掘。
推荐阅读
- scala - 加入与条件相同的最后一个字母的数据帧
- smartcard - Java Card:发送 T=0 的长响应
- reactjs - antd中选择标签的占位符属性不起作用
- android - 如何使用 ViewTreeObserver.OnGlobalLayoutListener() 从回收器视图项访问图像视图
- sap-ase - 获取 AUTO INCREMENT 的下一个值
- java - 如何将 Python 套接字转换为 Java?Tello DJI 无人机
- variables - 在 go 中声明一个没有值的全局变量
- google-cloud-platform - 我是否需要在 gcloud 中部署功能才能使用 OCR?
- node.js - -print 通过 npm 打印出字符串,但实际上通过 powershell 进行评估
- mysql - MYSQL Group By 值 > 0