1. 认识Kubernetes
1.1 应用部署方式演变
在部署应用程序的方式上,主要经历了三个时代:
传统部署:互联网早期,会直接将应用程序部署在物理机上
优点:简单,不需要其它技术的参与
缺点:不能为应用程序定义资源使用边界,很难合理地分配计算资源,而且程序之间容易产生影响
虚拟化部署:可以在一台物理机上运行多个虚拟机,每个虚拟机都是独立的一个环境
优点:程序环境不会相互产生影响,提供了一定程度的安全性
缺点:增加了操作系统,浪费了部分资源
容器化部署:与虚拟化类似,但是共享了操作系统
优点:
可以保证每个容器拥有自己的文件系统、CPU、内存、进程空间等
运行应用程序所需要的资源都被容器包装,并和底层基础架构解耦
容器化的应用程序可以跨云服务商、跨Linux操作系统发行版进行部署
容器化部署方式给带来很多的便利,但是也会出现一些问题,比如说:
- 一个容器故障停机了,怎么样让另外一个容器立刻启动去替补停机的容器
- 当并发访问量变大的时候,怎么样做到横向扩展容器数量
这些容器管理的问题统称为容器编排问题,为了解决这些容器编排问题,就产生了一些容器编排的软件:
- Swarm:Docker自己的容器编排工具
- Mesos:Apache的一个资源统一管控的工具,需要和Marathon结合使用
- Kubernetes:Google开源的的容器编排工具
1.2 什么是Kubernetes?
Kubernetes官方文档:https://kubernetes.io/zh-cn/docs/home/
Kubernetes 是一个可移植、可扩展的开源平台,用于管理容器化的工作负载和服务,方便进行声明式配置和自动化。Kubernetes 拥有一个庞大且快速增长的生态系统,其服务、支持和工具的使用范围广泛。
Kubernetes 这个名字源于希腊语,意为“舵手”或“飞行员”。K8s 这个缩写是因为 K 和 s 之间有 8 个字符的关系。
1.3 为什么需要Kubernetes?
kubernetes的本质是一组服务器集群,它可以在集群的每个节点上运行特定的程序,来对节点中的容器进行管理。目的是实现资源管理的自动化,主要提供了如下的主要功能:
- 自我修复:一旦某一个容器崩溃,能够在1秒中左右迅速启动新的容器
- 弹性伸缩:可以根据需要,自动对集群中正在运行的容器数量进行调整
- 自动部署和回滚:如果发现新发布的程序版本有问题,可以立即回退到原来的版本
- 服务发现和负载均衡:服务可以通过自动发现的形式找到它所依赖的服务,如果一个服务起动了多个容器,能够自动实现请求的负载均衡
- 存储编排:可以根据容器自身的需求自动创建存储卷
- 机密和配置管理
- 批处理
2. 集群架构与组件
2.1 kubernetes组件
一个kubernetes集群主要是由**控制节点(master)、工作节点(node)**构成,每个节点上都会安装不同的组件。
2.1.1 控制面板组件(Control Plane Components)
Kubernetes组件:https://kubernetes.io/zh-cn/docs/concepts/overview/components/

管理集群的整体状态(这些组件都在master节点):
-
公开 Kubernetes HTTP API 的核心组件服务器
基于REST风格开放k8s接口的服务。
-
运行控制器来实现 Kubernetes API 行为。
控制器管理器:管理各个类型的控制器,针对k8s中的各种资源进行管理。
这些控制器包括:
- 节点控制器(Node Controller):负责在节点出现故障时进行通知和响应。
- 任务控制器(Job Controller):监测代表一次性任务的Job对象,然后创建Pods来运行这些任务直至完成。
- 端点分片控制器(EndpointSlice Controller):填充端点分片(EndpointSlice)对象(以提供Service和Pod之间的连接)。
- 服务账号控制器(ServiceAccount Controller):为新的命名空间创建默认的服务账号(ServiceAccount)。
cloud-controller-manager (optional)
与底层云驱动集成
云控制管理器:第三方云平台提供的控制器API对接管理功能。
-
查找尚未绑定到节点的 Pod,并将每个 Pod 分配给合适的节点
调度器:负责将 Pod 基于一定算法,将其调用到更合适的节点(服务器)上。
-
具备一致性和高可用性的键值存储,用于所有 API 服务器的数据存储
理解为k8s的数据库,键值类型存储的分布式数据库,提供了基于Raft算法实现自主的集群高可用。
新老版本存储区别:老版本(基于内存),新版本(持久化存储)
2.1.2 节点组件

