首页 > 其他分享 >一文读懂Pod以及实践攻略

一文读懂Pod以及实践攻略

时间:2024-09-08 10:54:37浏览次数:13  
标签:kubectl nginx hcie 读懂 攻略 Pod k8s pod

❤️ 感谢关注,原文来自: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 注入临时容器对应用程序进行调试工作。

一文读懂Pod以及实践攻略_nginx

1.2 Pod管理容器

Pod 是容器的“宿主”,负责启动、运行和管理其中的容器, 可以将容器形成一个共同协作的服务单元。 Pod 中的容器在k8s的同一节点上并满足同时调度。容器间可以共享资源和依赖关系、相互通信以及协调终止的时间和方式。

Kubernetes 集群中的 Pod 主要有两种使用方式:

  • 运行单个容器的 Pod 。 “单一容器的Pod ”模型是最常见的 Kubernetes 用例;在这种情况下,您可以将 Pod 视为单个容器的封装器; Kubernetes仅管理 Pod,而不是直接管理容器。
  • 运行多个协同工作的容器的 Pod 。 Pod 可以封装由多个紧密耦合且需要共享资源的共置容器组成的应用程序。这些位于同一位置的容器形成了一个单一的内聚服务单元,例如,一个容器向外提供应用入口,而一个单独的sidecar容器会更新应用数据文件。 Pod 会将这些容器、存储资源和临时网络身份包装在一起作为一个单元进行管理。

一文读懂Pod以及实践攻略_重新启动_02

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 的某些字段。然而,像patchreplace Pod 更新操作有一些限制:

  • 有关 Pod 的大部分元数据都是不可变的。例如,您不能更改namespacenameuidcreationTimestamp字段; generation领域是独一无二的。它只接受增加字段当前值的更新。
  • 如果设置了metadata.deletionTimestamp ,则不能将新条目添加到metadata.finalizers列表中。
  • Pod 更新不得更改除spec.containers[*].imagespec.initContainers[*].imagespec.activeDeadlineSecondsspec.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 创建容器。容器有三种可能的状态: WaitingRunningTerminated

以下每个状态的含义:

Value

描述

Waiting

如果容器既不处于Running状态,也不处于Terminated状态,则它处于Waiting 。处于Waiting状态的容器仍在运行完成启动所需的操作:例如,从容器镜像注册表中拉取容器镜像,或者应用Secret数据。当您使用kubectl查询容器处于Waiting状态的 Pod 时,您还会看到 Reason 字段来总结容器处于该状态的原因。

Running

Running状态表示容器正在正常执行。如果配置了postStart挂钩,则它已经执行并完成。当您使用kubectl查询容器处于Running的 Pod 时,您还会看到有关容器何时进入Running状态的信息。

Terminated

处于Terminated状态的容器开始执行,然后要么运行完成,要么由于某种原因失败。当您使用kubectl查询容器Terminated Pod 时,您会看到原因、退出代码以及该容器执行周期的开始和结束时间。

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字段,其可能值包括 AlwaysOnFailureNever。默认值是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进行控制。

⚠️ 注意:静态 Pod 的spec不能引用其他 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&#x20;

  • ❓ 思考:“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

只有当镜像在本地不存在时才会拉取。&#xA;如果你省略了 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,东八区时间) &#x20;
  • 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

相关文章

  • 速解《黑神话:悟空》dbghelp.dll缺失难题:即刻修复游戏故障攻略
    遇到《黑神话:悟空》提示dbghelp.dll文件缺失的问题,可以按照以下步骤尝试解决:1.重新安装DirectX:dbghelp.dll是MicrosoftDirectX的一部分,有时通过重新安装DirectX可以解决这个问题。访问微软官方网站下载并安装最新版本的DirectX。DirectX修复工具最新版(点击即可下载)https://......
  • Pod 生命周期的钩子函数
    在Kubernetes中,Pod的生命周期管理可以通过钩子函数(LifecycleHooks)来增强。这些钩子允许开发者在Pod的特定生命周期阶段执行自定义操作。以下是两种主要的钩子函数:1.PreStopHook描述:在容器被终止之前执行的钩子。这个钩子通常用于在容器停止前执行一些清理操作,比如关闭连接......
  • pod几种常见状态
    在Kubernetes中,Pod的状态反映了其当前的运行情况和健康状况。以下是几种常见的Pod状态:1.Pending描述:Pod已被调度到节点,但尚未启动。可能是由于资源不足(如CPU、内存)或其他原因导致未能创建容器。原因:等待所需资源可用、等待Volume绑定等。2.Running描述:Pod正在运行,至少有......
  • pod DNS解析流程
    在Kubernetes中,Pod的DNS解析流程主要涉及到KubernetesDNS服务(通常是CoreDNS或kube-dns)以及KubernetesAPI。以下是PodDNS解析的详细流程:1.DNS配置每个Pod在创建时,会根据其所在的Namespace和集群的DNS设置获得DNS配置。Pod的/etc/resolv.conf文件通......
  • 全栈性能优化秘籍--Linux 系统性能调优全攻略:多维度优化技巧大揭秘
           ......
  • 平安银行25届秋招金融类专业笔试/测评通关攻略题库考什么
    平安银行测评和笔试有什么区别?平安测评【平安IQ新、16PF】侧重个性扫描,主要是对能反应个体人格因素的测试评估,考察参考人的性格特点。平安金融类笔试【60分钟60题,前程无忧考试系统】侧重综合能力考察,考试内容包括金融/银行行业的基础知识、常识判断、言语理解与表达、数量关......
  • pod之间访问不通怎么排查
    当Kubernetes集群中的Pod之间无法相互访问时,可以通过以下步骤进行排查:1.检查Pod状态使用以下命令查看Pod的状态,确认所有相关Pod都在运行状态:kubectlgetpods-n<namespace>2.检查网络策略如果集群中使用了网络策略(NetworkPolicies),需要确保相关的网络策略允许Pod之间的......
  • 不同node上的Pod之间的通信过程
    在Kubernetes(K8s)中,不同节点上的Pod之间的通信是通过一套复杂的网络机制实现的。以下是不同节点上Pod之间通信的主要过程:1.网络模型K8s遵循“每个Pod都有一个唯一IP地址”的网络模型,确保集群内的Pod可以直接通过IP地址互相访问。这意味着无论Pod位于哪个节点,它们都可以通过其分......
  • 简述删除一个Pod流程
    删除一个Pod的流程在Kubernetes(K8s)中是一个相对简单但又涉及多个步骤的过程。以下是删除Pod的简要流程:1.发起删除请求用户可以通过kubectldeletepod<pod-name>命令或K8sAPI发起删除Pod的请求。2.APIServer接收请求APIServer接收到删除请求后,会验证请求的有效性。如......