kubernetes pod 调度基础
一.replication controller和replicaset
1.replication controller
Replication Controller(复制控制器,RC)
目录
一.replication controller和replicaset
1.replication controller
(1)编辑replicationcontroller文件
(2)创建replicationcontroller
(3)删除一个pod并立即查看pod状态
(4)删除replicationconteroller
2:标签与标签选择器
(1)标签
(2)标签选择器
(3)标签与标签选择器举例
3: ReplicaSet
(1)编辑replicaset文件
(2)创建rs
二:无状态应用管理 Deployment
1:什么是无状态
2:无状态服务特点
(8)扩缩容方式:随机缩容
3.无状态服务的应用场景
4.创建deployment
(1)编写deployment文件
(2)使用kubectl create 创建此deployment
(3)查看Deployment 的状态
(4)使用rollout查看整个Deployment 的创建过程状态
(5)查看这个Deployment 对应的RS
(6)查看此Deployment 创建的pod
2:更新 Deployment
(1)更新pod的image
(2)查看更新过程
(3)此时的RS有新的和旧的
(4)通过describe 查看deployment 的详细信息
3:回滚 deployment
(1)多更新几次 deployment
(2)查看更新历史
(3)查看某次更新的详情
(4)回滚到指定版本
(5)回滚到指定版本
4:扩容deployment
(1)调整pod的副本数
5:删除 Deployment
三:有状态应用管理 StatefulSet
1:有状态服务的定义
2:有状态服务的特征
3:有状态服务的应用场景
4:无状态服务和有状态服务的比较
5:编写statefulSet 资源文件
(1)定义一个statefulSet 资源文件
(2)创建statefulSet
(3)查看statefilset 状态
(4)查看群集状态
6: statefulset扩容
7.缩容
(1)打开第二个终端,动态显示缩容流程
(2)在原来第一个终端修改副本数为2
(3)在第一个终端上查看最终结果
8:非级联删除 statefulset
(1)采用非级联删除
(2)查看管理的pod
(3)删除pod
9:级联删除 statefulset
(1)先创建出statefulset
(2)级联删除
(3)删除 redis服务
四:守护进程集 DaemonSet
1:什么是DaemonSet
2:定义一个DaemonSet
3: DaemonSet
4:查看DaemonSet
5:查看pod所在的节点
6:删除 DaemonSet
五:CronJob
1.创建cronjob
(1)编辑cronjob文件
(2)创建Cronjob
(3)查看创建结果
(4)查看生成的pod,并查看pod的执行日志
(5)删除Cronjob
一.replication controller和replicaset
RC用来确保Pod副本数达到期望值,这样可以确保一个或多个同类Pod总是可用的。如果存在的Pod数量大于设定的值,Replication Controller 将终止额外的Pod,如果太少,Replication Controller将会启动更多的Pod用于保证达到期望值,与手动创建Pod不同的是,用Replication Controller 维护的Pod在失败、删除或终止时会自动替换。因此,即使应用程序只需要一个Pod,也应该使用Replication Controller或其他方式管理。Replication Controller类似于进程管理程序,但是Replication Controller 不是监视单个节点上的各个进程,而是监视多个节点上的多个Pod。
Replication Controller的使用如下列示例。
(1)编辑replicationcontroller文件
vim replicationcontroller-nginx.yaml
apiVersion: v1kind: ReplicationControllermetadata:name: nginxspec:replicas: 3selector:app: ngin
template:metadata:name: nginxlabels:app: nginxspec:containers:- name: nginximage: nginx:1.7.9ports:- containerPort: 80
(2)创建replicationcontroller
kubectl apply -f replicationcontroller-nginx.yamlkubectl get podNAME READY STATUS RESTAPTS AGE
nginx-9g78r 1/1 Running 0 11mnginx-bbtqj 1/1 Running 0 11mnginx-w28bq 1/1 Running 0 11mkubect1 get rc
NAME DESIRED CURRENT READY AGEnginx 3 3 3 116s
(3)删除一个pod并立即查看pod状态
kubect1 delete pod nginx-9g78r -n defaultkubectl get pod
(4)删除replicationconteroller
kubectl delete -f replicationcontroller-nginx.yaml
2:标签与标签选择器
(1)标签
标签是用来标识K8S对象的一组附加在其上的键值对,通过标签我们可以方便地筛选或排除一组对象。借鉴资料中的话来讲,集群中的应用部署或是批处理的程序部署通常都是多维度的,为了实现对这些对象的管理,往往需要对某一特定维度的对象进行操作,而标签可以通过用户的意愿组织集群中的对象之间的结构,而不需要对集群进行修改。
在同一个对象之下标签的Key值必须唯一的。名称方面,标签名不得多于63个字符且必须由字母或数字开头或结尾,可以包含字母、数字、-、_、.等字符;标签前缀是可选的,必须以DNS子域名的方式指定,例如:kubernetes.io,后用/将其与标签名分隔。通常情况下,若不使用标签前缀,那么该标签的Key将被视为专属于用户的,在K8S的系统组件向对象添加标签时,必须指定前缀。在标签值方面,若标签值不为空,则其长度不得多于63个字符且必须由字母或数字开头或结尾,可以包含字母、数字、_、·等字符
(2)标签选择器
标签选择器可以用来选择一组对象(标签并不能唯一标识一个对象),APIServer支持两种标签选择器:基于等式的标签选择器与基于集合的标签选器:
基于等式的标签选择方式:在这种选择方式下可以使用=、 == 、 != 三种操作符来进行选择,前两个的含义是一样的,都代表相等,第三种代表不等。选择条件可以通过,叠加,例如date=day1,name != build代表选择date值为day1且name值不为build的对象。
基于集合的标签选择方式:这种选择器可以同时选择一组对象。支持的操作符有:in、notin、exists。
具体的使用方法为:
选择date包含有值为day1、day2、day3的标签:date in (day1,day2,day3)
选择name值不为build、pipline的标签:name notin (build, pipline)
选择所有包含test的标签:test
选择所有不包含test的标签 :! test
基于集合的标签选择器也支持使用“,”分隔以同时叠加选择,相同意义上的选择条件在这两种选择方式之间是等价的。
(3)标签与标签选择器举例
基于等式标签选择器
selector:
component: redis
基于集合标签选择器
selector:
matchLabels:
component: redis
matchExpressions:
- {key: tier, operator: In, values: [cache]}
- {key: environment, operator: NotIn, values: [dev]}
matchlabels 是{key,value}对的映射。matchlabels映射中的单个{key,value}等价于matchexpressions 的元素,其键字段为“key”,运算符为“in”,值数组仅包含“value”。matchexpressions是pod选择器需求的列表。有效的运算符包括in、notin、exists和doesnotexist。对于in和notin,设置的值必须为非空。matchlabels和matchexpressions 中的所有要求都被放在一起,必须满足所有这些要求才能匹配。
3: ReplicaSet
ReplicaSet(复制集,RS)是支持基于集合的标签选择器的下一代Replication Controller,它主要用于Deployment协调创建、删除和更新Pod,和Replication Controller唯一的区别是,eplicaSet 支持标签选择器。在实际应用中,虽然ReplicaSet可以单独使用,但是一般建议使用Deployment来自动管理ReplicaSet,除非自定义的Pod不需要更新或有其他编排等。定义一个ReplicaSet的实例如下:
(1)编辑replicaset文件
vim replicaset-example.yaml
各关键字具体含义如下。
>matchExpressions 是一个列表,其中可以包含多个匹配表达式。这里的例子只包含了一个表达式。
>-表示列表中的一个条目。
>{key: tier, operator: In, values:[frontend]}这是一个具体的匹配表达式,它包含以
下几个部分:
>key:标签键(label key),这里是tier。
>operator:匹配操作符,在这里为In,表示“在 …. 之中”
>values:匹配值列表,这里只有一个值[frontend]。
>requests:代表容器启动请求的资源限制,分配的资源必须要达到此要求
l>imits:代表最多可以请求多少资源
这个匹配表达式的含义是:“选择那些在其标签中包含键为tier 并且该键对应的值为frontend 的
对象。”例如如下写法:
matchExpressions:
- {key: tier, operator: In, values: ["frontend"]}
- {key: environment, operator: In, values: ["production", "staging"]}
CPU的计量单位叫毫核(m)。一个节点的CPU核心数量乘以1000,得到的就是节点总的CPU总数量。如一个节点有两个核,那么该节点的CPU总量为2000m。该容器启动时请求100/2000的核心(5%)
(2)创建rs
kubectl create -f replicaset-example.yamlkubectl get podkubectl delete -f replicaset-example.yaml
二:无状态应用管理 Deployment
1:什么是无状态
无状态服务(stateless service)对单次请求的处理,不依赖其他请求,也就是说,处理一次请求所需的全部信息,要么都包含在这个请求里,要么可以从外部获取到(比如说数据库),服务器本身不存储任何信息。这种服务叫做无状态服务。
无状态服务:就是没有特殊状态的服务,各个请求对于服务器来说统一无差别处理,请求自身携带了所有服务端所需要的所有参数(服务端自身不存储跟请求相关的任何数据,不包括数据库存储信息)
如果在启动一个服务时,不依赖于该服务之前的运行状态,或者不依赖于其他服务,这个服务就是无状态服务;反之,就是有状态服务。
2:无状态服务特点
(1)数据方面:无状态服务不会在本地存储持久化数据.多个实例可以共享相同的持久化数据
(2)结果方面:多个服务实例对于同一个用户请求的响应结果是完全一致的
(3)关系方面:这种多服务实例之间是没有依赖关系
(4)影响方面:在k8s控制器中动态启停无状态服务的pod并不会对其它的pod产生影响
(5)示例方面:nginx实例,tomcat实例,web应用
(6)资源方面:相关的k8s资源有:ReplicaSet、ReplicationController、Deployment
(7)创建方式:Deployment 被设计用来管理无状态服务的pod
>每个pod完全一致,原因如下:
>无状太服多内的多个 Pod创強的师序是没右师序的
>无状态服务内的多个Pod的名称是随机的
> pod被重新启动调度后,它的名称与IP都会发生变化> 无状态服务内的多个Pod背后是共享存储的
(8)扩缩容方式:随机缩容
由于是无状态服务,所以这些控制器创建的pod序号都是随机值。并且在缩容也是随机,并不会明确缩容某一个pod。因为所有实例得到的返回值都是一样,所以缩容任何一个pod都可以。
3.无状态服务的应用场景
Deployment 用来管理RS,并为Pod和RS提供声明性更新,以及许多其他的新的功能,生产环境中使用Deployment 替代RS。
Deployment一般用于部署公司的无状态服务,因为企业内部现在都是以微服务为主,微服务实现无状态化也是最佳实践。可以利用Deployment的高级功能做到无缝迁移、自动扩容缩容、自动灾难恢复、一键回滚等功能。
无状态服务不会在本地存储持久化数据。多个服务实例对于同一个用户请求的响应结果是完全一致的。这种多服务实例之间是没有依赖关系,比如web应用,在k8s控制器中动态启停无状态服务的pod并不会对其它的pod产生影响。
Deployment 被设计用来管理无状态服务的pod,每个pod完全一致
无状态服务内的多个Pod创建的顺序是没有顺序的。
无状态服务内的多个Pod的名称是随机的.pod被重新启动调度后,它的名称与IP都会发生变化。
无状态服务内的多个Pod背后是共享存储的。
4.创建deployment
(1)编写deployment文件
vim nginx-deployment.yaml
各关键字的含义如下:
replicas: pod的副本数
selector:定义Deployment如何找到要管理的Pod,与template的label标签对应。
template:
■ app: nginx使用label标记pod
■ spec:定义pod的详细信息
■ name: nginx 表示pod运行一个名字为nginx的容器
■ image:运行此pod使用的镜像
■ port:容器用于发送和接收流量的端口
(2)使用kubectl create 创建此deployment
ku create -f nginx-deployment.yaml
(3)查看Deployment 的状态
kubectl get deploy
(4)使用rollout查看整个Deployment 的创建过程状态
kubect1 rollout status deployment/nginx-deployment
(5)查看这个Deployment 对应的RS
kubectl get rs -1 app=nginx
(6)查看此Deployment 创建的pod
kubectl get pods -- show-labels
2:更新 Deployment
通过Deployment部署应用后,如果需要对Deployment文件的配置文件或者镜像版本进行更新,更改后该Deployment会创建新的RepliccaSet,之后会对管理的Pod进行滚动升级。\
(1)更新pod的image
kubectl set image deployment nginx-deployment nginx=nginx:1.9.1 -- recordkubectl set image deployment nginx-deployment nginx=nginx:1.12.0 -- record
(2)查看更新过程
kubectl rollout status deployment.v1.apps/nginx-deployment
(3)此时的RS有新的和旧的
kubectl get rs
(4)通过describe 查看deployment 的详细信息
kubectl describe deploy nginx-deployment
3:回滚 deployment
当更新的版本不稳定或者配置不合理时,可以对其进行回滚操作。
(1)多更新几次 deployment
kubectl set image deployment nginx-deployment nginx=dotbalo/canary:v1 -- recordkubectl set image deployment nginx-deployment nginx=dotbalo/canary:v2 -- record
(2)查看更新历史
kubectl rollout history deployment/nginx-deployment
(3)查看某次更新的详情
kubect1 rollout history deployment/nginx-deployment -- revision=2
(4)回滚到指定版本
kubectl rollout undo deployment/nginx-deployment -- to-revision=2查看回滚结果:kubectl rollout history deployment/nginx-deployment
(5)回滚到指定版本
kubect1 rollout undo deployment/nginx-deployment查看回滚结果:kubectl rollout history deployment/nginx-deployment
4:扩容deployment
(1)调整pod的副本数
kubectl scale deployment.v1.apps/nginx-deployment -- replicas=3查看扩容结果:kubect1 get pods
5:删除 Deployment
kubectl delete -f nginx-deployment.yaml
三:有状态应用管理 StatefulSet
1:有状态服务的定义
StatefulSet(有状态集,缩写为sts)常用于部署有状态的且需要有序启动的应用程序。比如在生产环境中,可以部署Elasticsearch集群、MongoDB集群或者需要持久化的RabbitMQ集群、Redis集群、Kafka 集群和ZooKeeper集群等。
一个StatefulSet 管理着基于相同容器规范的Pod。与Deployment不同的是,StatefulSet 为每个Pod维护了一个标识。这些Pod是根据相同规范创建的,但是不可互换,每个Pod都有一个持久的标识符,在重新调度时也会被保留。
2:有状态服务的特征
(1)数据方面:有状态服务需要在本地存储持久化数据,典型的应用是分布式数据库
(2)结果方面:实例之间,请求结果可能存在不一致
(3)关系方面:分布式节点实例之间有依赖的拓扑关系,比如主从关系。
(4)影响方面:如果K8S停止分布式集群中任一实例pod,就可能会导致数据丢失或者集群的crash(溃)
(5)示例方面:mysq1数据库、kafka、zookeeper、Redis 主从架构
(6)资源方面:statefulSet
(7)创建方式:statefulSet 管理
Stateful 管理有状态的应用,Pod有如下特征:
> 唯一性:每个Pod会被分配一个唯一序号.
> 顺序性:Pod启动,更新,销毁是按顺序进行.
>稳定的网络标识:Pod主机名,DNS地址不会随着Pod被重新调度而发生变化.
>稳定的持久化存储:Pod被重新调度后,仍然能挂载原有的PV,从而保证了数据的完整性和一致性
3:有状态服务的应用场景
有状态的 pod是用来运行有状态应用的,所以其在数据卷上存储的数据非常重要,在 Statefulset缩容时删除这个声明将是灾难性的,特别是对于Statefulset 来说,缩容就像减少其 replicas 数值一样简单。基于这个原因,当需要释放特定的持久卷时,需要手动删除对应的持久卷声明。
有状态服务需要在本地存储持久化数据,典型的是分布式数据库的应用,分布式节点实例之间有依赖的拓扑关系.比如,主从关系. 如果K8S停止分布式集群中任一实例pod,就可能会导致数据丢失或者群的crash(崩溃)。
有状态服务 可以说是需要数据存储功能的服务、或者指多线程类型的服务,队列等。库、kafka、zookeeper 等)
有状态服务常常用于实现事务(并不是唯一办法,下文有另外的方案)。举一个常见的例子,在商城里购买一件商品。需要经过放入购物车、确认订单、付款等多个步骤。由于HTTP协议本身是无状态的,所以为了实现有状态服务,就需要通过一些额外的方案。比如最常见的session,将用户挑选的商品(购物车),保存到session中,当付款的时候,再从购物车里取出商品信息。
4:无状态服务和有状态服务的比较
(1)无状态服务
> 服务不依赖自身的状态,实例的状态数据可以维护在内存中。
> 任何一个请求都可以被任意一个实例处理。
> 不存储状态数据,实例可以水平拓展,通过负载均衡将请求分发到各个节点。
> 在一个封闭的系统中,只存在一个数据闭环。
> 通常存在于单体架构的集群中。
(2)有状态服务
>服务本身依赖或者存在局部的状态数据,这些数据需要自身持久化或者可以通过其他节点恢复。
>个请求只能被某个节点(或者同等状态下的节点)处理。
>存储状态数据,实例的拓展需要整个系统参与状态的迁移。
>在一个封闭的系统中,存在多个数据闭环,需要考虑这些闭环的数据一致性问题。
>通常存在于分布式架构中。
5:编写statefulSet 资源文件
(1)定义一个statefulSet 资源文件
vim redis-statefulset.yaml
备注:
>kind:Service 定义了一个名字为redis-svc的服务,
>kind:StatefulSet 定义了一个名字为redis-sts的StatefulSet,replicas表示部署Pod的副本数。
(2)创建statefulSet
kubectl create -f redis-statefulset.yaml
(3)查看statefilset 状态
kubect1 get sts
(4)查看群集状态
kubectl get serviceku get o -l app=redis-sts
-1:指定标签(label)
注意NAME列,名称是sts的name-序号,这里序号越小则说明创建的越早从AGE列也可以看出来,这就解决了有状态应用中的启动顺序问题,比如可以让redis-sts-0作为redis的主节点,redis-sts-1作为从节点
6: statefulset扩容
(1)扩容,将副本数修改为3
ku scale sts redis-sts --replicas=3ku get pod
7.缩容
(1)打开第二个终端,动态显示缩容流程
ku get pods -w -l app=redis-sts
备注:
-W:动态监听所有的pod
(2)在原来第一个终端修改副本数为2
kubectl patch sts redis-sts -p '{"spec": {"replicas":2}}'
注意:
此时可以查看第二个终端上的变化
(3)在第一个终端上查看最终结果
kubectl get pods -1 app=redis-sts
8:非级联删除 statefulset
删除StatefulSet 有两种方式:级联删除和非级联删除。
使用非级联方式删除 StatefulSet 时,StatefulSet 的Pod不会被删除。使用级联方式删除StatefulSet时,StatefulSet 和它的Pod都会被删除。
(1)采用非级联删除
kubectl delete statefulset redis-sts --cascade=false查看删除结果:kubect1 get sts
(2)查看管理的pod
kubectl get po
发现pod并没有被删除
(3)删除pod
kubectl delete po redis-sts-0kubectl delete po redis-sts-1
9:级联删除 statefulset
(1)先创建出statefulset
kubectl create -f redis-statefulset.yaml
(2)级联删除
kubectl delete statefulset redis-sts
查看
ku get po
(3)删除 redis服务
kubectl delete -f redis-statefulset.yaml
四:守护进程集 DaemonSet
1:什么是DaemonSet
有时候我们需要在每个Kubernetes节点或符合条件的节点上都部署某个应用,那么就可以使用Kubernetes 的DaemonSet 调度Pod。DaemonSet 确保全部(或符合条件)的节点上运行一个Pod副本。当有新的节点加入集群时,也会为他们新增一个Pod,当节点从集群中移除时,这些Pod会被回收,删除DaemonSet 将会删除它创建的所有的Pod。
2:定义一个DaemonSet
cat demonset-nginx.yaml
3: DaemonSet
kubectl create namespace devkubectl create -f daemonset-nginx.yaml
4:查看DaemonSet
kubectl get ds -n dev -o wide
5:查看pod所在的节点
kubectl get pod -n dev -o wide
6:删除 DaemonSet
kubectl delete ds pod-controller -n dev
五:CronJob
Cronjob(计划任务,缩写为cj)用于以时间为基准的周期性地执行任务,这些自动化任务和运行在Linu系统上的CronJob一样。
1.创建cronjob
(1)编辑cronjob文件
cat cronjob-example.yaml
备注:
这个案例会在每分钟执行一次计划任务,
并输出当前时间和“Hello from the Kubernetes cluster"
(2)创建Cronjob
kubectl create -f cronjob-example.yaml
(3)查看创建结果
kubectl get cj等待一会后可以查看生成的podkubect1 get jobs
(4)查看生成的pod,并查看pod的执行日志
kubectl get podkubectl logs -f hello-27743522-crnf8
(5)删除Cronjob
kubectl delete cronjob hello