Skip to content

Commit

Permalink
Merge pull request #185 from intelligentfu/disaggregated
Browse files Browse the repository at this point in the history
Disaggregated
  • Loading branch information
intelligentfu authored Jul 3, 2024
2 parents 6f1052c + 47e08e3 commit 1d029d5
Show file tree
Hide file tree
Showing 57 changed files with 4,271 additions and 588 deletions.
135 changes: 82 additions & 53 deletions api/disaggregated/cluster/v1/doris_disaggregated_cluster_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,11 @@ import (
)

type DorisDisaggregatedClusterSpec struct {
//ClusterId is the identifier of Doris Disaggregated cluster, default is namespace_name.
ClusterId string `json:"clusterId,omitempty"`
//TODO: give the example config.
//VaultConfigmap specify the configmap that have configuration of file object information. example S3.
//configmap have to config, please reference the doc.
VaultConfigmap string `json:"vaultConfigmap,omitempty"`

//the user id, default = cluster name.
UserId string `json:"userId,omitempty"`

//MetaService describe the metaservice that cluster want to storage metadata.
MetaService MetaService `json:"metaService,omitempty"`

Expand All @@ -31,52 +26,13 @@ type MetaService struct {
Namespace string `json:"namespace,omitempty"`
//Name specify the name of metaservice resource.
Name string `json:"name,omitempty"`
//MsPort specify the port of ms listen.
MsPort int32 `json:"msPort,omitempty"`
}

type FeSpec struct {
//Image is the fe of Disaggregated docker image to deploy. please reference the selectdb repository to find.
Image string `json:"image,omitempty"`

// ImagePullSecrets is an optional list of references to secrets in the same namespace to use for pulling any of the images used by this PodSpec.
// If specified, these secrets will be passed to individual puller implementations for them to use.
// More info: https://kubernetes.io/docs/concepts/containers/images#specifying-imagepullsecrets-on-a-pod
// +optional
// +patchMergeKey=name
// +patchStrategy=merge
ImagePullSecrets []corev1.LocalObjectReference `json:"imagePullSecrets,omitempty"`

//Replicas represent the number of fe. default is 2. fe is master-slave architecture only one is master.
Replicas *int32 `json:"replicas,omitempty"`

//defines the specification of resource cpu and mem. ep: {"requests":{"cpu": 4, "memory": "8Gi"},"limits":{"cpu":4,"memory":"8Gi"}}
// usually not need config, operator will set default {"requests": {"cpu": 4, "memory": "8Gi"}, "limits": {"cpu": 4, "memory": "8Gi"}}
corev1.ResourceRequirements `json:",inline"`

//Labels for organize and categorize objects
Labels map[string]string `json:"labels,omitempty"`

//Annotations is an unstructured key value map stored with a resource that may be
// set by external tools to store and retrieve arbitrary metadata.
Annotations map[string]string `json:"annotations,omitempty"`

// VolumeClaimTemplate allows customizing the persistent volume claim for the pod.
VolumeClaimTemplate *corev1.PersistentVolumeClaim `json:"volumeClaimTemplate,omitempty"`

//+optional
// Affinity is a group of affinity scheduling rules.
Affinity *corev1.Affinity `json:"affinity,omitempty"`

// (Optional) Tolerations for scheduling pods onto some dedicated nodes
//+optional
Tolerations []corev1.Toleration `json:"tolerations,omitempty"`

// export metaservice for accessing from outside k8s.
Service *ExportService `json:"service,omitempty"`

// ConfigMaps describe all configmaps that need to be mounted.
ConfigMaps []ConfigMap `json:"configMaps,omitempty"`
CommonSpec `json:",inline"`
}

// ComputeGroup describe the specification that a group of compute node.
Expand All @@ -90,6 +46,13 @@ type ComputeGroup struct {
//CloudUniqueId represents the cloud code, if deployed in cloud platform. default cloudUniqueId=clusterId.
CloudUniqueId string `json:"cloudUniqueId,omitempty"`

//Replicas represent the number of compute node.
Replicas *int32 `json:"replicas,omitempty"`

CommonSpec `json:",inline"`
}

type CommonSpec struct {
//Image is the be of Disaggregated docker image to deploy. please reference the selectdb repository to find.
Image string `json:"image,omitempty"`
// ImagePullSecrets is an optional list of references to secrets in the same namespace to use for pulling any of the images used by this PodSpec.
Expand All @@ -100,9 +63,6 @@ type ComputeGroup struct {
// +patchStrategy=merge
ImagePullSecrets []corev1.LocalObjectReference `json:"imagePullSecrets,omitempty"`

//Replicas represent the number of compute node.
Replicas *int32 `json:"replicas,omitempty"`

//defines the specification of resource cpu and mem. ep: {"requests":{"cpu": 4, "memory": "8Gi"},"limits":{"cpu":4,"memory":"8Gi"}}
corev1.ResourceRequirements `json:",inline"`

Expand All @@ -117,22 +77,72 @@ type ComputeGroup struct {
// Affinity is a group of affinity scheduling rules.
Affinity *corev1.Affinity `json:"affinity,omitempty"`

// VolumeClaimTemplate allows customizing the persistent volume claim for the pod.
PersistentVolume *PersistentVolume `json:"persistentVolume,omitempty"`

//when set true, the log will store in disk that created by volumeClaimTemplate
NoStoreLog bool `json:"noStoreLog,omitempty"`

// (Optional) Tolerations for scheduling pods onto some dedicated nodes
//+optional
Tolerations []corev1.Toleration `json:"tolerations,omitempty"`

// export metaservice for accessing from outside k8s.
Service *ExportService `json:"service,omitempty"`

// ConfigMaps describe all configmaps that need to be mounted.
// ConfigMaps describe all configmap that need to be mounted.
ConfigMaps []ConfigMap `json:"configMaps,omitempty"`

//secrets describe all secret that need to be mounted.
Secrets []Secret `json:"secrets,omitempty"`

// specify what's node to deploy compute group pod.
// +optional
NodeSelector map[string]string `json:"nodeSelector,omitempty"`

//serviceAccount for compute node access cloud service.
ServiceAccount string `json:"serviceAccount,omitempty"`

// HostAliases is an optional list of hosts and IPs that will be injected into the pod's hosts
// file if specified. This is only valid for non-hostNetwork pods.
// +optional
HostAliases []corev1.HostAlias `json:"hostAliases,omitempty"`

//Security context for pod.
//+optional
SecurityContext *corev1.PodSecurityContext `json:"securityContext,omitempty"`

//Security context for all containers running in the pod (unless they override it).
//+optional
ContainerSecurityContext *corev1.SecurityContext `json:"containerSecurityContext,omitempty"` //+optional

//EnvVars is a slice of environment variables that are added to the pods, the default is empty.
EnvVars []corev1.EnvVar `json:"envVars,omitempty"`
}

// PersistentVolume defines volume information and container mount information.
type PersistentVolume struct {
// PersistentVolumeClaimSpec is a list of claim spec about storage that pods are required.
// +kubebuilder:validation:Optional
corev1.PersistentVolumeClaimSpec `json:"persistentVolumeClaimSpec,omitempty"`

//Annotation for PVC pods. Users can adapt the storage authentication and pv binding of the cloud platform through configuration.
//It only takes effect in the first configuration and cannot be added or modified later.
Annotations map[string]string `json:"annotations,omitempty"`
}

type Secret struct {
//specify the secret need to be mounted in deployed namespace.
Name string `json:"name,omitempty"`
//display the path of secret be mounted in pod.
MountPath string `json:"mountPath,omitempty"`
}

type ConfigMap struct {
//Name specify the configmap in deployed namespace that need to be mounted in pod.
//Name specify the configmap need to be mounted in pod in deployed namespace.
Name string `json:"name,omitempty"`

//MountPath specify the position of configmap be mounted. the component start conf please mount to /etc/doris, ep: fe-configmap contains 'fe.conf', mountPath must be '/etc/doris'.
//display the path of configMap be mounted in pod. the component start conf please mount to /etc/doris, ep: fe-configmap contains 'fe.conf', mountPath must be '/etc/doris'.
// key in configMap's data is file name.
MountPath string `json:"mountPath,omitempty"`
}
Expand Down Expand Up @@ -176,10 +186,16 @@ type PortMap struct {

type DorisDisaggregatedClusterStatus struct {
//ClusterId display the clusterId of DorisDisaggregatedCluster in meta.
ClusterId string `json:"clusterId,omitempty"`
InstanceId string `json:"instanceId,omitempty"`
//CloudUniqueId display the cloud code.
CloudUniqueId string `json:"cloudUniqueId,omitempty"`

// the ms address for store meta of disaggregated cluster.
MsEndpoint string `json:"msEndpoint,omitempty"`

//the token for access ms service.
MsToken string `json:"msToken,omitempty"`

//FEStatus describe the fe status.
FEStatus FEStatus `json:"feStatus,omitempty"`

Expand All @@ -196,7 +212,7 @@ const (
//Failed represents service failed to start, can't be accessed.
Failed Phase = "Failed"
//Creating represents service in creating stage.
Creating Phase = "Creating"
Reconciling Phase = "Reconciling"
)

type AvailableStatus string
Expand All @@ -212,12 +228,25 @@ const (
type ComputeGroupStatus struct {
//Phase represent the stage of reconciling.
Phase Phase `json:"phase,omitempty"`
// the statefulset of control this compute group pods.
StatefulsetName string `json:"statefulsetName,omitempty"`
// the service that can access the compute group pods.
ServiceName string `json:"serviceName,omitempty"`
//represents the compute group.
ComputeGroupName string `json:"ComputeGroupName,omitempty"`
//AvailableStatus represents the compute group available or not.
AvailableStatus AvailableStatus `json:"availableStatus,omitempty"`
//ClusterId display the clusterId of compute group in meta.
ClusterId string `json:"clusterId,omitempty"`
//CloudUniqueId display the cloud code.
CloudUniqueId string `json:"cloudUniqueId,omitempty"`

// replicas is the number of Pods created by the StatefulSet controller.
Replicas int32 `json:"replicas,omitempty"`

// Total number of available pods (ready for at least minReadySeconds) targeted by this statefulset.
// +optional
AvailableReplicas int32 `json:"availableReplicas,omitempty"`
}

type FEStatus struct {
Expand Down
106 changes: 106 additions & 0 deletions api/disaggregated/cluster/v1/unique_id.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
package v1

import (
"strings"
)

/*
please use get function to replace new function.
*/

func newCGStatefulsetName(ddcName /*dorisDisaggregatedCluster Name*/, cgName /*computegroup's name*/ string) string {
return ddcName + "-" + cgName
}

// RE:[a-zA-Z][0-9a-zA-Z_]+
func newCGClusterId(namespace, stsName string) string {
return strings.ReplaceAll(namespace+"_"+stsName, "-", "_")
}

// RE:[a-zA-Z][0-9a-zA-Z_]+
func newCGCloudUniqueId(namespace, instanceName, statefulsetName string) string {
return strings.ReplaceAll("1:"+namespace+"_"+instanceName+":"+statefulsetName, "-", "_")
}

func (ddc *DorisDisaggregatedCluster) GetCGStatefulsetName(cg *ComputeGroup) string {
cgStsName := ""
for _, cgs := range ddc.Status.ComputeGroupStatuses {
if cgs.ComputeGroupName == cg.Name || cgs.ClusterId == cg.ClusterId || cgs.CloudUniqueId == cg.CloudUniqueId {
cgStsName = cgs.StatefulsetName
}
}

if cgStsName != "" {
return cgStsName
}
return newCGStatefulsetName(ddc.Name, cg.Name)
}

func (ddc *DorisDisaggregatedCluster) GetInstanceId() string {
if ddc.Status.InstanceId != "" {
return ddc.Status.InstanceId
}

// need config in CR.
return ""
}
func (ddc *DorisDisaggregatedCluster) GetCGClusterId(cg *ComputeGroup) string {
if cg == nil || ddc == nil {
return ""
}
for _, cgs := range ddc.Status.ComputeGroupStatuses {
if cg.Name == cgs.ComputeGroupName || cg.ClusterId == cgs.ClusterId || cg.CloudUniqueId == cgs.CloudUniqueId {
return cg.ClusterId
}
}

stsName := ddc.GetCGStatefulsetName(cg)
//update cg' clusterId for auto assemble, if not config.
if cg.ClusterId == "" {
cg.ClusterId = newCGClusterId(ddc.Namespace, stsName)
}

return cg.ClusterId
}

func (ddc *DorisDisaggregatedCluster) GetCGCloudUniqueId(cg *ComputeGroup) string {
if cg == nil || ddc == nil {
return ""
}
for _, cgs := range ddc.Status.ComputeGroupStatuses {
if cg.Name == cgs.ComputeGroupName || cg.ClusterId == cgs.ClusterId || cg.CloudUniqueId == cgs.CloudUniqueId {
return cg.CloudUniqueId
}
}

statefulsetName := ddc.GetCGStatefulsetName(cg)
//update cg' clusterId for auto assemble, if not config.
if cg.CloudUniqueId == "" {
cg.CloudUniqueId = newCGCloudUniqueId(ddc.Namespace, ddc.Name, statefulsetName)
}

return cg.CloudUniqueId
}

func (ddc *DorisDisaggregatedCluster) GetFEStatefulsetName() string {
return ddc.Name + "-" + "fe"
}

func (ddc *DorisDisaggregatedCluster) GetCGServiceName(cg *ComputeGroup) string {
svcName := ""
for _, cgs := range ddc.Status.ComputeGroupStatuses {
if cgs.ComputeGroupName == cg.Name || cgs.ClusterId == cg.ClusterId || cgs.CloudUniqueId == cg.CloudUniqueId {
svcName = cgs.ServiceName
}
}

if svcName != "" {
return svcName
}

return ddc.Name + "-" + cg.Name
}

func (ddc *DorisDisaggregatedCluster) GetFEServiceName() string {
return ddc.Name + "-" + "fe"
}
23 changes: 23 additions & 0 deletions api/disaggregated/cluster/v1/utils.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package v1

const (
DorisDisaggregatedClusterName string = "app.doris.disaggregated.cluster"

//OwnerReference list ownerReferences this object
DorisDisaggregatedOwnerReference string = "app.doris.disaggregated.ownerreference/name"

DorisDisaggregatedComputeGroupClusterId string = "app.doris.disaggregated.cg-clusterid"

DorisDisaggregatedComputeGroupCloudUniqueId string = "app.doris.disaggregated.cg-clouduniqueid"

DorisDisaggregatedPodType string = "app.doris.disaggregated.type"

DisaggregatedSpecHashValueAnnotation string = "doris.disaggregated.cluster/hash"
)

type DisaggregatedComponentType string

var (
DisaggregatedFE DisaggregatedComponentType = "FE"
DisaggregatedBE DisaggregatedComponentType = "BE"
)
Loading

0 comments on commit 1d029d5

Please sign in to comment.