【Kubernetes】服务账号 Service Account

K8s 的安全认证》系列,共包含以下文章:

😊 如果您觉得这篇文章有用 ✔️ 的话,请给博主一个一键三连 🚀🚀🚀 吧 (点赞 🧡、关注 💛、收藏 💚)!!!您的支持 💖💖💖 将激励 🔥 博主输出更多优质内容!!!

服务账号Service Account)是为了方便 Pod 中的进程调用 Kubernetes API 资源或访问其他外部服务而设计的。

1.服务账号与用户账号

服务账号Service Account)和 用户账号User Account)有着以下的不同:

  • 服务账号 是为 Pod 而设计的,目的是让 Pod 中的进程能够访问 Kubernetes APl 的资源;用户账号 是为用户而设计的,目的是让用户能够访问 Kubernetes 集群。
  • 服务账号 仅作用在当前的命名空间中;用户账号 是全局性的,可以跨越不同的命名空间。
  • 服务账号 的创建应遵循权限最小化的原则,Kubernetes 允许为实现某个具体任务而创建服务账号;而创建 用户账号 通常需要使用外部的数据库,且可能需要组合不同的权限。
  • 服务账号 属于轻量级配置,只作用在当前命名空间中,因此,在一个复杂系统中可能包含各种服务账号的定义;用户账号 的创建规则比较复杂,且可能涉及复杂的业务流程。由于服务账号和用户账号的使用对象不同,因此对二者的监控也不同。

2.【实战】创建和使用服务账号

下面来演示如何创建和使用服务账号。

2.1 创建命名空间

创建一个新的命名空间 sa-demo

kubectl create namespace sa-demo

查看新命名空间中的 Service Account。

kubectl get sa -n sa-demo

输出的信息如下:

在这里插入图片描述

🚀 对于每一个命名空间会自动创建一个默认的 Service Account。

2.2 创建 Pod

编辑 pod-sa-demo1.yaml 文件在新创建的命名空间中新建一个 Pod。

kind: Pod
apiVersion: v1
metadata:
  name: pod-sa-demo1
  namespace: sa-demo
spec:
  containers:
  - name: nginx
    image: nginx
    imagePullPolicy: IfNotPresent
    ports:
     - containerPort: 80
       name: http

创建 Pod,并查看 Pod 的信息。

kubectl apply -f pod-sa-demo1.yaml
kubectl get pod pod-sa-demo1 -o yaml -n sa-demo

输出的信息如下:

在这里插入图片描述

🚀 可以看出,对于每一个新创建的 Pod 来说,如果没有指定 Service Account,则它会自动挂载默认的 Service Acount,即其值为 default

2.3 创建 Service Account

sa-demo 命名空间中创建一个名称为 mysa 的 Service Account,并查看当前命名空间中存在的 Service Account。

kubectl create serviceaccount mysa -n sa-demo
kubectl get sa -n sa-demo

输出的信息如下:

在这里插入图片描述

查看新创建的 Service Account。

kubectl get serviceaccount mysa -n sa-demo -o yaml

在这里插入图片描述

🚀 在 Service Account 创建成功后,可以使用 RoleBinding 将 Service Account 与 Role 进行绑定,使用 ClusterRoleBinding 将 ServiceAccount 与 ClusterRole 进行绑定。

在这里插入图片描述

2.4 使用 RoleBinding 将 Service Account 与 Role 进行绑定

编辑 sa-demo-role.yaml 文件创建 Role。

kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  #限定可访问的命名空间为sa-demo
  namespace: sa-demo
  #角色名称
  name: sa-demo-role
rules:
  #空字符串表示使用core API group
- apiGroups: [""]
  resources: ["namespaces","pods","pods/log"]
  verbs: ["get", "watch", "list", "create", "update", "patch", "delete"]
- apiGroups: [ "apps"]
  resources: ["deployments", "daemonsets"]
  verbs: ["get", "list", "watch"]

编辑 sa-demo-rolebinding.yaml 文件创建 RoleBinding。

kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  namespace: sa-demo
  name: sa-demo-rolebinding
subjects:
- kind: ServiceAccount
  namespace: sa-demo
  # Service Account的名称
  name: mysa
