【Kubernetes专项】最小调度单元 Pod、名称空间及资源配额
四、K8s 最小调度单元 Pod 概述
4.1 Pod 是什么?
4.1.1 Pod 概述及举例
Pod 资源对应的官方文档:https://kubernetes.io/docs/concepts/workloads/pods/

可以把 Pod 看成一个“豌豆荚”,里面有很多的“豆子”(容器)。
Pod 是 K8s 中的最小调度单元;
K8s 是通过定义一个 Pod 的资源,然后在 Pod 里面运行容器(可以看上面的示例图);
容器需要指定一个镜像,这样就可以运行具体的服务。
- 一个 Pod 封装一个容器(也可以封装多个容器),Pod 容器里共享存储、网络等。
也就是说:应该把整个 Pod 看做虚拟机,然后每个容器相当于运行在虚拟机的进程之中。

- Pod 是需要调度到 K8s 集群的工作节点来运行,具体调度到哪个节点,是根据 scheduler 调度器实现的。
举个例子:
部署一个 Tomcat 应用,如果不用容器,我们可能会部署到物理机、虚拟机或者云主机上面;此时,出现 K8s 之后,我们就可以定义一个 Pod 资源,在 Pod 里面一个创建一个 Tomcat 容器,因此,Pod 充当的是一个逻辑主机的角色。
4.1.2 Pod 如何管理多个容器?

Pod 中可以同时运行多个容器;同一个 Pod 中的容器会自动的分配到同一个 node 上。同一个 Pod 中的容器共享资源、网络环境,他们总是被同时调度,在一个 Pod 中同时运行多个容器是一种比较高级的用法,只有当你的容器需要紧密配合协作的时候才考虑这种模式。
- 一些Pod有init容器和应用容器。 在应用程序容器启动之前,运行初始化容器。
4.1.3 Pod 网络
Pod 是有IP地址的,假如 Pod 不是共享物理机 IP,由网络插件(Calico,Flannel,Weave)划分的IP,每个Pod都被分配唯一的 IP 地址。
4.1.3.1 Docker 容器互联的方式
创建新容器的时候,**通过--net container参数,**指定其和已经存在的某个容器共享一个 Network Namespace。如下图所示:
右侧新建的Container,其网卡共享左侧的容器。
因此不会拥有自己独立的 IP,而是共享左侧容器的IP,端口范围等网络资源

4.1.3.2 K8s 中容器共享的方式
在 k8s 中,启动 Pod 是,会先启动一个 pause 的容器,然后将后续所有容器都 “link” 到这个 pause 的容器,以此来实现网络共享。

4.1.4 Pod 存储
创建 Pod 的时候可以指定挂载的存储卷。Pod 中所有的容器都可以访问共享卷,允许这些容器共享数据。
Pod 只要挂载持久化数据卷,Pod 重启之后数据还是会存在的。

4.2 之前学习过容器,为何还需要 Pod ?
4.2.1 解释说明
Pod 是由一组紧耦合的容器组成的容器组(Pod 可以比作容器的集合),当然目前最流行的就是Docker、containerd、podman容器,Pod就可以作为1或者多个容器的载体。
- Pod 中所用容器都会被一致调度、同节点部署,并且在一个“共享环境”中运行。
- “共享环境”(包括):
- 所有容器共享一个IP地址和端口空间;意味着:容器之间可以直接通过 localhost 高效访问,不会有端口冲突;
- 允许容器之间共享存储卷,通过文件系统交互信息;
- ps:当 K8s 挂载 Volume 到 Pod 上,本质上是将 volume 挂载到 Pod 中的每一个容器里。
- Pod 中所有容器使用同一个网络的 namespace ,即相同的 IP 地址和 Port 空间。
4.2.2 代码自动更新

假如生产环境部署了一个go的应用,而且部署了几百个节点,希望这个应用可以定时的同步最新的代码,以便自动升级线上环境。这时,我们不希望改动原来的go应用,可以开发一个Git代码仓库的自动同步服务,然后通过Pod的方式进行编排,并共享代码目录,就可以达到更新java应用代码的效果。
4.2.3 收集业务日志

