眾所周知懂酱,配置管理是微服務(wù)中非常重要的一環(huán)。通過(guò)集中化的配置中心誊抛,可以使維護(hù)人員統(tǒng)一管理
dev
列牺、test
、stage
拗窃、prod
等各類環(huán)境的配置瞎领,大大提高了維護(hù)效率,并使得配置變更可以實(shí)時(shí)下發(fā)給各節(jié)點(diǎn)随夸,并被追蹤和審計(jì)九默,本文探討云原生環(huán)境下基于Spring Cloud Config+kubernetes ConfigMap的配置管理實(shí)踐,大家如果有更好的實(shí)現(xiàn)方式宾毒,也歡迎一起探討驼修。
方案選擇
目前的配置獲取方式,基本上有以下幾種
環(huán)境變量注入:這種方式把配置參數(shù)直接注入系統(tǒng)環(huán)境變量,應(yīng)用直接從環(huán)境變量中獲取配置信息乙各,配置項(xiàng)較少的情況還是可以用用的墨礁,多了麻煩不說(shuō),配置的變更審計(jì)也是問(wèn)題耳峦,
configmap
即是這種方式恩静,好處是系統(tǒng)級(jí),外部依賴較少通過(guò)maven工具:執(zhí)行類似
mvn cleanpackage-Penv
這樣的命令妇萄,在編譯打包階段將環(huán)境信息注入spring boot:Spring Boot中也提供了多環(huán)境配置功能蜕企,可以設(shè)置
application-{env}.properties
區(qū)分環(huán)境信息咬荷,啟動(dòng)時(shí)增加
spring.profiles.active=dev
這樣的參數(shù)冠句,在啟動(dòng)時(shí)將配置信息注入配置中心:這是微服務(wù)架構(gòu)中比較主流的解決方案,有代表性的有攜程的apollo幸乒、百度disconf以及spring自己的 spring cloud config
綜合幾種方式的優(yōu)缺點(diǎn)懦底,我選擇了Spring Cloud Config+kubernetes ConfigMap的解決方案。選擇Spring Cloud Config的原因是比較輕量級(jí)罕扎,配合eureka可以快速搭建一個(gè)分布式的配置中心聚唐,再結(jié)合一些開(kāi)源的配置管理UI框架(比如SCCA,后面會(huì)提到)腔召,基本可以滿足目前的需要杆查。結(jié)合Spring Cloud Bus組件可以實(shí)現(xiàn)實(shí)時(shí)的配置下發(fā),另外由于是原生的臀蛛,和Spring其他組件的集成也比較方便亲桦,不像apollo都是自己一套(自帶eureka),個(gè)人感覺(jué)有點(diǎn)重了浊仆。為便于敘述客峭,下文假設(shè)有dev、test抡柿、prod三個(gè)配置中心舔琅,分別對(duì)應(yīng)三個(gè)不同的環(huán)境。
環(huán)境變量配置
使用環(huán)境變量的原因洲劣,是開(kāi)發(fā)和測(cè)試的環(huán)境不一致备蚓,開(kāi)發(fā)一般在自己電腦上進(jìn)行開(kāi)發(fā),所以需要設(shè)置自己終端的環(huán)境變量囱稽,而測(cè)試及生產(chǎn)環(huán)境都是在K8S集群內(nèi)郊尝,所以需要通過(guò)ConfigMap來(lái)進(jìn)行環(huán)境變量配置,從而實(shí)現(xiàn)了配置中心地址與環(huán)境的解耦粗悯。
開(kāi)發(fā)終端配置
比較簡(jiǎn)單虚循,直接在環(huán)境變量中設(shè)置如下參數(shù),注意這里設(shè)置的是dev環(huán)境的配置中心
注意設(shè)置完之后eclipse需要重啟一下,否則讀不到變更的環(huán)境變量(IDEA我沒(méi)有測(cè)過(guò)横缔,不知道是不是一樣)铺遂。可以通過(guò)下面這段代碼看看環(huán)境變量是否正確獲取
@RestController
public class WebController {
@Autowired
private Environment env;
@RequestMapping(value = "getEnvParam", method = RequestMethod.GET)
public String getEnvParam() {
return "config server : " + env.getProperty("CONFIG_SERVER_ADDRESS");
}
}
在瀏覽器輸入U(xiǎn)RL后應(yīng)該可以顯示對(duì)應(yīng)的環(huán)境變量值
ConfigMap配置
使用kubectl創(chuàng)建configmap資源有幾種方式茎刚,這里我們直接使用命令行參數(shù)的方式創(chuàng)建配置信息對(duì)象襟锐,注意這里配置的是test環(huán)境的配置中心
[root@localhost ~]# kubectl create configmap config-server --from-literal=config.address=http://10.10.0.2:10002 --from-literal=config.profile=test
configmap "config-server" created
執(zhí)行如下命令確認(rèn)configmap資源被成功創(chuàng)建
[root@localhost ~]# kubectl get configmap config-server -o yaml
apiVersion: v1
data:
config.address: http://10.10.0.2:10002
config.profile: test
kind: ConfigMap
metadata:
creationTimestamp: 2018-11-07T11:14:27Z
name: config-server
namespace: default
resourceVersion: "18390952"
selfLink: /api/v1/namespaces/default/configmaps/config-server
uid: 4a4b3713-e27e-11e8-8088-005056bd4c7c
將configmap對(duì)象注入我們創(chuàng)建的應(yīng)用deployment對(duì)象中,可以直接edit資源膛锭,也可以使用patch方式粮坞,注意spec.containers.env
部分,即是我們注入的configmap信息
spec:
replicas: 1
selector:
matchLabels:
run: service-base
strategy:
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
type: RollingUpdate
template:
metadata:
creationTimestamp: null
labels:
run: service-base
spec:
containers:
- command:
- java
- -Djava.security.egd=file:/dev/./urandom
- -jar
- /home/app.jar
env:
- name: CONFIG_SERVER_ADDRESS
valueFrom:
configMapKeyRef:
key: config.uri
name: config-server
- name: CONFIG_SERVER_PROFILE
valueFrom:
configMapKeyRef:
key: config.profile
name: config-server
image: 10.0.0.62:5000/alpine/jre:8
imagePullPolicy: IfNotPresent
name: service-base
ports:
- containerPort: 33300
protocol: TCP
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /home
name: app-volume
dnsPolicy: ClusterFirst
Spring Cloud Config配置
這其實(shí)就是一個(gè)標(biāo)準(zhǔn)的Spring Cloud Config配置中心配置初狰,這里不展開(kāi)了莫杈,需要的同學(xué)可以直接看這篇教程∩萑耄考慮到開(kāi)發(fā)生產(chǎn)環(huán)境的隔離筝闹、管理和可靠性的需要,我這邊使用的是db存儲(chǔ)模式(需要edgware以上版本)腥光,配置文件如下
spring:
application:
name: config-server
datasource:
driver-class-name: oracle.jdbc.driver.OracleDriver
url: jdbc:oracle:thin:@10.0.0.56:1521/orac
username: test
password: test
jpa:
properties:
hibernate:
dialect: org.hibernate.dialect.Oracle10gDialect
profiles:
active: jdbc
cloud:
config:
server:
jdbc:
sql: SELECT P_KEY, P_VALUE from PROPERTY where APPLICATION=? and PROFILE=? and LABEL=?
server:
port: 10002
encrypt:
key: test
之后配合一個(gè)程序猿DD同學(xué)開(kāi)源的配置管理項(xiàng)目SCCA(github地址),能以可視化方式管理各環(huán)境配置关顷,基本滿足目前要求。如果想和內(nèi)部已有的服務(wù)管理平臺(tái)集成武福,也非常方便议双,只要實(shí)現(xiàn)對(duì)property這張配置表的CRUD就行了,spring cloud config會(huì)自動(dòng)監(jiān)聽(tīng)property里的變化并刷新參數(shù)捉片,這也是我比較推薦db模式的原因平痰。SCCA配置界面如下:
應(yīng)用配置
至此所有準(zhǔn)備工作完成,在應(yīng)用里直接配置上配置中心的環(huán)境變量界睁,就可以在各環(huán)境中無(wú)縫切換了觉增,應(yīng)用配置如下
spring:
application:
name: service-base
cloud:
config:
uri: ${CONFIG_SERVER_ADDRESS}
profile: ${CONFIG_SERVER_PROFILE}
label: master
server:
port: 33000