Kubernetes 学习13 kubernetes pv pvc configmap 和secret

一、概述

  1、我们在pvc申请的时候未必就有现成的pv能正好符合这个pvc在申请中指定的条件,毕竟上一次的成功是我们有意设定了有一些满足有一些不满足的前提下我们成功创建了一个pvc并且被pod绑定所使用了。但是正常情况下刚好让二者之间符合或者在一众pv中正好有存在符合需要的这么一个pv未必在多种情况下都能满足。所以k8s的设计者也注意到了这些问题,因此他们为此有意设计了一种工作逻辑能够让pvc在申请pv时不针对某个pv进行或者是我们可以直接针对某个存储类(k8s之上的标准资源之一,叫StorageClass),我们可以事先把众多的存储设备当中存储管理员所准备好的包含了nfs,glusterfs,ceph甚至是一些云端的存储等等,把他们提供好的存储空间,因为我们没有事先做好pv,因为我不确定这个用户到底会用到多大的pv,以及什么样的pv,因此我们不妨去把现有可用存储空间尚未做成pv的存储空间都拿出来给他做一个分类,根据综合服务质量,或者根据他的io性能等等做一个简单分类。假如我们有两个nfs集群,那么我们把两个nfs做成一类,另外我们还有一个ceph的rbd集群,我们把ceph的rbd集群又分为一类等等,可以用多个维度分类。

    

  2、分完类后我们可以给他定义出来这个类,这个类就是标准的k8s资源,当定义好存储类以后我们pvc再去申请pv的时候不针对某个pv直接进行而是针对存储类类进行,向某个类申请就从这个类中动态创建出一个符合其需求的pv来。另外还有一个前提条件是必须让存储设备必须要支持restful 风格请求的创建接口才行。意思是你的存储系统上本来是没有划分好的存储空间。工作逻辑应该是这样的,我们只提供了存储空间,就是存储服务器或者存储集群,在这个存储上没有任何已经划分好的卷,以nfs为例可以想象成在nfs服务器中并没有一个导出的v1到v5路径,假设本地有一块硬盘,我们可以把它划分成很多分区来,每一个分区输出一个共享点,然后我们在nfs前端定义一个restful 风格的接口,这个接口通过api请求,第一,能请求在这个磁盘上划分一个刚好符合需求大小的分区。第二,编辑我们的exports文件把这个对应的分区挂载至本地的某个目录上并且将其导出出去让其它客户端能够挂载。第三,我们动态创建出一个pv刚好绑定并使用刚刚动态导出的这组空间。当然nfs不支持这个功能,只是举例说明。ceph是支持的。

二、configmap存储卷

  1、secret和configmap作为存储卷来说目的不是为了给pod提供存储空间来用的,而是给我们的管理员和用户提供了从集群外部向pod内部的应用注入配置信息的方式。

  2、比如在我们集群之上我们有一个名称空间,我们名称空间中有一pod,pod可以正常运行的,我们启动pod是基于镜像来运行容器的,我们镜像做好以后,镜像内的应用程序启动时要读配置文件也是镜像内的配置文件,因此这个镜像内的应用启动时应该运行在什么配置下在做镜像之前就确定好。除非我们在启动时加入变量。在k8s上也一样,本来镜像都是做好了的,一个镜像应付不了那么多场景我们就不得不做多个镜像。所以能够从镜像外部在向镜像内部启动为容器时添加配置信息是至关重要的。

  3、假如说我们现在部署了20个pod,后来我们发现这个pod的内部的容器中的配置信息就算我们能够通过容器外部环境变量注入进去,但是运行了一段时间后我们发现我们需要改配置,我们就需要改entrypoint脚本或者重启pod内部的容器,这个过程是非常麻烦的,并且还要一个一个的去改其环境变量的值,因此,我们有一种简单的功能,可以使用配置中心,每一个pod的启动应用的配置文件都可以从配置中心加载,这样如果需要涉及到修改那么只需要修改配置中心中的配置然后通知给所有容器让其重载配置文件即可,而不需要登陆到每一个容器修改配置。

  4、我们使用deployment控制着20个pod,将来我们这20个pod需要更新的时候发现我们只是为了改一下配置文件就是为了做灰度更新,直接更新整个镜像就是为了改一个配置信息,这样代价太大了,因此我们不把配置写死在镜像中,而是引入一个新的资源,这个资源叫configmap,他里面放的是配置信息。随后,我们启动每一个pod的时候,这个pod都可以共享使用同一个configmap资源,这个资源对象可以当存储卷来使用,也可以从中基于环境变量的方式从里面获取数据传递给环境变量从而注入到容器中使用。重复一遍:

    a、我们现在要启动一个pod,pod启动时可以把这一个configmap资源关联到pod上来,从中读一个数据传递给容器的一个变量,任然是变量注入的方式来给容器传配置信息。

    b、我也可以把每一个configmap当一个存储卷,直接把它挂载到容器的目录上,这个目录恰好是容器应用程序读取配置信息的目录,所以他也能读取到配置,更有意思的是它是支持动态修改的,意思是如果configmap改变了,因为所有pod都共享的同一个配置,所以他改完后会通知给所有pod,所有pod中的应用就会重载(当然有时候有可能不能自动重载而需要手动重载)。因此configmap扮演了k8s之上的配置中心的功能。

  5、所以我们要传一个配置文件给容器,把配置文件打包在configmap中就可以了让pod启动时把configmap挂载为子路径,挂载到配置文件目录下就从里面读配置文件就ok了。

