概念:
- Pod是一个逻辑抽象概念,是K8s创建和管理的最小单元,一个Pod由一个容器或多个容器组成。
- 可以把Pod看成一个箱子,箱子里装的就是容器,每个箱子都是互相隔离的。
特点:
- 一个Pod可以理解为是一个应用实例,提供服务。
- Pod中容器始终部署在一个Node上。
- Pod中容器共享网络、存储资源。
主要用法:
- 运行单个容器:最常见的用法,在这种情况下,可以将Pod看做是单个容器的抽象封装。
- 运行多个容器:边车模式(Sidecar) ,通过在Pod中定义专门容器,来执行主业务容器需要的辅助工作,其好处是将辅助功能同主业务容器解耦,实现独立发布和能力重用。
应用场景:
- 日志收集
- 应用监控
注意事项:
- 和kubectl create deployment 命令相比,kubectl run 【Pod名称】命令更加单一,就相当于只运行了一个容器,前者可以生成多个副本等多项功能,后者没有,一般用于测试,正式环境还是用的前者。
功能 | 命令 |
---|---|
创建Pod | kubectl apply -f pod.yaml 或者 kubectl run nginx --image=nginx |
查看Pod | kubectl get pods 或者 kubectl describe pod |
查看日志 | kubectl logs |
进入容器终端 | kubectl exec -it |
删除Pod | kubectl delete pod |
查看Pod里的所有容器 | kubectl get pod 【Pod名称】 -o jsonpath=“{.spec[‘containers’,‘initContainers’][*].name}” |
参数 | 释义 | 是否必选 |
---|---|---|
version | 版本号,例如v1 | 必选 |
kind | 资源对象类型,例如pod、deployment、service | 必选 |
metadata | 元数据 | 必选 |
metadata.name | 对象名称 | 必选 |
metadata.namespace | 对象所属的命名空间,默认值为 default | 必选 |
metadata.labels | 自定义标签列表 | |
metadata.annotation | 自定义注解列表 | |
Spec | Pod 中容器的详细定义 | 必选 |
spec.containers | 容器列表 | 必选 |
spec.containers.name | 容器名称 | 必选 |
spec.containers.image | 镜像名称 | 必选 |
spec.containers.imagePullPolicy | 镜像拉取策略,可选值Always、Never、IfNotPresent,默认为Always。 Always:表示每次都尝试重新拉取镜像。 IfNotPresent:表示若本地有该镜像,则使用本地的镜像,若本地不存在则拉取镜像。 Never:表示仅使用本地镜像。 若存在以下设置,系统则将设置成默认设置imagePullPolicy=Always: 1、不设置 imagePullPolicy,也未指定镜像的tag。 2、不设置 imagePullPolicy,镜像tag为 latest。 3、启用了名为 AlwaysPulllmages 的准入控制器Admission Controller ) |
|
spec.containers.command | 容器的启动命令列表。 若不指定,则使用镜像打包时使用的启动命令。 |
|
spec.containers.args | 容器的启动命令参数列表。 | |
spec.containers.workingDir | 容器的工作目录 | |
spec.containers.volumeMounts | 挂载到容器内部的存储卷配置 | |
spec.containers.volumeMounts .name | 引用在volumes部分定义的共享存储卷名称 | |
spec.containers.volumeMounts.mountPath | 挂载到容器内的绝对路径 | |
spec.containers.volumeMounts.readOnly | 设置是否为只读模式,默认为读写模式 | |
spec.containers.ports | 容器需要暴露的端口号列表 | |
spec.containers.ports.name | 端口名称 | |
spec.containers.ports.containerPort | 容器内部端口 | |
spec.containers.ports.hostPort | 暴露在宿主机上的端口,默认与containerPort相同,需要保证唯一性。 | |
spec.containers.ports.protocol | 端口协议,默认为TCP,支持 TCP、UDP、SCTP | |
spec.containers.env | 容器运行前需设置的环境变量列表。 | |
spec.containers.env.name | 变量名称 | |
spec.containers.env.value | 变量值 | |
spec.containersl.resources | 资源限制和资源请求的设置配置,用于资源配额和资源限制功能。 | |
spec.containers.resources.limits | 资源限制值,允许容器内程序最大的使用资源。 | |
spec.containers.resources.limits.cpu | CPU 限制,可以写m也可以写浮点数,例如0.5=500m,1=1000m | |
spec.containers.resources.limits.memory | 内存限制,单位可以为 MiB、GiB 等 | |
spec.containers.resources.requests | 容器资源请求值。 告诉k8s最小分配的资源,分配的节点必须能够满足requests指定的值。 |
|
spec.containers .resources.requests.cpu | CPU请求,可以写m也可以写浮点数,例如0.5=500m,1=1000m | |
spec.containers.resources.requests.memo | 内存请求,单位可以为MiB、GiB 等。 | |
spec.volumes | 共享存储卷列表 | |
spec.volumes.name | 共享存储卷的名称。 可以定义多个 Volume,每个 Volume的 name 保持唯一。 容器定义部分的containers.volumeMounts.name 将引用该共享存储卷的名称。 类型有: emptyDir、hostPath、secret、nfs、iscsi等等。 |
|
spec.volumes.emptyDir | 类型为emptyDir 的存储卷。 表示与 Pod 同生命周期的-个临时目录,其值为一个空对象:emptyDir:{} |
|
spec.volumes .hostPath | 类型为 hostPath的存储卷。 表示 Pod 容器挂载的宿主机目录,通过volumes.hostPath.path 指定 |
|
spec.volumes.hostPath.path | Pod 容器挂载的宿主机目录 | |
spec.volumes.secret | 类型为secret的存储卷,表示挂载集群预定义的secret对象到容器内部 | |
spec.volumes.configMap | 类型为 configMap 的存储卷,表示挂载集群预定义的configMap对象到容器内部 | |
spec.volumes.livenessProbe | 健康检查配置项。 当探测无响应几次之后,系统将自动重启该容器。可设值有:exec、httpGet 和 tcpSocket。 对一个容器仅需设置一种健康检查方法 |
|
spec.volumes.livenessProbe.exec | 健康检查方式之一,exec 方式 | |
spec.volumes.livenessProbe.exec.command | exec 方式需要指定的命令或者脚本 | |
spec.volumes.livenessProbe.httpGet | 健康检查方式之一,httpGet方式。需指定 path、port | |
spec.volumes.livenessProbe.tcpSocket | 健康检查方式之一,cpSocket 方式。 | |
spec.volumes.livenessProbe.initialDelaySeconds | 容器启动完成后首次探测的时间,单位为s | |
spec.volumes .livenessProbe.timeoutSeconds | 健康检查的探测等待响应超时时间,单位为 s,默认值为 1s。若超过该超时时间设置,则将认为该容器不健康,会重启该容器。 | |
spec.volumes .livenessProbe.periodSeconds | 健康检查的定期探测时间,单位为 s,默认 10s 探测一次。 | |
spec.restartPolicy | 重启策略,可选值为Always、OnFailure,默认值为Always。 Always:Pod 一旦终止运行,则无论容器是如何终止的,kubelet 都将重启它。 OnFailure:只有 Pod 以非零退出码终止时kubelet 才会重启该容器。如果容器正常结束(退出码为 0),则 kubelet 将不会重启它。 Never:Pod 终止后,kubelet 将退出码报告给Master,不会再重启该 Pod |
|
spec.nodeSelector | 节点标签,以 key:value 格式指定,Pod将被调度到具有这些Label的节点上。 | |
spec.imagePullSecrets | pull 镜像时使用的 Secret 名称,以name:secretkey格式指定。 | |
spec.hostNetwork | 是否使用主机网络模式,默认值为 false。 设置为true,表示容器使用宿主机网络,不再使用 Docker网桥。 |
基本了解:
- Kubernetes基于list-watch机制的控制器架构,实现组件间交互的解耦。
- 其他组件监控自己负责的资源,当这些资源发生变化时,kube-apiserver会通知这些组件,这个过程类似于发布与订阅。
流程图:
流程解析:
创建一个Pod命令为:kubectl run pod1 --image=nginx,命令执行过程步骤如下:
- kubectl向apiserver发送一个创建pod的请求,apiserver会将数据写到etcd(实线),etcd将接受数据情况反馈给apiserver(虚线)。
- scheduler调度器订阅apiserver,当apiserver有新事件时scheduler会第一时间收到,此时会根据算法选择一个节点加入分配到k8s-node1节点,并将选择结果告诉给apiserver,apiserver会将数据写到etcd(实线),etcd将接受数据情况反馈给apiserver(虚线)。
- k8s-node1节点上的kubelet收到apiserver分配到我这个节点的pod,kubelet调用docker api创建容器,汇报容器的状态。
注意事项:
- 从以上的流程中来看,缺少两个组件的使用。
- kube-controller-manager # 负责一些控制器工作的,例如deployment
- kube-proxy # 负载pod网络,例如service
情景模拟流程:
- 把apiserver 看成 “小卖铺老板”,etcd 看成 “仓库”,scheduler看成“送货员”,其他组件 看成 “学生”。
- 当老板接到货物时,会先把货物放进仓库,仓库返回给老板结果。
- 送货员根据算法规则算出货物要配送到哪个节点,将结果告诉老板。
- 老板根据每个组件学生的订阅要求,发布货物给各个订阅学生。
- 学生接收到货物后找docker api获取生成任务,并把结果返回给老板。
- 老板把情况记录到仓库里。
yaml文件示例:
apiVersion: v1 kind: Pod metadata: labels: app: test name: pod-net-test namespace: default spec: containers: - image: busybox name: test command: ["/bin/sh","-c","sleep 12h"] - image: nginx name: web
1.先尝试运行一个Pod,导出查看yaml文件。
[root@k8s-master bck]# kubectl run nginx --image=nginx --dry-run=client -o yaml > nginx.yaml
[root@k8s-master bck]# cat nginx.yaml
apiVersion: v1
kind: Pod
metadata:
labels:
run: nginx
name: nginx
spec:
containers:
- image: nginx
name: nginx
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Always
2.尝试运行创建一个deployemnt,,导出查看yaml文件。
[root@k8s-master bck]# kubectl create deployment web --image=nginx --dry-run=client --replicas=3 -o yaml > deploymnet.yaml
[root@k8s-master bck]# cat deploymnet.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: web
name: web
spec:
replicas: 3
selector:
matchLabels:
app: web
strategy: {}
template:
metadata:
labels:
app: web
spec:
containers:
- image: nginx
name: nginx
resources: {}
3.对比两个命令导出的yaml文件,Pod为对象的内容就是以deployment为对象的最后一部分内容。
4.修改nginx.yaml文件内容,新增辅助容器busybox使其后台运行24小时不退出。
[root@k8s-master bck]# cat nginx.yaml
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: nginx
name: nginx
spec:
containers:
- image: nginx ##主容器。
name: nginx
- image: busybox ##辅助容器。
name: bs
command:
- sleep
- 24h
5.导入yaml文件,并查看Pod,其内部有两个容器就是nginx和busybox。
[root@k8s-master bck]# kubectl apply -f nginx.yaml
6.进入Pod验证。没有使用-c参数指定进入哪个容器,就会提示这行。当一个Pod中有多个容器时,不指定进入容器就默认进入主容器。
[root@k8s-master bck]# kubectl exec -it nginx -- bash
8.进入辅助容器验证。可以监听到nginx的80端口,但是查看不到Nginx进程,是因为nginx和busybox容器是通过加入了Infra Container网络容器,该容器通过共用网络协议栈,使busybox容器和nginx容器里实现网络共享。而端口是属于协议栈中的一部分能看到,进程不属于协议栈内容就看不到。
9.查看Infra Container网络容器位置。
1.通过yaml文件定义数据卷。
[root@k8s-master bck]# cat nginx2.yaml
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: nginx
name: nginx2
spec:
containers:
- image: nginx ##主容器。
name: nginx
volumeMounts: ## 数据卷挂载
- name: log ## 指定挂载的数据卷名称
mountPath: /data ## 数据卷挂载到容器中的路径
- image: busybox ##辅助容器。
name: bs
command:
- sleep
- 24h
volumeMounts: ## 数据卷挂载
- name: log ## 指定挂载的数据卷名称
mountPath: /data ## 数据卷挂载到容器中的路径
volumes: ##定义数据卷
- name: log ##数据卷名称
emptyDir: {} ##数据卷类型
[root@k8s-master bck]# kubectl apply -f nginx2.yaml
3.进入nginx容器创建123.txt文件,之后退出进入bs容器里可以看到123.txt文件;进入bs容器创建456.txt文件,之后退出进入bs容器里可以看到456.txt文件。
pod状态 | 释义 |
---|---|
Pending | 等待状态。 API Server 已经创建该 Pod,但在 Pod 内还有一个或多个容器的像没有创建,包括正在下载镜像的过程。 |
Running | Pod内所有容器均已创建,且至少有一个容器处于运行状态、正在启动状态或正在重启状态 |
Succeeded | Pod内所有容器均成功执行后退出,且不会再重启 |
Failed | Pod 内所有容器均已退出,但至少有一个容器为退出失败状态 |
Unknown | 由于某种原因无法获取该 Pod 的状态,可能由于网络通信不畅导致 |
重启策略:
- Always:当容器终止退出后,总是重启容器,默认策略。
- OnFailure:当容器异常退出(退出状态码非0)时,才重启容器。
- Never:当容器终止退出,从不重启容器。
健康检查3种类型:
- livenessProbe(存活检查):判断容器是否存活(Running状态)。若检查失败,则将杀死容器,再根据Pod的容器策略来操作。
- readinessProbe(就绪检查):判断容器服务是否可用(Ready状态),达到Ready状态的Pod才可以接收请求。如果在运行过程中Ready状态变为False,则系统自动将其从Service的后端Endpoint列表中隔离出去,后续再把恢复到Ready状态的Pod加回后端Endpoint列表,这样就能保证客户端在访问Service时不会被转发到服务不可用的Pod实例上。
- startupProbe(启动检查):检查成功才由存活检查接手,用于保护慢启动容器。适用于应用启动较慢的情况,就绪检查就不适用了,需要用启动检查。
健康检查支持的3种检查方法:
- httpget:通过容器的IP地址、端口号及路径调用HTTP Get方法,返回200-400范围状态码为成功。
- exec:执行Shell命令返回状态码是0为成功。
- tcpSocket:通过容器的IP地址和端口号执行TCP检查,如果能够建立TCP连接,则表明容器健康。
1.创建deployment时,加入健康检查策略。
[root@k8s-master bck]# cat qingjun.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: qingjun
name: qingjun
spec:
replicas: 3
selector:
matchLabels:
app: qingjun
template:
metadata:
labels:
app: qingjun
spec:
containers:
- image: nginx
name: nginx
livenessProbe: # 存活检查,重启容器
httpGet:
path: /index.html #检查网页文件
port: 80
initialDelaySeconds: 10 #启动容器后多少秒后进行第一次健康检查
periodSeconds: 30 #以后每间隔多少秒检查一次
readinessProbe: # 就绪检查,从Service中剔除容器
httpGet:
path: /index.html
port: 80
initialDelaySeconds: 10
periodSeconds: 30
2.导入yaml文件,并创建service。
[root@k8s-master bck]# kubectl apply -f qingjun.yaml
[root@k8s-master bck]# kubectl expose deployment qingjun --port=80 --target-port=80 --type=NodePort
3.此时查看svc的地址,集群内的三个副本都能监听到。
4.删除一个副本容器里的网页文件。
5.此时再查看service监听状态,被删除网页文件的副本容器IP地址监听消失,该容器日志也显示报错异常。这是就绪检查起作用。
6.过一段时间,该容器又重新生成,日志恢复,前端文件恢复。这是存活检查在起作用。
为什么会有环境变量的用法?
- 创建 Pod 时,可以为其下的容器设置环境变量。官网地址
应用场景:
- 容器内应用程序获取Pod信息。
- 容器内应用程序通过用户定义的变量改变默认行为。
变量值几种定义方式:
- 自定义变量值。
- 变量值从Pod属性获取。
- 变量值从Secret、ConfigMap挂载获取。
设置方式 | 可设置的参数 | 释义 |
---|---|---|
fieldRef | metadata.name | Pod名称 |
fieldRef | metadata.namespace | |
fieldRef | metadata.uid | Pod的UID,从Kubernetes 1.8.0-alpha.2版本开始支持。 |
fieldRef | metadata.labels[‘< KEY >’] | Pod某个Label的值,通过< KEY >进行引用,从Kubernetes 1.9版本开始支持。 |
fieldRef | metadata.annotations[‘< KEY >’] | Pod某个Annotation的值,通过< KEY >进行引用,从Kubernetes 1.9版本开始支持。 |
resourceFieldRef | Container级别的CPU Limit | 容器的CPU限制值 |
resourceFieldRef | Container级别的CPU Request。 | 容器的CPU请求值 |
resourceFieldRef | Container级别的Memory Limit。 | 容器的内存限制值 |
resourceFieldRef | Container级别的Memory Request。 | 容器的内存请求值 |
resourceFieldRef | Container级别的临时存储空间(ephemeral-storage)Limit,从K8s 1.8.0-beta.0版本开始支持。 | |
resourceFieldRef | Container级别的临时存储空间(ephemeral-storage)Request,从K8s 1.8.0-beta.0版本开始支持。 | |
fieldRef字段 | metadata.labels | Pod的Label列表,每个Label都以key为文件名,value为文件内容,每个Label各占一行。 |
fieldRef字段 | metadata.namannotations | Pod的Annotation列表,每个Annotation都以key为文件名,value为文件内容,每个Annotation各占一行。 |
Pod元数据信息 | status.podIP | Pod的IP地址 |
Pod元数据信息 | spec.serviceAccountName | Pod使用的ServiceAccount名称。 |
Pod元数据信息 | spec.nodeName | Pod所在Node的名称,从Kubernetes 1.4.0-alpha.3版本开始支持。 |
Pod元数据信息 | status.hostIP | Pod所在Node的IP地址,从Kubernetes 1.7.0-alpha.1版本开始支持。 |
1.创建一个deployment,编辑yaml文件添加环境变量。
[root@k8s-master bck]# cat env.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: env
name: env
spec:
replicas: 3
selector:
matchLabels:
app: qingjun
template:
metadata:
labels:
app: qingjun
spec:
containers:
- image: nginx
name: nginx
env:
- name: ABC
value: "123"
- name: MY_NODE_NAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName ##pod所在node节点的名称。
- name: MY_POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name ##pod名称。
- name: MY_POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace ##pod所在命名空间的名称。
- name: MY_POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP ##pod的IP地址。
- name: MY_POD_SERVICE_ACCOUNT
valueFrom:
fieldRef:
fieldPath: spec.serviceAccountName ##pod使用sa的名称。
定义:
- Init Container初始化容器用于初始化工作,执行完就结束,可以理解为一次性任务。
- 初始化容器与应用容器本质上是一样的,但是仅运行一次就结束任务,并且必须在成功运行完成后,系统才能继续执行下一个容器。
特点:
- 支持大部分应用容器配置,但不支持健康检查。
- 运行方式与应用容器不同,优先应用容器执行。当有多个init container时,会按顺序逐个运行,并且只有前一个init container运行成功后才能运行后一个init container。在所有init container都成功运行后,K8s才会初始化Pod的各种信息,并开始创建和运行应用容器。
应用场景:
- 环境检查:例如确保应用容器依赖的服务启动后再启动应用容器。
- 初始化配置:例如给应用容器准备配置文件。
Pod内的容器类型:
- Infrastructure Container:基础容器
- 维护整个Pod网络空间,镜像为pause。某节点上又多少个pause镜像容器,该节点上就有多少个pod。
- InitContainers:初始化容器
- 先于业务容器开始执行
- Containers:业务容器
- 并行启动
注意事项:
- Pod重新启动时,init container将会重新运行。
- 情景一,init container的镜像被更新时,init container将会重新运行,导致Pod重启。仅更新应用容器的镜像只会使得应用容器被重启。
- 情景二,Pod的infrastructure容器更新时,Pod将会重启。
- 情景三,若Pod中的所有应用容器都终止了,并且RestartPolicy=Always,则Pod会重启。
- 也可以对init container设置资源限制、挂载卷和安全策略等。但资源限制的设置与应用容器略有不同。
- 若多个init container都定义了资源请求/资源限制,则取最大的值作为所有init container的资源请求值/资源限制值。
- Pod的有效(effective)资源请求值/资源限制值取以下二者中的较大值:
- 所有应用容器的资源请求值/资源限制值之和。
- initcontainer的有效资源请求值/资源限制值。
- 调度算法将基于Pod的有效资源请求值/资源限制值进行计算,也就是说init container可以为初始化操作预留系统资源,即使后续应用容器无须使用这些资源。
- Pod的有效QoS等级适用于init container和应用容器。
- 资源配额和限制将根据Pod的有效资源请求值/资源限制值计算生效。
- Pod级别的cgroup将基于Pod的有效资源请求/限制,与调度机制一致。
- 测试初始化容器下载一个前端文件到本地并挂载共享目录,主容器从共享目录里下载前端文件。
1.创建一个Pod,编辑yaml文件。
[root@k8s-master bck]# cat init.yaml
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: nginx
name: init666
spec:
## 初始化容器
initContainers: ##定义初始化容器
- image: busybox ##容器镜像
name: bs ##容器名称
command: ##执行动作,下载访问aliang官网前端文件到/data/index.html,并共享/data目录。
- wget
- "-O"
- "/data/index.html"
- "https://www.aliangedu.cn"
volumeMounts: ## 数据卷挂载
- name: log ## 指定挂载的数据卷名称
mountPath: /data ## 数据卷挂载到容器中的路径
## 主容器
containers:
- image: nginx
name: nginx
volumeMounts: ## 数据卷挂载
- name: log ## 指定挂载的数据卷名称
mountPath: /usr/share/nginx/html/ ## 共享目录,此时该目录下也有下载的aliang官网前端文件。
volumes: # 定义数据卷
- name: log # 数据卷名称
emptyDir: {} # 数据卷类型
2.导入yaml文件,查看Pod状态。先是运行初始化容器,再运行主容器。
3.进入容器内检查下载文件,验证成功。
为什么会有静态Pod?
- 只是一种使用kubeadm方式部署k8S集群的思路,和k8s集群没有直接关系,是分开的。
- 正常情况下,K8s集群搭建完成后才能创建Pod,而使用Kubeadm方式搭建集群时组件又需要使用Pod来启动,这时候就需要没有容器化的Kubelet来管理静态Pod,通过静态Pod拉起K8s组件,也就是master节点上/etc/kubernetes/manifests/目录下的yaml文件。
静态Pod的特点:
- Pod由特定节点上的kubelet管理。
- 不能使用控制器,不能通过API Server进行管理,无法与ReplicationController、Deployment、DaemonSet进行关联,也无法对它们进行健康检查。
- Pod名称标识当前节点名称
实现方式:
- 配置文件方式。在kubelet配置文件/var/lib/kubelet/config.yaml中设置参数staticPodPath,指定需要监控的配置文件所在目录,kubelet会定期扫描该目录,并根据该目录下的.yaml或.json文件进行创建操作。
- HTTP方式。在kubelet配置文件中设置参数“–manifest-url”,kubelet将会定期从该URL地址下载Pod的定义文件,并以.yaml或.json文件的格式进行解析,然后创建Pod。
注意事项:
- 在kubelet配置文件启用静态Pod的参数:
vi /var/lib/kubelet/config.yaml
…
staticPodPath: /etc/kubernetes/manifests
…- 将部署的pod yaml放到该目录会由kubelet自动创建。
- 业务层面上用不到静态Pod,都是从K8s集群层面上拉取Pod。
1.在master节点上查看这几个Pod名称是带有节点说明的,这些Pod就是静态Pod。
2.在node1节点上的/etc/kubernetes/manifests目录下添加pod.yaml文件后,会自动创建此pod。
3.也可以在master节点上查看此pod存在node1节点上。
4.讲该pod.yaml文件移到别的目录,该pod会自动被删除。