欢迎光临
我们一直在努力

k8spod管理知识点总结

目录

  • 一、命令式对象管理
    • 1.1 命名空间管理
    • 1.2 Pod 的创建与查看
    • 1.3 Pod 故障排查
    • 1.4 Pod 的删除
  • 二、kubectl 命令实操
    • 2.1 实验镜像准备
    • 2.2 用 dry-run 生成 yaml 文件
    • 2.3 常用管理命令
    • 2.4 滚动更新命令
    • 2.5 弹性伸缩命令
  • 三、利用 yaml 文件声明资源
    • 3.1 单 Pod 运行多容器
    • 3.2 暴露端口
    • 3.3 指定环境变量
    • 3.4 选择运行节点
    • 3.5 共享宿主机网络
    • 3.6 资源优先级 QoS
    • 3.7 容器重启规则
  • 四、Pod 的生命周期
    • 4.1 init 容器
    • 4.2 存活探针 livenessProbe
    • 4.3 就绪探针 readinessProbe

一、命令式对象管理

命令式对象管理是指直接通过 kubectl 命令操作集群中的资源对象,不依赖 yaml 文件。

命令分类

操作命令格式说明
查看 kubectl get <资源> 查看资源列表,-o wide 显示 IP 和所在节点
创建 kubectl run/create <资源> 命令式创建 Pod、Deployment 等
描述 kubectl describe <资源> 查看资源详细信息,包括事件
删除 kubectl delete <资源> 删除资源

1.1 命名空间管理

命名空间(Namespace)用来对集群资源做逻辑隔离。集群初始化后会自带 5 个命名空间:

[root@k8s-master ~]# kubectl get namespaces
NAME STATUS AGE
default Active 4h20m
kube-flannel Active 3h31m
kube-node-lease Active 4h20m
kube-public Active 4h20m
kube-system Active 4h20m

命名空间用途
default 默认命名空间,用户资源默认放这里
kube-system 集群核心组件(apiserver、controller-manager 等)
kube-public 公共资源,所有用户可读
kube-node-lease 节点心跳租约
kube-flannel 网络插件 flannel 的资源

创建命名空间后,kubectl get namespaces 中会出现新项:

[root@k8s-master ~]# kubectl create namespace timinglee
[root@k8s-master ~]# kubectl get namespaces
NAME STATUS AGE
default Active 4h22m
kube-flannel Active 3h32m
kube-node-lease Active 4h22m
kube-public Active 4h22m
kube-system Active 4h22m
timinglee Active 5s

删除命名空间:

[root@k8s-master ~]# kubectl delete namespaces timinglee
namespace "timinglee" deleted

删除命名空间会连同其中的所有资源一起删除,操作前要确认。

1.2 Pod 的创建与查看

Pod 是 Kubernetes 的最小调度单位。用 kubectl run 直接创建:

# 查看当前命名空间中的 pod
[root@k8s-master ~]# kubectl get pods -o wide
No resources found in default namespace.

# 创建 pod
[root@k8s-master ~]# kubectl run lee –image nginx:latest
pod/lee created

