提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

提示:这里可以添加本文要记录的大概内容:

在K8s平台上,我们可以使用kubectl命令对Deployment、pod、Service等资源进行增删改查。本文章将提供一些Java代码操作API方式实现与集群交互,来创建、更新、删除和查询资源。


一、准备工作

1、Maven依赖

        <!--k8s集群依赖-->
        <dependency>
            <groupId>io.kubernetes</groupId>
            <artifactId>client-java</artifactId>
            <version>7.0.0</version>
        </dependency>

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

2、配置文件

import io.kubernetes.client.openapi.ApiClient;
import io.kubernetes.client.util.ClientBuilder;
import io.kubernetes.client.util.credentials.AccessTokenAuthentication;

import java.io.IOException;

public class KubernetesConfig {
    // 返回client,默认使用这个方法
    public static ApiClient defaultClient() throws IOException {

        /*
         * 机器配置
         * */

		// IP:默认端口
        String master = "https://192.168.0.200:6443";
        // 会很长
        String oauthToken = "eyJhbXXX...............XXXXXXXXXXXXXXXXX";

        ApiClient apiClient = new ClientBuilder()
                //设置 k8s 服务所在 ip地址
                .setBasePath(master)
                //是否开启 ssl 验证
                .setVerifyingSsl(false)
                //插入访问 连接用的 Token
                .setAuthentication(new AccessTokenAuthentication(oauthToken))
                .build();
        io.kubernetes.client.openapi.Configuration.setDefaultApiClient(apiClient);
        return apiClient;
    }
}

2.1、tonken获取

可以借助dashboard用户token,获取同样的结果

# 创建用户
kubectl create serviceaccount dashboard-admin -n kube-system

# 用户授权
kubectl create clusterrolebinding dashboard-admin --clusterrole=cluster-admin --serviceaccount=kube-system:dashboard-admin

# # 获取用户Token
kubectl describe secrets -n kube-system $(kubectl -n kube-system get secret | awk '/dashboard-admin/{print $1}')

在这里插入图片描述

二、deployMent

1、创建deployment

import io.kubernetes.client.openapi.ApiClient;
import io.kubernetes.client.openapi.ApiException;
import io.kubernetes.client.openapi.Configuration;
import io.kubernetes.client.openapi.apis.AppsV1Api;
import io.kubernetes.client.openapi.models.*;
import io.kubernetes.client.util.Config;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

public class createNamespacedDeployment {

    public static void createNamespacedDeployment() throws IOException {

        // 连接交互
        ApiClient client = Config.defaultClient();
        Configuration.setDefaultApiClient(client);
        AppsV1Api apiInstance = new AppsV1Api(client);

        //命名空间
        String namespace = "default";
        String name = "depDemo";

        // Service.Spec.Selector下的值
        Map<String, String> selectLabels = new HashMap<>();
        selectLabels.put("app", name);

        // 构建deployment
        V1Deployment body = new V1DeploymentBuilder()
                .withMetadata(new V1ObjectMetaBuilder()
                        .withName(name) // 容器名称
                        .withNamespace(namespace)   // 命名空间
                        .withLabels(selectLabels)   // 标签参数
                        .build())
                .withSpec(new V1DeploymentSpecBuilder()
                        .withReplicas(1)    // 设置默认副本数
                        //设置选择器
                        .withSelector(new V1LabelSelectorBuilder()
                                .withMatchLabels(selectLabels)
                                .build())
                        .withTemplate(new V1PodTemplateSpecBuilder()
                                .withMetadata(new V1ObjectMetaBuilder()
                                        .withLabels(selectLabels)   //选择器
                                        .build())
                                .withSpec(new V1PodSpecBuilder()
                                        .withContainers(new V1ContainerBuilder()
                                                .withName("redisDeployment")  //设置docker名
                                                .withImage("redis:latest")    //docker镜像名
                                                .withImagePullPolicy("IfNotPresent")    // 镜像拉取策略
                                                .build())
                                        .build())
                                .build())
                        .build())
                .build();

        //定义返回结果
        Map<String, String> messages = new HashMap<>();

        try {
            // 发送请求
            V1Deployment result = apiInstance.createNamespacedDeployment(namespace, body, null, null, null);//调用createNamespacedDeployment方法创建容器部署
            System.out.println(result);
        } catch (ApiException e) {

            if (e.getCode() == 409) {
                messages.put("error", "工作负载创建已重复!");
            } else if (e.getCode() == 200) {
                messages.put("success", "工作负载创建成功!");
            } else if (e.getCode() == 201) {
                messages.put("error", "工作负载创建已重复!");
            } else if (e.getCode() == 401) {
                messages.put("error", "无权限操作!");
            } else {
                messages.put("error", "工作负载创建失败!");
            }
        }

        System.out.println("最终结果----" + messages);
    }

2、删除deployment

import io.kubernetes.client.openapi.ApiClient;
import io.kubernetes.client.openapi.ApiException;
import io.kubernetes.client.openapi.Configuration;
import io.kubernetes.client.openapi.apis.AppsV1Api;
import io.kubernetes.client.openapi.models.*;
import io.kubernetes.client.util.Config;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

