.NET Core + K8S + Apollo 玩转配置中心

1.引言

Apollo(阿波罗)是携程框架部门研发的分布式配置中心,能够集中化管理应用不同环境、不同集群的配置,配置修改后能够实时推送到应用端,并且具备规范的权限、流程治理等特性,适用于微服务配置管理场景。

如官网所述:Apollo 是携程打造的开源配置中心,GitHub的星星也快点满22K,因此足见它的成熟度和社区活跃度。因此最近在做配置中心选型的时候,经过一番预演,最终敲定Apollo。

Apollo作为微服务体系中必不可少的基础服务,其架构设计和基本使用我们不得不有所了解。

因此本文接下来将主要来介绍如何基于Helm快速部署Apollo集群至K8S,并与.NET Core应用进行集成,同时介绍下如何平滑迁移配置到Apollo。

本文具有详细的部署步骤,建议动手实操。
部署Chart包和Demo已上传至GitHub:K8S.NET.Apollo,可收藏备用。

2. Apollo 架构一览

在部署之前,需要了解Apollo的基础架构,以便在后续部署工作的展开。

关于其的解读,我这里就不再详细展开,但以下几点还是要有所了解,感兴趣的可以直接看官网详细介绍:Apollo配置中心设计。

  1. Config Service提供配置的读取、推送等功能,服务对象是Apollo客户端

  2. Admin Service提供配置的修改、发布等功能,服务对象是Apollo Portal(管理界面)

  3. Config Service和Admin Service都是多实例、无状态部署,需要通过注册中心进行服务注册和发现

  4. 注册中心默认采用的是Eureka,在K8S中由Service充当

  5. Apollo客户端通过注册中心获取Config Service服务列表进行配置读取

  6. Apollo Portal通过注册中心获取Admin Service服务列表进行配置管理

基于上面对Apollo的介绍,其物理架构总结起来就是:

  1. 每一套环境都必须拥有自己独立的Config Service 和 Admin Service 以及独立ConfigDB。

  2. 多套环境可以公用一套Apollo Portal 进行管理,Portal拥有独立PortalDB。

3. 基于Helm部署到K8S

因为Apollo 1.7.0版本增加了基于Kubernetes原生服务发现的部署模式,来替换内置的Eureka,所以在整体部署上有很大简化,同时官方也提供了Helm Charts,让Apollo更加易于开箱即用。下面就以部署一套测试环境为例讲解一下Apollo的部署要点。(部署至本机Docker Desktop Local K8S环境)。

环境要求:Kubernetes 1.10+,Helm 3

3.1 搭建 Apollo Config&Portal DB

从上图的物理架构上来看,首先要部署好Config DB和PortalDB。关于DB的搭建,建议直接使用bitnami/mysqlchart搭建。搭建步骤如下:

> helm repo add bitnami https://charts.bitnami.com/bitnami
> helm repo list
> helm repo update
> helm search repo bitnami/mysql
NAME            CHART VERSION   APP VERSION     DESCRIPTION
bitnami/mysql   6.14.8          8.0.21          Chart to create a Highly available MySQL cluster

执行helm包的安装,需要自定义配置文件,也就是values.yaml。我们可以先行下载 mysql chart包。

之所以选择将chart包下载到本地,是为了确保后续维护能够基于一致的chart包版本。避免因为执行helm repo update导致chart包版本自动升级,而不自知。

> helm pull bitnami/mysql --untar  //下载并解包
mysql├── Chart.yaml├── ci│   └── values-production.yaml├── files│   └── docker-entrypoint-initdb.d│       └── README.md├── README.md├── templates│   ├── initialization-configmap.yaml│   ├── master-configmap.yaml│   ├── master-statefulset.yaml│   ├── master-svc.yaml│   ├── NOTES.txt│   ├── secrets.yaml│   ├── serviceaccount.yaml│   ├── servicemonitor.yaml│   ├── slave-configmap.yaml│   ├── slave-statefulset.yaml│   ├── slave-svc.yaml│   └── _helpers.tpl├── values-production.yaml└── values.yaml

根据官网分布式部署指南中所示,其提供了DB的初始化脚本用来分别创建ApolloConfigDBApolloPortalDB。因此可以直接将以上SQL脚本下载到mysql chart的files/docker-entrypoint-initdb.d目录下,这样在部署mysql实例时就会自动执行脚本创建数据库。

