1、Service资源
  • Service是Kubernetes标准的API资源类型之一

● 为动态的Pod资源提供近似静态的流量入口

◆服务发现:通过标签选择器筛选同一名称空间下的Pod资源的标签,完成Pod筛选

实际上是由与Service同名的Endpoint或EndpointSlice资源及控制器完成

◆流量调度:由运行各工作节点的kube-proxy根据配置的模式生成相应的流量调度规则

iptables

ipvs

  • 持续监视着相关Pod资源的变动,并实时反映至相应的流量调度规则之上
[root@k8s-master01 ~]#kubectl get cm -n kube-system     #查看kube-proxy
[root@k8s-master01 ~]#kubectl edit cm kube-proxy -n kube-system #在线编辑kube-proxy配置
1-1、动态可配置负载均衡

从Service的视角来看,Kubernetes集群的每个工作节点都是动态可配置的负载均衡器

  • 对于隶属某Service的一组Pod资源,该Service资源能够将集群中的每个工作节点配置为该组Pod的负载均衡器
  • 客户端可以是来自集群之上的Pod,也可以是集群外部的其它端点
  • 对于一个特定的工作节点上的某Service来说,其客户端通常有两类

◆ 该节点之上的进程,可通过该Service的Cluster IP进入

Service_IP:Service_Port

◆ 该节点之外的端点,可经由该Service的NodePort进入

Node_IP:Node_Port

显然,若客户端进入的节点,并非目标Pod所在的节点时,报文转发的路径中必然存在跃点

1-2、Service类型

Service根据其所支持的客户端接入的方式,可以分为4种类型

  • ClusterIP:支持Service_IP:Service_Port接入;
  • NodePort:支持Node_IP:Node_Port接入,同时支持ClusterIP;
  • LoadBalancer:支持通过外部的LoadBalancer的LB_IP:LB_Port接入,同时支持NodePort和ClusterIP;

◆ Kubernetes集群外部的LoadBalancer负责将接入的流量转发至工作节点上的NodePort

◆ LoadBalancer需与相关的NodePort的Service生命周期联动

LoadBalancer应该是由软件定义

Kubernetes需要同LoadBalancer所属的管理API联动

  • ExternalName

◆ 负责将集群外部的服务引入到集群中

◆ 需要借助于ClusterDNS上的CNAME资源记录完成

◆ 特殊类型,无需ClusterIP和NodePort

◆ 无须定义标签选择器发现Pod对象

由Service表示的负载均衡器,主要定义如下内容

负载均衡器入口:ClusterIP及相关的Service Port、NodePort(每个节点的Node IP都可用)

◆ 根据通信需求,确定选择的类型

标签选择器:用于筛选Pod,并基于筛选出的Pod的IP生成后端端点列表(被调度的上游端点)

Service类型的专有配置

kubernetes-003_负载均衡

1-3、标签和标签选择器
  • 标签:附加在资源对象上的键值型元数据

键标识:由“键前缀(可选)”和“键名”组成,格式为“key_prefix/key_name”

◆ 键前缀必须使用DNS域名格式

◆ 键名的命名格式:支持字母、数字、连接号、下划线和点号,且只能以字母或数字开头;最长63个字符;

“kubectl label”命令可管理对象的标签

  • 标签选择器:基于标签筛选对象的过滤条件,支持两种类型基于等值关系的选择器

◆ 操作符:=或==、!=

基于集合关系的选择器

◆ 操作符:in、notin和exists

◆ 使用格式:KEY in (VALUE1, VALUE2, …)、 KEY notin (VALUE1, VALUE2, …)、KEY 和 !KEY

[root@k8s-master01 ~]#kubectl label pod wordpress version=1.0
pod/wordpress labeled
[root@k8s-master01 ~]#kubectl get pod -l version=1.0
NAME READY STATUS RESTARTS AGE
mydb 1/1 Running 0 25h
wordpress 1/1 Running 0 23h
[root@k8s-master01 ~]#kubectl get pod -l version=1.0 --show-labels
NAME READY STATUS RESTARTS AGE LABELS
mydb 1/1 Running 0 25h app=mydb,version=1.0
wordpress 1/1 Running 0 23h app=wordpress,version=1.0
[root@k8s-master01 ~]#kubectl get pod -L version
NAME READY STATUS RESTARTS AGE VERSION
demoapp-55c5f88dcb-4j5bm 0/1 ContainerCreating 0 9m28s
demoapp-55c5f88dcb-9f52z 1/1 Running 0 9m28s
mydb 1/1 Running 0 25h 1.0
wordpress 1/1 Running 0 23h 1.0
[root@k8s-master01 ~]#kubectl get pod -l version=1.0 -L version
NAME READY STATUS RESTARTS AGE VERSION
mydb 1/1 Running 0 25h 1.0
wordpress 1/1 Running 0 23h 1.0
[root@k8s-master01 ~]#kubectl get pod -l version!=1.0 --show-labels
NAME READY STATUS RESTARTS AGE LABELS
demoapp-55c5f88dcb-4j5bm 0/1 ContainerCreating 0 11m app=demoapp,pod-template-hash=55c5f88dcb
demoapp-55c5f88dcb-9f52z 1/1 Running 0 11m app=demoapp,pod-template-hash=55c5f88dcb

