4. Kubernetes核心概念:Pod、Service、Deployment、Namespace、ConfigMap、Secret等核心资源对象

聊到Kubernetes,很多人第一反应就是“编排”。但说白了,K8s的核心就是一堆资源对象。你把这些对象定义好,它就能帮你把应用跑起来、管起来。今天我就带你过一遍最常用的那几个——Pod、Service、Deployment、Namespace、ConfigMap、Secret。这些都是我每天打交道的东西,踩过的坑也不少,咱们一个一个说。

4.1 Pod:最小的调度单元

Pod是K8s里最小的部署单元。一个Pod可以包含一个或多个容器。为什么要有Pod?因为有些容器需要共享网络和存储,比如一个日志采集容器和一个业务容器,它们得待在一起。

我个人习惯,一个Pod里只放一个主容器。除非有明确的“边车模式”需求,比如加个Envoy代理或者日志采集器。否则,别把一堆不相干的容器塞进一个Pod,那是给自己找麻烦。

核心要点:

  • Pod内的容器共享同一个网络命名空间(IP和端口)
  • Pod内的容器共享存储卷(Volume)
  • Pod是短暂的,随时可能被销毁重建

举个例子,一个简单的Nginx Pod定义长这样:

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

嗯,这里要注意:Pod的IP是动态分配的。你没法保证它重启后IP不变。所以,直接访问Pod IP是不靠谱的。那怎么办?用Service。

4.2 Service:稳定的访问入口

Service解决了Pod IP不固定的问题。它提供一个稳定的虚拟IP(ClusterIP),背后代理一组Pod。你访问Service,它帮你把请求转发到某个Pod上。

我在项目中遇到过一个问题:有个同事直接写死了Pod IP,结果Pod一重启,整个服务就挂了。后来改成Service,再也没出过事。说白了,Service就是K8s里的“负载均衡器”。

Service的类型有几种:

类型 说明 使用场景
ClusterIP 集群内部可访问,外部不可达 内部服务调用
NodePort 在每个节点上开放一个端口,外部可通过节点IP+端口访问 开发测试环境
LoadBalancer 云厂商提供的外部负载均衡器 生产环境对外暴露服务

一个简单的Service定义:

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

注意看selector字段,它通过标签选择Pod。只要Pod的标签匹配,Service就会自动把流量转发过去。

4.3 Deployment:声明式更新与扩缩容

Deployment是我用得最多的资源。它管理Pod的副本数、滚动更新、回滚等。你想想看,如果手动管理Pod,扩缩容得一个个删、一个个建,多麻烦。Deployment把这些都自动化了。

我曾经在生产环境遇到过一个问题:更新镜像时,新版本有Bug,导致Pod启动失败。Deployment自动触发了回滚策略,把Pod恢复到了上一个版本。整个过程我没做任何操作,它自己就搞定了。这就是声明式的好处——你告诉它“我要什么状态”,它自己想办法达成。

一个典型的Deployment定义:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.21
        ports:
        - containerPort: 80

避坑指南:我曾经把replicas设成0,结果Pod全被删了。后来才意识到,Deployment会严格按照你定义的副本数来管理。所以,改副本数之前,先想清楚。

4.4 Namespace:逻辑隔离

Namespace用来做逻辑隔离。一个集群里可以划分多个Namespace,每个Namespace里的资源互不干扰。比如,开发环境用dev命名空间,生产环境用prod命名空间。

我个人习惯,每个项目单独一个Namespace。这样资源管理起来清晰,权限控制也方便。你想想看,如果所有Pod都堆在default命名空间里,时间长了根本分不清谁是谁。

创建Namespace很简单:

apiVersion: v1
kind: Namespace
metadata:
  name: my-project

然后在其他资源里指定namespace: my-project即可。

4.5 ConfigMap与Secret:配置管理

这两个资源都是用来管理配置的。区别在于:ConfigMap存明文配置,Secret存敏感信息(密码、密钥等)。

ConfigMap的例子:

apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
data:
  app.properties: |
    db.host=localhost
    db.port=3306

Secret的例子:

apiVersion: v1
kind: Secret
metadata:
  name: db-secret
type: Opaque
data:
  password: bXlwYXNzd29yZA==  # base64编码后的密码

注意:Secret的data字段要求base64编码,但这只是简单的编码,不是加密。别把真正的敏感信息直接写进YAML文件里。我建议用外部密钥管理工具(比如Vault)来管理Secret。

在Pod里使用ConfigMap或Secret,有两种方式:

  • 环境变量注入:把配置项变成容器的环境变量
  • 挂载成文件:把配置项挂载到容器的文件系统里

我个人更推荐挂载成文件的方式。因为环境变量在Pod运行期间无法动态更新,而挂载的文件可以热更新(虽然需要应用自己监听文件变化)。

知识体系总览

下面这张图,我把这几个核心资源的关系画出来了。你看一眼就能明白它们是怎么配合的:

Kubernetes核心资源关系图 Namespace(逻辑隔离) Deployment 管理Pod副本数 滚动更新与回滚 Pod 最小调度单元 包含一个或多个容器 Service 稳定的访问入口 负载均衡与服务发现 ConfigMap 明文配置管理 Secret 敏感信息管理 实线:管理关系 虚线:配置注入

从图里能看出来:Deployment管理Pod,Pod通过Service对外暴露,ConfigMap和Secret给Pod注入配置。Namespace把这一切都包在里面,实现隔离。

好了,这几个核心资源就聊到这儿。记住一句话:Pod是基础,Service是入口,Deployment是管家,Namespace是隔间,ConfigMap和Secret是配置中心。把这几个玩明白了,K8s就算入门了。


公众号:蓝海资料掘金营,微信deep3321