当前位置:   article > 正文

ConfigMap使用_configmap作用

configmap作用

1.configMap作用

  应用部署的一个最佳实践是将应用所需的配置信息与程序进行分离,这样可以使应用程序被更好地复用,通过不同的配置也能实现更灵活的功能。将应用打包为容器镜像后,可以通过环境变量或者外挂文件的方式在创建容器时进行配置注入,但在大规模容器集群的环境中,对多个容器进行不同的配置将变得非常复杂。从Kubernetes 1.2开始提供了一种统一的应用配置管理方案—ConfigMap。

  应用程序的运行可能会依赖一些配置,而这些配置又是可能会随着需求产生变化的,如果我们的应用程序架构不是应用和配置分离的,那么就会存在当我们需要去修改某些配置项的属性时需要重新构建镜像文件的窘境。现在,ConfigMap组件可以很好的帮助我们实现应用和配置分离,避免因为修改配置项而重新构建镜像。

  ConfigMap 用于保存配置数据的键值对,可以用来保存单个属性,也可以用来保存配置文件。ConfigMap 跟 Secret 很类似,但它可以更方便地处理不包含敏感信息的字符串。
 

1.1 ConfigMap供容器使用的典型用法

  1. 生成为容器内的环境变量。
  2. 设置容器启动命令的启动参数(需设置为环境变量)。
  3. 以Volume的形式挂载为容器内部的文件或目录。

ConfigMap以一个或多个key:value的形式保存在Kubernetes系统中供应用使用,既可以用于表示一个变量的值(例如apploglevel=info),也可以用于表示一个完整配置文件的内容(例如server.xml=<?xml…>…)
可以通过YAML配置文件或者直接使用kubectl create configmap命令行的方式来创建ConfigMap。

2.创建configMap资源

就像java一样,要用某个对象你得先new一个,要先创建了这个configMap资源别人才能用呀。

2.1 通过yaml文件创建

2.1.1 key: value (value是变量值)

  • cm-appvars.yaml
  1. apiVersion: v1
  2. kind: ConfigMap
  3. metadata:
  4. name: cm-appvars
  5. data: # 定义了两个key: value形式的配置
  6. apploglevel: info
  7. appdatadir: /var/data

创建命令:

  1. [root@k8s-master Chapter3]# kubectl apply -f cm-appvars.yaml
  2. configmap/cm-appvars created

查看configMap

  1. [root@k8s-master Chapter3]# kubectl describe configmap cm-appvars
  2. Name: cm-appvars
  3. Namespace: default
  4. Labels: <none>
  5. Annotations: <none>
  6. Data
  7. ====
  8. apploglevel:
  9. ----
  10. info
  11. appdatadir:
  12. ----
  13. /var/data
  14. BinaryData
  15. ====

2.1.2 key:value (value是一个完整的文件)

创建 Kubernetes 的 ConfigMap 资源,用于存储 Mysql 的配置文件 my.cnf 内容:

  • mysql-config.yaml
  1. apiVersion: v1
  2. kind: ConfigMap
  3. metadata:
  4. name: mysql-config
  5. labels:
  6. app: mysql
  7. data:
  8. my.cnf: |-
  9. [client]
  10. default-character-set=utf8mb4
  11. [mysql]
  12. default-character-set=utf8mb4
  13. default-time_zone = '+8:00'
  14. [mysqld]
  15. max_connections = 2000
  16. secure_file_priv=/var/lib/mysql
  17. sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION

这里就是一个完整的my.conf: ${value} value是一个完整的配置文件。

2.2 通过kubectl 手动创建

不使用YAML文件,直接通过kubectl create configmap也可以创建ConfigMap,可以使用参数–from-file或–from-literal指定内容,并且可以在一行命令中指定多个参数。

