发布于 2026-01-06 1 阅读
0

教程:Kubernetes 卷的基础知识(第 1 部分)DEV 的全球展示挑战赛,由 Mux 呈现:展示你的项目!

教程:Kubernetes 卷的基础知识(第 1 部分)

由 Mux 主办的 DEV 全球展示挑战赛:展示你的项目!

我们将继续“Kubernetes 入门指南”系列,本部分将介绍 Kubernetes 卷!您将学习到:

  • 概述Volumes 及其必要性
  • 如何使用Volume
  • 提供实际操作示例以帮助探索Volumes 的实际应用

代码已上传至 GitHub。

欢迎通过Twitter或留言的方式向我们反馈!

先决条件:

你需要minikubekubectl

在计算机上的虚拟机中安装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
Enter fullscreen mode Exit fullscreen mode

安装后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
Enter fullscreen mode Exit fullscreen mode

概述

存储在 Docker 容器中的数据是短暂的,也就是说,它只存在于容器存活期间。Kubernetes 可以重启失败或崩溃的容器(在同一容器内Pod),但您仍然会丢失存储在容器文件系统中的所有数据。Kubernetes 通过云存储解决了这个问题Volume。它支持多种类型的Volume云存储,包括外部云存储(例如Azure Disk、Amazon EBS、GCE Persistent Disk 等)、网络文件系统(例如 Ceph、GlusterFS 等)以及其他选项,例如云存储emptyDir、云存储hostPath、云local存储downwardAPI、云存储等secretconfig

容量是如何使用的?

使用 aVolume相对简单——请看这个部分Pod规范示例。

spec:
  containers:
  - name: kvstore
    image: abhirockzz/kvstore:latest
    volumeMounts:
    - mountPath: /data
      name: data-volume
    ports:
    - containerPort: 8080
  volumes:
    - name: data-volume
      emptyDir: {}
Enter fullscreen mode Exit fullscreen mode

请注意以下几点:

  • 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
Enter fullscreen mode Exit fullscreen mode

部署kvstore应用程序。这将创建一个Deployment包含一个Pod应用程序实例()以及一项NodePort服务的容器。

kubectl apply -f https://raw.githubusercontent.com/abhirockzz/kubernetes-in-a-nutshell/master/volumes-1/kvstore.yaml
Enter fullscreen mode Exit fullscreen mode

为了简单起见,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
Enter fullscreen mode Exit fullscreen mode

如果您不了解什么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
Enter fullscreen mode Exit fullscreen mode

检查该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'
Enter fullscreen mode Exit fullscreen mode

例如

curl http://192.168.99.100:32598/save -d 'foo=bar'
curl http://192.168.99.100:32598/save -d 'mac=cheese'
Enter fullscreen mode Exit fullscreen mode

访问键的值foo

curl http://[host]:[port]/read/foo
Enter fullscreen mode Exit fullscreen mode

你应该得到你之前保存的值foobar同样,对于mac其他情况,你也会得到cheese相应的值。程序会将键值对数据保存在某个位置/data——让我们直接查看 Docker 容器内部来确认这一点。Pod

kubectl exec <pod name> -- ls /data/

foo
mac
Enter fullscreen mode Exit fullscreen mode

foo这些mac文件是以键名命名的独立文件。如果我们进一步深入研究,应该也能确认它们各自的值。

确认密钥的值mac

kubectl exec <pod name> -- cat /data/mac`

cheese
Enter fullscreen mode Exit fullscreen mode

正如预期的那样,你得到了cheese正确的答案,因为那是你之前存储的密钥。如果你尝试查找尚未存储的密钥,将会收到错误提示。

cat: can't open '/data/moo': No such file or directory
command terminated with exit code 1
Enter fullscreen mode Exit fullscreen mode

终止容器 ;-)

好了,目前为止一切顺利!使用这种方法Volume可以确保数据在容器重启/崩溃后仍然保留。我们稍微“作弊”一下,手动终止 Docker 容器。

kubectl exec [pod name] -- ps

PID   USER     TIME  COMMAND
  1   root     0:00 /kvstore
  31 root      0:00  ps
Enter fullscreen mode Exit fullscreen mode

请注意应用程序的进程 ID kvstore(应该是1)。

在另一个终端上,监控这些舱体。

kubectl get pods -l app=kvstore --watch
Enter fullscreen mode Exit fullscreen mode

我们终止了应用程序进程

kubectl exec [pod name] -- kill 1
Enter fullscreen mode Exit fullscreen mode

你会注意到,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
Enter fullscreen mode Exit fullscreen mode

执行此操作kubectl exec <pod name> -- ls /data以确认数据在容器重启后确实仍然存在。

删除 Pod!

但这些数据不会在 Pod 的生命周期结束后仍然存在。为了验证这一点,让我们Pod手动删除它们。

kubectl delete pod -l app=kvstore
Enter fullscreen mode Exit fullscreen mode

您应该会看到类似如下的确认信息。

pod "kvstore-6c94877886-gzq25" deleted
Enter fullscreen mode Exit fullscreen mode

Kubernetes 将Pod再次重启。几秒钟后您可以确认这一点。

kubectl get pods -l app=kvstore
Enter fullscreen mode Exit fullscreen mode

你应该会看到一个新PodRunning

获取 pod 名称并再次查看文件

kubectl get pods -l app=kvstore
kubectl exec [pod name] -- ls /data/store
Enter fullscreen mode Exit fullscreen mode

正如预期的那样,该/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
Enter fullscreen mode Exit fullscreen mode

这就完了?还没完呢!😉 这种方法也有局限性。我们将在本系列的下一部分讨论这些以及更多内容——敬请期待!

希望您喜欢这篇文章并从中有所收获😃😃 如果喜欢的话,请点赞并关注!

文章来源:https://dev.to/itnext/tutorial-basics-of-kubernetes-volumes-part-1-jhm