最近需要做一个项目,将k8s上的日志经过java工程输出到前端,大概想了下思路,首先要java连接kubernete监控到job的日志,然后通过websocket将日志持续输出到前端,因为这些从来没有写过,所以只能一点一点积累知识,一点一点攻破,目前是java连接kubernete成功了,并取到了日志,暂时记录一下
1、java连接kubernete方法:配置文件方式,这个文件需要配置到你的工程里面,怎么获取到配置文件?问你们单位的运维,告诉他在机器上帮你取这个文件~/.kube/config 运维说这个是开发环境的超级证书,这个证书只能运维取,因为估计普通测试员没有权限,运维有管理员权限的账号才能取下来
创建k8sclient文件
- package com.example.demo.config;
-
- /**
- * @Author: lxx
- * @Date: 2022/8/4 下午5:43
- */
-
- 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.apis.ExtensionsV1beta1Api;
- import io.kubernetes.client.openapi.apis.NetworkingV1Api;
- import io.kubernetes.client.openapi.models.*;
- import io.kubernetes.client.util.ClientBuilder;
- import io.kubernetes.client.util.KubeConfig;
- import lombok.extern.slf4j.Slf4j;
- import okhttp3.Call;
- import org.slf4j.Logger;
-
- import java.io.FileReader;
- import java.io.IOException;
- import java.util.Map;
-
- /**
- * 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() throws Exception {
- // new a CoreV1Api
- CoreV1Api api = new CoreV1Api(apiClient);
-
- // invokes the CoreV1Api client
- // V1Pod pod = api.readNamespacedPod("reconcile-l75kp","dev5",null,null,null);
- try {
- //V1PodList list = api.listPodForAllNamespaces(null, null, null, null, null, null, null, null, null, null);
- V1PodList list = api.listNamespacedPod("dev5",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
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
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
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;
- }
- public V1Pod readNamespacedPod(String podName,String spaceName)throws Exception{
- CoreV1Api api = new CoreV1Api(apiClient);
- V1Pod pod = api.readNamespacedPod(podName,spaceName,null,null,null);
- return pod;
- }
-
- public Call readNamespacedPodLogCall (String podName, String spaceName, Integer tailLines)throws Exception{
- CoreV1Api api = new CoreV1Api(apiClient);
- Call log = api.readNamespacedPodLogCall(podName,spaceName,null,true,null,null,null,null,null,100,null,null);
- return log;
- }
- public String readNamespacedPodLog (String podName, String spaceName, Integer tailLines)throws Exception{
- // CoreV1Api api = new CoreV1Api(apiClient);
- CoreV1Api api = new CoreV1Api(apiClient);
- String log = api.readNamespacedPodLog(podName,spaceName,null,true,false,1024,"true",false,null,10,false);
- return log;
- }
- }
写单元测试
- package com.example.demo;
-
- import com.example.demo.config.K8sClient;
- import io.kubernetes.client.openapi.models.V1Pod;
- import io.kubernetes.client.openapi.models.V1PodList;
- import org.junit.Test;
- import java.io.File;
-
- /**
- * @Author:
- * @Date: 2022/8/4 下午5:31
- */
- public class KuberneteTest {
-
- @Test
- public void testK8sLog()throws Exception{
- String kubeConfigPath = "/Users/xxx/k8s/config";
- if (!new File(kubeConfigPath).exists()) {
- System.out.println("kubeConfig不存在,跳过");
- return;
- }
- K8sClient k8sClient = new K8sClient(kubeConfigPath);
- String call=k8sClient.readNamespacedPodLog("test-l75kp","dev5",100);
- System.out.println(call);
- }
- }
这样就可以连上kubernete啦,连接k8的用户名密码什么的都在/Users/xxx/k8s/config这个配置文件中,连上之后读取 space为dev5 job名为test-l75kp的日志
不要觉得代码多,亲自试一试吧!