Secret and ConfigMap for Kubernetes Data Persistence

Keywords: Kubernetes vim encoding Docker

ConfigMap and Secret are two special types of storage volumes in Kubernetes. ConfigMap is a resource object mainly used to provide configuration data to customize program behavior. However, some sensitive configuration information, such as user name, password, key and so on, are usually configured by a resource object such as Secret, which stores the corresponding configuration information in the object and then invests it in Pod.The source mounts it as a storage volume and gets the corresponding configuration to decouple the configuration from the mirror file.

Secret Resource Object

1) Overview of Secret

Secret resource objects store data as key-value pairs. Secret for Pod resources accesses data as environment variables or storage volumes, which solves the configuration problem of sensitive data such as passwords, token s, keys, etc. without exposing these sensitive data to mirrors or Pod spec fields.In addition, Secret objects are stored and printed in Base64-encoded strings, so users need to provide data in that type of encoding format when creating Secret objects.When accessed in a container as an environment variable or a storage volume, it is automatically decoded in plain text.It is important to note that if the Secret object is stored in the etcd in an unencrypted format on the Master node, strict control over the management and permissions of the etcd is required.

2) Types of Secret resources

Secret has four types:
1) Service Account: Used to access the Kubernetes API, which is automatically created by Kubernetes and automatically mounted in Pod's/run/secrets/kubernetes.io/service account directory;
2) Secret in Opaque:base64 encoding format, used to store passwords, keys, information, certificates, etc. The type identifier is generic;
3) kubernetes.io/dockerconfigjson: used to store authentication information for private docker registries, identified as docker-registry;
4) kubernetes.io/tls: used to store certificates and private key files for the SSL communication mode, with the command creation type identified as tls;

3) How to create Secret

Assume the data stored is:
username: root
password: 123.com
The following storage methods store this information!

1) How to use--from-literal

[root@master ~]# kubectl create secret generic mysecret01 --from-literal=username=root --from-literal=password=123.com
#Create a secret resource object named mysecret01 encrypted by generic (generic, generic)
#Note: Only one message per entry can be saved in this way
[root@master ~]# kubectl get secrets mysecret01 
NAME         TYPE     DATA   AGE
mysecret01   Opaque   2      25s
[root@master ~]# kubectl describe secrets mysecret01     #View the details of this resource
Name:         mysecret01
Namespace:    default
Labels:       <none>
Annotations:  <none>

Type:  Opaque                         #Opaque, invisible

Data
====
password:  7 bytes                     #Only the name of the key can be viewed, not the value corresponding to the key
username:  4 bytes
[root@master ~]# kubectl get secrets mysecret01 -o yaml            
#Display this resource as a yaml file
apiVersion: v1
data:
  password: MTIzLmNvbQ==                       #The keys correspond to values that are garbled and encrypted using the base64 encoding format
  username: cm9vdA==
kind: Secret
metadata:
  creationTimestamp: "2020-02-14T10:08:21Z"
  name: mysecret01
  namespace: default
  resourceVersion: "2474"
  selfLink: /api/v1/namespaces/default/secrets/mysecret01
  uid: 1aee0635-7bfb-4e8a-a21e-be993e534156
type: Opaque
[root@master ~]# echo -n cm9vdAo= | base64 --d              #The result of decoding the scramble code
root
[root@master ~]# echo -n MTIzLmNvbQ== | base64 --d
123.com

2) How to use--from-file

This way is similar to the first one, which may seem a little more troublesome!

[root@master ~]# echo root > username
[root@master ~]# echo 123.com > password
#You need to write the stored key-value pairs to the file first and only one value per file
[root@master ~]# kubectl create secret generic mysecret02 --from-file=username --from-file=password
[root@master ~]# rm -rf username password              
#Even after the file is deleted, the value corresponding to the resource key still exists
[root@master ~]# kubectl get secrets mysecret02
NAME         TYPE     DATA   AGE
mysecret02   Opaque   2      58s
[root@master ~]# kubectl describe secrets mysecret02
Name:         mysecret02
Namespace:    default
Labels:       <none>
Annotations:  <none>

Type:  Opaque

Data
====
password:  8 bytes
username:  5 bytes

3) by--from-env-file (environment variable)

This method can write multiple key-value pairs in the same file, which is recommended!

[root@master ~]# tee  env.txt <<EOF            #Write multiple key values to the same file that need to be stored
 username=root
 password=123.com
 EOF
[root@master ~]# kubectl create secret generic mysecret03 --from-env-file=env.txt
secret/mysecret03 created
[root@master ~]# kubectl get secrets mysecret03
NAME         TYPE     DATA   AGE
mysecret03   Opaque   2      19s
[root@master ~]# kubectl describe secrets mysecret03
Name:         mysecret03
Namespace:    default
Labels:       <none>
Annotations:  <none>

