如何阻止Namespace2的Pod访问Namespace1的RDS Service?
问题
我在Namespace1中创建了用于RDS的ExternalName类型Service,想要阻止Namespace2中的Pod或任何资源访问该Service。我配置了RBAC规则,但仍然能成功连接,执行kubectl auth can-i命令显示该ServiceAccount没有Namespace1的Service列表权限,这是为什么?
配置代码
--- apiVersion: v1 kind: ServiceAccount metadata: name: mysqlsa namespace: namespace2 automountServiceAccountToken: false --- apiVersion: v1 kind: Pod metadata: name: mysql-client namespace: namespace2 spec: serviceAccountName: mysqlsa containers: - image: mysql:8 command: - sleep - "3600" imagePullPolicy: IfNotPresent name: busybox restartPolicy: Always --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: namespace: namespace2 name: mysqlaccess rules: - apiGroups: ["*"] resources: ["*"] verbs: ["get", "watch", "list","create","update","patch","delete"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: mysqlaccess-binding namespace: namespace2 roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: mysqlaccess subjects: - kind: ServiceAccount name: mysqlsa namespace: namespace2
连接测试结果
kubectl exec -it mysql-client -n namespace2 -- bash bash-4.4# mysql -h my-database-svc.namespace1.svc.cluster.local -P 3306 -u admin -ppassword mysql: [Warning] Using a password on the command line interface can be insecure. Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 900 Server version: 8.0.32 Source distribution Copyright (c) 2000, 2023, Oracle and/or its affiliates. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql> exit
权限检查结果
kubectl auth can-i list services --as=system:serviceaccount:namespace2:mysqlsa -n namespace1 no
原因分析与解决方案
- RBAC管控的是K8s API操作权限,而非网络连通性:你设置的RBAC规则只是限制
mysqlsa这个ServiceAccount无法通过K8s API查询Namespace1的Service资源,但Pod直接通过网络访问Service对应的RDS地址时,根本不经过K8s API,所以RBAC规则无法阻止这类访问。kubectl auth can-i返回的是API操作权限,和实际网络连通性没有关系。 - ExternalName Service本质是DNS别名:这种类型的Service只是给外部RDS地址创建了一个集群内的DNS别名,Pod访问该Service域名时,K8s DNS会直接解析到RDS的真实IP,整个过程和K8s API无关,RBAC自然无法干预。
- 要阻止跨命名空间访问,需使用NetworkPolicy:如果你的集群部署了支持NetworkPolicy的网络插件(如Calico、Cilium),可以创建NetworkPolicy限制Namespace2的Pod无法访问RDS的IP和端口。示例配置如下:
apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: block-namespace2-to-rds namespace: namespace2 spec: podSelector: {} # 匹配Namespace2下所有Pod policyTypes: - Egress egress: # 先允许Pod访问必要的集群资源(如DNS),否则无法解析域名 - to: - namespaceSelector: matchLabels: kubernetes.io/metadata.name: kube-system ports: - port: 53 protocol: UDP - port: 53 protocol: TCP # 拒绝访问RDS的IP和端口,替换为你的RDS实际地址 - to: - ipBlock: cidr: 1.2.3.4/32 # 填写RDS的公网/内网IP ports: - port: 3306 protocol: TCP
- 若集群不支持NetworkPolicy,可在外部层面限制:比如在云厂商安全组中,仅允许Namespace1的Pod所在IP段访问RDS,从源头拦截Namespace2的流量。
内容的提问来源于stack exchange,提问作者Rad4
相关产品推荐
相关产品推荐

