Java程序调kubernetes(k8s1.30.7)core API简单示例,并解决403权限验证问题,即何进行进行权限授权以及验证

简单记录问题

一、问题描述

希望通过Java程序使用Kubernetes提供的工具包实现对Kubernetes集群core API的调用,但是在高版本上遇见权限验证问题4xx。

XML 复制代码
        <dependency>
            <groupId>io.kubernetes</groupId>
            <artifactId>client-java</artifactId>
            <version>20.0.0</version> <!-- 请根据需要选择合适的版本 -->
        </dependency>

权限验证的问题:

diff 复制代码
{
  "kind": "Status",
  "apiVersion": "v1",
  "metadata": {},
  "status": "Failure",
  "message": "pods is forbidden: User \"system:anonymous\" cannot list resource \"pods\" in API group \"\" at the cluster scope",
  "reason": "Forbidden",
  "details": {
    "kind": "pods"
  },
  "code": 403
}

大意是system:anonymous匿名用户被禁止去访问相应集群的pods资源信息。

Kubernetes支持许多不同的身份验证方案,这些方案几乎总是在集群外部实现,包括X.509证书,基本身份验证,bearer令牌,用于通过可信身份提供商进行身份验证的OpenID Connect(OIDC)等。使用API服务器上的相关配置选项可以启用多种方案,因此请务必为计划使用的身份验证方案提供这些选项。例如,X.509客户端证书身份验证需要包含一个或多个CA证书( -client-ca-file)文件路径。需要记住的一点是,默认情况下,任何未通过其中一种身份验证方案验证的API请求都会被视为匿名请求。 匿名用户(system:anonymous)默认被拒绝访问任何 API。即使是基本的 API(如列出 Pods),也需要显式分配权限,现阶段,所有 API 调用都需要经过明确的认证和授权

查看一下集群的默认验证模式设置:

bash 复制代码
grep -C3 'authorization-mode' /etc/kubernetes/manifests/kube-apiserver.yaml

默认开启的是RBAC(基于角色的访问控制)。

各类模式以及下方各类k8s资源的介绍可参见:

Kubernetes K8S之鉴权RBAC详解 - 踏歌行666 - 博客园

二、解决方案

我需要针对集群中相关资源(pods lists)通过Java client进行增删改查操作,那么最直接快速的方式就是创建一个具有集群超级用户权限的用户,并将其对应的Key用于Java client,进行API的访问操作。

Prepare:查看clusterrole

clusterrole是集群范围的角色,用于管理整个集群中的资源。

通过指令

bash 复制代码
kubectl get clusterroles

查看到集群下有众多的clusterrole

其中有cluster-admin角色,我们可以通过如下指令查看其权限:

bash 复制代码
kubectl get clusterrole cluster-admin -o yaml

我们能看出它是 Kubernetes 内置的超级权限角色,其中rules部分均为通配符,表明该角色对所有 API 组的所有资源具有所有操作权限,即为管理员提供对集群所有资源的完全控制。

具体操作

1.将用户与cluster-admin角色相绑定

bash 复制代码
kubectl create clusterrolebinding admin-access --clusterrole=cluster-admin --user=apiinvoker

2.创建serviceaccount

bash 复制代码
#serviceaccount 后接名称  
kubectl create serviceaccount apiinvoker -n kube-system

2.将serviceaccount绑定到cluster-admin

bash 复制代码
kubectl create clusterrolebinding admin-sa-binding --clusterrole=cluster-admin --serviceaccount=kube-system:apiinvoker

3.创建Token

分为临时的(选择一)以及永久的(选择二)两种方式。

选择一

下述代码能直接生成并显示token,但是该方式的token是存在有效期的。

bash 复制代码
# 需要设置有效期 添加参数--duration 其他参数使用指令kubectl -n kube-system create token --help查看
kubectl -n kube-system create token apiinvoker

选择二

要创建永久有效的Token需要使用Secret方式

在创建serviceaccount之后为其手动创建Secret,并将其与serviceaccount绑定。

  1. 创建apiinvoker-token.yaml
bash 复制代码
apiVersion: v1
kind: Secret
metadata:
  name: apiinvoker-token
  namespace: kube-system
  annotations:
    kubernetes.io/service-account.name: "apiinvoker" # 绑定到服务账户 改成你自定义的serviceaccount
