github.com/1aal/kubeblocks@v0.0.0-20231107070852-e1c03e598921/docs/developer_docs/integration/multi-component.md (about) 1 --- 2 title: Multi-component configuration 3 description: How to configure multi-component in KubeBlocks with NebulaGraph as an example 4 keywords: [multi-component,add-on] 5 sidebar_position: 7 6 sidebar_label: Multi-component configuration 7 --- 8 9 # Multi-component configuration 10 11 So far, you've learned the definition, backup, and configuration of single-component clusters (e.g., Oracle-MySQL). 12 13 This tutorial takes NebulaGraph as an example to demonstrate how to integrate a multi-component cluster and address several common issues in multi-component configurations. You can find more details in [this repository](https://github.com/apecloud/kubeblocks/tree/main/deploy/nebula). 14 15 ## Before you start 16 17 - Finish [Tutorial 1](./how-to-add-an-add-on.md). 18 - Knowledge about basic KubeBlocks concepts, such as ClusterDefinition, Cluster, ComponentRef, and Component. 19 20 ## NebulaGraph Architecture 21 22 First, take a look at the overall architecture of NebulaGraph. 23 24 NebulaGraph applies the separation of storage and computing architecture and consists of three services: the Graph Service, the Meta Service, and the Storage Service. The following figure shows the architecture of a typical NebulaGraph cluster. 25 26  27 28 - Metad: It is a component based on the Raft protocol and is responsible for data management tasks such as Schema operations, cluster management, and user permission management. 29 - Graphd: It is the compute component and is responsible for handling query requests, including query parsing, validation, and generating and executing query plans. 30 - Storaged: It is the distributed storage component based on Multi Group Raft, responsible for storing data. 31 32 If the client is considered, the fourth component is: 33 34 - Client: It is a stateless component used to connect to Graphd and send graph queries. 35 36 ## Configure cluster typology 37 38 Now you've learned the four components of NebulaGraph, and how each component is started and configured. 39 40 Similar to a single-component cluster, you can quickly assemble the definition for a multi-component cluster. 41 42 ```yaml 43 apiVersion: apps.kubeblocks.io/v1alpha1 44 kind: ClusterDefinition 45 metadata: 46 name: nebula 47 spec: 48 componentDefs: 49 - name: nebula-console # client 50 workloadType: Stateless 51 characterType: nebula 52 podSpec: ... 53 - name: nebula-graphd # graphd 54 workloadType: Stateful 55 podSpec: ... 56 - name: nebula-metad # metad 57 workloadType: Stateful 58 podSpec: ... 59 - name: nebula-storaged # storaged 60 workloadType: Stateful 61 podSpec: ... 62 --- 63 apiVersion: apps.kubeblocks.io/v1alpha1 64 kind: ClusterVersion 65 metadata: 66 name: nebula-3.5.0 67 spec: 68 clusterDefinitionRef: nebula # clusterdef name 69 componentVersions: 70 - componentDefRef: nebula-console # Specify image for client 71 versionsContext: 72 containers: 73 - name: nebula-console 74 image: ... 75 - componentDefRef: nebula-graphd # Specify image for graphd 76 versionsContext: 77 containers: 78 - name: nebula-graphd 79 image: 80 - componentDefRef: nebula-metad # Specify image for metad 81 versionsContext: 82 containers: 83 - name: nebula-metad 84 image: ... 85 - componentDefRef: nebula-storaged # Specify image for storaged 86 versionsContext: 87 containers: 88 - name: nebula-storaged 89 image: ... 90 ``` 91 92 The above YAML file provides an outline of the ClusterDefinition and ClusterVersion for NebulaGraph. Corresponding to Figure 1., four components (including the client) and their version information are specified. 93 94 If each component can be started independently, the information provided in Figure 2. would be sufficient. 95 96 However, it can be observed that in a multi-component cluster, there are often inter-component references. So, how to specify the references thereof? 97 98 ## Configure inter-component references 99 100 As discovered, components may refer to each other and Figure 3. shows the inter-component references in a NebulaGraph cluster. For example, 101 102 1. Nebula-Console needs to know the port number and service name of Nebula-Graphd. 103 2. Nebula-Graphd needs to know the DNS of each Pod of Nebula-Metad. 104 3. Nebula-Storaged also needs to know the DNS of each Pod of Nebula-Metad. 105 106  107 108 Therefore, three common types of inter-component references are: \ 109 110 1. **Service Reference** 111 e.g., Nebula-Console needs to obtain the service name of Nebula-Graphd. 112 2. **HostName Reference** 113 e.g., Nebula-Graphd needs to configure the DNS of all Pods of Nebula-metad. This reference typically points to a stateful component. 114 3. **Field Reference** 115 e.g., Nebula-Console needs to obtain a service port name of Nebula-Graphd. 116 117 To ensure that the cluster starts normally, the above information needs to be injected into the Pod through environment variables (whether it is loaded through configmap or defined as pod env). 118 119 In KubeBlocks, the `ComponentDefRef` API can be used to achieve the goal. It introduces the following APIs: 120 121 - `componentDefName`, used to specify the name of the component definition that is being referenced to. 122 - `componentRefEnv`, which defines a set of environment variables that need to be injected. 123 - `name` defines the name of the injected environment variable. 124 - `valueFrom` defines the source of the variable value. 125 126 Next, you will learn how `ComponentDefRef` deals with the three types of references mentioned above. 127 128 ### Service Reference 129 130 Case 1: Nebula-Console needs to obtain the service name of Nebula-Graphd. 131 132 When defining `nebula-console`, add the following definitions (as `componentDefRef` shows): 133 134 ```yaml 135 - name: nebula-console 136 workloadType: Stateless 137 characterType: nebula 138 componentDefRef: 139 - componentDefName: nebula-graphd 140 componentRefEnv: 141 - name: GRAPHD_SVC_NAME 142 valueFrom: 143 type: ServiceRef 144 ``` 145 146 - Specify the component that is being referenced to as `nebula-graphd`. 147 - The name of the injected environment variable is `GRAPHD_SVC_NAME`. 148 - The value type of the variable is `ServerRef`, indicating that the value comes from the service name of the referenced component. 149 150 :::note 151 152 In KubeBlocks, if you've defined the `service` for a component, when you create a cluster, KubeBlocks will create a service named `{clusterName}-{componentName}` for that component. 153 154 ::: 155 156 ### HostName Reference 157 158 Case 2: Nebula-Graphd needs to configure the DNS of all PODs of Nebula-Metad. 159 160 ```yaml 161 - name: nebula-graphd 162 workloadType: Statelful 163 componentDefRef: 164 - componentDefName: nebula-metad 165 componentRefEnv: 166 - name: NEBULA_METAD_SVC 167 valueFrom: 168 type: HeadlessServiceRef 169 format: $(POD_FQDN):9559 # Optional, specify value format 170 ``` 171 172 - Specify the component that is being referenced to as nebula-metad. 173 - The name of the injected environment variable is NEBULA_METAD_SVC. 174 - The value type of the variable is HeadlessServiceRef. 175 - It indicates that the value comes from the FQDN of all Pods of the referenced component, and multiple values are connected with , by default. 176 - If the default FQDN format does not meet your needs, customize the format through format (as shown in Line 9). 177 178 :::note 179 180 KubeBlocks provides three built-in variables as placeholders and they will be replaced with specific values when the cluster is created: 181 - ${POD_ORDINAL}, which is the ordinal number of the Pod. 182 - ${POD_NAME}, which is the name of the Pod, formatted as `{clusterName}-{componentName}-{podOrdinal}`. 183 - ${POD_FQDN}, which is the Fully Qualified Domain Name (FQDN) of the Pod. 184 185 In KubeBlocks, each stateful component has a Headless Service named `headlessServiceName = {clusterName}-{componentName}-headless` by default. 186 187 Therefore, the format of the Pod FQDN of each stateful component is: 188 `POD_FQDN = {clusterName}-{componentName}-{podIndex}.{headlessServiceName}.{namespace}.svc`. 189 190 ::: 191 192 ### Field Reference 193 194 Case 3: Nebula-Console needs to obtain a service port name of Nebula-Graphd. 195 196 When defining `nebula-console` , add the following configurations (as `componentDefRef` shows): 197 198 ```yaml 199 - name: nebula-console 200 workloadType: Stateless 201 characterType: nebula 202 componentDefRef: 203 - componentDefName: nebula-graphd 204 componentRefEnv: 205 - name: GRAPHD_SVC_PORT 206 valueFrom: 207 type: FieldRef 208 fieldPath: $.componentDef.service.ports[?(@.name == "thrift")].port 209 ``` 210 211 - Specify the component that is being referenced to as `nebula-graphd`. 212 - The name of the injected environment variable is `GRAPHD_SVC_PORT`. 213 - The value type of the variable is `FieldRef`, indicating that the value comes from a certain property value of the referenced component and is specified by `fieldPath`. 214 215 `fieldPath` provides a way to parse property values through JSONPath syntax. 216 When parsing JSONPath, KubeBlocks registers two root objects by default: 217 218 - **componentDef**, the componentDef object being referenced. 219 - **components**, all components corresponding to the componentDef in the created cluster. 220 221 Therefore, in `fieldPath`, you can use `$.componentDef.service.ports[?(@.name == "thrift")].port` to obtain the port number named `thrift` in the service defined by this component. 222 223 ## Summary 224 225 This tutorial takes NebulaGraph as an example and introduces several types and solutions of inter-component references. 226 227 In addition to NebulaGraph, engines like GreptimDB, Pulsar, RisingWave and StarRocks also adopt `componentDefRef` API to deal with component references. You can also refer to their solutions. 228 229 For more information about the `componentDefRef`, refer to [ComponentDefRef API](https://kubeblocks.io/docs/release-0.6/developer_docs/api-reference/cluster#apps.kubeblocks.io/v1alpha1.ComponentDefRef). 230 231 ## Appendix 232 233 ### A1. YAML tips 234 235 Since Nebula-Graphd, Nebula-Metad and Nebula-Storaged all require the FQDN of each Pod in Nebula-Metad, you don't need to configure them repeatedly. 236 237 Quickly configure them with YAML anchors. 238 239 ```yaml 240 - name: nebula-graphd 241 # ... 242 componentDefRef: 243 - &metadRef # Define an anchor with `&` 244 componentDefName: nebula-metad 245 componentRefEnv: 246 - name: NEBULA_METAD_SVC 247 valueFrom: 248 type: HeadlessServiceRef 249 format: $(POD_FQDN){{ .Values.clusterDomain }}:9559 250 joinWith: "," 251 - name: nebula-storaged 252 componentDefRef: 253 - *metadRef # Use the anchor with `*` to avoid duplication 254 ```