Kubernetes(k8s)存储管理之数据卷volumes(二):hostPath数据卷
阅读原文时间:2023年07月08日阅读:3

目录

一.系统环境

服务器版本

docker软件版本

Kubernetes(k8s)集群版本

CPU架构

CentOS Linux release 7.4.1708 (Core)

Docker version 20.10.12

v1.21.9

x86_64

Kubernetes集群架构:k8scloude1作为master节点,k8scloude2,k8scloude3作为worker节点

服务器

操作系统版本

CPU架构

进程

功能描述

k8scloude1/192.168.110.130

CentOS Linux release 7.4.1708 (Core)

x86_64

docker,kube-apiserver,etcd,kube-scheduler,kube-controller-manager,kubelet,kube-proxy,coredns,calico

k8s master节点

k8scloude2/192.168.110.129

CentOS Linux release 7.4.1708 (Core)

x86_64

docker,kubelet,kube-proxy,calico

k8s worker节点

k8scloude3/192.168.110.128

CentOS Linux release 7.4.1708 (Core)

x86_64

docker,kubelet,kube-proxy,calico

k8s worker节点

二.前言

Kubernetes(k8s)数据卷volumes类型众多,本文介绍数据卷volumes之一hostPath数据卷

使用数据卷volumes的前提是已经有一套可以正常运行的Kubernetes集群,关于Kubernetes(k8s)集群的安装部署,可以查看博客《Centos7 安装部署Kubernetes(k8s)集群》https://www.cnblogs.com/renshengdezheli/p/16686769.html

三.hostPath数据卷

警告:HostPath 卷存在许多安全风险,最佳做法是尽可能避免使用 HostPath。 当必须使用 HostPath 卷时,它的范围应仅限于所需的文件或目录,并以只读方式挂载。如果通过 AdmissionPolicy 限制 HostPath 对特定目录的访问,则必须要求 volumeMounts 使用 readOnly 挂载以使策略生效。

hostPath 卷能将主机节点文件系统上的文件或目录挂载到你的 Pod 中。 虽然这不是大多数 Pod 需要的,但是它为一些应用程序提供了强大的逃生舱。

例如,hostPath 的一些用法有:

  • 运行一个需要访问 Docker 内部机制的容器;可使用 hostPath 挂载 /var/lib/docker 路径。
  • 在容器中运行 cAdvisor 时,以 hostPath 方式挂载 /sys
  • 允许 Pod 指定给定的 hostPath 在运行 Pod 之前是否应该存在,是否应该创建以及应该以什么方式存在。

除了必需的 path 属性之外,你可以选择性地为 hostPath 卷指定 type

支持的 type 值如下:

取值

行为

空字符串(默认)用于向后兼容,这意味着在安装 hostPath 卷之前不会执行任何检查。

DirectoryOrCreate

如果在给定路径上什么都不存在,那么将根据需要创建空目录,权限设置为 0755,具有与 kubelet 相同的组和属主信息。

Directory

在给定路径上必须存在的目录。

FileOrCreate

如果在给定路径上什么都不存在,那么将在那里根据需要创建空文件,权限设置为 0644,具有与 kubelet 相同的组和所有权。

File

在给定路径上必须存在的文件。

Socket

在给定路径上必须存在的 UNIX 套接字。

CharDevice

在给定路径上必须存在的字符设备。

BlockDevice

在给定路径上必须存在的块设备。

当使用这种类型的卷时要小心,因为:

HostPath 卷可能会暴露特权系统凭据(例如 Kubelet)或特权 API(例如容器运行时套接字),可用于容器逃逸或攻击集群的其他部分。

具有相同配置(例如基于同一 PodTemplate 创建)的多个 Pod 会由于节点上文件的不同而在不同节点上有不同的行为。下层主机上创建的文件或目录只能由 root 用户写入。 你需要在特权容器中以 root 身份运行进程,或者修改主机上的文件权限以便容器能够写入 hostPath 卷。

注意:FileOrCreate 模式不会负责创建文件的父目录。 如果欲挂载的文件的父目录不存在,Pod 启动会失败。 为了确保这种模式能够工作,可以尝试把文件和它对应的目录分开挂载。

hostPath卷类似于docker run -v /data:/xx

配置本地卷hostPath,把v1卷挂载到/xx目录

[root@k8scloude1 volume]# vim hostpath.yaml 

