k8s security information (Secret) and configuration information (ConfigMap)

Secret

  • secret is also a resource object in k8s. It is mainly used to store lightweight sensitive information, such as database user name and password, token, authentication key, etc.

  • We can put this kind of sensitive information in the secret object. If it is a little inappropriate to expose them to the image or pod spec, it can be better controlled and used in the secret object, and reduce the risk of accidental exposure.
    Secret can use volume or environment variables to use these lightweight data.

There are three types of Secret:

Service Account: used to access the kubernetes API. It is automatically created by k8s and will be automatically mounted in the / run/secrets/kubernetes.io/serviceaccount directory of the pod.
Opaque: base64 encoded Secret, used to store passwords, keys, etc.
kubernetes.io/dockerconfigjson: used to store the authentication information of private docker registry.

Secret can be created from the command line or YAML file. Suppose we need the information stored in the secret object:

1. User name: root
2. Password: 123456

1. Create Secret

There are four ways to create a Secret:
1.1 through -- from literal

[root@master ~]# kubectl  create secret generic mysecret --from-literal=username=root --from-literal=password=123456
secret/mysecret created

//To view the created secret:

//To view the details of the secret:

Feature: each -- from literal can only correspond to one message. It's complicated.

1.2 through -- from file

[root@master ~]# echo root > username
[root@master ~]# echo 123456 > password
[root@master ~]# kubectl create secret  generic newsecret --from-file=username --from-file=password
secret/newsecret created

//To view the created secret:

[root@master ~]# kubectl  get  secrets  | grep newsecret
newsecret             Opaque                                2      64s

Features: each file also corresponds to a piece of information. Only one file can be saved in each file. In order to ensure confidentiality, it is necessary to delete the local file after import.

1.3 through -- from env file (created as a variable)

[root@master ~]# cat > env.txt <<EOF
> username=root
> password=123456
> EOF
[root@master ~]# kubectl  create secret generic env-secret --from-env-file=env.txt
secret/env-secret created

Features: multiple information can be saved in the file. Each key=value in the file env.txt corresponds to one information entry.

1.4 through yaml configuration file:
#The sensitive data in the file must be the result of base64 encoding.

[root@master ~]# echo root | base64
cm9vdAo=
[root@master ~]# echo 123456 | base64
MTIzNDU2Cg==

#Write yaml file:

apiVersion: v1
kind: Secret
metadata:
  name: secret-app
data:       #This field is used to store data. Unlike other resource objects, it has no spec field.
  username: cm9vdAo=
  password: MTIzNDU2Cg==

//To create a secert:

[root@master ~]# kubectl apply -f  secret.yaml 
secret/secret-app created

//Reverse parsing encrypted data:

[root@master ~]# echo -n  cm9vdAo= | base64 --decode
root
[root@master ~]# echo -n MTIzNDU2Cg== | base64  --decode
123456

Features: easy to save, cross host use will be very convenient.

2. How to use secret

1, Use secret as volume:
pod uses secret by volume:
The configuration file of the pod is as follows:

apiVersion: v1
kind: Pod
metadata:
  name: secret-pod
spec:
  containers:
  - name: secret-pod
    image: busybox
    args:
      - /bin/sh
      - -c
      - sleep 10; touch /tmp/healthy; sleep 3000
    volumeMounts:
    - name: foo
      mountPath: /etc/foo
      readOnly: true
  volumes:
  - name: foo
    secret:
      secretName: secret-app

(1) Define volume foo from secret (secret APP)
(2) To mount foo to the container path / etc/foo, you can specify the read-write permission as readOnly.

//Create the pod and read the secret in the container:

[root@master secret]# kubectl apply -f  secret-pod.yaml 
pod/secret-pod created
[root@master secret]# kubectl  exec  -it secret-pod /bin/sh
/ # cd /etc/foo/
/etc/foo # ls
password  username
/etc/foo # cat password 
123456
/etc/foo # cat username 
root

As you can see, k8s will create a file for each sensitive data under the specified path / etc/foo. The file name is the key of the data entry. Here are / etc/foo/username and / etc/foo/password. value is stored in the file as an inscription.

