【云原生】三.Kubernetes核心对象(上):Pod与Label详解

写在前面

在上一篇文章中,我们了解了Kubernetes的整体架构和环境搭建方法。现在,我们需要深入理解Kubernetes的核心对象------Pod和Label。Pod是Kubernetes中最小的调度单元,Label则是资源组织和管理的关键机制。理解这两个概念,是掌握Kubernetes的基础。

这篇文章将详细讲解Pod的概念、生命周期、多容器模式和Init容器,以及Label和Selector的使用方法,帮助你建立对Kubernetes核心对象的深入理解。

一、Pod:最小调度单元

1.1 Pod的概念

Pod是Kubernetes中最小的可部署单元,它封装了一个或多个容器、存储资源、网络IP地址以及控制容器运行方式的选项。可以把Pod理解为一组共享资源的"进程组"。

复制代码
┌─────────────────────────────────────────────────────────────────────────┐
│                           Pod结构示意图                                   │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│   ┌─────────────────────────────────────────────────────────────────┐  │
│   │                           Pod                                    │  │
│   │  ┌─────────────────────────────────────────────────────────────┐│  │
│   │  │                    共享资源层                                ││  │
│   │  │  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐        ││  │
│   │  │  │   网络命名空间 │  │   IPC命名空间 │  │   存储卷     │        ││  │
│   │  │  │  (Network)  │  │   (IPC)     │  │  (Volumes)  │        ││  │
│   │  │  └─────────────┘  └─────────────┘  └─────────────┘        ││  │
│   │  └─────────────────────────────────────────────────────────────┘│  │
│   │                              │                                   │  │
│   │                              ▼                                   │  │
│   │  ┌─────────────────────────────────────────────────────────────┐│  │
│   │  │                    容器层                                    ││  │
│   │  │  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐        ││  │
│   │  │  │   容器A     │  │   容器B     │  │   容器C     │        ││  │
│   │  │  │  (主容器)   │  │ (Sidecar)   │  │ (Sidecar)   │        ││  │
│   │  │  │             │  │             │  │             │        ││  │
│   │  │  │  - 应用进程  │  │  - 日志收集  │  │  - 监控代理  │        ││  │
│   │  │  └─────────────┘  └─────────────┘  └─────────────┘        ││  │
│   │  └─────────────────────────────────────────────────────────────┘│  │
│   │                                                                 │  │
│   │  Pod IP: 10.244.1.5                                             │  │
│   │  Pod名称: my-app-xxxxx-yyyyy                                    │  │
│   └─────────────────────────────────────────────────────────────────┘  │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

Pod的核心特点:

共享网络命名空间:Pod内的所有容器共享同一个网络命名空间,它们可以通过localhost相互通信,共享同一个IP地址和端口空间。

共享存储卷:Pod内的容器可以共享存储卷,实现数据共享和持久化。

共享IPC命名空间:Pod内的容器可以通过IPC(进程间通信)机制进行通信。

原子性调度:Pod作为一个整体被调度到节点上,不会出现容器分散在不同节点的情况。

1.2 为什么需要Pod

你可能会问,为什么不直接调度容器,而要引入Pod这个概念?这涉及到容器编排的核心问题。

在容器化应用中,经常需要多个紧密协作的容器一起工作。例如:

  • 主容器+日志收集器:主应用容器产生日志,Sidecar容器负责收集和发送日志
  • 主容器+配置更新器:主应用容器读取配置,Sidecar容器负责监听配置变更
  • 主容器+代理容器:主应用容器处理业务逻辑,Sidecar容器负责网络代理

这些容器需要紧密协作,它们应该作为一个整体被调度和管理。Pod正是为这种场景设计的------它将紧密协作的容器组合在一起,作为一个原子单元进行调度。

1.3 Pod的YAML定义

下面是一个完整的Pod YAML定义:

复制代码
apiVersion: v1                    # API版本
kind: Pod                         # 资源类型
metadata:                         # 元数据
  name: my-app-pod                # Pod名称
  namespace: default              # 命名空间
  labels:                         # 标签
    app: my-app
    environment: production
  annotations:                    # 注解
    description: "This is my application pod"
