前言

本篇是Kubernetes第十二篇,大家一定要把环境搭建起来,看是解决不了问题的,必须实战。

Kubernetes系列文章:
  1. Kubernetes介绍
  2. Kubernetes环境搭建
  3. Kubernetes-kubectl介绍
  4. Kubernetes-Pod介绍(-)
  5. Kubernetes-Pod介绍(二)-生命周期
  6. Kubernetes-Pod介绍(三)-Pod调度
  7. Kubernetes-Pod介绍(四)-Deployment
  8. Kubernetes-Service介绍(一)-基本概念
  9. Kubernetes-Service介绍(二)-服务发现
  10. Kubernetes-Service介绍(三)-Ingress(含最新版安装踩坑实践)
  11. Kubernetes-网络

为什么需要存储

对于这个问题其实很简单,容器中持久化的文件生命周期是短暂的,如果容器中程序崩溃宕机,kubelet 就会重新启动,容器中的文件将会丢失,所以对于有状态的应用容器中持久化存储是至关重要的一个环节;另外很多时候一个 Pod 中可能包含多个 Docker 镜像,在 Pod 内数据也需要相互共享,Kubernetes 中 Pod 也可以增加副本数量,遇到故障时 Pod 可以转移到其它节点,为了浮动节点都能够访问统一的持久化存储以及容器间共享数据,Kubernetes 中定义了 Volume 来解决这些问题 ,从本质上讲,Volume 只是一个目录,可能包含一些数据,Pod 中的容器可以访问它。该目录是何种形式,是由所使用的 Volume 类型决定的。

Volume介绍

Kubernetes 支持很多 Volume类型,可以分为以下类型:


img

我们重点介绍下资源对象映射为存储卷、Node本地存储卷和持久卷。

资源对象映射为存储卷

在 Kubernetes中ConfigMap、Serect、DownwardAPI和ServiceAccountToken四种存储卷,存在的意义不是为了存放容器里的数据,也不是用来进行容器和宿主机之间的数据交换,是为容器提供预先定义好的数据。从容器的角度来看,这些 Volume里的信息就是被映射到容器当中的。

ConfigMap

ConfigMap用于保存应用程序的配置信息,可以通过Volume的形式挂载到容器内部文件系统中,供容器内的应用程序读取。

使用
  1. 创建configMap文件;
apiVersion: v1
kind: ConfigMap
metadata:
  name: env-config
data:
  env-key: test
  1. 创建Pod文件,在Pod使用configMap配置信息;
apiVersion: v1
kind: Pod
metadata:
  name: configmap-pod
spec:
  containers:
  - name: configmap-pod
    image: busybox:1.28.3
    command: [ "/bin/sh", "-c", "env" ]
    env:
     - name: ENV
       valueFrom:
         configMapKeyRef:
           name: env-config
           key: env-key 
  restartPolicy: Never
  1. 启动configMap和Pod;
kubectl apply -f env-configMap.yaml
kubectl apply -f configmap-pod.yaml
  1. 查看启动日志;
kubectl logs configmap-pod

image.png

Secret

Secret功能与ConfigMap类似,它与ConfigMap的区别在于,Secret保存的是需要加密的、应用所需的配置信息。Secret与ConfigMap用法完全相同:你可以使用 kubectl create secret从文件或者目录创建 Secret,也可以直接编写Secret对象的YAML文件。

Downward API

Downward API的作用是让Pod里的容器能够直接获取到这个Pod API对象本身的元数据信息。

使用
  1. 创建Pod,该Pod声明了一个projected类型的Volume,Volume的数据来源为Downward API,而这个 Downward API Volume,要暴露Pod的metadata.labels 信息给容器,容器启动以后,则是不断打印出 /etc/podinfo/labels 里的内容;
apiVersion: v1
kind: Pod
metadata:
  name: downwardapi-demo-pod
  labels:
    cluster: demo-test
spec:
  containers:
    - name: downwardapi-demo
      image: busybox:1.28.3
      command: ["sh", "-c"]
      args:
      - while true; do
          if [[ -e /etc/podinfo/labels ]]; then
            echo -en '\n\n'; cat /etc/podinfo/labels; fi;
          sleep 5;
        done;
      volumeMounts:
        - name: podinfo
          mountPath: /etc/podinfo
          readOnly: false
  volumes:
    - name: podinfo
      projected:
        sources:
        - downwardAPI:
            items:
              - path: "labels"
                fieldRef:
                  fieldPath: metadata.labels
  1. 启动Pod和查看日志;
