spring-cloud-kubernetes自动同步k8s的configmap更新

简介: 上一篇《spring-cloud-kubernetes与k8s的configmap》中,我们应用将k8s的configmap当做配置中心,但配置文件变更后我们的应用无法及时同步,今天就来解决这个问题

欢迎访问我的GitHub

这里分类和汇总了欣宸的全部原创(含配套源码): https://github.com/zq2599/blog_demos

本篇概览

  • 本文是《spring-cloud-kubernetes实战系列》的第七篇,在上一篇《spring-cloud-kubernetes与k8s的configmap》,我们的springboot应用将k8s的configmap当做配置中心,从configmap中获取yml配置文件使用,就像使用spring cloud config服务一样,但遗憾的是,配置文件发生变化时我们的应用上还是旧的配置信息,只能通过重启应用来重新加载,今天的实战就要解决这个问题:当configmap中的配置信息变更后,我们的springboot应用能自动更新;

提前小结和上一篇的差异

要达到实时同步configmap变更的效果,需要将上一章的应用作以下改动:

  • 增加以下两个jar依赖:
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-actuator</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-actuator-autoconfigure</artifactId>
</dependency>
AI 代码解读
  • bootstrap.yml增加以下配置:
management:
  endpoint:
    restart:
      enabled: true
    health:
      enabled: true
    info:
      enabled: true
AI 代码解读
  • bootstrap.yml中的spring.cloud.kubernetes节点下增加子节点reload的配置,完整的bootstrap.yml内容如下:
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
AI 代码解读
  • 在controller中增加path为/health的服务响应,在k8s部署时,健康和就绪探针会调用此接口,如果没有响应,pod就无法正常使用:
@GetMapping("/health")
    public String health() {
        return "success";
    }
AI 代码解读
  • 以上就是开启自动更新的步骤了,您基于上一章的源码做上述更改即可,也可以随同本文一起重新开发一个全新应用,来实现获取configmap的配置,并且实时同步configmap的变化;

环境信息

  • 本次实战的环境和版本信息如下:
  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
  • 准备完毕,可以开始实战啦!

源码下载

  • 如果您不打算写代码,也可以从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项目中有多个文件夹,本章的应用在springcloudk8sreloadconfigdemo文件夹下,如下图所示:

在这里插入图片描述

  • 接下来,一起开始实战,开发一个java应用吧;

开发Java应用

  • 通过maven创建名为springcloudk8sreloadconfigdemo的springboot工程,pom.xml内容如下,要注意的是新增了依赖spring-cloud-starter-kubernetes-configspring-boot-actuatorspring-boot-actuator-autoconfigure,这是本次实战的重点:
<?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>springcloudk8sreloadconfigdemo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springcloudk8sreloadconfigdemo</name>
    <description>Demo project for Spring Cloud Kubernetes with Kubernetes ConfigMap,Change of configmap is reloadable</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-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-actuator-autoconfigure</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>
AI 代码解读
  • 项目的src\main\resources路径下不要创建application.yml文件,只创建名为bootstrap.yml的文件,内容如下:
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
AI 代码解读
  • 可见新增了配置项spring.cloud.kubernetes.reload和spring.cloud.kubernetes.config,前者用于开启自动更新配置,执行更新模式为500毫秒拉取一次,后者指定配置来源于kubernetes的哪个namespace下的哪个configmap;
  • 增加一个配置类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: zq2599@gmail.com
 * @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;
    }
}
AI 代码解读
  • 启动类Springcloudk8sreloadconfigdemoApplication.java,简单起见,将用于验证配置项是否生效的web接口也写在了这里面,即hello方法 ,这个方法是应用的关键,方法内会返回配置文件的值,我们的应用能否成功取得k8s的configmap的配置文件,通过此方法的返回值就能验证了,还要增加path为/health的方法,因为在k8s部署时健康探针和就绪探针会调用此接口,如果没有响应pod就无法正常使用:
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);
    }
}
AI 代码解读
  • 以上就是实战工程的所有代码了,仅仅只是引入了少量jar依赖,以及在启动配置文件中指定了configmap的信息和同步模式,即完成了获取配置文件的所有操作,至于代码中用到配置文件的地方,和使用SpringCloud Config并无差别。