三、secret

  1、但是configmap是明文存数据的,比如连mysql,你把root账号放进去那我们拿到configmap你的信息就泄露了,因此,和configmap有着同样功能的标准的k8s资源叫secret,他的功能和configmap的功能一样,不同的是secret中的数据不是明文存放的而是base64编码存放的,也可以加密也可以解密,但是对很多人来说是不可能直接看到的。所以很多人看到secret时就不能看到直接数据也不懂怎么解码。

四、配置容器化应用的方式总结

  1、自定义命令行参数; command args

  2、把配置文件直接培进镜像里。

  3、环境变量

    a、cloud Native的应用程序一般可直接通过环境变量加载配置;

    b、通过entrypoint 脚本来预处理变量为配置文件中的配置信息;

  4、存储卷

五、configmap创建和使用

  1、pod资源环境变量的获取方式。在pod中我们要通过环境变量传递内容,传递信息给pod中的容器,我们需要在容器上使用env value或者valuefrom获取数据。

[root@k8smaster volumes]# kubectl explain pods.spec.containers.env
KIND:     Pod
VERSION:  v1

RESOURCE: env <[]Object>

DESCRIPTION:
     List of environment variables to set in the container. Cannot be updated.

     EnvVar represents an environment variable present in a Container.

FIELDS:
   name    <string> -required- #变量名
     Name of the environment variable. Must be a C_IDENTIFIER.

   value    <string> #数据
     Variable references $(VAR_NAME) are expanded using the previous defined
     environment variables in the container and any service environment
     variables. If a variable cannot be resolved, the reference in the input
     string will be unchanged. The $(VAR_NAME) syntax can be escaped with a
     double $$, ie: $$(VAR_NAME). Escaped references will never be expanded,
     regardless of whether the variable exists or not. Defaults to "".

   valueFrom    <Object> #表示数据不是直接给的字符串而是来自于引用另外一个对象或变量,他的数据拿过来以后我们传给本pod变量。
     Source for the environment variable's value. Cannot be used if value is not
     empty.
[root@k8smaster volumes]# kubectl explain pods.spec.containers.env.valueFrom
KIND:     Pod
VERSION:  v1

RESOURCE: valueFrom <Object>

DESCRIPTION:
     Source for the environment variable's value. Cannot be used if value is not
     empty.

     EnvVarSource represents a source for the value of an EnvVar.

