1. 写在前面

通常是自建k8s环境,创建的时候不规范,apiserver地址使用的是负载均衡器地址代理的,由于业务需要变更负载均衡器地址,因此需要对apiserver地址进行修改,生产实践之后的一个方案分享。

2. K8S中证书修改操作

2.1 master节点

## 当前证书的情况,可以看到看到当前节点的ip地址是 192.168.0.160
[root@k8s-master ~]# openssl x509 -in /etc/kubernetes/pki/apiserver.crt -noout -text | grep -A 1 "Subject Alternative Name"
            X509v3 Subject Alternative Name: 
                DNS:k8s-master, DNS:kubernetes, DNS:kubernetes.default, DNS:kubernetes.default.svc, DNS:kubernetes.default.svc.xingzhibang.top, IP Address:10.200.0.1, IP Address:192.168.0.160

## 备份整个master /etc/kubernetes 的目录
[root@k8s-master ~]# cp -r /etc/kubernetes/ /etc/kubernetes.bak
## 备份整个 $HOME/.kube 目录
[root@k8s-master ~]# cp -r $HOME/.kube  $HOME/.kube.bak

2.2 修改 Kubernetes 集群配置

--- 1. 导出当前的配置
[root@k8s-master ~]# kubectl get cm -n kube-system kubeadm-config -o jsonpath='{.data.ClusterConfiguration}' > kubeadm-config.yaml

--- 2. 编辑配置文件
## 找到 apiServer 部分下的 certSANs 字段。你需要修改 IPs 列表,将旧的 IP 替换为新的 IP,并确保保留所有其他必需的 IP(如 127.0.0.1)和域名(如 kubernetes, kubernetes.default, kubernetes.default.svc 等)


## 修改前
apiServer:
     certSANs:
     - 192.168.0.160 # 旧的 IP
     extraArgs:
       authorization-mode: Node,RBAC
     timeoutForControlPlane: 4m0s
   apiVersion: kubeadm.k8s.io/v1beta3
...


## 修改后
[root@k8s-master ~]# cat kubeadm-config.yaml 
apiServer:
  certSANs:
  - 192.168.0.165 ## 新的ip
  - k8s-master 
  - 192.168.0.165 ## master 节点的ip
  - 127.0.0.1
  - apiserver.host
  extraArgs:
    authorization-mode: Node,RBAC
  timeoutForControlPlane: 4m0s
...

--- 3. 更新 kubeadm ConfigMap
kubeadm init phase upload-config kubeadm --config=kubeadm-config.yaml

##  可能是出现的报错
[root@k8s-master ~]# kubeadm init phase upload-config kubeadm --config=kubeadm-config.yaml
[upload-config] Storing the configuration used in ConfigMap "kubeadm-config" in the "kube-system" Namespace
error execution phase upload-config/kubeadm: error uploading the kubeadm ClusterConfiguration: Post "https://192.168.0.160:6443/api/v1/namespaces/kube-system/configmaps?timeout=10s": dial tcp 192.168.0.160:6443: connect: no route to host
To see the stack trace of this error execute with --v=5 or higher

## 这个问题的根本原因是:kubeadm 正在尝试连接到已经初始化的集群,但你的配置中主节点 IP 发生了变化。
## 解决方法,重新初始化
[root@k8s-master ~]# kubeadm reset -f
[root@k8s-master ~]# kubeadm init --config=kubeadm-config.yaml
[root@k8s-master ~]# kubeadm init phase upload-config kubeadm --config=kubeadm-config.yaml
[upload-config] Storing the configuration used in ConfigMap "kubeadm-config" in the "kube-system" Namespace

--- 4. 删除旧的证书和密钥
[root@k8s-master ~]# rm /etc/kubernetes/pki/apiserver.*

