21-【kubernetes】Kubernetes pv、pvc、configmap和secret

一、pv、pvc、StorageClass存储类

1、存在的问题:

  • pvc在申请时,未必会有现成的满足pvc申请条件的pv资源

2、解决方案:

  • 引入StorageClass(存储类—k8s的标准资源)。那么pvc在申请时,不直接申请pv,而是向StorageClass存储类进行申请,然后StorageClss存储类再根据pvc的申请条件,动态创建,满足pvc申请条件的pv资源。前提条件:【1】、StorageClass存储类能够符合pvc申请条件;【2】、存储设备必须支持RestFul风格的请求创建接口
  • 举例:以cephfs类型的存储为例,比如现在有4PB的空间。当pvc的申请条件中指定的存储大小是20GB时,pvc会通过RestFull接口,请求立即划分出一个20GB大小的image(分区),并且将image(分区)格式化完成,然后通过cephfs输出出来,之后在集群中,定义成20GB的pv,接着,pv和pvc进行绑定。
  • 注意:有些类型的volume不支持StorageClass(比如nfs类型的volume不支持StorageClass)

二、配置容器化应用的方式

1、自定义命令行参数

[root@master volumes]# kubectl explain pod.spec.containers
   args <[]string>

2、把配置文件直接焙进镜像(不建议)

3、环境变量

  1. Cloud Native的应用程序一般可直接通过环境变量加载配置;(应用程序支持,直接通过环境变量,来加载配置信息)
  2. 通过预处理脚本(entrypoint脚本)来预处理为配置文件中的配置信息。
[root@master volumes]# kubectl explain pod.spec.containers.env
   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>
     Source for the environment variable's value. Cannot be used if value is not
     empty.



[root@master volumes]# kubectl explain pod.spec.containers.env.valueFrom
   configMapKeyRef      <Object>
     Selects a key of a ConfigMap.

   fieldRef     <Object>
     Selects a field of the pod: supports metadata.name, metadata.namespace,
     metadata.labels, metadata.annotations, spec.nodeName,
     spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs.

   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>
     Selects a key of a secret in the pod's namespace

4、存储卷

三、configmap和secret引入的背景

  • 让配置信息与镜像文件解耦,镜像可以做成一个骨架,配置信息可以通过configmap注入。所以,可以使得一个镜像文件可以应付多种不同配置情况下,为应用程序运行不同配置的环境而工作。从而增强了应用的可移植性,和可复用性。

四、configmap和secret资源的两种使用方式:

  1. 变量注入的方式,给Pod中的容器传递,配置信息:Pod启动时,可以把configmap资源关联到当前Pod上,从中读取一些数据,传递给Pod内容器的某个变量。
  2. 存储卷的方式:把configmap资源作为存储卷,挂载到Pod中的容器的某个目录下,此目录正好是运行程序要读取配置信息的文件所在的目录。

五、configmap(明文存储数据)—简称为cm

[root@master volumes]# kubectl explain configmap

   apiVersion   <string>
 
   binaryData   <map[string]string>    #二进制格式的键值对
  
   data <map[string]string>    #键值对

   immutable    <boolean>
    
   kind <string>

   metadata     <Object>

(1)创建configmap的方式一:命令行方式创建

#在命令行创建一个configmap
[root@master volumes]# kubectl create configmap --help
...
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
  
  # Create a new configmap named my-config from an env file
  kubectl create configmap my-config --from-env-file=path/to/bar.env

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

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

#其中--from-file表示从文件中加载数据,key值是文件名,value值是文件中的数据;--from-literal表示从命令行传入数据。

【1】、方式一:使用--from-literal引入配置

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

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

【2】、方式二:使用--from-file引入配置

[root@master manifests]# mkdir configmap
[root@master manifests]# cd configmap/
[root@master configmap]# vim www.conf
server{
        server_name myapp.magedu.com;
        listen 80;
        root /data/web/html;
}



[root@master configmap]# kubectl create configmap nginx-www --from-file=www.conf


[root@master configmap]# kubectl get cm
NAME           DATA   AGE
nginx-config   2      7m23s
nginx-www      1      5s

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

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

Events:  <none>

(2)创建configmap的方式二:配置文件的方式创建

1、使用方式一(变量注入的方式):

[root@master configmap]# vim pod-configmap.yaml
apiVersion: v1
kind: Pod
metadata: 
        name: pod-cm-1
        namespace: default
        labels:
                app: myapp
                tier: frontend
