### **ServiceAccount Token 与 CA 证书的完整关系解析**
#### **1. 核心逻辑**
Kubernetes 的 ServiceAccount (SA) Token 本质是 **由集群 CA 体系签名的 JWT**,其信任链如下:
```
ServiceAccount Token 有效性 → 由 sa.key/sa.pub 签名 → sa.pub 必须被集群 CA 证书信任
```
- **签发者**:`kube-controller-manager`(传统 Token)或 `kube-apiserver`(新版 Token)
- **验证者**:`kube-apiserver` 使用集群 CA 证书校验 Token 的合法性
---
### **2. 手动生成 ServiceAccount Token(依赖 CA)**
#### **步骤 1:检查当前集群的 SA 密钥对**
```bash
# 查看集群使用的 SA 密钥
ls /etc/kubernetes/pki/sa.*
# 必须存在:
# /etc/kubernetes/pki/sa.key (私钥,用于签名 Token)
# /etc/kubernetes/pki/sa.pub (公钥,用于验证 Token)
```
#### **步骤 2:用集群 CA 体系生成新 SA 密钥(如需)**
```bash
# 生成新的 SA 密钥对(由当前 CA 派生)
sudo kubeadm init phase certs sa --cert-dir /etc/kubernetes/pki
# 生成后检查公钥是否被 CA 信任
openssl x509 -in /etc/kubernetes/pki/ca.crt -pubkey | diff - /etc/kubernetes/pki/sa.pub
# 无输出表示 sa.pub 是 CA 的派生密钥
```
#### **步骤 3:创建 ServiceAccount 并生成 Token**
```bash
# 创建 ServiceAccount
kubectl create serviceaccount my-sa
# 获取自动生成的 Token(新版 Kubernetes)
kubectl create token my-sa --duration=8760h
# 传统方式(需手动绑定 Secret)
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Secret
metadata:
name: my-sa-token
annotations:
kubernetes.io/service-account.name: my-sa
type: kubernetes.io/service-account-token
EOF
```
---
### **3. 验证当前 SA Token 是否依赖 CA**
#### **方法 1:检查 Token 签名密钥**
```bash
# 获取任意 SA Token
TOKEN=$(kubectl get secret $(kubectl get sa my-sa -o jsonpath='{.secrets[0].name}') -o jsonpath='{.data.token}' | base64 -d)
# 解码 Token 头部查看签名算法
echo $TOKEN | cut -d '.' -f 1 | base64 -d
# 输出应包含:
# "alg": "RS256" # 表示使用 RSA 签名(依赖 sa.key/sa.pub)
```
#### **方法 2:强制用 CA 验证 Token**
```bash
# 使用集群 CA 验证 Token
curl -k --cacert /etc/kubernetes/pki/ca.crt \
-H "Authorization: Bearer $TOKEN" \
https://<API_SERVER_IP>:6443/api/v1/namespaces/default/pods
# 返回 200 表示 Token 被 CA 信任
```
#### **方法 3:检查组件启动参数**
```bash
# 查看 kube-apiserver 的 SA 配置
ps aux | grep kube-apiserver | grep service-account
# 关键参数:
# --service-account-key-file=/etc/kubernetes/pki/sa.pub # 必须与 CA 匹配
# --service-account-signing-key-file=/etc/kubernetes/pki/sa.key
# 查看 kube-controller-manager 的 SA 配置
ps aux | grep kube-controller-manager | grep service-account
# 关键参数:
# --service-account-private-key-file=/etc/kubernetes/pki/sa.key
```
---
### **4. SA 与 CA 的生成逻辑**
| 组件 | 依赖关系 |
|---------------------|--------------------------------------------------------------------------|
| **kube-apiserver** | 用 `sa.pub` 验证 Token,`sa.pub` 必须与 `ca.crt` 同源 |
| **controller-manager** | 用 `sa.key` 签发传统 Token,`sa.key` 必须与 `ca.key` 同属一个密钥体系 |
| **Pod/Token** | 携带的 Token 必须能被 `sa.pub` 验证,且 `sa.pub` 需被集群 CA 信任 |
#### **关键配置文件**
```bash
# CA 证书和密钥
/etc/kubernetes/pki/ca.crt
/etc/kubernetes/pki/ca.key
# ServiceAccount 密钥对(由 CA 派生)
/etc/kubernetes/pki/sa.pub
/etc/kubernetes/pki/sa.key
```
---
### **5. 故障排查**
#### **场景:更新 CA 后 SA Token 失效**
```bash
# 重新生成 SA 密钥对
sudo kubeadm init phase certs sa --cert-dir /etc/kubernetes/pki
# 重启组件
sudo systemctl restart kubelet
```
#### **场景:SA Token 无法通过验证**
```bash
# 检查 sa.pub 是否与 CA 匹配
openssl x509 -in /etc/kubernetes/pki/ca.crt -pubkey | diff - /etc/kubernetes/pki/sa.pub
# 如果不匹配,重新生成 SA 密钥
sudo mv /etc/kubernetes/pki/sa.{key,pub} /tmp/
sudo kubeadm init phase certs sa --cert-dir /etc/kubernetes/pki
```
---
### **6. 总结**
| 操作 | 命令/检查点 |
|-------------------------------|----------------------------------------------------------------------------|
| **验证 SA 依赖 CA** | `openssl x509 -in ca.crt -pubkey` 对比 `sa.pub` |
| **手动生成 SA Token** | `kubectl create token <sa-name>` |
| **修复 CA 更新导致的 SA 问题**| `kubeadm init phase certs sa` + 重启组件 |
| **检查 Token 有效性** | `curl --cacert ca.crt -H "Authorization: Bearer $TOKEN" $APISERVER/api` |
**核心结论**:
ServiceAccount Token **必须** 由集群 CA 证书体系(`sa.key/sa.pub`)签名,任何 CA 变更都需同步更新 SA 密钥!