专业的JAVA编程教程与资源

网站首页 > java教程 正文

Java如何从pod内部访问k3s集群API

temp10 2025-08-05 21:05:36 java教程 1 ℃ 0 评论

最近项目需要开发一个功能,需要监控 k3s 集群上每个应用的状态。因为 k3s 和 k8s 核心功能是一样的,我们可以通过 k8s 的 API 得到这些信息,而且官方也提供了 io.kubernetes 的 client-java ,所以使用这个 SDK 包就能通过 java 代码的方式获取到数据。

那么事不宜迟,马上动手开发吧!

Java如何从pod内部访问k3s集群API

首先,当然是在 pom.xml 引入 io.kubernetes 的 client-java。

<dependency>
    <groupId>io.kubernetes</groupId>
    <artifactId>client-java</artifactId>
    <version>10.0.0</version>
</dependency>


然后是初始化API的客户端,有三种方式。

第一种最简单的方式:使用 ClientBuilder.cluster().build() 直接进行初始化

@Slf4j
@Component
public classK3sClient{

    /**
     * 初始化API客户端
     */
    @PostConstruct
    privatevoidsetDefaultApiClient()throws IOException {
        // 自动获取配置初始化
        ApiClient apiClient = ClientBuilder.cluster().build();
        // 创建操作类
        Configuration.setDefaultApiClient(apiClient);
    }

    /**
     * 获取所有的Pod
     *
     * @return podList
     */
    public V1PodList getAllPodList(){
        CoreV1Api api = new CoreV1Api();
        try {
            V1PodList list = api.listPodForAllNamespaces(null, null, null, null, null, null, null, null, null, null);
            return list;
        } catch (ApiException e) {
            log.error("获取podlist异常:" + e.getResponseBody(), e);
        }
        return null;
    }
}


第二种方式:读取 k3s 的配置文件进行初始化 ApiClient

@Slf4j
@Component
public classK3sClient{

    //pod内部指定存放k3s配置文件的路径
    @Value("${k3sConf.path}")
    private String k3sConfigPath;

    /**
     * 初始化API客户端
     */
    @PostConstruct
    privatevoidsetDefaultApiClient()throws IOException {
        KubeConfig conf = KubeConfig.loadKubeConfig(new FileReader(k3sConfigPath));
        ApiClient apiClient = ClientBuilder.kubeconfig(conf).build();

        // 创建操作类
        Configuration.setDefaultApiClient(apiClient);
    }

    /**
     * 获取所有的Pod
     *
     * @return podList
     */
    public V1PodList getAllPodList(){
        CoreV1Api api = new CoreV1Api();
        try {
            V1PodList list = api.listPodForAllNamespaces(null, null, null, null, null, null, null, null, null, null);
            return list;
        } catch (ApiException e) {
            log.error("获取podlist异常:" + e.getResponseBody(), e);
        }
        return null;
    }
}

k3s 集群的配置文件可以从宿主机挂到Pod内部的指定路径,最好挂的时候设置为只读权限,以免因为代码的问题误修改了配置文件导致k3s出问题。


接下来测试一下,看看能否成功初始化。

从结果可以看出初始化失败,从报错信息中可以看出连接 k3s 集群的IP是127.0.0.1,显然是不对的。因为初始化配置读的是配置文件,肯定是配置文件的问题。

那么从pod内部访问k3s集群的IP该怎么获取呢?我们可以进入pod内部查看环境变量可以发现。


那么只要对 KubeConfig 的 server 配置修改成 pod 内部能访问的 k3s 集群的 IP 和端口即可。可惜 KubeConfig 并不提供修改 server 的方法,那么我们可以参考源码的方式进行初始化。