这种方式应该用的少,我看到的一般都是用yaml,所以这里只是记录可以这么干。真要这么用,再查吧。
 

  1. $ ls docs/user-guide/configmap/kubectl/
  2. game.properties
  3. ui.properties
  4. $ cat docs/user-guide/configmap/kubectl/game.properties
  5. enemies=aliens
  6. lives=3
  7. enemies.cheat=true
  8. enemies.cheat.level=noGoodRotten
  9. secret.code.passphrase=UUDDLRLRBABAS
  10. secret.code.allowed=true
  11. secret.code.lives=30
  12. $ cat docs/user-guide/configmap/kubectl/ui.properties
  13. color.good=purple
  14. color.bad=yellow
  15. allow.textmode=true
  16. how.nice.to.look=fairlyNice
  17. 应用:
  18. kubectl create configmap game-config --from-file=docs/user-guide/configmap/kubectl
  19. —from-file指定在目录下的所有文件都会被用在ConfigMap里面创建一个键值对,键的名字就是文件名,值就是文件的内容。
  20. $ kubectl describe configmaps game-config
  21. Name: game-config
  22. Namespace: default
  23. Labels: <none>
  24. Annotations: <none>
  25. Data
  26. ====
  27. game.properties: 158 bytes
  28. ui.properties: 83 bytes
  29. 我们以yaml格式输出配置。
  30. kubectl get configmaps game-config -o yaml
  31. ----output----
  32. apiVersion: v1
  33. data:
  34. game.properties: |
  35. enemies=aliens
  36. lives=3
  37. enemies.cheat=true
  38. enemies.cheat.level=noGoodRotten
  39. secret.code.passphrase=UUDDLRLRBABAS
  40. secret.code.allowed=true
  41. secret.code.lives=30
  42. ui.properties: |
  43. color.good=purple
  44. color.bad=yellow
  45. allow.textmode=true
  46. how.nice.to.look=fairlyNice
  47. kind: ConfigMap
  48. metadata:
  49. creationTimestamp: 2016-02-18T18:34:05Z
  50. name: game-config
  51. namespace: default
  52. resourceVersion: "407"
  53. selfLink: /api/v1/namespaces/default/configmaps/game-config
  54. uid: 30944725-d66e-11e5-8cd0-68f728db1985

这个案例没有自己尝试,都是其他人的。

3 在Pod中使用ConfigMap

3.1 用作环境变量

  在Pod“cm-test-pod”的定义中,将ConfigMap“cm-appvars”中的内容以环境变量(APPLOGLEVEL和APPDATADIR)方式设置为容器内部的环境变量,容器的启动命令将显示这两个环境变量的值(“env | grep APP”):

  • cm-test-pod-use-envvar.yaml
  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. name: cm-test-pod
  5. spec:
  6. containers:
  7. - name: cm-test
  8. image: busybox
  9. command: [ "/bin/sh", "-c", "env | grep APP" ]
  10. env:
  11. - name: APPLOGLEVEL
  12. valueFrom:
  13. configMapKeyRef:
  14. name: cm-appvars
  15. key: apploglevel
  16. - name: APPDATADIR # 环境变量的名称APPDATADIR
  17. valueFrom: # 值来源于
  18. configMapKeyRef: # 引用configMap里面的值
  19. name: cm-appvars # configMap的名称
  20. key: appdatadir # configMap中的key
  21. restartPolicy: Never # Pod重启策略

kubectl apply -f cm-test-pod-use-envvar.yaml

验证:

  1. [root@k8s-master Chapter3]# kubectl logs cm-test-pod
  2. APPDATADIR=/var/data
  3. APPLOGLEVEL=info

或者如果说,你需要configMap所有的环境变量的话,可以这么写:

  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. name: cm-test-pod
  5. spec:
  6. containers:
  7. - name: cm-test
  8. image: busybox
  9. command: [ "/bin/sh", "-c", "env" ]
  10. envFrom:
  11. - configMapRef:
  12. name: cm-appvars
  13. restartPolicy: Never

