解决k8s跨域访问的TLS穿透问题

问题背景

某业务有个k8s集群,因最初网络规划等原因,无法和现有IDC的网络进行打通(原因是云上网段和IDC网段有冲突)。某k8s控制托管系统(运维一体化流程系统)部署在酒仙桥的IDC,某k8s控制系统需要访问k8s集群的控制节点。如果无法访问,则该集群无法接入某k8s控制托管系统系统。因为某k8s控制托管系统系统是直接读取~/.kube/config文件来调用API,因此无法使用普通的代理方式实现需求。怎么打通网络或者其它方式解决这个问题, 成了我的重点任务。本文就以此案例分享给有同样需求的同事。

现状

云上k8s集群
控制节点:https://10.99.10.11:16443(CLB)
master节点:10.99.10.1 - 3
API Server证书SAN列表:127.0.0.1, 10.99.10.1 - 11, 10.99.12.1-11, 10.241.21.1 - 11 (仅运行这些IP操作控制节点)
云上中转服务器: 10.241.21.21
IDC(控制系统):10.100.221.0/24

部署架构

2026-05-16T06:32:12.png

解决思路

因为Nginx机器和两边的网络都通,因此初步考虑可以做个SNAT或者透明代理来解决这个问题

一、 使用SNAT解决该问题

操作步骤

  1. 在10.241.21.21机器上配置一条防火墙规则,使用snat将本机器16443端口的请求全部转发到控制节点:https://10.99.10.11:16443

    sysctl -w net.ipv4.ip_forward=1
    iptables -t nat -A PREROUTING -p tcp --dport 16443 -j DNAT --to-destination 10.99.10.11:16443
    iptables -t nat -A POSTROUTING -p tcp -d 10.99.10.11 --dport 16443 -j SNAT --to-source 10.241.21.21

  2. 加完规则后开始测试,在部署某k8s控制托管系统系统的机器上使用控制节点的~/.kube/config文件,修改server为https://10.241.21.21:16443
    2026-05-16T06:32:36.png
  3. 开始验证:kubectl get nodes, 提示当前机器IP不在证书允许的范围内
    2026-05-16T06:32:58.png
    问题总结
    直接转发,源IP信息无法被证书校验通过(转发的节点不在证书的SAN列表里面),导致报错
    二、采用Nginx代理

考虑到代理节点既不能丢失证书信息,还需要在证书的SAN列表中,开始考虑使用Nginx代理配置

  1. 在控制机器上面创建新的证书,设定SAN,包含转发的服务器以及某k8s控制托管系统所在的服务器IP信息

    生成配置csr.json

    cat > kubernetes-csr.json << EOF
    kubernetes-csr.json
    {
    "CN": "kubernetes",
    "hosts": [
    "kubernetes",
    "kubernetes.default",
    "kubernetes.default.svc",
    "kubernetes.default.svc.cluster",
    "kubernetes.default.svc.cluster.local",
    "127.0.0.1",
    "10.241.21.21",
    "10.100.106.35",
    "10.100.221.11",
    "10.100.221.12",
    "10.100.221.13",
    "10.100.221.14",
    "10.100.221.15",
    "10.100.221.16",
    "10.100.221.17",
    "10.100.221.18",
    "10.100.221.19"
    ],
    "key": {
    "algo": "rsa",
    "size": 2048
    },
    "names": [
    {
    "C": "CN",
    "L": "BeiJing",
    "ST": "BeiJing",
    "O": "k8s",
    "OU": "System"
    }
    ]
    }
    EOF

    再生成证书(使用kubeapiserver的CA证书)

cfssl gencert -ca=/etc/kubernetes/pki/ca.pem -ca-key=/etc/kubernetes/pki/ca-key.pem -config=../ca-config.json -profile=kubernetes kubernetes-csr.json | cfssljson -bare kubernetes

# 此时应该生成了证书和key文件 kubernetes-key.pem, kubernetes.pem

  1. 根据现有控制节点的~/.kube/config 文件导出k8s证书(如果不愿意重新生成证书,则可以直接导出),config文件总共有三个证书配置:certificate-authority-data, client-certificate-data,client-key-data
    2026-05-16T06:33:13.png

