Kubernetes 配置Pod和容器(十二)configmap的使用

很多应用程序需要一些配置通过组合的配置文件,命令行参数和环境变量。这些配置应该与镜像内容分离以保持容器化应用程序的可移植性。ConfigMap API资源提供了将配置数据注入容器的机制,同时保持容器不受kubernetes的影响。ConfigMap可用于存储细粒度信息如单个属性,或粗粒度信息如整个配置文件或JSON对象。

ConfigMap概述

ConfigMap API资源保存配置数据的键值对,可以在pods中使用或者可以用于存储系统组件的配置数据。ConfigMap类似于Secrets,但是旨在更方便的使用不包含敏感信息的字符串。

注意:ConfigMap不打算充当属性文件的替换者。你可以认为类似于/etc目录,以及Linux计算机上的文件。一个例子是从ConfigMap创建一个Kubernetes卷,其中ConfigMap的数据项变成一个新的文件。

例如下面的例子:

kind: ConfigMap
apiVersion: v1
metadata:
  creationTimestamp: 2016-02-18T19:14:38Z
  name: example-config
  namespace: default
data:
  example.property.1: hello
  example.property.2: world
  example.property.file: |-
    property.1=value-1
    property.2=value-2
    property.3=value-3

data字段包含配置信息。可以看到ConfigMap可以用于细粒度的单个属性,或者是配置文件的内容。

配置数据在pods中有多种使用方式。ConfigMap有以下几种使用方式:

1.填充环境变量的值

2.设置容器内的命令行参数

3.填充卷的配置文件

用户和系统组建都可以在ConfigMap中存储配置数据。

新建ConfigMap

可以使用kubectl create configmap 命令行非常容易的从字面值,文件或目录中创建configmaps。

让我们尝试用不同的方式创建一个ConfigMap:

从目录创建

比如说我们有一个目录其中包含一些已经已经包含要填充ConfigMap数据的文件:

$ ls docs/user-guide/configmap/kubectl/
game.properties
ui.properties

$ cat docs/user-guide/configmap/kubectl/game.properties
enemies=aliens
lives=3
enemies.cheat=true
enemies.cheat.level=noGoodRotten
secret.code.passphrase=UUDDLRLRBABAS
secret.code.allowed=true
secret.code.lives=30

$ cat docs/user-guide/configmap/kubectl/ui.properties
color.good=purple
color.bad=yellow
allow.textmode=true
how.nice.to.look=fairlyNice

kubectl create configmap 可用于创建一个保存此目录中每个文件内容的ConfigMap:

$ kubectl create configmap game-config --from-file=docs/user-guide/configmap/kubectl

当 --from-file指向一个目录,每个目录中的文件直接用于填充ConfigMap中的key,key的名称是文件名称,key的值是这个文件的内容。让我们看看上面命令创建的ConfigMap:

$ kubectl describe configmaps game-config
Name:           game-config
Namespace:      default
Labels:         <none>
Annotations:    <none>

Data
====
game.properties:        158 bytes
ui.properties:          83 bytes

可以看到map中的两个key是从我们指向的kubectl的目录中的文件名创建的。因为这些建的内容可能很大,kubectl describe你只能看到他们key的名称和大小。如果想看这些key的值,可以通过kubectl get获取:

$ kubectl get configmaps game-config -o yaml

apiVersion: v1
data:
  game.properties: |
    enemies=aliens
    lives=3
    enemies.cheat=true
    enemies.cheat.level=noGoodRotten
    secret.code.passphrase=UUDDLRLRBABAS
    secret.code.allowed=true
    secret.code.lives=30
  ui.properties: |
    color.good=purple
    color.bad=yellow
    allow.textmode=true
    how.nice.to.look=fairlyNice
kind: ConfigMap
metadata:
  creationTimestamp: 2016-02-18T18:34:05Z
  name: game-config
  namespace: default
  resourceVersion: "407"
  selfLink: /api/v1/namespaces/default/configmaps/game-config
  uid: 30944725-d66e-11e5-8cd0-68f728db1985

从文件创建