    /**
     * 删除对应的容器部署
     * 默认命名空间下-default
     *
     */
    public static void deleteDeployment(String deployName) {

        ApiClient client = null;
        try {
            client = Config.defaultClient();
        } catch (IOException e) {
            System.out.println("集群连接失败!!!");
            throw new RuntimeException(e);
        }
        AppsV1Api apiInstance = new AppsV1Api(client);
        Map<String, String> messages = new HashMap<>();

        //deployment 名称    命名空间   控制
        try {
            V1Status v1Status = apiInstance.deleteNamespacedDeployment(deployName, "default", null, null, null, null, null, null);
            System.out.println("v1Status-->>>" + v1Status);
        } catch (ApiException e) {
            System.out.println("e->>>>" + e.getCode());
            if (e.getCode() == 404) {
                messages.put("error", "工作负载删除失败,请检查参数是否正确!");
            } else if (e.getCode() == 409) {
                messages.put("error", "工作负载删除已重复!");
            } else if (e.getCode() == 200) {
                messages.put("success", "工作负载删除成功!");
            } else if (e.getCode() == 201) {
                messages.put("error", "工作负载删除已重复!");
            } else if (e.getCode() == 401) {
                messages.put("error", "无权限操作!");
            } else {
                messages.put("error", "工作负载删除失败!");
            }
        }

    }

3、查询deployment

import io.kubernetes.client.openapi.ApiClient;
import io.kubernetes.client.openapi.ApiException;
import io.kubernetes.client.openapi.Configuration;
import io.kubernetes.client.openapi.apis.AppsV1Api;
import io.kubernetes.client.openapi.models.V1DeploymentList;
import io.kubernetes.client.util.Config;

import java.io.IOException;

public class K8sDemo {

