美文网首页
9. kubernetes 存储卷

9. kubernetes 存储卷

作者: epiiplus1equal0 | 来源:发表于2019-09-26 16:13 被阅读0次

    9. kubernetes 存储卷

    [TOC]

    本文基于马哥的docker和k8s视频总结, 在此致谢马哥.

    k8s上可以用的三种存储卷类型

    emptyDir

    • (1) emptyDir 只在节点本地使用, 且pod删除时存储卷会随之被删除, 用于当临时目录或缓存, 此存储卷可使用节点的内存

      一个存储卷可以在同一个pod内的多个容器间共享:

    apiVersion: v1
    kind: Pod
    metadata:
        name: pod-demo
        namespace: default
        labels:
            app: myapp
            tier: frontend
        annotations:
            magedu.com/create-by: "cluster admin"
    spec:
        containers:
        - name: myapp
            image: nginx
            ports:
            - name: http
                containerPort: 80
            volumeMounts:
            - name: html # 挂载名为html的存储卷 (需要使用下面存在的volumes)
                mountPath: /usr/share/nginx/html/ # 挂载点路径
                # 其他参数: readOnly, subPath, mountPropagation
        - name: busybox
            image: busybox:latest
            imagePullPolicy: IfNotPresent
            volumeMounts: # 挂载是容器级别的, 哪个容器使用, 哪个容器就要挂载, 不挂载时访问不到数据
            - name: html
                mountPath: /data/ # 注意两个容器的挂载路径可以不同
            command:
            - "/bin/sh"
            - "-c"
            - "while true; done echo $(date) >> /data/index.html; sleep 10; done"
        volumes:
        - name: html
            emptyDir: {} # 可以指定为空, 表示使用默认值(使用硬盘空间, 不限制使用大小)
                # medium 指定使用的存储卷设备, 空字符串代表使用硬盘, Memory代表使用内存
                # sizeLimit 指定使用的存储卷大小
    
    kubectl apply -f vol-demo1.yml
    kubectl exec -it pod-demo -c busybox -- /bin/sh
    / # echo $(date) >> /data/index.html
    kubectl exec -it pod-demo -c myapp -- /bin/sh
    / # cat /data/web/html/index.html # 可以在另一个容器中看到共享的数据
    
    kubect get pods -o wide # 查看pod的IP
    curl pod_IP
    

    hostPath

    • (2) hostPath 宿主机路径, 将pod上的存储卷与宿主机的目录做映射
    hostPath支持的type类型.png
    apiVersion: v1
    kind: Pod
    metadata:
        name: pod-hostpath-vol
        namespace: default
    spec:
        containers:
        - name: myapp
            image: nginx:1.14:alpine
            volumeMounts:
            - name: html
                mountPath: /usr/share/nginx/html/  
            volumes:
            - name: html
                hostPath:
                    path: /data/pod/volume1/
                    type: DirectoryOrCreate # 目录不存在时自动创建
    
    mkdir -p /data/pod/volume1/
    echo "test hostPath" >> /data/pod/volume1/index.html # 只要节点上有相同内容, 则pod宕了也没关系
    kubectl apply -f pod-hostpath-vol.yml
    

    nfs为例

    • (3) 共享存储, 支持awsElasticBlockStore, azureDisk, cephfs, glusterfs, gitRepo, nfs, iscsi, rbd
    # node1(ip为192.168.200.200)作为nfs服务的提供者
    yum -y install nfs-utils # 作为nfs共享存储的节点需要安装此包
    mkdir /data/volumes -pv
    vi /etc/exports
    /data/volumes  192.168.0.0/16(rw,no_root_squash)
    systemctl start nfs
    
    # node2(ip为192.168.200.201)作为nfs服务的使用者
    yum -y install nfs-utils
    mount -t nfs 192.168.200.200:/data/volumes /mnt # 一定要进行挂载测试
    umount /mnt
    vi pod-nfs-vol.yml
    
    apiVersion: v1
    kind: Pod
    metadata:
        name: pod-nfs-vol
        namespace: default
    spec:
        containers:
        - name: myapp
            image: nginx:1.14:alpine
            volumeMounts:
            - name: html
                mountPath: /usr/share/nginx/html/  
            volumes:
            - name: html
                nfs:
                    path: /data/pod/volumes
                    server:
                        192.168.200.201
                    readOnly: false # 默认就是false, 即rw
    
    kubectl apply -f pod-nfs-vol.yml
    

    注: nfs支持多客户端同时挂载, 支持多客户端的多路读写访问

    pvc和pv

    pvcpv也是标准的k8s资源

    定义存储模型.png
    kubectl explain pods.spec.volumes.persistentVolumeClaim
        claimName # 必要选项, 指明已创建好的pvc名称
        readOnly # default false
    
    kubectl explain pvc.spec
        accessModes <[]string># 访问模型, 这里不可随便定义, 有些设备可能不支持某种模型
            ReadWriteOnce # 单路读写, 可简写为RWO
            ReadOnlyMany # 多路只读, 可简写为ROM
            ReadWriteMany # 多路读写, 可简写为RWM
        resources # 资源限制, 对应的存储空间至少需要的大小
        selecotr # pv可以有标签, pvc上使用selector时表示必须使用哪个pv建立关联关系, 不加selector时自动选择最佳匹配
        volumeMode # 后端存储卷的模式, 可以不指定
        volumeName # 卷名称, 绑定某个pv, 可以不指定
    
    kubectl explain pv.spec
        accessModes <[]string># 访问模型, 这里不可随便定义, 有些设备可能不支持某种模型
            ReadWriteOnce # 单路读写, 可简写为RWO
            ReadOnlyMany # 多路只读, 可简写为ROM
            ReadWriteMany # 多路读写, 可简写为RWM
        capacity <map[string]string> # 定义存储空间大小, 支持E, P, T, G, M, K, m和Ei, Pi, Ti, Gi, Mi, Ki, mi
            stroage
    
    • 创建pvc后会去找系统上合适的pv进行绑定, 如果没有则挂起(pending), 例如pvc需要使用30G, 而pv现在最大创建的容量只有20G, 不满足条件, 操作被挂起, 直到满足条件

    • pvpvc是一一对应的关系, 如果某个pvpvc占用了, 则这个pv不能再被其他pvc占用, 但一个pvc可以被多个pod访问

    # node1(ip为192.168.200.200)作为nfs服务的提供者
    yum -y install nfs-utils # 作为nfs共享存储的节点需要安装此包
    mkdir /data/volumes -pv
    vi /etc/exports
    /data/volumes/v1  192.168.0.0/16(rw,no_root_squash)
    /data/volumes/v2  192.168.0.0/16(rw,no_root_squash)
    /data/volumes/v3  192.168.0.0/16(rw,no_root_squash)
    /data/volumes/v4  192.168.0.0/16(rw,no_root_squash)
    /data/volumes/v5  192.168.0.0/16(rw,no_root_squash)
    exportfs -arv
    showmount -e
    
    # node2(ip为192.168.200.201)作为nfs服务的使用者
    yum -y install nfs-utils
    mount -t nfs 192.168.200.200:/data/volumes /mnt # 一定要进行挂载测试
    umount /mnt
    vi pod-pv.yml
    
    apiVersion: v1
    kind: PersistentVolume
    metadata:
        name: pv001 # 定义pv时千万不要定义namespace, 因为pv是集群级别的, 不属于namespace
        labels:
            name: pv001
    spec:
        nfs:
            path: /data/volumes/v1
            server: 192.168.200.200
        accessModes: ["ReadWriteMany", "ReadWriteOnce"]
        capacity:
            storage: 2Gi
    
    ---
    apiVersion: v1
    kind: PersistentVolume
    metadata:
        name: pv002
        labels:
            name: pv002
    spec:
        nfs:
            path: /data/volumes/v2
            server: 192.168.200.200
        accessModes: ["ReadWriteMany"]
        capacity:
            storage: 5Gi
    
    ---
    apiVersion: v1
    kind: PersistentVolume
    metadata:
        name: pv003
        labels:
            name: pv003
    spec:
        nfs:
            path: /data/volumes/v3
            server: 192.168.200.200
        accessModes: ["ReadWriteMany", "ReadWriteOnce"]
        capacity:
            storage: 20Gi
    
    ---
    apiVersion: v1
    kind: PersistentVolume
    metadata:
        name: pv004
        labels:
            name: pv004
    spec:
        nfs:
            path: /data/volumes/v4
            server: 192.168.200.200
        accessModes: ["ReadWriteMany", "ReadWriteOnce"]
        capacity:
            storage: 10Gi
    
    ---
    apiVersion: v1
    kind: PersistentVolume
    metadata:
        name: pv005
        labels:
            name: pv005
    spec:
        nfs:
            path: /data/volumes/v5
            server: 192.168.200.200
        accessModes: ["ReadWriteMany", "ReadWriteOnce"]
        capacity:
            storage: 10Gi
    
    ---
    
    kubectl apply -f pod-pv.yml
    kubectl get pv
        # RECLAIM POLICY 回收策略, 某个pvc绑定了pv, 当pvc被删除后pv内还有数据, 该如何处理?
            # Retain 保留数据
            # Recycle 回收
            # Delete 删除
    
    vi pod-pvc.yml
    
    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
        name: mypvc
        namespace: default
    spec:
        accessModes: ["ReadWriteMany"] # pvc的accessModes必须是pv的子集
        resources:
            requests: # 要求有多大的存储空间
                storage: 6Gi
    
    ---
    apiVersion: v1
    kind: Pod
    metadata:
        name: pod-vol-pvc
        namespace: default
    spec:
        containers:
        - name: myapp
            image: nginx:1.14:alpine
            volumeMounts:
            - name: html
                mountPath: /usr/share/nginx/html/  
            volumes:
            - name: html
                persistentVolumeClaim:
                    claimName: mypvc
    
    kubeclt apply -f pod-pvc.yml
    kubectl get pv # 可查看STATUS, 是否被Bound
    kubectl get pvc
    

    特殊类型的存储卷: 用于制作数据中心

    配置容器化应用的方式有以下几种:

    • (1) 自定义命令行参数
      • command
      • args: []
    • (2) 把配置文件直接放入基本镜像并重构
    • (3) 环境变量
      • (3.1) Could Native的应用程序一般可直接通过环境变量加载配置
      • 通过entrypoint脚本来预处理变量为配置文件中配置信息
    • (4) 存储卷
      • (4.1) configmap: 明文
      • (4.2) secret: 密文

    configmap

    # 创建configmap的方式:
    # 第一种: 直接直接用命令行的方式给定
    kubectl create configmap nginx-config --from-literal=nginx_port=80 --from-ilteral=server_name=myapp.magedu.com
        # --from-literal=key=value 直接用命令行的方式给定
    kubectl get cm
    kubectl describe cm nginx-config
        # 可在显示信息中看到Data (定义的key和value)
    
    # 第二种: 配置文件给定
    mkdir configmap
    vi www.conf
    server {
        server_name myapp.magedu.com;
        listen 80;
        root /data/web/html/;
    }
    
    kubectl create configmap nginx-www --from-file=www=./www.conf
        # 按这种方式指定, key=www, value=www.conf的文件内容
    kubectl create configmap nginx-www --from-file=./www.conf
        # 按照这种方式指定, key=文件名(此例中为www.conf), value=www.conf的文件内容
    kubectl descirbe cm nginx-www
    
    vi pod-configmap.yml
    
    • 通过环境变量的方式向pod传数据:
    apiVersion: v1
    kind: Pod
    metadata:
        name: pod-demo-1
        namespace: default
        labels:
            app: myapp
            tier: frontend 
        annotations:
            alexti/created-by: "cluster admin"
    spec:
        containers: 
        - name: myapp 
            image: nginx:1.14-alpine 
            ports: 
            - name: http
                containerPort: 80
            env:
            - name: NGINX_SERVER_PORT # 变量最好使用下划线
                valueFrom: 
                    configMapKeyRef: # 引用configmap获取数据
                        name: nginx-config
                        key: nginx_port # nginx_port的值会传递给变量NGINX_SERVER_PORT
                        optional: true # 如果configmap不存在或者configmap中定义的变量没有你需要使用的key, pod将无法被启动, 可以将这一项的值设置为true, 表示此configmap可以在定义完之后再创建
            - name: NGINX_SERVER_NAME
                valueFrom:
                    configMapKeyRef:
                        name: nginx-conf
                        key: server_name
                        optional: true
    
    kubectl apply -f pod-configmap.yml
    kubectl exec -it pod pod-demo-1 -- /bin/sh
    / # printenv # 可查看到自定义的变量: NGINX_SERVER_PORT和NGINX_SERVER_NAME
    
    kubectl edit cm nginx-config # 支持编辑
    
    • 通过存储卷的方式向pod传数据:

    方法一, 使用命令行创建的configmap:

    vi pod-configmap2.yml
    
    apiVersion: v1
    kind: Pod
    metadata:
        name: pod-demo-2
        namespace: default
        labels:
            app: myapp
            tier: frontend 
        annotations:
            alexti/created-by: "cluster admin"
    spec:
        containers: 
        - name: myapp 
            image: nginx:1.14-alpine 
            ports: 
            - name: http
                containerPort: 80
            volumeMounts:
            - name: nginxconf
                mountPath: /etc/nginx/config.d/
                readOnly: true # 不允许容器修改配置文件
            volumes:
            - name: nginxconf
                configMap: # 存储卷类型为configMap
                    name: nginx-config
    
    kubectl apply -f pod-configmap2.yml
    kubectl exec -it pod pod-demo-2 -- /bin/sh
    / # cd /etc/nginx/config.d/
    / # ls # 可以查看到两个文件, 文件名为nginx_port和server_name
    
    kubectl edit cm nginx-config
        # 将nginx_port从80改为8080
    
    kubectl exec -it pod pod-demo-2 -- /bin/sh
    / # cat /etc/nginx/config/nginx_port # 此时可以查看到结果为修改后的8080
    

    方法二, 使用创建的配置文件:

    vi pod-configmap3.yml
    
    apiVersion: v1
    kind: Pod
    metadata:
        name: pod-demo-3
        namespace: default
        labels:
            app: myapp
            tier: frontend 
        annotations:
            alexti/created-by: "cluster admin"
    spec:
        containers: 
        - name: myapp 
            image: nginx:1.14-alpine 
            ports: 
            - name: http
                containerPort: 80
            volumeMounts:
            - name: nginxconf
                mountPath: /etc/nginx/conf.d/
                readOnly: true # 不允许容器修改配置文件
            volumes:
            - name: nginxconf
                configMap: # 存储卷类型为configMap
                    name: nginx-www
                    # 指定items可以只挂载部分键值而不是全部
    
    kubecgtl apply -f pod-configmap3.yml
    kubectl get pods
    kuebctl exec -it pod-demo-3 -- /bin/sh
    / # cat /etc/nginx/conf.d/www.conf # 可看到使用配置文件定义的配置
    / # nginx -T # 查看nginx加载的配置
    
    kubectl edit cm nginx-www
        # 将某个参数修改, 例如listen的值改为8080, 等待一段时间后会发现pod内的配置会随之修改为8080, 但此时配置还未生效, 需要重载配置文件
    / # nginx -s reload
    

    secret

    kubectl create secret --help
        # 有三种类型
        generic # 通用的secret, 一般用于保存密码
        tls # 保存私钥和证书
        docker-registry # 保存docker-registry认证信息, 连接私有仓库时拉取镜像时使用
    
    kubectl create secret generic mysql-root-password --form-literal=password=MyP@ss123
    kubectl get secret
    kubectl descirbe secret mysql-root-password # 会发现值不显示
    kubectl get secret mysql-root-password -o yaml
    echo "经base加密后的密码" | base64 -d # 解码, 可看到密码源码, 说明密码安全性不佳
    
    vi pod-secret-1.yml
    
    apiVersion: v1
    kind: Pod
    metadata:
        name: pod-demo-4
        namespace: default
        labels:
            app: myapp
            tier: frontend 
        annotations:
            alexti/created-by: "cluster admin"
    spec:
        containers: 
        - name: myapp 
            image: nginx:1.14-alpine 
            ports: 
            - name: http
                containerPort: 80
            env:
            - name: MYSQL_ROOT_PASSWORD
                valueFrom: 
                    secretKeyRef:
                        name: mysql-root-password
                        key: password
                        optional: true
    
    kubectl apply -f pod-secret-1.yml
    kubectl exec -it pod-demo-4 -- printenv # 会发现传入的MYSQL_ROOT_PASSWORD在会解密后通过环境变量的方式注入pod
    

    相关文章

      网友评论

          本文标题:9. kubernetes 存储卷

          本文链接:https://www.haomeiwen.com/subject/uqknuctx.html