那么环境变量的名称就是configMap里面的key,环境变量的值就是configMap里面的value。

Tips:
需要说明的是,环境变量的名称受POSIX命名规范([a-zA-Z_][a-zA-Z0-9_]*)约束,不能以数字开头。如果包含非法字符,则系统将跳过该条环境变量的创建,并记录一个Event来提示环境变量无法生成,但并不阻止Pod的启动。
 

3.2 通过volumeMount使用ConfigMap

这个就比较有用了,为什么呢?例如一个mysql服务,你的配置文件不可能在容器里面改来改去,一定是要有一个地方专门去存储的。configMap就可以做到,因为,它可以将configMap里面的内容直接映射到container容器指定的一个目录下面去。

3.2.1 configMap定义

  1. apiVersion: v1
  2. kind: ConfigMap
  3. metadata:
  4. name: cm-appconfigfiles
  5. data:
  6. key-serverxml: |
  7. <?xml version='1.0' encoding='utf-8'?>
  8. <Server port="8005" shutdown="SHUTDOWN">
  9. <Listener className="org.apache.catalina.startup.VersionLoggerListener" />
  10. <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
  11. <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
  12. <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
  13. <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
  14. <GlobalNamingResources>
  15. <Resource name="UserDatabase" auth="Container"
  16. type="org.apache.catalina.UserDatabase"
  17. description="User database that can be updated and saved"
  18. factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
  19. pathname="conf/tomcat-users.xml" />
  20. </GlobalNamingResources>
  21. <Service name="Catalina">
  22. <Connector port="8080" protocol="HTTP/1.1"
  23. connectionTimeout="20000"
  24. redirectPort="8443" />
  25. <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
  26. <Engine name="Catalina" defaultHost="localhost">
  27. <Realm className="org.apache.catalina.realm.LockOutRealm">
  28. <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
  29. resourceName="UserDatabase"/>
  30. </Realm>
  31. <Host name="localhost" appBase="webapps"
  32. unpackWARs="true" autoDeploy="true">
  33. <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
  34. prefix="localhost_access_log" suffix=".txt"
  35. pattern="%h %l %u %t &quot;%r&quot; %s %b" />
  36. </Host>
  37. </Engine>
  38. </Service>
  39. </Server>
  40. key-loggingproperties: "handlers
  41. = 1catalina.org.apache.juli.FileHandler, 2localhost.org.apache.juli.FileHandler,
  42. 3manager.org.apache.juli.FileHandler, 4host-manager.org.apache.juli.FileHandler,
  43. java.util.logging.ConsoleHandler\r\n\r\n.handlers = 1catalina.org.apache.juli.FileHandler,
  44. java.util.logging.ConsoleHandler\r\n\r\n1catalina.org.apache.juli.FileHandler.level
  45. = FINE\r\n1catalina.org.apache.juli.FileHandler.directory = ${catalina.base}/logs\r\n1catalina.org.apache.juli.FileHandler.prefix
  46. = catalina.\r\n\r\n2localhost.org.apache.juli.FileHandler.level = FINE\r\n2localhost.org.apache.juli.FileHandler.directory
  47. = ${catalina.base}/logs\r\n2localhost.org.apache.juli.FileHandler.prefix = localhost.\r\n\r\n3manager.org.apache.juli.FileHandler.level
  48. = FINE\r\n3manager.org.apache.juli.FileHandler.directory = ${catalina.base}/logs\r\n3manager.org.apache.juli.FileHandler.prefix
  49. = manager.\r\n\r\n4host-manager.org.apache.juli.FileHandler.level = FINE\r\n4host-manager.org.apache.juli.FileHandler.directory
  50. = ${catalina.base}/logs\r\n4host-manager.org.apache.juli.FileHandler.prefix =
  51. host-manager.\r\n\r\njava.util.logging.ConsoleHandler.level = FINE\r\njava.util.logging.ConsoleHandler.formatter
  52. = java.util.logging.SimpleFormatter\r\n\r\n\r\norg.apache.catalina.core.ContainerBase.[Catalina].[localhost].level
  53. = INFO\r\norg.apache.catalina.core.ContainerBase.[Catalina].[localhost].handlers
  54. = 2localhost.org.apache.juli.FileHandler\r\n\r\norg.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/manager].level
  55. = INFO\r\norg.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/manager].handlers
  56. = 3manager.org.apache.juli.FileHandler\r\n\r\norg.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/host-manager].level
  57. = INFO\r\norg.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/host-manager].handlers
  58. = 4host-manager.org.apache.juli.FileHandler\r\n\r\n"

