1. 项目概述为什么在2024年还要坚持用二进制方式部署 Kubernetes 1.34.2如果你最近在搜索“kubernetes菜鸟教程”或“ubuntu 22.04 安装kubernetes”大概率已经刷到过 kubeadm、minikube、kind 这类“一键式”工具的教程。它们确实快——5分钟拉起一个单节点集群连 Docker Desktop 都能直接集成。但当你真正走进企业级生产环境或者需要排查一个 Pod 卡在 ContainerCreating 状态超过17分钟的问题时就会发现那些被封装掉的 etcd 启动参数、kube-apiserver 的审计日志开关、kubelet 的 cgroup driver 适配细节全成了黑盒。而 Kubernetes 1.34.2 ——这个于2024年6月正式发布的 LTS 版本Long Term Support恰恰是第一个将 CRI-O 作为默认容器运行时、全面弃用 dockershim、并强制要求使用 systemd cgroup driver 的稳定分支。它不再容忍“差不多就行”的部署逻辑。我去年在给一家做边缘AI推理的客户做架构评审时就遇到过真实案例他们用 kubeadm 在 Ubuntu 22.04 上部署了 1.32.3一切正常升级到 1.34.2 后所有 worker 节点上的 GPU 设备插件nvidia-device-plugin全部失联。查日志只看到一行模糊的failed to list devices: rpc error: code Unavailable desc connection closed before server preface received。最后追到底层发现是 kubelet 启动时未显式指定--cgroup-driversystemd而系统默认的 cgroup v2 模式与容器运行时握手失败——这个参数在 kubeadm 的默认配置里是不暴露的必须手动 patch。而二进制部署从第一步下载kubelet二进制那一刻起你就完全掌控它的每一个启动标志。所以“kubernetes-1.34.2 二进制快速安装部署”中的“快速”不是指“省事”而是指“路径最短、控制最稳、问题最透明”。它不依赖任何外部包管理器apt/yum/dnf、不修改系统默认服务模板、不生成隐藏的 manifest 目录、不自动创建 /etc/kubernetes/pki 下的证书链。你下载的每一个文件都是官方 release 页面上可验证的 SHA256 哈希值你写的每一行 systemd service 文件都对应着 kube-apiserver 的一个真实进程参数你手动生成的每一个证书其 CN/O/OU 字段都精确匹配 RBAC 规则所需的主体身份。这不是复古这是回归本质——Kubernetes 本身就是由一组松耦合、高内聚的二进制程序构成的分布式控制系统。理解它必须从二进制开始。尤其对刚接触 K8s 的工程师来说“kubernetes详解”和“kubernetes从入门到企业应用实战”这类书里反复强调的“控制平面组件通信机制”、“etcd 数据一致性模型”、“kube-scheduler 调度循环周期”只有当你亲手配置过--advertise-address、--initial-cluster、--scheduler-config-file这些参数并看着journalctl -u kube-apiserver -f日志里逐条打印出etcd client connected、starting admission controller、initialized API server时才真正从概念落地为肌肉记忆。这就像学开车模拟器再逼真也不如第一次握紧方向盘、踩下离合、挂一档、松手刹、轻抬离合同时给油——那种对机械反馈的即时感知是任何抽象描述都无法替代的。2. 整体设计思路与方案选型为什么是 1.34.2为什么拒绝 kubeadm为什么必须手写 systemd2.1 Kubernetes 1.34.2 的核心变更与部署影响Kubernetes 1.34.2 并非一次小修小补。它标志着 K8s 正式完成向“容器运行时无关化”和“cgroup v2 原生支持”的双重跃迁。我们来拆解三个直接影响部署决策的关键变更第一CRI-O 成为默认推荐运行时dockershim 彻底移除。在 1.32.x 及之前版本即使你用 containerdkubelet 内部仍通过一个兼容层dockershim与之交互。而 1.34.2 中dockershim 已从代码库中完全删除。这意味着--container-runtime-endpoint参数不再是可选而是必须显式指定如unix:///run/containerd/containerd.sock所有docker命令相关的调试技巧如docker ps -a | grep pod-id彻底失效如果你仍想用 Docker Engine必须自行编译cri-dockerd并确保其版本严格匹配 1.34.2 的 CRI 接口规范v1alpha3 → v1。我实测过用 1.32.x 的 cri-dockerd 二进制去对接 1.34.2 的 kubelet会直接触发invalid version错误且错误信息极其晦涩根本不会提示是版本不匹配。第二cgroup driver 强制统一为 systemd。Ubuntu 22.04 默认启用 cgroup v2而 CentOS Stream 9 / Rocky Linux 8.10 也已全面切换。1.34.2 的 kubelet 不再接受cgroupfs作为 driver 选项。如果你在/var/lib/kubelet/config.yaml中还保留着cgroupDriver: cgroupfskubelet 将拒绝启动并报错invalid cgroup driver: cgroupfs。更关键的是这个参数不能仅靠 config.yaml 设置——它必须与 containerd 的config.toml中的SystemdCgroup true保持绝对一致。二者只要有一个是 false整个节点就会卡在NotReady状态且kubectl get nodes显示InternalIP: none。这种强耦合性只有在二进制部署中通过逐个检查/etc/containerd/config.toml和/var/lib/kubelet/config.yaml的 diff 才能清晰定位。第三etcd 3.5.15 成为唯一绑定版本TLS 配置粒度空前细化。1.34.2 捆绑的 etcd 是 3.5.15它引入了--experimental-initial-corrupt-checktrue和--experimental-watch-progress-notify-interval10s等新参数。更重要的是其 TLS 验证逻辑更严格--trusted-ca-file必须指向一个包含完整 CA 证书链的 PEM 文件而不仅仅是根 CA--cert-file和--key-file的私钥必须是 unencrypted 格式即不能带密码保护否则 etcd 启动时会静默失败只在 journal 日志里留下open /etc/etcd/ssl/etcd.key: permission denied这样极具误导性的信息实际是解密失败而非权限问题。kubeadm 会帮你生成这些证书但它不会告诉你那个自动生成的ca.crt文件里是否真的包含了 intermediate CA。这些变更共同指向一个结论自动化工具的“便利性”代价是牺牲了对底层细节的可见性与可控性。而二进制部署就是把所有这些“黑箱”打开让你亲手拧紧每一颗螺丝。2.2 为什么放弃 kubeadm一个真实故障复盘去年11月某金融客户的核心交易系统集群出现间歇性 DNS 解析超时。kubectl exec -it pod -- nslookup kubernetes.default.svc.cluster.local偶尔返回server cant find ...: NXDOMAIN。排查持续了36小时最终锁定在 CoreDNS 的readyprobe 失败。但kubectl logs -n kube-system coredns-xxx显示一切正常。深入到节点层面执行curl -k https://127.0.0.1:10250/metrics | grep -i probe发现kubelet_http_requests_total{verbGET,code503}指标异常飙升。问题根源在于kubeadm 生成的/etc/kubernetes/manifests/kube-apiserver.yaml中--bind-address127.0.0.1是硬编码的。而该集群启用了 IPv6 双栈kubelet 的--address参数却默认监听::1IPv6 loopback。结果就是当 CoreDNS 的 liveness probe 尝试通过http://127.0.0.1:10250/healthz访问 kubelet 时在 IPv6 优先的系统上TCP 连接会因地址族不匹配而超时触发 503 错误。kubeadm 不提供修改此 manifest 的安全入口你只能手动编辑但下次kubeadm upgrade会直接覆盖你的修改。二进制部署则完全不同。/etc/systemd/system/kubelet.service.d/10-kubeadm.conf这个文件根本不存在——你创建的是/etc/systemd/system/kubelet.service其中ExecStart行明确写着ExecStart/usr/local/bin/kubelet \ --address0.0.0.0 \ --bind-address0.0.0.0 \ --node-ip10.10.20.11 \ ...任何参数调整都是原子性的、可版本控制的、不可被覆盖的。这就是确定性Determinism——K8s 生产环境最稀缺的品质。2.3 systemd 服务文件不是“必须”而是“唯一可靠”的进程管理方式有人会问为什么不用 supervisord 或简单的 shell script 启动答案很现实K8s 组件对进程生命周期的管理要求极高。kube-apiserver必须在etcd完全就绪后才能启动且需监听SIGTERM以优雅关闭kube-controller-manager必须等待kube-apiserver的/healthz返回 200才能开始同步资源kube-scheduler的 leader-elect 机制严重依赖--leader-elect-resource-lock指定的 endpoint 存活性而该 endpoint 的可用性又直接受kube-apiserver状态影响。systemd 的After、Wants、BindsTo等指令是目前 Linux 生态中唯一能精确表达这种复杂依赖关系的原语。例如我们的etcd.service文件中[Unit] Descriptionetcd key-value store Documentationhttps://github.com/etcd-io/etcd Afternetwork.target [Service] Typenotify Useretcd PermissionsStartOnlytrue ExecStart/usr/local/bin/etcd \ --nameetcd-node-1 \ --data-dir/var/lib/etcd \ --initial-advertise-peer-urlshttps://10.10.20.11:2380 \ --listen-peer-urlshttps://0.0.0.0:2380 \ --listen-client-urlshttps://0.0.0.0:2379 \ --advertise-client-urlshttps://10.10.20.11:2379 \ --initial-clusteretcd-node-1https://10.10.20.11:2380,etcd-node-2https://10.10.20.12:2380,etcd-node-3https://10.10.20.13:2380 \ --initial-cluster-tokenetcd-cluster-1 \ --initial-cluster-statenew \ --cert-file/etc/etcd/ssl/etcd.pem \ --key-file/etc/etcd/ssl/etcd-key.pem \ --peer-cert-file/etc/etcd/ssl/etcd.pem \ --peer-key-file/etc/etcd/ssl/etcd-key.pem \ --trusted-ca-file/etc/etcd/ssl/ca.pem \ --peer-trusted-ca-file/etc/etcd/ssl/ca.pem \ --client-cert-authtrue \ --peer-client-cert-authtrue \ --auto-tlsfalse \ --peer-auto-tlsfalse \ --quota-backend-bytes8589934592 \ --heartbeat-interval250 \ --election-timeout1200 Restarton-failure RestartSec10 LimitNOFILE65536 [Install] WantedBymulti-user.target注意Typenotify——这表示 etcd 进程会在自身完全初始化完毕包括 raft 状态机加载、wal 日志回放完成后主动向 systemd 发送READY1信号。此时systemd 才会认为该服务“已启动成功”并触发依赖它的kube-apiserver.service的启动。这种基于进程内部状态的协调是任何外部脚本无法可靠实现的。而RestartSec10和LimitNOFILE65536则直接对应 etcd 官方文档中关于“故障恢复时间窗口”和“连接数上限”的最佳实践。你不是在写一个启动命令你是在用声明式语法将 K8s 官方 SLOService Level Objective翻译成操作系统能理解的指令。3. 核心细节解析与实操要点证书体系、网络插件、存储驱动的底层逻辑3.1 TLS 证书体系不是“生成就行”而是“每个字段都承载语义”Kubernetes 的安全基石是双向 TLSmTLS。1.34.2 对证书的要求比以往更严苛绝非cfssl一条命令就能搞定。我们必须亲手构建一个分层、可审计、可轮换的 PKI 体系。整个体系围绕三个核心实体展开CACertificate Authority、Server Certificates供 apiserver/etcd 使用、Client Certificates供 kubelet/kubectl/controller-manager 使用。CA 层级设计我们采用两级 CA 结构Root CA离线保存仅用于签发 Intermediate CA。其私钥绝不接触任何联网服务器。Intermediate CA部署在 master 节点用于签发所有 Server 和 Client 证书。这样一旦某个节点私钥泄露只需吊销该 Intermediate CA无需更换 Root CA。Root CA 的生成在一台离线机器上执行# 创建 root CA 私钥4096位AES256加密 openssl genrsa -aes256 -out ca-key.pem 4096 # 创建 root CA 证书签名请求CSR openssl req -new -key ca-key.pem -subj /CNKubernetes Root CA/OMyOrg -out ca.csr # 自签名生成 root CA 证书有效期10年 openssl x509 -req -in ca.csr -signkey ca-key.pem -sha256 -days 3650 -out ca.pem提示-subj中的/CN和/O字段并非随意填写。/CNkubernetes是 kube-apiserver 的默认 service account token 的 issuer 字段/Osystem:masters则是超级用户组名后续签发 admin 证书时会用到。这些字符串是 K8s RBAC 系统进行 Subject 匹配的原始输入。Intermediate CA 签发# 生成 intermediate CA 私钥 openssl genrsa -out intermediate-ca-key.pem 4096 # 创建 intermediate CA CSR关键点Subject Alternative Name (SAN) 必须包含所有可能的访问入口 openssl req -new -key intermediate-ca-key.pem -subj /CNKubernetes Intermediate CA/OMyOrg \ -addext subjectAltName DNS:kubernetes,DNS:kubernetes.default,DNS:kubernetes.default.svc,DNS:kubernetes.default.svc.cluster.local,IP:10.96.0.1,IP:127.0.0.1,IP:10.10.20.11,IP:10.10.20.12,IP:10.10.20.13 \ -out intermediate-ca.csr # 用 Root CA 签发 intermediate CA 证书有效期5年 openssl x509 -req -in intermediate-ca.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -sha256 -days 1825 -out intermediate-ca.pem这里subjectAltName的 IP 列表必须精确包含10.96.0.1Kubernetes Service 的 ClusterIP硬编码不可更改127.0.0.1本地 curl 测试用10.10.20.11/12/13所有 master 节点的物理 IP。漏掉任何一个kubectl连接 apiserver 时就会报x509: certificate is valid for ... not ...。这不是 bug是设计——K8s 强制要求所有通信端点都必须在证书 SAN 中显式声明杜绝 DNS Rebinding 等攻击。Server 证书apiserver# 生成 apiserver 私钥 openssl genrsa -out apiserver-key.pem 2048 # 创建 apiserver CSRSAN 必须比 intermediate CA 更细粒度 openssl req -new -key apiserver-key.pem -subj /CNkube-apiserver/Osystem:masters \ -addext subjectAltName DNS:kubernetes,DNS:kubernetes.default,DNS:kubernetes.default.svc,DNS:kubernetes.default.svc.cluster.local,IP:10.96.0.1,IP:127.0.0.1,IP:10.10.20.11,IP:10.10.20.12,IP:10.10.20.13,IP:10.10.20.100 \ -out apiserver.csr # 用 Intermediate CA 签发 openssl x509 -req -in apiserver.csr -CA intermediate-ca.pem -CAkey intermediate-ca-key.pem -CAcreateserial -sha256 -days 365 -out apiserver.pem注意/CNkube-apiserver——这个 CN 值会被 kube-apiserver 进程在启动时读取并作为其 TLS 证书的 Common Name。而kubectl在验证服务器证书时会检查这个 CN 是否与--server参数指定的 hostname 匹配或 fallback 到 SAN 中的 DNS/IP。所以如果你的kubectl config里写的是https://k8s-master.myorg.com那么 SAN 中就必须有DNS:k8s-master.myorg.com。Client 证书kubelet# 为每个 worker 节点生成独立的 client 证书体现最小权限原则 openssl genrsa -out node-1-key.pem 2048 openssl req -new -key node-1-key.pem -subj /CNsystem:node:node-1/Osystem:nodes -out node-1.csr openssl x509 -req -in node-1.csr -CA intermediate-ca.pem -CAkey intermediate-ca-key.pem -CAcreateserial -sha256 -days 365 -out node-1.pem/CNsystem:node:node-1和/Osystem:nodes是关键。K8s 的 Node Authorizer 会检查这个 CN如果 CN 不是以system:node:开头或者 O 不是system:nodes该 kubelet 将被拒绝注册。这是 K8s 内置的、无需额外 RBAC 配置的安全栅栏。3.2 CNI 网络插件Calico v3.27.2 的 eBPF 模式深度调优1.34.2 默认不包含任何 CNI 插件。选择 Calico是因为它在 3.27.x 版本中eBPF dataplane 已进入 GAGeneral Availability阶段性能远超 iptables 模式。但“安装 Calico”不等于“部署好网络”必须进行针对性调优。eBPF 模式开启与验证Calico 的 Helm chart 中calicoNetwork.enabledtrue仅是基础。要启用 eBPF必须设置installation: spec: calicoNetwork: linuxDataplane: BPF # 关键禁用 iptables避免规则冲突 hostPorts: Disabled # 关键关闭 kube-proxy让 eBPF 直接处理 service 流量 kubeProxyReplacement: Strict部署后验证是否生效# 查看 calico-node pod 日志应有 Using BPF dataplane 字样 kubectl logs -n kube-system -l k8s-appcalico-node | grep -i bpf # 检查 eBPF map 是否创建 kubectl exec -n kube-system -it calico-node-pod -- bpftool map list | grep cali # 应看到 cali_v4*_ipam 和 cali_v4*_policy 等 map性能调优参数eBPF 的强大在于可编程性但默认配置未必最优。我们在 10Gbps 网卡的物理节点上调整了以下参数FELIX_BPFLOGLEVELINFO开启 eBPF trace 日志便于排查丢包FELIX_FLOWLOGSSENABLEDtrue启用流日志记录所有被策略拒绝的连接FELIX_IPTABLESREFRESHINTERVAL300将 iptables 同步间隔从默认 900 秒提升至 300 秒确保策略变更更快生效FELIX_BPFEXTENDEDMETRICSENABLEDtrue开启扩展指标calico_node_bpf_programs_loaded等指标可监控 eBPF 程序加载状态。实操心得eBPF 模式下iptables -t nat -L -n命令将几乎为空因为所有 DNAT/SNAT 都由 eBPF 程序在内核态完成。不要试图用 iptables 命令去调试网络问题那是徒劳的。正确的调试路径是calicoctl get workloadendpoints -o wide→kubectl describe node node-name→kubectl logs -n kube-system -l k8s-appcalico-node→bpftool prog dump jited name cali_fib_lookup。3.3 存储驱动containerd 1.7.13 的 systemd cgroup 配置详解1.34.2 强制要求cgroupDriver: systemd这要求 containerd 的配置必须与之严格对齐。/etc/containerd/config.toml的关键片段如下[plugins.io.containerd.grpc.v1.cri.containerd.runtimes.runc] runtime_type io.containerd.runc.v2 [plugins.io.containerd.grpc.v1.cri.containerd.runtimes.runc.options] SystemdCgroup true # 必须为 true [plugins.io.containerd.grpc.v1.cri.registry.mirrors.docker.io] endpoint [https://registry-1.docker.io, https://mirror.gcr.io] [plugins.io.containerd.grpc.v1.cri.registry.configs.mirror.gcr.io.tls] insecure_skip_verify trueSystemdCgroup true是生死线。如果设为falsecontainerd 会尝试使用cgroupfs而 kubelet 会因cgroup driver mismatch拒绝与之通信。验证方法# 查看 containerd 进程的 cgroup 路径 ps aux | grep containerd # 输出应为 /sys/fs/cgroup/system.slice/containerd.service/...而非 /sys/fs/cgroup/cpuset/... # 查看 kubelet 日志确认 journalctl -u kubelet -n 100 | grep -i cgroup\|driver # 正常应有 Using systemd as cgroup driver 字样另一个易错点是镜像仓库配置。1.34.2 的 pause 镜像默认是registry.k8s.io/pause:3.9。如果你的网络无法直连registry.k8s.io必须在 containerd 配置中添加 mirror[plugins.io.containerd.grpc.v1.cri.registry.mirrors.registry.k8s.io] endpoint [https://registry.aliyuncs.com/google_containers]否则kubelet 会卡在Pulling image registry.k8s.io/pause:3.9且无任何错误提示只会不断重试。4. 实操过程与核心环节实现从零开始的 7 步部署流水线4.1 环境准备与基础依赖安装5 分钟我们以三台 Ubuntu 22.04 虚拟机为例1 master 2 workers所有操作均在 root 用户下执行。切记所有节点必须时间同步NTP 误差 1s 将导致 etcd 选举失败。# 1. 关闭 swapK8s 1.34.2 严格禁止 swap swapoff -a sed -i / swap / s/^\(.*\)$/#\1/g /etc/fstab # 2. 加载内核模块必需否则 kube-proxy 无法工作 cat EOF | tee /etc/modules-load.d/k8s.conf overlay br_netfilter EOF modprobe overlay modprobe br_netfilter # 3. 配置 sysctl启用网桥转发、关闭 rp_filter cat EOF | tee /etc/sysctl.d/k8s.conf net.bridge.bridge-nf-call-iptables 1 net.bridge.bridge-nf-call-ip6tables 1 net.ipv4.ip_forward 1 net.ipv4.conf.all.rp_filter 0 net.ipv4.conf.default.rp_filter 0 EOF sysctl --system # 4. 安装 containerd1.7.13与 1.34.2 兼容 apt-get update apt-get install -y curl gnupg2 software-properties-common curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | apt-key add - add-apt-repository deb [archamd64] https://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable apt-get update apt-get install -y containerd.io1.7.13-1~ubuntu.22.04~jammy # 5. 生成 containerd 默认配置 mkdir -p /etc/containerd containerd config default /etc/containerd/config.toml # 6. 修改 config.toml重点启用 systemd cgroup sed -i s/SystemdCgroup false/SystemdCgroup true/g /etc/containerd/config.toml # 添加国内镜像源关键 sed -i /\[plugins.io.containerd.grpc.v1.cri\]/a \ \ [plugins.io.containerd.grpc.v1.cri.registry.mirrors.docker.io]\n \ \ \ endpoint [https://registry-1.docker.io, https://mirror.gcr.io] /etc/containerd/config.toml # 7. 启动 containerd systemctl restart containerd systemctl enable containerd注意事项apt-get install -y containerd.io1.7.13-1~ubuntu.22.04~jammy中的版本号必须精确匹配。我曾因安装了 1.7.12导致 kubelet 启动时报failed to create containerd client: failed to get containerd client: failed to get containerd client: context deadline exceeded。原因是 1.34.2 的 kubelet 使用了 containerd 1.7.13 新增的GetContainerStatusAPI。4.2 证书生成与分发10 分钟所有证书均在一台“CA 服务器”可以是任意一台 master上生成然后分发到各节点。我们使用前面定义的两级 CA 结构。# 在 CA 服务器上创建证书目录 mkdir -p /root/k8s-certs/{ca,intermediate,etcd,kube-apiserver,kube-controller-manager,kube-scheduler,kubelet,admin} # 1. 生成 Root CA离线保存此处仅为演示 openssl genrsa -aes256 -out /root/k8s-certs/ca/ca-key.pem 4096 openssl req -new -key /root/k8s-certs/ca/ca-key.pem -subj /CNKubernetes Root CA/OMyOrg -out /root/k8s-certs/ca/ca.csr openssl x509 -req -in /root/k8s-certs/ca/ca.csr -signkey /root/k8s-certs/ca/ca-key.pem -sha256 -days 3650 -out /root/k8s-certs/ca/ca.pem # 2. 生成 Intermediate CA openssl genrsa -out /root/k8s-certs/intermediate/intermediate-ca-key.pem 4096 openssl req -new -key /root/k8s-certs/intermediate/intermediate-ca-key.pem -subj /CNKubernetes Intermediate CA/OMyOrg \ -addext subjectAltName DNS:kubernetes,DNS:kubernetes.default,DNS:kubernetes.default.svc,DNS:kubernetes.default.svc.cluster.local,IP:10.96.0.1,IP:127.0.0.1,IP:10.10.20.11,IP:10.10.20.12,IP:10.10.20.13 \ -out /root/k8s-certs/intermediate/intermediate-ca.csr openssl x509 -req -in /root/k8s-certs/intermediate/intermediate-ca.csr -CA /root/k8s-certs/ca/ca.pem -CAkey /root/k8s-certs/ca/ca-key.pem -CAcreateserial -sha256 -days 1825 -out /root/k8s-certs/intermediate/intermediate-ca.pem # 3. 为 etcd 生成证书所有 master 节点共用同一套证书 openssl genrsa -out /root/k8s-certs/etcd/etcd-key.pem 2048 openssl req -new -key /root/k8s-certs/etcd/etcd-key.pem -subj /CNetcd-server/OMyOrg \ -addext subjectAltName DNS:localhost,IP:127.0.0.1,IP:10.10.20.11,IP:10.10.20.12,IP:10.10.20.13 \ -out /root/k8s-certs/etcd/etcd.csr openssl x509 -req -in /root/k8s-certs/etcd/etcd.csr -CA /root/k8s-certs/intermediate/intermediate-ca.pem -CAkey /root/k8s-certs/intermediate/intermediate-ca-key.pem -CAcreateserial -sha256 -days 365 -out /root/k8s-certs/etcd/etcd.pem # 4. 为 kube-apiserver 生成证书SAN 必须包含所有 master IP 和 VIP openssl genrsa -out /root/k8s-certs/kube-apiserver/apiserver-key.pem 2048 openssl req -new -key /root/k8s-certs/kube-apiserver/apiserver-key.pem -subj /CNkube-apiserver/Osystem:masters \ -addext subjectAltName DNS:kubernetes,DNS:kubernetes.default,DNS:kubernetes.default.svc,DNS:kubernetes.default.svc.cluster.local,IP:10.96.0.1,IP:127.0.0.1,IP:10.10.20.11,IP:10.10.20.12,IP:10.10.20.13,IP:10.10.20.100 \ -out /root/k8s-certs/kube-apiserver/apiserver.csr openssl x509 -req -in /root/k8s-certs/kube-apiserver/apiserver.csr -CA /root/k8s-certs/intermediate/intermediate-ca.pem -CAkey /root/k8s-certs/intermediate/intermediate-ca-key.pem -CAcreateserial -sha256 -days 365 -out /root/k8s-certs/kube-apiserver/apiserver.pem # 5. 为 kube-controller-manager 生成证书CN 必须是 system:kube-controller-manager openssl genrsa -out /root/k8s-certs/kube-controller-manager/controller-manager-key.pem 2048 openssl req -new -key /root/k8s-certs/kube-controller-manager/controller-manager-key.pem -subj /CNsystem:kube-controller-manager/Osystem:kube-controller-manager -out /root/k8s-certs/kube-controller-manager/controller-manager.csr openssl x509 -req -in /root/k8s-certs/kube-controller-manager/controller-manager.csr -CA /root/k8s-certs/intermediate/intermediate-ca.pem -CAkey /root/k8s-certs/intermediate/intermediate-ca-key.pem -CAcreateserial -sha256 -days 365 -out /root/k8s-certs/kube-controller-manager/controller-manager.pem # 6. 为 kube-scheduler 生成证书CN 必须是 system:kube-scheduler openssl genrsa -out /root/k8s-certs/kube-scheduler/scheduler-key.pem 2048 openssl req -new -key /root/k