Kubernetes 生产入门:Deployment 与 Service 配置实战

0 阅读7分钟

文章简介

最近在做服务迁移部署,学习了 Kubernetes 相关技术,在此做个简单记录。 部署期间我只用到 Deployment 配置 Pod 和 Service 配置网络,所以这里主要介绍 Deployment 的配置文件和 Service 的配置文件。

概念介绍

  • Pod:
    • 书面概念:k8s 中可以创建和管理的最小、最简单的可部署计算单元。
    • 我的理解:就是一台电脑/虚拟机,里面可以运行多个容器,容器之间可以通过 localhost 通信,也可以访问同一个文件目录,同一个 Pod 内如果有多个容器监听同一个端口会出现端口冲突。
    • 一般每个 Pod 中只会有一个容器,如果是多容器 Pod,那这几个容器业务最好是紧密相连的。
    • 一般通过 Deployment、StatefulSet 等管理 Pod,不直接创建 Pod。我用到的是 Deployment。
  • Deployment:用来管理 Pod,可以通过修改 Deployment 配置来自动创建、更新、扩缩容 Pod。
    • 自动创建:将编写好的 Deployment 配置文件导入 k8s 之后,就会自动根据配置文件拉取镜像/创建容器。
    • 更新 Pod:更新 Deployment 配置文件中 Pod 对应镜像,就会自动拉起新的 Pod,慢慢关闭旧的 Pod,这个过程是平滑的,过渡方式也可以配置。
    • 扩缩容:通过修改 Deployment 配置文件参数,动态的进行增加/减少 Pod,还能够根据 CPU、内存使用率来动态扩缩容。
    • 备注:Deployment 管理的是 Pod,扩缩容也是增加/减少 Pod 数量,并非 Pod 内的容器。假设我们有 1 个 Pod 内有 A、B 两个容器,扩容是直接复制生成新的 Pod,新的 Pod 内也有 A、B 两个容器,而不是 一个 Pod 有两个 A 容器,另一个 Pod 有两个 B 容器。
  • Service:
    • 书面概念:为一组动态变化的 Pod 提供了一个稳定的访问抽象层。
    • 我的理解:用来提供一个稳定的网络访问入口。Pod 的 IP 分配是随机的、动态的、临时的,每次拉起的新 Pod 和旧 Pod 所分配的 IP 不固定,如果我们的服务需要或想拥有一个固定的 IP,那我们就可以为这个服务定义一个 Service。比如 Nginx 服务、Gateway 服务、Nacos 服务。
    • Service 可以将流量以负载均衡的方式转发到所有符合条件且健康的 Pod,转发方式可配置,默认轮询。
  • volumes:存储卷, 可以认为是硬盘,只是这个硬盘的生命周期与所属 Pod 相同,Pod 消亡则消亡,除非是 PersistentVolume(持久存储卷)。
    • 我用来为 Nginx 提供配置文件,首先建立一个名为 nginx-config 的 configMap 对象,然后为其添加一个 key 为 nginx.conf,value 为配置内容的 k-v 对象。然后在 Deployment 中将 nginx-config 对象定义为 Pod configMap 类型的 volumes,接着将这个 volumes 中的 nginx.conf 挂载到 Nginx 服务容器内的 /etc/nginx/nginx.conf 文件上。
  • configMap:key - value 结构的配置文件对象,用来存储配置文件、环境变量等信息,将配置文件与镜像分离,不能用来存储敏感信息。
  • 备注:configMap 对象更新后想要立即生效需要重新部署 pod。
  • 结构:configMap 对象 ——> key - value 对象。 - configMap 对象可以有多个。 - key - value 对象也可以有多个。

Deployment 配置

Deployment 配置分为基础信息、副本策略、Pod 模板、容器配置、资源配置、存储配置(Nginx配置文件)几个部分

  • 基础信息:这部分是设置配置文件版本、类型、名称、标签等信息。
  • 副本策略:这部分用来配置选择哪些 Pod、以及拉起多个 Pod 副本。
  • Pod 模板:用来设置 Pod 的名称、标签等信息,Pod 标签要和 Deployment 的 selector 所设置的保持一致。
  • 容器配置:用来配置 Pod 有哪些容器(一般只有一个)。
    • 镜像:这里的镜像可以设置已有的,如果是我们自己开发、制作的镜像,那此处可以随意填写,后续通过 Jenkins 等工具制作、设置镜像。k8s 会自动拉取镜像,拉起新的 Pod,完成更新。
    • 镜像拉取策略:可以设置本地有就不拉取,也可以设置总是拉取最新的。我设置的是本地有就不拉取(IfNotPresent)。我通过 Jenkins 部署,由于每次制作的镜像 tag 不同(如:nginx:202511291717),节点上没有特定 tag 的镜像,k8s 会拉取新的镜像,所以此处使用 IfNotPresent。这样既能保证使用新的镜像,又能避免不必要的拉取。
    • 备注:Jenkins 部署方面的流水线脚本可以查看我 Jenkins 相关的文章。
  • 资源配置:用来指定该容器所需的 CPU、内存资源。
  • 存储配置:这里用来配置 nginx 配置文件。