> cd mysql/files/docker-entrypoint-initdb.d
> curl https://raw.githubusercontent.com/ctripcorp/apollo/master/scripts/sql/apolloportaldb.sql > apolloportaldb.sql //下载apolloportaldb.sql
> curl https://raw.githubusercontent.com/ctripcorp/apollo/master/scripts/sql/apolloconfigdb.sql > apolloconfigdb.sql 下载apolloconfigdb.sql
> lsDirectory: C:\Users\Shengjie\k8s\helm\charts\apollo\mysql\files\docker-entrypoint-initdb.dMode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a---           8/12/2020 11:01 PM          21291 apolloconfigdb.sql
-a---           8/12/2020 10:56 PM          16278 apolloportaldb.sql
-a---            8/9/2020  6:26 PM            242 README.md

然后复制values.yaml并命名为dev-mysql-values.yaml。然后修改核心配置:

  1. global.storageClass=hostpath
    可通过kubectl get sc查看集群支持的storageClass,我这边选择默认的hostpath。其创建的pv的默认回收策略为delete,也就意味着卸载mysql,数据直接删除,这点需要注意!!!如果需要保留测试数据,请更新storageClass。

  2. root.password=root
    修改默认root用户的密码

修改完毕后,执行以下脚本进行安装:

> kubectl create ns db #创建单独db命名空间
> helm install mysql-apollo . -f dev-mysql-values.yaml -n db
NAME: mysql-apollo
LAST DEPLOYED: Sun Aug 16 11:01:18 2020
NAMESPACE: db
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
Please be patient while the chart is being deployedTip:Watch the deployment status using the command: kubectl get pods -w --namespace dbServices:echo Master: mysql-apollo.db.svc.cluster.local:3306echo Slave:  mysql-apollo-slave.db.svc.cluster.local:3306Administrator credentials:echo Username: rootecho Password : $(kubectl get secret --namespace db mysql-apollo -o jsonpath="{.data.mysql-root-password}" | base64 --decode)To connect to your database:1. Run a pod that you can use as a client:kubectl run mysql-apollo-client --rm --tty -i --restart='Never' --image  docker.io/bitnami/mysql:8.0.21-debian-10-r17 --namespace db --command -- bash2. To connect to master service (read/write):mysql -h mysql-apollo.db.svc.cluster.local -uroot -p my_database3. To connect to slave service (read-only):mysql -h mysql-apollo-slave.db.svc.cluster.local -uroot -p my_databaseTo upgrade this helm chart:1. Obtain the password as described on the 'Administrator credentials' p and set the 'root.password' parameter as shown below:ROOT_PASSWORD=$(kubectl get secret --namespace db mysql-apollo -o jsonpath="{.data.mysql-root-password}" | base64 --decode)helm upgrade mysql-apollo bitnami/mysql --set root.password=$ROOT_PASSWORD

按照上面提示,验证数据库成功创建:

> kubectl run mysql-apollo-client --rm --tty -i --restart='Never' --image  docker.io/bitnami/mysql:8.0.21-debian-10-r17
--namespace db --command -- bash  # 创建mysql-client pod
I have no name!@mysql-apollo-client:/$ mysql -h mysql-apollo.db.svc.cluster.local -uroot -proot    # 连接至master 节点
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 61
Server version: 8.0.21 Source distributionCopyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.mysql> show databases; # 查看databases;
+--------------------+
| Database           |
+--------------------+
| ApolloConfigDB     |
| ApolloPortalDB     |
| information_schema |
| my_database        |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
7 rows in set (0.00 sec)mysql> use ApolloConfigDB; # 切换至ApolloConfigDB;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -ADatabase changed
mysql> show tables;  # 查看数据表;
+--------------------------+
| Tables_in_ApolloConfigDB |
+--------------------------+
| AccessKey                |
| App                      |
| AppNamespace             |
| Audit                    |
| Cluster                  |
| Commit                   |
| GrayReleaseRule          |
| Instance                 |
| InstanceConfig           |
| Item                     |
| Namespace                |
| NamespaceLock            |
| Release                  |
| ReleaseHistory           |
| ReleaseMessage           |
| ServerConfig             |
+--------------------------+
16 rows in set (0.01 sec)

至此,确认Apollo ConfigDB和PortalDB搭建成功。

3.2 搭建 Apollo Config Service