    public static void main(String[] args) throws IOException {
        try {
            // 加载kubeconfig文件
            ApiClient client = Config.defaultClient();
            Configuration.setDefaultApiClient(client);

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

            // 指定命名空间
            String namespace = "default";

            // 查询指定命名空间下的所有Deployment
            V1DeploymentList deploymentList = api.listNamespacedDeployment(namespace, null, null, null, null, null, null, null, null, null);

            // 输出查询结果
            System.out.println("Deployments in namespace " + namespace + ":");
            deploymentList.getItems().forEach(deployment -> System.out.println(deployment.getMetadata().getName()));

        } catch (ApiException e) {
            System.err.println("Exception when calling AppsV1Api#listNamespacedDeployment: " + e.getMessage());
        }
    }
}

三、Pod

1、创建pod

package com.k8s.k8s_demo_chained.server.csdn;

import com.k8s.k8s_demo_chained.config.Config;
import io.kubernetes.client.custom.Quantity;
import io.kubernetes.client.openapi.ApiClient;
import io.kubernetes.client.openapi.ApiException;
import io.kubernetes.client.openapi.Configuration;
import io.kubernetes.client.openapi.apis.CoreV1Api;
import io.kubernetes.client.openapi.models.*;

import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class CodePod2 {


    public static void main(String[] args) throws IOException {
        ApiClient client = Config.defaultClient();
        Configuration.setDefaultApiClient(client);

        CoreV1Api apiInstance = new CoreV1Api(client);

        // 构建选择器
        Map<String, String> selectLabels = new HashMap<>();
        String name = "162-3";
        selectLabels.put("deploy", name);

        // 容器暴漏端口
        List<V1ContainerPort> portList = Arrays.asList(
                new V1ContainerPort().containerPort(8080).protocol("TCP")
        );

        // 资源限制map,--默认会转换成字节
        HashMap<String, Quantity> limitsMap = new HashMap<>();
        limitsMap.put("memory", new Quantity("4Gi"));
        HashMap<String, Quantity> requestsMap = new HashMap<>();
        requestsMap.put("memory", new Quantity("4Gi"));

        // 构建Pod
        V1Pod body = new V1Pod()
                .metadata(new V1ObjectMeta()
                        .name(name) // 名称
                        .namespace("default")   //命名空间
                        .labels(selectLabels))
                .spec(new V1PodSpec()
                        .containers(Arrays.asList(new V1Container()
                                .name("nginxPod")   // 容器名称
                                .image("nginx:latest")   // 镜像名称
                                .imagePullPolicy("IfNotPresent")   // 镜像拉取策略
                                .ports(portList)    //对外暴漏接口
                                .volumeMounts(Arrays.asList(new V1VolumeMount()
                                        .name("声明挂载名称-同下")
                                        .mountPath("挂载到容器内执行目录")))
                                .resources(new V1ResourceRequirements()
                                        .limits(limitsMap)  //限制参数,构建在上面
                                        .requests(requestsMap))  //限制参数,构建在上面
                                .livenessProbe(new V1Probe()
                                        .exec(new V1ExecAction()
                                                .command(Arrays.asList("/bin/sh", "-c", "shell执行结果"))   // 存活探针-shell方式
                                        )
                                        .initialDelaySeconds(300)   // 启动后等待/秒
                                        .periodSeconds(60)         // 探测的时间间隔/秒
                                        .failureThreshold(1)        // 失败次数
                                )
                        ))
                        .restartPolicy("Never") // pod重启策略
                        .volumes(Arrays.asList(new V1Volume()
                                .name("声明挂载名称-同上")
                                .hostPath(new V1HostPathVolumeSource()
                                        .path("宿住机目录"))))   //需挂载宿住机的目录结构
                );


        //定义返回结果
        Map<String, String> messages = new HashMap<>();
        try {
            V1Pod result = apiInstance.createNamespacedPod("default", body, null, null, null);
        } catch (ApiException e) {
            if (e.getCode() == 409) {
                messages.put("error", "Pod创建已重复!");
            } else if (e.getCode() == 200) {
                messages.put("success", "Pod创建成功!");
            } else if (e.getCode() == 201) {
                messages.put("error", "Pod创建已重复!");
            } else if (e.getCode() == 401) {
                messages.put("error", "无权限操作!");
            } else {
                messages.put("error", "Pod创建失败!");
            }
        }

        System.out.println("最终结果----" + messages);
    }

}

2、删除pod

import com.k8s.k8s_demo_chained.config.Config;
import io.kubernetes.client.custom.Quantity;
import io.kubernetes.client.openapi.ApiClient;
import io.kubernetes.client.openapi.ApiException;
import io.kubernetes.client.openapi.Configuration;
import io.kubernetes.client.openapi.apis.CoreV1Api;
import io.kubernetes.client.openapi.models.*;
import okhttp3.Response;
import okhttp3.ResponseBody;

import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class DeletePod {
    public static void main(String[] args) throws IOException {
        ApiClient client = Config.defaultClient();
        Configuration.setDefaultApiClient(client);
        CoreV1Api apiInstance = new CoreV1Api(client);
        try {
            // 删除pod    pod名称    命名空间
            apiInstance.deleteNamespacedPodCall("162-3", "default", null, null, null, null, null, null, null).execute();

        } catch (ApiException e) {
        	System.out.println(e);
        }
    }

}

3、查询Pod

import io.kubernetes.client.openapi.ApiClient;
import io.kubernetes.client.openapi.ApiException;
import io.kubernetes.client.openapi.Configuration;
import io.kubernetes.client.openapi.apis.CoreV1Api;
import io.kubernetes.client.openapi.models.V1PodList;
import io.kubernetes.client.util.Config;

import java.io.IOException;

public class K8sDemo {
    public static void main(String[] args) throws IOException {
        try {
            // 加载kubeconfig文件
            ApiClient client = Config.defaultClient();
            Configuration.setDefaultApiClient(client);

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

            // 指定命名空间
            String namespace = "default";

            // 查询指定命名空间下的所有Pod
            V1PodList podList = api.listNamespacedPod(namespace, null, null, null, null, null, null, null, null, null);

            // 输出查询结果
            System.out.println("Pods in namespace " + namespace + ":");
            podList.getItems().forEach(pod -> System.out.println(pod.getMetadata().getName()));
        } catch (ApiException e) {
            System.err.println("Exception when calling CoreV1Api#listNamespacedPod: " + e.getMessage());
        }
    }
}

四、Sevice

1、创建Serivce

import com.k8s.k8s_demo_chained.config.Config;
import io.kubernetes.client.custom.IntOrString;
import io.kubernetes.client.openapi.ApiClient;
import io.kubernetes.client.openapi.ApiException;
import io.kubernetes.client.openapi.apis.CoreV1Api;
import io.kubernetes.client.openapi.models.*;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class CodeServe {

    public static void main(String[] args) throws IOException {
        ApiClient client = Config.defaultClient();
        CoreV1Api coreV1Api = new CoreV1Api(client);


        //端口暴露服务的对应的是 Service.Spec.Selector下的值
        Map<String, String> selectLabels = new HashMap<>();
        String name = "162-3";
        String serviceName = "service-162-3";
        selectLabels.put("deploy", name);

// 创建 V1ServicePortBuilder 对象列表
        List<V1ServicePortBuilder> portBuilders = new ArrayList<>();

        // 添加端口构建器到列表中
        portBuilders.add(new V1ServicePortBuilder()
                .withProtocol("TCP")
                .withPort(8080)
                .withTargetPort(new IntOrString(8080))  //目标接口
                .withNodePort(30880));  // 对外网暴漏端口

        // 使用 Stream API 将 portBuilders 列表转换为 servicePorts 列表
        List<V1ServicePort> servicePorts = portBuilders.stream()
                .map(V1ServicePortBuilder::build)
                .collect(Collectors.toList());


        V1Service body = new V1ServiceBuilder()
                .withMetadata(new V1ObjectMetaBuilder()
                        .withName("网络名称") //DNS-1035
                        .withNamespace("default")   //命名空间
                        .build())
                .withSpec(new V1ServiceSpecBuilder()
                        .withType("NodePort") // 设置服务类型为NodePort
                        .withSelector(selectLabels) // 设置选择器
                        .withPorts(servicePorts)
                        .build())
                .build();


        //定义返回结果
        Map<String, String> messages = new HashMap<>();
        try {
            coreV1Api.createNamespacedService("default", body, null, null, null);
            messages.put("success", "网络创建成功!");
        } catch (ApiException e) {
            System.out.println(e);
            if (e.getCode() == 409) {
                messages.put("error", "网络创建已重复!");
            } else if (e.getCode() == 200) {
                messages.put("success", "网络创建成功!");
            } else if (e.getCode() == 201) {
                messages.put("error", "网络创建已重复!");
            } else if (e.getCode() == 401) {
                messages.put("error", "无权限操作!");
            } else {
                messages.put("error", "网络创建失败!");
            }
        }

        System.out.println("最终结果----" + messages);
    }
}

2、删除Serivce

package com.k8s.k8s_demo_chained.server.csdn;

import com.k8s.k8s_demo_chained.config.Config;
import io.kubernetes.client.openapi.ApiClient;
import io.kubernetes.client.openapi.ApiException;
import io.kubernetes.client.openapi.Configuration;
import io.kubernetes.client.openapi.apis.CoreV1Api;
import io.kubernetes.client.openapi.models.V1Status;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

public class DeleteService {

