Kubernetes-存储(一)
前言
本篇是Kubernetes第十二篇,大家一定要把环境搭建起来,看是解决不了问题的,必须实战。
Kubernetes系列文章:
Kubernetes介绍 Kubernetes环境搭建 Kubernetes-kubectl介绍 Kubernetes-Pod介绍(-) Kubernetes-Pod介绍(二)-生命周期 Kubernetes-Pod介绍(三)-Pod调度 Kubernetes-Pod介绍(四)-Deployment Kubernetes-Service介绍(一)-基本概念 Kubernetes-Service介绍(二)-服务发现 Kubernetes-Service介绍(三)-Ingress(含最新版安装踩坑实践) Kubernetes-网络
为什么需要存储
对于这个问题其实很简单,容器中持久化的文件生命周期是短暂的,如果容器中程序崩溃宕机,kubelet 就会重新启动,容器中的文件将会丢失,所以对于有状态的应用容器中持久化存储是至关重要的一个环节;另外很多时候一个 Pod 中可能包含多个 Docker 镜像,在 Pod 内数据也需要相互共享,Kubernetes 中 Pod 也可以增加副本数量,遇到故障时 Pod 可以转移到其它节点,为了浮动节点都能够访问统一的持久化存储以及容器间共享数据,Kubernetes 中定义了 Volume 来解决这些问题 ,从本质上讲,Volume 只是一个目录,可能包含一些数据,Pod 中的容器可以访问它。该目录是何种形式,是由所使用的 Volume 类型决定的。
Volume介绍
Kubernetes 支持很多 Volume类型,可以分为以下类型:

我们重点介绍下资源对象映射为存储卷、Node本地存储卷和持久卷。
资源对象映射为存储卷
在 Kubernetes中ConfigMap、Serect、DownwardAPI和ServiceAccountToken四种存储卷,存在的意义不是为了存放容器里的数据,也不是用来进行容器和宿主机之间的数据交换,是为容器提供预先定义好的数据。从容器的角度来看,这些 Volume里的信息就是被映射到容器当中的。
ConfigMap
ConfigMap用于保存应用程序的配置信息,可以通过Volume的形式挂载到容器内部文件系统中,供容器内的应用程序读取。
使用
创建configMap文件;
apiVersion: v1
kind: ConfigMap
metadata:
name: env-config
data:
env-key: test
创建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
启动configMap和Pod;
kubectl apply -f env-configMap.yaml
kubectl apply -f configmap-pod.yaml
查看启动日志;
kubectl logs configmap-pod

Secret
Secret功能与ConfigMap类似,它与ConfigMap的区别在于,Secret保存的是需要加密的、应用所需的配置信息。Secret与ConfigMap用法完全相同:你可以使用 kubectl create secret从文件或者目录创建 Secret,也可以直接编写Secret对象的YAML文件。
Downward API
Downward API的作用是让Pod里的容器能够直接获取到这个Pod API对象本身的元数据信息。
使用
创建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
启动Pod和查看日志;
kubectl apply -f downwardapi-demo-pod.yaml
kubectl logs downwardapi-demo-pod

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机制
查看该Pod的详细信息,可以看到该Po的默认挂载一个serviceaccount的路径;
kubectl describe pod downwardapi-demo-pod

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

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

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

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

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

创建使用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
启动该Pod;
#创建pod资源
kubectl create -f sa-demo-pod.yaml
#查看Pod资源
kubectl get pods
#查看pod是否挂载serviceaccount
kubectl describe pod sa-demo-pod


进入容器内部访问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


使用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

Node本地存储卷
Kubernetes管理Node本地存储卷有是那种类型:
EmptyDir: 与Pod同生命周期,Node临时存储;
HostPath: Node目录;
Local: 基于持久卷PV管理的Node目录;
EmptyDir
当Pod被调度到某个节点上时,在Node上创建的是一个emptyDir卷,此卷刚开始是一个空目录,并且只要 Pod在该节点上运行,卷就一直存在,与Pod生命周期相同, 当Pod被销毁的时候,Node上的目录也会被销毁。同一个Pod的多个容器都可以挂载到改卷上。
emptyDir可以在以下几种场景下使用:
临时空间,例如基于磁盘的合并排序;
设置检查点以从崩溃事件中恢复未执行完毕的长计算;
保存内容管理器容器从Web服务器容器提供数据时所获取的文件;
使用
创建一个使用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: {}
创建完成之后我们通过describe命令查看该Pod的详情,我们可以看到上面创建的Pod Volumes 类型是:EmptyDir;
kubectl describe pod emptydir-pod

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

HostPath
hostPath类型则是映射Node节点文件系统中的文件或者目录到Pod里。在使用hostPath类型的存储卷时,也可以设置type字段,支持的类型有文件、目录、File、Socket、CharDevice和BlockDevice。
hostPath可以在以下几种场景使用:
容器应用中关键的数据需要持久化到宿主机上;
需要使用运行一个访问 Docker内部数据Pod, 可以将主机的/var/lib/docker目录挂载到容器内;
监控系统,例如在容器中运行cAdvisor需要以hostPath方式挂载/sys;
Pod启动需要依赖宿主机某个目录或者文件信息;
使用
创建一个使用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
创建完成之后我们通过describe命令查看该Pod的详情,我们可以看到上面创建的Pod Volumes 类型是:HostPath,如果发现有个hostPath type check failed: /data is not a directory的告警,你需要在每个节点创建/data目录;
kubectl describe pod hostpath-pod


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

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

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

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

