K3s 与 Kubernetes 入门:用一次部署理解核心对象

Kubernetes 的核心价值不是“运行容器”,而是持续把集群的实际状态调整为你声明的期望状态:你声明要两个 API 副本、一个稳定访问入口和一套健康检查,控制器负责创建、替换和更新 Pod。

K3s 是 Kubernetes 的轻量级发行版,降低了安装和运行资源成本,并为小规模、边缘和本地环境提供了更易用的默认选择。对应用开发者而言,K3s 使用的核心 Kubernetes API、kubectl 工作流和工作负载对象与其他 Kubernetes 发行版基本一致。

本文只讲部署一个无状态服务时最需要掌握的内容。存储、HPA、StatefulSet、亲和性和集群运维应作为后续专题学习。

1. 最重要的心智模型:声明期望状态

使用 Kubernetes 时,通常不需要手动创建和重启每个容器。你向 API 提交 YAML,描述期望状态;控制器持续比较期望状态与实际状态,并尝试消除差异。

例如,当一个 Deployment 期望 replicas: 2,某个 Pod 异常退出时,控制器会创建替代 Pod。发布新镜像时,Deployment 会按更新策略逐步替换旧 Pod,而不是让你逐台机器执行命令。

应用需要配合这个模型:进程应无状态、可重复启动、能输出日志、能优雅停止,并通过健康检查告诉平台何时可以接流量。

2. 无状态服务最常见的对象

对象 作用 何时需要
Namespace 资源隔离范围 区分应用、团队或环境。
Pod 最小调度单元,可包含一个或多个紧密协作的容器 通常由 Deployment 创建,不直接手写单个 Pod。
Deployment 声明副本数、镜像和滚动更新策略 大多数无状态 API、Web 服务和消费者。
Service 为一组 Pod 提供稳定 DNS 和虚拟访问地址 让集群内调用方不依赖 Pod IP。
ConfigMap 非敏感配置 注入环境变量或配置文件。
Secret 敏感配置引用 仅是编码,不等于加密或密钥治理。
Ingress HTTP/HTTPS 路由规则 需要通过域名或路径从集群外访问时。

Pod 是 Kubernetes 调度的单位,容器只是 Pod 中的运行进程。一个 API 通常是“一 Pod 一业务容器”;日志收集、网络代理等确实需要共享生命周期和网络命名空间时,才考虑 sidecar。

3. 部署一个无状态 API

下面的 app.yaml 创建 Namespace、ConfigMap、两副本 API 和集群内 Service。将镜像地址替换为可被你的 K3s/Kubernetes 集群拉取的实际镜像。

apiVersion: v1
kind: Namespace
metadata:
  name: demo
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: api-config
  namespace: demo
data:
  APP_ENV: development
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: api
  namespace: demo
spec:
  replicas: 2
  selector:
    matchLabels:
      app: api
  template:
    metadata:
      labels:
        app: api
    spec:
      containers:
        - name: api
          image: registry.example.com/demo/api:1.0.0
          ports:
            - name: http
              containerPort: 8080
          env:
            - name: APP_ENV
              valueFrom:
                configMapKeyRef:
                  name: api-config
                  key: APP_ENV
          readinessProbe:
            httpGet:
              path: /ready
              port: http
            initialDelaySeconds: 3
            periodSeconds: 5
          livenessProbe:
            httpGet:
              path: /healthz
              port: http
            initialDelaySeconds: 10
            periodSeconds: 10
          resources:
            requests:
              cpu: 100m
              memory: 128Mi
            limits:
              cpu: 500m
              memory: 256Mi
---
apiVersion: v1
kind: Service
metadata:
  name: api
  namespace: demo
spec:
  selector:
    app: api
  ports:
    - name: http
      port: 80
      targetPort: http

这份 YAML 的关键关系是:Deployment 根据 app: api 标签管理 Pod;Service 用同一标签选择后端 Pod,并为它们提供稳定的 api.demo.svc.cluster.local DNS 名称。Pod 重建后 IP 会变化,调用方应访问 Service,而不是记录 Pod IP。