搭建Apollo Service 需要添加携程官方chart仓库:

> helm repo add apollo http://ctripcorp.github.io/apollo/charts
> helm search repo apollo
NAME                    CHART VERSION   APP VERSION     DESCRIPTION
apollo/apollo-portal    0.1.0           1.7.0           A Helm chart for Apollo Portal
apollo/apollo-service   0.1.0           1.7.0           A Helm chart for Apollo Config Service and Apol...

从上可知,主要包含两个chart,分别用来部署service和portal。下来研究下apollo/apollo-service 这个chart。老规矩,先把chart包下载下来:

> helm pull apollo/apollo-service --untar
apollo-service├── Chart.yaml├── templates│   ├── deployment-adminservice.yaml│   ├── deployment-configservice.yaml│   ├── NOTES.txt│   ├── service-adminservice.yaml│   ├── service-configdb.yaml│   ├── service-configservice.yaml│   └── _helpers.tpl└── values.yaml

从上面的树形图来看,主要就是用来部署config service 和 admin service。紧接着,复制一个values.yaml,命名为dev-apollo-svc-values.yaml。主要修改以下配置:

  1. configdb.host=mysql-apollo.db
    指定configdb的主机,因为是在集群内部,直接使用服务名即可

  2. configdb.password=root
    指定configdb的秘密

修改后的配置如下:

configdb:name: apollo-configdb# apolloconfigdb hosthost: "mysql-apollo.db"port: 3306dbName: ApolloConfigDB# apolloconfigdb user nameuserName: "root"# apolloconfigdb passwordpassword: "root"
....

其他配置可以暂定不动,紧接着执行以下命令进行安装:

> kubectl create ns apollo # 创建apollo 命名空间
> helm install --dry-run --debug apollo-dev-svc . -f dev-apollo-svc-values.yaml -n apollo # 测试安装,验证模板生成的资源文件是否有误
> helm install apollo-dev-svc . -f dev-apollo-svc-values.yaml -n apollo
NAME: apollo-dev-svc
LAST DEPLOYED: Sun Aug 16 11:17:38 2020
NAMESPACE: apollo
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
Get meta service url for current release by running these commands:echo http://apollo-dev-svc-apollo-configservice.apollo:8080      For local test use:export POD_NAME=$(kubectl get pods --namespace apollo -l "app=apollo-dev-svc-apollo-configservice" -o jsonpath="{.items[0].metadata.name}")echo http://127.0.0.1:8080kubectl --namespace apollo port-forward $POD_NAME 8080:8080

这里要记住上面的meta service url:http://apollo-dev-svc-apollo-configservice.apollo:8080

那如何确认正确部署了呢:

> kubectl get all -n apollo # 查看apollo命名空间下部署的资源
NAME                                                       READY   STATUS    RESTARTS   AGE
pod/apollo-dev-svc-apollo-adminservice-7d4468ff46-gw6h4    1/1     Running   0          3m26s
pod/apollo-dev-svc-apollo-configservice-58d6c44cd4-n4qk9   1/1     Running   0          3m26sNAME                                          TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
service/apollo-dev-svc-apollo-adminservice    ClusterIP   10.99.251.14     <none>        8090/TCP   3m26s
service/apollo-dev-svc-apollo-configservice   ClusterIP   10.108.121.201   <none>        8080/TCP   3m26sNAME                                                  READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/apollo-dev-svc-apollo-adminservice    1/1     1            1           3m26s
deployment.apps/apollo-dev-svc-apollo-configservice   1/1     1            1           3m26sNAME                                                             DESIRED   CURRENT   READY   AGE
replicaset.apps/apollo-dev-svc-apollo-adminservice-7d4468ff46    1         1         1       3m26s
replicaset.apps/apollo-dev-svc-apollo-configservice-58d6c44cd4   1         1         1       3m26s

从上可知暴露了两个服务configservice和adminservice,来尝试将configservice进行端口转发到本地端口来看一下。

> kubectl port-forward service/apollo-dev-svc-apollo-configservice 8080:8080 -n apollo # 转发configservice到本地服务
Forwarding from 127.0.0.1:8080 -> 8080
Forwarding from [::1]:8080 -> 8080

