instanceset

package
v1.0.0-beta.7 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 26, 2024 License: AGPL-3.0 Imports: 52 Imported by: 0

Documentation

Overview

Package instanceset is a general-purpose workload API designed to manage role-based stateful workloads, such as databases. Think of InstanceSet as an enhanced version of StatefulSet.

While the native StatefulSet in Kubernetes handles stateful workloads effectively, additional work is required when the workload pods have specific roles (e.g., leader/follower in etcd, primary/secondary in PostgreSQL, etc.).

InstanceSet provides the following features:

1. Role-based Update Strategy (Serial/Parallel/BestEffortParallel) 2. Role-based Access Mode (ReadWrite/Readonly/None) 3. Automatic Switchover 4. Membership Reconfiguration 5. Multiple Instance Templates 6. Specified Instance Scale In 7. In-place Instance Update

Index

Constants

View Source
const (
	WorkloadsManagedByLabelKey = "workloads.kubeblocks.io/managed-by"
	WorkloadsInstanceLabelKey  = "workloads.kubeblocks.io/instance"

	RoleLabelKey       = "kubeblocks.io/role"
	AccessModeLabelKey = "workloads.kubeblocks.io/access-mode"

	LegacyRSMFinalizerName = "rsm.workloads.kubeblocks.io/finalizer"

	RoleUpdateMechanismVarName = "KB_RSM_ROLE_UPDATE_MECHANISM"
)
View Source
const (
	EventReasonInvalidSpec   = "InvalidSpec"
	EventReasonStrictInPlace = "StrictInPlace"
)
View Source
const (
	// MaxPlainRevisionCount specified max number of plain revision stored in status.updateRevisions.
	// All revisions will be compressed if exceeding this value.
	MaxPlainRevisionCount = "MAX_PLAIN_REVISION_COUNT"

	FeatureGateIgnorePodVerticalScaling = "IGNORE_POD_VERTICAL_SCALING"
)
View Source
const ControllerRevisionHashLabel = "controller.kubernetes.io/hash"

ControllerRevisionHashLabel is the label used to indicate the hash value of a ControllerRevision's Data.

Variables

View Source
var (
	ErrContinue error
	ErrWait     = errors.New("wait")
	ErrStop     = errors.New("stop")
)

Functions

func AddAnnotationScope

func AddAnnotationScope(scope AnnotationScope, annotations map[string]string) map[string]string

AddAnnotationScope will add AnnotationScope defined by 'scope' to all keys in map 'annotations'.

func BuildInstanceName2TemplateMap

func BuildInstanceName2TemplateMap(itsExt *InstanceSetExt) (map[string]*instanceTemplateExt, error)

BuildInstanceName2TemplateMap serves as a Public API, through which users can obtain InstanceName2TemplateMap objects processed by the buildInstanceName2TemplateMap function.

func BuildInstanceTemplateRevision

func BuildInstanceTemplateRevision(template *corev1.PodTemplateSpec, parent *workloads.InstanceSet) (string, error)

func BuildInstanceTemplates

func BuildInstanceTemplates(totalReplicas int32, instances []workloads.InstanceTemplate, instancesCompressed *corev1.ConfigMap) []*workloads.InstanceTemplate

BuildInstanceTemplates serves as a Public API, allowing users to construct InstanceTemplates. The constructed InstanceTemplates can be used as part of the input for BuildInstanceTemplateExts.

func BuildPodTemplate

func BuildPodTemplate(its *workloads.InstanceSet) *corev1.PodTemplateSpec

func CalculateConcurrencyReplicas added in v0.9.1

func CalculateConcurrencyReplicas(concurrency *intstr.IntOrString, replicas int) (int, error)

CalculateConcurrencyReplicas returns absolute value of concurrency for workload. This func can solve some corner cases about percentage-type concurrency, such as: - if concurrency > "0%" and replicas > 0, it will ensure at least 1 pod is reserved. - if concurrency < "100%" and replicas > 1, it will ensure at least 1 pod is reserved.

if concurrency is nil, concurrency will be treated as 100%.

func ComposeRolePriorityMap

func ComposeRolePriorityMap(roles []workloads.ReplicaRole) map[string]int

ComposeRolePriorityMap generates a priority map based on roles.

func ControllerRevisionName

func ControllerRevisionName(prefix string, hash string) string

ControllerRevisionName returns the Name for a ControllerRevision in the form prefix-hash. If the length of prefix is greater than 223 bytes, it is truncated to allow for a name that is no larger than 253 bytes.

func ConvertOrdinalsToSortedList added in v0.9.1

func ConvertOrdinalsToSortedList(ordinals workloads.Ordinals) ([]int32, error)

func DeepHashObject

func DeepHashObject(hasher hash.Hash, objectToWrite interface{})

DeepHashObject writes specified object to hash using the spew library which follows pointers and prints actual values of the nested objects ensuring the hash does not change when a pointer changes.

