006-k8s资源控制器-ReplicaSet、Deployment、DaemonSet
一、概述
Pod的分类:
自主式Pod:自己编写,创建启动,Pod退出了,此类型的Pod不会被创建,上文学习时使用的Pod均是自主式:005-k8s资源清单-02-Pod生命周期、Init容器、以及编写yaml
控制器管理的Pod:在控制器的生命周期里,始终要维持Pod的副本数,生产使用此类。
1.1、Pod控制器及其功用
Pod控制器是用于实现管理pod的中间层,确保pod资源符合预期的状态,pod的资源出现故障时,会尝试 进行重启,当根据重启策略无效,则会重新新建pod的资源。
1.1.1、pod控制器有多种类型:
RC和RS【部署一般应用】
RelicationController:RC旧版本使用,新版本使用ReplicaSet。
ReplicaSet: 代用户创建指定数量的pod副本数量,确保pod副本数量符合预期状态,并且支持滚动式自动扩容和缩容功能。与RC一样只是名称不一致,并且RS支持集合式的selector;
ReplicaSet主要三个组件组成:
(1)用户期望的pod副本数量
(2)标签选择器,判断哪个pod归自己管理
(3)当现存的pod数量不足,会根据pod资源模板进行新建
帮助用户管理无状态的pod资源,精确反应用户定义的目标数量,但是RelicaSet不是直接使用的控制器,而是使用Deployment。
Deployment【部署一般应用】
工作在ReplicaSet之上,用于管理无状态应用,目前来说最好的控制器。支持滚动更新和回滚功能,还提供声明式配置。
定义Deployment来创建Pod和ReplicaSet
滚动升级和回滚应用
扩容和缩容
暂停和继续Deployment
DaemonSet【部署一守护进程类应用】
用于确保集群中的每一个节点只运行特定的pod副本,通常用于实现系统级后台任务。比如ELK服务;特性:服务是无状态的;服务必须是守护进程
确保全部(或者一些)Node上运行一个Pod的副本。当有Node加入集群时,也会为他们新增一个Pod,当有Node从集群移除时,这些Pod也会被回收。删除DaemonSet将会删除它创建的所有Pod
典型用法:运行集群存储daemon,例如在每个Node上运行glusterd、ceph
在每个Node上运行日志收集的daemon,如fluentd、logstash、ELK
在每个Node上运行监控daemon,如Prometheus Node Exportor、collectd、Datadog代理、New Relic代理或Ganglia gmond
Job【部署批处理任务】
只要完成就立即退出,不需要重启或重建。负责批处理任务,他保证批处理任务的一个或多个Pod成功结束
Cronjob【部署批处理任务】
周期性任务控制,不需要持续后台运行,给定时间只运行一次,分 时 日 月 周 ;如数据库备份、发邮件
StatefulSet:管理有状态应用
作为Control为Pod提供唯一的标识,他可以保证部署和scale的顺序。
StatefulSet是为了解决有状态服务问题(对应的Deployment和ReplicaSet均是为无状态服务而设计),其应用场景包括:
稳定的持久化存储,即Pod重新调度后还是能访问到相同的持久化数据,基于PVC来实现
稳定的网络标志,即Pod重新调度后其PodName和HostName不变,基于Headless Service(即没有ClusterIP的Service)来实现
有序部署,有序扩展,即Pod是有顺序的,在部署或者扩展的时候要依据定义的顺序依次进行(从0到N-1,在下一个Pod运行之前所有的Pod必须是Running和Ready状态),基于init containers来实现
有序收缩,有序删除(从N-1到0)
其实docker主要通过卷来管理有状态服务,k8s主要通过StatefulSet控制有状态服务,但是也有些不太适合被k8s管理,如mysql这个有状态的服务,但是mongodb就比较稳定
HPA(Horizontal Pod Autoscaling)
应用的资源使用率通常都有高峰和低谷的时候,如何削峰填谷,提高集群的整体资源利用率,让service中的pod个数自动调整。使用HPA,使Pod水平自动缩放。可基于指标,如cpu,增加资源收集方案才可以使用。
上述中:
命令式编程:侧重于如何实现程序,按照逻辑一步一步编写;rs的create命令
声明式编程:侧重于定义想要什么,然后告诉计算机、引擎,让他去实现,如sql语句。主要有:deployment 的apply命令
二、详细讲解
2.1、ReplicaSet控制器
ReplicationController用来确保容器应用的副本数始终保持在用户定义的副本数,即如果有容器异常退出,会自动创建新的Pod来替代;而如果异常多出来的容器也会自动回收。
在新版本的Kubernetes中建议使用ReplicaSet来取代ReplicationController。ReplicaSet跟ReplicationController没有本质的不同,只是名字不一样,并且ReplicaSet支持集合式的selector。
虽然ReplicaSet可以独立使用,但一般还是建议使用 Deployment 来自动管理ReplicaSet,这样就无需担心跟其他机制的不兼容问题(比如ReplicaSet不支持rolling-update但Deployment支持)。RS是通过控制label标签来控制版本
(1)命令行查看ReplicaSet清单定义规则
[root@k8s-master ~]# kubectl explain rs [root@k8s-master ~]# kubectl explain rs.spec [root@k8s-master ~]# kubectl explain rs.spec.template
(2)新建ReplicaSet示例
vim rs-demo.yaml
apiVersion: apps/v1 #api版本定义 kind: ReplicaSet #定义资源类型为ReplicaSet metadata: #元数据定义 name: myapp namespace: default spec: #ReplicaSet的规格定义 replicas: 2 #定义副本数量为2个 selector: #标签选择器,定义匹配pod的标签 matchLabels: app: myapp release: v1 template: #pod的模板定义 metadata: #pod的元数据定义 name: myapp-pod #自定义pod的名称 labels: #定义pod的标签,需要和上面定义的标签一致,也可以多出其他标签 app: myapp release: v1 environment: qa spec: #pod的规格定义 containers: #容器定义 - name: myapp-container #容器名称 image: 10.0.0.82/library/myapp:v1 #容器镜像 ports: #暴露端口 - name: http containerPort: 80
(3)创建ReplicaSet定义的pod
[root@k8s-master ~]# kubectl create -f rs-demo.yaml
[root@k8s-master ~]# kubectl get pods #获取pod信息
[root@k8s-master ~]# kubectl describe pods myapp #查看pod详细信息
(4)修改pod的副本数量
[root@k8s-master ~]# kubectl edit rs myapp
replicas: 5
[root@k8s-master ~]# kubectl get rs -o wide
(5)修改pod的标签【RS 通过标签管理 pod副本数,删除也是按照标签删除】
查看 : kubectl get pod --show-labels
NAME READY STATUS RESTARTS AGE LABELS
myapp-88dl2 1/1 Running 0 2m12s app=myapp,environment=qa,release=v1
myapp-q4lzr 1/1 Running 0 7m6s app=myapp,environment=qa,release=v1
myapp-xpjg5 1/1 Running 0 7m6s app=myapp,environment=qa,release=v1
修改其中一个:kubectl label pod myapp-88dl2 release=v2 --overwrite=True
再次查看:kubectl get pod --show-labels
NAME READY STATUS RESTARTS AGE LABELS
myapp-88dl2 1/1 Running 0 4m50s app=myapp,environment=qa,release=v2
myapp-b6q48 1/1 Running 0 11s app=myapp,environment=qa,release=v1
myapp-q4lzr 1/1 Running 0 9m44s app=myapp,environment=qa,release=v1
myapp-xpjg5 1/1 Running 0 9m44s app=myapp,environment=qa,release=v1
发现原来的没变 labels修改,由于rs是通过控制标签管理版本,故标签变了,结果副本数缺少,又新建了一个。
2.2、Deployment
Deployment为Pod和Replica Set(下一代Replication Controller)提供声明式更新。
只需要在 Deployment 中描述想要的目标状态是什么,Deployment controller 就会帮您将 Pod 和ReplicaSet 的实际状态改变到您的目标状态。也可以定义一个全新的 Deployment 来创建 ReplicaSet 或者删除已有的 Deployment 并创建一个新的来替换。
使用过程如下:
- (1)使用Deployment来创建ReplicaSet。ReplicaSet在后台创建pod。检查启动状态,看它是成功还是失败。
- (2)然后,通过更新Deployment的PodTemplateSpec字段来声明Pod的新状态。这会创建一个新的ReplicaSet,Deployment会按照控制的速率将pod从旧的ReplicaSet移动到新的ReplicaSet中。
- (3)如果当前状态不稳定,回滚到之前的Deployment revision。每次回滚都会更新Deployment的revision。
- (4)扩容Deployment以满足更高的负载。
- (5)暂停Deployment来应用PodTemplateSpec的多个修复,然后恢复上线。
- (6)根据Deployment 的状态判断上线是否hang住了。
- (7)清除旧的不必要的 ReplicaSet。
1、解析Deployment Spec
首先看一个官方的nginx-deployment.yaml的例子:
apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment spec: replicas: 3 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.7.9 ports: - containerPort: 80
创建: kubectl apply -f nginx-deployment.yaml
[root@k8s-master01 ~]# kubectl get deployment NAME READY UP-TO-DATE AVAILABLE AGE nginx-deployment 3/3 3 3 49s [root@k8s-master01 ~]# kubectl get rs NAME DESIRED CURRENT READY AGE nginx-deployment-5754944d6c 3 3 3 53s [root@k8s-master01 ~]# kubectl get pod NAME READY STATUS RESTARTS AGE nginx-deployment-5754944d6c-6vpd5 1/1 Running 0 56s nginx-deployment-5754944d6c-b4p64 1/1 Running 0 56s nginx-deployment-5754944d6c-m7jxj 1/1 Running 0 56s
可以看到一次创建了Deployment、rs、pod
使用kubectl explain deployment.spec查看具体Deployment spec的配置选项,解析如下:
Replicas(副本数量):
.spec.replicas 是可以选字段,指定期望的pod数量,默认是1。
Selector(选择器):
.spec.selector是可选字段,用来指定 label selector ,圈定Deployment管理的pod范围。如果被指定, .spec.selector 必须匹配 .spec.template.metadata.labels,否则它将被API拒绝。如果 .spec.selector 没有被指定, .spec.selector.matchLabels 默认是.spec.template.metadata.labels。
在Pod的template跟.spec.template不同或者数量超过了.spec.replicas规定的数量的情况下,Deployment会杀掉label跟selector不同的Pod。
Pod Template(Pod模板):
.spec.template 是 .spec中唯一要求的字段。
.spec.template 是 pod template. 它跟 Pod有一模一样的schema,除了它是嵌套的并且不需要apiVersion 和 kind字段。
另外为了划分Pod的范围,Deployment中的pod template必须指定适当的label(不要跟其他controller重复了,参考selector)和适当的重启策略。
.spec.template.spec.restartPolicy 可以设置为 Always , 如果不指定的话这就是默认配置。
strategy(更新策略):
.spec.strategy 指定新的Pod替换旧的Pod的策略。 .spec.strategy.type 可以是"Recreate"或者是 "RollingUpdate"。"RollingUpdate"是默认值。
Recreate: 重建式更新,就是删一个建一个。类似于ReplicaSet的更新方式,即首先删除现有的Pod对象,然后由控制器基于新模板重新创建新版本资源对象。
rollingUpdate:滚动更新,简单定义 更新期间pod最多有几个等。可以指定maxUnavailable
和 maxSurge
来控制 rolling update 进程。
maxSurge:.spec.strategy.rollingUpdate.maxSurge
是可选配置项,用来指定可以超过期望的Pod数量的最大个数。该值可以是一个绝对值(例如5)或者是期望的Pod数量的百分比(例如10%)。当MaxUnavailable
为0时该值不可以为0。通过百分比计算的绝对值向上取整。默认值是1。
例如,该值设置成30%,启动rolling update后新的ReplicatSet将会立即扩容,新老Pod的总数不能超过期望的Pod数量的130%。旧的Pod被杀掉后,新的ReplicaSet将继续扩容,旧的ReplicaSet会进一步缩容,确保在升级的所有时刻所有的Pod数量和不会超过期望Pod数量的130%。
maxUnavailable:.spec.strategy.rollingUpdate.maxUnavailable
是可选配置项,用来指定在升级过程中不可用Pod的最大数量。该值可以是一个绝对值(例如5),也可以是期望Pod数量的百分比(例如10%)。通过计算百分比的绝对值向下取整。 如果.spec.strategy.rollingUpdate.maxSurge
为0时,这个值不可以为0。默认值是1。
例如,该值设置成30%,启动rolling update后旧的ReplicatSet将会立即缩容到期望的Pod数量的70%。新的Pod ready后,随着新的ReplicaSet的扩容,旧的ReplicaSet会进一步缩容确保在升级的所有时刻可以用的Pod数量至少是期望Pod数量的70%。
PS:maxSurge和maxUnavailable的属性值不可同时为0,否则Pod对象的副本数量在符合用户期望的数量后无法做出合理变动以进行更新操作。
在配置时,用户还可以使用Deployment控制器的spec.minReadySeconds属性来控制应用升级的速度。新旧更替过程中,新创建的Pod对象一旦成功响应就绪探测即被认为是可用状态,然后进行下一轮的替换。而spec.minReadySeconds能够定义在新的Pod对象创建后至少需要等待多长的时间才能会被认为其就绪,在该段时间内,更新操作会被阻塞。
revisionHistoryLimit(历史版本记录):
Deployment revision history存储在它控制的ReplicaSets中。默认保存记录10个
.spec.revisionHistoryLimit 是一个可选配置项,用来指定可以保留的旧的ReplicaSet数量。该理想值取决于心Deployment的频率和稳定性。如果该值没有设置的话,默认所有旧的Replicaset或会被保留,将资源存储在etcd中,是用kubectl get rs查看输出。每个Deployment的该配置都保存在ReplicaSet中,然而,一旦删除的旧的RepelicaSet,Deployment就无法再回退到那个revison了。
如果将该值设置为0,所有具有0个replica的ReplicaSet都会被删除。在这种情况下,新的Deployment rollout无法撤销,因为revision history都被清理掉了。
PS:为了保存版本升级的历史,需要再创建Deployment对象时,在命令中使用"--record"选项
rollbackTo:
.spec.rollbackTo
是一个可以选配置项,用来配置Deployment回退的配置。设置该参数将触发回退操作,每次回退完成后,该值就会被清除。
revision:.spec.rollbackTo.revision
是一个可选配置项,用来指定回退到的revision。默认是0,意味着回退到上一个revision。
progressDeadlineSeconds:
.spec.progressDeadlineSeconds
是可选配置项,用来指定在系统报告Deployment的failed progressing——表现为resource的状态中type=Progressing
、Status=False
、 Reason=ProgressDeadlineExceeded
前可以等待的Deployment进行的秒数。Deployment controller会继续重试该Deployment。未来,在实现了自动回滚后, deployment controller在观察到这种状态时就会自动回滚。
如果设置该参数,该值必须大于 .spec.minReadySeconds
。
paused:
.spec.paused
是可以可选配置项,boolean值。用来指定暂停和恢复Deployment。Paused和没有paused的Deployment之间的唯一区别就是,所有对paused deployment中的PodTemplateSpec的修改都不会触发新的rollout。Deployment被创建之后默认是非paused。
2、扩容
针对上述的deployment的nginx-deployment扩容,三种方式
(1)使用以下命令扩容 Deployment:
[root@k8s-master ~]# kubectl scale deployment nginx-deployment --replicas 5
(2)直接修改yaml文件的方式进行扩容:
[root@k8s-master ~]# vim nginx-deployment.yaml
修改.spec.replicas的值
spec:
replicas: 5
[root@k8s-master ~]# kubectl apply -f nginx-deployment.yaml
(3)通过打补丁的方式进行扩容:
[root@k8s-master ~]# kubectl patch deployment nginx-deployment -p '{"spec":{"replicas":5}}'
[root@k8s-master ~]# kuebctl get pods
如果集群支持hpa更新策略。
kubectl autosacle deployment nginx-deployment --min=10 --max=15 --cpu-percent=80
3、更新镜像
(1)通过set 命令直接修改image的版本进行升级,如下:
[root@k8s-master ~]# kubectl set image deployment/nginx-deployment nginx=nginx:1.9.1
(2)通过直接更改yaml的方式进行升级,
image: nginx:1.9.1
通过 使用
kubectl apply -f nginx-deployment.yaml
上述两种方案都会使pod以及rs重建
kubectl get pods -l app=nginx -w
kubectl get rs -o wide
4、Deployment版本回退
默认情况下,kubernetes 会在系统中保存前两次的 Deployment 的 rollout 历史记录,以便可以随时回退(您可以修改revision history limit
来更改保存的revision数)。
注意: 只要 Deployment 的 rollout 被触发就会创建一个 revision。也就是说当且仅当 Deployment 的 Pod template(如.spec.template
)被更改,例如更新template 中的 label 和容器镜像时,就会创建出一个新的 revision。
其他的更新,比如扩容 Deployment 不会创建 revision——因此我们可以很方便的手动或者自动扩容。这意味着当您回退到历史 revision 时,只有 Deployment 中的 Pod template 部分才会回退。
[root@k8s-master ~]# kubectl rollout history deploy nginx-deployment #检查Deployment升级记录 deployments "nginx-deployment" REVISION CHANGE-CAUSE 0 <none> 3 <none> 4 <none> 5 <none>
这里在创建deployment时没有增加--record参数,所以并不能看到revision的变化。在创建 Deployment 的时候使用了--record
参数可以记录命令,就可以方便的查看每次 revision 的变化。
查看单个revision 的详细信息:
[root@k8s-master ~]# kubectl rollout history deployment/myapp-deploy --revision=2
回退历史版本,默认是回退到上一个版本:
[root@k8s-master ~]# kubectl rollout undo deployment/myapp-deploy deployment "myapp-deploy" rolled back
也可以使用 --revision
参数指定某个历史版本:
[root@k8s-master ~]# kubectl rollout undo deployment/myapp-deploy --to-revision=2 deployment "myapp-deploy" rolled back
5、金丝雀发布
Deployment控制器支持自定义控制更新过程中的滚动节奏,如“暂停(pause)”或“继续(resume)”更新操作。比如等待第一批新的Pod资源创建完成后立即暂停更新过程,此时,仅存在一部分新版本的应用,主体部分还是旧的版本。然后,再筛选一小部分的用户请求路由到新版本的Pod应用,继续观察能否稳定地按期望的方式运行。确定没问题之后再继续完成余下的Pod资源滚动更新,否则立即回滚更新操作。这就是所谓的金丝雀发布(Canary Release),如下命令演示:
(1)更新deployment的v3版本,并配置暂停deployment
[root@k8s-master ~]# kubectl set image deployment nginx-deployment nginx=nginx:1.9.1 && kubectl rollout pause deployment nginx-deployment deployment.extensions/nginx-deployment image updated deployment.extensions/nginx-deployment paused [root@k8s-master ~]# kubectl rollout status deployments nginx-deployment #观察更新状态
(2)监控更新的过程,可以看到已经新增了一个资源,但是并未按照预期的状态去删除一个旧的资源,就是因为使用了pause暂停命令
[root@k8s-master ~]# kubectl get pods -l app=nginx -w NAME READY STATUS RESTARTS AGE nginx-deployment-5754944d6c-6vpd5 1/1 Running 0 23h nginx-deployment-5754944d6c-b4p64 1/1 Running 0 23h nginx-deployment-5754944d6c-dj5xw 1/1 Running 0 18m nginx-deployment-5754944d6c-m7jxj 1/1 Running 0 23h nginx-deployment-7448597cd5-5jvpx 0/1 ContainerCreating 0 78s nginx-deployment-7448597cd5-9p7hg 1/1 Running 0 78s nginx-deployment-7448597cd5-h2ss7 1/1 Running 0 78s
(3)确保更新的pod没问题了,继续更新
[root@k8s-master ~]# kubectl rollout resume deploy nginx-deployment error: deployments.extensions "nginx-deployment" is not paused
(4)查看最后的更新情况
[root@k8s-master ~]# kubectl get pods -l app=nginx -w NAME READY STATUS RESTARTS AGE nginx-deployment-7448597cd5-dpwvk 1/1 Running 0 24m nginx-deployment-7448597cd5-frspv 1/1 Running 0 24m
2.3、DaemonSet
2.3.1、概述
DaemonSet 确保全部(或者一些)Node 上运行一个 Pod 的副本。当有 Node 加入集群时,也会为他们新增一个 Pod 。当有 Node 从集群移除时,这些 Pod 也会被回收。删除 DaemonSet 将会删除它创建的所有 Pod。
使用 DaemonSet 的一些典型用法:
- 运行集群存储 daemon,例如在每个 Node 上运行
glusterd
、ceph
。 - 在每个 Node 上运行日志收集 daemon,例如
fluentd
、logstash
。 - 在每个 Node 上运行监控 daemon,例如 Prometheus Node Exporter、
collectd
、Datadog 代理、New Relic 代理,或 Gangliagmond
。
一个简单的用法是,在所有的 Node 上都存在一个 DaemonSet,将被作为每种类型的 daemon 使用。 一个稍微复杂的用法可能是,对单独的每种类型的 daemon 使用多个 DaemonSet,但具有不同的标志,和/或对不同硬件类型具有不同的内存、CPU要求。
2.3.2、编写DaemonSet的spec
(1)必需字段
和其它所有 Kubernetes 配置一样,DaemonSet 需要 apiVersion
、kind
和 metadata
字段。
命令查看:kubectl explain daemonset
(2)Pod模板
.spec
唯一必需的字段是 .spec.template
。
.spec.template
是一个 Pod 模板。 它与 Pod 具有相同的 schema,除了它是嵌套的,而且不具有 apiVersion
或 kind
字段。
Pod 除了必须字段外,在 DaemonSet 中的 Pod 模板必须指定合理的标签(查看 pod selector)。
在 DaemonSet 中的 Pod 模板必需具有一个值为 Always
的 RestartPolicy
,或者未指定它的值,默认是 Always
。
[root@k8s-master ~]# kubectl explain daemonset.spec.template.spec
(3)Pod Seletor
.spec.selector
字段表示 Pod Selector,它与 Job 或其它资源的 .sper.selector
的原理是相同的。
spec.selector
表示一个对象,它由如下两个字段组成:
matchLabels
- 与 ReplicationController 的.spec.selector
的原理相同。matchExpressions
- 允许构建更加复杂的 Selector,可以通过指定 key、value 列表,以及与 key 和 value 列表的相关的操作符。
当上述两个字段都指定时,结果表示的是 AND 关系。
如果指定了 .spec.selector
,必须与 .spec.template.metadata.labels
相匹配。如果没有指定,它们默认是等价的。如果与它们配置的不匹配,则会被 API 拒绝。
如果 Pod 的 label 与 selector 匹配,或者直接基于其它的 DaemonSet、或者 Controller(例如 ReplicationController),也不可以创建任何 Pod。 否则 DaemonSet Controller 将认为那些 Pod 是它创建的。Kubernetes 不会阻止这样做。一个场景是,可能希望在一个具有不同值的、用来测试用的 Node 上手动创建 Pod。
(4)Daemon Pod通信
与 DaemonSet 中的 Pod 进行通信,几种可能的模式如下:
- Push:配置 DaemonSet 中的 Pod 向其它 Service 发送更新,例如统计数据库。它们没有客户端。
- NodeIP 和已知端口:DaemonSet 中的 Pod 可以使用
hostPort
,从而可以通过 Node IP 访问到 Pod。客户端能通过某种方法知道 Node IP 列表,并且基于此也可以知道端口。 - DNS:创建具有相同 Pod Selector 的 Headless Service,然后通过使用
endpoints
资源或从 DNS 检索到多个 A 记录来发现 DaemonSet。 - Service:创建具有相同 Pod Selector 的 Service,并使用该 Service 访问到某个随机 Node 上的 daemon。(没有办法访问到特定 Node)
2.3.3、创建redis-filebeat的DaemonSet演示
(1)编辑daemonSet的yaml文件
可以在同一个yaml文件中定义多个资源,这里将redis和filebeat定在一个文件当中
vim ds-demo.yaml apiVersion: apps/v1 kind: Deployment metadata: name: redis namespace: default spec: replicas: 1 selector: matchLabels: app: redis role: logstor template: metadata: labels: app: redis role: logstor spec: containers: - name: redis image: redis:4.0-alpine ports: - name: redis containerPort: 6379 --- apiVersion: apps/v1 kind: DaemonSet metadata: name: filebeat-ds namespace: default spec: selector: matchLabels: app: filebeat release: stable template: metadata: labels: app: filebeat release: stable spec: containers: - name: filebeat image: ikubernetes/filebeat:5.6.5-alpine env: - name: REDIS_HOST value: redis.default.svc.cluster.local - name: REDIS_LOG_LEVEL value: info
(2)创建pods
[root@k8s-master mainfests]# kubectl apply -f ds-demo.yaml deployment.apps/redis created daemonset.apps/filebeat-ds created
(3)暴露端口
[root@k8s-master mainfests]# kubectl expose deployment redis --port=6379 service/redis exposed [root@k8s-master mainfests]# kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE redis ClusterIP 10.107.163.143 <none> 6379/TCP 4s [root@k8s-master mainfests]# kubectl get pods NAME READY STATUS RESTARTS AGE filebeat-ds-rpp9p 1/1 Running 0 5m filebeat-ds-vwx7d 1/1 Running 0 5m redis-5b5d6fbbbd-v82pw 1/1 Running 0 36s
(4)测试redis是否收到日志
[root@k8s-master mainfests]# kubectl exec -it redis-5b5d6fbbbd-v82pw -- /bin/sh /data # netstat -tnl Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State tcp 0 0 0.0.0.0:6379 0.0.0.0:* LISTEN tcp 0 0 :::6379 :::* LISTEN /data # nslookup redis.default.svc.cluster.local nslookup: can't resolve '(null)': Name does not resolve Name: redis.default.svc.cluster.local Address 1: 10.107.163.143 redis.default.svc.cluster.local /data # redis-cli -h redis.default.svc.cluster.local redis.default.svc.cluster.local:6379> KEYS * #由于redis在filebeat后面才启动,日志可能已经发走了,所以查看key为空 (empty list or set) [root@k8s-master mainfests]# kubectl get pods NAME READY STATUS RESTARTS AGE filebeat-ds-rpp9p 1/1 Running 0 14m filebeat-ds-vwx7d 1/1 Running 0 14m redis-5b5d6fbbbd-v82pw 1/1 Running 0 9m [root@k8s-master mainfests]# kubectl exec -it filebeat-ds-rpp9p -- /bin/sh / # cat /etc/filebeat/filebeat.yml filebeat.registry_file: /var/log/containers/filebeat_registry …… [root@k8s-master mainfests]# kubectl get pods -l app=filebeat -o wide NAME READY STATUS RESTARTS AGE IP NODE filebeat-ds-rpp9p 1/1 Running 0 16m 10.244.2.12 k8s-node02 filebeat-ds-vwx7d 1/1 Running 0 16m 10.244.1.15 k8s-node01
然后进入filebeat容器添加一点测试数据:
# kubectl exec -it filebeat-ds-pgmzt -- /bin/bash # cd /var/log/containers/ # echo "123" > a.log
然后进redis容器查看数据:
# kubectl exec -it redis-85c7ccb675-ks4rc -- /bin/sh /data # redis-cli -h redis.default.svc.cluster.local -p 6379 redis.default.svc.cluster.local:6379> KEYS * 1) "filebeat" redis.default.svc.cluster.local:6379>
2.3.4、DaemonSet的滚动更新
DaemonSet有两种更新策略类型:
- OnDelete:这是向后兼容性的默认更新策略。使用
OnDelete
更新策略,在更新DaemonSet模板后,只有在手动删除旧的DaemonSet pod时才会创建新的DaemonSet pod。这与Kubernetes 1.5或更早版本中DaemonSet的行为相同。 - RollingUpdate:使用
RollingUpdate
更新策略,在更新DaemonSet模板后,旧的DaemonSet pod将被终止,并且将以受控方式自动创建新的DaemonSet pod。
要启用DaemonSet的滚动更新功能,必须将其设置 .spec.updateStrategy.type
为RollingUpdate
。
(1)查看当前的更新策略:
[root@k8s-master mainfests]# kubectl get ds/filebeat-ds -o go-template='{{.spec.updateStrategy.type}}{{"\n"}}' RollingUpdate
(2)更新DaemonSet模板
对RollingUpdate
DaemonSet的任何更新都.spec.template
将触发滚动更新。这可以通过几个不同的kubectl
命令来完成。
声明式命令方式:
如果使用配置文件进行更新DaemonSet,可以使用kubectl aapply:
kubectl apply -f ds-demo.yaml
补丁式命令方式:
kubectl edit ds/filebeat-ds
kubectl patch ds/filebeat-ds -p=<strategic-merge-patch>
仅仅更新容器镜像还可以使用以下命令:
kubectl set image ds/<daemonset-name> <container-name>=<container-new-image>
下面对filebeat-ds的镜像进行版本更新,如下:
[root@k8s-master mainfests]# kubectl set image daemonsets filebeat-ds filebeat=ikubernetes/filebeat:5.6.6-alpine daemonset.extensions/filebeat-ds image updated
[root@k8s-master mainfests]# kubectl get pods -w #观察滚动更新状态 NAME READY STATUS RESTARTS AGE filebeat-ds-rpp9p 1/1 Running 0 27m filebeat-ds-vwx7d 0/1 Terminating 0 27m pod-demo 2/2 Running 6 5d redis-5b5d6fbbbd-v82pw 1/1 Running 0 23m filebeat-ds-vwx7d 0/1 Terminating 0 27m filebeat-ds-vwx7d 0/1 Terminating 0 27m filebeat-ds-s466l 0/1 Pending 0 0s filebeat-ds-s466l 0/1 ContainerCreating 0 0s filebeat-ds-s466l 1/1 Running 0 13s filebeat-ds-rpp9p 1/1 Terminating 0 28m filebeat-ds-rpp9p 0/1 Terminating 0 28m filebeat-ds-rpp9p 0/1 Terminating 0 28m filebeat-ds-rpp9p 0/1 Terminating 0 28m filebeat-ds-hxgdx 0/1 Pending 0 0s filebeat-ds-hxgdx 0/1 ContainerCreating 0 0s filebeat-ds-hxgdx 1/1 Running 0 28s [root@k8s-master mainfests]# kubectl get pods NAME READY STATUS RESTARTS AGE filebeat-ds-hxgdx 1/1 Running 0 2m filebeat-ds-s466l 1/1 Running 0 2m pod-demo 2/2 Running 6 5d redis-5b5d6fbbbd-v82pw 1/1 Running 0 25m
从上面的滚动更新,可以看到在更新过程中,是先终止旧的pod,再创建一个新的pod,逐步进行替换的,这就是DaemonSet的滚动更新策略!