85·安全进阶

ServiceAccount

kubernetessecurityrbacserviceaccount

ServiceAccount

学习目标

  1. 理解 ServiceAccount 的概念和用途
  2. 掌握 ServiceAccount 的创建和管理
  3. 了解 ServiceAccount 与 RBAC 的集成

核心概念

一句话解释

ServiceAccount 是 Kubernetes 中用于 Pod 内进程访问 API Server 的身份标识。

ServiceAccount vs User

┌─────────────────────────────────────────────────────────────┐
│                    身份类型对比                              │
├─────────────────────────────────────────────────────────────┤
│  User (用户)                                                │
│  ├── 由外部身份系统管理 (LDAP, OIDC)                        │
│  ├── 集群管理员创建                                         │
│  └── 用于人类用户访问                                       │
├─────────────────────────────────────────────────────────────┤
│  ServiceAccount (服务账户)                                   │
│  ├── 由 Kubernetes 管理                                     │
│  ├── 自动创建 Token                                         │
│  └── 用于 Pod 内进程访问                                    │
└─────────────────────────────────────────────────────────────┘

ServiceAccount 工作流程

1. 创建 ServiceAccount
   │
   ▼
2. 自动创建 Token (Secret)
   │
   ▼
3. Pod 引用 ServiceAccount
   │
   ▼
4. Pod 内进程使用 Token 访问 API Server
   │
   ▼
5. RBAC 检查权限

创建 ServiceAccount

# 创建 ServiceAccount
apiVersion: v1
kind: ServiceAccount
metadata:
  name: my-app-sa
  namespace: default
# 应用 ServiceAccount
kubectl apply -f my-app-sa.yaml

# 查看 ServiceAccount
kubectl get serviceaccounts -n default

# 查看 ServiceAccount 详情
kubectl describe serviceaccount my-app-sa -n default

Pod 使用 ServiceAccount

# Pod 指定 ServiceAccount
apiVersion: v1
kind: Pod
metadata:
  name: my-app
  namespace: default
spec:
  serviceAccountName: my-app-sa
  containers:
  - name: my-app
    image: my-app:latest

默认 ServiceAccount

# 每个命名空间都有默认的 ServiceAccount
kubectl get serviceaccounts default -n default

# Pod 默认使用 default ServiceAccount
# 如果未指定 serviceAccountName,自动使用 default

ServiceAccount Token

# 查看 ServiceAccount 的 Token (Secret)
kubectl get secrets -n default | grep my-app-sa

# 查看 Token 详情
kubectl describe secret my-app-sa-token-xxxxx -n default

# Token 内容 (Base64 编码)
kubectl get secret my-app-sa-token-xxxxx -n default -o jsonpath='{.data.token}' | base64 -d

手动创建长期 Token

# 手动创建 Secret 绑定 ServiceAccount
apiVersion: v1
kind: Secret
metadata:
  name: my-app-sa-secret
  namespace: default
  annotations:
    kubernetes.io/service-account.name: my-app-sa
type: kubernetes.io/service-account-token

ServiceAccount 与 RBAC 集成

# 创建 Role
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: pod-reader
  namespace: default
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "list", "watch"]

---
# 绑定 Role 到 ServiceAccount
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: read-pods-sa
  namespace: default
subjects:
- kind: ServiceAccount
  name: my-app-sa
  namespace: default
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io

ServiceAccount 最佳实践

1. 不使用 default ServiceAccount
   - 为每个应用创建专用 ServiceAccount
   - 限制权限范围

2. 最小权限原则
   - 只授予必要的权限
   - 使用 RoleBinding 限制命名空间

3. 定期轮换 Token
   - 使用 TokenRequest API (短期 Token)
   - 避免长期 Token

4. 禁用自动挂载 Token
   - 如果 Pod 不需要访问 API,禁用 Token 挂载

禁用自动挂载 Token

# 禁用 ServiceAccount Token 自动挂载
apiVersion: v1
kind: ServiceAccount
metadata:
  name: my-app-sa
  namespace: default
automountServiceAccountToken: false

---
# 或在 Pod 中禁用
apiVersion: v1
kind: Pod
metadata:
  name: my-app
spec:
  automountServiceAccountToken: false
  containers:
  - name: my-app
    image: my-app:latest

实践练习

练习 1:创建 ServiceAccount

# 创建 ServiceAccount
apiVersion: v1
kind: ServiceAccount
metadata:
  name: app-sa
  namespace: default
# 应用
kubectl apply -f app-sa.yaml

# 查看
kubectl get sa app-sa -n default

练习 2:配置 RBAC

# 创建 Role 和 RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: configmap-reader
  namespace: default
rules:
- apiGroups: [""]
  resources: ["configmaps"]
  verbs: ["get", "list"]

---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: read-configmaps-sa
  namespace: default
subjects:
- kind: ServiceAccount
  name: app-sa
  namespace: default
roleRef:
  kind: Role
  name: configmap-reader
  apiGroup: rbac.authorization.k8s.io
# 验证权限
kubectl auth can-i list configmaps --as system:serviceaccount:default:app-sa

常见误解

1. ServiceAccount 是用户

事实:ServiceAccount 是 Pod 内进程的身份,不是人类用户
误解:ServiceAccount 可以用于人类用户访问
解决:人类用户应使用证书或 OIDC 认证

2. default ServiceAccount 足够安全

事实:default ServiceAccount 权限可能过大
误解:可以使用 default ServiceAccount
解决:为每个应用创建专用 ServiceAccount

小结

要点说明
ServiceAccountPod 内进程访问 API 的身份
与 User 区别ServiceAccount 由 K8s 管理,User 由外部系统管理
Token自动创建,用于认证
RBAC 集成通过 RoleBinding 授权
最佳实践专用 SA、最小权限、禁用自动挂载

练习编辑器

bash
Loading...

继续学习

完成本课后,建议继续学习下一课「Pod 安全」 以巩固所学知识。