其中configMap中分别定义了两个key,一个是key-serverxml,另一个是key-loggingproperties。这两个key的value都是一个文件。所以我们需要通过volumeMount,对这两个进行相应的挂载。

3.2.2 通过items,设置挂载的文件名

  • cm-test-app.yaml
  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. name: cm-test-app
  5. spec:
  6. containers:
  7. - name: cm-test-app
  8. image: kubeguide/tomcat-app:v1
  9. ports:
  10. - containerPort: 8080
  11. volumeMounts:
  12. - name: serverxml
  13. mountPath: /configfiles # 将name=serverxml的volume,改在到/configfiles这个目录之下
  14. volumes:
  15. - name: serverxml
  16. configMap:
  17. name: cm-appconfigfiles
  18. items:
  19. - key: key-serverxml #key就是configMap的key
  20. path: server.xml #将value里面的内容形成server.xml文件<==>/configfiles/server.xml
  21. - key: key-loggingproperties
  22. path: logging.properties

3.2.3 不指定items的默认情况

  如果在引用ConfigMap时不指定items,则使用volumeMount方式在容器内的目录下为每个item都生成一个文件名为key的文件。

  登录容器,查看到在/configfiles目录下存在key-loggingproperties和key-serverxml文件,文件的名称来自在ConfigMap cm-appconfigfiles中定义的两个key的名称,文件的内容则为value的内容:

那么也就是说,如果你不指定的话,key最好就写成文件名就好了,这样也省的麻烦

3.2.4 关于configMap 挂载时候的文件覆盖问题

  在一般情况下 通过configmap 挂载文件时,会先覆盖掉挂载目录也就是这里/configfiles原来的内容会被覆盖,然后再将 congfigmap 中的内容作为文件挂载进行。如果想不对原来的文件夹下的文件造成覆盖,只是将 configmap 中的每个 key,按照文件的方式挂载到目录下,可以使用 subpath 参数。比如这样:
 

  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. name: dapi-test-pod
  5. spec:
  6. containers:
  7. - name: test-container
  8. image: hub.coreqi.cn/library/myapp:v1
  9. command: [ "/bin/sh", "-c", "cat /etc/config/special.how" ]
  10. # 把config-volume下的key1的值。完整地赋值给appsettings.Production.json
  11. volumeMounts:
  12. - name: config-volume
  13. mountPath: /app/appsettings.Production.json
  14. subPath: key1
  15. # 导入“special-config”的configmap,并命名为config-volume
  16. volumes:
  17. - name: config-volume
  18. configMap:
  19. name: special-config
  20. restartPolicy: Never

4 ConfigMap的热更新问题

  • 热更新只有对volume挂载文件的使用方式有效(Pod 同步间隔(默认10秒) + ConfigMap 本地缓存的 TTL)
  • 对该ConfigMap挂载的Env不会同步更新
  • 对subPath热更新是无效的,可以通过其他方式强制更新,搜一下就知道了,比如这里通过更改annotation的方法,但是这种方法是否是最恰当的,现在还未知。
     
kubectl patch deployment mysql --patch '{"spec": {"template": {"metadata": {"annotations": {"update": "2" }}}}}'

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/378580
推荐阅读
  

闽ICP备14008679号