1. 程式人生 > >spring-cloud-kubernetes與k8s的configmap

spring-cloud-kubernetes與k8s的configmap

本文是《spring-cloud-kubernetes實戰系列》的第六篇,主要內容是在kubernetes上部署一個java web應用,該應用使用了spring-cloud-kubernetes框架,可以使用kubernetes的configmap;

系列文章列表

  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》
  7. 《spring-cloud-kubernetes自動同步k8s的configmap更新》

關於SpringCloud Config

如果您開發過SpringCloud應用,相信您對SpringCloud Config不會陌生,在微服務環境中,業務應用可以從config server獲取所需的配置資訊,如下圖所示:

關於kubernetes的configmap

這是kubernetes提供的基本服務之一,建立一個configmap資源,對應著一份配置檔案,可以將該資源通過資料卷的形式對映到Pod上,這樣Pod就能用上這個配置檔案了,如下圖:

spring-cloud-kubernetes帶來的禮物

spring-cloud-starter-kubernetes-config是spring-cloud-starter-kubernetes框架下的一個庫,作用是將kubernetes的configmap與SpringCloud Config結合起來,通過spring-cloud-starter-kubernetes-config,我們的應用就像在通過SpringCloud Config取得配置資訊,只不過這裡的配置資訊來自kubernetes的configmap,而不是SpringCloud Config server,如下圖所示:

理論上的準備工作已經差不多了,接下來通過實戰來展示spring-cloud-starter-kubernetes-config的神奇之處;

原始碼下載

如果您不打算寫程式碼,也可以從GitHub上下載本次實戰的原始碼,地址和連結資訊如下表所示:

名稱 連結 備註
專案主頁 https://github.com/zq2599/blog_demos 該專案在GitHub上的主頁
git倉庫地址(https) https://github.com/zq2599/blog_demos.git 該專案原始碼的倉庫地址,https協議
git倉庫地址(ssh) [email protected]:zq2599/blog_demos.git 該專案原始碼的倉庫地址,ssh協議


這個git專案中有多個資料夾,本章的應用在springcloudk8sconfigdemo資料夾下,如下圖所示:

環境資訊

本次實戰的環境和版本資訊如下:

  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
  7. springboot:2.1.6.RELEASE

準備完畢,可以開始實戰啦!

編碼

  1. 通過maven建立名為springcloudk8sconfigdemo的springboot工程,pom.xml內容如下,要注意的是新增了依賴spring-cloud-starter-kubernetes-config,這是本次實戰的重點:
<?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.6.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.bolingcavalry</groupId>
    <artifactId>springcloudk8sconfigdemo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springcloudk8sconfigdemo</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
        <spring-boot.version>2.1.6.RELEASE</spring-boot.version>
        <maven-checkstyle-plugin.failsOnError>false</maven-checkstyle-plugin.failsOnError>
        <maven-checkstyle-plugin.failsOnViolation>false</maven-checkstyle-plugin.failsOnViolation>
        <maven-checkstyle-plugin.includeTestSourceDirectory>false</maven-checkstyle-plugin.includeTestSourceDirectory>
        <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>
        <springcloud.kubernetes.version>1.0.1.RELEASE</springcloud.kubernetes.version>
        <spring-cloud.version>Greenwich.SR2</spring-cloud.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-kubernetes-config</artifactId>
            <version>${springcloud.kubernetes.version}</version>
        </dependency>
    </dependencies>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <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>
    </profiles>
</project>
  1. 專案的src\main\resources路徑下不要建立application.yml檔案,只建立名為bootstrap.yml的檔案,內容如下:
spring:
  application:
    name: springcloudk8sconfigdemo
  cloud:
    kubernetes:
      config:
        sources:
          - name: ${spring.application.name}
            namespace: default

可見新增了配置項spring.cloud.kubernetes.config.source.name和spring.cloud.kubernetes.config.source.namespace,用於配置資訊來源於kubernetes的哪個namespace下的哪個configmap;

  1. 增加一個配置類DummyConfig.java,註解ConfigurationProperties的prefix="greeting"表示該類用到的配置項都是名為"greeting"的配置項的子內容 :
package com.bolingcavalry.springcloudk8sconfigdemo;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;

@Configuration
@ConfigurationProperties(prefix = "greeting")
public class DummyConfig {

    private String message = "This is a dummy message";

    public String getMessage() {
        return this.message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}
  1. 啟動類Springcloudk8sconfigdemoApplication.java,簡單起見,將用於驗證配置項是否生效的web介面也寫在了這裡面,即hello方法 :
package com.bolingcavalry.springcloudk8sconfigdemo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.text.SimpleDateFormat;
import java.util.Date;

@SpringBootApplication
@RestController
@EnableConfigurationProperties(DummyConfig.class)
public class Springcloudk8sconfigdemoApplication {