FIELDS:
   configMapKeyRef    <Object> #在configmap中
     Selects a key of a ConfigMap.

   fieldRef    <Object> #某个字段,可以是pod自身的字段,如解释中所述,将字段对应的值引用过来。
     Selects a field of the pod: supports metadata.name, metadata.namespace,
     metadata.labels, metadata.annotations, spec.nodeName,
     spec.serviceAccountName, status.hostIP, status.podIP.

   resourceFieldRef    <Object> #资源需求和资源限制
     Selects a resource of the container: only resources limits and requests
     (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu,
     requests.memory and requests.ephemeral-storage) are currently supported.

   secretKeyRef    <Object> #在secret中
     Selects a key of a secret in the pod's namespace

  2、configmap作用在于配置信息与镜像文件解耦,镜像可以做成骨架,配置信息可以通过configmap进行注入。所以使得一个镜像文件就可以应付多种不同配置情况下为应用程序运行不同配置的环境而工作。所以他的主要作用是为了将配置文件从镜像中解耦从而增强了我们应用的可移植性以及应用的可复用性。简单来讲一个configmap就是一系列配置数据的集合,而这些数据将来可以注入到pod对象的容器中所使用,而注入方式有两种,第一,直接把configmap当存储卷。第二,使用env的valuefrom方式引用configmap当中所保存进去的数据。在每一个configmap中所有的配置信息都保存键值格式,比如键名叫name,值叫张三,这是一种方式,但是这种能够保存的数据量很小,我们可以保存更复杂的格式,比如键名为server.com或者www.conf,而值是我们曾经在nginx上配置时给他传递的www.conf的内容,可以是整个文本的所有内容,因为value长度是没有限制的。所以整个configmap中放的是多个键值对键值数据{k1:value1,k2:value2...},每一个key,它的v只是代表了一段配置信息,可能只是一个简单的配置参数,也可能是一整个文本配置内容都是没问题的,我们可以在想办法在pod启动时从configmap的某个键上来获取相应的数据对象。

  3、接来下我们看看怎么去创建configmap,configmap是k8s上的标准的资源,他也是属于名称空间级别的资源

[root@k8smaster volumes]# kubectl explain configmap
KIND:     ConfigMap
VERSION:  v1

DESCRIPTION:
     ConfigMap holds configuration data for pods to consume.

FIELDS:
   apiVersion    <string>
     APIVersion defines the versioned schema of this representation of an
     object. Servers should convert recognized schemas to the latest internal
     value, and may reject unrecognized values. More info:
     https://git.k8s.io/community/contributors/devel/api-conventions.md#resources

   binaryData    <map[string]string> #二进制格式给数据
     BinaryData contains the binary data. Each key must consist of alphanumeric
     characters, '-', '_' or '.'. BinaryData can contain byte sequences that are
     not in the UTF-8 range. The keys stored in BinaryData must not overlap with
     the ones in the Data field, this is enforced during validation process.
     Using this field will require 1.10+ apiserver and kubelet.

   data    <map[string]string> #
     Data contains the configuration data. Each key must consist of alphanumeric
     characters, '-', '_' or '.'. Values with non-UTF-8 byte sequences must use
     the BinaryData field. The keys stored in Data must not overlap with the
     keys in the BinaryData field, this is enforced during validation process.

   kind    <string>
     Kind is a string value representing the REST resource this object
     represents. Servers may infer this from the endpoint the client submits
     requests to. Cannot be updated. In CamelCase. More info:
     https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds

   metadata    <Object>
     Standard object's metadata. More info:
     https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata
[root@k8smaster volumes]# kubectl create configmap --help
Create a configmap based on a file, directory, or specified literal value. 

A single configmap may package one or more key/value pairs. 

When creating a configmap based on a file, the key will default to the basename of the file, and the value will default
to the file content.  If the basename is an invalid key, you may specify an alternate key. 

When creating a configmap based on a directory, each file whose basename is a valid key in the directory will be
packaged into the configmap.  Any directory entries except regular files are ignored (e.g. subdirectories, symlinks,
devices, pipes, etc).

Aliases:
configmap, cm

Examples:
  # Create a new configmap named my-config based on folder bar
  kubectl create configmap my-config --from-file=path/to/bar #值是来自文件的
  
  # Create a new configmap named my-config with specified keys instead of file basenames on disk
  kubectl create configmap my-config --from-file=key1=/path/to/bar/file1.txt --from-file=key2=/path/to/bar/file2.txt
  
  # Create a new configmap named my-config with key1=config1 and key2=config2
  kubectl create configmap my-config --from-literal=key1=config1 --from-literal=key2=config2
  
  # Create a new configmap named my-config from the key=value pairs in the file
  kubectl create configmap my-config --from-file=path/to/bar #指定时也可以不用写key,文件名直接为key
  
  # Create a new configmap named my-config from an env file
  kubectl create configmap my-config --from-env-file=path/to/bar.env

