首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >闯进 Kubernetes 的世界(四)

闯进 Kubernetes 的世界(四)

作者头像
JanYork_简昀
发布2025-06-08 13:12:13
发布2025-06-08 13:12:13
18500
代码可运行
举报
运行总次数:0
代码可运行

第四章:Kubernetes(K8s) 实战入门:部署有状态应用

在本章节开始之前,交给大家一个任务,自行部署一个可用的 K8s 集群(例如通过 Minikube、Kind 或云服务商提供的 K8s 服务或者本地计算机部署)以及一个配置好 kubectl 命令行的本地环境。

如果你尚未准备好,请参考相关文档完成 K8s 和 Docker 的安装与配置( Windows 或者 Macos 可以通过 Docker Desktop 来简易运行 K8s 服务)。

在前三章中,我们详细探讨了 K8s 的基本概念、架构以及工作原理。现在,是时候将这些理论知识付诸实践了!

本章将带你完成两个常见的实战部署任务:在 K8s 集群中部署一个 Redis 集群和一个 PostgreSQL 数据库。

4.1 理解有状态应用与持久化存储

在开始部署之前,我们需要明确有状态应用持久化存储的概念。

  • 无状态应用 (Stateless Application): 这类应用不存储任何会话数据或用户数据。每次请求都是独立的,不依赖之前的任何状态。例如,一个简单的网页服务器。这类应用在 K8s 中部署起来相对简单,因为它们的 Pod 可以随时被创建、销毁或替换,而不会丢失数据。
  • 有状态应用 (Stateful Application): 这类应用需要持久化地存储数据或者需要存储部分运行时数据,其行为依赖于之前的状态或数据。例如,数据库(PostgreSQL, Redis)、消息队列等。这类应用在 K8s 中部署更复杂,因为 Pod 的销毁意味着数据的丢失,我们必须确保数据能够独立于 Pod 的生命周期而存在。

通常在分布式架构环境的前提下,我们的程序都会尽可能设计为无状态应用(服务)。

为了支持有状态应用,K8s 也引入了持久化存储 (Persistent Storage) 的概念。它允许应用程序将数据存储在独立于 Pod 的存储卷上,即使 Pod 被删除或重新创建,数据也不会丢失。

4.2 部署必备的“工具箱”:K8s 的三个 YAML 文件

在 K8s 中部署任何应用,都需要通过 YAML 文件来描述你期望的集群状态。我们将主要使用以下三种类型的 YAML 文件作为我们的“工具”:

ConfigMap (配置映射):配置的“百宝箱”

  • 作用: 这是一个 K8s 对象,专门用来存储非敏感的配置数据,例如应用程序的配置文件、启动参数、环境变量等。
  • 为什么用它: 它将应用程序的配置与代码分离,让你可以在不修改、不重新构建应用镜像的情况下,灵活地修改配置。就像给你的应用程序准备了一个外部的“操作手册”,随时可以更新。

Service (服务):应用程序的“稳定入口”

  • 作用: Service 为一组 Pod 提供一个稳定、不变的网络地址,无论底层的 Pod IP 如何变化,Service 的地址始终不变。它还负责将流入的流量负载均衡到后端健康的 Pod 上。
  • 为什么用它: Pod 的生命周期是短暂且动态的,IP 地址会变。Service 就像是你的应用程序在 K8s 内部的“电话总机”或“固定门牌号”,保证了其他应用或外部流量总能找到它。

StatefulSet (有状态集):管理有状态应用的“金牌管家”

  • 作用: StatefulSet 是 K8s 专门为有状态应用设计的一种控制器。它能够管理一组 Pod,并为每个 Pod 提供稳定、唯一的网络标识持久化存储
  • 为什么用它: 相比普通的 Deployment,StatefulSet 确保 Pod 具有有序的启动/停止/扩缩容(例如,redis-0 总是第一个启动),并且每个 Pod 都会绑定一个稳定的、唯一的名称和持久化存储卷。这对于数据库等需要数据持久性和身份一致性的应用至关重要。它就像一个“金牌管家”,精心地照顾每一个需要身份和私人空间(持久存储)的应用程序。

感觉没听懂?没有关系,我们来实际的操作一下。