[root@k8s-master01 ~]#kubectl get pod --show-labels
NAME READY STATUS RESTARTS AGE LABELS
demoapp-55c5f88dcb-4j5bm 0/1 ContainerCreating 0 12m app=demoapp,pod-template-hash=55c5f88dcb
demoapp-55c5f88dcb-9f52z 1/1 Running 0 12m app=demoapp,pod-template-hash=55c5f88dcb
mydb 1/1 Running 0 25h app=mydb,env=test,ver=test,version=1.0
wordpress 1/1 Running 0 23h app=wordpress,version=1.0

[root@k8s-master01 ~]#kubectl get pod -l ver=test -l env=test --show-labels
NAME READY STATUS RESTARTS AGE LABELS
mydb 1/1 Running 0 25h app=mydb,env=test,ver=test,version=1.0

[root@k8s-master01 ~]#kubectl get pod -l ver=test -l version=1.0 --show-labels
NAME READY STATUS RESTARTS AGE LABELS
mydb 1/1 Running 0 25h app=mydb,env=test,ver=test,version=1.0
wordpress 1/1 Running 0 23h app=wordpress,version=1.0

[root@k8s-master01 ~]#kubectl get pod -l "ver=test,version=1.0" --show-labels
NAME READY STATUS RESTARTS AGE LABELS
mydb 1/1 Running 0 25h app=mydb,env=test,ver=test,version=1.0
apiVersion: v1
kind: Service
metadata:
name: …
namespace: …
spec:
type <string> # Service类型,默认为ClusterIP
selector <map[string]string> # 等值类型的标签选择器,内含“与”逻辑
ports: # Service的端口对象列表
- name <string> # 端口名称
protocol <string> # 协议,目前仅支持TCP、UDP和SCTP,默认为TCP
port <integer> # Service的端口号
targetPort <string> # 后端目标进程的端口号或名称,名称需由Pod规范定义
nodePort <integer> # 节点端口号,仅适用于NodePort和LoadBalancer类型
clusterIP <string> # Service的集群IP,建议由系统自动分配
externalTrafficPolicy <string> # 外部流量策略处理方式,Local表示由当前节点处理,Cluster表示向集群范围调度
loadBalancerIP <string> # 外部负载均衡器使用的IP地址,仅适用于LoadBlancer
externalName <string> # 外部服务名称,该名称将作为Service的DNS CNAME值
kind: Service
apiVersion: v1
metadata:
name: demoapp
spec:
type: ClusterIP # 类型标识,默认即为ClusterIP;
selector:
app: demoapp
ports:
- name: http # 端口名称标识
protocol: TCP # 协议,支持TCP、UDP和SCTP
port: 80 # Service的端口号
targetPort: 80 # 目标端口号,即后端端点提供服务的监听端口号
kind: Service
apiVersion: v1
metadata:
name: demoapp
spec:
type: NodePort # 必须明确给出Service类型
selector:
app: demoapp
ports:
- name: http
protocol: TCP
port: 80
targetPort: 80
nodePort: 30080 # 可选,为避免冲突,建议由系统动态分配
1-4、NodePort Service流量策略
1-4-1、流量策略一:

Cluster,表示在整个Kubernetes集群范围内调度;

该流量策略下,请求报文从某个节点上的NodePort进入,该节点上的Service会将其调度至任何一个可用后端Pod之上,而不关心Pod运行于哪个节点;

kubernetes-003_负载均衡_02

1-4-2、流量策略二:

Local,表示仅将请求调度至当前节点上运行的可用后端端点;

该流量策略下,请求报文从某节点NodePort进入后,该节点上的Service仅会将请求调度至当前节点上适配到该Service的后端端点

仅应该从运行有目标Service对象后端Pod对象的节点的NodePort发起访问

kubernetes-003_负载均衡_03

1-4-3、LoadBalancer类型的Service

在接入外部流量方面,NodePort存在着几个方面的问题

