乐趣区

关于etcd:不使用-K8s-API如何直接修改-etcd-数据

作者:Flant staff
翻译:Bach(才云)
校对:星空下的文仔(才云)、bot(才云)

大家是否已经思考过更改 Kubernetes 集群的 etcd 数据的“低级”办法?就是说在不应用任何通用的 Kubernetes 工具(例如 CLI 程序甚至 API)就更改 etcd 存储的数据。

K8sMeetup

所有从这开始

越来越多的客户(大多是开发人员)要求提供对 Kubernetes 集群的拜访权限,以便与外部服务进行交互。他们心愿可能间接连贯到数据库或服务,将本地应用程序连贯到集群中的其余应用程序等等。

例如,从本地计算机连贯到 memcached.staging.svc.cluster.local service。咱们能够通过客户端连贯的集群外部 VPN 来实现。咱们公开与 Pod 和 service 相干的子网,并将集群的 DNS 推送到客户端。后果,当客户端尝试连贯到 memcached.staging.svc.cluster.local service 时,申请转到了集群的 DNS,它从集群的服务网络或 Pod 的地址返回该 service 的地址。

咱们应用 kubeadm 配置 K8s 集群。在这种状况下,默认 service subnet(子网)是 192.168.0.0/16,而 Pod 子网是 10.244.0.0/16。此办法大部分时候成果很好,然而也有几点值得注意:

  • 192.168.*.* 子网往往是在客户办公室中应用,甚至是开发商的家庭办公室。这就呈现了问题:家用路由器会应用雷同的地址空间,VPN 会将这些子网从集群推送到客户端。
  • 有几个集群(production、stage、多个 dev 集群)的状况下,它们将默认全副具备与  Pod 和服务的雷同子网,这使得同时应用多个集群中的 services 十分艰难。

咱们在同一我的项目中应用了不同的子网来实现同一我的项目中的不同 service 和 Pod。在这种状况下,任何集群都有其本人的网络。在保护大量 K8s 集群时,咱们不心愿它们从头开始重新部署,因为会有许多正在运行的 service、有状态的应用程序等。这时候就呈现了一个问题: 咱们如何更改现有集群中的子网?

K8sMeetup

解决方案

最常见的办法是从新创立所有 ClusterIP 类型的 service。不过也有问题:

以下过程存在问题:配置完所有内容后,Pod 在 /etc/resolv.conf 中将旧 IP 用作 DNS nameserver。

因为依然找不到解决方案,因而不得不应用 kubeadm reset 重置整个集群,再次将其初始化。

这并不适宜所有场景,这里是案例更具体的状况:

  • 应用 Flannel。
  • 既有裸机集群,也有 Kubernetes 星散群。
  • 心愿防止重新部署集群中的所有 service。
  • 心愿尽可能轻松地进行过渡。
  • 该集群由 Kubernetes v1.16.6 治理(但也实用于其余版本)。
  • 指标是在应用 kubeadm 在部署的集群中将 192.168.0.0/16 service subnet 替换为 172.24.0.0/16

实际上,很多人始终想钻研 Kubernetes 是如何将其数据存储在 etcd 中以及该存储能够做什么。那咱们为什么不通过替换旧的来更新 etcd 中的数据子网 IP 与新 IP?

最好有现成的工具来批改 etcd 中的数据,尽管目前没有任何工具能够很好地满足咱们的需要,但 OpenShift 的 etcdhelper 是一个很好的终点。这个工具能够应用证书连贯 etcd,并能用 lsgetdump 命令浏览 etcd 数据。

扩大 etcdhelper

因而,咱们筹备扩大 etcdhelper,以便将数据写入 etcd。咱们创立了具备两个新性能的 etcdhelper 的更新版本:changeServiceCIDRchangePodCIDR。其源代码可在此处取得:https://github.com/flant/exam…

新性能有什么作用?这是 changeServiceCIDR 算法:

  • 创立一个反序列化器(deserializer)。
  • 编译正则表达式以替换 CIDR。
  • 遍历集群中的 ClusterIP service 列表,并对每个 service 执行操作。

这是咱们的操作:

  • 解码 etcd 值并将其搁置在 Go 对象中。
  • 应用正则表达式替换地址的前两个字节。
  • 从新子网的地址范畴为 service 调配 IP 地址。
  • 创立一个序列化器,将 Go 对象转换为 protobuf,将新数据写入 etcd。

changePodCIDR 性能与 changeServiceCIDR 基本上雷同,惟一的区别是咱们编辑节点的标准时,用新的子网替换了 .spec.PodCIDR 的值,而不是 service。

