1.引入kubernetes java SDK maven依赖
<!–k8sclient–>
<dependency>
<groupId>io.kubernetes</groupId>
<artifactId>client-java</artifactId>
<version>12.0.1</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
2.增加工具类
package com.mfc.common;
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 java.io.FileReader;
import java.io.IOException;
import java.util.Map;
/**
* @author cmf
* @date 2022/12/21
*/
@Slf4j
public class K8sUtils {
/**
* 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 K8sUtils() {
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 K8sUtils(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.测试类
package k8s;
import com.mfc.common.K8sUtils;
import io.kubernetes.client.openapi.models.*;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
/**
* @author cmf
* @date 2022/12/21
*/
public class K8sClientTest {
public void getAllPodListTest() {
String kubeConfigPath = "C:\\Users\\mfc\\.kube\\config";
if (!new File(kubeConfigPath).exists()) {
System.out.println("kubeConfig不存在");
return;
}
K8sUtils k8sClient = new K8sUtils(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;
}
K8sUtils k8sClient = new K8sUtils(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;
}
K8sUtils k8sClient = new K8sUtils(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;
}
K8sUtils k8sClient = new K8sUtils(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: nginx-deploy
spec:
selector: #定义标签选择器
matchLabels: #定义匹配的标签,必须要设置
app: nginx #匹配的目标标签
replicas: 3 #开启Pod的数量
template: #定义模板,必须定义,模板是起到描述要创建的pod的作用
metadata: #定义模板元数据
labels: #定义模板label,Deployment.spec.template.metadata.labels
app : nginx #定义标签,必须等于 matchLabels 定义的标签
spec:
containers:
– image: msxt.harbor.com/k8s/nginx:1.18.0 #我的镜像是从本地的Harbor上拉取
name: nginx #镜像名称
ports:
– containerPort: 80 #定义容器使用的端口
应用部署单,生成pod
kubectl apply -f ./my-nginx.yam
查看相关pod信息
kubectl get pods -l run=nginx-deploy -o wide
4.2 创建service
my-nginx-service.yaml
apiVersion: v1kind: Servicemetadata: name: my-nginx-service labels: run: my-nginx-servicespec: 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/v1beta1kind: Ingressmetadata: 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/v1kind: Ingressmetadata: 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 部署环境中,集群中的节点都不在公共网络中。
转自:https://mp.weixin.qq.com/s?__biz=MzAxMjY5NDU2Ng==&mid=2651865371&idx=1&sn=91184d1214a31b84af993c3458a4eb47&chksm=80490452b73e8d4498135e04d9342a394414cd203e3e4f1c8892e7780c26fe4118578e148050&scene=27