• 我们可以直接在打包镜像的时候写在应用配置文件里面,但是这种方式的坏处显而易见而且非常明显。


  • 我们可以在配置文件里面通过 env 环境变量传入,但是这样的话我们要修改env就必须去修改 yaml 文件,而且需要重启所有的 Container 才行。


  • 我们可以在应用启动的时候去数据库或者某个特定的地方拿,没问题!但是第一,实现起来麻烦;第二,如果配置的地方变了怎么办?


漫画:Kubernetes中的ConfigMap和Secret_java

而且,还有一个问题就是,如果说我的一个配置,是要多个应用一起使用的,以上除了第三种方案,都没办法进行配置的共享,就是说我如果要改配置的话,那得一个一个手动改。假如我们有100个应用,就得改100份配置,以此类推……


那就没有其他方法解决这些问题嘛?

漫画:Kubernetes中的ConfigMap和Secret_java_02

漫画:Kubernetes中的ConfigMap和Secret_java_03

漫画:Kubernetes中的ConfigMap和Secret_java_04

漫画:Kubernetes中的ConfigMap和Secret_java_05

漫画:Kubernetes中的ConfigMap和Secret_java_06


| ConfigMap


ConfigMap让我们能够从容器镜像中把配置的详细信息给解耦出来。通过ConfigMap 我们能够把配置以 key-value 对的形式传递到Container 或者别的系统组件(比如Controller)里面。


如何创建ConfigMap?


我们可以通过两种方式来创建 ConfigMap:

From Literal Values和From Configuration File;


From Literal Values 方法:

我们可以用 kubectl create 来创建一个 ConfigMap,然后通过 kubectl get 来获取:


# Create the ConfigMap$ kubectl create configmap my-config --from-literal=key1=value1 --from-literal=key2=value2configmap "my-config" created # Get the ConfigMap Details for my-config$ kubectl get configmaps my-config -o yamlapiVersion: v1data:  key1: value1  key2: value2kind: ConfigMapmetadata:  creationTimestamp: 2017-05-31T07:21:55Z  name: my-config  namespace: default  resourceVersion: "241345"  selfLink: /api/v1/namespaces/default/configmaps/my-config  uid: d35f0a3d-45d1-11e7-9e62-080027a46057


-o yaml 的作用是通过 yaml 的形式来返回我们所要求的配置信息。


From Configuration File 方法:

除了上面的方式,我们还可以直接通过配置文件来创建(好吧,虽然我感觉是同一种,只不过是放到文件里面了而已……),首先,我们得有一个配置文件,假设名字叫做 myconfigmap.yaml:


apiVersion: v1kind: ConfigMapmetadata:  name: customer1data:  TEXT1: Customer1_Company  TEXT2: Welcomes You  COMPANY: Customer1 Company Technology Pct. Ltd.


然后,我们可以通过 kubectl create -f 来创建:


$ kubectl create -f myconfigmap.yamlconfigmap "customer1" created




同时也有两种使用方法,通过 env 和通过 Volume。


通过 env 方法:

我们可以设置 env从ConfigMap 读取:


.... containers:      - name: rsvp-app        image: teamcloudyuga/rsvpapp        env:        - name: MONGODB_HOST          value: mongodb        - name: TEXT1          valueFrom:            configMapKeyRef:              name: customer1              key: TEXT1        - name: TEXT2          valueFrom:            configMapKeyRef:              name: customer1              key: TEXT2        - name: COMPANY          valueFrom:            configMapKeyRef:              name: customer1              key: COMPANY....


这样,我们的 Container 就可以读取到 ConfigMap 里面存储的信息了。

不过一般情况下,我个人推荐使用另一种方式:


通过Volume

这种方式我比较推荐,因为随着 ConfigMap 被修改(比如你想要更新一些设置),Container 里面对应的文件内容也会被修改,这样可以不用重启Container 就让应用能够得到最新的配置信息。


这个内容需要一些 Volume 相关的知识,在此不做更多讲解,大家可以去参考官方文档。

https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap/#adding-configmap-data-to-a-volume


漫画:Kubernetes中的ConfigMap和Secret_java_07


通过上面的部分,我们可以看到 ConfigMap 是用来做一些配置信息。


漫画:Kubernetes中的ConfigMap和Secret_java_06


| 就是我们介绍的 Secret 方法:


看到这个名字大家应该就明白了吧,Kubernetes 提供了 Secret 来存储相关的信息。具体为什么要存在 Secret 里面,Secret 和 ConfigMap 有什么区别,后面会讲到。


先介绍如何创建和使用 Secret。


创建Secret

我们可以通过 kubectl create secret 来通过一个文件创建一个 Secret,如下:


# Create a file with password$ echo 'mysqlpassword' > password.txt# Make sure there is no trailing newline in the file, after our password. # To remove any newline, we can use the tr command:$ tr -Ccsu '\n' < password.txt > .strippedpassword.txt && mv .strippedpassword.txt password.txt# Create the Secret $ kubectl create secret generic my-password --from-file=password.txtsecret "my-password" created



我们也可以手动创建一个 Secret,不过要注意,所有的 Secret 的 data 都要以 base64 进行加密:


$ cat password.txt | base64bXlzcWxwYXN3b3JkCg==# and then use it in the configuration file:apiVersion: v1kind: Secretmetadata:  name: my-passwordtype: Opaquedata:  password: bXlzcWxwYXN3b3JkCg==


使用Secret


获取 Secret

我们可以通过 get 和 describe 来获取 Secret,不过我们发现,kubectl 并没有向我们返回 Secret 具体的内容:


$ kubectl get secret my-passwordNAME          TYPE     DATA   AGE my-password   Opaque   1      8m$ kubectl describe secret my-passwordName:          my-passwordNamespace:     defaultLabels:        <none>Annotations:   <none>Type  OpaqueData====password.txt:  13 bytes


在 Pod 里面使用

和 ConfigMap 一样,我们可以通过设置成 env 或者挂载成 volume 来使容器可以使用我们的 Secret。


具体格式如下:


.....         spec:      containers:      - image: wordpress:4.7.3-apache        name: wordpress        env:        - name: WORDPRESS_DB_HOST          value: wordpress-mysql        - name: WORDPRESS_DB_PASSWORD          valueFrom:            secretKeyRef:              name: my-password              key: password.txt.....


关于如何在 Volume 中使用的还是需要自行查询文档学习。


漫画:Kubernetes中的ConfigMap和Secret_java_03


漫画:Kubernetes中的ConfigMap和Secret_java_10

其实目前 Secret 的实现,就是 ConfigMap 把 value 用 base64 encode了一下,所以,其实不存在任何安全性,只要 decode 一下就能出现原来结果,相当于明文存储。


base64 这玩意儿都不能叫做加密,只能叫做编码,所以我们都不说 encrypt,而是 encode 和 decode。


当然,Kubernetes 社区有在计划对 Secret 进行下一步的安全性增强,当然这是后话了,截止目前为止,Secret 基本和 ConfigMap一样是明文存储。


好了,大家理解了 ConfigMap 和 Secret 了嘛?由于时间关系,更多内容下节课在讲。