kubernetes笔记—卷和存储
临时卷 | Kubernetes
持久卷 | Kubernetes
问题随记
1、各个目录的含义
/var/lib/docker/containers /容器ID:容器数据
/var/lib/docker/overlay2
/var/lib/kubelet/pods/uid :pod中的数据,如临时卷、开启日志采集的日志(本质还是临时卷)等
持久卷存储位置:NFS主机/挂载目录/命名空间-PVC名称-PV名称
存储卷
除了可以让一个Pod里的多个容器共享文件、让容器的数据写到宿主机的磁盘上或者写文件到网络存储
中,Kubernetes的Volume还扩展出了一种非常有实用价值的功能,即容器配置文件集中化定义与管理,这是
通过ConfigMap这种新的资源对象来实现的
Volume类型
EmptyDir
一个emptyDir Volume是在Pod分配到Node时创建的。
它的初始内容为空,并且无须指定宿主机上对应的目录文件,因为这是Kubernetes自动分配的一个目录,
当Pod从Node上移除时,emptyDir中的数据也会被永久删除。
emptyDir的一些用途如下。
◎ 临时空间,例如用于某些应用程序运行时所需的临时目录,且无须永久保留。
◎ 长时间任务的中间过程CheckPoint的临时保存目录。
◎ 一个容器需要从另一个容器中获取数据的目录(多容器共享目录)。
参考:
《Kubernetes中容器到容器通信》
https://mp.weixin.qq.com/s/P-xKd6HeOGxyt-YXCnZjmQ
hostPath
hostPath为在Pod上挂载宿主机上的文件或目录,它通常可以用于以下几方面。
◎ 容器应用程序生成的日志文件需要永久保存时,可以使用宿主机的高速文件系统进行存储。
◎ 需要访问宿主机上Docker引擎内部数据结构的容器应用时,可以通过定义hostPath为宿主
机/var/lib/docker目录,使容器内部应用可以直接访问Docker的文件系统。
通常用于单节点情况 (集群状态下,pod容易被删除,而新pod可能会被调度到其他主机上)
NFS
安装
#关闭防火墙
$ systemctl stop firewalld.service
$ systemctl disable firewalld.service
#安装配置 nfs
$ yum -y install nfs-utils rpcbind
#共享目录设置权限
$ mkdir -p /data/k8s/
$ chmod 755 /data/k8s/
#配置 nfs,nfs 的默认配置文件在 /etc/exports 文件下,在该文件中添加下面的配置信息
$ vi /etc/exports
/data/k8s *(rw,sync,no_root_squash)
#/data/k8s:是共享的数据目录
#*:表示任何人都有权限连接,当然也可以是一个网段,一个 IP,也可以是域名
#rw:读写的权限
#sync:表示文件同时写入硬盘和内存
#no_root_squash:当登录 NFS 主机使用共享目录的使用者是 root 时,
#其权限将被转换成为匿名使用者,通常它的 UID 与 GID,都会变成 nobody 身份
启动
#启动 rpcbind
$ systemctl start rpcbind.service
$ systemctl enable rpcbind
$ systemctl status rpcbind
#启动NFS服务
$ systemctl start nfs.service
$ systemctl enable nfs
$ systemctl status nfs
#验证
$ rpcinfo -p|grep nfs
$ cat /var/lib/nfs/etab
安装 nfs 的客户端
$ systemctl stop firewalld.service
$ systemctl disable firewalld.service
$ yum -y install nfs-utils rpcbind
$ systemctl start rpcbind.service
$ systemctl enable rpcbind.service
$ systemctl start nfs.service
$ systemctl enable nfs.service
在客户端验证
$ showmount -e <nfs_server_ip>
#新建一个目录
$ mkdir -p /root/course/kubeadm/data
#挂载
$ mount -t nfs <nfs_server_ip>:/data/k8s /root/course/kubeadm/data
在客户端新建一个文件
$ touch /root/course/kubeadm/data/test.txt
在服务端查看是否有文件:
$ ls -ls /data/k8s/
PV和PVC
PV(持久卷):描述一个具体的Volume属性,比如Volume的类型、挂载目录、远程存储服务器地址等
PV可以被理解成Kubernetes集群中的某个网络存储对应的一块存储,它与Volume类似,但有以下区
别。
◎ PV只能是网络存储,不属于任何Node,但可以在每个Node上访问。
◎ PV并不是被定义在Pod上的,而是独立于Pod之外定义的。
PV 描述的,是持久化存储数据卷。这个 API 对象主要定义的是一个持久化存储在宿主机上的目录,比如一个 NFS 的挂载目录。
通常情况下,PV 对象是由运维人员事先创建在 Kubernetes 集群里待用的
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs
spec:
storageClassName: manual
capacity:
storage: 1Gi
accessModes:
- ReadWriteMany
nfs:
server: 10.244.1.4
path: "/"
PVC(持久卷声明):描述 Pod想要使用的持久化属性,比如存储大小、读写权限等
PVC 对象通常由开发人员创建;或者以 PVC 模板的方式成为 StatefulSet 的一部分,然后由 StatefulSet 控制器负责创建带编号的 PVC。
创建PVC:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nfs
spec:
accessModes:
- ReadWriteMany
storageClassName: manual
resources:
requests:
storage: 1Gi
使用PVC
用户创建的 PVC 要真正被容器使用起来,就必须先和某个符合条件的 PV 进行绑定。(满足存储大小、storageClassName等条件)
绑定后,即可使用:
apiVersion: v1
kind: Pod
metadata:
labels:
role: web-frontend
spec:
containers:
- name: web
image: nginx
ports:
- name: web
containerPort: 80
volumeMounts:
- name: nfs
mountPath: "/usr/share/nginx/html"
volumes:
- name: nfs
persistentVolumeClaim:
claimName: nfs
StorageClass
一个大规模的 Kubernetes 集群里很可能有成千上万个 PVC,这就意味着运维人员必须得事先创建出成千上万个 PV。在实际操作中,这几乎没办法靠人工做到。
Kubernetes 为我们提供了一套可以自动创建 PV 的机制,即:Dynamic Provisioning。
Dynamic Provisioning 机制工作的核心,在于一个名叫 StorageClass 的 API 对象
StorageClass 对象的作用,其实就是创建 PV 的模板。具体地说,StorageClass 对象会定义如下两个部分内容:
第一,PV 的属性。比如,存储类型、Volume 的大小等等。
第二,创建这种 PV 需要用到的存储插件。比如,Ceph 等等。
StorageClass作为对存储资源的抽象定义,对用户设置的PVC申请屏蔽后端存储的细节,一方面减少了
用户对于存储资源细节的关注,另一方面减轻了管理员手工管理PV的工作,由系统自动完成PV的创建和绑
定,实现了动态的资源供应。基于StorageClass的动态资源供应模式将逐步成为云平台的标准存储配置模
式。
StorageClass的定义主要包括名称、后端存储的提供者(provisioner)和后端存储的相关参数配置。
从图中我们可以看到,在这个体系中:
- PVC 描述的,是 Pod 想要使用的持久化存储的属性,比如存储的大小、读写权限等。
- PV 描述的,则是一个具体的 Volume 的属性,比如 Volume 的类型、挂载目录、远程存储服务器地址等。
- 而 StorageClass 的作用,则是充当 PV 的模板。并且,只有同属于一个 StorageClass 的 PV 和 PVC,才可以绑定在一起。
配置卷
Projected Volume
在 Kubernetes 中,有几种特殊的 Volume,它们存在的意义不是为了存放容器里的数据,也不是用来进行容器和宿主机之间的数据交换。这些特殊 Volume 的作用,是为容器提供预先定义好的数据。所以,从容器的角度来看,这些 Volume 里的信息就是仿佛是被 Kubernetes“投射”(Project)进入容器当中的。这正是 Projected Volume 的含义。
到目前为止,Kubernetes 支持的 Projected Volume 一共有四种:
Secret;
ConfigMap;
Downward API;
ServiceAccountToken。
Secret
从文件夹创建
#首先创建目录secret-test,创建两个文件,写入
[root@zm secret-test]# cat user
test
[root@zm secret-test]# cat pass
test
[root@zm secret-test]# kubectl -n cka create secret generic my-secret --from-file=.
secret/my-secret created
#查看
[root@zm secret-test]# kubectl -n cka get secrets my-secret -o yaml
apiVersion: v1
data:
pass: dGVzdAo=
user: dGVzdAo=
kind: Secret
metadata:
creationTimestamp: "2022-04-20T03:16:57Z"
name: my-secret
namespace: cka
resourceVersion: "568020"
uid: f4dffc10-0a9e-405f-8ed8-f78544060f7c
type: Opaque
从YAML文件创建
apiVersion: v1
kind: Secret
metadata:
name: mysecret
type: Opaque
data:
user: YWRtaW4=
pass: MWYyZDFlMmU2N2Rm
前提是需要先转码
#加密
[root@zm ~]# echo test|base64
dGVzdAo=
#解密
[root@zm ~]# echo dGVzdAo= |base64 -d
test
这里需要注意的是,像这样创建的 Secret 对象,它里面的内容仅仅是经过了转码,而并没有被加密。在真正的生产环境中,你需要在 Kubernetes 中开启 Secret 的加密插件,增强数据的安全性
ConfigMap
应用部署的一个最佳实践是将应用所需的配置信息与程序进行分离,这样可以使应用程序被更好地复
用,通过不同的配置也能实现更灵活的功能。从Kubernetes 1.2开始提供了一种统一的应用配置管理方案—ConfigMap
创建:与Secret类似
从文件/文件夹创建
文件名为key,文件内容为value
kubectl -n cka create cm my-cm --from-file=.
从YAML文件创建
使用场景:
1、环境变量;
2、配置文件
使用方式之-环境变量
与使用场景相对应,容器应用对ConfigMap的使用有以下两种方式。
(1)通过环境变量获取ConfigMap中的内容。
使用方式之-挂载到容器
(2)通过Volume挂载的方式将ConfigMap中的内容挂载为容器内部的文件或目录。
使用ConfigMap的限制条件
◎ConfigMap必须在Pod之前创建。
◎ ConfigMap受Namespace限制,只有处于相同Namespace中的Pod才可以引用它。
◎ ConfigMap中的配额管理还未能实现。
◎ kubelet只支持可以被API Server管理的Pod使用ConfigMap。kubelet在本Node上通过 —manifest-url
或—config自动创建的静态Pod将无法引用ConfigMap。
◎ 在Pod对ConfigMap进行挂载(volumeMount)操作时,在容器内部只能挂载为“目录”,无法挂载为“文件”。
- 容器以 subPath 卷挂载方式使用 ConfigMap 时,将无法接收 ConfigMap 的更新。
采用环境变量的方式使用ConfigMap:ConfigMap内存放键值对;无需挂载,需要在部署时定义环境变量去引用ConfigMap。适合于,应用内没有一个特定文件存放配置信息。
采用Volume挂载方式使用ConfigMap:ConfigMap内存放文件名和文件内容。适合于,应用内有特定文件来存放配置信息,或文件内容有特定格式要求。
Downward API
作用:让 Pod 里的容器能够直接获取到这个 Pod API 对象本身的信息。
例子:
定义了一个简单的容器,声明了一个 projected 类型的 Volume。只不过这次 Volume 的数据来源,变成了 Downward API。而这个 Downward API Volume,则声明了要暴露 Pod 的 metadata.labels 信息给容器。
通过这样的声明方式,当前 Pod 的 Labels 字段的值,就会被 Kubernetes 自动挂载成为容器里的 /etc/podinfo/labels 文件。
apiVersion: v1
kind: Pod
metadata:
name: test-downwardapi-volume
labels:
zone: us-est-coast
cluster: test-cluster1
rack: rack-22
spec:
containers:
- name: client-container
image: k8s.gcr.io/busybox
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. 使用fieldRef可以声明使用:
spec.nodeName - 宿主机名字
status.hostIP - 宿主机IP
metadata.name - Pod的名字
metadata.namespace - Pod的Namespace
status.podIP - Pod的IP
spec.serviceAccountName - Pod的Service Account的名字
metadata.uid - Pod的UID
metadata.labels['<KEY>'] - 指定<KEY>的Label值
metadata.annotations['<KEY>'] - 指定<KEY>的Annotation值
metadata.labels - Pod的所有Label
metadata.annotations - Pod的所有Annotation
2. 使用resourceFieldRef可以声明使用:
容器的CPU limit
容器的CPU request
容器的memory limit
容器的memory request
需要注意的是,Downward API 能够获取到的信息,一定是 Pod 里的容器进程启动之前就能够确定下来的信息。而如果你想要获取 Pod 容器运行后才会出现的信息,比如,容器进程的 PID,那就肯定不能使用 Downward API 了,而应该考虑在 Pod 里定义一个 sidecar 容器。
ServiceAccountToken
一种特殊的 Secret
Service Account 对象的作用,就是 Kubernetes 系统内置的一种“服务账户”,它是 Kubernetes 进行权限分配的对象。比如,Service Account A,可以只被允许对 Kubernetes API 进行 GET 操作,而 Service Account B,则可以有 Kubernetes API 的所有操作权限。
像这样的 Service Account 的授权信息和文件,实际上保存在它所绑定的一个特殊的 Secret 对象里的。这个特殊的 Secret 对象,就叫作 ServiceAccountToken。
如果你查看一下任意一个运行在 Kubernetes 集群里的 Pod,就会发现,每一个 Pod,都已经自动声明一个类型是 Secret、名为 default-token-xxxx 的 Volume,然后 自动挂载在每个容器的一个固定目录上
$ kubectl describe pod nginx-deployment-5c678cfb6d-lg9lw
Containers:
...
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from default-token-s8rbq (ro)
Volumes:
default-token-s8rbq:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-s8rbq
Optional: false
高级
一文理解 Kubernetes 的存储系统机制
https://mp.weixin.qq.com/s/XLe6pnGNCeM5ilTRiJfwKA
《Kubernetes 存储原理解析》
https://mp.weixin.qq.com/s/bkpZMbmKa6lBKg8Fc3Lkzw
Kubernetes存储架构原理深度剖析(上、下)
https://mp.weixin.qq.com/s/juKJWg7dXtOSBFOSu84kjQ
https://mp.weixin.qq.com/s/FFt_Y1Kt6tNtNGe50QpQUQ