本文是《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) git@github.com: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;

3. 增加一个配置类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

5. 浏览器访问地址:http://192.168.121.133:31646/hello ,得到响应如下图,可见已经从configmap取得了配置文件,并且加载成功:

修改profile

前面的实战没有指定springboot工程的profile,接下来指定profile为development,看能否加载到配置文件中指定的配置,如下图红框所示:

  1. 修改项目的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

4. 浏览器访问地址: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-kubernetes与k8s的configmap的更多相关文章

  1. 朱晔和你聊Spring系列S1E11:小测Spring Cloud Kubernetes @ 阿里云K8S

    有关Spring Cloud Kubernates(以下简称SCK)详见https://github.com/spring-cloud/spring-cloud-kubernetes,在本文中我们主要 ...

  2. Spring Cloud Config整合Spring Cloud Kubernetes,在k8s上管理配置

    1 前言 欢迎访问南瓜慢说 www.pkslow.com获取更多精彩文章! Kubernetes有专门的ConfigMap和Secret来管理配置,但它也有一些局限性,所以还是希望通过Spring C ...

  3. Springboot整合Spring Cloud Kubernetes读取ConfigMap,支持自动刷新配置

    1 前言 欢迎访问南瓜慢说 www.pkslow.com获取更多精彩文章! Docker & Kubernetes相关文章:容器技术 之前介绍了Spring Cloud Config的用法,但 ...

  4. spring cloud kubernetes之serviceaccount permisson报错

    spring boot项目引用spring-cloud-starter-kubernetes <dependency> <groupId>org.springframework ...

  5. Netflix OSS、Spring Cloud还是Kubernetes? 都要吧!

    Netflix OSS是由Netflix公司主持开发的一套代码框架和库,目的是解决上了规模之后的分布式系统可能出现的一些有趣问题.对于当今时代的Java开发者们来说,Netflix OSS简直就是在云 ...

  6. 039.[转] 基于 Kubernetes 和 Spring Cloud 的微服务化实践

    http://dockone.io/article/2967 基于 Kubernetes 和 Spring Cloud 的微服务化实践 写在前面 网易云容器平台期望能给实施了微服务架构的团队提供完整的 ...

  7. 微服务Spring Cloud与Kubernetes比较

    转 http://www.tuicool.com/articles/VnMf2y3 Spring Cloud或Kubernetes都宣称它们是开发运行微服务的最好环境,哪个更好?答案是两个都是,但他们 ...

  8. 【架构】Kubernetes和Spring Cloud哪个部署微服务更好?

    Spring Cloud 和Kubernetes都自称自己是部署和运行微服务的最好环境,但是它们在本质上和解决不同问题上是有很大差异的.在本文中,我们将看到每个平台如何帮助交付基于微服务的架构(MSA ...

  9. 使用Spring Cloud Config统一管理配置,别再到处放配置文件了

    1 前言 欢迎访问南瓜慢说 www.pkslow.com获取更多精彩文章! 可配置是一个成熟软件系统应该提供的特性,而配置管理对于大型系统就显得十分重要,特别是对于拥有多个应用的微服务系统.可喜的是, ...

随机推荐

  1. CSDN Markdown 超链接

    CSDN Markdown 的超链接总是在当前页面打开新的链接,后来发现了一种可以在新窗口打开超链接的语法,如下: <a href="https://zh.wikipedia.org/ ...

  2. Linux基础文件类型

    一.文件时间 ls -l 文件名 仅看的是文件的修改时间 [root@linux ~]# ls -l /etc/passwd -rw-r--r-- root root 5月 : /etc/passwd ...

  3. 使用vue实现行列转换的一种方法。

    行列转换是一个老生常谈的问题,这几天逛知乎有遇到了这个问题.一个前端说,拿到的数据是单列的需要做转换才能够绑定,折腾了好久才搞定,还说这个应该后端直接出数据,不应该让前端折腾. 这个嘛,行列转换在后端 ...

  4. Power Designer导出模型的sql加注释-Oracle语句

    第一步:Database-->Edit Current DBMS 第二步: 然后分别将 Script-->Objects-->Table-->TableComment Scri ...

  5. 通过wireshark学习Traceroute命令和mtr(UDP,ICMP协议)

    traceroute: 通过TTL限定的ICMP/UDP/TCP侦测包来发现从本地主机到远端目标主机之间的第三层转发路径.用来调试网络连接性和路由问题. mtr: traceroute的一个变种,能根 ...

  6. canvas 使用图片跨域问题

    项目中需要生成海报,使用了前端生成图片的插件,将背景图,详情图,以及部分的文字说明放在一块并且生成一张新的图片,大体看了一下源码是通过canvas来实现的,在本地的时候完全没有问题,提交到服务器之后就 ...

  7. Linux--shell编程原理--03

    一.编程原理: 1.编程介绍: 计算机只能识别二进制指令 程序=指令+数据 根据服务的重心不同,我们分为面向过程编程,面向对象编程: a) 面向过程:侧重于指令的编程语言 b) 面向对象:侧重于数据的 ...

  8. HashMap与ConcurrentHashMap在Java8的改进

    链接:http://www.cnblogs.com/huaizuo/archive/2016/04/20/5413069.html#undefined http://www.cnblogs.com/h ...

  9. python语言特点简介 以及在Windows以及Mac中安装以及配置的注意事项

    正如前一篇随笔所提到的,python属于解释型语言 python语言有两个特点: 1.胶水语言(历史遗留问题,原来Perl语言作为Unix内置标准件,获得极大追捧,作为竞争者的python一开始是作为 ...

  10. 用原生JS实现AJAX和JSONP

    前端开发在需要与后端进行数据交互时,为了方便快捷,都会选择JQuery中封装的AJAX方法,但是有些时候,我们只需要JQuery的AJAX请求方法,而其他的功能用到的很少,这显然是没必要的.其实,原生 ...