非知名端口、私网IP地址、节点故障转移、节点间负载均衡、识别能适配到某Service的Local流量策略的节点等

外置的Cloud Load Balancer可以解决以上诸问题

kubernetes-003_端口号_04

2、Service名称解析
  • Cluster DNS(CoreDNS)是Kubernetes集群的必备附件,负责为Kubernetes提供名称解析和服务发现

★每个Service资源对象,在CoreDNS上都会自动生成一个遵循“<service>.<ns>.svc.<zone>”格式的名称

◆ <service>:当前Service对象的名称
◆ <ns>:当前Service对象所属的名称空间
◆ <zone>:当前Kubernetes集群使用的域名后缀,默认为“cluster.local”
★围绕该名称会生成一些DNS格式的资源记录
  • CoreDNS会持续监视API Server上的Service资源对象的变动,并实时反映到相关的DNS资源记录中
  • Pod中各容器默认会在/etc/resolv.conf中,将nameserver指向CoreDNS相关的Service的ClusterIP

★由kubelet创建Pod时根据指定的配置自动注入

  • 每个Service,在CoreDNS上都会有A/AAAA、SRV和PTR资源记录

★A/AAAA资源记录

◆ <service>.<ns>.svc.<zone>. <ttl> IN A <cluster-ip>

◆ <service>.<ns>.svc.<zone>. <ttl> IN AAAA <cluster-ip>

★为每个定义了名称的端口生成一个SRV记录,以支持服务发现

◆ _<port>._<proto>.<service>.<ns>.svc.<zone>. <ttl> IN SRV <weight> <priority> <port-number> <service>.<ns>.svc.<zone>.

★为每个A记录(例如a.b.c.d)或AAAA记录生成对应的PTR记录,例如

◆ <d>.<c>.<b>.<a>.in-addr.arpa. <ttl> IN PTR <service>.<ns>.svc.<zone>. 
◆h4.h3.h2.h1.g4.g3.g2.g1.f4.f3.f2.f1.e4.e3.e2.e1.d4.d3.d2.d1.c4.c3.c2.c1.b4.b3.b2.b1.a4.a3.a2.a1.ip6.arpa <ttl> IN PTR <service>.<ns>.svc.<zone>.
  • Pod可基于Service的DNS名称向其发起服务访问请求
2-1、Pod上的DNS解析策略
  • Kubernetes支持在单个Pod资源规范上自定义DNS解析策略和配置,并组合生效

★spec.dnsPolicy:解析策略

★spec.dnsConfig:名称解析机制

  • DNS解析策略

★Default:从运行在的节点继承DNS名称解析相关的配置

★ClusterFirst:于集群DNS服务上解析集群域内的名称,其他域名的解析则交由从节点继承而来的上游名称服务器

★ClusterFirstWithHostNet:专用于在设置了hostNetwork的Pod对象上使用的ClusterFirst策略

★ None:用于忽略Kubernetes集群的默认设定,而仅使用由dnsConfig自定义的配置

  • DNS解析机制

★nameservers <[]string>:DNS名称服务器列表,附加于由dnsPolicy生成的DNS名称服务器之后

★searches <[]string>:DNS名称解析时的搜索域,附加由于dnsPolicy生成的搜索域之后

★options <[]Object>:DNS解析选项列表,同dnsPolicy生成的解析选项合并成最终生效的定义

ClusterDNS服务的名称:kube-dns.kube-system.svc.cluster.local 
固定的地址:Cluster Network地址范围内的第10个地址;
10.96.0.0/12 --> 10.96.0.10
[root@k8s-master01 ~]#kubectl get svc -n kube-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP,9153/TCP 2d20h
[root@k8s-master01 ~]#kubectl describe svc kube-dns -n kube-system
Name: kube-dns
Namespace: kube-system
Labels: k8s-app=kube-dns
kubernetes.io/cluster-service=true
kubernetes.io/name=CoreDNS
Annotations: prometheus.io/port: 9153
prometheus.io/scrape: true
Selector: k8s-app=kube-dns
Type: ClusterIP
IP Family Policy: SingleStack
IP Families: IPv4
IP: 10.96.0.10
IPs: 10.96.0.10
Port: dns 53/UDP
TargetPort: 53/UDP
Endpoints: 10.244.58.193:53,10.244.58.195:53
Port: dns-tcp 53/TCP
TargetPort: 53/TCP
Endpoints: 10.244.58.193:53,10.244.58.195:53
Port: metrics 9153/TCP
TargetPort: 9153/TCP
Endpoints: 10.244.58.193:9153,10.244.58.195:9153
Session Affinity: None
Events: <none>
[root@k8s-master01 ~]#kubectl run client-$RANDOM --image=ikubernetes/admin-box:v1.2 --restart=Never -it --command -- /bin/bash
If you don't see a command prompt, try pressing enter.