spec:                             # 规格定义
  containers:                     # 容器列表
  - name: app-container           # 容器名称
    image: nginx:1.21             # 镜像
    imagePullPolicy: IfNotPresent # 镜像拉取策略
    ports:                        # 端口定义
    - containerPort: 80
      name: http
      protocol: TCP
    env:                          # 环境变量
    - name: APP_ENV
      value: "production"
    - name: DB_HOST
      valueFrom:
        configMapKeyRef:
          name: app-config
          key: db_host
    resources:                    # 资源限制
      requests:                   # 最小资源需求
        memory: "128Mi"
        cpu: "100m"
      limits:                     # 最大资源限制
        memory: "256Mi"
        cpu: "200m"
    volumeMounts:                 # 挂载卷
    - name: app-data
      mountPath: /data
    - name: config-volume
      mountPath: /etc/config
      readOnly: true
    livenessProbe:                # 存活探针
      httpGet:
        path: /health
        port: 80
      initialDelaySeconds: 30
      periodSeconds: 10
    readinessProbe:               # 就绪探针
      httpGet:
        path: /ready
        port: 80
      initialDelaySeconds: 5
      periodSeconds: 5
  volumes:                        # 卷定义
  - name: app-data
    emptyDir: {}
  - name: config-volume
    configMap:
      name: app-config
  restartPolicy: Always           # 重启策略
  nodeSelector:                   # 节点选择器
    disktype: ssd
  tolerations:                    # 容忍度
  - key: "dedicated"
    operator: "Equal"
    value: "app"
    effect: "NoSchedule"

1.4 Pod的生命周期

Pod的生命周期包含多个阶段,理解这些阶段对于调试和管理Pod至关重要。

复制代码
┌─────────────────────────────────────────────────────────────────────────┐
│                        Pod生命周期状态流转                                 │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│   ┌─────────────┐                                                    │
│   │   Pending   │  Pod已创建,等待调度到节点                           │
│   └──────┬──────┘                                                    │
│          │ 调度成功                                                    │
│          ▼                                                           │
│   ┌─────────────┐                                                    │
│   │   Running   │  Pod已绑定节点,容器正在运行                         │
│   └──────┬──────┘                                                    │
│          │                                                           │
│          ├──────────────────────┬──────────────────────┐              │
│          ▼                      ▼                      ▼              │
│   ┌─────────────┐        ┌─────────────┐        ┌─────────────┐      │
│   │  Succeeded  │        │   Failed    │        │   Unknown   │      │
│   │  成功完成    │        │   运行失败   │        │   状态未知   │      │
│   └─────────────┘        └─────────────┘        └─────────────┘      │
│                                                                         │
│   容器状态:                                                             │
│   ┌─────────────┐  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐  │
│   │   Waiting   │  │   Running   │  │  Terminated │  │   Unknown   │  │
│   │   等待中    │  │   运行中    │  │   已终止    │  │    未知     │  │
│   └─────────────┘  └─────────────┘  └─────────────┘  └─────────────┘  │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

Pod阶段(Phase)

|-----------|------------------------------------------|
| 阶段 | 说明 |
| Pending | Pod已被Kubernetes接受,但容器尚未创建。包括调度时间和下载镜像时间。 |
| Running | Pod已绑定到节点,所有容器都已创建,至少有一个容器正在运行。 |
| Succeeded | Pod中的所有容器都已成功终止,不会重启。 |
| Failed | Pod中的所有容器都已终止,至少有一个容器以失败状态终止。 |
| Unknown | 无法获取Pod状态,通常是与节点通信失败。 |

容器状态

  • Waiting:容器正在等待启动,可能正在拉取镜像或应用Secret
  • Running:容器正在运行
  • Terminated:容器已终止,可能是成功完成或失败退出
  • Unknown:无法获取容器状态

查看Pod状态:

复制代码
# 查看Pod状态
kubectl get pods

# 查看Pod详细信息
kubectl describe pod pod-name

# 查看Pod的YAML定义
kubectl get pod pod-name -o yaml

# 查看Pod状态(JSON格式)
kubectl get pod pod-name -o jsonpath='{.status.phase}'

1.5 Pod的重启策略

Pod的重启策略决定了容器退出后的行为:

|-----------|----------------|
| 策略 | 说明 |
| Always | 容器退出后总是重启(默认值) |
| OnFailure | 只有失败时才重启 |
| Never | 从不重启 |

复制代码
apiVersion: v1
kind: Pod
metadata:
  name: restart-demo
spec:
  restartPolicy: OnFailure    # 设置重启策略
  containers:
  - name: app
    image: busybox
    command: ["sh", "-c", "echo 'Hello' && exit 1"]

1.6 Pod的探针

探针是Kubernetes检测容器健康状态的机制,有三种类型:

存活探针(Liveness Probe):检测容器是否存活。如果探测失败,Kubernetes会重启容器。

就绪探针(Readiness Probe):检测容器是否准备好接收流量。如果探测失败,Service会将该Pod从Endpoints中移除。

启动探针(Startup Probe):检测容器是否已启动。对于启动时间较长的应用,可以避免被存活探针杀死。

复制代码
apiVersion: v1
kind: Pod
metadata:
  name: probe-demo
spec:
  containers:
  - name: app
    image: nginx
    # 存活探针
    livenessProbe:
      httpGet:
        path: /health
        port: 80
      initialDelaySeconds: 30    # 初始延迟
      periodSeconds: 10          # 检测间隔
      timeoutSeconds: 5          # 超时时间
      failureThreshold: 3        # 失败阈值
    # 就绪探针
    readinessProbe:
      httpGet:
        path: /ready
        port: 80
      initialDelaySeconds: 5
      periodSeconds: 5
    # 启动探针
    startupProbe:
      httpGet:
        path: /health
        port: 80
      initialDelaySeconds: 0
      periodSeconds: 10
      failureThreshold: 30       # 允许失败30次(300秒)

探针的三种检测方式:

复制代码
# HTTP GET探针
livenessProbe:
  httpGet:
    path: /health
    port: 80
    httpHeaders:
    - name: Custom-Header
      value: value

# TCP Socket探针
livenessProbe:
  tcpSocket:
    port: 80

# Exec探针(执行命令)
livenessProbe:
  exec:
    command:
    - cat
    - /tmp/health

二、多容器Pod模式

2.1 Sidecar模式

Sidecar模式是最常见的多容器模式,辅助容器与主容器协同工作。

复制代码
┌─────────────────────────────────────────────────────────────────────────┐
│                        Sidecar模式示意图                                  │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│   ┌─────────────────────────────────────────────────────────────────┐  │
│   │                           Pod                                    │  │
│   │  ┌─────────────────────────┐  ┌─────────────────────────┐      │  │
│   │  │      主容器              │  │     Sidecar容器          │      │  │
│   │  │                         │  │                         │      │  │
│   │  │  ┌─────────────────┐   │  │  ┌─────────────────┐   │      │  │
│   │  │  │   应用进程       │   │  │  │   日志收集器     │   │      │  │
│   │  │  │                 │   │  │  │                 │   │      │  │
│   │  │  │  写入日志文件    │───┼──┼─▶│  读取日志文件    │   │      │  │
│   │  │  │                 │   │  │  │                 │   │      │  │
│   │  │  └─────────────────┘   │  │  │  发送到中心      │   │      │  │
│   │  │                         │  │  └─────────────────┘   │      │  │
│   │  └─────────────────────────┘  └─────────────────────────┘      │  │
│   │              │                           │                      │  │
│   │              ▼                           ▼                      │  │
│   │  ┌─────────────────────────────────────────────────────────┐  │  │
│   │  │                    共享存储卷                             │  │  │
│   │  │                    /var/log/app                          │  │  │
│   │  └─────────────────────────────────────────────────────────┘  │  │
│   └─────────────────────────────────────────────────────────────────┘  │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

Sidecar模式的典型应用场景:

  • 日志收集:主容器写入日志文件,Sidecar容器收集并发送到日志系统
  • 配置同步:Sidecar容器监听配置变更,更新主容器的配置文件
  • 代理服务:Sidecar容器作为代理,处理网络通信
  • 监控采集:Sidecar容器采集主容器的指标数据

Sidecar示例:

复制代码
apiVersion: v1
kind: Pod
metadata:
  name: sidecar-demo
