博观而约取,厚积而薄发。这篇文章主要讲述持续集成CI&CD之配置管理最佳实践相关的知识,希望能为你提供帮助。
上一章:??持续集成CI&
CD之工具快速搭建??
下一章:??持续集成CI&
CD之CI的完整版最佳实践??
选用阿里的nacos配置管理进行最佳实践
Nacos Config 配置方案设计业务配置的一些场景
在实际的业务场景中应用和共享配置间的关系可能如下图所示:
极简配置方案设计
在实际开发、运维过程中,如果一个或多个应用使用了多个配置文件,特别是共享的配置文件,很容易出现误解,搞混配置【需要区别多个配置文件的优先级】;建议设计2层配置文件即可,手动配置的全局共享配置只能有一个,并且不支持动态刷新;每一个应用除了有一个全局配置文件后,还应该默认有一个专属的配置(默认可以不存在),支持动态刷新;如下图
配置的优化级别应该是:本地配置 <
全局共享配置<
专属配置不同的环境配置,应该使用空间进行隔离
实现案例nacos配置的优先级
Spring Cloud Alibaba Nacos Config 目前提供了三种配置能力从 Nacos 拉取相关的配置。
当三种方式共同使用时,他们的一个优先级关系是:A <
B <
C?spring.cloud.nacos.config.shared-configs[n].data-id?
? 支持多个共享 Data Id 的配置?spring.cloud.nacos.config.extension-configs[n].data-id?
? 的方式支持多个扩展 Data Id 的配置
nacos配置的使用
以spring-cloud为例基于nacos配置优先级,以及设计方案的最简原则,建议spring-cloud项目使用以下bootstrap.yml文件配置
server:
port:
$CONTAINER_PORT:8080
#所有类似$CONTAINER_PORT:8080写法的
CONTAINER_PORT不能改动,默认值根据业务修改
servlet:
context-path:
/
#工程访问路径业务自己定义
#
https://github.com/spring-projects
spring:
main:
allow-bean-definition-overriding:
true
#
允许定义bean的覆盖
application:
name:
$APP_NAME:talkweb-demo
#默认值一般修改为与工程名或子模块名相同
cloud:
###nacos配置###
nacos:
server-addr:
$NACOS_URL:192.168.141.203:8848
username:
$NACOS_USR:nacos-usr
password:
$NACOS_PWD:nacos-pwd
discovery:
namespace:
$NACOS_NAMESPACE:namespace-dev
group:
$NACOS_GROUP:DEFAULT_GROUP
config:
namespace:
$NACOS_NAMESPACE:namespace-dev
file-extension:
properties
extension-configs:
#
全局配置不支持动态刷新
-
data-id:
$GLOBAL_COMM:global-comm.properties
group:
$NACOS_GROUP:DEFAULT_GROUP
??全局配置文件?
?:global-comm.properties,(手动设置data-id,全局的公共配置)
??空间ID?
?:namespace-dev(设置空间ID时,建议手动输入可读的ID,不要系统自动生成)
??应用专属配置文件?
?:$spring.application.name.properties,(系统默认设置的data-id,主要使用场景是,”单个服务调优“或者“在公共配置中会影响其他服务的特别的配置“)
为保证代码完整性、可阅读性,所有的代码配置都必须在本地的配置中体现,并设置默认值[$环境:默认值]。所以建议nacos中的配置文件以key=vue 的形式的属性文件存在,用于覆盖本地的默认值。
扩展有些管理系统的配置的一些开关,可以结合nacos的配置实现,如下增加??系统全局配置?
?
spring:
application:
name:
$APP_NAME:talkweb-demo
#默认值一般修改为与工程名或子模块名相同
cloud:
###nacos配置###
nacos:
server-addr:
$NACOS_URL:192.168.141.203:8848
username:
$NACOS_USR:nacos-usr
password:
$NACOS_PWD:nacos-pwd
discovery:
namespace:
$NACOS_NAMESPACE:namespace-dev
group:
$NACOS_GROUP:DEFAULT_GROUP
config:
namespace:
$NACOS_NAMESPACE:namespace-dev
file-extension:
properties
extension-configs:
#
全局配置不支持动态刷新
-
data-id:
$GLOBAL_COMM:global-comm.properties
group:
$NACOS_GROUP:DEFAULT_GROUP
#
系统全局配置支持动态刷新[该配置由系统默认创建,不能人为操作]
-
data-id:
$SYS_GLOBAL_CONFIG:sys-global-config.properties
group:
$NACOS_GROUP:DEFAULT_GROUP
refresh:
true
系统默认全局配置:sys-global-config.properties (手动设置data-id,支持动态刷新,业务系统自动生成,不能人为操作,主要用于管理后台配置的参数,eg:邮箱配置、短信配置、系统开关等等)
前端使用nacos配置
为了使一套代码能再不同的环境中,前端也需要使用配置中心,最好能与后端使用一套配置。设计方案:前端工程(vue)在项目中使用公共的一个配置文件;部署时利用shell脚本,从nacos中获取配置后, 自动替换前端配置文件中的配置项。
以k8s部署为例1.在docker编译时,将??默认的配置文件?
??替换为??带有占位符配置文件?
?。(占位符,只是将具体值由nacos中key取代,eg: $key)
FROM
nginx:stable
MAINTAINER
Qiming
Mei
<
meiqiming@talkweb.com.cn>
COPY
dist/
/usr/share/nginx/html/
COPY
init.js
/usr/share/nginx/html/static/js/config.js
COPY
entrypoint.sh
/
RUN
chmod
+x
/entrypoint.sh
#CMD
["/bin/bash","-c",
"/entrypoint.sh"
]
ENTRYPOINT
["/entrypoint.sh"]
2.利用启动entrypoint.sh配置文件中??替换占位符?
?
#!/bin/bash
#配置文件路径,默认是static/js/config.js
__config_file="/usr/share/nginx/html/static/js/config.js"
if
[
-n
"$VUE_CONFIG_FILE_PATH"
];
then
__config_file="/usr/share/nginx/html/$VUE_CONFIG_FILE_PATH"
fi;
#
if
[
-f
"/init-env/env.conf"
];
then
grep
-v
"^#"
/init-env/env.conf
|grep
-v
^$
|while
read
LINE
do
A=`echo
$LINE
|awk
-F
"="
print
$1`
B=`echo
$LINE
|awk
-F
"$A="
print
$2`
result=$(echo
$A
|
grep
"\\.")
if
[[
"$result"
!=
""
]];
then
echo
"#$A=\\"$B\\""
>
>
/init-env/env1.conf
elif
[[
-z
"$B"
]];
then
echo
"空行,不需转换舍弃";
else
B=$B//\\"/\\\\\\";
#处理特殊字符
echo
"$A=\\"$B/\\`/\\\\\\`\\""
>
>
/init-env/env1.conf
fi
done
sed
-i
s/\\r//
/init-env/env1.conf
#sed
-e
s#\\&
#\\\\&
#g
env.conf
>
env1.conf
eval
"$(cat
/init-env/env1.conf)"
rm
-f
/init-env/env1.conf
else
echo
"/init-env/env.conf文件不存在,注意需要引入外部环境变量哦!";
fi;
#备份配置文件,存在就不备份,不存在就备份
if
[
!
-f
"$__config_file.env"
];
then
cp
$__config_file
$__config_file.env
fi
#
变量替换方式直接会将$的变量替换掉
if
[
-f
"/init-env/env.conf"
-o
"$IS_ENV_REPLACE"
=
"true"
];
then
#替换$中的环境变量
eval
"cat
<
<
EOF
$(<
$__config_file.env)
EOF
"
>
$__config_file
#删除环境变量文件
rm
-rf
/init-env/env.conf
#赋予可读权限
chmod
-R
+r
/usr/share/nginx/html
fi
nginx
-g
daemon
off;
3.利用k8s的初始化容器下载nacos配置文件 ??__XXX__?
?为占位符,部署时会替换为具体的值
---
apiVersion:
apps/v1
kind:
Deployment
metadata:
name:
__DOMAIN_NAME__
namespace:
__NAME_SPACE__
spec:
selector:
matchLabels:
app:
__DOMAIN_NAME__
replicas:
__REPLICAS_NUM__
template:
metadata:
labels:
app:
__DOMAIN_NAME__
spec:
initContainers:
-
name:
init-env-sidecar
image:
busybox:latest
command:
[
"sh",
"-c"]
args:
-
set
-ex;
CONFIG_FILE=$CONFIG_FILE:-"vue-comm.properties";
SYS_GLOBAL_CONFIG=$SYS_GLOBAL_CONFIG:-"sys-global-config.properties";
wget
--post-data="https://www.songbingjia.com/android/username=$NACOS_USR&
password=$NACOS_PWD"
-S
"$NACOS_URL/nacos/v1/auth/users/login"
-O
login-token;
access_token=$(grep
-Eo
"accessToken":"([^"]*)"
login-token
|awk
-F
\\":\\"
print
$2);
access_token=$access_token/\\"/;
rm
-f
/init-env/env.conf;
rm
-f
/init-env/env-sys.conf;
wget
"$NACOS_URL/nacos/v1/cs/configs?dataId=$CONFIG_FILE&
group=$NACOS_GROUP&
tenant=$NACOS_NAMESPACE&
accessToken=$access_token"
-O
/init-env/env.conf;
wget
"$NACOS_URL/nacos/v1/cs/configs?dataId=$SYS_GLOBAL_CONFIG&
group=$NACOS_GROUP&
tenant=$NACOS_NAMESPACE&
accessToken=$access_token"
-O
/init-env/env-sys.conf
||
return
0;
if
[
$?
-eq
0
-a
-f
"/init-env/env-sys.conf"
];
then
echo
-e
"\\n"
>
>
/init-env/env.conf;
cat
/init-env/env-sys.conf
>
>
/init-env/env.conf;
fi
env:
#环境变量设置
-
name:
NACOS_NAMESPACE
value:
__NACOS_NAMESPACE__
-
name:
NACOS_GROUP
value:
__NACOS_GROUP__
-
name:
SYS_GLOBAL_CONFIG
value:
__SYS_GLOBAL_CONFIG__
-
name:
CONFIG_FILE
value:
__CONFIG_FILE__
-
name:
NACOS_URL
value:
__NACOS_URL__
envFrom:
-
secretRef:
name:
__NACOS_AUTH__
volumeMounts:
-
name:
init-env
mountPath:
/init-env/
containers:
-
name:
__DOMAIN_NAME__
image:
__DOCKER_IMAGE__
imagePullPolicy:
IfNotPresent
#本地存在就不到远程拉取镜像
env:
#环境变量设置
-
name:
TZ
value:
Asia/Shanghai
-
name:
DOMAIN_NAME
value:
__DOMAIN_NAME__.__NAME_SPACE__
resources:
#资源限制
requests:
memory:
"128Mi"
cpu:
"100m"
#最低需要
0.1个cpu
limits:
memory:
"__LIMIT_MEMORY__Mi"
cpu:
"1000m"
ports:
-
containerPort:
80
readinessProbe:
#就绪探针
#
httpGet:
#
path:
/index.html
#
port:
80
tcpSocket:
port:
80
initialDelaySeconds:
30
periodSeconds:
15
timeoutSeconds:
5
livenessProbe:
#健康检查
#
httpGet:
#
path:
/index.html
#
port:
80
tcpSocket:
port:
80
initialDelaySeconds:
30
periodSeconds:
15
timeoutSeconds:
5
volumeMounts:
-
name:
time-config
mountPath:
/etc/localtime
readOnly:
true
-
name:
init-env
mountPath:
/init-env/
imagePullSecrets:
-
name:
__DOCKER_REGISTRY_SECRET__
nodeSelector:
isDev:
"true"
volumes:
-
name:
time-config
hostPath:
path:
/etc/localtime
-
name:
init-env
emptyDir:
【持续集成CI&CD之配置管理最佳实践】
推荐阅读
- 客快物流大数据项目(十五)(DockeFile常用命令)
- Docker容器(将带UI的程序直接转为Web应用,so easy)
- Jetbrains GoLand 2021软件安装包和安装教程
- 虚拟机数据恢复Linux系统下误删除KVM虚拟机的数据恢复案例
- C#/VB.NET 将文本内容更改为大写
- openGauss安装前主机初始化
- 汇编语言入门-存储寄存器
- netstat查看网络状态
- 太厉害了,通过文档内容快速查找文件,1行Python代码实现