[root@k8scloude1 volume]# cat hostpath.yaml
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: hostpath
  name: hostpath
spec:
  terminationGracePeriodSeconds: 0
  #指定卷
  volumes:
  #卷的名字
  - name: v1
    #卷的类型为hostPath
    hostPath:
      #宿主上目录位置
      path: /hostdir
  containers:
  - image: nginx
    imagePullPolicy: IfNotPresent
    name: h1
    resources: {}
    volumeMounts:
    - name: v1
      mountPath: /xx
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

创建pod

[root@k8scloude1 volume]# kubectl apply -f hostpath.yaml
pod/hostpath created

[root@k8scloude1 volume]# kubectl get pods -o wide
NAME       READY   STATUS    RESTARTS   AGE   IP               NODE         NOMINATED NODE   READINESS GATES
hostpath   1/1     Running   0          6s    10.244.112.183   k8scloude2   <none>           <none>

进入pod,/xx/hostpath.txt写入数据

[root@k8scloude1 volume]# kubectl exec -it hostpath -- bash
root@hostpath:/# echo "hostPath" >/xx/hostpath.txt
root@hostpath:/#
root@hostpath:/# ls /xx/
hostpath.txt  test.txt
root@hostpath:/#
root@hostpath:/# exit
exit

在对应的k8scloude2上查看容器

[root@k8scloude2 ~]# docker ps | grep hostpath
6e4d959332d3   605c77e624dd                                          "/docker-entrypoint.…"   33 seconds ago   Up 33 seconds             k8s_h1_hostpath_volume_9bbf4660-7e37-4c38-b2db-900246301329_0
f5e3d63fe676   registry.aliyuncs.com/google_containers/pause:3.4.1   "/pause"                 34 seconds ago   Up 33 seconds             k8s_POD_hostpath_volume_9bbf4660-7e37-4c38-b2db-900246301329_0

查看物理机目录:/hostdir,容器目录:/xx

