❤️ 感谢关注,原文来自:https://www.cnblogs.com/StevenZengStudy/p/18402282
目录
- 1. 概念
- 1.1 什么是Pod
- 1.2 Pod管理容器
- 1.3 通过工作负载管理Pod
- 1.4 Pod的生命周期
- 1.5 静态pod
- 2. Pod的基础操作
- 2.1创建第一个Pod
- 2.2修改和更新Pod
- 2.3 进入Pod的容器
- 2.4删除Pod
- 3. 使用yaml文件配置Pod
- 3.1 使用pod的标签筛选
- 3.2 imagePullPolicy 的作用
- 3.3 restartPolicy 的作用
- RestartPolicy 补充实验
- 3.4 dnsPolicy 的作用
- 3.5 容器对外暴露端口设置
- 3.6 容器执行的命令及参数设置
- 3.7 容器中环境变量设置
- 3.8 在相同 Pod 中运行多个容器
- 3.9 Pod时区与宿主时区同步
- 补充:4.“kubectl apply”和“kubectl create”的区别
- 5. 参考文献
1. 概念
1.1 什么是Pod
- Pod 是在 Kubernetes 中创建和管理的最小的可部署的基础单元。
- Pod就像豌豆荚中包含了一组(一个或多个) 紧密协作的容器,这些容器共享存储和网络资源。 Pod 为容器提供了一个统一的上下文,确保它们在同一个宿主机上运行。你可以把 Pod 想象成一个“迷你计算机”,它不仅承载了运行的应用,还配置了网络接口、IP 地址、存储卷等资源。即使 Pod 内的容器相互独立运行,它们也通过共享的网络环境和文件系统实现紧密的协作。
- 除了应用程序容器,**Pod **可以在 Pod 启动期间运行的 init 容器实现容器环境初始化。还可以为正在运行的 Pod 注入临时容器对应用程序进行调试工作。
1.2 Pod管理容器
Pod 是容器的“宿主”,负责启动、运行和管理其中的容器, 可以将容器形成一个共同协作的服务单元。 Pod 中的容器在k8s的同一节点上并满足同时调度。容器间可以共享资源和依赖关系、相互通信以及协调终止的时间和方式。
Kubernetes 集群中的 Pod 主要有两种使用方式:
- 运行单个容器的 Pod 。 “单一容器的Pod ”模型是最常见的 Kubernetes 用例;在这种情况下,您可以将 Pod 视为单个容器的封装器; Kubernetes仅管理 Pod,而不是直接管理容器。
- 运行多个协同工作的容器的 Pod 。 Pod 可以封装由多个紧密耦合且需要共享资源的共置容器组成的应用程序。这些位于同一位置的容器形成了一个单一的内聚服务单元,例如,一个容器向外提供应用入口,而一个单独的sidecar容器会更新应用数据文件。 Pod 会将这些容器、存储资源和临时网络身份包装在一起作为一个单元进行管理。
1.3 通过工作负载管理Pod
在一般场景中,你不需要直接创建 Pod,即使是单个 Pod。这是因为 Pod 被设计为相对短暂的、一次性的实体。当 Pod 创建时(直接由你创建,或由控制器间接创建),新 Pod 会计划在集群中的节点上运行。 Pod 保留在该节点上,直到 Pod 完成执行、Pod 对象被删除、Pod 因缺乏资源而被驱逐或节点发生故障。
所以通常使用工作负载资源创建Pod, 以下是管理一个或多个 Pod 的工作负载资源的示例:
- Deployment : 部署一个或多个无状态的Pod;
- StatefulSet : 部署一个或多个有状态的Pod;
- DaemonSet : 部署在每一个节点的Pod;
- Job : 执行临时的、一次性任务的Pod;
- CronJob : 执行定时任务的Pod。
Pod 模板
工作负载资源的控制器根据Pod 模板创建和管理 Pod,而Pod模板是创建 Pod 的规则集,包含在Deployments 、 Jobs和DaemonSets等工作负载资源描述中。
创建 Pod 时,你可以在 Pod 模板中包含 Pod 中运行的容器的环境变量、启动命令、配置项等。
修改 Pod 模板或切换到新的 Pod 模板时,已存在的 Pod不会有直接影响。在更改工作负载资源的 Pod 模板,控制器会根据更新后模板创建新的替换 Pod, 而旧的Pod则进行消亡。
Pod 更新和更换
如上所述,当工作负载资源的 Pod 模板发生更改时,控制器会根据更新的模板创建新的 Pod,而不是更新或修补现有的 Pod。
但Kubernetes也不会阻止你直接管理 Pod。你可以直接更新正在运行的 Pod 的某些字段。然而,像patch和replace Pod 更新操作有一些限制:
- 有关 Pod 的大部分元数据都是不可变的。例如,您不能更改
namespace
、name
、uid
或creationTimestamp
字段;generation
领域是独一无二的。它只接受增加字段当前值的更新。 - 如果设置了
metadata.deletionTimestamp
,则不能将新条目添加到metadata.finalizers
列表中。 - Pod 更新不得更改除
spec.containers[*].image
、spec.initContainers[*].image
、spec.activeDeadlineSeconds
或spec.tolerations
以外的字段。对于spec.tolerations
,您只能添加新条目。
1.4 Pod的生命周期
Pod 遵循定义的生命周期,从Pending
阶段开始,如果至少一个主容器启动正常,则进入Running
阶段,然后根据 Pod 中是否有任何容器因失败终止,再判断进入Succeeded
还是Failed
阶段。
与单个容器一样,Pod 被认为是临时的实体(为任务而生,任务完成而亡)。 Pod 被创建,分配一个唯一的 ID ( UID ),并被调度到它们保留的节点上运行,直到终止(根据重启策略)或删除。如果节点故障,则在该节点上运行(或计划运行)的 Pod 会被标记为删除。控制平面将 Pod 标记为在超时后删除。
调度
Pod 在其生命周期中仅调度一次;将 Pod 分配给特定节点称为绑定,选择使用哪个节点的过程称为调度。一旦 Pod 被调度并绑定到节点,Kubernetes 就会尝试在该节点上运行该 Pod。 Pod 在该节点上运行,直到停止,或者直到 Pod终止;如果 Kubernetes 无法在所选节点上启动 Pod(例如,如果节点在 Pod 启动之前崩溃),则该特定 Pod 永远不会启动。
Pod的故障恢复
如果 Pod 中的某个容器发生故障,那么 Kubernetes 可能会根据重启策略尝试重新启动该特定容器。
然而,Pod 可能发生集群无法恢复的故障,在这种情况下,Kubernetes 不会尝试修复 Pod;相反,Kubernetes 会删除 Pod 并依赖其他组件来提供自动修复。
如果 Pod 被调度到某个节点,而该节点随后发生故障,则该 Pod 会被视为不健康,并且 Kubernetes 最终会删除该 Pod。同时由于缺乏资源或其他节点在维护中,Pod 将无法在驱逐中幸存。
在pod恢复中,Kubernetes 不保证新的pod会被安排到与被替换的旧 Pod 相同的节点。不过新的pod与旧 Pod 具有相同的名称(如.metadata.name
),但新的pod的.metadata.uid
与旧 Pod 不同。
Pod的生命阶段
Pod 的phase
的数量和含义受到严格保护,以下是phase
的可能值:
Value | 描述 |
Pending | Pod 已被 Kubernetes 集群接受,但一个或多个容器尚未设置并准备好运行。这包括 Pod 等待调度的时间以及通过网络下载容器映像所花费的时间。 |
Running | Pod 已绑定到节点,并且所有容器已创建。至少有一个容器仍在运行,或者正在启动或重新启动。 |
Succeeded | Pod 中的所有容器已成功终止,并且不会重新启动。 |
Failed | Pod 中的所有容器均已终止,并且至少有一个容器因故障而终止。也就是说,容器要么以非零状态退出,要么被系统终止,并且未设置为自动重新启动。 |
Unknown | Pod 中的所有容器均已终止,并且至少有一个容器因故障而终止。也就是说,容器要么以非零状态退出,要么被系统终止,并且未设置为自动重新启动。 |
容器状态
除了 Pod 整体的生命阶段之外,Kubernetes 还跟踪 Pod 内每个容器的状态。您可以使用容器生命周期挂钩(container lifecycle hooks)来触发事件以在容器生命周期中的某些点运行。
一旦kube-scheduler将 Pod 分配给 Node,kubelet 就会开始使用容器运行时(CRI)为该 Pod 创建容器。容器有三种可能的状态: Waiting
、 Running
和Terminated
。
以下每个状态的含义:
Value | 描述 |
| 如果容器既不处于 |
|
|
| 处于 |
Pod 如何处理容器问题
Kubernetes 使用 Pod spec
中定义的restartPolicy来管理 Pod 内的容器故障。该策略决定了 Kubernetes 如何对由于错误或其他原因而退出的容器做出反应,其顺序如下:
错误状态 | 处理策略 |
Initial crash | Kubernetes 尝试根据 Pod restartPolicy立即重新启动。 |
Repeated crashes | 在初始崩溃后,Kubernetes 对后续重新启动应用指数退避延迟,如restartPolicy中所述。这可以防止快速、重复的重新启动尝试导致系统过载。 |
CrashLoopBackOff | 这表示退避延迟机制( backoff delay)对于当前处于崩溃循环、失败和重复重启的容器有效。 |
Backoff reset | 如果容器成功运行一段时间(例如 10 分钟),Kubernetes 会重置退避延迟( backoff delay),将任何新的崩溃视为第一次崩溃。 |
容器重启策略
Pod 的spec
有一个restartPolicy
字段,其可能值包括 Always
、OnFailure
和 Never
。默认值是Always
。
可能值 | 描述 |
Always | 任何终止后自动重新启动容器。 |
OnFailure | 仅在容器因错误退出(非零退出状态)时重新启动容器。 |
Never | 不自动重新启动已终止的容器。 |
- 当 kubelet 根据重启策略处理容器重启时,这适用于在同一 Pod 内被替换容器并在同一节点上执行重启。 Pod 中的容器退出后,kubelet 以指数增加退避延迟( backoff delay)(10 秒、20 秒、40 秒……)重新启动它们,上限为 300 秒(5 分钟)。一旦容器执行 10 分钟且没有任何问题,kubelet 就会重置该容器的重启退避计时器。
- 不要将“重启 Pod 中的容器”与“重启 Pod” 相混淆。Pod不是一个进程,而是运行容器的环境。 Pod 会持续存在,直到它被删除了。
1.5 静态pod
静态 Pod 始终绑定到节点上的一个Kubelet,由 kubelet 守护进程直接管理,无需kube-apiserver观察它们。大多数 Pod 由控制平面(control-plane)管理,而对于静态 Pod,kubelet 直接监督每个静态 Pod(如果失败则重新启动它)。
静态 Pod 的主要用途是运行自托管的控制平面:换句话说,使用 kubelet 来监督各个控制平面组件(kube-apiserver, etcd, kube-scheduler, kube-controller-manager)。
kubelet 会自动尝试在 Kubernetes API 服务器上为每个静态 Pod 创建镜像 Pod (Mirror Pod)。这意味着节点上运行的 Pod 在 API 服务器上可见,但无法通过Api进行控制。
2. Pod的基础操作
2.1创建第一个Pod
创建一个名称为 hcie 的 namespace:
kubectl create namespace hcie
- 思考:尝试使用命令“kubectl create namespace HCIE”测试是否能够创出响应的namespace?
[root@k8s-master3 ~]# kubectl create namespace HCIE
The Namespace "HCIE" is invalid: metadata.name: Invalid value: "HCIE": a lowercase RFC 1123 label must consist of lower case alphanumeric characters or '-', and must start and end with an alphanumeric character (e.g. 'my-name', or '123-abc', regex used for validation is '[a-z0-9]([-a-z0-9]*[a-z0-9])?')
- 说明:命名规范需要符合
RFC 1123
规范,仅支持小写、数字和中线
查看当前系统的 namespace
[root@k8s-master3 ~]# kubectl get namespaces
NAME STATUS AGE
default Active 2d7h
hcie Active 47s
kube-node-lease Active 2d7h
kube-public Active 2d7h
kube-system Active 2d7h
使用“kubectl run NAME”命令创建一个名称为 nginx 的 Pod,镜像使用的为 nginx:1.21:
[root@k8s-master3 ~]# kubectl run nginx --image=swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/nginx:1.21
pod/nginx created
使用命令“kubectl get pod”列出命名空间 default 中,当前的 Pod:
[root@k8s-master3 ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx 1/1 Running 0 28s
使用命令“kubectl describe pod nginx”列出 Pod 的详细信息:
[root@k8s-master3 ~]# kubectl describe pod
Name: nginx
Namespace: default
Priority: 0
Service Account: default
Node: k8s-worker2/10.10.0.5
Start Time: Sun, 21 Jul 2024 21:53:40 +0800
Labels: run=nginx
Annotations: cni.projectcalico.org/containerID: 70455ae930d9e9d79e0c69b168ed0fe603f99c99dd3a33a10e7fd99b3c876c4c
cni.projectcalico.org/podIP: 172.16.126.10/32
cni.projectcalico.org/podIPs: 172.16.126.10/32
Status: Running
IP: 172.16.126.10
IPs:
IP: 172.16.126.10
Containers:
nginx:
Container ID: containerd://52b2123ecd63bd3879d0cc1991f18a6b48f224216e3d5c64a4d4c8bd0b324f69
Image: swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/nginx:1.21
Image ID: swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/nginx@sha256:25dedae0aceb6b4fe5837a0acbacc6580453717f126a095aa05a3c6fcea14dd4
Port: <none>
Host Port: <none>
State: Running
Started: Sun, 21 Jul 2024 21:53:52 +0800
Ready: True
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-s4kx6 (ro)
Conditions:
Type Status
PodReadyToStartContainers True
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
kube-api-access-s4kx6:
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 25s default-scheduler Successfully assigned default/nginx to k8s-worker2
Normal Pulling 25s kubelet Pulling image "swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/nginx:1.21"
Normal Pulled 15s kubelet Successfully pulled image "swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/nginx:1.21" in 9.847s (9.847s including waiting)
Normal Created 15s kubelet Created container nginx
Normal Started 14s kubelet Started container nginx
⚠️ 说明:当前 Pod 运行在
Node:k8s-worker2/10.10.0.5
 
- ❓ 思考:“Conditions”字段表示什么意思?
Conditions:
Type Status
PodReadyToStartContainers True # Pod 沙箱已成功创建并配置网络。
Initialized True # 所有初始化容器已成功完成。
Ready True # Pod 能够服务请求,并且应该添加到所有匹配服务的负载均衡池中。
ContainersReady True # Pod 中的所有容器都已准备就绪。
PodScheduled True # Pod 已被调度到节点。
使用 YAML 文件进行 Pod 的创建,可以使用“--dry-run”仅打印向 kubernetes 发送的内容,而不真正执行,同时使用“-o”可以指定输出的格式:
[root@k8s-master3 ~]# kubectl run nginx1 --dry-run -o yaml --image=swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/nginx:1.21 >> deployment-nginx.yaml
W0721 22:10:20.060817 2486 helpers.go:704] --dry-run is deprecated and can be replaced with --dry-run=client.
编辑nginx.yaml内容
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: nginx1
name: nginx1
spec:
containers:
- image: swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/nginx:1.21
name: nginx1
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}
借助生成的 YAML 文件,创建一个新的 Pod:
[root@k8s-master3 ~]# kubectl create -f nginx.yaml
Error from server (AlreadyExists): error when creating "deployment-nginx.yaml": pods "nginx1" already exists
- ❓ 思考:产生报错的原因是什么?该如何处理?
- 因为pod在同一个namespace内是唯一,所以不允许重复创建pod,需要把原来的pod删除,或者pod改名。
- 也可以使用apply或者replace,检查pod配置,如有更新则更新pod。
[root@k8s-master3 ~]# kubectl apply -f deployment-nginx.yaml
pod/nginx1 configured
- ❓ 思考:如何将该 Pod 创建到命名空间 hcie 中?
- kubectl run 加
-n NAMESPACE
指定命名空间 - 也可以在yaml的
.metadata.namespace
字段指定
2.2修改和更新Pod
使用命令“kubectl edit”将新创建出的 Pod 的镜像修改为“nginx:latest”:
[root@k8s-master3 ~]# kubectl edit pod nginx2 -n hcie
...
- image: swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/nginx:latest
- ❓ 思考:如何判断修改是否生效?
kubectl get pod
显示修改后无法启动,原因是无法获取该镜像nginx:latest
[root@k8s-master3 ~]# kubectl get pod -n hcie -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx2 0/1 CrashLoopBackOff 0 3m8s 172.16.126.11 k8s-worker2 <none> <none>
修改成nginx:stable,重新部署pod成功:
[root@k8s-master3 ~]# k get pod -n hcie -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx2 1/1 Running 1 (2m52s ago) 4m51s 172.16.126.11 k8s-worker2 <none> <none>
[root@k8s-master3 ~]# k describe pod nginx2 -n hcie
Name: nginx2
Namespace: hcie
...
Containers:
nginx2:
Container ID: containerd://261aed489e5be161851f82b76851e2cf81c5e4be6478a841c4ca8974f9c13b7c
Image: swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/nginx:stable
Image ID: swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/nginx@sha256:46de27bdbc70956c55c447f374bfdd3624a299701099fbdf61ad2f7c3f1ba894
2.3 进入Pod的容器
使用命令“kubectl exec”登入到容器中:
[root@k8s-master3 ~]# kubectl exec -it nginx2 -n hcie -- /bin/bash
root@nginx2:/# cat /etc/hostname
nginx2
2.4删除Pod
使用命令“kubectl delete”将创建的 Pod 删除:
# 命令式删除
[root@k8s-master3 ~]# kubectl delete pod nginx
pod "nginx" deleted
# 声明式删除
[root@k8s-master3 ~]# kubectl delete -f deployment-nginx.yaml
pod "nginx1" deleted
3. 使用yaml文件配置Pod
3.1 使用pod的标签筛选
创建三个 YAML,分别命名为 nginx1.yaml、nginx1.yaml 和nginx3.yaml
kubectl run nginx -o yaml --image=nginx:1.21 --dry-run=client > nginx1.yaml
kubectl run nginx -o yaml --image=nginx:1.21 --dry-run=client > nginx2.yaml
kubectl run nginx -o yaml --image=nginx:1.21 --dry-run=client > nginx3.yaml
修改三个 YAML,生成不同标签的 Pod
将 nginx1 做以下修改:
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
app: nginx1
name: nginx1
namespace: hcie
spec:
containers:
- image: nginx:1.21
name: nginx
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}
将 nginx2 做以下修改:
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
app: nginx2
name: nginx2
namespace: hcie
spec:
containers:
- image: nginx:1.21
name: nginx
resources: {}
dnsPolicy: ClusterFir st
restartPolicy: Alw ays
status: {}
将 nginx3 做以下修改:
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
app: nginx3
name: nginx3
spec:
containers:
- image: nginx:1.21
name: nginx
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}
创建pod
[root@k8s-master3 ~]# kubectl apply -f nginx1.yaml
pod/nginx1 created
[root@k8s-master3 ~]# kubectl apply -f nginx2.yaml
pod/nginx2 created
[root@k8s-master3 ~]# kubectl apply -f nginx3.yaml
pod/nginx3 created
通过label对pod进行筛选
#查看默认ns的pod
[root@k8s-master3 ~]# kubectl get pods -l app
NAME READY STATUS RESTARTS AGE
nginx3 1/1 Running 0 30s
#查看hcie命名空间的pod
[root@k8s-master3 ~]# kubectl get pods -l app -n hcie
NAME READY STATUS RESTARTS AGE
nginx1 1/1 Running 0 40s
nginx2 1/1 Running 0 38s
# 带有app=nginx1的pod
[root@k8s-master3 ~]# kubectl get pods -l app -n hcie -l app=nginx1
NAME READY STATUS RESTARTS AGE
nginx1 1/1 Running 0 48s
# 除了app=nginx1的pod
[root@k8s-master3 ~]# kubectl get pods -l app -n hcie -l app!=nginx1
NAME READY STATUS RESTARTS AGE
nginx2 1/1 Running 0 48s
- ❓ 思考:以上对比能体现出标签有什么作用?
- 可以,对pod进行筛选过滤
- ❓ 思考:命名空间是否能后隔离标签?
- 命名空间可以隔离标签
3.2 imagePullPolicy 的作用
将三个 YAML 文件的 imagePullPolicy 策略分别修改为 Always、IfNotPresent 和 Never,同时将镜像修改为 nginx:1.18。
说明:使用“kubectl delete -f nginx1.yaml”、“kubectl delete -f nginx2.yaml”和“kubectl delete -f nginx3.yaml”删除上实验中创建的 Pod。
将 nginx1.yaml 做以下修改:
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
app: nginx1
name: nginx1
namespace: hcie
spec:
containers:
- image: swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/nginx:1.18.0
imagePullPolicy: Always
name: nginx
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}
将 nginx2.yaml 做以下修改:
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
app: nginx2
name: nginx2
namespace: hcie
spec:
containers:
- image: swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/nginx:1.18.0
imagePullPolicy: IfNotPresent
name: nginx
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}
将 nginx3.yaml 做以下修改:
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
app: nginx3
name: nginx3
spec:
containers:
- image: swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/nginx:1.18.0
imagePullPolicy: Never
name: nginx
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}
按以下顺序重新创建三个 Pod:(注意:为了能看到效果,nginx2 需等待 nginx1 创建完成后再创建)
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 3m15s default-scheduler Successfully assigned default/nginx3 to k8s-worker2
Warning ErrImageNeverPull 2m31s (x6 over 3m15s) kubelet Container image "swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/nginx:1.18.0" is not present with pull policy of Never
Warning Failed 2m31s (x6 over 3m15s) kubelet Error: ErrImageNeverPull
Normal Pulled 2m16s kubelet Container image "swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/nginx:1.18.0" already present on machine
Normal Created 2m16s kubelet Created container nginx
Normal Started 2m15s kubelet Started container nginx
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 108s default-scheduler Successfully assigned hcie/nginx1 to k8s-worker2
Normal Pulling 107s kubelet Pulling image "swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/nginx:1.18.0"
Normal Pulled 98s kubelet Successfully pulled image "swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/nginx:1.18.0" in 9.296s (9.296s including waiting)
Normal Created 98s kubelet Created container nginx
Normal Started 98s kubelet Started container nginx
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 107s default-scheduler Successfully assigned hcie/nginx2 to k8s-worker1
Normal Pulling 106s kubelet Pulling image "swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/nginx:1.18.0"
Normal Pulled 97s kubelet Successfully pulled image "swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/nginx:1.18.0" in 9.03s (9.03s including waiting)
Normal Created 97s kubelet Created container nginx
Normal Started 97s kubelet Started container nginx
- ❓ 思考:对比三个事件输出描述:
- nginx1构建时总会拉取镜像
- nginx2构建时,当本地没有镜像会拉取镜像
- nginx3默认不会拉取镜像,所以第一次构建失败,当nginx2构建时下载了镜像,nginx3会自动检测,再构建成功。
.spec.imagePullPolicy
中不同的策略:
参数 | 描述 |
IfNotPresent | 只有当镜像在本地不存在时才会拉取。
如果你省略了 imagePullPolicy 字段,并且你为容器镜像指定了摘要, 那么 imagePullPolicy 会自动设置为 IfNotPresent。 |
Always | 每当 kubelet 启动一个容器时,kubelet 会查询容器的镜像仓库, 将名称解析为一个镜像摘要。 如果 kubelet 有一个容器镜像,并且对应的摘要已在本地缓存,kubelet 就会使用其缓存的镜像; 否则,kubelet 就会使用解析后的摘要拉取镜像,并使用该镜像来启动容器。 |
Never | kubelet 不会尝试获取镜像。如果镜像已经以某种方式存在本地, kubelet 会尝试启动容器;否则,会启动失败。 更多细节见提前拉取镜像。 |
删除 nginx3 和 nginx1,再次重新创建,并再次对比输出的事件:
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 2s default-scheduler Successfully assigned default/nginx3 to k8s-worker2
Normal Pulled 1s kubelet Container image "swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/nginx:1.18.0" already present on machine
Normal Created 1s kubelet Created container nginx
Normal Started 1s kubelet Started container nginx
- 本节点已经存在镜像,nginx3直接使用镜像创建。
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 6s default-scheduler Successfully assigned hcie/nginx1 to k8s-worker2
Normal Pulling 5s kubelet Pulling image "swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/nginx:1.18.0"
Normal Pulled 4s kubelet Successfully pulled image "swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/nginx:1.18.0" in 452ms (452ms including waiting)
Normal Created 4s kubelet Created container nginx
Normal Started 4s kubelet Started container nginx
- nginx1使用缓存,比第一次部署速度快。
3.3 restartPolicy 的作用
三个 YAML 文件中的 imagePullPolicy 策略修改为 IfNotPresent,并删除上实验中创建的三个 Pod。
将 nginx1 做以下修改:(注意加粗斜体的内容)
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
app: nginx1
name: nginx1
namespace: hcie
spec:
containers:
- image: swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/nginx:1.18.0
imagePullPolicy: IfNotPresent
name: nginx
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}
将 nginx2.yaml 做以下修改:(注意加粗斜体的内容)
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
app: nginx2
name: nginx2
namespace: hcie
spec:
containers:
- image: swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/nginx:1.18.0
imagePullPolicy: IfNotPresent
name: nginx
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: OnFailure
status: {}
将 nginx3.yaml做以下修改:(注意加粗斜体的内容)
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
app: nginx3
name: nginx3
spec:
containers:
- image: swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/nginx:1.18.0
imagePullPolicy: IfNotPresent
name: nginx
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Never
status: {}
使用修改的 YAML 文件重新创建三个 Pod。
删除原pod
[root@k8s-master3 ~]# kubectl delete pod nginx3
pod "nginx3" deleted
[root@k8s-master3 ~]# kubectl delete pod nginx2 -n hcie
pod "nginx2" deleted
[root@k8s-master3 ~]# kubectl delete pod nginx1 -n hcie
pod "nginx1" deleted
重建pod
[root@k8s-master3 hcie]# kubectl apply -f nginx1.yaml
pod/nginx1 created
[root@k8s-master3 hcie]# kubectl apply -f nginx2.yaml
pod/nginx2 created
[root@k8s-master3 hcie]# kubectl apply -f nginx3.yaml
pod/nginx3 created
在容器中分别执行“nginx -s stop”命令:
[root@k8s-master3 hcie]# kubectl exec -it nginx1 -n hcie -- nginx -s stop
2024/07/22 02:14:38 [notice] 30#30: signal process started
[root@k8s-master3 hcie]# kubectl exec -it nginx2 -n hcie -- nginx -s stop
2024/07/22 02:14:47 [notice] 30#30: signal process started
[root@k8s-master3 hcie]# kubectl exec -it nginx3 -- nginx -s stop
2024/07/22 02:14:52 [notice] 30#30: signal process started
⚠️ 说明:命令“nginx -s stop”用来停止 nginx 服务,由于容器是为任务而生的,因此,停止nginx 服务后,容器也会随之停止。
然后查看各个容器的状态:
[root@k8s-master3 hcie]# kubectl get pod -A
NAMESPACE NAME READY STATUS RESTARTS AGE
default nginx3 0/1 Completed 0 86s
hcie nginx1 1/1 Running 1 (27s ago) 91s
hcie nginx2 0/1 Completed 0 88s
使用“kubectl describe”命令查看容器的退出码(Exit Code):
[root@k8s-master3 hcie]# kubectl describe pods nginx3 |grep "Exit Code"
Exit Code: 0
[root@k8s-master3 hcie]# kubectl describe pods nginx2 -n hcie |grep "Exit Code"
Exit Code: 0
[root@k8s-master3 hcie]# kubectl describe pods nginx1 -n hcie |grep "Exit Code"
Exit Code: 0
- ❓ 思考:为什么 nginx1 重启了,而 nginx2 和 nginx3 没有重启?nginx2 什么条件下才会重启?
- nginx1-3都是正常退出的,根据策略nginx2-3不会重启,只要退出代码不为0,nginx2才会重启。
- 策略解释参考:容器重启策略
RestartPolicy 补充实验
创建三个退出状态的pod,根据不同的重启策略,观察不同策略的效果。
1. 准备 Pod 配置文件
创建一个 YAML 文件 pod-restart-policy.yaml
,定义不同 restartPolicy
的 Pod:
apiVersion: v1
kind: Pod
metadata:
name: always-pod
spec:
restartPolicy: Always
containers:
- name: busybox
image: busybox
command: ["sleep", "60"]
---
apiVersion: v1
kind: Pod
metadata:
name: onfailure-pod
spec:
restartPolicy: OnFailure
containers:
- name: busybox
image: busybox
command: ["sh", "-c", "exit 1"]
---
apiVersion: v1
kind: Pod
metadata:
name: never-pod
spec:
restartPolicy: Never
containers:
- name: busybox
image: busybox
command: ["sleep", "60"]
2. 创建 Pods
使用 kubectl
创建三个 Pods:
kubectl apply -f pod-restart-policy.yaml
3. 观察 Pods 状态
使用以下命令查看详细信息,包括日志和事件:
Pod1的日志:
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 49s default-scheduler Successfully assigned default/always-pod to k8s-worker1
Normal Pulled 47s kubelet Container image "swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/library/busybox:1.28" already present on machine
Normal Created 47s kubelet Created container busybox
Normal Started 47s kubelet Started container busybox
Pod2的日志:
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 116s default-scheduler Successfully assigned default/onfailure-pod to k8s-worker2
Normal Pulled 21s (x5 over 114s) kubelet Container image "swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/library/busybox:1.28" already present on machine
Normal Created 21s (x5 over 114s) kubelet Created container busybox
Normal Started 21s (x5 over 113s) kubelet Started container busybox
Warning BackOff 5s (x10 over 111s) kubelet Back-off restarting failed container busybox in pod onfailure-pod_default(5694fe99-f1b8-4ea6-9579-c9d4cbf18b29)
Pod3的日志:
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 95s default-scheduler Successfully assigned default/never-pod to k8s-master1
Normal Pulled 94s kubelet Container image "swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/library/busybox:1.28" already present on machine
Normal Created 94s kubelet Created container busybox
Normal Started 94s kubelet Started container busybox
使用以下命令查看 Pod 的状态和重启情况:
[root@k8s-master3 hcie]# kubectl get pod
NAME READY STATUS RESTARTS AGE
always-pod 1/1 Running 1 (24s ago) 86s
never-pod 0/1 Completed 0 86s
onfailure-pod 0/1 CrashLoopBackOff 3 (38s ago) 86s
- 总结:与策略描述一致。
3.4 dnsPolicy 的作用
修改yaml配置:
Nginx1手动配置dns服务
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
app: nginx1
name: nginx1
namespace: hcie
spec:
containers:
- image: swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/nginx:1.18.0
imagePullPolicy: IfNotPresent
name: nginx
resources: {}
dnsPolicy: None
dnsConfig:
nameservers: ["192.168.1.1","192.168.1.2"]
restartPolicy: Always
status: {}
Nginx2使用宿主机dns服务
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
app: nginx2
name: nginx2
namespace: hcie
spec:
containers:
- image: swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/nginx:1.18.0
imagePullPolicy: IfNotPresent
name: nginx
resources: {}
dnsPolicy: Default
restartPolicy: OnFailure
status: {}
Nginx3使用集群dns插件
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
app: nginx3
name: nginx3
namespace: hcie
spec:
containers:
- image: swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/nginx:1.18.0
imagePullPolicy: IfNotPresent
name: nginx
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Never
status: {}
删除原pod
kubectl delete -f nginx1.yaml
kubectl delete -f nginx2.yaml
kubectl delete -f nginx3.yaml
使用修改后的 YAML 文件分别创建三个 Pod。
[root@k8s-master3 hcie]# kubectl apply -f nginx1.yaml
pod/nginx1 created
[root@k8s-master3 hcie]# kubectl apply -f nginx2.yaml
pod/nginx2 created
[root@k8s-master3 hcie]# kubectl apply -f nginx3.yaml
pod/nginx3 created
使用以下命令查看 Pod 的 DNS 配置:
[root@k8s-master3 hcie]# kubectl exec -it nginx3 -n hcie -- cat /etc/resolv.conf
search hcie.svc.cluster.com svc.cluster.com cluster.com
nameserver 10.245.0.254
options ndots:5
[root@k8s-master3 hcie]# kubectl exec -it nginx2 -n hcie -- cat /etc/resolv.conf
nameserver 8.8.8.8
nameserver 114.114.114.114
[root@k8s-master3 hcie]# kubectl exec -it nginx1 -n hcie -- cat /etc/resolv.conf
nameserver 192.168.1.1
nameserver 192.168.1.2
在 nginx2 所在的宿主机上查看 DNS 配置:
[root@k8s-master3 hcie]# cat /etc/resolv.conf
nameserver 8.8.8.8
nameserver 114.114.114.114
然后查找 10.245.0.254是谁的地址?
[root@k8s-master3 hcie]# kubectl get service -A |grep 254
kube-system coredns-coredns ClusterIP 10.245.0.254 <none> 53/UDP,53/TCP 20h
coredns详细信息
[root@k8s-master3 hcie]# kubectl describe service -n kube-system coredns-coredns
Name: coredns-coredns
Namespace: kube-system
Labels: app.kubernetes.io/instance=coredns
app.kubernetes.io/managed-by=Helm
app.kubernetes.io/name=coredns
helm.sh/chart=coredns-1.13.8
k8s-app=coredns
kubernetes.io/cluster-service=true
kubernetes.io/name=CoreDNS
Annotations: meta.helm.sh/release-name: coredns
meta.helm.sh/release-namespace: kube-system
Selector: app.kubernetes.io/instance=coredns,app.kubernetes.io/name=coredns,k8s-app=coredns
Type: ClusterIP
IP Family Policy: SingleStack
IP Families: IPv4
IP: 10.245.0.254
IPs: 10.245.0.254
Port: udp-53 53/UDP
TargetPort: 53/UDP
Endpoints: 172.16.159.138:53
Port: tcp-53 53/TCP
TargetPort: 53/TCP
Endpoints: 172.16.159.138:53
Session Affinity: None
Events: <none>
测试dns解析
# 运行测试容器
[root@k8s-master3 hcie]# kubectl run -it --image=swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/library/busybox:1.28 test -- sleep 3600 &
# 进入终端
[root@k8s-master3 ~]# kubectl exec -it test -- /bin/sh
/ # nslookup www.baidu.com
Server: 10.245.0.254
Address 1: 10.245.0.254 coredns-coredns.kube-system.svc.cluster.local
Name: www.baidu.com
Address 1: 182.61.200.7
Address 2: 182.61.200.6
3.5 容器对外暴露端口设置
删除原先创建的 Pod nginx1、nginx2 和 nginx3。
将 nginx3.yaml 做以下修改:
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
app: nginx3
name: nginx3
namespace: hcie
spec:
containers:
- image: swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/nginx:1.18.0
imagePullPolicy: IfNotPresent
name: nginx
ports:
- name: nginx
protocol: TCP
containerPort: 80
hostPort: 30001
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Never
status: {}
使用修改后的 YAML 创建 Pod,然后在宿主机上访问该 Pod,看是否能够访问到。
[root@k8s-master3 hcie]# curl 172.16.126.35:80
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
- ❓ 思考:使用 Pod 地址访问正常后,如何在集群外访问该 Pod?
- 使用运行节点的30001端口, 可以对外提供访问
- 如果是公有云环境, 节点出口还会设置SLB负载均衡。
[root@k8s-master3 hcie]# curl 10.10.0.5:30001
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
3.6 容器执行的命令及参数设置
删除原先创建的 Pod nginx3。
kubectl delete pod nginx3
修改nginx1.yaml配置
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
app: nginx1
name: nginx1
namespace: hcie
spec:
containers:
- image: swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/library/busybox:1.28
imagePullPolicy: IfNotPresent
name: nginx
command: ["ping","www.baidu.com","-c","10"]
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}
修改nginx2.yaml配置
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
app: nginx2
name: nginx2
namespace: hcie
spec:
containers:
- image: swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/library/busybox:1.28
imagePullPolicy: IfNotPresent
name: nginx
command:
- "ping"
- "www.baidu.com"
- "-c"
- "10"
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: OnFailure
status: {}
修改nginx3.yaml配置
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
app: nginx3
name: nginx3
namespace: hcie
spec:
containers:
- image: swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/library/busybox:1.28
imagePullPolicy: IfNotPresent
name: nginx
command: ["ping"]
args: ["www.baidu.com","-c","10"]
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Never
status: {}
根据输出,可以看到三个 Pod 都执行了“ping www.baidu.com -c 10”的命令。
[root@k8s-master3 hcie]# k logs nginx3 -n hcie
PING www.baidu.com (182.61.200.7): 56 data bytes
64 bytes from 182.61.200.7: seq=0 ttl=46 time=56.556 ms
64 bytes from 182.61.200.7: seq=1 ttl=46 time=56.266 ms
64 bytes from 182.61.200.7: seq=2 ttl=46 time=56.075 ms
64 bytes from 182.61.200.7: seq=3 ttl=46 time=55.928 ms
64 bytes from 182.61.200.7: seq=4 ttl=46 time=57.467 ms
64 bytes from 182.61.200.7: seq=5 ttl=46 time=56.107 ms
64 bytes from 182.61.200.7: seq=6 ttl=46 time=56.530 ms
64 bytes from 182.61.200.7: seq=7 ttl=46 time=56.048 ms
64 bytes from 182.61.200.7: seq=8 ttl=46 time=55.978 ms
64 bytes from 182.61.200.7: seq=9 ttl=46 time=55.709 ms
--- www.baidu.com ping statistics ---
10 packets transmitted, 10 packets received, 0% packet loss
round-trip min/avg/max = 55.709/56.266/57.467 ms
[root@k8s-master3 hcie]# k logs nginx2 -n hcie
PING www.baidu.com (182.61.200.6): 56 data bytes
64 bytes from 182.61.200.6: seq=0 ttl=46 time=69.806 ms
64 bytes from 182.61.200.6: seq=1 ttl=46 time=70.412 ms
64 bytes from 182.61.200.6: seq=2 ttl=46 time=70.991 ms
64 bytes from 182.61.200.6: seq=3 ttl=46 time=69.951 ms
64 bytes from 182.61.200.6: seq=4 ttl=46 time=70.006 ms
64 bytes from 182.61.200.6: seq=5 ttl=46 time=70.181 ms
64 bytes from 182.61.200.6: seq=6 ttl=46 time=70.080 ms
64 bytes from 182.61.200.6: seq=7 ttl=46 time=72.164 ms
64 bytes from 182.61.200.6: seq=8 ttl=46 time=70.616 ms
64 bytes from 182.61.200.6: seq=9 ttl=46 time=70.114 ms
--- www.baidu.com ping statistics ---
10 packets transmitted, 10 packets received, 0% packet loss
round-trip min/avg/max = 69.806/70.432/72.164 ms
[root@k8s-master3 hcie]# k logs nginx1 -n hcie
PING www.baidu.com (182.61.200.7): 56 data bytes
64 bytes from 182.61.200.7: seq=0 ttl=46 time=56.085 ms
64 bytes from 182.61.200.7: seq=1 ttl=46 time=55.840 ms
64 bytes from 182.61.200.7: seq=2 ttl=46 time=56.810 ms
64 bytes from 182.61.200.7: seq=3 ttl=46 time=56.333 ms
64 bytes from 182.61.200.7: seq=4 ttl=46 time=56.746 ms
64 bytes from 182.61.200.7: seq=5 ttl=46 time=56.036 ms
64 bytes from 182.61.200.7: seq=6 ttl=46 time=59.552 ms
64 bytes from 182.61.200.7: seq=7 ttl=46 time=56.057 ms
64 bytes from 182.61.200.7: seq=8 ttl=46 time=55.761 ms
64 bytes from 182.61.200.7: seq=9 ttl=46 time=56.123 ms
--- www.baidu.com ping statistics ---
10 packets transmitted, 10 packets received, 0% packet loss
round-trip min/avg/max = 55.761/56.534/59.552 ms
3.7 容器中环境变量设置
实验前删除原先创建的 Pod nginx1、nginx2 和 nginx3。
将 nginx3.yaml 做以下修改:(注意加粗斜体的内容)
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
app: nginx3
name: nginx3
namespace: hcie
spec:
containers:
- image: nginx:1.21
imagePullPolicy: IfNotPresent
name: nginx
env:
- name: WELCOME
value: "this is from master3"
- name: WRONG
value: "try again"
command: ["env"]
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Never
status: {}
使用修改后的 YAML 创建 Pod,并查看该 Pod 的日志,可以发现日志输出为:
[root@k8s-master3 hcie]# k create -f nginx3.yaml
pod/nginx3 created
[root@k8s-master3 hcie]# kubectl logs nginx3 -n hcie
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=nginx3
NGINX_VERSION=1.21.6
NJS_VERSION=0.7.3
PKG_RELEASE=1~bullseye
WELCOME=this is from master3
WRONG=try again
KUBERNETES_SERVICE_PORT=443
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_PORT=tcp://10.245.0.1:443
KUBERNETES_PORT_443_TCP=tcp://10.245.0.1:443
KUBERNETES_PORT_443_TCP_PROTO=tcp
KUBERNETES_PORT_443_TCP_PORT=443
KUBERNETES_PORT_443_TCP_ADDR=10.245.0.1
KUBERNETES_SERVICE_HOST=10.245.0.1
HOME=/root
- ❓ 思考:使用“kubectl exec -it nginx3 -- echo \$WELCOME”是否能够打印出对应的变量值?
# 不可以打印, 因为pod已经结束任务了
[root@k8s-master3 hcie]# kubectl exec -it nginx3 -n hcie -- echo $WELCOME
error: cannot exec into a container in a completed pod; current phase is Succeeded
# pod的状态是complete
[root@k8s-master3 hcie]# kubectl get pod -A
NAMESPACE NAME READY STATUS RESTARTS AGE
default test 1/1 Running 3 (32m ago) 3h33m
hcie nginx3 0/1 Completed 0 73s
- ❓ 思考:如果使用“kubectl exec -it nginx3 -- /bin/bash”登入容器后,再使用命令"echo \$WELCOME"是否可以打印出对应的变量值?
# 无法进入pod,pod已经结束了。
[root@k8s-master3 hcie]# kubectl exec -it nginx3 -n hcie -- /bin/bash
error: cannot exec into a container in a completed pod; current phase is Succeeded
3.8 在相同 Pod 中运行多个容器
删除原先创建的nginx3
[root@k8s-master3 hcie]# kubectl delete -f nginx3.yaml
pod "nginx3" deleted
修改nginx3.yaml
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
app: nginx3
name: nginx3
namespace: hcie
spec:
imagePullSecrets:
- name: hcie
containers:
- image: swr.cn-south-1.myhuaweicloud.com/steven-hcie/nginx:1.21
imagePullPolicy: IfNotPresent
name: nginx
- image: swr.cn-south-1.myhuaweicloud.com/steven-hcie/busybox
name: busybox
command:
- sleep
- "3600"
dnsPolicy: ClusterFirst
restartPolicy: Never
status: {}
创建nginx3
[root@k8s-master3 hcie]# kubectl create -f nginx3.yaml
详细信息
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 27s default-scheduler Successfully assigned hcie/nginx3 to k8s-worker2
Normal Pulling 26s kubelet Pulling image "swr.cn-south-1.myhuaweicloud.com/steven-hcie/nginx:1.21"
Normal Pulled 17s kubelet Successfully pulled image "swr.cn-south-1.myhuaweicloud.com/steven-hcie/nginx:1.21" in 9.191s (9.191s including waiting)
Normal Created 17s kubelet Created container nginx
Normal Started 16s kubelet Started container nginx
Normal Pulling 16s kubelet Pulling image "swr.cn-south-1.myhuaweicloud.com/steven-hcie/busybox"
Normal Pulled 15s kubelet Successfully pulled image "swr.cn-south-1.myhuaweicloud.com/steven-hcie/busybox" in 1.817s (1.817s including waiting)
Normal Created 15s kubelet Created container busybox
Normal Started 14s kubelet Started container busybox
[root@k8s-master3 hcie]# kubectl get pod -A
NAMESPACE NAME READY STATUS RESTARTS AGE
hcie nginx3 2/2 Running 0 29s
- 思考:两个容器是否有启动顺序?如果其中一个容器没有顺利启动,是否会影响另外一个容器的启动?如果要登入某个容器,该如何执行命令?
- 多个容器通常是并行启动的,没有特定的启动顺序;
- 如果一个 Pod 中的某个容器没有顺利启动,默认情况下不会直接影响其他容器的启动;
- 如果进入pod的某一个容器,执行
kubectl exec PODNAME -C CONTAINER
Pod的容器启动实验
部署多Pod场景启动失败实验
修改nginx3.yaml
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
app: nginx3
name: nginx3
namespace: hcie
spec:
imagePullSecrets:
- name: hcie
containers:
- image: swr.cn-south-1.myhuaweicloud.com/steven-hcie/nginx:1.21
imagePullPolicy: IfNotPresent
name: nginx
command: ["sh", "-c", "exit 1"] # 测试nginx启动后,立刻退出,导致启动失败
resources:
requests:
cpu: 0.1
limits:
cpu: 0.3
- image: swr.cn-south-1.myhuaweicloud.com/steven-hcie/busybox
name: busybox
command:
- sleep
- "3600"
dnsPolicy: ClusterFirst
restartPolicy: Never
status: {}
重新部署nginx3
[root@k8s-master3 hcie]# kubectl create -f nginx3.yaml
pod/nginx3 created
检查pod状态
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 28s default-scheduler Successfully assigned hcie/nginx3 to k8s-worker2
Normal Pulled 27s kubelet Container image "swr.cn-south-1.myhuaweicloud.com/steven-hcie/nginx:1.21" already present on machine
Normal Created 27s kubelet Created container nginx
Normal Started 27s kubelet Started container nginx
Normal Pulling 27s kubelet Pulling image "swr.cn-south-1.myhuaweicloud.com/steven-hcie/busybox"
Normal Pulled 26s kubelet Successfully pulled image "swr.cn-south-1.myhuaweicloud.com/steven-hcie/busybox" in 660ms (660ms including waiting)
Normal Created 26s kubelet Created container busybox
Normal Started 26s kubelet Started container busybox
[root@k8s-master3 hcie]# kubectl get pod -A
NAMESPACE NAME READY STATUS RESTARTS AGE
hcie nginx3 1/2 Error 0 3s
- ❔ 说明:nginx容器无法运行
进入busybox
[root@k8s-master3 hcie]# kubectl exec -it nginx3 -n hcie -c busybox -- /bin/sh
/ # ip ad
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: tunl0@NONE: <NOARP> mtu 1480 qdisc noop qlen 1000
link/ipip 0.0.0.0 brd 0.0.0.0
4: eth0@if406220: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1480 qdisc noqueue
link/ether 26:b8:d6:42:dc:1a brd ff:ff:ff:ff:ff:ff
inet 172.16.126.44/32 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::24b8:d6ff:fe42:dc1a/64 scope link
valid_lft forever preferred_lft forever
/ #
- ❔ 说明: busybox可以正常创建并运行
3.9 Pod时区与宿主时区同步
容器和主机的时间可能存在不同步的情况,如下所示,前者为容器的时间,后者为宿主机时间,容器的时间比宿主机的时间早8小时。在某些时间敏感的场景,如日志定位问题,为了方便,需要实现容器时间和宿主机时间保持一致。
[root@k8s-master1 \]# kubectl exec -ti myapp-statefulset-0 -- sh
# date Tue Aug 25 06:50:29 UTC 2024
# exit
[root@k8s-master1 \]# date 2024年 08月 25日 星期二 14:50:37 CST
- CST应该是指(China Shanghai Time,东八区时间)  
- UTC应该是指(Coordinated Universal Time,标准时间)
1. 通过将宿主机的时区文件挂载到Pod
修改nginx1.yaml
apiVersion: apps/v1
kind: pod
metadata:
name: nginx1
namespace: default
labels:
app: nginx1
spec:
containers:
- name: nginx
image: nginx:1.18
ports:
- containerPort: 80
volumeMounts:
- name: timezone
mountPath: /etc/localtime # 挂载到容器的目录
volumes:
- name: timezone
hostPath:
path: /usr/share/zoneinfo/Asia/Shanghai # 宿主机的目录
创建nginx1
kubectl apply nginx1.yaml
查看创建结果
[root@k8s-master1 ]# kubectl get pod |grep time
nginx1-6c7b6f86c6-2dlp7 1/1 Running 0 22m
nginx1-6c7b6f86c6-vdzwh 1/1 Running 0 22m
[root@k8s-master1 ]# kubectl exec -it nginx1-6c7b6f86c6-2dlp7 -- bash
root@nginx1-6c7b6f86c6-2dlp7:/# date
Tue Aug 25 14:57:01 CST 2024
root@nginx1-6c7b6f86c6-2dlp7:/# exit
exit
[root@k8s-master1 ]# date
2024年 08月 25日 星期二 14:57:07 CST
- ❔ 说明:将宿主机的区间文件通过mountPath挂载到容器之后,可以看到两者时区已经保持了一致。
2. 通过环境变量
修改nginx2.yaml
apiVersion: apps/v1
kind: pod
metadata:
name: nginx2
namespace: default
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.18
ports:
- containerPort: 80
env:
- name: TZ
value: Asia/Shanghai # 宿主机的环境变量
创建nginx2
kubectl apply nginx2.yaml
查看创建结果
root@nginx2-7b6d4c8b5-kbj9q:/# date
Tue Aug 25 19:03:09 CST 2024
root@nginx2-7b6d4c8b5-kbj9q:/# exit
exit
[root@k8s-master1 \]# date
2024年 08月 25日 星期二 19:03:18 CST
- ❔ 说明:可以看到容器时间和宿主机的时间保持了一致
3. 通过dockfile镜像构建来同步容器和宿主机的时区
这个方法最复杂,但从根本解决问题
编写dockerfile
vim testdockertime
# dockerfine
FROM nginx
RUN rm -f /etc/localtime \
&& ln -sv /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
&& echo "Asia/Shanghai" > /etc/timezone
创建docker
[root@k8s-master1 ]# docker build -t nginx:testdate -f testdockertime .
Sending build context to Docker daemon 82.43kB
Step 1/2 : FROM nginx
---> 4bb46517cac3
Step 2/2 : RUN rm -f /etc/localtime && ln -sv /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo "Asia/Shanghai" > /etc/timezone
---> Running in 29c9ffc202e6
'/etc/localtime' -> '/usr/share/zoneinfo/Asia/Shanghai'
Removing intermediate container 29c9ffc202e6
---> d3cde57b8afc
Successfully built d3cde57b8afc
Successfully tagged nginx:testdate
- ❔ 说明:通过上面的步骤在nginx的基础上重新制作了镜像,其新的镜像的tag为testdate;
修改nginx3.yaml
apiVersion: apps/v1
kind: pod
metadata:
name: nginx3
namespace: default
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:testdate
ports:
- containerPort: 80
创建nginx3
kubectl apply nginx3.yaml
查看创建结果
root@nginx3-7b6d4c8b5-kb79d:/# date
root@nginx3-7b6d4c8b5-kb79d:/# date
Tue Aug 25 19:35:00 CST 2024
root@nginx3-7b6d4c8b5-kb79d:/# exit
exit
[root@k8s-master1]# date
2024年 08月 25日 星期二 19:35:09 CST
- 如上可以看到通过制作镜像也可实现容器与宿主机的时区同步
补充:4.“kubectl apply”和“kubectl create”的区别
官方解释
序号 | kubectl apply | kubectl create |
1 | 它会直接在当前活动源中更新文件中给定的属性。 | 它会先删除资源,然后从提供的文件中重新创建资源。 |
2 | 在 apply 命令中使用的文件可以是一个不完整的规范。 | 在 create 命令中使用的文件应是完整的。 |
3 | apply 命令只适用于资源的某些属性。 | create 命令适用于资源的所有属性。 |
4 | 你可以使用 apply 命令只更改一个注解,而无需指定资源的其他属性。 | 如果使用相同的文件执行 replace 命令,由于缺少信息,命令将会失败 |
对比实验
使用kubectl create创建
# 第一次执行create
kubectl create -f deployment-nginx.yaml
# 修改声明文件
vim deployment-nginx.yaml
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: nginx1
disktype: ssd
name: nginx1
spec:
containers:
- image: swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/nginx:1.27
name: test
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}
# 第二次执行create
[root@k8s-master3 ~]# kubectl create -f deployment-nginx.yaml
Error from server (AlreadyExists): error when creating "deployment-nginx.yaml": pods "nginx1" already exists
- kubectl create命令可创建新资源。 因此,如果再次运行该命令,则会抛出错误,因为资源名称在名称空间中应该是唯一的。
使用kubectl apply创建
# 第一次执行apply
[root@k8s-master3 ~]# kubectl apply -f deployment-nginx.yaml
pod/nginx2 created
# 修改声明文件
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: nginx2
disktype: ssd
name: nginx2
spec:
containers:
- image: swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/nginx:1.27
name: test
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}
# 第二次执行apply
[root@k8s-master3 ~]# kubectl apply -f deployment-nginx.yaml
pod/nginx2 configured
# 检查更新内容
[root@k8s-master3 ~]# k get pod --show-labels
NAME READY STATUS RESTARTS AGE LABELS
nginx1 1/1 Running 0 6m38s run=nginx1
nginx2 1/1 Running 0 73s disktype=ssd,run=nginx2
- kubectl apply命令将配置应用于资源。 如果资源不在那里,那么它将被创建。 kubectl apply命令可以第二次运行,因为它只是应用如下所示的配置。 在这种情况下,配置没有改变。 \\
总结
- 在文档中理解的是kubectl apply = kubectl create + kubectl replace。
- 从执行的角度来看,如上所示,在kubectl create和kubectl apply之间第一次创建资源时没有区别。 但是,第二次kubectl create会抛出错误。
- 如果在单个文件上运行操作以创建资源,则create和apply基本相同。 但是apply允许您在目录下的多个文件上同时创建和修补。
5. 参考文献
【1】https://kubernetes.io/docs/concepts/workloads/pods/
【2】https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/
【3】https://stackoverflow.com/questions/47369351/kubectl-apply-vs-kubectl-create
【4】https://blog.csdn.net/textdemo123/article/details/104400985
标签:kubectl,nginx,hcie,读懂,攻略,Pod,k8s,pod From: https://blog.51cto.com/u_13965025/11951264