4.3 部署 Redis 集群:键值存储的分布式实践

Redis 是一个高性能的键值存储数据库,常用于缓存、消息队列等场景。为了实现高可用和数据分片,我们通常会部署 Redis 集群。

在 K8s 中,我们主要会用到以下 K8s 对象来部署 Redis 集群:

  • Deployment (部署): 用于管理 Redis 节点的 Pod 副本。
  • Service (服务): 为 Redis 节点提供稳定的网络访问入口。
  • ConfigMap (配置映射): 用于存储 Redis 的配置文件。
  • StatefulSet (有状态集): 这是一个专为有状态应用设计的 K8s 对象,它能为每个 Pod 提供稳定的网络标识和持久化存储。Redis 集群的每个主从节点都需要稳定的身份,因此 StatefulSet 是更合适的选择。
  • PersistentVolumeClaim (持久卷声明, PVC): 声明 Pod 需要的持久化存储空间。
  • PersistentVolume (持久卷, PV): 集群管理员提供的实际存储资源。

部署步骤概览:

  1. 创建 Redis 配置: 使用 ConfigMap 来定义 Redis 的集群模式配置。
  2. 定义持久化存储: 准备好 Pod 需要的存储空间(通过 PV/PVC 机制)。
  3. 部署 Redis 主从节点: 使用 StatefulSet 来部署 Redis 的主从 Pod,确保它们具有稳定的身份和持久化存储。
  4. 暴露 Redis 服务: 使用 Service 来为 Redis 节点提供集群内部的访问入口,并可能通过其他 Service 类型暴露给外部。

让我们赶紧开始吧~。

创建 ConfigMap

我们的目标是部署一个简单的 Redis 集群,包含 3 个主节点和 3 个从节点。为了简化,我们将让每个主节点带一个从节点,共 3 对主从副本。

代码语言:javascript
代码运行次数:0
运行
复制
apiVersion: v1
kind: ConfigMap # 申明类型
metadata:
  name: redis-cluster-config
data:
  # redis.conf(配置信息)
  redis.conf: |
    cluster-enabled yes
    cluster-config-file /data/nodes.conf
    cluster-node-timeout 5000
    appendonly yes
    protected-mode no
    bind 0.0.0.0
    # 确保日志级别为 notice,方便调试
    loglevel notice

创建 Headless Service

为了让 StatefulSet 中的每个 Pod 拥有稳定的网络名称(redis-0.redis-service 等),我们需要一个特殊的 Service,称为 Headless Service (无头服务)。它不会分配一个集群 IP,也不负责负载均衡,而是直接返回所有关联 Pod 的 IP 地址(暴露所有服务的地址)。

代码语言:javascript
代码运行次数:0
运行
复制
apiVersion: v1
kind:Service
metadata:
name:redis-service# 这个名称会被 StatefulSet 用作网络域
labels:
    app:redis-cluster
spec:
ports:
-port:6379# Redis 端口
    name:client
-port:16379# 集群总线端口
    name:cluster
clusterIP:None# 关键:设置为 None 表示这是一个 Headless Service
selector:
    app:redis-cluster

Headless Service 名称 redis-service 将会用于构成 Pod 的完整 FQDN:<pod-name>.<service-name>.<namespace>.svc.cluster.local

创建 StatefulSet

这是核心部分,定义了 Redis Pod 如何被管理、存储和网络标识。我们将创建 6 个副本(3 主 3 从)。

代码语言:javascript
代码运行次数:0
运行
复制
apiVersion: apps/v1
kind:StatefulSet
metadata:
name:redis             # StatefulSet 的名称
labels:                 # StatefulSet 的标签,用于标识
    app:redis-cluster
spec:
serviceName:"redis-service"# 必须指定一个 Headless Service 的名称,StatefulSet 会用它来为 Pod 提供稳定的网络标识
replicas:6             # 定义 Pod 数量,这里是 6 个 (3 主 + 3 从),它们将自动命名为 redis-0,...,redis-5
selector:               # Pod 选择器,用于 StatefulSet 查找和管理其所属的 Pod
    matchLabels:
      app:redis-cluster
template:               # Pod 模板,用于创建 Pod
    metadata:
      labels:             # Pod 的标签,需要与 selector.matchLabels 匹配
        app:redis-cluster
    spec:
      containers:         # 定义 Pod 中运行的容器列表
      -name:redis       # 容器的名称
        image:redis:6.2.7-alpine# 容器使用的镜像及其版本
        command:["redis-server"]# 容器启动时执行的命令,这里是启动 Redis 服务器
        args:["/etc/redis/redis.conf"]# 传递给 command 的参数,指定 Redis 配置文件路径
        ports:
        -containerPort:6379# 容器暴露的端口号,用于客户端连接
          name:client        # 端口名称
        -containerPort:16379# 容器暴露的端口号,用于集群内部通信
          name:cluster
        volumeMounts:         # 容器内卷的挂载点列表
        -name:redis-config# 引用名为 'redis-config' 的卷
          mountPath:/etc/redis# 将该卷挂载到容器内的 /etc/redis 路径
        -name:redis-data    # 引用名为 'redis-data' 的卷
          mountPath:/data    # 将该卷挂载到容器内的 /data 路径 (Redis 数据目录)
        env:                  # 容器内的环境变量列表
        -name:POD_NAME      # 定义一个名为 POD_NAME 的环境变量
          valueFrom:          # 环境变量的值来源于 K8s 的某个字段
            fieldRef:
              fieldPath:metadata.name# 获取当前 Pod 的名称作为环境变量的值 (如 redis-0, redis-1)
      volumes:                  # 定义 Pod 中可用的卷列表
      -name:redis-config      # 定义一个名为 'redis-config' 的卷
        configMap:              # 这个卷的数据来源是 ConfigMap
          name:redis-cluster-config# 引用名为 'redis-cluster-config' 的 ConfigMap
volumeClaimTemplates:# 卷声明模板:StatefulSet 为每个 Pod 自动创建 PVC 的模板
-metadata:
      name:redis-data    # PVC 的名称,每个 Pod 会是 redis-data-<pod-name> (如 redis-data-redis-0)
    spec:
     storageClassName:standard# 明确示例存储类名称
      accessModes:["ReadWriteOnce"]# 存储的访问模式:ReadWriteOnce 表示只能被单个节点以读写模式挂载
      resources:
        requests:
          storage:1Gi      # 请求的存储空间大小,每个 Pod 将获得 1GB
      # storageClassName: your-storage-class # (可选) 指定存储类。如果 K8s 集群没有默认 StorageClass,或者需要特定的存储类型,请在此处指定。例如 'standard' 或 'gp2' (AWS)。

运行 Pod

拓展:

现在,我们配置都已经定义好了,只需要我们开始传达执行命令即可让整个服务运转起来。

kubectl 是 Kubernetes 的命令行工具 (Command-Line Interface)。它是你与 K8s 集群进行交互的主要方式,就像一个遥控器,它允许你发送指令给 K8s 集群的 API Server,从而实现对集群中各种资源的创建、管理、查看、删除等操作。

我们需要使用以下命令来应用我们的配置文件:

代码语言:javascript
代码运行次数:0
运行
复制
kubectl apply -f xxx.yaml
代码语言:javascript
代码运行次数:0
运行
复制
kubectl apply -f redis-config.yaml

kubectl apply -f redis-service.yaml

kubectl apply -f redis-statefulset.yaml
  • Pod: K8s 中最小的部署单元。
  • Service: 用于暴露 Pod 的稳定网络服务。
  • Deployment: 用于管理无状态应用程序的 Pod 副本和更新。
  • StatefulSet: 用于管理有状态应用程序的 Pod 副本,提供稳定的身份和持久化存储。
  • ConfigMap: 用于存储非敏感配置数据。
  • Secret: 用于存储敏感数据(如密码、API 密钥)。
  • PersistentVolumeClaim (PVC): Pod 对持久化存储的请求。
  • PersistentVolume (PV): 集群提供的实际持久化存储资源。
  • Namespace: 用于集群内资源隔离的逻辑分组。
  • Node: 集群中的一台物理或虚拟机(由 K8s 自动发现并创建对应资源)。
  • ReplicaSet: 确保特定数量的 Pod 副本在运行(通常由 Deployment 间接创建和管理)。
  • API Server 解析: 当你使用 kubectl apply -f your-file.yaml 命令提交一个 YAML 文件时,K8s 的 API Server 会首先读取 kind 字段,以确定如何解析和处理这个 YAML 文件。如果 kind 写错了,K8s 就不知道你想要创建什么,从而报错。
  • 资源分类:kind 帮助 K8s 内部系统对各种资源进行分类和管理。
  • CLI 操作: 你在执行 kubectl get <kind>kubectl describe <kind> 等命令时,也需要指定 kind 来筛选和查看特定类型的资源。
  • 有时候我们会将 pvc 模版单独划分为一个文件运行,有时候我们也可能将所有配置都放在一个 yaml 中,本质只是将配置分类。
  • 配置分类都是遵照 kind 的定义来划分的。

