4、副本机制和其他控制器
kubernetes 提供了两个探针,livenees probe与readnees probe 来影响容器的生存周期
这两个探针支持三种配置方法
- exec 执行一段命令
探针在容器中执行任何的命令,并检查命令运行退出的状态码,如果是0表示成功,所有其他的状态码都表示失败。 - HTTP 检测某个HTTP请求
通过HTTP GET探针对容器的IP地址(或指定的端口好路径)执行HTTP GET请求,如果收到响应,且响应返回的状态码不代表错误(如果HTTP的响应状态码是2xx,3xx),则认为探测成功。如果服务器返回错误的响应状态码或无响应,则认为探测失败,容器将重启
spec: #其他的内容没有列出
containers:
livenessProbe: # 存活探针的路径为spec.containers.livenessProbe
httpGet:
path: /
port: 8080
- tcpsocket kubelet
与容器指定的端口建立TCP连接,如果建立成功,则探测成功,否则,表示失败将重启容器
获取崩溃容器的应用日志
kubectl logs 可获取当前容器的日志,如果容器崩溃了重启了,你要获取前一个容器停止时的日志,可通过–previous选项来完成。 kubectl logs mypod --previous
也可通过kubectl describe的内容来获取为什么要重启的原因
livenees probe 存活探针
kubectl describe获取的内容中Liveness:中会列出其他一些详细信息
例如:
http-get http://8080/ delay=0s timeout=1s period=10s #success=1 #failure=3
delay=0s 表示延时,容器在启动时后立即开始探测
timeout=1s 表示超时时间为1s,容器必须在1s内响应
period=10s 表示探测的周期为10ss
#failure=3 表示探测连续三次失败后重启容器
livenessProbe:
httpGet:
path: /
port: 8080
initDelaySeconds: 15 # kubernetes 会在以一次探测时等待15s
如果没有设置延时,探针在启动时就立即开始探测容器,这通常会导致探测失败,所以要设置一个合适的初始延时时间
探针在创建时,尽量做到以下几点
- 保持探针的轻量:因为探测器执行的频率相对较高,如果探针过重会大大降低容器的运行。且探针的CPU时间会计入容器的CPU时间配额。
- 无须再探针中实现重试循环:探针的失败阈值是可以设置的,所以不用在探针中循环从而加重探针
- 如果容器中运行的是Java程序,清确保使用HTTP GET
存活探针,而不是启动全新的JVM以获取存活信息的exec探针。任何基于JVM的应用程序也是如此,它们的启动过程需要大量的计算资源
存活探针失败时,重启容器的任务,是由承载其Pod的节点上的kubelet执行
readiness probe 可读性探针(或称为就绪探针)
与存活探针一样类似,存在三种一样的类型
exec、HTTP、TCP socket
与存活探针不一样的是,存活探针是用来监听pod是否还正常,如果存活探针探测失败,探测pod出现问题,pod则会被kubernetes删除,且重新部署。就绪探针探测失败时,不会被kubernetes删除,只会继续探测,探测成功后kubernetes才会采取后续的动作
pod从开始到初始化完成能够正常工作,可能需要一定的时间,如果一开就将pod添加到服务中,则可能出现访问失败等现象。所以需要添加就绪探针,避免该类现象出现。当就绪探针探测成功后,再将pod添加到服务,探测失败则继续探测,一般默认探测周期为10s。
一般所有的pod都需要添加就绪探针,即使添加最简单的向基准URL发生HTTP请求。
不要将终止pod的逻辑添加到就绪探针中。
ReplicationController——RC
ReplicationController 是一种kubernetes的资源,可确保它的pod始终保持运行状态。RC会持续监听正在运行的pod列表,并保证相应的“类型”的pod数目与期望值一致。这里的“类型”指pod是否匹配某个标签选择器。
RC重要的三个部分
- label selector:标签选择器,用于确定RC作用域中有哪些pod
- pod template: pod模板文件,御用创建新的模板
- replicas count:副本的个数,指定运行的pod数量
RC的好处
- 确保一个(或对个)pod副本持续运行,方法是在现有的pod丢失时启动一个新的pod副本
- 集群节点发生故障时,它将为故障点上的运行的所有pod(受RC控制的节点上的那些pod)创建新的替代副本
- 能轻松的实现pod的水平伸缩,不管手动还是自动都可以
rc-demo.yaml
apiVersion: v1
kind: ReplicationController
metadata:
name: rc-name
spec:
replicas: 3 # 需要保持的副本个数
selector:
app: rc-label # pod选择器决定了RC的操作对象
template:
metadata:
labels:
app: rc-label # 该标签的值必须与pod选择器中的标签值匹配
spec:
containers:
- name: template-name1
image: image-name1
ports:
- containerPorts: 80
- name:template-name2
image: image-name2
ports:
- containerPorts: 80
...
模板中pod的标签必须与RC的标签选择器匹配,否则控制器将无休止的创建副本,因为新的pod的不会实际的副本数与期望值一致。为防止这种情况出现,API服务会校验RC的定义,不会接受错误配置。根本不指定选择器也是一种选择,会自动根据pod模板中的标签自动配置
控制器不会删除pod本身做出什么反应,而是对由此产生的pod副本数量状态发生变化做出反应。虽然RC会立即收到删除pod的通知,但这不是它创建新的pod的原因,该通知会触发控制器检查实际的pod数量,并采取措施。
将pod移入或移除RC的作用域
可以同修改已托管pod的标签,将pod移除当前RC的作用域。
kubectl label pod-name labelName=labelNewValue --overwrite
此时RC会检测到副本数变化,从而根据pod模板重新创建一个pod副本。而更改标签后的pod,它不再受监管,它将与其他通过手动创建的pod一致。
RC不关心托管的pod是否添加其他的附加标签,它只关心该pod是否具有RC标签选择器中引用的标签
修改pod模板
修改pod模板,只会影响之后新创建的pod,对之前的pod无影响。
kubectl edit rc rcName
会使用默认的编辑器打开rcName.yaml 文件,就可以修改pod模板的内容。修改完后,删除旧的pod,RC就会根据新的pod模板文件创建新的pod。也可使用该方法对pod进行升级,但是不推荐使用该方法,使用deployment是更好的方式。
配置 kubectl edit使用不同的文件编辑器
可通过修改KUBE_EDITOR 环境变量来设定kubectl edit 的默认编辑器
可通过 export KUBE_EDITOR="/usr/bin/nano" 或vim、vs(/usr/bin/code)
也可将其写到"~/.bashrc" 配置文件中
水平缩放pod
有两种方式可对pod进行水平缩放
- kubectl scale rc rcName --replicas=10 将会立即把pod的副本数更新到10
- kubectl edit rc rcName 直接编辑对应的yaml文件中replicas的值,也会立即更新
删除ReplicationController
kubectl delete rc rcName
可删除对应的rc,同时也会删除由该rc管理的pod
kubectl delete rc rcName --cascade=false
只删除rc,保存pod,这些pod将会独立起来,后续也可通过再创建rc将其管理起来
ReplicaSet
ReplicaSet是一个rc的升级版,并最终替换了rc(rc已被放弃),但有可能还会遇到rc,所以还是要学习的。
ReplicaSet与ReplicationController的行为完全相同,但是ReplicaSet在pod选择器上表达能力更强。rc只能选择包含某个的标签的pod进行匹配,但ReplicaSet还可以允许匹配缺少某个标签的pod,甚至包含特定标签名的pod,不管其值是多少。
ReplicaSet-demo.yaml
apiVersion: apps/v1beta2
kind: ReplicaSet
metadata:
name: replicaSet-name
spec:
replicas: 3 # 需要保持的副本个数
selector:
matchLabels:
app: replicaSet-label # pod选择器决定了ReplicaSet的操作对象
template:
metadata:
labels:
app: replicaSet-label # 该标签的值必须与pod选择器中的标签值匹配
spec:
containers:
- name: template-name1
image: image-name1
ports:
- containerPorts: 80
- name:template-name2
image: image-name2
ports:
- containerPorts: 80
...
需要注意的是apiVersion的值,且需要在selector.matchLabels下制定标签,而不是像rc直接列出
ReplicaSet在kubectl 命令操作时可简写为 “rs”
kubectl get rs 列出rs资源对象
kubectl describe rs rsName 列出rs的详情
kubectl delete rs rsName 删除rs,同时会删除pod
使用ReplicaSet更为丰富表达力的标签选择器
使用简单的matchLabel ,rs与rc没有区别。但rs可以使用强大的matchExpressions
selector:
matchExpressions:
- key: app # 需要选择的标签名
operator: In # label的值必须与其中的一个value值匹配
values:
- xxx # 标签的值,这是一个数组,可以有多个值
可以给选择器添加额外的表达式,每个表达式都必须包含一个key、operator,且有可能包含一个values的列表(取决于values)
运算符有四个
- In:Label的值必须与values列表中的一个值匹配
- NotIn:Label的值不能与values列表中的任何一个值匹配
- Exists:pod必须包含一个指定名称的标签,但是值不重要,使用此运算符时,不应有values
- NotExist:pod不得包含指定名称的标签,不应有values
如果有多个表达式,必须所有表达式的值都为true,pod才会选择器匹配。如果同时使用了matchLabel 与 matchExpressions,则所有标签都需要匹配,且所哟的表达式的值都要为true
DaemonSet
需要在所有集群节点上运行一个pod,这时就需要创建一个DaemonSet。ds值保证在每一个节点上运行一个pod,pod的构建也是跟ds的pod模板。
档一个节点下线后,DaemonSet 不会去其他节点再创建一个pod。档一个新的节点加入节点后,DaemonSet会立马在该节点上部署一个新的pod实例。
也可指定在特定的节点上运行DaemonSet,只要在pod模板文件中的nodeSelector属性指定即可。
有时候我们可以将节点设置为不可调度,防止pod部署到节点上。但是DaemonSet会将pod部署到这些节点上,因为不可调用的属性只会被调度器使用,而DaemonSet的目的是运行系统服务,所有还是会绕过调度器将pod部署到这些节点。即使是在不可调度的节点上,系统服务还是可以运行的。
ssd-daemonset-demo.yaml 只在带有ssd标签的节点上部署ds的pod
apiVersion: apps/v1beta2
kind: DeamonSet
metadata:
name: ssd-ds
spec:
selector:
matchLabels:
app: ssd
template:
metadata:
labels:
app: ssd
spec:
nodeSelector:
disk: ssd
containers:
- name: ssd-check
image: xxx
删除 DaemonSet,同时也会删除其部署的pod
(本文章是学习《kubernetes in action》 一书时做的笔记,由于本人是刚学习k8s,且自学方式就是把它敲一遍,然后加一些自己的理解。所以会发现很多内容是跟书中内容一模一样,如果本文是对本书的侵权,敬请谅解,告知后会删除。如果引用或转载,请注明出处——谢谢)