Options:
      --allow-missing-template-keys=true: If true, ignore any errors in templates when a field or map key is missing in
the template. Only applies to golang and jsonpath output formats.
      --append-hash=false: Append a hash of the configmap to its name.
      --dry-run=false: If true, only print the object that would be sent, without sending it.
      --from-env-file='': Specify the path to a file to read lines of key=val pairs to create a configmap (i.e. a Docker
.env file).
      --from-file=[]: Key file can be specified using its file path, in which case file basename will be used as
configmap key, or optionally with a key and file path, in which case the given key will be used.  Specifying a directory
will iterate each named file in the directory whose basename is a valid configmap key.
      --from-literal=[]: Specify a key and literal value to insert in configmap (i.e. mykey=somevalue)
      --generator='configmap/v1': The name of the API generator to use.
  -o, --output='': Output format. One of:
json|yaml|name|template|go-template|go-template-file|templatefile|jsonpath|jsonpath-file.
      --save-config=false: If true, the configuration of current object will be saved in its annotation. Otherwise, the
annotation will be unchanged. This flag is useful when you want to perform kubectl apply on this object in the future.
      --template='': Template string or path to template file to use when -o=go-template, -o=go-template-file. The
template format is golang templates [http://golang.org/pkg/text/template/#pkg-overview].
      --validate=true: If true, use a schema to validate the input before sending it

Usage:
  kubectl create configmap NAME [--from-file=[key=]source] [--from-literal=key1=value1] [--dry-run] [options]

Use "kubectl options" for a list of global command-line options (applies to all commands).

  4、从命令行中直接创建configmap

    a、直接给键和值

[root@k8smaster volumes]# kubectl create configmap nginx-config --from-literal=nginx_port=80 --from-literal=server_name=myapp.wohaoshuai.com
configmap/nginx-config created
[root@k8smaster volumes]# kubectl get cm -o wide
NAME           DATA      AGE
nginx-config   2         8s
[root@k8smaster volumes]# kubectl describe cm nginx-config
Name:         nginx-config
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
nginx_port:
----
80
server_name:
----
myapp.wohaoshuai.com
Events:  <none>

    b、直接给文件

[root@k8smaster configmap]# cat www.conf 
server {
    server_name myapp.wohaoshuai.com;
    listen 80;
    root /data/web/html;
}
[root@k8smaster configmap]# kubectl create configmap nginx-www --from-file=./www.conf #不给键直接给文件默认键为文件名
configmap/nginx-www created
[root@k8smaster configmap]# kubectl get cm
NAME           DATA      AGE
nginx-config   2         8m
nginx-www      1         11s
[root@k8smaster configmap]# kubectl get cm nginx-www -o yaml
apiVersion: v1
data:
  www.conf: "server {
	server_name myapp.wohaoshuai.com;
	listen 80;
	root /data/web/html;
}
"
kind: ConfigMap
metadata:
  creationTimestamp: 2019-06-19T09:57:34Z
  name: nginx-www
  namespace: default
  resourceVersion: "754139"
  selfLink: /api/v1/namespaces/default/configmaps/nginx-www
  uid: a9098a25-9278-11e9-814e-000c29d142be
[root@k8smaster configmap]# kubectl describe cm nginx-www
Name:         nginx-www
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
www.conf:
----
server {
  server_name myapp.wohaoshuai.com;
  listen 80;
  root /data/web/html;
}

Events:  <none>

  5、这些键值数据可以注入到pod中去,具体有两种方式,第一种方式是我们在容器当中使用env,然后使用envfrom来获取,如果我们要通过这个环境变量来注入的话你必须确保这个环境变量能传递过去后这个变量可以被容器作为配置信息使用,否则传过去没用。

    a、引用方式一

