07 Deployment 功能及应用场景


Deployment 控制器

Pod与controllers的关系

  1. controllers: 在集群上管理和运行容器的对象
  2. 通过label-selector相关联
  3. Pod通过控制器实现应用的运维,如伸缩,滚动升级等
1
2
3
4
1. Pod是k8s当中最小的调度单元,但是一般很少直接使用pod
2. 使用控制器去对应用做部署
3. 控制器是高级对象,Pod是抽象的,控制器可以完成更高级的应用部署
4. controllers另外的学名 workload 工作负载

1
2
3
4
5
6
7
# 在一个yaml文件中可以分成两类:
1. 控制器
- 指定控制器和api
- 元数据
- 标明标签,通过标签找到一组Pod
2. Pod模板
- 标明标签,关联控制器
1
2
3
# 知识点总结:
1. 控制器管理Pod,使用控制器去部署应用
2. 控制器通过标签关联Pod

Deployment 功能与应用场景

  1. 部署无状态应用
  2. 管理Pod和ReplicaSet
  3. 具有上线部署、副本设定、滚动升级、回滚等功能
  4. 提供声明式更新,例如值只更新一个新的Image
  5. 应用场景: Web服务,微服务
1
1. ReplicaSet也是控制器,但是他得功能比较单一

Deployment YAML文件字段解析

1
2
3
在k8s集群中创建pod的两种方式:
1. 使用命令创建 用于测试
2. 使用yaml文件 便于管理和复用

Deployment 部署无状态应用

1
2
3
[root@k8s-master1 demo]# kubectl create deployment --help
Usage:
kubectl create deployment NAME --image=image [--dry-run] [options]
1
2
3
# 测试并输出到yaml格式文件
[root@k8s-master1 demo]# kubectl create deployment web --image=nginx1.16 --dry-run -o yaml
[root@k8s-master1 demo]# kubectl create deployment web --image=nginx1.16 --dry-run -o yaml > web.yaml
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
# 修改为应用属性
# 1. 副本个数
# 2. 标签名
# 3. 容器镜像

[root@k8s-master1 demo]# vim web.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: web
name: web
spec:
replicas: 3
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- image: 172.17.70.252/project/java-demo:latest
name: java-demo
1
2
3
4
5
6
7
8
9
10
11
[root@k8s-master1 demo]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
web-84c6fbbdcc-6tbkx 1/1 Running 0 28s 10.244.0.45 k8s-node1 <none> <none>
web-84c6fbbdcc-ldv48 1/1 Running 0 28s 10.244.0.46 k8s-node1 <none> <none>
web-84c6fbbdcc-qvl9f 1/1 Running 0 28s 10.244.1.48 k8s-node2 <none> <none>

[root@k8s-master1 demo]# kubectl logs web-84c6fbbdcc-6tbkx

[root@k8s-master1 demo]# kubectl get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
web 3/3 3 3 6m23s

暴露应用

1
2
3
在k8s集群中暴露应用两种方式:
1. service
2. ingress
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
[root@k8s-master1 demo]# kubectl expose --help
Usage:
kubectl expose (-f FILENAME | TYPE NAME) [--port=port] [--protocol=TCP|UDP|SCTP] [--target-port=number-or-name]
[--name=name] [--external-ip=external-ip-of-service] [--type=type] [options]

# kubectl expose service名称 pod资源 pod名称 service端口 pod端口 service类型
[root@k8s-master1 demo]# kubectl expose --name=web deployment web --port=80 --target-port=8080 --type=NodePort --dry-run -o yaml > web-service.yaml
[root@k8s-master1 demo]# vim web-service.yaml

apiVersion: v1
kind: Service
metadata:
labels:
app: web
name: web
spec:
ports:
- port: 80
protocol: TCP
targetPort: 8080
selector:
app: web # 关联pod标签
type: NodePort

[root@k8s-master1 demo]# kubectl apply -f web-service.yaml

[root@k8s-master1 demo]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.0.0.1 <none> 443/TCP 15d
web NodePort 10.0.0.204 <none> 80:31619/TCP 13s

[root@k8s-master1 demo]# kubectl edit service/web

[root@k8s-master1 demo]# kubectl get ep
NAME ENDPOINTS AGE
kubernetes 172.17.70.251:6443,172.17.70.252:6443 16d
web 10.244.0.45:8080,10.244.0.46:8080,10.244.1.48:8080 3m50s
1
# nodeIP+端口测试访问

升级与回滚

升级操作 set

  1. 升级更新
1
2
3
4
5
6
7
8
[root@k8s-master1 demo]# kubectl set --help
# 动态修改镜像
# 镜像通过tag版本号进行区分
[root@k8s-master1 demo]# kubectl set image --help
Usage:
kubectl set image (-f FILENAME | TYPE NAME) CONTAINER_NAME_1=CONTAINER_IMAGE_1 ... CONTAINER_NAME_N=CONTAINER_IMAGE_N
[options]
# kubectl set image deployment/nginx busybox=busybox nginx=nginx:1.9.1
  1. 模拟程序升级
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
# 需要修改模拟程序并打包一个新的镜像,推送到镜像仓库,这里先用nginx替代