根据config文件导出证书

复制certificate-authority-data字段后面的内容,使用base64解码, 导出CA证书

echo LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUR3RENDQXFpZ0F3SUJBZ0lVTGU1YThpanhJeEVIeXlXaVZud0t5UXNpa3VNd0R21YY0FqQJBUXNGQUFPQ0FRRUFjeTlKd2xlbnZCSXNZcXdSaWdOVGp0T2JWcH......YxUmFGbHVYRVd4RkpoSlRvTTgwS0t5E1CVnRBb0lpVGxONjExcHkKRWVraUtPTFE2TnhqZE9MRjV0blZIVG1GSGt3TkFrTkF3b2k5M1Q5cnNBTFV5YzJUdFRUTjUwY2UxRkxLMlN6Ygo0bm1JeXc9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg== | base64 -d > ca.pem

复制client-certificate-data字段后面的内容,使用base64解码, 导出私钥证书

echo LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUQzekNDQXNlZ0F3SUJBZ0lVV3kzeEsrVXUzNDBvTEwzL3lDUWVIcUJTTVRzd0RRWUpLb1pJaHZjTkFRRUwKRUxNQWtHQTFVRUJoTUNRMDR4RURBT0JnTlZCQWdUQjBK......NEJTTW1mNApsRC9mK2xKdVIrQmlXMTU4eVB2di9WbUtCQ1FKZ0R5SHdEN0ViUFAwR2lNRWlUdz0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= | base64 -d > k8s.pem

复制client-key-data字段后面的内容,使用base64解码, 导出私钥秘钥

echo LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFb2dJQkFBS0NBUUVBckVxVkdnYjZMc1YzellYaTVQNHRbUVkNDJnZ0tpcmUzV3WUxHZmppMTNSUHdFMFdDc0JJd3hKMGNURjhsUTJPa2pN......dVVzUFduQjB1bgpuQzJqV0pZSXFtaEh5M09DcVNCYzd3Y09jMnFXSkpWZHhtM0ZBR3dKYTAyZHpiRzFHWFN1RUtMRDM0OVpZOFhuawppb2NOUXhPSGVvSDhZUmszU3h2akxyOHBYaWpuUlY4Q2dLVmlPWFB6cDFCbFVyK01xTk09Ci0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tCg== | base64 -d > k8s.pem

  1. 在中转的服务器上面部署Nginx,增加控制节点代理

    Nginx部署的过程略

    增加代理配置 k8s.conf

cat > k8s.conf << EOF
server {
    listen 16443 ssl;
    server_name 10.241.21.21;
    ssl_certificate     /etc/nginx/conf/key/k8s.pem;
    ssl_certificate_key /etc/nginx/conf/key/k8s.key;

    # 透传客户端证书
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header Authorization $http_authorization;
    proxy_pass_header Authorization;

    # 关键配置:透传客户端证书到API Server
    proxy_ssl_certificate /etc/nginx/conf/key/kubernetes.pem;  # kubeconfig中的客户端证书
    proxy_ssl_certificate_key /etc/nginx/conf/key/kubernetes-key.pem;  # kubeconfig中的私钥
    proxy_ssl_verify off;  # 开启API Server证书验证
    proxy_ssl_trusted_certificate /etc/nginx/conf/key/ca.pem;  # API Server的CA证书
    access_log /data/accesslogs/k8s.access.log main;

    location / {
        proxy_pass https://10.99.10.11:16443;  # 目标API Server
    }
}

EOF
  1. 复制第2/3步骤生成的证书(kubernetes-key.pem, kubernetes.pem,k8s.pem, k8s.key, ca.pem ),放到nginx服务器的/etc/nginx/conf/key/目录, 启动nginx
  2. 在需要操作集群的IDC的服务器上修改config配置
    2026-05-16T06:34:47.png
  3. 在需要操作集群的IDC的服务器上测试:kubectl get nodes
    2026-05-16T06:34:56.png
    发现可以远程执行kubeapi了,该方法可行

暂无评论

评论已关闭。