1. 程式人生 > >可能是Asp.net Core On host、 docker、kubernetes(K8s) 配置讀取的最佳實踐

可能是Asp.net Core On host、 docker、kubernetes(K8s) 配置讀取的最佳實踐

![](https://img2020.cnblogs.com/blog/641760/202008/641760-20200803235106453-1133624102.png) # 寫在前面 為了不違反廣告法,我竭盡全力,不過“最佳實踐”確是標題黨無疑,如果硬要說的話 只能是個人最佳實踐。 # 問題引出 ​ 可能很多新手都會遇到同樣的問題:我要我的Asp.net Core 應用傳統方式直接部署(host),docker部署(docker-compose),kubernetes(以下稱k8s)下部署,都用統一的方式讀取配置,怎麼實現呢?。 ​ 大家知道,我們預設平時配置檔案以`appsettings.json` 、`appsettings.{EnvironmentName}.json` 形式存在,這樣在host方式下面沒有問題,但在docker下,如果直接把配置打包到映象,那每次改一下下配置就需要重新打包,那成本太大了。另外在k8s下面又有Secret、ConfigMap等多種方式管理配置,如何把多種配置儲存和讀取,有機結合、同一份程式碼統一管理使用,是我們今天的主題。 ​ 下面我用一個Api閘道器Ocelot作為示例([demo](https://github.com/gebiWangshushu/Hei.Ocelot.ApiGateway)),講講我處理的方式,希望能給大家帶來一定啟發。 # 一、先把配置檔案改成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` 載入配置檔案改寫為: ```c# .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](https://github.com/gebiWangshushu/Hei.Ocelot.ApiGateway),然後 `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 ``` 完整請看[這裡](https://github.com/gebiWangshushu/Hei.Ocelot.ApiGateway/blob/dev/deploy.yml) 大家可以看到,我們的data節點是跟我們程式裡面的`appsettings.json`一樣一樣的,這也是我們比較喜歡不再用json的原因。 建立configMap: ``` kubectl apply -f hei-ocelot-config.yml ``` 檢視configMap: ``` kubectl describe configmaps hei-ocelot-apigateway -n dotnetcore ``` ![1596101753461](https://img2020.cnblogs.com/blog/641760/202008/641760-20200803000056540-844409082.png) 使用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 ,確確實實有我們要的配置; ![1596383131953](https://img2020.cnblogs.com/blog/641760/202008/641760-20200803000055922-515957027.png) 這裡因為我們是volumes 的方式的,大家可以試著改下上面的configMap-- hei-ocelot-config.yml 再重新apply 一下,會看到這裡的配置是幾乎是即時更新的(有一點點延遲); **PS:**有一個問題有些在startup使用的配置,即時更新了也需要重啟下應用,這個我暫時還沒想到什麼辦法好辦法,各位老哥有什麼思路的可以直接甩我一臉~ # 總結 其實寫完我覺得也有點怪怪,說新手引導吧,不夠保姆式、說經驗分享,不夠精簡,下次我定好好想,認真寫好點; 然後我的主題,其實思考過同樣問題的讀者,全文就一句:volumes掛載配置做到各種環境下的配置統一; 最後,**我丟擲了一個問題**:On K8s的時候, 程式啟動使用的配置,如何在配置檔案更新的情況後重啟程式應用新配置(或者叫熱載入配置?當然這裡不是指配置檔案的reloadOnChange=true); # 原始碼 [https://github.com/gebiWangshushu/Hei.Ocelot.ApiGateway](https://github.com/gebiWangshushu/Hei.Ocelot.ApiGateway) # 參考 龍哥[Edison Zhou](https://www.cnblogs.com/edisonchou/)k8s 系列部落格:[https://www.cnblogs.com/edisonchou/p/aspnet_core_on_k8s_foundation_artcles_index.html](https://www.cnblogs.com/edisonchou/p/aspnet_core_on_k8s_foundation_artcles_index.html)