@Slf4j
@Component
public classK3sClient{
    //pod内部指定存放k3s配置文件的路径
    @Value("${k3sConf.path}")
    private String k3sConfigPath;

    /**
     * 初始化API客户端
     */
    @PostConstruct
    private void setDefaultApiClient() throws IOException {
        Yaml yaml = new Yaml(new SafeConstructor());
        Object config = yaml.load(new FileReader(k3sConfigPath));

        Map<String, Object> configMap = (Map)config;
        String currentContext = (String)configMap.get("current-context");
        ArrayList<Object> contexts = (ArrayList)configMap.get("contexts");
        ArrayList<Object> clusters = (ArrayList)configMap.get("clusters");

        // 替换server地址
        Map<String, Object> map = findObject(clusters, "default");
        if (map != null) {
            Map<String, Object> cluster = (Map)map.get("cluster");
            cluster.put("server", String.format("https://%s:%s", System.getenv("KUBERNETES_SERVICE_HOST"),
                    System.getenv("KUBERNETES_SERVICE_PORT")));
        }

        ArrayList<Object> users = (ArrayList)configMap.get("users");
        Object preferences = configMap.get("preferences");

        // 以config作为入参创建的client对象,可以访问到K8S的API Server
        KubeConfig kubeConfig = new KubeConfig(contexts, clusters, users);
        kubeConfig.setContext(currentContext);
        kubeConfig.setPreferences(preferences);

        ApiClient client = ClientBuilder.kubeconfig(kubeConfig).build();

        // 创建操作类
        Configuration.setDefaultApiClient(client);
    }

    private Map<String, Object> findObject(ArrayList<Object> list, String name) {
        if (list == null) {
            return null;
        } else {
            Iterator var2 = list.iterator();
            Map map;
            do {
                if (!var2.hasNext()) {
                    return null;
                }
                Object obj = var2.next();
                map = (Map)obj;
            } while(!name.equals(map.get("name")));
            return map;
        }
    }

    /**
     * 获取所有的Pod
     *
     * @return podList
     */
    public V1PodList getAllPodList() {
        CoreV1Api api = new CoreV1Api();
        try {
            V1PodList list = api.listPodForAllNamespaces(null, null, null, null, null, null, null, null, null, null);
            return list;
        } catch (ApiException e) {
            log.error("获取podlist异常:" + e.getResponseBody(), e);
        }
        return null;
    }
}


第三种方式:Token 认证的方式初始化 ApiClient

k3s 集群的地址同样可以通过环境变量中获取,而 token 是存放在 Pod 内的 /var/run/secrets/kubernetes.io/serviceaccount/token 文件。此方式要确认已经为Pod 创建好 serviceAccount。

@Slf4j
@Component
public classK3sClient{

    //ApiServer地址
    @Value("${k3s.apiServer}")
    private String k3sApiServer;

    //请求Token
    @Value("${k3s.token}")
    private String k3sToken;

    //是否本机k3s集群
    @Value("${k3s.local}")
    private Boolean isK3sLocal;

    /**
     * 初始化API客户端
     */
    @PostConstruct
    privatevoidsetDefaultApiClient()throws IOException {
        if (isK3sLocal) {
            // 本机k3s集群地址
            k3sApiServer = String.format("https://%s:%s", System.getenv("KUBERNETES_SERVICE_HOST"),
                    System.getenv("KUBERNETES_SERVICE_PORT"));

            // 获取Token
            FileReader fr = new FileReader("/var/run/secrets/kubernetes.io/serviceaccount/token");
            BufferedReader br = new BufferedReader(fr);
            k3sToken = br.readLine();
            br.close();
        }

        ApiClient client = new ClientBuilder().setBasePath(k3sApiServer).setVerifyingSsl(false)
                .setAuthentication(new AccessTokenAuthentication(k3sToken)).build();

        // 创建操作类
        Configuration.setDefaultApiClient(apiClient);
    }

    /**
     * 获取所有的Pod
     *
     * @return podList
     */
    public V1PodList getAllPodList(){
        CoreV1Api api = new CoreV1Api();
        try {
            V1PodList list = api.listPodForAllNamespaces(null, null, null, null, null, null, null, null, null, null);
            return list;
        } catch (ApiException e) {
            log.error("获取podlist异常:" + e.getResponseBody(), e);
        }
        return null;
    }
}

通过这几种方式,我们就可以从 pod 内部访问 k3s 集群 API 了。其实客户端初始化使用 ClientBuilder.cluster().build() 是最简单的,刚开始时我为了读配置文件还绕了个大弯,很多东西官方其实早就为用户考虑到了,所以使用之前要多看看官方文档。


下期给大家分享如何简单使用pysyncobj,敬请期待~

欢迎各位关注、留言,大家的支持就是我的动力!

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表