ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

kOps 权威指南:kops create keypair —— keyset 证书注入、CA 轮换与源码级原理剖析

kOps 权威指南:kops create keypair —— keyset 证书注入、CA 轮换与源码级原理剖析 kOps 权威指南kops create keypair —— keyset 证书注入、CA 轮换与源码级原理剖析【免费下载链接】kopsKubernetes Operations (kOps) - Production Grade k8s Installation, Upgrades and Management项目地址: https://gitcode.com/gh_mirrors/kop/kopskops create keypair是 kOps 中向集群 keyset密钥集添加 CA 证书与私钥的核心命令也是实施自定义 CA、CA 轮换与 service-account 密钥管理等安全操作的入口。本文将以其官方 CLI 文档 docs/cli/kops_create_keypair.md 为骨架结合 cmd/kops/create_keypair.go 与 upup/pkg/fi/ca.go 等源码实现完整讲解命令语法、参数语义、四类输入组合行为、all批量轮换模式以及底层的 keyset 模型与证书签发原理帮助你理解并能直接上手使用该命令。命令概述向 keyset 添加 CA 证书与私钥kops create keypair的作用是向一个指定的 keyset 添加一对 CA 证书与私钥。其官方 Synopsis 描述如下Add a CA certificate and private key to a keyset.kOps 将集群的 PKI 材料CA 证书、私钥、service-account 密钥等组织为若干个keyset每个 keyset 内含一个或多个证书/私钥对称为 keypair item。当集群需要更换 CA、引入外部 CA、或者轮换 service-account 签名密钥时就通过本命令向对应 keyset 注入新的 keypair。命令基本语法kops create keypair {KEYSET | all} [flags]该命令是kops create的子命令之一与create cluster、create instancegroup、create secret、create sshpublickey并列注册于 cmd/kops/create.go 中。其定位与create cluster等资源创建命令不同keypair 属于 PKI 密钥材料不能通过 YAML 配置文件创建kops create的文档明确注明 keypairs and secrets cannot be created from YAML config files yet。核心概念keyset、primary 与可轮换 keyset理解本命令之前需要先掌握三个关键概念它们都直接体现在源码数据结构中。keyset 与 KeysetItem在 upup/pkg/fi/ca.go 中Keyset是一个由多个KeysetItem证书/私钥对组成的集合// Keyset is a parsed api.Keyset. type Keyset struct { LegacyFormat bool Items map[string]*KeysetItem // Primary is the KeysetItem that is considered the active key. // It is guaranteed to be non-nil, if there are any keypairs. Primary *KeysetItem } // KeysetItem is a certificate/key pair in a Keyset. type KeysetItem struct { Id string DistrustTimestamp *time.Time Certificate *pki.Certificate PrivateKey *pki.PrivateKey }也就是说一个 keyset 内部可以同时保存多个 keypair例如新旧两代 CA每个 keypair 有唯一Id由证书序列号派生、可选的DistrustTimestamp吊销/不信任时间戳、证书与私钥。Keyset.Primary指向当前活跃的那一个。Primary真正负责签发的那个 keypair文档明确说明One of the certificate/private key pairs in each keyset must be primary. The primary keypair is the one used to issue certificates (or, for the service-account keyset, service-account tokens). As a consequence, a keypair added to an empty keyset must be made primary.每个 keyset 中必须有一个 primary keypair它是实际用于签发证书对service-accountkeyset 而言则是签发 service-account token的密钥。因此向空 keyset 添加的第一个 keypair 必须标记为 primary非 primary 的 keypair 是备用/轮换中的候选等待未来被 promote。rotatableKeysetFilter哪些 keyset 允许被操作并非所有 keyset 都支持通过本命令添加 keypair。cmd/kops/create_keypair.go 中的过滤器rotatableKeysetFilter见该文件第 86-88 行定义了可轮换 keyset的判定规则func rotatableKeysetFilter(name string, _ *fi.Keyset) bool { return name all || name service-account || strings.Contains(name, -ca) }即keyset 名称为service-account或者以-ca结尾如kubernetes-ca、kubelet-ca或者特殊值all才被视为可轮换并允许注入新 keypair。若对其它 keyset 执行命令RunCreateKeypair会直接报错adding keypair to xxx is not supported命令语法与全部参数kops create keypair {KEYSET | all} [flags]专属选项选项类型说明--cert stringStringCA 证书文件的路径--key stringStringCA 私钥文件的路径--primaryBool将该 keypair 设为签发证书所用的 primary keypair-h, --helpBool显示帮助三个专属 flag 都在 cmd/kops/create_keypair.go 第 138-140 行注册cmd.Flags().StringVar(options.CertPath, cert, options.CertPath, Path to CA certificate) cmd.Flags().StringVar(options.PrivateKeyPath, key, options.PrivateKeyPath, Path to CA private key) cmd.Flags().BoolVar(options.Primary, primary, options.Primary, Make the keypair the one used to issue certificates)继承自父命令的全局选项与其它 kops 命令一致本命令还继承以下全局选项选项说明--name string集群名称覆盖KOPS_CLUSTER_NAME环境变量--state stringstate 存储位置kops config 文件覆盖KOPS_STATE_STORE环境变量--config stringYAML 配置文件默认$HOME/.kops.yaml-v, --v Level日志级别 verbosity--alsologtostderrthreshold severity等klog 相关日志参数--name是必填的命令的Args校验逻辑第 99-129 行在集群名为空时直接返回--name is required。四类输入组合与行为规则文档的核心逻辑围绕证书/私钥是否提供展开共四种组合分别对应不同的行为1. 两者都不提供自动生成自签名 CAIf neither a certificate nor a private key is provided, a new self-signed certificate and private key will be generated.此时命令会自动生成一对全新的自签名证书与私钥。对应源码createKeypair函数先通过pki.GeneratePrivateKey()生成 RSA 私钥见下文私钥生成再以pki.BuildPKISerial(time.Now().UnixNano())生成序列号构造pki.IssueCertRequest其中Type: ca、Subject.CommonName为 keyset 名称调用pki.IssueCert签发自签名 CA 证书。2. 只提供私钥由私钥推导自签名证书If no certificate is provided but a private key is, a self-signed certificate will be generated from the provided private key.当--key给出但--cert未给出时命令读取并解析用户私钥pki.ParsePEMPrivateKey然后用该私钥生成对应的自签名证书——证书的公钥对应该私钥保证证书与私钥匹配。3. 只提供证书仅注入证书、无私钥If a certificate is provided but no private key is, the certificate will be added to the keyset without a private key. Such a certificate cannot be made primary.当--cert给出但--key未给出时仅把该 CA 证书加入 keyset不附带私钥。这类证书-only条目无法成为 primaryprimary 必须持有私钥才能签发证书。upup/pkg/fi/ca.go 的AddItem对此有强校验if privateKey nil primary { return item, fmt.Errorf(private key not provided for primary item) }典型使用场景导入外部/公司 CA 的公钥证书用于信任链构建但私钥由外部 CA 保管、不落入 kOps state store。4. 两者都提供注入完整外部 CAkops create keypair kubernetes-ca \ --cert ~/ca.pem --key ~/ca-key.pem \ --name k8s-cluster.example.com --state s3://my-state-store这是最典型的接入自有 CA场景读取~/ca.pem与~/ca-key.pem内部会执行utils.ExpandPath展开~分别经pki.ParsePEMCertificate/pki.ParsePEMPrivateKey解析后写入 keystore。命令成功后输出using user provided cert: /home/user/ca.pem using user provided private key: /home/user/ca-key.pem Created kubernetes-ca id实战为所有可轮换 keyset 批量生成次级密钥If the keyset is specified as all, a newly generated secondary certificate and private key will be added to each rotatable keyset.当第一个参数为all时命令会遍历 keystore 中所有 keyset对每个可轮换 keyset 自动生成一对全新的次级secondary证书与私钥并加入kops create keypair all \ --name k8s-cluster.example.com --state s3://my-state-store这正是集群 CA 轮换的标准前置步骤。其源码路径RunCreateKeypairkeyStore.ListKeysets()列出全部 keyset对每个 keyset 用rotatableKeysetFilter过滤逐个调用createKeypair生成并写入次级 keypair。之后可用kops promote keypair将新生成的次级 keypair 提升为 primary完成切换具体流程可参考 kops_promote_keypair 与 kops_distrust_keypair 文档。注意all模式不能与--cert、--key、--primary同时使用否则会报错例如cannot specify --cert with all cannot specify --primary with all同时命令每次只能操作一个 keysetcan only add to one keyset at a time即kops create keypair ca-a ca-b这样的多 keyset 写法是不被允许的。源码级原理从参数到写入 keystore 的完整链路createKeypair的完整执行流程cmd/kops/create_keypair.go 第 186-268 行解析私钥若--key非空展开路径、os.ReadFile读取、pki.ParsePEMPrivateKey解析确定证书来源若--cert为空若还没有私钥则先生成私钥随后用pki.IssueCert以Type: ca签发自签名证书Subject.CommonName为 keyset 名序列号由时间戳 随机数构成若--cert非空读取文件并pki.ParsePEMCertificate解析定位 keysetkeyStore.FindKeyset(ctx, name)keyset 不存在时若指定了--primary则fi.NewKeyset(cert, privateKey)创建新 keyset首个条目自动为 primary否则报错the first keypair added to a keyset must be primarykeyset 已存在时调用keyset.AddItem(cert, privateKey, options.Primary)追加条目持久化keyStore.StoreKeyset(ctx, name, keyset)写回 state store输出结果打印Created keyset id。其中AddItem还有两个值得注意的细节upup/pkg/fi/ca.go 第 199-246 行不能向空 keyset 添加 secondary!primary k.Primary nil时报错cannot add secondary item when no existing primary item条目 Id 与序列号的关系新条目的 Id 基于pki.BuildPKISerial(time.Now().UnixNano())生成并保证不高于现有条目的序列号确保新条目 Id 更大/更新且 primary 的 Id 不会低于已有条目纯证书条目无私钥的 Id 会被安排在 primary 之前。私钥生成细节pkg/pki/privatekey.go 中GeneratePrivateKey默认生成RSA 2048 位私钥DefaultPrivateKeySize 2048并支持通过环境变量KOPS_RSA_PRIVATE_KEY_SIZE覆盖密钥长度var DefaultPrivateKeySize 2048 ... if os.Getenv(KOPS_RSA_PRIVATE_KEY_SIZE) ! { rsaKeySize int(v) } rsaKey, err : rsa.GenerateKey(crypto_rand.Reader, rsaKeySize)证书序列号生成pkg/pki/csr.go 的BuildPKISerial将纳秒时间戳左移 32 位后与 32 位加密随机数做或运算得到一个极难碰撞且随创建时间单调递增的序列号serial : big.NewInt(timestamp) serial.Lsh(serial, 32) serial.Or(serial, randomComponent)自签名 CA 的签发pkg/pki/issue.go 的IssueCert在收到Type: ca的请求时会把证书模板的IsCA置为true并自行签名不需要 keystore 中的签发者从而产出符合 CA 语义的自签名根证书而签发非 CA 证书时则会从 keystore 中查找 primary keypair 作为签发者——这也解释了为什么 primary 必须持有私钥。常见报错与排查要点错误信息原因--name is required未通过--name或KOPS_CLUSTER_NAME提供集群名must specify name of keyset to add keypair to缺少{KEYSET \| all}位置参数can only add to one keyset at a time传入了多个 keyset 名称adding keypair to xxx is not supported目标 keyset 不满足-ca后缀 /service-account/all过滤条件cannot specify --cert with all等all模式下误传了--cert/--key/--primarythe first keypair added to a keyset must be primary向不存在的 keyset 添加 keypair 时未指定--primaryprivate key not provided for primary item只提供证书却试图用--primary标记或新 keyset 首条目无私钥cannot add secondary item when no existing primary itemkeyset 为空或 Primary 为 nil时添加非 primary 条目与相关命令的协同完整的密钥生命周期kops create keypair只是 kOps 密钥管理链路的一环围绕 keyset 还提供kops promote keypair将 keyset 中的某个 keypair 提升为 primarykops distrust keypair给 keypair 打上DistrustTimestamp使其不再受信任kops get keypairs列出/查看集群 keyset 及其 keypairkops trust keypair撤销 distrust重新信任。典型轮换流程为create keypair生成次级→promote keypair切换 primary→ 滚动更新集群 →distrust keypair吊销旧密钥。此外常见的kubernetes-cakeyset 名称在 upup/pkg/fi/ca.go 中被定义为常量CertificateIDCA kubernetes-ca是集群主 CA 的固定标识。总结kops create keypair通过一条命令优雅地解决了 kOps 集群 PKI 的三大诉求注入外部 CA证书私钥、信任外部证书仅证书、非 primary、自动化 CA 轮换all批量生成次级密钥。理解其背后的 keyset/primary 模型、rotatableKeysetFilter过滤规则以及首个条目必须 primary的约束就能在实际运维中安全、正确地管理集群证书生命周期。本文所有命令与参数说明均以当前仓库的 docs/cli/kops_create_keypair.md 及 cmd/kops/create_keypair.go 为准可据此查阅更完整的代码细节。【免费下载链接】kopsKubernetes Operations (kOps) - Production Grade k8s Installation, Upgrades and Management项目地址: https://gitcode.com/gh_mirrors/kop/kops创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表