参考资料:从Docker到Kubernetes进阶-阳明

一、ConfigMap

1. ConfigMap简介

在我们部署一些应用服务时,通常都会有一些配置文件,而在k8s中,我们如果在将这些配置文件写到代码应用程序中,需要修改配置的话,我们还得重新去修改代码,重新制作一个镜像,这样操作起来很麻烦。

还好kubernetes为我们提供了一个ConfigMap资源对象,它的主要作用就是为了让镜像和配置文件解耦,以便实现镜像的可移植性和可复用性,提供了向容器中注入配置信息的能力,不仅可以用来保存单个属性,还可以用来保存整个配置文件,我们只需要将配置文件以ConfigMap的方式挂载到应用Pod中,这样我们在更新配置信息的时候只需要更新这个ConfigMap对象即可。

ConfigMap使用场景:

  • 通过环境变量的方式,直接传递给pod
  • 通过在pod的命令行下运行的方式(启动命令中)
  • 作为volume的方式挂载到pod内

2. 创建ConfigMap

2.1 通过目录创建

$ ls /app/web/configmap/kubectl/
ftp.properties
jdbc.properties

$ cat /app/web/configmap/kubectl/ftp.properties
FTP_ADDRESS=192.168.133.11
FTP_PORT=21
FTP_USERNAME=ftpuser
FTP_PASSWORD=ftpuser
FTP_BASEPATH=/
IMAGE_BASE_URL=http://test.test.com/image

$ cat /app/web/configmap/kubectl/jdbc.properties
#database configuration
connection.url=jdbc:mysql://10.1.133.111:3306/web
connection.username=testdata
#connection.password=abcde
connection.password=SN9+koFJWHmf

创建Configmap对象

$ kubectl create configmap web-config --from-file=/app/web/configmap/kubectl

--from-file:指定目录路径,该目录下的所有文件都会被用在ConfigMap里面创建一个键值对,键的名字就是文件名,值就是文件的内容。
查看Configmap信息

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

Data
====
ftp.properties:
----
FTP_ADDRESS=192.168.133.11
FTP_PORT=21
FTP_USERNAME=ftpuser
FTP_PASSWORD=ftpuser
FTP_BASEPATH=/
IMAGE_BASE_URL=http://test.test.com/image

jdbc.properties:
----
#database configuration
connection.url=jdbc:mysql://10.1.133.111:3306/web
connection.username=testdata
#connection.password=abcde
connection.password=SN9+koFJWHmf

Events:  <none>

如果配置文件信息较多的话,describe的输出信息会显示不全,我们可以使用以下命令来查看完整内容:

$ kubectl get configmaps web-config -o yaml
apiVersion: v1
data:
  ftp.properties: |
    FTP_ADDRESS=192.168.133.11
    FTP_PORT=21
    FTP_USERNAME=ftpuser
    FTP_PASSWORD=ftpuser
    FTP_BASEPATH=/
    IMAGE_BASE_URL=http://test.test.com/image
  jdbc.properties: |
    #database configuration
    connection.url=jdbc:mysql://10.1.133.111:3306/web
    connection.username=testdata
    #connection.password=abcde
    connection.password=SN9+koFJWHmf  
kind: ConfigMap
metadata:
  creationTimestamp: 2020-02-18T18:34:05Z
  name: web-config
  namespace: default
  resourceVersion: "407"
  selfLink: /api/v1/namespaces/default/configmaps/web-config
  uid: 680944725-d62e-10e5-8cd0-68f123db1985

2.2 使用文件创建

$ kubectl create configmap web-config-2 --from-file=/app/web/configmap/kubectl/ftp.properties 
$ kubectl get configmaps web-config-2  -o yaml
apiVersion: v1
data:
  ftp.properties: |+
    FTP_ADDRESS=192.168.133.11
    FTP_PORT=21
    FTP_USERNAME=ftpuser
    FTP_PASSWORD=ftpuser
    FTP_BASEPATH=/
    IMAGE_BASE_URL=http://test.test.com/image

