Kubernetes学习笔记
一、K8S简介Kubernetes是一个可移植的、可扩展的开源平台,用于管理容器化的工作负载和服务,可促进声明式配置和自动化。Kubernetes拥有庞大的且快速增长的生态系统。2014年,google开源了k8s。1.1、对于物理机时代、虚机时代、容器时代1、物理机时代:无法为物理服务器中的应用程序定义资源边界,会导致资源分配的问题。例如,如果在物理服务器上运行的多个应用程序,可能会出现一个应用
一、K8S简介
Kubernetes是一个可移植的、可扩展的开源平台,用于管理容器化的工作负载和服务,可促进声明式配置和自动化。Kubernetes拥有庞大的且快速增长的生态系统。
2014年,google开源了k8s。
1.1、对于物理机时代、虚机时代、容器时代
1、物理机时代:无法为物理服务器中的应用程序定义资源边界,会导致资源分配的问题。例如,如果在物理服务器上运行的多个应用程序,可能会出现一个应用程序占用大多数资源的情况,结果可能导致其他应用程序性能下降。一种解决方案是在不同物理服务器上运行每个应用程序,但由于资源不足而无法扩展。
2、虚机时代:虚拟化功能,允许您在单个物理服务器的CPU上运行多个虚拟机(VM)。虚拟化功能允许应用程序在VM之间隔离,并提供安全级别,因为一个应用程序的信息不能被另一个应用程序访问。
虚机可以更好地利用物理服务器中的资源,并实现更好的可伸缩性。
每个VM是一台完整的计算机,在虚拟化硬件之上运行所有组件,包括操作系统。
3、容器时代:容器类似于VM,但具有轻量级的隔离属性,可以在应用程序直接共享操作系统(OS)。因此,容器被认为是轻量级的。容器与VM类似,具有自己的文件系统、CPU、内存、进程空间等。
下面列举容器的好处:
- 方便部署:通过镜像
- 方便迁移:在dev, test, product环境中都一样
- 操作系统可移植性:在各操作系统上都可以运行
- 方便做微服务:应用程序被分级成较小的独立单元,且可以动态的部署和管理
- 资源隔离
1.2、为什么需要K8S?
在生成环境中,我们需要管理运行应用程序的容器,并确保他不会停机。例如一个容器故障,需要拉起另一个容器。
这就是为什么需要k8s, 它提供了一个可弹性运行分布式系统的框架,做容器扩容、故障转移、部署等。
K8S可提供如下功能:
- 服务发现和负载均衡:k8s可使用DNS名称或自己的IP地址来公开容器,如果容器的流量很大,k8s可以负载均衡并分配网络流量。
- 存储编排:k8s允许您自动挂载你选择的存储系统,如本地存储、公共云存档等
- 自动部署和回滚:如可自动化用k8s来创建新容器,删除容器并将它上面的资源用于新容器
- 自动二进制打包:k8s允许指定每个容器所需的CPU和内存。
- 自我修复:可重启失败的容器、替换容器、杀死不响应健康检查的容器,并且在准备好之前不提供服务给用户。
- 秘钥与配置管理:k8s允许你存储和管理敏感信息,如密码、OAuth、ssh秘钥等。
二、k8s组件
一个K8s集群包含一组被称为节点的机器组成,这些节点上运行了k8s所管理的容器化应用。集群至少一个工作节点和至少一个主节点。
工作节点:作为应用组件的Pod。
主节点:管理集群中的工作节点和Pod。多个主节点用于为集群提供故障转移和高可靠性。
下图展示了包含所有互相关联组件的k8s集群:
2.1、控制平面组件(Control Plane Components)
用于对集群做出全局决策(如调度),及检测和响应集群事件(例如,当不满足部署的replicas字段时,启动新的Pod)。
控制平面组件可以在集群中的任何节点上运行。然而,为了简单起见,设置脚本通常会再同一个计算机上启动所有控制平面组件,并且不会在此计算机上运行用户容器。
2.1.1、Kube-apiserver
主节点上负责提供k8s API服务的组件,他是k8s控制面的前端。
kube-apiserver在设计上考虑了水平扩缩容的需要。换言之,铜鼓部署多个实例可以实现扩缩容。
2.1.2、etcd
etcd是兼具一致性和高可用性的KV数据库,可作为保存k8s所有集群数据的后台数据库。
2.1.3、kube-scheduler
主节点上的组件,用于监视那些新创建的未指定运行节点的Pod,并选择节点让Pod在上面运行。
2.1.4、kube-controller-manager
在主节点上运行控制器的组件
从逻辑上讲,每个控制器都是一个单独的进程,但为了降低复杂性,他们被编译到同一个可执行文件,并在一个进程中运行。
这些控制器包括:
- 节点控制器(Node Controller):负责在节点出现故障时进行通知和响应
- 副本控制器(Replication Controller):负责为系统中的每个副本控制器对象维护正确数量的Pod。
- 端点控制器(Endpoints Controller):填充端点(Endpoints)对象(即加入Service与Pod)。
- 服务账户和令牌控制器(Service Account & Token Controllers):为新的命名空间创建默认账户和API访问令牌。
云控制管理器是1.8 alpha的特性,在未来发布的版本中,这将是k8s与其他云集成的最佳方式。
2.1.5、cloud-controller-manager
运行特定于云平台的控制回路。如果在自己的环境中运行k8s, 或在本地计算机中运行学习环境,所部署的环境中不需要云控制器管理利器。
与kube-controller-manager类似,cloud-controller-manager将若干逻辑上独立的控制回路组合到同一个可执行文件中,供你在统一进程中运行。你可以对其执行水平扩容以提升性能或增加容错能力。
下面的控制器都包含对云平台驱动的依赖:
- 节点控制器(Node Controller):用于在节点上终止响应后检查云提供商以确定节点是否已被删除
- 路由控制器(Route Controller):用于在底层云基础架构中设置路由
- 服务控制器(Service Controller):用于创建、更新和删除云提供商负载均衡器。
2.2、Node组件
节点组件在每个节点上运行,维护运行的Pod并提供k8s运行环境。
2.2.1、Kubelet
一个在集群中每个节点上运行的代理,他保证容器都运行在Pod中。
Kubelet接收一组通过各类机制提供给他的PodSpecs,确保这些PodSpecs中描述的容器处于运行状态并且健康。Kubelet不会管理不是由K8s创建的容器。
2.2.2、Kube-proxy
kube-proxy是集群中每个节点上运行的网络代理,实现k8s service概念中的一部分。
kube-proxy维护节点上的网络规则。这些网络规则允许从集群内部或外部的网络会话与Pod进行网络通信。
如果操作系统提供了数据包过滤层并可用的话,kube-proxy会通过他来实现网络规则。否则,kube-proxy仅转发流量本身。
2.2.3、容器运行时(Container Runtime)
容器运行时是负责运行容器的软件
k8s支持多个容器运行环境:Docker, containerd, cri-o, rktlet及任何实现k8s CRI(容器运行环境接口)
2.2.4、插件(Addons)
插件使用k8s资源(DaemonSet, Deployment等)实现集群功能。因为这些插件提供集群基本的功能,插件中命名空间域的资源属于kube-system命名空间。
2.2.5、DNS
尽管其他插件都并发严格意义上的必须组件,但几乎所有k8s集群都应该有集群DNS,因为很多实例都需要DNS服务。
集群DNS是一个DNS服务器,和环境中的其他DNS服务器一起工作,他为k8s服务提供DNS记录。
k8s启动的容器自动将此DNS服务器包含在其DNS搜索列表中。
2.2.6、Web界面(仪表盘)
Dashboard是k8s集群通用的、基于Web的用户界面。他使用户可以管理集群中的运行的应用程序以及集群本身并进行故障排除。
2.2.7、容器资源监控
容器资源监控将关于容器的一些常见的时间序列度量值保存到一个集中的数据库中,并提供用于浏览这些数据的界面。
2.9、集群层面日志
负责将容器的日志数据保存到一个集中的日志存储中,该存储能够提供搜索和浏览接口。
三、节点
k8s通过将容器放入在节点(Node)上运行的Pod中来执行你的工作负载。节点可以是一个虚拟机或物理机。每个Node都包含用于运行Pod所需的服务,这些服务由控制平面统一管理。
通常集群中会有多个节点。节点上的组件包括kubelet, 容器运行时和kube-proxy。
3.1、管理
向API服务器添加节点方式有两种:
1、节点上的kubelet向控制面执行自注册
2、手动添加一个Node对象
当你创建了Node对象,或者节点上的kubelet执行了自注册操作后,控制面会检测新的Node对象是否合法,例如,你使用下面的json来创建node:
{
"kind": "Node",
"apiVersion": "v1",
"metadata": {
"name": "10.240.79.157",
"labels": {
"name": "my-first-k8s-node"
}
}
}
k8s会再内部创建一个Node对象作为节点的标识,k8s检测kubelet向API服务器注册节点时使用的metadata.name字段是否匹配。如果节点是健康的(即所有必要的服务都在运行中),则该节点可以用来运行Pod。否则,直到该节点变为健康之前,所有的集群活动都会忽略该节点。
3.2、节点自注册
当 kubelet 标志 --register-node 为 true(默认)时,它会尝试向 API 服务注册自己。 这是首选模式,被绝大多数发行版选用。
对于自注册模式,kubelet使用下列参数启动:
- kubeconfig - 用于向 API 服务器表明身份的凭据路径。
- cloud-provider - 与某云驱动 进行通信以读取与自身相关的元数据的方式。
- register-node - 自动向 API 服务注册。
- register-with-taints - 使用所给的污点列表(逗号分隔的 =:)注册节点。 当 register-node 为 false 时无效。
- node-ip - 节点 IP 地址。
- node-labels - 在集群中注册节点时要添加的 标签。 (参见 NodeRestriction 准入控制插件所实施的标签限制)。
- node-status-update-frequency - 指定 kubelet 向控制面发送状态的频率。
3.3、手动节点管理
你可以使用kubectl 来创建和修改node对象
如果你希望手动创建节点对象时,请设置kebelet标志 --register-node=false
你可以结合使用节点上的标签和Pod尚的选择算法来控制调度。例如,你可以限制某Pod只能在符合要求的节点子集上运行。
如果标记节点为不可调度(unschedulable),将阻止新Pod调度到该节点上,但不会影响任何已经在其上的Pod。这是重启节点或执行其他维护操作之前的一个有用的准备步骤。
要标记一个节点为不可调度,执行以下命令:
kubectl cordon $NODENAME
3.4、节点状态
一个节点的状态包括:
- 地址
- 状况
- 容量与可分配
- 信息
可使用kubectl来查看节点状态:
kubectl describe node <节点名称>
3.4.1、地址
这些字段的用法取决于你的云服务商或物理机配置:
- HostName:由节点的内核设置。可以通过 kubelet 的 --hostname-override 参数覆盖。
- ExternalIP:通常是节点的可外部路由(从集群外可访问)的 IP 地址。
- InternalIP:通常是节点的仅可在集群内部路由的 IP 地址。
3.4.2、状况
conditions字段描述了所有Running节点的状态。状况的实例包括:
节点条件使用json对象表示。例如,下面的json表述了一个健康的节点:
"conditions": [
{
"type": "Ready",
"status": "True",
"reason": "KubeletReady",
"message": "kubelet is posting ready status",
"lastHeartbeatTime": "2019-06-05T18:38:35Z",
"lastTransitionTime": "2019-06-05T11:41:27Z"
}
]
如果 Ready 条件处于 Unknown 或者 False 状态的时间超过了 pod-eviction-timeout 值, (一个传递给 kube-controller-manager 的参数), 节点上的所有 Pod 都会被节点控制器计划删除。默认的逐出超时时长为 5 分钟。 某些情况下,当节点不可达时,API 服务器不能和其上的 kubelet 通信。 删除 Pod 的决定不能传达给 kubelet,直到它重新建立和 API 服务器的连接为止。 与此同时,被计划删除的 Pod 可能会继续在游离的节点上运行。
节点控制器在确认 Pod 在集群中已经停止运行前,不会强制删除它们。 你可以看到这些可能在无法访问的节点上运行的 Pod 处于 Terminating 或者 Unknown 状态。 如果 kubernetes 不能基于下层基础设施推断出某节点是否已经永久离开了集群, 集群管理员可能需要手动删除该节点对象。 从 Kubernetes 删除节点对象将导致 API 服务器删除节点上所有运行的 Pod 对象并释放它们的名字。
节点生命周期控制器会自动创建代表状况的 污点。 当调度器将 Pod 指派给某节点时,会考虑节点上的污点。 Pod 则可以通过容忍度(Toleration)表达所能容忍的污点。
capacity 块中的字段标识节点拥有的资源总量。 allocatable 块指示节点上可供普通 Pod 消耗的资源量。
第二个是保持节点控制器内的节点列表与云服务商所提供的可用机器列表同步。 如果在云环境下运行,只要某节点不健康,节点控制器就会询问云服务是否节点的虚拟机仍可用。 如果不可用,节点控制器会将该节点从它的节点列表删除
第三个是监控节点的健康情况。节点控制器负责在节点不可达 (即,节点控制器因为某些原因没有收到心跳,例如节点宕机)时, 将节点状态的 NodeReady 状况更新为 “Unknown”。 如果节点接下来持续处于不可达状态,节点控制器将逐出节点上的所有 Pod(使用体面终止)。 默认情况下 40 秒后开始报告 “Unknown”,在那之后 5 分钟开始逐出 Pod。 节点控制器每隔 --node-monitor-period 秒检查每个节点的状态。
kubelet 负责创建和更新 NodeStatus 和 Lease 对象。
当一个可用区域(Availability Zone)中的节点变为不健康时,节点的驱逐行为将发生改变。 节点控制器会同时检查可用区域中不健康(NodeReady 状况为 Unknown 或 False) 的节点的百分比。如果不健康节点的比例超过 --unhealthy-zone-threshold (默认为 0.55), 驱逐速率将会降低:如果集群较小(意即小于等于 --large-cluster-size-threshold 个节点 - 默认为 50),驱逐操作将会停止,否则驱逐速率将降为每秒 --secondary-node-eviction-rate 个(默认为 0.01)。 在单个可用区域实施这些策略的原因是当一个可用区域可能从控制面脱离时其它可用区域 可能仍然保持连接。 如果你的集群没有跨越云服务商的多个可用区域,那(整个集群)就只有一个可用区域。
跨多个可用区域部署你的节点的一个关键原因是当某个可用区域整体出现故障时, 工作负载可以转移到健康的可用区域。 因此,如果一个可用区域中的所有节点都不健康时,节点控制器会以正常的速率 --node-eviction-rate 进行驱逐操作。 在所有的可用区域都不健康(也即集群中没有健康节点)的极端情况下, 节点控制器将假设控制面节点的连接出了某些问题, 它将停止所有驱逐动作直到一些连接恢复。
节点控制器还负责驱逐运行在拥有 NoExecute 污点的节点上的 Pod, 除非这些 Pod 能够容忍此污点。 节点控制器还负责根据节点故障(例如节点不可访问或没有就绪)为其添加 污点。 这意味着调度器不会将 Pod 调度到不健康的节点上。
Kubernetes 调度器保证节点上 有足够的资源供其上的所有 Pod 使用。它会检查节点上所有容器的请求的总和不会超过节点的容量。 总的请求包括由 kubelet 启动的所有容器,但不包括由容器运行时直接启动的容器, 也不包括不受 kubelet 控制的其他进程。
四、容器
4.1、镜像
容器镜像(Image)所承载的是封装了应用程序及其所有软件依赖的二进制数据。 容器镜像是可执行的软件包,可以单独运行。
你通常会创建应用的容器镜像并将其推送到某仓库,然后在 Pod 中引用它。
五、工作负载
5.1、Pod
Pod是可以在k8s中创建和管理的最小的可部署的计算单元。
Pod是一组(一个或多个)容器;这些容器共享存储、网络、及怎样运行这些容器的声明。
Pod的共享上下文包括一组Linux命名空间、cgroup和可能一些其他的隔离方面。
Pod类似于共享namespace和文件系统卷的一组Docker容器。
5.2、使用Pod
可以用Deployment或job这类工作负载资源来创建Pod, 如果Pod需要跟踪状态,可以Kelvin用StatefulSet资源。
K8s集群中的Pod主要有两种用法:
1)运行单个容器的Pod:“每个Pod一个容器”模型是最常见的k8s用例;在这种情况下,可以将Pod看做单个容器的包装器,并且k8s直接管理Pod, 而不是容器。
2)运行多个协同工作的容器的Pod:Pod可能封装由多个紧密耦合且需要共享资源的共处容器组成的应用集群。这些位于同一位置的容器可能形成当个内聚的服务单元-- 一个容器将文件从共享卷提供给公众,而另一个单独的sidecar容器则刷新或更新这些文件,Pod将这些容器和存储资源打包为一个可管理的实体。
5.3、Pod和控制器
你可以使用工作负载资源来创建和管理多个Pod。资源的控制器能够处理副本的管理、上线,并在Pod失效时提供自愈的能力。
例如,如果一个节点不可用,控制器注意到该节点上的Pod已经停止工作,就可以创建替换性的Pod。调度器会替身Pod调度到一个监控的节点执行。
六、控制器
6.1、ReplicaSet
ReplicaSet是通过一组字段来定义的,包括一个用来识别可获得的Pod的集合的选择算符,一个用来表明应该维护的副本个数的数字,一个用来指定应该创建新Pod以满足副本个数条件时要使用的Pod模板等。
每个ReplicaSet都通过根据需要创建和删除Pod以是的副本个数达到期望值,进而实现其存在价值。
ReplicaSet确保任何时间都有指定数量的Pod副本在运行。但Deployment是一个更高级的概念,他管理ReplicaSet,并向Pod提供声明式更新及许多其他有用的功能。因此,我们建议使用Deployment而不是直接使用ReplicaSet,除非你需要自定义更新业务流程或根本不需要更新。
6.2、ReplicationController
ReplicationController确保在任何时候都有特定梳理的Pod副本处于运行状态。换句话说,ReplicationController确保一个Pod或一组同类的Pod总是可用的。
当Pod数量过多时,ReplicationController会终止多余的Pod。当Pod数量太少时,ReplicationController会启动新的Pod。与手动创建的Pod不同,由ReplicationController创建的Pod在失败、被删除或被终止时,会被自动替换。
6.3、Deployments
一个Deployment控制器为Pods和ReplicaSets提供描述性的更新方式。
Deployment是一个高级API对象,他以 kubectl rolling-update的方式更新其底层副本集及其Pod。如果你需要滚动更新功能,建议使用Deployment.
6.4、StatefulSet
StatefulSet用来管理有状态应用的工作负载API对象
StatefulSet用来管理Deployment和扩展一组Pod,并能为这些Pod提供序号和唯一性保证。
和Deployment相同的事,StatefulSet管理了基于相同容器定义的一组Pod。但和Deployment不同的是,StatefulSet为他们每个Pod维护了一个固定的ID。这些Pod是基于相同的声明来创建的,但不能互相替换;无论怎样调度,每个Pod都偶遇一个永久不变的ID。
6.5、DaemonSet
DaemonSet确保全部(或者某些)节点上运行一个Pod的副本。当有节点加入集群时,也会为他们新增一个Pod。当有节点从集群移除时,这些Pod也会被回收。删除DaemonSet将会删除他创建的所有的Pod。
DaemonSet的典型用法:
- 在每个节点上运行集群存储守护进程
- 在每个节点上运行日志搜集守护进程
- 在每个节点上运行监控守护进程。
一种简单的用法是为每种类型的守护进程在所有的节点上都启动一个DaemonSet;一个稍微复杂的用法是为同一种守护进程部署多个DaemonSet;每个具有不同的标志,并且对不同硬件类型具有不同的内存、CPU要求。
6.6、Jobs
Job会创建一个或多个Pods, 并确保指定数量的Pod成功完成。
更多推荐
所有评论(0)