spring-cloud-kubernetes是springcloud官方推出的開源項目,用於將Spring Cloud和Spring Boot應用運行在kubernetes環境,而且提供了通用的接口來調用kubernetes服務,GitHub上官方地址是:https://github.com/spring-cloud/spring-cloud-kubernetesjava
該項目的提交者之一,就是SpringCloud的做者之一Spencer Gibb: linux
本文是《spring-cloud-kubernetes實戰系列》的第二篇,全文連接以下:git
spring-cloud-kubernetes項目也提供了豐富的官方demo來幫助開發者瞭解和學習spring-cloud-kubernetes,您能夠參考《spring-cloud-kubernetes官方demo運行實戰》快速體驗官方demo;github
今天實戰的內容是開發一個簡單的java應用,而後將其部署在kubernetes環境(minikube 1.1.1),該應用經過spring-cloud-kubernetes調用當前kubernetes的服務;web
本次實戰的環境和版本信息以下:spring
上面的linux、minikube、java、maven,請確保已準備好,linux環境下minikube的安裝和啓動請參考《Linux安裝minikube指南 》。shell
準備工做已經OK,開始編碼吧。apache
若是您不打算寫代碼,也能夠從GitHub上下載本次實戰的源碼,地址和連接信息以下表所示:json
名稱 | 連接 | 備註 |
---|---|---|
項目主頁 | https://github.com/zq2599/blog_demos | 該項目在GitHub上的主頁 |
git倉庫地址(https) | https://github.com/zq2599/blog_demos.git | 該項目源碼的倉庫地址,https協議 |
git倉庫地址(ssh) | git@github.com:zq2599/blog_demos.git | 該項目源碼的倉庫地址,ssh協議 |
</br>瀏覽器
這個git項目中有多個文件夾,本章源碼在springcloudk8sdiscovery這個文件夾下,以下圖紅框所示:
<?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 https://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的服務:
org.springframework.cloud:spring-cloud-kubernetes-core:1.0.1.RELEASE org.springframework.cloud:spring-cloud-kubernetes-discovery:1.0.1.RELEASE
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來構建和部署;
spring.application.name=springcloudk8sdiscovery
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); } }
@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環境;
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 https://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] ------------------------------------------------------------------------
[root@minikube springcloudk8sdiscovery]# kubectl get deployments NAME READY UP-TO-DATE AVAILABLE AGE springcloudk8sdiscovery 1/1 1 1 75m [root@minikube 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
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
因爲下載鏡像須要必定時間,因此須要稍做等待; 7. 再去訪問地址http://192.168.121.133:31583/services ,以下圖,my-tomcat赫然在列: 8. 訪問地址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背後的三個關鍵知識點》,這裏面有詳細的分析。