kind: ConfigMap
metadata:
  creationTimestamp: "2020-05-22T16:36:39Z"
  name: web-config-2
  namespace: default
  resourceVersion: "33386795"
  selfLink: /api/v1/namespaces/default/configmaps/web-config-2
  uid: cffef22c-be55-4de3-8835-79195de8ec7e

--from-file: 可以多次使用,指定多个文件

2.3 使用命令行创建

$ kubectl create configmap web-config-3 --from-literal=FTP_ADDRESS=192.168.133.11  --from-literal=FTP_PORT=21  --from-literal=FTP_USERNAME=ftpuser   --from-literal=FTP_PASSWORD=ftpuser    --from-literal=FTP_BASEPATH=/  --from-literal=IMAGE_BASE_URL=http://test.test.com/image
configmap/web-config-3 created
$ kubectl get configmap web-config-3 -o yaml
apiVersion: v1
data:
  FTP_ADDRESS: 192.168.133.11
  FTP_BASEPATH: /
  FTP_PASSWORD: ftpuser
  FTP_PORT: "21"
  FTP_USERNAME: ftpuser
  IMAGE_BASE_URL: http://test.test.com/image
kind: ConfigMap
metadata:
  creationTimestamp: "2020-05-22T16:46:50Z"
  name: web-config-3
  namespace: default
  resourceVersion: "33387937"
  selfLink: /api/v1/namespaces/default/configmaps/web-config-3
  uid: d69afbaf-0ac4-4405-a4ea-351ad613bdb4

--from-literal:可以多次使用,指定多个值

3. 使用Configmp

3.1 使用ConfigMap来填充环境变量

编写Pod资源文件,使用上面名为web-config-3的configmap

apiVersion: v1
kind: Pod
metadata:
  name: testweb-pod
spec:
  containers:
    - name: testweb
      image: busybox
      command: [ "/bin/sh", "-c", "env" ]
      env:
        - name: FTP_ADDRESS
          valueFrom:
            configMapKeyRef:
              name: web-config-3
              key: FTP_ADDRESS  #configmap的key值
        - name: FTP_PORT
          valueFrom:
            configMapKeyRef:
              name: web-config-3
              key: FTP_PORT
      envFrom:
        - configMapRef:   
            name: web-config-3  #使用名为web-config-3的configmap对象

创建Pod并查看日志

$ kubectl  logs -f testweb-pod
--------
FTP_ADDRESS=192.168.133.11
IDLE_LLAMA_NGINX_INGRESS_DEFAULT_BACKEND_PORT_80_TCP=tcp://10.98.12.71:80
PLUNDERING_MARMOT_NGINX_INGRESS_CONTROLLER_PORT_80_TCP_ADDR=10.108.129.64
FTP_PORT=21
MY_RELEASE_TOMCAT_PORT_80_TCP_ADDR=10.101.28.152
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1

FTP_USERNAME=ftpuser
EXACERBATED_HEDGEHOG_NGINX_INGRESS_DEFAULT_BACKEND_SERVICE_PORT=80
PLUNDERING_MARMOT_NGINX_INGRESS_CONTROLLER_PORT_80_TCP=tcp://10.108.129.64:80
PLUNDERING_MARMOT_NGINX_INGRESS_CONTROLLER_PORT_443_TCP_ADDR=10.108.129.64
MYDB_MYSQL_SERVICE_PORT_MYSQL=3306
--------

3.2 使用ConfigMap设置命令行参数

apiVersion: v1
kind: Pod
metadata:
  name: testweb2-pod
spec:
  containers:
    - name: testweb2
      image: busybox
      command: [ "/bin/sh", "-c", "echo $(FTP_ADDRESS) $(FTP_PORT)" ]
      env:
        - name: FTP_ADDRESS
          valueFrom:
            configMapKeyRef:
              name: web-config-3
              key: FTP_ADDRESS 
        - name: FTP_PORT
          valueFrom:
            configMapKeyRef:
              name: web-config-3
              key: FTP_PORT

查看Pod的输出信息

kubectl  logs -f testweb2-pod
192.168.133.11 21

3.3 通过数据卷使用ConfigMap

apiVersion: v1
kind: Pod
metadata:
  name: testweb3-pod
spec:
  volumes:
    - name: config-volume
      configMap:
        name: web-config-2
  containers:
    - name: testweb3
      image: busybox
      command: [ "/bin/sh", "-c", "cat /etc/config/ftp.properties" ]
      volumeMounts:
      - name: config-volume
        mountPath: /etc/config

查看pod输出日志

$ kubectl  logs -f testweb3-pod
FTP_ADDRESS=192.168.133.11
FTP_PORT=21
FTP_USERNAME=ftpuser
FTP_PASSWORD=ftpuser
FTP_BASEPATH=/
IMAGE_BASE_URL=http://test.test.com/image

注意,当 ConfigMap 以数据卷的形式挂载进 Pod 的时,这时更新 ConfigMap(或删掉重建ConfigMap),Pod 内挂载的配置信息会热更新。这时可以增加一些监测配置文件变更的脚本,然后重新加载对应服务就可以实现应用的热更新。

二、Secret

1. Secret简介

一般情况下ConfigMap 是用来存储一些非安全的配置信息,因为ConfigMap是明文存储的,面对敏感信息时,我们就需要使用k8s的另一个对象Secret。

Secret用来保存敏感信息,例如密码、OAuth 令牌和 ssh key 等等,将这些信息放在 Secret 中比放在 Pod 的定义中或者 Docker 镜像中要更加安全和灵活。

Secret 主要使用的有以下三种类型:

  • Opaque:base64 编码格式的 Secret,用来存储密码、密钥等;但数据也可以通过base64 –decode解码得到原始数据,所有加密性很弱。
  • kubernetes.io/dockerconfigjson:用来存储私有docker registry的认证信息。
  • kubernetes.io/service-account-token:用于被 ServiceAccount ServiceAccount 创建时 Kubernetes 会默认创建一个对应的 Secret 对象。Pod 如果使用了 ServiceAccount,对应的 Secret 会自动挂载到 Pod 目录 /run/secrets/kubernetes.io/serviceaccount 中。
    bootstrap.kubernetes.io/token:用于节点接入集群的校验的 Secret

Secret对比ConfigMap

相同点

  • key/value的形式
  • 属于某个特定的命名空间
  • 可以导出到环境变量
  • 可以通过目录/文件形式挂载
  • 通过 volume 挂载的配置信息均可热更新

不同点

  • Secret 可以被 ServerAccount 关联
  • Secret 可以存储 docker register 的鉴权信息,用在 ImagePullSecret 参数中,用于拉取私有仓库的镜像
  • Secret 支持 Base64 加密
  • Secret 分为 kubernetes.io/service-account-token、kubernetes.io/dockerconfigjson、Opaque 三种类型,而 Configmap 不区分类型

2. Opaque Secret

2.1 手动创建Secret

$ echo -n "admin" | base64
YWRtaW4=
$ echo -n "adminpass" | base64
YWRtaW5wYXNz

Opaque 类型的数据是一个 map 类型,要求 value 必须是 base64 编码格式。

使用上面加密的编码编写Yaml

apiVersion: v1
kind: Secret
metadata:
  name: mysecret
type: Opaque
data:
  username: YWRtaW4=
  password: YWRtaW5wYXNz

创建Secret

$ kubectl  create -f secret-demo.yaml 
secret/mysecret created
$ kubectl  get  secret
NAME                                             TYPE                                  DATA   AGE
default-token-g7sqf                              kubernetes.io/service-account-token   3      219d
exacerbated-hedgehog-nginx-ingress-token-zrwpn   kubernetes.io/service-account-token   3      174d
idle-llama-nginx-ingress-token-r2j5k             kubernetes.io/service-account-token   3      174d
istio.default                                    istio.io/key-and-cert                 3      185d
mydb-mysql                                       Opaque                                2      181d
mysecret                                         Opaque                                2      6m13s