    @Autowired
    private DummyConfig dummyConfig;

    @GetMapping("/hello")
    public String hello() {
        return dummyConfig.getMessage()
                + " ["
                + new SimpleDateFormat().format(new Date())
                + "]";
    }

    public static void main(String[] args) {
        SpringApplication.run(Springcloudk8sconfigdemoApplication.class, args);
    }
}

以上就是實戰工程的所有程式碼了,僅僅只是引入了spring-cloud-kubernetes-config的依賴,以及在啟動配置檔案中指定了configmap的資訊,即完成了獲取配置檔案的所有操作,至於程式碼中用到配置檔案的地方,和使用SpringCloud Config並無差別。

解決許可權問題

我這裡的是minikube,在部署了應用之後,預設的serviceaccount是沒有許可權訪問K8S的API Server資源的,執行以下命令可以提升許可權:

kubectl create clusterrolebinding permissive-binding \
  --clusterrole=cluster-admin \
  --user=admin \
  --user=kubelet \
  --group=system:serviceaccounts

注意:以上辦法只能用於開發和測試環境,不要用在生產環境,生產環境應參考Kubernetes的RBAC授權相關設定來處理,步驟如下:

  1. 建立role:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: default
  name: pod-reader
rules:
  - apiGroups: [""]
    resources: ["pods","configmaps"]
    verbs: ["get", "watch", "list"]
  1. 建立ServiceAccount:
apiVersion: v1
kind: ServiceAccount
metadata:
  name: config-reader
  namespace: default
  1. 繫結Role和ServiceAccount:
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: pod-reader
  namespace: default
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: pod-reader
subjects:
  - kind: ServiceAccount
    name: config-reader
    namespace: default
  1. 在deployment中指定上面的ServiceAccount;

驗證

接下來我們在kubernetes環境建立configmap,再將springcloudk8sconfigdemo在kubernetes部署和啟動,通過springcloudk8sconfigdemo提供的http介面驗證應用是否已經從configmap中取得指定的配置;

  1. 在kubernetes環境新建名為springcloudk8sconfigdemo.yml的檔案,內容如下:
kind: ConfigMap
apiVersion: v1
metadata:
  name: springcloudk8sconfigdemo
data:
  application.yml: |-
    greeting:
      message: Say Hello to the World
    farewell:
      message: Say Goodbye
    ---
    spring:
      profiles: development
    greeting:
      message: Say Hello to the Developers
    farewell:
      message: Say Goodbye to the Developers
    ---
    spring:
      profiles: production
    greeting:
      message: Say Hello to the Ops
  1. 在springcloudk8sconfigdemo.yml檔案所在目錄執行以下命令,即可在kubernetes建立名為的configmap的資源:
kubectl apply -f springcloudk8sconfigdemo.yml
  1. 在springcloudk8sconfigdemo專案的pom.xml檔案所在目錄,執行以下命令,即可編譯構建部署全部完成:
mvn clean install fabric8:deploy -Dfabric8.generator.from=fabric8/java-jboss-openjdk8-jdk -Pkubernetes

操作成功後的控制檯資訊如下:

[INFO] Installing /usr/local/work/k8s/springcloudk8sconfigdemo/target/classes/META-INF/fabric8/kubernetes.json to /root/.m2/repository/com/bolingcavalry/springcloudk8sconfigdemo/0.0.1-SNAPSHOT/springcloudk8sconfigdemo-0.0.1-SNAPSHOT-kubernetes.json
[INFO] 
[INFO] <<< fabric8-maven-plugin:3.5.37:deploy (default-cli) < install @ springcloudk8sconfigdemo <<<
[INFO] 
[INFO] 
[INFO] --- fabric8-maven-plugin:3.5.37:deploy (default-cli) @ springcloudk8sconfigdemo ---
[INFO] F8: Using Kubernetes at https://192.168.121.133:8443/ in namespace default with manifest /usr/local/work/k8s/springcloudk8sconfigdemo/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-springcloudk8sconfigdemo.json
[INFO] Using namespace: default
[INFO] Updating Deployment from kubernetes.yml
[INFO] Updated Deployment: target/fabric8/applyJson/default/deployment-springcloudk8sconfigdemo.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:  13.538 s
[INFO] Finished at: 2019-07-14T17:06:25+08:00
[INFO] ------------------------------------------------------------------------
  1. 如果您的環境也是minikube,可以執行以下命令檢視服務地址:
minikube service springcloudk8sconfigdemo --url

得到服務地址是:http://192.168.121.133:31646