kubectl apply -f downwardapi-demo-pod.yaml
kubectl logs downwardapi-demo-pod

image.png

Service Account Token

Service Account Token是一种针对Pod的账号,它是Kubernetes进行权限分配的对象。比如Service Account A,可以只被允许对 Kubernetes API 进行 GET 操作,而 Service Account B,则可以有 Kubernetes API 的所有操作权限。Service Account的授权信息和文件,实际上保存在它所绑定的一个特殊的 Secret 对象里的,对于Service Account Token可以理解为一种特殊的Secret对象。

Kubernetes对所有的Pod都提供了一个default Service Account,任何一个运行在 Kubernetes的Pod,都可以直接使用这个默认的 Service Account,而无需显示地声明挂载它。

原理探索

实现方式还是靠Projected Volume机制

  1. 查看该Pod的详细信息,可以看到该Po的默认挂载一个serviceaccount的路径;
kubectl describe pod downwardapi-demo-pod

image.png
  1. 我们进入容器内部查看下serviceaccount具体内容,我们可以看到包括3方面内容,分别是token、ca.crt、namespace;
#进入容器
kubectl exec -it downwardapi-demo-pod -- /bin/sh
#查看具体内容
ls /var/run/secrets/kubernetes.io/serviceaccount

image.png
  1. 接下来我们看下系统中的Service Account对象,可以看到有一个default-token-q4qts的Secret对象,该对象是一个Mountable secrets对象,说明此对象需要被挂载的;

image.png
  1. 接下来我们看下default-token-q4qts包含什么东西,我们可以看到包含了token、ca.crt、namespace三类对象;

image.png

通过Mountable secrets标识、Pod内容对象以及Secrets包含的对象,我们可以证明每个命名空间下面都会有一个名为default默认的Service Account,在Pod启动的时候,Secret对象会自动挂载到Pod指定的目录下,帮助Pod来完成API Server的身份鉴权。

使用
  1. 创建Service Account资源;
#创建Service Account资源
kubectl create serviceaccount sa-demo
#查看Service Account资源
kubectl get sa

image.png
  1. 查看下是否创建Secret;
#查看是否创建Secret
kubectl describe sa sa-demo、
#查看具体的Secret内容
kubectl describe secret sa-demo-token-k4t96

image.png
  1. 创建使用sa-demo的Pod;
apiVersion: v1
kind: Pod
metadata:
  name: sa-demo-pod
spec:  
  serviceAccountName: sa-demo
  containers:
  - image: nginx          
    name: sa-demo-pod               
    resources:                      
      limits:
        cpu: 100m
        memory: 200Mi
      requests:
        cpu: 100m
        memory: 200Mi
  1. 启动该Pod;
#创建pod资源
kubectl create -f sa-demo-pod.yaml
#查看Pod资源
kubectl get pods
#查看pod是否挂载serviceaccount
kubectl describe pod sa-demo-pod

image.png

image.png
  1. 进入容器内部访问kubernetes服务的API,在Kubernetes集群中,默认为API Server创建了一个名为kubernetes的Service,通过这个Service可以访问API Server,使用curl命令直接访问会得到如下返回信息,表示并没有权限;
#查看服务列表
kubectl get svc
#进入容器内部
kubectl exec -it sa-demo-pod -- /bin/sh
#访问kubernetes服务
curl https://kubernetes

image.png

image.png
  1. 使用ca.crt和Token做认证,先将ca.crt放到CURL_CA_BUNDLE这个环境变量中,curl命令使用CURL_CA_BUNDLE指定证书;再将Token的内容放到TOKEN中,然后带上TOKEN访问API Server;
#声明变量
export CURL_CA_BUNDLE=/var/run/secrets/kubernetes.io/serviceaccount/ca.crt
TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
#携带token访问服务
curl -H "Authorization: Bearer $TOKEN" https://kubernetes

image.png

Node本地存储卷

Kubernetes管理Node本地存储卷有是那种类型:

  1. EmptyDir: 与Pod同生命周期,Node临时存储;

  2. HostPath: Node目录;

  3. Local: 基于持久卷PV管理的Node目录;

EmptyDir

当Pod被调度到某个节点上时,在Node上创建的是一个emptyDir卷,此卷刚开始是一个空目录,并且只要 Pod在该节点上运行,卷就一直存在,与Pod生命周期相同, 当Pod被销毁的时候,Node上的目录也会被销毁。同一个Pod的多个容器都可以挂载到改卷上。

