本文是《spring-cloud-kubernetes实战系列》的第七篇,在上一篇《spring-cloud-kubernetes与k8s的configmap》,我们的springboot应用将k8s的configmap当做配置中心,从configmap中获取yml配置文件使用,就像使用spring cloud config服务一样,但遗憾的是,配置文件发生变化时我们的应用上还是旧的配置信息,只能通过重启应用来重新加载,今天的实战就要解决这个问题:当configmap中的配置信息变更后,我们的springboot应用能自动更新;
要达到实时同步configmap变更的效果,需要将上一章的应用作以下改动:
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-actuatorartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-actuator-autoconfigureartifactId>
dependency>
management:
endpoint:
restart:
enabled: true
health:
enabled: true
info:
enabled: true
management:
endpoint:
restart:
enabled: true
health:
enabled: true
info:
enabled: true
spring:
application:
name: springcloudk8sconfigdemo
profiles:
active: development
cloud:
kubernetes:
reload:
#自动更新配置的开关设置为打开
enabled: true
#更新配置信息的模式是主动拉取
mode: polling
#主动拉取的间隔时间是500毫秒
period: 500
config:
sources:
- name: ${spring.application.name}
namespace: default
@GetMapping("/health")
public String health() {
return "success";
}
以上就是开启自动更新的步骤了,您基于上一章的源码做上述更改即可,也可以随同本文一起重新开发一个全新应用,来实现获取configmap的配置,并且实时同步configmap的变化;
本次实战的环境和版本信息如下:
准备完毕,可以开始实战啦!
如果您不打算写代码,也可以从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项目中有多个文件夹,本章的应用在springcloudk8sreloadconfigdemo文件夹下,如下图所示:
接下来,一起开始实战,开发一个java应用吧;
<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.0modelVersion>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.1.6.RELEASEversion>
<relativePath/>
parent>
<groupId>com.bolingcavalrygroupId>
<artifactId>springcloudk8sreloadconfigdemoartifactId>
<version>0.0.1-SNAPSHOTversion>
<name>springcloudk8sreloadconfigdemoname>
<description>Demo project for Spring Cloud Kubernetes with Kubernetes ConfigMap,Change of configmap is reloadabledescription>
<properties>
<java.version>1.8java.version>
<spring-boot.version>2.1.6.RELEASEspring-boot.version>
<maven-checkstyle-plugin.failsOnError>falsemaven-checkstyle-plugin.failsOnError>
<maven-checkstyle-plugin.failsOnViolation>falsemaven-checkstyle-plugin.failsOnViolation>
<maven-checkstyle-plugin.includeTestSourceDirectory>falsemaven-checkstyle-plugin.includeTestSourceDirectory>
<maven-compiler-plugin.version>3.5maven-compiler-plugin.version>
<maven-deploy-plugin.version>2.8.2maven-deploy-plugin.version>
<maven-failsafe-plugin.version>2.18.1maven-failsafe-plugin.version>
<maven-surefire-plugin.version>2.21.0maven-surefire-plugin.version>
<fabric8.maven.plugin.version>3.5.37fabric8.maven.plugin.version>
<springcloud.kubernetes.version>1.0.1.RELEASEspringcloud.kubernetes.version>
<spring-cloud.version>Greenwich.SR2spring-cloud.version>
properties>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-actuatorartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-actuator-autoconfigureartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-kubernetes-configartifactId>
<version>${springcloud.kubernetes.version}version>
dependency>
dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-dependenciesartifactId>
<version>${spring-cloud.version}version>
<type>pomtype>
<scope>importscope>
dependency>
dependencies>
dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
<version>${spring-boot.version}version>
<executions>
<execution>
<goals>
<goal>repackagegoal>
goals>
execution>
executions>
plugin>
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-deploy-pluginartifactId>
<version>${maven-deploy-plugin.version}version>
<configuration>
<skip>trueskip>
configuration>
plugin>
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-surefire-pluginartifactId>
<version>${maven-surefire-plugin.version}version>
<configuration>
<skipTests>trueskipTests>
<useSystemClassLoader>falseuseSystemClassLoader>
configuration>
plugin>
<plugin>
<groupId>io.fabric8groupId>
<artifactId>fabric8-maven-pluginartifactId>
<version>${fabric8.maven.plugin.version}version>
<executions>
<execution>
<id>fmpid>
<goals>
<goal>resourcegoal>
goals>
execution>
executions>
plugin>
plugins>
build>
<profiles>
<profile>
<id>kubernetesid>
<build>
<plugins>
<plugin>
<groupId>io.fabric8groupId>
<artifactId>fabric8-maven-pluginartifactId>
<version>${fabric8.maven.plugin.version}version>
<executions>
<execution>
<id>fmpid>
<goals>
<goal>resourcegoal>
<goal>buildgoal>
goals>
execution>
executions>
<configuration>
<enricher>
<config>
<fmp-service>
<type>NodePorttype>
fmp-service>
config>
enricher>
configuration>
plugin>
plugins>
build>
profile>
profiles>
project>
management:
endpoint:
restart:
enabled: true
health:
enabled: true
info:
enabled: true
spring:
application:
name: springcloudk8sreloadconfigdemo
cloud:
kubernetes:
reload:
#自动更新配置的开关设置为打开
enabled: true
#更新配置信息的模式:polling是主动拉取,event是事件通知
mode: polling
#主动拉取的间隔时间是500毫秒
period: 500
config:
sources:
- name: ${spring.application.name}
namespace: default
可见新增了配置项spring.cloud.kubernetes.reload和spring.cloud.kubernetes.config,前者用于开启自动更新配置,执行更新模式为500毫秒拉取一次,后者指定配置来源于kubernetes的哪个namespace下的哪个configmap;
3. 增加一个配置类DummyConfig.java,注解ConfigurationProperties的prefix="greeting"表示该类用到的配置项都是名为"greeting"的配置项的子内容 :
package com.bolingcavalry.springcloudk8sreloadconfigdemo;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
/**
* @Description: 配置类,此处可以加载配置文件中的内容
* @author: willzhao E-mail: [email protected]
* @date: 2019/7/27 18:24
*/
@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.springcloudk8sreloadconfigdemo;
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 Springcloudk8sreloadconfigdemoApplication {
@Autowired
private DummyConfig dummyConfig;
@GetMapping("/health")
public String health() {
return "success";
}
@GetMapping("/hello")
public String hello() {
return dummyConfig.getMessage()
+ " ["
+ new SimpleDateFormat().format(new Date())
+ "]";
}
public static void main(String[] args) {
SpringApplication.run(Springcloudk8sreloadconfigdemoApplication.class, args);
}
}
以上就是实战工程的所有代码了,仅仅只是引入了少量jar依赖,以及在启动配置文件中指定了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
现在进入验证阶段,验证步骤:
接下来,验证开始:
6. 在kubernetes环境新建名为springcloudk8sreloadconfigdemo.yml的文件,内容如下:
kind: ConfigMap
apiVersion: v1
metadata:
name: springcloudk8sreloadconfigdemo
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 springcloudk8sreloadconfigdemo.yml
mvn clean install fabric8:deploy -Dfabric8.generator.from=fabric8/java-jboss-openjdk8-jdk -Pkubernetes
操作成功后的控制台信息如下:
...
[INFO]
[INFO] <<< fabric8-maven-plugin:3.5.37:deploy (default-cli) < install @ springcloudk8sreloadconfigdemo <<<
[INFO]
[INFO]
[INFO] --- fabric8-maven-plugin:3.5.37:deploy (default-cli) @ springcloudk8sreloadconfigdemo ---
[INFO] F8: Using Kubernetes at https://192.168.121.128:8443/ in namespace default with manifest /usr/local/temp/201907/27/springcloudk8sreloadconfigdemo/target/classes/META-INF/fabric8/kubernetes.yml
[INFO] Using namespace: default
[INFO] Creating a Service from kubernetes.yml namespace default name springcloudk8sreloadconfigdemo
[INFO] Created Service: target/fabric8/applyJson/default/service-springcloudk8sreloadconfigdemo.json
[INFO] Using namespace: default
[INFO] Creating a Deployment from kubernetes.yml namespace default name springcloudk8sreloadconfigdemo
[INFO] Created Deployment: target/fabric8/applyJson/default/deployment-springcloudk8sreloadconfigdemo.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: 08:38 min
[INFO] Finished at: 2019-07-27T18:56:21+08:00
minikube service springcloudk8sreloadconfigdemo --url
得到服务地址是:http://192.168.121.128:31178
10. 浏览器访问地址:http://192.168.121.128:31178/hello ,得到响应如下图,可见已经从configmap取得了配置文件,并且加载成功:
接下来修改configmap的配置,看能不能在应用上立即生效。
kubectl edit configmap springcloudk8sreloadconfigdemo
回顾一下bootstrap.yml中和同步配置相关的参数,如下图红框所示:
polling是定时拉取的模式,间隔时间太大会影响实时性,太小又导致请求过于密集,所以spring-cloud-kubernetes框架还给出了另一种模式:事件通知,对应的值是event;
设置事件通知模式的步骤:先将mode的值从polling改为event,再将period参数注释掉(该参数只在mode等于polling时有效),修改后如下:
修改后,再次执行mvn命令构建和部署应用,然后将前面的验证步骤再做一次,看修改能否立即生效,具体的操作就不在此重复了,您自行验证即可;
至此,spring-cloud-kubernetes与k8s的configmap的实战就完成了,尽管上一章已经能使用k8s的configmap,但是无法实时获取到configmap的变更,今天的实战弥补了这一遗憾,通过两种同步方式,任何配置的变更都能同步到我们的应用中。