roleRef:
  kind: Role
  # 角色名称
  name: sa-demo-role
  apiGroup: rbac.authorization.k8s.io

🚀 这里将命名空间 sa-demo 中名为 mysa 的 Service Account 绑定到 sa-demo-role 角色上了。

创建 Role 和 RoleBinding。

kubectl apply -f sa-demo-role.yaml
kubectl apply -f sa-demo-rolebinding.yaml

查看 sa-demo 命名空间中的 Role 和 RoleBinding。

kubectl get role,rolebinding -n sa-demo -o wide

输出的信息如下:

在这里插入图片描述

🚀 从输出信息可以看出,命名空间中的 mysa 服务账号通过 sa-demo-rolebinding 绑定到 sa-demo-role 了。

2.5 使用 ClusterRoleBinding 将 ServiceAccount 与 ClusterRole 进行绑定

编辑 sa-demo-clusterrole.yaml 文件创建 ClusterRole。

kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  # 由于ClusterRole针对的是集群范围对象,因此不需要定义namespace字段
  name: sa-demo-clusterrole
rules:
  # 空字符串""表明使用core API group
- apiGroups: ["rbac.authorization.k8s.io",""]
  resources: ["pods","pods/log"]
  verbs: ["get", "watch", "list"]
- apiGroups: ["apps"]
  resources: ["namespaces"]
  verbs: ["get", "list", "watch"]

编辑 sa-demo-clusterrolebinding.yaml 文件创建 ClusterRoleBinding。

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: sa-demo-clusterrolebinding
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: sa-demo-clusterrole
subjects:
- apiGroup: ""
  kind: ServiceAccount
  namespace: sa-demo
  name: mysa

创建 ClusterRole 和 ClusterRoleBinding。

kubectl apply -f sa-demo-clusterrole.yaml
kubectl apply -f sa-demo-clusterrolebinding.yaml

🚀 这里将命名空间 sa-demo 中名为 mysa 的 Servicc Account 绑定到 sa-demo-clusterrole 角色上了。

查看 ClusterRole 的信息。

kubectl get clusterrole

输出的信息如下:

在这里插入图片描述

查看 ClusterRoleBinding 的信息。

kubectl describe clusterrolebinding sa-demo-clusterrolebinding

在这里插入图片描述

另外一种查询方法:

kubectl get clusterrolebinding -o \
custom-columns=NAME:.metadata.name,ROLE:.roleRef.name,SERVICEACCOUNT:.subjects[0].name | grep sa-demo

在这里插入图片描述

3.服务账号的工作机制

Kubernetes 的 APl Service 默认开启了 Service Account 的准入控制功能。因此,在创建 Service Account 后,服务账号将按照以下方式运行。

🚀 如果 API Server 没有启用 Service Account 的准入控制功能,则可以在启动 API Server 时加入以下参数:--admission_control-ServiceAccount

  • 1️⃣ 在 Pod 创建时,通过 spec.serviceAccount 字段挂载指定的 Service Account。如果没有指定该字段,则挂载命名空间中的默认 Service Account,即 default 的 Service Account。
  • 2️⃣ API Server 验证挂载的 Service Account 是否存在。如果存在,则创建 Pod;否则拒绝创建 Pod。
  • 3️⃣ 如果在 Pod 中没有指定 ImagePullSecrets,则把 Service Account 中的 ImagePullSecrets 字段加载到 Pod 中。

🚀 在拉取私有镜像仓库中的镜像时,往往需要先进行用户认证。ImagePullSecrets 字段用于指定拉取镜像时用户的 Secret 信息。

  • 4️⃣ 在 Pod 创建成功并启动容器后,会将 Service Account 的 Token 挂载到 /var/run/secrets/kubernetes.io/serviceaccount/ 目录下。

🚀 可以通过 kubectl describe pod 命令查看到挂载的信息。