使用浏览器访问 localhost:8080,可以看到输出[{"appName":"apollo-configservice","instanceId":"apollo-configservice:http://apollo.shisheng.wang/config-svc","homepageUrl":"http://apollo.shisheng.wang/config-svc"},{"appName":"apollo-adminservice","instanceId":"apollo-adminservice:http://apollo.shisheng.wang/admin-svc","homepageUrl":"http://apollo.shisheng.wang/admin-svc"}]

至此说明,Apollo Service 搭建成功。

3.3 搭建 Apollo Portal Service

同样,先来下载portal chart包,并研究下目录结构:

> helm pull apollo/apollo-portal --untar
apollo-portal├── Chart.yaml├── templates│   ├── deployment-portal.yaml│   ├── ingress-portal.yaml│   ├── NOTES.txt│   ├── service-portal.yaml│   ├── service-portaldb.yaml│   └── _helpers.tpl└── values.yaml

从上可知,portal 相对来说,主要是构建portal服务,并可以通过ingress暴露服务。复制一个values.yaml,命名为dev-apollo-portal-values.yaml。主要修改以下配置:

  1. ingress.enabled=true
    启用ingress,并通过注解设置ingress controller,因为portal是个有状态服务,所以要关注Sessiion状态维持。以下主要是针对nginx-ingress-controller的配置,如果使用的其他的ingress-controller请注意更改。(nginx-ingress-controller的安装,这里就不具体展开了,可以简单执行helm install nginx bitnaim/nginx-ingress-controller 安装就好了。)

ingress:enabled: trueannotations:kubernetes.io/ingress.class: nginxnginx.ingress.kubernetes.io/rewrite-target: /nginx.ingress.kubernetes.io/affinity: "cookie"nginx.ingress.kubernetes.io/session-cookie-name: "route"hosts:- host: "apollo.demo.com"paths: ["/"]tls: []
  1. 指定配置源 ,主要是envs和metaServers两个配置项:
    config.envs=dev
    config.metaServers.dev=http://apollo-dev-svc-apollo-configservice.apollo:8080(上面部署apollo service输出的apollo service url)如果同时启用开发、测试和生产环境。可以配置为:envs: "dev,uat,prd",metaServers 分别指定对应环境的配置即可。
    以下是只启用开发环境的配置:

config:# spring profiles to activateprofiles: "github,auth"# specify the env names, e.g. dev,proenvs: "dev"# specify the meta servers, e.g.# dev: http://apollo-configservice-dev:8080# pro: http://apollo-configservice-pro:8080metaServers:dev: http://apollo-svc-dev-apollo-configservice.apollo:8080# dev: http://apollo.shisheng.wang# specify the context path, e.g. /apollocontextPath: ""# extra config files for apollo-portal, e.g. application-ldap.ymlfiles: {}
  1. portaldb.host=mysql-apollo.db & portaldb.password=root
    指定portaldb的主机和密码

portaldb:name: apollo-portaldb# apolloportaldb hosthost: mysql-apollo.dbport: 3306dbName: ApolloPortalDB# apolloportaldb user nameuserName: root# apolloportaldb passwordpassword: root

其他配置可以暂定不动,紧接着执行以下命令进行安装:

> Helm install --dry-run --debug apollo-dev-portal . -f dev-apollo-portal-values.yaml -n apollo # 测试安装,验证模板生成的资源文件是否有误
> Helm install apollo-dev-portal . -f dev-apollo-portal-values.yaml -n apollo
PS C:\Users\Shengjie\k8s\helm\charts\apollo\apollo-portal> Helm install apollo-dev-portal . -f dev-apollo-portal-values.yaml -n apollo
NAME: apollo-dev-portal
LAST DEPLOYED: Sun Aug 16 11:53:18 2020
NAMESPACE: apollo
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
Get apollo portal url by running these commands:http://apollo.demo.com/

到这一步,如果需要本地可以访问,还需要修改本地hosts,添加127.0.0.1 apollo.demo.com。然后打开你的Browser输入http://apollo.demo.com/,就可以访问了。默认用户密码是:[apollo/admin]。

3.4. 暴露 config service

以上部署的是开发环境,但要想开发环境要访问到config service,我们还需要些小动作。这个时候就需要修改apollo service的chart模板,在template目录增加ingress-configservice.yaml文件,内容如下:

# ingress-configservice.yaml
{{- if .Values.configService.ingress.enabled -}}{{- $fullName := include "apollo.configService.fullName" . -}}{{- $svcPort := .Values.configService.service.port -}}{{- if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}}
apiVersion: networking.k8s.io/v1beta1
{{- else -}}
apiVersion: extensions/v1beta1
{{- end }}
kind: Ingress
metadata:name: {{ $fullName }}labels:{{- include "apollo.service.labels" . | nindent 4 }}{{- with .Values.configService.ingress.annotations }}annotations:{{- toYaml . | nindent 4 }}{{- end }}
spec:
{{- if .Values.configService.ingress.tls }}tls:{{- range .Values.configService.ingress.tls }}- hosts:{{- range .hosts }}- {{ . | quote }}{{- end }}secretName: {{ .secretName }}{{- end }}{{- end }}rules:{{- range .Values.configService.ingress.hosts }}- host: {{ .host | quote }}http:paths:{{- range .paths }}- path: {{ . }}backend:serviceName: {{ $fullName }}servicePort: {{ $svcPort }}{{- end }}{{- end }}{{- end }}

然后修改values.yamlconfigService节点下增加ingress配置选项:

configService:name: apollo-configservicefullNameOverride: ""replicaCount: 2containerPort: 8080image:repository: apolloconfig/apollo-configservicepullPolicy: IfNotPresentimagePullSecrets: []service:fullNameOverride: ""port: 8080targetPort: 8080type: ClusterIP# 以下为新增ingress配置项ingress:enabled: falseannotations: {}hosts:- host: ""paths: []tls: []

然后再修改上面我们创建的dev-apollo-svc-values.yaml下的configService节点,添加对应ingressconfig.configServiceUrlOverride配置:

configService:name: apollo-configservicefullNameOverride: ""replicaCount: 1containerPort: 8080image:repository: apolloconfig/apollo-configservicepullPolicy: IfNotPresentimagePullSecrets: []service:fullNameOverride: ""port: 8080targetPort: 8080type: ClusterIPingress:enabled: trueannotations:kubernetes.io/ingress.class: nginxnginx.ingress.kubernetes.io/rewrite-target: /$2hosts:- host: "apollo.demo.com"paths: ["/config-svc(/|$)(.*)"]tls: []liveness:initialDelaySeconds: 100periodSeconds: 10readiness:initialDelaySeconds: 30periodSeconds: 5config:# spring profiles to activateprofiles: "github,kubernetes"# override apollo.config-service.url: config service url to be accessed by apollo-clientconfigServiceUrlOverride: "http://apollo.demo.com/config-svc"# override apollo.admin-service.url: admin service url to be accessed by apollo-portaladminServiceUrlOverride: ""

修改完毕,执行以下命令升级apollo service:

> helm upgrade apollo-service-dev . -f dev-apollo-svc-values.yaml -n apollo
NAME: apollo-service-dev
LAST DEPLOYED: Tue Aug 18 14:20:41 2020
NAMESPACE: apollo
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
Get meta service url for current release by running these commands:echo http://apollo-service-dev-apollo-configservice.apollo:8080For local test use:export POD_NAME=$(kubectl get pods --namespace apollo -l "app=apollo-service-dev-apollo-configservice" -o jsonpath="{.items[0].metadata.name}")echo http://127.0.0.1:8080kubectl --namespace apollo port-forward $POD_NAME 8080:8080
> curl http://apollo.demo.com/config-svc
[{"appName":"apollo-configservice","instanceId":"apollo-configservice:http://apollo.demo.com/config-svc","homepageUrl":"http://apollo.demo.com/config-svc"},{"appName":"apollo-adminservice","instanceId":"apollo-adminservice:http://apollo-service-dev-apollo-adminservice.apollo:8090","homepageUrl":"http://apollo-service-dev-apollo-adminservice.apollo:8090"}]

从上面的输出可以看到,现在已经可以通过http://apollo.demo.com/config-svc读取metaServer配置了,后面本地开发环境就可以通过这个链接来读取Apollo的配置。

4. .NET Core 集成Apollo

这一部分我就快速带过了,执行以下命令创建项目,并引入apolloswagger相关包:

> dotnet new webapi -n K8S.NET.Apollo
> cd K8S.NET.Apollo
> dotnet add package Com.Ctrip.Framework.Apollo.Configuration
> dotnet add package Swashbuckle.AspNetCore

修改appsettings.json增加apollo配置:

{"AllowedHosts": "*","apollo": {"AppId": "test","MetaServer": "http://apollo.demo.com/config-svc","Env": "Dev"}
}

