kubernetes-handbook 实战指南:管理 Kubernetes 集群中的 TLS 证书签发与信任
kubernetes-handbook 实战指南管理 Kubernetes 集群中的 TLS 证书签发与信任【免费下载链接】kubernetes-handbookKubernetes 架构与生态从云原生到 AI 原生基础设施的构建指南项目地址: https://gitcode.com/gh_mirrors/ku/kubernetes-handbook本指南以 kubernetes-handbook 中管理集群中的 TLS为核心系统讲解 Kubernetes 集群根 CA 的信任模型、通过certificates.k8s.ioAPI 为工作负载签发 TLS 证书的完整流程以及 CSR 的审批机制与控制面签名配置。读完本文你将掌握从生成私钥、构造 CSR、提交 API server、批准签发到下载证书启动 HTTPS 服务的全链路操作并理解 CA 证书在集群中的分发与信任建立方式。为什么需要理解集群中的 TLS在 kubernetes-handbook 的最佳实践部分如 install-kubernetes-on-centos.md部署集群的第一步就是创建 TLS 认证所需的证书与秘钥相关操作详见创建TLS证书和秘钥。这一步是创建集群的基础却也是众多用户在实操中遇到问题最多、最难排查的环节因此有必要深入了解其背后的流程和原理。集群根 CA 与组件信任链每个 Kubernetes 集群都有一个集群根证书颁发机构CA。集群中的组件通常使用该 CA 来验证 API server 的证书同时 API server 也使用它验证 kubelet 客户端证书等。这套双向信任机制保证了控制面各组件之间通信的保密性与完整性。为了支撑这套机制CA 证书包被分发到集群中的每个节点作为各节点上 kubelet、kube-proxy 等组件验证对端证书的信任锚点CA 证书同时作为一个 secret 附加分发到默认 service account 上这样 Pod 内运行的 workload 可以通过挂载的 secret 建立对集群 CA 的信任你的 workload 也可以使用certificates.k8s.ioAPI 请求证书签名实现类似 ACME 草案的自动签发流程。在本书的示例集群中CA 与各组件证书统一生成后存放在/etc/kubernetes/ssl目录下并通过 etc/kubernetes/apiserver、etc/kubernetes/controller-manager 等配置文件中的--client-ca-file、--tls-cert-file等参数指定给各控制面组件使用详见下文。集群中的 TLS 信任让 Pod 中运行的应用程序信任集群根 CA通常需要一些额外的应用程序配置你需要将 CA 证书包添加到 TLS 客户端或服务器信任的 CA 证书列表中。例如在 Go 程序中可以使用crypto/tls的配置解析证书链并将解析出的证书添加到tls.Config结构体的Certificates字段中。而 CA 证书捆绑包会自动通过默认 service account 加载到 Pod 中挂载路径为/var/run/secrets/kubernetes.io/serviceaccount/ca.crt如果你的 workload 没有使用默认 service account可以请求集群管理员构建一个包含你有权访问的证书包的 ConfigMap 来提供同样的信任材料。从仓库中的认证文档authentication.md可以看出service account 关联的 secret 中同时包含 API server 的公共 CAca.crt和用于身份认证的 JWT token这些凭证被挂载到 Pod 中使得集群内进程既能信任集群 CA又能与 API server 通信。为工作负载签发 TLS 证书完整实操流程以下部分演示如何为通过 DNS 访问的 Kubernetes 服务创建 TLS 证书整个流程分为五个步骤安装 cfssl 工具、生成私钥与 CSR、构造 CSR 对象提交给 API server、查看状态、批准后下载签名证书。下载并安装 cfssl首先从 cfssl 官网 下载 cfssl 工具集。cfssl 是 CloudFlare 的 PKI 工具集在 创建TLS证书和秘钥 中给出了两种安装方式方式一直接使用二进制包安装wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64 chmod x cfssl_linux-amd64 mv cfssl_linux-amd64 /usr/local/bin/cfssl wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64 chmod x cfssljson_linux-amd64 mv cfssljson_linux-amd64 /usr/local/bin/cfssljson wget https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64 chmod x cfssl-certinfo_linux-amd64 mv cfssl-certinfo_linux-amd64 /usr/local/bin/cfssl-certinfo export PATH/usr/local/bin:$PATH方式二使用 go 命令安装go get -u github.com/cloudflare/cfssl/cmd/...安装完成后在$GOPATH/bin目录下可以得到cfssl、cfssl-bundle、cfssl-certinfo、cfssljson、cfssl-newkey、cfssl-scan等以 cfssl 开头的命令。创建证书签名请求通过运行以下命令使用 cfssl 生成私钥和证书签名请求CSR$ cat EOF | cfssl genkey - | cfssljson -bare server { hosts: [ my-svc.my-namespace.svc.cluster.local, my-pod.my-namespace.pod.cluster.local, 172.168.0.24, 10.0.34.2 ], CN: my-pod.my-namespace.pod.cluster.local, key: { algo: ecdsa, size: 256 } } EOFJSON 中各字段的含义如下字段值含义hosts域名与 IP 列表证书的 Subject Alternative NameSAN即该证书合法覆盖的 DNS 名称与 IP 地址CNmy-pod.my-namespace.pod.cluster.localCommon Name证书主体通用名称key.algo/key.sizeecdsa/256密钥算法与位长此处使用 ECDSA-256其中172.168.0.24是 service 的 cluster IPmy-svc.my-namespace.svc.cluster.local是 service 的 DNS 名称10.0.34.2是 Pod 的 IPmy-pod.my-namespace.pod.cluster.local是 Pod 的 DNS 名称。执行后你将看到如下输出2017/03/21 06:48:17 [INFO] generate received request 2017/03/21 06:48:17 [INFO] received CSR 2017/03/21 06:48:17 [INFO] generating key: ecdsa-256 2017/03/21 06:48:17 [INFO] encoded CSR此命令生成两个文件server.csr包含 PEM 编码的 pkcs #10 认证请求server-key.pem包含仍然要创建的证书对应的 PEM 编码私钥请务必妥善保管。创建证书签名请求对象以发送到 Kubernetes API使用以下命令创建 CSR 的 YAML 文件并发送到 API server$ cat EOF | kubectl create -f - apiVersion: certificates.k8s.io/v1beta1 kind: CertificateSigningRequest metadata: name: my-svc.my-namespace spec: groups: - system:authenticated request: $(cat server.csr | base64 | tr -d \n) usages: - digital signature - key encipherment - server auth EOF请注意第 1 步中创建的server.csr文件需要base64 编码后存储在.spec.request字段中spec.groups指定了请求者所在的组示例中为system:authenticated所有已验证用户都会被加入该组详见 authentication.md我们还要求提供 数字签名digital signature、密钥加密key encipherment和 服务器身份验证server auth这三种密钥用途的证书spec.usages字段会在签发时写入证书的 Extended Key Usage 扩展。在 API server 中可以看到这些 CSR 处于 pending 状态。执行下面的命令你将可以看到$ kubectl describe csr my-svc.my-namespace Name: my-svc.my-namespace Labels: none Annotations: none CreationTimestamp: Tue, 21 Mar 2017 07:03:51 -0700 Requesting User: yournameexample.com Status: Pending Subject: Common Name: my-svc.my-namespace.svc.cluster.local Serial Number: Subject Alternative Names: DNS Names: my-svc.my-namespace.svc.cluster.local IP Addresses: 172.168.0.24 10.0.34.2 Events: nonekubectl describe csr会展示 CSR 的请求用户Requesting User、证书主体Subject以及主题备用名称Subject Alternative Names管理员可以据此判断是否应当批准该请求。获取证书签名请求批准证书签名请求可以通过自动批准过程完成也可以由集群管理员一次完成。有关批准机制的详细说明见下文批准证书签名请求一节。下载签名并使用一旦 CSR 被签署并获得批准你将看到以下内容$ kubectl get csr NAME AGE REQUESTOR CONDITION my-svc.my-namespace 10m yournameexample.com Approved,Issued你可以通过运行以下命令下载颁发的证书并将其保存到server.crt文件中$ kubectl get csr my-svc.my-namespace -o jsonpath{.status.certificate} \ | base64 -d server.crt注意kubectl get csr返回的.status.certificate字段是 base64 编码的 PEM 证书因此需要用base64 -d解码后写入文件。现在你可以用server.crt和server-key.pem作为 keypair 来启动 HTTPS server 了。批准证书签名请求Kubernetes 管理员具有适当权限可以使用以下两个命令手动批准或拒绝证书签名请求kubectl certificate approve csr-name kubectl certificate deny csr-name但是如果你打算大量使用此 API则可以考虑编写自动化的证书控制器。在 Kubernetes 1.7 版本之前没有直接的批准/拒绝命令审批者需要直接更新 CSR 的 Status 信息此后的版本中才提供了上述两个命令详见 tls-bootstrapping.md。无论批准者是机器还是使用 kubectl 的人类批准者的核心职责是验证 CSR 满足如下两个要求CSR 的主体控制用于签署 CSR 的私钥。这解决了伪装成授权主体的第三方的威胁。在上述示例中此步骤将验证该 Pod 确实控制了用于生成 CSR 的私钥。CSR 的主体被授权在请求的上下文中执行。这解决了我们不期望的主体加入集群的威胁。在上述示例中此步骤将是验证该 Pod 是否被允许加入到所请求的服务中。当且仅当这两个要求都满足时审批者应该批准 CSR否则应拒绝 CSR。自动化批准与 CSR 子资源对于 kubelet 证书引导场景csrapproving控制器作为 kube-controller-manager 的一部分被默认启用它使用SubjectAccessReviewAPI 判断给定用户是否已被授权请求 CSR并根据授权结果进行批准。内置审批者不会明确拒绝 CSR只会忽略未授权的请求以防与其他批准者冲突。控制器将 CSR 分为三个子资源进行授权检查nodeclient用户的客户端认证请求Osystem:nodesCNsystem:node:(node name)selfnodeclient更新具有相同O和CN的客户端证书的节点selfnodeserver更新服务证书的节点Alpha需要RotateKubeletServerCertificatefeature gate。对应的 RBAC ClusterRole 示例如approve-node-client-csr、approve-node-client-renewal-csr、approve-node-server-renewal-csr以及将 bootstrap token 组与这些角色绑定的 ClusterRoleBinding 完整示例请参阅 tls-bootstrapping.md。给集群管理员的一个建议配置控制面证书签发器本教程假设将 signer 设置为服务证书 API。Kubernetes controller manager 提供了一个 signer 的默认实现。要启用它请将以下两个参数传递给 controller manager并配置具有证书颁发机构的密钥对的路径--cluster-signing-cert-file/etc/kubernetes/ssl/ca.pem --cluster-signing-key-file/etc/kubernetes/ssl/ca-key.pem在本书的示例集群中etc/kubernetes/controller-manager 的KUBE_CONTROLLER_MANAGER_ARGS正是这样配置的KUBE_CONTROLLER_MANAGER_ARGS--address127.0.0.1 --service-cluster-ip-range10.254.0.0/16 --cluster-namekubernetes --cluster-signing-cert-file/etc/kubernetes/ssl/ca.pem --cluster-signing-key-file/etc/kubernetes/ssl/ca-key.pem --service-account-private-key-file/etc/kubernetes/ssl/ca-key.pem --root-ca-file/etc/kubernetes/ssl/ca.pem --leader-electtrue同时systemd/kube-controller-manager.service 中通过EnvironmentFile加载该配置文件并将$KUBE_CONTROLLER_MANAGER_ARGS传给kube-controller-manager进程EnvironmentFile-/etc/kubernetes/config EnvironmentFile-/etc/kubernetes/controller-manager ExecStart/usr/bin/kube-controller-manager \ $KUBE_LOGTOSTDERR \ $KUBE_LOG_LEVEL \ $KUBE_MASTER \ $KUBE_CONTROLLER_MANAGER_ARGS各参数的作用如下参数示例值作用--cluster-signing-cert-file/etc/kubernetes/ssl/ca.pem用于给 CSR 签名的 CA 证书--cluster-signing-key-file/etc/kubernetes/ssl/ca-key.pem与 CA 证书配对的 CA 私钥--service-account-private-key-file/etc/kubernetes/ssl/ca-key.pem用于签名 service account token 的私钥--root-ca-file/etc/kubernetes/ssl/ca.pem注入到 service account secret 中的根 CA 证书对应 Pod 内/var/run/secrets/kubernetes.io/serviceaccount/ca.crt集群初始化阶段的证书体系在为工作负载签发证书之前集群本身在初始化阶段就需要一套完整的证书体系。在 创建TLS证书和秘钥 中这套体系使用 cfssl 生成共产生 8 个文件ca-key.pem, ca.pem kubernetes-key.pem, kubernetes.pem kube-proxy.pem, kube-proxy-key.pem admin.pem, admin-key.pem各组件使用证书的情况如下组件使用的证书etcdca.pem、kubernetes-key.pem、kubernetes.pemkube-apiserverca.pem、kubernetes-key.pem、kubernetes.pemkubeletca.pemkube-proxyca.pem、kube-proxy-key.pem、kube-proxy.pemkubectlca.pem、admin-key.pem、admin.pemkube-controller-managerca-key.pem、ca.pem创建 CA首先创建 CA 配置文件ca-config.json可定义多个 profiles分别指定不同的过期时间、使用场景signing表示该证书可用于签名其它证书生成的ca.pem中CATRUEserver auth表示 client 可用该 CA 验证 server 证书client auth表示 server 可用该 CA 验证 client 证书{ signing: { default: { expiry: 87600h }, profiles: { kubernetes: { usages: [ signing, key encipherment, server auth, client auth ], expiry: 87600h } } } }创建 CA 证书签名请求ca-csr.json注意CN字段会被 kube-apiserver 提取为请求的用户名O字段会被提取为请求用户所属的组然后生成 CA 证书和私钥cfssl gencert -initca ca-csr.json | cfssljson -bare ca创建各组件证书以 kubernetes 证书为例其hosts字段必须包含 etcd 集群、kubernetes master 集群的主机 IP以及 kubernetes 服务的服务 IP一般是kube-apiserver指定的service-cluster-ip-range网段的第一个 IP如10.254.0.1cfssl gencert -caca.pem -ca-keyca-key.pem -configca-config.json -profilekubernetes kubernetes-csr.json | cfssljson -bare kubernetesadmin 证书的O字段需要设置为system:masterskube-apiserver 预定义的cluster-adminRoleBinding 将 Groupsystem:masters与 Rolecluster-admin绑定该 Role 授予调用 kube-apiserver 所有 API 的权限因此使用 admin 证书的 kubectl 拥有整个集群的管理权限。kube-proxy 证书的CN字段需要设置为system:kube-proxy其对应的预定义 RoleBindingsystem:node-proxier授予调用 Proxy 相关 API 的权限。证书分发与校验将生成的证书和秘钥文件后缀名为.pem拷贝到所有机器的/etc/kubernetes/ssl目录下备用mkdir -p /etc/kubernetes/ssl cp *.pem /etc/kubernetes/ssl校验证书可以使用openssl命令openssl x509 -noout -text -in kubernetes.pem需要确认Issuer、Subject、X509v3 Subject Alternative Name字段分别与ca-csr.json、kubernetes-csr.json一致并确认X509v3 Key Usage、Extended Key Usage字段与ca-config.json中kubernetesprofile 一致。也可以使用cfssl-certinfo -cert kubernetes.pem以 JSON 形式查看证书信息。控制面如何使用这些证书从仓库中的配置文件可以完整还原证书在控制面各组件中的使用方式etc/kubernetes/apiserver 中--tls-cert-file/--tls-private-key-file指向kubernetes.pem/kubernetes-key.pem作为 API server 自身的 TLS 服务证书--client-ca-file指向ca.pem用于验证客户端证书--etcd-cafile/--etcd-certfile/--etcd-keyfile用于与 etcd 之间的双向 TLSetc/kubernetes/kubelet 中--experimental-bootstrap-kubeconfig/etc/kubernetes/bootstrap.kubeconfig与--cert-dir/etc/kubernetes/ssl配合实现 kubelet 的 TLS 证书引导详见 tls-bootstrapping.mdetc/kubernetes/proxy 中kube-proxy 通过--kubeconfig/etc/kubernetes/kube-proxy.kubeconfig携带自己的客户端证书与 API server 通信。与认证授权的衔接理解集群 TLS 之后可以进一步把它与认证授权机制串联起来当 API server 以--client-ca-fileSOMEFILE启用客户端证书认证时如果客户端证书验证通过则使用证书 subject 的Common NameCN作为请求的用户名使用证书的OrganizationO字段指示用户的组成员身份。这也解释了为什么上一节中 admin 证书的O必须设置为system:masters、kube-proxy 证书的CN必须设置为system:kube-proxy——这些字段直接决定了请求者在 RBAC 体系中的身份详见 authentication.md。完整的用户身份认证方式X509 客户端证书、静态 Token 文件、Bootstrap Token、Service Account Token、OIDC 等以及集群访问配置auth-with-kubeconfig-or-token.md可继续查阅仓库中对应文档深入学习。【免费下载链接】kubernetes-handbookKubernetes 架构与生态从云原生到 AI 原生基础设施的构建指南项目地址: https://gitcode.com/gh_mirrors/ku/kubernetes-handbook创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考