K3s 双节点集群部署
本文采用 1 Server 1 Agent 架构仅实现工作负载双节点运行不属于 Kubernetes Control Plane 高可用方案。版本K3s v1.36.3k3s1Helm v3.21.3cert-manager 1.19.6Traefik3.7.1一、 环境规划与前置准备在进行任何安装步骤之前必须在所有节点Server 及 Agent 节点上完成操作系统OS级的内核模块加载与系统参数调优以避免重启后 Pod 通信异常或系统资源句柄不足。1. 节点基础信息节点主机名节点角色IP 地址核心服务名主要职责masterServer / Control Plane192.168.31.100k3s.serviceKubernetes API、调度、控制器、K3s Server、也可运行 Podnode1Agent / Worker192.168.31.101k3s-agent.service运行业务 Pod2. 前置准备所有节点必做(1) 内核模块与参数加固# 1、配置文件持久化重启后自动加载 # overlay 模块用于 containerd 镜像分层挂载br_netfilter 用于 K8s iptables 流量桥接过滤 sudo tee /etc/modules-load.d/k3s.conf /dev/null EOF overlay br_netfilter nf_conntrack EOF # 2、立即加载模块 sudo modprobe overlay sudo modprobe br_netfilter sudo modprobe nf_conntrack # 3、开启 IPv4 转发、二层网桥 iptables 处理以及调高文件监听/连接跟踪上限 sudo tee /etc/sysctl.d/k3s.conf /dev/null EOF net.bridge.bridge-nf-call-iptables1 net.bridge.bridge-nf-call-ip6tables1 net.ipv4.ip_forward1 net.ipv4.conf.all.forwarding1 net.netfilter.nf_conntrack_max131072 fs.inotify.max_user_instances8192 fs.inotify.max_user_watches524288 vm.max_map_count262144 EOF # 4、使所有参数生效 sudo sysctl --system # 5. 验证 (确保两个模块都在) lsmod | grep -E br_netfilter|overlay # 输出如下 overlay 155648 21 br_netfilter 32768 0 bridge 270336 1 br_netfilter(2) 其它设置# 本地使用 VMWare 部署需要执行下面操作云服务器下面设置一般默认都是关闭的 # 唯一需要关注的是 selinux建议设置为宽容模式或不设置也可以。但如果项目涉及金钱或核心机密或者追求极致安全将模式设为 Enforcing # 1、关闭防火墙 sudo systemctl disable --now firewalld # 查看防火墙状态 firewall-cmd --state # 2、禁用 swap 虽然标准 K8s 要求关闭但 K3s 支持开启 swapoff -a sed -ri s/.*swap.*/#/ /etc/fstab # 3、关闭 selinux sudo setenforce 0 sudo sed -i s/^SELINUX.*/SELINUXpermissive/ /etc/selinux/config # 4、设置 hostname # 在 IP 为 192.168.31.100 的机器上执行 sudo hostnamectl set-hostname master # 在 IP 为 192.168.31.101 的机器上执行 sudo hostnamectl set-hostname node1 检查 hostnamectl # 5、配置 /etc/hosts所有节点 echo -e 192.168.31.100 master\n192.168.31.101 node1 | sudo tee -a /etc/hosts二、 核心配置文件编写1、创建目录sudo mkdir -p /etc/rancher/k3s/2. Server 节点的 config.yaml控制面定制# 在 master 节点创建 /etc/rancher/k3s/config.yaml。使用 config.yaml 可以避免在 curl 一键脚本中写过长且易错的环境变量 # 下面内容是一整条命令 sudo tee /etc/rancher/k3s/config.yaml /dev/null EOF # 1. 节点名称 node-name: master # 2. 数据与镜像存储路径指向独立的磁盘挂载点防止撑爆系统盘目录>3. 所有节点的镜像加速配置# 在 master 和 node1 节点同时创建 /etc/rancher/k3s/registries.yaml # 国内镜像服务的可用性、同步范围和访问策略可能变化 # 生产环境建议优先使用企业自己的私有镜像仓库并将业务镜像及关键基础镜像同步到自己的 SWR/ACR Harbor 等 Registry。 sudo tee /etc/rancher/k3s/registries.yaml /dev/null EOF mirrors: docker.io: endpoint: - https://docker.m.daocloud.io registry.k8s.io: endpoint: - https://k8s.m.daocloud.io gcr.io: endpoint: - https://gcr.m.daocloud.io ghcr.io: endpoint: - https://ghcr.m.daocloud.io quay.io: endpoint: - https://quay.m.daocloud.io EOF三、 集群部署1、部署 Server 节点 (master)由于之前已写好 /etc/rancher/k3s/config.yamlK3s 安装脚本启动时会自动加载该文件的所有配置。在 master (192.168.31.100) 上运行国内镜像安装脚本curl -sfL https://rancher-mirror.rancher.cn/k3s/k3s-install.sh | \ INSTALL_K3S_MIRRORcn \ INSTALL_K3S_VERSIONv1.36.3k3s1 \ sh -安装完成后获取 Worker 节点加入集群所需的 Token记录输出的 Token 字符串形如 K10xxx…::server:abc123xxx。# 上面 config.yaml 中自定义了数据目录 # 如果没有自定义执行 sudo cat /var/lib/rancher/k3s/server/node-token cat /data/k3s/server/node-token2、部署 Agent 节点 (node1)登录到 node1 (192.168.31.101)使用 K3S_URL 和 K3S_TOKEN 环境变量启动 Agent 安装脚本curl -sfL https://rancher-mirror.rancher.cn/k3s/k3s-install.sh | \ INSTALL_K3S_MIRRORcn \ INSTALL_K3S_VERSIONv1.36.3k3s1 \ K3S_URLhttps://192.168.31.100:6443 \ K3S_TOKEN从Master获取的Token \ sh -注安装脚本在启动 k3s-agent 服务时会自动读取之前写好的 /etc/rancher/k3s/registries.yaml无需手动重启。如后续修改该文件需运行 sudo systemctl restart k3s-agent 生效。3、 验证节点连接回到 master 上验证节点加入状态kubectl get nodes标准预期输出NAME STATUS ROLES AGE VERSION master Ready control-plane 3h v1.36.3k3s1 node1 Ready none 5m v1.36.3k3s1四、 集群组件 Helm 安装Helm 是 Kubernetes 的官方包管理工具Package Manager相当于 Linux 世界的 apt / yum或 Node.js 世界的 npm。它把多个关联的 Kubernetes 资源打包成一个整体Chart实现应用的一键安装、升级、配置和回滚。只在 Servermaster 节点安装。1、Helm 国内安装# 1. 创建临时目录并下载 Helm 3 二进制包 # 如果下载慢可以访问 https://mirrors.huaweicloud.com/helm/ 或利用 GitHub wget https://mirrors.huaweicloud.com/helm/v3.21.3/helm-v3.21.3-linux-amd64.tar.gz # 2. 解压 tar -zxvf helm-v3.21.3-linux-amd64.tar.gz # 3. 将解压出来的 helm 二进制移动到系统 PATH 路径中 mv linux-amd64/helm /usr/local/bin/helm # 4. 验证安装 helm version2、配置 K3s 权限# 1. 创建 root 用户的默认 config 目录 mkdir -p /root/.kube # 2. 复制 K3s 的配置文件到默认位置 cp /etc/rancher/k3s/k3s.yaml /root/.kube/config # 3. 赋予正确的权限 chmod 600 /root/.kube/config3、配置 Helm 镜像仓库# 1. 添加 Bitnami 仓库这是全球最全的开源软件库如 MySQL, Redis helm repo add bitnami https://charts.bitnami.com/bitnami # 2. 添加 cert-manager 官方仓库 # cert-manager自动 HTTPS 证书签发与续签 helm repo add jetstack https://charts.jetstack.io # 3. 更新本地仓库索引 helm repo update # 4. 查看已添加的仓库列表 helm repo list # 5. 在仓库中搜索 Chart如搜索 nginx helm search repo nginx # 移除已经添加的仓库 stable 替换为想要移除的仓库 helm repo remove stableK8s 官方推出了 [Artifact Hub](https://artifacthub.io/)。Artifact Hub 不是仓库而是一个搜索引擎/目录索引网站。它不存文件只告诉你某个组件如 cert-manager的官方 Repo 网址是什么你需要自己把它添加helm repo add到本地。4、使用 Helm 部署应用4.1 直接以默认配置创建一个 Chart# 创建一个 Chart 模版其实就是项目或者应用 helm create my-webapp # 为什么叫 Chart海图/航海图 # 这源于 Kubernetes 生态系统深度使用的 航海/航海术主题命名法 # Kubernetes (k8s)源自希腊语 κυβερνήτης意思是 “舵手” 或 “船长” # Helm字面意思是 “舵轮” 或 “船舵”掌控船只航向的工具 # Docker字面意思是 “码头工人”负责搬运集装箱 # Container字面意思是 “集装箱” # 在这一整套航海隐喻下你的集群是一个在海里航行的庞大舰队Helm 是控制方向的船舵而 Chart航海图/海图 就是指导这艘船该去哪里、如何布置各个集装箱容器的路线图与设计蓝图。4.2 创建私有容器镜像仓库凭证# 在 Kubernetes 集群中创建一个类型为 docker-registry 的 Secret 资源存储访问私有容器镜像仓库的认证凭证用户名和密码/Token # docker-registrySecret 的类型专门用于镜像仓库身份验证 # huawei-swr-secret这个 Secret 自定义的名称后续在 YAML 中的 imagePullSecrets.name 引用的就是这个名字 # --docker-server镜像仓库的域名地址 # --docker-username登录镜像仓库的账号名称 # --docker-password登录镜像仓库的密码或者在云厂商控制台中生成的临时/长效镜像拉取密钥Token # --namespacedefault指定将这个 Secret 创建到哪一个命名空间下默认为 default # 注意Secret 是隔离在 Namespace命名空间中的如果你的 Pod 部署在 default 命名空间该 Secret 必须创建在 default kubectl create secret docker-registry huawei-swr-secret \ --docker-serverswr.cn-north-4.myhuaweicloud.com \ --docker-username你的用户名 \ --docker-password你的密码 \ --namespacedefault4.3 修改 values.yaml本地部署 values.yaml# 副本Pod 个数 replicaCount: 2 # 镜像这里提供了一个公共的镜像 it-tools 可以直接使用 image: # 镜像仓库地址 repository: swr.cn-east-5.myhuaweicloud.com/zhixu/it-tools pullPolicy: IfNotPresent # 镜像版本号 tag: 1.0 # 下载私有镜像的凭证如果是公开镜像设置不设置都无所谓如果是私有镜像必须设置 imagePullSecrets: - name: huawei-swr-secret nameOverride: fullnameOverride: serviceAccount: create: true automount: true annotations: {} name: podAnnotations: {} podLabels: {} podSecurityContext: {} securityContext: {} # 网络服务配置 # type: 服务以什么方式暴露有四种 # ① NodePort通过宿主机物理端口暴露本地或者临时调试使用 # ② ClusterIP默认模式集群内部服务应用首选。配合网关实现统一公网域名暴露。生产环境通常优先使用 ClusterIP Ingress/Gateway由统一入口负责域名和 HTTPS。 # ③ LoadBalancer配合云厂商的公网负载均衡器云上环境通常只为网关 配置 1~2 个不建议每个微服务都开。 # ④ ExternalName服务别名/外链映射用于访问集群外预设的第三方服务或 RDS # targetPort如果 Pod 内部程序监听的端口 恰好 和 Service 对外暴露的端口完全相同此时 targetPort 可以省略不写Kubernetes 默认会把 targetPort 设置为与 port 相同的值。 # 比如 Java/Spring Boot 或者 .NET Core 默认 8080、Node.js/Express 默认 3000、Python/Django 默认 8000时需要写 targetPort # 如果设置了targetPort那 service.yaml 中 targetPort 改成引用 values 中的变量: targetPort: {{ .Values.service.targetPort }} service: type: NodePort # 通过节点 IP NodePort 对外暴露服务适合测试或没有 Ingress/LB 的简单场景。 port: 80 # 服务对外的端口 targetPort: 80 # 流量转发到容器内部的端口 # 外网访问与证书 ingress: enabled: false className: annotations: {} # kubernetes.io/ingress.class: nginx # kubernetes.io/tls-acme: true hosts: - host: chart-example.local paths: - path: / pathType: ImplementationSpecific tls: [] # - secretName: chart-example-tls # hosts: # - chart-example.local httpRoute: enabled: false annotations: {} parentRefs: - name: gateway sectionName: http hostnames: - chart-example.local rules: - matches: - path: type: PathPrefix value: /headers # 扩展与高级配置 resources: # requests: K8s 调度时“预留”的资源保证 Pod 至少能拿到这么多 requests: cpu: 100m # 0.1 核 memory: 256Mi # 256 MB # limits: 强制上限超过这个值会被限制或杀掉 limits: cpu: 1000m # 1 核 (通常不建议给太低否则启动慢请求高峰会卡顿) memory: 512Mi # 512 MB # 健康检查 livenessProbe: # (存活检查): 如果 GET / 失败K8s 会直接重启容器 httpGet: path: / port: 80 readinessProbe: # (就绪检查): 如果 GET / 失败K8s 会把这个 Pod 从负载均衡中剔除停止发给它流量直到它恢复正常。 httpGet: path: / port: 80 autoscaling: enabled: false minReplicas: 1 maxReplicas: 100 targetCPUUtilizationPercentage: 80 volumes: [] volumeMounts: [] nodeSelector: {} tolerations: [] affinity: {}生产环境部署 values.yaml主要区别在 service 和 ingress# 副本Pod 个数 replicaCount: 2 # 镜像这里提供了一个公共的镜像 it-tools 可以直接使用 image: # 镜像仓库地址 repository: swr.cn-east-5.myhuaweicloud.com/zhixu/it-tools pullPolicy: IfNotPresent # 镜像版本号 tag: 1.0 # 下载私有镜像的凭证 imagePullSecrets: - name: huawei-swr-secret nameOverride: fullnameOverride: serviceAccount: create: true automount: true annotations: {} name: podAnnotations: {} podLabels: {} podSecurityContext: {} securityContext: {} # 网络服务配置 service: type: ClusterIP # 默认模式仅在集群内部可用 port: 80 # 服务对外的端口 # 外网访问与证书 # 需要配置 cert-manager 使用letsencrypt-prod 怎么来的下面会详细介绍 ingress: enabled: true className: traefik annotations: cert-manager.io/cluster-issuer: letsencrypt-prod # 证书签发指令 hosts: - host: ittools.ddzhixu.com paths: - path: / pathType: ImplementationSpecific tls: - secretName: ittools-prod-zhixu-tls hosts: - ittools.ddzhixu.com httpRoute: enabled: false annotations: {} parentRefs: - name: gateway sectionName: http hostnames: - chart-example.local rules: - matches: - path: type: PathPrefix value: /headers # 扩展与高级配置 resources: # requests: K8s 调度时“预留”的资源保证 Pod 至少能拿到这么多 requests: cpu: 100m # 0.1 核 memory: 256Mi # 256 MB # limits: 强制上限超过这个值会被限制或杀掉 limits: cpu: 1000m # 1 核 (通常不建议给太低否则启动慢请求高峰会卡顿) memory: 512Mi # 512 MB # 健康检查 # 在项目中实际提供这些接口 /health/live 和 /health/ready startupProbe: # 启动探针给慢启动应用充分的时间成功后才交棒给下面两个探针 httpGet: path: /health/live port: 80 failureThreshold: 30 periodSeconds: 5 livenessProbe: # 存活探针轻量只检查进程 httpGet: path: /health/live port: 80 periodSeconds: 10 timeoutSeconds: 2 failureThreshold: 3 readinessProbe: # 就绪探针检查依赖决定是否接收流量 httpGet: path: /health/ready port: 80 periodSeconds: 5 timeoutSeconds: 2 failureThreshold: 3 autoscaling: enabled: false minReplicas: 1 maxReplicas: 100 targetCPUUtilizationPercentage: 80 volumes: [] volumeMounts: [] nodeSelector: {} tolerations: [] # 高可用打散策略避免两个副本分到同一个节点 # 软亲和性单节点也可以设置 affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 100 podAffinityTerm: labelSelector: matchExpressions: - key: app.kubernetes.io/name operator: In values: - it-tools topologyKey: kubernetes.io/hostnameAffinity tips# 不要配置硬性的“反亲和性Anti-Affinity” 如果你此前在 YAML 中配置了 podAntiAffinity强制要求同一个 Pod 的多个副本不能放在同一台节点那么 # 当你设置 replicaCount: 2 时第 1 个副本会顺利落到 Agent 1 上。 # 第 2 个副本因为“不能与第 1 个副本同节点”且 Master 节点有污点无法投递就会直接变成 Pending 挂起状态 # 解决办法只有 1 台 Agent 时不要加反亲和性或者配置为 preferredDuringScheduling...弱亲和能分散就分散分散不了就挤在一块允许 2 个副本同时挤在这一台 Agent 上运行。4.4 安装项目# 把应用部署到了 Kubernetes 的 zhixu 命名空间中并且利用 NodePort 成功拿到访问地址 # -n 指定命名空间--create-namespace 命名空间不存在会自动建 # ittools第一个本次发布的 Release 名称相当于实例名 # ./ittools第二个你本地的 Chart 文件夹路径 # -n zhixu--namespace指定部署到名为 zhixu 的命名空间中 # --create-namespace自动检查如果 zhixu 这个命名空间不存在就先帮创建它 [rootmaster ~]# helm upgrade --install ittools ./ittools -n zhixu --create-namespace Release ittools does not exist. Installing it now. NAME: ittools LAST DEPLOYED: Thu Aug 13 16:59:32 2026 NAMESPACE: zhixu STATUS: deployed REVISION: 1 NOTES: 1. Get the application URL by running these commands: export NODE_PORT$(kubectl get --namespace zhixu -o jsonpath{.spec.ports[0].nodePort} services ittools) export NODE_IP$(kubectl get nodes --namespace zhixu -o jsonpath{.items[0].status.addresses[0].address}) echo http://$NODE_IP:$NODE_PORT [rootmaster ~]# export NODE_PORT$(kubectl get --namespace zhixu -o jsonpath{.spec.ports[0].nodePort} services ittools) [rootmaster ~]# export NODE_IP$(kubectl get nodes --namespace zhixu -o jsonpath{.items[0].status.addresses[0].address}) [rootmaster ~]# echo http://$NODE_IP:$NODE_PORT http://192.168.31.101:32061 # 上面是执行了三条命令之后获取的 ip 端口号 # 获取 zhixu 命名空间下 NodePort 模式下的端口号 32061 [rootmaster ~]# kubectl get svc -n zhixu NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE ittools NodePort 10.43.177.71 none 80:32061/TCP 16h # 获取 ip192.168.31.101 kubectl get nodes -o wide # 查看 release 分布的节点 kubectl get pods -n zhixu -o wide4.5 常用命令# 1. 创建 Chart 模版其实就是项目或者应用 helm create my-webapp # 2. 语法静态检查检查 Chart YAML 语法是否符合标准 helm lint ./my-webapp # 3. 本地预览生成的 K8s YAML调试用 helm template my-app ./my-webapp -f values.yaml # 4. 安装/升级应用推荐带上 --install 参数自动兼容初次部署与续更新 # 第一个参数 my-webapp 是 Release 名称第二个参数 ./webmy-app 是 Chart 目录路径 helm upgrade --install my-webapp ./my-webapp -f values.yaml -n zhixu --create-namespace # 如果只有一份 values.yaml下面和上面命令执行结果是一样的 helm upgrade --install my-webapp ./my-webapp -n zhixu --create-namespace # 上面的 upgrade 和 install 拆开也可以用 # 安装项目 helm install my-webapp ./my-webapp -n zhixu --create-namespace # 当你修改了 values.yaml 或想要更新应用版本时使用 upgrade 命令 helm upgrade my-webapp ./my-webapp -n default # 实际开发中通常用 -f values.yaml 区分开发/生产环境比如 # values-dev.yaml开发环境 (Development)本地或开发联调环境资源给得少方便调试 # values-test.yaml测试环境 (Testing / QA)QA 团队自动化/功能测试环境 # values-staging.yaml预发/灰度环境 (Staging)生产前的最终验证环境连接生产只读库或镜像生产数据 # values-prod.yaml生产环境 (Production)线上正式环境高可用、高资源、严格证书与安全策略 # 5. 查看版本与状态 helm list -n zhixu # 查看当前 Namespace 下的 Release 列表 helm status my-app -n zhixu # 查看特定 Release 的详细部署信息和状态 helm history my-app -n zhixu # 查看历史版本记录 helm get values my-app -n zhixu # 查看特定 Release 当前生效的所有配置参数 # 6. 回滚与卸载 helm rollback my-app 1 -n zhixu # 回滚到指定的 Revision (如 1) helm uninstall my-app -n zhixu # 卸载并清除 Release 包含的所有 Kubernetes 资源Deployment、Service、Secret 等五、生产环境中域名 SSL证书的处理方案本地部署不需要看这一部分内容部署到云服务器上的时候需要关注1、cert-manager推荐使用 Helm 进行安装官方最推荐的方式易于后续升级和管理上面已经添加并更新 Helm 仓库https://charts.jetstack.io# 1、执行安装命令 helm upgrade --install cert-manager jetstack/cert-manager \ --version 1.19.6 \ --namespace cert-manager \ --create-namespace \ --set installCRDstrue # 2、验证安装状态 # 安装完成后需确保 3 个 Pod 全部处于 Running 状态 kubectl get pods --namespace cert-manager # 你应该看到 # cert-manager-xxx: 核心控制器。 # cert-manager-cainjector-xxx: 负责注入 CA 证书。 # cert-manager-webhook-xxx: 负责校验配置。 以及安装完成后会退出的startupapicheck2、创建证书签发器ClusterIssuer证书签发器集群中可以创建多个下面是生产环境签发器新建 cluster-issuer.yaml 文件内容如下apiVersion: cert-manager.io/v1 kind: ClusterIssuer metadata: name: letsencrypt-prod spec: acme: # Lets Encrypt 官方 ACME 生产环境 API server: https://acme-v02.api.letsencrypt.org/directory # ⚠️ 务必替换为你自己的真实邮箱证书即将到期但自动续期失败时Lets Encrypt 会发邮件提醒 email: your-emailexample.com # 保存 ACME 账户私钥的 Secret 名称 privateKeySecretRef: name: letsencrypt-prod-account-key solvers: - http01: ingress: class: traefik # 如果你的网关是 NGINX写 nginxK3s 默认写 traefik测试环境签发器调试时使用防止触发公网频率限制新建 cluster-staging-issuer.yaml 文件内容如下apiVersion: cert-manager.io/v1 kind: ClusterIssuer metadata: name: letsencrypt-staging spec: acme: server: https://acme-staging-v02.api.letsencrypt.org/directory email: your-emailexample.com # 替换为真实邮箱 privateKeySecretRef: name: letsencrypt-staging-account-key solvers: - http01: ingress: class: traefik3、证书签发器配置到集群# 应用配置 kubectl apply -f cluster-issuer.yaml # 检查 ClusterIssuer 状态 # 查看名为 letsencrypt-prod 的这一个 ClusterIssuer 资源状态 kubectl get clusterissuer letsencrypt-prod # 或者查看当前集群中已创建的所有 ClusterIssuer 资源状态 kubectl get clusterissuer # 正常输出示例 NAME READY AGE letsencrypt-prod True 38h # 如果 READY 为 False 或没有显示使用 describe 命令查看具体的事件Events和状态条件Conditions kubectl describe clusterissuer letsencrypt-prod4、HTTPS 证书处理方案方案 A在 Ingress 中启用 SSL 自动签发和续期最推荐、全自动签发器配置好后使用者完全不需要写繁琐的证书申请命令只需要在应用的 Ingress 配置里加上一行 annotation 规则cert-manager 就会全自动感知并完成证书申请、域名验证和 Secret 创建。以上面的 it-tools 应用配置为例在 values.yaml 中配置# 域名 ittools.ddzhixu.com 必须解析到正确的公网 IP ingress: enabled: true className: traefik annotations: # 核心步骤通过注解绑定刚才创建的 ClusterIssuer cert-manager.io/cluster-issuer: letsencrypt-prod hosts: - host: ittools.ddzhixu.com paths: - path: / pathType: ImplementationSpecific tls: - secretName: ittools-prod-zhixu-tls # cert-manager 自动创建并存储证书的 Secret 名称 hosts: - ittools.ddzhixu.com让配置生效# 部署/升级该 Helm Chart 后cert-manager 会自动触发签发流程。 helm upgrade --install ittools ./ittools -n zhixu --create-namespace # 查看与排查证书状态 # 如果签发顺利READY 列会变为 True kubectl get certificate -n zhixu # 如果 READY 一直是 False可以通过以下命令诊断排查 # 1. 查看证书详细描述通常包含了失败的原因 kubectl describe certificate certificate-name -n zhixu # 2. 查看 cert-manager 订单和挑战状态 kubectl get order -n zhixu kubectl get challenge -n zhixu方案 B手动绑定已有的商业证书/免费证书如果你已经在云厂商如阿里云/腾讯云申请到了域名的 SSL 证书文件tls.crt 和 tls.key# 1、手动在命名空间 zhixu 下创建 typecraft-tls-secret kubectl create secret tls typecraft-tls-secret \ --certpath/to/tls.crt \ --keypath/to/tls.key \ -n zhixu # 2、发布应用只要 Secret 名字typecraft-tls-secret与 values.yaml 中的 tls[0].secretName 保持一致Traefik 就会自动加载该证书。六、其它1、K3s 主要端口端口协议源地址 (Source)目标 (Destination)用途与作用安全组放行建议以阿里云/腾讯云为例6443TCPAgent 节点 IP(及管理员运维 IP)Server (Master)K3s API Server 通信切勿对 0.0.0.0/0 全网开放仅放行 Agent 节点内网 IP如 192.168.31.101/32及公司堡垒机/运维 IP。8472UDP集群所有节点内网 IP(Node ↔ Node)所有节点Flannel VXLAN 跨节点容器网络叠加包传输内网互通即可。仅在安全组中设置集群节点内网 IP 互通严禁对公网暴露 UDP。10250TCP集群所有节点内网 IP(Server ↔ Agent)所有节点kubelet API用于 kubectl logs、exec 及 Metrics-Server 收集指标仅限集群内网节点互通。如果对外暴露黑客可利用 kubelet 接口未授权访问执行命令。80TCPInternet (0.0.0.0/0)所有节点 / IngressHTTP 业务流量入口及 ACME (cert-manager) HTTP-01 证书签发校验公网全网开放 (0.0.0.0/0)。cert-manager 自动签发 Let’s Encrypt 证书必须依赖公网 80 端口的回调。443TCPInternet (0.0.0.0/0)所有节点 / IngressHTTPS 加密业务流量入口公网全网开放 (0.0.0.0/0)。30000-32767TCP按需放行 / 内网放行所有节点K8s NodePort 默认端口范围按需开放。生产环境如果使用了 Ingress (80/443)建议不要向公网全量放行整个 30000-32767 网段仅在需要裸露特定 Service 时针对性放行某个端口如 32061。2、常用诊断命令# 节点 kubectl get nodes -o wide # 所有 Pod kubectl get pods -A -o wide # 服务 kubectl get svc -A # Ingress kubectl get ingress -A # Deployment kubectl get deployment -A # 事件 kubectl get events -A --sort-by.lastTimestamp # Pod 日志 kubectl logs pod -n namespace # Pod 描述 kubectl describe pod pod -n namespace # 常见 ImagePullBackOff重点看Events如果ImagePullBackOff # 检查镜像地址 / Registry / 网络 / DNS / 认证 / registries.yaml # 可以直接测试sudo crictl pull image # 常见 Pending # 重点看Insufficient cpu / Insufficient memory / node affinity / pod anti-affinity / taint / toleration / PVC # 节点资源 kubectl top nodes # Pod 资源 kubectl top pods -A3、K3s 服务日志# Server sudo journalctl -u k3s -n 200 --no-pager # 实时 sudo journalctl -u k3s -f # Agent sudo journalctl -u k3s-agent -n 200 --no-pager # 实时 sudo journalctl -u k3s-agent -f4、磁盘问题# 检查 df -h # 检查 inode df -i # 检查 K3s sudo du -sh /var/lib/rancher/k3s # 检查容器数据 sudo du -sh /var/lib/rancher/k3s/agent # 如果磁盘不断增长重点检查 容器日志 镜像 Pod 临时文件 应用日志 数据库数据5、常见证书问题# 执行 kubectl get certificate -A # 然后 kubectl describe certificate name -n namespace # 再 kubectl get order -n namespace kubectl get challenge -n namespace 重点排查 DNS 80/TCP IngressClass Traefik ClusterIssuer 域名 公网 IP6、环境检查# 查看内核版本 uname -r # 查看系统架构 uname -m # 查看 hostname hostnamectl # 查看 cgroup stat -fc %T /sys/fs/cgroup # 查看 IP 转发 sysctl net.ipv4.ip_forward # 查看 bridge netfilter sysctl net.bridge.bridge-nf-call-iptables sysctl net.bridge.bridge-nf-call-ip6tables # 查看模块 lsmod | grep -E overlay|br_netfilter # 查看磁盘 df -h # 查看内存 free -h # 查看防火墙 sudo systemctl status firewalld 2/dev/null sudo systemctl status ufw 2/dev/null # 查看监听端口 sudo ss -lntup # 如果虚拟机设置了快照恢复快照出现时间不一致问题 systemctl restart chronyd chronyc makestep # 检查时间 date7、部署完成后的最终检查# 建议按照下面顺序检查。 # 1. 节点 kubectl get nodes -o wide # 必须 Ready # 2. 系统 Pod kubectl get pods -A 不能长期 Pending CrashLoopBackOff ImagePullBackOff Error # 3. Storage kubectl get storageclass # 4. Ingress kubectl get ingress -A # 5. Certificate kubectl get certificate -A # 应该 READYTrue # 6. Service kubectl get svc -A # 7. 应用 kubectl get deployment -A kubectl get pods -A -o wide # 8. HTTPS curl -I https://ittools.example.com

相关新闻