emptyDir可以在以下几种场景下使用:

  1. 临时空间,例如基于磁盘的合并排序;

  2. 设置检查点以从崩溃事件中恢复未执行完毕的长计算;

  3. 保存内容管理器容器从Web服务器容器提供数据时所获取的文件;

使用
  1. 创建一个使用emptyDir volume的Pod;
apiVersion: v1
kind: Pod
metadata:
  name: emptydir-pod
spec:
  containers:
  - image: busybox:1.28.3
    name: emptydir-pod
    command: [ "sleep", "3600" ]
    volumeMounts:
    - mountPath: /data
      name: data-volume
  volumes:
  - name: data-volume
    emptyDir: {}
  1. 创建完成之后我们通过describe命令查看该Pod的详情,我们可以看到上面创建的Pod Volumes 类型是:EmptyDir;
kubectl describe pod emptydir-pod

image.png
  1. 进入容器中查看挂载情况;
kubectl exec -it emptydir-pod /bin/sh

image.png

HostPath

hostPath类型则是映射Node节点文件系统中的文件或者目录到Pod里。在使用hostPath类型的存储卷时,也可以设置type字段,支持的类型有文件、目录、File、Socket、CharDevice和BlockDevice。

hostPath可以在以下几种场景使用:

  1. 容器应用中关键的数据需要持久化到宿主机上;

  2. 需要使用运行一个访问 Docker内部数据Pod, 可以将主机的/var/lib/docker目录挂载到容器内;

  3. 监控系统,例如在容器中运行cAdvisor需要以hostPath方式挂载/sys;

  4. Pod启动需要依赖宿主机某个目录或者文件信息;

使用
  1. 创建一个使用hostPath volume的Pod;
apiVersion: v1
kind: Pod
metadata:
  name: hostpath-pod
spec:
  containers:
  - image: busybox:1.28.3
    name: hostpath-pod
    command: [ "sleep", "3600" ]
    volumeMounts:
    - mountPath: /test-data
      name: test-volume
  volumes:
  - name: test-volume
    hostPath:
      # directory location on host
      path: /data
      # this field is optional
      type: Directory
  1. 创建完成之后我们通过describe命令查看该Pod的详情,我们可以看到上面创建的Pod Volumes 类型是:HostPath,如果发现有个hostPath type check failed: /data is not a directory的告警,你需要在每个节点创建/data目录;
kubectl describe pod hostpath-pod

image.png

image.png
  1. 接下来我们进入容器,在容器中创建文件;
#进入容器
kubectl exec -it hostpath-pod /bin/sh
#编辑文件
vi 123.txt
#输出文件
cat 123.txt

image.png
  1. 查看Pod被调度到那个节点;
kubectl get pods -o wide

image.png
  1. 进入demo-slave-2查看/data目录下是否增加文件;

image.png
  1. 销毁hostpath-pod,检查文件是否存在,我们会发现Pod已经被删除了,volume卷中的数据仍然还在;
kubectl delete -f hostpath-pod.yaml

image.png

emptyDir和hostPath都可以实现本地存储卷的功能、但是二者在功能上还是有异同的:

  1. 二者都是node节点的本地存储卷方式;

  2. emptyDir可以选择把数据存到tmpfs类型的本地文件系统中去,hostPath并不支持这一点;

  3. hostPath除了支持挂载目录外,还支持File、Socket、CharDevice和BlockDevice,既支持把已有的文件和目录挂载到容器中,也提供了“如果文件或目录不存在,就创建一个”的功能;

  4. emptyDir是临时存储空间,完全不提供持久化支持;

  5. hostPath的卷数据是持久化在Node节点的文件系统中的,即便pod已经被删除了,volume卷中的数据还会留存在Node节点上;

结束

欢迎大家点点关注,点点赞!

