教程:Kubernetes 卷的基础知识(第 1 部分)
由 Mux 主办的 DEV 全球展示挑战赛:展示你的项目!
我们将继续“Kubernetes 入门指南”系列,本部分将介绍 Kubernetes 卷!您将学习到:
- 概述
Volumes 及其必要性 - 如何使用
Volume - 提供实际操作示例以帮助探索
Volumes 的实际应用
代码已上传至 GitHub。
欢迎通过Twitter或留言的方式向我们反馈!
先决条件:
你需要minikube和kubectl。
在计算机上的虚拟机中安装minikube单节点 Kubernetes 集群。在 Mac 上,您可以简单地:
curl -Lo minikube https://storage.googleapis.com/minikube/releases/latest/minikube-darwin-amd64 \
&& chmod +x minikube
sudo mv minikube /usr/local/bin
安装后kubectl即可与您的 AKS 集群交互。在 Mac 上,您可以简单地执行以下操作:
curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/darwin/amd64/kubectl
chmod +x ./kubectl
sudo mv ./kubectl /usr/local/bin/kubectl
概述
存储在 Docker 容器中的数据是短暂的,也就是说,它只存在于容器存活期间。Kubernetes 可以重启失败或崩溃的容器(在同一容器内Pod),但您仍然会丢失存储在容器文件系统中的所有数据。Kubernetes 通过云存储解决了这个问题Volume。它支持多种类型的Volume云存储,包括外部云存储(例如Azure Disk、Amazon EBS、GCE Persistent Disk 等)、网络文件系统(例如 Ceph、GlusterFS 等)以及其他选项,例如云存储emptyDir、云存储hostPath、云local存储downwardAPI、云存储等secret。config
容量是如何使用的?
使用 aVolume相对简单——请看这个部分Pod规范示例。
spec:
containers:
- name: kvstore
image: abhirockzz/kvstore:latest
volumeMounts:
- mountPath: /data
name: data-volume
ports:
- containerPort: 8080
volumes:
- name: data-volume
emptyDir: {}
请注意以下几点:
spec.volumes- 声明可用卷及其name(例如data-volume)和其他卷特定特征,例如,在本例中,它指向 Azure 磁盘。spec.containers.volumeMountsspec.volumes- 它指向在(例如)中声明的卷data-volume,并准确指定要在容器文件系统中挂载该卷的位置(例如/data)。
一个容器可以声明Pod多个卷。容器内的所有容器都可以访问这些卷,但并非所有容器都必须挂载或使用所有卷。如有需要,容器内的容器可以将多个卷挂载到其文件系统中的不同路径。此外,不同的容器可以同时挂载同一个卷。Volumespec.volumesVolumePodPod
另一种对卷册进行分类的方法
我喜欢将它们分为:
- 短暂性-与生命周期(例如卷)
Volume紧密相关的 s ,即如果该卷被移除(由于任何原因),它们也会被删除。PodemptyDirPod - 持久化存储——
Volume用于长期存储且独立于Pod生命Node周期。这可以是NFS本地存储,也可以是云存储,例如在 Azure Kubernetes 服务、Google Kubernetes Engine 等托管 Kubernetes 服务中。
我们来看emptyDir一个例子
emptyDir 卷正在运行
卷emptyDir初始状态为空(因此得名!),并且具有短暂性,即仅在容器Pod存活期间存在。一旦容器Pod被删除,emptyDir数据也会随之消失。它在某些场景/需求中非常有用,例如临时缓存、多个容器的共享存储等等Pod。
为了运行这个示例,我们将使用一个简单的、过于简化的键值存储,它公开了用于以下用途的 REST API:
- 添加键值对
- 读取键的值
如果你感兴趣,这是代码。
初始部署
minikube如果尚未运行,则启动。
minikube start
部署kvstore应用程序。这将创建一个Deployment包含一个Pod应用程序实例()以及一项NodePort服务的容器。
kubectl apply -f https://raw.githubusercontent.com/abhirockzz/kubernetes-in-a-nutshell/master/volumes-1/kvstore.yaml
为了简单起见,YAML 文件直接引用自GitHub 仓库,但您也可以将该文件下载到本地计算机并以相同的方式使用它。
确认它们已创建
kubectl get deployments kvstore
NAME READY UP-TO-DATE AVAILABLE AGE
kvstore 1/1 1 1 28s
kubectl get pods -l app=kvstore
NAME READY STATUS RESTARTS AGE
kvstore-6c94877886-gzq25 1/1 Running 0 40s
如果您不了解什么
NodePort是服务,没关系——我们将在后续的博客文章中进行讲解。目前,您只需明白服务是访问我们应用程序的一种方式(在本例中为 REST 端点)。
检查服务生成的随机端口值NodePort- 您可能会看到类似这样的结果(IP 地址和端口不同)。
kubectl get service kvstore-service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kvstore-service NodePort 10.106.144.48 <none> 8080:32598/TCP 5m
检查该PORT(S)列以找出随机端口,例如32598本例中的(8080是我们的应用程序暴露的容器内的内部端口 - 请忽略它)。
minikube现在,您只需要使用您的节点的 IP 地址即可。minikube ip
192.168.99.100如果您使用的是 VirtualBox 虚拟机,则可能会返回类似这样的结果。
在以下命令中,将host`<minikube VM IP>` 替换为 minikube 虚拟机的 IP 地址,port将 `<random port value>` 替换为随机端口值。
创建几个新的键值对条目
curl http://[host]:[port]/save -d 'foo=bar'
curl http://[host]:[port]/save -d 'mac=cheese'
例如
curl http://192.168.99.100:32598/save -d 'foo=bar'
curl http://192.168.99.100:32598/save -d 'mac=cheese'
访问键的值foo
curl http://[host]:[port]/read/foo
你应该得到你之前保存的值foo。bar同样,对于mac其他情况,你也会得到cheese相应的值。程序会将键值对数据保存在某个位置/data——让我们直接查看 Docker 容器内部来确认这一点。Pod
kubectl exec <pod name> -- ls /data/
foo
mac
foo这些mac文件是以键名命名的独立文件。如果我们进一步深入研究,应该也能确认它们各自的值。
确认密钥的值mac
kubectl exec <pod name> -- cat /data/mac`
cheese
正如预期的那样,你得到了cheese正确的答案,因为那是你之前存储的密钥。如果你尝试查找尚未存储的密钥,将会收到错误提示。
cat: can't open '/data/moo': No such file or directory
command terminated with exit code 1
终止容器 ;-)
好了,目前为止一切顺利!使用这种方法Volume可以确保数据在容器重启/崩溃后仍然保留。我们稍微“作弊”一下,手动终止 Docker 容器。
kubectl exec [pod name] -- ps
PID USER TIME COMMAND
1 root 0:00 /kvstore
31 root 0:00 ps
请注意应用程序的进程 ID
kvstore(应该是1)。
在另一个终端上,监控这些舱体。
kubectl get pods -l app=kvstore --watch
我们终止了应用程序进程
kubectl exec [pod name] -- kill 1
你会注意到,Pod 会经历几个阶段(例如Error等等),然后才会回到Running状态(由 Kubernetes 重新启动)。
NAME READY STATUS RESTARTS AGE
kvstore-6c94877886-gzq25 1/1 Running 0 15m
kvstore-6c94877886-gzq25 0/1 Error 0 15m
kvstore-6c94877886-gzq25 1/1 Running 1 15m
执行此操作kubectl exec <pod name> -- ls /data以确认数据在容器重启后确实仍然存在。
删除 Pod!
但这些数据不会在 Pod 的生命周期结束后仍然存在。为了验证这一点,让我们Pod手动删除它们。
kubectl delete pod -l app=kvstore
您应该会看到类似如下的确认信息。
pod "kvstore-6c94877886-gzq25" deleted
Kubernetes 将Pod再次重启。几秒钟后您可以确认这一点。
kubectl get pods -l app=kvstore
你应该会看到一个新的
Pod州Running
获取 pod 名称并再次查看文件
kubectl get pods -l app=kvstore
kubectl exec [pod name] -- ls /data/store
正如预期的那样,该/data/目录为空!
对持久存储的需求
简单的(临时的)Volume数据存储会随着节点的生命周期而消亡,Pod但这对于大多数应用程序来说远远不够。为了实现弹性、可靠性、可用性和可扩展性,Kubernetes 应用程序需要能够在多个 Pod 中以多个实例运行,而这些 Pod 本身可能被调度或放置在 Kubernetes 集群中的不同节点上。我们需要的是一个稳定且持久的存储,其寿命Pod甚至超过NodePod 运行所在的节点。
正如本博客开头提到的那样,使用起来很简单Volume——不仅是像我们刚才看到的那种临时存储,甚至是长期持久存储。
以下是一个(人为设计的)示例,说明如何使用Azure 磁盘作为部署到Azure Kubernetes 服务的应用程序的存储介质。
apiVersion: v1
kind: Pod
metadata:
name: testpod
spec:
volumes:
- name: logs-volume
azureDisk:
kind: Managed
diskName: myAKSDiskName
diskURI: myAKSDiskURI
containers:
- image: myapp-docker-image
name: myapp
volumeMounts:
- mountPath: /app/logs
name: logs-volume
这就完了?还没完呢!😉 这种方法也有局限性。我们将在本系列的下一部分讨论这些以及更多内容——敬请期待!
希望您喜欢这篇文章并从中有所收获😃😃 如果喜欢的话,请点赞并关注!
文章来源:https://dev.to/itnext/tutorial-basics-of-kubernetes-volumes-part-1-jhm


