如何在Kubernetes集群中限制PostgreSQL服务仅通过指定子域名访问?
没问题,咱们来解决这个问题。现在你的PostgreSQL服务既能通过db.x.io访问,又能通过localhost访问,是因为你直接暴露了5432端口(大概率是用NodePort、LoadBalancer或者kubectl port-forward的方式)。要把访问限制在仅db.x.io这个子域名,我们需要切断直接访问的路径,同时用支持TCP代理的Ingress控制器来接管流量——毕竟PostgreSQL走的是TCP协议,普通HTTP Ingress没法直接处理。具体步骤如下:
第一步:把PostgreSQL服务改成ClusterIP类型
首先,我们要关闭服务直接暴露给外部的端口,让它只能在K8s集群内部被访问。修改你的PostgreSQL Service配置:
apiVersion: v1 kind: Service metadata: name: postgres-service namespace: your-namespace # 替换成你的服务所在的命名空间 spec: type: ClusterIP # 替换掉原来的NodePort/LoadBalancer类型 ports: - port: 5432 targetPort: 5432 selector: app: postgres # 替换成你的PostgreSQL Pod对应的标签
应用这个配置后,外部就没法直接通过节点IP或者localhost访问PostgreSQL了,只能通过集群内部的服务发现来访问。
第二步:配置NGINX Ingress Controller代理TCP流量
因为PostgreSQL是TCP协议,普通的HTTP Ingress处理不了,所以我们要用支持TCP代理的Ingress控制器(比如NGINX Ingress Controller)来转发5432端口的流量。
2.1 创建TCP服务转发的ConfigMap
先创建一个ConfigMap,告诉Ingress控制器要把5432端口的流量转发到哪个服务:
apiVersion: v1 kind: ConfigMap metadata: name: tcp-services namespace: ingress-nginx # 这里要对应你的Ingress控制器所在的命名空间 data: 5432: "your-namespace/postgres-service:5432" # 格式是:<服务命名空间>/<服务名>:<端口>
2.2 让Ingress控制器加载这个ConfigMap
如果你是用Helm安装的NGINX Ingress Controller,可以用下面的命令更新配置,让它加载这个TCP转发规则:
helm upgrade ingress-nginx ingress-nginx/ingress-nginx \ --namespace ingress-nginx \ --set controller.config.tcp.5432="your-namespace/postgres-service:5432"
如果是手动部署的Ingress控制器,需要修改它的Deployment或者DaemonSet,添加启动参数--tcp-services-configmap=$(POD_NAMESPACE)/tcp-services,同时确保这个ConfigMap被挂载到控制器的Pod里。
第三步:配置Ingress资源关联子域名
接下来创建Ingress资源,把db.x.io这个子域名和PostgreSQL的TCP服务关联起来:
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: postgres-ingress namespace: your-namespace spec: rules: - host: db.x.io http: paths: - path: / pathType: Prefix backend: service: name: postgres-service port: number: 5432
虽然这里写的是HTTP路径,但NGINX Ingress控制器会结合我们之前配置的TCP转发规则,自动把db.x.io的5432端口流量转发到PostgreSQL服务。
第四步:验证访问控制
现在你可以测试一下访问情况:
- 正常访问:
psql -h db.x.io -p 5432 -U your-username应该能成功连接到数据库 - 禁止访问:
psql -h localhost -p 5432 -U your-username会提示连接失败(因为Service已经改成ClusterIP,localhost没法直接访问了)
可选:限制集群内部非法访问
如果还需要进一步限制,只允许Ingress控制器访问PostgreSQL,可以创建一个NetworkPolicy:
apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: postgres-network-policy namespace: your-namespace spec: podSelector: matchLabels: app: postgres # 匹配你的PostgreSQL Pod标签 policyTypes: - Ingress ingress: - from: - namespaceSelector: matchLabels: name: ingress-nginx # 匹配Ingress控制器所在的命名空间 podSelector: matchLabels: app.kubernetes.io/name: ingress-nginx # 匹配Ingress控制器的Pod标签 ports: - protocol: TCP port: 5432
这样一来,整个访问链路就被严格限制住了:只有通过db.x.io域名解析到Ingress控制器的请求,才能被转发到PostgreSQL服务,其他任何方式的访问都会被拒绝。
内容的提问来源于stack exchange,提问作者WiseStrawberry