spec:
  containers:
  # 主容器:Nginx
  - name: nginx
    image: nginx
    volumeMounts:
    - name: logs
      mountPath: /var/log/nginx
  # Sidecar容器:日志收集器
  - name: log-collector
    image: fluent/fluentd
    volumeMounts:
    - name: logs
      mountPath: /var/log/nginx
      readOnly: true
  volumes:
  - name: logs
    emptyDir: {}

2.2 Ambassador模式

Ambassador模式中,辅助容器作为代理,代表主容器与外部服务通信。

复制代码
┌─────────────────────────────────────────────────────────────────────────┐
│                        Ambassador模式示意图                                │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│   ┌─────────────────────────────────────────────────────────────────┐  │
│   │                           Pod                                    │  │
│   │  ┌─────────────────────────┐  ┌─────────────────────────┐      │  │
│   │  │      主容器              │  │    Ambassador容器        │      │  │
│   │  │                         │  │                         │      │  │
│   │  │  ┌─────────────────┐   │  │  ┌─────────────────┐   │      │  │
│   │  │  │   应用进程       │   │  │  │   代理服务       │   │      │  │
│   │  │  │                 │   │  │  │                 │   │      │  │
│   │  │  │  访问本地端口    │───┼──┼─▶│  转发到外部服务  │───┼────┼──┼──▶ 外部服务
│   │  │  │  localhost:3306 │   │  │  │                 │   │    │  │  │
│   │  │  └─────────────────┘   │  │  └─────────────────┘   │    │  │  │
│   │  │                         │  │                         │    │  │  │
│   │  └─────────────────────────┘  └─────────────────────────┘    │  │  │
│   │                                                               │  │  │
│   │  主容器通过localhost访问Ambassador,Ambassador代理到外部服务    │  │  │
│   │                                                               │  │  │
│   └─────────────────────────────────────────────────────────────────┘  │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

Ambassador示例:

复制代码
apiVersion: v1
kind: Pod
metadata:
  name: ambassador-demo
spec:
  containers:
  # 主容器:应用
  - name: app
    image: my-app
    env:
    - name: DB_HOST
      value: "localhost"    # 连接本地代理
    - name: DB_PORT
      value: "3306"
  # Ambassador容器:数据库代理
  - name: db-proxy
    image: envoyproxy/envoy
    ports:
    - containerPort: 3306
    volumeMounts:
    - name: envoy-config
      mountPath: /etc/envoy
  volumes:
  - name: envoy-config
    configMap:
      name: envoy-config

2.3 Adapter模式

Adapter模式中,辅助容器将主容器的输出转换为统一格式。

复制代码
┌─────────────────────────────────────────────────────────────────────────┐
│                        Adapter模式示意图                                  │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│   ┌─────────────────────────────────────────────────────────────────┐  │
│   │                           Pod                                    │  │
│   │  ┌─────────────────────────┐  ┌─────────────────────────┐      │  │
│   │  │      主容器              │  │     Adapter容器          │      │  │
│   │  │                         │  │                         │      │  │
│   │  │  ┌─────────────────┐   │  │  ┌─────────────────┐   │      │  │
│   │  │  │   应用进程       │   │  │  │   格式转换器     │   │      │  │
│   │  │  │                 │   │  │  │                 │   │      │  │
│   │  │  │  输出自定义格式  │───┼──┼─▶│  转换为标准格式  │───┼────┼──┼──▶ 监控系统
│   │  │  │                 │   │  │  │                 │   │    │  │  │
│   │  │  └─────────────────┘   │  │  └─────────────────┘   │    │  │  │
│   │  │                         │  │                         │    │  │  │
│   │  └─────────────────────────┘  └─────────────────────────┘    │  │  │
│   │                                                               │  │  │
│   │  Adapter将不同应用的输出转换为统一的监控格式                      │  │  │
│   │                                                               │  │  │
│   └─────────────────────────────────────────────────────────────────┘  │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

Adapter示例:

复制代码
apiVersion: v1
kind: Pod
metadata:
  name: adapter-demo