    public static void main(String[] args) throws IOException {
        ApiClient client = Config.defaultClient();
        Configuration.setDefaultApiClient(client);
        CoreV1Api apiInstance = new CoreV1Api(client);

        Map<String, String> selectLabels = new HashMap<>();
        String name = "162-3";
        selectLabels.put("deploy", name);
        
        try {
            V1Status v1Status = apiInstance.deleteNamespacedService("service-162-3", "default", null, null, null, null, null, null);
        } catch (ApiException e) {
         System.out.println(e)
        }
    }

}

3、查询Serivce

package com.k8s.k8s_demo_chained.server.csdn;

import io.kubernetes.client.openapi.ApiClient;
import io.kubernetes.client.openapi.ApiException;
import io.kubernetes.client.openapi.Configuration;
import io.kubernetes.client.openapi.apis.CoreV1Api;
import io.kubernetes.client.openapi.models.V1ServiceList;
import io.kubernetes.client.util.Config;

import java.io.IOException;

public class K8sDemo {
    public static void main(String[] args) throws IOException {
        try {
            // 加载kubeconfig文件
            ApiClient client = Config.defaultClient();
            Configuration.setDefaultApiClient(client);

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

            // 指定命名空间
            String namespace = "default";

            // 查询指定命名空间下的所有Service
            V1ServiceList serviceList = api.listNamespacedService(namespace, null, null, null, null, null, null, null, null, null);

            // 输出查询结果
            System.out.println("Services in namespace " + namespace + ":");
            serviceList.getItems().forEach(service -> System.out.println(service.getMetadata().getName()));
        } catch (ApiException e) {
            System.err.println("Exception when calling CoreV1Api#listNamespacedService: " + e.getMessage());
        }
    }
}

四、注意事项

在每次的代码操作之前,都会使用默认的ApiClient对象,并将其设置为全局默认的ApiClient。
具体来说,Config.defaultClient()方法返回一个默认的ApiClient对象,该对象已经配置了与Kubernetes API服务器通信所需的所有参数,例如API版本、认证信息等。然后,通过调用Configuration.setDefaultApiClient(client)方法将这个ApiClient对象设置为全局默认的ApiClient,这样在后续的操作中就不需要每次都创建一个新的ApiClient对象了。
用于初始化Kubernetes Java客户端库,以便在后续的操作中使用它来与Kubernetes API服务器进行交互。
那么,都需要区分开不同操作,构建不同的API,区别如下:

  • AppsV1Api:用于管理 Kubernetes 应用程序的 API 对象,如 Deployment、StatefulSet、DaemonSet 和 ReplicaSet 等
  • BatchV1Api:用于管理 Kubernetes 批处理作业的 API 对象,如 Job 和 CronJob 等。
  • CoreV1Api:用于管理 Kubernetes 核心 API 对象,如 Pod、Service、Namespace、Node 和 PersistentVolume 等。

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