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 部署环境中,集群中的节点都不在公共网络中。