Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ceph: allow setting primary-affinity to osd #7807

Merged
merged 1 commit into from
May 6, 2021

Conversation

synarete
Copy link
Contributor

@synarete synarete commented May 2, 2021

A user with unbalanced system (e.g., some OSDs use a partition which
resides on a device along-side OS partition) may want to have a
fine-grained control on the overall load of specific OSD. While osd
weight affects write-load, primary-affinity affects read-load.

This patch allow user to define osd's primary-affinity (similar to
'DeviceClass' and 'InitialWeight'), which is sent to the osd (via mon)
as part of deployment sequence, using 'ceph osd primary-affinity' command.

Valid values are within the range [0.0, 1.0). If not set, default value
is 1.

ROOK issue: #7773

Signed-off-by: Shachar Sharon ssharon@redhat.com

Description of your changes:

Which issue is resolved by this Pull Request:
Resolves #

Checklist:

  • Commit Message Formatting: Commit titles and messages follow guidelines in the developer guide.
  • Skip Tests for Docs: Add the flag for skipping the build if this is only a documentation change. See here for the flag.
  • Skip Unrelated Tests: Add a flag to run tests for a specific storage provider. See test options.
  • Reviewed the developer guide on Submitting a Pull Request
  • Documentation has been updated, if necessary.
  • Unit tests have been added, if necessary.
  • Integration tests have been added, if necessary.
  • Pending release notes updated with breaking and/or notable changes, if necessary.
  • Upgrade from previous release is tested and upgrade user guide is updated, if necessary.
  • Code generation (make codegen) has been run to update object specifications, if necessary.

@mergify mergify bot added the ceph main ceph tag label May 2, 2021
pkg/daemon/ceph/client/osd.go Show resolved Hide resolved
@@ -270,6 +270,11 @@ func deploymentOnNode(c *Cluster, osd OSDInfo, nodeName string, config *provisio
return nil, errors.Wrapf(err, "failed to generate deployment for %s", osdLongName)
}