spec:
        containers:
        - name: myapp
          image: ikubernetes/myapp:v1
          ports:
          - name: http
            containerPort: 80
          env:
          - name: NGINX_SERVER_PORT
            valueFrom:
                configMapKeyRef:
                        name: nginx-config
                        key: nginx_port     #把key=nginx_port的value值赋给容器中的NGINX_SERVER_PORT
          - name: NGINX_SERVER_NAME     
            valueFrom:
                configMapKeyRef:
                        name: nginx-config
                        key: server_name     #把key=server_name的value值赋给容器中的NGINX_SERVER_NAME



[root@master configmap]# kubectl apply -f pod-configmap.yaml 


[root@master configmap]# kubectl get pods pod-cm-1
NAME       READY   STATUS    RESTARTS   AGE
pod-cm-1   1/1     Running   0          2m4s


[root@master configmap]# kubectl describe pod pod-cm-1    #可以看到configmap的配置信息已经传递成功
...
    Environment:
      NGINX_SERVER_PORT:  <set to the key 'nginx_port' of config map 'nginx-config'>   Optional: false
      NGINX_SERVER_NAME:  <set to the key 'server_name' of config map 'nginx-config'>  Optional: false
...


#进入pod-cm-1再次进行验证
[root@master configmap]# kubectl exec -it pod-cm-1 -- /bin/sh
/ # env        #也可以输入命令:printenv
...
NGINX_SERVER_PORT=80
NGINX_SERVER_NAME=myapp.magedu.com
...
  • 此方式的缺点在于:如果configmap中的信息发生了变化,注入到Pod中的容器的配置信息并不会发生变化。即做不到实时更新变化
[root@master configmap]# kubectl edit cm nginx-config
...
data:
  nginx_port: "8080"      #把原来的80改为8080
  server_name: myapp.magedu.com
...


[root@master configmap]# kubectl describe cm nginx-config
...
Data
====
nginx_port:     #可以看到原来的80已经改为8080
----
8080
server_name:
----
myapp.magedu.com
...


[root@master configmap]# kubectl exec -it pod-cm-1 -- env
...
NGINX_SERVER_PORT=80       #可以看到Pod中的环境变量的端口信息还是原来的80,而非8080。
NGINX_SERVER_NAME=myapp.magedu.com

2、使用方式二(存储卷的方式):

【1】、案例一:

[root@master configmap]# vim pod-configmap-2.yaml 
apiVersion: v1
kind: Pod
metadata: 
        name: pod-cm-2
        namespace: default
        labels:
                app: myapp
                tier: frontend
spec:
        containers:
        - name: myapp
          image: ikubernetes/myapp:v1
          ports:
          - name: http
            containerPort: 80
          volumeMounts:
          - name: nginxconf
            mountPath: /etc/nginx/config.d     #这个目录如果不存在的话,会新建
            readOnly: true
        volumes:
        - name: nginxconf
          configMap:
                name: nginx-config



[root@master configmap]# kubectl apply -f pod-configmap-2.yaml 


[root@master configmap]# kubectl get pod pod-cm-2
NAME       READY   STATUS    RESTARTS   AGE
pod-cm-2   1/1     Running   0          7s


[root@master configmap]# kubectl exec -it pod-cm-2 -- /bin/sh
/ # ls -l /etc/nginx/config.d/      #可以看到nginx_port和server_name这两个文件是链接文件,链接的目的地不是真实存在的(特殊的路径)。即其实是多次链接之后,链接到configmap存储卷上
total 0
lrwxrwxrwx    1 root     root            17 Oct 13 10:48 nginx_port -> ..data/nginx_port
lrwxrwxrwx    1 root     root            18 Oct 13 10:48 server_name -> ..data/server_name
/ # cd /etc/nginx/config.d/      #可以看到configmap的信息挂载到容器中之后,把configmap中的key值作为文件名,configmap中的value值作为文件的内容。
/etc/nginx/config.d # ls
nginx_port   server_name
/etc/nginx/config.d # cat nginx_port 
8080
/etc/nginx/config.d # cat server_name 
myapp.magedu.com/
  • 此方式的优点:如果configmap中的信息发生了变化,注入到Pod中的容器的配置信息会跟着发生变化。即可以做到实时更新变化
[root@master configmap]# kubectl edit cm nginx-config
...
  nginx_port: "8088"
  server_name: myapp.magedu.com


[root@master configmap]# kubectl exec -it pod-cm-2 -- /bin/sh    #注意同步需要一定的时间,因为信息是先同步到apiServer上,然后再同步到Pod上。
/ # cat /etc/nginx/config.d/nginx_port 
8088

【2】、案例二:

[root@master configmap]# vim pod-configmap-3.yaml 
apiVersion: v1
kind: Pod
metadata: 
        name: pod-cm-3
        namespace: default
        labels:
                app: myapp
                tier: frontend
spec:
        containers:
        - name: myapp
          image: ikubernetes/myapp:v1
          ports:
          - name: http
            containerPort: 80
          volumeMounts:
          - name: nginxconf
            mountPath: /etc/nginx/conf.d     #挂载到nginx中存放虚拟主机文件(.conf)的目录下
            readOnly: true
        volumes:
        - name: nginxconf
          configMap:
                name: nginx-www     #nginx-www这个配置项中的key值是www.conf,value值是关于虚拟主机的配置


[root@master configmap]# kubectl apply -f pod-configmap-3.yaml 
[root@master configmap]# kubectl exec -it pod-cm-3 -- /bin/sh
/ # ls /etc/nginx/conf.d/
www.conf
/ # nginx -T       #查看nginx加载的配置,从下面可以看到,nginx加载了nginx-www配置项中的配置
...
# configuration file /etc/nginx/conf.d/www.conf:
server{
        server_name myapp.magedu.com;
        listen 80;
        root /data/web/html;
}

/ # mkdir -p /data/web/html
/ # vi /data/web/html/index.html
<h1>Nginx Server configured by CM</h1>
#测试过程:
[root@master configmap]# kubectl get pods pod-cm-3 -o wide
NAME       READY   STATUS    RESTARTS   AGE   IP             NODE     NOMINATED NODE   READINESS GATES
pod-cm-3   1/1     Running   0          10m   10.244.1.124   node01   <none>           <none>
  

#1、测试1:在任意一个节点上添加解析
[root@,master ~]# vim /etc/hosts      
10.244.1.124    myapp.magedu.com
[root@master ~]# curl myapp.magedu.com
<h1>Nginx Server configured by CM</h1>


[root@node01 ~]# vim /etc/hosts      
10.244.1.124    myapp.magedu.com
[root@node01 ~]# curl myapp.magedu.com
<h1>Nginx Server configured by CM</h1>


[root@node02 ~]# vim /etc/hosts      
10.244.1.124    myapp.magedu.com
[root@node02 ~]# curl myapp.magedu.com
<h1>Nginx Server configured by CM</h1>


#2、测试2:修改nginx-www配置项的内容之后,再次进行测试
[root@master configmap]# kubectl edit cm nginx-www
...
data:       #将下面监听的端口由原来的80改为8080
  www.conf: "server{\n\tserver_name myapp.magedu.com;\n\tlisten 8080;\n\troot /data/web/html;\n}\n"
...

[root@master configmap]# kubectl exec -it pod-cm-3 -- /bin/sh
/ # cat /etc/nginx/conf.d/www.conf     #可以看到配置文件中监听的端口已经改为了8080 
server{
        server_name myapp.magedu.com;
        listen 8080;
        root /data/web/html;
}


/ # nginx -T       #可以看到配置文件中监听的端口已经改为了8080
...
# configuration file /etc/nginx/conf.d/www.conf:
server{
        server_name myapp.magedu.com;
        listen 8080;
        root /data/web/html;
}


/ # netstat -antulpe      #但是发现,nginx实际监听的端口还是原来的80,并没有改为配置信息中的8080。此时需要重新加载一下nginx
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
2020/10/13 11:28:20 [notice] 33#33: signal process started
/ # netstat -antulpe     #此时可以看到nginx监听的端口由原来的80改为了8080
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




[root@master ~]# curl myapp.magedu.com:8080
<h1>Nginx Server configured by CM</h1>

[root@node01 ~]# curl myapp.magedu.com:8080
<h1>Nginx Server configured by CM</h1>

[root@node02 ~]# curl myapp.magedu.com:8080
<h1>Nginx Server configured by CM</h1>
  • 从上面的案例中可以看到,pod中的volume中指定的configmap的name字段之后,把该configmap中的全部信息都引入了,那么如何引入configmap中的部分信息呢?方法如下:
#在configmap字段中,写入items字段的信息
[root@master configmap]# kubectl explain pod.spec.volumes.configMap
   defaultMode  <integer>
   items        <[]Object>
   name <string>
   optional     <boolean>
    

