使用Kubernetes的configmap为微服务提供配置中心

在做微服务部署到kubernetes环境的时候,如果之前是docker运行环境的话,一般会使用consul, euraka, nacos等作为服务发现注册配置中心,从而作为微服务环境的重要部分来配置和调度服务间的访问。

然而在kubernetes的集群环境里边,实际上也只提供了一些组件也作为配置中心和服务发现的机制。比如我们下边介绍的configmap, secret以及env等为平台部署的服务提供了配置中心的功能。

在微服务的环境里边,一般服务读取配置信息的时候都是在服务加载启动的时候。一旦服务运行起来,再修改配置信息是不能生效的,除非有自动刷新配置信息的监听(这个在springcloud的组件里边是可以配置的)。

现在重点介绍下k8s的configmap,顾名思义这个就是做配置使用的,但是我们之前的docker环境因为已经使用consul做注册,配置中心,所以如果迁移到k8s部署应用,也会在k8s里边部署consul来配置服务。下边我们介绍使用configmap来替换consul做配置中心。另外如果这些配置信息是需要加密的,可以使用secret做配置,功能跟configmap是类似的。

前提:

  • 创建单独的namespace (farm)
  • 如果k8s cluster使用RBAC,需要创建clusterrole,serviceaccount, 并将两者bind,否则使用default的serviceaccount是无法访问configmap的,因为k8s的apiserver是通过角色访问接口的。

首先,需要创建configmap in k8s  (farm-service-configmap)

kind: ConfigMap apiVersion: v1 metadata: name: farm-service-configmap namespace: farm labels: app: farm-user-service data: application.yaml: |- server: port: 10000 

其次,创建clusterrole, 注意一定要包括configmaps的权限,

kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: farm-config
labels:
app.kubernetes.io/instance: farm
app.kubernetes.io/name: farm-config
rules:
- verbs:
- get
- list
- watch
apiGroups:
- ''
resources:
- services
- endpoints
- verbs:
- get
- list
- watch
apiGroups:
- ''
resources:
- secrets
- verbs:
- get
- list
- watch
- update
- create
apiGroups:
- ''
resources:
- configmaps
- verbs:
- list
- watch
apiGroups:
- ''
resources:
- pods
- verbs:
- create
- patch
- list
apiGroups:
- ''
resources:
- events

然后创建serviceaccount, clusterrolebinding, 通过clusterrolebinding把sa and clusterrole跟绑定起来, 注意一定要指定namespace, 否则在部署服务的时候如果namespace不一致就还是没有权限服务api server

--
apiVersion: v1
kind: ServiceAccount
metadata:
labels:
app: farm-sa
name: farm-sa
namespace: farm

--
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: farm-config
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: farm-config
subjects:
- kind: ServiceAccount
name: farm-sa
namespace: farm 

最后,在deployment pod的时候一定要把serviceaccountname给指定了。

案例一:

kind: Deployment
apiVersion: apps/v1
metadata:
name: farm-user-service
namespace: farm
labels:
app: farm-user-service
spec:
replicas: 1
selector:
matchLabels:
app: farm-user-service
template:
metadata:
labels:
app: farm-user-service
spec:
containers:
- name: farm-user-service
image: 'harbor.farm.com/farm/farm-user-service:v1.0.0'
command:
- /bin/sh
- '-c'
args:
- >-
java -Djava.security.egd=file:/dev/./urandom -jar
/deployments/farm-user-service-0.0.1-SNAPSHOT.jar
--spring.cloud.kubernetes.config.name=farm-service-configmaps
--spring.cloud.kubernetes.config.namespace=farm
--spring.cloud.consul.enabled=false
--spring.cloud.consul.port=8500
--spring.application.name=farm-user-service
ports:
- containerPort: 9901
protocol: TCP
imagePullPolicy: Always
restartPolicy: Always
dnsPolicy: ClusterFirst
serviceAccountName: farm-sa
serviceAccount: farm-sa

  • 服务使用springboot开发的微服务
  • configmap配置服务的启动端口为10000
  • k8s服务会优先加载configmap的配置,再加载consul的配置信息,如果还是找不到就会取服务里边的yml or properties文件的配置
  1. springboot项目添加kubernets-config的依赖    <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-kubernetes-config</artifactId> </dependency>
  2. 在项目启动参数添加k8s configmap的name and namespace    spring.cloud.kubernetes.config.name=farm-service-configmap, spring.cloud.kubernetes.config.namespace=farm , 这个指定项目要加载的configmap,优先加载configmap
  3. 启动测试,查看服务日志,端口是否是10000

案例二:

kind: Deployment
apiVersion: apps/v1
metadata:
name: farm-user-service
namespace: farm
labels:
app: farm-user-service

spec:
replicas: 1
selector:
matchLabels:
app: farm-user-service
template:
metadata:
labels:
app: farm-user-service
spec:
containers:
- name: farm-user-service
image: >-
harbor.farm.com/farm/farm-user-service:v1.0.0
command:
- ./application
args:
- '-Dquarkus.consul-config.enabled=false'
- '-Dquarkus.kubernetes-config.enabled=true'
- '-Dquarkus.kubernetes-config.namespace=farm'
- '-Dquarkus.kubernetes-config.config-maps=farm-service-configmap'
ports:
- containerPort: 9900
protocol: TCP
resources:
limits:
cpu: 300m
memory: 512Mi
imagePullPolicy: Always
restartPolicy: Always
dnsPolicy: ClusterFirst
serviceAccountName: farm-sa
serviceAccount: farm-sa
schedulerName: default-scheduler

  • 使用quarkus开发的微服务
  • configmap配置数据库的连接地址
  1. quarkus项目添加依赖, 这里有两个配置源,consul和k8s的config, 我们可以验证config的读取顺序是不是(configmap -> consul -> application.properties)
    <dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-consul-config</artifactId>
    </dependency>
    <dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-kubernetes</artifactId>
    </dependency>
    <dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-kubernetes-config</artifactId>
    </dependency>
  2. 服务的启动参数添加如下配置  , 开启读取k8s-config,和consul-config的功能
    quarkus.kubernetes-config.enabled=true
    quarkus.kubernetes-config.namespace=farm
    quarkus.consul-config.enabled=true
  3.   启动服务,验证服务连接数据库使用的是否是k8s-configmap里边的地址
    通过上述两个案例,我们可以发现k8s的configmap可以作为服务的配置中心来提供配置信息,而且k8s也是可以自动发现服务的,因此在k8s的环境中使用consul是没必要的。
    由于openshift container platform也是使用k8s作为基础组件的,实际运行的也是kubernetes,因此里边的configmap也是适用于做配置管理的。

沟通交流合作请加微信!