Kubernetes-存储(一)的更多相关文章

  1. kubernetes 存储卷

    kubernetes 存储卷    数据卷用于实现容器持久化数据,Kubernetes对于数据卷重新定义,提供了丰富强大的功能.在Kubernetes系统中,当Pod重建的时候,数据卷会丢失,Kube ...

  2. (九)Kubernetes 存储卷

    Kubernetes存储卷概述 Pod本身具有生命周期,这就带了一系列的问题,第一,当一个容器损坏之后,kubelet会重启这个容器,但是文件会丢失-这个容器会是一个全新的状态:第二,当很多容器在同一 ...

  3. 从零开始入门 K8s | Kubernetes 存储架构及插件使用

    本文整理自<CNCF x Alibaba 云原生技术公开课>第 21 讲. 导读:容器存储是 Kubernetes 系统中提供数据持久化的基础组件,是实现有状态服务的重要保证.Kubern ...

  4. 第21 章 : Kubernetes 存储架构及插件使用

    Kubernetes 存储架构及插件使用 本文将主要分享以下三方面的内容: Kubernetes 存储体系架构: Flexvolume 介绍及使用: CSI 介绍及使用. Kubernetes 存储体 ...

  5. 详解Kubernetes存储体系

    Volume.PV.PVC.StorageClass由来 先思考一个问题,为什么会引入Volume这样一个概念? " 答案很简单,为了实现数据持久化,数据的生命周期不随着容器的消亡而消亡. ...

  6. Kubernetes存储之Persistent Volumes简介

    简介 管理存储和管理计算有着明显的不同.PersistentVolume子系统给用户和管理员提供了一套API,从而抽象出存储是如何提供和消耗的细节.在这里,我们介绍两种新的API资源:Persiste ...

  7. kubernetes存储之GlusterFS

    目录 1.glusterfs概述 1.1.glusterfs简介 1.2.glusterfs特点 1.3.glusterfs卷的模式 2.heketi概述 3.部署heketi+glusterfs 3 ...

  8. Kubernetes 存储卷管理 PV&PVC(十)

    目录 一.emptyDir 二.hostPath 三.PV & PVC 1.NFS PersistentVolume 2.创建 PVC 3.创建 Pod 进行挂载 为了持久化保存容器的数据,可 ...

  9. Kubernetes 学习12 kubernetes 存储卷

    一.概述 1.我们此前讲过根据应用本身是否需要持久存储数据以及某一次请求和之前的请求是否有联系,可以分为四类应用 a.有状态,要存储 b.有状态,无持久存储 c.无状态,要存储 d.无状态,无持久存储 ...

  10. Spark in action on Kubernetes - 存储篇(一)

    前言 在上篇文章中,我们分析了Spark Operator内部的机制,今天我们会讨论一个在大数据领域中最重要的话题 - 存储.大数据已经无声无息的融入了每个人的生活中.大到旅游买房,小到外卖打车,都可 ...

随机推荐

  1. QMake(Qt项目构建)

    qmake工具能够简化不同平台上的项目构建.可以自动产生Makefiles文件,仅仅需要少量的信息就可以生成Makefile文件.同时qmake也可以构建不是Qt的项目.qmake基于项目文件中的信息 ...

  2. DP接口中AUX

    背景技术: DP接口(DisplayPort)是一种图像显示接口,它不仅可以支持全高清显示分辨率(1920×1080),还能支持4k分辨率(3840×2160),以及最新的8k分辨率(7680×432 ...

  3. hdu 5185 Equation(分析+DP)

    题意: Gorwin is very interested in equations. Nowadays she gets an equation like thisx1+x2+x3+⋯+xn=n, ...

  4. Java中Lambda表达式的进化之路

    Lambda表达式的进化之路 为什么要使用Lambda表达式 可以简洁代码,提高代码的可读性 可以避免匿名内部类定义过多导致逻辑紊乱 在原先实现接口抽象方法的时候,需要通过定义一个实现接口的外部类来实 ...

  5. Vue脚手架最新版本安装使用

    现在很多的插件如Vant 这类的样式框架,都去兼容了Vue的3.0版本,所以我总结一下如何去简单的搭建一个Vue3.0的框架 开始 一,如何安装 在这里说明一下,Vue脚手架版本,和Vue版本是两个东 ...

  6. lamp 架构的理解

    1,lamp架构下的求情过程如下: 2,httpd服务器连接php服务器的三种方式 3,php和mysql的连接

  7. Linux&C open creat read write lseek 函数用法总结

    一:五个函数的参数以及返回值. 函数                                 参数                      返回值     open (文件名,打开方式以及读 ...

  8. 【java+selenium3】元素的扩展操作(二)

    1.判断当前元素是否可显示 isDisplay(); //判断元素是否可见 boolean a= driver.findElement(By.id("xxx")).isDispla ...

  9. 数据代理Object.defineProperty()

    数据代理: 通过一个对象代理对另一个对象中属性的操作(读/写) 数据代理 Object.defineProperty() Object.defineProperty() 方法会直接在一个对象上定义一个 ...

  10. 端口被占用(启动tomcat时 错误: 代理抛出异常 : java.rmi.server.ExportException: Port already in use: 1099的解决办法)

    一.问题描述 在IntelliJ IDEA 中启动Tomcat服务器时就出现了如下图所示的错误: 错误: 代理抛出异常错误**: java.rmi.server.ExportException: Po ...