(1). 部署应用步骤
- 通过Dockerfile,创建镜像,并提交到仓库(建议自建私有仓库).
- 编写yaml文件,部署镜像到K8S中.
- 编写yaml(service)文件,暴露容器端口.
(2). 项目准备
项目结构如下:
hello-example
├── Dockerfile
├── pom.xml
├── src
│ ├── main
│ │ ├── java
│ │ │ └── help
│ │ │ └── lixin
│ │ │ ├── App.java
│ │ │ └── controller
│ │ │ └── HelloController.java
│ │ └── resources
│ │ ├── application.properties
│ │ └── logback-spring.xml
│ └── test
│ └── java
└── target
- 本地需要安装有docker环境.
- 执行: mvn clean package dockerfile:build
- 推送镜像到仓库(我这里用的是docker公有仓库:docker pull lixinhelp/hello:2.0.0-SNAPSHOT)
(3). 部署镜像到K8S中
# 通过kubectl创建yaml模板
[root@master ~]# kubectl create deployment hello-world --image=lixinhelp/hello:2.0.0-SNAPSHOT --dry-run -o yaml > hello-world-deployment.yml
hello-world-deployment.yml
[root@master ~]# cat hello-world-deployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: hello-world
name: hello-world
spec:
replicas: 3
selector:
matchLabels:
app: hello-world
template:
metadata:
labels:
app: hello-world
spec:
containers:
- image: lixinhelp/hello:2.0.0-SNAPSHOT
name: hello
应用配置到K8S里
# --record会把部署的信息记录到:kubectl rollout history的CHANGE-CAUSE信息里
[root@master ~]# kubectl apply -f hello-world-deployment.yml --record
deployment.apps/hello-world created
# 查看pod启动信息
[root@master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
hello-world-6b6d6fd479-d7tp4 1/1 Running 1 94m
hello-world-6b6d6fd479-ksgbr 1/1 Running 1 94m
hello-world-6b6d6fd479-zn85h 1/1 Running 2 94m
# 查看某个应用是否启动成功
[root@master ~]# kubectl logs hello-world-6b6d6fd479-ksgbr
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.1.0.RELEASE)
2021-01-12 08:25:32.371 INFO 1 --- [ main] help.lixin.App : Starting App on hello-world-6b6d6fd479-ksgbr with PID 1 (/opt/service/app.jar started by root in /)
(4). 暴露应用
# 查看deploy
[root@master ~]# kubectl get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
hello-world 2/2 2 2 30h
# 通过export生成service配置文件.
# hello-world要与上面deploy的名称相同
# --port : 集群内部容器通信端口
# --target-port : 应用程序(Dockerfile)暴露(EXPOSE)的端口
# --type=NodePort : NodePort会创建CLUSTER-IP并随机生成端口
# -o : 生成YAML格式的文件
# --dry-run : 尝试运行(并不是真正的运行)
[root@master ~]# kubectl expose deployment hello-world --port=9090 --target-port=9090 --type=NodePort -o yaml --dry-run > hello-world-expose.yml
# 查看配置文件
[root@master ~]# cat hello-world-expose.yml
apiVersion: v1
kind: Service
metadata:
labels:
app: hello-world
name: hello-world
spec:
ports:
- port: 9090
protocol: TCP
targetPort: 9090
selector:
app: hello-world
type: NodePort
# 应用配置
[root@master ~]# kubectl apply -f hello-world-expose.yml
service/hello-world created
# 查看pod和service
[root@master ~]# kubectl get pods,svc
NAME READY STATUS RESTARTS AGE
pod/hello-world-6b6d6fd479-4fntx 1/1 Running 0 11m
pod/hello-world-6b6d6fd479-d7tp4 1/1 Running 1 108m
pod/hello-world-6b6d6fd479-ksgbr 1/1 Running 1 108m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
# 31355就是NodePort随机生成的
service/hello-world NodePort 10.1.232.6 <none> 9090:31355/TCP 37s
# 测试访问
lixin-macbook:~ lixin$ curl http://10.211.55.100:31355/hello
Hello World!!!test-hello
lixin-macbook:~ lixin$ curl http://10.211.55.101:31355/hello
Hello World!!!test-hello
lixin-macbook:~ lixin$ curl http://10.211.55.102:31355/hello
Hello World!!!test-hello
(5). 滚动更新
kubectl set image升级应用.
# 为了测试方便(网络慢),我先在两台机器上分别拉取镜像.
[root@node-1 ~]# docker pull lixinhelp/hello:3.0.0-SNAPSHOT
[root@node-2 ~]# docker pull lixinhelp/hello:3.0.0-SNAPSHOT
# 查看待升级的镜像
[root@node-1 ~]# docker images|grep 3.0.0
lixinhelp/hello 3.0.0-SNAPSHOT 35fffb48c583 27 hours ago 576MB
[root@node-2 ~]# docker images|grep 3.0.0
lixinhelp/hello 3.0.0-SNAPSHOT 35fffb48c583 27 hours ago 576MB
# 查看K8S集群有哪些deployment
[root@master ~]# kubectl get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
hello-world 3/3 3 3 26h
# 升级deploy中的镜像
# hello-world : 为deployment名称
# hello : 为容器中定义的镜像名称
[root@master ~]# kubectl set image deployment hello-world hello=lixinhelp/hello:3.0.0-SNAPSHOT
deployment.extensions/hello-world image updated
# 查看启动的service
[root@master ~]# kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
hello-world NodePort 10.1.232.6 <none> 9090:31355/TCP 25h
# 测试访问查看是否升级成功
lixin-macbook:~ lixin$ curl http://10.211.55.100:31355/hello
Hello World-3.0.0-SNAPSHOT!!!test-hello
lixin-macbook:~ lixin$ curl http://10.211.55.101:31355/hello
Hello World-3.0.0-SNAPSHOT!!!test-hello
lixin-macbook:~ lixin$ curl http://10.211.55.102:31355/hello
Hello World-3.0.0-SNAPSHOT!!!test-hello
kubectl edit实时修改配置
# 可实时修改deployment/hello-world的配置信息,都不需要重新应用配置.
# [root@master ~]# kubectl edit deployment/hello-world
# 可实时修改service/hello-world的配置信息,都不需要重新应用配置.
[root@master ~]# kubectl edit service/hello-world
apiVersion: v1
kind: Service
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"labels":{"app":"hello-world"},"name":"hello-world","namespace":"default"},"spec":{"ports":[{"port":9090,"protocol":"TCP","targetPort":9090}],"selector":{"app":"hello-world"},"type":"NodePort"}}
creationTimestamp: "2021-01-12T08:39:39Z"
labels:
app: hello-world
name: hello-world
namespace: default
resourceVersion: "35142"
selfLink: /api/v1/namespaces/default/services/hello-world
uid: 05854b40-4413-4faa-aeba-d1d7e2ce0381
spec:
clusterIP: 10.1.232.6
externalTrafficPolicy: Cluster
ports:
- nodePort: 31355
port: 9090
protocol: TCP
targetPort: 9090
selector:
app: hello-world
sessionAffinity: None
type: NodePort
status:
loadBalancer: {}
kubectl rollout status查看升级状态
# 查看资源(deployment/hello-world)升级状态
[root@master ~]# kubectl rollout status deployment/hello-world
deployment "hello-world" successfully rolled out
(6). 回滚
# 查看资源(deployment/hello-world),升级记录
[root@master ~]# kubectl rollout history deployment/hello-world
deployment.extensions/hello-world
REVISION CHANGE-CAUSE
1 <none>
2 <none>
# 回滚到上一个版本
# [root@master ~]# kubectl rollout undo deployment/hello-world
# 回滚到指定版本
[root@master ~]# kubectl rollout undo deployment/hello-world --to-revision=1
deployment.extensions/hello-world rolled back
# 测试是否回滚成功
lixin-macbook:~ lixin$ curl http://10.211.55.100:31355/hello
Hello World!!!test-hello
lixin-macbook:~ lixin$ curl http://10.211.55.101:31355/hello
Hello World!!!test-hello
lixin-macbook:~ lixin$ curl http://10.211.55.102:31355/hello
Hello World!!!test-hello
(7). 弹性伸缩Pod
# 查看当前的pod
[root@master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
hello-world-5f8d77c9f7-589kd 1/1 Running 0 40m
hello-world-5f8d77c9f7-hg5fx 1/1 Running 0 38m
hello-world-5f8d77c9f7-xthp7 1/1 Running 0 6m28s
# 对hello-world进行扩容
[root@master ~]# kubectl scale deployment hello-world --replicas=5
deployment.extensions/hello-world scaled
# 再次查看pod,已经增加到5个
[root@master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
hello-world-5f8d77c9f7-2srd8 1/1 Running 0 33s
hello-world-5f8d77c9f7-589kd 1/1 Running 0 41m
hello-world-5f8d77c9f7-5n7gg 1/1 Running 0 33s
hello-world-5f8d77c9f7-hg5fx 1/1 Running 0 40m
hello-world-5f8d77c9f7-xthp7 1/1 Running 0 8m20s
(8). 删除pod和deployment
deployment能够保证你预期的副本数的Pod,所以,如果,删除的是pod,deployment会立即再启动新的Pod.
# 查看有哪些pod
[root@master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
hello-world-5f8d77c9f7-2xls6 1/1 Running 0 33m
hello-world-5f8d77c9f7-589kd 1/1 Running 0 33m
hello-world-5f8d77c9f7-hg5fx 1/1 Running 0 32m
# 删除某个pod
[root@master ~]# kubectl delete pod hello-world-5f8d77c9f7-2xls6
pod "hello-world-5f8d77c9f7-2xls6" deleted
# 发现pod又重新启动了
[root@master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
hello-world-5f8d77c9f7-589kd 1/1 Running 0 35m
hello-world-5f8d77c9f7-hg5fx 1/1 Running 0 34m
hello-world-5f8d77c9f7-xthp7 1/1 Running 0 103s
# 删除deployment(hello-world)
[root@master ~]# kubectl delete deployment hello-world