本文是《spring-cloud-kubernetes實戰系列》的第六篇,主要內容是在kubernetes上部署一個java web應用,該應用使用了spring-cloud-kubernetes框架,可使用kubernetes的configmap;java
若是您開發過SpringCloud應用,相信您對SpringCloud Config不會陌生,在微服務環境中,業務應用能夠從config server獲取所需的配置信息,以下圖所示:git
這是kubernetes提供的基本服務之一,建立一個configmap資源,對應着一份配置文件,能夠將該資源經過數據卷的形式映射到Pod上,這樣Pod就能用上這個配置文件了,以下圖:程序員
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,以下圖所示:web
理論上的準備工做已經差很少了,接下來經過實戰來展現spring-cloud-starter-kubernetes-config的神奇之處;spring
若是您不打算寫代碼,也能夠從GitHub上下載本次實戰的源碼,地址和連接信息以下表所示:apache
這個git項目中有多個文件夾,本章的應用在springcloudk8sconfigdemo文件夾下,以下圖所示:json
本次實戰的環境和版本信息以下:bootstrap
準備完畢,能夠開始實戰啦!api
<?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>複製代碼
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;瀏覽器
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;
}
}複製代碼
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受權相關設置來處理,步驟以下:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: default
name: pod-reader
rules:
- apiGroups: [""]
resources: ["pods","configmaps"]
verbs: ["get", "watch", "list"]複製代碼
apiVersion: v1
kind: ServiceAccount
metadata:
name: config-reader
namespace: default複製代碼
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複製代碼
接下來咱們在kubernetes環境建立configmap,再將springcloudk8sconfigdemo在kubernetes部署和啓動,經過springcloudk8sconfigdemo提供的http接口驗證應用是否已經從configmap中取得指定的配置;
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複製代碼
kubectl apply -f springcloudk8sconfigdemo.yml複製代碼
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] ------------------------------------------------------------------------複製代碼
minikube service springcloudk8sconfigdemo --url複製代碼
獲得服務地址是:http://192.168.121.133:31646
前面的實戰沒有指定springboot工程的profile,接下來指定profile爲development,看可否加載到配置文件中指定的配置,以下圖紅框所示:
spring:
application:
name: springcloudk8sconfigdemo
profiles:
active: development
cloud:
kubernetes:
config:
sources:
- name: ${spring.application.name}
namespace: default複製代碼
mvn clean install fabric8:deploy -Dfabric8.generator.from=fabric8/java-jboss-openjdk8-jdk -Pkubernetes複製代碼
minikube service springcloudk8sconfigdemo --url複製代碼
獲得服務地址是:http://192.168.121.133:30659
雖然咱們的應用已經成功從configmap取得配置信息,但遺憾的是,configmap的配置信息被修改後,這些修改是沒法實時同步到咱們的應用的,只能重啓應用來重現獲取配置,爲了解決這個問題,請參考本系列的下一篇 《spring-cloud-kubernetes自動同步k8s的configmap更新》