err = prepareForDeployment(c, osdProps, osd, osdLongName)
if err != nil {
return nil, errors.Wrapf(err, "failed to apply deployment fixup for %s", osdLongName)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixup? Also please use %q instead of %s

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@leseb used "%s" to follow same pattern as rest of this error-formatting in this function. Note that "%q" is already used to format 'osdLongName'

@@ -286,9 +291,22 @@ func deploymentOnPVC(c *Cluster, osd OSDInfo, pvcName string, config *provisionC
return nil, errors.Wrapf(err, "failed to generate deployment for %s", osdLongName)
}

err = prepareForDeployment(c, osdProps, osd, osdLongName)
if err != nil {
return nil, errors.Wrapf(err, "failed to prepare for deployment %s", osdLongName)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return nil, errors.Wrapf(err, "failed to prepare for deployment %s", osdLongName)
return nil, errors.Wrapf(err, "failed to prepare for deployment %q", osdLongName)

return d, nil
}

func prepareForDeployment(c *Cluster, osdProps osdProperties, osd OSDInfo, osdLongName string) error {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It feels unnecessary to pass osdLongNamesince you have osd OSDInfo, you can build it directly within prepareForDeployment()

return d, nil
}

func prepareForDeployment(c *Cluster, osdProps osdProperties, osd OSDInfo, osdLongName string) error {
if osdProps.storeConfig.PrimaryAffinity != "" {
logger.Infof("Set primary-affinity %s for %s", osdProps.storeConfig.PrimaryAffinity, osdLongName)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move this logger inside cephclient.OsdPrimaryAffinity.

Copy link
Contributor

@sp98 sp98 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(asking to better understand how primary-affinity works) I've seen some docs where its mentioned that we need to set mon osd allow primary affinity = true on ceph.conf to enable this functionality. Do we no longer need to do that ?

Some nits

pkg/daemon/ceph/client/osd.go Outdated Show resolved Hide resolved
pkg/apis/rook.io/v1/types.go Outdated Show resolved Hide resolved
@@ -221,6 +221,10 @@ type VolumeSource struct {
// +kubebuilder:validation:Pattern=`^([0-9]*[.])?[0-9]$`
// +optional
CrushInitialWeight string `json:"crushInitialWeight,omitempty"`
// CrushPrimaryAffinity represents OSD primary-affinity within range [0,1)
// +kubebuilder:validation:Pattern=`^0.[0-9]+$`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you use a float type with a min and max value, instead of the string?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We actually don't use the schema for VolumeSource so you don't need to worry about this schema. I'm opening a separate PR to clean that up...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It appears that floats are highly discouraged in k8s API (kubernetes-sigs/controller-tools#245)

However, as there is no schema for VolumeSource, I will change it to float (optional, pointer).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We already have the flag to force the generation if the API has floats, I'm not saying we should continue though. Also, I think the validation only works on strings IIRC.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMHO, if float is acceptable I think it would be better (and I will also make a fix for InitialWeight).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMHO, if float is acceptable I think it would be better (and I will also make a fix for InitialWeight).

Can we still use the validation pattern?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@leseb No we can't. +kubebuilder:validation:Minimum/Maximum apply only for integers, not floats.
However, with @travisn #7813 there is no more validation pattern to any field in VolumeSource

@@ -355,3 +355,15 @@ func OSDOkToStop(context *clusterd.Context, clusterInfo *ClusterInfo, osdID, max

return stats.OSDs, nil
}

// OsdPrimaryAffinity assigns primary-affinity (within range [0.0, 1.0]) to a specific OSD.
func OsdPrimaryAffinity(context *clusterd.Context, clusterInfo *ClusterInfo, osdID int, affinity string) error {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the method doesn't indicate taking action, it's typically a "get" operation. How about this?

Suggested change
func OsdPrimaryAffinity(context *clusterd.Context, clusterInfo *ClusterInfo, osdID int, affinity string) error {
func SetPrimaryAffinity(context *clusterd.Context, clusterInfo *ClusterInfo, osdID int, affinity string) error {

pkg/daemon/ceph/client/osd.go Show resolved Hide resolved
pkg/daemon/ceph/client/osd.go Show resolved Hide resolved
return d, nil
}

func prepareForDeployment(c *Cluster, osdProps osdProperties, osd OSDInfo) error {
if osdProps.storeConfig.PrimaryAffinity != "" {
return cephclient.OsdPrimaryAffinity(c.context, c.clusterInfo, osd.ID, osdProps.storeConfig.PrimaryAffinity)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not excited about setting this property with every reconcile, so would prefer if we can set it with a command line param.

return d, nil
}

func prepareForDeployment(c *Cluster, osdProps osdProperties, osd OSDInfo) error {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
func prepareForDeployment(c *Cluster, osdProps osdProperties, osd OSDInfo) error {
func setOSDProperties(c *Cluster, osdProps osdProperties, osd OSDInfo) error {

@mergify
Copy link

mergify bot commented May 4, 2021

This pull request has merge conflicts that must be resolved before it can be merged. @synarete please rebase it. https://rook.io/docs/rook/master/development-flow.html#updating-your-fork

Copy link
Member

@travisn travisn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code changes look good. Please add this new setting to the docs in ceph-cluster-crds.md next to the deviceClass setting.

pkg/operator/ceph/cluster/osd/osd.go Show resolved Hide resolved
Copy link
Contributor

@sp98 sp98 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just one small nit

@@ -283,9 +288,24 @@ func deploymentOnPVC(c *Cluster, osd OSDInfo, pvcName string, config *provisionC
return nil, errors.Wrapf(err, "failed to generate deployment for %s", osdLongName)
}

err = setOSDProperties(c, osdProps, osd)
if err != nil {
return nil, errors.Wrapf(err, "failed to prepare for deployment %s", osdLongName)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return nil, errors.Wrapf(err, "failed to prepare for deployment %s", osdLongName)
return nil, errors.Wrapf(err, "failed to prepare deployment for %s", osdLongName)

and there is already a comment about using %q

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sp98 You are correct!

@synarete synarete force-pushed the osd-primary-affinity branch 2 times, most recently from fe07667 to f252aaf Compare May 6, 2021 13:25
A user with unbalanced system (e.g., some OSDs use a partition which
resides on a device along-side OS partition) may want to have a
fine-grained control on the overall load of specific OSD. While osd
weight affects write-load, primary-affinity affects read-load.

This patch allow user to define osd's primary-affinity (similar to
'DeviceClass' and 'InitialWeight'), which is sent to the osd (via mon)
as part of deployment sequence, using 'ceph osd primary-affinity' command.

Valid values are within the range [0.0, 1.0). If not set, default value
is 1.

ROOK issue: rook#7773

Signed-off-by: Shachar Sharon <ssharon@redhat.com>
@travisn travisn merged commit f6ae92f into rook:master May 6, 2021
travisn added a commit that referenced this pull request May 6, 2021
ceph: allow setting primary-affinity to osd (backport #7807)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ceph main ceph tag
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants