一、Pod 概念
Pod是Kubernetes中最小的调度单位
,是一组容器的集合,Pod中的容器共享网络和存储资源,Pod中的容器可以通过localhost进行通信,Pod中的容器可以通过共享的Volume进行数据共享。
k8s 是通过定义一个 Pod 的资源,然后再 Pod 里面运行容器,容器需要指定一个镜像,这样就可以用来运行具体的服务。
Pod 需要调度到k8s集群的工作节点来运行,具体的调度过程是由 kube-scheduler
组件来完成的,kube-scheduler 会根据 Pod 的资源需求和节点的资源容量,选择一个合适的节点来运行 Pod。
1、Pod 如何管理多个容器
Pod 中可以同时运行多个容器。
- 同一个Pod中的容器会自动分配到同一个工作节点上
- 同一个Pod中的容器共享资源、网络环境
- 同一个Pod中的容器可以通过localhost进行通信
- 同一个Pod中的容器总是被同时调度
只有当你的容器需要紧密配合协作的时候才考虑用这种模式。如果你的容器需要独立扩展,或者你的容器需要被不同的团队管理,那么你应该把它们放到不同的 Pod 中。
一些 Pod 有 init 容器和应用容器,init 容器会先于应用容器启动,init 容器会一直运行直到它们成功完成为止。如果 init 容器失败,Pod 会被重新启动,直到 init 容器成功为止。
2、Pod 网络
Pod 是有 IP 地址的,每个 pod 都被分配唯一的 IP 地址(IP地址靠网络插件calico、flannel、canal、weave等实现),Pod 中的容器共享网络命名空间,包括IP地址和网络端口。
- Pod 内部的容器可以通过 localhost 相互通信。
- Pod 中的容器也可以通过网络插件calico 与其他节点上的 Pod 进行通信。
3、Pod 存储
创建 Pod 的时候可以指定挂载的存储卷。
- Pod 中的所有容器都可以访问这个存储卷,允许容器之间共享数据
- 这个存储卷的生命周期与 Pod 的生命周期相同
- Pod 只要挂载持久化数据卷,重启后数据不会丢失
- Pod 可以挂载多个存储卷
4、Pod 工作方式
在K8S中,所有的资源都可以使用一个 yaml 文件来创建,Pod 也不例外,下面是一个 Pod 的 yaml 文件示例:
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
labels:
app: nginx
spec:
containers:
- name: nginx-container
image: nginx
ports:
- containerPort: 80
或者使用 kubectl run
命令来创建 Pod:
kubectl run nginx-pod --image=nginx --restart=Never --port=80
Pod 的 yaml 文件中,有几个重要的字段:
- apiVersion:指定 Pod 的 API 版本,一般都是 v1
- kind:指定资源类型,Pod 的类型是 Pod
- metadata:指定 Pod 的元数据,包括 Pod 的名称、标签等
- spec:指定 Pod 的规格,包括 Pod 中的容器、存储卷等
Pod 的 yaml 文件中,spec 字段是最重要的,它包含了 Pod 中的容器、存储卷等信息,下面是 spec 字段的详细介绍:
spec:
containers: # 容器列表
- name: nginx-container # 容器名称
image: nginx # 容器镜像
ports: # 容器端口列表
- containerPort: 80 # 容器端口
restartPolicy: Never # Pod 重启策略
Pod 的 yaml 文件中,spec 字段中的 containers
字段是一个容器列表,可以在一个 Pod 中运行多个容器,这些容器会被同时调度到同一个工作节点上。
Pod 的 yaml 文件中,spec 字段中的 restartPolicy
字段是 Pod 的重启策略,它有三个取值:
- Always:Pod 一旦终止就立即重启,用于部署应用
- OnFailure:Pod 只有在非零退出码时才重启,用于批处理任务
- Never:Pod 不重启,用于静态 Web 网站
Pod 的 yaml 文件中,spec 字段中的 nodeName
字段是 Pod 的调度节点,如果指定了 nodeName 字段,那么 Pod 就会被调度到指定的节点上,如果没有指定 nodeName 字段,那么 Pod 就会被调度到一个合适的节点上。
(1)自主式 Pod
自主式 Pod
是指没有被任何控制器管理的 Pod,它的生命周期由用户手动管理,一般用于测试和开发环境。示例如下:
[root@master tomcat-test]# vim pod-tomcat.yaml
apiVersion: v1
kind: Pod
metadata:
name: tomcat-test
namespace: default
labels:
app: tomcat
spec:
containers:
- name: tomcat-java
ports:
- containerPort: 8080
image: xianchao/tomcat-8.5-jre8:v1
imagePullPolicy: IfNotPresent
# 导入镜像,且发送文件给node
[root@master tomcat-test]# scp xianchao-tomcat.tar.gz [email protected]:/root/
# 将镜像导入到本地
[root@master tomcat-test]# docker load -i xianchao-tomcat.tar.gz
[root@node ~]# docker load -i xianchao-tomcat.tar.gz
df64d3292fd6: Loading layer [==================================================>] 4.672MB/4.672MB
0c3170905795: Loading layer [==================================================>] 3.584kB/3.584kB
9bca1faaa73e: Loading layer [==================================================>] 79.44MB/79.44MB
e927085edc33: Loading layer [==================================================>] 2.56kB/2.56kB
e5f8376fd9dc: Loading layer [==================================================>] 27.08MB/27.08MB
e82a3681bb38: Loading layer [==================================================>] 2.048kB/2.048kB
Loaded image: xianchao/tomcat-8.5-jre8:v1
# 查看镜像
[root@master tomcat-test]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
xianchao/tomcat-8.5-jre8 v1 4ac473a3dd92 4 years ago 108MB
# 更新资源清单文件
[root@master tomcat-test]# kubectl apply -f pod-tomcat.yaml
pod/tomcat-test created
# 查看 Pod 是否创建成功
[root@master tomcat-test]# kubectl get pods -o wide -l app=tomcat
NAME READY STATUS IP NODE
tomcat-test 1/1 Running 10.244.1.13 node
# 查看 Pod 详情
[root@master tomcat-test]# kubectl describe -f pod-tomcat.yaml
# 注意:
# 自主式Pod是可以删除的,而且一旦被删除是彻底删除。
# 这在生产环境具有非常大风险,因此要应该选择使用控制器管理。
[root@master tomcat-test]# kubectl delete -f pod-tomcat.yaml
pod "tomcat-test" deleted
[root@master tomcat-test]# kubectl get pods -o wide -l app=tomcat
No resources found in default namespace.
(2)控制器管理的 Pod
常见的管理 Pod 的控制器:Replicaset、Deployment、Job、CronJob、Daemonset、Statefulset。
控制器管理的 Pod 可以确保 Pod 始终维持在指定的副本数运行。通过 Deployment 管理 pod 案例:
# 上传xianchao-nginx.tar.gz 上传到node节点
[root@node ~]# ls
anaconda-ks.cfg install.sh original-ks.cfg xianchao-nginx.tar.gz
# 创建资源清单文件
[root@master ~]# mkdir nginx-test && cd nginx-test
[root@master nginx-test]# vi nginx-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-test
labels:
app: nginx-deploy
spec:
selector:
matchLabels:
app: nginx
replicas: 2
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: my-nginx
image: nginx
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
# 更新资源清单文件
[root@master nginx-test]# kubectl apply -f nginx-deploy.yaml
deployment.apps/nginx-test created
# 查看deployment
[root@master nginx-test]# kubectl get deploy -l app=nginx-deploy
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-test 2/2 2 2 87s
# 查看replicaset
[root@master nginx-test]# kubectl get rs -l app=nginx
NAME DESIRED CURRENT READY AGE
nginx-test-854985cc6f 2 2 2 2m11s
# 查看pod
[root@master nginx-test]# kubectl get pods -o wide -l app=nginx
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-test-854985cc6f-9qnnj 1/1 Running 0 2m56s 10.244.1.18 node <none> <none>
nginx-test-854985cc6f-fw55w 1/1 Running 0 2m56s 10.244.0.250 master <none> <none>
# 查看deployment详情
[root@master nginx-test]# kubectl describe deploy nginx-test
# 删除nginx-test-854985cc6f-9qnnj这个Pod
[root@master nginx-test]# kubectl delete pod nginx-test-854985cc6f-9qnnj
pod "nginx-test-854985cc6f-9qnnj" deleted
# 发现重新创建了一个新的pod
[root@master nginx-test]# kubectl get pods -o wide -l app=nginx
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-test-854985cc6f-dfm5b 1/1 Running 0 6s 10.244.1.19 node <none> <none>
nginx-test-854985cc6f-fw55w 1/1 Running 0 4m10s 10.244.0.250 master <none> <none>
由此可见,通过 deployment 管理的 pod,当 pod 被删除后,会自动创建一个新的 pod,保证 pod 的副本数始终维持在指定副本数量。
二、如何创建一个Pod资源
k8s创建pod流程:
Pod 是 Kubernetes 中最基本的部署调度单位,可以包含 container,逻辑上表示某种应用的一个实例。如:一个web站点应用由前端、后端、数据库构建而成,这个站点的所有容器可以放在一个 Pod 中,也可以将前端、后端、数据库分别放在不同的 Pod 中,这取决于用户的实际需求。
1、创建 pod 流程
第一步:用户通过 kubectl 命令或者 API Server 发送创建 Pod 的请求。
第二步:apiserver 接收到请求后,将 yaml 文件转换成 json 格式,然后将 json 格式的 Pod 对象存储到 etcd 中。
第三步:apiserver 将 Pod 对象转发给控制器管理器。调度器使用调度算法为 Pod 选择合适的 Node 节点,将node信息给apiserver,apiserver将node信息存储到etcd中。
- 调度器的调度算法:
- 1、过滤器:过滤掉不符合要求的节点,如:资源不足、污点、亲和性等。
- 2、优选器:对符合要求的节点进行打分,选择分数最高的节点。
第四步:apiserver 通过 watch 机制,调用 kebelet,指定 pod 信息,调用 docker api 在 node 节点上创建 pod。
第五步:创建完成后反馈给 kubelet,kubelet 又将pod的状态信息反馈给 apiserver,apiserver 将 pod 的状态信息存储到 etcd 中。
2、资源清单yaml文件书写技巧
yaml文件书写技巧:
- 1、yaml文件中的空格不能随意添加,否则会报错。
- 2、yaml文件中的缩进必须是两个空格,不能是tab键。
- 3、yaml文件中的注释必须是#号开头。
- 4、yaml文件中的字符串必须加上引号,否则会报错。
- 5、yaml文件中的字符串如果有特殊字符,必须加上单引号或者双引号,否则会报错。
- 6、yaml文件中的字符串如果有多行,必须使用|或者>,否则会报错。
编写yaml文件遇到字段含义不明确时,可以使用kubectl explain命令查看字段的含义。
(1)kubectl explain 命令
kubelet explain 命令可以查看资源清单文件中的字段的含义。
# kubelet explain 语法
[root@master ~]# kubectl explain -h
List the fields for supported resources. # 列出支持的资源的字段
This command describes the fields associated with each supported API resource. Fields are identified via a simple JSONPath identifier: # 该命令描述与每个支持的API资源相关联的字段。字段通过简单的JSONPath标识符进行标识:
<type>.<fieldName>[.<fieldName>]
Add the --recursive flag to display all of the fields at once without descriptions. Information about each field is retrieved from the server in OpenAPI format. # 添加--recursive标志以一次显示所有字段而无需描述。有关每个字段的信息以OpenAPI格式从服务器检索。
Use "kubectl api-resources" for a complete list of supported resources. # 使用“kubectl api-resources”获取支持的资源的完整列表。
Examples:
# 获取资源及其字段的文档
kubectl explain pods
# 获取资源的特定字段的文档
kubectl explain pods.spec.containers
Options:
--api-version='': 获取特定API版本(API组/版本)的不同解释
--recursive=false: 打印字段的字段(目前只有1级深)
查看pod的字段,示例如下所示:
[root@master ~]# kubectl explain pods
KIND: Pod # 资源类型
VERSION: v1 # 资源版本
DESCRIPTION: # 描述
Pod是可以在主机上运行的容器集合。此资源由客户端创建并安排到主机上。
FIELDS: # 字段
apiVersion <string> # api版本
APIVersion定义此对象的版本化模式。服务器应将已识别的模式转换为最新的内部值,并且可以拒绝未识别的值。
kind <string> # 字符串类型的值,代表要创建的资源类型
Kind是表示此对象表示的REST资源的字符串值.服务器可以从客户端提交请求的端点推断此值。不能更新。在CamelCase中。
metadata <Object> # metadata是对象,定义元数据属性信息
标准对象的元数据
spec <Object> # 制定了定义pod的规格,里面包含容器的信息
Pod的期望行为的规范。
status <Object> # 状态,不可修改,定义pod时不需要填写
最近观察到的Pod的状态。这些数据可能不是最新的。状态字段,由系统填充,只读。
查看pod.metadata的字段,示例如下所示:
[root@master ~]# kubectl explain pods.metadata
KIND: Pod # 资源类型
VERSION: v1 # 资源版本
RESOURCE: metadata <Object> # 资源为 metadata 对象<object>
DESCRIPTION:
标准对象的元数据
ObjectMeta是所有持久化资源必须具有的元数据,其中包括用户必须创建的所有对象。
FIELDS: # 字段
annotations <map[string]string> # annotations是注解,map类型表示对应值是键值对
注释是存储在资源中的非结构化键值映射,可以由外部工具设置以存储和检索任意元数据。它们不可查询,并且在修改对象时应该保留。
creationTimestamp <string>
创建时间戳是表示创建此对象时的服务器时间的时间戳。不能保证在单独操作中以发生之前的顺序设置它。客户端可能不会设置此值。它以RFC3339形式表示,并且处于UTC中。可以设置为任何时间,但一旦设置,就不能更改。只读。
deletionGracePeriodSeconds <integer>
此对象在从系统中删除之前允许优雅终止的秒数。仅在设置deletionTimestamp时设置。可能只缩短。只读。
deletionTimestamp <string> # 删除时间戳
删除时间戳是表示删除此对象时的服务器时间的时间戳。如果未设置,则此对象尚未删除。只读。
finalizers <[]string> # finalizers是终结器,[]string表示对应值是字符串数组
终结器是在删除对象时运行的一组非同步任务。在删除对象时,系统会阻止对该对象的修改,直到所有终结器都已完成。终结器可能会以任何顺序运行。系统不会保证它们将在删除操作完成之前运行,或者将在删除操作完成之后运行。终结器可能会在删除操作完成之前或之后失败。终结器是在删除操作完成之前运行的,因此它们可以在删除操作完成之前阻止对象的删除。失败的终结器可能会在下一次删除操作中重新运行。终结器通常用于将群集外部的资源与Kubernetes对象关联起来,以便在删除对象时清理这些资源。
generateName <string>
生成名称是服务器使用的可选前缀,仅在未提供名称字段时生成唯一名称。如果使用此字段,则返回给客户端的名称将与传递的名称不同。此值还将与唯一后缀组合。提供的值具有与名称字段相同的验证规则,并且可能会被所需的后缀的长度截断,以使该值在服务器上唯一。
generation <integer>
表示所需状态的特定生成的序列号。由系统填充,只读。
labels <map[string]string>
标签是一组键值对,用于组织和分类对象. 可以与复制控制器和服务的选择器匹配。
managedFields <[]Object>
管理字段将工作流ID和版本映射到由该工作流管理的字段集。这主要用于内部事务处理,用户通常不需要设置或了解此字段。工作流可以是用户的名称,控制器的名称,或者特定应用程序路径的名称,例如“ci-cd”。字段集始终在工作流修改对象时使用的版本中。
name <string>
名称必须在命名空间内唯一。在创建资源时是必需的,尽管某些资源可能允许客户端自动请求生成适当的名称。名称主要用于创建幂等性和配置定义。不能更新。
namespace <string>
命名空间定义了每个名称必须唯一的空间。空命名空间等同于“默认”命名空间,但“默认”是规范表示。并非所有对象都必须限定于命名空间 - 这些对象的此字段的值将为空。
ownerReferences <[]Object>
依赖的对象列表。如果列表中的所有对象都已删除,则将对此对象进行垃圾回收。如果此对象由控制器管理,则列表中的条目将指向此控制器,其中控制器字段设置为true。不能有多个管理控制器。
resourceVersion <string>
资源版本,用于乐观锁,客户端不需要修改,只读
selfLink <string>
selfLink是一个遗留的只读字段,不再由系统填充。
uid <string>
UID是此对象的时间和空间唯一值。通常由服务器在成功创建资源时生成,并且不允许在PUT操作上更改。客户端可以使用此值确定是否已替换服务器上的对象。不能更新。更多信息请参见类型元数据。
3、通过资源清单文件创建pod
[root@master tomcat-test]# vi pod-tomcat.yaml
apiVersion: v1
kind: Pod
metadata:
name: tomcat-test
namespace: default
labels:
app: tomcat-pod-first
spec:
containers:
- name: tomcat-first
image: tomcat:8.5.51
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
# 更新资源清单文件
[root@master tomcat-test]# kubectl apply -f pod-tomcat.yaml
# 查看pod是否创建成功
[root@master tomcat-test]# kubectl get pods -o wide -l app=tomcat-pod-first
# 查看pod日志
[root@master tomcat-test]# kubectl logs tomcat-test
# 进入刚刚创建的Pod
[root@master tomcat-test]# kubectl exec -it tomcat-test /bin/bash
# 架设pod有多个容器时,可以指定容器名称
[root@master tomcat-test]# kubectl exec -it tomcat-test -c tomcat-first /bin/bash
4、通过命令行创建pod
# Kubectl run语法
标签:tomcat,解读,nginx,深入,test,Pod,root,pod
From: https://www.cnblogs.com/xiugeng/p/17527249.html