好的,我们来详细解释一下 K8s YAML 文件中的 kind 字段。这是一个非常基础但核心的 K8s 概念。


kind:K8s 对象的“类型标识” 在 K8s 的 YAML 定义文件中,kind 字段是有严格规定的,不能自定义名称1. kind 的定义 kind(英文单词“种类”的意思)字段用于指定你正在创建或操作的 K8s 资源的类型。每一个 K8s 资源都有一个唯一的 kind。 K8s 是一个高度模块化的系统,它通过各种不同的“对象”(也就是资源)来管理集群中的各种元素。kind 字段就是用来告诉 K8s API Server:“我正在定义一个什么类型的资源”。 2. 常见的 kind 以下是一些最常见的 kind 值及其对应的 K8s 对象: 3. kind 的重要性 4. kind 的来源 kind 值是 K8s API 定义的一部分,它们由 K8s 的开发者预先定义好,并在 K8s 的官方文档中列出。你可以在 K8s 官方文档的 API 参考中找到所有可用的 kind 类型。

验证 Pod 和 PVC 状态

让我们稍等一段时间,大约半分钟左右,K8s 会自动完成 Pod 的创建。

代码语言:javascript
代码运行次数:0
运行
复制
# 查看 Pod 状态,你应该会看到 `redis-0` 到 `redis-5` 陆续创建并变为 `Running` 状态。
kubectl get pods -l app=redis-cluster

# 查看 PVC 状态,你应该会看到为每个 Pod 自动创建的 PVC,例如 `redis-data-redis-0` 到 `redis-data-redis-5`,它们应该都处于 `Bound` 状态。
kubectl get pvc -l app=redis-cluster

初始化集群

嘿!别着急!还没有结束!

StatefulSet 启动 Redis 实例后,它们仅仅是独立的 Redis 服务器,还没有组成集群。我们需要手动执行 Redis 集群初始化命令。通常,我们会选择一个 Pod(例如 redis-0)来执行这个命令。