[root@k8scloude2 ~]# docker inspect 6e4d959332d3 | grep -A10 Mounts
        "Mounts": [
            {
                "Type": "bind",
                "Source": "/hostdir",
                "Destination": "/xx",
                "Mode": "",
                "RW": true,
                "Propagation": "rprivate"
            },
            {
                "Type": "bind",

pod里创建了hostpath.txt,对应的物理机目录也生成了文件

[root@k8scloude2 ~]# cat /hostdir/hostpath.txt
hostPath

[root@k8scloude2 ~]# touch /hostdir/test.txt

[root@k8scloude2 ~]# ls /hostdir/
hostpath.txt  test.txt

删除pod

[root@k8scloude1 volume]# kubectl delete pod hostpath --force
warning: Immediate deletion does not wait for confirmation that the running resource has been terminated. The resource may continue to run on the cluster indefinitely.
pod "hostpath" force deleted

pod删除了之后,k8scloude2对应物理机上的文件还存在

[root@k8scloude2 ~]# ls /hostdir/
hostpath.txt  test.txt

再次创建pod,对应的/xx/下的文件还在

[root@k8scloude1 volume]# kubectl apply -f hostpath.yaml
pod/hostpath created

[root@k8scloude1 volume]# kubectl exec -it hostpath -- bash
root@hostpath:/# ls /xx/
hostpath.txt  test.txt
root@hostpath:/# exit
exit

[root@k8scloude1 volume]# kubectl delete pod hostpath --force
warning: Immediate deletion does not wait for confirmation that the running resource has been terminated. The resource may continue to run on the cluster indefinitely.
pod "hostpath" force deleted

Tps:假如hostpath.yaml文件丢失了,就可kubectl get pod hostpath -o yaml >hostpathpodx.yaml使用这种方式进行备份yaml文件,运行hostpathpodx.yaml文件,生成一个一模一样的pod

[root@k8scloude1 volume]# kubectl apply -f hostpath.yaml
pod/hostpath created

[root@k8scloude1 volume]# kubectl get pods -o wide
NAME       READY   STATUS    RESTARTS   AGE   IP               NODE         NOMINATED NODE   READINESS GATES
hostpath   1/1     Running   0          5s    10.244.112.185   k8scloude2   <none>           <none>

[root@k8scloude1 volume]# kubectl get pod hostpath -o yaml >hostpathpodx.yaml

[root@k8scloude1 volume]# vim hostpathpodx.yaml 

[root@k8scloude1 volume]# kubectl delete pod hostpath --force
warning: Immediate deletion does not wait for confirmation that the running resource has been terminated. The resource may continue to run on the cluster indefinitely.
pod "hostpath" force deleted

[root@k8scloude1 volume]# kubectl get pods -o wide
No resources found in volume namespace.

重新生成的pod和之前一模一样

[root@k8scloude1 volume]# kubectl apply -f hostpathpodx.yaml
pod/hostpath created

[root@k8scloude1 volume]# kubectl get pods -o wide
NAME       READY   STATUS    RESTARTS   AGE   IP               NODE         NOMINATED NODE   READINESS GATES
hostpath   1/1     Running   0          6s    10.244.112.186   k8scloude2   <none>           <none>

[root@k8scloude1 volume]# kubectl exec -it hostpath -- bash
root@hostpath:/# ls /xx/
hostpath.txt  test.txt
root@hostpath:/# exit
exit

[root@k8scloude1 volume]# kubectl delete pod hostpath --force
warning: Immediate deletion does not wait for confirmation that the running resource has been terminated. The resource may continue to run on the cluster indefinitely.
pod "hostpath" force deleted

可以添加readOnly: true选项,使容器目录只具有只读权限

[root@k8scloude1 volume]# vim hostpath.yaml 

[root@k8scloude1 volume]# cat hostpath.yaml
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: hostpath
  name: hostpath
spec:
  terminationGracePeriodSeconds: 0
  volumes:
  - name: v1
    hostPath:
      path: /hostdir
  containers:
  - image: nginx
    imagePullPolicy: IfNotPresent
    name: h1
    resources: {}
    volumeMounts:
    - name: v1
      mountPath: /xx
      readOnly: true
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

创建pod

[root@k8scloude1 volume]# kubectl apply -f hostpath.yaml
pod/hostpath created

[root@k8scloude1 volume]# kubectl get pod -o wide
NAME       READY   STATUS    RESTARTS   AGE   IP               NODE         NOMINATED NODE   READINESS GATES
hostpath   1/1     Running   0          10s   10.244.112.187   k8scloude2   <none>           <none>

只读权限,不能创建文件

[root@k8scloude1 volume]# kubectl exec -it hostpath -- bash
root@hostpath:/# ls /xx/
hostpath.txt  test.txt
root@hostpath:/# touch /xx/ceshi.txt
touch: cannot touch '/xx/ceshi.txt': Read-only file system
root@hostpath:/# exit
exit
command terminated with exit code 1

删除pod

[root@k8scloude1 volume]# kubectl delete pod hostpath --force
warning: Immediate deletion does not wait for confirmation that the running resource has been terminated. The resource may continue to run on the cluster indefinitely.
pod "hostpath" force deleted

nodeName: k8scloude3,让pod运行在k8scloude3上

[root@k8scloude1 volume]# vim hostpath.yaml 

[root@k8scloude1 volume]# cat hostpath.yaml
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: hostpath
  name: hostpath
spec:
  nodeName: k8scloude3
  terminationGracePeriodSeconds: 0
  volumes:
  - name: v1
    hostPath:
      path: /hostdir
  containers:
  - image: nginx
    imagePullPolicy: IfNotPresent
    name: h1
    resources: {}
    volumeMounts:
    - name: v1
      mountPath: /xx
      readOnly: true
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

创建pod

[root@k8scloude1 volume]# kubectl apply -f hostpath.yaml
pod/hostpath created

[root@k8scloude1 volume]# kubectl get pod -o wide
NAME       READY   STATUS    RESTARTS   AGE   IP               NODE         NOMINATED NODE   READINESS GATES
hostpath   1/1     Running   0          3s    10.244.251.250   k8scloude3   <none>           <none>

对应的/xx/目录下面没文件,因为刚才是在k8scloude2上创建的文件,现在k8scloude3上没文件,所以/xx/下面没文件,由于k8scloude2和k8scloude3没有共享存储,所以k8scloude2上有的文件,k8scloude3上没有,可以使用共享存储卷来解决此问题。共享存储卷请查看博客《Kubernetes(k8s)存储管理之数据卷volumes(三):NFS数据卷》

[root@k8scloude1 volume]# kubectl exec -it hostpath -- bash
root@hostpath:/# ls /xx/
root@hostpath:/#
root@hostpath:/# exit
exit