root@client-15972 /# host -t A demoapp-nodeport-svc
demoapp-nodeport-svc.default.svc.cluster.local has address 10.98.75.75

root@client-15972 /# host -t A wordpress
wordpress.default.svc.cluster.local has address 10.103.135.96

root@client-15972 /# host -t A wordpress.default
wordpress.default.svc.cluster.local has address 10.103.135.96

root@client-15972 /# host -t A wordpress.default.svc
wordpress.default.svc.cluster.local has address 10.103.135.96

root@client-15972 /# host -t A wordpress.default.svc
wordpress.default.svc.cluster.local has address 10.103.135.96

root@client-15972 /# host -t PTR 10.103.135.96
96.135.103.10.in-addr.arpa domain name pointer wordpress.default.svc.cluster.local.

root@client-15972 /# host -t SRV _80-80._tcp.wordpress
_80-80._tcp.wordpress.default.svc.cluster.local has SRV record 0 100 80 wordpress.default.svc.cluster.local.

[root@k8s-master01 ~]#kubectl get cm coredns -o yaml -n kube-system
apiVersion: v1
data:
Corefile: |
.:53 {
errors
health {
lameduck 5s
}
ready
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
fallthrough in-addr.arpa ip6.arpa
ttl 30
}
prometheus :9153
forward . /etc/resolv.conf {
max_concurrent 1000
}
cache 30
loop
reload
loadbalance
}
kind: ConfigMap
metadata:
creationTimestamp: "2022-11-10T05:59:38Z"
name: coredns
namespace: kube-system
resourceVersion: "232"
uid: 829218dc-39d1-486c-ab66-24db6e059f7c
2-2、Headless Service

Service的各类型中,ClusterIP、NodePort和LoadBalancer都为其Service配置一个ClusterIP,CoreDNS上,这些

Service对象的A记录也解析为它的ClusterIP;

  • 广义上,那些没有ClusterIP的Service则称为Headless Service,它们又可以为分两种情形

★有标签选择器,或者没有标签选择器,但有着与Service对象同名的Endpoint资源

◆ Service的DNS名称直接解析为后端各就绪状态的Pod的IP地址

◆ 调度功能也将由DNS完成

◆ 各Pod IP相关PTR记录将解析至Pod自身的名称,假设Pod IP为a.b.c.d,则其名称为a-b-c-d.<service>.<ns>.svc.<zone>

◆ 这种类型也就是狭义上的Headless Service

★无标签选择器且也没有与Service对象同名的Endpoint资源

◆ Service的DNS名称将会生成一条CNAME记录,对应值由Service对象上的spec.externalName字段指定

3、Service流量转发机制

3-1、ClusterIP类型
  • 源自Pod

◆ 没启动masquerade-all:请求报文的目标IP和目标端口由Service转为挑选出的后端Pod的IP和端口,并由后端Pod直接响应给客户端Pod

发夹问题:Pod访问自身所属的Service后,由Service又调度回该Pod

存在发夹问题(haripin)的场景中,需要启用源IP地址转换

◆ 启用masquerade-all:请求报文的源IP和目标IP都将由Service进行转换,原IP将转为客户端Pod所在节点在Pod网络中的IP地址

  • 源自非Pod网络中的请求流量

◆ 接入流量的节点充当NAT网关,请求报文的源IP和目标IP都将由Service进行转换

3-2、NodePort和LoadBalancer类型
  • 流量来自集群外部,节点扮演网关的角色,请求报文的源IP和目标IP都将由Service进行转换,原IP将转为客户端Pod所在节点的IP地址,以确保响应报文能正确送达

4、Kubernetes控制器模式

4-1、API设计方法
  • 命令式API

◆也称为指令式API,用户需要一步步地告诉机器该如何做(How),机器自身不具有任何“智能”,只被动接受指令

◆高度依赖用户自身理解和达成目标的能力和处理各类异常问题的经验,实现的是“命令式编程(Imperative

Programming)”

  • 声明式API

◆也称为申明式API,用户只需要告诉机器想要的结果(What),机器自身需要确定如何达成该目标

◆机器需要一定的“智能”,但通常只能支持事先预设和可被其理解的特定任务

◆实现的是“声明式编程(Declarative Programming)”

4-2、声明式API和控制器模式
  • 相较于命令式编程,声明式编程是一个更高的层次上的编程

★ 声明式API允许用户以给出最终期望目标的方式编写代码,但具体的执行过程(即机器智能的那部分代码),最终仍然需要以命令式编程实现,只不过,它们可由不同的人群完成

