Kubernetes 官方 java 客户端之八:fluent style,mysql 入门视频教程
实战步骤概述
在父工程 kubernetesclient 下面新建名为 fluent 的子工程;
fluent 工程中只有一个类 FluentStyleApplication,启动的 main 方法以及 fluent style 的代码都在此类中;
FluentStyleApplication.java 提供四个 web 接口,功能分别是:新建 namespace、新建 deployment、新建 service、删除前面三个接口新建的所有资源;
fluent 工程编码完成后,不需要做成镜像部署在 kubernetes 环境内部,而是作为一个普通 SpringBoot 应用找个 java 环境启动即可,与《Kubernetes官方java客户端之三:外部应用 》一文的部署和启动一致;
依次调用每个接口,验证功能是否符合预期;
编码
在父工程 kubernetesclient 下面新建名为 fluent 的 maven 子工程,pom.xml 内容如下,需要注意的是排除掉 spring-boot-starter-json,原因请参考《Kubernetes官方java客户端之二:序列化和反序列化问题 》:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.bolingcavalry</groupId>
<artifactId>kubernetesclient</artifactId>
<version>1.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>com.bolingcavalry</groupId>
<artifactId>fluent</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>fluent</name>
<description>Demo project for fluent style</description>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclus
ions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-json</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>io.kubernetes</groupId>
<artifactId>client-java</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.3.0.RELEASE</version>
</plugin>
</plugins>
</build>
</project>
新建 FluentStyleApplication.java,首先,该类作为启动类,要有 main 方法:
public static void main(String[] args) {
SpringApplication.run(FluentStyleApplication.class, args);
}
定义常量 NAMESPACE 作为本次实战的 namespace:
private final static String NAMESPACE = "fluent";
用 @PostConstruct 注解修饰 setDefaultApiClient 方法,令其在实例化时执行一次,里面做了一些全局性的初始化设置,注意 kubeConfigPath 变量对应的 config 文件路径要正确:
/**
默认的全局设置
@return
@throws Exception
*/
@PostConstruct
private void setDefaultApiClient() throws Exception {
// 存放 K8S 的 config 文件的全路径
String kubeConfigPath = "/Users/zhaoqin/temp/202007/05/config";
// 以 config 作为入参创建的 client 对象,可以访问到 K8S 的 API Server
ApiClient client = ClientBuilder
.kubeconfig(KubeConfig.loadKubeConfig(new FileReader(kubeConfigPath)))
.build();
// 会打印和 API Server 之间请求响应的详细内容,生产环境慎用
client.setDebugging(true);
// 创建操作类
Configuration.setDefaultApiClient(client);
}
接下来是创建 namespace 的 web 服务,如下所示,由于 namespace 在 kubernetes 的 apiVersion 是 v1,因此创建的是 V1Namespace 实例:
@RequestMapping(value = "/fluent/createnamespace")
public V1Namespace createnamespace() throws Exception {
V1Namespace v1Namespace = new V1NamespaceBuilder()
.withNewMetadata()
.withName(NAMESPACE)
.addToLabels("label1", "aaa")
.addToLabels("label2", "bbb")
.endMetadata()
.build();
return new CoreV1Api().createNamespace(v1Namespace, null, null, null);
}
为了更清晰的展现 fluent style 效果,将上述代码与创建 namespace 的 yaml 文件内容放在一起对比,如下图所示,可见对照着 yaml 文件就能将代码写出来:
接下来是创建 service 的代码,为了便于和 yaml 对应起来,代码中特意加了缩进:
@RequestMapping(value = "/fluent/createservice")
public V1Service createservice() throws Exception {
V1Service v1Service = new V1ServiceBuilder()
// meta 设置
.withNewMetadata()
.withName("nginx")
.endMetadata()
// spec 设置
.withNewSpec()
.withType("NodePort")
.addToPorts(new V1ServicePort().port(80).nodePort(30103))
.addToSelector("name", "nginx")
.endSpec()
.build();
return new CoreV1Api().createNamespacedService(NAMESPACE, v1Service, null, null, null);
}
创建 deployment 的代码如下,因为内容较多所以相对复杂一些,请注意,由于 deployment 在 kubernetes 的 apiVersion 是 extensions/v1beta1,因此创建的是 ExtensionsV1beta1Deployment 实例:
@RequestMapping(value = "/fluent/createdeployment")
public ExtensionsV1beta1Deployment createdeployment() throws Exception {
ExtensionsV1beta1Deployment v1Deployment = new ExtensionsV1beta1DeploymentBuilder()
// meta 设置
.withNewMetadata()
.withName("nginx")
.endMetadata()
// spec 设置
.withNewSpec()
.withReplicas(1)
// spec 的 templat
.withNewTemplate()
// template 的 meta
.withNewMetadata()
.addToLabels("name", "nginx")
.endMetadata()
// template 的 spec
.withNewSpec()
.addNewContainer()
.withName("nginx")
.withImage("nginx:1.18.0")
.addToPorts(new V1ContainerPort().containerPort(80))
.endContainer()
.endSpec()
.endTemplate()
.endSpec()
.build();
return new ExtensionsV1beta1Api().createNamespacedDeployment(NAMESPACE, v1Deployment, null, null, null);
}
评论