跳至内容

集群启动顺序

Kubernetes 启动

这是关于使用 kOps 启动 Kubernetes 集群的概述。

从规范到完整配置

kOps 工具本身会获取用户指定的集群的(最小)规范,并计算出完整的配置,在未指定值的 地方设置默认值,并推导出适当的依赖关系。 “完整”规范包括将传递给所有组件的所有标志的集合。 所有关于如何安装集群的决策都在此阶段做出,因此如果用户在规范中指定了值,理论上 可以更改所有决策。

此完整规范设置在自动伸缩组(在 AWS 上)或托管实例组(在 GCE 上)的启动模板中。

在 AWS 和 GCE 上,所有内容(节点和主节点)都在 ASG/MIG 中运行;这意味着故障(或用户) 可以终止机器,并且系统会自动修复。

nodeup: 从镜像到 kubelet

nodeup 是安装软件包并设置操作系统的组件,足以满足 Kubelet 的要求。 核心要求是

  • 必须安装 Docker。 nodeup 将安装 Docker 1.13.1,这是经过 Kubernetes 1.8 测试的 Docker 版本
  • Kubelet,作为 systemd 服务安装

此外,nodeup 还安装了

  • Protokube,这是一个 kops 特定的组件

/etc/kubernetes/manifests

kubelet 根据 /etc/kubernetes/manifests 中的文件启动 pod。 这些文件由 nodeup 和 protokube 创建(理想情况下,所有文件都由 protokube 创建,但目前在两者之间 分开)。

这些 pod 使用标准的 k8s 清单声明,就像它们存储在 API 中一样。 但是,这些用于打破启动 etcd 和 kube-apiserver 等核心组件的循环依赖关系。

在主节点上

  • kube-apiserver
  • kube-controller-manager(运行各种控制器)
  • kube-scheduler(将 pod 分配到节点)
  • etcd(实际上是由 protokube 创建的)
  • dns-controller

在节点上

  • kube-proxy(配置 iptables 使 k8s 网络正常工作)

可以通过在集群规范中使用 fileAssets 添加自定义静态 pod。 这对于任何不适合 additionalUserDatahooks 的自定义启动来说可能很有用。

kubelet 启动

Kubelet 启动并启动(并重新启动)/etc/kubernetes/manifests 中的所有容器。

它还尝试联系 API 服务器(主 kubelet 最终将启动),注册节点。 节点注册后,kube-controller-manager 将为其分配 PodCIDR,即 k8s 网络 IP 范围的分配。 kube-controller-manager 更新节点,设置 PodCIDR 字段。 kubelet 看到此分配后,它将使用此 CIDR 设置本地网桥,从而允许 docker 启动。 在此之前,只有具有 hostNetwork 的 pod 才能工作 - 因此所有 “核心”容器都使用 hostNetwork=true 运行。

api-server 启动

APIServer 还监听所有接口上的 HTTPS 端口 (443)。 这是一个安全的端点,需要有效的身份验证/授权才能使用它。 这是节点 kubelet 将访问的端点,也是最终用户将访问的端点。

kOps 使用 DNS 允许节点和最终用户发现 api-server。 apiserver pod 清单(在 /etc/kubernetes/manifests 中)包含将导致 dns-controller 创建记录的注释。 它创建用于在集群内部(使用 InternalIP 地址)的 api.internal.mycluster.com,以及用于在集群外部(使用 ExternalIP 地址)的 api.mycluster.com

etcd 启动

etcd 是我们放置所有同步逻辑的地方,因此它比大多数其他组件更复杂,我们在启动它时必须格外小心。

kOps 遵循 CoreOS 的建议程序,用于 在云中启动 etcd

  • 每个 etcd 集群成员(在不同的节点中)都有一个 EBS 卷
  • 我们将 EBS 卷附加到主节点,并在该主节点上启动 etcd
  • 我们设置指向 etcd 进程的 DNS 名称
  • 我们使用静态集群设置 etcd,使用这些 DNS 名称

由于数据是持久性的,集群成员资格也是一组静态 DNS 名称,这意味着我们不需要直接管理 etcd。 我们只需要确保某些主节点始终挂载每个卷,etcd 正在运行,并且 DNS 设置正确。 这是 protokube 的工作。

Protokube

  • 发现保存 etcd 数据的 EBS 卷(使用标签)
  • 尝试安全格式化并挂载它们
  • 如果成功挂载卷,它将为 etcd 写入清单到 /etc/kubernetes/manifests
  • 配置 etcd 节点的 DNS(我们不能使用 dns-controller,因为 API 尚未启动)
  • 然后 kubelet 启动并运行 etcd

节点启动

大部分内容都集中在主节点上发生的事情,但节点启动非常相似,只是更简单

  • nodeup 安装 docker 和 kubelet
  • 在 /etc/kubernetes/manifests 中,我们有 kube-proxy

因此 kubelet 将启动,kube-proxy 也将启动。 它将尝试在内部 DNS 名称上访问 api-server,并且一旦主节点启动,它将成功。 然后

  • kubelet 创建一个代表自身的节点对象
  • kube-controller-manager 看到节点创建并为其分配 PodCIDR
  • kubelet 看到 PodCIDR 分配并配置本地 docker 网桥 (cbr0)
  • 该节点将被标记为就绪,并且 kube-scheduler 将开始将 pod 分配到该节点
  • kubelet 看到分配的 pod 后,它将运行它们