本文档将对近期所学习到的k8s知识、概念进行简单的总结,并结合实践加以记录。
Kubernetes 是谷歌开源的容器集群管理系统,是 Google 多年大规模容器管理技术 Borg 的开源版本,主要功能包括:
- 基于容器的应用部署、维护和滚动升级
- 负载均衡和服务发现
- 跨机器和跨地区的集群调度
- 自动伸缩
- 无状态服务和有状态服务
- 广泛的 Volume 支持
- 插件机制保证扩展性
- ….
以上这些功能,几乎完美贴合一套运维架构体系。实现了运维的部署更新,动态扩容,这都交由k8s强大调度系统进行完成。
像以前单体的运维架构,无非就是:
提交代码仓库—>交由CI/CD工具进行源码的编译和打包—>将需要更新的应用包解压至服务器上—>逐一停止业务应用—>逐一启动—>完成更新
以上种种步骤,取决于运维团队的自动化、规范化完善度到达何种程度。有的通过脚本进行管控,有的可能会有运维发布平台。
目前,Kubernetes 是 DevOps 应用必须掌握的一个平台。如果要构建一套比较不错的devops 体系,那k8s是必不可少的。现在,提到容器第一个联想到的就是k8s,外加微服务时代的盛行,使用和学习k8s再适合不过了。
核心组件
Kubernetes 主要由以下几个核心组件组成:
etcd 保存了整个集群的状态;
apiserver 提供了资源操作的唯一入口,并提供认证、授权、访问控制、API 注册和发现等机制;
controller manager 负责维护集群的状态,比如故障检测、自动扩展、滚动更新等;
scheduler 负责资源的调度,按照预定的调度策略将 Pod 调度到相应的机器上;
kubelet 负责维护容器的生命周期,同时也负责 Volume(CVI)和网络(CNI)的管理;
Container runtime 负责镜像管理以及 Pod 和容器的真正运行(CRI);
kube-proxy 负责为 Service 提供 cluster 内部的服务发现和负载均衡
Kubernetes 整体架构
核心组件
组件通信
Kubernetes 多组件之间的通信原理为
- apiserver 负责 etcd 存储的所有操作,且只有 apiserver 才直接操作 etcd 集群
- apiserver 对内(集群中的其他组件)和对外(用户)提供统一的 REST API,其他组件均通过 apiserver 进行通信
- controller manager、scheduler、kube-proxy 和 kubelet 等均通过 apiserver watch API 监测资源变化情况,并对资源作相应的操作
- 所有需要更新资源状态的操作均通过 apiserver 的 REST API 进行
- apiserver 也会直接调用 kubelet API(如 logs, exec, attach 等),默认不校验 kubelet 证书,但可以通过
--kubelet-certificate-authority
开启(而 GKE 通过 SSH 隧道保护它们之间的通信)
比如典型的创建 Pod 的流程为
- 用户通过 REST API 创建一个 Pod
- apiserver 将其写入 etcd
- scheduluer 检测到未绑定 Node 的 Pod,开始调度并更新 Pod 的 Node 绑定
- kubelet 检测到有新的 Pod 调度过来,通过 container runtime 运行该 Pod
- kubelet 通过 container runtime 取到 Pod 状态,并更新到 apiserver 中
C/S 架构
从宏观上看,K8S 遵循 C/S 架构,可以用下面的图来表示:
1 | +-------------+ |
Master
Master
是整个 K8S 集群的大脑,他有几个重要的功能:
- 接收:外部的请求和集群内部的通知反馈
- 发布:对集群整体的调度和管理
- 存储:存储集群所需持久化的状态信息
Master
主要包含以下几个重要的组成部分:
1. Cluster state store
用来存储集群所有需要持久化的状态,并且提供watch
的功能支持,可以快速的通知各组件的变更等操作。
目前 Kubernetes 的存储层选择是etcd
,所以一般情况下,我们直接以etcd
来代表集群状态存储服务,即将所有状态存储到etcd
实例中。
2. API Server
这是整个集群的入口,类似于人体的感官,接收外部的信号和请求,并将相应的信息写入到etcd
中。
为了保证安全,API Server 还提供了认证相关的功能,用于判断客户端是否有权限进行操作。API Server 支持多种认证方法,不过一般情况下,我们使用x509
证书来进行认证。
API Server 的目标是成为一个极简的 Server,只提供
REST
操作,更新etcd
,并充当着集群的网关。至于其他的业务逻辑,则通过插件或者其他组件来实现
3. Controller Manager
Controller Manager 大概是 K8S 集群中最繁忙的部分,它在后台运行着许多不同的控制器进程,用来调节集群的状态。
当集群的配置发生改变时,控制器就会朝着预期的状态开始工作。
4. Scheduler
Scheduler 是集群的调度器,它会持续关注集群中未被调度的 Pod,并根据资源可用性、节点亲和性或是其他一些限制条件,通过绑定的 API 将 Pod 调度/绑定到 Node 上。
在这个过程中,调度程序一般只考虑调度开始时 Node 的状态,而不考虑在调度过程中 Node 的状态变化
节点(Node)
K8s集群中的计算能力由Node提供,最初Node称为服务节点Minion,后来改名为Node。K8s集群中的Node也就等同于Mesos集群中的Slave节点,是所有Pod运行所在的工作主机,可以是物理机也可以是虚拟机。不论是物理机还是虚拟机,工作主机的统一特征是上面要运行kubelet管理节点上运行的容器。
Pod
K8s有很多技术概念,同时对应很多API对象,最重要的也是最基础的是微服务Pod。Pod是在K8s集群中运行部署应用或服务的最小单元,它是可以支持多容器的。Pod的设计理念是支持多个容器在一个Pod中共享网络地址和文件系统,可以通过进程间通信和文件共享这种简单高效的方式组合完成服务。Pod对多容器的支持是K8s最基础的设计理念。比如你运行一个操作系统发行版的软件仓库,一个Nginx容器用来发布软件,另一个容器专门用来从源仓库做同步,这两个容器的镜像不太可能是一个团队开发的,但是他们一块儿工作才能提供一个微服务;这种情况下,不同的团队各自开发构建自己的容器镜像,在部署的时候组合成一个微服务对外提供服务。
Pod是K8s集群中所有业务类型的基础,可以看作运行在K8s集群中的小机器人,不同类型的业务就需要不同类型的小机器人去执行。目前K8s中的业务主要可以分为长期伺服型(long-running)、批处理型(batch)、节点后台支撑型(node-daemon)和有状态应用型(stateful application);分别对应的小机器人控制器为Deployment、Job、DaemonSet和StatefulSet。
Pod分类:
- 自主式Pod
- 由控制器管理的Pod,管理不同类型的Pod资源
- ReplicaSet(替代ReplicationController)
- Deployment(只能管理无状态的应用)
- StatefulSet(管理有状态的应用)
- DaemonSet(在每一个node上运行一个副本)
- Job(运行结束自动删除)
- Ctonjob(周期性job)
其中DaemonSet、Job、Ctonjob是给特殊应用使用,另外Deployment还支持二级控制器HPA(HorizontalPodAutoscaler),HPA控制器自动监控资源,当前服务能力不能满足时,自动扩展Pod,当Pod资源空闲时,自动回收资源,这些阈值由用户设置。
附上k8s各种对象详细表格:
Kubernetes主要模块概念:
名称 | 说明 |
---|---|
Cluster | Cluster是指由Kubernetes使用一系列的物理机、虚拟机和其他基础资源来运行你的应用程序。 |
Node | 一个node就是一个运行着Kubernetes的物理机或虚拟机,并且pod可以在其上面被调度。 |
Pod | 一个pod对应一个由相关容器和卷组成的容器组。 |
Label | 一个label是一个被附加到资源上的键/值对,例如附加到一个Pod上,为它传递一个用户自定的并且可识别的属性,Label还可以被应用来组织和选择子网中的资源。 |
selector | selector是一个通过匹配labels来定义资源之间关系得表达式,例如为一个负载均衡的service指定所目标Pod。 |
Replication Controller | replication controller 是为了保证一定数量被指定的Pod的复制品在任何时间都能正常工作,它不仅允许复制的系统易于扩展,还会处理当pod在机器在重启或发生故障的时候再次创建一个。 |
Service | 一个service定义了访问pod的方式,就像单个固定的IP地址和与其相对应的DNS名之间的关系。 |
Volume | 一个volume是一个目录,可能会被容器作为未见系统的一部分来访问。 |
Kubernetes volume | 构建在Docker Volumes之上,并且支持添加和配置volume目录或者其他存储设备。 |
Secret | Secret 存储了敏感数据,例如能允许容器接收请求的权限令牌。 |
Name | 用户为Kubernetes中资源定义的名字。 |
Namespace | Namespace 好比一个资源名字的前缀。它帮助不同的项目、团队或是客户可以共享cluster,例如防止相互独立的团队间出现命名冲突。 |
Annotation | 相对于label来说可以容纳更大的键值对,它对我们来说可能是不可读的数据,只是为了存储不可识别的辅助数据,尤其是一些被工具或系统扩展用来操作的数据。 |
一些实际应用的经验
- 在引用一个yaml文件时,请使用–record选项,带了这个选项之后,每次升级的时都会保存到部署的日志里面,这样就提供了回滚一个变更的能力。
- 部署大多数应用都需要配套一个service对象,如果需要外部访问需要映射NodePort类型
- 使用git管理k8s yml 可以方便回滚
- ….
实践
使用k8s创建应用
1 | cat > nginx-ds.yml <<EOF |
访问service资源映射的nodeport
1 | curl k8s-node01:22462 |