# Kubernetes生命周期管理
# 步骤
- 制作镜像
- 使用Deployment控制器部署镜像
kubectl create deployment my-blog --image=registry.cn-hangzhou.aliyuncs.com/liuxiaoluxx/blog:v1.0
kubectl get deploy,pods
- 使用Service发布Pod
kubectl expose deployment my-blog --port=80 --type=NodePort --target-port=8080 --name=my-blog-service
kubectl get service
# Pod与Deployment的关系
Deployment是最为常用的controllers(也称为workload),其他控制器还有DaemonSet、StatefulSet等。
Controllers作用:
管理Pod对象
使用标签与Pod关联
控制器了Pod的运维,例如滚动更新、伸缩、副本管理、维护Pod状态等。
Deployment的功能:
管理Pod和ReplicaSet
具有上线部署、副本设定、滚动升级、回滚等功能
提供声明式更新,例如只更新一个新的Image
应用场景:
- 网站
- API
- 微服务
示例:
使用yaml文件的方式创建deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
在该例中:
创建名为
nginx-deployment
(由.metadata.name
字段标明)的 Deployment。该 Deployment 创建三个(由
replicas
字段标明)Pod 副本。selector
字段定义 Deployment 如何查找要管理的 Pods。 在这里,你只需选择在 Pod 模板中定义的标签(app: nginx
)。 不过,更复杂的选择规则是也可能的,只要 Pod 模板本身满足所给规则即可。说明:
matchLabels
字段是{key,value}
偶对的映射。在matchLabels
映射中的单个{key,value}
映射等效于matchExpressions
中的一个元素,即其key
字段是 “key”,operator 为 “In”,value
数组仅包含 “value”。在matchLabels
和matchExpressions
中给出的所有条件都必须满足才能匹配。template字段包含以下子字段:
- Pod 被使用
labels
字段打上app: nginx
标签。 - Pod 模板规约(即
.template.spec
字段)指示 Pods 运行一个nginx
容器, 该容器运行版本为 1.14.2 的nginx
Docker Hub (opens new window)镜像。 - 创建一个容器并使用
name
字段将其命名为nginx
。
- Pod 被使用
使用service发布deploy
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
type: NodePort
在该例中
- 创建名为my-service(由
.metadata.name
字段标明)的Service。 spec.selector
将绑定标签为app=nginx的所有podspec.ports[0].targetPort
表示代理容器内部的80端口
# 服务编排
# YAML文件创建资源对象
# YAML文件格式说明
YAML 是一种简洁的非标记语言。
语法格式:
- 缩进表示层级关系
- 不支持制表符“tab”缩进,使用空格缩进
- 通常开头缩进 2 个空格
- 字符后缩进 1 个空格,如冒号、逗号等
- “---”表示YAML格式,一个文件的开始
- “#”注释
示例
在刚才的例子中,我们创建了两个yaml文件,分别创建了pod,和service,我们也可以将两个文件合并,用---隔开即可。这样就实现了在创建deploy的同时,创建service,对外发布服务
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
type: NodePort
# 资源字段太多,记不住怎么办
用create命令生成 我们无需强行记住一个yaml文件应该有哪些属性,只需命令生成可生成基本的yaml结构,如果有附加属性,只需根据模板调整即可。
kubectl create deployment nginx --image=nginx:1.16 -o yaml --dry-run=client > nginx-deploy.yaml
示例
执行命令如下:
kubectl create deploy nginx-deploy --image=nginx -o yaml --dry-run=client > nginx-deploy.yaml
查看生成的yaml文件
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: nginx-deploy
name: nginx-deploy
spec:
replicas: 1
selector:
matchLabels:
app: nginx-deploy
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
app: nginx-deploy
spec:
containers:
- image: nginx
name: nginx
resources: {}
status: {}
可以看到,基本的yaml结构已有,这里还需要注意一点,我们需要将creationTimestamp的部分删除。
修改后,内容如下:
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx-deploy
name: nginx-deploy
spec:
replicas: 1
selector:
matchLabels:
app: nginx-deploy
strategy: {}
template:
metadata:
labels:
app: nginx-deploy
spec:
containers:
- image: nginx
name: nginx
resources: {}
status: {}
用get命令导出
我们也可以使用直接将现有的deployment的yaml配置文件导出
kubectl get deployment nginx -o yaml > my-deploy.yaml
示例
执行命令如下:
kubectl get deploy nginx-deployment -o yaml > nginx-deployment2.yaml
查看生成的nginx-deplotment2.yaml文件
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
deployment.kubernetes.io/revision: "1"
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"apps/v1","kind":"Deployment","metadata":{"annotations":{},"labels":{"app":"nginx"},"name":"nginx-deployment","namespace":"default"},"spec":{"replicas":3,"selector":{"matchLabels":{"app":"nginx"}},"template":{"metadata":{"labels":{"app":"nginx"}},"spec":{"containers":[{"image":"nginx:1.14.2","name":"nginx","ports":[{"containerPort":80}]}]}}}}
creationTimestamp: "2021-01-25T13:51:37Z"
generation: 1
labels:
app: nginx
managedFields:
- apiVersion: apps/v1
fieldsType: FieldsV1
fieldsV1:
f:metadata:
f:annotations:
.: {}
f:kubectl.kubernetes.io/last-applied-configuration: {}
f:labels:
.: {}
f:app: {}
f:spec:
f:progressDeadlineSeconds: {}
f:replicas: {}
f:revisionHistoryLimit: {}
f:selector:
f:matchLabels:
.: {}
f:app: {}
f:strategy:
f:rollingUpdate:
.: {}
f:maxSurge: {}
f:maxUnavailable: {}
f:type: {}
f:template:
f:metadata:
f:labels:
.: {}
f:app: {}
f:spec:
f:containers:
k:{"name":"nginx"}:
.: {}
f:image: {}
f:imagePullPolicy: {}
f:name: {}
f:ports:
.: {}
k:{"containerPort":80,"protocol":"TCP"}:
.: {}
f:containerPort: {}
f:protocol: {}
f:resources: {}
f:terminationMessagePath: {}
f:terminationMessagePolicy: {}
f:dnsPolicy: {}
f:restartPolicy: {}
f:schedulerName: {}
f:securityContext: {}
f:terminationGracePeriodSeconds: {}
manager: kubectl-client-side-apply
operation: Update
time: "2021-01-25T13:51:37Z"
- apiVersion: apps/v1
fieldsType: FieldsV1
fieldsV1:
f:metadata:
f:annotations:
f:deployment.kubernetes.io/revision: {}
f:status:
f:availableReplicas: {}
f:conditions:
.: {}
k:{"type":"Available"}:
.: {}
f:lastTransitionTime: {}
f:lastUpdateTime: {}
f:message: {}
f:reason: {}
f:status: {}
f:type: {}
k:{"type":"Progressing"}:
.: {}
f:lastTransitionTime: {}
f:lastUpdateTime: {}
f:message: {}
f:reason: {}
f:status: {}
f:type: {}
f:observedGeneration: {}
f:readyReplicas: {}
f:replicas: {}
f:updatedReplicas: {}
manager: kube-controller-manager
operation: Update
time: "2021-01-25T13:52:01Z"
name: nginx-deployment
namespace: default
resourceVersion: "3800213"
selfLink: /apis/apps/v1/namespaces/default/deployments/nginx-deployment
uid: e68c77ca-d9da-4ef5-a446-d46baea9de89
spec:
progressDeadlineSeconds: 600
replicas: 3
revisionHistoryLimit: 10
selector:
matchLabels:
app: nginx
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
template:
metadata:
creationTimestamp: null
labels:
app: nginx
spec:
containers:
- image: nginx:1.14.2
imagePullPolicy: IfNotPresent
name: nginx
ports:
- containerPort: 80
protocol: TCP
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
dnsPolicy: ClusterFirst
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
status:
availableReplicas: 3
conditions:
- lastTransitionTime: "2021-01-25T13:52:01Z"
lastUpdateTime: "2021-01-25T13:52:01Z"
message: Deployment has minimum availability.
reason: MinimumReplicasAvailable
status: "True"
type: Available
- lastTransitionTime: "2021-01-25T13:51:37Z"
lastUpdateTime: "2021-01-25T13:52:01Z"
message: ReplicaSet "nginx-deployment-66b6c48dd5" has successfully progressed.
reason: NewReplicaSetAvailable
status: "True"
type: Progressing
observedGeneration: 1
readyReplicas: 3
replicas: 3
updatedReplicas: 3
可以看到,这个文件内容非常多,我们需要将不需要的信息剔除
删减后内容如下:
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx
name: nginx-deployment
namespace: default
spec:
replicas: 3
selector:
matchLabels:
app: nginx
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
template:
metadata:
labels:
app: nginx
spec:
containers:
- image: nginx:1.14.2
imagePullPolicy: IfNotPresent
name: nginx
ports:
- containerPort: 80
protocol: TCP
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Always
Pod容器的指定字段下,不清楚支持哪些子字段怎么查询?
kubectl explain pods.spec.containers
kubectl explain deployment
# 应用升级,弹性伸缩,回滚,删除
# 应用升级
kubectl set image deployment web nginx=nginx:1.16
将名为web的deployment中,name为nginx的pod的镜像更新到1.16版本
这里需要提到一点,这是一个滚动更新的过程,先创建新的容器,然后将旧的容器删掉,对用户来说是无感的
# 弹性伸缩
# 手动扩容
kubectl scale deployment web --replicas=3
将名为web的deployment的副本设置为3个
# 自动水平扩容(注意Pod必须配置resource.request)
HPA机制:pod水平扩容,根据设置的阈值,自动触发扩容
kubectl autoscale deployment web --min=3 --max=10 --cpu-percent=80
设定名为web的deployment,最小的pod数为3,最大的pod数为10,在cpu到达80%的时候触发扩容,注意需要与metric-server配合使用
在这里,我们可以调整一下之前的yaml,增加pod的资源使用限制,这里限制cpu为0.5核
新增内容如下:
resources:
requests:
cpu: 0.5
以下为修改后的完整版本:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
resources:
requests:
cpu: 0.5
---
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
type: NodePort
kubectl get hpa
压测
- 这里可使用httpd-tools进行一个简单的压力测试
[root@liuxiaolu-master ~]# yum install httpd-tools
- 使用ab命令,主要使用两个参数,其他参数可使用ab --help查看
-n requests Number of requests to perform # 请求数 -c concurrency Number of multiple requests to make at a time # 并发数
- 执行命令,只需用k8s内部的service地址即可
- 查看k8s内部的service地址
[root@liuxiaolu-master ~]# kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 21d my-service NodePort 10.105.226.230 <none> 80:30331/TCP 2d1h
- 可以看到,我们之前创建的my-service的地址是10.105.226.230,接下来执行压测命令(100000个请求,每次同时有1000请求执行)
[root@liuxiaolu-master ~]# ab -n 100000000 -c 10000 http://10.105.226.230/html
- 稍等一两分钟之后查看hpa,可以看到,机器的负载已经上来了,超过5%了,这时候应该是会执行自动拉起pod的
[root@liuxiaolu-master ~]# kubectl get hpa NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE nginx-deployment Deployment/nginx-deployment 22%/5% 3 10 10 22m
- 查看pod, 可以看到,有三个pending状态的pod,已经被自动拉起。这里提到一点,在我们没有进行压测后,负载下去之后,大概5分钟,将会进行自动缩容
[root@liuxiaolu-master ~]# kubectl get pod NAME READY STATUS RESTARTS AGE nginx-deployment-7c5784685b-5w56n 1/1 Running 0 5m nginx-deployment-7c5784685b-64znz 1/1 Running 0 5m nginx-deployment-7c5784685b-6scjx 0/1 Pending 0 4m45s nginx-deployment-7c5784685b-6v5rw 0/1 Pending 0 4m45s nginx-deployment-7c5784685b-bml66 1/1 Running 0 5m nginx-deployment-7c5784685b-bv5wk 1/1 Running 0 27m nginx-deployment-7c5784685b-bx6q6 1/1 Running 0 27m nginx-deployment-7c5784685b-t4t9g 1/1 Running 0 4m45s nginx-deployment-7c5784685b-t4wjp 1/1 Running 0 27m nginx-deployment-7c5784685b-xpgkp 0/1 Pending 0 4m45s
# 回滚
kubectl rollout history deployment web
# 查看历史版本kubectl rollout undo deployment web
# 回滚上一个版本kubectl rollout undo deployment web --to-revision=2
# 回滚指定版本
# 删除
kubectl delete deploy web
# 删除名为web的deploy(deploy是deployment的缩写词)kubectl delete svc web
# 删除名为web的svc(svc是service的缩写词)