你好 spring-cloud-kubernetes
欢迎访问我的 GitHub
这里分类和汇总了欣宸的全部原创(含配套源码): http://github.com/zq2599/blog_demos
关于 spring-cloud-kubernetes
-
spring-cloud-kubernetes 是 springcloud 官方推出的开源项目,用于将 Spring Cloud 和 Spring Boot 应用运行在 kubernetes 环境,并且提供了通用的接口来调用 kubernetes 服务,GitHub 上官方地址是:http://github.com/spring-cloud/spring-cloud-kubernetes
-
该项目的提交者之一,就是 SpringCloud 的作者之一 Spencer Gibb:
通过官方 demo 来了解 spring-cloud-kubernetes
-
spring-cloud-kubernetes 项目也提供了丰富的官方 demo 来帮助开发者了解和学习 spring-cloud-kubernetes,您可以参考 《spring-cloud-kubernetes官方demo运行实战》 快速体验官方 demo;
实战 spring-cloud-kubernetes
-
今天实战的内容是开发一个简单的 java 应用,然后将其部署在 kubernetes 环境(minikube 1.1.1),该应用通过 spring-cloud-kubernetes 调用当前 kubernetes 的服务;
环境信息
-
本次实战的环境和版本信息如下:
-
操作系统:CentOS Linux release 7.6.1810
-
minikube:1.1.1
-
Java:1.8.0_191
-
Maven:3.6.0
-
fabric8-maven-plugin 插件:3.5.37
-
spring-cloud-kubernetes:1.0.1.RELEASE
-
上面的 linux、minikube、java、maven,请确保已准备好,linux 环境下 minikube 的安装和启动请参考《Linux 安装 minikube 指南 》。
-
准备工作已经 OK,开始编码吧。
源码下载
-
如果您不打算写代码,也可以从 GitHub 上下载本次实战的源码,地址和链接信息如下表所示:
-
这个 git 项目中有多个文件夹,本章源码在 springcloudk8sdiscovery 这个文件夹下,如下图红框所示:
-
开发应用
-
基于 maven 创建一个 springboot 应用,名为 springcloudk8sdiscovery ;
-
该应用完整的 pom.xml 内容如下:
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.bolingcavalry</groupId>
<artifactId>springcloudk8sdiscovery</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springcloudk8sdiscovery</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<spring-boot.version>2.1.1.RELEASE</spring-boot.version>
<maven-compiler-plugin.version>3.5</maven-compiler-plugin.version>
<maven-deploy-plugin.version>2.8.2</maven-deploy-plugin.version>
<maven-failsafe-plugin.version>2.18.1</maven-failsafe-plugin.version>
<maven-surefire-plugin.version>2.21.0</maven-surefire-plugin.version>
<fabric8.maven.plugin.version>3.5.37</fabric8.maven.plugin.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<type>pom</type>
<scope>import</scope>
<version>${spring-boot.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-kubernetes-core</artifactId>
<version>1.0.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-kubernetes-discovery</artifactId>
<version>1.0.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-commons</artifactId>
<version>2.1.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.1.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.1.1.RELEASE</version>
</dependency>
<!--
We need that(actuator) so that it can be used in readiness probes.
Readiness checks are needed by arquillian, so that it
knows when to run the actual test.
-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<version>2.1.1.RELEASE</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.28</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<!--skip deploy -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<version>${maven-deploy-plugin.version}</version>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${maven-surefire-plugin.version}</version>
<configuration>
<skipTests>true</skipTests>
<!-- Workaround for http://issues.apache.org/jira/browse/SUREFIRE-1588 -->
<useSystemClassLoader>false</useSystemClassLoader>
</configuration>
</plugin>
<plugin>
<groupId>io.fabric8</groupId>
<artifactId>fabric8-maven-plugin</artifactId>
<version>${fabric8.maven.plugin.version}</version>
<executions>
<execution>
<id>fmp</id>
<goals>
<goal>resource</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>kubernetes</id>
<build>
<plugins>
<plugin>
<groupId>io.fabric8</groupId>
<artifactId>fabric8-maven-plugin</artifactId>
<version>${fabric8.maven.plugin.version}</version>
<executions>
<execution>
<id>fmp</id>
<goals>
<goal>resource</goal>
<goal>build</goal>
</goals>
</execution>
</executions>
<configuration>
<enricher>
<config>
<fmp-service>
<type>NodePort</type>
</fmp-service>
</config>
</enricher>
</configuration>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>release</id>
<build>
<plugins>
<plugin>
<groupId>io.fabric8</groupId>
<artifactId>fabric8-maven-plugin</artifactId>
<version>${fabric8.maven.plugin.version}</version>
<executions>
<execution>
<id>fmp</id>
<goals>
<goal>resource</goal>
<goal>helm</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>integration</id>
<build>
<plugins>
<plugin>
<groupId>io.fabric8</groupId>
<artifactId>fabric8-maven-plugin</artifactId>
<version>${fabric8.maven.plugin.version}</version>
<executions>
<execution>
<id>fmp</id>
<goals>
<goal>resource</goal>
<goal>build</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>${maven-failsafe-plugin.version}</version>
<executions>
<execution>
<id>run-integration-tests</id>
<phase>integration-test</phase>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
<configuration>
<skipTests>false</skipTests>
<skipITs>false</skipITs>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>
复制代码
-
上述 pom.xml 文件有几处需要关注:a. 直接依赖了 spring-cloud-kubernetes 的以下两个库,后面才能使用 spring-cloud-kubernetes 的服务:
<code data-type="codeline">org.springframework.cloud:spring-cloud-kubernetes-core:1.0.1.RELEASE</code><code data-type="codeline">org.springframework.cloud:spring-cloud-kubernetes-discovery:1.0.1.RELEASE</code>
复制代码
b. 使用插件 fabric8-maven-plugin 来构建镜像并部署到 minikube 环境:
<plugin>
<groupId>io.fabric8</groupId>
<artifactId>fabric8-maven-plugin</artifactId>
<version>${fabric8.maven.plugin.version}</version>
<executions>
<execution>
<id>fmp</id>
<goals>
<goal>resource</goal>
</goals>
</execution>
</executions>
</plugin>
复制代码
c. 为 fabric8-maven-plugin 插件准备了三个 profile,本次实战主要用到 kubernetes 这个:
<profile>
<id>kubernetes</id>
<build>
<plugins>
<plugin>
<groupId>io.fabric8</groupId>
<artifactId>fabric8-maven-plugin</artifactId>
<version>${fabric8.maven.plugin.version}</version>
<executions>
<execution>
<id>fmp</id>
<goals>
<goal>resource</goal>
<goal>build</goal>
</goals>
</execution>
</executions>
<configuration>
<enricher>
<config>
<fmp-service>
<!--部署到kubernetes后,会创建一个类型为NodePort的service-->
<type>NodePort</type>
</fmp-service>
</config>
</enricher>
</configuration>
</plugin>
</plugins>
</build>
</profile>
复制代码
-
以上就是 pom.xml 的内容了,主要是添加 spring-cloud-kubernetes 的依赖,以及使用 fabric8 来构建和部署;
-
在 application.properties 文件中设置应用名称:
spring.application.name=springcloudk8sdiscovery
复制代码
-
创建应用启动类 Springcloudk8sdiscoveryApplication,可见这是个很普通的 springboot 启动类:
package com.bolingcavalry.springcloudk8sdiscovery;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class Springcloudk8sdiscoveryApplication {
public static void main(String[] args) {
SpringApplication.run(Springcloudk8sdiscoveryApplication.class, args);
}
}
复制代码
-
创建 controller 类,对外提供 http 服务,部署完成后通过这些 http 服务来验证功能:
@RestController
public class DiscoveryController {
@Autowired
private DiscoveryClient discoveryClient;
/**
* 探针检查响应类
* @return
*/
@RequestMapping("/health")
public String health() {
return "health";
}
/**
* 返回远程调用的结果
* @return
*/
@RequestMapping("/getservicedetail")
public String getservicedetail(
@RequestParam(value = "servicename", defaultValue = "") String servicename) {
return "Service [" + servicename + "]'s instance list : " + JSON.toJSONString(discoveryClient.getInstances(servicename));
}
/**
* 返回发现的所有服务
* @return
*/
@RequestMapping("/services")
public String services() {
return this.discoveryClient.getServices().toString()
+ ", "
+ new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
}
}
复制代码
-
上述代码有几点需要注意:a. health 方法用于响应 kubernetes 的探针检查;b. getservicedetail 方法接收名为 servicename 的参数,然后去服务列表中检查对应的服务对象并返回;c. services 方法返回的是所有服务的名称;
-
以上就是所有代码了,功能是通过 autowire 得到 DiscoveryClient 实例,再调用该实例的 API 取得服务信息。
-
接下来我们将应用构建并部署到 minikube 环境;
编译构建
-
请确保当前电脑上 java、maven、minikube 都是正常的;
-
在 pom.xml 文件所在目录执行以下命令,即可编译构建部署一次性完成:
mvn clean package fabric8:deploy -Pkubernetes
复制代码
-
构建成功后,控制台输出信息如下:
...
[INFO]
[INFO] <<< fabric8-maven-plugin:3.5.37:deploy (default-cli) < install @ springcloudk8sdiscovery <<<
[INFO]
[INFO]
[INFO] --- fabric8-maven-plugin:3.5.37:deploy (default-cli) @ springcloudk8sdiscovery ---
[INFO] F8: Using Kubernetes at http://192.168.121.133:8443/ in namespace default with manifest /usr/local/work/demo/springcloudk8sdiscovery/target/classes/META-INF/fabric8/kubernetes.yml
[INFO] Using namespace: default
[INFO] Updating a Service from kubernetes.yml
[INFO] Updated Service: target/fabric8/applyJson/default/service-springcloudk8sdiscovery.json
[INFO] Using namespace: default
[INFO] Updating Deployment from kubernetes.yml
[INFO] Updated Deployment: target/fabric8/applyJson/default/deployment-springcloudk8sdiscovery.json
[INFO] F8: HINT: Use the command `kubectl get pods -w` to watch your pods start up
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 11.207 s
[INFO] Finished at: 2019-06-09T18:50:09+08:00
[INFO] ------------------------------------------------------------------------
复制代码
-
用 kubectl 命令查看部署和服务,都处于正常状态:
[[email protected] springcloudk8sdiscovery]# kubectl get deployments
NAME READY UP-TO-DATE AVAILABLE AGE
springcloudk8sdiscovery 1/1 1 1 75m
[[email protected] springcloudk8sdiscovery]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 33h
springcloudk8sdiscovery NodePort 10.102.167.79 <none> 8080:31583/TCP 75m
复制代码
-
执行命令 minikube service springcloudk8sdiscovery --url ,得到的是可以从外部访问的服务地址:http://192.168.121.133:31583 ,其中 192.168.121.133 是宿主机 IP 地址;
-
在浏览器上访问地址 http://192.168.121.133:31583/services ,如下图,返回的"所有服务"其实是 kubernetes 中的所有 service:
-
-
为了验证当前 namespace 下的所有服务都能被发现,我们再创建个服务实施,执行以下命令,会创建名为 my-tomcat 的部署和服务:
kubectl run my-tomcat --image=tomcat:7.0.94-jre7-alpine --replicas=2 --port=8080 \
&& kubectl expose deployment my-tomcat --port=8080 --target-port=8080 --external-ip=192.168.50.7 --type=LoadBalancer
复制代码
-
由于下载镜像需要一定时间,所以需要稍作等待;
-
再去访问地址 http://192.168.121.133:31583/services ,如下图,my-tomcat 赫然在列:
-
-
访问地址 http://192.168.121.133:31583/getservicedetail?servicename=my-tomcat ,会得到名为 my-tomcat 的服务信息,该信息格式化后的内容如下所示:
[
{
"host": "172.17.0.4",
"instanceId": "91201db9-8aa6-11e9-a5b5-000c29fd2001",
"metadata": {
"run": "my-tomcat"
},
"port": 8080,
"scheme": "http://",
"secure": false,
"serviceId": "my-tomcat",
"uri": "http://172.17.0.4:8080"
},
{
"host": "172.17.0.5",
"instanceId": "91223cda-8aa6-11e9-a5b5-000c29fd2001",
"metadata": {
"$ref": "$[0].metadata"
},
"port": 8080,
"scheme": "http://",
"secure": false,
"serviceId": "my-tomcat",
"uri": "http://172.17.0.5:8080"
}
]
复制代码
-
可见 spring-cloud-kubernetes 的 DiscoveryClient 服务将 kubernetes 中的"service"资源与 SpringCloud 中的服务对应起来了,有了这个 DiscoveryClient,我们在 kubernetes 环境就不需要 eureka 来做注册发现了,而是直接使用 kubernetes 的服务机制,此时不得不感慨 SpringCloud 的对 DiscoveryClient 的设计是如此的精妙。
-
至此,spring-cloud-kubernetes 的初体验就结束了,通过简单的编码我们的程序在 kubernetes 环境可以取得 service 资源的信息,随着学习的深入,我们会用到更多的 spring-cloud-kubernetes 能力,感谢 spring-cloud-kubernetes 的设计者,让我们的 SpringCloud 应用畅游在在 kubernetes 世界。
疑惑待解
-
您可能会有些疑惑:上面的代码都是和 SpringCloud 相关的,和 spring-cloud-kubernetes 没什么关系呀,为什么程序运行起来后就能取得 kubernetes 环境中的服务信息呢?
-
此问题如果不弄清楚,后面的学习很难展开,因为我们都不知道自己的代码与 kubernetes 环境有什么关系,和 kubernetes 有没有交互?
-
以上问题,在下一篇《spring-cloud-kubernetes 背后的三个关键知识点》会有详细的分析。
欢迎关注 InfoQ:程序员欣宸
- 拒绝八股文!这篇图解动态路由分分钟爱了
- 从使用者走向引领者,如何加速国产开源生态建设?
- Docker 实践经验(二)镜像的构建、镜像仓库、压缩、导入
- 云原生之 Ansible 篇(一)
- ElastricSearch 第二弹之分片原理
- 超视频时代音视频架构建设与演进
- 腾讯内容结算下一代系统探索实践
- 10 分钟,带你了解 3 篇 SIGMOD、WWW 等数据库顶会论文的研究成果
- Java 近期新闻:NetBeans 14、Spring Tool Suite 3 支持接近尾声、Hibernate 6.1、TornadoVM
- 打破焦虑,分析师是如何研判技术趋势的?
- 最小可行架构实践:构建家庭保险聊天机器人
- MobTech 杨冠军:管理是一生的提炼,数字是一生的总结 | TGO 专访
- StackOverflow 2022 年度调查报告:JavaScript 连续霸榜,Java 被挤出前五,Rust 最受欢迎
- Kafka ETL 之后,我们将如何定义新一代实时数据集成解决方案?
- Linux 之父发话:Rust 即将出现在 Linux 内核中
- 程序猿必备的数电知识,快来看看你掌握多少!(建议收藏)
- 保险产品 SaaS 化实践之路(上)
- PerfDog 创始人 Awen 邀您共话移动产品质量管理之道
- spring4.1.8 扩展实战之七:控制 bean(BeanPostProcessor 接口)
- PyTorch 分布式训练原来可以更高效