spec:
  containers:
  # 主容器:应用
  - name: app
    image: my-app
    volumeMounts:
    - name: metrics
      mountPath: /var/metrics
  # Adapter容器:指标转换
  - name: metrics-adapter
    image: prom/statsd-exporter
    volumeMounts:
    - name: metrics
      mountPath: /var/metrics
      readOnly: true
  volumes:
  - name: metrics
    emptyDir: {}

三、Init容器

3.1 Init容器的概念

Init容器是一种特殊容器,在Pod的主容器启动之前运行。Init容器必须成功完成,主容器才会启动。

复制代码
┌─────────────────────────────────────────────────────────────────────────┐
│                        Init容器执行流程                                   │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│   时间线 ────────────────────────────────────────────────────────────▶  │
│                                                                         │
│   ┌─────────────┐  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐  │
│   │ Init容器1   │  │ Init容器2   │  │ Init容器3   │  │  主容器     │  │
│   │             │  │             │  │             │  │             │  │
│   │  初始化数据库│  │  下载配置   │  │  等待依赖   │  │  启动应用   │  │
│   │             │  │             │  │             │  │             │  │
│   └─────────────┘  └─────────────┘  └─────────────┘  └─────────────┘  │
│          │                │                │                │          │
│          ▼                ▼                ▼                ▼          │
│       成功完成         成功完成         成功完成         开始运行       │
│                                                                         │
│   特点:                                                                 │
│   - Init容器按顺序执行,前一个成功后才执行下一个                           │
│   - Init容器失败会导致Pod重启,重新执行所有Init容器                         │
│   - Init容器不支持探针                                                   │
│   - Init容器与主容器共享存储卷和网络命名空间                               │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

3.2 Init容器的应用场景

  • 等待依赖服务就绪:等待数据库、缓存等服务启动完成
  • 初始化数据库:创建数据库表、导入初始数据
  • 下载配置文件:从远程服务器下载配置
  • 注册服务:向服务发现系统注册

3.3 Init容器示例

复制代码
apiVersion: v1
kind: Pod
metadata:
  name: init-demo
spec:
  initContainers:
  # Init容器1:等待数据库就绪
  - name: wait-for-db
    image: busybox
    command: ['sh', '-c', 'until nc -z mysql-service 3306; do echo waiting for mysql; sleep 2; done;']
  
  # Init容器2:初始化数据库
  - name: init-db
    image: mysql:5.7
    command: ['sh', '-c', 'mysql -h mysql-service -u root -p$MYSQL_ROOT_PASSWORD < /init-scripts/init.sql']
    env:
    - name: MYSQL_ROOT_PASSWORD
      valueFrom:
        secretKeyRef:
          name: mysql-secret
          key: root-password
    volumeMounts:
    - name: init-scripts
      mountPath: /init-scripts
  
  # Init容器3:下载配置
  - name: download-config
    image: busybox
    command: ['sh', '-c', 'wget -O /config/app.conf http://config-server/app.conf']
    volumeMounts:
    - name: config
      mountPath: /config
  
  # 主容器
  containers:
  - name: app
    image: my-app
    volumeMounts:
    - name: config
      mountPath: /etc/app/config
  
  volumes:
  - name: init-scripts
    configMap:
      name: init-scripts
  - name: config
    emptyDir: {}

3.4 Init容器与普通容器的区别

|------|------------|---------|
| 特性 | Init容器 | 普通容器 |
| 执行时机 | 主容器启动前 | Pod运行期间 |
| 执行顺序 | 顺序执行 | 并行执行 |
| 重启条件 | 任何Init容器失败 | 根据重启策略 |
| 探针支持 | 不支持 | 支持 |
| 生命周期 | 一次性 | 持续运行 |

四、Label和Selector

4.1 Label的概念

Label是附加在Kubernetes对象上的键值对,用于组织和选择资源。Label是用户定义的标识,可以用于分组、查询和操作资源。

复制代码
metadata:
  labels:
    app: my-app              # 应用名称
    environment: production  # 环境标识
    tier: frontend           # 层级
    version: v1.2.0          # 版本号
    team: backend            # 团队归属

Label的特点:

  • 键值对形式:每个Label由键和值组成
  • 可变性:Label可以在运行时添加、修改或删除
  • 选择性:通过Selector选择具有特定Label的资源
  • 命名空间作用域:Label只在同一命名空间内有效