通过上述步骤,你已经在 K8s 中成功部署了一个具备持久化存储的 Redis 集群。这展示了 K8s 在管理复杂有状态应用方面的强大能力。

  • 获取所有 Pod 的稳定 DNS 名称:先来解释一下即将要执行的命令:# 定义一个名为 REDIS_POD_IPS 的 Shell 变量# (...) 表示执行括号内的命令,并将其标准输出作为变量的值REDIS_POD_IPS=( \# 使用 kubectl 命令获取 K8s 集群中 Pod 的信息 kubectl get pods \# -l app=redis-cluster 是一个标签选择器,只选择带有 "app: redis-cluster" 标签的 Pod -l app=redis-cluster \# -o jsonpath='...' 指定输出格式为 JSONPath,用于从 JSON 结构中精确提取数据 -o jsonpath='{ \ # {range.items[*]} 遍历 kubectl get pods 返回的 JSON 结果中所有的 Pod 对象 range.items[*] \ # {.status.podIP} 提取每个 Pod 的实际 IP 地址 .status.podIP \ # :6379 手动拼接 Redis 的默认端口号,因为 Redis 集群创建命令需要 "IP:Port" 格式 # {end} 在每个 IP:Port 组合后添加一个空格,确保它们作为独立的参数被后续命令识别 }:6379 {end}' \)# 打印 REDIS_POD_IPS 变量的值,用于验证其内容是否正确# 预期输出类似:"10.244.1.4:6379 10.244.2.5:6379 10.244.1.5:6379 10.244.2.6:6379 10.244.1.6:6379 10.244.2.7:6379 "echo"Redis Pod IPs: REDIS_POD_IPS"----------# kubectl exec -it redis-0 -- 用于在指定的 Pod (redis-0) 内部执行命令# -i: 保持标准输入打开,允许你进行交互式输入 (例如确认 'yes')# -t: 分配一个伪 TTY (终端),让输出更像在真实终端中# --: 分隔符,表示其后的内容都是要执行的命令及其参数,而不是 kubectl exec 自身的参数kubectl exec -it redis-0 -- \# sh -c "..." 启动一个 Shell 进程 (sh) 在 Pod 内部,并让它执行双引号内的字符串命令# 这是解决 Shell 变量展开问题的关键:确保 REDIS_POD_IPS 变量在此处被容器内部的 sh Shell 展开为一串以空格分隔的 IP:Port 列表 REDIS_POD_IPS \ # --cluster-replicas 1 指定每个主节点带一个从节点 --cluster-replicas 1 \ "为了更好拷贝内容,我再附上一份没有多余解释的命令:REDIS_POD_IPS=(kubectl get pods -l app=redis-cluster -o jsonpath='{range.items[*]}{.status.podIP}:6379 {end}')echo "Redis Pod IPs: REDIS_POD_IPS --cluster-replicas 1"你会得到如下类似的执行结果:❯ REDIS_POD_IPS=REDIS_POD_IPS"Redis Pod IPs: 10.1.0.18:6379 10.1.0.19:6379 10.1.0.20:6379 10.1.0.21:6379 10.1.0.22:6379 10.1.0.23:6379 ❯ kubectl exec -it redis-0 -- sh -c "redis-cli --cluster create
  • 验证集群状态: kubectl exec -it redis-0 -- redis-cli cluster info kubectl exec -it redis-0 -- redis-cli cluster nodes ---------- # 执行示例如下: ❯ kubectl exec -it redis-0 -- redis-cli cluster info cluster_state:ok cluster_slots_assigned:16384 cluster_slots_ok:16384 cluster_slots_pfail:0 cluster_slots_fail:0 cluster_known_nodes:6 cluster_size:3 cluster_current_epoch:6 cluster_my_epoch:1 cluster_stats_messages_ping_sent:546 cluster_stats_messages_pong_sent:561 cluster_stats_messages_sent:1107 cluster_stats_messages_ping_received:556 cluster_stats_messages_pong_received:546 cluster_stats_messages_meet_received:5 cluster_stats_messages_received:1107 ❯ kubectl exec -it redis-0 -- redis-cli cluster nodes 5441d7b3cee660294a44436ce5e28f124a8a3013 10.1.0.19:6379@16379 master - 0 1749203764236 2 connected 5461-10922 6478f1d8216315e1442218966ef7653b0f73dce3 10.1.0.21:6379@16379 slave bae2c19ca08ff1836e7049ae2680f068f179ab46 0 1749203765000 3 connected bae2c19ca08ff1836e7049ae2680f068f179ab46 10.1.0.20:6379@16379 master - 0 1749203764000 3 connected 10923-16383 d3969c843d26d8f7f69f7756f72cccf7ed250017 10.1.0.22:6379@16379 slave 1eb3dd6f7712c7661f934ec1c65d36ac4daa9ac3 0 1749203763514 1 connected 3e136252b41a52ec278911a086f674c21c83c270 10.1.0.23:6379@16379 slave 5441d7b3cee660294a44436ce5e28f124a8a3013 0 1749203765252 2 connected 1eb3dd6f7712c7661f934ec1c65d36ac4daa9ac3 10.1.0.18:6379@16379 myself,master - 0 1749203763000 1 connected 0-5460 你应该能看到集群的状态为 ok,并且所有节点都已加入集群,并分配了主从角色。
4.4 部署 PostgreSQL 数据库:关系型数据的持久化基石

PostgreSQL 是一款功能强大、高度稳定、被广泛使用的开源关系型数据库。在 K8s 中部署 PostgreSQL,与 Redis 类似,核心在于处理持久化存储敏感数据(密码)。我们将部署一个单实例的 PostgreSQL 数据库,并确保它的数据是持久化的。

