Enable "Storage Capacity Tracking"
This commit is contained in:
parent
45d1ab1aa3
commit
110dee7d3d
@ -21,4 +21,7 @@ DriverInfo:
|
||||
nodeExpansion: true
|
||||
onlineExpansion: true
|
||||
volumeLimits: false
|
||||
singleNodeVolume: true
|
||||
topology: true
|
||||
capacity: true
|
||||
InlineVolumes: []
|
||||
|
@ -2,8 +2,8 @@
|
||||
set -ex
|
||||
source .ci/common
|
||||
|
||||
K8S_VERSION=1.19.12
|
||||
MINIKUBE_VERSION=1.19.0
|
||||
K8S_VERSION=1.21.5
|
||||
MINIKUBE_VERSION=1.21.0
|
||||
curl -Lo kubectl https://storage.googleapis.com/kubernetes-release/release/v${K8S_VERSION}/bin/linux/amd64/kubectl && chmod +x kubectl && sudo mv kubectl /usr/local/bin/
|
||||
sudo apt update && sudo apt install -y conntrack
|
||||
curl -Lo minikube https://storage.googleapis.com/minikube/releases/v${MINIKUBE_VERSION}/minikube-linux-amd64 && chmod +x minikube && sudo mv minikube /usr/local/bin/
|
||||
|
@ -7,7 +7,7 @@ Kubernetes LocalPVs on Steroids
|
||||
|
||||
Prerequisite
|
||||
---
|
||||
- Kubernetes: 1.19+
|
||||
- Kubernetes: 1.21+
|
||||
|
||||
Install
|
||||
---
|
||||
|
4
bd2fs.py
4
bd2fs.py
@ -211,6 +211,10 @@ class Bd2FsControllerServicer(csi_pb2_grpc.ControllerServicer):
|
||||
def DeleteVolume(self, request, context):
|
||||
return self.bds.DeleteVolume(request, context)
|
||||
|
||||
@log_grpc_request
|
||||
def GetCapacity(self, request, context):
|
||||
return self.bds.GetCapacity(request, context)
|
||||
|
||||
@log_grpc_request
|
||||
def ControllerExpandVolume(self, request, context):
|
||||
response = self.bds.ControllerExpandVolume(request, context)
|
||||
|
@ -6,5 +6,6 @@ spec:
|
||||
attachRequired: false
|
||||
podInfoOnMount: true
|
||||
fsGroupPolicy: File
|
||||
storageCapacity: true
|
||||
volumeLifecycleModes:
|
||||
- Persistent
|
||||
|
@ -40,6 +40,15 @@ rules:
|
||||
- apiGroups: ["storage.k8s.io"]
|
||||
resources: ["volumeattachments"]
|
||||
verbs: ["get", "list", "watch"]
|
||||
- apiGroups: ["storage.k8s.io"]
|
||||
resources: ["csistoragecapacities"]
|
||||
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
|
||||
- apiGroups: [""]
|
||||
resources: ["pods"]
|
||||
verbs: ["get"]
|
||||
- apiGroups: ["apps"]
|
||||
resources: ["daemonsets"]
|
||||
verbs: ["get"]
|
||||
---
|
||||
kind: ClusterRoleBinding
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
|
@ -63,20 +63,6 @@ spec:
|
||||
containerPort: 9808
|
||||
resources:
|
||||
{{- toYaml .Values.controller.resources | nindent 12 }}
|
||||
- name: external-provisioner
|
||||
image: k8s.gcr.io/sig-storage/csi-provisioner:v2.2.2
|
||||
imagePullPolicy: IfNotPresent
|
||||
args:
|
||||
- "--csi-address=$(ADDRESS)"
|
||||
- "--feature-gates=Topology=true"
|
||||
- "--strict-topology"
|
||||
- "--timeout=120s"
|
||||
env:
|
||||
- name: ADDRESS
|
||||
value: /csi/csi.sock
|
||||
volumeMounts:
|
||||
- name: socket-dir
|
||||
mountPath: /csi
|
||||
- name: external-resizer
|
||||
image: k8s.gcr.io/sig-storage/csi-resizer:v1.2.0
|
||||
imagePullPolicy: IfNotPresent
|
||||
|
@ -123,3 +123,33 @@ spec:
|
||||
requests:
|
||||
cpu: 10m
|
||||
memory: 100Mi
|
||||
- name: external-provisioner
|
||||
image: k8s.gcr.io/sig-storage/csi-provisioner:v2.2.2
|
||||
imagePullPolicy: IfNotPresent
|
||||
args:
|
||||
- "--csi-address=$(ADDRESS)"
|
||||
- "--feature-gates=Topology=true"
|
||||
- "--strict-topology"
|
||||
- "--immediate-topology=false"
|
||||
- "--timeout=120s"
|
||||
- "--enable-capacity=true"
|
||||
- "--capacity-ownerref-level=1" # DaemonSet
|
||||
- "--node-deployment=true"
|
||||
env:
|
||||
- name: ADDRESS
|
||||
value: /csi/csi.sock
|
||||
- name: NODE_NAME
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: spec.nodeName
|
||||
- name: NAMESPACE
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: metadata.namespace
|
||||
- name: POD_NAME
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: metadata.name
|
||||
volumeMounts:
|
||||
- name: socket-dir
|
||||
mountPath: /csi
|
||||
|
@ -11,7 +11,7 @@ from declarative import be_symlink, be_absent
|
||||
from fs_util import device_stats, mountpoint_to_dev
|
||||
from orchestrator.k8s import volume_to_node, run_on_node
|
||||
from rawfile_util import attach_loop, detach_loops
|
||||
from remote import init_rawfile, scrub, expand_rawfile
|
||||
from remote import init_rawfile, scrub, get_capacity, expand_rawfile
|
||||
from util import log_grpc_request, run
|
||||
|
||||
NODE_NAME_TOPOLOGY_KEY = "hostname"
|
||||
@ -134,6 +134,7 @@ class RawFileControllerServicer(csi_pb2_grpc.ControllerServicer):
|
||||
return csi_pb2.ControllerGetCapabilitiesResponse(
|
||||
capabilities=[
|
||||
Cap(rpc=Cap.RPC(type=Cap.RPC.CREATE_DELETE_VOLUME)),
|
||||
Cap(rpc=Cap.RPC(type=Cap.RPC.GET_CAPACITY)),
|
||||
Cap(rpc=Cap.RPC(type=Cap.RPC.EXPAND_VOLUME)),
|
||||
]
|
||||
)
|
||||
@ -186,10 +187,7 @@ class RawFileControllerServicer(csi_pb2_grpc.ControllerServicer):
|
||||
)
|
||||
|
||||
try:
|
||||
run_on_node(
|
||||
init_rawfile.as_cmd(volume_id=request.name, size=size),
|
||||
node=node_name,
|
||||
)
|
||||
init_rawfile(volume_id=request.name, size=size),
|
||||
except CalledProcessError as exc:
|
||||
if exc.returncode == RESOURCE_EXHAUSTED_EXIT_CODE:
|
||||
context.abort(
|
||||
@ -210,10 +208,15 @@ class RawFileControllerServicer(csi_pb2_grpc.ControllerServicer):
|
||||
|
||||
@log_grpc_request
|
||||
def DeleteVolume(self, request, context):
|
||||
node_name = volume_to_node(request.volume_id)
|
||||
run_on_node(scrub.as_cmd(volume_id=request.volume_id), node=node_name)
|
||||
scrub(volume_id=request.volume_id)
|
||||
return csi_pb2.DeleteVolumeResponse()
|
||||
|
||||
@log_grpc_request
|
||||
def GetCapacity(self, request, context):
|
||||
return csi_pb2.GetCapacityResponse(
|
||||
available_capacity=get_capacity(),
|
||||
)
|
||||
|
||||
@log_grpc_request
|
||||
def ControllerExpandVolume(self, request, context):
|
||||
volume_id = request.volume_id
|
||||
|
15
remote.py
15
remote.py
@ -1,7 +1,6 @@
|
||||
from util import remote_fn
|
||||
|
||||
|
||||
@remote_fn
|
||||
def scrub(volume_id):
|
||||
import time
|
||||
import rawfile_util
|
||||
@ -17,18 +16,18 @@ def scrub(volume_id):
|
||||
rawfile_util.gc_if_needed(volume_id, dry_run=False)
|
||||
|
||||
|
||||
@remote_fn
|
||||
def init_rawfile(volume_id, size):
|
||||
import time
|
||||
import rawfile_util
|
||||
from volume_schema import LATEST_SCHEMA_VERSION
|
||||
from subprocess import CalledProcessError
|
||||
from pathlib import Path
|
||||
|
||||
import rawfile_util
|
||||
from volume_schema import LATEST_SCHEMA_VERSION
|
||||
from util import run
|
||||
from consts import RESOURCE_EXHAUSTED_EXIT_CODE
|
||||
|
||||
if rawfile_util.get_capacity() < size:
|
||||
exit(RESOURCE_EXHAUSTED_EXIT_CODE)
|
||||
raise CalledProcessError(returncode=RESOURCE_EXHAUSTED_EXIT_CODE, cmd="")
|
||||
|
||||
img_dir = rawfile_util.img_dir(volume_id)
|
||||
img_dir.mkdir(exist_ok=True)
|
||||
@ -48,6 +47,12 @@ def init_rawfile(volume_id, size):
|
||||
run(f"truncate -s {size} {img_file}")
|
||||
|
||||
|
||||
def get_capacity():
|
||||
import rawfile_util
|
||||
|
||||
return rawfile_util.get_capacity()
|
||||
|
||||
|
||||
@remote_fn
|
||||
def expand_rawfile(volume_id, size):
|
||||
import rawfile_util
|
||||
|
Loading…
Reference in New Issue
Block a user