第9节 Pod
❤️💕💕新时代拥抱云原生,云原生具有环境统一、按需付费、即开即用、稳定性强特点。Myblog:http://nsddd.top
[TOC]
理解Pod
什么是pod?
pod是运行中的一组容器,pod是kubernetes中应用的最小单位。
什么是CRI?(container runtime interface)
或许你可以理解是docker,CRI就是容器运行时的环境。我们开发的应用就能以容器化的方式运行~
提示
💡 那么k8s为了管理方便,又封装了pod,所以说pod是容器运行的最小单位~
- 每一个容器封装成一个pod
- 每个pod可能有一个或者多个容器,但是也称之为一组容器
pod是可以有多个容器的,而且组成原子,这个是和容器的区别~
⚡ 描述某一个pod是如何运行的
kubectl describe pod my-nginx-7fb96c846b-m9rjp
展开查看详情💡
[root@k8s-master03 ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
my-nginx-7fb96c846b-cnhbz 1/1 Running 2 (92m ago) 38h
my-nginx-7fb96c846b-g55km 1/1 Running 2 (92m ago) 38h
my-nginx-7fb96c846b-m9rjp 1/1 Running 2 (92m ago) 38h
[root@k8s-master03 ~]# kubectl describe pod my-nginx-7fb96c846b-m9rjp
Name: my-nginx-7fb96c846b-m9rjp
Namespace: default
Priority: 0
Service Account: default
Node: k8s-master03/192.168.0.4
Start Time: Thu, 20 Oct 2022 22:05:22 +0800
Labels: app=nginx
pod-template-hash=7fb96c846b
Annotations: cni.projectcalico.org/containerID: 66626e89ebcb580eeef3f2e75d7d860fe14ee213458642f7b25a860e164ea9a3
cni.projectcalico.org/podIP: 100.66.195.18/32
cni.projectcalico.org/podIPs: 100.66.195.18/32
Status: Running
IP: 100.66.195.18
IPs:
IP: 100.66.195.18
Controlled By: ReplicaSet/my-nginx-7fb96c846b
Containers:
nginx:
Container ID: containerd://85c401a1bca6531519ad09b539ee57bb2b508b370d71053926a1df0b5421597e
Image: nginx:1.14.2
Image ID: docker.io/library/nginx@sha256:f7988fb6c02e0ce69257d9bd9cf37ae20a60f1df7563c3a2a6abe24160306b8d
Port: 80/TCP
Host Port: 0/TCP
State: Running
Started: Sat, 22 Oct 2022 11:27:59 +0800
Last State: Terminated
Reason: Unknown
Exit Code: 255
Started: Fri, 21 Oct 2022 11:10:13 +0800
Finished: Sat, 22 Oct 2022 11:27:01 +0800
Ready: True
Restart Count: 2
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-x77br (ro)
Conditions:
Type Status
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
kube-api-access-x77br:
Type: Projected (a volume that contains injected data from multiple sources)
TokenExpirationSeconds: 3607
ConfigMapName: kube-root-ca.crt
ConfigMapOptional: <nil>
DownwardAPI: true
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events: <none>
我们只要看Events
就好了~
可以查看状态和原因,可以去排查事故原因
Pod 状态
状态 | 描述 | 原因 |
---|---|---|
Pending | Pod已被Kubernetes系统接受,但尚未被调度到节点上运行 | Pod正在等待调度到节点上运行。可能是由于节点资源不足,或者Pod定义中的控制器正在等待其他Pod先启动。 |
Running | Pod正在正常运行 | Pod已被调度到节点上,并且容器正在运行。 |
Succeeded | Pod中的所有容器都已成功运行并已退出 | 所有容器都已成功完成,并且已达到其预期的状态。 |
Failed | Pod中的所有容器都已退出,并且至少有一个容器因错误而退出 | 所有容器都已退出,并且至少有一个容器已失败。 |
Unknown | 无法确定Pod的状态 | Kubernetes无法确定Pod的状态。可能是由于与Pod相关的节点(node)失去联系。 |
一般出现 Failed 的原因都是由于 容器运行异常退出或者是被系统终止掉了。
Pod 的重启策略
在 Kubernetes 中,可以为 pod 设置三种不同的重启策略:
- Always:无论其中的容器退出代码如何,pod 都将始终重新启动。
- OnFailure:仅当其中一个或多个容器以非零退出代码退出时,pod 才会重新启动。
- Never:即使其中一个或多个容器以非零退出代码退出,pod 也永远不会重新启动。
要为 pod 设置重启策略,需要在 pod 的 YAML 文件中指定 spec.restartPolicy
字段。例如,要将重启策略设置为 OnFailure
,可以使用以下 YAML:
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
restartPolicy: OnFailure
containers:
- name: my-container
image: my-image
Pod 中健康检查
在 Kubernetes 中,可以为 Pod 配置以下三种类型的健康检查:
- livenessProbe:检查容器是否正在运行。如果容器没有运行,则 kubelet 将根据 Pod 的重启策略重启容器。
- readinessProbe:检查容器是否已准备好接收流量。如果容器没有准备好,则 kube-proxy 将在其所在的节点上从 Service 的 Endpoint 中删除它。
- startupProbe:检查容器是否已经完成了启动过程。如果容器已经完成了启动过程,则 kubelet 将开始进行 livenessProbe 和 readinessProbe 检查。
要为容器配置这些检查,需要在 Pod 的 YAML 文件中为容器指定 livenessProbe
、readinessProbe
和 startupProbe
字段。例如,要为容器 my-container
配置 livenessProbe 和 readinessProbe,可以使用以下 YAML:
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
containers:
- name: my-container
image: my-image
livenessProbe:
tcpSocket:
port: 8080
initialDelaySeconds: 15
periodSeconds: 20
readinessProbe:
httpGet:
path: /healthz
port: 8080
httpHeaders:
- name: X-Custom-Header
value: Awesome
initialDelaySeconds: 5
periodSeconds: 10
在平常的使用中,建议对全部的服务同时设置 readiness 和 liveness 的健康检查。
删除pod
由于k8s的概念很多,删除需要指定概念
- 指定命名空间,不指定是默认
- 指定删除
pod
kubectl delete pod mypodName -n xxxNamespace
管理对象的两种方式
命令行指令
使用 kubectl
命令来创建和管理 kubernetes
对象
简单、高效快速但是功能有限,操作不容易追溯,多用于开发和调试。
声明式配置
kubernetes
使用 yaml
文件来描述 kubernetes
对象
声明式配置就好比申请表,学习难度大而且配置麻烦
好处是操作留痕迹,适合操作复杂的对象,多用于生产
yaml 语法介绍
- https://yaml.org/
YAML 语言创建于 2001 年,比 XML 晚了三年。XML 你应该知道吧,它是一种类似 HTML 的标签式语言,有很多繁文缛节。而 YAML 虽然在名字上模仿了 XML,但实质上与 XML 完全不同,更适合人类阅读,计算机解析起来也很容易。
YAML 是 JSON 的 超集,支持整数、浮点数、布尔、字符串、数组和对象等数据类型。也就是说,任何合法的 JSON 文档也都是 YAML 文档,如果你了解 JSON,那么学习 YAML 会容易很多。
yaml 语法
- 缩进代表上下级关系
- 缩进时使用空格,不要使用tab,通常使用2个空格
- 使用双引号,不要使用单引号
:
键值对的分隔符,前面不要有空格,后面要有空格-
数组的分隔符,前后都要有空格#
注释,后面要有空格|
多行文本,后面要有空格,后面可以有换行>
多行文本,后面要有空格---
yaml文件的分隔符,前后都要有空格
如何编写 yaml
第一个技巧其实前面已经说过了,就是 kubectl api-resources 命令,它会显示出资源对象相应的 API 版本和类型,比如 Pod 的版本是“v1”,Ingress 的版本是“networking.k8s.io/v1”,照着它写绝对不会错。
kubectl api-resources
第二个技巧,是命令 kubectl explain,它相当于是 Kubernetes 自带的 API 文档,会给出对象字段的详细说明,这样我们就不必去网上查找了。比如想要看 Pod 里的字段该怎么写,就可以这样:
kubectl explain pod
kubectl explain pod.metadata
kubectl explain pod.spec
kubectl explain pod.spec.containers
不过我们还可以让 kubectl 为我们“代劳”,生成一份“文档样板”,免去我们打字和对齐格式的工作。这第三个技巧就是 kubectl 的两个特殊参数 --dry-run=client
和 -o yaml
,前者是空运行,后者是生成 YAML 格式,结合起来使用就会让 kubectl 不会有实际的创建动作,而只生成 YAML 文件。
例如,想要生成一个 Pod 的 YAML 样板示例,可以在 kubectl run 后面加上这两个参数:
kubectl run ngx --image=nginx:alpine --dry-run=client -o yaml
就会生成一个绝对正确的 YAML 文件:
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: ngx
name: ngx
spec:
containers:
- image: nginx:alpine
name: ngx
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}
接下来你要做的,就是查阅对象的说明文档,添加或者删除字段来定制这个 YAML 了。
这个小技巧还可以再进化一下,把这段参数定义成 Shell 变量(名字任意,比如$do/$go
,这里用的是$out
),用起来会更省事,比如:
export out="--dry-run=client -o yaml"
kubectl run ngx --image=nginx:alpine $out
离线任务
我们在后面会知道 Kubernetes 中的离线任务意味着什么。
上次课讲 Pod 的时候我们运行了两个 Pod:Nginx 和 busybox,它们分别代表了 Kubernetes 里的两大类业务。一类是像 Nginx 这样长时间运行的“在线业务”,另一类是像 busybox 这样短时间运行的“离线业务”。
“在线业务”类型的应用有很多,比如 Nginx、Node.js、MySQL、Redis 等等,一旦运行起来基本上不会停,也就是永远在线。
而“离线业务”类型的应用也并不少见,它们一般不直接服务于外部用户,只对内部用户有意义,比如日志分析、数据建模、视频转码等等,虽然计算量很大,但只会运行一段时间。“离线业务”的特点是必定会退出,不会无期限地运行下去,所以它的调度策略也就与“在线业务”存在很大的不同,需要考虑运行超时、状态检查、失败重试、获取计算结果等管理事项。
“离线业务”也可以分为两种。一种是“临时任务”,跑完就完事了,下次有需求了说一声再重新安排;另一种是“定时任务”,可以按时按点周期运行,不需要过多干预。
对应到 Kubernetes 里,“临时任务”就是 API 对象 Job,“定时任务”就是 API 对象 CronJob,使用这两个对象你就能够在 Kubernetes 里调度管理任意的离线业务了。
如何使用 YAML 描述 Job
比如用 busybox 创建一个“echo-job”,命令就是这样的:
export out="--dry-run=client -o yaml" # 定义Shell变量
kubectl create job echo-job --image=busybox $out
会生成一个基本的 YAML 文件,保存之后做点修改,就有了一个 Job 对象:
apiVersion: batch/v1
kind: Job
metadata:
name: echo-job
spec:
template:
spec:
restartPolicy: OnFailure
containers:
- image: busybox
name: echo-job
imagePullPolicy: IfNotPresent
command: ["/bin/echo"]
args: ["hello", "world"]
你会注意到 Job 的描述与 Pod 很像,但又有些不一样,主要的区别就在“spec”字段里,多了一个 template 字段,然后又是一个“spec”,显得有点怪。
如果你理解了刚才说的面向对象设计思想,就会明白这种做法的道理。它其实就是在 Job 对象里应用了组合模式,template 字段定义了一个“应用模板”,里面嵌入了一个 Pod,这样 Job 就可以从这个模板来创建出 Pod。
而这个 Pod 因为受 Job 的管理控制,不直接和 apiserver 打交道,也就没必要重复 apiVersion 等“头字段”,只需要定义好关键的 spec,描述清楚容器相关的信息就可以了,可以说是一个“无头”的 Pod 对象。
为了辅助你理解,我把 Job 对象重新组织了一下,用不同的颜色来区分字段,这样你就能够很容易看出来,其实这个“echo-job”里并没有太多额外的功能,只是把 Pod 做了个简单的包装:
总的来说,这里的 Pod 工作非常简单,在 containers 里写好名字和镜像,command 执行 /bin/echo
,输出“hello world”。
不过,因为 Job 业务的特殊性,所以我们还要在 spec 里多加一个字段 restartPolicy
,确定 Pod 运行失败时的策略,OnFailure 是失败原地重启容器,而 Never 则是不重启容器,让 Job 去重新调度生成一个新的 Pod。
如何在 Kubernetes 里操作 Job
现在让我们来创建 Job 对象,运行这个简单的离线作业,用的命令还是 kubectl apply:
kubectl apply -f job.yml
查看:
kubectl get job
kubectl get pod
NAME COMPLETIONS DURATION AGE
echo-job 0/1 5s 5s
NAME READY STATUS RESTARTS AGE
echo-job-tl75m 0/1 Pending 0 5skubectl get job
kubectl get pod
NAME COMPLETIONS DURATION AGE
echo-job 0/1 5s 5s
NAME READY STATUS RESTARTS AGE
echo-job-tl75m 0/1 Pending 0 5s
可以看到,因为 Pod 被 Job 管理,它就不会反复重启报错了,而是会显示为 Completed 表示任务完成,而 Job 里也会列出运行成功的作业数量,这里只有一个作业,所以就是 1/1。
你还可以看到,Pod 被自动关联了一个名字,用的是 Job 的名字(echo-job)再加上一个随机字符串(pb5gh),这当然也是 Job 管理的“功劳”,免去了我们手工定义的麻烦,这样我们就可以使用命令 kubectl logs 来获取 Pod 的运行结果:
配置对象
在创建 Kubernetes 对象所对应的 yaml
文件中,需要配置的字段:
apiVersion
:Kubernetes API 版本Kind
:对象类别,例如Pod
、Deployment
metadata
:描述对象的元数据,包括一个 name 字符串、UID 和 可选的namespace
spec
:对象的配置
配置文件创建pod
我们或许可以用配置文件的方式去创建一个pod~
[root@k8s-master01 ~]# vim pod.yaml
[root@k8s-master01 ~]# kubectl apply -f pod.yaml
yaml创建pod格式
apiVersion: v1
kind: Pod # 资源类型
metadata:
labels:
run: myapp
name: myapp # pod名称
spec: # pod详细配置信息
containers: # 启动一个容器
- image: nginx # 启动nginx
name: mynginx
- image: tomcat:8.5.68
name: mytomcat
- image: redis
name: myredis
可能会出现pod状态处于ContainerCreating的情况,常见的原因之一是镜像拉取失败。
💡容器的创建详情查看如下:
kubectl describe pod mynginx
⚡ 展开查看详情
[root@k8s-master01 ~]# kubectl describe pod mynginx
Name: mynginx
Namespace: default
Priority: 0
Service Account: default
Node: k8s-master03/192.168.0.4
Start Time: Sat, 22 Oct 2022 13:20:17 +0800
Labels: run=mynginx
Annotations: cni.projectcalico.org/containerID: 9fc6db4dd24c4816b28be43c1f2907c89adea8fadb36fb49844fea42142671e7
cni.projectcalico.org/podIP: 100.66.195.25/32
cni.projectcalico.org/podIPs: 100.66.195.25/32
Status: Running
IP: 100.66.195.25
IPs:
IP: 100.66.195.25
Containers:
mynginx:
Container ID: containerd://69b25d59d551f94e8f7cc659ef3b740765e23673b60f45de7353cfbc13d52420
Image: nginx
Image ID: docker.io/library/nginx@sha256:5ffb682b98b0362b66754387e86b0cd31a5cb7123e49e7f6f6617690900d20b2
Port: <none>
Host Port: <none>
State: Running
Started: Sat, 22 Oct 2022 13:21:13 +0800
Ready: True
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-m6rqn (ro)
myredis:
Container ID: containerd://e72e35e2f7dda8d6108a89e98c41da32b4678eab31cf26c8406eeaee5e3ecc3c
Image: redis
Image ID: docker.io/library/redis@sha256:c95835a74c37b3a784fb55f7b2c211bd20c650d5e55dae422c3caa9c01eb39fa
Port: <none>
Host Port: <none>
State: Running
Started: Sat, 22 Oct 2022 13:21:47 +0800
Ready: True
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-m6rqn (ro)
Conditions:
Type Status
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
kube-api-access-m6rqn:
Type: Projected (a volume that contains injected data from multiple sources)
TokenExpirationSeconds: 3607
ConfigMapName: kube-root-ca.crt
ConfigMapOptional: <nil>
DownwardAPI: true
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 113s default-scheduler Successfully assigned default/mynginx to k8s-master03
Normal Pulling 112s kubelet Pulling image "nginx"
Normal Pulled 58s kubelet Successfully pulled image "nginx" in 54.707721222s
Normal Created 57s kubelet Created container mynginx
Normal Started 57s kubelet Started container mynginx
Normal Pulling 57s kubelet Pulling image "redis"
Normal Pulled 23s kubelet Successfully pulled image "redis" in 33.819467112s
Normal Created 23s kubelet Created container myredis
Normal Started 23s kubelet Started container myredis
可视化界面创建pod
注意
这个板块待补充~ 欢迎pr
pod日志
好像只有pod有日志把?
和docker的日志一样用法
我们查看pod日志:
kubectl logs mynginx
⚡ 可以加上 -f
追踪式日志
kubectl logs -f mynginx
pod - IP
⚡ 每个pod – k8s都会分配一个ip,使用下面命令查看:
kubectl get pod -owide
进入pod并修改pod
🗓️ 回忆我们docker修改容器内部
docker exec -it idName #/bin/bash
使用K8s进入pod命令:
和docker命令大致一样,注意后面有
–
kubectl exec -it mynginx -- /bin/bash
可视化界面
可以直接进去k8s的可视化界面进行修改~
多容器pod细节
提醒⚠️
在Kubernetes
中部署应用时,都是以pod
进行调度的,它们基本上是单个容器的包装或房子。从某种意义上说,容器的容器。 pod
是一个逻辑包装实体,用于在K8s
集群上执行容器。可以把每个pod
想象成一个透明的包装,为容器提供一个插槽。pod
是Kubernetes
最小的可部署单位。pod
是一组一个或多个容器,具有共享的存储/网络资源,以及如何运行容器的规范。因此,最简单地说,pod
是一个容器如何在Kubernetes
中“用起来”的机制。
pod是k8s的最小单元,容器包含在pod中,一个pod中有一个pause容器和若干个业务容器,而容器是单独的一个容器,简而言之,pod是一组容器的集合。
pod相当于逻辑主机,每个pod都有自己的ip地址
pod内的容器共享相同的ip和端口
默认情况下,每个容器的文件系统与其他容器完全隔离
pod是一组容器,一个pod也是可以部署两个甚至是多个容器
更多命令
更多命令:
# 查看全部
kubectl get all
# 重新部署
kubectl rollout restart deployment test-k8s
# 命令修改镜像,--record 表示把这个命令记录到操作历史中
kubectl set image deployment test-k8s test-k8s=ccr.ccs.tencentyun.com/k8s-tutorial/test-k8s:v2-with-error --record
# 暂停运行,暂停后,对 deployment 的修改不会立刻生效,恢复后才应用设置
kubectl rollout pause deployment test-k8s
# 恢复
kubectl rollout resume deployment test-k8s
# 输出到文件
kubectl get deployment test-k8s -o yaml >> app2.yaml
# 删除全部资源
kubectl delete all --all
遗留问题:
- 每次只能访问一个 pod,没有负载均衡自动转发到不同 pod
- 访问还需要端口转发
- Pod 重创后 IP 变了,名字也变了
END 链接
✴️版权声明 © :本书所有内容遵循CC-BY-SA 3.0协议(署名-相同方式共享)©