如何修改 K8S Master节点 IP?可没想象中那么简单

  昨天网络环境出了点问题,本地的虚拟机搭建的 Kubernetes 环境没有固定 IP,结果节点 IP 变了,当然最简单的方式是将节点重新固定回之前的 IP 地址,但是自己头铁想去修改下集群的 IP 地址,结果一路下来踩了好多坑,压根就没那么简单~
 
  环境
  首先看下之前的环境:
 
  复制
  ➜  ~ cat /etc/hosts
  192.168.0.111 master1
  192.168.0.109 node1
  192.168.0.110 node2
   新的 IP 地址:
 
  复制
  ➜  ~ cat /etc/hosts
  192.168.0.106 master1
  192.168.0.101 node1
  192.168.0.105 node2
   所以我们需要修改所有节点的 IP 地址。
 
  操作
  首先将所有节点的 /etc/hosts 更改为新的地址。
 
  提示:在操作任何文件之前强烈建议先备份。
 
  master 节点备份 /etc/kubernetes 目录。
 
  复制
  ➜ cp -Rf /etc/kubernetes/ /etc/kubernetes-bak
   替换 /etc/kubernetes 中所有配置文件的 APIServer 地址。
 
  复制
  ➜ oldip=192.168.0.111
  ➜ newip=192.168.0.106
  # 查看之前的
  ➜ find . -type f | xargs grep $oldip
  # 替换IP地址
  ➜ find . -type f | xargs sed -i "s/$oldip/$newip/"
  # 检查更新后的
  ➜ find . -type f | xargs grep $newip
   识别 /etc/kubernetes/pki 中以旧的 IP 地址作为 alt name 的证书。
 
  复制
  ➜ cd /etc/kubernetes/pki
  ➜ for f in $(find -name "*.crt"); do
    openssl x509 -in $f -text -noout > $f.txt;
  done
  ➜ grep -Rl $oldip .
  ➜ for f in $(find -name "*.crt"); do rm $f.txt; done
   找到 kube-system 命名空间中引用旧 IP 的 ConfigMap。
 
  复制
  # 获取所有的 kube-system 命名空间下面所有的 ConfigMap
  ➜ configmaps=$(kubectl -n kube-system get cm -o name | \
    awk '{print $1}' | \
    cut -d '/' -f 2)
 
  # 获取所有的ConfigMap资源清单
  ➜ dir=$(mktemp -d)
  ➜ for cf in $configmaps; do
    kubectl -n kube-system get cm $cf -o yaml > $dir/$cf.yaml
  done
 
  # 找到所有包含旧 IP 的 ConfigMap
  ➜ grep -Hn $dir/* -e $oldip
 
  # 然后编辑这些 ConfigMap,将旧 IP 替换成新的 IP
  ➜ kubectl -n kube-system edit cm kubeadm-config
  ➜ kubectl -n kube-system edit cm kube-proxy
   这一步非常非常重要,我在操作的时候忽略了这一步,导致 Flannel CNI 启动不起来,一直报错,类似下面的日志信息:
 
  复制
  ➜ kubectl logs -f kube-flannel-ds-pspzf -n kube-system
  I0512 14:46:26.044229       1 main.go:205] CLI flags config: {etcdEndpoints:http://127.0.0.1:4001,http://127.0.0.1:2379 etcdPrefix:/coreos.com/network etcdKeyfile: etcdCertfile: etcdCAFile: etcdUsername: etcdPassword: version:false kubeSubnetMgr:true kubeApiUrl: kubeAnnotationPrefix:flannel.alpha.coreos.com kubeConfigFile: iface:[ens33] ifaceRegex:[] ipMasq:true subnetFile:/run/flannel/subnet.env publicIP: publicIPv6: subnetLeaseRenewMargin:60 healthzIP:0.0.0.0 healthzPort:0 iptablesResyncSeconds:5 iptablesForwardRules:true netConfPath:/etc/kube-flannel/net-conf.json setNodeNetworkUnavailable:true}
  W0512 14:46:26.044617       1 client_config.go:614] Neither --kubeconfig nor --master was specified.  Using the inClusterConfig.  This might not work.
  E0512 14:46:56.142921       1 main.go:222] Failed to create SubnetManager: error retrieving pod spec for 'kube-system/kube-flannel-ds-pspzf': Get "https://10.96.0.1:443/api/v1/namespaces/kube-system/pods/kube-flannel-ds-pspzf": dial tcp 10.96.0.1:443: i/o timeout
   其实就是连不上 apiserver,排查了好久才想起来查看 kube-proxy 的日志,其中出现了如下所示的错误信息:
 
  复制
 
  E0512 14:53:03.260817       1 reflector.go:138] k8s.io/client-go/informers/factory.go:134: Failed to watch *v1.EndpointSlice: failed to list *v1.EndpointSlice: Get "https://192.168.0.111:6443/apis/discovery.k8s.io/v1/endpointslices?labelSelector=%21service.kubernetes.io%2Fheadless%2C%21service.kubernetes.io%2Fservice-proxy-name&limit=500&resourceVersion=0": dial tcp 192.168.0.111:6443: connect: no route to host
   这就是因为 kube-proxy 的 ConfigMap 中配置的 apiserver 地址是旧的 IP 地址,所以一定要将其替换成新的。
 
  删除第3步中 grep 出的证书和私钥,重新生成这些证书。
 
  复制
  ➜ cd /etc/kubernetes/pki
  ➜ rm apiserver.crt apiserver.key
  ➜ kubeadm init phase certs apiserver
  ➜ rm etcd/peer.crt etcd/peer.key
  ➜ kubeadm init phase certs etcd-peer
 
  当然也可以全部重新生成:
 
  复制
  ➜ kubeadm init phase certs all
  1.
  生成新的 kubeconfig 文件。
 
  复制
  ➜ cd /etc/kubernetes
  ➜ rm -f admin.conf kubelet.conf controller-manager.conf scheduler.conf
  ➜ kubeadm init phase kubeconfig all
  I0513 15:33:34.404780   52280 version.go:255] remote version is much newer: v1.24.0; falling back to: stable-1.22
  [kubeconfig] Using kubeconfig folder "/etc/kubernetes"
  [kubeconfig] Writing "admin.conf" kubeconfig file
  [kubeconfig] Writing "kubelet.conf" kubeconfig file
  [kubeconfig] Writing "controller-manager.conf" kubeconfig file
  [kubeconfig] Writing "scheduler.conf" kubeconfig file
  # 覆盖默认的 kubeconfig 文件
  ➜ cp /etc/kubernetes/admin.conf $HOME/.kube/config
   重启 kubelet。
 
  复制
  ➜ systemctl restart containerd
  ➜ systemctl restart kubelet
   正常现在可以访问的 Kubernetes 集群了。
 
  复制
  ➜ kubectl get nodes
  NAME      STATUS     ROLES                  AGE   VERSION
  master1   Ready      control-plane,master   48d   v1.22.8
  node1     NotReady   <none>                 48d   v1.22.8
  node2     NotReady   <none>                 48d   v1.22.8
   node 节点
  虽然现在可以访问集群了,但是我们可以看到 Node 节点现在处于 NotReady 状态,我们可以去查看 node2 节点的 kubelet 日志:
 
  复制
  ➜ journalctl -u kubelet -f
  ......
  May 13 15:47:55 node2 kubelet[1194]: E0513 15:47:55.470896    1194 kubelet.go:2412] "Error getting node" err="node \"node2\" not found"
  May 13 15:47:55 node2 kubelet[1194]: E0513 15:47:55.531695    1194 reflector.go:138] k8s.io/client-go/informers/factory.go:134: Failed to watch *v1.Service: failed to list *v1.Service: Get "https://192.168.0.111:6443/api/v1/services?limit=500&resourceVersion=0": dial tcp 192.168.0.111:6443: connect: no route to host
  May 13 15:47:55 node2 kubelet[1194]: E0513 15:47:55.571958    1194 kubelet.go:2412] "Error getting node" err="node \"node2\" not found"
  May 13 15:47:55 node2 kubelet[1194]: E0513 15:47:55.673379    1194 kubelet.go:2412] "Error g

dawei

【声明】:站长网内容转载自互联网,其相关言论仅代表作者个人观点绝非权威,不代表本站立场。如您发现内容存在版权问题,请提交相关链接至邮箱:bqsm@foxmail.com,我们将及时予以处理。