4.2 Label的命名规范

Label的键和值有一定的命名规范:

键的格式[前缀/]名称

  • 前缀:可选,必须是DNS子域名格式,最长253字符
  • 名称:必须以字母或数字开头和结尾,可包含字母、数字、连字符、下划线和点,最长63字符

值的格式

4.3 Selector的使用

Selector用于选择具有特定Label的资源,有两种类型:

等值Selector:匹配Label的值是否相等

复制代码
# 选择app=my-app的Pod
kubectl get pods -l app=my-app

# 选择多个Label
kubectl get pods -l app=my-app,environment=production

# 选择不等于某个值
kubectl get pods -l app!=my-app

集合Selector:匹配Label的值是否在某个集合中

复制代码
# 选择environment为production或staging的Pod
kubectl get pods -l 'environment in (production,staging)'

# 选择environment不在production的Pod
kubectl get pods -l 'environment notin (production)'

# 选择有某个Label的Pod
kubectl get pods -l 'app'

# 选择没有某个Label的Pod
kubectl get pods -l '!app'

4.4 在YAML中使用Selector

复制代码
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  # 选择器:选择要管理的Pod
  selector:
    matchLabels:           # 等值匹配
      app: my-app
    matchExpressions:      # 表达式匹配
    - key: environment
      operator: In
      values:
      - production
      - staging
    - key: tier
      operator: Exists     # 存在性匹配
  template:
    metadata:
      labels:              # Pod模板的Label
        app: my-app
        environment: production
        tier: frontend
    spec:
      containers:
      - name: app
        image: my-app:latest

Selector操作符:

|--------------|-----------|---------------------------------|
| 操作符 | 说明 | 示例 |
| In | 值在指定集合中 | environment in (prod,staging) |
| NotIn | 值不在指定集合中 | environment notin (dev) |
| Exists | 存在该Label | app |
| DoesNotExist | 不存在该Label | !app |

4.5 Label操作命令

复制代码
# 添加Label
kubectl label pod my-pod app=my-app

# 修改Label
kubectl label pod my-pod app=my-new-app --overwrite

# 删除Label
kubectl label pod my-pod app-

# 查看Label
kubectl get pods --show-labels

# 按Label筛选
kubectl get pods -l app=my-app

# 按Label排序
kubectl get pods --sort-by=.metadata.labels.app

4.6 Label的最佳实践

使用标准Label前缀

复制代码
# Kubernetes推荐的Label
app.kubernetes.io/name: my-app           # 应用名称
app.kubernetes.io/instance: my-app-xyz   # 实例标识
app.kubernetes.io/version: "1.0.0"       # 版本号
app.kubernetes.io/component: backend     # 组件类型
app.kubernetes.io/part-of: my-system     # 所属系统
app.kubernetes.io/managed-by: helm       # 管理工具

保持Label的一致性

复制代码
# Deployment和Pod的Label应该一致
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
  labels:
    app: my-app
spec:
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app    # 与selector匹配

使用有意义的Label

复制代码
labels:
  # 应用相关
  app: my-app
  version: v1.0.0
  
  # 环境相关
  environment: production
  region: cn-east-1
  
  # 架构相关
  tier: frontend
  component: web
  
  # 团队相关
  team: platform
  owner: backend-team

五、实战案例:部署多容器应用

让我们通过一个完整的案例,演示Pod、多容器模式和Label的综合应用。

5.1 应用场景

部署一个Web应用,包含:

  • Nginx主容器:提供Web服务
  • Fluentd Sidecar:收集日志
  • Init容器:等待数据库就绪

5.2 完整YAML配置

复制代码
apiVersion: v1
kind: Pod
metadata:
  name: web-app
  labels:
    app: web-app
    environment: production
    tier: frontend
    version: v1.0.0
