几乎所有的应用程序都需要配置(实例的配置信息,外部系统的访问信息等),而这些配置显然不应该被打包到应用程序本身中。
本篇文章看看如何在Kubernetes中配置应用程序的信息。
1.配置容器应用的方式
命令行 最简单的应用配置方式,是使用命令行。
配置文件
随着配置信息增多,考虑到维护成本,可以将配置信息存储到配置文件中。但对于容器而言,使用配置文件的方式需要将配置项打包到镜像中,而且每次配置信息的变更都会导致重新生成镜像,重新部署,维护和变更成本较高。
- 环境变量
在容器应用中,使用环境变量来实现配置,也是较普遍的一种做法,通过将参数传递给容器中的应用,变更容器运行期的配置信息,如MySQL官方的镜像就使用环境变量MYSQL_ROOT_PASSWORD
来修改超级用户root的密码。
- volume
另外,基于volume的方式获取配置信息也是一种可行的方式,如使用Git Repo存储配置信息,能有效的做到版本化管理会随时回退。
在K8S中,存储配置信息的资源被称ConfigMap,本部分将介绍ConfigMap、Secret的使用。
2.从命令行传递参数
在Docker容器中,通常使用如下方式传递参数:
- 使用
ENTRYPOINT
定义可执行命令 - 使用
CMD
传递参数
在ENTRYPOINT中,可以使用如下两种方式启动应用:
- Shell方式,如
ENTRYPOINT node app.js
- exec方式,如
ENTRYPOINT ["node", "app.js"]
注意: 这两种方式的区别在于前者是先启动Shell,由Shell调用node,而后者直接启动node应用。
在K8S中,可以通过配置文件中的command
和args
来设置容器中的ENTRYPOINT
和CMD
譬如
1 2 3 4 5 6 |
|
它们之间的区别如下图所示:
Docker | Kubernetes | 描述 |
---|---|---|
ENTRYPOINT | command | 在容器中执行命令 |
CMD | args | 给命令传递参数 |
3.使用环境变量
在K8S中,使用env
设置镜像中定义的环境变量。
譬如,容器中存在如下脚本,其中的INTERVAL
使用环境变量进行设置:
1 2 3 4 5 6 |
|
在K8S中,其配置文件类似如下:
1 2 3 4 5 6 7 8 |
|
4.使用CONFIGMAP解耦配置
Kubernetes允许将配置项分离到一个称为ConfigMap
的单独对象中,它包含若干键/值对,并且值的范围可以从文本到整个配置文件。
应用程序不需要直接读取ConfigMap,甚至不需要知道它的存在。Map的内容可以作为环境变量或者卷传递给容器。
使用kubectl
创建ConfigMap的过程中,可以指定多样化的配置机制,类似如下所示:
1 2 3 4 5 |
|
4.1 使用ConfigMap Entry设置环境变量的值
接下来, 在如上环境变量的例子中,我们使用ConfigMap配置环境变量$INTERVAL
的值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
在如上的例子中,读取ConfigMapfortune-config
中Keysleep-interval
对应的值,作为$INTERVAL
的值。
4.2 使用ConfigMap Entry作为环境变量
譬如有个ConfigMap,它有两个键,分别是foo、bar。您可以使用envFrom属性将它们全部公开为环境变量,而不是像在前面的示例中那样依次使用env。
如下所示:
1 2 3 4 5 6 7 8 |
|
CONFIG_作为前缀,将导出如下环境变量CONFIG_foo和CONFIG_bar。当然,前缀是可选的,如不设置,则容器中的环境变量为foo和bar。
4.3 使用ConfigMap Entry作为命令行参数
接下来,让我们看看如何将ConfigMap中的值作为参数传递给容器中运行的进程。我们不能在pod.spec.containers.args字段中直接引用ConfigMap,但是可以从ConfigMap中初始化一个环境变量,然后引用参数中的值,相关代码如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
其关系如图所示:
4.3 使用ConfigMap volume导出ConfigMap的Entry
ConfigMap除了可以作为环境变量以及命令行参数外,还可以包括整个目录中的配置文件。
譬如,在configmap-files
目录下存在如下2个文件:
- my-nginx-config.conf
1 2 3 4 5 6 7 8 9 10 11 12 |
|
- sleep-interval.txt
1
|
|
接下来,使用命令创建ConfigMap
1
|
|
然后,我们可以使用volume将ConfigMap中的内容暴露给容器:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
|