[root@k8s-master1 demo]# cat web.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: web
name: web
spec:
replicas: 3
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- image: 172.17.70.252/project/java-demo:latest
name: java-demo

# deployment name
# 容器 name

[root@k8s-master1 demo]# kubectl set image deployment web java-demo=nginx:1.16
deployment.apps/web image updated

# 滚动升级 重新创建容器 失败了就不会删除之前的容器
# 先启动一个新镜像的pod 成功后再删除之前打好标记的pod 一个一个平滑升级
[root@k8s-master1 demo]# kubectl get pods
NAME READY STATUS RESTARTS AGE
web-7bddf7b45f-6ntcs 0/1 ContainerCreating 0 4s
web-84c6fbbdcc-6tbkx 1/1 Running 0 30m
web-84c6fbbdcc-ldv48 1/1 Running 0 30m
web-84c6fbbdcc-qvl9f 1/1 Running 0 30m
1
2
3
4
5
6
7
8
9
10
# 错误原因 镜像名字写错了 
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled <unknown> default-scheduler Successfully assigned default/web-7bddf7b45f-6ntcs to k8s-node1
Normal BackOff 23s (x4 over 102s) kubelet, k8s-node1 Back-off pulling image "nginx1.16"
Warning Failed 23s (x4 over 102s) kubelet, k8s-node1 Error: ImagePullBackOff
Normal Pulling 11s (x4 over 110s) kubelet, k8s-node1 Pulling image "nginx1.16"
Warning Failed 6s (x4 over 103s) kubelet, k8s-node1 Failed to pull image "nginx1.16": rpc error: code = Unknown desc = Error response from daemon: pull access denied for nginx1.16, repository does not exist or may require 'docker login'
Warning Failed 6s (x4 over 103s) kubelet, k8s-node1 Error: ErrImagePull
1
2
3
4
5
6
7
8
9
10
11
12
13
14
[root@k8s-master1 demo]# kubectl set image deployment web java-demo=nginx:1.16

# 还需要修改service里面的端口 8080 -> 80
[root@k8s-master1 demo]# kubectl edit service/web
...
spec:
clusterIP: 10.0.0.204
externalTrafficPolicy: Cluster
ports:
- nodePort: 31619
port: 80
protocol: TCP
targetPort: 80 # 修改目标端口
...
  1. 查看升级状态
1
2
# 如果pod做了健康检查,那么在更新的时候可以查看更新状态
[root@k8s-master1 demo]# kubectl rollout status deployment/web
  1. kubectl patch 补丁命令
1
[root@k8s-master1 demo]# kubectl patch --help

回滚操作 rollout

  1. 查看deployment历史记录
1
2
3
4
5
6
7
8
9
[root@k8s-master1 demo]# kubectl rollout --help

[root@k8s-master1 demo]# kubectl rollout history deployment/web
deployment.apps/web
REVISION CHANGE-CAUSE
1 <none> # 第一次部署demo
2 <none>
3 <none>
4 <none>
  1. 回滚到上一个版本
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[root@k8s-master1 demo]# kubectl rollout undo deployment/web
deployment.apps/web rolled back

# 滚动回滚 部署了新的pod

[root@k8s-master1 demo]# kubectl get pods
NAME READY STATUS RESTARTS AGE
web-68d86dd855-pgjlq 0/1 Terminating 0 13m
web-68d86dd855-pp8mv 0/1 Terminating 0 13m
web-68d86dd855-pq6w6 0/1 Terminating 0 13m
web-8598778cf-2m7lb 1/1 Running 0 9s
web-8598778cf-fnjtd 1/1 Running 0 8s
web-8598778cf-qjsd6 1/1 Running 0 10s
[root@k8s-master1 demo]# kubectl get pods
NAME READY STATUS RESTARTS AGE
web-8598778cf-2m7lb 1/1 Running 0 14s
web-8598778cf-fnjtd 1/1 Running 0 13s
web-8598778cf-qjsd6 1/1 Running 0 15s
  1. 回滚到指定版本
1
2
3
4
5
6
# 我这个nginx 回滚到 java-demo  别忘记修改回端口

[root@k8s-master1 demo]# kubectl rollout undo deployment/web --to-revision=1
deployment.apps/web rolled back
[root@k8s-master1 demo]# kubectl edit svc/web
service/web edited

删除应用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 删除pod还会拉起,因为创建的是deployment会保证副本数量
[root@k8s-master1 demo]# kubectl delete pod web-84c6fbbdcc-7dh5h
pod "web-84c6fbbdcc-7dh5h" deleted
[root@k8s-master1 demo]# kubectl get pods
NAME READY STATUS RESTARTS AGE
web-84c6fbbdcc-w2v5g 1/1 Running 0 3m33s
web-84c6fbbdcc-w56vs 1/1 Running 0 4s
web-84c6fbbdcc-xzglk 1/1 Running 0 3m30s