[root@k8s-master ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
lee 1/1 Running 0 25s 10.244.1.10 k8s-node1 <none> <none>

-o wide 会额外显示 pod 的 IP 和所在节点。本例中 pod 被调度到 k8s-node1,分配的集群 IP 是 10.244.1.10。

1.3 Pod 故障排查

镜像不存在时,pod 会停在 ImagePullBackOff 状态:

[root@k8s-master ~]# kubectl run error –image lee:v1
[root@k8s-master ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
error 0/1 ImagePullBackOff 0 38s 10.244.2.3 k8s-node2 <none> <none>
lee 1/1 Running 0 91s 10.244.1.10 k8s-node1 <none> <none>

用 kubectl describe 查看详细信息定位原因:

[root@k8s-master ~]# kubectl describe pods error
Name: error
Namespace: default
Node: k8s-node2/172.25.254.20
Status: Pending
IP: 10.244.2.3
Containers:
error:
Image: lee:v1
State: Waiting
Reason: ImagePullBackOff
Ready: False
Conditions:
Type Status
PodReadyToStartContainers True
Initialized True
Ready False
ContainersReady False
PodScheduled True
QoS Class: BestEffort
Events:
Type Reason Age From Message
—- —— —- —- ——-
Normal Scheduled 87s default-scheduler Successfully assigned default/error to k8s-node2
Warning Failed 28s (x2 over 65s) kubelet Failed to pull image "lee:v1": ... not found
Warning Failed 28s (x2 over 65s) kubelet Error: ErrImagePull
Normal BackOff 16s (x2 over 64s) kubelet Back-off pulling image "lee:v1"
Warning Failed 16s (x2 over 64s) kubelet Error: ImagePullBackOff
Normal Pulling 2s (x3 over 86s) kubelet Pulling image "lee:v1"

Pod 从创建到运行,以及拉镜像失败的路径如下:

#mermaid-svg-idCeFR1RsOJl3kCx{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-idCeFR1RsOJl3kCx .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-idCeFR1RsOJl3kCx .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-idCeFR1RsOJl3kCx .error-icon{fill:#552222;}#mermaid-svg-idCeFR1RsOJl3kCx .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-idCeFR1RsOJl3kCx .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-idCeFR1RsOJl3kCx .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-idCeFR1RsOJl3kCx .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-idCeFR1RsOJl3kCx .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-idCeFR1RsOJl3kCx .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-idCeFR1RsOJl3kCx .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-idCeFR1RsOJl3kCx .marker{fill:#333333;stroke:#333333;}#mermaid-svg-idCeFR1RsOJl3kCx .marker.cross{stroke:#333333;}#mermaid-svg-idCeFR1RsOJl3kCx svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-idCeFR1RsOJl3kCx p{margin:0;}#mermaid-svg-idCeFR1RsOJl3kCx .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-idCeFR1RsOJl3kCx .cluster-label text{fill:#333;}#mermaid-svg-idCeFR1RsOJl3kCx .cluster-label span{color:#333;}#mermaid-svg-idCeFR1RsOJl3kCx .cluster-label span p{background-color:transparent;}#mermaid-svg-idCeFR1RsOJl3kCx .label text,#mermaid-svg-idCeFR1RsOJl3kCx span{fill:#333;color:#333;}#mermaid-svg-idCeFR1RsOJl3kCx .node rect,#mermaid-svg-idCeFR1RsOJl3kCx .node circle,#mermaid-svg-idCeFR1RsOJl3kCx .node ellipse,#mermaid-svg-idCeFR1RsOJl3kCx .node polygon,#mermaid-svg-idCeFR1RsOJl3kCx .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-idCeFR1RsOJl3kCx .rough-node .label text,#mermaid-svg-idCeFR1RsOJl3kCx .node .label text,#mermaid-svg-idCeFR1RsOJl3kCx .image-shape .label,#mermaid-svg-idCeFR1RsOJl3kCx .icon-shape .label{text-anchor:middle;}#mermaid-svg-idCeFR1RsOJl3kCx .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-idCeFR1RsOJl3kCx .rough-node .label,#mermaid-svg-idCeFR1RsOJl3kCx .node .label,#mermaid-svg-idCeFR1RsOJl3kCx .image-shape .label,#mermaid-svg-idCeFR1RsOJl3kCx .icon-shape .label{text-align:center;}#mermaid-svg-idCeFR1RsOJl3kCx .node.clickable{cursor:pointer;}#mermaid-svg-idCeFR1RsOJl3kCx .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-idCeFR1RsOJl3kCx .arrowheadPath{fill:#333333;}#mermaid-svg-idCeFR1RsOJl3kCx .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-idCeFR1RsOJl3kCx .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-idCeFR1RsOJl3kCx .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-idCeFR1RsOJl3kCx .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-idCeFR1RsOJl3kCx .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-idCeFR1RsOJl3kCx .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-idCeFR1RsOJl3kCx .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-idCeFR1RsOJl3kCx .cluster text{fill:#333;}#mermaid-svg-idCeFR1RsOJl3kCx .cluster span{color:#333;}#mermaid-svg-idCeFR1RsOJl3kCx div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-idCeFR1RsOJl3kCx .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-idCeFR1RsOJl3kCx rect.text{fill:none;stroke-width:0;}#mermaid-svg-idCeFR1RsOJl3kCx .icon-shape,#mermaid-svg-idCeFR1RsOJl3kCx .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-idCeFR1RsOJl3kCx .icon-shape p,#mermaid-svg-idCeFR1RsOJl3kCx .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-idCeFR1RsOJl3kCx .icon-shape .label rect,#mermaid-svg-idCeFR1RsOJl3kCx .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-idCeFR1RsOJl3kCx .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-idCeFR1RsOJl3kCx .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-idCeFR1RsOJl3kCx :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

kubectl run lee–image nginx:latest

Scheduler 调度Scheduled → k8s-node1

kubelet 拉取镜像Pulling → 成功

容器启动Running 1/1

kubectl run error–image lee:v1

Scheduler 调度Scheduled → k8s-node2

镜像不存在ErrImagePull

ImagePullBackOff状态 Waiting, Ready False

describe 中的 Events 是排查问题的关键:Scheduled 表示调度成功,ErrImagePull / ImagePullBackOff 说明镜像拉取失败,通常是镜像名写错或镜像不存在。

1.4 Pod 的删除

# 删除单个 pod
[root@k8s-master ~]# kubectl delete pods error

# 删除当前命名空间下所有 pod
[root@k8s-master ~]# kubectl delete pods –all
pod "error" deleted from default namespace
pod "lee" deleted from default namespace


二、kubectl 命令实操

2.1 实验镜像准备

加载到本地并推送进 Harbor 仓库的 library 项目:

[root@k8s-master ~]# docker load -i myapp.tar.gz
[root@k8s-master ~]# docker tag timinglee/myapp:v1 reg.timinglee.org/library/myapp:v1
[root@k8s-master ~]# docker push reg.timinglee.org/library/myapp:v1
[root@k8s-master ~]# docker tag timinglee/myapp:v2 reg.timinglee.org/library/myapp:v2
[root@k8s-master ~]# docker push reg.timinglee.org/library/myapp:v2

2.2 用 dry-run 生成 yaml 文件

–dry-run=client -o yaml 可以在不真正创建资源的情况下,把资源的 yaml 定义输出到文件,再按需修改后 apply:

[root@k8s-master pod]# kubectl create deployment webcluster –image myapp:v1 –replicas 2 –dry-run=client -o yaml > webcluster.yml
[root@k8s-master pod]# vim webcluster.yml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: webcluster
name: webcluster
spec:
replicas: 2
selector:
matchLabels:
app: webcluster
template:
metadata:
labels:
app: webcluster
spec:
containers:
– image: myapp:v1
name: myapp

[root@k8s-master pod]# kubectl apply -f webcluster.yml
deployment.apps/webcluster created

yaml 中四个字段的含义:

字段含义
metadata.labels 资源的标签
spec.replicas 期望的 pod 数量
spec.selector.matchLabels 控制器通过该标签选择它管理的 pod
spec.template 创建 pod 的属性模板

2.3 常用管理命令

create:创建资源

[root@k8s-master ~]# kubectl create deployment webcluster –replicas 2 –image myapp:v1
deployment.apps/webcluster created
[root@k8s-master ~]# kubectl get deployments.apps
NAME READY UP-TO-DATE AVAILABLE AGE
webcluster 2/2 2 2 15s
[root@k8s-master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
webcluster-77c87d9946-28thm 1/1 Running 0 24s
webcluster-77c87d9946-vwrsq 1/1 Running 0 24s

# 删除
[root@k8s-master ~]# kubectl delete deployments.apps webcluster
deployment.apps "webcluster" deleted from default namespace
[root@k8s-master ~]# kubectl get pods
No resources found in default namespace.

由 Deployment 创建的 pod 命名带 pod-template-hash 后缀(如 77c87d9946),同一个 Deployment 下的 pod 使用相同的模板哈希。

edit:编辑资源

[root@k8s-master ~]# kubectl edit deployments.apps webcluster
replicas: 2 # 在编辑器中修改副本数

[root@k8s-master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
webcluster-77c87d9946-2cgr7 1/1 Running 0 36s
webcluster-77c87d9946-2wqn7 1/1 Running 0 103s

patch:打补丁修改单个字段

[root@k8s-master ~]# kubectl patch deployments.apps webcluster -p '{"spec":{"replicas":1}}'
deployment.apps/webcluster patched

[root@k8s-master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
webcluster-77c87d9946-2wqn7 1/1 Running 0 6m20s

expose:暴露服务

[root@k8s-master ~]# kubectl expose deployment webcluster –port 80 –target-port 80
service/webcluster exposed

[root@k8s-master ~]# kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 6h
webcluster ClusterIP 10.97.61.108 <none> 80/TCP 18s

[root@k8s-master ~]# kubectl describe svc webcluster
Name: webcluster
Selector: app=webcluster
Type: ClusterIP
IP: 10.97.61.108
Port: <unset> 80/TCP
TargetPort: 80/TCP
Endpoints: 10.244.1.11:80,10.244.5.10:80,10.244.5.9:80 + 1 more...

Service 通过 Selector(标签选择器)找到后端的 pod,访问 ClusterIP 时会轮询到不同的 pod:

[root@k8s-master ~]# curl 10.97.61.108/hostname.html
webcluster-77c87d9946-gh9v7
[root@k8s-master ~]# curl 10.97.61.108/hostname.html
webcluster-77c87d9946-m69wl
[root@k8s-master ~]# curl 10.97.61.108/hostname.html
webcluster-77c87d9946-4p4mz

多次 curl 返回不同的 pod 名,说明流量被分发到多个副本上。

logs:查看日志

[root@k8s-master ~]# kubectl logs pods/webcluster-77c87d9946-gh9v7
10.244.0.0 – – [20/Aug/2026:08:43:52 +0000] "GET /hostname.html HTTP/1.1" 200 28 "-" "curl/7.76.1" "-"

attach:挂接容器

# 交互式创建 pod
[root@k8s-master ~]# kubectl run -it testpod –image busybox:latest
/ # # ctrl+pq 退出

# 重新挂接到容器终端
[root@k8s-master ~]# kubectl attach pods/testpod -it
/ #

exec:在容器中执行命令

[root@k8s-master ~]# kubectl run testpod –image nginx:latest
[root@k8s-master ~]# kubectl exec -it pods/testpod -c testpod — /bin/bash
root@testpod:/#

exec 适合进容器做诊断,attach 是挂接到容器的主进程终端,两者场景不同。

cp:容器与主机间拷贝文件

# 容器 → 主机
[root@k8s-master ~]# kubectl cp testpod:/usr/share/nginx/html/index.html /mnt/test

# 主机 → 容器
[root@k8s-master ~]# echo timinglee > /mnt/index.html
[root@k8s-master ~]# kubectl cp /mnt/index.html testpod:/usr/share/nginx/html/index.html

[root@k8s-master ~]# curl 10.244.1.12
timinglee

label:管理标签

[root@k8s-master pod]# kubectl get pods –show-labels
NAME READY STATUS RESTARTS AGE LABELS
webcluster-9787d97f6-zl6q2 1/1 Running 0 6m57s app=webcluster,pod-template-hash=9787d97f6

# 删除标签(app- 表示删除 app 标签)
[root@k8s-master pod]# kubectl label pods webcluster-9787d97f6-zl6q2 app-
pod/webcluster-9787d97f6-zl6q2 unlabeled

# 添加标签
[root@k8s-master pod]# kubectl label pods webcluster-9787d97f6-zl6q2 app=webcluster
pod/webcluster-9787d97f6-zl6q2 labeled

标签是 Kubernetes 资源关联的基础:Service 靠标签找 Pod,控制器靠标签管理 Pod。删除标签后 pod 会脱离控制器的管理范围。

2.4 滚动更新命令

rollout status:查看更新状态

[root@k8s-master pod]# kubectl rollout status deployment webcluster
deployment "webcluster" successfully rolled out

rollout restart:重启应用

[root@k8s-master pod]# kubectl rollout restart deployment webcluster
deployment.apps/webcluster restarted

[root@k8s-master pod]# kubectl get pods
NAME READY STATUS RESTARTS AGE
webcluster-7bfd865747-jmhwl 1/1 Running 0 19s
webcluster-7bfd865747-qv2xt 0/1 Completed 0 21s
webcluster-9787d97f6-z7xv5 1/1 Running 0 1s
webcluster-9787d97f6-zl6q2 0/1 ContainerCreating 0 0s

restart 不是重启已有容器,而是用新的 pod 模板重新创建一批 pod。pod 名中的模板哈希从 77c87d9946 变成了 7bfd865747、9787d97f6,旧 pod 状态变为 Completed。

2.5 弹性伸缩命令

# 扩容到 4 个副本
[root@k8s-master pod]# kubectl scale deployment webcluster –replicas 4
deployment.apps/webcluster scaled
[root@k8s-master pod]# kubectl get pods
NAME READY STATUS RESTARTS AGE
webcluster-9787d97f6-bh796 1/1 Running 0 2s
webcluster-9787d97f6-bh8jd 1/1 Running 0 2s
webcluster-9787d97f6-z7xv5 1/1 Running 0 89s
webcluster-9787d97f6-zl6q2 1/1 Running 0 88s

# 缩容到 1 个副本
[root@k8s-master pod]# kubectl scale deployment webcluster –replicas 1
deployment.apps/webcluster scaled


三、利用 yaml 文件声明资源

命令式操作适合临时实验,正式的资源配置用 yaml 文件声明,便于版本管理。

3.1 单 Pod 运行多容器

一个 Pod 可以放多个容器,它们共享网络和存储。下面在 testpod 中同时运行 myapp 和 busybox 两个容器:

[root@k8s-master ~]# kubectl run testpod –image myapp:v1 –dry-run=client -o yaml > testpod.yaml
[root@k8s-master ~]# vim testpod.yaml
apiVersion: v1
kind: Pod
metadata:
labels:
run: testpod
name: testpod
spec:
containers:
– image: myapp:v1
name: myapp1
– image: busyboxplus:latest
name: busybox
command:
– /bin/sh
-c
sleep 10000

[root@k8s-master ~]# kubectl apply -f testpod.yaml
[root@k8s-master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
testpod 2/2 Running 0 2m41s

READY 2/2 表示两个容器都正常运行。进入 busybox 容器,用 127.0.0.1 访问同 Pod 内 myapp 的服务:

[root@k8s-master ~]# kubectl exec -it pods/testpod -c busybox — /bin/sh
/ # curl 127.0.0.1
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>

多容器共享网络栈,所以容器间用 localhost 就能互通。exec 时要通过 -c 指定进哪个容器。

3.2 暴露端口

在容器配置中声明端口映射,可以把 pod 的端口映射到宿主机上:

[root@k8s-master pod]# vim testpod.yaml
apiVersion: v1
kind: Pod
metadata:
labels:
run: testpod
name: testpod
spec:
containers:
– image: myapp:v1
name: myapp1
ports:
– name: http
containerPort: 80 # pod 内部容器端口
hostPort: 80 # pod 所在节点端口
protocol: TCP # 端口所用协议

[root@k8s-master pod]# kubectl apply -f testpod.yaml
[root@k8s-master pod]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
testpod 1/1 Running 0 3m33s 10.244.5.43 k8s-node2 <none> <none>

[root@k8s-master pod]# curl k8s-node2
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>

字段含义
name 端口名称
containerPort 容器内服务的端口
hostPort 映射到宿主机的端口
protocol 协议类型,一般 TCP

pod 运行在 k8s-node2 上,所以直接访问 k8s-node2 的 80 端口就能拿到业务页面。

3.3 指定环境变量

用 env 给容器传环境变量。下面用 mysql 和 phpmyadmin 两个容器演示:

[root@k8s-master pod]# vim mysql.yml
apiVersion: v1
kind: Pod
metadata:
labels:
run: mysql
name: mysql
spec:
containers:
– image: mysql:8.0
name: mysql8
env:
– name: MYSQL_ROOT_PASSWORD
value: lee

– image: phpmyadmin:latest
name: mysqladmin
env:
– name: PMA_ARBITRARY
value: "1"
ports:
– name: phpadminport
containerPort: 80
hostPort: 80
protocol: TCP

[root@k8s-master pod]# kubectl apply -f mysql.yml
[root@k8s-master pod]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
mysql 2/2 Running 0 36s 10.244.1.44 k8s-node1 <none> <none>

MYSQL_ROOT_PASSWORD 是 mysql 镜像要求的 root 密码变量,PMA_ARBITRARY 让 phpmyadmin 可以连接任意 mysql 服务器。

3.4 选择运行节点

默认由调度器决定 pod 跑在哪台节点。想指定节点,用 nodeSelector 按节点的标签匹配:

[root@k8s-master ~]# kubectl get nodes –show-labels
NAME STATUS ROLES AGE VERSION LABELS
k8s-master Ready control-plane 29h v1.35.7 ...,kubernetes.io/hostname=k8s-master,...
k8s-node1 Ready <none> 29h v1.35.7 ...,kubernetes.io/hostname=k8s-node1,...
k8s-node2 Ready <none> 24h v1.35.7 ...,kubernetes.io/hostname=k8s-node2,...

[root@k8s-master pod]# vim mysql.yml
spec:
nodeSelector:
kubernetes.io/hostname: k8s-node2 # 指定调度到 k8s-node2
containers:
...

[root@k8s-master pod]# kubectl apply -f mysql.yml
pod/mysql created
[root@k8s-master pod]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
mysql 0/2 ContainerCreating 0 11s <none> k8s-node2 <none> <none>

pod 被调度到了 k8s-node2,节点选择生效。nodeSelector 的值取自节点的标签,比如 kubernetes.io/hostname。

3.5 共享宿主机网络

hostNetwork: true 让 pod 直接使用宿主机网络栈,不再分配独立的 Pod IP:

[root@k8s-master pod]# vim testpod.yaml
apiVersion: v1
kind: Pod
metadata:
labels:
run: testpod
name: testpod
spec:
hostNetwork: true
containers:
– image: busybox:latest
name: busybox
command:
– /bin/sh
-c
sleep 10000

[root@k8s-master pod]# kubectl apply -f testpod.yaml
[root@k8s-master pod]# kubectl exec -it pods/testpod -c busybox — /bin/sh
/ # ifconfig
eth0 Link encap:Ethernet HWaddr 00:0C:29:E9:E3:90
inet addr:172.25.254.20 Bcast:172.25.254.255 Mask:255.255.255.0
...
flannel.1 Link encap:Ethernet HWaddr DE:5A:26:1C:E5:A0
inet addr:10.244.5.0 Bcast:0.0.0.0 Mask:255.255.255.255
...

容器里看到的 eth0 地址是宿主机 172.25.254.20,说明 pod 直接用了宿主机的网卡。

3.6 资源优先级 QoS

Kubernetes 根据容器是否设置 requests(期望值)和 limits(上限值),把 pod 划分为三个 QoS 等级。资源紧张时按优先级回收:

BestEffort:没有任何资源限制,优先级最低

[root@k8s-master pod]# kubectl describe pods testpod | grep "QoS Class:"
QoS Class: BestEffort

Burstable:设定了资源限制,但期望值和限制值不同,优先级次之

spec:
containers:
– image: busybox:latest
name: busybox
command:
– /bin/sh
-c
sleep 10000
resources:
limits:
cpu: 700m
memory: 200M
requests:
cpu: 500m
memory: 100M

[root@k8s-master pod]# kubectl describe pods testpod | grep "QoS Class:"
QoS Class: Burstable

Guaranteed:期望值和最大使用限制相同,优先级最高

spec:
containers:
– image: busybox:latest
name: busybox
command:
– /bin/sh
-c
sleep 10000
resources:
limits:
cpu: 500m
memory: 100M
requests:
cpu: 500m
memory: 100M

[root@k8s-master pod]# kubectl apply -f testpod.yaml
[root@k8s-master pod]# kubectl describe pods testpod | grep "QoS Class:"
QoS Class: Guaranteed

QoS 等级资源设置条件优先级
BestEffort 未设置任何 requests / limits 最低
Burstable requests 与 limits 不同 次之
Guaranteed requests 与 limits 相同 最高

优先级越高,节点资源不足时越不容易被驱逐。

3.7 容器重启规则

restartPolicy 决定容器退出后是否重启,有三种取值:

策略行为
Always 无论什么原因退出都会重新运行
OnFailure 非正常关闭(报错退出)才重启
Never 容器关闭后不重启

实验验证:在节点上用 docker rm -f 强制删除容器,观察 pod 的反应。

# restartPolicy: Always,容器被删除后会自动拉起
[root@k8s-master pod]# kubectl get pods -o wide -w
[root@k8s-node2 ~]# docker rm -f 3051d9de4c36

# restartPolicy: OnFailure,正常退出(sleep 命令跑完)后不重启
apiVersion: v1
kind: Pod
metadata:
labels:
run: testpod
name: testpod
spec:
hostNetwork: true
restartPolicy: OnFailure
containers:
– image: busybox:latest
name: busybox
command:
– /bin/sh
-c
sleep 30

# 等 30 秒让容器中的命令运行完成后再次观察

# restartPolicy: Never,容器关闭后不重启
apiVersion: v1
kind: Pod
metadata:
labels:
run: testpod
name: testpod
spec:
hostNetwork: true
restartPolicy: Never
containers:
– image: busybox:latest
name: busybox
command:
– /bin/sh
-c
sleep 30

[root@k8s-master pod]# kubectl get pods -o wide -w
[root@k8s-node2 ~]# docker rm -f 3051d9de4c36

容器退出后是否重启由 restartPolicy 决定:Always 无论什么原因都重新运行,OnFailure 只在非正常关闭时重启,Never 关闭后不再拉起。


四、Pod 的生命周期

Pod 从创建到销毁要经历初始化、运行、探针检查等阶段:

#mermaid-svg-h0C2ViuGnpaOXx1V{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-h0C2ViuGnpaOXx1V .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-h0C2ViuGnpaOXx1V .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-h0C2ViuGnpaOXx1V .error-icon{fill:#552222;}#mermaid-svg-h0C2ViuGnpaOXx1V .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-h0C2ViuGnpaOXx1V .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-h0C2ViuGnpaOXx1V .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-h0C2ViuGnpaOXx1V .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-h0C2ViuGnpaOXx1V .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-h0C2ViuGnpaOXx1V .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-h0C2ViuGnpaOXx1V .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-h0C2ViuGnpaOXx1V .marker{fill:#333333;stroke:#333333;}#mermaid-svg-h0C2ViuGnpaOXx1V .marker.cross{stroke:#333333;}#mermaid-svg-h0C2ViuGnpaOXx1V svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-h0C2ViuGnpaOXx1V p{margin:0;}#mermaid-svg-h0C2ViuGnpaOXx1V .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-h0C2ViuGnpaOXx1V .cluster-label text{fill:#333;}#mermaid-svg-h0C2ViuGnpaOXx1V .cluster-label span{color:#333;}#mermaid-svg-h0C2ViuGnpaOXx1V .cluster-label span p{background-color:transparent;}#mermaid-svg-h0C2ViuGnpaOXx1V .label text,#mermaid-svg-h0C2ViuGnpaOXx1V span{fill:#333;color:#333;}#mermaid-svg-h0C2ViuGnpaOXx1V .node rect,#mermaid-svg-h0C2ViuGnpaOXx1V .node circle,#mermaid-svg-h0C2ViuGnpaOXx1V .node ellipse,#mermaid-svg-h0C2ViuGnpaOXx1V .node polygon,#mermaid-svg-h0C2ViuGnpaOXx1V .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-h0C2ViuGnpaOXx1V .rough-node .label text,#mermaid-svg-h0C2ViuGnpaOXx1V .node .label text,#mermaid-svg-h0C2ViuGnpaOXx1V .image-shape .label,#mermaid-svg-h0C2ViuGnpaOXx1V .icon-shape .label{text-anchor:middle;}#mermaid-svg-h0C2ViuGnpaOXx1V .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-h0C2ViuGnpaOXx1V .rough-node .label,#mermaid-svg-h0C2ViuGnpaOXx1V .node .label,#mermaid-svg-h0C2ViuGnpaOXx1V .image-shape .label,#mermaid-svg-h0C2ViuGnpaOXx1V .icon-shape .label{text-align:center;}#mermaid-svg-h0C2ViuGnpaOXx1V .node.clickable{cursor:pointer;}#mermaid-svg-h0C2ViuGnpaOXx1V .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-h0C2ViuGnpaOXx1V .arrowheadPath{fill:#333333;}#mermaid-svg-h0C2ViuGnpaOXx1V .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-h0C2ViuGnpaOXx1V .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-h0C2ViuGnpaOXx1V .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-h0C2ViuGnpaOXx1V .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-h0C2ViuGnpaOXx1V .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-h0C2ViuGnpaOXx1V .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-h0C2ViuGnpaOXx1V .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-h0C2ViuGnpaOXx1V .cluster text{fill:#333;}#mermaid-svg-h0C2ViuGnpaOXx1V .cluster span{color:#333;}#mermaid-svg-h0C2ViuGnpaOXx1V div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-h0C2ViuGnpaOXx1V .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-h0C2ViuGnpaOXx1V rect.text{fill:none;stroke-width:0;}#mermaid-svg-h0C2ViuGnpaOXx1V .icon-shape,#mermaid-svg-h0C2ViuGnpaOXx1V .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-h0C2ViuGnpaOXx1V .icon-shape p,#mermaid-svg-h0C2ViuGnpaOXx1V .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-h0C2ViuGnpaOXx1V .icon-shape .label rect,#mermaid-svg-h0C2ViuGnpaOXx1V .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-h0C2ViuGnpaOXx1V .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-h0C2ViuGnpaOXx1V .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-h0C2ViuGnpaOXx1V :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

检测失败

正常

就绪

未就绪

Pod 创建

init 容器按顺序执行,全部成功才启动主容器

主容器启动Running

存活探针livenessProbe

kubelet 重启容器RestartCount +1

就绪探针readinessProbe

加入 Service Endpoints接收流量

从 Endpoints 移除不接收流量

4.1 init 容器

initContainers 在业务容器之前运行,按顺序逐个执行,全部成功后才启动主容器。适合做前置检查、初始化数据等。

[root@k8s-master pod]# kubectl run webserver –image myapp:v1 –dry-run=client -o yaml > init-example.yml
[root@k8s-master pod]# vim init-example.yml
apiVersion: v1
kind: Pod
metadata:
labels:
run: webserver
name: webserver
spec:
initContainers:
– name: busybox
image: busybox:latest
command:
– /bin/sh
-c
"until test -e /testfile;do echo wating for myservice; sleep 2;done"
containers:
– image: myapp:v1
name: webserver
restartPolicy: Always

[root@k8s-master pod]# kubectl apply -f init-example.yml

# 另一终端监控 pod 状态
[root@k8s-master pod]# watch -n 1 kubectl get pods -o wide

# init 容器会一直等待 /testfile 出现,此时主容器未启动
[root@k8s-master pod]# kubectl exec -it pods/webserver -c busybox — /bin/sh
/ # touch /testfile

touch /testfile 之后 init 容器的等待条件满足,主容器才开始创建。

4.2 存活探针 livenessProbe

存活探针用来判断容器是否还活着。没有存活探针时,进程死掉容器不会自动恢复:

[root@k8s-master pod]# kubectl apply -f livness-example.yaml

# 测试操作:停掉 nginx 进程
[root@k8s-master pod]# kubectl exec -it pods/webserver -c webserver — /bin/sh
# nginx -s stop

# pod 状态仍是 Running,但访问已经失败
[root@k8s-master pod]# curl 10.244.5.47
curl: (7) Failed to connect to 10.244.5.47 port 80: 拒绝连接

加了存活探针后,探针检测失败会触发容器重启:

apiVersion: v1
kind: Pod
metadata:
labels:
run: webserver
name: webserver
spec:
containers:
– image: myapp:v1
name: webserver
command: ["/bin/sh", "-c"]
args:
|
nginx -g "daemon off;"
sleep 10000
livenessProbe:
tcpSocket:
port: 80
initialDelaySeconds: 3
periodSeconds: 1
timeoutSeconds: 1
restartPolicy: Always

[root@k8s-master pod]# kubectl get pods -o wide -w

# 停掉 nginx 后,探针连续检测失败,容器被 kubelet 重启
[root@k8s-master pod]# kubectl exec -it pods/webserver -c webserver — /bin/sh
/ # nginx -s stop

[root@k8s-master pod]# curl 10.244.5.66
curl: (7) Failed to connect to 10.244.5.66 port 80: 拒绝连接
[root@k8s-master pod]# curl 10.244.5.66
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a> # 恢复

探针参数含义
tcpSocket.port 探测方式:TCP 连接指定端口
initialDelaySeconds 容器启动后延迟多久开始探测
periodSeconds 探测周期
timeoutSeconds 单次探测超时时间

nginx 停了之后,pod 先是连不上,过几秒探针发现异常自动重启容器,服务恢复。没有探针时同样的情况只能人工介入。

4.3 就绪探针 readinessProbe

就绪探针判断容器是否准备好接收流量。没有就绪探针时,只要容器 Running,Service 就会把流量转进来,即使业务实际不可用:

[root@k8s-master pod]# vim readness-example.yml
apiVersion: v1
kind: Pod
metadata:
labels:
run: webserver
name: webserver
spec:
containers:
– image: myapp:v1
name: webserver
restartPolicy: Always

apiVersion: v1
kind: Service
metadata:
labels:
run: webserver
name: webserver
spec:
ports:
– port: 80
protocol: TCP
targetPort: 80
selector:
run: webserver

[root@k8s-master pod]# kubectl apply -f readness-example.yml
[root@k8s-master pod]# kubectl describe svc webserver
Endpoints: 10.244.5.67:80

# 删除默认发布文件,业务已经 403
[root@k8s-master ~]# kubectl exec -it pods/webserver -c webserver — /bin/sh
/usr/share/nginx/html # rm -fr index.html

# Service 的 Endpoints 里 pod 还在,但访问返回 403
[root@k8s-master pod]# kubectl describe svc webserver
Endpoints: 10.244.5.67:80 # 还在
[root@k8s-master pod]# curl 10.102.162.217
<html>
<head><title>403 Forbidden</title></head>
<body bgcolor="white">
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx/1.12.2</center>
</body>
</html>

加了就绪探针后,只有探针检查通过(这里是对 /index.html 做 HTTP GET)pod 才会被加入 Endpoints:

apiVersion: v1
kind: Pod
metadata:
labels:
run: webserver
name: webserver
spec:
containers:
– image: myapp:v1
name: webserver
readinessProbe:
httpGet:
path: /index.html
port: 80
initialDelaySeconds: 3
periodSeconds: 2
timeoutSeconds: 1
restartPolicy: Always

apiVersion: v1
kind: Service
metadata:
labels:
run: webserver
name: webserver
spec:
ports:
– port: 80
protocol: TCP
targetPort: 80
selector:
run: webserver

[root@k8s-master pod]# kubectl apply -f readness-example.yml
[root@k8s-master pod]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
webserver 1/1 Running 0 7s 10.244.5.69 k8s-node2 <none> <none>

探针作用失败后果
livenessProbe 判断容器是否存活 重启容器
readinessProbe 判断容器是否就绪 从 Endpoints 摘除,不接收流量

存活探针管"要不要重启",就绪探针管"能不能接流量",两者职责不同,一般同时配置。

赞(0)
未经允许不得转载:171主机测评 » k8spod管理知识点总结
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址