也可以通过--from-file指定文件,并将他多次传递给kubectc。下面的命令和上面的示例产生相同的结果:

$ kubectl create configmap game-config-2 --from-file=docs/user-guide/configmap/kubectl/game.properties --from-file=docs/user-guide/configmap/kubectl/ui.properties

$ kubectl get configmaps game-config-2 -o yaml
apiVersion: v1
data:
  game.properties: |
    enemies=aliens
    lives=3
    enemies.cheat=true
    enemies.cheat.level=noGoodRotten
    secret.code.passphrase=UUDDLRLRBABAS
    secret.code.allowed=true
    secret.code.lives=30
  ui.properties: |
    color.good=purple
    color.bad=yellow
    allow.textmode=true
    how.nice.to.look=fairlyNice
kind: ConfigMap
metadata:
  creationTimestamp: 2016-02-18T18:52:05Z
  name: game-config-2
  namespace: default
  resourceVersion: "516"
  selfLink: /api/v1/namespaces/default/configmaps/game-config-2
  uid: b4952dc3-d670-11e5-8cd0-68f728db1985

我们可以通过key=value表达式为每个文件设置key:

--from-file=game-special-key=docs/user-guide/configmap/kubectl/game.properties

$ kubectl create configmap game-config-3 --from-file=game-special-key=docs/user-guide/configmap/kubectl/game.properties

$ kubectl get configmaps game-config-3 -o yaml
apiVersion: v1
data:
  game-special-key: |
    enemies=aliens
    lives=3
    enemies.cheat=true
    enemies.cheat.level=noGoodRotten
    secret.code.passphrase=UUDDLRLRBABAS
    secret.code.allowed=true
    secret.code.lives=30
kind: ConfigMap
metadata:
  creationTimestamp: 2016-02-18T18:54:22Z
  name: game-config-3
  namespace: default
  resourceVersion: "530"
  selfLink: /api/v1/namespaces/default/configmaps/game-config-3
  uid: 05f8da22-d671-11e5-8cd0-68f728db1985

通过字面值创建

也可以通过kubectl create configmap创建ConfigMap使用字面值。--from-literal选项使用一个key=value语法,允许直接在命令行中直接提供字面值:

$ kubectl create configmap special-config --from-literal=special.how=very --from-literal=special.type=charm

$ kubectl get configmaps special-config -o yaml
apiVersion: v1
data:
  special.how: very
  special.type: charm
kind: ConfigMap
metadata:
  creationTimestamp: 2016-02-18T19:14:38Z
  name: special-config
  namespace: default
  resourceVersion: "651"
  selfLink: /api/v1/namespaces/default/configmaps/special-config
  uid: dadce046-d673-11e5-8cd0-68f728db1985

pods使用ConfigMap

用例:在环境变量中使用ConfigMap

ConfigMap可用于填充各个环境变量或者整个使用。例如下面的例子:

apiVersion: v1
kind: ConfigMap
metadata:
  name: special-config
  namespace: default
data:
  special.how: very
  special.type: charm
apiVersion: v1
kind: ConfigMap
metadata:
  name: env-config
  namespace: default
data:
  log_level: INFO

可以在pod中这样使用ConfigMap的键:

apiVersion: v1
kind: Pod
metadata:
  name: dapi-test-pod
spec:
  containers:
    - name: test-container
      image: gcr.io/google_containers/busybox
      command: [ "/bin/sh", "-c", "env" ]
      env:
        - name: SPECIAL_LEVEL_KEY
          valueFrom:
            configMapKeyRef:
              name: special-config
              key: special.how
        - name: SPECIAL_TYPE_KEY
          valueFrom:
            configMapKeyRef:
              name: special-config
              key: special.type
      envFrom:
        - configMapRef:
            name: env-config
  restartPolicy: Never

当这个pod运行起来的时候,它输出包含下面的行:

SPECIAL_LEVEL_KEY=very
SPECIAL_TYPE_KEY=charm
log_level=INFO

可选ConfigMap在环境变量中

有些情况环境变量不是总是需要。这些环境变量可以标记为可选的在pods:

apiVersion: v1
kind: Pod
metadata:
  name: dapi-test-pod
spec:
  containers:
    - name: test-container
      image: gcr.io/google_containers/busybox
      command: [ "/bin/sh", "-c", "env" ]
      env:
        - name: SPECIAL_LEVEL_KEY
          valueFrom:
            configMapKeyRef:
              name: a-config
              key: akey
              optional: true
  restartPolicy: Never

当这个pod运行,输出是空的。

设置命令行参数用ConfigMap

ConfigMaps可以用于设置容器里面的命令行参数的值。这是使用Kubernetes替换$(value)语法完成的。考虑ConfigMap:

apiVersion: v1
kind: ConfigMap
metadata:
  name: special-config
  namespace: default
data:
  special.how: very
  special.type: charm

为了把值注入到命令行,我们必须使用我们作为环境变量的键,例如上一个例子。我们可以参考在容器内命令行使用$(VAR_NAME)语法:

apiVersion: v1
kind: Pod
metadata:
  name: dapi-test-pod
spec:
  containers:
    - name: test-container
      image: gcr.io/google_containers/busybox
      command: [ "/bin/sh", "-c", "echo $(SPECIAL_LEVEL_KEY) $(SPECIAL_TYPE_KEY)" ]
      env:
        - name: SPECIAL_LEVEL_KEY
          valueFrom:
            configMapKeyRef:
              name: special-config
              key: special.how
        - name: SPECIAL_TYPE_KEY
          valueFrom:
            configMapKeyRef:
              name: special-config
              key: special.type
  restartPolicy: Never

当pod运行起来的时候,从test-container容器的输出会是:

very charm

用例:使用ConfigMap通过卷插件

ConfigMaps也可以在卷内使用。再次返回我们的示例:

apiVersion: v1
kind: ConfigMap
metadata:
  name: special-config
  namespace: default
data:
  special.how: very
  special.type: charm

在卷中使用ConfigMap我们有几个不同的选项。最基础的方式是填充卷文件,键值是文件名内容是键对应的值:

apiVersion: v1
kind: Pod
metadata:
  name: dapi-test-pod
spec:
  containers:
    - name: test-container
      image: gcr.io/google_containers/busybox
      command: [ "/bin/sh", "-c", "cat /etc/config/special.how" ]
      volumeMounts:
      - name: config-volume
        mountPath: /etc/config
  volumes:
    - name: config-volume
      configMap:
        name: special-config
  restartPolicy: Never

当这个pod运行起来,会输出下面的内容:

very

我们还可以控制卷中的路径通过ConfigMap键映射:

apiVersion: v1
kind: Pod
metadata:
  name: dapi-test-pod
spec:
  containers:
    - name: test-container
      image: gcr.io/google_containers/busybox
      command: [ "/bin/sh","-c","cat /etc/config/path/to/special-key" ]
      volumeMounts:
      - name: config-volume
        mountPath: /etc/config
  volumes:
    - name: config-volume
      configMap:
        name: special-config
        items:
        - key: special.how
          path: path/to/special-key
  restartPolicy: Never

当这个pod运行起来,会输出下面:

very

映射key指定的路径和权限

你可以在每个文件基础上指定key映射的特定路径和权限。Secrets用户指南介绍语法。

可选ConfigMap通过卷插件

卷和文件也可以标记为可选。ConfigMap或指定的键不一定存在。将始终创建这些项目的挂载路径。

apiVersion: v1
kind: Pod
metadata:
  name: dapi-test-pod
spec:
  containers:
    - name: test-container
      image: gcr.io/google_containers/busybox
      command: [ "/bin/sh", "-c", "ls /etc/config" ]
      volumeMounts:
      - name: config-volume
        mountPath: /etc/config
  volumes:
    - name: config-volume
      configMap:
        name: no-config
        optional: true
  restartPolicy: Never

当pod运行起来,输出将是空。

真实的示例:配置Redis

让我看一个真实示例:使用ConfigMap配置redis。加入我们想用推荐的配置注入redis作为缓存。redis的配置文件应该包含:

