学习笔记
分享学习经验,记录生活点滴

pod的副本机制和其他控制器:部署托管的pod

部署托管的pod

1 保持pod健康

​ 只要将pod调度到某个节点,该节点上的Kubelet就会运行pod的容器,从此只要该pod存在,就会保持运行。如果容器的主进程崩溃,Kubelet将重启容器。如果应用程序中有一个导致它每隔一段时间就会崩溃的bug,Kubernetes会自动重启应用程序,所以即使应用程序本身没有做任何特殊的事,在Kubernetes中运行也能自动获得自我修复的能力。

1.1 存活探针

​ Kubernetes可以通过存活探针(liveness probe)检查容器是否还在运行。可以为pod中的每个容器单独指定存活探针。如果探测失败,Kubernetes将定期执行探针并重新启动容器。

Kubernetes有以下三种探测容器的机制:

  • HTTP GET探针对容器的IP地址(指定的端口和路径)执行HTTPGET请求。
  • TCP套接字探针尝试与容器指定端口建立TCP连接。
  • Exec探针在容器内执行任意命令,并检查命令的退出状态码。如果状态码是0,则探测成功。所有其他状态码都被认为失败。

1.2 创建基于HTTP的存活指针

apiVersion:v1
kind:Pod
metadata:
    name:kubia-liveness
spec:
    containers:
    -image:luksa/kubia-unhealthy  #这个镜像包含了(不知道怎么的)坏掉的应用
        name:kubia
        livenessProbe:            #一个HTTP GET存活指针
            httpGet:              #
                path:/            #HTTP请求的路径
                port:8080         #探针连接的网络端口

1.3 使用存活指针

​ 要查看存活探针是如何工作的,需要尝试立即创建该pod。大约一分半钟后,容器将重启。可以通过运行kubectl get看到容器重启的次数。

1.4 配置存活探针的附加属性

定义探针时可以自定义附加参数。例如,要设置初始延迟,可以将initialDelaySeconds 属性添加到存活探针的配置中,如下面的代码清单所示。

livenessProbe:
    httpGet:
        path:/
        port:8080
    initialDelaySeconds:15  #Kubernetes会在第一次探测前等待15秒

1.5 创建有效的存活指针

​ 对于在生产中运行的pod,一定要定义一个存活探针。没有探针的话,Kubernetes无法知道你的应用是否还活着。只要进程还在运行,Kubernetes会认为容器是健康的。

简易的存活探针仅仅检查了服务器是否响应。

保持探针轻量

​ 存活探针不应消耗太多的计算资源,并且运行不应该花太长时间。

无须在探针中实现重试循环

存活探针小结:

​ 知道Kubernetes会在容器崩溃或其存活探针失败时,通过重启容器来保持运行。这项任务由承载pod的节点上的Kubelet执行---在主服务器上运行的Kubernetes Control Plane组件不会参与此过程。

​ 但如果节点本身崩溃,那么Control Plane必须为所有随节点停止运行的pod创建替代品。它不会为你直接创建的pod执行此操作。这些pod只被Kubelet管理,但由于Kubelet本身运行在节点上,所以如果节点异常终止,它将无法执行任何操作。

​ 为了确保应用程序在另一个节点上重新启动,需要使用ReplicationController或类似机制管理pod。

2 了解ReplicationController

​ ReplicationController是一种Kubernetes资源,可确保它的pod始终保持运行状态。如果pod因任何原因消失(例如节点从集群中消失或由于该pod已从节点中逐出),则ReplicationController会注意到缺少了pod并创建替代pod。

2.1 ReplicationController的操作

​ ReplicationController会持续监控正在运行的pod列表,并保证相应“类型”的pod的数目与期望相符。如正在运行的pod太少,它会根据pod模板创建新的副本。如正在运行的pod太多,它将删除多余的副本。

控制器的协调流程:

1564370020610

ReplicationController的三部分:

  • label selector(标签选择器),用于确定ReplicationController作用域中有哪些pod
  • replica count(副本个数),指定应运行的pod数量
  • pod template(pod模板),用于创建新的pod副本

更改标签选择器和pod模板对现有pod没有影响

使用ReplicationController的好处:

  • 确保一个pod(或多个pod副本)持续运行,方法是在现有pod丢失时启动一个新pod
  • 集群节点发生故障时,它将为故障节点上运行的所有pod(即受ReplicationController 控制的节点上的那些pod)创建替代副本
  • 它能轻松实现pod的水平伸缩——手动和自动都可以

2.2 创建一个ReplicationController

代码清单 ReplicationController的YAML定义:kubia-rc.yaml

apiVersion:v1
kind:ReplicationController  #配置定义了ReplicationController(RC)
metadata:
    name:kubia
spec:
    replicas:3
    selector:               #pod选择器决定了RC的操作对象
        app:kubia           #
    template:           #下面为创建新pod的模板
        metadata:
            labels:
                app:kubia
        spec:
            containers:
            -name:kubia
                image:luksa/kubia
                ports:
                -containerPort:8080

要创建ReplicationController,请使用已知的kubectl create命令:

$ kubectl create -f kubia-rc.yaml

2.3 使用ReplicationController

获取有关ReplicationController的信息:

$ kubectl get rc

可以通过kubectl describe 命令看到ReplicationController的附加信息:

$ kubectl describe rc kubia

控制器如何创建新的pod

控制器通过创建一个新的替代pod来响应pod的删除操作

2.4 将pod移入或移出ReplicationController的作用域

​ 由ReplicationController创建的pod并不是绑定到ReplicationController。在任可时刻,ReplicationController管理与标签选择器匹配的pod。通过更改pod的标签,可以将它从ReplicationController的作用域中添加或删除。

2.5 修改pod模板

使用以下命令编辑ReplicationController:

$ kubectl edit rc kubia

2.6 水平缩放pod

ReplicationController扩容:

$ kubectl scale rc kubia --replicas=10

通过编辑定义来缩放 ReplicationController

$ kubectl edit rc kubia

当文本编辑器打开时,找到spec.replicas字段并将其值更改为10

2.7 删除一个ReplicationController

​ 当通过kubectl delete删除ReplicationController时,pod也会被删除。但是由于由ReplicationController创建的pod不是ReplicationController的组成部分,只是由其进行管理,因此可以只删除ReplicationController并保持pod运行。

​ 当使用kubectl delete删除ReplicationController时,可以通过给命令增加--cascade=false选项来保持pod的运行。

$ kubectl delete rc kubia --cascade=false

3 使用ReplicaSet而不是ReplicationController

3.1 比较ReplicaSet 和ReplicationController

​ ReplicaSet的行为与ReplicationController完全相同,但pod选择器的表达能力更强。ReplicationController的标签选择器只允许包含某个标签的匹配pod,但ReplicaSet的选择器还允许匹配缺少某个标签的pod,或包含特定标签名的pod,不管其值如何。
​ 另外,举个例子,单个ReplicationControler无法将pod与标签env=production和env=devel同时匹配。它只能匹配带有env=production标签的pod或带有env=devel标签的pod。但是一个ReplicaSet可以匹配两组pod并将它们视为一个大组。

​ 同样,无论ReplicationController的值如何,ReplicationController都无法仅基于标签名的存在来匹配pod,而ReplicaSet则可以。例如,ReplicaSet可匹配所有包含名为env的标签的pod,无论ReplicaSet的实际值是什么(可以理解为env=*)。

3.2 定义ReplicaSet

代码清单 ReplicaSet的YAML定义:kubia-replicaset.yaml

apiVersion:apps/v1beta2
kind:ReplicaSet
metadata:
    name:kubia
spec:
    replicas:3
    selector:
        matchLabels:   #这里使用了更简单的mathLabels选择器,这非常类似于ReplicationController
            app:kubia  #的选择器
    template:       #该模板与ReplicationController中的相同
        metadata:
            labels:
                app:kubia
        spec:
            containers:
                -name:kubia
                image:luksa/kubia

3.3 创建和检查 ReplicaSet

使用kubectl create 命令根据YAML文件创建ReplicaSet。之后,可以使用kubectl getkubectl describe 来检查ReplicaSet:

$ kubectl get rs

$ kubectl describe rs

3.4 使用ReplicaSet的更富表达力的标签选择器

​ ReplicaSet相对于ReplicationController的主要改进是它更具表达力的标签选择器。之前故意在第一个ReplicaSet示例中,用较简单的matchLabels选择器来确认ReplicaSet与ReplicationController没有区别。现在,将用更强大的matchExpressions属性来重写选择器,如下面的代码清单所示。

selector:
    matchExpressions:
    - key:app  #此选择器要求改pod包含名为"app"的标签
    operator:In    #
        values:    #  标签的值必须是"kubia"
            -kubia #  

​ 可以给选择器添加额外的表达式。如示例,每个表达式都必须包含一个key、一个operator(运算符),并且可能还有一个values的列表(取决于运算符)。
​ 会看到四个有效的运算符:

  • In:Label的值必须与其中一个指定的values匹配
  • NotIn:Label的值与任何指定的values不匹配
  • Exists:pod必须包含一个指定名称的标签(值不重要),使用此运算符时,不应指定values字段
  • DoesNotExist:pod不得包含有指定名称的标签,values属性不得指定。

4 使用DaemonSet在每个节点上运行一个pod

4.1 使用DaemonSet 在每个节点上运行一个pod

​ 要在所有集群节点上运行一个pod,需要创建一个DaemonSet对象,这很像一个ReplicationController或ReplicaSet,除了由DaemonSet创建的pod,已经有一个指定的目标节点并跳过Kubernetes调度程序。它们不是随机分布在集群上的。

4.2 使用DaemonSet只在特定的节点上运行pod

​ DaemonSet将pod部署到集群中的所有节点上,除非指定这些pod只在部分节点上运行。这是通过pod模板中的nodeSelector属性指定的,这是DaemonSet定义的一部分(类似于ReplicaSet 或ReplicationController中的pod模板)。

5 运行执行单个任务的pod

