欢迎访问我的GitHub
https://github.com/zq2599/blog_demos
内容:所有原创文章分类汇总及配套源码,涉及Java、Docker、Kubernetes、DevOPS等;
概览
- 本文是《K8S官方java客户端》系列的第九篇,以下提到的java客户端都是指client-jar.jar;
- 《K8S官方java客户端之七:patch操作 》涉及的知识点、代码、操作都太多了,对作者和读者都是莫大的折磨,于是从上一篇《K8S官方java客户端之八:fluent style 》,再到本篇都以放松为主题吧,写得尽量简单一些,但是该学该练的不会缩水;
- 平时用命令行操作kubernetes时,经常用到yaml文件,实际上java客户端也支持yaml格式的操作:通过yaml生成资源对象、将资源对象转成yaml格式的内容,也就是今天咱们的实战内容;
- 今天的实战对应的java应用无需部署在K8S环境内部,只需当做一个普通的SpringBoot运行起来即可,详情请参考《K8S官方java客户端之三:外部应用 》
实战步骤
今天的实战由以下步骤组成:
- 编码:编写namespace和service的yaml文件;
- 编码:用java客户端的API,基于yaml文件创建namespace和service;
- 编码:用java客户端的API,将namespace和service对象转成yaml格式的字符串;
- 验证:运行应用,验证上述代码的功能:通过http请求创建namespace、service,通过http请求下载已有namespace和service的yaml文件、通过http请求清理本次实战的所有资源;
源码下载
如果您不想编码,可以在GitHub下载所有源码,地址和链接信息如下表所示(https://github.com/zq2599/blog_demos):
- 这个git项目中有多个文件夹,《K8S官方java客户端》系列的源码在kubernetesclient文件夹下,如下图红框所示:
编码
- 在父工程kubernetesclient下面新建名为yaml的maven子工程,pom.xml内容如下,需要注意的是排除掉spring-boot-starter-json,原因请参考《K8S官方java客户端之二:序列化和反序列化问题 》:
<?xml version="1.0" encoding="UTF-8"?>4.0.0com.bolingcavalry kubernetesclient 1.0-SNAPSHOT../pom.xmlcom.bolingcavalry yaml 0.0.1-SNAPSHOTyamlDemo project for yamljarorg.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-json org.projectlombok lombok trueio.kubernetes client-java org.springframework.boot spring-boot-maven-plugin 2.3.0.RELEASE
- 在resources目录下新建namespace.yaml,这是创建namespace用的yaml文件,内容如下:
apiVersion: v1kind: Namespacemetadata: name: yaml
- 在resources目录下新建service.yaml,这是创建service用的yaml文件,内容如下:
apiVersion: v1kind: Servicemetadata: namespace: yaml name: test-servicespec: type: ClusterIP selector: app: test-service ports: - name: port-of-container port: 8080
- 接下来是java代码,都集中在同一个文件YamlApplication.java中,咱们分成几部分逐个看,首先是类注解:
@SpringBootApplication@RestController@Slf4jpublic class YamlApplication {
- 其次是main方法:
public static void main(String[] args) { SpringApplication.run(YamlApplication.class, args); }
- 定义两个常量,分别是实战用到的namespace和service的name,稍后用到:
/** * 本次实战用到的namespace,和namespace.yaml、service.yaml文件中的一致 */ private final static String NAMESPACE = "yaml"; /** * 本次实战用到的service的名称,和service.yaml文件中的一致 */ private final static String SERVICE_NAME = "test-service";
- 接下来是初始化方法,kubeConfigPath变量的值,请指向您的kubernetes环境的config文件,还要注意的是Yaml.addModelMap方法,这是为了在war包或者junit测试的时候规避load方法失效的问题:
@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); // 规避已知问题:https://github.com/kubernetes-client/java/issues/474 // 如果应用是war包,或者运行在junit等涉及到反射类型的class-loader场景下,Yaml.load方法有可能不生效, // 此时要执行Yaml.addModelMap来规避此问题 Yaml.addModelMap("v1", "Namespace", V1Namespace.class); Yaml.addModelMap("v1", "Service", V1Service.class); }
- 开发一个web接口,用来基于yaml文件创建namespace和service,可见核心方法是Yaml.load这个API,入参是yaml文件,返回的是创建好的API实例,CoreV1Api可以直接用这个实例创建资源:
@RequestMapping(value = "/yaml/load") public String load() throws Exception { CoreV1Api api = new CoreV1Api(); // 通过yaml文件创建namespace实例 V1Namespace namespace = (V1Namespace) Yaml.load(new ClassPathResource("namespace.yaml").getFile()); // 创建namespace资源 api.createNamespace(namespace, null, null, null); // 通过yaml文件创建service实例 V1Service service = (V1Service) Yaml.load(new ClassPathResource("service.yaml").getFile()); // 创建service资源 api.createNamespacedService(NAMESPACE, service, null, null, null); return "load operation success " + new Date(); }
- 将API实例转成yaml格式的字符串,依靠的是Yaml.dump方法,这里为了方便查看,我封装了一个私有方法,该方法接收API实例,然后用Yaml.dump方法转成yaml格式的字符串,接着在日志中打印,并在浏览器产生一个yaml格式的下载文件:
private void writeResponse(HttpServletResponse httpServletResponse, Object dumpObject, String fileName) throws Exception { String yaml = Yaml.dump(dumpObject); log.info(yaml); byte[] bytes = yaml.getBytes("UTF-8"); httpServletResponse.setHeader("content-type", "application/yaml"); httpServletResponse.setContentType("application/yaml"); httpServletResponse.setHeader("Content-Disposition", "attachment;filename=" + fileName); httpServletResponse.setHeader("Content-Length", "" + bytes.length); httpServletResponse.getOutputStream().write(bytes); }
- 有了上面的writeResponse方法,就可以轻松开发两个web接口了,分别用来下载service和namespace的yaml格式内容:
@RequestMapping(value = "/yaml/getnamespace") @ResponseBody public String getNamespace(HttpServletResponse httpServletResponse) throws Exception { // 查找名为yaml的namespace V1Namespace namespace = new CoreV1Api().readNamespace(NAMESPACE, null, null, null); // 通过Yaml.dump方法将资源对象转成Yaml格式的字符串,在日志中打印,然后在浏览器以yaml文件的格式下载 writeResponse(httpServletResponse, namespace, "namespace.yaml"); return "getnamespace operation success " + new Date(); } @RequestMapping(value = "/yaml/getservice") @ResponseBody public String getService(HttpServletResponse httpServletResponse) throws Exception { // 在yaml这个namespace下,查找名为test-service的service V1Service service = new CoreV1Api().readNamespacedService(SERVICE_NAME, NAMESPACE, null, null, null); // 通过Yaml.dump方法将资源对象转成Yaml格式的字符串,在日志中打印,然后在浏览器以yaml文件的格式下载 writeResponse(httpServletResponse, service, "service.yaml"); return "getservice operation success " + new Date(); }
- 最后是清理资源的方法,实战最后调用一下,干干净净不留残余:
@RequestMapping(value = "/yaml/clear") public String clear() throws Exception { CoreV1Api coreV1Api = new CoreV1Api(); // 删除service coreV1Api.deleteNamespacedService(SERVICE_NAME, NAMESPACE, null, null, null, null, null, null); // 删除namespace try { coreV1Api.deleteNamespace(NAMESPACE, null, null, null, null, null, null); } catch (Exception e) { log.error("delete namespace error", e); } return "clear finish, " + new Date(); }
- 编码已经完成,下图红框中是新增的三个文件:
- 启动这个Spring Boot应用,开始验证;
验证
- 浏览器访问:http://localhost:8080/yaml/load ,即可根据yaml创建namespace和service,命令行查看kubernetes环境,可见创建成功:
- 浏览器访问:http://localhost:8080/yaml/getnamespace ,浏览器会提示下载,如下图,选择保存:
- 打开下载好的namespace.yaml,内容如下:
- 浏览器访问:http://localhost:8080/yaml/getservice ,会下载service的yaml,如下图:
- 验证结束,浏览器访问:http://localhost:8080/yaml/clear ,相关的service和namespace都被清理掉了:
- 至此,java客户端的yaml支持实战已经完成,轻松愉快的氛围中咱们又掌握一项基本功能;
新的起点
截止目前,《K8S官方java客户端》系列已经推出九篇文章,这些都是紧密结合kubernetes基本概念和操作的实战,有了这些扎实的基本功,接下来可以进入进阶篇了,前方有更多精彩的内容等着咱们!