java使用io.kubernetes.client-java调用k8s api创建pod/service/ingress示例

1.maven配置

<!-- k8s client -->
<dependency>
    <groupId>io.kubernetes</groupId>
    <artifactId>client-java</artifactId>
    <version>12.0.1</version>
</dependency>                

2.工具类

/**
 * k8s客户端
 *
 * @author wanghuidong
 * @date 2021/6/18 14:14
 */
@Slf4j
public class K8sClient {

    /**
     * k8s-api客户端
     */
    private ApiClient apiClient;

    /**
     * 构建集群POD内通过SA访问的客户端
     * loading the in-cluster config, including:
     * 1. service-account CA
     * 2. service-account bearer-token
     * 3. service-account namespace
     * 4. master endpoints(ip, port) from pre-set environment variables
     */
    public K8sClient() {
        try {
            this.apiClient = ClientBuilder.cluster().build();
        } catch (IOException e) {
            log.error("构建K8s-Client异常", e);
            throw new RuntimeException("构建K8s-Client异常");
        }
    }

    /**
     * 构建集群外通过UA访问的客户端
     * loading the out-of-cluster config, a kubeconfig from file-system
     *
     * @param kubeConfigPath kube连接配置文件
     */
    public K8sClient(String kubeConfigPath) {
        try {
            this.apiClient = ClientBuilder.kubeconfig(KubeConfig.loadKubeConfig(new FileReader(kubeConfigPath))).build();
        } catch (IOException e) {
            log.error("读取kubeConfigPath异常", e);
            throw new RuntimeException("读取kubeConfigPath异常");
        } catch (Exception e) {
            log.error("构建K8s-Client异常", e);
            throw new RuntimeException("构建K8s-Client异常");
        }
    }

    /**
     * 获取所有的Pod
     *
     * @return podList
     */
    public V1PodList getAllPodList() {
        // new a CoreV1Api
        CoreV1Api api = new CoreV1Api(apiClient);

        // invokes the CoreV1Api client
        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;
    }

    /**
     * 创建k8s service
     *
     * @param namespace   命名空间
     * @param serviceName 服务名称
     * @param port        服务端口号(和目标pod的端口号一致)
     * @param selector    pod标签选择器
     * @return 创建成功的service对象
     */
    public V1Service createService(String namespace, String serviceName, Integer port, Map<String, String> selector) {
        //构建service的yaml对象
        V1Service svc = new V1ServiceBuilder()
                .withNewMetadata()
                .withName(serviceName)
                .endMetadata()
                .withNewSpec()
                .addNewPort()
                .withProtocol("TCP")
                .withPort(port)
                .withTargetPort(new IntOrString(port))
                .endPort()
                .withSelector(selector)
                .endSpec()
                .build();

        // Deployment and StatefulSet is defined in apps/v1, so you should use AppsV1Api instead of CoreV1API
        CoreV1Api api = new CoreV1Api(apiClient);
        V1Service v1Service = null;
        try {
            v1Service = api.createNamespacedService(namespace, svc, null, null, null);
        } catch (ApiException e) {
            log.error("创建service异常:" + e.getResponseBody(), e);
        } catch (Exception e) {
            log.error("创建service系统异常:", e);
        }
        return v1Service;
    }

    /**
     * 创建k8s V1Ingress
     *
     * @param namespace   命名空间
     * @param ingressName ingress名称
     * @param annotations ingress注解
     * @param path        匹配的路径
     * @param serviceName 路由到的服务名称
     * @param servicePort 路由到的服务端口
     * @return 创建成功的ingress对象
     */
    public V1Ingress createV1Ingress(String namespace, String ingressName, Map<String, String> annotations, String path,
                                     String serviceName, Integer servicePort) {
        //构建ingress的yaml对象
        V1Ingress ingress = new V1IngressBuilder()
                .withNewMetadata()
                .withName(ingressName)
                .withAnnotations(annotations)
                .endMetadata()
                .withNewSpec()
                .addNewRule()
                .withHttp(new V1HTTPIngressRuleValueBuilder().addToPaths(new V1HTTPIngressPathBuilder()
                        .withPath(path)
                        .withPathType("Prefix")
                        .withBackend(new V1IngressBackendBuilder()
                                .withService(new V1IngressServiceBackendBuilder()
                                        .withName(serviceName)
                                        .withPort(new V1ServiceBackendPortBuilder()
                                                .withNumber(servicePort).build()).build()).build()).build()).build())
                .endRule()
                .endSpec()
                .build();

        //调用对应的API执行创建ingress的操作
        NetworkingV1Api api = new NetworkingV1Api(apiClient);
        V1Ingress v1Ingress = null;
        try {
            v1Ingress = api.createNamespacedIngress(namespace, ingress, null, null, null);
        } catch (ApiException e) {
            log.error("创建ingress异常:" + e.getResponseBody(), e);
        } catch (Exception e) {
            log.error("创建ingress系统异常:", e);
        }
        return v1Ingress;
    }