★ 类比来说,声明式编程的用户类似于企业的高管,只用关心和交待最终目标;而命令式编程的用户类似于企业部门经理,他需要理解目标的达成路径,并组织人力完成目标

  • Kubernetes的声明式API

★ 用户能够以声明式定义资源对象的目标状态(spec)

★ 由控制器代码(机器智能组件)负责确保实际状态(status)与期望状态一致

◆控制器即“部门经理”,负责确保部门内的各项具体任务得以落地

◆控制器通常由API的提供者负责编写

★ 用户需要做的是根据资源类型及其控制器提供的DSL进行声明式编程

  • 控制器模型(控制回路)

★ 初始,Controller负责根据Input(目标状态)控制System,并生成Output(结果状态)

★ Feedback根据Output生成Feedback Signal,而后由Error Detector基于Feedback Signal和Input来判定是否存在错误,并在有错误时生成Error Signal

★ Error Signal将驱动Controller生成Actuating Signal,并控制System的行为与Input要求相同

kubernetes-003_选择器_05

  • Kubernetes Controller的控制回路

★ Controller根据spec,控制System生成Status

★ Controller借助于Sensor持续监视System的Spec和Status,在每一次控制回路中都会对二者进行比较,并确保System的Status不断逼近或完全等同Status

kubernetes-003_选择器_06

4-3、Kubernetes的控制器
  • Kubernetes的控制器类型

★ 打包于Controller Manager中内置提供的控制器,例如Service Controller、Deployment Controller等

◆基础型、核心型控制器

◆打包运行于kube-controller-manager中

★ 插件或第三方应用的专用控制器,例如Ingress插件ingress-nginx的Controller,网络插件Project Calico的Controller等

◆高级控制器,通常需要借助于基础型控制器完成其功能

◆以Pod形式托管运行于Kubernetes之上,而且这些Pod很可能会由内置的控制器所控制

  • 以编排Pod化运行的应用为核心的控制器,通常被统称为工作负载型控制器

★ 无状态应用编排:ReplicaSet、Deployment

★ 有状态应用编排:StatefulSet、第三方专用的Operator

★ 系统级应用:DaemonSet

★ 作业类应用:Job和CronJob

4-4、应用编排
  • 定义工作负载型控制器资源对象以编排应用

★ 内置的各工作负载型控制器都有对应的资源类型,控制器专用于管控其对应类型的资源对象

◆例如,Deployment控制器对应有Deployment资源类型

◆这些资源类型都是Kubernetes上标准的API资源,并遵循资源规范的通用格式

★ 用户需要编排某应用时,需要事先确认好应用的运行目标模式,例如实例数据及结束条件等,并根据模式选出对应的工作负载控制器类型

★ 而后根据相应控制器的资源类型的规范,编写资源配置,并提交给API Server即可

★ 相应控制器监视到API Server上新建的资源后,即会运行代码确保对象实例的实际状态(Status)与期望状态(Spec)一致

  • 注意:控制器对象仅负责确保API Server上有相应数量的符合标签选择器的Pod对象的定义,至于Pod对象的Status如何与Spec保持一致,则要由相应节点上的kubelet负责保证
4-5、Deployment资源及控制器
  • 负责编排无状态应用的基础控制器是ReplicaSet,相应的资源类型通过三个关键组件定义如何编排一个无状态应用

★ replicas:期望运行的Pod副本数

★ selector:标签选择器

★ podTemplate:Pod模板

  • Deployment是建立在ReplicaSet控制器上层的更高级的控制器

★ 借助于ReplicaSet完成无状态应用的基本编排任务

★ 它位于ReplicaSet更上面一层,基于ReplicaSet提供了滚动更新回滚等更为强大的应用编排功能

★ 是ReplicaSet资源的编排工具

◆Deployment编排ReplicaSet

◆ReplicaSet编排Pod

★ 但是,应该直接定义Deployment资源来编排Pod应用,ReplicaSet无须显式给出

4-6、获取资源状态
  • 获取ReplicaSet资源对象的状态
~$ kubectl get replicasets/rs-example
NAME DESIRED CURRENT READY AGE
rs-example 2 2 2 115s
#说明:
DESIRED:期望的Pod数量
CURRENT:当前的Pod数量
READY:就绪状态的Pod数量
AGE:当前资源的创建后生存时长
  • 获取Deployment资源对象的状态
