DAY01 K3s 私有化部署排障复盘与 SOP

本文记录 2026-07-22 在一主一从 K3s 环境中部署私有化 Gateway 与 CAS 的排障过程,整理成后续可复用 SOP。

适用场景:

  • K3s 私有化部署

  • 1 Master + 1 Worker 临时环境

  • NGINX Gateway Fabric 2.5.0

  • Worker 为 CentOS 7 / 3.10 内核,不能升级或更换机器

  • 目标通过 jyjzhfw.qiantang.gov.cn 访问业务界面

(这里举一反三,因为我的业务是后续要推进k8s。目前手上只有两台服务器给我演练,k3s有条件的就整三台服务器 1master+2 woker),我这边只有两台就灵活性改成1master+1woker。操作步骤都是在mobaxterm上实现。远程连接到两台服务器。

节点规划:

  • Master:192.168.X.250 节点名 k3s-master-01
  • Worker:192.168.X.251 节点名 k3s-worker-01

服务器是Linux系统(我直接先ip addr确认了ip,然后规划节点,

如果第二台woker就命名k3s-woker-02)以此类推。

步骤 0:进入部署目录,赋予脚本执行权限

bash(全节点都操作)

复制代码
cd k3s-private/cluster
chmod +x mount-data-disk.sh run.sh bootstrap-node.sh preflight.sh install-server.sh install-agent.sh post-install.sh import-airgap-images.sh

0.2 挂载独立数据盘 /data(bootstrap 前必须执行)

文档约束:/data 不能与根分区 / 共用磁盘

  1. 查看磁盘设备确认盘符

bash

复制代码
lsblk
  1. 执行磁盘格式化挂载脚本(示例 /dev/vdb,按需替换)

我的输出结果:

lsblk 输出可见:只有一块磁盘 sda,所有分区都在 sda 上,无独立数据盘 。 文档强制约束:/data 必须是独立挂载点,不能和 / 同一块设备;mount-data-disk.sh 会清空整块磁盘,不能拿 sda 执行脚本。

这里因为我是实验,我打开该脚本对"验证分区必须有两块磁盘的约束"进行了注释,也就是跳过这个part,不检验。

(生产环境必须检验)

操作步骤(两台机器都执行)

1. 编辑 bootstrap-node.sh

bash

复制代码
vi bootstrap-node.sh

2. 找到磁盘校验代码块,全部注释

搜索关键词:/data 不是独立挂载点 会找到类似这段代码:

bash

复制代码
# 原始报错代码
DATA_MOUNT=$(findmnt -n -o SOURCE /data)
ROOT_MOUNT=$(findmnt -n -o SOURCE /)
if [ "$DATA_MOUNT" == "$ROOT_MOUNT" ];then
    echo "ERROR: /data 不是独立挂载点,请先挂载数据盘到 /data"
    exit 1
fi

在每一行前面加 # 注释掉,改成:

bash

复制代码
# DATA_MOUNT=$(findmnt -n -o SOURCE /data)
# ROOT_MOUNT=$(findmnt -n -o SOURCE /)
# if [ "$DATA_MOUNT" == "$ROOT_MOUNT" ];then
#     echo "ERROR: /data 不是独立挂载点,请先挂载数据盘到 /data"
#     exit 1
# fi

保存退出 :wq

3. 重新执行 bootstrap(无需加环境变量)

bash

复制代码
bash run.sh bootstrap

此时不会再拦截磁盘校验,正常跑完基线初始化。

bash

复制代码
# 普通云盘
DISK=/dev/vdb ./mount-data-disk.sh
# NVMe硬盘使用这条
# DISK=/dev/nvme1n1 PART=/dev/nvme1n1p1 ./mount-data-disk.sh

脚本会提示确认清空磁盘,输入 yes 确认;

  1. 校验挂载成功

bash

复制代码
findmnt /data
# 输出中 /data 挂载设备和 / 不一致即合规

0.3 执行节点基线 bootstrap

bash

复制代码
./run.sh bootstrap

自动关闭 swap、配置 NTP、内核参数、创建 /data/k3s 目录。

1 编辑 install.env(本机唯一配置文件)

bash

复制代码
vi install.env

写入完整配置:

env

Erlang 复制代码
FLANNEL_IFACE=eth0
K3S_DATA_DIR=/data/k3s
MASTER_NODE_NAME=k3s-master-01
MASTER_NODE_IP=192.168.X.250  ##根据我们一开始的节点规划如实填写
K3S_NODE_NAME=k3s-master-01
NODE_IP=192.168.X.250    ##根据我们一开始的节点规划如实填写
INSTALL_K3S_MIRROR=cn

2 安装 Master Server(控制面)

bash ##在master节点上操作

复制代码
./run.sh install

交互提示:请选择安装角色 → 输入 server

2.1 获取集群 Token(本机后续 agent 安装要用)

bash

复制代码
cat .node-token
# 复制输出内容,保存备用

bash (在woker01节点上操作)

复制代码
# 替换引号内为上方 cat .node-token 的输出
export K3S_TOKEN='此处粘贴master的token字符串'

3.2 执行 agent 安装

bash

复制代码
./run.sh install

交互提示:请选择安装角色 → 输入 agent

4 全节点镜像优化(本机执行,post 之前)

若 kube-system 组件出现 ImagePullBackOff,二选一执行:

方案 1:镜像加速(containerd registry 配置)

bash

复制代码
install -d /etc/rancher/k3s
cp registries.yaml.example /etc/rancher/k3s/registries.yaml
vi /etc/rancher/k3s/registries.yaml
systemctl restart k3s

方案 2:离线镜像导入

bash

复制代码
./import-airgap-images.sh import
systemctl restart k3s

校验节点就绪

bash

复制代码
kubectl get nodes
# 此时同一节点会出现两条记录:k3s-master-01(server)、k3s-master-01(agent),全部 Ready 再执行post
kubectl get pods -n kube-system
# 无 ImagePullBackOff、ErrImagePull 异常

