你好spring-cloud-kubernetes

關於spring-cloud-kubernetes

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

  1. 《spring-cloud-kubernetes官方demo運行實戰》
  2. 《你好spring-cloud-kubernetes》
  3. 《spring-cloud-kubernetes背後的三個關鍵知識點》
  4. 《spring-cloud-kubernetes的服務發現和輪詢實戰(含熔斷)》
  5. 《spring-cloud-kubernetes與SpringCloud Gateway》
  6. 《spring-cloud-kubernetes與k8s的configmap》

經過官方demo來了解spring-cloud-kubernetes

spring-cloud-kubernetes項目也提供了豐富的官方demo來幫助開發者瞭解和學習spring-cloud-kubernetes,您能夠參考《spring-cloud-kubernetes官方demo運行實戰》快速體驗官方demo;github

實戰spring-cloud-kubernetes

今天實戰的內容是開發一個簡單的java應用,而後將其部署在kubernetes環境(minikube 1.1.1),該應用經過spring-cloud-kubernetes調用當前kubernetes的服務;web

環境信息

本次實戰的環境和版本信息以下:spring

  1. 操做系統:CentOS Linux release 7.6.1810
  2. minikube:1.1.1
  3. Java:1.8.0_191
  4. Maven:3.6.0
  5. fabric8-maven-plugin插件:3.5.37
  6. spring-cloud-kubernetes:1.0.1.RELEASE

上面的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這個文件夾下,以下圖紅框所示: 在這裏插入圖片描述

開發應用

  1. 基於maven建立一個springboot應用,名爲<font color="blue">springcloudk8sdiscovery</font>;
  2. 該應用完整的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 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來構建和部署;

  1. 在application.properties文件中設置應用名稱:
spring.application.name=springcloudk8sdiscovery
  1. 建立應用啓動類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);
    }
}
  1. 建立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環境;

編譯構建

  1. 請確保當前電腦上java、maven、minikube都是正常的;
  2. 在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 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] ------------------------------------------------------------------------
  1. 用kubectl命令查看部署和服務,都處於正常狀態:
[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
  1. 執行命令<font color="blue">minikube service springcloudk8sdiscovery --url</font>,獲得的是能夠從外部訪問的服務地址:http://192.168.121.133:31583 ,其中192.168.121.133是宿主機IP地址;
  2. 在瀏覽器上訪問地址http://192.168.121.133:31583/services ,以下圖,返回的"全部服務"實際上是kubernetes中的全部service: 在這裏插入圖片描述
  3. 爲了驗證當前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

因爲下載鏡像須要必定時間,因此須要稍做等待; 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背後的三個關鍵知識點》,這裏面有詳細的分析。

歡迎關注個人公衆號

在這裏插入圖片描述

相關文章
相關標籤/搜索