查看Secret信息

kubectl describe secret mysecret
Name:         mysecret
Namespace:    default
Labels:       <none>
Annotations:  <none>

Type:  Opaque

Data
====
password:  9 bytes
username:  5 bytes

查看Secret详细信息

apiVersion: v1
data:
  password: YWRtaW5wYXNz
  username: YWRtaW4=
kind: Secret
metadata:
  creationTimestamp: "2020-05-25T14:50:01Z"
  name: mysecret
  namespace: default
  resourceVersion: "33864313"
  selfLink: /api/v1/namespaces/default/secrets/mysecret
  uid: cf560ef9-eb67-4b3d-ac17-ed930e6799ce
type: Opaque

2.2 使用Secret作为环境变量

编写Yaml

apiVersion: v1
kind: Pod
metadata:
  name: secret1-pod
spec:
  containers:
  - name: secret1
    image: busybox
    command: [ "/bin/sh", "-c", "env" ]
    env:
    - name: USERNAME
      valueFrom:
        secretKeyRef:
          name: mysecret
          key: username
    - name: PASSWORD
      valueFrom:
        secretKeyRef:
          name: mysecret
          key: password

secretKeyRef :和前面Configmap定义相同,获取Secret的key值

创建Pod后查看日志输出

$  kubectl  create -f testpod.yaml 
pod/secret1-pod created
$ kubectl   logs -f secret1-pod | grep  USERNAME
USERNAME=admin
$ kubectl   logs -f secret1-pod | grep  PASSWORD
PASSWORD=adminpass

2.3 通过数据卷使用Secret

将Sercret挂载到Pod的/etc/secret路径下

apiVersion: v1
kind: Pod
metadata:
  name: secret2-pod
spec:
  containers:
  - name: secret2
    image: busybox
    command: ["/bin/sh", "-c", "ls /etc/secrets"]
    volumeMounts:
    - name: secrets
      mountPath: /etc/secrets
  volumes:
  - name: secrets
    secret:
     secretName: mysecret

创建Pod并查看日志输出

$ kubectl  create -f testpod2.yaml 
 pod/secret2-pod created
$ kubectl  logs -f secret2-pod
password
username

可以看到 Secret 把两个 key 以两个对应的文件挂载到了Pod中/etc/secret路径下,如果挂载到指定的文件上面,可以使用上面Configmap的数据卷挂载方式。

3. kubernetes.io/dockerconfigjson

3.1 创建Secret对象

这个类型的Secret对象用来创建建镜像仓库认证信息,如下:

$ kubectl create secret docker-registry harbor --docker-server=http://192.168.166.229  --docker-username=admin   --docker-password=harbor123 --docker-email=test@163.com
secret/harbor created

查看创建的secret,注意Sercret对应的TYPE类型

$ kubectl get secret
NAME                                             TYPE                                  DATA   AGE
default-token-g7sqf                              kubernetes.io/service-account-token   3      233d
exacerbated-hedgehog-nginx-ingress-token-zrwpn   kubernetes.io/service-account-token   3      188d
harbor                                           kubernetes.io/dockerconfigjson        1      66s

3.2 查看Secret信息

$ kubectl get secret  harbor  -o yaml
apiVersion: v1
data:
  .dockerconfigjson: eyJhdXRocyI6eyJodHRwOi8vMTkyLjE2OC4xNjYuMjI5Ijp7InVzZXJuYW1lIjoiYWRtaW4iLCJwYXNzd29yZCI6IkhhcmJvckAxYW4iLCJlbWFpbCI6InRlc3RAMTYzLmNvbSIsImF1dGgiOiJZV1J0YVc0NlNHRnlZbTl5UURGaGJnPT0ifX19
kind: Secret
metadata:
  creationTimestamp: "2020-06-08T14:20:41Z"
  name: harbor
  namespace: default
  resourceVersion: "36160653"
  selfLink: /api/v1/namespaces/default/secrets/harbor
  uid: 69f79c70-245a-4a91-b846-878a026e7ba6
