一:Replication Controller和ReplicaSet
1:Replication Controller
Replication Controller(复制控制器,RC)
RC 用来确保 Pod 副本数达到期望值,这样可以确保一个或多个同类 Pod 总是可用的。如果存在的 Pod 数量大于设定的值,Replication controller 将终止额外的 Pod,如果太少,Replication controller 将会启动更多的 Pod 用于保证达到期望值,与手动创建 Pod 不同的是,用Replication Controller 维护的 Pod 在失败、删除或终止时会自动替换。因此,即使应用程序只需要一个 Pod,也应该使用 Replication controller 或其他方式管理。Replication Controller 类似于进程管理程序,但是 Replication controller 不是监视单个节点上的各个进程,而是监视多个节点上的多个 Pod。
(1)编辑ReplicationController文件
vim replicationcontroller-nginx.yaml
(2)创建ReplicationController
ku apply -f replicationcontroller-nginx.yaml
ku get pod
ku get rc
(3)删除一个pod并查看pod状态
ku delete pod nginx-9g78r -n default
ku get pod
(4)删除ReplicationController
ku 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 的对象。
含义是一样的,都代表相等,第三种代表不等。选择条件可以通过,叠加,例如 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:
matchLables:
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 唯一的区别是,Replicaset 支持标签选择器。在实际应用中,虽然 Replicaset 可以单独使用,但是一般建议使用Deployment 来自动管理 Replicaset,除非自定义的 Pod 不需要更新或有其他编排等。
(1)编辑ReplicaSet文件
vim replicaset-example.yaml
各关键字具体含义如下。
matchExpressions 是一个列表,其中可以包含多个匹配表达式。这里的例子只包含了一个表达式
- 表示列表中的一个条目。
{key:tier,operator:In,values:[frontend]}这是一个具体的匹配表达式,它包含以下几个部分:
key:标签键(label key),这里是 tier。
operator:匹配操作符,在这里为In,表示“在...之中”
values:匹配值列表,这里只有一个值[frontend]。
requests:代表容器启动请求的资源限制,分配的资源必须要达到此要求
limits:代表最多可以请求多少资源
这个匹配表达式的含义是:“选择那些在其标签中包含键为 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.yaml
ku get pod
二:无状态应用管理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)使用kubect1 create创建此Deployment
kubectl create -f nginx-deployment.yaml
(3)查看Deployment 的状态
kubectl get deploy
(4)使用ro11out 查看整个 Deployment 的创建过程状态
kubectl rollout status deployment/nginx-deployment
(5)查看这个Deployment 对应的 RS
kubectl get rs -l app=nginx
(6)查看此Deployment创建的pod
ku get pods --show-labels
2:更新Deployment
通过Deployment部署应用后,如果需要对Deployment文件的配置文件或镜像版本进行更新,更改后该Deployment会创建的RepliccaSet,之后会对管理的pod进行滚动升级
(1)更新pod的image
ku set image deployment nginx-deployment nginx=nginx:1.9.1 --record
ku set image deployment nginx-deployment nginx=nginx:1.12.0 --record
(2)查看更新过程
ku rollout status deployment.v1.apps/nginx-deployment
(3)此时的RS有新的和旧的
ku get rs
(4)通过describe查看deployment的详细信息
ku describe deploy nginx-deployment
3:回滚deployment
当更新的版本不稳定或者配置不合理时,可以对其进行回滚操作
(1)多更新几次deployment
ku set image deployment nginx-deployment nginx=dotbalo/canary:v1 --record
ku set image deployment nginx-deployment nginx=dotbalo/canary:v2 --record
(2)查看更新历史
ku rollout history deployment/nginx-deployment
最后一个版本是当前版本
(3)查看某次更新的详细
kubectl rollout history deployment/nginx-deployment --revision=2
(4)回滚到指定版本
kubectl rollout undo deployment/nginx-deployment --to-revision=2
查看回滚结果:
kubectl rollout history deployment/nginx-deployment
(5)回滚到上次版本
kubectl rollout undo deployment/nginx-deployment
4:扩容deployment
(1)调整pod的副本数
ku scale deployment.v1.apps/nginx-deployment --replicas=3
查看扩容结果:
ku get pods
5:删除Deployment
ku 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)示例方面:mysql数据库、kafka、zookeeper、Redis 主从架构
(6)资源方面:statefulset
(7)创建方式:statefulset 管理
statefu1 管理有状态的应用,Pod 有如下特征:
唯一性:每个 Pod 会被分配一个唯一序号:
顺序性:Pod 启动,更新,销毁是按顺序进行。
稳定的网络标识:Pod 主机名,DNS 地址不会随着Pod 被重新调度而发生变化,稳定的持久化存储:Pod 被重新调度后,仍然能挂载原有的 PV,从而保证了数据的完整性和一致性
3:有状态服务的应用场景
有状态的 pod 是用来运行有状态应用的,所以其在数据卷上存储的数据非常重要,在 statefulset缩容时删除这个声明将是灾难性的,特别是对于 statefulset 来说,缩容就像减少其 replicas 数值一样简单。基于这个原因,当需要释放特定的持久卷时,需要手动删除对应的持久卷声明。有状态服务需要在本地存储持久化数据,典型的是分布式数据库的应用,分布式节点实例之间有依赖的拓扑关系.比如,主从关系。如果 K8S 停止分布式集群中任一实例 pod,就可能会导致数据丢失或者集群的 crash(崩溃)。
有状态服务 可以说是需要数据存储功能的服务、或者指多线程类型的服务,队列等。(mysgl 数据库、kafka、zookeeper等)
有状态服务常常用于实现事务(并不是唯一办法,下文有另外的方案)。举一个常见的例子,在商城里购买一件商品。需要经过放入购物车、确认订单、付款等多个步骤。由于 HTTP 协议本身是无状态的,所以为了实现有状态服务,就需要通过一些额外的方案。比如最常见的 session,将用户挑选的商品(购物车),保存到 session 中,当付款的时候,再从购物车里取出商品信息。
4:无状态服务和有状态服务的比较
(1)无状态服务
服务不依赖自身的状态,实例的状态数据可以维护在内存中。
任何一个请求都可以被任意一个实例处理。
不存储状态数据,实例可以水平拓展,通过负载均衡将请求分发到各个节点。
在一个封闭的系统中,只存在一个数据闭环。
通常存在于单体架构的集群中。
(2)有状态服务
服务本身依赖或者存在局部的状态数据,这些数据需要自身持久化或者可以通过其他节点恢复。
一个请求只能被某个节点(或者同等状态下的节点)处理。
存储状态数据,实例的拓展需要整个系统参与状态的迁移。
在一个封闭的系统中,存在多个数据闭环,需要考虑这些闭环的数据一致性问题。
通常存在于分布式架构中。