在每个节点上运行,维护运行的 Pod 并提供 Kubernetes 运行时环境:
-
确保 Pod 及其容器正常运行。
负责 Pod 的生命周期、存储、网络。
kube-proxy(可选)
维护节点上的网络规则以实现 Service 的功能。
网络代理,负责 Service 的服务发现、负载均衡(4层负载)。(仅仅只是内部网络访问)
-
负责运行容器的软件,阅读容器运行时以了解更多信息。
容器运行时环境:docker、containerd、CRI-O
2.1.3 附加组件(Addons)
插件扩展了 Kubernetes 的功能。一些重要的例子包括:
-
集群范围内的 DNS 解析
负责为整个集群提供DNS服务
Web 界面(Dashboard)
通过 Web 界面进行集群管理
-
用于收集和存储容器指标
-
用于将容器日志保存到中央日志存储
Ingress Controller
为服务提供外网入口
2.2 分层架构

生态系统
接口层
管理层
系统度量(如基础设施、容器和网络的度量),自动化(如自动扩展、动态 Provision等)以及策略管理(RBAC、Quota、PSP、NetworkPolicy等)。
应用层
部署(无状态应用、有状态应用、批处理任务、集群应用等)和路由(服务发现、DNS 解析等)
核心层
Kubernetes最核心的功能,对外提供 API 构建高层的应用,对内提供插件式应用执行环境。
3. 核心概念与专业术语
3.1 服务的分类
3.1.1 无状态应用
无状态应用:不会对本地环境产生任何依赖,例如不会存储数据到本地磁盘
代表应用:Nginx、Apache
优点:对客户端透明,无依赖关系,可以高效实现扩容、迁移
缺点:不能存储数据,需要额外的数据服务支撑
3.1.2 有状态应用
有状态应用:会对本地环境产生任何依赖,例如需要存储数据到本地磁盘
代表应用:MySQL、Redis
优点:可以独立存储数据,实现数据管理
缺点:集群环境下需要实现主从、数据同步、备份、水平扩容复杂
3.2 资源和对象
3.2.1 资源的分类
3.2.1.1 元数据型
元空间(元数据级别的资源),每一个资源都可以使用元空间的数据。
Horizontal Pod Autoscaler(HPA)
Horizontal Pod Autoscaler(HPA)介绍
Pod自动扩容:可以根据CPU使用率或自定义指标(metrics)自动对Pod进行扩/缩容。 - 控制管理器每隔30s(可以通过-horizontal-pod-autoscaler-sync-period修改)查询metrics的资源使用情况 - 支持三种metrics类型 - 预定义metrics(比如Pod的CPU)以利用率的方式计算 - 自定义的Pod metrics,以原始值(raw value)的方式计算 - 自定义的object metrics - 支持两种metrics查询方式:Heapster和自走义的RESTAPI - 支持多metrics
PodTemplate
Pod Template 是关于 Pod 的定义,但是被包含在其他的Kubernetes对象中(例如 Deployment、StatefulSet、Daemonset等控制器)。控制器通过 Pod Template 信息来创建Pod。
LimitRange
可以对集群内 Request 和 Limits 的配置做一个全局的统一的限制,相当于批量设置了某一个范围内(某个命名空间)的 Pod的资源使用限制。
3.2.1.2 集群
集群级别的资源,作用于集群之上,集群下的所有资源都可以共享使用。
Namespace
Node
不像其他的资源(如 Pod 和 Namespace),Node 本质上不是Kubernetes 来创建的,Kubernetes 只是管理 Node上的资源。虽然可以通过 Manifest 创建一个Node对象(如下json 所示)但 Kubernetes 也只是去检查是否真的是有这么一个 Node,如果检查失败,也不会往上调度 Pod。
ClusterRole
ClusterRoleBinding
根据名字可知只能绑定到集群角色级别。
3.2.1.3 命名空间(重点关注的地方)
命名空间级别的资源,通常只能在该命名空间范围内使用。
工作负载型
Pod
Pod(容器组)是 Kubernetes 中最小的可部署单元。一个Pod(容器组)包含了一个应用程序容器(某些情况下是多个容器)、存储资源、一个唯一的网络 IP 地址、以及一些确定容器该如何运行的选项。Pod 容器组代表了 Kubernetes 中一个独立的应用程序运行实例,该实例可能由单个容器或者几个紧耦合在一起的容器组成。 Docker 是 Kubernetes Pod 中使用最广泛的容器引擎; Kubernetes Pod 同时也支持其他类型的容器引擎。 Kubernetes 集群中的 Pod 存在如下两种使用途径: - 一个 Pod 中只运行一个容器。"one-container-per-pod"是Kubernetes 中最常见的使用方式。此时,您可以认为Pod容器组是该容器的 wrapper,Kubernetes 通过 Pod 管理容器,而不是直接管理容器。 - 一个 Pod 中运行多个需要互相协作的容器。您可以将多个紧密耦合、共享资源且始终在一起运行的容器编排在同一个Pod 中。
副本(replicas)
先引入“副本”的概念——一个 Pod 可以被复制成多份,每一份可被称之为一个“副本”,这些“副本”除了一些描述性的信息(Pod的名字、uid 等)不一样以外,其它信息都是一样的,譬如Pod内部的容器、容器数量、容器里面运行的应用等的这些信息都是一样的,这些副本提供同样的功能。 Pod 的“控制器”通常包含一个名为“replicas”的属性。“replicas”属性则指定了特定 Pod 的副本的数量,当当前集群中该 Pod 的数量与该属性指定的值不一致时,k8s会采取一些策略去使得当前状态满足配置的要求。
控制器
适用于无状态服务
ReplicationController(RC) (弃用)ReplicaSet(RS)
帮助我们动态更新 Pod 的副本数,可以通过 selector 来选择对哪些 Pod 生效(RC不支持selector)
Deployments(常用,重点)
针对RS的更高层次的封装,提供了更丰富的部署相关的功能。
比如:创建 Replica Set/Pod、滚动升级/回滚、平滑扩容和缩容、暂停与恢复Deployment
适用有状态服务
StatefulSet 是用来管理有状态应用的工作负载 API 对象。
主要特点:
- 稳定的持久化存储
- 稳定的网络标志
- 有序部署,有序扩展
- 有序收缩,有序删除
组成:
- Headless Service(对于有状态服务的DNS管理)
- volumeClaimTemplate(用于创建持久化卷的模板)
注意事项:
- 所有Pod的Volume必须使用PersistentVolume或者是管理员事先创建好
- 为了保证数据安全,删除Statefulset时不会删除Volume
- StatefulSet需要一个Headless Service 来定义 DNSdomain,需要在 StatefulSet 之前创建好
守护进程
Daemonset 保证在每个Node上都运行一个容器副本,常用来部署一些集群的日志、监控或者其他系统管理应用。典型的应用包括:
- 日志收集,比如 fuentd,logstash等
- 系统监控,比如 Prometheus Node Exporter,collectd,New Relic agent,Ganglia gmond 等
- 系统程序,比如 kube-proxy,kube-dns,glusterd,ceph 等
任务/定时任务
- Job:一次性任务,运行完成后Pod销毁,不再重新启动新容器。
- CronJob:CronJob是在Job基础上加了定时功能。
服务发现
- Service:实现 k8s 集群内部网络调用、负载均衡(四层负载)。
- Ingress:Ingress实现将 k8s 内部服务暴露给外网访问的服务。
存储
Volume:数据卷,共享 Pod 中容器使用的数据。用来存放持久化的数据,比如数据库数据。
CSI:Container Storage Interface 是由来自 Kubernetes、Mesos、Docker 等社区成员联合制定的一个行业标准接口规范,旨在将任意存储系统暴露给容器化应用程序。
CSI规范定义了存储提供商实现 CSI 兼容的 Volume Plugin 的最小操作集和部署建议。CSI 规范的主要焦点是声明 Volume Plugin必须实现的接口。
特殊类型配置
- ConfigMap
- Secret
- DownwardAPI
其他
- Role
- RoleBinging
3.2.2 资源清单
参数名 | 类型 | 字段说明 |
---|---|---|
apiVersion | String | K8S APl 的版本,可以用 kubectl api versions 命令查询 |
kind | String | yam 文件定义的资源类型和角色 |
metadata | Object | 元数据对象,下面是它的属性 |
metadata.name | String | 元数据对象的名字,比如 pod 的名字 |
metadata.namespace | String | 元数据对象的命名空间 |
Spec | Object | 详细定义对象 |
spec.containers[] | list | 定义 Spec 对象的容器列表 |
spec.containers[].name | String | 为列表中的某个容器定义名称 |
spec.containers[].image | String | 为列表中的某个容器定义需要的镜像名称 |
spec.containers[].imagePullPolicy | string | 定义镜像拉取策略,有 Always、Never、IfNotPresent 三个值可选 - Always(默认):意思是每次都尝试重新拉取镜像 - Never:表示仅适用本地镜像 - IfNotPresent:如果本地有镜像就使用本地镜像,没有就拉取在线镜像。 |
spec.containers[].command[] | list | 指定容器启动命令,因为是数组可以指定多个,不指定则使用镜像打包时使用的启动命令。 |
spec.containers[].args[] | list | 指定容器启动命令参数,因为是数组可以指定多个。 |
spec.containers[].workingDir | string | 指定容器的工作目录 |
spec.containers[].volumeMounts[] | list | 指定容器内部的存储卷配置 |
spec.containers[].volumeMounts[].name | string | 指定可以被容器挂载的存储卷的名称 |
spec.containers[].volumeMounts[].mountPath | string | 指定可以被容器挂载的存储卷的路径 |
spec.containers[].volumeMounts[].readOnly | string | 设置存储卷路径的读写模式,ture 或者 false,默认是读写模式 |
spec.containers[].ports[] | list | 指定容器需要用到的端口列表 |
spec.containers[].ports[].name | string | 指定端口的名称 |
spec.containers[].ports[].containerPort | string | 指定容器需要监听的端口号 |
spec.containers[].ports[].hostPort | string | 指定容器所在主机需要监听的端口号,默认跟上面 containerPort 相同,注意设置了 hostPort 同一台主机无法启动该容器的相同副本(因为主机的端口号不能相同,这样会冲突) |
spec.containers[].ports[].protocol | string | 指定端口协议,支持 TCP 和 UDP,默认值为 TCP |
spec.containers[].env[] | list | 指定容器运行前需设置的环境变量列表 |
spec.containers[].env[].name | string | 指定环境变量名称 |
spec.containers[].env[].value | string | 指定环境变量值 |
spec.containers[].resources | Object | 指定资源限制和资源请求的值(这里开始就是设置容器的资源上限) |
spec.containers[].resources.limits | Object | 指定设置容器运行时资源的运行上限 |
spec.containers[].resources.limits.cpu | string | 指定 CPU 的限制,单位为 Core 数,将用于 docker run –cpu-shares 参数 |
spec.containers[].resources.limits.memory | string | 指定 mem 内存的限制,单位为 MIB、GiB |
spec.containers[].resources.requests | Object | 指定容器启动和调度时的限制设置 |
spec.containers[].resources.requests.cpu | string | CPU请求,单位为core数,容器启动时初始化可用数量 |
spec.containers[].resources.requests.memory | string | 内存请求,单位为MIB、GiB,容器启动的初始化可用数量 |
spec.restartPolicy | string | 定义 pod 的重启策略,可选值为 Always、OnFailure、Never,默认值为 Always。 - Always:pod 一旦终止运行,则无论容器是如何终止的,kubelet 服务都将重启它。 - OnFailure:只有 pod 以非零退出码终止时,kubelet 才会重启该容器。如果容器正常结束(退出码为0),则 kubectl 将不会重启它。 - Never:Pod 终止后,kubelet 将退出码报告给 master,不会重启该 pod |
spec.nodeSelector | Object | 定义 Node 的 label 过滤标签,以 key:value 格式指定 |
spec.imagePullSecrets | Object | 定义 pull 镜像时使用 secret 名称,以 name:secretkey 格式指定 |
spec.hostNetwork | Boolean | 定义是否使用主机网络模式,默认值为 false。设置 true 表示使用宿主机网络,不使用 docker 网桥,同时设置了 true将无法在同一台宿主机上启动第二个副本 |
3.3 对象规约和状态
规约(Spec)
“spec”是“规约”、“规格” 的意思,spec 是必需的,它描述了对象的期望状态(Desired state)——希望对象所具有的特征。当创建 Kubernetes 对象时,必须提供对象的规约,用来描述该对象的期望状态,以及关于对象的一些基本信息(例如名称)。
状态(Status)
表示对象的实际状态,该属性由 k8s 自己维护,k8s会通过一系列的控制器对对应对象进行管理,让对象尽可能的让实际状态与期望状态重合。