K8S系列深入解析无状态服务
Posted 颜淡慕潇
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了K8S系列深入解析无状态服务相关的知识,希望对你有一定的参考价值。
目录
序言
所有幸运和巧合的事,要么是上天注定,要么是一个人偷偷的在努力。
文章标记颜色说明:
- 黄色:重要标题
- 红色:用来标记结论
- 绿色:用来标记一级论点
- 蓝色:用来标记二级论点
Kubernetes (k8s) 是一个容器编排平台,允许在容器中运行应用程序和服务。今天学习一下无状态服务。
1. 无服务介绍
无状态服务是一种不需要保存任何数据状态的服务,也不需要维护任何会话信息的服务。
这些服务通常被设计为可扩展和高可用性的,因为它们可以在任何时间点部署或删除,而不会对应用程序的可用性产生影响。
1.1 优点
无状态服务的优点包括:
可扩展性:由于无状态服务不需要维护状态信息,因此它们可以轻松地水平扩展,以应对高流量和负载情况。
高可用性:无状态服务可以通过多个副本来提高可用性,并且它们可以在任何时间点部署或删除,而不会影响应用程序的可用性。
简单性:由于无状态服务不需要维护状态信息,因此它们通常比有状态服务更简单、更容易维护。
1.2 使用场景
以下是一些无状态服务的使用场景详细介绍:
网络应用程序:无状态服务非常适合网络应用程序,例如Web服务器、API服务器、负载均衡器等。这些应用程序可以通过多个副本来提高可用性,并且它们可以通过水平扩展来处理更多的请求。
批处理作业:无状态服务也可以用于批处理作业,例如数据处理、日志分析、图像处理等。这些作业可以在任何时间点启动或停止,并且可以在多个节点上并行运行以提高效率。
队列服务:无状态服务还可以用于队列服务,例如消息队列、任务队列等。这些服务可以将消息或任务发送到队列中,并由多个工作者节点消费它们,以提高处理效率。
1.3 资源类型
在Kubernetes中,无状态服务资源类型主要包括以下几种:
Deployment:Deployment是一种用于创建可扩展的无状态服务的资源类型。它允许定义副本数,并使用Rolling Update策略来升级服务,从而保持服务的可用性。
ReplicaSet:ReplicaSet是Deployment的底层实现,用于确保在任何时间点都有指定数量的Pod副本在运行。当Pod崩溃或者被删除时,ReplicaSet会自动创建新的Pod副本,以确保所需的Pod副本数不变。
Pod:Pod是Kubernetes中最小的可部署单元,用于运行一个或多个容器。通常,每个Pod只运行一个容器,但在某些情况下,可能需要在同一个Pod中运行多个容器。
Service:Service是一种用于将多个Pod打包在一起并提供访问它们的统一入口的资源类型。Service可以使用Cluster IP、NodePort或者LoadBalancer等不同类型的服务来暴露Pod。
Ingress :Ingress 是一种 k8s 资源类型,用于将集群内部的 HTTP 和 HTTPS 流量路由到 Service 上。Ingress 可以根据域名或 URL 路径将流量转发到不同的 Service 上,并支持 SSL/TLS 终止和负载均衡等功能。
ConfigMap:ConfigMap 是一种 k8s 资源类型,用于将配置信息注入到无状态服务中。ConfigMap 可以存储键值对和配置文件等信息,并将它们作为环境变量、命令行参数或配置文件挂载到 Pod 中。
Ingress 和 Service、ConfigMap 一样,都是 Kubernetes 中的资源对象,它们都是抽象的概念,不包含任何具体的状态信息。Ingress 只是定义了一组规则,而 Service 则定义了如何暴露一个或多个 Pod,以便可以从集群内部或外部访问它们。因此,Ingress 和 Service 都可以看作是无状态的 Kubernetes 资源对象。
总之,使用Kubernetes中的无状态服务资源类型,可以更轻松地管理和扩展无状态服务,并提高其可用性和可靠性。
1.4 总结
无状态服务并不适用于所有的应用程序。一些应用程序可能需要维护会话信息、状态信息或持久化数据,这就需要使用有状态服务。
因此,在设计应用程序时,需要考虑应用程序的特定要求,以确定应该使用无状态服务还是有状态服务。
2 使用介绍
2.1 Deployment
Deployment资源控制器将用户定义的Deployment对象转换为实际运行的Pods,并确保Pods的状态与用户定义的状态一致。如果某个Pod因为某些原因被删除了,Deployment控制器会启动一个新的Pod,以确保在任何时候都有指定数量的Pods在运行。
Deployment 是 Kubernetes 中一种常用的资源类型,用于定义一组可扩展的 Pod,并确保它们按照所需的副本数在集群中运行。
Deployment 可以:
- 确保应用程序在集群中始终以所需的副本数运行。
- 自动升级应用程序,以便部署新的版本。
- 自动回滚到以前的版本,以便应对故障情况。
- 通过滚动升级、重启或暂停来更新部署。
下面是一个使用 Deployment 创建一个可扩展的 nginx 服务的示例:
apiVersion: apps/v1
kind: Deployment #资源类型
metadata:
name: nginx-deployment
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
该示例使用了 Deployment 资源来创建一个名为 nginx-deployment 的部署。该部署将创建 3 个副本,并使用 label 选择器来识别与该部署关联的 Pod。
该示例的 Pod 使用了 nginx:latest 镜像,并且暴露了容器端口 80。
要部署该示例,将 YAML 文件保存为 nginx-deployment.yaml 并运行以下命令:
kubectl apply -f nginx-deployment.yaml
该命令将在集群中创建一个名为 nginx-deployment 的 Deployment,并自动创建与其相关的 3 个 Pod。
要更新部署的镜像,可以通过编辑 YAML 文件并运行以下命令来轻松更新:
kubectl apply -f nginx-deployment.yaml
Kubernetes 将自动将更新部署,并逐步将所有 Pod 升级到新版本。
总结一下,Deployment 资源是 Kubernetes 中一个非常有用的资源类型,它使得容器化应用程序的部署和管理变得更加容易和可靠。
使用场景:
应用程序部署:使用 Kubernetes Deployment 可以轻松地部署您的应用程序,并确保它们始终以所需的方式运行。您可以定义应用程序的副本数、容器映像、存储和网络设置等。
应用程序升级和回滚:使用 Kubernetes Deployment 可以轻松地升级和回滚您的应用程序。您可以定义应用程序的新版本,并控制升级的速率和流程。如果需要回滚,则可以通过简单的命令将应用程序回退到旧版本。
水平扩展:使用 Kubernetes Deployment 可以根据负载自动扩展应用程序。您可以定义水平扩展规则,并让 Kubernetes 自动扩展您的应用程序。
服务发现和负载均衡:使用 Kubernetes Deployment 可以轻松地为您的应用程序定义服务发现和负载均衡规则。Kubernetes 可以自动将流量路由到正确的副本集,并确保它们始终处于健康状态。
多环境部署:使用 Kubernetes Deployment 可以轻松地在不同的环境(如开发、测试和生产)之间部署应用程序。您可以使用不同的配置文件和策略来定义不同的部署规则,从而确保您的应用程序在不同的环境中始终以所需的方式运行。
2.2 ReplicaSet
Kubernetes的ReplicaSet(副本集)是一种控制器(Controller),用于确保Pod的副本数始终保持在指定的数量。如果发现副本数低于预期,则ReplicaSet将自动创建新的Pod。相反,如果副本数多于预期,则会删除多余的Pod。
以下是一个ReplicaSet的示例定义:
文件名:example-rs.yaml
apiVersion: apps/v1
kind: ReplicaSet #资源类型
metadata:
name: example-rs
spec:
replicas: 3
selector:
matchLabels:
app: example
template:
metadata:
labels:
app: example
spec:
containers:
- name: example
image: nginx:latest
逐行解释这个示例:
apiVersion: apps/v1
:表示使用API版本v1的apps组。kind: ReplicaSet
:表示我们定义的是ReplicaSet对象。metadata
:包含ReplicaSet的元数据,如名称、标签和注释。name: example-rs
:指定ReplicaSet的名称。spec
:定义了ReplicaSet的规范,包括副本数、选择器和Pod模板。replicas: 3
:指定我们要运行的Pod副本数为3个。selector
:指定要选择的Pod标签。matchLabels
:指定匹配的标签,与模板中的标签相同。template
:定义了要创建的Pod模板。metadata
:定义了Pod元数据,如标签。labels
:指定Pod标签,与选择器中的标签相同。spec
:指定了Pod的规范,如容器和容器映像。containers
:定义了Pod中的容器。name: example
:定义了容器的名称。image: nginx:latest
:定义了容器映像。
创建这个ReplicaSet:
kubectl apply -f example-rs.yaml
这将创建一个名为
example-rs
的ReplicaSet,并确保有3个标记为app=example
的Pod在运行。如果Pod数目低于3个,则ReplicaSet将自动创建新的Pod。
如果要更新ReplicaSet,可以更新Pod模板的定义,并使用以下命令执行滚动更新:
kubectl apply -f example-rs.yaml
这将创建新的Pod,以替换旧的Pod,直到达到指定的副本数。这个过程被称为滚动更新。
要删除ReplicaSet及其所有Pod,可以使用以下命令:
kubectl delete rs example-rs
这个命令,删除名为
example-rs
的ReplicaSet及其所有Pod。
使用场景
ReplicaSet的主要使用场景包括:
扩展应用程序:通过创建多个Pod副本并在它们之间负载均衡,可以轻松地扩展应用程序的能力。
确保高可用性:当一个Pod副本出现故障时,ReplicaSet会自动创建一个新的Pod副本来替代它,从而确保应用程序的高可用性。
管理滚动升级:通过在ReplicaSet中定义新版本的Pod模板,可以实现滚动升级应用程序,从而最小化应用程序的停机时间。
确保资源利用率:通过控制Pod副本的数量,可以确保在负载轻的情况下不会浪费资源,同时在负载高峰期间有足够的资源可供使用。
2.3 pod
在 K8s 中,有两种主要类型的 Pod 资源:
Pod 资源定义:这是用于定义 Pod 规格的 YAML 或 JSON 文件。它描述了 Pod 的容器及其相关配置、网络、存储等信息。
Pod 运行时实例:这是由 Pod 资源定义创建的实际运行时实例。在运行时,K8s 负责管理 Pod 实例的生命周期、容器的运行状态以及网络和存储资源的分配。
Pod 资源定义示例
下面是一个 Pod 资源定义的示例:
apiVersion: v1
kind: Pod #资源类型
metadata:
name: my-pod
spec:
containers:
- name: my-container
image: nginx
ports:
- containerPort: 80
2.4 service
Kubernetes (K8s) Service是一种用于提供网络访问的抽象机制,用于将一组Pods公开为单个网络服务。服务提供了一个虚拟IP地址和一个DNS名称,允许客户端通过这些标识符访问Kubernetes集群中的应用程序。服务还允许负载平衡和自动容错,以确保即使在一个或多个Pod失败时,服务仍然可用。
在Kubernetes中,Service对象是一个Kubernetes API对象,可以使用Kubernetes API或kubectl命令行工具创建、管理和删除它们。
创建一个Service对象时,需要指定一个标签选择器,用于确定要将哪些Pods作为后端。Service还可以使用不同的负载平衡算法(如轮询或IP哈希)将请求路由到后端Pods。
下面是一个简单的Kubernetes Service示例:
创建一个Deployment:
apiVersion: apps/v1
kind: Deployment #资源类型
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx
replicas: 3
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
创建一个Service:
apiVersion: v1
kind: Service #资源类型
metadata:
name: nginx-service
spec:
selector:
app: nginx
type: ClusterIP
ports:
- name: http
port: 80
targetPort: 80
这个示例创建了一个名为
nginx-deployment
的Deployment,它运行3个Nginx Pod。接下来,它创建了一个名为
nginx-service
的Service,使用selector
指定将后端Pods选择器设置为app: nginx
。该Service使用默认的ClusterIP类型,并将所有传入流量路由到
80
端口。在这个示例中,
targetPort
被设置为80
,因为后端Pods也在80
端口上监听。
总结:
此时,可以通过Kubernetes集群内部的虚拟IP地址和DNS名称访问Nginx服务。
例如,在Kubernetes集群中的Pod中,可以使用
nginx-service
名称来访问该服务。注意:上述示例仅供参考,具体实现可能因Kubernetes版本和配置而异。请参阅Kubernetes文档以获取更多详细信息和最佳实践建议。
2.5 ingress
Kubernetes Ingress是一个API对象,它允许管理在集群内的HTTP和HTTPS路由。Ingress充当负载均衡器,将流量路由到集群内的服务。它还可以提供TLS终止和基于名称的虚拟主机。
在Kubernetes中,Ingress控制器是一个运行Ingress规则的实体。许多不同的Ingress控制器可用,如Nginx,Traefik,Istio等,它们具有不同的功能和优缺点。
以下是使用Kubernetes Ingress的示例:
安装Ingress控制器
不同的Ingress控制器安装方式可能不同,这里以Nginx为例:
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/provider/cloud/deploy.yaml
创建Ingress规则
创建一个Ingress对象以定义路由规则。以下示例将指定所有来自/example路径的HTTP请求将被路由到名为example-service的服务上:
apiVersion: networking.k8s.io/v1
kind: Ingress #资源类型
metadata:
name: example-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- http:
paths:
- path: /example
pathType: Prefix
backend:
service:
name: example-service
port:
number: 80
应用Ingress规则
使用以下命令将Ingress规则应用于Kubernetes集群:
kubectl apply -f example-ingress.yaml
访问服务
可以使用Ingress规则定义的路由访问服务。
http://ip地址/example
总结:
使用Kubernetes Ingress可以轻松地为集群内的服务设置路由规则,并将流量分发到相应的服务上。
同时,Ingress控制器的选择对性能和功能等方面也有一定影响,需要根据具体情况选择合适的控制器。
2.6 configMap
Kubernetes (k8s) 的 ConfigMap 是一种用于存储非敏感配置数据的 Kubernetes 对象。ConfigMap 可以包含键值对、文件或者纯文本数据,并可以在容器中通过环境变量、命令行参数或者挂载路径的方式使用。
以下是一个 k8s ConfigMap 的示例 YAML 文件:
apiVersion: v1
kind: ConfigMap #资源类型
metadata:
name: my-configmap
data:
CONFIG_VAR1: value1
CONFIG_VAR2: value2
CONFIG_FILE: |-
This is the content of a file in the ConfigMap.
It can be accessed in a container as a volume.
上面的示例定义了一个名为
my-configmap
的 ConfigMap 对象,其中包含三个键值对:CONFIG_VAR1
、CONFIG_VAR2
和CONFIG_FILE
。CONFIG_FILE
中包含了一些纯文本数据,可以在容器中以挂载的方式访问。
下面是一个使用 ConfigMap 的示例 YAML 文件:
apiVersion: v1
kind: Pod #资源类型为pod
metadata:
name: my-pod
spec:
containers:
- name: my-container
image: nginx
env:
- name: VAR1
valueFrom:
configMapKeyRef:
name: my-configmap
key: CONFIG_VAR1
- name: VAR2
valueFrom:
configMapKeyRef:
name: my-configmap
key: CONFIG_VAR2
volumeMounts:
- name: config-volume
mountPath: /etc/config
readOnly: true
volumes:
- name: config-volume
configMap:
name: my-configmap
上面的示例定义了一个名为
my-pod
的 Pod 对象,其中包含一个名为my-container
的容器。该容器使用了
my-configmap
中的CONFIG_VAR1
和CONFIG_VAR2
值,并将my-configmap
中的CONFIG_FILE
文件挂载到容器的/etc/config
目录下。
总的来说,ConfigMap 是一种非常有用的 Kubernetes 对象,可以用于存储配置数据,并将其传递到容器中,以便在运行时使用。
3 总结
使用场景总结
以下是一些适合使用无状态服务的业务场景:
Web 应用程序:Web 应用程序通常是无状态的,它们的行为仅取决于用户的请求和输入。无状态服务可以帮助您轻松地扩展 Web 应用程序并提高其可靠性。
批处理作业:批处理作业通常是独立的任务,它们的执行不需要存储状态信息。无状态服务可以帮助您快速地运行大规模的批处理作业。
计算密集型应用程序:计算密集型应用程序通常需要大量的计算资源来处理数据。无状态服务可以帮助您快速地扩展应用程序以处理更多的计算任务。
微服务架构:在微服务架构中,服务通常被设计为无状态的。这是因为无状态服务可以更容易地扩展,并且更容易实现高可用性和负载均衡。
媒体流服务:媒体流服务通常是无状态的,因为它们不需要存储状态信息。无状态服务可以帮助您快速地扩展媒体流服务以处理更多的请求。
ReplicaSet 和 Deployment区别总结:
Kubernetes (k8s) ReplicaSet 和 Deployment 是两个常用的 Kubernetes 资源对象,它们都用于管理 Pod 的创建、扩展、缩减和更新。
Deployment 和 ReplicaSet 的使用场景:
- Deployment:Deployment 资源对象用于管理应用的版本更新。当您需要发布新版本的应用程序时,可以使用 Deployment 对象来创建一个新的 ReplicaSet,然后 Kubernetes 会逐步将 Pod 的数量从旧版本的 ReplicaSet 逐渐缩减到新版本的 ReplicaSet。如果发生故障,Deployment 会自动回滚至上一个可用版本。
- ReplicaSet:ReplicaSet 资源对象用于管理 Pod 的数量。如果您需要扩展或缩减 Pod 的数量,可以使用 ReplicaSet 对象来定义所需的副本数,并让 Kubernetes 自动创建或删除 Pod,以达到您定义的副本数。
Deployment 和 ReplicaSet 的区别:
- Deployment 是 ReplicaSet 的上层控制器,它在 ReplicaSet 的基础上增加了更多的更新、回滚和版本管理的功能,因此 Deployment 更适合用于应用程序版本的管理。
- ReplicaSet 负责确保 Pod 的数量达到指定的副本数,但是它不会关心 Pod 的版本号。因此 ReplicaSet 更适合用于控制相同版本的 Pod 的数量,以确保可用性和容错性。
K8S系列深入解析控制器
目录
序言
在你想要放弃的时候,想想是什么让你当初坚持走到了这里。
Kubernetes (k8s) 是一个容器编排平台,允许在容器中运行应用程序和服务。今天学习一下k8s 控制器。
文章标记颜色说明:
- 黄色:重要标题
- 红色:用来标记结论
- 绿色:用来标记一级论点
- 蓝色:用来标记二级论点
1 基础介绍
1.1 前情提要
回忆一下,我和你详细介绍了 Pod 的用法,讲解了 Pod 这个 API 对象的各个字段。而接下来,我们就一起来看看“编排”这个 Kubernetes 项目最核心的功能吧。
实际上,你可能已经有所感悟:Pod 这个看似复杂的 API 对象,实际上就是对容器的进一步抽象和封装而已。
说得更形象些,“容器”镜像虽然好用,但是容器这样一个“沙盒”的概念,对于描述应用来说,还是太过简单了。
这就好比,集装箱固然好用,但是如果它四面都光秃秃的,吊车还怎么把这个集装箱吊起来并摆放好呢?
所以,Pod 对象,其实就是容器的升级版。它对容器进行了组合,添加了更多的属性和字段。这就好比给集装箱四面安装了吊环,使得 Kubernetes 这架“吊车”,可以更轻松地操作它。
Kubernetes 操作这些“集装箱”的逻辑,都由控制器(Controller)完成
1.2 Kube-controller-manager介绍
Kube-controller-manager是Kubernetes中的一个控制器,是Kubernetes系统中的一个组件,负责运行一些后台控制循环(controller loop),并监视系统中的各个资源的状态。
kube-controller-manager通常运行在Master节点上。kube-controller-manager包含了多个控制器,每个控制器都负责处理不同的资源。
1.3 控制器类型
以下是kube-controller-manager中的一些重要控制器:
Deployment控制器:用于确保Deployment对象所管理的Pod副本数量符合预期,并且进行滚动更新(Rolling Update)。
ReplicaSet控制器:用于确保ReplicaSet对象所管理的Pod副本数量符合预期。
DaemonSet 控制器:DaemonSet 控制器用于在集群中的每个节点上启动一个 Pod 副本,以便运行一些系统级别的守护进程,如日志收集器和监控代理。如果有新的节点加入集群,DaemonSet 控制器会自动在新节点上启动相应的 Pod 副本。
StatefulSet控制器:用于确保StatefulSet对象所管理的有状态应用程序的副本数量符合预期。
Node控制器:用于确保所有Node对象的状态都是最新的,并管理Node的状态。
Service控制器:用于确保Service对象的状态符合预期,并处理Service的创建、更新和删除等操作。
Namespace控制器:用于确保Namespace对象的状态符合预期,并处理Namespace的创建、更新和删除等操作。
Endpoint控制器:用于确保Endpoint对象的状态符合预期,并处理Endpoint的创建、更新和删除等操作。
Job控制器:用于确保Job对象所管理的任务成功完成,并对失败的任务进行重试。
CronJob控制器:用于确保CronJob对象所管理的定时任务按照预期执行。
在kube-controller-manager中,每个控制器都是一个独立的进程,它们之间相互独立,互不影响。同时,kube-controller-manager会自动监视资源对象的状态变化,并触发相应的控制器处理,以确保系统状态的一致性和稳定性。
2 使用介绍
2.1 控制循环
了解具体的使用之前,需要先看下“循环控制”这个概念
在 Kubernetes 中,控制循环(control loop)是一种通用的编排模式,用于监控和控制集群中的资源。
控制循环通过对比当前状态和期望状态之间的差异来确保集群的期望状态得以实现。
具体而言,控制循环包括以下几个步骤:
监控资源状态:控制循环会定期检查集群中的资源状态,例如 Pod、Service、Deployment 等。
计算期望状态:根据 Kubernetes 集群的配置文件和用户提交的操作,控制循环会计算出资源的期望状态。例如,用户可能会提交一个 Deployment 的 YAML 文件,其中指定了需要部署的 Pod 数量和镜像版本等信息,控制循环就会根据这些信息计算出 Deployment 的期望状态。
对比当前状态和期望状态:控制循环会将当前状态和期望状态进行对比,找出二者之间的差异。例如,如果一个 Deployment 的期望 Pod 数量为 3,但是当前只有 2 个 Pod 在运行,那么控制循环就会发现这个差异。
执行调整操作:控制循环会根据差异来执行调整操作,使得当前状态逐渐接近期望状态。例如,控制循环会自动创建新的 Pod,以便使得 Deployment 中的 Pod 数量达到期望值。
重复执行:控制循环会一直重复上述步骤,直到当前状态和期望状态完全一致。
注意,控制循环并不是一个线性的过程,而是由多个控制器(Controller)组成的复杂系统。每个控制器都会负责监控和管理一个或多个资源,例如 Deployment、StatefulSet、DaemonSet 等。不同的控制器之间还可以相互协作,以实现更复杂的功能。
2.2 Deployment控制器
我们曾经使用过 Deployment 这个最基本的控制器对象。现在,我们一起来回顾一下这个名叫 nginx-deployment 的例子:
apiVersion: apps/v1
kind: Deployment #资源类型
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx
replicas: 2
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
这个 Deployment 定义的编排动作非常简单,即:确保携带了 app=nginx 标签的 Pod 的个数,永远等于 spec.replicas 指定的个数,即 2 个。
这就意味着,如果在这个集群中,携带 app=nginx 标签的 Pod 的个数大于 2 的时候,就会有旧的 Pod 被删除;反之,就会有新的 Pod 被创建。
这时,你也许就会好奇:究竟是 Kubernetes 项目中的哪个组件,在执行这些操作呢?
没错,就是今天介绍 kube-controller-manager 的组件。
那他具体怎么控制的呢?我们以这个 Deployment 为例,分析一下:
实际上,这个组件,是一系列控制器的集合。可以查看一下 Kubernetes 项目pkg/controller 目录:
$ cd kubernetes/pkg/controller/
$ ls -d */
deployment/ job/ podautoscaler/
cloud/ disruption/ namespace/
replicaset/ serviceaccount/ volume/
cronjob/ garbagecollector/ nodelifecycle/ replication/ statefulset/ daemon/
...
这个目录下面的每一个控制器,都以独有的方式负责某种编排功能。而我们的 Deployment,正是这些控制器中的一种。
实际上,这些控制器之所以被统一放在 pkg/controller 目录下,就是因为它们都遵循 Kubernetes 项目中的一个通用编排模式,即:控制循环(control loop)。就是上面说的那个控制循环
比如,现在有一种待编排的对象 X,它有一个对应的控制器。那么,用一段 Go 语言风格的伪代码,描述这个控制循环:
for
实际状态 := 获取集群中对象 X 的实际状态(Actual State)
期望状态 := 获取集群中对象 X 的期望状态(Desired State)
if 实际状态 == 期望状态
什么都不做
else
执行编排动作,将实际状态调整为期望状态
实际状态:
在具体实现中,实际状态往往来自于 Kubernetes 集群本身。
比如,kubelet 通过心跳汇报的容器状态和节点状态,或者监控系统中保存的应用监控数据,或者控制器主动收集的它自己感兴趣的信息,这些都是常见的实际状态的来源。
期望状态:
而期望状态,一般来自于用户提交的 YAML 文件。
比如,Deployment 对象中 Replicas 字段的值。
很明显,这些信息往往都保存在 Etcd 中。接下来,以 Deployment 为例,简单描述一下它对控制器模型的实现:
Deployment 控制器从 Etcd 中获取到所有携带了“app: nginx”标签的 Pod,然后统计它们的数量,这就是实际状态;
Deployment 对象的 Replicas 字段的值就是期望状态;
Deployment 控制器将两个状态做比较,然后根据比较结果,确定是创建 Pod,还是删除已有的 Pod
PodTemplate:
其实,像 Deployment 这种控制器的设计原理,就是“用一种对象管理另一种对象”的“艺术”。
其中,这个控制器对象本身,负责定义被管理对象的期望状态。比如,Deployment 里的 replicas=2 这个字段。
而被控制对象的定义,则来自于一个“模板”。比如,Deployment 里的 template 字段。
可以看到,Deployment 这个 template 字段里的内容,跟一个标准的 Pod 对象的 API 定义,丝毫不差。而所有被这个 Deployment 管理的 Pod 实例,其实都是根据这个 template 字段的内容创建出来的。
像 Deployment 定义的 template 字段,在 Kubernetes 项目中有一个专有的名字,叫作 PodTemplate(Pod 模板)。
这个概念非常重要,因为后面讲解到的大多数控制器,都会使用 PodTemplate 来统一定义它所要管理的 Pod。更有意思的是,我们还会看到其他类型的对象模板,比如 Volume 的模板。
至此,对 Deployment 以及其他类似的控制器,做一个简单总结了:
如上图所示,类似 Deployment 这样的一个控制器,实际上都是由
- 上半部分的控制器定义(包括期望状态)
- 下半部分的被控制对象的模板组成的
3 总结
在这篇文章中,以 Deployment 为例,详细分享了 Kubernetes 项目如何通过一个称作“控制器模式”(controller pattern)的设计方法,来统一地实现对各种不同的对象或者资源进行的编排操作。
这个实现思路,正是 Kubernetes 项目进行容器编排的核心原理。
在此后讲解 Kubernetes 编排功能的文章中,我都会遵循这个逻辑展开,并且带你逐步领悟控制器模式在不同的容器化作业中的实现方式。
4 投票
以上是关于K8S系列深入解析无状态服务的主要内容,如果未能解决你的问题,请参考以下文章
容器技术Docker K8s 12 容器服务Kubernetes版ACK详解-使用镜像快速创建无状态应用
Kubernetes基础_05_StatefulSet全解析(有状态的Pod)