  1. 瀏覽器訪問地址:http://192.168.121.133:31646/hello ,得到響應如下圖,可見已經從configmap取得了配置檔案,並且載入成功:

    修改profile

    前面的實戰沒有指定springboot工程的profile,接下來指定profile為development,看能否載入到配置檔案中指定的配置,如下圖紅框所示:

  2. 修改專案的src\main\resources路徑下的bootstrap.yml檔案,增加配置項spring.profiles.active,修改後的完整內容如下:
spring:
  application:
    name: springcloudk8sconfigdemo
  profiles:
    active: development
  cloud:
    kubernetes:
      config:
        sources:
          - name: ${spring.application.name}
            namespace: default
  1. 在springcloudk8sconfigdemo專案的pom.xml檔案所在目錄,執行以下命令,即可編譯構建部署全部完成:
mvn clean install fabric8:deploy -Dfabric8.generator.from=fabric8/java-jboss-openjdk8-jdk -Pkubernetes
  1. 如果您的環境也是minikube,可以執行以下命令檢視服務地址:
minikube service springcloudk8sconfigdemo --url

得到服務地址是:http://192.168.121.133:30659

  1. 瀏覽器訪問地址:http://192.168.121.133:30659/hello ,得到響應如下圖,可見已經從configmap取得了指定profile的配置檔案,並且載入成功:

    至此,spring-cloud-kubernetes與k8s的configmap的實戰就完成了,我們可以發現藉助spring-cloud-kubernetes-config的神奇能力,曾經使用SpringCloud Config來配置的應用幾乎不用修改程式碼,僅僅調整了配置和依賴,就能順利遷移到kubernetes之上,直接使用原生的配置服務,並且SpringCloud Config Server也可以不用在kubernetes上部署了,再次感受到SpringCloud設計的前瞻性。

一點遺憾

雖然我們的應用已經成功從configmap取得配置資訊,但遺憾的是,configmap的配置資訊被修改後,這些修改是無法實時同步到我們的應用的,只能重啟應用來重現獲取配置,為了解決這個問題,請參考本系列的下一篇 《spring-cloud-kubernetes自動同步k8s的configmap更新》

歡迎關注我的公眾號:程式設計師欣宸

相關推薦

spring-cloud-kubernetesk8s的configmap

本文是《spring-cloud-kubernetes實戰系列》的第六篇,主要內容是在kubernetes上部署一個java web應用,該應用使用了spring-cloud-kubernetes框架,可以使用kubernetes的configmap; 系列文章列表 《spring-cloud-kubern

spring cloud實戰思考(一) spring config全局配置方案設計

功能 IE 基於 比較 此外 fig eureka 搜索 地址 “spring cloud”的配置中心工具“spring cloud config”提供了分布式系統配置文件集中管理解決方案。該工具功能強大,實現也很簡單。網上可以搜索到很多開發教程和用例。本文並不是分享“

spring cloud實戰思考(二) 微服務之間通過fiegn上傳多個文件1

jar 多文件 上傳文件 ret nmap spa 不同 port 問題 需求場景: 微服務之間調用接口一次性上傳多個文件。 上傳文件的同時附帶其他參數。 多個文件能有效的區分開,以便進行不同處理。   Spring cloud的微服務之間接口調用使用Feign。原裝的

spring cloud實戰思考(三) 微服務之間通過fiegn上傳一組文件(下)

ets inf str ceo iter protected let pan ins 需求場景:   用戶調用微服務1的接口上傳一組圖片和對應的描述信息。微服務1處理後,再將這組圖片上傳給微服務2進行處理。各個微服務能區分開不同的圖片進行不同處理。   上一篇博客已經討

Spring Cloud Kubernetes容器化實踐

隨著公司業務量和產品線的增加,專案越來越多,普通運維繫統架構對整個軟體研發生命週期的管理越來越難,效率低下,難以統一管理。近年來Docker統一了容器標準,對於軟體開發流程產生了深遠的影響,Docker可以一次打包,處處執行。過去幾年Kubernetes平臺發展日新月益,K

Spring系列學習之Spring Cloud Kubernetes容器編排應用管理

英文原文:https://spring.io/projects/spring-cloud-kubernetes 目錄 概述 kubernetes Kubernetes 特點 Kubernetes 元件 快速開始 學習 文件 概述 kubernetes

Spring Cloud入門實踐(三)-Hystrix

接著跟著前一篇,通過負載均衡來減輕服務端壓力,客戶端利用RestTemplate來獲取服務。 那麼這裡有個問題,如果所有伺服器極限壓力了,那麼就算負載都沒有用了,等了好久沒返回怎麼辦? 此時就需要伺服器的容錯機制了。 容錯性 服務的容錯性,簡單講就是

Spring Cloud入門實踐(二)-Ribbon

前一篇文章介紹了Spring Cloud Eureka的簡單實踐,本篇文章介紹Ribbon的實踐。 What is Ribbon Spring Cloud Ribbon是一個基於HTTP和TCP的客戶端負載均衡工具,這裡的客戶端是站在伺服器的角度來看的,它基

Spring Cloud入門實踐(一)-Eureka

微服務,很火的一個概念,無數的架構師和開發者在實際專案中實踐該設計理念併為此付出了諸多努力,同時也湧現出針對不同應用場景出現的各種問題的各種解決方案和開源框架, 服務治理例如Dubbo,Netflix的Eureka。 分散式配置管理Spring Cloud的

Spring Cloud入門實踐(四)-Feign

Feign是什麼呢?宣告式服務呼叫,記得在使用Ribbon負載均衡時候,需要用到一個RestTemplate來進行呼叫,而有了Feign,可以直接寫類似於Controller的方式來進行一個宣告式的服務呼叫了。 Feign Feign基於Netflix

Spring Cloud + Kubernetes 微服務框架原理和實踐

早在半年前,公司開始推行容器化部署方案 AppOS,雖然釋出介面過於極客,十分晦澀,不過仔細研究起來真的覺得十分強大,容器化推行後,計算資源(CPU、記憶體)的利用率可以極大提高,降低伺服器數量,從而節約技術成本。恰巧,若干個朋友所在創業公司最近也在嘗試做微服務、容器化。架構

Spring Cloud ConfigGitLab整合,並使用webhook實時更新配置