某服务模块已经实现了一些核心的业务逻辑,并且稳定运行了一段时间,日志记录在了某个目录下,按照不同级别分别为 error.log、access.log、warning.log、info.log,现在希望收集这些日志并发送到统一的日志处理服务器上。
这时我们可以修改原来的服务模块,在其中添加日志收集、发送的服务,但这样可能会影响原来服务的配置、部署方式,从而带来不必要的问题和成本,也会增加业务逻辑和基础服务的藕合度。
如果使用Pod的方式,通过简单的编排,既可以保持原有服务逻辑、部署方式不变,又可以增加新的日志收集服务。
而且如果我们对所有服务的日志生成有一个统一的标准,或者仅对日志收集服务稍加修改,就可以将日志收集服务和其他服务进行Pod编排,提供统一、标准的日志收集方式。
这里的“核心业务服务”、“日志收集服务”分别是一个镜像,运行在隔离的容器环境中。
4.3 Pod 工作方式
在K8s中,所有的资源都可以使用一个yaml文件来创建,创建Pod也可以使用yaml配置文件。或者使用kubectl run在命令行创建Pod(不常用)。
4.3.1 自主式 Pod
所谓的自助式 Pod,就是直接定义一个 Pod 资源,如下:
# 工作节点上传所需镜像并手动导入(资源包上传)
n1 && n2 ~]# ctr -n k8s.io images import xianchao-tomcat.tar.gz
# 工作节点编写yaml文件(前期学习只需要复制yaml文件即可,后期学习自主编写)
[root@k8s-master1 ~]# mkdir pod # 在控制节点创建一个专门放置yaml文件的目录
[root@k8s-master1 ~]# cd pod/
[root@k8s-master1 pod]# 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
# 更新yaml资源文件并查看pod状态
[root@k8s-master1 pod]# kubectl apply -f pod-tomcat.yaml
[root@k8s-master1 pod]# kubectl get pods
NAME READY STATUS RESTARTS AGE
tomcat-test 1/1 Running 0 13s
# 删除pod并查看变化(模拟生产环境中误删pod --> 自助式pod的问题)
[root@k8s-master1 pod]# kubectl delete pods tomcat-test
# 发现pod不存在,已经被删除了
[root@k8s-master1 pod]# kubectl get pods
No resources found in default namespace.
通过上面可以看到,如果直接定义一个Pod资源,那Pod被删除,就彻底被删除了,不会再创建一个新的Pod,这在生产环境还是具有非常大风险的,所以今后我们接触的Pod,都是控制器管理的。
4.3.2 控制器管理 Pod
常见的管理 Pod 控制器:Replicaset、Deployment、Job、CronJob、Daemonset、Statefulset。
控制器管理的 Pod 可以确保 Pod 始终在指定的副本数运行(即使删除,控制器也会新建一个相同的 pod 以保证副本数稳定)。
# 演示如下:
# 上传实验所需镜像
n1 && n2]# ctr -n k8s.io images import xianchao-nginx.tar.gz
# 控制节点创建yaml文件
[root@k8s-master1 pod]# vim nginx-deploy.yaml
apiVersion: apps/v1
kind: Deployment # 控制器
metadata:
name: nginx-test
labels:
app: nginx-deploy
spec:
selector:
matchLabels:
app: nginx
replicas: 2 # 副本数为2
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: my-nginx
image: xianchao/nginx:v1
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
# 更新资源yaml文件
[root@k8s-master1 pod]# kubectl apply -f nginx-deploy.yaml
# 查看控制器的状态
[root@k8s-master1 pod]# kubectl get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-test 2/2 2 2 22s
# 查看pods的状态
[root@k8s-master1 pod]# kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-test-5fbcf9f6-wcr9v 1/1 Running 0 26s
nginx-test-5fbcf9f6-wn7hk 1/1 Running 0 26s
# 新开一个终端去监控pods的实时状态
[root@k8s-master1 ~]# watch -n1 kubectl get pods
# 发现:随便删除一个pod,控制器会立即启动一个相同的pod以保持副本数的稳定(如下.gif图所示)
[root@k8s-master1 pod]# kubectl delete pods nginx-test-xxxx
[root@k8s-master1 pod]# kubectl get pods
因此这种管理方式更可靠!
4.4 创建 Pod 过程
4.4.1 核心过程
**1. 提交请求:**Kubectl 将Pod 提交至 apiserver ,apiserver 验证后将元数据持久化到 etcd
**2.调度分配:**scheduler 通过 watch 机制监听 etcd 中的新 Pod,执行调度算法选择节点,并将绑定信息写回 etcd
**3.节点执行:**目标节点的 kubelet 通过 watch 获取绑定信息,调用容器进行时(ps:containerd)创建并启用容器
**4.状态同步:**kubelet 将 Pod 运行状态上报 apiserver,apiserver 更新 etcd 中的状态数据
4.4.2 使用 yaml 文件创建pod
4.4.2.1 Pod资源清单–常用参数及解释
示例文件
apiVersion: v1 # Kubernetes API版本(Pod属于核心v1组)
kind: Pod # 资源类型
metadata: # 元数据定义字段
name: nginx-pod # Pod名称
namespace: default # 所属命名空间
labels: # 标签(用于服务发现/调度)
app: nginx
spec: # 期望状态定义
containers: # 容器列表
- name: nginx-container # 容器名称
image: nginx:1.25 # 镜像地址
imagePullPolicy: Nerver # 拉取策略
ports:
- containerPort: 80 # 容器暴露端口
resources: # 资源限制
limits:
memory: "128Mi" # 最大内存
cpu: "500m" # 最大CPU(500毫核)
requests:
memory: "64Mi" # 预留内存
cpu: "250m" # 预留CPU
restartPolicy: Always # 重启策略(Always/OnFailure/Never)
nodeSelector: # 节点选择器(调度约束)
disktype: ssd
volumes: # 存储卷定义
- name: cache-volume
emptyDir: {} # 临时存储卷
4.4.2.2 实操练习
[root@k8s-master1 pod]# vim pod-first.yaml
apiVersion: v1
kind: Pod
metadata:
labels:
app: tomcat
name: tomcat-test
namespace: default
spec:
containers:
- name: tomcat-java
image: xianchao/tomcat-8.5-jre8:v1
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
[root@k8s-master1 pod]# kubectl apply -f pod-first.yaml
[root@k8s-master1 pod]# kubectl get pods
4.4.3 使用命令行创建pod(不推荐)
[root@k8s-master1 pod]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
xianchao/tomcat-8.5-jre8 v1 4ac473a3dd92 7 years ago 108MB
[root@k8s-master1 pod]# kubectl run tomcat --image=xianchao/tomcat-8.5-jre8:v1 --image-pull-policy='IfNotPresent' --port=8080
[root@k8s-master1 pod]# kubectl get pods
NAME READY STATUS RESTARTS AGE
tomcat 1/1 Running 0 7s
4.4.4 常见的命令
# 查看帮助手册
]# kubectl --help
# 查看节点状况
[root@k8s-master1 ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s-master1.kaser.org NotReady control-plane 39m v1.31.3
k8s-node1.kaser.org NotReady <none> 41s v1.31.3
k8s-node2.kaser.org NotReady <none> 37s v1.31.3
# 将工作节点打标签,以便于观察 --> work
~]# kubectl label nodes k8s-node1.kaser.org node-role.kubernetes.io/work=work
~]# kubectl label nodes k8s-node2.kaser.org node-role.kubernetes.io/work=work
# 再次查看,发现标签已经打上
[root@k8s-master1 ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s-master1.kaser.org Ready control-plane 7d v1.31.3
k8s-node1.kaser.org Ready work 6d23h v1.31.3
k8s-node2.kaser.org Ready work 6d23h v1.31.3
# 查看命名空间
[root@k8s-master1 pod]# kubectl get namespace
NAME STATUS AGE
default Active 7d # 默认命名空间
kube-node-lease Active 7d
kube-public Active 7d
kube-system Active 7d
# 查看pod(默认namespace=dafault,省略不写)
[root@k8s-master1 pod]# kubectl get pods
[root@k8s-master1 pod]# kubectl get pods -n xxx
# 查看namespace=kube-system内的pod(-n xxxx 即可)
[root@k8s-master1 pod]# kubectl get pods -n kube-system
# 查看IP/pod被调度在哪个工作节点上
[root@k8s-master1 pod]# kubectl get pods -owide
# 可以查看对应的yaml文件
[root@k8s-master1 pod]# more pod-first.yaml
apiVersion: v1
kind: Pod
metadata:
labels:
app: tomcat
name: tomcat-test
namespace: default
spec:
containers:
- name: tomcat-java # 这里查看容器名
image: xianchao/tomcat-8.5-jre8:v1
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
# 进入pod里面的容器(不指定就什么都不加,指定进入哪个文件就加参数 -c xxx容器名 )
[root@k8s-master1 pod]# kubectl exec -it tomcat-test -- /bin/bash
bash-4.4# exit
[root@k8s-master1 pod]# kubectl exec -it tomcat-test -c tomcat-java -- /bin/bash
bash-4.4# exit
# 查看pod具有哪些标签可以结合grep使用
[root@k8s-master1 pod]# kubectl get pods --show-labels
[root@k8s-master1 pod]# kubectl get pods --show-labels | grep tomcat
# 这种情况是知道要找哪些标签的pod( -l app=xxx标签名)
[root@k8s-master1 pod]# kubectl get pods -l app=tomcat
# 查看具体pod的日志( logs pod名称 )
[root@k8s-master1 pod]# kubectl logs tomcat-test
# 查看具体pod的详细信息( describe pods pod名称)
[root@k8s-master1 pod]# kubectl describe pods tomcat-test
# 删除pod两种方式
# 1.删除pod (kubectl delete pod pod名称)
# 2.删除yaml文件 (kubectl delete -f xxx.yaml文件)
# 第一种:
[root@k8s-master1 pod]# kubectl delete pod tomcat-test
# 第二种:
[root@k8s-master1 pod]# kubectl delete -f pod-first.yaml
# 以上为自主式pod删除方式,两种方式都可以
# 以下为控制器pod删除方式
# 第一种删除之后,控制器会立即新建一个保持副本数稳定
# 第二种是直接删除yaml文件,即为永久删除,如下动图所示:
# 可以另外启动一个终端去监控
[root@k8s-master1 ~]# watch -n1 kubectl get pods
# 执行yaml文件创建pod
[root@k8s-master1 pod]# kubectl apply -f nginx-deploy.yaml
# 尝试常规删除,发现不行
[root@k8s-master1 pod]# kubectl delete pod nginx-test-5fbcf9f6-4m45r
[root@k8s-master1 pod]# kubectl delete pod nginx-test-5fbcf9f6-xfsv8
[root@k8s-master1 pod]# kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-test-5fbcf9f6-mcdxj 1/1 Running 0 7s
nginx-test-5fbcf9f6-vg5d4 1/1 Running 0 7s
# 尝试删除yaml文件,即可永久删除
[root@k8s-master1 pod]# kubectl delete -f nginx-deploy.yaml
[root@k8s-master1 pod]# kubectl get pods
No resources found in default namespace.
## 五、K8s名称空间及资源配额
5.1 namespace 名称空间
命名空间又称为“namespace(ns)”,也称为虚拟机群。它们底层都依赖于同一个物理集群,K8s 支持多个虚拟机群。
命名空间适用于存在很多跨团队或项目的场景。
对于只有几个或几十个用户的集群,根本不需要创建或考虑命名空间。
5.2 namespace 与 resourcequota 资源配额 的使用案例
# 新建一个命名空间 test
[root@k8s-master1 pod]# kubectl create ns test
# 新建一个资源配额 yaml 文件放到 test 的命名空间里
[root@k8s-master1 pod]# vim namespace-quota.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: mem-cpu-quota # resourcequota的名称
namespace: test # 在哪个命名空间
spec:
hard:
limits.cpu: "4" # 所有容器的 cpu 限制总和 <= 4CPU
limits.memory: "4Gi" # 所有容器的 内存 限制总和 <= 4GiB
requests.cpu: "2" # 所有容器的 cpu 请求总和 <= 2CPU
requests.memory: "2Gi" # 所有容器的 内存 请求总和 <= 2GiB
# 查看
[root@k8s-master1 pod]# kubectl get resourcequota -n test
NAME AGE REQUEST LIMIT
mem-cpu-quota 11m requests.cpu: 0/2, requests.memory: 0/2Gi limits.cpu: 0/4, limits.memory: 0/4Gi
# 养成查找文档的习惯
https://kubernetes.io/zh-cn/docs/concepts/policy/resource-quotas/
# 创建pod时候必须设置资源限额,否则创建失败,如下:
[root@k8s-master1 pod]# more pod-test.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-test
namespace: test
labels:
app: tomcat-pod-test
spec:
containers:
- image: xianchao/tomcat-8.5-jre8:v1
imagePullPolicy: IfNotPresent
name: tomcat-test
ports:
- containerPort: 8080
resources:
limits:
memory: "2Gi"
cpu: "2"
requests:
memory: "100Mi"
cpu: "500m"
[root@k8s-master1 pod]# kubectl get resourcequota -n test
NAME AGE REQUEST LIMIT
mem-cpu-quota 72m requests.cpu: 500m/2, requests.memory: 100Mi/2Gi limits.cpu: 2/4, limits.memory: 2Gi/4Gi
[root@k8s-master1 pod]# kubectl get pod -n test
NAME READY STATUS RESTARTS AGE
pod-test 1/1 Running 0 5s
更多推荐



所有评论(0)