在项目开发中, 大都会为不同的运行环境编写不同的配置文件, 比如生产环境使用application-prod.yml, 开发环境使用application-dev.yml.
在spring boot 应用部署到k8s之前, 配置文件的挂载一般都会在打jar包时包含在内, 或者把配置文件的内容保存在nacos之类的中间件中在启动应用时读取配置.
在应用k8s之后, 配置文件可以在通过ConfigMap资源剥离出来单独部署, 本次记录spring boot框架的java应用结合k8s的ConfigMap的实现外部配置文件挂载及配置热更新的一次实践。
一、配置自动更新,需要引入 kubernetes-config、健康检测依赖
1、项目依赖
- <?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 https://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.2.7.RELEASE</version>
- <relativePath/> <!-- lookup parent from repository -->
- </parent>
- <groupId>com.example</groupId>
- <artifactId>demo-v6</artifactId>
- <version>0.0.1</version>
- <name>demo-v6</name>
- <description>Demo project for Spring Boot</description>
- <properties>
- <java.version>1.8</java.version>
- </properties>
- <dependencies>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-web</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-starter-kubernetes-config</artifactId>
- <version>1.1.8.RELEASE</version>
- </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>
- </dependencies>
- <dependencyManagement>
- <dependencies>
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-dependencies</artifactId>
- <version>Hoxton.RELEASE</version>
- <type>pom</type>
- <scope>import</scope>
- </dependency>
- </dependencies>
- </dependencyManagement>
- <build>
- <plugins>
- <plugin>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-maven-plugin</artifactId>
- </plugin>
- </plugins>
- </build>
- </project>
2、使用到配置项的代码
- @RefreshScope
- @RestController
- public class HelloController {
-
- @Value("${name:null}")
- private String name;
-
- @Value("${age:0}")
- private int age;
-
- @GetMapping("/hello")
- public Object hello () {
- return name + ": " + age;
- }
- }
3、Dockerfile
- FROM openjdk:8-jdk-alpine
- RUN mkdir -p /app/
- COPY ./demo-v6-0.0.1.jar /app/
- RUN touch /app/demo-v6-0.0.1.jar
- RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
4、添加账号角色绑定demo-account.yaml
- apiVersion: v1
- kind: ServiceAccount
- metadata:
- name: config-reader
- namespace: demo
- ---
- apiVersion: rbac.authorization.k8s.io/v1
- kind: Role
- metadata:
- name: pod-reader
- namespace: demo
- rules:
- - apiGroups:
- - ""
- resources:
- - endpoints
- - pods
- - configmaps
- verbs:
- - list
- - get
- - watch
- ---
- apiVersion: rbac.authorization.k8s.io/v1
- kind: RoleBinding
- metadata:
- name: pod-reader
- namespace: demo
- roleRef:
- apiGroup: rbac.authorization.k8s.io
- kind: Role
- name: pod-reader
- subjects:
- - kind: ServiceAccount
- name: config-reader
- namespace: demo
5、configmap
- apiVersion: v1
- kind: ConfigMap
- metadata:
- name: demo-configmap
- namespace: demo
- labels:
- spring.cloud.kubernetes.config: "true"
- data:
- application.yml: |-
- server:
- port: 8989
-
- spring:
- application:
- name: demo-configmap
-
- cloud:
- kubernetes:
- config:
- sources:
- - name: demo-configmap
- namespace: demo
- reload:
- #自动更新配置的开关设置为打开
- enabled: true
- monitoring-config-maps: true
- monitoring-secrets: true
- mode: polling
- strategy: refresh
-
- management:
- endpoints:
- web:
- exposure:
- include: refresh,health
- endpoint:
- restart:
- enabled: true
- health:
- enabled: true
- info:
- enabled: true
-
- age: 18
- name: Tom
6、后端yaml
- apiVersion: apps/v1
- kind: Deployment
- metadata:
- name: demo
- namespace: demo
- labels:
- app: demo
- spec:
- replicas: 1
- selector:
- matchLabels:
- app: demo
- template:
- metadata:
- labels:
- app: demo
- spec:
- serviceAccountName: config-reader
- imagePullSecrets:
- - name: harbor-secret
- containers:
- - name: demo
- image: 192.168.1.6:8037/demo:0.0.1
- imagePullPolicy: Always
- command: ["java", "-jar", "/app/demo-v6-0.0.1.jar"]
- args: ["--spring.config.location=/app/config/application.yml", "--spring.profiles.active=dev"]
- ports:
- - containerPort: 8001
- volumeMounts:
- - name: host-time
- mountPath: /etc/localtime
- - name: demo-config
- mountPath: /app/config
- volumes:
- - name: host-time
- hostPath:
- path: /etc/localtime
- - name: demo-config
- configMap:
- name: demo-configmap
- ---
- apiVersion: v1
- kind: Service
- metadata:
- name: demo
- namespace: demo
- labels:
- app: demo
- spec:
- type: ClusterIP
- ports:
- - port: 8001
- targetPort: 8001
- selector:
- app: demo
效果:
configmap修改前:
configmap修改后:
二、手动触发滚动更新,无须引入任何依赖
1、configmap
- apiVersion: v1
- kind: ConfigMap
- metadata:
- name: demo-configmap
- namespace: demo
- labels:
- spring.cloud.kubernetes.config: "true"
- data:
- application.yml: |-
- server:
- port: 8989
- spring:
- application:
- name: demo-configmap
- age: 18
- name: Tom
2、后端yaml
- apiVersion: apps/v1
- kind: Deployment
- metadata:
- name: demo
- namespace: demo
- labels:
- app: demo
- spec:
- replicas: 1
- selector:
- matchLabels:
- app: demo
- template:
- metadata:
- labels:
- app: demo
- spec:
- imagePullSecrets:
- - name: harbor-secret
- containers:
- - name: demo
- image: 192.168.1.6:8037/demo:0.0.1
- imagePullPolicy: Always
- command: ["java", "-jar", "/app/demo-v6-0.0.1.jar"]
- args: ["--spring.config.location=/app/config/application.yml", "--spring.profiles.active=dev"]
- ports:
- - containerPort: 8001
- volumeMounts:
- - name: host-time
- mountPath: /etc/localtime
- - name: demo-config
- mountPath: /app/config
- volumes:
- - name: host-time
- hostPath:
- path: /etc/localtime
- - name: demo-config
- configMap:
- name: demo-configmap
- ---
- apiVersion: v1
- kind: Service
- metadata:
- name: demo
- namespace: demo
- labels:
- app: demo
- spec:
- type: ClusterIP
- ports:
- - port: 8001
- targetPort: 8001
- selector:
- app: demo
3、利用patch更新annotation的值,来触发pod滚动更新
kubectl patch deployment -n demo --patch '{"spec": {"template": {"metadata": {"annotations": {"version/config": "20220614" }}}}}'
三、Secret保存账号密码信息
思路:jasypt加密 -> ENC(加密后的字符串) -> base64编码 -> Secret
1、jasypt加密
2、base64编码
3、secret
4、后端引用yaml
5、修改configmap值后,发现程序中的值不会自动更新,采用手动方式触发刷新
curl ‘ip:port/actuator/refresh’