        大家都知道Spring Cloud Config統一配置中心預設支援GitHub。由於公司使用的是內部的GitLab來管理程式碼,因此配置還是有一點出入的。在這記錄下來,方便有同樣需求的小夥伴。 一、在後臺專案的bootstrap.yml配置git地址:

Spring Cloud介紹環境搭建(一)

前言使用Spring Cloud需要用到Spring boot的知識,如果沒有相關經驗,請參考Spring Boot的簡單使用(二),做一個簡單的入門。Spring Cloud系列部落格是基於MyEclipse開發工具的。LAMP專案傳統的單體專案用一個LAMP結構就可以完成

Spring Cloud SleuthELK配合使用

<?xml version="1.0" encoding="UTF-8"?> <configuration> <include resource="org/springframework/boot/logging/logback/defaults.xml" />

spring cloud busspring cloud config整合實現應用配置動態重新整理

準備工作, 在碼雲上 建立 一個 專案,並在在目錄下建立 spring_cloud_in_action/config-repo 層級目錄,其中儲存了應用名為shendu的多環境配置檔案,配置檔案中有一個from引數 spring boot 版本是 1.5.

Spring Cloud SleuthZipkin整合時遇到的問題記錄

    在《spring cloud 微服務實戰》第402頁-----將spring cloud sleuth的跟蹤資訊通過訊息中介軟體收集傳送到zipkin這一部分,在之前你已經按照第一種方式(http方式)將跟蹤資訊收集到了zipkin上,現在又跟著書上用訊息中介軟體來

Spring Cloud & Kubernetes

spring-cloud-kubernetes(Kubernetes integration with Spring Cloud):該元件主要提供三方面的內容: 1. 將KubernetesClient注入到Spring Cloud應用中,用於服務發現,將一個

介紹Spring Cloud StreamRabbitMQ整合

Spring Cloud Stream是一個建立在Spring Boot和Spring Integration之上的框架,有助於建立事件驅動或訊息驅動的微服務。在本文中,我們將通過一些簡單的例子來介紹Spring Cloud Stream的概念和構造。 1

Spring cloud propertiesyml配置說明

encrypt說明 名稱 默 認 描述 encrypt.fail-on-error true 標記說,如果存在加密或解密錯誤,程序將失敗。 encrypt.key 對稱金鑰。作為一個更強大的替代方案,考慮使用金鑰庫。 encrypt.

Spring Cloud AlibabaSpring Boot、Spring Cloud之間不得不說的版本關系

微服務 git artifact ble tee strong 那些事兒 release tro 這篇博文是臨時增加出來的內容,主要是由於最近連載《Spring Cloud Alibaba基礎教程》系列的時候,碰到讀者咨詢的大量問題中存在一個比較普遍的問題:版本的選擇。其實