修改Program.cs,添加Apollo配置源如下:

public static IHostBuilder CreateHostBuilder(string[] args) =>Host.CreateDefaultBuilder(args).ConfigureAppConfiguration(configBuilder =>{configBuilder.AddApollo(configBuilder.Build().GetSection("apollo")).AddDefault().AddNamespace("TEST1.connectionstrings", "ConnectionStrings").AddNamespace("logging", ConfigFileFormat.Json);}).ConfigureWebHostDefaults(webBuilder =>{webBuilder.UseStartup<Startup>();});

修改Startup.cs,添加Swagger集成,方便测试:

public void ConfigureServices(IServiceCollection services)
{services.AddControllers();services.AddSwaggerGen(c =>{c.SwaggerDoc("v1", new OpenApiInfo { Title = this.GetType().Namespace, Version = "v1" });});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{if (env.IsDevelopment()){app.UseDeveloperExceptionPage();}app.UseSwagger();app.UseSwaggerUI(c =>{c.SwaggerEndpoint("/swagger/v1/swagger.json", $"{this.GetType().Namespace} V1");c.RoutePrefix = string.Empty;});//...
}

添加ApolloController,增加以下测试代码:

namespace K8S.NET.Apollo.Controllers
{[ApiController][Route("[controller]/[action]")]public class ApolloController : Controller{private readonly IConfiguration _configuration;public ApolloController(IConfiguration configuration){_configuration = configuration;}[HttpGet("key")]public IActionResult GetLogLevelSection(){var key = "Logging:LogLevel";var val = _configuration.GetSection(key).Get<LoggingOptions>();return Ok($"{key}:{JsonSerializer.Serialize(val)}");}[HttpGet("key")]public IActionResult GetString(string key){var val = _configuration.GetValue<string>(key);return Ok($"{key}:{val}");}[HttpGet("key")]public IActionResult GetConnectionStrings(string key){var val = _configuration.GetConnectionString(key);return Ok($"{key}:{val}");}}public class LoggingOptions : Dictionary<string, string>{}
}

登录Apollo Portal,添加test项目,并增加以下配置,并发布。

本地调试,就能够获取云端配置,另外Apollo同时会同步一份配置到本地目录:c:/opt/data/test/config-cache。这样就可以保证即使无法建立云端连接,也可以正常加载本地配置。
执行以下命令,进行配置读取和验证:

> curl https://localhost:5001/Apollo/GetLogLevelSection
Logging:LogLevel:{"Default":"Information","Microsoft":"Warning","Microsoft.Hosting.Lifetime":"Information"}
> curl https://localhost:5001/Apollo/GetString/key?key=name
name:Shengjie
> curl https://localhost:5001/Apollo/GetConnectionStrings/key?key=Default
Default:Server=mu3ne-mysql;port=3306;database=mu3ne0001;user id=root;password=abc123;AllowLoadLocalInfile=true

5.配置迁移指北

相信采用Apollo的绝大多数都不是一开始就用的,都是再配置逐渐复杂之后,才进行迁移的。我也不例外,之前是用K8S的ConfigMap来做配置管理。下面就来讲下迁移指南,我将其分为两种模式:

  1. 偷懒模式
    如果想改动最小,就直接将项目配置继续以Json格式维护到Apollo的私有命名空间下。

public static IHostBuilder CreateHostBuilder(string[] args) =>Host.CreateDefaultBuilder(args).ConfigureAppConfiguration((context, builder) =>{builder.AddApollo(builder.Build().GetSection("apollo")).AddDefault().AddNamespace("appsettings",ConfigFileFormat.Json);}).ConfigureWebHostDefaults(webBuilder =>{webBuilder.UseStartup<Startup>();});
  1. 强迫症模式
    也有人考虑,既然上Apollo,就要用到它的特性,因此对现有配置就要分门别类。哪些是公用的,哪些是私有的。对于公用的就要定义到公共的命名空间下。公共命名空间的配置格式只有Properties格式,因此需要将Json转为Properties。比如针对Logging配置可以借助网站 json2properties converter进行在线转换。如下所示:

如果真这样做,你就错了,你会发现最终的日志配置不生效。这是因为properties格式是以.进行分割,而.NET Core是用:来识别节点配置, 因此properties配置按:分割就好了,如下所示,以下两种配置等效:

6. 最后

以上,相信若能够动手实操,你将收获匪浅。

本文Demo和Chart包的完整配置已上传至Github:K8S.NET.Apollo,请按需取用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/308157.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

计算机格式化后数据恢复的基础,电脑硬盘格式化后还能恢复吗

电脑硬盘是电脑运行的基础固件&#xff0c;我们使用电脑需要依赖它储存文件、运行软件等。那么在使用电脑的过程中你有没有遇到这样的问题&#xff1a;当打开一个电脑磁盘分区时&#xff0c;该分区无法使用并提示格式化&#xff0c;这时候一般的小伙伴是不是都手欠格式化硬盘了…

路线错误的教训对如今的模范企业也有借鉴意义

此前&#xff0c;倪光南院士对L公司如今的困境做了深刻的剖析&#xff0c;那就是“路线不对”、“知识产权0股份”。“路线不对”指的是L公司放弃了技术路线&#xff0c;选择了“造不如买”&#xff0c;玩组装和贸易。几十年如一日依附于Wintel体系&#xff0c;“跟在洋人身后吃…

7-3 最小生成树-kruskal (10 分)(思路+详解+并查集详解+段错误超时解决)宝 Come

一&#xff1a;前言 本题需要用到并查集的知识&#xff0c;建议先学完并查集后再看看本题 二&#xff1a;题目 题目给出一个无向连通图&#xff0c;要求求出其最小生成树的权值。 温馨提示&#xff1a;本题请使用kruskal最小生成树算法。 输入格式: 第一行包含两个整数 N(1&…

计算机等级delphi取消,计算机二级DELPHI控件:DELPHI过滤记录的实现方法

所谓过滤就是从表中选取满足特定条件的部分记录。过滤记录首先要通过Filter。属性设置过滤条件&#xff0c;然后将Filtered属性设置为True&#xff0c;即可从数据集组件连接的表中过滤出满足条件的记录。1&#xff0e;Filter属性Filter属性用于设置过滤条件&#xff0c;它是一个…

Azure认知服务之使用墨迹识别功能识别手写汉字

前面我们使用Azure Face实现了人脸识别、使用Azure表格识别器提取了表格里的数据。这次我们试试使用Azure墨迹识别API来对笔迹进行识别。墨迹识别墨迹识别器认知服务提供基于云的 REST API 用于分析和识别数字墨迹内容。与使用光学字符识别 (OCR) 的服务不同&#xff0c;该 API…

7-9 删数问题 (10 分)(思路加详解)

一&#xff1a;题目 有一个长度为n&#xff08;n < 240&#xff09;的正整数&#xff0c;从中取出k&#xff08;k < n&#xff09;个数&#xff0c;使剩余的数保持原来的次序不变&#xff0c;求这个正整数经过删数之后最小是多少。 输入格式: n和k 输出格式: 一个数字…

【LeetCode】1. 盛最多水的容器:C#三种解法

题目&#xff1a;https://leetcode-cn.com/problems/container-with-most-water/盛最多水的容器难度:中等给你 n 个非负整数 a1&#xff0c;a2&#xff0c;...&#xff0c;an&#xff0c;每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线&#xff0c;垂直线 i 的两个…

7-1 银行家算法--安全性检查 (20 分)(思路+详解+知识分析)宝 你今天 AC了吗

一&#xff1a;前言 停更一周了&#xff0c;在这一周里&#xff0c;我每时每刻都在 想这我这 29个粉丝&#xff0c;庆幸教师资格证终于结束了&#xff0c;贴心杰又可以天天更新博客了 哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈&#xff0c;I am come back; 二&#xff1a;题目&a…

.Net Core中的诊断日志DiagnosticSource讲解

前言近期由于需要进行分布式链路跟踪系统的技术选型&#xff0c;所以一直在研究链路跟踪相关的框架。作为能在.Net Core中使用的APM&#xff0c;SkyWalking自然成为了首选。SkyAPM-dotnet是SkyWalking在.Net Core端的探针实现&#xff0c;其主要的收集日志的手段就是基于Diagno…

7-2 银行家算法--申请资源 (30 分)

7-2 银行家算法–申请资源 (30 分)&#xff08;思路详解&#xff09;Come 乖宝宝们 一&#xff1a;前言 这道题需要用到前面的一道题 安全性检查 算法知识&#xff0c;所以强烈建议先看前面那道题 7-1 银行家算法–安全性检查 (20 分) 二&#xff1a;题目 输入N个进程(N<…

年薪100万和10万程序员的差距

点击蓝字关注&#xff0c;回复“职场进阶”获取职场进阶精品资料一份我们看武侠大片&#xff0c;经常有那种本来可以练就绝世武功的大虾。阴差阳错练的走火入魔。一开始还可以硬撑&#xff0c;还能打败一些虾兵蟹将。遇见真正的高手&#xff0c;这些大虾们立马就败下阵来。其实…

7-3 银行家算法--综合 (50 分)(思路+详解+分析输入)宝宝们 加油

一&#xff1a;前言 这道题涉及到 银行家算法的申请资源 算法 还有 安全性检查的耍算法 那么强烈建议 把前面的学完再看本题 7-1 银行家算法–安全性检查 (20 分) 7-2 银行家算法–申请资源 (30 分) 二&#xff1a;题目 输入N个进程(N<100)&#xff0c;以及M类资源&#…

如何在龙芯3B4000上部署基于.Net Core 开发的物联网平台IoTSharp

今天很开心的拿到了龙芯的测试服务器账号&#xff0c; 先上图show一下&#xff0c; 双核&#xff0c; 8G内存&#xff0c; 50G硬盘。架构 mips64el 登录后&#xff0c; 显示为 uos 及其网址信息:接下来&#xff0c; 二话不说&#xff0c; 我们开始下载龙芯版的.Net Core &#…

46. 全排列015(回溯法求解)

一:题目 示例 1&#xff1a; 输入&#xff1a;nums [1,2,3] 输出&#xff1a;[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]] 示例 2&#xff1a;输入&#xff1a;nums [0,1] 输出&#xff1a;[[0,1],[1,0]] 示例 3&#xff1a;输入&#xff1a;nums [1] 输出&#xf…

git did not exit cleanly(解决办法)

一&#xff1a;问题描述 我们在push的时候&#xff0c;出现如下问题 这个图是我拿别人的&#xff08;因为我的问题解决后 没保存图&#xff09; 二:解决 1.新建一个仓库在gitee上: 2:将新建的仓库克隆到本地 3&#xff1a;将原来的文件剪切到javanew(新建的仓库) 4&#…

[Hei.Captcha] Asp.Net Core 跨平台验证码实现

&#xfeff;&#xfeff;写在前面说起来比较丢脸。我们有个手机的验证码发送逻辑需要使用验证码&#xff0c;这块本来项目里面就有验证码绘制逻辑&#xff0c;.Net Framework的&#xff0c;使用的包是System.Drawing,我把这验证码绘制逻辑复制到.Net Core的新项目引用对比包Sy…

77. 组合016(回溯法)

一:题目 给定两个整数 n 和 k&#xff0c;返回范围 [1, n] 中所有可能的 k 个数的组合。 你可以按 任何顺序 返回答案。 示例 1&#xff1a; 输入&#xff1a;n 4, k 2 输出&#xff1a; [[2,4],[3,4],[2,3],[1,2],[1,3],[1,4], ] 示例 2&#xff1a;输入&#xff1a;n …

.NET5即至,你准备好了吗?

.NET 5.0 Preview7是RC版前倒数第二个预览版&#xff0c;发布至今恰好一个月&#xff0c;算起来&#xff0c;.NET Core开源已经4年了&#xff0c;然而在互联网大型系统开发中很多环节都还是空白的&#xff0c;造轮子诚非一日之功&#xff01;这里为大家推荐一个分布式日志分析解…

216. 组合总和 III017(回溯法求解)

一&#xff1a;题目 二:思路 1.总体来看这是一个解空间为k层的排列树 第一层为1~9 2.递归函数的参数和返回值 1>:返回值&#xff1a;vector<vector > res 每次的求解结果&#xff1a;vector path 2>:参数&#xff1a; backtacking(int k,int n,int index,int sum)…

基于IdentityServer4的OIDC实现单点登录(SSO)原理简析

&#xfeff;&#xfeff;# 写在前面IdentityServer4的学习断断续续&#xff0c;兜兜转转&#xff0c;走了不少弯路&#xff0c;也花了不少时间。可能是因为没有阅读源码&#xff0c;也没有特别系统的学习资料&#xff0c;相关文章很多园子里的大佬都有涉及&#xff0c;有系列文…