Type:  Opaque

Data
====
username:  4 bytes
password:  7 bytes

4) via yaml file

 [root@master ~]# echo root | base64                  #The value corresponding to the key needs to be encrypted
cm9vdAo=
[root@master ~]# echo 123.com | base64
MTIzLmNvbQo=
[root@master ~]# vim secret.yaml  
apiVersion: v1
kind: Secret
metadata:
  name: mysecret04
data:
  username: cm9vdAo=                            #Write encrypted values to configuration file
  password: MTIzLmNvbQo=
[root@master ~]# kubectl apply -f secret.yaml
[root@master ~]# kubectl get secrets mysecret04
NAME         TYPE     DATA   AGE
mysecret04   Opaque   2      118s
[root@master ~]# kubectl describe secrets mysecret04
Name:         mysecret04
Namespace:    default
Labels:       <none>
Annotations:  
Type:         Opaque

Data
====
password:  8 bytes
username:  5 bytes

4) How Secret resources are used

1) Use as volume mount

[root@master ~]# vim secret-pod01.yaml
apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
  - name: mypod
    image: busybox
    args:
      - /bin/sh
      - -c
      - sleep 3000000                  #The above fields simply create a container
    volumeMounts:
    - name: secret-test
      mountPath: "/etc/secret-test"                  #Specify directories in containers
      readOnly: true                                         #Mount as read-only
  volumes:
  - name: secret-test
    secret:
      secretName: mysecret04          #Specifies the name of an existing secret resource
[root@master ~]# kubectl apply -f secret-pod01.yaml 
[root@master ~]# kubectl exec -it mypod /bin/sh        #Enter Container
/ # cat -n /etc/secret-test/username /etc/secret-test/password     #See if there is data in the corresponding directory
     1  root
     2  123.com
#And it's the decrypted data         
/ # echo 12324235532 > /etc/secret-test/username 
/bin/sh: can't create /etc/secret-test/username: Read-only file system

Now we can verify that if you change the contents of secret04 at this time, will the contents of the corresponding mount directory in the container change?

[root@master ~]# echo zhangsan | base64
emhhbmdzYW4K
[root@master ~]# echo 123456 | base64
MTIzNDU2Cg==
[root@master ~]# vim secret.yaml 
apiVersion: v1
kind: Secret
metadata:
  name: mysecret04
data:
  username: emhhbmdzYW4K
  password: MTIzNDU2Cg==
[root@master ~]# kubectl apply -f secret.yaml 
[root@master ~]# kubectl exec -it mypod /bin/sh
/ # cat -n /etc/secret-test/username /etc/secret-test/password 
     1  zhangsan
     2  123456
#Look again at the data in the container and see that it has changed!    

Note: If the secert stored value is called by volume mounting, the value in the container will change with the secert stored value!

2) Run as an environment variable

[root@master ~]# vim secret-pod02.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: mypod2
spec:
  containers:
  - name: mypod
    image: busybox
    args:
      - /bin/sh
      - -c
      - sleep 3000000
    env:                                   #Setting environment variables
      - name: SECRET_USERNAME               #Refers to the name of a variable in a container
        valueFrom:
          secretKeyRef:
            name: mysecret02                 #mysecret02 was called 
            key: username                       #Corresponds to the value of username in mysecret02
      - name: SECRET_PASSWORD     #Ditto
        valueFrom:
          secretKeyRef:
            name: mysecret02
            key: password
[root@master ~]# kubectl apply -f secret-pod02.yaml
[root@master ~]# kubectl exec -it mypod2 /bin/sh
/ # echo ${SECRET_USERNAME}
root
/ # echo ${SECRET_PASSWORD}
123.com
#After entering the container, look at the value of the variable

Note: If the secert stored value is called as a variable, the value of the variable in the container will not change with the secert stored value unless the pod is regenerated.

ConfigMap Resource Object

1) Overview of ConfigMap

We know that in almost all application development, configuration file changes are involved, for example, in web applications, connections to databases, caches, even queues, and so on.One of our applications starts with writing the first line of code and goes through development, test, pre-release environments to the final online environment.Each environment defines its own individual configurations.If we don't manage these profiles well, your operations and maintenance will become extremely cumbersome.For this reason, some large companies in the industry have developed their own set of configuration management centers, such as 360 Qcon, Baidu disconf, etc.kubernetes also provides its own set of scenarios, ConfigMap.kubernetes uses ConfigMap to manage the configurations applied in containers.

2) How ConfigMap was created