func GenerateAllInstanceNames

func GenerateAllInstanceNames(parentName string, replicas int32, templates []InstanceTemplate, offlineInstances []string, defaultTemplateOrdinals workloads.Ordinals) ([]string, error)

func GenerateInstanceNames

func GenerateInstanceNames(parentName, templateName string,
	replicas int32, ordinal int32, offlineInstances []string, ordinalList []int32) ([]string, error)

GenerateInstanceNames generates instance names based on certain rules: The naming convention for instances (pods) based on the Parent Name, InstanceTemplate Name, and ordinal. The constructed instance name follows the pattern: $(parent.name)-$(template.name)-$(ordinal).

func GenerateInstanceNamesFromTemplate

func GenerateInstanceNamesFromTemplate(parentName, templateName string, replicas int32, offlineInstances []string, ordinalList []int32) ([]string, error)

func GenerateInstanceNamesWithOrdinalList added in v0.9.1

func GenerateInstanceNamesWithOrdinalList(parentName, templateName string,
	replicas int32, offlineInstances []string, ordinalList []int32) ([]string, error)

GenerateInstanceNamesWithOrdinalList generates instance names based on ordinalList and offlineInstances.

func GetOrdinalListByTemplateName added in v0.9.1

func GetOrdinalListByTemplateName(its *workloads.InstanceSet, templateName string) ([]int32, error)

func GetOrdinalsByTemplateName added in v0.9.1

func GetOrdinalsByTemplateName(its *workloads.InstanceSet, templateName string) (workloads.Ordinals, error)

func GetPodNameSetFromInstanceSetCondition

func GetPodNameSetFromInstanceSetCondition(its *workloads.InstanceSet, conditionType workloads.ConditionType) map[string]sets.Empty

GetPodNameSetFromInstanceSetCondition get the pod name sets from the InstanceSet conditions

func GetRevisions

func GetRevisions(revisions map[string]string) (map[string]string, error)

func HashControllerRevision

func HashControllerRevision(revision *apps.ControllerRevision, probe *int32) string

HashControllerRevision hashes the contents of revision's Data using FNV hashing. If probe is not nil, the byte value of probe is added written to the hash as well. The returned hash will be a safe encoded string to avoid bad words.

func IsInstanceSetReady

func IsInstanceSetReady(its *workloads.InstanceSet) bool

IsInstanceSetReady gives InstanceSet level 'ready' state: 1. all instances are available 2. and all members have role set (if they are role-ful)

func IsInstancesReady

func IsInstancesReady(its *workloads.InstanceSet) bool

IsInstancesReady gives Instance level 'ready' state when all instances are available

func IsPodUpdated

func IsPodUpdated(its *workloads.InstanceSet, pod *corev1.Pod) (bool, error)

IsPodUpdated tells whether the pod's spec is as expected in the InstanceSet. This function is meant to replace the old fashion `GetPodRevision(pod) == updateRevision`, as the pod template revision has been redefined in instanceset.

func MergeNodeSelectorOnceAnnotation

func MergeNodeSelectorOnceAnnotation(its *workloads.InstanceSet, podToNodeMapping map[string]string) error

MergeNodeSelectorOnceAnnotation merges its's nodeSelectorOnce annotation in place

func NewAssistantObjectReconciler

func NewAssistantObjectReconciler() kubebuilderx.Reconciler

func NewControllerRevision

func NewControllerRevision(parent metav1.Object,
	parentKind schema.GroupVersionKind,
	templateLabels map[string]string,
	data runtime.RawExtension,
	revision int64,
	collisionCount *int32) (*apps.ControllerRevision, error)

NewControllerRevision returns a ControllerRevision with a ControllerRef pointing to parent and indicating that parent is of parentKind. The ControllerRevision has labels matching template labels, contains Data equal to data, and has a Revision equal to revision. The collisionCount is used when creating the name of the ControllerRevision so the name is likely unique. If the returned error is nil, the returned ControllerRevision is valid. If the returned error is not nil, the returned ControllerRevision is invalid for use.

func NewDeletionReconciler

func NewDeletionReconciler() kubebuilderx.Reconciler

func NewFixMetaReconciler

func NewFixMetaReconciler() kubebuilderx.Reconciler

func NewReplicasAlignmentReconciler

func NewReplicasAlignmentReconciler() kubebuilderx.Reconciler

func NewRevision

func NewRevision(its *workloads.InstanceSet) (*apps.ControllerRevision, error)

func NewRevisionUpdateReconciler

func NewRevisionUpdateReconciler() kubebuilderx.Reconciler

func NewStatusReconciler

func NewStatusReconciler() kubebuilderx.Reconciler

func NewTreeLoader

func NewTreeLoader() kubebuilderx.TreeLoader

func NewUpdatePlan

func NewUpdatePlan(its workloads.InstanceSet, pods []*corev1.Pod, isPodUpdated func(*workloads.InstanceSet, *corev1.Pod) (bool, error)) updatePlan