# 需要删除deployment
[root@k8s-master1 demo]# kubectl delete deployment/web
deployment.apps "web" deleted
[root@k8s-master1 demo]# kubectl get pods
NAME READY STATUS RESTARTS AGE
web-84c6fbbdcc-w2v5g 0/1 Terminating 0 4m5s
web-84c6fbbdcc-w56vs 0/1 Terminating 0 36s
1
2
3
4
5
6
7
8
9
10
[root@k8s-master1 demo]# kubectl apply -f web.yaml 
deployment.apps/web created
[root@k8s-master1 demo]# kubectl rollout history deployment/web
deployment.apps/web
REVISION CHANGE-CAUSE
1 <none>

# service 和 pod 是不同的一种组件,删除pod并不会影响已创建的svc,这种解耦太棒了
# 删除svc
[root@k8s-master1 demo]# kubectl delete svc/web

弹性伸缩 scale

1
2
1. 根据活动扩容实例
2. 传统的方式是虚拟机,准备扩容环境
1
2
3
4
5
6
7
8
9
10
11
12
13
# kubectl scale 快速扩容 承担并发
[root@k8s-master1 demo]# kubectl scale --help

[root@k8s-master1 demo]# kubectl scale --replicas=5 deployment/web
deployment.apps/web scaled

[root@k8s-master1 demo]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
web-84c6fbbdcc-685nc 1/1 Running 0 5m41s 10.244.0.55 k8s-node1 <none> <none>
web-84c6fbbdcc-88289 1/1 Running 0 30s 10.244.1.57 k8s-node2 <none> <none>
web-84c6fbbdcc-9mdjv 1/1 Running 0 5m41s 10.244.0.56 k8s-node1 <none> <none>
web-84c6fbbdcc-dvdkn 1/1 Running 0 5m41s 10.244.1.55 k8s-node2 <none> <none>
web-84c6fbbdcc-fpwqt 1/1 Running 0 30s 10.244.1.56 k8s-node2 <none> <none>
  1. 如果集群的资源不够,单只扩容pod是不行的
1
2
3
4
1. 增加nodes节点或者增加nodes的资源
2. 如果扩容node节点 都是根据业务的量去扩容,并且提前规划
3. 现在都是手动扩容,缩容,如何自动弹性实现
4. 自动需要借助node的资源指标进行弹性扩容,比如cpu,内存等
  1. 手动缩容
1
2
3
4
5
6
7
8
9
10
11
12
13
14
[root@k8s-master1 demo]# kubectl scale --replicas=3 deployment/web 
deployment.apps/web scaled
[root@k8s-master1 demo]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
web-84c6fbbdcc-685nc 1/1 Running 0 9m36s 10.244.0.55 k8s-node1 <none> <none>
web-84c6fbbdcc-88289 0/1 Terminating 0 4m25s 10.244.1.57 k8s-node2 <none> <none>
web-84c6fbbdcc-9mdjv 1/1 Running 0 9m36s 10.244.0.56 k8s-node1 <none> <none>
web-84c6fbbdcc-dvdkn 1/1 Running 0 9m36s 10.244.1.55 k8s-node2 <none> <none>
web-84c6fbbdcc-fpwqt 0/1 Terminating 0 4m25s 10.244.1.56 k8s-node2 <none> <none>
[root@k8s-master1 demo]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
web-84c6fbbdcc-685nc 1/1 Running 0 9m41s 10.244.0.55 k8s-node1 <none> <none>
web-84c6fbbdcc-9mdjv 1/1 Running 0 9m41s 10.244.0.56 k8s-node1 <none> <none>
web-84c6fbbdcc-dvdkn 1/1 Running 0 9m41s 10.244.1.55 k8s-node2 <none> <none>

Deployment 和 ReplicaSet

1
2
3
4
5
6
7
8
1. 部署1个Deployment,会自动创建1个ReplicaSet和Pod

[root@k8s-master1 demo]# kubectl get deploy,rs
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/web 3/3 3 3 12m

NAME DESIRED CURRENT READY AGE
replicaset.apps/web-84c6fbbdcc 3 3 3 12m
1
2
3
4
5
1. 部署Deployment -> 创建RS -> RS管理多个Pod
2. RS会判断replicas: 3 副本数 也会获取当前Pod的副本数
3. 如果少了一个 RS会帮助我们拉起
4. RS 帮我们实现了控制副本个数 和 历史版本记录,rollout回滚找rs回滚
5. 滚动更新会创建新的RS
1
2
3
1. Deployment -> 创建RS -> RS管理多个Pod
2. 滚动更新 创建新的RS -> 启动新的Pod 关闭之前rs中的1个,直到全部更新完成
3. service 指向 pod不变
1
2
3
4
5
6
7
8
9
10
11
12
13
14
[root@k8s-master1 ~]# kubectl set image deployment/web java-demo=nginx:1.16

[root@k8s-master1 ~]# kubectl get rs,deploy
NAME DESIRED CURRENT READY AGE
replicaset.apps/web-68d86dd855 3 3 3 17s
replicaset.apps/web-7bddf7b45f 0 0 0 2m
replicaset.apps/web-84c6fbbdcc 0 0 0 107m

[root@k8s-master1 ~]# kubectl rollout history deployment/web
deployment.apps/web
REVISION CHANGE-CAUSE
1 <none>
2 <none>
3 <none>