[root@k8smaster configmap]# cat pod-configmap.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: pod-cm-1
  namespace: default
  labels: #也可以在此处写上{app:myapp,tier:frontend}代替下面两行
    app: myapp #应用层级标签
    tier: frontend #架构层级标签,在分层架构中属于frontend层
  annotations:
    wohaoshuai.com/created-by: "cluster admin"
spec:
  containers: #是一个列表,具体定义方式如下
  - name: myapp
    image: ikubernetes/myapp:v1
    ports: #不暴露端口其实也可以被访问,目的是为了说明启动的端口有哪些
    - name: http #service 中可以通过名称来引用端口
      containerPort: 80
    env: 
    - name: NGINX_SERVER_PORT
      valueFrom:
        configMapKeyRef:
          name: nginx-config
          key: nginx_port
    - name: NGINX_SERVER_NAME
      valueFrom:
        configMapKeyRef:
          name: nginx-config
          key: server_name
[root@k8smaster configmap]# kubectl apply -f pod-configmap.yaml 
pod/pod-cm-1 created
[root@k8smaster ~]# kubectl exec -it pod-cm-1 printenv |grep -E "NGINX_SERVER_PORT|NGINX_SERVER_NAME"
NGINX_SERVER_PORT=80
NGINX_SERVER_NAME=myapp.wohaoshuai.com

      现在我们修改configmap中内容再看Pod的环境变量发现对应环境变量值并没有随着cm中的修改而改变,因此这个在pod中不是实时更新的,需要重启pod才可以。

[root@k8smaster ~]# kubectl edit cm nginx-config
configmap/nginx-config edited
[root@k8smaster ~]# kubectl describe cm nginx-config
Name:         nginx-config
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
nginx_port:
----
8080
server_name:
----
myapp.wohaoshuai.com
Events:  <none>
[root@k8smaster ~]# kubectl exec -it pod-cm-1 printenv |grep -E "NGINX_SERVER_PORT|NGINX_SERVER_NAME"
NGINX_SERVER_PORT=80
NGINX_SERVER_NAME=myapp.wohaoshuai.com

    b、引用方式2,上述configmap中nginx-www是被我们做成了文件内容,其实无论是不是文件内容都可以把它转成文件格式放到我们pod中,都可以把它们转为文件,键名就是文件名,键值就是文件内容,无论创建时是不是文件,比如在命令行中指了一个key指了一个数据,我们可以把整个configmap目录当存储卷挂载到pod上,或者是关联到pod上让pod中的容器挂载,挂载完以后放在某个目录下让每一个键就转换成一个文件名,在挂载点目录下,这个键的值就转换成文件内容,就这样来做映射。对存储卷挂载的方式来获得的存储信息在在外部configmap中改了后会自动同步到我们对应的文件中来。

[root@k8smaster configmap]# cat pod-configmap-2.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: pod-cm-2
  namespace: default
  labels: #也可以在此处写上{app:myapp,tier:frontend}代替下面两行
    app: myapp #应用层级标签
    tier: frontend #架构层级标签,在分层架构中属于frontend层
  annotations:
    wohaoshuai.com/created-by: "cluster admin"
spec:
  containers: #是一个列表,具体定义方式如下
  - name: myapp
    image: ikubernetes/myapp:v1
    ports: #不暴露端口其实也可以被访问,目的是为了说明启动的端口有哪些
    - name: http #service 中可以通过名称来引用端口
      containerPort: 80
    volumeMounts:  #在容器中使用pod定义的volumes
    - name: nginxconfig
      mountPath: /etc/nginx/config.d/
      readOnly: true
  volumes:  #在pod中定义volumes
  - name: nginxconfig
    configMap:
      name: nginx-config
[root@k8smaster configmap]# kubectl apply -f pod-configmap-2.yaml 
pod/pod-cm-2 created

[root@k8smaster ~]# kubectl exec -it pod-cm-2 ls /etc/nginx/config.d/
nginx_port   server_name
[root@k8smaster ~]# kubectl exec -it pod-cm-2 cat /etc/nginx/config.d/nginx_port
8080
[root@k8smaster ~]# kubectl exec -it pod-cm-2 cat /etc/nginx/config.d/server_name
myapp.wohaoshuai.com

      现在将我们cm中的端口变量值改为8088,此时我们pod中文件也就动态更新。其实我们可以发现这个文件为链接文件,严格意义上来说它不是同步进来的,而是指向不同的configmap版本,有新版本时这个链接就指向新版本配置。