type: kubernetes.io/service-account-token
  1. 运行yaml文件
bash 复制代码
kubectl apply -f apiinvoker-token.yaml

4.获取serviceaccount的Token

bash 复制代码
kubectl -n kube-system describe secret apiinvoker-token

这样就能在Java client使用这个token进行API的调用了。

5.编写Java程序代码示例

在pom中添加依赖:

XML 复制代码
        <dependency>
            <groupId>io.kubernetes</groupId>
            <artifactId>client-java</artifactId>
            <version>20.0.0</version> <!-- 请根据需要选择合适的版本 -->
        </dependency>

运行如下示例代码:

java 复制代码
package com.yang.collector;

import io.kubernetes.client.openapi.ApiClient;
import io.kubernetes.client.openapi.Configuration;
import io.kubernetes.client.openapi.apis.CoreV1Api;
import io.kubernetes.client.openapi.models.V1NamespaceList;
import io.kubernetes.client.openapi.models.V1PodList;

import java.io.IOException;

public class K8SAPITest {
    public static void main(String[] args) {
        try {

            ApiClient client = new ApiClient();
            client.setBasePath("https://k8s-master IP:6443"); // 集群的 API 地址
            client.setApiKey("Bearer "+"生成的Token");
//            client.setDebugging(true);
            client.setVerifyingSsl(false);

            Configuration.setDefaultApiClient(client);
            // 将配置设置为默认的 API 客户端
            io.kubernetes.client.openapi.Configuration.setDefaultApiClient(client);

            // 创建 CoreV1Api 实例
            CoreV1Api api = new CoreV1Api();

            // 获取所有命名空间中的 Pod 列表
            CoreV1Api.APIlistPodForAllNamespacesRequest list = api.listPodForAllNamespaces();

            V1PodList execute = list.execute();
            // 遍历并打印每个 Pod 的信息
            execute.getItems().forEach(v1Pod -> {
                System.out.println(v1Pod.toJson());
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

结果如下:

说明调用成功,克服权限验证问题。

:当然在实际的生产环境中不建议直接将 超级权限(如 cluster-admin 交给 Java 程序(或任何外部程序)。这样做存在高安全风险,可能导致集群被误操作或恶意利用。

但是使用 服务账户(ServiceAccount) 的 Token的形式进行细粒度权限控制API的调用是推荐的,本文直接赋值所有资源的所有操作权限十分不可取,仅供学习参考。

推荐方式:在生产环境中,所有权限分配都应该基于实际需求,授予 Java 程序仅需要的权限即可。创建自定义Role或ClusterRole,仅授予程序需要的权限,再通过Rolebinding或ClusterRoleBinding将权限绑定到服务账户,再将此token交给API调用程序。token的使用也不建议永久有效,通过使用kubectl create token动态生成短期 Token,供程序动态获取使用更为安全,避免了长期token的泄露风险。

参考文献

1.Kubernetes K8S之鉴权RBAC详解 - 踏歌行666 - 博客园

2.API 访问控制 | Kubernetes

3.Kubernetes集群组件的安全_手机搜狐网

相关推荐
腥臭腐朽的日子熠熠生辉28 分钟前
解决maven失效问题(现象:maven中只有jdk的工具包,没有springboot的包)
java·spring boot·maven
ejinxian30 分钟前
Spring AI Alibaba 快速开发生成式 Java AI 应用
java·人工智能·spring
杉之35 分钟前
SpringBlade 数据库字段的自动填充
java·笔记·学习·spring·tomcat
小刘爱喇石( ˝ᗢ̈˝ )39 分钟前
玛卡巴卡的k8s知识点问答题(六)
云原生·容器·kubernetes
rider18942 分钟前
【1】搭建k8s集群系列(二进制部署)之系统初始化
云原生·容器·kubernetes
圈圈编码1 小时前
Spring Task 定时任务
java·前端·spring
俏布斯1 小时前
算法日常记录
java·算法·leetcode
阳小江1 小时前
Docker知识点
运维·docker·容器
27669582921 小时前
美团民宿 mtgsig 小程序 mtgsig1.2 分析
java·python·小程序·美团·mtgsig·mtgsig1.2·美团民宿
爱的叹息1 小时前
Java 连接 Redis 的驱动(Jedis、Lettuce、Redisson、Spring Data Redis)分类及对比
java·redis·spring