六、k8s之各组件介绍(二)Volume

原创
2020/10/14 10:23
阅读数 361

存储类型

  • configMap
  • Secret
  • volume
  • Persistent Volume

存储-ConfigMap

ConfigMap功能在k8s1.2引入,许多应用程序会从配置文件、命令行参数或环境变量中读取配置信息。ConfigMap API提供了向容器注入配置信息的机制。

ConfigMap可以用来保存单个属性,也可以用来保存整个配置文件或json二进制大对象。

ConfigMap的创建

1. 使用目录创建

$ ls /path/to/configmap/files/
	game.properties
  ui.properties
$ vim game.properties
  enemies=aliens
  lives=3
  enemies.cheat=true
  enemies.cheat.level=noGoodRotten
  secret.code.passphrase=UUDDLRLRBABAS
  secret.code.allowed=true
  secret.code.lives=30

$ vim ui.properties
	color.good=purple
	color.bad=yellow
	allow.textmode=true
	how.nice.to.look=failyNice
	
$ kubectl create configmap game-config --from-file=/path/to/configmap/files

--from-file 指定在目录下的所有文件都会被用在 ConfigMap 里面创建一个键值对 ,键的名字就是文件名,值就是文件的内容。

2. 使用文件创建

只要指定为一个文件就可以从单个文件中创建ConfigMap。

$ kubectl create configmap game-config-2 --from-file=/path/to/configmap/files/game.properties

# 查看配置信息
$ kubectl get configmaps game-config-2 -o yaml

--from-file 这个参数可以使用多次,你可以使用两次分别指定上个实例中的那两个配置文件,效果和指定整个目录是一样的。

3. 使用字面值创建

使用文字值创建,利用 --from-literal 参数传递配置信息,该参数可以使用多次,格式如下:

$ kubectl create configmap special-config --from-literal=special.how=very --from-literal=special.type=charm

$ kubectl get configmaps special-config -o yaml

Pod中使用 ConfigMap

1. 使用 ConfigMap 替代环境变量

special-config:

apiVersion: v1
kind: ConfigMap
metadata:
  name: special-config
  namespace: default
data:
  special.how: very
  special.type: charm

env-config:

apiVersion: v1
kind: ConfigMap
metadata:
  name: env-config
  namespace: default
data:
  log_level: INFO

eg:

apiVersion: v1
kind: Pod
metadata:
  name: dapi-test-pod
spec:
  containers:
    - name: test-container
      image: hub.adaixuezhang.cn/library/myapp:v1
      command: ["/bin/sh", "-c", "env"]
      env:
        - name: SPECIAL_LEVEL_KEY
          valueFrom:
            configMapKeyRef:
              name: special-config
              key: special.how
        - name: SPECIAL_TYPE_KEY
          valueFrom:
            configMapKeyRef:
              name: special-config
              key: special.type
      envFrom:
        - configMapRef:
            name: env-config
  restartPolicy: Never

2. 用 ConfigMap 设置命令行参数

apiVersion: v1
kind: ConfigMap
metadata:
  name: special-config
  namespace: default
data:
  special.how: very
  special.type: charm

pod:

apiVersion: v1
kind: Pod
metadata:
  name: dapi-test-pod
spec:
  containers:
    - name: test-container
      image: hub.adaixuezhang.cn/library/myapp:v1
      command: ["/bin/sh", "-c", "echo $(SPECIAL_LEVEL_KEY) $(SPECIAL_TYPE_KEY)"]
      env:
        - name: SPECIAL_LEVEL_KEY
          valueFrom:
            configMapKeyRef:
              name: special-config
              key: special.how
        - name: SPECIAL_TYPE_KEY
          valueFrom:
            configMapKeyRef:
              name: special-config
              key: special.type
      envFrom:
        - configMapRef:
            name: env-config
  restartPolicy: Never

3. 通过数据卷插件使用ConfigMap

apiVersion: v1
kind: ConfigMap
metadata:
  name: special-config
  namespace: default
data:
  special.how: very
  special.type: charm

