一 Kubernetes API Server
Kubernetes API Server 提供了以下几种功能:
- 提供集群管理的 API 接口
- 成为集群内各个模块之间数据交互和通信的中心枢纽
- 拥有完备的集群安全机制
✨访问 Kubernetes API
Kubernetes API 通过一个叫 Kubernetes apiserver 的进程提供服务,这个进程运行在 kubernetes-master 节点上。该进程包含两个端口:
本地端口
- 该端口用于接受 HTTP 请求
- 该端口的默认值是 8080,IP 是 localhost
- 非认证或授权的 HTTP 请求可以通过该端口进行访问
安全端口
- 该端口默认为 6443,默认的 IP 为非本地(Non-localhost)网络端口
- 该端口用于接受 HTTPS 请求
- 用于基于 Token 文件或客服端证书以及 HTTP Base 进行认证
- Kubernetes 默认不启动该安全访问机制
Kubernetes 提供了一个代理 —— kubectl proxy,它即能作为 Kubernetes API 的反向代理,也可以作为普通的 client 来访问 Kubernetes API 的代理。Kubernetes 给我们提供来一个客户端工具 kubectl,用它将 kubernetes 提供的API 包装成命令集来使用:
kubectl [command] [options]
✨通过 API Server 访问 Node、Pod、Service
访问 Node
/api/v1/proxy/nodes/{name} // name 为节点的名称或者IP地址(REST 接口,支持CURD)
/api/v1/proxy/nodes/{name}/pods //列出该 Node 下所有 Pod 的信息
/api/v1/proxy/nodes/{name}/stats //列出该 Node 内物理资源的统计信息
/api/v1/proxy/nodes/{name}/spec //列出该 Node 概要信息
后面三个接口只有在该 Node 的 Kubelet 启动时包含 --enable-server=true
参数时才会开始。如果在启动时还包含了 --enbale-debugging-handlers=true
,那么 API Server 还会包含以下访问接口
/api/v1/proxy/nodes/{name}/run //在节点内运行一个 container,run 命令和 Docker 的 run 用法一致
/api/v1/proxy/nodes/{name}/exec //用法同上
/api/v1/proxy/nodes/{name}/attach //用法同上
/api/v1/proxy/nodes/{name}/logs //列出该 Node 的各类 log 信息
访问 Pod 提供的服务
/api/v1/namespaces/{namespace}/pods/{name}/proxy //访问Pod
/api/v1/namespaces/{namespace}/pods/{name}/proxy/{path:*} // 访问该 Pod 的某个服务的接口
访问 Service
如果 Service 包含 kubernetes.io/cluster-service:true
和 kubernetes.io/name:$CLUSTERSERVICENAME
(集群 Service 的名称) 标签,那么用户可以通过 API Server 的/api/v1/namespaces/{namespace}/services/{service}
接口来访问 Service,通过 /api/v1/namespaces/{namespace}/services/{service}/{path:*}
来访问该 Service 中的 Pod 中的 containers 提供的服务;
✨集群功能模块之间的通信
API Server 作为集群的核心,负责集群各功能模块之间的通信。各功能模块会通过 API Server 将信息存入 etcd ,其它模块可以(get、list、watch)读取这些信息,从而实现模块之间的通信;比如 Node 上的 kubelet 会定期的将自身的状态报告给 API Server,API Server 接收到信息之后会存入到 etcd 中,Controller Manager 中的 Node Manager 会定期的通过 API Server 读取 Node 的信息并做相应的处理;
二 调度器控制原理
Controller Manager 作为集群内部的管理控制中心,主要负责对 Node(Node Controller)、Pod 副本(Replication Controller)、Endpoint(Endpoint Controller)、Namespace(Namespace Controller)、服务账号(ServiceAccount Controller)、资源定额(ResourceQuota Controller)等管理并自动化修复。每种都对应了一个 Controller 进行管理,通过 API Server 监听共享状态,从而自动化实现从”现有状态“修复到”期望状态“。
✨ Replication Controller
为了区分 Controller Manager 中的 Replication Controller(副本控制器)和资源对象 Replication Controller,一般把资源对象 Replication Controller 简写为 RC。
Replication Controller 的核心作用就是确保在任何时候集群中的一个 RC 所关联的 Pod 都保持在一定的数量 Pod 副本处于正常运行的状态;以多退少补的原则对 Pod 副本进行管理,根据 RC 的定义,实现自动创建、补足、替换、删除 Pod 副本。
Pod 的几种状态
- pending:API Server 已经创建该 Pod,Pod 内还有一个or多个 container 的 image 还没有创建
- running:Pod 内所有的 container 都已创建,且至少有一个 container 处于运行状态或正在重启or启动
- succeeded:Pod 内所有的 container 都成功中止,且不会再重启
- failed:Pod 内所有 container 均已退出,且至少有一个 container 应为发生错误而退出
通常情况下,Pod 对象创建后不会消失,即使手动删除 Pod,除了使用 Replication Controller进行删除外唯一的例外是当 Pod 处于 succeeded 或 failed 状态的时间过长,该 Pod 会被回收。
RC 的使用
RC 可以被认为是一个模版文件,里面定义的是 Pod 的模版,里面包含 Pod 的标签属性,同时 RC 也包含了一个标签选择器(Label Selector),Selector 的值表明了该 RC 所关联的 Pod,从而筛选出该 RC 管理的 Pod。
kind: ReplicationController
apiVersion: v1
metadata:
name: teciplsrc
labels:
name: teciplsrc
spec:
replicas: 3
selector:
name: teciplsrc
template:
metadata:
labels:
name: teciplsrc
spec:
containers:
- image: xxxx
name: teciplsrc-01
这个 RC 创建了一个包含一个 container 的 Pod —— teciplsrc,包含三个副本。一旦 Pod 创建出来后,无论 RC 怎么改变都不会影响到 Pod,即使是删除,Pod 也可以通过修改 Label 来实现脱离该 RC 的控制,如果想要删除 Pod,则需要修改 RC 的副本数为0,这样所有的副本都会被干掉。
Replication Controller 的职责
- 确保当前集群中存在且仅有N个 Pod 实例
- 通过调整 RC 的 sprc.replicas 属性来控制 Pod 的副本数量(以此实现 重新调度、弹性收缩、滚动更新等功能)
✨ Node Controller
Node Controller 负责发现、管理和监控集群中的各 Node 节点,Node 节点的 kubelet 在启动时通过 API Server 注册节点信息,并定时向 API Server 发送节点信息,API Server 接受到信息后会存到 etcd 中。这些信息包括了节点的健康状况(就绪 True、未就绪False、未知Unknow)、节点资源、节点名称、节点地址、操作系统、Docker 版本等。
✨ ResourceQuota Controller
ResourceQuota Controller 确保指定的对象在任何时候都不会超量占用系统资源,避免了某些业务的进程设计或实现的缺陷导致整个系统运行紊乱的问题。ResourceQuota Controller 支持以下三个层次的资源配额管理:
- container 级别,可以对 CPU 和Memory 进行限制
- Pod 级别,可以对一个 Pod 内所有容器的可用资源进行限制
-
Namespace 级别,同一 Namespace 下的资源进行限制,包括 Pod 数量、Replication Controller 数量、Service 数量、ResourceQuota Controller 数量、Secret 数量、PV 数量等。
✨ Namespace Controller
用户通过 API Server 来创建新的 Namespace 并保存在 etcd 中,Namespace Controller 定时通过 API Server 读取 Namespace 信息。
如果 Namespace 被标记为删除,那么会将 Namespace 的状态置为 “Terminating” 并保存到 etcd 中,同时 Namespace Controller 会删除该 Namespace 下的所有的资源;在这种状态下,Adminssion Controller 的 NamespaceLifecycle 插件会阻止为该 Namespace 创建新的资源;当该 Namespace 下的资源被删干净后,Namespace Controller 会执行 finalize 操作,删除 spec.finalizers 域中的信息。当 Namespace Controller 检测到 Namespace 设置来删除期限,且 spec.finalzers 域值为空,那么就会通过 API Server 删除该 Namespace。
✨ Service Controller 与 Endpoint Controller
Kubernetes 中的 Service 同 Pod 类似也是一种资源,可以通过 API Server 中国中 POST 接口创建。
kind: Service
apiVersion: v1
metadata:
name: my-service
spec:
selector:
app: myApp
ports:
- port: 80
targetPort:9999
protocol: TCP
上面创建了一个名称为 my-service 的 Service,包含了一个选择器,通过这个选择器会选择所有包含该标签的 Pod 作为该 Service 的 Pod 集合。Pod 集合中每个 Pod 的80端口都会映射到该节点的 9999 端口,同时 Kubernetes 会指派一个集群 IP 给该 Service。
在创建 Service 时,如果指定了 selector,那么系统会自动创建一个和该 Service 同名的 Endpoint 资源对象,该 Endpoint 包含了一个地址和端口集合,分配给服务该选择器的 Pod 。
通过虚拟IP访问 Pod
每个 Node 节点上都运行了一个叫 kube-proxy 的进程,该进程会监控 Kubernetes Master 节点添加or删除 Service 和 Endpoint 的操作,kube-proxy 会为每个 Service 在当前所在 Node 上开一个端口(随机),任何访问该端口的连接都会代理到该 Service 中的某个 Pod 上。
集群外部访问 Service
Kubernetes 提供了两种方式来实现,一种是 NodePort ,另一种是 LoadBalancer。每个 Service 定义的 spec.type 域作为定于 Service 类型的地儿,有三个选项
- ClusterIP:默认值,仅使用集群内部虚拟IP
- NodePort:使用虚拟IP,同时通过在每个节点暴露相同的端口来暴露 Service
- LoadBalancer:使用虚拟IP和NodePort,并拥有负载均衡的功能
在 Kubernetes 1.0 中,NodePort 支持 TCP 和 UDP,而 LoadBalancer 仅支持 TCP。
Endpoint Controller 通过 store 缓存 Service 和 Pod 信息。如果监听到 Service 被删除,则会删除该 Service 和 同名的 Endpoint 对象;根据 Service 信息获取相关的 Pod 列表,创建新的 Endpoint 的 subset 对象。如果监听到新建or修改 Service,那么会根据 Service 的 name 和 labels 新建一个新的 Endpoint 对象,并同步到 etcd。
如果 Endpoint Controller 监听到添加 or 删除 Pod,则会从本地找到与该 Pod 相关的 Service 列表并更新相关的 Service 的 Endpoint 且保存到 etcd 中。
✨ Kubernetes Scheduler
Kubernetes Scheduler 负责对 Pod 的调度工作,起到了承上启下的作用。承上:接收 Controller Manger 创建的新 Pod;启下:安置好 Pod 后,会将对 Pod 管理的工作交给目标 Node 上的 Kubelet 服务进程。
- Scheduler 监听到 Pod Queue 有新的 Pod 需要创建
- 通过检测 NodeList 以及相应的调度算法和策略绑定到集群中某个合适 Node 上,并将绑定信息保存到 etcd 中
- Node 上的 kubelet 通过 API Server 监听到 Kubernetes Scheduler 产生的 Pod 绑定事件,获取到对应的 Pod 清单,下载 image 镜像,启动容器。