[root@master configmap]# kubectl explain pod.spec.volumes.configMap.items
   key  <string> -required-        #指定要引入的configmap中的哪个key
     The key to project.

   mode <integer>
     Optional: mode bits to use on this file, must be a value between 0 and
     0777. If not specified, the volume defaultMode will be used. This might be
     in conflict with other options that affect the file mode, like fsGroup, and
     the result can be other mode bits set.

   path <string> -required-       #引入上面的key之后,挂载到Pod中的容器时,要不要把这个key作为文件名,所以这是要指定path(path可以与key相同,也可以与key不同)
     The relative path of the file to map the key to. May not be an absolute
     path. May not contain the path element '..'. May not start with the string
     '..'.

六、secret(不是明文存储数据的,而是通过一种编码机制存储数据的

参考文章:K8s 安全抽象:Secret|k8s,secret,tls,镜像拉取,环境变量|陈一乐

1、secret的三种类型:

[root@master configmap]# kubectl create secret --help
...
Available Commands:
  docker-registry Create a secret for use with a Docker registry
  generic         Create a secret from a local file, directory or literal value
  tls             Create a TLS secret
...

#如果存放的是(比如密码数据),则使用generic类型的secret;
#如果存放的是(比如私钥和证书数据),则使用tls类型的secret;
#如果存放的是Docker registry的认证信息,则使用docker-registry类型的secret。
(k8s节点为了运行Pod,而运行Pod需要获取容器的镜像,如果容器的镜像托管在必须要认证才能获取的私有镜像
仓库上的时候,kubelet要能够自动认证到私有仓库的机器上,然后指挥docker把镜像下载下来。那么这时就需要docker-registry类型的secret
1、创建docker-registry类型的secret,然后在Pod中定义使用
[root@master configmap]# kubectl explain pod.spec
...
   imagePullSecrets     <[]Object>

[root@master configmap]# kubectl explain pod.spec.imagePullSecrets
...
   name <string>      docker-registry类型的secret的名字

(1)generic类型的secret:创建方式类似于configmap的创建,在Pod中的两种使用方式也类似于configmap

[root@master configmap]# kubectl create secret generic --help
...

Usage:
  kubectl create secret generic NAME [--type=string] [--from-file=[key=]source] [--from-literal=key1=value1]
[--dry-run=server|client|none] [options]

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

Type:  Opaque

Data
====
password:  9 bytes      #可以看到这里并没有明文显示passwrod这个key对应的value值

[root@master configmap]# kubectl get secret mysql-root-password -o yaml
...
data:
  password: TXlQQHNzMTIz      #可以看到这里并没有明文显示passwrod这个key对应的value值,而显示是的经过base64这种编码方式,编码之后的结果
...


[root@master configmap]# echo TXlQQHNzMTIz | base64 -d     #使用base64这种编码方式进行解码,可以看到MyP@ss123。
MyP@ss123
[root@master manifests]# mkdir secret
[root@master manifests]# cd secret/
[root@master secret]# vim pod-secret.yaml
apiVersion: v1
kind: Pod
metadata: 
        name: pod-secret-1
        namespace: default
        labels:
                app: myapp
                tier: frontend
spec:
        containers:
        - name: myapp
          image: ikubernetes/myapp:v1
          ports:
          - name: http
            containerPort: 80
          env:
          - name: MYSQL_ROOT_PASSWORD
            valueFrom:
                secretKeyRef:
                        name: mysql-root-password
                        key: password


[root@master secret]# kubectl apply -f pod-secret.yaml 

[root@master secret]# kubectl get pods pod-secret-1
NAME           READY   STATUS    RESTARTS   AGE
pod-secret-1   1/1     Running   0          64s
[root@master secret]# kubectl exec -it pod-secret-1 -- printenv
...
MYSQL_ROOT_PASSWORD=MyP@ss123     #可以看到secret类型的配置信息已经导入了
...

(2)tls类型的secret

[root@master configmap]# kubectl create secret tls --help
...

Usage:
  kubectl create secret tls NAME --cert=path/to/cert/file --key=path/to/key/file [--dry-run=server|client|none]
[options]

...

(3)docker-registry类型的secret

[root@master configmap]# kubectl create secret docker-registry --help
...

Usage:
  kubectl create secret docker-registry NAME --docker-username=user --docker-password=password --docker-email=email
[--docker-server=string] [--from-literal=key1=value1] [--dry-run=server|client|none] [options]

...
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值