前提

该实战基于假设了解并清楚,ServiceAccountClusterRoleClusterRoleBinding
以下是简要介绍:

  1. ServiceAccount:为Pod提供了一个身份,允许Pod与Kubernetes API进行安全交互。Local Path Provisioner需要访问和管理PV、PVC、Nodes等资源
  2. ClusterRole:定义了一组权限,允许某个身份(如ServiceAccount)对Kubernetes集群中的资源执行特定操作。
  3. ClusterRoleBinding:ClusterRoleBinding将ClusterRole与一个或多个主体(如ServiceAccount)绑定,以便这些主体获得ClusterRole定义的权限

    目标

    手撕StorageClass用rancher的local-path的方式进行PVC申领动态制备PV

简要步骤

  1. 建立命名空间进行资源隔离
  2. 创建ServiceAccount、ClusterRole和ClusterRoleBinding(前提解释)
  3. 创建deploy,控制pod副本数量
  4. 创建configMap,存储不含机密信息的配置数据。(参考:存储基础)
  5. 创建StorageClass(参考第4条)

废话不多说@#¥%……&*实战开始

namespace

# 好的,已经成功一半了
kubectl create namespace(ns) local-path-storage

ServiceAccount

apiVersion: v1
kind: ServiceAccount
metadata:
name: local-path-provisioner-service-account
namespace: local-path-storage

image-20240801104527213

ClusterRole,直接拿官方的

apiVersion: rbac.authorization.k8s.io/v1 # 指定API版本,这里是rbac.authorization.k8s.io/v1
kind: ClusterRole # 资源类型,这里是ClusterRole,表示集群级别的权限定义
metadata:
name: local-path-provisioner-role # ClusterRole的名称,这里是local-path-provisioner-role
rules: # 定义该角色的权限规则列表
- apiGroups: [""] # 指定API组,空字符串表示核心API组
resources: ["nodes", "persistentvolumeclaims", "persistentvolumes"] # 资源类型列表,包括nodes、persistentvolumeclaims和persistentvolumes
verbs: ["get", "list", "watch", "create", "delete"] # 允许的操作,包括获取、列出、监视、创建和删除
- apiGroups: [""] # 再次指定核心API组
resources: ["pods"] # 资源类型是pods
verbs: ["get", "list", "watch"] # 允许的操作,包括获取、列出和监视
- apiGroups: ["storage.k8s.io"] # 指定API组storage.k8s.io
resources: ["storageclasses"] # 资源类型是storageclasses
verbs: ["get", "list", "watch"] # 允许的操作,包括获取、列出和监视
- apiGroups: ["batch", "extensions"] # 指定API组batch和extensions
resources: ["jobs"] # 资源类型是jobs
verbs: ["get", "list", "watch", "create", "delete"] # 允许的操作,包括获取、列出、监视、创建和删除

image-20240801105301424

ClusterRoleBinding

apiVersion: rbac.authorization.k8s.io/v1 # 指定API版本,这里是rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding # 资源类型,这里是ClusterRoleBinding,表示集群级别的角色绑定
metadata:
name: local-path-provisioner-bindings # ClusterRoleBinding的名称,这里是local-path-provisioner-bindings
roleRef: # 指定要绑定的角色
apiGroup: rbac.authorization.k8s.io # 角色所属的API组,这里是rbac.authorization.k8s.io
kind: ClusterRole # 角色类型,这里是ClusterRole
name: local-path-provisioner-role # 角色名称,这里是local-path-provisioner-role
subjects: # 定义该角色绑定的主体列表
- kind: ServiceAccount # 主体类型,这里是ServiceAccount(服务账户)
name: local-path-provisioner-service-account # 服务账户的名称,这里是local-path-provisioner-service-account
namespace: local-path-storage # 服务账户所属的命名空间,这里是local-path-storage

image-20240801105734783

Deploy

apiVersion: apps/v1 # 指定API版本,这里是apps/v1
kind: Deployment # 资源类型,这里是Deployment,表示部署一个应用
metadata:
name: local-path-provisioner # Deployment的名称,这里是local-path-provisioner
namespace: local-path-storage # Deployment所属的命名空间,这里是local-path-storage
spec: # Deployment的规格定义
replicas: 1 # 副本数,这里是1,表示只部署一个副本
selector: # 用于选择要部署的Pod
matchLabels:
# 标签选择器,选择标签为app: local-path-provisioner的Pod
app: local-path-provisioner
template: # Pod模板定义
metadata:
labels:
app: local-path-provisioner # 为Pod设置的标签,这里是app: local-path-provisioner
spec: # Pod的规格定义
# 使用的服务账户名称,这里是local-path-provisioner-service-account
serviceAccountName: local-path-provisioner-service-account
containers: # 容器列表
- name: provisioner # 容器名称,这里是provisioner
# 容器镜像,这里是rancher/local-path-provisioner:latest
image: rancher/local-path-provisioner:master-head # 换加速啊啊啊啊啊啊啊啊叼毛
imagePullPolicy: Always # 镜像拉取策略,总是拉取最新的镜像
volumeMounts: # 挂载的卷列表
- name: config-volume # 卷名称,这里是config-volume
mountPath: /etc/config # 挂载路径,这里是/etc/config
- name: local-path-storage # 卷名称,这里是local-path-storage
mountPath: /opt/local-path-storage # 挂载路径,这里是/opt/local-path-storage
volumes: # 定义Pod中使用的卷
- name: config-volume # 卷名称,这里是config-volume
configMap: # 使用ConfigMap作为卷
name: local-path-config # ConfigMap的名称,这里是local-path-config
- name: local-path-storage # 卷名称,这里是local-path-storage
hostPath: # 使用主机路径作为卷
path: /opt/local-path-storage # 主机路径,这里是/opt/local-path-storage

image-20240801110044796

config

apiVersion: v1 # 指定API版本,这里是v1
kind: ConfigMap # 资源类型,这里是ConfigMap,用于存储配置信息
metadata:
name: local-path-config # ConfigMap的名称,这里是local-path-config
namespace: local-path-storage # ConfigMap所属的命名空间,这里是local-path-storage
data: # 配置数据
config.json: | # 配置文件的名称,这里是config.json,使用多行字符串格式
{
"nodePathMap":[
{
"node":"DEFAULT_PATH_FOR_NON_LISTED_NODES", # 节点名称,表示未列出的节点的默认路径
"paths":["/opt/local-path-storage"] # 路径列表,这里是/opt/local-path-storage
}
]
}

image-20240801110611178

StorageClass

apiVersion: storage.k8s.io/v1 # 指定API版本,这里是storage.k8s.io/v1
kind: StorageClass # 资源类型,这里是StorageClass,表示存储类
metadata:
name: local-path # StorageClass的名称,这里是local-path
provisioner: rancher.io/local-path # 指定的provisioner,这里是rancher.io/local-path
reclaimPolicy: Delete # 回收策略,这里是Delete,表示当持久卷被释放时删除它
# 卷绑定模式,这里是WaitForFirstConsumer,表示延迟绑定,直到Pod被调度到节点上
volumeBindingMode: WaitForFirstConsumer

image-20240801110811688

验证

创建pvc yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: my-local-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
storageClassName: local-path

image-20240801142550578

因为设计的是WaitForFirstConsumer,所以需要设计一个pod

apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
spec:
containers:
- name: myapp-container
image: m.daocloud.io/docker.io/library/nginx
volumeMounts:
- mountPath: "/usr/share/nginx/html"
name: my-local-storage
volumes:
- name: my-local-storage
persistentVolumeClaim:
claimName: my-local-pvc

image-20240801145710135

总结

以上的配置文件只是一个参考,实际的可以用官方的配置文件,需要注意的是换加速镜像地址时候要换全哦,带image的都换。配置不正确多半进入cashloopbackoff的问题。

apiVersion: v1
kind: Namespace
metadata:
name: local-path-storage

---
apiVersion: v1
kind: ServiceAccount
metadata:
name: local-path-provisioner-service-account
namespace: local-path-storage

---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: local-path-provisioner-role
namespace: local-path-storage
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch", "create", "patch", "update", "delete"]

---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: local-path-provisioner-role
rules:
- apiGroups: [""]
resources: ["nodes", "persistentvolumeclaims", "configmaps", "pods", "pods/log"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["persistentvolumes"]
verbs: ["get", "list", "watch", "create", "patch", "update", "delete"]
- apiGroups: [""]
resources: ["events"]
verbs: ["create", "patch"]
- apiGroups: ["storage.k8s.io"]
resources: ["storageclasses"]
verbs: ["get", "list", "watch"]

---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: local-path-provisioner-bind
namespace: local-path-storage
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: local-path-provisioner-role
subjects:
- kind: ServiceAccount
name: local-path-provisioner-service-account
namespace: local-path-storage

---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: local-path-provisioner-bind
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: local-path-provisioner-role
subjects:
- kind: ServiceAccount
name: local-path-provisioner-service-account
namespace: local-path-storage

---
apiVersion: apps/v1
kind: Deployment
metadata:
name: local-path-provisioner
namespace: local-path-storage
spec:
replicas: 1
selector:
matchLabels:
app: local-path-provisioner
template:
metadata:
labels:
app: local-path-provisioner
spec:
serviceAccountName: local-path-provisioner-service-account
containers:
- name: local-path-provisioner
image: docker.m.daocloud.io/rancher/local-path-provisioner:master-head # ps:换
imagePullPolicy: IfNotPresent
command:
- local-path-provisioner
- --debug
- start
- --config
- /etc/config/config.json
volumeMounts:
- name: config-volume
mountPath: /etc/config/
env:
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: CONFIG_MOUNT_PATH
value: /etc/config/
volumes:
- name: config-volume
configMap:
name: local-path-config

---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: local-path
provisioner: rancher.io/local-path
volumeBindingMode: Immediate
reclaimPolicy: Delete

---
kind: ConfigMap
apiVersion: v1
metadata:
name: local-path-config
namespace: local-path-storage
data:
config.json: |-
{
"nodePathMap":[
{
"node":"DEFAULT_PATH_FOR_NON_LISTED_NODES",
"paths":["/opt/local-path-provisioner"]
}
]
}
setup: |-
#!/bin/sh
set -eu
mkdir -m 0777 -p "$VOL_DIR"
teardown: |-
#!/bin/sh
set -eu
rm -rf "$VOL_DIR"
helperPod.yaml: |-
apiVersion: v1
kind: Pod
metadata:
name: helper-pod
spec:
priorityClassName: system-node-critical
tolerations:
- key: node.kubernetes.io/disk-pressure
operator: Exists
effect: NoSchedule
containers:
- name: helper-pod
image: m.daocloud.io/docker.io/library/busybox # ps:换
imagePullPolicy: IfNotPresent