K8S存储之特殊存储(ConfigMap、Secret和downwardAPI)

摘要:
测试configmapNamespace:<}error_ page500502503504/50x。html;<----服务器{listen8080;server_namelocalhost;包含/etc/nginx/conf.d/myserver-*.confocation/{root/usr/share/nginx/html;

1 ConfigMap

ConfigMap用于保持配置数据的键值对,可以用来保持单个熟悉,也可以用来保存配置文件。ConfigMap跟secret很类似,但它可以更方便地处理不包含敏感信息的字符串。

1.1 ConfigMap创建

可以使用kubectl create configmap从文件、目录或者key-value字符串创建等创建Configmap。

范例1:从key-value字符串创建ConfigMap

#创建ConfigMap
root@ubuntu-200 ~]# kubectl create configmap name --from-literal=name=yang
configmap/name created

#查看创建的Configmap
[root@ubuntu-200 ~]# kubectl describe configmaps name 
Name:         name
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
name:
----
yang
Events:  <none>

#也可以多个值一起跟在后面,创建的Configmap会有多个键值对
[root@ubuntu-200 ~]# kubectl create configmap test-configmap --from-literal=name=yang --from-literal=name2=wang
configmap/test-configmap created
#查看创建的Configmap
[root@ubuntu-200 ~]# kubectl describe configmaps test-configmap 
Name:         test-configmap
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
name:
----
yang
name2:
----
wang
Events:  <none>

范例2:基于文件创建

这种方式创建的ConfigMap对象,其数据存储的键为文件路径的基名,值为文件内容。

[root@ubuntu-200 ~]# cat config.env 
a=b
c=d

#创建configmap
[root@ubuntu-200 ~]# kubectl create configmap test2 --from-env-file=config.env 
configmap/test2 created

#查看Configmap
[root@ubuntu-200 ~]# kubectl get configmaps -o wide
NAME             DATA   AGE
demoapp-config   2      28h
name             1      31m
test-configmap   2      26m
test2            2      8m31s
[root@ubuntu-200 ~]# kubectl describe configmaps test2
Name:         test2
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
c:
----
d
a:
----
b
Events:  <none>
[root@ubuntu-200 /data]# cat myserver.conf 
server {
    listen 8080;
    server_name  localhost;
    include /etc/nginx/conf.d/myserver-*.conf
    
    location / {
    root /usr/share/nginx/html;
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }

}

[root@ubuntu-200 /data]# kubectl create configmap nginx-config --from-file=/data/myserver.conf

[root@ubuntu-200 /data]# kubectl describe configmaps nginx-config 
Name:         nginx-config
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
myserver.conf:
----
server {
    listen 8080;
    server_name  localhost;
    include /etc/nginx/conf.d/myserver-*.conf
  
    location / {
  root /usr/share/nginx/html;
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }

}

范例3:直接从文件目录创建,如果从文件创建,那么文件名会成为key,而文件内容会成为value

[root@ubuntu-200 ~]# mkdir /data/config
[root@ubuntu-200 ~]# cd /data/
[root@ubuntu-200 /data]# echo a > config/a
[root@ubuntu-200 /data]# echo b > config/b
[root@ubuntu-200 /data]# cat config/a
a
[root@ubuntu-200 /data]# cat config/b
b

#创建Configmap
[root@ubuntu-200 /data]# kubectl create configmap test3 --from-file=/data/config/ 
configmap/test3 created

#查看创建的Configmap
[root@ubuntu-200 /data]# kubectl get configmaps -o wide
NAME             DATA   AGE
demoapp-config   2      28h
name             1      37m
test-configmap   2      32m
test2            2      14m
test3            2      18s
[root@ubuntu-200 /data]# kubectl describe configmaps test3
Name:         test3
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
a:
----
a

b:
----
b

Events:  <none>

范例4:使用资源清单创建

基于配置文件创建ConfigMap资源时,它所使用的字段包括通常的apiVersion、kind和metadata字段,以及用于存储数据的关键字段“data”。

[root@ubuntu-200 /data]# cat ConfigMap.yaml 
apiVersion: v1
kind: ConfigMap
metadata:
  name: configmap-demo
  namespace: default
data:
  log_level: INFO    #前面为键,后面为值
  log_file: /data/configmap.log
[root@ubuntu-200 /data]# kubectl apply -f ConfigMap.yaml
[root@ubuntu-200 /data]# kubectl describe configmaps configmap-demo 
Name:         configmap-demo
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
log_file:
----
/data/configmap.log
log_level:
----
INFO
Events:  <none>

1.2 ConfigMap的使用

ConfigMap可以通过多种方式在Pod中使用,比如设置环境变量、设置容器命令行参数、在Volume中创建配置文件等。

注意:

  • ConfigMap必须在pod引用它之前创建

  • 使用envFrom时,将会自动忽略无效点键

  • Pod只能使用同一个命令空间内的ConfigMap

范例1:基于键值进行引用

#编写资源清单
[root@ubuntu-200 ~]# cat configmap-env.yaml 
apiVersion: v1
kind: ConfigMap
metadata:
  name: configmap-app
  namespace: default
data:
  demoapp.port: "8080"
  demoapp.host: 0.0.0.0
---
apiVersion: v1
kind: Pod
metadata:
  name: configmap-env-demo
  namespace: default
spec:
  containers:
  - image: ikubernetes/demoapp:v1.0
    name: demoapp
    env:
    - name: PORT
      valueFrom:
        configMapKeyRef:
          name: configmap-app
          key: demoapp.port
          optional: false
    - name: HOST
      valueFrom:
        configMapKeyRef:
          name: configmap-app
          key: demoapp.host
          optional: true 

#创建Pod和ConfigMap
[root@ubuntu-200 ~]# kubectl apply -f configmap-env.yaml 
configmap/configmap-app created
pod/configmap-env-demo created

#查看Pod
[root@ubuntu-200 ~]# kubectl get pods -o wide
NAME                 READY   STATUS    RESTARTS   AGE     IP             NODE         NOMINATED NODREADINESS GATES
configmap-env-demo   1/1     Running   0          6s      10.244.5.118   c8-48        <none>       <none>
nginx                1/1     Running   0          72m     10.244.2.84    ubuntu-210   <none>       <none>
pod-redis            1/1     Running   0          11h     10.244.1.67    ubuntu-220   <none>       <none>
tomcat-sc            0/1     Pending   0          4h57m   <none>         <none>       <none>       <none>
volume-nfs-redis     1/1     Running   1          24h     10.244.2.72    ubuntu-210   <none>       <none>

#验证ConfigMap是否生效,可看到更改的端口已生效
[root@ubuntu-200 ~]# kubectl exec configmap-env-demo -- netstat -tnl
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       
tcp        0      0 0.0.0.0:8080            0.0.0.0:*               LISTEN  

范例2:基于存储卷引用

格式1:挂载ConfigMap中所有值

  volumes:
  - name: nginxconfs
    configMap:
      name: nginx-config    #ConfigMap的名称
      optional: false

格式2:挂载ConfigMap中的部分值

  volumes:
  - name: nginxconfs
    configMap:
      name: nginx-confs #ConfigMap的名称
      items:
      - key: envoy.yaml
        path: envoy.yaml
        mode: 0644
      - key: lds.conf
        path: lds.conf
        mode: 0644
      optional: false #是否为必要选项,false表示必要,true表示非必要.
#查看名为nginx-config的ConfigMap
[root@ubuntu-200 ~]# kubectl describe cm nginx-config 
Name:         nginx-config
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
myserver.conf:
----
server {
    listen 8080;
    server_name  localhost;
  
    location / {
  root /usr/share/nginx/html;
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }

}

Events:  <none>

#编写Pod资源清单,在清单中引用ConfigMap
[root@ubuntu-200 ~]# cat configmap-volume.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: configmap-volume
  namespace: default
spec:
  containers:
  - name: nginx-server
    image: nginx:alpine
    volumeMounts:
    - name: nginxconfs
      mountPath: /etc/nginx/conf.d/
      readOnly: true
  volumes:
  - name: nginxconfs
    configMap:
      name: nginx-config
      optional: false

#创建pod
[root@ubuntu-200 ~]# kubectl apply -f configmap-volume.yaml

#查看pod并访问
[root@ubuntu-200 ~]# kubectl get pods -o wide
NAME                 READY   STATUS    RESTARTS   AGE     IP             NODE         NOMINATED NODE   READINESS GATES
configmap-env-demo   1/1     Running   0          30m     10.244.5.118   c8-48        <none>           <none>
configmap-volume     1/1     Running   0          10m     10.244.5.122   c8-48        <none>           <none>
[root@ubuntu-200 ~]# curl 10.244.5.122:8080
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
         35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

#进入Pod查看配置文件
[root@ubuntu-200 ~]# kubectl exec -it configmap-volume -- /bin/sh
/ # cat /etc/nginx/conf.d/myserver.conf
server {
    listen 8080;
    server_name  localhost;
    
    location / {
    root /usr/share/nginx/html;
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }

}

2 Secret

Secret解决了密码、token、秘钥等敏感数据的配置问题,而不需要把这些敏感数据暴露到镜像或者Pod Spec中。Secret可以以Volume或者环境变量的方式使用。

Secret根据用途存在类型的概念,如下:

#调用方法
Secret资源,使用环境变量 

containers:
- name: …
  image: …
  env:
  - name: <string>       # 变量名,其值来自于某Secret对象上的指定键的值;
    valueFrom:            # 键值引用; 
      secretKeyRef:       
        name: <string>    # 引用的Secret对象的名称,需要与该Pod位于同一名称空间;
        key: <string>     # 引用的Secret对象上的键,其值将传递给环境变量;
        optional: <boolean> # 是否为可选引用;
  envFrom:                 # 整体引用指定的Secret对象的全部键名和键值;
  - prefix: <string>     # 将所有键名引用为环境变量时统一添加的前缀;
secretRef:        
  name: <string>     # 引用的Secret对象名称;
  optional: <boolean> # 是否为可选引用;

1、docker-registry:专用于让kubelet启动Pod时从私有镜像仓库pull镜像时,首先认证到Registry时使用;

Docker Registry类型,也是独特类型:

#语法
# kubectl create secret docker-registry my-secret --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL

也能从dokcer的认证文件中加载信息,这时使用--from-file选项;

$HOME/.dockercfg, ~/.docker/config.json

何时引用,以及如何引用

pod.spec.imagePullSecrets

2、tls:专门用于保存tls/ssl用到证书和配对的私钥;

TLS类型是一种独特点类型,在创建secret的命令行中,除了类型标识的不同之外,它还需要使用专用的选项--cert和--key。

无论证书和私钥文件名是什么,它们会被统一为tls.key和tls.crt

#创建私钥
[root@ubuntu-200 /data/crt]# (umask 077;openssl genrsa -out nginx.key 2048)
Generating RSA private key, 2048 bit long modulus (2 primes)
.........................+++++
................................................+++++
e is 65537 (0x010001)

#创建自签名证书
[root@ubuntu-200 /data/crt]# openssl req -new -x509 -key nginx.key -out nginx.crt -subj /C=CN/ST=Beijing/L=Beijing/O=Devops/CN=www.magedu.com
[root@ubuntu-200 /data/crt]# ls
nginx.crt  nginx.key

#创建Secret
[root@ubuntu-200 /data/crt]# kubectl create secret tls nginx-ssl-secret --key=/data/crt/nginx.key  --cert=/data/crt/nginx.crt 
secret/nginx-ssl-secret created

#查看Secret
[root@ubuntu-200 /data/crt]# kubectl get secrets 
NAME                  TYPE                                  DATA   AGE
default-token-tdksz   kubernetes.io/service-account-token   3      9d
mysql-root-auth       Opaque                                2      47m
nginx-ssl-secret      kubernetes.io/tls                     2      78s
web-basic-authn       kubernetes.io/basic-auth              2      31m

3、generic:余下通用配置;可以存在的子类型

--type="kubernetes.io/basic-auth"

--type="kubernetes.io/rbd"

--type="kubernetes.io/ssh-auth"

另外,保存有专用于ServiceAccount的相关的token信息的Secret资源会使用资源注解来保存其使用场景。

资源的元数据:除了name,namespace之外,常用的还有labels,annotations(资源注解);

(1)annotation的名称遵循类似于labels的名称命名格式,但其数据长度不受限制;

(2)它不能用于被标签选择器作为筛选条件;但常用于为那些仍处于Beta阶段点应用程序提供临时的配置接口;

(3)管理命令:

添加注解:kubectl annotate TYPE/NAME KEY=VALUE

删除注解:kubectl annotate TYPE/NAME KEY-

还有一种由kubeadm的bootstrap所使用的token专用的类型,它通常保存于kube-system名称空间,以bootstrap-token-为前缀。

 

范例1:命令创建Secret

#创建Secret
[root@ubuntu-200 ~]# kubectl create secret generic mysql-root-auth --from-literal=username=root --from-literal=password=123456

#查看创建的Secret
[root@ubuntu-200 ~]# kubectl get secrets 
NAME                  TYPE                                  DATA   AGE
default-token-tdksz   kubernetes.io/service-account-token   3      9d
mysql-root-auth       Opaque                                2      71s
[root@ubuntu-200 ~]# kubectl describe secrets mysql-root-auth 
Name:         mysql-root-auth
Namespace:    default
Labels:       <none>
Annotations:  <none>

Type:  Opaque

Data
====
password:  6 bytes
username:  4 bytes

[root@ubuntu-200 ~]# kubectl get secrets mysql-root-auth -o yaml      
apiVersion: v1
data:
  password: MTIzNDU2    #看似加密,实际是base64编码
  username: cm9vdA==
kind: Secret
metadata:
  creationTimestamp: "2020-12-11T13:40:16Z"
  managedFields:
  - apiVersion: v1
    fieldsType: FieldsV1
    fieldsV1:
      f:data:
        .: {}
        f:password: {}
        f:username: {}
      f:type: {}
    manager: kubectl-create
    operation: Update
    time: "2020-12-11T13:40:16Z"
  name: mysql-root-auth
  namespace: default
  resourceVersion: "1114872"
  selfLink: /api/v1/namespaces/default/secrets/mysql-root-auth
  uid: 1acde185-0ad9-4fce-be1a-2547dad974ab
type: Opaque
#用base64 -d进行解码
[root@ubuntu-200 ~]# echo "MTIzNDU2" | base64 -d
123456

#创建特定标签的generic
[root@ubuntu-200 ~]# kubectl create secret generic web-basic-authn --from-literal=username=devopser --from-literal=password=123456 --type="kubernetes.io/basic-auth"
secret/web-basic-authn created
[root@ubuntu-200 ~]# kubectl get secrets 
NAME                  TYPE                                  DATA   AGE
default-token-tdksz   kubernetes.io/service-account-token   3      9d
mysql-root-auth       Opaque                                2      15m
web-basic-authn       kubernetes.io/basic-auth              2      9s

2.2 secret的调用

范例1: 环境变量引用

使用环境变量传递值的,只有在第一次调用时生效,启用过后修改不起作用.

#编辑资源清单
[root@ubuntu-200 ~]# cat secret-env.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: secret-env
  namespace: default
spec:
  containers:
  - name: mysql
    image: mysql
    imagePullPolicy: IfNotPresent
    env:
    - name: MYSQL_ROOT_PASSWORD
      valueFrom:
        secretKeyRef:
          name: mysql-root-auth        #调用的secret
          key: password                #调用secret中的卷

#创建pod
[root@ubuntu-200 ~]# kubectl apply -f secret-env.yaml

#查看pod是否正常运行
[root@ubuntu-200 ~]# kubectl get pods
NAME         READY   STATUS    RESTARTS   AGE
secret-env   1/1     Running   0          9m18s

#进入容器测试,使用secret中的密码进行登录
[root@ubuntu-200 ~]# kubectl exec -it secret-env -- bash
root@secret-env:/# mysql -uroot -p123456    
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or g.
Your MySQL connection id is 8
Server version: 8.0.22 MySQL Community Server - GPL

Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or 'h' for help. Type 'c' to clear the current input statement.

mysql> exit
Bye

范例2: 存储卷挂载

#编写资源清单
[root@ubuntu-200 ~]# cat secret-volume.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: secret-volume
  namespace: default
spec:
  containers:
  - name: ngx-server
    image: nginx:alpine
    volumeMounts:
    - name: nginxcerts
      mountPath: /etc/nginx/certs/
      readOnly: true
    - name: nginxconfs
      mountPath: /etc/nginx/conf.d/
      readOnly: true
  volumes:
  - name: nginxcerts    
    secret:
      secretName: nginx-ssl-secret    #确保引用的secret存在
  - name: nginxconfs
    configMap:
      name: nginx-sslvhosts-confs    #确保引用的configMap存在
      optional: false

#创建ConfigMap
[root@ubuntu-200 /data/sslconf]# cat myserver.conf 
server {
    listen 443 ssl;
    server_name www.1234.com;

    ssl_certificate /etc/nginx/certs/tls.crt; 
    ssl_certificate_key /etc/nginx/certs/tls.key;

    ssl_session_timeout 5m;

    ssl_protocols TLSv1 TLSv1.1 TLSv1.2; 

    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE; 
    ssl_prefer_server_ciphers on;

    include /etc/nginx/conf.d/myserver-*.cfg;

    location / {
        root /usr/share/nginx/html;
    }
}

server {
    listen 80;
    server_name www.ilinux.io; 
    return 301 https://$host$request_uri; 
}
[root@ubuntu-200 /data/sslconf]# cat myserver-gzip.cfg
gzip on;
gzip_comp_level 5;
gzip_proxied     expired no-cache no-store private auth;
gzip_types text/plain text/css application/xml text/javascript;
[root@ubuntu-200 /data/sslconf]# cat myserver-status.cfg
location /nginx-status {
    stub_status on;
    access_log off;
}
#创建ConfigMap
[root@ubuntu-200 /data/sslconf]# kubectl create configmap nginx-sslvhosts-confs --from-file=/data/sslconf/

#查看引用的ConfigMap是否存在,如不存在则创建
[root@ubuntu-200 ~]# kubectl get configmaps 
NAME                    DATA   AGE
configmap-app           2      36h
configmap-demo          2      36h
demoapp-config          2      2d18h
name                    1      38h
nginx-config            1      35h
nginx-sslvhosts-confs   3      15m
test-configmap          2      38h
test2                   2      38h
test3                   2      38h

[root@ubuntu-200 ~]# kubectl describe configmaps nginx-sslvhosts-confs
Name:         nginx-sslvhosts-confs
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
myserver.conf:
----
server {
    listen 443 ssl;
    server_name www.1234.com;

    ssl_certificate /etc/nginx/certs/tls.crt; 
    ssl_certificate_key /etc/nginx/certs/tls.key;

    ssl_session_timeout 5m;

    ssl_protocols TLSv1 TLSv1.1 TLSv1.2; 

    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE; 
    ssl_prefer_server_ciphers on;

    include /etc/nginx/conf.d/myserver-*.cfg;

    location / {
        root /usr/share/nginx/html;
    }
}

server {
    listen 80;
    server_name www.ilinux.io; 
    return 301 https://$host$request_uri; 
}

myserver-gzip.cfg:
----
gzip on;
gzip_comp_level 5;
gzip_proxied     expired no-cache no-store private auth;
gzip_types text/plain text/css application/xml text/javascript;

myserver-status.cfg:
----
location /nginx-status {
    stub_status on;
    access_log off;
}

Events:  <none>

#创建pod
[root@ubuntu-200 ~]# kubectl apply -f secret-volume.yaml 
[root@ubuntu-200 ~]# kubectl get pods
NAME            READY   STATUS    RESTARTS   AGE
secret-env      1/1     Running   0          50m
secret-volume   1/1     Running   0          18m

#进入pod测试
[root@ubuntu-200 ~]# kubectl exec secret-volume -it -- sh
#可看到已监听443端口
/ # netstat -tnl
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      
tcp        0      0 0.0.0.0:443             0.0.0.0:*               LISTEN      
/ # ifconfig 
eth0      Link encap:Ethernet  HWaddr B2:1C:CA:F1:44:9E  
          inet addr:10.244.2.108  Bcast:10.244.2.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1450  Metric:1
          RX packets:6 errors:0 dropped:0 overruns:0 frame:0
          TX packets:1 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:488 (488.0 B)  TX bytes:42 (42.0 B)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
#访问测试
/ # curl -H "Host:www.1234.com" https://10.244.2.108:443
curl: (60) SSL certificate problem: self signed certificate
More details here: https://curl.haxx.se/docs/sslcerts.html

curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.
/ # curl -k -H "Host:www.1234.com" https://10.244.2.108:443
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
         35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

3 downwardAPI存储卷类型

从严格意义上来说好,downwardAPI不是存储卷,它自身就存在,原因在于,它引用的是Pod自身的运行环境信息,这些信息在Pod启动时就存在

类似于ConfigMap和Secret资源,容器能够在环境变量中在valueFrom字段中嵌套fieldRef或resourceFieldRef字段来引用其所属Pod对象的元数据信息.不过,通常只有常量类型的属性才能通过环境变量注入到容器中,毕竟,在进程启动完成后无法再向其告知变量值的变动,于是环境变量也就不支持中途的更新操作.容器规范中可以在环境变量配置中的valueFrom通过内嵌字段filedRef引用的信息包括如下这些:

3.1 第一类:

  1.metadata.name:Pod对象的名称;

  2.metadata.namespace:Pod对象隶属的名称空间;

  3.metadata.uid:Pod对象的UID;

  4.metadata.labels['<KEY>']:Pod对象标签中的指定键的值,例如:metadata.labels['mylabel'],仅Kubernetes 1.9及之后的版本才支持;

  5.metadata.annotations['<KEY>']:Pod对象注解信息中的指定键的值,仅Kubernetes 1.9及之后的版本才支持。

3.2 第二类:容器上的计算资源需求和资源限制相关的信息,以及临时存储资源需求和资源限制相关的信息可通过容器规范中的resourceFieldRef字段引用,相关字段包括requests.cpu、limits.cpu、requests.memory和limits.memory等。另外,可通过环境变量引用的信息有如下几个:

  1. status.podIP:Pod对象的IP地址

  2. spec.serviceAccountName:Pod对象使用的ServiceAccount资源名称

  3. spec.nodeName:节点名称

  4. status.hostIP:节点IP地址

3.3 第三类:还可以通过resourceFieldRef字段引用当前容器的资源请求及资源限额的定义,因此它们包括以下6项:

  1. requests.cpu

  2. requests.memory

  3. requests.ephemeral-storage

  4. limits.cpu

  5. limits.memory

  6. limits.ephemeral-storage

范例1:直接引用

#编辑资源清单
[root@ubuntu-200 ~]# cat downwardAPI-01.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: downwardapi-01
  labels:
    app: demoapp
spec:
  containers:
  - name: demoapp
    image: ikubernetes/demoapp:v1.0
#    command: [ "/bin/sh", "-c", "env" ]
    resources:
      requests:
        memory: "32Mi"
        cpu: "250m"
      limits:
        memory: "64Mi"
        cpu: "500m"
    env:
    - name: THIS_POD_NAME
      valueFrom:
        fieldRef:
            fieldPath: metadata.name
    - name: THIS_POD_MAMESPACE
      valueFrom:
        fieldRef:
          fieldPath: metadata.namespace
    - name: THIS_APP_LABEL
      valueFrom:
        fieldRef:
          fieldPath: metadata.labels['app']
    - name: THIS_CPU_LIMIT
      valueFrom:
        resourceFieldRef:
          resource: limits.cpu
    - name: THIS_MEM_REQUEST
      valueFrom:
        resourceFieldRef:
          resource: requests.memory
          divisor: 1Mi
#  restartPolicy: Never

#创建pod
[root@ubuntu-200 ~]# kubectl apply -f downwardAPI-01.yaml 
pod/downwardapi-01 created

#查看pod
[root@ubuntu-200 ~]# kubectl get pods 
NAME             READY   STATUS    RESTARTS   AGE
downwardapi-01   1/1     Running   0          5s
secret-env       1/1     Running   0          102m
secret-volume    1/1     Running   0          69m

#进入容器内部查看
[root@ubuntu-200 ~]# kubectl exec downwardapi-01 -it -- sh
[root@downwardapi-01 /]# env 
NGINX_SERVICE_PORT_81_TCP_PROTO=tcp
KUBERNETES_SERVICE_PORT=443
KUBERNETES_PORT=tcp://10.96.0.1:443
HOSTNAME=downwardapi-01
THIS_CPU_LIMIT=1    #自定义的
THIS_APP_LABEL=demoapp    #自定义的
SHLVL=1
HOME=/root
NGINX_SERVICE_PORT_81_TCP=tcp://10.96.57.111:81
THIS_MEM_REQUEST=32    #自定义的
PS1=[u@h w]$ 
NGINX_SERVICE_SERVICE_PORT_HTTP=81
MYSQL_SERVICE_SERVICE_PORT_HTTP=8080
TERM=xterm
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
NGINX_SERVICE_SERVICE_HOST=10.96.57.111
THIS_POD_NAME=downwardapi-01    #自定义的
KUBERNETES_PORT_443_TCP_PORT=443
KUBERNETES_PORT_443_TCP_PROTO=tcp
MYSQL_SERVICE_PORT_8080_TCP_ADDR=10.96.27.252
MYSQL_SERVICE_SERVICE_HOST=10.96.27.252
MYSQL_SERVICE_PORT_8080_TCP_PORT=8080
MYSQL_SERVICE_PORT_8080_TCP_PROTO=tcp
DEPLOYENV=Production
NGINX_SERVICE_PORT=tcp://10.96.57.111:81
NGINX_SERVICE_SERVICE_PORT=81
MYSQL_SERVICE_SERVICE_PORT=8080
MYSQL_SERVICE_PORT=tcp://10.96.27.252:8080
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
RELEASE=Stable
KUBERNETES_SERVICE_HOST=10.96.0.1
PWD=/
THIS_POD_MAMESPACE=default    #自定义的
NGINX_SERVICE_PORT_81_TCP_ADDR=10.96.57.111
MYSQL_SERVICE_PORT_8080_TCP=tcp://10.96.27.252:8080
NGINX_SERVICE_PORT_81_TCP_PORT=81

范例2:存储卷挂载

#编写资源清单
[root@ubuntu-200 ~]# cat downwardAPI-01.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: downwardapi-01
  labels:
    app: demoapp
spec:
  containers:
  - name: demoapp
    image: ikubernetes/demoapp:v1.0
#    command: [ "/bin/sh", "-c", "env" ]
    resources:
      requests:
        memory: "32Mi"
        cpu: "250m"
      limits:
        memory: "64Mi"
        cpu: "500m"
    env:
    - name: THIS_POD_NAME
      valueFrom:
        fieldRef:
            fieldPath: metadata.name
    - name: THIS_POD_MAMESPACE
      valueFrom:
        fieldRef:
          fieldPath: metadata.namespace
    - name: THIS_APP_LABEL
      valueFrom:
        fieldRef:
          fieldPath: metadata.labels['app']
    - name: THIS_CPU_LIMIT
      valueFrom:
        resourceFieldRef:
          resource: limits.cpu
    - name: THIS_MEM_REQUEST
      valueFrom:
        resourceFieldRef:
          resource: requests.memory
          divisor: 1Mi
#  restartPolicy: Never

#创建pod
[root@ubuntu-200 ~]# kubectl apply -f downwardAPI-volume.yaml 
pod/dapi-vol-pod created
#查看pod
[root@ubuntu-200 ~]# kubectl get pods
NAME             READY   STATUS    RESTARTS   AGE
dapi-vol-pod     1/1     Running   0          5s
downwardapi-01   1/1     Running   0          25m
secret-env       1/1     Running   0          127m
secret-volume    1/1     Running   0          95m

#进入pod查看
[root@ubuntu-200 ~]# kubectl exec -it dapi-vol-pod -- sh
[root@dapi-vol-pod /]# cd /etc/podinfo/
[root@dapi-vol-pod /etc/podinfo]# ls
cpu_limit        mem_request      pod_annotations  pod_labels       pod_namespace
[root@dapi-vol-pod /etc/podinfo]# cat cpu_limit 
[root@dapi-vol-pod /etc/podinfo]# cat mem_request 
[root@dapi-vol-pod /etc/podinfo]# cat pod_annotations 
ilinux.io/app="demoapp"
kubectl.kubernetes.io/last-applied-configuration="{"apiVersion":"v1","kind":"Pod","metadata":{"annotations":{"ilinux.io/app":"demoapp"},"labels":{"app":"dapi-vol-pod","rack":"rack-101","zone":"east-china"},"name":"dapi-vol-pod","namespace":"default"},"spec":{"containers":[{"image":"ikubernetes/demoapp:v1.0","name":"volume-test-container","resources":{"limits":{"cpu":"500m","memory":"64Mi"},"requests":{"cpu":"200m","memory":"32Mi"}},"volumeMounts":[{"mountPath":"/etc/podinfo","name":"podinfo","readOnly":false}]}],"volumes":[{"downwardAPI":{"defaultMode":420,"items":[{"fieldRef":{"fieldPath":"metadata.namespace"},"path":"pod_namespace"},{"fieldRef":{"fieldPath":"metadata.labels"},"path":"pod_labels"},{"fieldRef":{"fieldPath":"metadata.annotations"},"path":"pod_annotations"},{"path":"cpu_limit","resourceFieldRef":{"containerName":"volume-test-container","resource":"limits.cpu"}},{"path":"mem_request","resourceFieldRef":{"containerName":"volume-test-container","divisor":"1Mi","resource":"requests.memory"}}]},"name":"podinfo"}]}}
"
kubernetes.io/config.seen="2020-12-12T03:43:53.245628998Z"
kubernetes.io/config.source="api"[root@dapi-vol-pod /etc/podinfo]# 
#如果引用的选项有多个,会以键值对的形式生成在pod内
[root@dapi-vol-pod /etc/podinfo]# cat pod_labels 
app="dapi-vol-pod"
rack="rack-101"
zone="east-china"

免责声明:文章转载自《K8S存储之特殊存储(ConfigMap、Secret和downwardAPI)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇JMeter执行性能测试如何快速确定拐点Flexigrid详解下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

win32-localtime的使用

下面的例子用于反映本地系统的日期格式变化 // locale test #include <stdio.h> #include <locale.h> #include <time.h> #include <locale> #include <Windows.h> #pragma warning(...

如何用IDEA创建springboot(maven)并且整合mybatis连接mysql数据库和遇到的问题

一、New->Project 二、点击next  三、在Group栏输入组织名,Artifact就是项目名。选择需要的java版本,点击next  四、添加需要的依赖 在这里我们也可以添加sql方面的依赖,这样的话,我们就不用手动在pom文件添加依赖了  五、修改您希望放项目的位置,点击finish,等待idea下载springboot项目模板...

从零开始的react入门教程(五),了解react中的表单,何为受控组件与非受控组件

壹 ❀ 引 我们在从零开始的react入门教程(四),了解常用的条件渲染、列表渲染与独一无二的key一文中介绍了react中常用的条件渲染操作,比如三元运算符,逻辑运算符等,结合react组件或者react元素,我们能做到很多视图层的切换效果。 除此之外我们也介绍了react中的渲染操作,不同于vue类似框架使用循环指令,react中直接使用数组API达...

Visual Studio中你所不知道的智能感知

在Visual Studio中的智能感知,相信大家都用过。summary,param,returns这几个相信很多人都用过的吧。那么field,value等等这些呢。 首先在Visual Studio中支持的JavaScript智能感知有以下6种 summary 用于方法和主体内容 param 用于方法的参数 field 用于类的属性 va...

WPF样式学习第一天

因为上班的公司要我用wpf写软件,刚毕业出来,学校也没教过wpf,只会winform,再加上wpf用winform的框架写法也能实现很多需求,但是就不能体现wpf的优点了,今天就先来学wpf的样式,因为对美的认识不足,所以排版不好,对代码有意见或建议的,希望多多提出,我是初学者。 今天就先弄个Button的简单样式吧 ButtonStyle是源名称。 P...

svg 直线水平渐变为什么没有效果,必须得是一条倾斜的不水平的直线才有渐变效果呢??

参考:https://blog.csdn.net/u012260672/article/details/80905631 对x1=x2(没有宽度)或者y1=y2(没有高度)的直线(line以及path,如果,stroke里使用的是渐变效果,那么,在各种浏览器上都会出现同一个BUG,这条线会消失。关键字objectBoundingBox这玩意儿,在元素没有宽...