k8s最核心的4个资源对象
**Namespace**: 名称空间,一般用来隔离容器,提高控制性和安全性
**Deployment:** 最常见的无状态应用的控制器,支持应用的扩缩容、滚动更新等操作。
**Servcie**: 为弹性变动且存在生命周期的Pod对象提供了一个固定的访问接口,用于服务发现和服务访问。
**Pod**: 是运行容器以及调度的最小单位。同一个Pod可以同时运行多个容器,这些容器共享NET、UTS、IPC。除此之外还有 USER、PID、MOUNT
-----------------------------------------
## Namespace:名称空间
默认的名称空间: Default.
//查看名称空间
~]#
kubectl get ns
//查看名称空间详细信息
~]#
kubectl describe ns default
//创建名称空间
~]#
kubectl create ns bdqn
apiVersion: v1
kind: Namespace
metadata:
name: test
PS: namespace资源对象仅用于资源对象的隔离,并不能隔绝不同名称空间的Pod之间的通信,那是网络策略资源的功能。
查看指定名称空间的资源可以使用--namespace 或者-n 选项
//删除某个名称空间
kubectl delete ns bdqn
namespace "bd" deleted
> 在执行删除某个名称空间的时候,千万注意,轻易不执行此操作,因为,如果执行之后,默认会将所以在此名称空间之下资源全部删除。
--------------------------------------------
## Pod //自主式的pod 不支持副本,和tempele
kind: Pod
apiVersion: v1
metadata:
name: test-pod
namespace: bdqn
spec:
containers:
- name: test-app
image: httpd
- name: test-web
image: busybox
### Pod中镜像获取策略:
#将上述Pod资源的镜像下载策略改为IfNotPresent.
apiVersion: v1
kind: Pod
metadata:
name: pod1
spec:
containers:
- name: pod1
image: httpd
imagePullPolicy: IfNotPresent
k8s默认根据镜像的TAG的不同,有3中不同策略。
**Always**: 镜像标签为"latest"或镜像标签不存在时,总是从指定的仓库(默认的官方仓库、或者私有仓库)中获取最新镜像。
**IfNotPresent**:仅当本地镜像不存在时才从目标仓库中下载。也就意味着,如果本地存在,直接使用本地镜像,无需再联网下载。
**Never**: 禁止从仓库中下载镜像,即只使用本地镜像。
> PS: 对于标签为“latest”或者这标签不存在,其默认镜像下载策略为“Always”,而对于其他标签的镜像,默认则使用了“IfNotPresent”.
>
> 上述语句中提到的"本地"是指: docker images命令能够给查看到的镜像。
## 容器的重启策略
//将上述Pod资源添加重启策略为OnFailure.
apiVersion: v1
kind: Pod
metadata:
name: pod1
spec:
restartPolicy: OnFailure
containers:
- name: pod1
image: httpd
imagePullPolicy: IfNotPresent
**Always**: 但凡Pod对象终止就将其重启,此为默认设定。
**OnFailure**: 仅在Pod对象出现错误时才将其重启。
以上两种方案:我们可以换个角度去理解,比如: echo $? 可以利用 Pod的退出状态。
Always:如果Pod是正常退出,而且重启策略为Always,那么Pod也会被重启。
OnFailure: 仅在Pod是异常退出的时候,才重启Pod。
**Never**: 从不重启。//使用场景少
小技巧:
同一个yaml文件内,可以同时存在多种资源对象,但最好是同一个服务相关的资源。并且在写的时候,不同的资源需要用“---” 将资源隔离。其实默认是一个资源的yaml,最上方也有“---"不过是通常会省略不写。
vim pod1.yaml
---
apiVersion: v1
kind: Namespace
metadata:
name: bdqn
---
apiVersion: v1
kind: Pod
metadata:
name: pod1
namespace: bdqn
spec:
restartPolicy: OnFailure
containers:
- name: pod1
image: httpd
imagePullPolicy: IfNotPresent
```
#//kubectl get pod 发现查看不到,想想默认名称空间是谁,我们创建的什么? -n 选项 --namespace作用
kubectl apply -f pod1.yaml
kubectl get pod -o wide -n bdqn
====================================
### Pod的默认健康检查
//根据Pod的默认重启策略,对Pod进行健康检查
apiVersion: v1
kind: Pod
metadata:
name: healthcheck
spec:
restartPolicy: OnFailure
containers:
- name: healthcheck
image: busybox
args:
- /bin/sh
- -c
- sleep 10; exit 1 #模拟pod异常退出了。给了一个退出状态码,值为1 结合pod重启策略验证
//kubectl get pod -w #执行查看完整状态过程 和重启次数
ps:-w选项持续监控
如果此时,我们将推出状
kubectl get pod -w
NAME READY STATUS RESTARTS AGE
healthcheck 0/1 CrashLoopBackOff 2 2m7s
healthcheck 1/1 Running 3 2m10s
healthcheck 0/1 Error 3 2m20s
healthcheck 0/1 CrashLoopBackOff 3 2m31s
healthcheck 1/1 Running 4 3m21s
healthcheck 0/1 Error 4 3m31s
healthcheck 0/1 CrashLoopBackOff 4 3m45s
态码改为0,也就是正常退出,仍使用OnFailure策略,但它就不会重启Pod了
kind: Pod
apiVersion: v1
metadata:
name: healthcheck
spec:
restartPolicy: OnFailure
containers:
- name: healthcheck
image: busybox
args:
- /bin/sh
- -c
- sleep 10; exit 0
###探针
LivenessProbe 生存探测
ReadinessProbe 就绪探测
1. LivenessProbe(活跃度、存活性)
kind: Pod
apiVersion: v1
metadata:
name: liveness
labels:
test: liveness #通过标签选择器和svc资源关联
spec:
restartPolicy: OnFailure #配置pod的重启策略
containers:
- name: liveness
image: busybox
args:
- /bin/sh
- -c
- touch /tmp/test; sleep 30; rm -rf /tmp/test; sleep 300
livenessProbe: #在容器里面创建一个文件,在存活性字段中执行动作判断这个文件存在与否,根据返回值来和重启策略联动。先休眠30秒,这期间文件肯定存在,之后往下按照存活检测规则判断并得到返回值。
exec:
command:
- cat
- /tmp/test
initialDelaySeconds: 10 #Pod运行10秒后开始探测
periodSeconds: 5 #每5秒探测一次
PS: Liveness活跃度探测,根据探测某个文件是否存在,来确认某个服务是否正常运行,如果存在则正常,否则,它会根据你设置的Pod的重启策略操作Pod。
kubectl apply -f liveness.yaml
pod/liveness created
[root@master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
liveness 1/1 Running 0 24s
[root@master ~]# kubectl get pod liveness -w
NAME READY STATUS RESTARTS AGE
liveness 1/1 Running 0 42s
liveness 1/1 Running 1 105s
liveness 1/1 Running 2 3m49s
liveness 1/1 Running 3 5m54s
可以看到重启策略生效了
2. Readiness(敏捷探测、就绪性探测)
kind: Pod
apiVersion: v1
metadata:
name: readiness
labels:
test: readiness #通过标签选择器和svc资源关联
spec:
restartPolicy: OnFailure
containers:
- name: readiness
image: busybox
args:
- /bin/sh
- -c
- touch /tmp/test; sleep 30; rm -rf /tmp/test; sleep 300
readinessProbe: #readiness判断关键文件是否存在后,而决定pod的状态,这点和liveiness一样,不同点在于他并不会触发对pod操作和重启策略,而是会将pod设置为不可用状态,既然pod不可用,如果关联了service资源,那么思考一下会有什么效果?
exec:
command:
- cat
- /tmp/test
initialDelaySeconds: 10
periodSeconds: 5
kubectl get pod readiness -w
NAME READY STATUS RESTARTS AGE
readiness 1/1 Running 0 20s
readiness 0/1 Running 0 81s
#我们结合一个service资源来全面了解一下
cat test-svc.yaml
apiVersion: v1
kind: Service
metadata:
name: test-svc
spec:
selector:
test: readiness #svc资源标签选择器选中readiness标签,做好关联
ports:
- protocol: TCP
port: 80
targetPort: 80
kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
test-svc ClusterIP 10.107.74.81 <none> 80/TCP 18m
kubectl describe svc test-svc
Name: test-svc
Namespace: default
Labels: <none>
Annotations: Selector: test=readiness
Type: ClusterIP
IP: 10.107.74.81
Port: <unset> 80/TCP
TargetPort: 80/TCP
Endpoints: <none> #观察点
Session Affinity: None
Events: <none>
kubectl apply -f readiness.yaml
pod/readiness created
kubectl get pod -o wide -w
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
readiness 0/1 Running 0 6s 10.244.1.45 node01 <none> <none>
test-web 1/1 Running 2 4d 10.244.1.37 node01 <none> <none>
^C[root@master ~]# kubectl describe svc test-svc
Name: test-svc
Namespace: default
Labels: <none>
Annotations: Selector: test=readiness
Type: ClusterIP
IP: 10.107.74.81
Port: <unset> 80/TCP
TargetPort: 80/TCP
Endpoints: 10.244.1.45:80 #观察点
Session Affinity: None
Events: <none>
kubectl get pod -o wide -w
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
readiness 1/1 Running 0 42s 10.244.1.45 node01 <none> <none>
test-web 1/1 Running 2 4d 10.244.1.37 node01 <none> <none>
kubectl describe pod readiness #通过event事件观察
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 10m default-scheduler Successfully assigned default/readiness to node01
Normal Pulling 10m kubelet, node01 Pulling image "busybox"
Normal Pulled 10m kubelet, node01 Successfully pulled image "busybox"
Normal Created 10m kubelet, node01 Created container readiness
Normal Started 10m kubelet, node01 Started container readiness
Warning Unhealthy 5m58s (x48 over 9m53s) kubelet, node01 Readiness probe failed: cat: can't open '/tmp/test': No such file or directory
PS: 总结liveness和 readiness探测 *****
1)liveness和readiness是两种健康检查机制,如果不特意配置,k8s将两种探测采取相同的默认行为,即通过判断容器启动进程的返回值是否为零,来判断探测是否成功。
2)两种探测配置方法完全一样,不同之处在于探测失败后的行为:
liveness探测是根据Pod重启策略操作容器,大多数是重启容器。
readiness则是将容器设置为不可用,不接收Service转发的请求。
3)两种探测方法可以独立存在,也可以同时使用。用liveness判断容器是否需要重启实现自愈;用readiness判断容器是否已经准备好对外提供服务。
### 健康检测的应用
#### 在扩容中的应用。
kind: Deployment
apiVersion: apps/v1
metadata:
name: myweb2
labels:
run: web2
spec:
selector:
matchLabels:
run: web2
replicas: 3
template:
metadata:
labels:
run: web2
spec:
containers:
- name: web2
image: httpd:latest
ports:
- containerPort: 80
readinessProbe:
httpGet: #返回的是访问80端口后的健康码 200-400之间为正常,针对的是pod中的服务是否正常启动
scheme: HTTP
path: /healthy #指的是httpd镜像网站家目录
port: 80
initialDelaySeconds: 10
periodSeconds: 5
apiVersion: v1
kind: Service
metadata:
name: scalweb-svc
spec:
type: NodePort
selector:
run: web2
ports:
- port: 90
targetPort: 80
nodePort: 30111
总结: 服务扩容中,如果没有针对性就绪探测,往往扩容之后,表面看Pod的状态是没有问题的,但其实Pod内的服务是否运行正常也是我们要关注的,而Readiness的关注点就在这,如果Pod内的服务运行有问题,那么,这些新扩容的Pod就不会被添加到Service资源的转发中,从而保证用户能够有最起码正常的服务体验。
kubectl apply -f scale.yaml
deployment.apps/myweb2 created
service/scalweb-svc created
[root@master ~]# kubectl get pods #为什么没启动呢?
NAME READY STATUS RESTARTS AGE
myweb2-7786977449-9ln8l 0/1 ContainerCreating 0 16s
myweb2-7786977449-fk4kn 0/1 Running 0 16s
myweb2-7786977449-pc74m 0/1 ContainerCreating 0 16s
[root@master ~]# kubectl describe svc scalweb-svc
Name: scalweb-svc
Namespace: default
Labels: <none>
Annotations: Selector: run=web2
Type: NodePort
IP: 10.102.120.240
Port: <unset> 90/TCP
TargetPort: 80/TCP
NodePort: <unset> 30111/TCP
Endpoints: #结束点也没有 原因在与/health这个参数 代表访问的是网站根目录的healthy文件
Session Affinity: None
External Traffic Policy: Cluster
Events: <none>
kubectl exec -it myweb2-7786977449-9ln8l bash
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl kubectl exec [POD] -- [COMMAND] instead.
root@myweb2-7786977449-9ln8l:/usr/local/apache2# cd htdocs/
root@myweb2-7786977449-9ln8l:/usr/local/apache2/htdocs# touch healthy
root@myweb2-7786977449-9ln8l:/usr/local/apache2/htdocs# exit
exit
kubectl get pods
NAME READY STATUS RESTARTS AGE
bdqn1-6847f7cdcd-cn4d2 1/1 Running 1 25h
bdqn1-6847f7cdcd-gk67r 1/1 Running 1 25h
bdqn1-6847f7cdcd-kpdm2 1/1 Running 1 25h
myweb2-7786977449-9ln8l 1/1 Running 0 9m14s
myweb2-7786977449-fk4kn 0/1 Running 0 9m14s
myweb2-7786977449-pc74m 0/1 Running 0 9m14s
kubectl exec -it myweb2-7786977449-fk4kn touch /usr/local/apache2/htdocs/healthy #直接touch的命令
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl kubectl exec [POD] -- [COMMAND] instead.
kubectl get pods
NAME READY STATUS RESTARTS AGE
myweb2-7786977449-9ln8l 1/1 Running 0 10m
myweb2-7786977449-fk4kn 1/1 Running 0 10m
curl -I http://192.168.8.20:30111/healthy
HTTP/1.1 200 OK
Date: Fri, 19 Nov 2021 07:51:47 GMT
Server: Apache/2.4.51 (Unix)
Last-Modified: Fri, 19 Nov 2021 07:49:29 GMT
ETag: "0-5d11f83cd1440"
Accept-Ranges: bytes
ps:注意这里healthy模拟的是容器里的关键文件,不要随便判断一个,我们的例子是学习方法!
#### 在更新过程中的使用
yaml]# vim update1.yaml
kind: Deployment
apiVersion: apps/v1
metadata:
name: update
spec:
selector:
matchLabels:
run: update
replicas: 3
template:
metadata:
labels:
run: update
spec:
containers:
- name: update
image: nginx:1.17
imagePullPolicy: IfNotPresent
args:
- /bin/sh
- -c
- sleep 10; touch /tmp/healthy ; sleep 300
ports:
- containerPort: 80
readinessProbe:
exec:
command:
- cat
- /tmp/healthy
initialDelaySeconds: 10
periodSeconds: 5
kubectl apply -f update1.yaml --record
deployment.apps/update created
kubectl get pod -w
NAME READY STATUS RESTARTS AGE
readiness 0/1 Completed 0 61m
test-web 1/1 Running 2 4d1h
update-77977855db-2xptr 0/1 ContainerCreating 0 15s
update-77977855db-5t97n 0/1 ContainerCreating 0 15s
update-77977855db-9p4wm 0/1 ContainerCreating 0 15s
update-77977855db-b8fkj 0/1 ContainerCreating 0 15s
update-77977855db-gf5xn 0/1 ContainerCreating 0 15s
update-77977855db-grhqh 0/1 ContainerCreating 0 15s
update-77977855db-jdgw9 0/1 ContainerCreating 0 15s
update-77977855db-l8sbb 0/1 ContainerCreating 0 15s
update-77977855db-rggww 0/1 ContainerCreating 0 15s
update-77977855db-t27nx 0/1 ContainerCreating 0 15s
update-77977855db-l8sbb 0/1 Running 0 17s
update-77977855db-jdgw9 0/1 Running 0 22s
update-77977855db-l8sbb 1/1 Running 0 28s
update-77977855db-5t97n 0/1 Running 0 28s
update-77977855db-grhqh 0/1 Running 0 28s
update-77977855db-b8fkj 0/1 Running 0 29s
update-77977855db-2xptr 0/1 Running 0 30s
update-77977855db-jdgw9 1/1 Running 0 34s
update-77977855db-grhqh 1/1 Running 0 38s
update-77977855db-2xptr 1/1 Running 0 40s
//复制update1的yaml文件,命名update2.yaml,并更改镜像和args的命令部分,这里我们确定,更新肯定会失败,因为它没有符合readiness探测文件。
apiVersion: apps/v1
kind: Deployment
metadata:
name: update
spec:
selector:
matchLabels:
run: update
replicas: 3
template:
metadata:
labels:
run: update
spec:
containers:
- name: update
image: nginx:1.18
imagePullPolicy: IfNotPresent
args:
- /bin/sh
- -c
- sleep 3000 #直接休眠 ,这里readiness检测肯定是失败的。因为没有这个文件,这时候升级会发生什么?
readinessProbe:
exec:
command:
- cat
- /tmp/healthy
initialDelaySeconds: 10
periodSeconds: 5
```sh
[root@master ~]# kubectl apply -f update2.yaml --record #更新镜像到v2版本,记录到更新历史记录2
[root@master ~]# kubectl get pod -o wide 持续观察,更新肯定是失败的。
[root@master ~]# kubectl rollout undo deployment update --to-revision=1
```
//在更新的过程中,Readiness探测同样重要,想象一下,如果更新完成的Pod内没有更新的内容,并且也没有相对应的探测,那么有可能我们更新的Pod全部都会是不可用的,这是一个天大的灾难。
//其实在更新过程中,为了保证,即使更新失败,至少也有相对数量的副本数量仍能正常提供服务,其实是有数值可以设置。
```sh
[root@master scale]# kubectl explain deploy.spec.strategy.rollingUpdate
```
> **maxSurge**: 此参数控制滚动更新过程中,副本总数超过预期数(ReplicaSet)的值。可以是整数,也可以是百分比,默认是1.默认最多不超过更新pod设置中的10%
>
> **maxUnavailable**: 不可用Pod的值。默认为1.可以是整数,也可以是百分比。
练习:
在更新过程中,期望的Replicas值为10个,更改rollingupdate策略,要求在更新过程中,最大不可用Pod的值为4个,允许同时出现的Pod的总数量为13个。
name: update
spec:
strategy: #在yaml中的一级字段spec中可以设置上述两个值
rollingUpdate: #滚动更新规则
maxSurge: 3
maxUnavailable: 4
replicas: 10
template:
metadata:
labels: