rancher-desktop with k3s 如何做基于hostpath的本地持久化?

rancher-desktop with k3s 如何做基于hostpath的本地持久化?

我希望用rancher-desktop,搭配k3s,在我的mac上部署一个postgres,并且创建数据库所需的文件我希望持久化到一个我指定的路径/Users/<username>/Workspaces/postgres/pg_data
但持久化到我的Mac上这个需求始终不能解决,每次rancher-desktop都是自己创建了一个映射到lima虚拟机内的/var/lib/rancher/k3s/storage/pv,但是我如果把rancher-desktop with k3s换成Docker-desktop with k8s,就没有问题,可以顺利完成,yaml文件是一样的:

# 安装postgres

# 定义一个命名空间
apiVersion: v1
kind: Namespace
metadata:
  name: postgresd
---

# 定义配置
apiVersion: v1
kind: ConfigMap
metadata:
  name: postgres-config
  namespace: postgresd
data:
  POSTGRES_DB: postgres
  MAX_CONNECTIONS: "10000"
  LOG_MIN_DURATION_STATEMENT: "500ms"
---

# 定义存储卷
apiVersion: v1
kind: PersistentVolume
metadata:
  name: postgres-data-pv
spec:
  capacity:
    storage: 10Gi  # 根据实际需求设置存储容量
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Delete
#  storageClassName: local-path
  hostPath:
    path: "/Users/hulei/Workspaces/postgres/pg_data"
#  nodeAffinity:
#    required:
#      nodeSelectorTerms:
#        - matchExpressions:
#          - key: kubernetes.io/hostname
#            operator: In
#            values:
#              - lima-rancher-desktop
---

# 定义用户名、密码等敏感信息
apiVersion: v1
kind: Secret
metadata:
  name: postgres-secret
  namespace: postgresd
type: Opaque
data:
  postgres-user: cG9zdGdyZXM= # Base64编码的用户名,这里是"postgres"
  postgres-password: U2VjdXJlUGFzc3dvcmQ= # Base64编码的密码,这里是"SecurePassword"

---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: postgres-statefulset
  namespace: postgresd
spec:
  replicas: 1
  selector:
    matchLabels:
      app: postgres
  serviceName: postgres-serive
  template:
    metadata:
      labels:
        app: postgres
    spec:
      containers:
        - name: postgresd
          image: postgres:16.2-alpine3.19
          ports:
            - containerPort: 5432
              name: postgresd-port
          env:
            - name: POSTGRES_USER
              valueFrom:
                secretKeyRef:
                  name: postgres-secret
                  key: postgres-user
            - name: POSTGRES_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: postgres-secret
                  key: postgres-password
            - name: POSTGRES_DB
              valueFrom:
                configMapKeyRef:
                  name: postgres-config
                  key: POSTGRES_DB
          volumeMounts:
            - name: postgres-data
              mountPath: /var/lib/postgresql/data
              subPath: data
  volumeClaimTemplates:
    - metadata:
        name: postgres-data
      spec:
        accessModes: [ "ReadWriteOnce" ]
        resources:
          requests:
            storage: 5Gi
#        storageClassName: local-path
---

# 定义将5432端口映射到kind cluster  5432端口的service
apiVersion: v1
kind: Service
metadata:
  namespace: postgresd
  name: postgres-service
spec:
  selector:
    app: postgres
  ports:
  - port: 5432
    targetPort: 5432
  type: ClusterIP

我想知道如何在rancher-desktop中实现基于hostpath的本地持久化?

在我的mac上运行上述yaml文件后,kubectl get pv 总是得到如下结果:
image.png

k3s会自己创建一个pv,不会用我创建的pv,这是为什么?

阅读 890
avatarAI BotBETA

在 Rancher Desktop 中使用 k3s 实现基于 hostPath 的本地持久化时,你需要确保几个关键步骤被正确执行。下面是一些可能的解决步骤和注意事项:

  1. 确认路径可访问性

    • 确保你指定的路径 /Users/<username>/Workspaces/postgres/pg_data 在你的 Mac 上是存在的,并且 Rancher Desktop 有权访问这个路径。
    • 如果路径不存在,你需要先创建它。如果权限不足,你可能需要调整文件或文件夹的权限。
  2. 检查 hostPath 配置

    • 确保你的 PersistentVolume 配置中的 hostPath 字段正确指向了你希望使用的本地路径。
    • 在 hostPath 中使用绝对路径,并确保路径的格式正确。
  3. 节点亲和性(Node Affinity)

    • 在你的 PersistentVolume 配置中,你可以尝试添加节点亲和性(Node Affinity)来确保你的 PV 只被绑定到正确的节点上。由于 Rancher Desktop 使用 Lima 虚拟机作为节点,你需要确保 PV 被绑定到这个节点。
    • 示例中的 nodeAffinity 部分是被注释掉的,你可以尝试取消注释并调整以匹配你的环境。
  4. StatefulSet 配置

    • 确保你的 StatefulSet 配置中的 volumeMounts 和 volumeClaimTemplates 部分正确引用了你的 PV 和 PVC。
    • 检查 StatefulSet 是否能够正确创建并挂载 PV。
  5. 检查 PV 和 PVC 状态

    • 运行 kubectl get pvkubectl get pvc 来检查 PersistentVolume 和 PersistentVolumeClaim 的状态。确保 PVC 已经成功绑定到了你创建的 PV。
  6. 查看事件和日志

    • 使用 kubectl describe pv <your-pv-name>kubectl describe pvc <your-pvc-name> 来查看 PV 和 PVC 的详细信息和事件。这可能会提供为什么 PV 没有被正确使用的线索。
  7. Rancher Desktop 设置

    • 检查 Rancher Desktop 的设置,确保没有与存储或路径映射相关的特殊配置干扰你的 hostPath 设置。
  8. 更新 YAML 配置

    • 如果以上步骤都无法解决问题,尝试简化你的 YAML 配置,只保留必要的部分,并逐步添加其他配置以确定问题所在。

