云原生-Kubernetes Pod 介绍
K8s学习
Pod 直译是豆荚,可以把容器想像成豆荚里的豆子,把一个或多个关系紧密的豆子包在一起
就是豆荚(一个 Pod)。在 k8s 中我们不会直接操作容器,而是把容器包装成 Pod 再进行管
理。
一、 Pod 介绍与原理讲解
是 Kubernetes 项目中最小的 API 对象。如果换一个更专业的说法,我们可以这样描述:
Pod,是 Kubernetes 项目的原子调度单位。
Pod 是运行服务的基础.
基础容器是 pause.
每启动一个 Pod 都会附加启动这样一个容器,它的作用就只是简单的等待,设置 Pod 的网
络。
一个 Pod 中的应用容器共享同一组资源:
(1)PID 命名空间:Pod 中的不同应用程序可以看见其他应用程序的进程 ID
(2)网络命名空间:Pod 中的多个容器能访问同一个 IP 和端口范围
(3)IPC 命名空间:Pod 中的多个容器能够使用 SystemV IPC 或 POSIX 消息队列进行通
信。
(4)UTS 命名空间:Pod 中的多个容器共享一个主机名
(5)Volumes(共享存储卷):Pod 中的各个容器可以访问在 Pod 级别定义的 Volumes
每个 pod 中容器的镜像应该不同(不同的应用),避免端口重复
Pod 的设计
第一个最典型的例子是:WAR 包与 Web 服务器
第二个例子,则是容器的日志收集。比如,我现在有一个应用,需要不断地把日志文件输出
到容器的 /var/log 目录中。这时,我就可以把一个 Pod 里的 Volume 挂载到应用容器的
/var/log 目录上。然后,我在这个 Pod 里同时运行一个 sidecar 容器,它也声明挂载同一
个 Volume 到自己的 /var/log 目录上。这样,接下来 sidecar 容器就只需要做一件事儿,
那 就 是不 断地 从自 己的 /var/log 目 录里 读取 日 志文 件, 转发 到 MongoDB 或者
Elasticsearch 中存储起来。这样,一个最基本的日志收集工作就完成了。跟第一个例子一样,
这个例子中的 sidecar 的主要工作也是使用共享的 Volume 来完成对文件的操作。
二、 Pod 创建与删除
1、kubectl 创建 pod
K run nginx --image=nginx:1.9 –port=80
状态检查
K get pod name
K describe pod name
K logs name
2、Yaml 基本语法规则
大小写敏感
使用缩进表示层级关系
缩进时不允许使用 Tab 键,只允许使用空格。
缩进的空格数目不重要,只要相同层级的元素左侧对齐即可
# 表示注释,从这个字符一直到行尾,都会被解析器忽略。
3、Yaml 文件创建 pod
k run nginx --image=nginx:1.9 --port=80 --dry-run=client -o yaml>nginx.yaml
cat nginx.yaml
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: nginx
name: nginx
spec:
containers:
- image: nginx:1.9
name: nginx
ports:
- containerPort: 80
resources: {}
dnsPolicy: ClusterFirst restartPolicy: Always
status: {}
4、多容器 Pod 创建
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: nginx
name: multi-container
spec:
containers:
- image: nginx:1.9
name: nginx
ports:
- containerPort: 80
resources: {}
- image: tomcat
name: tomcat
ports:
- containerPort: 8080
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}
三、 Pod 生命周期管理
Pod 生命周期的变化,主要体现在 Pod API 对象的 Status 部分,这是它除了
Metadata 和 Spec 之外的第三个重要字段。其中,pod.status.phase,就是 Pod 的当前状
态,
它有如下几种可能的情况:
Pending。这个状态意味着,Pod 的 YAML 文件已经提交给了 Kubernetes,API 对象
已经被创建并保存在 Etcd 当中。但是,这个 Pod 里有些容器因为某种原因而不能被顺利
创建。比如,调度不成功。
Running。这个状态下,Pod 已经调度成功,跟一个具体的节点绑定。它包含的容器都
已经创建成功,并且至少有一个正在运行中。
Succeeded。这个状态意味着,Pod 里的所有容器都正常运行完毕,并且已经退出了。
这种情况在运行一次性任务时最为常见。
Failed。这个状态下,Pod 里至少有一个容器以不正常的状态(非 0 的返回码)退出。
这个状态的出现,意味着你得想办法 Debug 这个容器的应用,比如查看 Pod 的 Events 和
日志。
Unknown。这是一个异常状态,意味着 Pod 的状态不能持续地被 kubelet 汇报给
kube-apiserver,这很有可能是主从节点(Master 和 Kubelet)间的通信出现了问题。
更进一步地,Pod 对象的 Status 字段,还可以再细分出一组 Conditions。这些细分状
态的值包括:PodScheduled、Ready、Initialized,以及 Unschedulable。它们主要用于描述
造成当前 Status 的具体原因是什么。
Restart policy
Restart policy for all containers within the pod. One of Always, OnFailure, Never.
Default to Always
1、Pod 资源的配额和限制
apiVersion: v1
kind: Pod
metadata:
name: qos-demo
namespace: qos-example
spec:
containers:
- name: qos-demo-ctr
image: nginx
resources:
limits:
memory: "200Mi"
cpu: "700m"
requests:
memory: "200Mi"
cpu: "700m"
kubectl get pod qos-demo --namespace=qos-example --output=yaml
spec:
containers: ...
resources:
limits:
cpu: 700m
memory: 200Mi
requests:
cpu: 700m
memory: 200Mi
...
status:
qosClass: Guaranteed
k describe pod -A |grep QoS
Service SLA
No define best of effort
Request < limit burstable
Request = limit guaranteed
五、Pod 的健康检查
探针是由 kubelet 对容器执行的定期诊断。要执行诊断,kubelet 调用由容器实现的
Handler。有三种类型的探针:
Exec 探针:执行进程的地方,容器的状态由进程的退出状态代码确认;
Http get 探针:向容器发送 HTTP GET 请求,通过响应的 HTTP 状态代码判断容器是否准备
好;如果响应的状态码大于等于 200 且小于 400,则诊断被认为是成功的
Tcp socket 探针:它打开一个 TCP 连接到容器的指定端口,如果连接己建立,则认为容器己
准备就绪。
kubernetes 会周期性地调用探针,并根据就绪探针的结果采取行动。如果某个 pod 报告它
尚未准备就绪,则会从该服务中删除该 pod。如果 pod 再次准备就绪,则重新添加 pod;
每次探测都将获得以下三种结果之一:
成功:容器通过了诊断。
失败:容器未通过诊断。
未知:诊断失败,因此不会采取任何行动
livenessProbe:指示容器是否正在运行。如果存活探测失败,则 kubelet 会杀死容器,并且
容器将受到其 重启策略 的影响。如果容器不提供存活探针,则默认状态为 Success
readinessProbe:指示容器是否准备好服务请求。如果就绪探测失败,端点控制器将从与 Pod
匹配的所有 Service 的端点中删除该 Pod 的 IP 地址。初始延迟之前的就绪状态默认为
Failure。如果容器不提供就绪探针,则默认状态为 Success
只要 pod 的标签和服务的 pod 选择器匹配,pod 就可以作为服务的后端,但是如果 pod 没
有准备好,是不能处理请求的,这时候就需要就绪探针了,用来检查 pod 是否已经准备好
了,如果检查成功就可以作为服务的后端处理消息了;
1、向 pod 添加检测探针 - 存活检测
livenessProbe-exec
apiVersion: v1
kind: Pod
metadata:
name: liveness-exec-pod
namespace: default
spec:
containers:
- name: liveness-exec-container
image: busybox
imagePullPolicy: IfNotPresent
command: ["/bin/sh","-c","touch /tmp/live ; sleep 60; rm -rf /tmp/live; sleep 3600"]
livenessProbe:
exec:
command: ["test","-e","/tmp/live"]
initialDelaySeconds: 1
periodSeconds: 3
检测/tmp/live,每隔 60 秒就会被删除,liveness 检测,如果被删除,就会返回失败,重启
pod。陷入无限循环。
2、向 pod 添加准备就绪探针
编辑 yaml 文件,修改 pod 模版添加就绪探针
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: nginx
name: nginx
spec:
containers:
- image: nginx:1.9
name: nginx
ports:
- containerPort: 80
resources: {}
readinessProbe:
exec:
command: - ls
- /var/ready
dnsPolicy: ClusterFirst
restartPolicy: Always
就绪探针将定期在容器内执行 ls/var/ready 命令。如果文件存在,则 ls 命令返回退出码 0,
否则返回非零的退出码;如果文件存在,则就绪探针将成功,否则失败;我们编辑完 yaml
并产生新的 pod,所以可以发现以上 pod 的 READY 为 0;
K apply -f nginx.yaml
K get pods
进入 pod 增加相应的文件
k exec -it nginx -- sh
Defaulting container name to nginx.
Use 'kubectl describe pod/nginx -n default' to see all of the containers in this pod.
# touch /var/ready
K get pods
修改探针。
httpGet:
path: /
port: 80
initialDelaySeconds: 3
periodSeconds: 3
六、.Pod 调度
1、调度原理
2、Pod调度过程
1. 用户提交 pod,APIServer 记录到 etcd 中;
2. scheduler 周期性查询 APIServer,以获取未绑定的 pod,尝试为 pod 分配节点;
3. scheduler 调度:首先过滤不符合 pod 资源要求的主机。然后考虑整体优化策略对
主机打分,比如使用最低负载,使用分散主机等。最后选择最高分的主机存储绑
定信息到 etcd 中;
4. kubelet 周期查询绑定对象,获取需要在本机启动的 pod 并通过 docker 启动。
更多推荐
所有评论(0)