在数据卷里面使用这个 ConfigMap,有不同的选项。最基本的就是将文件填入数据卷,在这个文件中,键就是文件名,键值就是文件内容。

apiVersion: v1
kind: Pod
metadata:
  name: dapi-test-pod
spec:
  containers:
    - name: test-container
        image: hub.adaixuezhang.cn/library/myapp:v1
      command: ["/bin/sh", "-c", "cat /etc/config/special.how"]
      volumeMounts:
        - name: config-volume
          mountPath: /etc/config
  volumes:
    - name: config-volume
      configMap:
        name: special-config
  restartPolicy: Never

ConfigMap的热更新

apiVersion: v1
kind: ConfigMap
metadata:
  name: log-config
  namespace: default
data:
  log_level: INFO
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nginx
spec:
  replicas: 1
  selector:
    matchLabels:
	    run: my-nginx
  template:
    metadata:
      labels:
        run: my-nginx
    spec:
      containers:
        - name: my-nginx
          image: hub.adaixuezhang.cn/library/myapp:v1
          ports:
            - containerPort: 80
          volumeMounts:
            - name: config-volume
              mountPath: /etc/config
          volumes:
            - name: config-volume
              configMap:
                name: log-config

检查:

$ kubectl exec `kubectl get pods -l run=my-nginx -o=name|cut -d "/" -f2` cat /etc/config/log_level

修改ConfigMap:

$ kubectl edit configmap log-config

特别注意:ConfigMap 如果以 ENV 的方式挂载至容器,修改ConfigMap并不会实现热更新!

ConfigMap更新后滚动更新Pod

更新ConfigMap目前并不会触发相关Pod的滚动更新,可以通过修改 Pod annotations 的方式强制触发滚动更新:

$ kubectl patch deployment my-nginx --patch '{"spec": {"template": {"metadata": {"annotations": {"version/config": "20200924"}}}}}'

如上在 .spec.template.metadata.annotations 中添加 version/config,每次通过修改 version/config 来触发滚动更新。

更新 ConfigMap 后

  • 使用该 ConfigMap 挂载的Env不会同步更新;
  • 使用该 ConfigMap 挂载的Volume中的数据需要一段时间(实测大概60s)才能同步更新。

存储-Secret

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

Secret有三种类型:

  • service account:用来访问k8s API,由k8s自动创建,并且会自动挂载到Pod的 /run/secrets/kubernetes.io/serviceaccount 目录中;
  • Opaque:base64编码格式的Secret,用来存储密码、密钥等;
  • kubernetes.io/dockerconfigjson:用来存储私有 docker registry 的认证信息。

Service Account

$ kubectl run nginx --image nginx
$ kubectl get pods
$ kubectl exec nginx-pod-id ls /run/secrets/kubernetes.io/serviceaccount

Opaque Secret

1. 创建说明

Opaque 类型的数据是一个 map 类型,要求 value 是 base64 编码格式:

$ echo -n "admin" |base64
YWRtaW4=
$ echo -n "12lkwghs873" |base64
MTJsa3dnaHM4NzM=

secrets.yaml

apiVersion: v1
kind: Secret
metadata:
  name: mysecret
type: Opaque
data:
  password: MTJsa3dnaHM4NzM=
  username: YWRtaW4=

2. 使用方式

  1. 将Secret挂载到Volume中

    apiVersion: v1
    kind: Pod
    metadata:
      labels:
        name: mysecret
      name: secret-test
    spec:
      volumes:
        - name: secrets
          secret:
            secretName: mysecret
      containers:
        - image: hub.adaixuezhang.cn/library/myapp:v1
          name: db
          volumeMounts:
            - name: secrets
              mountPath: "/etc/secrets"
              readOnly: true
    

    进入容器查看 /etc/secrets 目录。

  2. 将Secret导出到环境变量中

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: pod-deployment
    spec:
      replicas: 2
      selector:
        matchLabels:
          app: pod-deployment
      template:
        metadata:
          labels:
            app: pod-deployment
        spec:
          containers:
            - name: pod-1
              image: hub.adaixuezhang.cn/library/myapp:v1
              ports:
                - containerPort: 80
              env:
                - name: TEST_USER
                  valueFrom:
                    secretKeyRef:
                      name: mysecret
                      key: username
                - name: TEST_PASSWORD
                  valueFrom:
                    secretKeyRef:
                      name: mysecret
                      key: password
    

    进入容器,查看环境变量 echo $TEST_USER $TEST_PASSWORD

