Kubernetes集群中的本地存储资源一般通过手动或者使用Ansible进行批量初始化,但是这两种方式操作复杂且不适用于大规模集群,而Node Resource Manager组件根据ConfigMap的定义可自动初始化并更新当前节点上的本地存储资源。本文介绍如何通过Node Resource Manager组件实现本地存储资源的自动初始化。

背景信息

Kubernetes集群中的本地存储资源初始化一直是个令人困扰的问题,迄今为止一般手动或者使用Ansible进行批量初始化,但是这两种方式存在以下问题:
  • Ansible无法便捷的使用Kubernetes特有的节点信息进行定制化部署,需要提前安装Kubelet,执行shell command命令以及需要自助解析返回结果。
  • 在大规模集群中,手动登录节点部署本地存储资源是很难实现的。
  • 无法持续维护初始化的资源,若某个节点需要更新资源,则需要手动登录节点更新资源,且相关存储资源的使用信息无法上报,在Kubernetes调度Pod时无法被利用起来。
基于以上问题可通过Node Resource Manager组件实现本地存储资源的自动初始化。Node Resource Manager组件是一个简单易用的Kubernetes本地存储管理组件,可上报本地存储资源的使用信息,配合Scheduler自动化调度使用本地存储资源的Pod。关于Node Resource Manager组件的更多信息,请参见node-resource-manager

步骤一:通过ConfigMap定义资源所在节点

通过以下三个参数共同定义资源所在的节点。
key: kubernetes.io/hostname
operator: In
value: xxxxx
参数 说明
key 匹配Kubernetes Node Labels中的key值。
operator Kubernetes定义的Labels selector operator,主要包含如下四种操作符:
  • In:只有value值与节点上Labels Key对应的value值相同时匹配。
  • NotIn:只有value值与节点上Labels Key对应的value值不相同时匹配。
  • Exists:只要节点的Labels上存在Key就会匹配。
  • DoesNotExist:只要节点的Labels上不存在Key就会匹配。
value 匹配Kubernetes Node Labels Key对应的value值。

根据需要选择定义资源拓扑的方式,即LVM或Quotapath,进而初始化定义节点上的本地存储资源。

使用LVM定义资源拓扑

通过LVM定义资源拓扑,支持以下三种方式:
  • type: device:通过Node Resource Manager组件所在宿主机上的块设备devices进行LVM的声明,声明的块设备会组成一个volumegroupvolumegroup的名称由name指定,供后续应用启动时分配Logical Volume。
  • type: alibabacloud-local-disk:通过Node Resource Manager组件所在宿主机上所有的本地盘(选择带有本地盘的ECS类型)共同创建一个名称为name值的volumegroup
    注意 在使用本地SSD型 (i2)实例创建的ECS实例中,手动挂载的块设备为云盘,非本地盘。
  • type: pmem:通过Node Resource Manager组件所在宿主机上的PMEM资源创建一个名称为name值的volumegroup,其中regions可以指定当前机器上多个PMEM的region资源。
根据以下YAML示例,使用LVM定义资源拓扑:
apiVersion: v1
kind: ConfigMap
metadata:
  name: unified-resource-topo
  namespace: kube-system
data:
  volumegroup: |-
    volumegroup:
    - name: volumegroup1
      key: kubernetes.io/hostname
      operator: In
      value: cn-zhangjiakou.192.168.XX.XX
      topology:
        type: device
        devices:
        - /dev/vdb
        - /dev/vdc
    - name: volumegroup2
      key: kubernetes.io/nodetype
      operator: NotIn
      value: localdisk
      topology:
        type: alibabacloud-local-disk
    - name: volumegroup1
      key: kubernetes.io/hostname
      operator: Exists
      value: cn-beijing.192.168.XX.XX
      topology:
        type: pmem
        regions:
        - region0

使用Quotapath定义资源拓扑

通过Quotapath定义资源拓扑,支持以下两种方式:
  • type: device:通过Node Resource Manager组件所在宿主机的块设备初始化Quotapath,初始化路径是name字段定义的值。
  • type: pmem:通过Node Resource Manager组件所在宿主机的PMEM设备初始化Quotapath,初始化路径是name字段定义的值。
根据以下YAML示例,使用Quotapath定义资源拓扑:
apiVersion: v1
kind: ConfigMap
metadata:
  name: unified-resource-topo
  namespace: kube-system
data:
  quotapath: |-
    quotapath:
    - name: /mnt/path1
      key: kubernetes.io/hostname
      operator: In
      value: cn-beijing.192.168.XX.XX
      topology:
        type: device
        options: prjquota
        fstype: ext4
        devices:
        - /dev/vdb
    - name: /mnt/path2
      key: kubernetes.io/hostname
      operator: In
      value: cn-beijing.192.168.XX.XX
      topology:
        type: pmem
        options: prjquota,shared
        fstype: ext4
        regions:
        - region0

相关参数说明如下表所示:

参数 说明
options 在挂载块设备时使用的参数。
fstype 格式化块设备使用的文件系统,默认使用ext4
devices 挂载使用的块设备,可声明多个块设备。在多个块设备的情况下,将依次尝试挂载,直到挂载成功。

步骤二:部署Node Resource Manager组件

通过在集群中创建DaemonSet工作负载部署Node Resource Manager组件,YAML示例如下所示:
cat <<EOF | kubectl apply -f -
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: node-resource-manager
  namespace: kube-system
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: node-resource-manager
rules:
  - apiGroups: [""]
    resources: ["configmaps"]
    verbs: ["get", "watch", "list", "delete", "update", "create"]
  - apiGroups: [""]
    resources: ["nodes"]
    verbs: ["get", "list", "watch"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: node-resource-manager-binding
subjects:
  - kind: ServiceAccount
    name: node-resource-manager
    namespace: kube-system
roleRef:
  kind: ClusterRole
  name: node-resource-manager
  apiGroup: rbac.authorization.k8s.io
---
kind: DaemonSet
apiVersion: apps/v1
metadata:
  name: node-resource-manager
  namespace: kube-system
spec:
  selector:
    matchLabels:
      app: node-resource-manager
  template:
    metadata:
      labels:
        app: node-resource-manager
    spec:
      tolerations:
        - operator: "Exists"
      priorityClassName: system-node-critical
      serviceAccountName: node-resource-manager
      hostNetwork: true
      hostPID: true
      containers:
        - name: node-resource-manager
          securityContext:
            privileged: true
            capabilities:
              add: ["SYS_ADMIN"]
            allowPrivilegeEscalation: true
          image: registry.cn-hangzhou.aliyuncs.com/acs/node-resource-manager:v1.18.8.0-983ce56-aliyun
          imagePullPolicy: "Always"
          args:
            - "--nodeid=$(KUBE_NODE_NAME)"
          env:
            - name: KUBE_NODE_NAME
              valueFrom:
                fieldRef:
                  apiVersion: v1
                  fieldPath: spec.nodeName
          volumeMounts:
            - mountPath: /dev
              mountPropagation: "HostToContainer"
              name: host-dev
            - mountPath: /var/log/
              name: host-log
            - name: etc
              mountPath: /host/etc
            - name: config
              mountPath: /etc/unified-config
      volumes:
        - name: host-dev
          hostPath:
            path: /dev
        - name: host-log
          hostPath:
            path: /var/log/
        - name: etc
          hostPath:
            path: /etc
        - name: config
          configMap:
            name: node-resource-topo
EOF
部署完成之后,组件会自动将ConfigMap中的配置应用到节点上。如果更新ConfigMap,组件会在一分钟内对资源更新。
注意 为了保障数据安全,Node Resource Manager组件不会删除任何资源。

联系方式

若您在使用该功能时有任何疑问或优化建议,欢迎使用钉钉搜索钉钉群号33936810加入钉钉群进行反馈。