如何在MicroK8s/K8s集群中配置容器化MySQL/PostgreSQL的SSH隧道
一、先解决你当前的Pod报错问题
你遇到的Could not resolve hostname bastion-host.example.com是因为示例中的域名是占位符,需要替换为实际的堡垒机/数据库主机地址,同时确保MicroK8s集群能解析该地址(或直接用IP)。此外,还需要补全几个关键步骤:
1. 启用MicroK8s必要插件
全新安装的MicroK8s需要启用DNS插件解决集群内域名解析问题,若后续需要数据库持久化,还需启用storage插件:
microk8s enable dns storage
2. 将SSH密钥存入K8s Secret
Pod无法直接访问本地的~/.ssh/id_rsa,必须将密钥存储为K8s Secret:
microk8s kubectl create secret generic ssh-tunnel-key --from-file=id_rsa=~/.ssh/id_rsa
3. 修正ssh-client.py参数并调整生成的YAML
运行脚本时替换占位符为实际值(以PostgreSQL为例):
./ssh-client.py 5432:你的数据库主机IP/域名:5432 堡垒机用户名@堡垒机IP/域名 /etc/ssh-secrets/id_rsa ssh-tunnel-service-postgres
生成ssh-tunnel-service-postgres.yaml后,需要修改Deployment配置,添加Secret挂载:
- 在
spec.template.spec.containers[0]下添加:volumeMounts: - name: ssh-secrets mountPath: /etc/ssh-secrets readOnly: true - 在
spec.template.spec下添加:volumes: - name: ssh-secrets secret: secretName: ssh-tunnel-key defaultMode: 0600 # SSH密钥必须是600权限才能被正常使用
同时,确保容器镜像包含openssh-client,若脚本生成的镜像缺少该工具,可将镜像替换为alpine:latest,并在command中先安装:
command: ["/bin/sh", "-c"] args: ["apk add --no-cache openssh-client && ssh -N -L ..."]
4. 重新部署并验证
microk8s kubectl apply -f ssh-tunnel-service-postgres.yaml
等待Pod启动后,查看日志确认无报错:
microk8s kubectl logs <ssh-tunnel-pod-name>
二、适配本地无密码PostgreSQL的场景
如果你是想在MicroK8s内部部署PostgreSQL,同时通过SSH隧道从外部无密码访问,可采用反向隧道方案:
1. 部署无密码访问的PostgreSQL
在PostgreSQL的Deployment中,修改pg_hba.conf(可通过ConfigMap挂载),添加集群内信任规则:
host all all 0.0.0.0/0 trust
同时设置环境变量POSTGRES_HOST_AUTH_METHOD=trust(注意:仅在集群内部完全可信的场景下使用,生产环境不建议)。
2. 部署SSH堡垒机Pod
创建一个运行SSH服务的Deployment,挂载你的公钥到authorized_keys,外部可通过SSH连接该Pod并建立隧道:
ssh -L 5432:postgres-service:5432 ssh-user@<堡垒机Pod的NodePort/LoadBalancer地址>
此时本地即可通过localhost:5432无密码访问集群内的PostgreSQL。
三、关键注意事项
- 确保堡垒机/数据库主机允许MicroK8s集群节点的IP通过SSH访问
- SSH密钥权限必须为600,否则会被ssh客户端拒绝
- 生产环境中,建议限制SSH隧道的访问范围,避免暴露数据库端口
内容的提问来源于stack exchange,提问作者thor