--- 5. 使用kubeadmin生成新的证书
[root@k8s-master ~]# kubeadm init phase certs apiserver --config=kubeadm-config.yaml 
[certs] Generating "apiserver" certificate and key
[certs] apiserver serving cert is signed for DNS names [apiserver.host k8s-master kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.xingzhibang.top] and IPs [10.200.0.1 192.168.0.165 127.0.0.1]

--- 6. 更新 kubeconfig 文件
## 管理员和 kubelet 使用的 kubeconfig 文件中嵌入了旧的 API Server 地址,也需要更新。
## 删除旧的admin.conf
[root@k8s-master ~]# rm /etc/kubernetes/admin.conf
## 更新 admin.conf
[root@k8s-master ~]# kubeadm init phase kubeconfig admin --config=kubeadm-config.yaml
# 将新生成的 admin.conf 复制到当前用户目录
[root@k8s-master ~]# cp /etc/kubernetes/admin.conf $HOME/.kube/config
[root@k8s-master ~]# chown $(id -u):$(id -g) $HOME/.kube/config

--- 7. 更新 kubelet.conf (在所有节点上执行),kubelet 的配置也需要更新以指向新的 API Server 地址。
[root@k8s-node02 ~]# vim /etc/kubernetes/kubelet.conf

--- 8. 重启 kubelet 以应用更改
[root@k8s-master ~]# systemctl restart kubelet

3. 重启控制平面组件

API Server 以及其他控制平面组件(如 scheduler, controller-manager)是以静态 Pod 运行的,kubelet 会自动监控并重启它们。

##  最简单的方法是移动它们的 manifest 文件,稍后再移回来,kubelet 会自动重启它们
[root@k8s-master ~]# mv /etc/kubernetes/manifests/kube-apiserver.yaml /tmp/

##  等待几秒钟,确认 apiserver pod 已终止
[root@k8s-master ~]# mv /tmp/kube-apiserver.yaml /etc/kubernetes/manifests/

## 同样地,重启 controller-manager 和 scheduler 以确保它们使用新的 API Server 地址
[root@k8s-master ~]# mv /etc/kubernetes/manifests/kube-controller-manager.yaml /tmp/

## 等待几秒钟
[root@k8s-master ~]# mv /etc/kubernetes/manifests/kube-scheduler.yaml /tmp/
sleep 10s
[root@k8s-master ~]# mv /tmp/kube-controller-manager.yaml /etc/kubernetes/manifests/
[root@k8s-master ~]# mv /tmp/kube-scheduler.yaml /etc/kubernetes/manifests/

## 检查证书信息
[root@k8s-master ~]# openssl x509 -in /etc/kubernetes/pki/apiserver.crt -noout -text | grep -A1 "Subject Alternative Name" 
            X509v3 Subject Alternative Name: 
                DNS:apiserver.host, DNS:k8s-master, DNS:kubernetes, DNS:kubernetes.default, DNS:kubernetes.default.svc, DNS:kubernetes.default.svc.xingzhibang.top, IP Address:10.200.0.1, IP Address:192.168.0.165, IP Address:127.0.0.1

3.1 验证集群状态

[root@k8s-master ~]# kubectl  get nodes
[root@k8s-master ~]# kubectl get pods --all-namespaces

--- 1. 更新cluster-info的configmap文件,获取当前的配置,不更新这个配置会导致kubeadm添加节点报错
# 获取当前的配置
[root@k8s-master ~]# kubectl get cm -n kube-public cluster-info -o yaml > cluster-info.yaml

--- 2. 更新configmap配置,修改server地址为最新的apiserver地址,然后apply
[root@k8s-master ~]# kubectl apply  -f cluster-info.yaml

--- 3. 更新kube-proxy的configmap文件,不更新这个配置会导致svc转发流量异常
# 获取当前的配置
[root@k8s-master ~]# kubectl get cm -n kube-system kube-proxy -o yaml > kube-proxy.yaml

# 修改里面的server地址为最新的apiserver地址
[root@k8s-master ~]# kubectl apply -f kube-proxy.yaml