func NewUpdateReconciler

func NewUpdateReconciler() kubebuilderx.Reconciler

func ParseAnnotationsOfScope

func ParseAnnotationsOfScope(scope AnnotationScope, scopedAnnotations map[string]string) map[string]string

ParseAnnotationsOfScope parses all annotations with AnnotationScope defined by 'scope'. the AnnotationScope suffix of keys in result map will be trimmed.

func ParseNodeSelectorOnceAnnotation

func ParseNodeSelectorOnceAnnotation(its *workloads.InstanceSet) (map[string]string, error)

ParseNodeSelectorOnceAnnotation will return a non-nil map

func ParseParentNameAndOrdinal

func ParseParentNameAndOrdinal(s string) (string, int)

ParseParentNameAndOrdinal parses parent (instance template) Name and ordinal from the give instance name. -1 will be returned if no numeric suffix contained.

func SortPods

func SortPods(pods []corev1.Pod, rolePriorityMap map[string]int, reverse bool)

SortPods sorts pods by their role priority e.g.: unknown -> empty -> learner -> follower1 -> follower2 -> leader, with follower1.Name > follower2.Name reverse it if reverse==true

func ValidateDupInstanceNames

func ValidateDupInstanceNames[T any](instances []T, getNameFunc func(item T) string) error

Types

type AnnotationScope

type AnnotationScope string

AnnotationScope defines scope that annotations belong to.

it is a common pattern to add annotations to extend the functionalities of K8s builtin resources.

e.g.: Prometheus will start to scrape metrics if a service has annotation 'prometheus.io/scrape'.

The InstanceSet has encapsulated K8s builtin resources like Service, Headless Service, Pod, ConfigMap etc. AnnotationScope specified a way to tell the InstanceSet controller which resource an annotation belongs to.

e.g.: let's say we want to add an annotation 'prometheus.io/scrape' with value 'true' to the underlying headless service. here is what we should do: add annotation 'prometheus.io/scrape' with an HeadlessServiceScope suffix to the RSM object's annotations field.

kind: InstanceSet
metadata:
  annotations:
    prometheus.io/scrape.headless.its: true

the InstanceSet controller will figure out which objects this annotation belongs to, cut the suffix and set it to the right place:

kind: Service
metadata:
  annotations:
    prometheus.io/scrape: true
const (
	// RootScope specifies the annotation belongs to the RSM object itself.
	// they will also be set on the encapsulated StatefulSet.
	RootScope AnnotationScope = ""

	// HeadlessServiceScope specifies the annotation belongs to the encapsulated headless Service.
	HeadlessServiceScope AnnotationScope = ".headless.its"

	// ServiceScope specifies the annotation belongs to the encapsulated Service.
	ServiceScope AnnotationScope = ".svc.its"

	// AlternativeServiceScope specifies the annotation belongs to the encapsulated alternative Services.
	AlternativeServiceScope AnnotationScope = ".alternative.its"

	// ConfigMapScope specifies the annotation belongs to the encapsulated ConfigMap.
	ConfigMapScope AnnotationScope = ".cm.its"
)

type InstanceSetExt

type InstanceSetExt struct {
	Its               *workloads.InstanceSet
	InstanceTemplates []*workloads.InstanceTemplate
}

InstanceSetExt serves as a Public Struct, used as the type for the input parameters of BuildInstanceTemplateExts.

type InstanceTemplate

type InstanceTemplate interface {
	GetName() string
	GetReplicas() int32
	GetOrdinals() workloads.Ordinals
}

type InstanceTemplateExt

type InstanceTemplateExt struct {
	Name     string
	Replicas int32
	corev1.PodTemplateSpec
	VolumeClaimTemplates []corev1.PersistentVolumeClaim
}

InstanceTemplateExt serves as a Public Struct, used as the type for the construction results returned by BuildInstanceTemplateExts.

func BuildInstanceTemplateExts

func BuildInstanceTemplateExts(itsExt *InstanceSetExt) []*InstanceTemplateExt

BuildInstanceTemplateExts serves as a Public API, through which users can obtain InstanceTemplateExt objects processed by the buildInstanceTemplateExts function. Its main purpose is to acquire the PodTemplate rendered by InstanceTemplate.

type PodRoleEventHandler

type PodRoleEventHandler struct{}

func (*PodRoleEventHandler) Handle

func (h *PodRoleEventHandler) Handle(cli client.Client, reqCtx intctrlutil.RequestCtx, recorder record.EventRecorder, event *corev1.Event) error

type PodUpdatePolicy

type PodUpdatePolicy string
const (
	NoOpsPolicy         PodUpdatePolicy = "NoOps"
	RecreatePolicy      PodUpdatePolicy = "Recreate"
	InPlaceUpdatePolicy PodUpdatePolicy = "InPlaceUpdate"
)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL