zoukankan      html  css  js  c++  java
  • 可能是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
    

    1596101753461

    使用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

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

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

    总结

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

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

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

    源码

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

    参考

    龙哥Edison Zhouk8s 系列博客:https://www.cnblogs.com/edisonchou/p/aspnet_core_on_k8s_foundation_artcles_index.html

  • 相关阅读:
    Python:如何显示进度条
    Python:常用函数封装
    Javascript:常用函数封装
    Javascript:alert(1)可以这样写以绕过filter
    SQL注入备忘单
    Web渗透:PHP字符编码绕过漏洞总结
    SQLi Lab的视频教程和文字教程
    Python:使用基于事件驱动的SAX解析XML
    Python:渗透测试开源项目【源码值得精读】
    Python:SQLMap源码精读—start函数
  • 原文地址:https://www.cnblogs.com/xiaxiaolu/p/13430776.html
Copyright © 2011-2022 走看看