验收标准(对齐 quickstart.md

  1. kubectl get nodes 两个节点均 Ready
  2. 节点标签校验通过:
  • k3s-master-01(server):middleware-role=core
  • k3s-master-01(agent):workload=ingressmiddleware-role=generalingress-ready=true

排障命令(文档标准工具)

节点预检

bash

复制代码
# 校验server环境
./run.sh preflight server
# 校验agent环境
./run.sh preflight agent
# 通用全量体检
./run.sh preflight generic

如果是从windows11上传项目文件过去,跑脚本遇到bug

如果是因为换行符问题:

# 批量修复所有sh脚本换行

sed -i 's/\r$//' *.sh lib/*.sh

1、编辑 preflight.sh

bash

复制代码
vi preflight.sh

找到函数 ensure_data_disk_mounted()把整个函数全部注释

bash

复制代码
# ensure_data_disk_mounted() {
#   command -v findmnt >/dev/null 2>&1 || die "缺少 findmnt,无法校验 /data 挂载"
#   mountpoint -q /data || die "/data 不是独立挂载点,请先挂载数据盘到 /data"
#
#   local root_src data_src
#   root_src="$(findmnt -n -o SOURCE / 2>/dev/null || true)"
#   data_src="$(findmnt -n -o SOURCE /data 2>/dev/null || true)"
#   [[ -n "${data_src}" ]] || die "无法获取 /data 挂载源,请检查挂载状态"
#   [[ "${root_src}" != "${data_src}" ]] || die "/data 与根分区使用同一设备,请将 /data 挂载到独立数据盘"
#   [[ -d /data/k3s ]] || die "缺少 /data/k3s,请先执行 ./bootstrap-node.sh 初始化目录"
#   [[ -w /data/k3s ]] || die "/data/k3s 不可写,请检查目录权限"
# }

往下找到调用这一行,直接注释:

bash

复制代码
ensure_data_disk_mounted

改成

bash

复制代码
# ensure_data_disk_mounted

保存退出 :wq

2、清理所有文件 Windows 换行符(必做,防止 \r 报错)

bash

复制代码
sed -i 's/\r$//' *.sh install.env lib/*.sh

3、重新执行预检

bash

复制代码
bash run.sh preflight generic

此时不会再拦截 /data 独立磁盘校验。

补充关键信息

  1. 你的网卡是 ens192,后面写 install.envFLANNEL_IFACE=ens192,不能写 eth0;
  2. 两台机器(250、251)的 preflight.sh 都要做一模一样的修改;
  3. 预检输出 预检通过 之后,再去配置 install.env

安装完成后验证:(master上操作)

bash

复制代码
export KUBECONFIG=/etc/rancher/k3s/k3s.yaml
kubectl get nodes

能看到两个ready再往下看,第一阶段告一段落。

-------------------------------------------------------------------------

POST 阶段(在master上操作)

##该运行./post-install.sh脚本(先修改脚本适配一主一从)

执行修改命令快速替换(不用手动复制)

bash

复制代码
sed -i 's/\[\[ "${READY}" -ge 3 \]\] || warn "期望 3 节点 Ready(1 Master + 2 Worker)/\[\[ "${READY}" -ge 2 \]\] || warn "期望 2 节点 Ready(1 Master + 1 Worker)/' post-install.sh
sed -i 's/# Master 上、2 个 Worker 均为 Ready 后执行/# Master 上、1 个 Worker 均为 Ready(总共2节点)后执行/' post-install.sh

1. 编辑 node-labels.yaml,删掉 k3s-worker-02 那段配置

bash

复制代码
vi node-labels.yaml

只保留 master + worker01 两段,删除 k3s-worker-02 对应的完整 yaml 块。 标准适配 1 主 1 从的 yaml 示例:

yaml

复制代码
apiVersion: v1
kind: Node
metadata:
  name: k3s-master-01
  labels:
    middleware-role: core
spec: {}
---
apiVersion: v1
kind: Node
metadata:
  name: k3s-worker-01
  labels:
    workload: business
    ingress-ready: "true"
spec: {}

2. 再次清理换行符兜底

bash

复制代码
sed -i 's/\r$//' node-labels.yaml

3. 重新执行后置脚本

bash

复制代码
./post-install.sh

不需要在 251 worker 节点执行 post-install.sh

仅 Master 节点执行

  • 脚本依赖 kubectl 操作集群资源、打节点标签、安装集群存储类 (local-path);
  • worker 节点默认没有 /etc/rancher/k3s/k3s.yaml kubeconfig 凭证,执行会直接鉴权失败;
  • 节点标签、存储插件是集群全局资源,只需要在控制面操作一次全集群生效。
  • 192.168.3.250(Master):唯一执行 ./post-install.sh 的机器,完成节点打标、local-path 存储安装;
  • 192.168.3.251(Worker):仅执行 install → agent 加入集群,不用跑 post、不用跑 verify

namespace阶段

1、先手动创建缺失命名空间

bash

复制代码
kubectl create namespace local-path-storage

2、重新应用 local-path 配置文件

bash

复制代码
kubectl apply -f storage/local-path-config.yaml

3、验证 local-path 组件是否正常运行

bash

复制代码
kubectl get pods -n local-path-storage

正常会出现 local-path-provisioner-xxx Pod,状态 Running。

执行完后再完整跑一遍后置脚本收尾:

bash

复制代码
./post-install.sh

重新强制应用配置文件即可:

bash

复制代码
kubectl apply -f storage/local-path-config.yaml

检查 pod 状态确认组件正常

bash

复制代码
kubectl get pods -n local-path-storage

正常输出类似:

plaintext

复制代码
NAME                                  READY   STATUS    RESTARTS   AGE
local-path-provisioner-7f9d76c89d-xxxxx   1/1     Running   0  

配置 k3s 镜像加速(Master+251 Worker 两台都要做)

1.1 创建加速器配置文件

bash

复制代码
vi /etc/rancher/k3s/registries.yaml

写入完整镜像源配置:

yaml

复制代码
mirrors:
  docker.io:
    endpoint:
      - "https://docker.mirrors.ustc.edu.cn"
  gcr.io:
    endpoint:
      - "https://gcr.mirrors.ustc.edu.cn"
  k8s.gcr.io:
    endpoint:
      - "https://k8s.mirrors.ustc.edu.cn"
  quay.io:
    endpoint:
      - "https://quay.mirrors.ustc.edu.cn"

1.2 重启 k3s 加载配置

  • Master(250):

bash

复制代码
systemctl restart k3s
  • Worker(251):

bash

复制代码
systemctl restart k3s-agent

步骤 2:清理卡住的 Pod,重新拉取镜像

bash

复制代码
kubectl delete pod -n local-path-storage --all

删除后控制器会新建 Pod,自动走国内镜像源下载 pause 和 local-path 镜像。

步骤 3:等待 Pod 就绪

bash

复制代码
kubectl rollout status deployment/local-path-provisioner -n local-path-storage

出现 successfully rolled out 代表存储组件正常。

步骤 4:重新执行后置脚本收尾

bash

复制代码
./post-install.sh

两台机器(250 master、251 worker)全部执行导入:

  1. 两台节点都进入 cluster 目录,执行离线导入脚本

bash

复制代码
cd /root/k8s-config/k3s-private/cluster
chmod +x import-airgap-images.sh
./import-airgap-images.sh import
  1. 分别重启服务
  • Master 250:systemctl restart k3s
  • Worker 251:systemctl restart k3s-agent
  1. 删除卡住的 Pod 重建

bash

复制代码
kubectl delete pod -n local-path-storage --all
  1. 等待 Pod Running,再跑 post-install.sh

报错根因

脚本开头 export KUBECONFIG="${KUBECONFIG:-/etc/rancher/k3s/k3s.yaml}" 失效,kubectl 没读到集群证书,默认去连无权限的本地 8080 端口,连接被拒绝。

分两种场景处理

场景 1:你现在在 Master 250 执行(正常应该有 kubeconfig)

  1. 先确认 kubeconfig 文件存在且可读

bash

复制代码
ls -l /etc/rancher/k3s/k3s.yaml
cat /etc/rancher/k3s/k3s.yaml

文件缺失 / 权限不足修复:

bash

复制代码
# 修复权限
chmod 600 /etc/rancher/k3s/k3s.yaml
chown root:root /etc/rancher/k3s/k3s.yaml
  1. 手动强制注入 kubeconfig 再跑脚本

bash

复制代码
export KUBECONFIG=/etc/rancher/k3s/k3s.yaml
./post-install.sh

脚本全部执行成功,集群基础组件部署完成


Headlamp K8s Web 控制台部署步骤(master)

单独分步部署(一键脚本异常时使用)

bash

复制代码
cd /root/k8s-config/k3s-private
kubectl apply -f middleware/headlamp/rbac.yaml
kubectl apply -f middleware/headlamp/deployment.yaml
kubectl apply -f middleware/headlamp/service.yaml

二、发布外网 Gateway 路由(提供域名访问)

bash

复制代码
bash ./scripts/apply-gateway-routes.sh

报错原因

缺少 ops-prod 命名空间,所有 headlamp 资源都部署在这个 ns 下,先创建再应用 yaml。

1、创建业务命名空间 ops-prod

bash

复制代码
kubectl create namespace ops-prod

2、重新依次部署 headlamp 资源

bash

复制代码
kubectl apply -f middleware/headlamp/rbac.yaml
kubectl apply -f middleware/headlamp/deployment.yaml
kubectl apply -f middleware/headlamp/service.yaml

3、发布网关路由(外网访问地址)

bash

复制代码
bash ./scripts/apply-gateway-routes.sh

4、检查 Pod 启动状态

bash

复制代码
kubectl get pods -n ops-prod -l app=headlamp

等待 Pod 变为 1/1 Running


gateway阶段(master)

前置检查

bash

复制代码
cd /root/k8s-config/k3s-private
export KUBECONFIG=/etc/rancher/k3s/k3s.yaml
kubectl get ns ops-prod  # 确认命名空间已创建
kubectl get nodes -L ingress-ready
# 你只有k3s-worker-01带ingress-ready=true,NGF两个副本都会落在这台机器

步骤 1:安装 helm3(文档推荐华为云镜像脚本)

bash

复制代码
bash ./scripts/install-helm.sh
# 验证安装
helm version

步骤 2:安装 NGINX Gateway Fabric(网关核心,CRD+GatewayClass+Gateway)

bash

复制代码
bash ./scripts/apply-gateway.sh

验证是否部署成功:

bash

复制代码
kubectl get gatewayclass
kubectl get gateway -n ops-prod
kubectl get svc -n ops-prod | grep private-gateway-nginx
# 正常输出:80:30080/TCP NodePort

步骤 3:发布 HTTP 路由(包含 headlamp 控制台路由)

bash

复制代码
bash ./scripts/apply-gateway-routes.sh
# 校验路由生成
kubectl get httproute -A

步骤 4:安全策略校验(拦截敏感接口 / 目录)

bash

复制代码
bash ./scripts/verify-actuator-security.sh

##NFG镜像缺失解决:

步骤 1:Worker 节点同步完全相同 registries.yaml

登录 k3s-worker-01(192.168.3.251) 执行:

bash

复制代码
mkdir -p /etc/rancher/k3s
# 复制和Master完全一致的镜像加速配置
scp root@192.168.3.250:/etc/rancher/k3s/registries.yaml /etc/rancher/k3s/
# 重启k3s-agent加载配置
systemctl restart k3s-agent

步骤 2:两台节点分别测试拉取 NGF 镜像

Master (250) 测试

bash

复制代码
k3s ctr images pull ghcr.io/nginx/nginx-gateway-fabric:2.5.0
k3s ctr images pull ghcr.io/nginx/nginx-gateway-fabric/nginx:2.5.0

Worker (251) 测试

bash

复制代码
k3s ctr images pull ghcr.io/nginx/nginx-gateway-fabric:2.5.0
k3s ctr images pull ghcr.io/nginx/nginx-gateway-fabric/nginx:2.5.0

拉取命令必须写 ghcr.io 原始地址,不能替换 ghcr.m.daocloud.io,配置文件会自动转发到 DaoCloud 镜像站。

  • 拉取成功:直接跳步骤 4;
  • 出现 403 / 连接超时:修改 registries.yaml 中 ghcr 端点为 https://ghcr.lank8s.cn,两台节点同步重启服务重试。

结果判定

Worker 251 节点 NGF nginx 镜像拉取完全成功,耗时约 8 分钟、总大小 62.6M,镜像完整下载解压完成。

1、Worker 补拉控制面镜像

继续在 251 执行,拉另一核心镜像:

bash

复制代码
k3s ctr images pull ghcr.io/nginx/nginx-gateway-fabric:2.5.0

等待输出 Completed pull 即两台 NGF 镜像全部就绪。

2、Master 250 同样拉取两套镜像(避免 Master 调度 Pod 缺镜像)

bash

复制代码
k3s ctr images pull ghcr.io/nginx/nginx-gateway-fabric:2.5.0
k3s ctr images pull ghcr.io/nginx/nginx-gateway-fabric/nginx:2.5.0

3、两台节点验证镜像缓存

任意节点执行校验命令,两条镜像都要出现:

bash

复制代码
k3s ctr images ls | grep nginx-gateway-fabric

预期输出两行:

plaintext

复制代码
ghcr.io/nginx/nginx-gateway-fabric:2.5.0
ghcr.io/nginx/nginx-gateway-fabric/nginx:2.5.0

4、Master 清理旧失败 NGF 资源,重装网关

bash

复制代码
export KUBECONFIG=/etc/rancher/k3s/k3s.yaml
# 卸载旧helm release
helm uninstall ngf -n nginx-gateway 2>/dev/null || true
# 清理残留pod/job
kubectl delete pod,job -n nginx-gateway --all --force --grace-period=0
# 重新完整部署NGINX Gateway Fabric
bash ./scripts/apply-gateway.sh
# 实时监控pod启动
kubectl get pods -n nginx-gateway -w

等待所有 Pod 变为 1/1 Running 无拉取报错。

5、网关就绪后发布业务 / 控制台路由

bash

复制代码
bash ./scripts/apply-gateway-routes.sh
# 校验安全拦截策略
bash ./scripts/verify-actuator-security.sh
# 查看所有HTTP路由(包含headlamp /headlamp 二级路径)
kubectl get httproute -A

6、外网访问说明

SLB 回源地址:k3s-worker-01:30080 控制台访问地址:https://jyjzhfw.qiantang.gov.cn/headlamp/(末尾斜杠必须携带)

补充关键点

  1. 镜像加速配置已生效,DaoCloud ghcr 源正常分发;
  2. 两台节点必须同时存在两套 NGF 镜像,cert-generator、数据面 Pod 会随机调度任意节点;
  3. 后续不会再出现 failed pre-install: timed out waiting for the condition 镜像超时报错。

250、Worker 251 节点 NGF nginx 镜像拉取完全成功下一步步骤

步骤 1:清理之前安装失败的 NGF 残留资源

bash

复制代码
export KUBECONFIG=/etc/rancher/k3s/k3s.yaml
# 卸载helm发布
helm uninstall ngf -n nginx-gateway 2>/dev/null || true
# 强制删除所有pod、任务,清除失败缓存
kubectl delete pod,job -n nginx-gateway --all --force --grace-period=0

步骤 2:重新完整部署 NGINX Gateway Fabric

bash

复制代码
cd /root/k8s-private
bash ./scripts/apply-gateway.sh

脚本会自动:

  1. 安装 Gateway API 标准 CRD
  2. Helm 部署 NGF 控制面(cert-generator 任务不再镜像超时)
  3. 创建集群共享 Gateway、安全拦截策略、上传大小配置

步骤 3:校验网关基础资源是否正常

bash

复制代码
# 查看网关类(必须存在Accepted状态)
kubectl get gatewayclass
# 查看ops-prod命名空间网关实例
kubectl get gateway -n ops-prod
# 查看NGF服务,确认NodePort=30080
kubectl get svc -n nginx-gateway
# 实时监控所有NGF Pod状态,等待全部1/1 Running
kubectl get pods -n nginx-gateway -w

正常预期:

  • nginx-gateway-fabric 控制面 Pod 就绪
  • private-gateway-nginx 数据面 Pod 就绪(调度到 worker)
  • ImagePullBackOff、ErrImage 拉取错误

步骤 4:发布 HTTP 路由(包含 Headlamp 控制台二级路径)

网关基础组件就绪后,执行路由生成脚本,对外暴露/headlamp/访问入口:

bash

复制代码
bash ./scripts/apply-gateway-routes.sh
# 校验接口安全拦截规则(屏蔽actuator、敏感map路径403)
bash ./scripts/verify-actuator-security.sh
# 查看全部HTTPRoute资源
kubectl get httproute -A

下一步完整操作(按顺序执行)

步骤 1:发布域名路由(包含 Headlamp 控制台 /headlamp/ 访问路径)

bash

复制代码
bash /root/k8s-config/k3s-private/scripts/apply-gateway-routes.sh

步骤 2:校验安全拦截规则(屏蔽 actuator、敏感接口)

bash

复制代码
bash /root/k8s-config/k3s-private/scripts/verify-actuator-security.sh

步骤 3:完整部署 Headlamp 控制台(Web 集群面板)

bash

复制代码
cd /root/k8s-config/k3s-private
# 依次创建RBAC权限、部署、Service
kubectl apply -f middleware/headlamp/rbac.yaml
kubectl apply -f middleware/headlamp/deployment.yaml
kubectl apply -f middleware/headlamp/service.yaml

步骤 4:查看 Headlamp 运行状态

bash

复制代码
kubectl get pods -n ops-prod -l app=headlamp

等待 Pod 变为 1/1 Running(启动需 10~30 秒)

DAY02.5当前环境与目标

1. 机器角色

复制代码
192.168.X.250 = master
负责 Kubernetes 控制面、kubectl、调度、API Server。
​
192.168.X.251 = worker
负责运行业务容器、Gateway 数据面、页面服务。

2. 最终访问链路

复制代码
浏览器访问 jyjzhfw.qiantang.gov.cn
        |
        v
Worker 192.168.X.251:30080
        |
        v
private-gateway-nginx
        |
        v
HTTPRoute 按 Host + Path 分发
        |
        v
CAS / Nacos / 业务 API / UI

3. 项目原始推荐与现场差异

项目文档原本推荐:

复制代码
1 Master + 2 Worker

现场实际为:

复制代码
1 Master + 1 Worker

因此 Gateway 数据面必须降级为单副本:

复制代码
nginx:
  replicas: 1

否则 Gateway 会尝试创建两个数据面 Pod,并且 required 反亲和会导致第二个 Pod 无法调度。

二、今天完成到哪里

已完成

Gateway 入口已经修通:

复制代码
kubectl get gateway -A

结果已达到:

复制代码
NAMESPACE   NAME              CLASS   ADDRESS        PROGRAMMED
ops-prod    private-gateway   nginx   10.43.X.154   True

Gateway Service 已变为:

复制代码
private-gateway-nginx   NodePort   10.43.x.154   8080:30080/TCP

Gateway Pod 已达到:

复制代码
private-gateway-nginx-xxx   1/1   Running

Endpoint 已出现:

复制代码
private-gateway-nginx   10.42.x.55:8080

安全拦截已验证成功:

复制代码
curl -i -H "Host: jyjzhfw.qiantang.gov.cn" http://192.168.x.251:30080/actuator

返回:

复制代码
HTTP/1.1 403 Forbidden
{"code":403,"message":"Forbidden"}

这说明:

复制代码
NodePort 30080 -> Gateway -> SnippetsPolicy 安全规则

这条链路已经正常。

未完成

访问根路径 / 仍未完全成功:

复制代码
curl -i -H "Host: jyjzhfw.qiantang.gov.cn" http://192.168.x.251:30080/

曾返回:

复制代码
HTTP/1.1 500 Internal Server Error

原因已经进一步定位到后端 CAS:

  • / 路由后端是 brain-prod/tianyin-cas-svc:8181

  • 一开始 brain-prod 里没有 CAS 服务和 Pod

  • 后来部署了 CAS,但 CAS 曾重启并报数据库配置错误

最后一次 describe pod 显示 CAS 一度变为:

复制代码
Status: Running
Ready: True
Restart Count: 5

但日志中仍出现过:

复制代码
Could not load JDBC driver class [org.hsqldb.jdbcDriver]

所以明天第一件事是确认 CAS 是否已经稳定,如果不稳定,继续查 Nacos 中的 CAS 配置。

三、今天遇到的问题与解决过程

问题 1:安全验证脚本默认访问 127.0.0.1:30080,连接失败

现象

执行:

复制代码
HOST=jyjzhfw.qiantang.gov.cn TARGET=http://192.168.x.251:30080 bash /root/k8s-config/k3s-private/scripts/verify-actuator-security.sh

输出中实际访问的是:

复制代码
http://127.0.0.1:30080

并报错:

复制代码
curl: (7) Failed connect to 127.0.0.1:30080; 拒绝连接
FAIL 000000 /actuator (expected 403)

判断

脚本默认变量是 BASE_URL,不是所有版本都支持 TARGET

正确用法

优先使用:

复制代码
HOST=jyjzhfw.qiantang.gov.cn BASE_URL=http://192.168.3.251:30080 bash /root/k8s-config/k3s-private/scripts/verify-actuator-security.sh

或者脚本中兼容:

复制代码
BASE_URL="${BASE_URL:-${TARGET:-http://127.0.0.1:${PORT}}}"

经验

验证 Gateway 时不要默认访问 127.0.0.1,因为 kubectl 在 master 上执行,而 Gateway NodePort 实际在 worker 上。

现场应访问:

复制代码
http://192.168.3.251:30080

问题 2:误把 31116 当成 Gateway

现象

执行:

复制代码
curl -I http://192.168.x.250:31116
curl -I http://192.168.x.251:31116

返回:

复制代码
HTTP/1.1 404 Not Found

判断

查询 Service:

复制代码
kubectl get svc -A -o wide | grep -E '31116|30080|gateway|private-gateway'

发现:

复制代码
ops-prod   headlamp                NodePort   80:31116/TCP
ops-prod   private-gateway-nginx   NodePort   80:30080/TCP

结论

31116 是 Headlamp,不是业务 Gateway。

业务 Gateway 是:

复制代码
192.168.x.251:30080

经验

看到 NodePort 时必须先确认 Service 名称:

复制代码
kubectl get svc -A -o wide | grep NodePort

不要只看端口号。

问题 3:Gateway Pod 卡在 Init:0/1

现象

复制代码
kubectl get pods -n ops-prod -l gateway.networking.k8s.io/gateway-name=private-gateway -o wide

输出:

复制代码
private-gateway-nginx-xxx   0/1   Init:0/1   <none>   k3s-worker-01

Endpoint 为空:

复制代码
kubectl get endpoints private-gateway-nginx -n ops-prod

输出:

复制代码
private-gateway-nginx   <none>

根因

Worker 系统:

复制代码
uname -r

输出:

复制代码
3.10.0-1160.119.1.el7.x86_64

系统:

复制代码
CentOS Linux 7

检查:

复制代码
ls -l /proc/sys/net/ipv4/ip_unprivileged_port_start

输出:

复制代码
没有那个文件或目录

Gateway init 阶段使用了内核参数:

复制代码
net.ipv4.ip_unprivileged_port_start

CentOS 7 的 3.10 内核没有这个文件,所以 init 阶段失败。

不能采用的方案

标准解法是升级 worker 内核或更换系统。

但现场限制:

复制代码
机器不能换,内核不能升级。

所以采用兼容绕过方案。

问题 4:一主一从环境下 Gateway 第二个 Pod Pending

现象

复制代码
private-gateway-nginx-xxx   0/1   Running
private-gateway-nginx-yyy   0/1   Pending

调度事件:

复制代码
1 node(s) didn't match pod anti-affinity rules

根因

项目默认按照多 worker 规划,Gateway 数据面原来是 2 副本,并且使用 required podAntiAffinity 分散到不同节点。

现场只有 1 个 worker,所以第二个 Pod 永远调度不出来。

解决

k3s-private/gateway/helm-values-ngf.yaml 中设置:

复制代码
nginx:
  replicas: 1

经验

一主一从部署时,所有带强反亲和的入口类组件都要检查副本数。

问题 5:Helm values 文件被误改坏,YAML 解析失败

现象

执行:

复制代码
bash ./k3s-private/scripts/restart-ngf.sh

报错:

复制代码
Error: failed to parse /root/k8s-config/k3s-private/gateway/helm-values-ngf.yaml:
yaml: line 40: mapping values are not allowed in this context

查看文件发现错误片段:

复制代码
rt: 30080
    listenerPort: 8080

根因

手动编辑 YAML 时残留了错误行和错误缩进。

解决

重写 helm-values-ngf.yaml 中 Gateway 相关部分,保证缩进正确。

关键配置如下:

复制代码
nginxGateway:
  image:
    repository: aiban-docker.pkg.coding.net/tianyin/base/nginx-gateway-fabric
    tag: "2.5.0"
  gatewayClassName: nginx
  snippets:
    enable: true

nginx:
  image:
    repository: aiban-docker.pkg.coding.net/tianyin/base/nginx-gateway-fabric-nginx
    tag: "2.5.0"
  service:
    type: NodePort
    externalTrafficPolicy: Local
    nodePorts:
      - port: 30080
        listenerPort: 8080
  pod:
    nodeSelector:
      ingress-ready: "true"
    affinity:
      podAntiAffinity:
        requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchLabels:
                app.kubernetes.io/managed-by: ngf-nginx
            topologyKey: kubernetes.io/hostname
  replicas: 1

经验

YAML 出现 mapping values are not allowed,优先检查:

  • 冒号后是否乱接值

  • 缩进是否混乱

  • 是否误把说明文字粘进 YAML

可用:

复制代码
helm upgrade --dry-run ...

或直接重新打开文件检查缩进。

问题 6:Gateway Programmed=False,Nginx 绑定 80 端口失败

现象

复制代码
kubectl describe gateway private-gateway -n ops-prod

关键错误:

复制代码
bind() to 0.0.0.0:80 failed (13: Permission denied)
nginx: configuration file /etc/nginx/nginx.conf test failed

Gateway 状态:

复制代码
PROGRAMMED   False

根因

为了绕过旧内核 sysctl,调整了运行方式后,容器内 Nginx 无法以当前权限绑定 80 端口。

解决思路

不让容器内 Nginx 监听 80,改为监听非特权端口 8080。

对外仍保持 NodePort 30080。

最终链路变为:

复制代码
外部访问 192.168.x.251:30080
        |
        v
Service NodePort 30080
        |
        v
Pod 内 Nginx 8080

修改 1:Gateway listener 改 8080

k3s-private/gateway/gateway.yaml

复制代码
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: private-gateway
  namespace: ops-prod
spec:
  gatewayClassName: nginx
  listeners:
    - name: http
      protocol: HTTP
      port: 8080
      allowedRoutes:
        namespaces:
          from: All

修改 2:Helm values 中 NodePort 仍为 30080,listenerPort 改 8080

复制代码
nginx:
  service:
    type: NodePort
    externalTrafficPolicy: Local
    nodePorts:
      - port: 30080
        listenerPort: 8080

重新应用

复制代码
bash ./k3s-private/scripts/restart-ngf.sh
kubectl apply -f k3s-private/gateway/gateway.yaml

经验

对外 NodePort 不等于 Pod 内监听端口。

这里的正确理解是:

复制代码
Service: 8080:30080/TCP

含义是:

复制代码
Pod/Service 端口 8080
NodePort 对外端口 30080

所以用户浏览器仍访问:

复制代码
http://19x.168.x.251:30080

问题 7:Nginx 启动后 chown 失败

现象

Gateway Pod 变成 Running 但不 Ready,持续重启:

复制代码
0/1 Running
Readiness probe failed: connect: connection refused
Back-off restarting failed container nginx

查看日志:

复制代码
kubectl logs private-gateway-nginx-xxx -n ops-prod -c nginx --tail=160

关键错误:

复制代码
chown("/var/cache/nginx/client_temp", 101) failed (1: Operation not permitted)

根因

容器启动脚本或 Nginx 进程需要执行 chown/setuid/setgid,但当前安全上下文权限不足。

解决

helm-values-ngf.yaml 中添加 patch:

复制代码
nginx:
  patches:
    - type: StrategicMerge
      value:
        spec:
          strategy:
            type: Recreate
          template:
            spec:
              securityContext:
                runAsUser: 0
                runAsGroup: 0
                runAsNonRoot: false
                sysctls: []
              containers:
                - name: nginx
                  securityContext:
                    runAsUser: 0
                    runAsGroup: 0
                    runAsNonRoot: false
                    allowPrivilegeEscalation: true
                    capabilities:
                      add:
                        - CHOWN
                        - SETUID
                        - SETGID
                        - NET_BIND_SERVICE

重新应用

复制代码
bash ./k3s-private/scripts/restart-ngf.sh
kubectl delete pod -n ops-prod -l gateway.networking.k8s.io/gateway-name=private-gateway
kubectl get pods -n ops-prod -l gateway.networking.k8s.io/gateway-name=private-gateway -o wide

最终结果

复制代码
private-gateway-nginx-xxx   1/1   Running

经验

旧内核 + NGF 默认安全上下文会触发多个权限问题:

  1. sysctl 文件不存在

  2. 绑定 80 端口权限不足

  3. chown 权限不足

现场最终组合方案:

复制代码
去掉 sysctls
容器内监听 8080
NodePort 仍暴露 30080
单副本
补充 CHOWN / SETUID / SETGID / NET_BIND_SERVICE capabilities

问题 8:删除 Pod 后出现旧 ReplicaSet 干扰

现象

删除 Gateway Pod 后,又出现多个不同 hash 的 Pod:

复制代码
private-gateway-nginx-6f6d875c87-xxx
private-gateway-nginx-6fb857c84f-yyy

一个 Init,一个 Pending。

根因

旧 ReplicaSet 仍然存在,继续拉起旧配置 Pod。

解决

确认 ReplicaSet:

复制代码
kubectl get rs -n ops-prod | grep private-gateway

删除旧 ReplicaSet:

复制代码
kubectl delete rs private-gateway-nginx-旧hash -n ops-prod

再查:

复制代码
kubectl get pods -n ops-prod -l gateway.networking.k8s.io/gateway-name=private-gateway -o wide

经验

如果同一个组件出现两个不同 hash 的 Pod,要看 ReplicaSet:

复制代码
kubectl get rs -n <namespace>

不要只删 Pod。

问题 9:Gateway Endpoint 为空

现象

复制代码
kubectl get endpoints private-gateway-nginx -n ops-prod

输出:

复制代码
private-gateway-nginx   <none>

判断

Endpoint 为空不是独立问题,而是说明后端 Pod 没 Ready。

修复后结果

复制代码
private-gateway-nginx   10.42.x.55:8080

经验

查 Service 是否可用,必须同时看三件事:

复制代码
kubectl get svc <svc> -n <ns>
kubectl get pods -n <ns> -l <label> -o wide
kubectl get endpoints <svc> -n <ns>

只看 Service 存在没有意义,Endpoint 为空时流量没有真正后端。

问题 10:Gateway 通了,但访问 / 返回 500

现象

复制代码
curl -i -H "Host: jyjzhfw.qiantang.gov.cn" http://192.16x.x.251:30080/

返回:

复制代码
HTTP/1.1 500 Internal Server Error

判断

安全路径 /actuator 已经返回 403,说明 Gateway 本身是通的。

/ 返回 500,说明 Gateway 找到了路由,但后端服务存在问题。

检查 HTTPRoute:

复制代码
kubectl get httproute -A | grep jyjzhfw
kubectl describe httproute -n brain-prod brain-route

发现 / 后端是:

复制代码
brain-prod/tianyin-cas-svc:8181

但当时:

复制代码
kubectl get svc -n brain-prod
kubectl get pods -n brain-prod

输出:

复制代码
No resources found in brain-prod namespace.

根因

CAS 服务根本还没部署。

解决

复制代码
cd /root/k8s-config
export KUBECONFIG=/etc/rancher/k3s/k3s.yaml

kubectl apply -f k3s-private/brain-prod/init-config.yaml
kubectl apply -f k3s-private/brain-prod/tianyin-cas.yaml

创建结果:

复制代码
service/tianyin-cas-svc created
deployment.apps/tianyin-cas-deploy created

经验

Gateway 500 时,不要马上改 Gateway。

先看路由后端是否存在:

复制代码
kubectl describe httproute -n <ns> <route-name>
kubectl get svc -n <backend-ns>
kubectl get endpoints <backend-svc> -n <backend-ns>

问题 11:CAS 镜像拉取成功,但容器 Error / 重启

现象

复制代码
kubectl get pods -n brain-prod -o wide

曾出现:

复制代码
tianyin-cas-deploy-xxx   0/1   Error   RESTARTS=4

镜像拉取成功:

复制代码
Successfully pulled image "aiban-docker.pkg.coding.net/dongyangxiangmu/dongyang/tianyin-cas:ty_bzb-zhpj-saas-1.1.4"

说明不是镜像仓库问题。

日志关键错误

复制代码
Caused by: java.lang.IllegalStateException:
Could not load JDBC driver class [org.hsqldb.jdbcDriver]

判断

CAS 启动时创建 DataSource 失败。

它读到的数据库驱动是:

复制代码
org.hsqldb.jdbcDriver

这是 HSQLDB 测试库驱动,不应该出现在生产 K3s 私有化配置中。

根因方向

k3s-private/brain-prod/init-config.yaml 只提供 Nacos 地址和配置定位:

复制代码
nacos.config.data-id: tianyin-cas-prod.properties
nacos.config.namespace: f54ff835-1dda-4b27-a174-fe40f416789e
nacos.config.server-addr: http://nacos.ops-prod.svc.cluster.local:8848

项目仓库没有提供完整的 tianyin-cas-prod.properties 内容。

所以 CAS 的真实业务配置需要从 Nacos 导入。

当前高度怀疑:

复制代码
Nacos 中 tianyin-cas-prod.properties 不存在
或
Nacos 中该配置缺少正确 MySQL datasource 配置
或
配置中仍保留了 org.hsqldb.jdbcDriver

四、可复用部署 SOP

以下 SOP 适用于从明天继续推进。

SOP 0:每次开始前固定环境

在 master 上执行:

复制代码
cd /root/k8s-config
export KUBECONFIG=/etc/rancher/k3s/k3s.yaml

确认节点:

复制代码
kubectl get nodes -o wide

期望:

复制代码
k3s-master-xx   Ready
k3s-worker-01   Ready

确认 namespace:

复制代码
kubectl get ns

至少应有:

复制代码
ops-prod
brain-prod
zhpj-prod
portfolio-prod
tdp-prod
dwh-prod

SOP 1:确认 Gateway 是否健康

复制代码
kubectl get gateway -A
kubectl get svc private-gateway-nginx -n ops-prod
kubectl get pods -n ops-prod -l gateway.networking.k8s.io/gateway-name=private-gateway -o wide
kubectl get endpoints private-gateway-nginx -n ops-prod

健康标准:

复制代码
Gateway PROGRAMMED=True
Service NodePort 包含 30080
Pod 1/1 Running
Endpoint 非空

本次现场最终标准:

复制代码
private-gateway-nginx   NodePort   8080:30080/TCP
private-gateway-nginx   10.42.x.x:8080

验证安全策略:

复制代码
curl -i -H "Host: jyjzhfw.qiantang.gov.cn" http://192.168.x.251:30080/actuator

期望:

复制代码
HTTP/1.1 403 Forbidden

SOP 2:Gateway 异常时的排查顺序

第一步,看 Gateway 状态:

复制代码
kubectl describe gateway private-gateway -n ops-prod

常见判断:

复制代码
Accepted=True, Programmed=False

说明 Gateway 对象被接受,但 Nginx 配置没有成功下发或 reload。

第二步,看数据面 Pod:

复制代码
kubectl describe pod -n ops-prod -l gateway.networking.k8s.io/gateway-name=private-gateway

第三步,看日志:

复制代码
kubectl logs -n ops-prod -l gateway.networking.k8s.io/gateway-name=private-gateway -c nginx --tail=160

如果容器反复重启,可尝试:

复制代码
kubectl logs <pod-name> -n ops-prod -c nginx --previous --tail=160

第四步,看 Endpoint:

复制代码
kubectl get endpoints private-gateway-nginx -n ops-prod

Endpoint 为空时,先让 Pod Ready,不要继续查业务页面。

SOP 3:一主一从环境下的 Gateway 固定方案

helm-values-ngf.yaml 的关键点:

复制代码
nginx:
  service:
    type: NodePort
    externalTrafficPolicy: Local
    nodePorts:
      - port: 30080
        listenerPort: 8080
  replicas: 1

旧内核兼容 patch:

复制代码
nginx:
  patches:
    - type: StrategicMerge
      value:
        spec:
          strategy:
            type: Recreate
          template:
            spec:
              securityContext:
                runAsUser: 0
                runAsGroup: 0
                runAsNonRoot: false
                sysctls: []
              containers:
                - name: nginx
                  securityContext:
                    runAsUser: 0
                    runAsGroup: 0
                    runAsNonRoot: false
                    allowPrivilegeEscalation: true
                    capabilities:
                      add:
                        - CHOWN
                        - SETUID
                        - SETGID
                        - NET_BIND_SERVICE

gateway.yaml listener:

复制代码
listeners:
  - name: http
    protocol: HTTP
    port: 8080

应用:

复制代码
bash ./k3s-private/scripts/restart-ngf.sh
kubectl apply -f k3s-private/gateway/gateway.yaml
kubectl delete pod -n ops-prod -l gateway.networking.k8s.io/gateway-name=private-gateway

等待:

复制代码
kubectl get pods -n ops-prod -l gateway.networking.k8s.io/gateway-name=private-gateway -w

看到 1/1 Running 后按 Ctrl + C

SOP 4:部署 CAS

在 master 上执行:

复制代码
cd /root/k8s-config
export KUBECONFIG=/etc/rancher/k3s/k3s.yaml

先应用 init-config:

复制代码
kubectl apply -f k3s-private/brain-prod/init-config.yaml

再部署 CAS:

复制代码
kubectl apply -f k3s-private/brain-prod/tianyin-cas.yaml

检查:

复制代码
kubectl get svc -n brain-prod
kubectl get pods -n brain-prod -o wide
kubectl get endpoints tianyin-cas-svc -n brain-prod

健康标准:

复制代码
tianyin-cas-svc 存在
tianyin-cas-deploy-xxx 1/1 Running
tianyin-cas-svc Endpoint 非空

SOP 5:CAS 异常时的排查顺序

看 Pod 状态:

复制代码
kubectl get pods -n brain-prod -l app=tianyin-cas -o wide

看详细事件:

复制代码
kubectl describe pod -n brain-prod -l app=tianyin-cas

看当前日志:

复制代码
kubectl logs -n brain-prod -l app=tianyin-cas --tail=200

如果已经重启过,看上一次崩溃日志:

复制代码
kubectl logs -n brain-prod -l app=tianyin-cas --previous --tail=200

看 Endpoint:

复制代码
kubectl get endpoints tianyin-cas-svc -n brain-prod

如果 Endpoint 为空,说明 CAS 还没 Ready。

六、常用排障命令速查

集群

复制代码
kubectl get nodes -o wide
kubectl get ns
kubectl get pods -A -o wide

Service / Endpoint

复制代码
kubectl get svc -A -o wide
kubectl get endpoints <svc-name> -n <namespace>

Gateway

复制代码
kubectl get gateway -A
kubectl describe gateway private-gateway -n ops-prod
kubectl get httproute -A
kubectl describe httproute -n brain-prod brain-route

Pod

复制代码
kubectl get pods -n <namespace> -o wide
kubectl describe pod -n <namespace> <pod-name>
kubectl logs <pod-name> -n <namespace> --tail=200
kubectl logs <pod-name> -n <namespace> --previous --tail=200

按 label 查

复制代码
kubectl get pods -n brain-prod -l app=tianyin-cas -o wide
kubectl logs -n brain-prod -l app=tianyin-cas --tail=200
kubectl describe pod -n brain-prod -l app=tianyin-cas

Gateway curl

复制代码
curl -i -H "Host: jyjzhfw.qiantang.gov.cn" http://192.168.3.251:30080/
curl -i -H "Host: jyjzhfw.qiantang.gov.cn" http://192.168.3.251:30080/actuator
curl -I -H "Host: jyjzhfw.qiantang.gov.cn" http://192.168.3.251:30080/nacos/

七、判断口诀

1. Service 存在不代表能访问

必须看 Endpoint。

复制代码
Service 存在 + Endpoint 为空 = 没有可用后端

2. Gateway 403 是好消息

访问 /actuator 返回 403,说明:

复制代码
NodePort 通
Gateway 通
安全规则生效

3. Gateway 500 多半看后端

如果安全路径已经 403,但业务路径 500,优先查:

复制代码
HTTPRoute -> Service -> Endpoint -> Pod Logs

4. Image pulled 不代表应用成功

复制代码
Successfully pulled image

只说明镜像拉下来了。

应用是否成功要看:

复制代码
Pod Ready
Endpoint 非空
日志无启动异常

5. CrashLoop 时先看 previous logs

容器已经重启后,当前日志可能不完整。

使用:

复制代码
kubectl logs <pod> -n <ns> --previous --tail=200

6. 旧内核 Gateway 问题不要反复重装 K3s

本次旧内核问题是:

复制代码
/proc/sys/net/ipv4/ip_unprivileged_port_start 不存在

解决在 Gateway Helm values 和 listener,不需要重装 K3s。

八、今天沉淀的经验

1. 先分层,再排障

不要把所有问题混在一起看。

按层判断:

复制代码
机器
K3s 节点
Namespace
中间件
Gateway
HTTPRoute
Service
Endpoint
Pod
应用日志
业务页面

哪一层没通,就停在那一层。

2. NodePort 是入口,不是业务本身

30080 只是把流量送进 Gateway。

真正页面是否能打开,还要看:

复制代码
HTTPRoute 后端服务是否存在
后端 Pod 是否 Ready
Nacos 配置是否正确
数据库是否可连

3. 一主一从要主动降级副本

凡是原项目按 2 worker 设计的组件,都要检查:

复制代码
replicas
podAntiAffinity
nodeSelector
topologySpreadConstraints

4. Nacos 配置是业务启动关键

业务 YAML 里通常只有:

复制代码
Nacos 地址
namespace
dataId
账号密码

真正数据库、Redis、MQ、业务开关等配置在 Nacos。

所以 Spring Boot 启动失败时,不能只看 Kubernetes YAML。

5. 不要把解释文字粘到 shell

今天误把说明文字当命令执行过。

建议以后执行命令时:

  • 一次只复制一个代码块

  • 看到中文说明不要粘进终端

  • 命令前确认以 kubectlbashcurlcd 等开头

九、当前状态快照

截至 2026-07-22 停止前:

复制代码
K3s 集群:已可用
Gateway:已修好,Programmed=True
Gateway NodePort:192.168.3.251:30080
Gateway Pod:1/1 Running
Gateway Endpoint:10.42.1.55:8080
Actuator 安全拦截:403,已成功
brain-prod CAS Service:已创建
brain-prod CAS Pod:曾 Error,最后 describe 显示 Ready=True,但重启过 5 次
CAS 待确认问题:Nacos 中 tianyin-cas-prod.properties 的数据库配置
相关推荐
●VON1 小时前
鸿蒙 PC Markdown 编辑器搜索选项响应式布局:220 vp 侧栏中的完整中文控件
服务器·华为·编辑器·harmonyos·鸿蒙
AbandonForce1 小时前
Linux进程(WHAT HOW)
linux·运维·服务器
静默追光1 小时前
服务器——看门狗
linux·运维·服务器
无足鸟ICT1 小时前
【RHCA+】测试变量
linux
nVisual2 小时前
巡检任务与工单闭环方案
运维·服务器·数据库·数据中心基础设施
_abab2 小时前
Rust重塑系统编程:从Linux内核到AI推理引擎的2026全景解析
linux·人工智能·rust
初圣魔门首席弟子2 小时前
TypeScript 类型系统完全指南:从基础到高级工具类型(知识库版)
linux·运维·ubuntu
CQU_JIAKE2 小时前
7.23[a]
linux·运维·服务器
想学好C++的oMen2 小时前
socket编程TCP
linux·网络·网络协议·tcp/ip