    /**
     * 创建k8s ExtensionIngress
     *
     * @param namespace   命名空间
     * @param ingressName ingress名称
     * @param annotations ingress注解
     * @param path        匹配的路径
     * @param serviceName 路由到的服务名称
     * @param servicePort 路由到的服务端口
     * @return 创建成功的ingress对象
     */
    public ExtensionsV1beta1Ingress createExtensionIngress(String namespace, String ingressName, Map<String, String> annotations, String path,
                                                           String serviceName, Integer servicePort) {
        //构建ingress的yaml对象
        ExtensionsV1beta1Ingress ingress = new ExtensionsV1beta1IngressBuilder()
                .withNewMetadata()
                .withName(ingressName)
                .withAnnotations(annotations)
                .endMetadata()
                .withNewSpec()
                .addNewRule()
                .withHttp(new ExtensionsV1beta1HTTPIngressRuleValueBuilder().addToPaths(new ExtensionsV1beta1HTTPIngressPathBuilder()
                        .withPath(path)
                        .withBackend(new ExtensionsV1beta1IngressBackendBuilder()
                                .withServiceName(serviceName)
                                .withServicePort(new IntOrString(servicePort)).build()).build()).build())
                .endRule()
                .endSpec()
                .build();

        //调用对应的API执行创建ingress的操作
        ExtensionsV1beta1Api api = new ExtensionsV1beta1Api(apiClient);
        ExtensionsV1beta1Ingress extensionsV1beta1Ingress = null;
        try {
            extensionsV1beta1Ingress = api.createNamespacedIngress(namespace, ingress, null, null, null);
        } catch (ApiException e) {
            log.error("创建ingress异常:" + e.getResponseBody(), e);
        } catch (Exception e) {
            log.error("创建ingress系统异常:", e);
        }
        return extensionsV1beta1Ingress;
    }
}

 

3.测试类

/**
 * @author wanghuidong
 * @date 2021/6/18 14:33
 */
public class K8sClientTest {


//    @Test
    public void getAllPodListTest() {
        String kubeConfigPath = "C:\\Users\\admin\\.kube\\config";
        if (!new File(kubeConfigPath).exists()) {
            System.out.println("kubeConfig不存在,跳过");
            return;
        }
        K8sClient k8sClient = new K8sClient(kubeConfigPath);
        V1PodList podList = k8sClient.getAllPodList();
        for (V1Pod item : podList.getItems()) {
            System.out.println(item.getMetadata().getNamespace() + ":" + item.getMetadata().getName());
        }
    }


//    @Test
    public void createServiceTest() {
        String kubeConfigPath = "C:\\Users\\admin\\.kube\\config";
        if (!new File(kubeConfigPath).exists()) {
            System.out.println("kubeConfig不存在,跳过");
            return;
        }
        K8sClient k8sClient = new K8sClient(kubeConfigPath);
        String namespace = "default";
        String serviceName = "my-nginx-service";
        Integer port = 80;
        Map<String, String> selector = new HashMap<>();
        selector.put("run", "my-nginx");
        V1Service v1Service = k8sClient.createService(namespace, serviceName, port, selector);
        System.out.println(v1Service != null ? v1Service.getMetadata() : null);
    }

//    @Test
    public void createV1IngressTest() {
        String kubeConfigPath = "C:\\Users\\admin\\.kube\\config";
        if (!new File(kubeConfigPath).exists()) {
            System.out.println("kubeConfig不存在,跳过");
            return;
        }
        K8sClient k8sClient = new K8sClient(kubeConfigPath);
        String namespace = "default";
        String ingressName = "my-nginx-ingress";
        Map<String, String> annotations = new HashMap<>();
        annotations.put("nginx.ingress.kubernetes.io/rewrite-target", "/");
        String path = "/my-nginx";
        String serviceName = "my-nginx-service";
        Integer servicePort = 80;
        V1Ingress v1Ingress = k8sClient.createV1Ingress(namespace, ingressName, annotations, path, serviceName, servicePort);
        System.out.println(v1Ingress != null ? v1Ingress.getMetadata() : null);
    }

//    @Test
    public void createExtensionIngressTest() {
        String kubeConfigPath = "C:\\Users\\admin\\.kube\\config";
        if (!new File(kubeConfigPath).exists()) {
            System.out.println("kubeConfig不存在,跳过");
            return;
        }
        K8sClient k8sClient = new K8sClient(kubeConfigPath);
        String namespace = "default";
        String ingressName = "my-nginx-ingress";
        Map<String, String> annotations = new HashMap<>();
        annotations.put("nginx.ingress.kubernetes.io/rewrite-target", "/");
        String path = "/my-nginx";
        String serviceName = "my-nginx-service";
        Integer servicePort = 80;
        ExtensionsV1beta1Ingress extensionsV1beta1Ingress = k8sClient.createExtensionIngress(namespace, ingressName, annotations, path, serviceName, servicePort);
        System.out.println(extensionsV1beta1Ingress != null ? extensionsV1beta1Ingress.getMetadata() : null);
    }
}

 