In fact, configMap and secert resource objects are created exactly the same way!

1) By--from-literal

[root@master ~]# kubectl create configmap configmap01 --from-literal=username=root --from-literal=password=123.com
#Create a configmap resource named configmap01
[root@master ~]# kubectl describe configmaps configmap01 
Name:         configmap01
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data      #You can clearly see the value of the stored key, so it is generally used to store profile information
====
password:
----
123.com
username:
----
root
Events:  <none>

2) via--from-file

[root@master ~]# echo root > username
[root@master ~]# echo 123.com > password
[root@master ~]# kubectl create configmap configmap02 --from-file=username --from-file=password
configmap/configmap02 created
[root@master ~]# kubectl describe configmaps configmap02
Name:         configmap02
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
password:
----
123.com

username:
----
root

Events:  <none>

3) via--from-env-file

[root@master ~]# tee 123.txt <<EOF
> username=root
> password=123.com
> EOF
[root@master ~]# kubectl create configmap configmap03 --from-env-file=123.txt
configmap/configmap03 created
[root@master ~]# kubectl describe configmaps configmap03
Name:         configmap03
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
username:
----
root
password:
----
123.com
Events:  <none>

4) via yaml file

[root@master ~]# vim configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: configmap04
data: 
  username: root                       #When configmap is created using a yaml file, the value corresponding to the key does not need to be encrypted beforehand
  password: 123.com                     #If the corresponding value is a number, a single quotation mark is required to cause it
[root@master ~]# kubectl apply -f configmap.yaml
[root@master ~]# kubectl describe configmaps configmap04
Name:         configmap04
Namespace:    default
Labels:       <none>
Annotations:  kubectl.kubernetes.io/last-applied-configuration:
                {"apiVersion":"v1","data":{"password":"123.com","username":"root"},"kind":"ConfigMap","metadata":{"annotations":{},"name":"configmap04","n...

Data
====
password:
----
123.com
username:
----
root
Events:  <none>

3) How ConfigMap is used

1) Use as volume mount

[root@master ~]# vim configmap-pod01.yaml
apiVersion: v1
kind: Pod
metadata:
  name: configmap-pod01
spec:
  containers:
  - name: configmap-pod01
    image: busybox
    args:
      - /bin/sh
      - -c
      - sleep 3000000
    volumeMounts:
    - name: configmap-test
      mountPath: "/etc/configmap-test"
      readOnly: true
  volumes:
  - name: configmap-test
    configMap:
      name: configmap01
[root@master ~]# kubectl apply -f configmap-pod01.yaml
[root@master ~]# kubectl exec -it configmap-pod01 /bin/sh
/ # cat -n /etc/configmap-test/username /etc/configmap-test/password
     1  root
     2  123.com

ConfigMap resources are mounted in volume, which is almost the same way Secret resources are mounted in volume, and changes with the source data!

2) Run as an environment variable

[root@master ~]# vim configmap-pod02.yaml
apiVersion: v1
kind: Pod
metadata:
  name: configmap-pod02
spec:
  containers:
  - name: configmap-pod02
    image: busybox
    args:
      - /bin/sh
      - -c
      - sleep 3000000
    env:
      - name: CONFIGMAP_USERNAME
        valueFrom:
          configMapKeyRef:
            name: configmap04
            key: username                   #Called is the value of username in configmap04
      - name: CONFIGMAP_PASSWORD
        valueFrom:
          configMapKeyRef:
            name: configmap04
            key: password
[root@master ~]# kubectl apply -f configmap-pod02.yaml                      
[root@master ~]# kubectl exec -it configmap-pod02 /bin/sh
/ # echo ${CONFIGMAP_USERNAME}
root
/ # echo ${CONFIGMAP_PASSWORD}
123.com

ConfigMap resources use environment variables in almost the same way Secret resources use variable variables, and do not change with the source data!

3. The similarities and differences between Secret and ConfigMap

1) Identity

They are used to hold lightweight information and can be mounted by other resource objects (Deployment, RC, RS, POd).
The two methods of creating resource objects (four) and referencing them (two) are the same and are stored as key-value pairs.

2) Differences

Secret is used to store sensitive information, while configMap is used to store less important data, as shown by the fact that when we execute the "kubectl describe...." command, a resource object of this type, Secret, does not see its specific information, while a configMap can see the specific content it saves.

3) Notes

1) Secret, ConfigMap must be created before Pod;
2) Only pod s within the same namespace as the current Secret and ConfigMap can use this Secret and ConfigMap; in other words, Secret and ConfigMap cannot be called across namespaces.

__________161

Posted by mattlatos on Fri, 14 Feb 2020 13:11:59 -0800