[root@k8smaster configmap]# kubectl edit cm nginx-config
configmap/nginx-config edited
[root@k8smaster configmap]# kubectl describe cm nginx-config
Name:         nginx-config
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
server_name:
----
myapp.wohaoshuai.com
nginx_port:
----
8088
Events:  <none>
[root@k8smaster configmap]# kubectl exec -it pod-cm-2 cat /etc/nginx/config.d/nginx_port
8088

  6、真正工作起来的案例

[root@k8smaster configmap]# cat pod-configmap-3.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: pod-cm-3
  namespace: default
  labels: #也可以在此处写上{app:myapp,tier:frontend}代替下面两行
    app: myapp #应用层级标签
    tier: frontend #架构层级标签,在分层架构中属于frontend层
  annotations:
    wohaoshuai.com/created-by: "cluster admin"
spec:
  containers: #是一个列表,具体定义方式如下
  - name: myapp
    image: ikubernetes/myapp:v1
    ports: #不暴露端口其实也可以被访问,目的是为了说明启动的端口有哪些
    - name: http #service 中可以通过名称来引用端口
      containerPort: 80
    volumeMounts:  #在容器中使用pod定义的volumes
    - name: nginxconfig
      mountPath: /etc/nginx/conf.d/
      readOnly: true
  volumes:  #在pod中定义volumes
  - name: nginxconfig
    configMap:
      name: nginx-www
[root@k8smaster configmap]# kubectl apply -f pod-configmap-3.yaml 
pod/pod-cm-3 created
[root@k8smaster configmap]# kubectl exec -it pod-cm-3 ls /etc/nginx/conf.d/
www.conf
[root@k8smaster configmap]# kubectl exec -it pod-cm-3 cat /etc/nginx/conf.d/www.conf
server {
    server_name myapp.wohaoshuai.com;
    listen 80;
    root /data/web/html;
}

      在对应目录下创建网页文件并访问

[root@k8smaster configmap]# kubectl get pod -o wide |grep pod-cm-3
pod-cm-3                         1/1       Running   0          9m        10.244.2.108   k8snode2
[root@k8smaster configmap]# kubectl exec -it pod-cm-3 /bin/sh
/ # mkdir -p /data/web/html
/ # echo "<h1>Nginx Server configured by CM<h1>" >>/data/web/html/index.html 
/ # exit
[root@k8smaster configmap]# curl
10.244.2.108

  <h1>Nginx Server configured by CM<h1>

     在configmap中修改我们值中的端口,可以发现在我们pod中也可以动态更新

[root@k8smaster configmap]# kubectl describe cm nginx-www
Name:         nginx-www
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
www.conf:
----
server {
  server_name myapp.wohaoshuai.com;
  listen 8080;
  root /data/web/html;
}

Events:  <none>
[root@k8smaster configmap]# kubectl exec -it pod-cm-3 cat /etc/nginx/conf.d/www.conf
server {
    server_name myapp.wohaoshuai.com;
    listen 8080;
    root /data/web/html;
}

[root@k8smaster configmap]# kubectl exec -it pod-cm-3 /bin/sh/ # netstat -anpt
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      1/nginx: master pro
/ # nginx -s reload #重载配置文件
2019/06/20 06:19:51 [notice] 29#29: signal process started
/ # netstat -anpt
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 0.0.0.0:8080            0.0.0.0:*               LISTEN      1/nginx: master pro

  7、我们想只挂载部分而不是挂在所有

