可能是Asp.net Core On host、 docker、kubernetes(K8s) 配置读取的最佳实践

可能是Asp.net Core On host、 docker、kubernetes(K8s) 配置读取的最佳实践

写在前面

为了不违反广告法,我竭尽全力,不过“最佳实践”确是标题党无疑,如果硬要说的话 只能是个人最佳实践。

问题引出

​ 可能很多新手都会遇到同样的问题:我要我的Asp.net Core 应用传统方式直接部署(host),docker部署(docker-compose),kubernetes(以下称k8s)下部署,都用统一的方式读取配置,怎么实现呢?。

​ 大家知道,我们默认平时配置文件以appsettings.jsonappsettings.{EnvironmentName}.json 形式存在,这样在host方式下面没有问题,但在docker下,如果直接把配置打包到镜像,那每次改一下下配置就需要重新打包,那成本太大了。另外在k8s下面又有Secret、ConfigMap等多种方式管理配置,如何把多种配置存储和读取,有机结合、同一份代码统一管理使用,是我们今天的主题。

​ 下面我用一个Api网关Ocelot作为示例(demo),讲讲我处理的方式,希望能给大家带来一定启发。

一、先把配置文件改成Yaml格式

注:

其实不改为yml也可以的!!

主要考虑到后面在docker、k8s等里面,更好管理,比如yaml的注释和json的注释语法不一致等等问题;

比如我原来的appsettings.json长这样:

{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*",
"AddAdministration": {
"Path": "/administration",
"IdentityServer": {
"Authority": "http://172.16.3.117:5100",
"ApiName": "ocelot",
"RequireHttpsMetadata": false,
"ApiSecret": "secret"
}
}
}

改成 appsettings.yml

Logging:
LogLevel:
Default: Information
Microsoft: Warning
Microsoft.Hosting.Lifetime: Information
AllowedHosts: '*'
AddAdministration:
Path: /administration
IdentityServer:
Authority: 'http://172.16.3.117:5100'
ApiName: ocelot
RequireHttpsMetadata: false
ApiSecret: secret

是不是看起来简单清晰了很多,其实我现在越来越喜欢用yml了

既然配置源的格式变了,那读取配置的方法也肯定变了,起码config.AddJsonFile(“xx.json”) 要改为 config.AddYamlFile(“xx.yml”)

新增引用的扩展:NetEscapades.Configuration.Yaml

加载配置文件改写为:

 .AddYamlFile("appsettings.yml", optional: false, reloadOnChange: true)
.AddYamlFile($"appsettings.{env.EnvironmentName}.yml", optional: true, reloadOnChange: true)

二、Docker使用

“但在docker下,如果直接把配置打包到镜像,那每次改一下下配置就需要重新打包,那成本太大了”

我前面提出了这个问题,如想不重新打包,Volume(挂载)就好了。

把你的配置文件放到/home/heidemo/config目录后,比如我们什么的示例配置文件: appsettings.yml

docker run --rm=true -v /home/heidemo/config:/config   gebiwangshushu/hei-ocelot-apigateway:1.0

这样就可以随性更新/home/heidemo/config下的配置信息而不需要每次都重新build镜像了,这样是支持热更新的,当然如果你修改的那个配置是需要重启程序才可以加载的,那还是要用docker-compose 重启下对应服务的;

三、docker-compose使用

我们知道 Docker是 官方编排(Orchestration)项目之一,如果我们在Docker环境下挂载配置的话,那在docker-compose下面的配置也是挂载的,我们来看下我们掐头去尾后的 docker-compose.yml:

version: '3.4'

services:
hei.ocelot.apigateway:
... volumes:
- /home/heidemo/config:/app/config ...

没错,docker-compose 额挂载就这么定义,这样可以实现跟Docker一样的挂载效果;

大家可以用以上配置 clone我的demo,然后 docker-compose up 一下,看看效果;

四、k8s使用

前面的docker、docker-compose 的方式还是非常容易理解的,就是挂载;那我们在k8s下面运行的时候,它的容器实例是动态的运行到集群的各台机器上的,那如果我们我们只用文件挂载很明显就不满足要求了,我们来看看怎么实现。

先准备一个configMap,hei-ocelot-config.yml

apiVersion: v1
kind: ConfigMap
metadata:
name: hei-ocelot-apigateway
namespace: dotnetcore
data:
appsettings.yml: |
Logging:
LogLevel:
Default: Information
Microsoft: Warning
Microsoft.Hosting.Lifetime: Information
AllowedHosts: '*'
AddAdministration:
Path: /administration
IdentityServer:
Authority: 'http://172.16.1.30:31100' #这里的授权中心可以配置你自己的
ApiName: ocelot
RequireHttpsMetadata: false
ApiSecret: secret

完整请看这里

大家可以看到,我们的data节点是跟我们程序里面的appsettings.json一样一样的,这也是我们比较喜欢不再用json的原因。

创建configMap:

kubectl apply -f hei-ocelot-config.yml

查看configMap:

kubectl describe configmaps hei-ocelot-apigateway -n dotnetcore

可能是Asp.net Core On host、 docker、kubernetes(K8s) 配置读取的最佳实践

使用configMap:

这里是使用示例,在我的demo根目录下面完整配置deploy.yml 是可以直接部署的。

apiVersion: apps/v1
kind: Deployment
metadata:
name: hei-ocelot-apigateway
namespace: dotnetcore
spec:
replicas: 1
selector:
matchLabels:
app: hei-ocelot-apigateway
template:
metadata:
labels:
app: hei-ocelot-apigateway
spec:
containers:
- name: hei-ocelot-apigateway
image: gebiwangshushu/hei-ocelot-apigateway:1.1
ports:
- containerPort: 80
volumeMounts:
- name: hei-ocelot-apigateway
mountPath: "/app/config"
readOnly: true
volumes:
- name: hei-ocelot-apigateway
configMap:
name: hei-ocelot-apigateway

可以看到我们在k8s下面也是用volumes的方式使用我们的configMap的,其中挂载目录volumeMounts:mountPath是"/app/config",我们进入运行中pod看下配置:

kubectl exec -it hei-ocelot-apigateway-795495f7c8-vpmhb sh -n dotnetcore

cd /app/config

我们可以看到我们的pod里面的/app/config ,确确实实有我们要的配置;

可能是Asp.net Core On host、 docker、kubernetes(K8s) 配置读取的最佳实践

这里因为我们是volumes 的方式的,大家可以试着改下上面的configMap-- hei-ocelot-config.yml 再重新apply 一下,会看到这里的配置是几乎是即时更新的(有一点点延迟);

PS:有一个问题有些在startup使用的配置,即时更新了也需要重启下应用,这个我暂时还没想到什么办法好办法,各位老哥有什么思路的可以直接甩我一脸~

总结

其实写完我觉得也有点怪怪,说新手引导吧,不够保姆式、说经验分享,不够精简,下次我定好好想,认真写好点;

然后我的主题,其实思考过同样问题的读者,全文就一句:volumes挂载配置做到各种环境下的配置统一;

最后,我提出了一个问题:程序启动使用的配置,如何在配置文件更新的情况后重启程序应用新配置(或者叫热加载配置?当然这里不是指配置文件的reloadOnChange=true);

github:https://github.com/gebiWangshushu/Hei.Ocelot.ApiGateway

上一篇:Flexbox指南


下一篇:paip.sqlite 管理最好的工具 SQLite Expert 最佳实践总结