spec:
  # Init容器:等待数据库
  initContainers:
  - name: wait-for-db
    image: busybox:1.35
    command:
    - sh
    - -c
    - |
      echo "Waiting for database..."
      until nc -z mysql-service 3306; do
        echo "Database is not ready yet..."
        sleep 2
      done
      echo "Database is ready!"

  # 主容器
  containers:
  # Nginx容器
  - name: nginx
    image: nginx:1.21
    ports:
    - containerPort: 80
      name: http
    volumeMounts:
    - name: html
      mountPath: /usr/share/nginx/html
    - name: logs
      mountPath: /var/log/nginx
    resources:
      requests:
        memory: "64Mi"
        cpu: "100m"
      limits:
        memory: "128Mi"
        cpu: "200m"
    livenessProbe:
      httpGet:
        path: /
        port: 80
      initialDelaySeconds: 10
      periodSeconds: 10
    readinessProbe:
      httpGet:
        path: /
        port: 80
      initialDelaySeconds: 5
      periodSeconds: 5

  # Sidecar容器:日志收集
  - name: fluentd
    image: fluent/fluentd:v1.14
    volumeMounts:
    - name: logs
      mountPath: /var/log/nginx
      readOnly: true
    - name: fluentd-config
      mountPath: /fluentd/etc
    resources:
      requests:
        memory: "32Mi"
        cpu: "50m"
      limits:
        memory: "64Mi"
        cpu: "100m"

  # 存储卷
  volumes:
  - name: html
    emptyDir: {}
  - name: logs
    emptyDir: {}
  - name: fluentd-config
    configMap:
      name: fluentd-config

  # 重启策略
  restartPolicy: Always

  # 节点选择
  nodeSelector:
    kubernetes.io/os: linux

5.3 部署和验证

复制代码
# 创建ConfigMap
kubectl create configmap fluentd-config --from-file=fluent.conf

# 创建Pod
kubectl apply -f web-app.yaml

# 查看Pod状态
kubectl get pods -l app=web-app

# 查看Pod详情
kubectl describe pod web-app

# 查看Init容器日志
kubectl logs web-app -c wait-for-db

# 查看主容器日志
kubectl logs web-app -c nginx

# 查看Sidecar容器日志
kubectl logs web-app -c fluentd

# 进入主容器
kubectl exec -it web-app -c nginx -- /bin/bash

# 查看Label
kubectl get pods --show-labels

# 按Label筛选
kubectl get pods -l app=web-app,environment=production

总结

这篇文章详细讲解了Kubernetes的核心对象------Pod和Label,主要内容包括:

  1. Pod的概念:Pod是Kubernetes最小的调度单元,封装了容器和共享资源
  2. Pod的生命周期:理解Pod的阶段和容器状态,掌握重启策略和探针机制
  3. 多容器Pod模式:Sidecar、Ambassador、Adapter三种常见模式及应用场景
  4. Init容器:在主容器启动前执行初始化任务的特殊容器
  5. Label和Selector:资源组织和选择的关键机制

Pod和Label是Kubernetes的基础,理解它们对于后续学习Deployment、Service等高级对象至关重要。下一篇文章将继续讲解Kubernetes的核心对象------Deployment、Service和Namespace,深入理解Kubernetes如何管理无状态应用和实现服务发现。

相关推荐
only_Klein8 小时前
Kubernetes发布策略之蓝绿发布与金丝雀发布
云原生·容器·kubernetes
@hdd11 小时前
Kubernetes 可观测性:Prometheus 监控、日志采集与告警
云原生·kubernetes·wpf·prometheus
yunteng52112 小时前
Sealos部署k8s集群
云原生·容器·kubernetes·sealos
好学且牛逼的马16 小时前
从“配置地狱“到“云原生时代“:Spring Boot 1.x到4.x演进全记录与核心知识点详解
hive·spring boot·云原生
岱宗夫up18 小时前
FastAPI进阶3:云原生架构与DevOps最佳实践
前端·python·云原生·架构·前端框架·fastapi·devops
技术栈壳18 小时前
了解K8s
云原生·容器·kubernetes
Tadas-Gao18 小时前
微服务注册中心选型深度分析:Eureka、Nacos与新一代替代方案
java·分布式·微服务·云原生·eureka·架构·系统架构
m0_4889130118 小时前
新手小白也能学会的Dify本地部署教程(超详细)
人工智能·搜索引擎·云原生·eureka·开源·大模型·产品经理
AI开发架构师18 小时前
大数据领域Eureka的服务注册中心搭建
大数据·ai·云原生·eureka