<think>我们正在使用fabric8 Kubernetes客户端(5.12.4版本)来获取Pod IP,但遇到了“Forbidden! Configured service account doesn't have access”错误。这表明当前Pod使用的服务账号ServiceAccount)没有足够的权限来获取Pod信息。下面我们将一步步解决这个问题。 ### 1. **确认服务账号和权限** 首先,我们需要确认当前Pod使用的服务账号以及该账号是否具有获取Pod信息的权限。 - 默认情况下,Pod使用`default`服务账号,但可能没有足够的权限。 - 我们可以通过创建RBAC(Role-Based Access Control)规则来授予服务账号必要的权限。 ### 2. **创建RBAC规则** 我们需要为服务账号创建一个`Role`(或`ClusterRole`)和`RoleBinding`(或`ClusterRoleBinding`)来授予访问Pod的权限。 **示例YAML文件(rbac.yaml)**: ```yaml # 创建一个Role,允许获取Pod信息 apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: namespace: your-namespace # 替换为你的命名空间 name: pod-reader rules: - apiGroups: [""] resources: ["pods"] # 资源类型为pods verbs: ["get", "list", "watch"] # 授予的权限 --- # 将Role绑定到服务账号(例如default) apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: read-pods namespace: your-namespace subjects: - kind: ServiceAccount name: default # 服务账号名称,通常为default namespace: your-namespace roleRef: kind: Role name: pod-reader apiGroup: rbac.authorization.k8s.io ``` 应用这个配置: ```bash kubectl apply -f rbac.yaml ``` > 注意:如果你需要跨命名空间访问Pod,则应该使用`ClusterRole`和`ClusterRoleBinding`[^4]。 ### 3. **在代码中使用fabric8客户端** 确保你的代码正确使用了服务账号的token。在Pod内部,fabric8客户端会自动使用挂载的token来访问Kubernetes API。 **Java代码示例(使用fabric8客户端)**: ```java import io.fabric8.kubernetes.api.model.Pod; import io.fabric8.kubernetes.api.model.PodList; import io.fabric8.kubernetes.client.DefaultKubernetesClient; import io.fabric8.kubernetes.client.KubernetesClient; public class PodIPFetcher { public static void main(String[] args) { try (KubernetesClient client = new DefaultKubernetesClient()) { // 获取指定命名空间中的所有Pod PodList podList = client.pods().inNamespace("your-namespace").list(); for (Pod pod : podList.getItems()) { System.out.println("Pod Name: " + pod.getMetadata().getName() + " IP: " + pod.getStatus().getPodIP()); } } } } ``` - 当在Pod中运行时,`DefaultKubernetesClient`会自动使用Pod内的服务账号token(通过`/var/run/secrets/kubernetes.io/serviceaccount`目录挂载)。 ### 4. **检查服务账号挂载** 确保你的Pod配置中已经挂载了服务账号的token。通常,这是默认行为,但可以通过以下方式检查: **Pod配置示例**: ```yaml apiVersion: v1 kind: Pod metadata: name: my-app spec: serviceAccountName: default # 使用default服务账号,也可以指定自定义账号 automountServiceAccountToken: true # 确保自动挂载token(默认为true) containers: - name: main image: my-java-app:latest ``` ### 5. **验证权限** 在应用RBAC规则后,我们可以验证服务账号是否具有所需权限: ```bash kubectl auth can-i get pods --as=system:serviceaccount:your-namespace:default ``` 如果返回`yes`,则表示权限已生效。 ### 6. **常见问题排查** - **权限未生效**:RBAC更改可能需要几秒钟才能生效,请稍等重试。 - **Token未挂载**:检查Pod的描述信息(`kubectl describe pod <your-pod>`),查看是否有关于服务账号挂载的错误。 - **跨命名空间访问**:如果你需要访问其他命名空间的Pod,请使用`ClusterRole`和`ClusterRoleBinding`。 - **Kubernetes版本**:确保你的Kubernetes集群版本支持RBAC(1.6+版本默认启用)。 ### 7. **使用fabric8客户端的注意事项** - 确保你的项目依赖了正确版本的fabric8客户端(本例中为5.12.4): ```xml <dependency> <groupId>io.fabric8</groupId> <artifactId>kubernetes-client</artifactId> <version>5.12.4</version> </dependency> ``` - 如果使用Spring Boot等框架,注意依赖冲突问题。 通过以上步骤,你应该能够解决使用fabric8 Kubernetes客户端获取Pod IP时的权限问题。如果问题仍然存在,请检查集群的RBAC设置和日志以获取更多信息。 §§相关问题§§ 1. 如何在Kubernetes中创建自定义服务账号? 2. fabric8 Kubernetes客户端与官方客户端的主要区别是什么? 3. 如何调试Kubernetes API的权限问题?</think>### 解决 Fabric8 Kubernetes 客户端获取 Pod IP 时的权限问题 当使用 Fabric8 Kubernetes 客户端(5.12.4 版本)获取 Pod IP 遇到 `Forbidden! Configured service account doesn't have access` 错误时,根本原因是当前服务账号缺少必要的 RBAC 权限。以下是完整的解决方案: --- ### 解决方案步骤 #### 1. **创建 RBAC 权限规则** 在目标命名空间创建 Role 和 RoleBinding(示例使用 `your-namespace`): ```yaml # pod-reader-role.yaml apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: namespace: your-namespace name: pod-reader rules: - apiGroups: [""] resources: ["pods"] # 授予访问 Pod 资源的权限 verbs: ["get", "list", "watch"] # 必需的操作权限 --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: read-pods namespace: your-namespace subjects: - kind: ServiceAccount name: default # 绑定到默认服务账号 namespace: your-namespace roleRef: kind: Role name: pod-reader apiGroup: rbac.authorization.k8s.io ``` 应用配置: ```bash kubectl apply -f pod-reader-role.yaml ``` > 注意:如果需跨命名空间访问,改用 `ClusterRole` 和 `ClusterRoleBinding`[^4] #### 2. **验证服务账号权限** ```bash # 检查 default 账号是否具有 Pod 读取权限 kubectl auth can-i get pods \ --as=system:serviceaccount:your-namespace:default \ -n your-namespace ``` 返回 `yes` 表示权限生效 #### 3. **Java 代码示例(Fabric8 5.12.4)** 确保使用正确的服务账号凭据: ```java import io.fabric8.kubernetes.api.model.Pod; import io.fabric8.kubernetes.api.model.PodList; import io.fabric8.kubernetes.client.DefaultKubernetesClient; import io.fabric8.kubernetes.client.KubernetesClient; public class PodIPFetcher { public static void main(String[] args) { try (KubernetesClient client = new DefaultKubernetesClient()) { // 获取指定命名空间的 Pod PodList podList = client.pods() .inNamespace("your-namespace") .list(); // 提取 Pod IP for (Pod pod : podList.getItems()) { String ip = pod.getStatus().getPodIP(); System.out.println( "Pod: " + pod.getMetadata().getName() + " | IP: " + ip ); } } catch (Exception e) { System.err.println("Error: " + e.getMessage()); } } } ``` #### 4. **关键配置检查** 在部署配置中确保: ```yaml spec: serviceAccountName: default # 显式指定服务账号 automountServiceAccountToken: true # 必须启用 token 挂载 ``` #### 5. **依赖确认(Maven)** ```xml <dependency> <groupId>io.fabric8</groupId> <artifactId>kubernetes-client</artifactId> <version>5.12.4</version> <!-- 指定正确版本 --> </dependency> ``` --- ### 常见问题排查 1. **权限延迟**:RBAC 变更需 1-2 分钟生效 2. **Token 挂载失败**: ```bash kubectl describe pod your-pod-name | grep Mounts ``` 检查是否包含 `serviceaccount token` 3. **跨命名空间问题**: - 使用 `ClusterRole` 替代 `Role` - 在 `ClusterRoleBinding` 中指定命名空间 4. **客户端认证问题**: ```java // 调试模式查看认证信息 System.getenv("KUBERNETES_SERVICE_HOST"); System.getenv("KUBERNETES_SERVICE_PORT"); ``` --- ### Fabric8 客户端最佳实践 1. **资源清理**:使用 `try-with-resources` 确保客户端关闭 2. **错误处理**:捕获 `KubernetesClientException` 处理特定错误 3. **版本兼容**:定期检查[客户端兼容性矩阵](https://github.com/fabric8io/kubernetes-client#compatibility-matrix) > 提示:生产环境建议创建专用服务账号(非 default)并分配最小权限
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大数据与AI实验室

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值