type: kubernetes.io/dockerconfigjson

可以看到dockerconfigjson信息已经被加密了,我们可以使用base64解码查看

$ echo eyJhdXRocyI6eyJodHRwOi8vMTkyLjE2OC4xNjYuMjI5Ijp7InVzZXJuYW1lIjoiYWRtaW4iLCJwYXNzd29yZCI6IkhhcmJvckAxYW4iLCJlbWFpbCI6InRlc3RAMTYzLmNvbSIsImF1dGgiOiJZV1J0YVc0NlNHRnlZbTl5UURGaGJnPT0ifX19  |  base64 -d 
{"auths":{"http://192.168.166.229":{"username":"admin","password":"harbor123 ","email":"test@163.com","auth":"YWRtaW46SGFyYm9yQDFhbg=="}}}

3.3 Pod使用Secret对象

使用名为harbor的Secret拉取镜像:

apiVersion: v1
kind: Pod
metadata:
  name: harbortest
spec:
  containers:
  - name: harbor
    image: 192.168.166.229/test/node-exporter:latest
  imagePullSecrets:
  - name: harbor

查看Pod状态

$ kubectl get pod 
NAME                                                              READY   STATUS             RESTARTS   AGE
harbortest                                                        1/1     Running            0          2m26s

查看Pod创建过程,镜像是否符合定义

$ kubectl  describe  pod  harbortest   
Events:
 Type    Reason     Age    From                 Message
 ----    ------     ----   ----                 -------
 Normal  Scheduled  3m2s   default-scheduler    Successfully assigned default/harbortest to kubesphere
 Normal  Pulling    2m57s  kubelet, kubesphere  Pulling image "192.168.166.229/test/node-exporter:latest"
 Normal  Pulled     2m57s  kubelet, kubesphere  Successfully pulled image "192.168.166.229/test/node-exporter:latest"
 Normal  Created    2m51s  kubelet, kubesphere  Created container harbor
 Normal  Started    2m51s  kubelet, kubesphere  Started container harbor

4.kubernetes.io/service-account-token

kubernetes.io/service-account-token类型的Secret用于被 ServiceAccount (服务账户)引用。

Service Account:为Pod中的进程和外部用户提供身份信息。ServiceAccout 创建时 Kubernetes 会默认创建对应的 Secret。

集群创建时会创建一个默认的Service Account,

$ kubectl  get sa
NAME                                 SECRETS   AGE
default                              1         233d
$ kubectl     describe sa default 
Name:                default
Namespace:           default
Labels:              <none>
Annotations:         <none>
Image pull secrets:  <none>
Mountable secrets:   default-token-g7sqf
Tokens:              default-token-g7sqf
Events:              <none>

可以看到名为“default”的Service Account对应的service-account-token
为“default-token-g7sqf”,这是因为ServiceAccout 创建时 Kubernetes 会默认创建对应的 Secret。

然后我们查看之前创建pod的详细信息

$ kubectl  describe pod web-0
.........................
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-g7sqf (ro)
Conditions:
  Type              Status
  Initialized       True 
  Ready             True 
  ContainersReady   True 
  PodScheduled      True 
Volumes:
  default-token-g7sqf:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-g7sqf
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:          <none>

可以看到创建的pod使用了名为“default-token-g7sqf”对应的service-account-token,这是因为我们使用kubectl指令请求apiserver创建的时候,使用的Service Account服务账户为default,而名为”default“ 的Service Account对应的service-account-token就是“default-token-g7sqf”。对应的 Secret 对象信息会通过 Volume 挂载到容器的/var/run/secrets/kubernetes.io/serviceaccount目录中。

关于Service Account 对象我会在下篇文章中详细解析,欢迎关注。

参考资料:从Docker到Kubernetes进阶-阳明


关注公众号回复【k8s】获取视频教程及更多资料:

在这里插入图片描述

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