问题背景
某业务有个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
部署架构

解决思路
因为Nginx机器和两边的网络都通,因此初步考虑可以做个SNAT或者透明代理来解决这个问题
一、 使用SNAT解决该问题
操作步骤
在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- 加完规则后开始测试,在部署某k8s控制托管系统系统的机器上使用控制节点的~/.kube/config文件,修改server为https://10.241.21.21:16443

- 开始验证:kubectl get nodes, 提示当前机器IP不在证书允许的范围内

问题总结
直接转发,源IP信息无法被证书校验通过(转发的节点不在证书的SAN列表里面),导致报错
二、采用Nginx代理
考虑到代理节点既不能丢失证书信息,还需要在证书的SAN列表中,开始考虑使用Nginx代理配置
在控制机器上面创建新的证书,设定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
- 根据现有控制节点的~/.kube/config 文件导出k8s证书(如果不愿意重新生成证书,则可以直接导出),config文件总共有三个证书配置:certificate-authority-data, client-certificate-data,client-key-data

根据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
在中转的服务器上面部署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
- 复制第2/3步骤生成的证书(kubernetes-key.pem, kubernetes.pem,k8s.pem, k8s.key, ca.pem ),放到nginx服务器的/etc/nginx/conf/key/目录, 启动nginx
- 在需要操作集群的IDC的服务器上修改config配置

- 在需要操作集群的IDC的服务器上测试:kubectl get nodes

发现可以远程执行kubeapi了,该方法可行
暂无评论
评论已关闭。