(2) We can also customize the file name for storing data. The complete configuration file is as follows:

apiVersion: v1
kind: Pod
metadata:
  name: secret-pod
spec:
  containers:
  - name: secret-pod
    image: busybox
    args:
      - /bin/sh
      - -c
      - sleep 10; touch /tmp/healthy; sleep 3000
    volumeMounts:
    - name: foo
      mountPath: /etc/foo
      readOnly: true
  volumes:
  - name: foo
    secret:
      secretName: secret-app
      items:
      - key: username:
        path: my-group/my-username
      - key: password
        path: my-group/my-password

At this time, the data is stored in / etc / foo / my group / my username and / etc / foo / my group / my password respectively.
//Verification data storage location:

[root@master secret]# kubectl  delete -f secret-pod.yaml 
pod "secret-pod" deleted
[root@master secret]# kubectl apply -f  secret-pod.yaml 
pod/secret-pod created
[root@master secret]# kubectl  exec  -it secret-pod /bin/sh
/ # cd /etc/foo/
/etc/foo # ls
my-group
/etc/foo # cd my-group/
/etc/foo/..2020_02_03_05_37_09.892671465/my-group # cat my-password 
123456
/etc/foo/..2020_02_03_05_37_09.892671465/my-group # cat my-username 
root

(3) Use secret in volume mode to support dynamic update: after the secret is updated, the data in the container will also be updated.
//We need to update password to "123456.com"

[root@master secret]# echo 123456.com | base64
MTIzNDU2LmNvbQo=

To modify the secret profile:

apiVersion: v1
kind: Secret
metadata:
  name: secret-app
data:
  username: cm9vdAo=
  password: MTIzNDU2LmNvbQo=

//Update secret:

[root@master secret]# kubectl apply -f  secret.yaml 
secret/secret-app configured

//Verify that the password was updated successfully:

[root@master secret]# kubectl  exec  -it secret-pod /bin/sh
/ # cd /etc/foo/my-group/
/etc/foo/..2020_02_03_05_40_42.995350019/my-group # cat my-password 
123456.com

Features: if the data of the secret changes, the data in the resource object that references the data will also change. When the secret is updated, the pod will also be updated.

2: Use as environment variable
When using secret through volume, the container must read data from the file, which is a little troublesome. k8s also supports using secret through environment variables.

An example pod configuration file is as follows:

apiVersion: v1
kind: Pod
metadata:
  name: secret-pod
spec:
  containers:
  - name: secret-pod
    image: busybox
    args:
      - /bin/sh
      - -c
      - sleep 10; touch /tmp/healthy; sleep 3000
    env:
      - name: SECRET_USERNAME
        valueFrom:
          secretKeyRef:
            name: secret-app
            key: username
      - name: SECRET_PASSWORD
        valueFrom:
          secretKeyRef:
            name: secret-app
            key: password

//Create pod and read secret:

[root@master secret]# kubectl apply -f  secret-pod.yaml 
pod/secret-pod created
[root@master secret]# kubectl exec  -it secret-pod /bin/sh
/ # echo $SECRET_USERNAME
root
/ # echo $SECRET_PASSWORD
123456.com

(2) Verification: next, we modify the password value in secret to see if the data in the pod will change?
After testing, it is found that the value in pod will not change.

Features: it's very convenient to read secret from environment variables, but it can't support the dynamic update of secret.

configMap

  • Secret can provide pod with password, Token, private key and other sensitive data. For some non sensitive data, such as application configuration information, ConfigMap can be used.
  • ConfigMap is very similar to secret. The main difference is that the data it saves is stored in clear text.

Suppose we need the information stored in the ConfigMap object:

config1=xxx
config2=yyy

1. Create ConfigMap

There are also four methods:
1.1 create through -- from literal:

[root@master configMap]# kubectl create configmap configmap1 --from-literal=config1=xxx --from-literal=config2=yyy
configmap/configmap1 created

//To view configmap information:

You can see that the saved data is stored in clear text.

Features: each -- from literal corresponds to a piece of information.

1.2 create through -- from file:

[root@master configMap]# echo xxx > config1
[root@master configMap]# echo yyy > config2
//Create configmap:
[root@master configMap]# kubectl create configmap configmap2 --from-file=config1 --from-file=config2
configmap/configmap2 created

Features: each file corresponds to one piece of information, and only one can be saved in each file. For confidentiality, the local file needs to be deleted after import.

1.3 create through -- from env file:

[root@master configMap]# cat > env.txt <<EOF
> config1=xxx
> config2=yyy
> EOF

//Create configmap:

[root@master configMap]# kubectl create configmap configmap3 --from-env-file=env.txt 
configmap/configmap3 created

Features: multiple information can be saved in the file. Each key=value in env.txt corresponds to one information entry.

1.4 through yaml configuration file:
#The sensitive data in the file must be the result of base64 encoding.
The configmap configuration file is as follows:

apiVersion: v1
kind: ConfigMap
metadata:
  name: configmap-app
data:
  config1: xxx   #The data in the file can be directly input in clear text
  config2: yyy

//Create configmap:

 [root@master configMap]# kubectl apply -f  configmap.yaml 
configmap/configmap-app created

Features: easy to save, cross host use will be very convenient.

2. Data reference

Like secret, pod can also use secret through volume or environment variables.
1: volume mode
The yaml configuration file is as follows:

apiVersion: v1
kind: Pod
metadata:
  name: configmap-pod
spec:
  containers:
  - name: configmap-pod
    image: busybox
    args:
      - /bin/sh
      - -c
      - sleep 10; touch /tmp/healthy; sleep 3000
    volumeMounts:
    - name: foo
      mountPath: /etc/foo
  volumes:
  - name: foo
    configMap:
      name: configmap-app

//Create a pod and read the data in the Pod:

[root@master configMap]# kubectl apply -f configmap-pod.yaml 
pod/configmap-pod created
[root@master configMap]# kubectl exec  -it configmap-pod /bin/sh
/ # cd /etc/foo/
/etc/foo # ls
config1  config2
/etc/test # cat config1
xxx
/etc/test # cat config2
yyy

2: env environment variable mode
The contents of the yaml configuration file are as follows:

apiVersion: v1
kind: Pod
metadata:
  name: configmap-pod
spec:
  containers:
  - name: configmap-pod
    image: busybox
    args:
      - /bin/sh
      - -c
      - sleep 10; touch /tmp/healthy; sleep 3000
    env:
      - name: CONFIG1
        valueFrom:
          configMapKeyRef:
            name: configmap-app
            key: config1
      - name: CONFIG2
        valueFrom:
          configMapKeyRef:
            name: configmap-app
            key: config2

//Create a pod and view the data in the Pod:

[root@master configMap]# kubectl  delete -f  configmap-pod.yaml 
pod "configmap-pod" deleted
[root@master configMap]# kubectl  apply -f  configmap-pod.yaml 
pod/configmap-pod created
[root@master configMap]# kubectl exec  -it configmap-pod /bin/sh
/ # echo $CONFIG1
xxx
/ # echo $CONFIG2
yyy

After testing: the two reference methods of configmap and secret are the same. The way of volume mounting is the same. If the data of configmap is updated, the data in the referenced resource object will also be updated. However, in the way of env environment variable, dynamic update is not supported (you can test and verify by yourself).

Note: the above is just an example. You should know that in most cases, configuration information is provided in the form of a file, so when creating a ConfigMap, you usually use -- from file or YAML mode, while when reading a ConfigMap, you usually use volume mode.

Summary:
Pass configuration information to the pod. If the information needs to be encrypted, use Secret; if it is general configuration information, use ConfigMap.
Secret and ConfigMap support four definition methods. pod can choose volume mode or environment variable mode when using them, but only volume mode supports dynamic update.

Tags: Kubernetes encoding Database Docker

Posted on Mon, 03 Feb 2020 00:24:36 -0800 by DwarV