Spring Config整合Kubernetes管理配置
1前言“
欢迎访问南瓜慢说www.pkslow.com获取更多精彩文章!
Kubernetes有专门的ConfigMap和Secret来管理配置 , 但它也有一些局限性 , 所以还是希望通过SpringCloudConfig来管理 。 在Kubernetes上面的微服务系统会有所不同 , 我们来探索一下如何整合SpringCloudKubernetes来做配置管理 。
整体方案与《使用SpringCloudConfig统一管理配置》差不多 , 只是引入SpringCloudKubernetes来使用Kubernetes的服务发现 , 而不使用Eureka等 。
2服务端引入依赖:
org.springframework.cloudspring-cloud-config-server2.2.0.RELEASEorg.springframework.cloudspring-cloud-starter-kubernetes服务端启动类如下:
packagecom.pkslow.config;importorg.springframework.boot.SpringApplication;importorg.springframework.boot.autoconfigure.SpringBootApplication;importorg.springframework.cloud.client.discovery.EnableDiscoveryClient;importorg.springframework.cloud.config.server.EnableConfigServer;@SpringBootApplication@EnableConfigServer@EnableDiscoveryClientpublicclassConfigServerK8s{publicstaticvoidmain(String[]args){SpringApplication.run(ConfigServerK8s.class,args);}}服务端的application.properties配置如下:
server.port=8888spring.application.name=config-server-k8sspring.cloud.config.server.git.uri=spring.cloud.config.server.git.username=admin@pkslow.comspring.cloud.config.server.git.password=***spring.cloud.config.server.git.default-label=masterspring.cloud.config.server.git.search-paths=demo这里的应用名字为config-server-k8s , 后续部署到k8s也是用这个名字 。
k8s的资源定义文件如下:
apiVersion:apps/v1kind:Deploymentmetadata:name:config-server-k8s-deploymentspec:selector:matchLabels:app:config-server-k8sreplicas:1template:metadata:labels:app:config-server-k8sspec:containers:-name:config-server-k8simage:pkslow/config-server-k8s:1.0-SNAPSHOTports:-containerPort:8888---apiVersion:v1kind:Servicemetadata:labels:app:config-server-k8sname:config-server-k8sspec:ports:-port:8888name:config-server-k8sprotocol:TCPtargetPort:8888selector:app:config-server-k8stype:ClusterIP---apiVersion:extensions/v1beta1kind:Ingressmetadata:name:config-server-k8sannotations:kubernetes.io/ingress.class:nginxspec:rules:-http:paths:-path:/backend:serviceName:config-server-k8sservicePort:8888host:config-server-k8s.localhost保持Service名字统一为config-server-k8s 。
3客户端引入依赖:
org.springframework.bootspring-boot-starter-weborg.springframework.cloudspring-cloud-starter-kubernetesorg.springframework.cloudspring-cloud-starter-configorg.springframework.bootspring-boot-starter-actuatorspring-cloud-starter-kubernetes为服务发现;
spring-cloud-starter-config作为配置客户端;
spring-boot-starter-actuator提供EndPoint来刷新配置 。
启动类为:
packagecom.pkslow.config;importorg.springframework.boot.SpringApplication;importorg.springframework.boot.autoconfigure.SpringBootApplication;importorg.springframework.cloud.client.discovery.EnableDiscoveryClient;@SpringBootApplication@EnableDiscoveryClientpublicclassConfigClientK8s{publicstaticvoidmain(String[]args){SpringApplication.run(ConfigClientK8s.class,args);}}配置文件bootstrap.properties如下:
server.port=8080#服务名spring.application.name=config-client-k8s#读取配置时的profilespring.profiles.active=dev#读取配置时的代码分支spring.cloud.config.label=release#开放刷新接口management.endpoints.web.exposure.include=*management.endpoint.health.show-details=always#通过服务名找到配置服务器spring.cloud.config.discovery.enabled=truespring.cloud.config.discovery.service-id=config-server-k8s展示配置结果的Web服务:
packagecom.pkslow.config;importorg.springframework.beans.factory.annotation.Value;importorg.springframework.cloud.context.config.annotation.RefreshScope;importorg.springframework.web.bind.annotation.GetMapping;importorg.springframework.web.bind.annotation.RestController;importjava.util.HashMap;importjava.util.Map;@RefreshScope@RestControllerpublicclassPkslowController{@Value("${pkslow.age:0}")privateIntegerage;@Value("${pkslow.email:null}")privateStringemail;@Value("${pkslow.webSite:null}")privateStringwebSite;@GetMapping("/pkslow")publicMapgetConfig(){Mapmap=newHashMap<>();map.put("age",age.toString());map.put("email",email);map.put("webSite",webSite);returnmap;}}客户端的k8s文件:
apiVersion:apps/v1kind:Deploymentmetadata:name:config-client-k8s-deploymentspec:selector:matchLabels:app:config-client-k8sreplicas:1template:metadata:labels:app:config-client-k8sspec:containers:-name:config-client-k8simage:pkslow/config-client-k8s:1.0-SNAPSHOTports:-containerPort:8080---apiVersion:v1kind:Servicemetadata:labels:app:config-client-k8sname:config-client-k8sspec:ports:-port:8080name:config-client-k8sprotocol:TCPtargetPort:8080selector:app:config-client-k8stype:ClusterIP---apiVersion:extensions/v1beta1kind:Ingressmetadata:name:config-client-k8sannotations:kubernetes.io/ingress.class:nginxspec:rules:-http:paths:-path:/backend:serviceName:config-client-k8sservicePort:8080host:config-client-k8s.localhost【Spring Config整合Kubernetes管理配置】注意Service名字为config-client-k8s 。
4部署与测试总结一下 , 服务端主要做了两件事:
(1)提供配置服务 , 从Github中读取配置;
(2)把自己注册到Kubernetes中去 , 以让客户端发现并读取配置 。
客户端主要做了件事:
(1)作为配置客户端 , 从服务端读配置;
(2)把自己注册到Kubernetes中去 , 让服务端可以访问;
(3)提供刷新配置的功能给外界调用 。
根据客户端的名字、配置的label和profile , 客户端便会读取release分支的配置文件config-client-k8s-dev.properties的内部 。
所以让服务去读取所有相关的客户端 , 并刷新 。 实现很简单 , 直接新增一个RefreshController就可以了:
packagecom.pkslow.config;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.cloud.client.ServiceInstance;importorg.springframework.cloud.client.discovery.DiscoveryClient;importorg.springframework.http.HttpEntity;importorg.springframework.http.HttpHeaders;importorg.springframework.http.MediaType;importorg.springframework.http.ResponseEntity;importorg.springframework.web.bind.annotation.GetMapping;importorg.springframework.web.bind.annotation.RestController;importorg.springframework.web.client.RestTemplate;importjava.util.HashMap;importjava.util.List;importjava.util.Map;@RestControllerpublicclassRefreshController{@AutowiredprivateDiscoveryClientdiscoveryClient;privateRestTemplaterest=newRestTemplate();@GetMapping("/refresh")publicMaprefresh(){Mapresult=newHashMap<>();Listservices=discoveryClient.getServices();result.put("BasicInfo","Totalservicesink8s:"+services.size());services.stream().filter(s->(!"config-server-k8s".equals(s))&&s.startsWith("config-client")).forEach(service->{Listinstances=discoveryClient.getInstances(service);instances.forEach(instance->{Stringurl="http://"+instance.getHost()+":"+instance.getPort()+"/actuator/refresh";try{HttpHeadersheaders=newHttpHeaders();headers.setContentType(MediaType.APPLICATION_JSON);HttpEntityentity=newHttpEntity<>(null,headers);ResponseEntityresponse=rest.postForEntity(url,entity,String.class);result.put(service+""+url,response.getStatusCode().getReasonPhrase());}catch(Exceptione){result.put(service+""+url,e.getMessage());}});});returnresult;}}注意上面的过滤逻辑 , 因为不是所有Service都可以、都需要refresh , 具体逻辑看业务 。
请求结果如下(把客户端的replicas设置成了3):
{"config-client-k8s":"OK","config-client-k8s":"OK","BasicInfo":"Totalservicesink8s:7","config-client-k8s":"OK
推荐阅读
- 丙肝|乙肝/丙肝之间区别,它可以整合细胞,还有稳定持续存在的模板
- 生物安全|如何提升国家生物安全体系建设?陈薇:整合力量扎根防御领域
- 细胞|英国科学家将人类大脑的干细胞整合到芯片里头
- 夏普|整合8K+5G、AIoT和ICT三大业务 夏普将被纳入日经225指数
- 涛咪电竞|炉石传说:全新成就系统上线,最难成就已诞生,啦啦啦看了都绝望成就系统整合,暗藏变态难度任务?强迫症玩家杀手!卡牌收藏家!生涯系列
- 逍遥单机游戏|《守墓人》整合DLC免安装中文版下载
- 华为|华为汽车业务将与消费者业务整合 由余承东总负责
- 传华为消费者BG正在与智能汽车解决方案BU进行整合
- 沈左权调研督办政协重点提案时强调 整合资源 互融互补 推动全域旅游高质量发展
- 专家:俄中正为提高中欧铁路运输效率整合电子物流平台
