K8s 运维系列 | 第 3 天:核心对象——Pod、Label、Selector 与命名空间

在上一篇文章里,我们一起完成了 minikube 与 kubeadm 的集群部署,跑通了一个最小的 Kubernetes 环境。很多刚接触 K8s 的朋友会有一种感觉:集群是起来了,可里面那一堆抽象对象到底是怎么回事?为什么一个应用不是直接”跑容器”,而是要先写 Pod?为什么还要给资源贴 Label,再用 Selector 去选?命名空间又是用来隔离什么的?

今天这篇文章,我们就聚焦 Kubernetes 最基础、也最核心的几个对象——Pod、Label、Selector 与命名空间。理解它们之间的关系,是后面学习 Deployment、Service、ConfigMap 等一切高级对象的前提。可以说,K8s 的学习是否扎实,很大程度取决于你有没有真正吃透今天这四个概念。

K8s 运维 第3天

核心概念:四个对象分别解决什么问题

在正式进入实战之前,我们先把这四个概念在脑中”对号入座”,搞清楚它们各自在集群中扮演的角色。

Pod:Kubernetes 的最小调度单位

Pod 是 Kubernetes 中最小的、可以创建和调度的计算单元。一个 Pod 内部可以包含一个或多个容器,这些容器共享同一个网络命名空间(也就是共享同一个 IP 和端口空间)以及存储卷。日常最常用的场景是”一个 Pod 一个容器”,即 Pod 作为单个应用实例的载体。

需要特别强调的是:在 Docker 时代,我们习惯直接管理容器;但在 K8s 里,你永远不直接运行容器,而是通过 Pod 间接管理。Pod 是 K8s 与容器运行时之间的”唯一接口”。

Label:给资源贴标签

Label 是一组键值对,可以附加在 Pod、Service、Deployment 等几乎所有 K8s 对象上。它本身不参与任何系统行为,纯粹是用来给资源做”标记”的元数据。比如你可以给一个 Pod 打上 app=nginxenv=prodtier=frontend 这样的标签。

Selector:根据标签筛选资源

有了 Label,就需要一种机制把它们”用起来”,这就是 Selector。Selector 通过标签的键值匹配规则,从一堆资源里筛出符合条件的目标。最常见的用法是 Service 通过 Selector 找到它要代理的那组 Pod。

命名空间:逻辑隔离的边界

Namespace(命名空间)提供了一种在单个集群内划分资源组的机制。不同团队、不同项目可以各自拥有独立的命名空间,彼此之间的资源名称互不冲突,也可以配合 RBAC 做权限隔离。默认集群里会有 defaultkube-systemkube-publickube-node-lease 这几个系统命名空间。

实战步骤:亲手创建并管理 Pod

光说不练假把式,下面我们直接上手,从写一个最简单的 Pod 清单开始。

第一步:编写 Pod 的 YAML 清单

K8s 的资源几乎都是用 YAML 声明的。下面是一个运行 Nginx 的 Pod 定义:

apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
  labels:
    app: nginx
    env: dev
spec:
  containers:
    - name: nginx
      image: nginx:1.25
      ports:
        - containerPort: 80

把上面的内容保存为 nginx-pod.yaml,然后执行创建命令:

kubectl apply -f nginx-pod.yaml

第二步:查看 Pod 状态

创建之后,用下面的命令确认 Pod 是否正常运行:

kubectl get pods
kubectl get pods -o wide
kubectl describe pod nginx-pod

get pods -o wide 可以看到 Pod 被调度到了哪个节点、分配到了哪个 IP;describe 则能看到更详细的 Events,方便排障。

第三步:验证 Label 与 Selector 的配合

Label 的真正价值在于被 Selector 使用。我们创建一个 Service,让它通过 Selector 选中上面打了 app=nginx 标签的 Pod:

apiVersion: v1
kind: Service
metadata:
  name: nginx-svc
spec:
  selector:
    app: nginx
  ports:
    - port: 80
      targetPort: 80

保存为 nginx-svc.yaml 并应用:

kubectl apply -f nginx-svc.yaml
kubectl get svc nginx-svc
kubectl get endpoints nginx-svc

执行 get endpoints 后,你会看到 Service 自动把 app=nginx 的 Pod IP 挂载到了 Endpoints 上。这就是 Label + Selector 最经典的协作方式:Pod 贴标签,Service 用选择器找到它。

第四步:用命名空间做资源分组

下面我们创建一个名为 dev 的命名空间,并把资源创建到其中:

kubectl create namespace dev
kubectl get namespaces

如果希望把 Pod 建到 dev 命名空间,只需要在 metadata 里加上 namespace 字段:

apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
  namespace: dev
  labels:
    app: nginx
spec:
  containers:
    - name: nginx
      image: nginx:1.25

或者直接使用命令行指定:

kubectl apply -f nginx-pod.yaml -n dev
kubectl get pods -n dev

常见问题:新手最容易踩的坑

为什么 Pod 一直处于 Pending 状态?

Pending 意味着 Pod 已经被 API Server 接受,但还没有被成功调度到节点上。常见原因包括:集群资源不足、节点不可用、或者 Pod 声明的资源请求超过了节点剩余容量。用 kubectl describe pod 查看 Events,通常能直接看到具体原因。

Label 和 Annotation 有什么区别?

Label 用于标识和筛选资源,会被 Selector 使用,因此有长度和字符集限制;Annotation 则用来存放非标识性的元数据(比如构建信息、联系方式、运维说明),不会被 Selector 用来选择资源,可以存更长的自由文本。

一个 Pod 里放多个容器有什么好处?

当多个容器需要紧密共享网络和存储、且生命周期一致时,可以把它们放进同一个 Pod。典型场景是”边车(Sidecar)”模式:比如主容器跑业务,边车容器负责日志采集或配置刷新。但要注意,同一 Pod 内的容器是”共进退”的,一个失败可能拖累整体。

命名空间能实现真正的隔离吗?

命名空间提供的是”逻辑隔离”,不是像虚拟机那样的强隔离。它隔离的是资源名称和部分权限,不同命名空间的 Pod 默认仍然可以互相通信(除非用 NetworkPolicy 限制)。真正要做强隔离,还需要配合网络策略、资源配额(ResourceQuota)和 RBAC。

总结

今天我们讲清楚了 Kubernetes 的四个核心对象:Pod 是最小调度单位,Label 是贴在资源上的标签,Selector 是根据标签筛选资源的机制,Namespace 则是逻辑隔离的边界。它们之间的关系可以浓缩成一句话:Pod 承载应用,Label 标记资源,Selector 连接资源,Namespace 划分空间

掌握这四个概念之后,你已经能够独立地”声明”并运行一个最简单的应用了。但从运维角度看,直接手动管理裸 Pod 是远远不够的——Pod 一旦挂了不会自动重建,扩容缩容也得靠人肉操作。这就需要我们引入工作负载控制器。下一篇文章,我们将进入 Deployment、ReplicaSet 与滚动更新,看看 K8s 是如何让应用”自愈”和”滚动升级”的。

下期预告

下一篇《K8s 运维系列 | 第 4 天:工作负载——Deployment、ReplicaSet 与滚动更新》将带你理解控制器模式,学会如何让应用实现自动修复、水平扩容和无损滚动发布,敬请期待。

微信二维码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片快捷回复

    暂无评论内容