如果以上步骤都不能解决问题,可能需要更深入地检查 Rancher Desktop 和 k3s 的文档,或者考虑在 Rancher Desktop 的社区论坛或 k3s 的 GitHub 仓库中寻求帮助。有时候,特定的环境配置或软件版本可能会导致预期之外的行为,因此查看官方文档和社区支持可能是解决问题的关键。

2 个回答

本地测试了一下,使用MacOS上的OrbStack模拟的k8s环境,实现应该和rancher-desktop差不多。

具体测试了一下,主要修改

  1. 这里取消注释了 storageClassName ,指定了之后,后面的pve才能工作

    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: postgres-data-pv
    spec:
      capacity:
     storage: 10Gi  # 根据实际需求设置存储容量
      accessModes:
     - ReadWriteOnce
      persistentVolumeReclaimPolicy: Delete
      storageClassName: local-path
      hostPath:
     path: "/Users/hy/Projects/kubernetes/sf/data"
  2. 这里指定一下 volumeName

    apiVersion: apps/v1
    kind: StatefulSet
    metadata:
      name: postgres-statefulset
      namespace: postgresd
    spec:
      replicas: 1
      selector:
     matchLabels:
       app: postgres
      serviceName: postgres-serive
      template:
        ...
      volumeClaimTemplates:
     - metadata:
         name: postgres-data
       spec:
         accessModes: [ "ReadWriteOnce" ]
         resources:
           requests:
             storage: 5Gi
         volumeName: postgres-data-pv

持久化正常:
image.png


补充一下可能的原因,我猜测原因可能是两个k8s环境的storageClass实现不一样,看了一下用了local-path的storageClass默认就是会自动创建出pv。

这里OrbStack默认使用的也是rancher.io/local-path,所以直接就能复现一样的问题。


OrbStack默认使用的是 local-path ,完整的yaml:


# 定义一个命名空间
apiVersion: v1
kind: Namespace
metadata:
  name: postgresd
---

# 定义配置
apiVersion: v1
kind: ConfigMap
metadata:
  name: postgres-config
  namespace: postgresd
data:
  POSTGRES_DB: postgres
  MAX_CONNECTIONS: "10000"
  LOG_MIN_DURATION_STATEMENT: "500ms"
---

# 定义存储卷
apiVersion: v1
kind: PersistentVolume
metadata:
  name: postgres-data-pv
spec:
  capacity:
    storage: 10Gi  # 根据实际需求设置存储容量
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Delete
  storageClassName: local-path
  hostPath:
    path: "/Users/hy/Projects/kubernetes/sf/data"

---

# 定义用户名、密码等敏感信息
apiVersion: v1
kind: Secret
metadata:
  name: postgres-secret
  namespace: postgresd
type: Opaque
data:
  postgres-user: cG9zdGdyZXM= # Base64编码的用户名,这里是"postgres"
  postgres-password: U2VjdXJlUGFzc3dvcmQ= # Base64编码的密码,这里是"SecurePassword"

---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: postgres-statefulset
  namespace: postgresd
spec:
  replicas: 1
  selector:
    matchLabels:
      app: postgres
  serviceName: postgres-serive
  template:
    metadata:
      labels:
        app: postgres
    spec:
      containers:
        - name: postgresd
          image: postgres:16.2-alpine3.19
          ports:
            - containerPort: 5432
              name: postgresd-port
          env:
            - name: POSTGRES_USER
              valueFrom:
                secretKeyRef:
                  name: postgres-secret
                  key: postgres-user
            - name: POSTGRES_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: postgres-secret
                  key: postgres-password
            - name: POSTGRES_DB
              valueFrom:
                configMapKeyRef:
                  name: postgres-config
                  key: POSTGRES_DB
          volumeMounts:
            - name: postgres-data
              mountPath: /var/lib/postgresql/data
              subPath: data
  volumeClaimTemplates:
    - metadata:
        name: postgres-data
      spec:
        accessModes: [ "ReadWriteOnce" ]
        resources:
          requests:
            storage: 5Gi
        volumeName: postgres-data-pv
  
#        storageClassName: local-path
---

# 定义将5432端口映射到kind cluster  5432端口的service
apiVersion: v1
kind: Service
metadata:
  namespace: postgresd
  name: postgres-service
spec:
  selector:
    app: postgres
  ports:
  - port: 5432
    targetPort: 5432
  type: ClusterIP

image.png
你本地应该已经配置了一个叫local-path的默认storageClass,可以通过命令kubectl get storageclass 确认,因为这个storageClass的存在,所以会自动创建pvc;

你要pvc和pv绑定那你应该使用volumeName: xxx 指定pvc和pv关联,类似你下面这个配置。

  volumeClaimTemplates:
    - metadata:
        name: postgres-data
      spec:
        accessModes: [ "ReadWriteOnce" ]
        resources:
          requests:
            storage: 5Gi
        volumeName: postgres-data-pv
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