Kubernetes The Hard Way:用 openssl 手动搭建 PKI,为全部组件签发 TLS 证书 Kubernetes The Hard Way用 openssl 手动搭建 PKI为全部组件签发 TLS 证书【免费下载链接】kubernetes-the-hard-wayBootstrap Kubernetes the hard way. No scripts.项目地址: https://gitcode.com/GitHub_Trending/ku/kubernetes-the-hard-way本篇围绕 Provisioning a CA and Generating TLS Certificates 实验展开讲解在 Kubernetes The Hard Way 教程中如何用openssl从零搭建一套 PKIPublic Key Infrastructure基础设施先创建一个自签名 Certificate AuthorityCA再为 kube-apiserver、kube-controller-manager、kube-scheduler、kubelet、kube-proxy 以及admin用户和 service-accounts 逐一批量签发 TLS 证书并把这些“组件级凭证”分发到server、node-0、node-1各台机器。读完本篇你不仅能完整复现 CA 创建、证书批量生成与分发的每一步操作还能理解 ca.conf 中每个 section 的 CN/OU 命名背后的 Kubernetes 授权机制以及各组件最终在 systemd unit 中如何消费这些证书。实验前提与整体脉络Kubernetes 组件之间默认通过 mTLS双向 TLS相互认证API Server 要求每个客户端kubelet、controller-manager、scheduler、kube-proxy、admin出示由同一 CA 签发的客户端证书kube-apiserver 自己又必须出示一张包含正确 SAN 的服务端证书。在 Kubernetes The Hard Way 的 13 个 lab 中本篇lab 04正是这些身份凭证的源头。它的输入输出关系是输入lab 03 中已经配好 SSH 免密访问的三台机器server、node-0、node-1和一台jumpbox以及仓库自带的 ca.conf输出ca.key/ca.crt一对根 CA 密钥加上 8 份组件级*.key/*.crt/*.csr文件全部生成在jumpbox的当前工作目录中。所有命令都应在jumpbox上执行——jumpbox是一台不承载集群组件的跳板机专门用于集中完成证书、kubeconfig 等“凭证生产”工作。理解 ca.confopenssl 的“证书生产配方”教程把复杂的 openssl 细节收敛到了一个配置文件里ca.conf。原文档明确说你不需要理解其中的每一行也能完成实验但它是学习 openssl 配置管理的一张很好的地图。下面按 section 拆解它的结构[req]根 CA 的自签名参数[req] distinguished_name req_distinguished_name prompt no x509_extensions ca_x509_extensions [ca_x509_extensions] basicConstraints CA:TRUE keyUsage cRLSign, keyCertSign [req_distinguished_name] C US ST Washington L Seattle CN CAprompt no表示不交互式询问 DN 字段直接取req_distinguished_name中的值这是脚本化生成的关键basicConstraints CA:TRUE与keyUsage cRLSign, keyCertSign声明这张根证书是 CA 证书只能用于签发证书和 CRL不能当普通 TLS 证书用CN CA即根 CA 的通用名。[admin] 与各组件 section用 CN/O 编码 Kubernetes 身份Kubernetes 的认证authentication会把证书中的 DN 字段映射为 API 用户身份。各 section 的命名正是围绕这套映射来设计的[admin]CN admin、O system:masters。system:masters组在 RBAC 中被预绑定为集群级管理员持有这张证书的用户等效于 cluster-admin[node-0] / [node-1]CN system:node:node-0node-1 同理、O system:nodes。ca.conf 中的注释解释了原因Kubernetes 有一个专门的 Node Authorizer它只放行“用户名形如system:node:nodeName且属于system:nodes组”的 kubelet 请求。此外每个 worker 的扩展字段里都带有subjectAltName DNS:host, IP:127.0.0.1保证 kubelet 作为服务端发布 10250 端口时本地回环访问也能通过主机名校验[kube-proxy]CN system:kube-proxy、O system:node-proxier对应 kube-proxy 拉取 Service/Endpoint 信息所需的身份与 RBAC 绑定[kube-controller-manager]CN system:kube-controller-manager、O system:kube-controller-manager[kube-scheduler]CN system:kube-scheduler其 DN 中的O system:system:kube-scheduler是配置文件中的原样写法[service-accounts]只有CN service-accounts。ca.conf 的注释说明用途controller-manager 会用这一对密钥生成并签名 service account token[kube-api-server]CN kubernetes且subjectAltName kube-api-server_alt_names引用了独立的 SAN 列表 section。扩展字段的三种“口味”组件 section 的req_extensions分为三类体现了“客户端证书”与“服务端证书”的差异扩展字段取值含义basicConstraintsCA:FALSE所有叶子证书均不可再签发子证书extendedKeyUsageclientAuthadmin/service-accounts 经 default_req_extensions或clientAuth, serverAuth各组件限定证书用途组件同时作为 API 客户端和节点服务端所以需要双用途keyUsagecritical, digitalSignature, keyEncipherment关键用途数字签名 密钥封装nsCertTypeclient或client, serverkube-api-serverNetscape 遗留标记apiserver 同时承担服务端角色subjectKeyIdentifierhash用公钥哈希生成 SKI供 CA 的authorityKeyIdentifier链式校验kube-api-server 的 SAN 清单最容易踩坑的一处API Server 是唯一一张服务端为主证书它的 kube-api-server_alt_names section 列出了客户端连接时会校验的所有地址[kube-api-server_alt_names] IP.0 127.0.0.1 IP.1 10.32.0.1 DNS.0 kubernetes DNS.1 kubernetes.default DNS.2 kubernetes.default.svc DNS.3 kubernetes.default.svc.cluster DNS.4 kubernetes.svc.cluster.local DNS.5 server.kubernetes.local DNS.6 api-server.kubernetes.localIP.1 10.32.0.1与DNS.0~DNS.4是为集群内部 DNS 预留的kubernetes/defaultservice 会被分配到10.32.0.0/24service CIDR中的10.32.0.1DNS.5 server.kubernetes.local是本教程里集群的实际 FQDNlab 03 中为server机器设置的 FQDN后续所有 kubeconfig 的--serverhttps://server.kubernetes.local:6443都依赖这张证书能校验通过IP.0 127.0.0.1覆盖本机回环访问。如果部署时改了服务器 FQDN 或 Service CIDR必须同步修改这里否则客户端 TLS 握手会因 SAN 不匹配而失败。创建自签名 CA4096 位根密钥 十年有效期每个 CA 都由“私钥 根证书”构成。本教程创建一个自签名 CA——原文档特别提醒这对完成教程已经足够但不应被视为真实生产环境的做法生产上通常使用受信任的根 CA 或内部证书体系。在jumpbox上执行{ openssl genrsa -out ca.key 4096 openssl req -x509 -new -sha512 -noenc \ -key ca.key -days 3653 \ -config ca.conf \ -out ca.crt }参数逐项说明openssl genrsa -out ca.key 4096生成 4096 位 RSA 私钥。ca.key是整个体系中最敏感的文件一旦泄露任何人都能签发“合法”证书-x509直接输出自签名的 X.509 证书而非 CSR-sha512根证书用 SHA-512 签名叶子证书后面会改用 SHA-256-noenc私钥不加密存储便于后续openssl x509 -CA自动读取——这也是“密钥必须严格保管”这一告诫的技术原因-days 3653约 10 年有效期-config ca.conf取[req]段的 DN 与ca_x509_extensions扩展。执行后工作目录应出现ca.crt与ca.key两个文件ca.crt ca.key批量签发 8 份客户端/服务端证书下一步为所有组件生成“密钥 CSR 签发证书”三件套。先定义证书清单数组certs( admin node-0 node-1 kube-proxy kube-scheduler kube-controller-manager kube-api-server service-accounts )然后循环调用三个 openssl 子命令for i in ${certs[*]}; do openssl genrsa -out ${i}.key 4096 openssl req -new -key ${i}.key -sha256 \ -config ca.conf -section ${i} \ -out ${i}.csr openssl x509 -req -days 3653 -in ${i}.csr \ -copy_extensions copyall \ -sha256 -CA ca.crt \ -CAkey ca.key \ -CAcreateserial \ -out ${i}.crt done循环体内每条命令的作用openssl genrsa -out ${i}.key 4096——为组件生成 4096 位 RSA 私钥openssl req -new -key ... -config ca.conf -section ${i}——按 ca.conf 中与证书同名的 section如[node-0]、[kube-proxy]填充 DN 和req_extensions生成 CSR。注意文件名与 section 名必须严格一致kube-api-server带连字符不是下划线openssl x509 -req ... -CA ca.crt -CAkey ca.key -CAcreateserial——用根 CA 的密钥对 CSR 签名产出最终证书-copy_extensions copyall是关键选项把 CSR 中经 section 注入的扩展SAN、extendedKeyUsage 等完整拷贝到最终证书里否则签出的证书会丢失 SANTLS 校验直接失败-CAcreateserial创建/递增ca.srl序列号文件。版本提示-copy_extensions是较新版本 openssl 才支持的选项依赖它的前提是 openssl 版本足够新。若你的 openssl 过老报错时需升级 openssl 或改用extfile方式手动传扩展。执行后8 个组件各自产出一份.key、一份.csr、一份.crt。用下面命令核对产物ls -1 *.crt *.key *.csr预期能看到ca.crt/ca.key加上admin.*、node-0.*、node-1.*、kube-proxy.*、kube-scheduler.*、kube-controller-manager.*、kube-api-server.*、service-accounts.*共 8 组文件。分发证书按“组件查找路径”投放证书签发完成后要拷到各机器上放到对应组件约定的查找路径。原文档强调真实环境中这些文件等同于敏感密钥secret因为它们就是各组件互相认证的“身份证”。分发到 worker 节点node-0 / node-1kubelet 的证书对统一放在/var/lib/kubelet/注意远端会重命名为固定的kubelet.crt/kubelet.key每台节点各自持有node-0/node-1自己的那份for host in node-0 node-1; do ssh root${host} mkdir /var/lib/kubelet/ scp ca.crt root${host}:/var/lib/kubelet/ scp ${host}.crt \ root${host}:/var/lib/kubelet/kubelet.crt scp ${host}.key \ root${host}:/var/lib/kubelet/kubelet.key doneca.crt同样下发因为 kubelet 需要它作为信任根来校验 API Server 的服务端证书后续生成 kubeconfig 时以--certificate-authorityca.crt引用。分发到控制平面serverAPI Server、service-accounts 的证书与根 CA 密钥一起放到server的 home 目录下一步 lab 会移入/var/lib/kubernetes/scp \ ca.key ca.crt \ kube-api-server.key kube-api-server.crt \ service-accounts.key service-accounts.crt \ rootserver:~/为什么根 CA 的key也要给server因为 kube-controller-manager.service 中--cluster-signing-cert-file/var/lib/kubernetes/ca.crt与--cluster-signing-key-file/var/lib/kubernetes/ca.key需要用它来再签发kubelet 的 Serving 证书和 service account 令牌签名密钥——CA 不只在 bootstrap 时用一次。原文档的后续提示kube-proxy、kube-controller-manager、kube-scheduler与kubelet的客户端证书将在下一个 labGenerating Kubernetes Configuration Files for Authentication中被打包进各组件的 kubeconfig 文件。纵深这些证书在各组件中到底被谁消费把证书“放对位置”只是第一步理解 systemd unit 中的消费方式才能验证前面 DN/SAN 设计的正确性API Serverunits/kube-apiserver.service--tls-cert-file/var/lib/kubernetes/kube-api-server.crt与--tls-private-key-file.../kube-api-server.key让 apiserver 以 TLS 服务端身份监听 6443客户端会按server.kubernetes.local校验 SAN--client-ca-file/var/lib/kubernetes/ca.crt声明“凡是本 CA 签发的客户端证书都予以信任”这正是 lab 04 为每个组件签发同一 CA 证书的落点--service-account-key-file.../service-accounts.crt与--service-account-signing-key-file.../service-accounts.key对应 ca.conf 中[service-accounts]的注释apiserver 用这对密钥验证 controller-manager 签发的 service account token--kubelet-client-certificate/--kubelet-client-key使用 kube-api-server 自己的证书作为客户端身份去访问 kubelet API--kubelet-certificate-authorityca.crt则用根 CA 校验 kubelet 的服务端证书。Controller Managerunits/kube-controller-manager.service--kubeconfig中内嵌kube-controller-manager.crt/.keylab 05 生成--cluster-signing-key-file/var/lib/kubernetes/ca.key解释了 ca.key 下发到 server 的必要性。Kubeletunits/kubelet.service通过--kubeconfig/var/lib/kubelet/kubeconfig使用 lab 05 基于node-0.crt/node-0.key生成的 kubeconfiglab 05 中特意要求 kubelet 的 kubeconfig 使用与节点同名的证书以匹配 Node Authorizer 的system:node:nodeName身份规则——这正是 ca.conf 中[node-0]section 的设计意图。Scheduler / kube-proxyunits/kube-scheduler.service、units/kube-proxy.service均以--config指向各自的 YAML 配置其中的客户端凭证即本 lab 签发的system:kube-scheduler、system:kube-proxy证书。从源码结构看etcd 是例外units/etcd.service 中 etcd 监听http://127.0.0.1:2379/2380走本机回环明文 HTTP不参与 TLS 体系因此 lab 04 没有为 etcd 签发证书。验证与收尾清单完成本 lab 后可对照以下清单自检任何一项缺失都会让后续 lab 0509 启动失败jumpbox工作目录含ca.key、ca.crt及 8 组*.key/*.csr/*.crt可用ls -1 *.crt *.key *.csr核对抽查证书 DN 是否与 ca.conf 对应 section 一致例如openssl x509 -in node-0.crt -noout -subject -ext subjectAltName应看到CN system:node:node-0, O system:nodes及DNS:node-0, IP:127.0.0.1node-0、node-1的/var/lib/kubelet/下各有ca.crt、kubelet.crt、kubelet.keyserver的 home 目录含ca.key、ca.crt、kube-api-server.crt/.key、service-accounts.crt/.key牢记 README 的定位该教程面向学习而非生产自签名 CA 明文传输的私钥分发方式仅适合学习环境。完成以上步骤后即可进入下一个实验 Generating Kubernetes Configuration Files for Authentication把本 lab 签发的各组件客户端证书封装成 kubelet、kube-proxy、scheduler、controller-manager 与 admin 的 kubeconfig 文件。【免费下载链接】kubernetes-the-hard-wayBootstrap Kubernetes the hard way. No scripts.项目地址: https://gitcode.com/GitHub_Trending/ku/kubernetes-the-hard-way创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考