You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在Kubernetes集群中限制PostgreSQL服务仅通过指定子域名访问?

让PostgreSQL服务仅允许db.x.io访问的解决方案

没问题,咱们来解决这个问题。现在你的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

火山引擎 最新活动