六、secret创建使用

  1、configmap都是明文存数据的,所以我们不能用它来访问,所以我们使用secret,但它比configmap要麻烦一点,只有敏感数据采用secrt来存放,比如你的私钥和证书,这个时候私钥和证书要放在secret中,其它内容应该放在configmap中,另外还有,比如我们连接mysql是我们打算把密码写在配置文件中,这个时候我们要把密码写成secret,而不能定义成configmap,所以他和configmap一样也是键值存储,只是它的值在看的时候不显示给你,或者就算显示给你的也是base64的编码格式,但除此之外我们secret还有一个特定就是它有多种类型。

    a、generic(通用的):保存密码数据等用它就可以

    b、tls:保存私钥和证书

    c、docker-registry:保存docker-registry的认证信息,我们每一个node运行pod之前会把pod依赖的镜像要先检查本地有没有,如果没有就回去仓库服务器上拖,如果我们用的是私有仓库的话,必须要输入账号和密码才能访问,账号密码放哪儿呢?也就意味着当前node要自动去通过认证然后去拖镜像否则pod就会运行失败,也就意味着拉取的时候要现在节点上使用docker login然后docker pull。因此很多时候我们k8s节点要运行pod获取镜像,而若镜像若托管在在必须要认证才能获取到的私有镜像仓库中时,kubelet要能自动完成,因此拖镜像和认证是通过kubelet指挥着docker去做的,那我们怎么去提供这个私有数据呢。第一种方式是我们使用secret,使用我们pods.spec.imagePullSecrets字段,表示pod创建时,它如果要连到私有镜像仓库服务器,需要认证那么这里我们应该放个secret,这个secret包含了让我们kubelet或我们docker去链接私有仓库服务器时的账号和密码,这个账号密码就是由secret提供的,这个对象必须是专用的对象,就是我们这个docker-registry

  2、创建一个generic类型的secret

[root@k8smaster configmap]# kubectl create secret generic mysql-root-password --from-literal=password=MyP@ss123
secret/mysql-root-password created

[root@k8smaster configmap]# kubectl get secret
NAME                    TYPE                                  DATA      AGE
default-token-jvtl7     kubernetes.io/service-account-token   3         42d
mysql-root-password     Opaque                                1         19s
tomcat-ingress-secret   kubernetes.io/tls                     2         6d
[root@k8smaster configmap]# kubectl describe secret mysql-root-password
Name:         mysql-root-password
Namespace:    default
Labels:       <none>
Annotations:  <none>

Type:  Opaque

Data
====
password:  9 bytes
[root@k8smaster configmap]# kubectl get secret mysql-root-password -o yaml
apiVersion: v1
data:
  password: TXlQQHNzMTIz
kind: Secret
metadata:
  creationTimestamp: 2019-06-20T06:57:03Z
  name: mysql-root-password
  namespace: default
  resourceVersion: "799998"
  selfLink: /api/v1/namespaces/default/secrets/mysql-root-password
  uid: 9b9d1d06-9328-11e9-814e-000c29d142be
type: Opaque

    当然它只是伪加密的,可以直接解码

[root@k8smaster configmap]# echo TXlQQHNzMTIz |base64 -d
MyP@ss123

  3、创建一个pod使用secret

[root@k8smaster configmap]# cat pod-secret-1.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: pod-secret-1
  namespace: default
  labels: #也可以在此处写上{app:myapp,tier:frontend}代替下面两行
    app: myapp #应用层级标签
    tier: frontend #架构层级标签,在分层架构中属于frontend层
  annotations:
    wohaoshuai.com/created-by: "cluster admin"
spec:
  containers: #是一个列表,具体定义方式如下
  - name: myapp
    image: ikubernetes/myapp:v1
    ports: #不暴露端口其实也可以被访问,目的是为了说明启动的端口有哪些
    - name: http #service 中可以通过名称来引用端口
      containerPort: 80
    env: 
    - name: MYSQL_ROOT_PASSWORD 
      valueFrom:
        secretKeyRef:
          name: mysql-root-password 
          key: password
[root@k8smaster configmap]# kubectl apply -f pod-secret-1.yaml 
pod/pod-secret-1 created
[root@k8smaster configmap]# kubectl exec -it pod-secret-1 printenv |grep MYSQL_ROOT_PASSWORD
MYSQL_ROOT_PASSWORD=MyP@ss123

  4、secret第二种获取方式和configmap一样也是挂载为存储卷,然后挂载至指定目录下转换为文件格式,一般来讲我们是作为私钥或证书文件时使用。tls格式的都是这样挂载的,挂载完后会生成一个tls.key,文件内容就是我们key私钥信息,tls.crt就是证书文件的内容。

原文地址:https://www.cnblogs.com/Presley-lpc/p/11044991.html