kubernetes.io/dockerconfigjson

使用kubectl 创建 docker registry认证的Secret

$ kubectl create secret docker-registry myregistry --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL
secret "myregistrykey" created.

在创建Pod时,通过 imagePullSecrets 来引用刚创建的 myregistrykey

apiVersion: v1
kind: Pod
metadata:
  name: foo
spec:
  containers:
    - name: foo
      image: hub.adaixuezhang.cn/test/myapp:v2
    imagePullSecrets:
      - name: myregistrykey

存储-volume

容器磁盘上的文件的生命周期是短暂的,这就使得在容器中运行重要应用时会出现一些问题。首先,当容器崩溃时,kubelet会重启它,但是容器中的文件将丢失——容器以干净的状态(镜像最初的状态)重新启动;其次,在Pod中同时运行多个容器时,这些容器之间通常需要共享文件。k8s中Volume 抽象就很好的解决了这些问题。

卷的类型

k8s支持一下类型的卷:

emptyDir

当 Pod 被分配给节点时,首先创建 emptyDir 卷,并且只要该Pod在该节点上运行,该卷就会存在。正如卷的名字所述,它最初是空的。Pod中的容器可以读取和写入 emptyDir 卷中相同的文件,该卷可以挂载到每个容器中的相同或不同路径上。当处于任何原因从节点中删除Pod时,emptyDir 中的数据将被永久删除。

注意:容器崩溃不会从节点中移除Pod,因此 emptyDir 卷中的数据在容器崩溃时是安全的。

emptyDir 的用法有:

  • 暂存空间,例如用于基于磁盘的合并排序;
  • 用作长时间计算崩溃恢复时的检查点;
  • web服务器容器提供数据时,保存内容管理器容器提取的文件。

eg:

apiVersion: v1
kind: Pod
metadata:
  name: test-pd
spec:
  containers:
    - name: test-container
      image: hub.adaixuezhang.cn/library/myapp:v1
      volumeMounts:
        - mountPath: /cache
          name: cache-volume
  volumes:
    - name: cache-volume
      emptyDir: {}

hostPath

hostPath 卷将主机节点的文件系统中的文件或目录挂载到集群中。

hostPath用途如下:

  • 运行需要访问Docker内部的容器:使用 /var/lib/dockerhostPath
  • 在容器中运行 CAdvisor:使用 /dev/cgroupshostPath

除了所需的 path 属性之外,用户还可以为 hostPath 卷指定 type:

含义
空字符串(默认)用于向后兼容,这意味着在挂载hostPath卷之前不会执行任何检查
DirectoryOrCreate 如果在给定的路径上没有任何东西存在,那么将根据需要在那里创建一个空目录,权限设置为0755,与kubelet具有相同的组合所有权
Directory 给定的路径下必须存在目录
FileOrCreate 如果在给定的路径上没有任何东西存在,那么会根据需要创建一个空文件,权限设置为0644,与kubelet具有相同的组合所有权
File 给定的路径下必须存在文件
Socket 给定的路径下必须存在 UNIX 套接字
CharDevice 给定的路径下必须存在字符设备
BlockDevice 给定的路径下必须存在块设备

使用这种类型时需要注意:

  • 由于每个节点上的文件都不同,具有相同配置(如从podTemplate创建的)的pod在不同节点上的行为可能会有所不同;
  • 当k8s安装计划添加资源感知调度时,将无法考虑 hostPath 使用的资源;
  • 在底层主机上创建的文件或目录只能由 root 写入。需要在特权容器中以root运行进程,或修改主机上的文件权限以便写入 hostPath 卷。

eg:

apiVersion: v1
kind: Pod
metadata:
  name: test-pd