K8sMeetup

用法

更换 serviceCIDR

这事很容易实现,但会导致停机,并且集群中的所有 Pod 都将被从新创立。这里咱们先展现次要步骤,而后分享如何最大水平地缩小停机工夫。

筹备步骤:

  • 装置必要的软件并构建补丁 etcdhelper 工具;
  • 备份 etcd 和 /etc/kubernetes

以下是更改 serviceCIDR 的操作摘要:

  • 更改 apiserver 和控制器管理器清单。
  • 从新颁发证书。
  • 批改 etcd 中 services 的 ClusterIP 标准。
  • 重新启动集群中的所有 Pod。

以下是这些步骤的具体阐明:

1. 装置 etcd-client 用于转储数据:

2. 构建 etcdhelper 工具:

  • 装置 golang

  • 复制 etcdhelper.go,下载依赖项,构建工具:

3. 备份 etcd 数据:

4. 在 Kubernetes 管制立体清单中切换 service subnet。在 /etc/kubernetes/manifests/kube-apiserver.yaml/etc/kubernetes/manifests/kube-controller-manager.yaml 中替换 --service-cluster-ip-range 值与新子网(172.24.0.0/16 代替 192.168.0.0/16)。

5. 因为咱们在对 kubeadm 颁发 apiserver 证书(以及其余证书)的 service subnet 进行更改,因而咱们须要从新颁发:

5.1. 查看以后证书颁发的域和 IP 地址:

5.2. 筹备 kubeadm 根本配置:

5.3. 删除 crtkey 旧文件(删除它们能力颁发新证书):

5.4. 从新颁发 API 服务器的证书:

5.5. 查看是否为新子网颁发了证书:

5.6. 从新颁发 API 服务器证书后,重启其容器:

5.7. 续订嵌入 admin.conf 的证书:

5.8. 编辑 etcd 中的数据:

此时 DNS 进行解析集群中的域名。这是因为现有的 Pod 在 /etc/resolv.conf 中仍具备旧的 CoreDNS(kube-dns)地址,而 kube-proxy 曾经应用新子网,并更改了 iptables 规定。

5.9. 在 kube-system 命名空间中编辑 ConfigMap:

在该 CM 中:

替换 ClusterDNS 为 kube-dns service 的新 IP 地址:kubectl -n kube-system get svc kube-dns

在该 CM 中:

data.ClusterConfiguration.networking.serviceSubnet 参数切换到新的子网。

5.10. 因为 kube-dns 地址已更改,因而须要在所有节点上更新 kubelet 配置:

5.11. 当初该重启集群中的所有 Pod 了:

缩小停机工夫

以下是无关如何最大水平地缩小停机工夫的一些想法:

  • 编辑管制立体清单后,咱们能够应用新名称(例如 kube-dns-tmp)和新地址(172.24.0.10)创立新的 kube-dns service。
  • 咱们在 etcdhelper 中插入 if 条件,这能避免批改 kube-dns service。
  • 将所有 kubelet 中的旧 ClusterDNS 地址替换为新的(旧 service 将持续与新 service 同时运行)。
  • 等所有应用程序的 Pod 都在约定的工夫重新部署。
  • 删除 kube-dns-tmp service 并编辑 serviceSubnetCIDRkube-dns service。

该策略能够将停机工夫缩短到大概一分钟:删除 kube-dns-tmp service 和切换 kube-dns service 的子网所需工夫。

批改 podNetwork

在此过程中,咱们应用 etcdhelper 来批改 podNetwork。这是操作程序:

  • kube-system 命名空间中编辑配置。
  • 编辑 kube-controller-manager 的清单。
  • 间接在 etcd 中编辑 podCIDR。
  • 重新启动集群中的所有节点。

以下是上述操作的具体阐明:

1. 在 kube-system 命名空间中编辑 ConfigMap:

替换 data.ClusterConfiguration.networking.podSubnet 为新的子网(10.55.0.0/16)。

指定新的 data.config.conf.clusterCIDR: 10.55.0.0/16

2. 编辑 controller-manager 清单:

指定:–cluster-cidr=10.55.0.0/16。

3. 验证所有集群节点的 .spec.podCIDR.spec.podCIDRs.InternalIP.status.addresses 以后值:

4. 间接编辑 etcd 替换 podCIDR

5. 查看 podCIDR 是否已更改:

6. 一次重新启动集群的所有节点。

7. 如果至多有一个带有旧 podCIDR 的节点,kube-controller-manager 将不会启动,集群中的 Pod 也不会被调度。

原文链接:https://medium.com/flant-com/…

退出移动版