emptyDir和hostPath都可以实现本地存储卷的功能、但是二者在功能上还是有异同的:
二者都是node节点的本地存储卷方式;
emptyDir可以选择把数据存到tmpfs类型的本地文件系统中去,hostPath并不支持这一点;
hostPath除了支持挂载目录外,还支持File、Socket、CharDevice和BlockDevice,既支持把已有的文件和目录挂载到容器中,也提供了“如果文件或目录不存在,就创建一个”的功能;
emptyDir是临时存储空间,完全不提供持久化支持;
hostPath的卷数据是持久化在Node节点的文件系统中的,即便pod已经被删除了,volume卷中的数据还会留存在Node节点上;
结束
欢迎大家点点关注,点点赞!

Kubernetes-存储(一)的更多相关文章
- kubernetes 存储卷
kubernetes 存储卷 数据卷用于实现容器持久化数据,Kubernetes对于数据卷重新定义,提供了丰富强大的功能.在Kubernetes系统中,当Pod重建的时候,数据卷会丢失,Kube ...
- (九)Kubernetes 存储卷
Kubernetes存储卷概述 Pod本身具有生命周期,这就带了一系列的问题,第一,当一个容器损坏之后,kubelet会重启这个容器,但是文件会丢失-这个容器会是一个全新的状态:第二,当很多容器在同一 ...
- 从零开始入门 K8s | Kubernetes 存储架构及插件使用
本文整理自<CNCF x Alibaba 云原生技术公开课>第 21 讲. 导读:容器存储是 Kubernetes 系统中提供数据持久化的基础组件,是实现有状态服务的重要保证.Kubern ...
- 第21 章 : Kubernetes 存储架构及插件使用
Kubernetes 存储架构及插件使用 本文将主要分享以下三方面的内容: Kubernetes 存储体系架构: Flexvolume 介绍及使用: CSI 介绍及使用. Kubernetes 存储体 ...
- 详解Kubernetes存储体系
Volume.PV.PVC.StorageClass由来 先思考一个问题,为什么会引入Volume这样一个概念? " 答案很简单,为了实现数据持久化,数据的生命周期不随着容器的消亡而消亡. ...
- Kubernetes存储之Persistent Volumes简介
简介 管理存储和管理计算有着明显的不同.PersistentVolume子系统给用户和管理员提供了一套API,从而抽象出存储是如何提供和消耗的细节.在这里,我们介绍两种新的API资源:Persiste ...
- kubernetes存储之GlusterFS
目录 1.glusterfs概述 1.1.glusterfs简介 1.2.glusterfs特点 1.3.glusterfs卷的模式 2.heketi概述 3.部署heketi+glusterfs 3 ...
- Kubernetes 存储卷管理 PV&PVC(十)
目录 一.emptyDir 二.hostPath 三.PV & PVC 1.NFS PersistentVolume 2.创建 PVC 3.创建 Pod 进行挂载 为了持久化保存容器的数据,可 ...
- Kubernetes 学习12 kubernetes 存储卷
一.概述 1.我们此前讲过根据应用本身是否需要持久存储数据以及某一次请求和之前的请求是否有联系,可以分为四类应用 a.有状态,要存储 b.有状态,无持久存储 c.无状态,要存储 d.无状态,无持久存储 ...
- Spark in action on Kubernetes - 存储篇(一)
前言 在上篇文章中,我们分析了Spark Operator内部的机制,今天我们会讨论一个在大数据领域中最重要的话题 - 存储.大数据已经无声无息的融入了每个人的生活中.大到旅游买房,小到外卖打车,都可 ...
随机推荐
- geos编译问题
gdal编译geos的时候会用到geos_c_i.lib这个文件,我用cmake编译的时候仅仅产生geos_c.lib这个文件,所以只能使用nmake的编译方式来编译geos库,nmake编译geos ...
- stm32学习心得体会
stm32作为现在嵌入式物联网单片机行业中经常要用多的技术,相信大家都有所接触,今天这篇就给大家详细的分析下有关于stm32的出口,还不是很清楚的朋友要注意看看了哦,在最后还会为大家分享有些关于stm ...
- Hash算法:双重散列
双重散列是线性开型寻址散列(开放寻址法)中的冲突解决技术.双重散列使用在发生冲突时将第二个散列函数应用于键的想法. 此算法使用: (hash1(key) + i * hash2(key)) % TAB ...
- 转:(WIN)S04-CH01 PCIE XDMA开发环境搭建以及环路测试
摘要: 这一章开始主要介绍 XILINX FPGA PICE IP XDMA IP的使用.XDMA IP使用部分教程分LINUX 篇和WINDOWS篇两个部分.通过实战,面向应用,提供给大家 XILI ...
- linked-list-cycle leetcode C++
Given a linked list, determine if it has a cycle in it. Follow up: Can you solve it without using ex ...
- vue3.x版本路由router跳转+传参
显示传参模式 get import { useRouter } from 'vue-router'; const router = useRouter(); let skipEdit = (key: ...
- 自定义容器tomcat应用
看不懂可以先去看:https://www.cnblogs.com/leihongnu/p/14506704.html 1.将103服务器上的mytomcat镜像打包为mytomcat.gz(花时间比较 ...
- Qt5 C++ GUI界面 开发环境配置 详细教程
本博客已暂停更新,需要请转新博客http://www.whbwiki.com/333.html Qt 下载 Qt 体积很大,有 1GB~3GB,官方下载通道非常慢,相信很多读者会崩溃,所以建议大家使用 ...
- go的常用数据类型-持续优化篇
p.p1 { margin: 0; font: 12px "Helvetica Neue"; color: rgba(69, 69, 69, 1) } p.p2 { margin: ...
- 字符编码和python文件操作
字符编码和文件操作 目录 字符编码和文件操作 1. 字符编码 1.1 什么是字符编码 1.2 字符编码的发展史 1.2.1 ASCII码 1.2.2 各国编码 1.2.3 Unicode 1.3 字符 ...