~$ kubectl get deployment/deploy-example
NAME READY UP-TO-DATE AVAILABLE AGE
deploy-example 2/2 2 2 27s
#说明:
READY:就绪的Pod数量/期望的Pod数量
UP-TO-DATE:到达期望的版本的Pod数量
AVAILABE:运行中并可用的Pod数量
AGE:当前资源的创建后生存时长
  • Deployment自动创建的ReplicaSet被添加等同于Pod对象的标签
~$ kubectl get replicasets -l app=demoapp,release=stable
NAME DESIRED CURRENT READY AGE
deploy-example-66db74fcfc 2 2 2 6m
4-7、更新策略
  • Deployment控制器支持两种更新策略

★ 滚动式更新(rolling updates)

◆逐批次更新Pod的方式,支持按百分比或具体的数量定义批次规模,默认策略

◆触发条件:podTemplate的hash码变动

● 仅podTemplate的配置变动才会导致hash码改变

● replicas和selector的变更不会导致podTemplate的hash变动

★ 重建式更新(recreate)

◆在Pod资源被删除时,使用新的模板定义被足缺失的Pod数量,完成更新

◆触发条件:现有Pod被删除

strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
4-8、触发更新
  • 触发滚动更新

★ 最为常见的更新需求是应用升级,即镜像文件更新,常用方法

◆~$ kubectl set image (-f FILENAME | TYPE NAME) CONTAINER_NAME_1=CONTAINER_IMAGE_1 ...

◆~$ kubectl patch (-f FILENAME | TYPE NAME) [-p PATCH|--patch-file FILE] [options]

◆直接更新原配置文件,而后使用“kubectl apply”命令触发更新

★ 上面第二和第三种方法可用于模板中任何必要配置的更新

  • 查看更新

★ 更新状态:kubectl rollout status (TYPE NAME | TYPE/NAME) [flags] [options]

★ 更新历史:kubectl rollout history (TYPE NAME | TYPE/NAME) [flags] [options]

  • 回滚

★ 回滚到前一版本: kubectl rollout undo (TYPE NAME | TYPE/NAME)

★ 回滚到指定版本: kubectl rollout undo (TYPE NAME | TYPE/NAME) --to-revisinotallow=X

4-9、配置滚动更新策略
  • Deployment的滚动更新支持使用如下两个字段来配置相关的策略

★ maxSurge:指定升级期间存在的总Pod对象数量最多可超出期望值的个数,其值可以是0或正整数,也可以是相对于期望值的一个百分比

★ maxUnavailable:升级期间正常可用的Pod副本数(包括新旧版本)最多不能低于期望值的个数,其值可以是0或正整数,也可以是相对于期望值的一个百分比,默认值为1

kubernetes-003_选择器_07

  • 存在的问题:必须以Pod为原子单位切割规模比例,且无法控制流量路由比例;
4-10、扩容和缩容
  • 容量管理类型

★ 横向伸缩:增加或减少Pod数量

★ 纵向(垂直)伸缩:调整Pod上的资源需求和资源限制

  • 变动Deployment资源对象中的replicas字段的值即会触发应用规模的扩容或缩容

★ 扩容和缩容是ReplicaSet的功能,具体操作由ReplicaSet完成

★ 根据应用规模的需要进行手动配置

  • 操作方法

★ patch命令

◆kubectl patch (-f FILENAME | TYPE NAME) [-p PATCH|--patch-file FILE] [options]

◆例如:kubectl patch deployment deploy-example -p '{"spec":{"replicas":3}}'

★ 直接更新原配置文件,而后使用“kubectl apply”命令触发更新

  • 扩展:自动扩容和缩容

★ HPA(Horizontal Pod Autoscaler)控制器

★ VPA(Vertical Pod Autoscaler)控制器

5、DaemonSet

5-1、DaemonSet的应用编排机制
  • 使用DaemonSet编排应用

★ 同Deployment相似,DaemonSet基于标签选择器管控一组Pod副本;

★ 但是,DaemonSet用于确保所有或选定的工作节点上都运行有一个Pod副本

◆提示:DaemonSet的根本目标在于让每个节点一个 Pod

◆有符合条件的新节点进入时,DaemonSet会将Pod自动添加至相应节点;而节点的移出,相应的Pod副本也将被回收;

  • 常用场景

★ 特定类型的系统化应用,例如kube-proxy,以及Calico网络插件的节点代理calico-node等

★ 集群存储守护进程、集群日志收集守护进程以及节点监控守护进程等

5-2、DaemonSet的资源规范

与Deployment相似,DaemonSet对象也使用标签选择器和Pod模板,区别之处在于,DaemonSet不需要定义replicas(Pod副本数量),其Pod数量随节点数量而定;