解决权限问题

  • 我这里的是minikube,在部署了应用之后,默认的serviceaccount是没有权限访问K8S的API Server资源的,执行以下命令可以提升权限:
kubectl create clusterrolebinding permissive-binding \
  --clusterrole=cluster-admin \
  --user=admin \
  --user=kubelet \
  --group=system:serviceaccounts
AI 代码解读
  • 注意:以上办法只能用于开发和测试环境,不要用在生产环境,生产环境应参考Kubernetes的RBAC授权相关设置来处理,步骤如下:
  • 创建role:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: default
  name: pod-reader
rules:
  - apiGroups: [""]
    resources: ["pods","configmaps"]
    verbs: ["get", "watch", "list"]
AI 代码解读
  • 创建ServiceAccount:
apiVersion: v1
kind: ServiceAccount
metadata:
  name: config-reader
  namespace: default
AI 代码解读
  • 绑定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
AI 代码解读
  • 在deployment中指定上面的ServiceAccount;

验证

  • 现在进入验证阶段,验证步骤:
  1. 在kubernetes环境创建configmap;
  2. 再将springcloudk8sreloadconfigdemo在kubernetes部署和启动;
  3. 访问springcloudk8sreloadconfigdemo的http接口,验证应用能取得configmap中的配置;
  4. 修改configmap中的配置;
  5. 再次访问springcloudk8sreloadconfigdemo的http接口,看返回的配置内容是否是修改后的;
  • 接下来,验证开始:
  • 在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
AI 代码解读
  • 在springcloudk8sreloadconfigdemo.yml文件所在目录执行以下命令,即可在kubernetes创建名为springcloudk8sreloadconfigdemo的configmap的资源:
kubectl apply -f springcloudk8sreloadconfigdemo.yml
AI 代码解读
  • 在springcloudk8sreloadconfigdemo项目的pom.xml文件所在目录,执行以下命令,即可编译构建部署全部完成:
mvn clean install fabric8:deploy -Dfabric8.generator.from=fabric8/java-jboss-openjdk8-jdk -Pkubernetes
AI 代码解读
  • 操作成功后的控制台信息如下:
...
[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
AI 代码解读
  • 如果您的环境也是minikube,可以执行以下命令查看服务地址:
minikube service springcloudk8sreloadconfigdemo --url
AI 代码解读

得到服务地址是:http://192.168.121.128:31178

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

在这里插入图片描述

修改configmap的配置

  • 接下来修改configmap的配置,看能不能在应用上立即生效。
  • 执行以下命令进入configmap的编辑模式:
kubectl edit configmap springcloudk8sreloadconfigdemo
AI 代码解读
  • 在编辑模式下,就像vim编辑文本文件一样修改配置springcloudk8sreloadconfigdemo的内容,如下图红框所示,在原有的内容基础上增加一段"123456789":

在这里插入图片描述修改完毕后记得保存退出;

  • 浏览器访问地址:http://192.168.121.128:31178/hello ,得到响应如下图,可见刚刚的修改已经立即生效了:

在这里插入图片描述
至此验证通过,confimap修改的内容可以实时同步到我们的java应用;

尝试另一种同步模式

  • 回顾一下bootstrap.yml中和同步配置相关的参数,如下图红框所示:

在这里插入图片描述
polling是定时拉取的模式,间隔时间太大会影响实时性,太小又导致请求过于密集,所以spring-cloud-kubernetes框架还给出了另一种模式:事件通知,对应的值是event;

  • 设置事件通知模式的步骤:先将mode的值从polling改为event,再将period参数注释掉(该参数只在mode等于polling时有效),修改后如下:

在这里插入图片描述修改后,再次执行mvn命令构建和部署应用,然后将前面的验证步骤再做一次,看修改能否立即生效,具体的操作就不在此重复了,您自行验证即可;

  • 至此,spring-cloud-kubernetes与k8s的configmap的实战就完成了,尽管上一章已经能使用k8s的configmap,但是无法实时获取到configmap的变更,今天的实战弥补了这一遗憾,通过两种同步方式,任何配置的变更都能同步到我们的应用中。

欢迎关注阿里云开发者社区博客:程序员欣宸

学习路上,你不孤单,欣宸原创一路相伴...
相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
相关文章
基于阿里云容器服务Kubernetes版(ACK)的微服务架构设计与实践
本文介绍了如何基于阿里云容器服务Kubernetes版(ACK)设计和实现微服务架构。首先概述了微服务架构的优势与挑战,如模块化、可扩展性及技术多样性。接着详细描述了ACK的核心功能,包括集群管理、应用管理、网络与安全、监控与日志等。在设计基于ACK的微服务架构时,需考虑服务拆分、通信、发现与负载均衡、配置管理、监控与日志以及CI/CD等方面。通过一个电商应用案例,展示了用户服务、商品服务、订单服务和支付服务的具体部署步骤。最后总结了ACK为微服务架构提供的强大支持,帮助应对各种挑战,构建高效可靠的云原生应用。
正式开源,Doris Operator 支持高效 Kubernetes 容器化部署方案
飞轮科技推出了 Doris 的 Kubernetes Operator 开源项目(简称:Doris Operator),并捐赠给 Apache 基金会。该工具集成了原生 Kubernetes 资源的复杂管理能力,并融合了 Doris 组件间的分布式协同、用户集群形态的按需定制等经验,为用户提供了一个更简洁、高效、易用的容器化部署方案。
正式开源,Doris Operator 支持高效 Kubernetes 容器化部署方案
Kubernetes(k8s)和Docker Compose本质区别
理解它们的区别和各自的优势,有助于选择合适的工具来满足特定的项目需求。
312 19
二进制安装Kubernetes(k8s)v1.32.0
本指南提供了一个详细的步骤,用于在Linux系统上通过二进制文件安装Kubernetes(k8s)v1.32.0,支持IPv4+IPv6双栈。具体步骤包括环境准备、系统配置、组件安装和配置等。
1091 11
阿里云ACK备份中心,K8s集群业务应用数据的一站式灾备方案
本文源自2024云栖大会苏雅诗的演讲,探讨了K8s集群业务为何需要灾备及其重要性。文中强调了集群与业务高可用配置对稳定性的重要性,并指出人为误操作等风险,建议实施周期性和特定情况下的灾备措施。针对容器化业务,提出了灾备的新特性与需求,包括工作负载为核心、云资源信息的备份,以及有状态应用的数据保护。介绍了ACK推出的备份中心解决方案,支持命名空间、标签、资源类型等维度的备份,并具备存储卷数据保护功能,能够满足GitOps流程企业的特定需求。此外,还详细描述了备份中心的使用流程、控制台展示、灾备难点及解决方案等内容,展示了备份中心如何有效应对K8s集群资源和存储卷数据的灾备挑战。
深入理解Kubernetes——容器编排的王者之道
深入理解Kubernetes——容器编排的王者之道
82 1
云原生应用:Kubernetes在容器编排中的实践与挑战
【10月更文挑战第27天】Kubernetes(简称K8s)是云原生应用的核心容器编排平台,提供自动化、扩展和管理容器化应用的能力。本文介绍Kubernetes的基本概念、安装配置、核心组件(如Pod和Deployment)、服务发现与负载均衡、网络配置及安全性挑战,帮助读者理解和实践Kubernetes在容器编排中的应用。
151 4
云原生应用:Kubernetes在容器编排中的实践与挑战
【10月更文挑战第26天】随着云计算技术的发展,容器化成为现代应用部署的核心趋势。Kubernetes(K8s)作为容器编排领域的佼佼者,以其强大的可扩展性和自动化能力,为开发者提供了高效管理和部署容器化应用的平台。本文将详细介绍Kubernetes的基本概念、核心组件、实践过程及面临的挑战,帮助读者更好地理解和应用这一技术。
101 3
中间层 k8s(Kubernetes) 到底是什么,架构是怎么样的?
中间层 k8s(Kubernetes) 到底是什么,架构是怎么样的?
93 3
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等