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

写在前面
为了不违反广告法,我竭尽全力,不过“最佳实践”确是标题党无疑,如果硬要说的话 只能是个人最佳实践。
问题引出
可能很多新手都会遇到同样的问题:我要我的Asp.net Core 应用传统方式直接部署(host),docker部署(docker-compose),kubernetes(以下称k8s)下部署,都用统一的方式读取配置,怎么实现呢?。
大家知道,我们默认平时配置文件以appsettings.json 、appsettings.{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

使用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 ,确确实实有我们要的配置;

这里因为我们是volumes 的方式的,大家可以试着改下上面的configMap-- hei-ocelot-config.yml 再重新apply 一下,会看到这里的配置是几乎是即时更新的(有一点点延迟);
PS:有一个问题有些在startup使用的配置,即时更新了也需要重启下应用,这个我暂时还没想到什么办法好办法,各位老哥有什么思路的可以直接甩我一脸~
总结
其实写完我觉得也有点怪怪,说新手引导吧,不够保姆式、说经验分享,不够精简,下次我定好好想,认真写好点;
然后我的主题,其实思考过同样问题的读者,全文就一句:volumes挂载配置做到各种环境下的配置统一;
最后,我提出了一个问题:程序启动使用的配置,如何在配置文件更新的情况后重启程序应用新配置(或者叫热加载配置?当然这里不是指配置文件的reloadOnChange=true);
github:https://github.com/gebiWangshushu/Hei.Ocelot.ApiGateway
可能是Asp.net Core On host、 docker、kubernetes(K8s) 配置读取的最佳实践的更多相关文章
- Docker+Kubernetes(k8s)微服务容器化实践
第1章 初识微服务微服务的入门,我们从传统的单体架构入手,看看在什么样的环境和需求下一步步走到微服务的,然后再具体了解一下什么才是微服务,让大家对微服务的概念有深入的理解.然后我们一起画一个微服务的架 ...
- 从头认识一下docker-附带asp.net core程序的docker化部署
从头认识一下docker-附带asp.net core程序的docker化部署 简介 在计算机技术日新月异的今天, Docker 在国内发展的如火如荼,特别是在一线互联网公司, Docker 的使用是 ...
- 理解ASP.NET Core - [04] Host
注:本文隶属于<理解ASP.NET Core>系列文章,请查看置顶博客或点击此处查看全文目录 本文会涉及部分 Host 相关的源码,并会附上 github 源码地址,不过为了降低篇幅,我会 ...
- 如何将 asp.net core 应用进行 docker 容器部署
asp.net core 部署在 docker 容器中比较简单,但常因asp.net core程序发布的问题造成容器无法正常启动.现在把详细的操作的步骤记录如下: 一.asp.net core web ...
- [ASP.NET Core开发实战]基础篇06 配置
配置,是应用程序很重要的组成部分,常常用于提供信息,像第三方应用登录钥匙.上传格式与大小限制等等. ASP.NET Core提供一系列配置提供程序读取配置文件或配置项信息. ASP.NET Core项 ...
- ASP.NET Core 2.2 基础知识(六) 配置(内含MySql+EF)
先上一段代码,了解一下 .NET Core 配置数据的结构. 新建一个 控制台项目,添加一个文件 json.json ,文件内容如下: { "country": "cn& ...
- asp.net core 3.0 MVC JSON 全局配置
asp.net core 3.0 MVC JSON 全局配置 System.Text.Json(default) startup配置代码如下: using System.Text.Encodings. ...
- [ASP.NET Core 3框架揭秘] Options[1]: 配置选项的正确使用方式[上篇]
依赖注入不仅是支撑整个ASP.NET Core框架的基石,也是开发ASP.NET Core应用采用的基本编程模式,所以依赖注入十分重要.依赖注入使我们可以将依赖的功能定义成服务,最终以一种松耦合的形式 ...
- [ASP.NET Core 3框架揭秘] Options[2]: 配置选项的正确使用方式[下篇]
四.直接初始化Options对象 前面演示的几个实例具有一个共同的特征,即都采用配置系统来提供绑定Options对象的原始数据,实际上,Options框架具有一个完全独立的模型,可以称为Options ...
随机推荐
- 记一次线上服务CPU 100%的处理过程
告警 正在开会,突然钉钉告警声响个不停,同时市场人员反馈客户在投诉系统登不进了,报504错误.查看钉钉上的告警信息,几台业务服务器节点全部报CPU超过告警阈值,达100%. 赶紧从会上下来,SSH登录 ...
- vue+element-ui JYAdmin后台管理系统模板-集成方案【项目搭建篇2】
项目搭建时间:2020-06-29 本章节:讲述基于vue/cli, 项目的基础搭建. 本主题讲述了: 1.跨域配置 2.axios请求封装 3.eslint配置 4.环境dev,test,pro(开 ...
- Django的Cookie Session和自定义分页
cookie Cookie的由来 大家都知道HTTP协议是无状态的. 无状态的意思是每次请求都是独立的,它的执行情况和结果与前面的请求和之后的请求都无直接关系,它不会受前面的请求响应情况直接影响,也不 ...
- 机器学习实战基础(九):sklearn中的数据预处理和特征工程(二) 数据预处理 Preprocessing & Impute 之 数据无量纲化
1 数据无量纲化 在机器学习算法实践中,我们往往有着将不同规格的数据转换到同一规格,或不同分布的数据转换到某个特定分布的需求,这种需求统称为将数据“无量纲化”.譬如梯度和矩阵为核心的算法中,譬如逻辑回 ...
- redis(八):Redis 哈希(Hash)
Redis 哈希(Hash) Redis hash 是一个 string 类型的 field 和 value 的映射表,hash 特别适合用于存储对象. Redis 中每个 hash 可以存储 232 ...
- python利用selenium(webdriver chrome)模拟登陆获取cookie
(我是在windows下进行实验的) 准备工作: 1.安装python环境. 2.python安装selenium插件(执行以下命令就行). pip install selenium 3.Wind ...
- JavaScript定时器及回调用法
JavaScript定时器及回调用法 循环定时任务 // 假设现在有这样一个需求:我需要请求一个接口,根据返回结果判断需不需要重复请求,直到达到某一条件为止,停止请求执行某操作 <script ...
- vue : 对 vue-class-component 的个人理解
vue-class-component 是 vue 的官方库,作用是用类的方式编写组件. 这种编写方式可以让.vue文件的js域结构更扁平,并使vue组件可以使用继承.混入等高级特性. 简单的示例: ...
- STL Queue(队列)学习笔记 + 洛谷 P1540 机器翻译
队(Queue) 队简单来说就是一个先进先出的“栈”,但是不同于标准“栈”的先进后出. 基本操作: push(x) 将x压入队列的末端 pop() 弹出队列的第一个元素(队顶元素),注意此函数并不返回 ...
- 题解 洛谷 P4546 【[THUWC2017]在美妙的数学王国中畅游】
首先发现有连边和删边的操作,所以我们肯定要用\(LCT\)来进行维护. 接下来考虑如何进行\(LCT\)上的信息合并. \(f=1\),则函数为\(f(x)=sin(ax+b)\) \(f=2\),则 ...