spec:
  containers:
    - name: test-container
      image: hub.adaixuezhang.cn/test/myapp:v2
      volumeMounts:
        - mountPath: /test-pd
          name: test-volume
  volumes:
    - name: test-volume
      hostPath:
        # directory location on host
        path: /data
        # this field is optional
        type: Directory

存储-PV-PVC

PV(PersistentVolume)

是由管理员设置的存储,它是集群的一部分。就像节点是集群中的资源一样,PV 也是集群中的资源。PV 是Volume之类的卷插件,但具有独立于使用PV的Pod的生命周期。此API对象包含存储实现的细节,即NFS、iSCSI或特定云供应商的存储系统。

PVC(PersistentVolumeClaim)

是用户存储的请求。它与pod相似。pod消耗节点资源,PVC消耗PV资源。Pod可以请求特定级别的资源(CPU和内存)。声明可以请求特定的大小和访问模式(例如,可以以读/写一次或只读多次模式挂载)

静态PV

集群管理员创建一些PV,它们带有可供集群用户使用的实际存储的细节。它们存在于k8s API中,可用于消费。

动态PV:

当管理员创建的静态PV都不匹配用户的 PVC 时,集群可能会尝试动态的为PVC创建卷。此配置基于 StrongClasses :PVC 必须请求【存储类】,并且管理员必须创建并配置该类才能进行动态创建。声明该类为 "" 可以有效地禁用其他动态配置。

要启用基于存储级别的动态存储配置,集群管理员需要启用 API Server 上的 DefaultStorageClass 【准入控制器】。例如,通过确保 DefaultStorageClass 位于 API Server 组件的 --admission-control 标志,使用逗号 分割的有序值列表中,可以完成此操作。

绑定

master中的控制环路监视新的PVC,寻找匹配的PV(如果可能),并将它们绑定在一起。如果为新的PVC动态调配PV,则该环路将始终将该PV绑定到PVC。否则,用户总会得到它们所请求的存储,但是容量可能会超出要求的数量。一旦PV和PVC绑定后,PVC绑定是排他性的,不管它们是如何绑定的。PVC和PV是一对一的映射。

持久化卷声明的保护

持久化卷类型

eg:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv0003
spec:
  capacity:
    storage: 1Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  storageClassName: slow
  mountOptions:
    - hard
    - nfsvers=4.1
  nfs:
    path: /tmp
    server: 172.16.180.132

PV 访问模式

Volume插件支持的访问模式:

回收策略

新版本k8s中 Recycle机制已废弃!详见官方文档!!!

状态

eg:

安装NFS服务器

Server端:

$ yum install -y nfs-common nfs-utils rpcbind
$ mkdir /nfs
$ chmod 777 /nfs
$ vim /etc/exports
	/nfs *(rw,no_root_squash,no_all_squash,sync)
$ systemctl enable --now rpcbind 
$ systemctl enable --now nfs 

client端:

$ yum install -y nfs-utils rpcbind

# 测试挂载-确保nfs服务可用
$ showmount -e 172.16.180.132
$ mkdir /share
$ mount -t nfs 172.16.180.132:/nfs /share

部署PV

apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfspv1
spec:
  capatcity:
    storage: 100M
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: nfs
  nfs:
    path: /nfs
    server: 172.16.180.132

创建服务并使用PVC

apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  ports:
    - port: 80
      name: web
  clusterIP: None
  selector:
    app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  selector:
    matchLabels:
      app: nginx
  serviceName: "nginx"
  replicas: 3
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: hub.adaixuezhang.cn/library/myapp:v1
          ports:
            - containerPort: 80
              name: web
          volumeMounts:
            - name: www
              mountPath: /usr/share/nginx/html
  volumeClaimTemplates:
    - metadata:
        name: www
      spec:
        accessModes: ["ReadWriteOnce"]
        storageClassName: "nfs"
        resources:
          requests:
            storage: 50M

关于StatefulSet

StatefulSet的启停顺序:

StatefulSet使用场景:

展开阅读全文
加载中

作者的其它热门文章

打赏
0
0 收藏
分享
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部