apiVersion: apps/v1 # API群组及版本;
kind: DaemonSet # 资源类型特有标识;
metadata:
name <string> # 资源名称,在作用域中要惟一;
namespace <string> # 名称空间;DaemonSet资源隶属名称空间级别;
spec:
minReadySeconds <integer> # Pod就绪后多少秒内任一容器无crash方可视为“就绪”;
selector <object> # 标签选择器,必须匹配template字段中Pod模板中的标签;
template <object> # Pod模板对象;
revisionHistoryLimit <integer> # 滚动更新历史记录数量,默认为10;
updateStrategy <Object> # 滚动更新策略
type <string> # 滚动更新类型,可用值有OnDelete和RollingUpdate;
rollingUpdate <Object> # 滚动更新参数,专用于RollingUpdate类型;
maxUnavailable <string> # 更新期间可比期望的Pod数量缺少的数量或比例;
5-3、查看DaemonSet状态
  • 使用kubectl get daemonset命令
~$ kubectl get daemonsets/daemonset-demo
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
daemonset-demo 2 2 2 2 2 <none> 2m

~$ kubectl get pods -l app=prometheus -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
daemonset-demo-694mw 1/1 Running 0 3m 172.29.1.11 k8s-node01.magedu.com <none> <none>
daemonset-demo-lmnpd 1/1 Running 0 3m 172.29.1.12 k8s-node02.magedu.com <none> <none>
#状态描述:

DESIRED:期望存在的Pod副本数
AVAILABLE:可用的Pod副本数
CURRENT:当前已存在的Pod副本数
NODE SELECTOR:节点选择器,<node>表示未使用选择器,因而将适配到所有节点
READY:当前已经转为就绪状态的Pod副本数
AGE:资源已经创建的时长
UP-TO-DATE :已经更新到期望版本的Pod副本数
5-4、更新策略
  • 更新策略

★ rollingUpdate:滚动更新,自动触发

★ onDelete:删除时更新,手动触发

  • 滚动更新

★ 配置策略:rollingUpdate更新策略支持使用maxUnavailable参数来定义单批次允许更新的最大副本数量

★ 更新方式

◆~$ kubectl set image (-f FILENAME | TYPE NAME) CONTAINER_NAME_1=CONTAINER_IMAGE_1 ...

◆~$ kubectl patch (-f FILENAME | TYPE NAME) [-p PATCH|--patch-file FILE] [options]

◆直接更新原配置文件,而后使用“kubectl apply”命令触发更新

6、Job和CronJob

6-1、Job控制器的应用编排机制

Job负责编排运行有结束时间的“一次性”任务,而前面的Deployment和DaemonSet主要负责编排始终运行的守护进程类应用;

  • 控制器要确保Pod内的进程“正常(成功完成任务)”地退出
  • 非正常退出的Pod可以根据需要重启,并在重试一次的次数后终止
  • 有些Job是单次任务,也有些Job需要运行多次(次数通常固定)
  • 有些任务支持同时创建及并行运行多个Pod以加快任务处理速度,Job控制器还允许用户自定义其并行度

需要周期性运行的Job,则由CronJob控制器负责编排

  • CronJob建立在Job的功能之上,是更高层级的控制器
  • 它以Job控制器完成单批次的任务编排,而后为这种Job作业提供需要运行的周期定义
6-2、Job资源规范