4.附录

4.1 创建pod应用

my-nginx.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nginx
spec:
  selector:
    matchLabels:
      run: my-nginx
  replicas: 2
  template:
    metadata:
      labels:
        run: my-nginx
    spec:
      containers:
      - name: my-nginx
        image: nginx
        ports:
        - containerPort: 80

应用部署单,生成pod

kubectl apply -f ./my-nginx.yaml

查看相关pod信息
kubectl get pods -l run=my-nginx -o wide

 

4.2 创建service

my-nginx-service.yaml

apiVersion: v1
kind: Service
metadata:
  name: my-nginx-service
  labels:
    run: my-nginx-service
spec:
  ports:
  - port: 80
    targetPort: 80
    protocol: TCP
  selector:
    run: my-nginx     

应用service单,创建service

kubectl apply -f ./my-nginx-service.yaml

查看相关服务
kubectl get svc my-nginx-service

查询服务详情
kubectl describe svc my-nginx-service

查看service后端结点
kubectl get ep my-nginx-service

 

4.3 创建ingress(ExtensionV1beta1)

my-nginx-ingress.yaml

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: my-nginx-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - http:
      paths:
      - path: /my-nginx
        backend:
          serviceName: my-nginx-service
          servicePort: 80

应用ingress单,创建ingress

kubectl apply -f ./my-nginx-ingress.yaml

查看ingress

kubectl get ingress

 

4.4 创建Ingress(V1)

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-nginx-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - http:
      paths:
      - path: /my-nginx
        pathType: Prefix
        backend:
          service:
            name: my-nginx-service
            port:
              number: 80

 

4.5 相关概念总结

k8s中配置客户端访问pod中应用的流程如下:

client->ingress->service->pod->container

 

INGRESS

Ingress 是对集群中服务的外部访问进行管理的 API 对象,典型的访问方式是 HTTP。

Ingress 可以提供负载均衡、SSL 终结和基于名称的虚拟托管。

 

SERVICE

将运行在一组 Pods 上的应用程序公开为网络服务的抽象方法。Kubernetes Service 定义了这样一种抽象:逻辑上的一组 Pod,一种可以访问它们的策略 —— 通常称为微服务。 Service 所针对的 Pods 集合通常是通过选择算符来确定的。

 

POD

Pod 是可以在 Kubernetes 中创建和管理的、最小的可部署的计算单元。

Pod (就像在鲸鱼荚或者豌豆荚中)是一组(一个或多个) 容器; 这些容器共享存储、网络、以及怎样运行这些容器的声明。 Pod 中的内容总是并置(colocated)的并且一同调度,在共享的上下文中运行。 Pod 所建模的是特定于应用的“逻辑主机”,其中包含一个或多个应用容器, 这些容器是相对紧密的耦合在一起的。 在非云环境中,在相同的物理机或虚拟机上运行的应用类似于 在同一逻辑主机上运行的云应用。

 

节点(Node)

Kubernetes 集群中其中一台工作机器,是集群的一部分。

 

集群(Cluster)

一组运行由 Kubernetes 管理的容器化应用程序的节点。 在此示例和在大多数常见的 Kubernetes 部署环境中,集群中的节点都不在公共网络中。

 

posted @ 2021-06-19 14:16  追极  阅读(8916)  评论(2编辑  收藏  举报