--- tags: [k8s, rke2, preview, infra] create time: 2026-07-04 12:00 --- # K8s + RKE2 基础 ## 概述 Kubernetes(K8s)是容器编排的事实标准,Rancher RKE2 是 CNCF 认证的轻量级、安全优先的 K8s 发行版,专为边缘和混合云场景设计。xinfra 平台的容器调度底层基于 RKE2,后续所有服务部署都建立在对这个知识栈的理解之上。 ## 核心概念 ### Kubernetes 核心对象关系 ```mermaid graph TD Node[Node / 节点] --> Pod[Pod / 最小部署单元] Pod --> C[Containers / 容器] Deployment[Deployment / 副本控制] --> Pod Service[Service / 网络暴露] --> Pod Namespace[Namespace / 资源隔离] --> Deployment Namespace --> Service PV[PersistentVolume / 持久存储] --> PVC[PVC / 申请存储] PvcRef[PVC ref by Pod] --> Pod ``` | 对象 | 职责 | 类比 | | ---------------------- | ------------------------------- | -------- | | **Node** | 运行 Pod 的物理机或虚拟机 | 服务器 | | **Pod** | 一个或多个容器的打包体 | 应用实例 | | **Deployment** | 管理 Pod 的副本数、滚动更新策略 | 发布控制器 | | **Service** | 为一组 Pod 提供稳定的访问入口(负载均衡) | 反向代理 | | **Namespace** | 逻辑隔离的资源分组 | 多租户文件夹 | | **ConfigMap / Secret** | 将配置注入 Pod(非敏感/敏感数据分离) | .env 文件 | | **Ingress** | 七层路由,HTTP/HTTPS 域名到 Service 的映射 | Nginx 规则 | ### RKE2 vs 原生 K8s RKE2(Rancher Kubernetes Engine v2)的核心特点: 1. **单二进制部署**:不需要单独安装 etcd、containerd 等依赖,一条命令拉起整集群 2. **SST(Simple System Tray)**内置 SQLite,etcd 作为可选而非必须 3. **FIPS 140-2 合规**:内置加密要求,适合企业对安全审计的需要 4. **自动注册与拉取**:可配合 Rancher Server 实现节点无感加入 > [!info] 为什么选 RKE2? > xinfra 需要管理**七机房多套集群**,RKE2 的"一键部署 + 低运维成本"特性正好契合——减少环境差异导致的兼容问题,让平台专注于上层抽象而非底层排障。 ### RKE2 安装方式对比 | 方式 | 命令特点 | 适用场景 | 是否支持 Rancher 集成 | |------|---------|---------|---------------------| | **单二进制直接运行** | curl → sh(安装脚本直出,无需额外依赖) | 开发测试、小规模集群(≤3 节点) | ✅ — 自动发现并注册 | | **Systemd 服务管理** | `systemctl enable --now rke2-server` | 生产环境标准化部署 | ✅ | | **Air-gap(离线)** | 预下载 `.tar.gz` 包 + `INSTALL_DIR=/opt/rke2` 指向本地文件 | 内网无外网环境的机房 | ❌ — 需手动同步镜像 | > [!warning] Air-gap 是常见坑点 > RKE2 Server/Agent 首次启动时会从官方 registry 拉取 K8s 组件 OCI 镜像。如果机房**无法访问外网**,必须提前准备 image bundle tarball,并通过 `--image-volume-mount /var/lib/rancher/rke2/agent/image-store` 指定本地缓存路径。 ### 节点注册机制详解 Worker 节点加入集群有两种认证方式: ```bash # 方式 1:静态 Token(最简单,适合小集群) # 服务端会在 /etc/rancher/rke2/rke2.yaml 旁生成 token export TOKEN="K10xxx...from server node" rke2 agent --server https://master-ip:6443 --token $TOKEN # 方式 2:Bootstrap 证书签名(推荐,支持 TLS 双向认证) # Agent 首次连接时发送 CSR(Certificate Signing Request), # kube-controller-manager 审批后颁发客户端证书 ``` 关键文件分布: | 路径 | 内容 | 说明 | |------|------|------| | `/etc/rancher/rke2/rke2.yaml` | kubeconfig(含 admin 权限证书) | ⚠️ 等同于集群 master key,务必备份保护 | | `/var/lib/rancher/rke2/agent/` | 容器镜像、kubelet 证书 | Agent 工作目录 | | `/var/lib/rancher/rke2/server/` | etcd 数据、控制平面组件 | Server 工作目录 | | `/var/lib/rancher/rke2/bin/` | rke2、kubectl、crictl 等 | 可执行文件软链到原位置 | ### RKE2 配置管理 RKE2 支持多种配置来源,优先级从低到高: ```yaml # 1. 系统级配置(最低优先级) # /etc/rancher/rke2/config.yaml tls-san: - "k8s.company.com" cluster-cidr: 10.42.0.0/16 service-cidr: 10.43.0.0/16 # 2. Systemd Override(覆盖默认 service 参数) # /etc/systemd/system/rke2-server.service.d/override.conf [Service] Environment="RKE2_TOKEN=${TOKEN}" Environment="NODE_LABEL=node-role=true,datacenter=bj" # 3. CLI 参数(最高优先级,覆盖 config.yaml) # systemctl start rke2-server --token=TOKEN --cluster-cidr=10.42.0.0/16 ``` > [!tip] 自定义 CNI 插件 > RKE2 默认使用 Canal(Calico + Flannel 组合)。如果需要更换为 Cilium,只需在 `config.yaml` 中添加: > ```yaml > cni: cilium > ``` > 重新拉起 Server 即可自动替换网络方案——这是 RKE2 比原生 K8s 更省心的地方:**网络方案可以配置驱动,而不是代码依赖**。 ### RKE2 集群架构 ```mermaid graph TB subgraph "Master Node(控制平面)" RKE2[RKE2 Server
rke2 server --token=TOKEN] APIServer[Kube-apiserver] ControllerMgr[Kube-controller-manager] Scheduler[Kube-scheduler] ETCD[(etcd DB)] CCM[Cloud Controller Manager] APIServer --> ControllerMgr APIServer --> Scheduler APIServer <--> ETCD RKE2 --> APIServer RKE2 --> ControllerMgr RKE2 --> Scheduler RKE2 --> ETCD RKE2 --> CCM end subgraph "Worker Node(工作节点)" RKE2W[RKE2 Agent
rke2 agent --server=https://MASTER_IP:6443 --token=TOKEN] Kubelet1[Kubelet] KubeProxy1[Kube-proxy] Containerd1[containerd] RKE2W --> Kubelet1 RKE2W --> KubeProxy1 RKE2W --> Containerd1 end Dev[kubectl / Wayne API] --> APIServer APIServer -. kubeconfig .-> RKE2W Kubelet1 -. etcd sync .-> ETCD ``` 关键流程说明: 1. **RKE2 Server 启动后**会自动拉取对应 K8s 版本的组件包(kube-apiserver、controller-manager 等),解压到 `/var/lib/rancher/rke2/`,通过 systemd 管理运行 2. **Agent 节点**只需传入 `--token`(静态认证令牌)和 `--server` URL,即可自动完成 TLS 证书握手并加入集群 3. **默认使用 containerd** 作为容器运行时——无需单独安装 Docker,这也是 RKE2 比 k3s 更"正规"的原因之一 ### Pod 生命周期与调度流程 Pod 从创建到运行的完整链路: ```mermaid sequenceDiagram participant user as 开发者 (kubectl/Wayne) participant apiserver as kube-apiserver participant scheduler as kube-scheduler participant node as Node Kubelet participant containerd as containerd user->>apiserver: POST /api/v1/namespaces/default/pods apiserver->>apiserver: 验证 RBAC + 持久化到 etcd Note over apiserver: Pod 状态 = Pending apiserver-->>user: 201 Created scheduler->>apiserver: LIST pods (unassigned) scheduler->>scheduler: 预选 (Fit) → 优先级排序 (Score) scheduler->>apiserver: PATCH pod -> set nodeName Note over apiserver: Pod 状态仍为 Pending(等待 Kubelet 响应) apiserver-->>node: WATCH pod assigned to this node node->>containerd: Pull image (if not cached) node->>containerd: Create container node->>node: Set readinessProbe Note over node: Pod 状态 = Running node->>apiserver: UPDATE pod status ``` > **启发问题**:为什么调度器选中节点后,Pod 不会立即变成 Running,而还需要 Kubelet 配合?——因为调度器只负责"选地址",真正的镜像拉取、容器创建、网络挂载都由 Kubelet 在本机完成。这体现了**控制面与数据面的职责分离**。 ### 典型部署流程 ```bash # 1. 编写 Deployment YAML kubectl apply -f deployment.yaml # 2. 编写 Service YAML kubectl apply -f service.yaml # 3. 查看状态 kubectl get pods -n kubectl describe pod -n # 4. 滚动更新(改镜像版本) kubectl set image deployment/ app= -n kubectl rollout status deployment/ -n ``` **Deployment YAML 骨架:** ```yaml apiVersion: apps/v1 kind: Deployment metadata: name: my-service namespace: default spec: replicas: 3 # 期望副本数 strategy: type: RollingUpdate # 滚动更新策略 rollingUpdate: maxSurge: 1 # 更新时最多比期望多 1 个 Pod maxUnavailable: 0 # 更新时不允许不可用 selector: matchLabels: app: my-service template: # Pod 模板 metadata: labels: app: my-service spec: containers: - name: app image: registry/my-service:v1.2.0 ports: - containerPort: 8080 ``` ### Service 类型详解 Service 是 Pod 的"稳定门面",不同 type 决定了流量如何到达 Pod: | type | 工作原理 | 适用场景 | |------|---------|---------| | **ClusterIP**(默认) | K8s 内部虚拟 IP,仅集群内可访问 | 服务间调用,不对外暴露 | | **NodePort** | 在每个节点上开放一个端口,外部可通过 `:` 访问 | 快速测试、开发环境验证 | | **LoadBalancer** | 对接云厂商 LB 自动创建公网 IP | 云上生产环境 | | **Ingress** | 七层路由,基于域名/路径分发到不同 Service | 多服务共享入口,HTTPS 终结 | > [!warning] NodePort vs Ingress > NodePort 只做到四层 TCP/UDP 负载均衡——无法按域名路由。如果你的应用需要 `api.example.com` → Service-A、`web.example.com` → Service-B 这种能力,必须用 **Ingress**。xinfra 中通常配合 Nginx Ingress Controller 使用。 **Ingress 示例:** ```yaml apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: my-service-ingress annotations: nginx.ingress.kubernetes.io/ssl-redirect: "true" # 强制 HTTPS spec: rules: - host: api.myapp.company.com http: paths: - path: / pathType: Prefix backend: service: name: my-service # 对应 ClusterIP Service port: number: 80 ``` --- ### kubectl 速查手册 日常运维最高频的命令组合: ```bash # ── 查看 ── kubectl get pods -A # 所有 namespace 的 Pod kubectl get svc,ingress -n prod # 查看 Service + Ingress kubectl top pod -n staging --containers # 容器级 CPU/Memory 用量 # ── 调试 ── kubectl exec -it -- /bin/sh # 进入容器 Shell kubectl logs -f -c -n ns # 查看指定 Sidecar 日志 kubectl describe pod -n ns # 查看详细事件(调度失败原因等) # ── 资源操作 ── kubectl rollout undo deployment/ -n ns # 回滚到上一版本 kubectl scale deployment/ --replicas=5 -n ns # 手动扩缩容 kubectl patch deployment/ -p '{"spec":{"template":{"spec":{"containers":[{"name":"app","image":"new:v2"}]}}}}' -n ns # 热更新镜像 ``` > [!tip] `-A` 标志 = `--all-namespaces`,当你不确定资源在哪个 namespace 时非常有用。但正式脚本中不建议滥用,容易造成误操作。 详见 [[k8s-rke2-fundamentals/core-objects-quiz]] — 覆盖 Pod 生命周期、Service 类型、探针机制等核心考点的 10 道选择题自测。 --- ## 常见陷阱与最佳实践 ### 1. Resource Limit 缺失 不设置 `resources.limits` 的 Pod 在节点资源紧张时会抢占其他 Pod 资源,导致雪崩: ```yaml # 推荐:每个容器都要设请求值和上限 containers: - name: app resources: requests: { cpu: "100m", memory: "128Mi" } # 调度依据 limits: { cpu: "500m", memory: "512Mi" } # 硬上限 ``` ### 2. Liveness vs Readiness 混淆 - **livenessProbe**:判断容器是否"活着",失败则重启 Pod - **readinessProbe**:判断容器能否接收流量,失败则从 Service 后端摘除 ```yaml # 正确姿势:两个都设,readiness 更激进(快判快入),liveness 更保守 readinessProbe: httpGet: { path: /healthz, port: 8080 } initialDelaySeconds: 3 periodSeconds: 5 livenessProbe: httpGet: { path: /healthz, port: 8080 } initialDelaySeconds: 15 periodSeconds: 10 ``` ### 3. 频繁查看日志的习惯 ```bash # 实时跟踪单个 Pod 日志 kubectl logs -f -n # 如果是重启过的 Pod,看上一次容器的日志 kubectl logs -f -n --previous ``` ### 4. CrashLoopBackOff — 最常见的 Pod 异常状态 Pod 反复崩溃重启时,排查顺序如下: ```mermaid flowchart TD S[CrashLoopBackOff] --> C1{kubectl describe pod
看 REASON} C1 -->|ImagePullBackOff| I1[检查镜像仓库可达性 + ImagePullSecrets] C1 -->|OOMKilled| M1[调大 memory limit / 排查内存泄漏] C1 -->|CreateContainerConfigError| CM1[检查 ConfigMap/Secret 是否存在] C1 -->|ErrImagePull| E1[镜像 tag 错误或 registry 认证失败] C1 -->|Initialized/Ready/-/Running| LOGS[kubectl logs -p] LOGS --> APP[应用自身启动失败?] APP -->|Yes| FIX[检查启动参数 + 依赖服务连接性] APP -->|No| DEEP[深入 containerd/containerd-shim 日志] ``` ### 5. Ingress 404 或无法访问 开发环境常见"Service 存在但外部打不通"的问题,排查清单: 1. **Nginx Ingress Controller Pod 是否 Running** → `kubectl get pods -n ingress-nginx` 2. **Ingress 资源是否有 `loadBalancer.ip`** → `kubectl get ingress -n `(若无 IP,可能云厂商 LB 未就绪) 3. **Endpoint 是否有地址** → `kubectl get endpoints -n `(为空说明没有 Ready 的 Pod 匹配) 4. **DNS 解析是否正确** → 内网环境可能需要手动配置 hosts 或使用 CoreDNS ## 关联笔记 以下文档构成了 xinfra 容器化部署的知识链: - [[technical/xinfra-preview/wayne-overview]] — Wayne 上层的 YAML 模板就是基于这些 K8s 对象 - [[technical/xinfra-preview/cachecloud-overview]] — CacheCloud 管理 Redis,其宿主机未来可能迁移至 K8s 部署 - [[technical/xinfra-preview/cloud-dm-overview]] — K8s 内的 MySQL 实例由 CloudDM 做 SQL 审核 - [[technical/xinfra-preview/ansible-playbook-basics]] — Ansible Playbook 负责 RKE2 集群的底层裸机/VMAutomation