Pod理论-企业实战案例讲解-资源清单编写技巧
Pod基本介绍
Pod概念
- 在·Kubernetes·中,Pod·是最小的调度单元,是容器的逻辑宿主机。Pod·可以包含一个或多个紧密关联的容器,这些容器共享同一个网络命名空间、存储卷以及主机名。通常情况下,这些容器会协同工作来提供一个完整的应用服务。(微念·批建行和段誉限落居中
- Pod·是·Kubernetes·中的一个重要概念,因为它为多个容器提供了一个共享的上下文和环境。Pod中的容器可以直接相互通信,它们之间的交互和通信可以通过本地主机的网络端口进行。Pod·还提供了一些共享的资源,如存储卷和命名空间等,可以使容器之间共享数据和状态。
- Pod·是·Kubernetes·中应用部署和管理的基本单元。当需要部署一个应用时,可以将所有相关的容器打包在同一个·Pod·中,然后通过·Kubernetes·控制器进行管理和调度。Pod·也是·Kubernetes的一种扩展点,可以通过定义自定义资源(Custom·Resources)来扩展·Pod·的功能和能力。
Pod:
container:
image: nginx
container:
image: tomcat
Pod、容器、节点关系:
- 在·Kubernetes·中,容器是部署和运行应用程序的主要载体,而·Pod·则是用来管理容器的。每个Pod·都可以包含一个或多个容器,这些容器共享同一个网络命名空间、存储卷以及主机名,它们在·Pod中是处于相同的生命周期和调度环境下的。也就是说,当一个·Pod·被创建时,它里面的所有容器都会被一起创建,而当·Pod·被删除时,里面的所有容器也会被一起删除。
- 节点是·Kubernetes·集群中的一台服务器,它是·Pod·的宿主机。当·Pod·被创建时,Kubernetes·调度器会选择一个节点来运行该·Pod,然后在该节点上启动·Pod·中的所有容器。Pod·可以被调度到任意一个节点上运行,也可以在不同节点之间自由迁移。
自主式Pod和控制器管理的Pod
自主式 pod:
- 在k8s中,我们部署pod的时候,基本上都是使用控制器管理,那如果不使用控制器,也可以直接定义一个pod资源,那么就是pod自己去控制自己,这样的pod称为自主式pod。
互动1:如何创建一个自主式Pod?
# 查看k8s哪些资源
$ kubectrl api-resources
# 查看控制节点描述
$ kubectrl describe nodes xuegod63
...
# 污点 起到保护作用,如果不能容忍污点,其调度器不会将pod调度过来
Taints: node-role.kubernetes.io/control-plane:NoSchedule
# 工作节点都要得到镜像
$ ctr -n k8s.io images pull docker.io/library/tomcat:8.5-jre8-alpine
- 编写pod
vim pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: tomcat-pod
namespace: default
# 定义了标签
labels:
tomcat: tomcat-pod
spec:
containers:
- name: tomcat-pod-java
ports:
- containerPort: 8080
image: tomcat:8.5-jre8-alpine
imagePullPolicy: IfNotPresent
- 使用
$ kubectl apply -f pod.yaml
# 查看pod
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
tomcat-pod 1/1 Running 0 42s
# 查看标签为 tomcat-pod 的 tomcat pod有哪些
$ kubectl get pod -l tomcat=tomcat-pod
NAME READY STATUS RESTARTS AGE
tomcat-pod 1/1 Running 0 96s
- 上面实验可以看到,当我们把pod删除之后,pod不会再创建一个新的pod,而是彻底从机器上删除了,这种自主式pod适合测试环境或者
非核心业务场景
,如果生产环境用自主式pod部署应用,那是存在风险的,所以,我们平时管理Pod都是通过控制器去管理的。
控制器管理的Pod
控制器可以根据不同的需求来创建和管理·Pod,例如: 1、Deployment·控制器:用于创建和管理可扩展的·Pod·集合,支持滚动升级和回滚操作。 2、StatefulSet·控制器:用于管理有状态的应用程序,支持有序部署和扩缩容操作。 3、DaemonSet·控制器:用于在每个节点上运行一组·Pod,以支持集群级别的后台任务等。 4、Job&&Cronjob 5、 Replicaset
当使用这些控制器来创建和管理·Pod·时,控制器会监视·Pod的状态并确保其持续满足用户的期望状态。如果·Pod·的状态发生变化,例如某个容器挂掉了,控制器会自动进行故障恢复操作,以确保Pod·的期望状态能够得到恢复。
示例:通过Deployment创建一个pod资源
vim deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx
spec:
selector:
matchLabels:
run: my-nginx
replicas: 2
template:
metadata:
labels:
run: my-nginx
spec:
containers:
- name: my-nginx
image: nginx
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
- 运行及查看
$ kubectl apply -f deployment.yaml
deployment.apps/my-nginx created
$ kubectl get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
my-nginx 2/2 2 2 24s
# deployment 资源会自动创建 replicaset 资源
$ kubectl get rs
NAME DESIRED CURRENT READY AGE
my-nginx-5f7668c4b 2 2 2 2m10s
# 查看 replicaset 创建的pod
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
my-nginx-5f7668c4b-j66rv 1/1 Running 0 3m29s
my-nginx-5f7668c4b-qbrxn 1/1 Running 0 3m29s
# 删除一个pod
$ kubectl delete pod my-nginx-5f7668c4b-j66rv
pod "my-nginx-5f7668c4b-j66rv" deleted
# 会马上新建一个pod
$ ubectl get pod
NAME READY STATUS RESTARTS AGE
my-nginx-5f7668c4b-qbrxn 1/1 Running 0 4m36s
my-nginx-5f7668c4b-z5lfk 1/1 Running 0 6s
# 删除deployment
$ kubectl delete deploy my-nginx
- 如果更改了镜像版本,apply后会自主删除更新pod
Pod资源清单的定义方法
- 配置命令自动补全
参考 https://kubernetes.io/zh-cn/docs/reference/kubectl/quick-reference/
$ yum install -y bash-completion $ source /usr/share/bash-completion/bash_completion $ kubectl completion bash > ~/.kube/completion.bash.inc $ source '/root/.kube/completion.bash.inc'
创建Pod资源技巧
在创建pod的时候,可以通过写资源清单文件去实现,Pod资源清单文件中有几个重要的部分:apiVersion、kind、metadata、spec 以及 status,其中 apiVersion 和kind 是比较固定的,status是运行时的状态,不需要我们自己定义,所以最重要的就是metadata和spec两个部分。
# 查看帮助
$ kubectl explain pod
apiVersion:v1
在·Kubernetes·中,每个资源都有一个apiVersion字段,它用于标识·APl·中的不同版本。apiVersion·字段由两个部分组成,用斜杠分隔:group/version。其中,group·表示·APl·组的名称,version·表示·API·版本号。
对于·Pod·资源来说,它的·apiVersion·字段通常是·v1,即·Kubernetes·的核心组的版本
# 查看 api-version 支持的版本
$ kubectl api-versions
admissionregistration.k8s.io/v1
apiextensions.k8s.io/v1
apiregistration.k8s.io/v1
apps/v1
authentication.k8s.io/v1
authorization.k8s.io/v1
autoscaling/v1
autoscaling/v2
batch/v1
certificates.k8s.io/v1
coordination.k8s.io/v1
crd.projectcalico.org/v1
discovery.k8s.io/v1
events.k8s.io/v1
flowcontrol.apiserver.k8s.io/v1beta2
flowcontrol.apiserver.k8s.io/v1beta3
networking.k8s.io/v1
node.k8s.io/v1
policy.networking.k8s.io/v1alpha1
policy/v1
rbac.authorization.k8s.io/v1
scheduling.k8s.io/v1
storage.k8s.io/v1
storage.k8s.io/v1beta1
v1
kind: Pod
在Kubernetes中,每个资源定义都包含一个·kind·字段,用于指定该资源的类型或种类
metadata
# 查看帮助
$ kubectl explain pod.metadata
name:资源名称
用于唯一标识该资源。
namespace:命名空间
- 用于将资源隔离和分类到不同的逻辑空间中,以避免命名冲突。
- namespace是k8s集群级别的资源,可以给不同的用户、利租户、环境或项目创建对应的名称空间,例如,可以为development、qa、和production应用环境分别创建各自的名称空间。
- k8s的绝大多数资源都属于名称空间级别,同一名称空间内的同一类资源名必须是唯一的,但跨名称空间时并无此限制。k8s还有一些资源属于集群级别的,如node、namespace、PersistentVolume等资源,它们不属于任何名称空间,因此资源对象的名称必须全局唯一。
1、查看名称空间及其资源对象 - k8s集群默认提供了几个名称空间用于特定目的,例如,kube-system主要用于运行系统级资源,而default则为那些未指定名称空间的资源操作提供一个默认值。 - 使用kubectl·get·namespace或者kubectl·get·ns可以查看namespace资源,使用kubectl·describe·namespace·$NAME可以查看特定的名称空间的详细信息。 2、管理namespace资源namespace是k8s·api的标准资源类型之一,namespace资源属性较少,通常只需要指定名称即可创建,如“kubectlcreate·namespace·qa"。namespace资源的名称仅能由字母、数字、下划线、连接线等字符组成。删除namespace资源会级联删除其包含的所有其他资源对象:
# 查看名称空间
$ kubectl get namespaces --show-labels
NAME STATUS AGE LABELS
default Active 30h kubernetes.io/metadata.name=default
kube-node-lease Active 30h kubernetes.io/metadata.name=kube-node-lease
kube-public Active 30h kubernetes.io/metadata.name=kube-public
kube-system Active 30h kubernetes.io/metadata.name=kube-system
# 查看描述
$ kubectl describe namespace
# 创建名称空间
$ kubectl create namespace qa
- 不要轻易执行的命令
kubectI delete TYPE RESOURCE -n NS # 删除指定名称空间内的指定资源
kubectl delete TYPE --all -n NS # 删除指定名称空间内的指定类型的所有资源
kubectl delete all -n NS # 删除指定名称空间内的所有资源
kubectl delete all --all # 删除所有名称空间中的所有资源
kubectl get all # 列出指定名称空间的所有资源,除了个别的资源,如 sa 等不会列出来,大部分都会列出来
kubectl get all -A #列出来所有名称空间的所有资源,除了个别的资源,如 sa 等不会列出来,大部分都会列出来
labels:标签
用于对资源进行分类和组织。可以通过标签选择器进行资源筛选和操作。
# 查看名称空间有哪些标签
$ kubectl get pods -n kube-system --show-labels
# 查看自己创建pod有哪些标签
$ kubectl get pods --show-labels
NAME READY STATUS RESTARTS AGE LABELS
my-nginx-5f7668c4b-qbrxn 1/1 Running 0 46m pod-template-hash=5f7668c4b,run=my-nginx
my-nginx-5f7668c4b-z5lfk 1/1 Running 0 42m pod-template-hash=5f7668c4b,run=my-nginx
# 根据标签筛选
$ kubectl get pods -l run=my-nginx
NAME READY STATUS RESTARTS AGE LABELS
my-nginx-5f7668c4b-qbrxn 1/1 Running 0 46m pod-template-hash=5f7668c4b,run=my-nginx
my-nginx-5f7668c4b-z5lfk 1/1 Running 0 42m pod-template-hash=5f7668c4b,run=my-nginx
# 给pod添加标签
$ kubectl label pod my-nginx-5f7668c4b-qbrxn release=canary
pod/my-nginx-5f7668c4b-qbrxn labeled
# 筛选release 标签
$ kubectl get pods -l release --show-labels
NAME READY STATUS RESTARTS AGE LABELS
my-nginx-5f7668c4b-qbrxn 1/1 Running 0 49m pod-template-hash=5f7668c4b,release=canary,run=my-nginx
# 删除标签
$ kubectl label pod my-nginx-5f7668c4b-qbrxn release-
# 没有了
$ kubectl get pods -l release --show-labels
No resources found in default namespace.
# 没有了
$ kubectl get pods --show-labels
NAME READY STATUS RESTARTS AGE LABELS
my-nginx-5f7668c4b-qbrxn 1/1 Running 0 53m pod-template-hash=5f7668c4b,run=my-nginx
my-nginx-5f7668c4b-z5lfk 1/1 Running 0 48m pod-template-hash=5f7668c4b,run=my-nginx
nodes 标签语法与pod相同
- annotations:注释,用于存储一些关于资源的元数据信息,如描述、版本、维护信息等,不影响·Kubernetes·的管理和操作。
- 1、·annotations: 假设你有一个·Kubernetes·集群,上面部署了一个·Web·应用,这个应用运行在一个·Pod·中。你想要记录该应用的版本号和部署时间,方便日后进行排查和版本管理。一种方案是将版本号和部署时间存储在·Pod·的·annotations·中。Pod·的定义文件可能如下所示
pod示例
demo-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: demo-pod
namespace: default
labels:
app: myapp
env: dev
spec:
containers:
- name: tomcat
image: tomcat:8.5-jre8-alpine
ports:
- containerPort: 8080
imagePullPolicy: IfNotPresent
- name: busybox
image: busybox
imagePullPolicy: IfNotPresent
command: ["/bin/sh", "-c", "sleep 3600"]
- 查看
$ kubectl apply -f demo-pod.yaml
# 查看日志
$ kubectl logs demo-pod
# 查看特定容器日志
$ kubectl logs demo-pod -c tomcat
# 进入pod默认容器(第一个container)
$ kubectl exec -it demo-pod -- /bin/sh
# 进入指定容器
$ kubectl exec -it demo-pod -c busybox -- /bin/sh
# 删除方式1
$ kubectl delete -f demo-pod.yaml
# 删除方式1 强制删除
$ kubectl delete -f demo-pod.yaml --force --grace-period=0
# 删除方式2
$ kubectl delete pod demo-pod
pod.spec 字段
$ kubectl explain pod.spec
参数解释说明: 1、activeDeadlineSeconds:它定义了一个·Pod·的运行时最长时间。一旦·Pod·的运行时间超过 这个时间,Kubernetes·就会自动终止·Pod,然后将其删除。这个参数可以用来避免某些应用程序的错 误或异常导致·Pod·的生命周期过长,占用集群资源,影响其他应用程序的性能。
-
eg: 举个例子,假设你有一个应用程序在·Kubernetes·中运行,这个应用程序可能因为某种原因陷入死循环或者其它异常情况,导 致它的生命周期无限延长。如果你没有设置·activeDeadlineSeconds,那么这个应用程序将会一直运行 下去,直到你手动停止它或者·Kubernetes·集群自动终止它为止。 如果你设置了·activeDeadlineSeconds,那么这个应用程序的生命周期将会被限制在指定的时间 内。一旦应用程序运行的时间超过了这个时间,Kubernetes·就会自动终止它,然后删除它。这样可以 避免应用程序的错误或异常对集群造成过多的负荷,保护集群的稳定性和安全性。
-
如果·Pod·需要一直提供服务,那么·activeDeadlineSeconds·参数就不再适用了,因为它的作用 是限制·Pod·生命周期最长时间。在这种情况下,你可以将·activeDeadlineSeconds·设置为一个非常 大的值,比如·100·天,以确保它不会影响你的服务稳定性。
-
需要注意的是,即使你将·activeDeadlineSeconds·设置为一个非常大的值,Pod·仍然可能会在某 些情况下被终止,比如它所在的节点发生故障,或者你手动将它删除。因此,为了保证服务的高可用性, 建议使用·Kubernetes·的高可用性特性,比如·Pod·的复制集、服务发现、自动扩展等,来确保服务的 稳定性和可用性。
2、 dnsConfig·字段用于设置·Pod·内部·DNS·解析的相关参数,可以通过该字段来配置·Pod·的 DNS·解析方式,包括·DNS·服务器地址、搜索域、是否启用·DNS·传输层安全(DNS-OVer-TLS)等 选项。
-
具体来说,dnsConfig·字段包含以下字段: nameservers:指定·DNS·服务器的·IP·地址列表 searches:指定·DNS·解析时的搜索域列表。
-
在·Kubernetes·中,通常情况下·Pod·内部的·DNS·解析是自动进行的,而且已经默认配置了一个 DNS·服务器(通常是·kube-dns·或·CoreDNS),以供·Pod·内部进行·DNS·解析。然而,在一些特 定的场景下,比如需要使用特定的·DNS·服务器或者搜索域时,就可以使用·dnsConfig·字段来进行配 置。
-
需要注意的是,dnsConfig·字段只对·Pod·内部的·DNS·解析生效,如果你需要在·Pod·外部访问 该·Pod,则需要通过·Service·或者·Ingress·等资源进行暴露,而不是通过·dnsConfig·字段进行配置。
eg:
- 什么使搜索域? 搜索域(Search·Domain)是指在·DNS·解析时,当查询的主机名(Hostname)不是一个完全合 格的域名(Fully·Qualified·Domain·Name,FQDN)时,系统会自动在查询之前加上一个默认的域名 后缀,尝试解析完整的主机名。 例如,假设你的应用程序要连接一个名为·db·的数据库服务。如果你的主机名为·myapp,而搜索 域设置为·example.com,那么在·DNs·解析时会自动将主机名解析为·db.example.com
3、dnsPolicy: dnsPolicy·是·Kubernetes·中用来指定·Pod·的·DNS·解析策略的一个字段,它的值可以是Default、ClusterFirst、ClusterFirstWithHostNet、None。具体各个取值的含义如下: - Default:继承自所在·Node·的·DNS·配置。这是默认的·DNS·策略。 - ClusterFirst:在·Pod·的·DNS·解析中,优先使用·Kubernetes·集群内部的·DNS·解析服务(kube-dns·或·CoreDNS),如果解析失败,则使用·Node·的·DNS·解析服务。 - ClusterFirstWithHostNet:当pod共享物理机网络时,它将首先查找集群内部的DNS服务来解析域名。如果无法解析,则尝试使用主机上的DNS解析· - None:禁用·Pod·的·DNS·解析功能,由用户自己负责配置。
具体的应用场景: - 如果一个·Pod·需要访问其他·Pod,且需要使用·Kubernetes·集群内部的·DNS·服务解析主机名,那么可以将·dnsPolicy·设置为·ClusterFirst。 - 如果一个·Pod·需要使用本地主机的·DNS·服务解析主机名,那么可以将·dnsPolicy·设置为 Default. - 如果一个·Pod·需要直接访问本地主机的·DNS·服务,那么可以将·dnsPolicy·设置为 ClusterFirstWithHostNet. 需要注意的是,在设置·dnsPolicy·时,需要根据具体的应用场景和网络环境来选择合适的值,以确保·DNS·解析的正确性和性能
4、hostAliases
它允许在·Pod·内部定义一个主机别名列表,以便在·Pod·内部解析主机名时使用。每个别名都是由一个IP·地址、一个主机名列表和一个可选的·IP·地址类型组成。例如:
5、hostNetwork: 如果一个·Pod·的·hostNetwork·参数设置为·true,那么这个·Pod·中的容器将会和宿主机共享网络命 名空间,即它们将会使用宿主机的网络配置,而不是·Kubernetes·中的网络配置。使用·hostNetwork 参数可以让容器直接访问宿主机上的网络资源,而无需通过·Kubernetes·网络插件进行网络转发和转 换。但同时,使用·hostNetwork·参数也会存在一些安全和隔离性问题,因为容器和宿主机共享同一个 网络命名空间,容器的网络流量也将会被宿主机上的其他进程所共享。因此,在使用·hostNetwork·参 数时需要仔细权衡安全和性能等方面的因素。
6.containers: containers → <[]object>·-required- containers是一个对象列表,,下面有很多对象,containers下的字段用-连接
查看containers下有哪些字段:
$ kubectl explain pods.spec.containers
2) image:镜像,每个容器需要指定一个镜像
3) command 和 args: 在Kubernetes中,容器的启动命令可以通过command和args字段来定义。command定义容器启 动的命令,而args则指定命令的参数。
eg: ubuntu/dockerfile
FROM ubuntu
CMD ["echo", "Hello World"]
docker build -t hello-world:1.0 .
这个·Dockerfile·文件的意思是,使用·ubuntu·镜像作为基础镜像,然后在容器启动时运行·echo "Hello·World"·命令。 接下来,我们可以使用这个·Dockerfile·构建一个·Docker·镜像,并启动一个容器:
$ docker build -t hello-world:1.0 .
$ docker run hello-world:1.0
Hello World
将其导入到 ctr 镜像
$ docker save -o ubuntu.tar.gz hello-world:1.0
# 工作节点导入镜像
$ ctr -n=k8s.io images import ubuntu.tar.gz
ubuntu.yaml
apiVersion: v1
kind: Pod
metadata:
name: hello-world
spec:
containers:
- name: hello-world
image: hello-world:1.0
imagePullPolicy: IfNotPresent
$ kubectl apply -f ubuntu.yaml
# 可以看到运行结束了
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
hello-world 0/1 CrashLoopBackOff 1 (5s ago) 6s
# 查看日志是否打印
$ kubectl logs hello-world
Hello World
重新定义 yaml
apiVersion: v1
kind: Pod
metadata:
name: hello-world
spec:
containers:
- name: hello-world
image: hello-world:1.0
imagePullPolicy: IfNotPresent
command: ["/bin/bash"]
args: ["-c", "echo 'Hello, Kubernetes'"]
重新查看,结果为 Hello, Kubernetes