Job资源同样需要标签选择器和Pod模板,但它不需要指定replicas,而是应该给定completions,即需要完成的作业次数,默认为1次;

  • Job资源会为其Pod对象自动添加“job-name=JOB_NAME”和“controller-uid=UID”标签,并使用标签选择器完成对controller-uid标签的关联,因此,selector并非必选字段
  • Pod的命名格式:`$(job-name)-$(index)-$(random-string),其中的$(index)字段取值与completions和completionMode有关

注意

◆ Job资源所在群组为“batch/v1”

◆ Job资源中,Pod的RestartPolicy的取值只能为Never或OnFailure

apiVersion: batch/v1 # API群组及版本;
kind: Job #资源类型特有标识;
metadata:
name <string> #资源名称,在作用域中要惟一;
namespace <string> #名称空间; Job 资源隶属名称空间级别;
spec:
selector <object> #标签选择器,必须匹配 template 字段中 Pod 模板中的标签;
suspend <boolean > # 是否挂起当前 Job 的执行,挂起作业会重置 StartTime 字段的值;
template <object> # Pod模板对象;
completions <integer> #期望的 成功完作业次数,运行结束Pod 数量;
completionMode <string> # 追踪 Pod 完成的模式,支持 Indexed 和NonIndexedNonIndexed(默认)两种;
ttlSecondsAfterFinished <integer> # 终止状态作业的生存时长,超期将被删除;
parallelism <integer> #作业的最大并行度,默认为 1;
backoffLimit<integer> # 将作业标记为“ Failed” 之前的重试次数,默认为 6;
activeDeadlineSeconds <integer> #作业启动后可处于活动状态的时长;

使用kubectl get jobs命令

使用kubectl describe jobs命令

~$ kubectl get jobs job-demo
NAME COMPLETIONS DURATION AGE
job-demo 1/3 58s 58s

~$ kubectl get pods -l job-name=job-demo
NAME READY STATUS RESTARTS AGE
job-demo--1-4vds6 1/1 Running 0 5s
job-demo--1-5xd5s 0/1 Completed 0 44s

状态描述(示例集群中共有两个工作节点):

COMPLETIONS:已经正常完成任务并退出的Pod数量

DURATION:Job业务的实际运行时长

AGE:Job资源创建后的时长

6-3、并行式Job
  • Job对象能够支持多个Pod的可靠、并发执行

★ 编排彼此间相互通信的并行进程并非Job的设计目标,它仅用于支撑一组相互独立而又有所关联的工作任务的并行处理

★ 常见的场景,有如发送电子邮件、渲染视频帧、编解码文件、NoSQL数据库中扫描主键范围等

◆ 并行式Job的关键配置参数

★ parallelism:任务并行度,即最大可同行运行的Pod数量,可以将其理解为工作队列的数量

★ completions:总共需要完成的任务数量,即总共需要多少个相关的Pod成功完成执行,通常要大于parallelism的值

[root@k8s-master01 ~]#vim para-job-demo.yaml
apiVersion: batch/v1
kind: Job
metadata:
creationTimestamp: null
name: para-job-demo
spec:
template:
metadata:
creationTimestamp: null
spec:
containers:
- image: ikubernetes/admin-box:v1.0
imagePullPolicy: IfNotPresent
command: ["/bin/sh","-c","sleep 30"]
name: para-job-demo
restartPolicy: OnFailure
completions: 7
parallelism: 2
completionMode: Indexed
ttlSecondsAfterFinished: 3600
backoffLimit: 3
activeDeadlineSeconds: 1200

[root@k8s-master01 ~]#kubectl apply -f para-job-demo.yaml
job.batch/para-job-demo created

[root@k8s-master01 ~]#kubectl get job
NAME COMPLETIONS DURATION AGE
para-job-demo 0/7 20s 20s

[root@k8s-master01 ~]#kubectl get job -w
NAME COMPLETIONS DURATION AGE
para-job-demo 2/7 99s 99s
para-job-demo 2/7 105s 105s
para-job-demo 3/7 106s 106s
para-job-demo 3/7 110s 110s
para-job-demo 3/7 112s 112s
para-job-demo 4/7 114s 114s
para-job-demo 4/7 118s 118s
para-job-demo 4/7 2m21s 2m21s
para-job-demo 5/7 2m24s 2m24s
para-job-demo 5/7 2m27s 2m27s
para-job-demo 6/7 2m29s 2m29s
para-job-demo 6/7 3m 3m
para-job-demo 7/7 3m3s 3m3s
para-job-demo 7/7 3m3s 3m3s
6-4、CronJob
  • CronJob控制器用于管理Job资源的运行时间,它允许用户在特定的时间或以指定的间隔运行Job
  • CronJob控制器的功能类似于linux操作系统的周期性任务作业计划(crontab),用于控制作业运行的时间点及周期性运行的方式:

★ 仅在未来某时间点将指定的作业运行一次

★ 在指定的周期性时间点重复运行指定的作业

  • CronJob资源也是标准的API资源类型
  • 注意:

在CronJob中,通配符“?”和“*”的意义相同,它们都表示任何可用的有效值

apiVersion: batch/v1     # API群组及版本;
kind: CronJob # 资源类型特有标识;
metadata:
name <string> # 资源名称,在作用域中要惟一;
namespace <string> # 名称空间;CronJob资源隶属名称空间级别;
spec:
jobTemplate <Object> # job作业模板,必选字段;
metadata <object> # 模板元数据;
spec <object> # 作业的期望状态;
schedule <string> # 调度时间设定,必选字段;
concurrencyPolicy <string> # 并发策略,可用值有Allow、Forbid和Replace;
failedJobsHistoryLimit <integer> # 失败作业的历史记录数,默认为1;
successfulJobsHistoryLimit <integer> # 成功作业的历史记录数,默认为3;
startingDeadlineSeconds <integer> # 因错过时间点而未执行的作业的可超期时长;
suspend <boolean> # 是否挂起后续的作业,不影响当前作业,默认为false;