加入收藏 | 设为首页 | 会员中心 | 我要投稿 我爱故事小小网_铜陵站长网 (http://www.0562zz.com/)- 视频终端、云渲染、应用安全、数据安全、安全管理!
当前位置: 首页 > 云计算 > 正文

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

发布时间:2022-08-05 14:08:32 所属栏目:云计算 来源:互联网
导读:昨天网络环境出了点问题,本地的虚拟机搭建的 Kubernetes 环境没有固定 IP,结果节点 IP 变了,当然最简单的方式是将节点重新固定回之前的 IP 地址,但是自己头铁想去修改下集群的 IP 地址,结果一路下来踩了好多坑,压根就没那么简单~ 环境 首先看下之前的
  昨天网络环境出了点问题,本地的虚拟机搭建的 Kubernetes 环境没有固定 IP,结果节点 IP 变了,当然最简单的方式是将节点重新固定回之前的 IP 地址,但是自己头铁想去修改下集群的 IP 地址,结果一路下来踩了好多坑,压根就没那么简单~
 
  环境
  首先看下之前的环境:
 
  复制
  ➜  ~ cat /etc/hosts
  192.168.0.111 master1
  192.168.0.109 node1
  192.168.0.110 node2
  1.
  2.
  3.
  4.
  新的 IP 地址:
 
  复制
  ➜  ~ cat /etc/hosts
  192.168.0.106 master1
  192.168.0.101 node1
  192.168.0.105 node2
  1.
  2.
  3.
  4.
  所以我们需要修改所有节点的 IP 地址。
 
  操作
  首先将所有节点的 /etc/hosts 更改为新的地址。
 
  提示:在操作任何文件之前强烈建议先备份。
 
  master 节点备份 /etc/kubernetes 目录。
 
  复制
  ➜ cp -Rf /etc/kubernetes/ /etc/kubernetes-bak
  1.
  替换 /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
  1.
  2.
  3.
  4.
  5.
  6.
  7.
  8.
  识别 /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
  1.
  2.
  3.
  4.
  5.
  6.
  找到 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
  1.
  2.
  3.
  4.
  5.
  6.
  7.
  8.
  9.
  10.
  11.
  12.
  13.
  14.
  15.
  16.
  17.
  这一步非常非常重要,我在操作的时候忽略了这一步,导致 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
  1.
  2.
  3.
  4.
  其实就是连不上 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
  1.
  2.
  这就是因为 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
  1.
  2.
  3.
  4.
  5.
  当然也可以全部重新生成:
 
  复制
  ➜ 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
  1.
  2.
  3.
  4.
  5.
  6.
  7.
  8.
  9.
  10.
  11.
  重启 kubelet。
 
  复制
  ➜ systemctl restart containerd
  ➜ systemctl restart kubelet
  1.
  2.
  正常现在可以访问的 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
  1.
  2.
  3.
  4.
  5.
  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 getting node" err="node "node2" not found"
  1.
  2.
  3.
  4.
  5.
  6.
  可以看到仍然是在访问之前的 APIServer 地址,那么在什么地方会明确使用 APIServer 的地址呢?我们可以通过下面的命令来查看 kubelet 的启动参数:
 
  复制
  ➜ systemctl status kubelet
  ● kubelet.service - kubelet: The Kubernetes Node Agent
     Loaded: loaded (/usr/lib/systemd/system/kubelet.service; enabled; vendor preset: disabled)
    Drop-In: /usr/lib/systemd/system/kubelet.service.d
             └─10-kubeadm.conf
     Active: active (running) since Fri 2022-05-13 14:37:31 CST; 1h 13min ago
       Docs: https://kubernetes.io/docs/
   Main PID: 1194 (kubelet)
      Tasks: 15
     Memory: 126.9M
     CGroup: /system.slice/kubelet.service
             └─1194 /usr/bin/kubelet --bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kub...
 
  May 13 15:51:08 node2 kubelet[1194]: E0513 15:51:08.787677    1194 kubelet.go:2412] "Error getting node" err="node "node2... found"
  May 13 15:51:08 node2 kubelet[1194]: E0513 15:51:08.888194    1194 kubelet.go:2412] "Error getting node" err="node "node2... found"
  ......
  1.
  2.
  3.
  4.
  5.
  6.
  7.
  8.
  9.
  10.
  11.
  12.
  13.
  14.
  15.
  16.
  其核心配置文件为 /usr/lib/systemd/system/kubelet.service.d/10-kubeadm.conf,内容如下所示:
 
  复制
  ➜ cat /usr/lib/systemd/system/kubelet.service.d/10-kubeadm.conf
  # Note: This dropin only works with kubeadm and kubelet v1.11+
  [Service]
  Environment="KUBELET_KUBECONFIG_ARGS=--bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf"
  Environment="KUBELET_CONFIG_ARGS=--config=/var/lib/kubelet/config.yaml"
  # This is a file that "kubeadm init" and "kubeadm join" generates at runtime, populating the KUBELET_KUBEADM_ARGS variable dynamically
  EnvironmentFile=-/var/lib/kubelet/kubeadm-flags.env
  # This is a file that the user can use for overrides of the kubelet args as a last resort. Preferably, the user should use
  # the .NodeRegistration.KubeletExtraArgs object in the configuration files instead. KUBELET_EXTRA_ARGS should be sourced from this file.
  EnvironmentFile=-/etc/sysconfig/kubelet
  ExecStart=
  ExecStart=/usr/bin/kubelet $KUBELET_KUBECONFIG_ARGS $KUBELET_CONFIG_ARGS $KUBELET_KUBEADM_ARGS $KUBELET_EXTRA_ARGS
  1.
  2.
  3.
  4.
  5.
  6.
  7.
  8.
  9.
  10.
  11.
  12.
  其中有一个配置 KUBELET_KUBECONFIG_ARGS=--bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf,这里提到了两个配置文件 bootstrap-kubelet.conf 与 kubelet.conf,其中第一个文件不存在:
 
  复制
  ➜ cat /etc/kubernetes/bootstrap-kubelet.conf
  cat: /etc/kubernetes/bootstrap-kubelet.conf: No such file or directory
  1.
  2.
  而第二个配置文件就是一个 kubeconfig 文件的格式,这个文件中就指定了 APIServer 的地址,可以看到还是之前的 IP 地址:
 
  复制
  ➜ cat /etc/kubernetes/kubelet.conf
  apiVersion: v1
  clusters:
  - cluster:
      certificate-authority-data: <......>
      server: https://192.168.0.111:6443
    name: default-cluster
  contexts:
  - context:
      cluster: default-cluster
      namespace: default
      user: default-auth
    name: default-context
  current-context: default-context
  kind: Config
  preferences: {}
  users:
  - name: default-auth
    user:
      client-certificate: /var/lib/kubelet/pki/kubelet-client-current.pem
      client-key: /var/lib/kubelet/pki/kubelet-client-current.pem
   所以我们最先想到的肯定就是去将这里的 APIServer 地址修改成新的 IP 地址,但是这显然是有问题的,因为相关证书还是以前的,需要重新生成,那么要怎样重新生成该文件呢?

(编辑:我爱故事小小网_铜陵站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读