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 部署環境中,集群中的節點都不在公共網絡中。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM