Pod控制器是用于实现管理pod的中间层,确保pod资源符合预期的状态,pod的资源出现故障时,会尝试 进行重启,当根据重启策略无效,则会重新新建pod的资源。
Master 的各组件中, API Server 仅负责将资源存储于 etcd 中,并将其变动通知给各相 关的客户端程序,如 kubelet、 kube-scheduler、 kube-proxy 和 kube-controlier-manager 等, kube剖heduler 监控到处于未绑定状态的 Pod 对象出现时遂启动调度器为其挑选适配的工作节 点,然而, Kubemetes 的核心功能之一还在于要确保各资源对象的当前状态( status)以匹配用 户期望的状态( spec),使当前状态不断地向期望状态“和解”( reconciliation)来完成容器应用 管理,而这些则是 kube-contro I !er-manager 的任务。 kube-contro lier-manager 是一个独立的单体 守护进程,然而它包含了众多功能不同的控制器类型分别用于各类和解任务,如图 5-1 所示。
本文主要讲解ReplicaSet、Deployment、DaemonSet 三中类型的pod控制器。
(1)什么是ReplicaSet?
ReplicaSet是下一代复本控制器,是Replication Controller(RC)的升级版本。ReplicaSet和 Replication Controller之间的唯一区别是对选择器的支持。ReplicaSet支持labels user guide中描述的set-based选择器要求, 而Replication Controller仅支持equality-based的选择器要求。
ReplicaSet (简称 RS )是 Pod 控制器类型的一种实现,用于确保由其管控的 Pod 对象副 本数在任一时刻都能精确满足期望的数量。 如图 5-4 所示, ReplicaSet 控制器资源启动后会 查找集群中匹配其标签选择器的 Pod 资源对象,当前活动对象的数量与期望的数量不吻合 时, 多则删除,少则通过 Pod 模板创建以补足, 等 Pod 资源副本数量符合期望值后即进入 下一轮和解循环。
(2)如何使用ReplicaSet
大多数kubectl 支持Replication Controller 命令的也支持ReplicaSets。rolling-update命令除外,如果要使用rolling-update,请使用Deployments来实现。
虽然ReplicaSets可以独立使用,但它主要被 Deployments用作pod 机制的创建、删除和更新。当使用Deployment时,你不必担心创建pod的ReplicaSets,因为可以通过Deployment实现管理ReplicaSets。
(3)何时使用ReplicaSet?
ReplicaSet能确保运行指定数量的pod。然而,Deployment 是一个更高层次的概念,它能管理ReplicaSets,并提供对pod的更新等功能。因此,我们建议你使用Deployment来管理ReplicaSets,除非你需要自定义更新编排。
这意味着你可能永远不需要操作ReplicaSet对象,而是使用Deployment替代管理 。后续讲解Deployment会详细描述。
(1)编写yaml文件,并创建启动
简单创建一个replicaset:启动2个pod
[root@master chapter5]# cat rs-example.yaml apiVersion: apps/v1 kind: ReplicaSet # 设置类型为ReplicaSet模式 metadata: name: myapp-rs # pod名称 namespace: prod # 创建一个空间 spec: replicas: 2 selector: matchLabels: # 定义pod控制器的标签选择器 app: myapp-pod # 控制器的标签选择器 template: metadata: labels: app: myapp-pod # 此处pod标签名称要与上面控制器的标签选择器一致 spec: containers: - name: myapp # 定义的myapp容器名称 image: ikubernetes/myapp:v1 ports: - name: http containerPort: 80
(2)创建pod并查询验证
[root@master chapter5]# kubectl apply -f rs-example.yaml # 创建pod replicaset.apps/myapp-rs created [root@master chapter5]# kubectl get rs -n prod # 查看ReplicaSet模式下创建的pod NAME DESIRED CURRENT READY AGE myapp-rs 2 2 2 21s # 此时myapp-rs容器下有两个pod在运行状态 [root@master chapter5]# kubectl describe rs myapp-rs -n prod # 查看pod的详细信息 Name: myapp-rs Namespace: prod Selector: app=myapp-pod # 标签选择器 Labels: <none> Annotations: Replicas: 2 current / 2 desired Pods Status: 2 Running / 0 Waiting / 0 Succeeded / 0 Failed Pod Template: Labels: app=myapp-pod # pod的标签 Containers: myapp: # 容器名称 Image: ikubernetes/myapp:v1 Port: 80/TCP Host Port: 0/TCP
(3)生成pod原则:“多退少补”
① 删除pod,会立即重新构建,生成新的pod
1 2 3 4 5 6 |
[root@master manifests] # kubectl delete pods myapp-zjc5l
pod "myapp-k4j6h" deleted
[root@master ~] # kubectl get pods
NAME READY STATUS RESTARTS AGE
myapp-r4ss4 1 /1 Running 0 33s
myapp-mdjvh 1 /1 Running 0 10s
|
② 若另一个pod,不小心符合了rs的标签选择器,就会随机干掉一个此标签的pod
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
---随便启动一个pod
[root@master manifests] # kubectl get pods --show-labels
NAME READY STATUS RESTARTS AGE LABELS
myapp-hxgbh 1 /1 Running 0 7m app=myapp,environment=qa,release=canary
myapp-mdjvh 1 /1 Running 0 6m app=myapp,environment=qa,release=canary
pod- test 1 /1 Running 0 13s app=myapp,tier=frontend
---将pod- test 打上release=canary标签
[root@master manifests] # kubectl label pods pod-test release=canary
pod /pod-test labeled
---随机停掉一个pod
[root@master manifests] # kubectl get pods --show-labels
NAME READY STATUS RESTARTS AGE LABELS
myapp-hxgbh 1 /1 Running 0 8m app=myapp,environment=qa,release=canary
myapp-mdjvh 1 /1 Running 0 7m app=myapp,environment=qa,release=canary
pod- test 0 /1 Terminating 0 1m app=myapp,release=canary,tier=frontend
|
1、动态扩容,只需要将replicas的数值改大点即可,就会实现动态扩容。
[root@master chapter5]# cat rs-example.yaml apiVersion: apps/v1 kind: ReplicaSet metadata: name: myapp-rs namespace: prod spec: replicas: 6 # 扩展副本只需要修改此处即可 selector: matchLabels: app: myapp-pod template: metadata: labels: app: myapp-pod spec: containers: - name: myapp image: ikubernetes/myapp:v1 ports: - name: http containerPort: 80
2、创建新的容器并验证效果:
[root@master chapter5]# kubectl apply -f rs-example.yaml # 创建新的pod副本 [root@master chapter5]# kubectl get pods -n prod # 查看此时就会出现6个pod NAME READY STATUS RESTARTS AGE myapp-rs-6gsdr 1/1 Running 0 17s myapp-rs-bqxdx 1/1 Running 0 12m myapp-rs-hscwt 1/1 Running 0 12m myapp-rs-kkz4x 1/1 Running 0 17s myapp-rs-kkzq7 1/1 Running 0 17s myapp-rs-ng2fb 1/1 Running 0 17s pod-demo 2/2 Running 2 21h [root@master chapter5]# kubectl get pods -n prod -o wide # 查看pod的详细信息 NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES myapp-rs-6gsdr 1/1 Running 0 30s 10.224.2.18 node2 <none> <none> myapp-rs-bqxdx 1/1 Running 0 12m 10.224.1.17 node1 <none> <none> myapp-rs-hscwt 1/1 Running 0 12m 10.224.1.16 node1 <none> <none> myapp-rs-kkz4x 1/1 Running 0 30s 10.224.2.19 node2 <none> <none> myapp-rs-kkzq7 1/1 Running 0 30s 10.224.1.18 node1 <none> <none> myapp-rs-ng2fb 1/1 Running 0 30s 10.224.1.19 node1 <none> <none> pod-demo 2/2 Running 2 21h 10.224.1.14 node1 <none> <none>
使用scale选项对pod进行缩容,此方法也可以进行扩容,只需要在replicas副本数量改大即可
[root@master chapter5]# kubectl scale --replicas=3 rs myapp-rs -n prod # 将副本数改为3个 replicaset.apps/myapp-rs scaled [root@master chapter5]# kubectl get pods -n prod # 查看此时的pod数量就只有三个 NAME READY STATUS RESTARTS AGE myapp-rs-bqxdx 1/1 Running 0 17m myapp-rs-hscwt 1/1 Running 0 17m myapp-rs-ng2fb 1/1 Running 0 5m39s pod-demo 2/2 Running 2 22h
1、修改repicaset的yaml文件格式,实现在线升级版本
[root@master chapter5]# cat rs-example.yaml apiVersion: apps/v1 kind: ReplicaSet metadata: name: myapp-rs namespace: prod spec: replicas: 1 # 将此时的副本先改为1,方便测试 selector: matchLabels: app: myapp-pod template: metadata: labels: app: myapp-pod spec: containers: - name: myapp image: ikubernetes/myapp:v2 # 将下载镜像的模板改为v2 ports: - name: http containerPort: 80
2、但是,修改完并没有升级
需删除pod,再自动生成新的pod时,就会升级成功;
即可以实现灰度发布:删除一个,会自动启动一个版本升级成功的pod
[root@master chapter5]# kubectl apply -f rs-example.yaml [root@master chapter5]# kubectl get pods -n prod # 查看最新的pod信息 NAME READY STATUS RESTARTS AGE myapp-rs-hscwt 1/1 Running 0 45m pod-demo 2/2 Running 2 22h ---访问没有删除pod的服务,显示是V1版 [root@master manifests]# curl 10.244.2.15 Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a> # 访问第一次的版本是v1的版本 [root@master chapter5]# kubectl delete pod -n prod myapp-rs-hscwt # 删除v1版本的pod,就会生成最新版本的pod pod "myapp-rs-hscwt" deleted [root@master chapter5]# kubectl get pods -n prod -o wide # 可以看到此时的容器IP地址为10.224.2.22 NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES myapp-rs-ltqjt 1/1 Running 0 5m53s 10.224.2.22 node2 <none> <none> pod-demo 2/2 Running 2 22h 10.224.1.14 node1 <none> <none> [root@master chapter5]# kubectl get rs -n prod -o wide # 查看此时创建的容器版本为v2 NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR myapp-rs 1 1 1 52m myapp ikubernetes/myapp:v2 app=myapp-pod [root@master chapter5]# curl 10.224.2.22 # 此时访问网页时,就会变成v2版本的代码,实现了代码的灰度发布 Hello MyApp | Version: v2 | <a href="hostname.html">Pod Name</a>
删除前面所作的pod容器信息,方便做以下实验
[root@master manifests]# kubectl delete all --all -n prod
(1)介绍
Deployment 为 Pod和Replica Set 提供了一个声明式定义(declarative)方法,用来替代以前的ReplicationController来方便的管理应用
你只需要在 Deployment 中描述您想要的目标状态是什么,Deployment controller 就会帮您将 Pod 和ReplicaSet 的实际状态改变到您的目标状态。您可以定义一个全新的 Deployment 来创建 ReplicaSet 或者删除已有的 Deployment 并创建一个新的来替换。
注意:您不该手动管理由 Deployment 创建的 Replica Set,否则您就篡越了 Deployment controller 的职责!
(2)典型的应用场景包括
(1)创建并创建一个简单的DaemonSet,启动pod,只后台运行filebeat手机日志服务
[root@master manifests]# vim ds-demo.yaml apiVersion: apps/v1 kind: DaemonSet metadata: name: filebeat-ds # pod名称为filebeat-ds namespace: prod # 名称空间改为prod,实验时以示区别 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 # 拉取5.6.5版本的镜像 env: - name: REDIS_HOST value: redis.default.svc.cluster.local - name: REDIS_LOG_LEVEL value: info
(2)创建pod并查询验证
[root@master manifests]# kubectl apply -f filebeat-ds.yaml # 创建pod daemonset.apps/filebeat-ds created [root@master manifests]# kubectl get ds -n prod -o wide # 查看此时的镜像是5.6.5版本 NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE CONTAINERS IMAGES SELECTOR filebeat-ds 2 2 2 2 2 <none> 7m7s filebeat ikubernetes/filebeat:5.6.5-alpine app=filebeat,release=stable
有2中方法实现
(1)方法1:直接修改yaml文件,将副本数改为3
1 2 3 4 5 6 7 |
[root@master manifests] # vim deploy-damo.yaml
... ...
spec:
replicas: 3
... ...
[root@master manifests] # kubectl apply -f deploy-damo.yaml
deployment.apps /myapp-deploy configured
|
查询验证成功:有3个pod
1 2 3 4 5 |
[root@master manifests] # kubectl get pods
NAME READY STATUS RESTARTS AGE
myapp-deploy-69b47bc96d-bcdnq 1 /1 Running 0 25s
myapp-deploy-69b47bc96d-bm8zc 1 /1 Running 0 2m
myapp-deploy-69b47bc96d-pjr5v 1 /1 Running 0 2m
|
(2)通过patch命令打补丁命令扩容
与方法1的区别:不需修改yaml文件;平常测试时使用方便;
但列表格式复杂,极容易出错
1 2 |
[root@master manifests] # kubectl patch deployment myapp-deploy -p '{"spec":{"replicas":5}}'
deployment.extensions /myapp-deploy patched
|
查询验证成功:有5个pod
1 2 3 4 5 6 7 |
[root@master ~] # kubectl get pods
NAME READY STATUS RESTARTS AGE
myapp-deploy-67f6f6b4dc-2756p 1 /1 Running 0 26s
myapp-deploy-67f6f6b4dc-2lkwr 1 /1 Running 0 26s
myapp-deploy-67f6f6b4dc-knttd 1 /1 Running 0 21m
myapp-deploy-67f6f6b4dc-ms7t2 1 /1 Running 0 21m
myapp-deploy-67f6f6b4dc-vl2th 1 /1 Running 0 21m
|
(1)直接修改deploy-damo.yaml配置文件,如果修改完版本会重新使用apply进行更新版本,如果只是修改了replicas副本数,是不会更新版本的
[root@master manifests]# cat deploy-demo.yaml apiVersion: apps/v1 kind: Deployment metadata: name: ngx-deploy namespace: prod spec: replicas: 2 selector: matchLabels: app: myapp release: canary template: metadata: labels: app: myapp release: canary spec: containers: - name: myapp image: ikubernetes/myapp:v2 ports: - name: http containerPort: 80
(2)重新创建一个pod,并动态监控版本升级
[root@master manifests]# kubectl apply -f deploy-demo.yaml # 重新创建一个pod deployment.apps/ngx-deploy configured [root@master manifests]# kubectl get pods -n prod -w # 实现实施跟踪创建新的pod过程
发现是滚动升级,先停一个,再开启一个新的(升级);再依次停一个...
(3)此时查看所有的pod信息,就可以看到有两个pod在运行,随便访问一个,此时版本已经变成v2版本
[root@master manifests]# kubectl get pods -n prod -o wide # 查看pod的详细信息,可以看到有两个pod在运行 NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES ngx-deploy-559ff5c66-7fbgg 1/1 Running 0 3m42s 10.224.2.24 node2 <none> <none> ngx-deploy-559ff5c66-q65bq 1/1 Running 0 3m44s 10.224.1.24 node1 <none> <none> [root@master manifests]# curl 10.224.2.24 # 查看此时的版本是v2版本 Hello MyApp | Version: v2 | <a href="hostname.html">Pod Name</a> [root@master manifests]# curl 10.224.1.24 Hello MyApp | Version: v2 | <a href="hostname.html">Pod Name</a>
(1)方法1:修改yaml文件
1 2 3 4 5 6 7 |
[root@master manifests] # vim deploy-damo.yaml
... ...
strategy:
rollingUpdate:
maxSurge: 1 #每次更新一个pod
maxUnavailable: 0 #最大不可用pod为0
... ...
|
(2)打补丁:修改更新策略
1 2 |
[root@master manifests] # kubectl patch deployment myapp-deploy -p '{"spec":{"strategy":{"rollingUpdate":{"maxSurge":1,"maxUnavailable":0}}}}'
deployment.extensions /myapp-deploy patched
|
(3)验证:查询详细信息
1 2 3 4 |
[root@master manifests] # kubectl describe deployment myapp-deploy
... ...
RollingUpdateStrategy: 0 max unavailable, 1 max surge
... ...
|
(4)升级到v3版
① 金丝雀发布:先更新一个pod,然后立即暂停,等版本运行没问题了,再继续发布
1 2 3 |
[root@master manifests] # kubectl set image deployment myapp-deploy myapp=ikubernetes/myapp:v3 && kubectl rollout pause deployment myapp-deploy
deployment.extensions /myapp-deploy image updated #一个pod更新成功
deployment.extensions /myapp-deploy paused #暂停更新
|
② 等版本运行没问题了,解除暂停,继续发布更新
1 2 |
[root@master manifests] # kubectl rollout resume deployment myapp-deploy
deployment.extensions /myapp-deploy resumed
|
③ 中间可以一直监控过程
1 2 3 4 5 6 7 8 9 10 |
[root@master ~] # kubectl rollout status deployment myapp-deploy #输出版本更新信息
Waiting for deployment "myapp-deploy" rollout to finish: 1 out of 5 new replicas have been updated...
Waiting for deployment spec update to be observed...
Waiting for deployment spec update to be observed...
Waiting for deployment "myapp-deploy" rollout to finish: 1 out of 5 new replicas have been updated...
Waiting for deployment "myapp-deploy" rollout to finish: 1 out of 5 new replicas have been updated...
Waiting for deployment "myapp-deploy" rollout to finish: 2 out of 5 new replicas have been updated...
Waiting for deployment "myapp-deploy" rollout to finish: 2 out of 5 new replicas have been updated...
---也可以使用get查询pod 更新过程
[root@master ~] # kubectl get pods -w
|
④ 验证:随便访问一个pod的服务,版本升级成功
1 2 3 4 5 |
[root@master ~] # kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE
myapp-deploy-6bdcd6755d-2bnsl 1 /1 Running 0 1m 10.244.1.77 node1
[root@master ~] # curl 10.244.1.77
Hello MyApp | Version: v3 | <a href= "hostname.html" >Pod Name< /a >
|
增加减少pod的数量,不会使代码进行滚动更新,滚动更新只会在你修改pod的模板时才会发生改变,修改了镜像版本,必然会触发模板更新,也就会是版本更新。
(1)命令
查询版本变更历史
# kubectl rollout history deployment deployment_name
undo回滚版本;--to-revision= 回滚到第几版本,默认等于0,是回滚到上一个版本
# kubectl rollout undo deployment deployment_name --to-revision=N
(1)查看历史版本,并开始回滚版本,如果想回到第一个版本,只需要将--to-revision= 1选项加在最后面即可
[root@master manifests]# kubectl rollout history deployment/ngx-deploy -n prod # 查看历史代码版本 deployment.apps/ngx-deploy REVISION CHANGE-CAUSE 3 <none> 5 <none> 6 kubectl apply --filename=deploy-demo.yaml --record=true [root@master manifests]# kubectl rollout undo deployment/ngx-deploy -n prod # 回滚到上一个版本 deployment.apps/ngx-deploy rolled back
(2)查看此时回滚的状态,此时的pod控制器在v2版本上
[root@master manifests]# kubectl get rs -n prod -o wide NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR ngx-deploy-559ff5c66 2 2 2 51m myapp ikubernetes/myapp:v2 app=myapp,pod-template-hash=559ff5c66,release=canary ngx-deploy-65fb6c8459 0 0 0 61m myapp ikubernetes/myapp:v1 app=myapp,pod-template-hash=65fb6c8459,release=canary ngx-deploy-6b9865d969 0 0 0 14m myapp ikubernetes/myapp:v3 app=myapp,pod-template-hash=6b9865d969,release=canary
(1)DemonSet介绍
DaemonSet保证在每个Node上都运行一个容器副本,常用来部署一些集群的日志、监控或者其他系统管理应用
(2)典型的应用包括
(1)创建并创建一个简单的DaemonSet,启动pod,只后台运行filebeat手机日志服务
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
[root@master manifests] # vim ds-demo.yaml
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
[root@master manifests] # kubectl apply -f ds-demo.yaml
daemonset.apps /myapp-ds created
|
(2)查询验证
1 2 3 4 5 6 7 8 9 10 11 |
[root@master ~] # kubectl get ds
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
filebeat-ds 2 2 2 2 2 <none> 6m
[root@master ~] # kubectl get pods
NAME READY STATUS RESTARTS AGE
filebeat-ds-r25hh 1 /1 Running 0 4m
filebeat-ds-vvntb 1 /1 Running 0 4m
[root@master ~] # kubectl exec -it filebeat-ds-r25hh -- /bin/sh
/ # ps aux
PID USER TIME COMMAND
1 root 0:00 /usr/local/bin/filebeat -e -c /etc/filebeat/filebeat .yml
|
(1)使用kubectl set image 命令更新pod的镜像;实现版本升级
1 2 |
[root@master ~] # kubectl set image daemonsets filebeat-ds filebeat=ikubernetes/filebeat:5.6.6-alpine
daemonset.extensions /filebeat-ds image updated
|
(2)验证,升级成功
1 2 3 |
[root@master ~] # kubectl get ds -o wide
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE CONTAINERS IMAGES SELECTOR
filebeat-ds 2 2 2 2 2 <none> 7m filebeat ikubernetes /filebeat :5.6.6-alpine app=filebeat,release=stable
|
(1)statefulset介绍
StatefulSet是为了解决有状态服务的问题(对应Deployments和ReplicaSets是为无状态服务而设计),其应用场景包括
(2)三个必要组件
从上面的应用场景可以发现,StatefulSet由以下几个部分组成:
其中, Headless Service 用于为 Pod 资源标识符生成可 解析的 DNS 资源记录, StatefulSet 用于管控 Pod 资源, volummeClaimTemplate 则基于静态或 动态的 PV 供给方式为 Pod 资源提供专有且固定的存储。
Kubemetes 自 1.7 版本起还支持用户自定义更新策略, 该版本兼容支持之前版本中的删除 后更新(OnDelete)策略, 以及新的滚动更新策略(RollingUpdate)。 OnDelete 意味着 ReplicaSet 不会自动更新 Pod 资源除非它被删而激活重建操作。 RollingUpdate 是默认的更新策略, 它 支持 Pod 资源的 自动、滚动更新。 更新顺 Pod web-0 序与终止 Pod 资源的顺序相同, 由索引号 最大的资源开始, 终止一个并完成其更新, 而后更新下一个。
1、在每台k8s集群和nfs服务器上安装nfs服务,并挂载要共享的目录
(1)在nfs服务器上先建立存储卷对应的目录
1 2 3 4 5 6 7 8 9 |
[root@nfs ~] # cd /data/volumes/
[root@nfs volumes] # mkdir v{1,2,3,4,5}
[root@nfs volumes] # ls
index.html v1 v2 v3 v4 v5
[root@nfs volumes] # echo "<h1>NFS stor 01</h1>" > v1/index.html
[root@nfs volumes] # echo "<h1>NFS stor 02</h1>" > v2/index.html
[root@nfs volumes] # echo "<h1>NFS stor 03</h1>" > v3/index.html
[root@nfs volumes] # echo "<h1>NFS stor 04</h1>" > v4/index.html
[root@nfs volumes] # echo "<h1>NFS stor 05</h1>" > v5/index.html
|
(2)修改nfs的配置
1 2 3 4 5 6 |
[root@nfs volumes] # vim /etc/exports
/data/volumes/v1 192.168.130.0 /24 (rw,no_root_squash)
/data/volumes/v2 192.168.130.0 /24 (rw,no_root_squash)
/data/volumes/v3 192.168.130.0 /24 (rw,no_root_squash)
/data/volumes/v4 192.168.130.0 /24 (rw,no_root_squash)
/data/volumes/v5 192.168.130.0 /24 (rw,no_root_squash)
|
(3)查看nfs的配置
1 2 3 4 5 6 |
[root@nfs volumes] # exportfs -arv
exporting 192.168.130.0 /24 : /data/volumes/v5
exporting 192.168.130.0 /24 : /data/volumes/v4
exporting 192.168.130.0 /24 : /data/volumes/v3
exporting 192.168.130.0 /24 : /data/volumes/v2
exporting 192.168.130.0 /24 : /data/volumes/v1
|
(4)是配置生效
1 2 3 4 5 6 7 |
[root@nfs volumes] # showmount -e
Export list for nfs:
/data/volumes/v5 192.168.7.0 /24
/data/volumes/v4 192.168.7.0 /24
/data/volumes/v3 192.168.7.0 /24
/data/volumes/v2 192.168.7.0 /24
/data/volumes/v1 192.168.7.0 /24
|
(5)启动nfs服务器
# systemctl start nfs
创建5个pv,需要有nfs服务,pv与pvc详情见:https://www.cnblogs.com/struggle-1216/p/13423505.html
[root@master volume]# vim pv-demo.yaml apiVersion: v1 kind: PersistentVolume metadata: name: pv001 labels: name: pv001 spec: nfs: path: /data/volumes/v1 server: nfs accessModes: ["ReadWriteMany","ReadWriteOnce","ReadOnlyMany"] volumeMode: Filesystem persistentVolumeReclaimPolicy: Retain # 定义回收策略为retain capacity: storage: 5Gi --- apiVersion: v1 kind: PersistentVolume metadata: name: pv002 labels: name: pv002 spec: nfs: path: /data/volumes/v2 server: nfs accessModes: ["ReadWriteMany","ReadWriteOnce","ReadOnlyMany"] volumeMode: Filesystem persistentVolumeReclaimPolicy: Retain # 定义回收策略 capacity: storage: 5Gi --- apiVersion: v1 kind: PersistentVolume metadata: name: pv003 labels: name: pv003 spec: nfs: path: /data/volumes/v3 server: nfs accessModes: ["ReadWriteMany","ReadWriteOnce","ReadOnlyMany"] volumeMode: Filesystem persistentVolumeReclaimPolicy: Retain capacity: storage: 5Gi --- apiVersion: v1 kind: PersistentVolume metadata: name: pv004 labels: name: pv004 spec: nfs: path: /data/volumes/v4 server: nfs accessModes: ["ReadWriteMany","ReadWriteOnce","ReadOnlyMany"] volumeMode: Filesystem persistentVolumeReclaimPolicy: Retain capacity: storage: 10Gi --- apiVersion: v1 kind: PersistentVolume metadata: name: pv005 labels: name: pv005 spec: nfs: path: /data/volumes/v5 server: nfs accessModes: ["ReadWriteMany","ReadWriteOnce","ReadOnlyMany"] volumeMode: Filesystem persistentVolumeReclaimPolicy: Retain capacity: storage: 15Gi [root@master volume]# kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE pv001 5Gi RWO,RWX Retain Available 3s pv002 5Gi RWO Retain Available 3s pv003 5Gi RWO,RWX Retain Available 3s pv004 10Gi RWO,RWX Retain Available 3s pv005 15Gi RWO,RWX Retain Available 3s
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
[root@master pod_controller] # vim statefulset-demo.yaml
#Headless Service
apiVersion: v1
kind: Service
metadata:
name: myapp
labels:
app: myapp
spec:
ports:
- port: 80
name: web
clusterIP: None
selector:
app: myapp-pod
---
#statefuleset
apiVersion: apps /v1
kind: StatefulSet
metadata:
name: myapp
spec:
serviceName: myapp
replicas: 3
selector:
matchLabels:
app: myapp-pod
template:
metadata:
labels:
app: myapp-pod
spec:
containers:
- name: myapp
image: ikubernetes /myapp :v1
ports:
- containerPort: 80
name: web
volumeMounts:
- name: myappdata
mountPath: /usr/share/nginx/html
#volumeClaimTemplates
volumeClaimTemplates:
- metadata:
name: myappdata
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 5Gi
[root@master pod_controller] # kubectl apply -f statefulset-demo.yaml
service /myapp created
statefulset.apps /myapp created
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
---无头服务的service创建成功
[root@master pod_controller] # kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443 /TCP 173d
myapp ClusterIP None <none> 80 /TCP 3s
---statefulset创建成功
[root@master pod_controller] # kubectl get sts
NAME DESIRED CURRENT AGE
myapp 3 3 6s
---查看pvc,已经成功绑定时候的pv
[root@master pod_controller] # kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
myappdata-myapp-0 Bound pv002 5Gi RWO 9s
myappdata-myapp-1 Bound pv001 5Gi RWO,RWX 8s
myappdata-myapp-2 Bound pv003 5Gi RWO,RWX 6s
---查看pv,有3个已经被绑定
[root@master pod_controller] # kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv001 5Gi RWO,RWX Retain Bound default /myappdata-myapp-1 21s
pv002 5Gi RWO Retain Bound default /myappdata-myapp-0 21s
pv003 5Gi RWO,RWX Retain Bound default /myappdata-myapp-2 21s
pv004 10Gi RWO,RWX Retain Available 21s
pv005 15Gi RWO,RWX Retain Available 21s
---启动了3个pod
[root@master pod_controller] # kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE
myapp-0 1 /1 Running 0 16s 10.244.1.127 node1
myapp-1 1 /1 Running 0 15s 10.244.2.124 node2
myapp-2 1 /1 Running 0 13s 10.244.1.128 node1
|
可以使用scale命令 或 patch打补丁两种方法实现。
由原本的3个pod扩容到5个
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
---①使用scale命令实现
[root@master ~] # kubectl scale sts myapp --replicas=5
statefulset.apps /myapp scaled
---②或者通过打补丁来实现
[root@master ~] # kubectl patch sts myapp -p '{"spec":{"replicas":5}}'
statefulset.apps /myapp patched
[root@master pod_controller] # kubectl get pods
NAME READY STATUS RESTARTS AGE
myapp-0 1 /1 Running 0 11m
myapp-1 1 /1 Running 0 11m
myapp-2 1 /1 Running 0 11m
myapp-3 1 /1 Running 0 9s
myapp-4 1 /1 Running 0 7s
[root@master pod_controller] # kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
myappdata-myapp-0 Bound pv002 5Gi RWO 11m
myappdata-myapp-1 Bound pv001 5Gi RWO,RWX 11m
myappdata-myapp-2 Bound pv003 5Gi RWO,RWX 11m
myappdata-myapp-3 Bound pv004 10Gi RWO,RWX 13s
myappdata-myapp-4 Bound pv005 15Gi RWO,RWX 11s
[root@master pod_controller] # kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv001 5Gi RWO,RWX Retain Bound default /myappdata-myapp-1 17m
pv002 5Gi RWO Retain Bound default /myappdata-myapp-0 17m
pv003 5Gi RWO,RWX Retain Bound default /myappdata-myapp-2 17m
pv004 10Gi RWO,RWX Retain Bound default /myappdata-myapp-3 17m
pv005 15Gi RWO,RWX Retain Bound default /myappdata-myapp-4 17m
|
由5个pod扩容到2个
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
---①使用scale命令
[root@master ~] # kubectl scale sts myapp --replicas=2
statefulset.apps /myapp scaled
---②通过打补丁的方法进行缩容
[root@master ~] # kubectl patch sts myapp -p '{"spec":{"replicas":2}}'
statefulset.apps /myapp patched
[root@master pod_controller] # kubectl get pods
NAME READY STATUS RESTARTS AGE
myapp-0 1 /1 Running 0 15m
myapp-1 1 /1 Running 0 15m
---但是pv和pvc不会被删除,从而实现持久化存储
[root@master pod_controller] # kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
myappdata-myapp-0 Bound pv002 5Gi RWO 15m
myappdata-myapp-1 Bound pv001 5Gi RWO,RWX 15m
myappdata-myapp-2 Bound pv003 5Gi RWO,RWX 15m
myappdata-myapp-3 Bound pv004 10Gi RWO,RWX 4m
myappdata-myapp-4 Bound pv005 15Gi RWO,RWX 4m
|
1 2 3 4 5 6 7 |
[root@master ~] # kubectl explain sts.spec.updateStrategy.rollingUpdate.partition
KIND: StatefulSet
VERSION: apps /v1
FIELD: partition <integer>
DESCRIPTION:
Partition indicates the ordinal at which the StatefulSet should be
partitioned. Default value is 0.
|
解释:partition分区指定为n,升级>n的分区;n指第几个容器;默认是0
可以修改yaml资源清单来进行升级;也可通过打补丁的方法升级。
(1)先升级一个pod
先将pod恢复到5个
① 打补丁,将partition的指设为4,就只升级第4个之后的pod;若新版本有问题,立即回滚;若没问题,就全面升级
1 2 3 4 5 6 7 8 9 10 11 |
[root@master ~] # kubectl patch sts myapp -p '{"spec":{"updateStrategy":{"rollingUpdate":{"partition":4}}}}'
statefulset.apps /myapp patched
---查询认证
[root@master ~] # kubectl describe sts myapp
Name: myapp
Namespace: default
... ...
Replicas: 5 desired | 5 total
Update Strategy: RollingUpdate
Partition: 4
... ...
|
第二种实现升级第4个之后pod的方法,比较麻烦就是需要在现网修改配置文件生成
[root@master statefulset]# kubectl edit sts myapp updateStrategy: rollingUpdate: partition: 4 # 将此处的修改并保存
② 升级并查看此时的pod版本是否是最新版本v2
1 2 3 4 5 6 |
[root@master ~] # kubectl set image sts/myapp myapp=ikubernetes/myapp:v2
statefulset.apps /myapp image updated
---已将pod镜像换位v2版
[root@master ~] # kubectl get sts -o wide
NAME DESIRED CURRENT AGE CONTAINERS IMAGES
myapp 5 5 21h myapp ikubernetes /myapp :v2
|
③ 验证,查看第四个pod已经是v2版本
[root@master statefulset]# kubectl get pods # 查看所有的Pod,其实有五个pod,修改的是4,实际升级的是第五个Pod NAME READY STATUS RESTARTS AGE myapp-0 1/1 Running 0 2m16s myapp-1 1/1 Running 0 2m19s myapp-2 1/1 Running 0 2m32s myapp-3 1/1 Running 0 2m39s myapp-4 1/1 Running 0 4m21s # 查看第4个之后的pod,已经完成升级 [root@master ~]# kubectl get pods myapp-4 -o yaml |grep image - image: ikubernetes/myapp:v2 # 查看前4个pod,都还是v1版本 [root@master ~]# kubectl get pods myapp-3 -o yaml |grep image - image: ikubernetes/myapp:v1 [root@master ~]# kubectl get pods myapp-0 -o yaml |grep image - image: ikubernetes/myapp:v1
(2)上面实现了金丝雀发布成功后,就需要全面升级剩下的pod,此时只需要将partition对应的值改为0即可
---只需将partition的指设为0即可 [root@master ~]# kubectl patch sts myapp -p '{"spec":{"updateStrategy":{"rollingUpdate":{"partition":0}}}}' statefulset.apps/myapp patched ---验证,所有pod已经完成升级 [root@master ~]# kubectl get pods myapp-0 -o yaml |grep image - image: ikubernetes/myapp:v2 [root@master statefulset]# kubectl get pods myapp-1 -o yaml |grep image - image: ikubernetes/myapp:v2 [root@master ~]# kubectl get pods myapp-2 -o yaml |grep image - image: ikubernetes/myapp:v2 [root@master ~]# kubectl get pods myapp-3 -o yaml |grep image - image: ikubernetes/myapp:v2 [root@master ~]# kubectl get pods myapp-4 -o yaml |grep image - image: ikubernetes/myapp:v2