​ ReplicationController、ReplicaSet和DaemonSet会持续运行任务,永远达不到完成态。这些pod中的进程在退出时会重新启动。但是在一个可完成的任务中,其进程终止后,不应该再重新启动。

5.1 Job资源

​ Job允许你运行一种pod,该pod在内部进程成功结束时,不重启容器。一旦任务完成,pod就被认为处于完成状态。

​ 在发生节点故障时,该节点上由Job管理的pod 将按照ReplicaSet的pod的方式,重新安排到其他节点。如果进程本身异常退出(进程返回错误退出代码时),可以将Job配置为重新启动容器。

5.2 定义Job资源

代码清单 Job的YAML定义:exporter.yaml

apiVersion:batch/v1  #Job属于batch API组,版本为v1
kind:Job
metadata:
    name:batch-job
spec:             #没有指定pod选择器,它将根据pod模板中的标签创建
    template:
        metadata:
            labels:
                app:batch-job
        spec:
            restartPolicy:OnFailure  #Job不能使用Always为默认的重新启动策略
            containers:
            -name:main
                image:luksa/batch-job

​ 在一个pod的定义中,可以指定在容器中运行的进程结束时,Kubernetes会做什么。这是通过pod配置的属性restartPolicy完成的,默认为Always。Job pod不能使用默认策略,因为它们不是要无限期地运行。因此,需要明确地将重启策略设置为OnFailure或Never。此设置防止容器在完成任务时重新启动(pod被Job管理时并不是这样的)。

6 安排Job定期运行或在将来运行一次

​ Job资源在创建时会立即运行pod。但是许多批处理任务需要在特定的时间运行,或者在指定的时间间隔内重复运行。在Linux和类UNIX操作系统中,这些任务通常被称为cron任务。Kubernetes也支持这种任务。

​ Kubernetes中的cron任务通过创建CronJob资源进行配置。运行任务的时间表以知名的cron格式指定,所以熟悉常规cron任务,将在几秒钟内了解Kubernetes的CronJob。
​ 在配置的时间,Kubernetes 将根据在CronJob对象中配置的Job模板创建Job资源。创建Job资源时,将根据任务的pod模板创建并启动一个或多个pod副本,如你在前一部分中所了解的那样。

6.1 创建一个CronJob

代码清单 CronJob资源的YAML:cronjob.yaml

apiversion:batch/v1betal
kind:CronJob
metadata:
    name:batch-job-every-fifteen-minutes
spec:
    schedule:"0,15,30,45****"  #这项工作应该每天在每小时0、15、30、45分钟运行
    jobTemplate:
        spec:
            template:    #以下部分为CronJob创建Job资源用到的模板
                metadata:
                    labels:
                        app:periodic-batch-job
                spec:
                    restart Policy:OnFailure
                    containers:
                    -name:main
                        image:1uksa/batch-job

配置时间表安排(简单版):

  • 分钟
  • 小时
  • 每月中的第几天
  • 星期几

配置Job模板

CronJob通过CronJob规范中配置的jobTemplate属性创建任务资源。

6.2 了解计划任务的运行方式

​ 在计划的时间内,CronJob资源会创建Job资源,然后Job创建pod。
​ 可能发生Job或pod创建并运行得相对较晚的情况。你可能对这项工作有很高的要求,任务开始不能落后于预定的时间过多。在这种情况下,可以通过指定CronJob规范中的startingDeadlineSeconds字段来指定截止日期,如下面的代码清单所示。

apiversion:batch/v1betal
kind:CronJob
spec:
    schedule:"0,15,30,45****
    startingDeadlineSeconds:15  #pod最迟必须在预定时间后15秒开始运行
    ...

​ 假设工作运行的时间是10:30:00。如果因为任何原因10:30:15不启动,任务将不会运行,并将显示为Failed。

7 小结

  • 使用存活探针,让Kubernetes在容器不再健康的情况下立即重启它(应用程序定义了健康的条件)。
  • 不应该直接创建pod,因为如果它们被错误地删除,它们正在运行的节点异常,或者它们从节点中被逐出时,它们将不会被重新创建。
  • ReplicationController始终保持所需数量的pod副本正在运行。
  • 水平缩放pod与在ReplicationController上更改所需的副本个数一样简单。
  • pod 不属于ReplicationController,如有必要可以在它们之间移动。
  • ReplicationController将从pod模板创建新的pod。更改模板对现有的pod没有影响。
  • ReplicationController 应该替换为ReplicaSet和DaemonSet,它们提供相同的能力,但具有额外的强大功能。
  • ReplicationController 和ReplicaSet 将pod 安排到随机集群节点,而DaemonSet确保每个节点都运行一个DaemonSet中定义的pod实例。
  • 执行批处理任务的pod应通过KubernetesJob资源创建,而不是直接或通过ReplicationController或类似对象创建。
  • 需要在未来某个时候运行的Job可以通过CronJob资源创建。
赞(7) 打赏
未经允许不得转载:ABCLearning » pod的副本机制和其他控制器:部署托管的pod
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

阿里云限时红包 助力一步上云

了解详情领取红包

觉得文章有用就打赏一下文章作者

微信扫一扫打赏