目录
理论
参考官方网文档:Pod | Kubernetes
在Kubernetes中,Pod是最基本的调度单元,可以包含一个或多个容器,它们共享网络和存储资源,并共同运行在一个节点上。
-
Pod的定义:
- Pod是Kubernetes中最小的可部署单元,通常包含一个或多个容器、存储资源、一个唯一的网络IP以及关于如何运行容器的配置选项。
- Pod可以被创建、调度到集群的节点上运行,并受Kubernetes的管理。
-
Pod的生命周期:
- 创建:通过Pod描述文件(YAML或JSON)定义Pod的规格。
- 调度:Kubernetes将Pod调度到可用节点,考虑资源需求和亲和性规则。
- 运行:Pod中的容器开始执行用户定义的应用程序。
- 终止:Pod完成任务或出现故障时终止,Kubernetes将自动重启或重新调度Pod。
-
Pod的管理:
- 控制器:如Deployment、StatefulSet等,用于管理Pod的生命周期,确保Pod的副本数目和健康状态。
- 命名空间:Pod通过命名空间进行逻辑隔离,以便在集群中组织和管理资源。
-
Pod的网络:
- 每个Pod都有自己的IP地址,所有Pod中的容器共享此IP。
- 可以使用Service将Pod公开到集群内部或外部的其他服务。
-
Pod的调度策略:
- Kubernetes根据Pod的资源需求、节点上的资源可用性和亲和性/反亲和性规则来决定将Pod调度到哪个节点上。
- 可以通过NodeSelector、Affinity和Taints/Tolerations等方式进行节点选择和约束。
基础结构
apiVersion: v1 # API版本,v1表示这个Pod描述文件遵循Kubernetes API的第1版规范
kind: Pod # 资源类型,这里定义的是一个Pod
metadata: # 元数据部分,用于描述Pod的基本信息
name: <pod-name> # Pod的名称,集群内必须唯一
namespace: <namespace> # 可选,指定Pod所在的命名空间,若不指定则使用默认命名空间
labels: # 标签,用于标识和选择Pod,可以帮助进行分组和查询
app: <app-name> # 标签的键值对,用于标识该Pod属于哪个应用
spec: # 规格部分,定义Pod的实际配置
containers: # 容器列表,定义Pod中运行的容器
- name: <container-name> # 容器名称,必须在Pod内唯一
image: <image> # 容器使用的镜像,通常包含镜像仓库路径、镜像名称和版本标签
ports: # 容器端口列表,声明容器暴露的端口
- containerPort: <port> # 容器监听的端口号,用于通信
resources: # 资源请求和限制,定义容器所需的计算资源
requests: # 容器启动时需要的最低资源
memory: "<amount>" # 请求的内存量,通常以Mi、Gi为单位
cpu: "<amount>" # 请求的CPU资源,通常以核数表示
limits: # 容器能够使用的最大资源
memory: "<amount>" # 限制的内存量
cpu: "<amount>" # 限制的CPU资源
env: # 环境变量列表,传递给容器的环境变量
- name: <env-var-name> # 环境变量名称
value: <env-var-value> # 环境变量的值
volumeMounts: # 卷挂载列表,将定义的卷挂载到容器内的文件系统路径
- name: <volume-name> # 卷的名称,必须与volumes部分的名称一致
mountPath: <mount-path> # 容器内的挂载路径
volumes: # 卷的定义,提供给容器使用的存储资源
- name: <volume-name> # 卷的名称,供volumeMounts引用
emptyDir: {} # 一个示例卷类型,表示一个空目录卷,生命周期与Pod相同,实际使用时可以指定其他类型,如persistentVolumeClaim、hostPath等
实践细节点记录:
1. 当你使用
kubectl delete
命令删除一个 Pod 或其他资源时,拉取的镜像不会被删除。kubectl delete
只会删除 Kubernetes 中的资源(如 Pods、Deployments 等),而不会影响已经下载到节点上的镜像。
2. Pod 的名称和容器的名称都必须遵循 Kubernetes 的命名规则。具体来说,名称必须符合 RFC 1123 子域名的要求,即只能包含小写字母(
a-z
)、数字(0-9
)、短横线(-
)或点(.
),并且必须以字母或数字开头和结尾,不能大写字母。
3. Kubernetes 中,Pod 的
ports
配置和 Docker Compose 的ports
配置在用途上类似,只是在详细信息里的声明,并没有实际使用到,定义端口是为了将来可能的服务暴露和网络配置做准备。当Kubernetes Service 和网络策略定义应用时,在pod中声明的prots才会实际使用。在 Kubernetes 中,ports
配置指定了容器内部的端口信息,实际的访问和流量路由依赖于 Service。
4. 在 Kubernetes 中,NodePort 类型的 Service 会在每个节点上打开一个端口,并将流量转发到对应的 Pod。这个端口是由 Kubernetes 自动分配的,你可以在 Service 的描述中找到这个端口号。
然而,这个端口只在节点的网络命名空间中打开,你无法直接在宿主机上看到它。这是因为 Kubernetes 使用了网络插件(如 Calico、Flannel 等)来实现网络功能,这些插件会在每个节点上创建一个虚拟网络,并将流量转发到对应的 Pod。
如果你想要从宿主机访问这个 Service,你需要使用节点的 IP 地址和 Service 的 NodePort。例如,如果你的节点的 IP 地址是
192.168.226.22
,Service 的 NodePort 是31720
,那么你可以通过192.168.226.22:31720
来访问这个 Service。然而,由于 Kubernetes 的网络模型,你实际上可以使用集群中的任何节点的 IP 地址来访问这个 Service。这是因为 Kubernetes 的网络插件会在每个节点上创建一个虚拟网络,并将流量转发到对应的 Pod。因此,无论你使用哪个节点的 IP 地址,流量都会被正确地转发到对应的 Pod。
5. Kubernetes 自动分配的 NodePort,而是使用 Service 和 Pod 中定义的端口,你可以将 Service 的类型设置为
ClusterIP
,并设置nodePort
字段为0
。这样,Kubernetes 将不会为 Service 分配 NodePort,而是使用 Pod 的端口。
6. 在 Kubernetes 中,一个 Pod 中的所有容器都运行在同一个节点上。你不能为每个容器指定不同的节点。如果你想要将 Pod 运行在不同的节点上,你需要创建多个 Pod。
7. 在 Kubernetes 中,Service 是一种抽象,用于定义一组 Pod 的访问方式。一个 Service 可以选择一个或多个 Pod,并将流量路由到这些 Pod。然而,你不能直接在 Service 中定义多个 Pod。你需要为每个 Pod 创建一个 Service。
8. Pod: 一个 Pod 可以包含多个容器。这些容器共享 Pod 的网络和存储资源,因此它们可以通过 localhost 和容器内的端口进行通信。
9. Service: Service 是 Kubernetes 用于在 Pod 和外部世界之间提供网络访问的资源。Service 为一个或多个 Pod 提供了一个稳定的访问点。Service 的名称在其命名空间中必须唯一,以确保网络路由的准确性。
10. 一个 Pod 内的每个端口号应该是唯一的。如果在 Pod 中定义了多个容器,并且这些容器使用相同的端口号,它们共享这个端口号。尽管容器可以共享端口号,但是每个容器的
containerPort
必须唯一,以避免冲突。如果你希望在集群节点上直接访问这些IP地址的域名,确实需要在节点的/etc/hosts
文件中进行配置。这种配置一般用于节点内部服务的本地测试和调试。如果你希望在整个集群中进行DNS解析(不仅限于Pod内),你可以考虑使用Kubernetes内置的DNS服务(如CoreDNS)。
11. 当一个节点在 Kubernetes 集群中宕机后,并不会直接影响其他节点的运行。如果宕机的节点恢复上线,它通常会自动重新加入集群并恢复正常工作,前提是该节点的配置和状态仍然有效。
12.
hostNetwork: true
- 用途: 使Pod的网络Namespace与宿主机共享。这意味着Pod中的所有容器将直接使用宿主机的网络栈(例如,IP地址和网络接口)。
- 场景: 如果你希望容器直接与宿主机网络交互(例如监听宿主机的端口),可以启用它。
hostIPC: true
- 用途: 使Pod的IPC Namespace与宿主机共享。这样,Pod中的容器可以访问和共享宿主机的IPC资源(如信号量和共享内存)。
- 场景: 如果你的应用需要与宿主机或其他容器进行IPC通信,或者需要访问宿主机的共享内存,可以启用它。
hostPID: true
- 用途: 使Pod的PID Namespace与宿主机共享。这样,Pod中的容器可以看到宿主机的进程,并与之交互。
- 场景: 如果你需要监控或管理宿主机上的进程,或者需要与宿主机的进程进行交互(例如通过PID控制某些服务),可以启用它。
13.
preStop
钩子中的命令不会直接打印到宿主机的终端中,因为它们在容器内部执行。这里的输出只会记录到容器的日志中,而不会直接显示在宿主机的终端或主机的标准输出上。
14.
postStart
:用于定义容器启动后的钩子函数。用于执行一些初始化操作,比如设置环境变量、准备应用所需的文件或配置等
preStop
:用于定义容器终止前的钩子函数。常用于优雅关闭应用程序、保存状态、释放锁定资源等。
15. 在 YAML 文件中,
|
是一个表示多行文本块的操作符。它允许你在不转义换行符的情况下编写多行字符串,并且保留每行的换行符。
16. 根据 Kubernetes 的要求,
nodePort
端口号必须在30000
到32767
的范围内
# 指定Kubernetes API的版本为v1
apiVersion: v1
# 定义一个命名空间
kind: Namespace
metadata:
# 设置命名空间的名称为my-namespace
name: my-namespace
---
# 指定Kubernetes API的版本为v1
apiVersion: v1
# 定义一个Pod
kind: Pod
metadata:
# 设置Pod的名称为title
name: title
# 设置Pod所属的命名空间为my-namespace
namespace: my-namespace
# 为Pod设置一个标签app为title
labels:
app: title
spec:
# 设置容器的详细配置
containers:
# 设置容器名称为nginx
- name: nginx
# 定义容器所使用的镜像为nginx
image: nginx
# 设置镜像拉取策略为如果本地不存在则拉取
imagePullPolicy: IfNotPresent
# 设置容器的资源限制和请求
resources:
limits:
# 限制容器可以使用的最大CPU为1核
cpu: "1"
# 限制容器可以使用的最大内存为1Gi
memory: "1Gi"
requests:
# 请求容器至少需要1核CPU
cpu: "1"
# 请求容器至少需要500Mi内存
memory: "500Mi"
# 设置容器的端口映射
ports:
- containerPort: 80 # 设置容器内部的端口为80
hostPort: 80 # 设置宿主机的端口为80
hostIP: 192.168.226.22 # 设置宿主机的IP地址为192.168.226.22
# 配置启动和停止钩子
lifecycle:
postStart:
exec:
command:
- /bin/sh
- -c
- |
echo "wo shi hello Nginx!" >> /usr/share/nginx/html/index.html
preStop:
exec:
command:
- /bin/sh
- -c
- |
echo "baibai,zaijian" >> /usr/share/nginx/html/index.html
- name: jenkins
image: jenkins/jenkins:lts
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
hostPort: 8080
# 设置Pod的重启策略为始终重启
restartPolicy: Always
# 设置Pod运行的节点为node01
nodeName: node01
# 配置Pod与宿主机共享Namespace
hostNetwork: true # 共享Network Namespace
hostIPC: true # 共享IPC Namespace
hostPID: true # 共享PID Namespace
hostAliases:
- ip: "192.168.226.21" # 第一个IP地址
hostnames:
- "service1.local" # 对应的域名
- "api1.local" # 另一个对应的域名
- ip: "192.168.226.22" # 第二个IP地址
hostnames:
- "service2.local" # 对应的域名
- "api2.local" # 另一个对应的域名
- ip: "192.168.226.23" # 第三个IP地址
hostnames:
- "service3.local" # 对应的域名
- "api3.local" # 另一个对应的域名
---
# 指定Kubernetes API的版本为v1
apiVersion: v1
# 定义一个Service
kind: Service
metadata:
# 设置Service的名称为title-service-nginx
name: title-service-nginx
# 设置Service所属的命名空间为my-namespace
namespace: my-namespace
spec:
# 设置Service的选择器
selector:
app: title # 选择标签为app=title的Pod
# 设置Service的端口映射
ports:
- protocol: TCP # 设置协议为TCP
port: 80 # 设置Service的端口为80
targetPort: 80 # 设置目标端口为80
nodePort: 0 # 设置NodePort为0
type: ClusterIP # 设置Service的类型为ClusterIP
---
apiVersion: v1
kind: Service
metadata:
# 设置Service的名称为title-service-jenkins
name: title-service-jenkins
# 设置Service所属的命名空间为my-namespace
namespace: my-namespace
spec:
# 设置Service的选择器
selector:
app: title
ports:
- protocol: TCP
port: 8080
targetPort: 8080
type: NodePort
容器监控检查及恢复机制
在 Kubernetes 中,探针(Probe)用于检测容器的健康状态和就绪状态,确保容器能够正常运行并为应用提供服务。Kubernetes 提供了三种主要的探针方式:
Exec 探针
- 描述:使用容器内的命令或脚本来检查容器的健康状况。
- 工作方式:Kubernetes 在容器内执行指定的命令,根据命令的退出状态来判断探针是否成功。退出状态码为
0
表示探针成功,非0
表示探针失败。 - 适用场景:适用于无法通过网络检查健康状态的容器,或者需要自定义检查逻辑的场景。
- 示例:
livenessProbe: exec: command: ["cat", "/tmp/healthy"] initialDelaySeconds: 5 periodSeconds: 10
HTTP GET 探针
- 描述:通过向容器内运行的 HTTP 服务器发送 GET 请求来检查健康状况。
- 工作方式:Kubernetes 向指定的路径发送 HTTP GET 请求,如果响应状态码在
200-299
范围内,探针成功;否则探针失败。 - 适用场景:适用于容器内运行了 HTTP 服务,并且可以通过 HTTP 请求来判断健康状况的场景。
- 示例:
readinessProbe: httpGet: path: /healthz port: 8080 initialDelaySeconds: 5 periodSeconds: 10
TCP Socket 探针
- 描述:通过尝试连接容器内的指定端口来检查健康状况。
- 工作方式:Kubernetes 尝试连接到指定的 TCP 端口,如果能够成功连接,探针成功;如果连接失败,探针失败。
- 适用场景:适用于运行了 TCP 服务的容器,可以通过端口连接状态来判断健康状况的场景。
- 示例:
livenessProbe: tcpSocket: port: 8080 initialDelaySeconds: 5 periodSeconds: 10
探针的配置选项
所有三种探针类型都可以配置以下选项:
initialDelaySeconds
:容器启动后,等待多少秒后才开始进行第一次探测。periodSeconds
:探针之间的时间间隔(以秒为单位)。timeoutSeconds
:探针等待响应的超时时间(以秒为单位)。successThreshold
:探针判定为成功之前,必须连续成功的次数。默认值是 1。failureThreshold
:探针判定为失败之前,必须连续失败的次数。默认值是 3。
POD 的恢复策略
在 Kubernetes 中,Pod 的恢复策略(Restart Policy)定义了当容器失败或退出时,Kubernetes 如何处理这些容器。恢复策略主要有以下三种类型:
Always
- 描述:无论容器以何种状态退出,Kubernetes 都会始终重新启动容器。这是最常用的恢复策略。
- 适用场景:适用于大部分需要持续运行的服务或应用,如 Web 服务、后台处理任务等。
- 默认值:对于
Deployment
、ReplicaSet
、DaemonSet
等资源,默认使用Always
策略。
OnFailure
- 描述:仅当容器因非 0 退出状态(表示失败)退出时,Kubernetes 才会重新启动容器。如果容器正常退出(状态码为 0),则不会重新启动。
- 适用场景:适用于只在出现错误时才需要重启的批处理任务或作业(job),如数据处理、批量任务等。
- 默认值:对于
Job
资源,默认使用OnFailure
策略。
Never
- 描述:无论容器如何退出,Kubernetes 都不会重新启动容器。
- 适用场景:适用于不需要重启的短暂任务,例如一次性运行的任务或调试容器。
- 默认值:对于
Pod
,默认策略不是Never
,但可以显式设置。
注意事项
-
Pod 的默认恢复策略:在创建 Pod 时,如果不指定
restartPolicy
,默认值为Always
。因此,除非明确指定,否则 Kubernetes 会自动重启失败的容器。 -
恢复策略的作用范围:恢复策略适用于 Pod 内的所有容器,不能为单个容器设置不同的恢复策略。
-
与控制器的关系:当使用控制器如
Deployment
、ReplicaSet
、StatefulSet
时,恢复策略通常为Always
。这些控制器会管理 Pod 的生命周期,确保应用的高可用性。