Add support for configurable OSD DB ratios

The default of 0.05 (5%) is likely ideal in the initial implementation,
but allow this to be set explicitly for maximum flexibility in
space-constrained or performance-critical use-cases.
This commit is contained in:
Joshua Boniface 2021-09-23 23:31:58 -04:00
parent d0f3e9e285
commit 65df807b09
7 changed files with 40 additions and 17 deletions

View File

@ -3751,6 +3751,7 @@ class API_Storage_Ceph_OSD_Root(Resource):
{'name': 'device', 'required': True, 'helptext': "A valid device must be specified."}, {'name': 'device', 'required': True, 'helptext': "A valid device must be specified."},
{'name': 'weight', 'required': True, 'helptext': "An OSD weight must be specified."}, {'name': 'weight', 'required': True, 'helptext': "An OSD weight must be specified."},
{'name': 'ext_db', 'required': False, 'helptext': "Whether to use an external OSD DB LV device."}, {'name': 'ext_db', 'required': False, 'helptext': "Whether to use an external OSD DB LV device."},
{'name': 'ext_db_ratio', 'required': False, 'helptext': "Decimal size ratio of the external OSD DB LV device."},
]) ])
@Authenticator @Authenticator
def post(self, reqargs): def post(self, reqargs):
@ -3781,6 +3782,11 @@ class API_Storage_Ceph_OSD_Root(Resource):
type: boolean type: boolean
required: false required: false
description: Whether to use an external OSD DB LV device description: Whether to use an external OSD DB LV device
- in: query
name: ext_db_ratio
type: float
required: false
description: Decimal ratio of total OSD size for the external OSD DB LV device, default 0.05 (5%)
responses: responses:
200: 200:
description: OK description: OK
@ -3798,6 +3804,7 @@ class API_Storage_Ceph_OSD_Root(Resource):
reqargs.get('device', None), reqargs.get('device', None),
reqargs.get('weight', None), reqargs.get('weight', None),
reqargs.get('ext_db', False), reqargs.get('ext_db', False),
float(reqargs.get('ext_db_ratio', 0.05)),
) )

View File

@ -1292,11 +1292,11 @@ def ceph_osd_db_vg_add(zkhandler, node, device):
@ZKConnection(config) @ZKConnection(config)
def ceph_osd_add(zkhandler, node, device, weight, ext_db_flag=False): def ceph_osd_add(zkhandler, node, device, weight, ext_db_flag=False, ext_db_ratio=0.05):
""" """
Add a Ceph OSD to the PVC Ceph storage cluster. Add a Ceph OSD to the PVC Ceph storage cluster.
""" """
retflag, retdata = pvc_ceph.add_osd(zkhandler, node, device, weight, ext_db_flag) retflag, retdata = pvc_ceph.add_osd(zkhandler, node, device, weight, ext_db_flag, ext_db_ratio)
if retflag: if retflag:
retcode = 200 retcode = 200

View File

@ -222,19 +222,20 @@ def ceph_osd_list(config, limit):
return False, response.json().get('message', '') return False, response.json().get('message', '')
def ceph_osd_add(config, node, device, weight, ext_db_flag): def ceph_osd_add(config, node, device, weight, ext_db_flag, ext_db_ratio):
""" """
Add new Ceph OSD Add new Ceph OSD
API endpoint: POST /api/v1/storage/ceph/osd API endpoint: POST /api/v1/storage/ceph/osd
API arguments: node={node}, device={device}, weight={weight}, ext_db={ext_db_flag} API arguments: node={node}, device={device}, weight={weight}, ext_db={ext_db_flag}, ext_db_ratio={ext_db_ratio}
API schema: {"message":"{data}"} API schema: {"message":"{data}"}
""" """
params = { params = {
'node': node, 'node': node,
'device': device, 'device': device,
'weight': weight, 'weight': weight,
'ext_db': ext_db_flag 'ext_db': ext_db_flag,
'ext_db_ratio': ext_db_ratio
} }
response = call_api(config, 'post', '/storage/ceph/osd', params=params) response = call_api(config, 'post', '/storage/ceph/osd', params=params)

View File