maxmemory 2mb
maxmemory-policy allkeys-lru

这个文件在docs/user-guide/configmap/redis,我们可以用下面的命令新建一个ConfigMap:

$ kubectl create configmap example-redis-config --from-file=docs/user-guide/configmap/redis/redis-config

$ kubectl get configmap example-redis-config -o yaml
apiVersion: v1
data:
  redis-config: |
    maxmemory 2mb
    maxmemory-policy allkeys-lru
kind: ConfigMap
metadata:
  creationTimestamp: 2016-03-30T18:14:41Z
  name: example-redis-config
  namespace: default
  resourceVersion: "24686"
  selfLink: /api/v1/namespaces/default/configmaps/example-redis-config
  uid: 460a2b6e-f6a3-11e5-8ae5-42010af00002

现在我们新建一个pod使用这个配置:

apiVersion: v1
kind: Pod
metadata:
  name: redis
spec:
  containers:
  - name: redis
    image: kubernetes/redis:v1
    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

注意,这个pod有一个ConfigMap卷,它将example-redis-config ConfigMap的redis-config键的值放入一个名为redis.conf的文件中。这个卷是挂载到redis容器里面的/redis-master目录里面,我们的配置文件在/redis-master/redis.conf,这个redis注解点在镜像里面的配置文件。

$ kubectl create -f docs/user-guide/configmap/redis/redis-pod.yaml

运行kubectl exec进入到这个pod里面并运行redis-cli工具,可以检查我们的配置是否正确应用:

$ kubectl exec -it redis redis-cli
127.0.0.1:6379> CONFIG GET maxmemory
1) "maxmemory"
2) "2097152"
127.0.0.1:6379> CONFIG GET maxmemory-policy
1) "maxmemory-policy"
2) "allkeys-lru"

限制

ConfigMap必须在pod消耗他之前创建,除非被标记为可选。对于不存在的ConfigMap将阻止它启动。控制器可能被写入以容忍丢失数据,可以个根据具体情况查看通过ConfigMap配置的各个组件。

通过configMapKeyRef引用命名ConfigMap中不存在的键将阻止他的启动。

ConfigMaps用于填充环境变量通过envFrom,它们被认为具有无效的环境变量名称的键将跳过这些键。该pod被允许启动。将会有一个事件,原因是InvalidVariabelNames,该消息包含被跳过的无效的键的列表。该示例显示一个pod它指的是 default/myconfig ConfigMap包含两个无效的键,1badkey和2alsobad。

$ kubectl.sh get events
LASTSEEN   FIRSTSEEN   COUNT     NAME            KIND      SUBOBJECT                         TYPE      REASON
0s         0s          1         dapi-test-pod   Pod                                         Warning   InvalidEnvironmentVariableNames   kubelet, 127.0.0.1      Keys [1badkey, 2alsobad] from the EnvFrom configMap default/myconfig were skipped since they are considered invalid environment variable names.

ConfigMap驻留到namespace里面。他们可以被引用和pod相同的namespace。ConfigMap配额大小是一个计划功能。

kubelet仅支持pod使用ConfigMap获取从API server。这包括使用kubectl创建每个pod,或者间接通过副本控制器。

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 123,242评论 18 134
  • Kubernetes |Pod 深入理解与实践 这篇文章参考自《Kubernete权威指南》,对其中的相关章节做...
    爱喝咖啡的土拨鼠阅读 33,545评论 2 15
  • 现场 | 工具控秦皇岛纸版画病友会 2016-06-15FOD工具控FOD工具控 FOD工具控病友会016回顾 秦...
    FOD生活升级阅读 103评论 0 1
  • 姓名:易平香 企业名称:东莞耀升机电有限公司 组别:AT感谢组/272期努力一组 【日精进打卡第67天】 【知~学...
    shine1yi阅读 90评论 0 0
  • 今天有个小宝贝过生日,五岁了,伴随着他的出生成长,我经历了前半生最复杂最精彩绝伦的六年。
    MISS言甚阅读 66评论 0 0