4. 健康检查和资源请求是基础能力

readinessProbe 决定 Pod 是否加入 Service 的可用后端。应用尚未完成初始化、无法处理请求时,应让 readiness 失败,以避免新流量进入。

livenessProbe 用于发现进程失去工作能力后是否应重启。不要把依赖数据库或远程服务的深度检查直接作为 liveness 条件,否则下游短暂故障可能造成应用集体重启。应用启动很慢时,还应评估 startupProbe

resources.requests 是调度器分配资源时的依据;limits 用于限制单个容器可使用的资源。数值必须来自压测和运行指标,不应照抄示例。缺少 requests 会让容量规划、调度和后续自动扩缩容都失去可靠基础。

5. 发布、观察与本地访问

# 提交期望状态
kubectl apply -f app.yaml

# 查看 Deployment、Pod 和 Service
kubectl -n demo get deployment,pods,service

# 等待本次发布完成
kubectl -n demo rollout status deployment/api

# 查看应用日志和某个 Pod 的详细事件
kubectl -n demo logs deployment/api --follow
kubectl -n demo describe pod <pod-name>

# 本地临时访问集群内 Service
kubectl -n demo port-forward service/api 8080:80

port-forward 适合开发和排障,不是生产暴露方式。生产 HTTP 流量通常通过已安装的 Ingress Controller 加上 Ingress 规则进入集群;Ingress 本身只是规则资源,没有 Controller 就不会生效。云环境的 LoadBalancer Service 是否可用也取决于云提供商或集群的负载均衡实现。

6. 更新和回滚

当镜像有新版本时,更新 Deployment 并观察滚动发布:

kubectl -n demo set image deployment/api \
  api=registry.example.com/demo/api:1.0.1

kubectl -n demo rollout status deployment/api
kubectl -n demo rollout history deployment/api

如果新版本异常:

kubectl -n demo rollout undo deployment/api

滚动更新能否真正做到低中断,取决于 readiness、优雅终止、足够的资源余量和正确的更新策略。它不是替代应用兼容性、数据库迁移和灰度验证的魔法。

7. 配置、密钥与状态数据的边界

ConfigMap 适合非敏感配置。Secret 可以让工作负载引用敏感值,但其默认 Base64 只是编码;生产环境还应考虑静态加密、访问控制、审计以及外部密钥系统。

数据库、消息队列等有状态组件涉及存储类型、备份、恢复和故障转移。Kubernetes 使用 PV、PVC 和 StorageClass 描述持久化存储,但不要在理解 Deployment 之前就试图掌握全部存储细节。对关键数据,先确认存储和备份方案,再决定是否放入集群。

8. 哪些内容应单独学习

以下内容很重要,但不应挤进基础部署流程:

  • StatefulSet、PV/PVC、StorageClass:有状态服务与数据恢复。
  • HPA 与 Cluster Autoscaler:指标、容量和自动扩缩容。
  • DaemonSet、节点亲和性、污点与容忍:节点级工作负载与调度约束。
  • NetworkPolicy、Ingress Controller、Service Mesh:网络隔离和流量治理。
  • 控制平面、etcd、高可用和升级:集群运维。

先能稳定地发布、观察和回滚一个无状态服务,再进入这些专题,学习路径会更清晰。

9. 上线检查清单

  • 镜像可被目标集群拉取,且标签或 digest 可追溯。
  • Deployment、Service 的标签选择器一致。
  • readiness、liveness 和必要的 startup 探针反映真实服务状态。
  • 已根据压测设置 CPU/内存 requests 和 limits。
  • 配置与密钥不写进镜像,Secret 不被误当作加密存储。
  • 已验证 rollout status、日志、事件查看和回滚流程。
  • 已明确外部流量由 Ingress、LoadBalancer 或其他网关方案承接。

掌握这一条从 YAML 到发布、观察和回滚的链路,就已经拥有使用 K3s/Kubernetes 部署无状态服务的核心能力。