@ -2635,17 +2635,24 @@ def ceph_osd_create_db_vg(node, device, confirm_flag):
is_flag=True, default=False, is_flag=True, default=False,
help='Use an external database logical volume for this OSD.' help='Use an external database logical volume for this OSD.'
) )
@click.option(
'-r', '--ext-db-ratio', 'ext_db_ratio',
default=0.05, show_default=True, type=float,
help='Decimal ratio of the external database logical volume to the OSD size.'
)
@click.option( @click.option(
'-y', '--yes', 'confirm_flag', '-y', '--yes', 'confirm_flag',
is_flag=True, default=False, is_flag=True, default=False,
help='Confirm the creation' help='Confirm the creation'
) )
@cluster_req @cluster_req
def ceph_osd_add(node, device, weight, ext_db_flag, confirm_flag): def ceph_osd_add(node, device, weight, ext_db_flag, ext_db_ratio, confirm_flag):
""" """
Add a new Ceph OSD on node NODE with block device DEVICE. Add a new Ceph OSD on node NODE with block device DEVICE.
If '--ext-db' is specified, the existing OSD database volume group on NODE will be used; it must exist first or OSD creation will fail. See the 'pvc storage osd create-db-vg' command for more details. If '--ext-db' is specified, the existing OSD database volume group on NODE will be used; it must exist first or OSD creation will fail. See the 'pvc storage osd create-db-vg' command for more details.
The default '--ext-db-ratio' of 0.05 (5%) is sufficient for most RBD workloads and OSD sizes, though this can be adjusted based on the sizes of the OSD(s) and the underlying database device. Ceph documentation recommends at least 0.02 (2%) for RBD use-cases, and higher values may improve WAL performance under write-heavy workloads with fewer OSDs per node.
""" """
if not confirm_flag and not config['unsafe']: if not confirm_flag and not config['unsafe']:
try: try:
@ -2653,7 +2660,7 @@ def ceph_osd_add(node, device, weight, ext_db_flag, confirm_flag):
except Exception: except Exception:
exit(0) exit(0)
retcode, retmsg = pvc_ceph.ceph_osd_add(config, node, device, weight, ext_db_flag) retcode, retmsg = pvc_ceph.ceph_osd_add(config, node, device, weight, ext_db_flag, ext_db_ratio)
cleanup(retcode, retmsg) cleanup(retcode, retmsg)

View File

@ -236,7 +236,7 @@ def add_osd_db_vg(zkhandler, node, device):
# OSD addition and removal uses the /cmd/ceph pipe # OSD addition and removal uses the /cmd/ceph pipe
# These actions must occur on the specific node they reference # These actions must occur on the specific node they reference
def add_osd(zkhandler, node, device, weight, ext_db_flag=False): def add_osd(zkhandler, node, device, weight, ext_db_flag=False, ext_db_ratio=0.05):
# Verify the target node exists # Verify the target node exists
if not common.verifyNode(zkhandler, node): if not common.verifyNode(zkhandler, node):
return False, 'ERROR: No node named "{}" is present in the cluster.'.format(node) return False, 'ERROR: No node named "{}" is present in the cluster.'.format(node)
@ -247,7 +247,7 @@ def add_osd(zkhandler, node, device, weight, ext_db_flag=False):
return False, 'ERROR: Block device "{}" on node "{}" is used by OSD "{}"'.format(device, node, block_osd) return False, 'ERROR: Block device "{}" on node "{}" is used by OSD "{}"'.format(device, node, block_osd)
# Tell the cluster to create a new OSD for the host # Tell the cluster to create a new OSD for the host
add_osd_string = 'osd_add {},{},{},{}'.format(node, device, weight, ext_db_flag) add_osd_string = 'osd_add {},{},{},{},{}'.format(node, device, weight, ext_db_flag, ext_db_ratio)
zkhandler.write([ zkhandler.write([
('base.cmd.ceph', add_osd_string) ('base.cmd.ceph', add_osd_string)
]) ])

View File

@ -5026,6 +5026,13 @@
"name": "ext_db", "name": "ext_db",
"required": false, "required": false,
"type": "boolean" "type": "boolean"
},
{
"description": "Decimal ratio of total OSD size for the external OSD DB LV device, default 0.05 (5%)",
"in": "query",
"name": "ext_db_ratio",
"required": false,
"type": "float"
} }
], ],
"responses": { "responses": {

View File

@ -68,7 +68,7 @@ class CephOSDInstance(object):
self.stats = json.loads(data) self.stats = json.loads(data)
@staticmethod @staticmethod
def add_osd(zkhandler, logger, node, device, weight, ext_db_flag=False): def add_osd(zkhandler, logger, node, device, weight, ext_db_flag=False, ext_db_ratio=0.05):
# We are ready to create a new OSD on this node # We are ready to create a new OSD on this node
logger.out('Creating new OSD disk on block device {}'.format(device), state='i') logger.out('Creating new OSD disk on block device {}'.format(device), state='i')
try: try:
@ -104,7 +104,7 @@ class CephOSDInstance(object):
if ext_db_flag: if ext_db_flag:
_, osd_size_bytes, _ = common.run_os_command('blockdev --getsize64 {}'.format(device)) _, osd_size_bytes, _ = common.run_os_command('blockdev --getsize64 {}'.format(device))
osd_size_bytes = int(osd_size_bytes) osd_size_bytes = int(osd_size_bytes)
result = CephOSDInstance.create_osd_db_lv(zkhandler, logger, osd_id, osd_size_bytes) result = CephOSDInstance.create_osd_db_lv(zkhandler, logger, osd_id, ext_db_ratio, osd_size_bytes)
if not result: if not result:
raise raise
db_device = "osd-db/osd-{}".format(osd_id) db_device = "osd-db/osd-{}".format(osd_id)
@ -359,7 +359,7 @@ class CephOSDInstance(object):
return False return False
@staticmethod @staticmethod
def create_osd_db_lv(zkhandler, logger, osd_id, osd_size_bytes): def create_osd_db_lv(zkhandler, logger, osd_id, ext_db_ratio, osd_size_bytes):
logger.out('Creating new OSD database logical volume for OSD ID {}'.format(osd_id), state='i') logger.out('Creating new OSD database logical volume for OSD ID {}'.format(osd_id), state='i')
try: try:
# 0. Check if an existsing logical volume exists # 0. Check if an existsing logical volume exists
@ -370,11 +370,11 @@ class CephOSDInstance(object):
logger.out('Ceph OSD database LV "osd-db/osd{}" already exists'.format(osd_id), state='e') logger.out('Ceph OSD database LV "osd-db/osd{}" already exists'.format(osd_id), state='e')
return False return False
# 1. Determine LV sizing (5% of OSD size, in MB) # 1. Determine LV sizing
osd_db_size = int(osd_size_bytes * 0.05 / 1024 / 1024) osd_db_size = int(osd_size_bytes * ext_db_ratio / 1024 / 1024)
# 2. Create the LV # 2. Create the LV
logger.out('Creating LV "osd-db/osd-{}"'.format(osd_id), state='i') logger.out('Creating DB LV "osd-db/osd-{}" of {}M ({} * {})'.format(osd_id, osd_db_size, osd_size_bytes, ext_db_ratio), state='i')
retcode, stdout, stderr = common.run_os_command( retcode, stdout, stderr = common.run_os_command(
'lvcreate --yes --name osd-{} --size {} osd-db'.format(osd_id, osd_db_size) 'lvcreate --yes --name osd-{} --size {} osd-db'.format(osd_id, osd_db_size)
) )
@ -489,14 +489,15 @@ def ceph_command(zkhandler, logger, this_node, data, d_osd):
# Adding a new OSD # Adding a new OSD
if command == 'osd_add': if command == 'osd_add':
node, device, weight, ext_db_flag = args.split(',') node, device, weight, ext_db_flag, ext_db_ratio = args.split(',')
ext_db_flag = bool(strtobool(ext_db_flag)) ext_db_flag = bool(strtobool(ext_db_flag))
ext_db_ratio = float(ext_db_ratio)
if node == this_node.name: if node == this_node.name:
# Lock the command queue # Lock the command queue
zk_lock = zkhandler.writelock('base.cmd.ceph') zk_lock = zkhandler.writelock('base.cmd.ceph')
with zk_lock: with zk_lock:
# Add the OSD # Add the OSD
result = CephOSDInstance.add_osd(zkhandler, logger, node, device, weight, ext_db_flag) result = CephOSDInstance.add_osd(zkhandler, logger, node, device, weight, ext_db_flag, ext_db_ratio)
# Command succeeded # Command succeeded
if result: if result:
# Update the command queue # Update the command queue