在 K8s 中,我们将主要用到以下 K8s 对象来部署 PostgreSQL 数据库:

  • Secret (密钥): 用于安全地存储数据库密码。
  • PersistentVolumeClaim (持久卷声明, PVC): 声明数据库需要的持久化存储空间。
  • Deployment (部署) / StatefulSet (有状态集): 用于管理 PostgreSQL 的 Pod(有状态应用通常使用 StatefulSet 部署,此处为了演示而使用 Deployment 进行部署)。
  • Service (服务): 为 PostgreSQL 提供稳定的网络访问入口。

部署步骤概览:

  1. 创建数据库密码: 使用 Secret 来安全地存储数据库密码。
  2. 定义持久化存储: 为 PostgreSQL 数据库文件准备持久卷(通过 PVC)。
  3. 部署 PostgreSQL 实例: 使用 Deployment 来部署 PostgreSQL Pod。
  4. 暴露数据库服务: 使用 Service 为 PostgreSQL 提供一个稳定的集群内部访问地址。

让我们赶紧开始吧~。

创建 Secret

我们将创建一个 Secret 对象,用于安全地存储 PostgreSQL 的超级用户密码。

Secret 是一种包含少量敏感信息例如密码、令牌或密钥的对象。 这样的信息可能会被放在 Pod 规约中或者镜像中。 使用 Secret 意味着你不需要在应用程序代码中包含机密数据。

由于创建 Secret 可以独立于使用它们的 Pod, 因此在创建、查看和编辑 Pod 的工作流程中暴露 Secret(及其数据)的风险较小。 Kubernetes 和在集群中运行的应用程序也可以对 Secret 采取额外的预防措施, 例如避免将敏感数据写入非易失性存储。

Secret 类似于 ConfigMap 但专门用于保存机密数据。

代码语言:javascript
代码运行次数:0
运行
复制
apiVersion: v1
kind:Secret
metadata:
name:postgres-secret# Secret 的名称,你将在 Deployment 中引用它
type:Opaque# Opaque 是默认类型,表示通用的秘密数据
data:
# 将 'your_strong_password' 替换为你自己的密码,并进行 Base64 编码。
# 推荐使用在线工具或命令行(例如:echo -n 'mysecretpassword' | base64)生成(K8s 也可配置对信息进行自动编码)。
# 示例:如果你的密码是 'mysecretpassword',Base64 编码后可能是 'bXlzZWNyZXRwYXNzd29yZAo='
# 注意:这里的 'postgres-password' 是一个键名,在 Deployment 中引用时会用到
postgres-password:<在这里填入你的Base64编码密码>

注意,如果密码不是 Base64 编码格式,将会显示错误。

代码语言:javascript
代码运行次数:0
运行
复制
echo -n '123456' | base64 # 进行编码
MTIzNDU2 # 编码结果

创建 PersistentVolumeClaim (PVC)

我们需要一个持久化存储来保存 PostgreSQL 的数据库文件,防止 Pod 重启或删除时数据丢失。我们将创建一个 PVC 来声明这个存储需求。

代码语言:javascript
代码运行次数:0
运行
复制
apiVersion: v1
kind:PersistentVolumeClaim
metadata:
name:postgres-pvc# PVC 的名称,你将在 Deployment 中引用它
labels:
    app:postgres# 标签,用于识别这个 PVC
spec:
accessModes:
    -ReadWriteOnce# 访问模式:允许单个节点以读写模式挂载。对于数据库这类应用,这通常是安全的默认选择。
resources:
    requests:
      storage:5Gi# 请求 5GB 的存储空间
# storageClassName: your-storage-class # (可选) 生产环境请指定 StorageClass。
                                          # 如果你的 K8s 集群有默认 StorageClass,可以不写。
                                          # 例如:storageClassName: standard (云厂商的常见默认 StorageClass)。

创建 Deployment

现在,我们定义 PostgreSQL 的部署。我们将使用 Deployment 来创建一个 PostgreSQL Pod,并将其与之前创建的 SecretPVC 关联起来。

代码语言:javascript
代码运行次数:0
运行
复制
apiVersion: apps/v1
kind:Deployment
metadata:
name:postgres-deployment# Deployment 的名称
labels:
    app:postgres# Deployment 的标签