# 基础信息
apiVersion: apps/v1 # 使用 Deployment API 版本
kind: Deployment    # 资源类型为 Deployment
metadata:
  labels:
    app: nginx      # Deployment 的标签,用于识别
  name: nginx       # Deployment 名称
spec:
  # 副本策略
  replicas: 1       # 只运行 1 个 Pod 副本
  selector:
    matchLabels:
      app: nginx    # 选择管理哪些 Pod(匹配 template 中的 labels)
  # Pod 模板
  template:
    metadata:
      labels:
        app: nginx  # Pod 的标签,必须与 selector 匹配
    # 容器配置
    spec:
      containers:
      - image: 'registry.xxxxx.com/nginx:xxx'   # 私有镜像仓库地址
        imagePullPolicy: IfNotPresent           # 镜像拉取策略(本地有就不拉取),如果希望总是拉取新的镜像,可以设置为 Always。我通过 Jenkins 部署,由于每次制作的镜像 tag 不同(如:nginx:build-123),节点上没有这个镜像,会拉取新的镜像,所以此处使用 IfNotPresent
        name: nginx                             # 容器名称
        # 容器暴露的端口(主要是文档作用,这里的端口也可以不用配置)
        ports:
          - containerPort: 80
            protocol: TCP
          - containerPort: 443
            protocol: TCP
        # 资源配置
        resources:
          requests:
            cpu: '1'      # 请求 1 核 CPU
            memory: 2Gi   # 请求 2GB 内存
        # 存储配置
        volumeMounts:
          - name: nginx-config
            mountPath: /etc/nginx/nginx.conf  # 挂载到容器内的文件路径
            subPath: nginx.conf               # 只挂载 configMap 中的 nginx.conf 键
      volumes:
        - name: nginx-config
          configMap:
            name: nginx-config                  # 使用的 ConfigMap 名称

Service 配置

Service 是网络方面到配置,由于 nginx 涉及到外部网络访问,我们是通过在阿里云页面上点点点来配置的,所以这里使用网关(Gateway)的 Service 配置来介绍。

  • nginx 的外网访问配置这里只提供一个思路。
    • 首先配置 nginx 的 Service 为 LoadBalancer 类型;
    • 然后选择私网类型的负载均衡器;
    • 最后创建一个弹性网卡绑定到对应的负载均衡器;
  • Gateway 的 Service 配置比较简单。
    • 设置服务类型为 ClusterIP;
    • 设置 Serivce 的名称、标签等信息;
    • 设置选择拥有哪个标签(例:app: gateway)的 Pod 最为后端;
    • 设置 Service 对外暴露端口和 后端 Pod 世纪端口就可以了;
  • 其他内网访问的 Service 与 Gateway 的差不多,比如:nacos。
# 基础信息
apiVersion: v1    # 使用 Core API,Service 是核心资源
kind: Service     # 资源类型为 Service
metadata:
  name: gateway     # Service 名称
  labels:
    app: gateway    # Service 的标签,用于资源筛选和识别
# 核心配置
spec:
  selector:
    app: gateway        # 关键:选择标签为 app:gateway 的 Pod 作为后端
  # 端口映射
  ports:
  - protocol: TCP
    port: 8080        # Service 对外暴露的端口
    targetPort: 8080  # 后端 Pod 容器的实际端口
  # 服务类型
  type: ClusterIP  # 通过云服务商创建外部负载均衡器(公网访问)

整个 k8s 网络流量流向的简单介绍(只是其中一种)

  • 外部流量来到 Nginx Service 后被转发到 Nginx Pod 内 Nginx,然后 Nginx 通过配置转发到 gateway,接着 gateway 通过从 nacos 拿到的配置信息将流量转发到对应的服务。
  • 外网 --> 弹性网卡 --> 私网负载均衡器 --> Nginx Service --> Nginx Pod --> Nginx 服务 --> Gateway Service --> Gateway Pod --> Gateway 服务 --> 相应服务 Pod --> 相应服务

备注

网关和其他服务需要通过 nacos 获取配置、注册、发现服务,所以 nacos 也需要配置一个 Service 来获得固定内网 IP,但这里我没有介绍,但方式和 gateway 差不多,朋友们可以自行上手操作。