1 - 示例:配置 java 微服务
1.1 - 使用 MicroProfile、ConfigMaps、Secrets 实现外部化应用配置
在本教程中,你会学到如何以及为什么要实现外部化微服务应用配置。 具体来说,你将学习如何使用 Kubernetes ConfigMaps 和 Secrets 设置环境变量, 然后在 MicroProfile config 中使用它们。
准备开始
创建 Kubernetes ConfigMaps 和 Secrets
在 Kubernetes 中,为 docker 容器设置环境变量有几种不同的方式,比如: Dockerfile、kubernetes.yml、Kubernetes ConfigMaps、和 Kubernetes Secrets。 在本教程中,你将学到怎么用后两个方式去设置你的环境变量,而环境变量的值将注入到你的微服务里。 使用 ConfigMaps 和 Secrets 的一个好处是他们能在多个容器间复用, 比如赋值给不同的容器中的不同环境变量。
ConfigMaps 是存储非机密键值对的 API 对象。 在互动教程中,你会学到如何用 ConfigMap 来保存应用名字。 ConfigMap 的更多信息,你可以在这里找到文档。
Secrets 尽管也用来存储键值对,但区别于 ConfigMaps 的是:它针对机密/敏感数据,且存储格式为 Base64 编码。 secrets 的这种特性使得它适合于存储证书、密钥、令牌,上述内容你将在交互教程中实现。 Secrets 的更多信息,你可以在这里找到文档。
从代码外部化配置
外部化应用配置之所以有用处,是因为配置常常根据环境的不同而变化。 为了实现此功能,我们用到了 Java 上下文和依赖注入(Contexts and Dependency Injection, CDI)、MicroProfile 配置。 MicroProfile config 是 MicroProfile 的功能特性, 是一组开放 Java 技术,用于开发、部署云原生微服务。
CDI 提供一套标准的依赖注入能力,使得应用程序可以由相互协作的、松耦合的 beans 组装而成。 MicroProfile Config 为 app 和微服务提供从各种来源,比如应用、运行时、环境,获取配置参数的标准方法。 基于来源定义的优先级,属性可以自动的合并到单独一组应用可以通过 API 访问到的属性。 CDI & MicroProfile 都会被用在互动教程中, 用来从 Kubernetes ConfigMaps 和 Secrets 获得外部提供的属性,并注入应用程序代码中。
很多开源框架、运行时支持 MicroProfile Config。 对于整个互动教程,你都可以使用开放的库、灵活的开源 Java 运行时,去构建并运行云原生的 apps 和微服务。 然而,任何 MicroProfile 兼容的运行时都可以用来做替代品。
教程目标
- 创建 Kubernetes ConfigMap 和 Secret
- 使用 MicroProfile Config 注入微服务配置
示例:使用 MicroProfile、ConfigMaps、Secrets 实现外部化应用配置
启动互动教程
1.2 - 互动教程 - 配置 java 微服务
2 - 使用 ConfigMap 来配置 Redis
这篇文档基于使用 ConfigMap 来配置 Containers 这个任务,提供了一个使用 ConfigMap 来配置 Redis 的真实案例。
教程目标
- 使用 Redis 配置的值创建一个 ConfigMap
- 创建一个 Redis Pod,挂载并使用创建的 ConfigMap
- 验证配置已经被正确应用。
准备开始
你必须拥有一个 Kubernetes 的集群,同时你的 Kubernetes 集群必须带有 kubectl 命令行工具。 建议在至少有两个节点的集群上运行本教程,且这些节点不作为控制平面主机。 如果你还没有集群,你可以通过 Minikube 构建一个你自己的集群,或者你可以使用下面任意一个 Kubernetes 工具构建:
要获知版本信息,请输入kubectl version
.
- 此页面上显示的示例适用于
kubectl
1.14和在其以上的版本。 - 理解使用ConfigMap来配置Containers。
真实世界的案例:使用 ConfigMap 来配置 Redis
按照下面的步骤,使用 ConfigMap 中的数据来配置 Redis 缓存。
首先创建一个配置模块为空的 ConfigMap:
cat <<EOF >./example-redis-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: example-redis-config
data:
redis-config: ""
EOF
应用上面创建的 ConfigMap 以及 Redis pod 清单:
kubectl apply -f example-redis-config.yaml
kubectl apply -f https://k8s.io/examples/pods/config/redis-pod.yaml
检查 Redis pod 清单的内容,并注意以下几点:
- 由
spec.volumes[1]
创建一个名为config
的卷。 spec.volumes[1].items[0]
下的key
和path
会将来自example-redis-config
ConfigMap 中的redis-config
密钥公开在config
卷上一个名为redis-config
的文件中。- 然后
config
卷被spec.containers[0].volumeMounts[1]
挂载在/redis-master
。
这样做的最终效果是将上面 example-redis-config
配置中 data.redis-config
的数据作为 Pod 中的 /redis-master/redis.conf
公开。
apiVersion: v1
kind: Pod
metadata:
name: redis
spec:
containers:
- name: redis
image: redis:5.0.4
command:
- redis-server
- "/redis-master/redis.conf"
env:
- name: MASTER
value: "true"
ports:
- containerPort: 6379
resources:
limits:
cpu: "0.1"
volumeMounts:
- mountPath: /redis-master-data
name: data
- mountPath: /redis-master
name: config
volumes:
- name: data
emptyDir: {}
- name: config
configMap:
name: example-redis-config
items:
- key: redis-config
path: redis.conf
检查创建的对象:
kubectl get pod/redis configmap/example-redis-config
你应该可以看到以下输出:
NAME READY STATUS RESTARTS AGE
pod/redis 1/1 Running 0 8s
NAME DATA AGE
configmap/example-redis-config 1 14s
回顾一下,我们在 example-redis-config
ConfigMap 保留了空的 redis-config
键:
kubectl describe configmap/example-redis-config
你应该可以看到一个空的 redis-config
键:
Name: example-redis-config
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
redis-config:
使用 kubectl exec
进入 pod,运行 redis-cli
工具检查当前配置:
kubectl exec -it redis -- redis-cli
查看 maxmemory
:
127.0.0.1:6379> CONFIG GET maxmemory
它应该显示默认值 0:
1) "maxmemory"
2) "0"
同样,查看 maxmemory-policy
:
127.0.0.1:6379> CONFIG GET maxmemory-policy
它也应该显示默认值 noeviction
:
1) "maxmemory-policy"
2) "noeviction"
现在,向 example-redis-config
ConfigMap 添加一些配置:
apiVersion: v1
kind: ConfigMap
metadata:
name: example-redis-config
data:
redis-config: |
maxmemory 2mb
maxmemory-policy allkeys-lru
应用更新的 ConfigMap:
kubectl apply -f example-redis-config.yaml
确认 ConfigMap 已更新:
kubectl describe configmap/example-redis-config
你应该可以看到我们刚刚添加的配置:
Name: example-redis-config
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
redis-config:
----
maxmemory 2mb
maxmemory-policy allkeys-lru
通过 kubectl exec
使用 redis-cli
再次检查 Redis Pod,查看是否已应用配置:
kubectl exec -it redis -- redis-cli
查看 maxmemory
:
127.0.0.1:6379> CONFIG GET maxmemory
它保持默认值 0:
1) "maxmemory"
2) "0"
同样,maxmemory-policy
保留为默认设置 noeviction
:
127.0.0.1:6379> CONFIG GET maxmemory-policy
返回:
1) "maxmemory-policy"
2) "noeviction"
配置值未更改,因为需要重新启动 Pod 才能从关联的 ConfigMap 中获取更新的值。 让我们删除并重新创建 Pod:
kubectl delete pod redis
kubectl apply -f https://k8s.io/examples/pods/config/redis-pod.yaml
现在,最后一次重新检查配置值:
kubectl exec -it redis -- redis-cli
查看 maxmemory
:
127.0.0.1:6379> CONFIG GET maxmemory
现在,它应该返回更新后的值 2097152:
1) "maxmemory"
2) "2097152"
同样,maxmemory-policy
也已更新:
127.0.0.1:6379> CONFIG GET maxmemory-policy
现在它反映了期望值 allkeys-lru
:
1) "maxmemory-policy"
2) "allkeys-lru"
删除创建的资源,清理你的工作:
kubectl delete pod/redis configmap/example-redis-config
接下来
- 了解有关 ConfigMaps的更多信息。