spec:
replicas:1# 部署一个 PostgreSQL 实例,因为是单实例数据库
selector:
    matchLabels:
      app:postgres# Pod 选择器,匹配带有 app: postgres 标签的 Pod
template:
    metadata:
      labels:
        app:postgres# Pod 的标签,需要与 selector.matchLabels 匹配
    spec:
      containers:
        -name:postgres# 容器的名称
          image:postgres:13# 使用 PostgreSQL 13 官方镜像
          imagePullPolicy:IfNotPresent# 如果本地有镜像就使用,否则拉取
          ports:
            -containerPort:5432# PostgreSQL 默认端口
          env:# 环境变量,用于配置 PostgreSQL 镜像在启动时初始化数据库
            -name:POSTGRES_DB# 数据库名称
              value:mydatabase# 你希望创建的数据库名称
            -name:POSTGRES_USER# 数据库用户
              value:myuser# 你希望创建的数据库用户
            -name:POSTGRES_PASSWORD# 数据库密码,从 Secret 中引用
              valueFrom:
                secretKeyRef:
                  name:postgres-secret# 引用名为 postgres-secret 的 Secret
                  key:postgres-password# 引用 Secret 中名为 postgres-password 的键
          volumeMounts:# 容器内卷的挂载点列表
            -name:postgres-storage# 引用名为 'postgres-storage' 的卷
              mountPath:/var/lib/postgresql/data# PostgreSQL 数据文件存放的默认路径,**非常重要!**
      volumes:# 定义 Pod 中可用的卷列表
        -name:postgres-storage# 定义一个名为 'postgres-storage' 的卷
          persistentVolumeClaim:
            claimName:postgres-pvc# 引用上面定义的 PVC

创建 Service

为了让 K8s 集群内部的其他应用程序能够稳定地连接到 PostgreSQL,我们需要一个 Service

代码语言:javascript
代码运行次数:0
运行
复制
apiVersion: v1
kind:Service
metadata:
name:postgres-service# Service 的名称,其他 Pod 将通过这个名称访问
labels:
    app:postgres
spec:
selector:
    app:postgres# 选择带有 app: postgres 标签的 Pod 作为后端(即 postgres-deployment 创建的 Pod)
ports:
    -protocol:TCP
      port:5432       # Service 监听的端口 (集群内部访问 Service 使用这个端口)
      targetPort:5432# 后端 Pod 内部容器监听的端口
type:ClusterIP      # 默认类型,Service 只能在 K8s 集群内部访问

# 如果需要外部访问可按照以下形式修改。
# ports:
#  - protocol: TCP
#    port: 5432       # Service 监听的端口 (集群内部访问 Service 使用这个端口)
#    targetPort: 5432 # 后端 Pod 内部容器监听的端口
#    nodePort: 30001   # 在每个 Node 上暴露的端口,范围通常是 30000-32767
# type: NodePort      # 将 Service 类型改为 NodePort

运行 Pod

现在,我们配置都已经定义好了,只需要我们开始传达执行命令即可让整个服务运转起来。

代码语言:javascript
代码运行次数:0
运行
复制
kubectl apply -f postgresql-secret.yaml

kubectl apply -f postgresql-pvc.yaml

kubectl apply -f postgresql-service.yaml

kubectl apply -f postgresql-deployment.yaml

验证运行状态

代码语言:javascript
代码运行次数:0
运行
复制
kubectl get pvc postgres-pvc # 确保 PVC 已绑定成功

kubectl get pods -l app=postgres # 确认 PostgreSQL Pod 正在运行

kubectl get svc postgres-service # 确认 Service 已创建并分配了 IP

最后,你可以尝试连接该数据库,如果可以正常连接,那么说明运行是成功的。

第五章节更新中,请前往账号主页搜索:闯进 Kubernetes 的世界。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-06-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 木有枝枝 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 第四章:Kubernetes(K8s) 实战入门:部署有状态应用
    • 4.1 理解有状态应用与持久化存储
    • 4.2 部署必备的“工具箱”:K8s 的三个 YAML 文件
    • 4.3 部署 Redis 集群:键值存储的分布式实践
    • 4.4 部署 PostgreSQL 数据库:关系型数据的持久化基石
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档