kubevela.github.io/docs/end-user/policies/replication.md

6.5 KiB

title
Component Replication

Background

In KubeVela, we can dispatch resources across the clusters using deploy workflow step and override, topology policy. But projects like OpenYurt have finer-grained division like node pool. This requires to dispatch some similar resources to the same cluster. These resources are called replication. Back to the example of OpenYurt, it can integrate KubeVela and replicate the resources then dispatch them to the different node pool.

Usage

To replicate component, replication policy is added as a built-in policy. It can be only used together with deploy workflow step. If using replication policy in deploy workflow step, a new field context.replicaKey will be added to when rendering the component. You can use this field to dispatch the resources to the same cluster with different replicaKey.

:::note replication policy is only supported in KubeVela version 1.6.0+. :::

:::tip context.replicaKey is always used in metadata.name in ComponentDefinition or TraitDefinition when dispatching resources to avoid name conflict. We'll see it later in the example. :::

Example

The following ComponentDefinition is an example which make use of replication policy. It uses context.replicaKey to add suffixes to resource names.

import (
	"strconv"
)

"replica-webservice": {
	alias: ""
	annotations: {}
	attributes: {
		status: {}
		workload: {
			definition: {
				apiVersion: "apps/v1"
				kind:       "Deployment"
			}
			type: "deployments.apps"
		}
	}
	description: "Webservice, but can be replicated"
	labels: {}
	type: "component"
}

template: {
	output: {
		apiVersion: "apps/v1"
		kind:       "Deployment"
		metadata: {
			if context.replicaKey != _|_ {
				name: context.name + "-" + context.replicaKey
			}
			if context.replicaKey == _|_ {
				name: context.name
			}
		}
		spec: {
			selector: matchLabels: {
				"app.oam.dev/component": context.name
				if context.replicaKey != _|_ {
					"app.oam.dev/replicaKey": context.replicaKey
				}
			}

			template: {
				metadata: {
					labels: {
						if parameter.labels != _|_ {
							parameter.labels
						}
						"app.oam.dev/name":      context.appName
						"app.oam.dev/component": context.name
						if context.replicaKey != _|_ {
							"app.oam.dev/replicaKey": context.replicaKey
						}
					}
				}

				spec: {
					containers: [{
						name:  context.name
						image: parameter.image
						if parameter["ports"] != _|_ {
							ports: [ for v in parameter.ports {
								{
									containerPort: v.port
									name:          "port-" + strconv.FormatInt(v.port, 10)
								}}]
						}
					}]
				}
			}
		}
	}
	exposePorts: [
		for v in parameter.ports {
			port:       v.port
			targetPort: v.port
			name:       "port-" + strconv.FormatInt(v.port, 10)
		},
	]
	outputs: {
		if len(exposePorts) != 0 {
			webserviceExpose: {
				apiVersion: "v1"
				kind:       "Service"
				metadata: {
					if context.replicaKey != _|_ {
						name: context.name + "-" + context.replicaKey
					}
					if context.replicaKey == _|_ {
						name: context.name
					}
				}
				spec: {
					selector: {
						"app.oam.dev/component": context.name
						if context.replicaKey != _|_ {
							"app.oam.dev/replicaKey": context.replicaKey
						}
					}
					ports: exposePorts
				}
			}
		}
	}
	parameter: {
		// +usage=Which image would you like to use for your service
		// +short=i
		image: string
		// +usage=Which ports do you want customer traffic sent to, defaults to 80
		ports?: [...{
			// +usage=Number of port to expose on the pod's IP address
			port: int
		}]
	}
}

Copy the definition to file replica-webservice.cue and apply the definition:

vela def apply replica-webservice.cue

Then user can apply application below. Replication policy is declared in application.spec.policies. And it is used in deploy step to influence its result.

apiVersion: core.oam.dev/v1beta1
kind: Application
metadata:
  name: app-replication-policy
spec:
  components:
    - name: hello-rep
      type: replica-webservice
      properties:
        image: crccheck/hello-world
        ports:
          - port: 80
            expose: true
  policies:
    - name: replication-default
      type: replication
      properties:
        keys: [ "beijing","hangzhou" ]
        selector: [ "hello-rep" ]

  workflow:
    steps:
      - name: deploy-with-rep
        type: deploy
        properties:
          policies: [ "replication-default" ]

Then application will dispatch two deployments and two services:

vela status app-replication-policy --detail --tree
CLUSTER    NAMESPACE  RESOURCE                      STATUS    APPLY_TIME          DETAIL
local  ─── default─┬─ Service/hello-rep-beijing     updated   2022-11-03 11:26:03 Type: ClusterIP  Cluster-IP: 10.43.26.211  External-IP: <none>
                   │                                                              Port(s): 80/TCP  Age: 3h10m
                   ├─ Service/hello-rep-hangzhou    updated   2022-11-03 11:26:03 Type: ClusterIP  Cluster-IP: 10.43.36.44  External-IP: <none>
                   │                                                              Port(s): 80/TCP  Age: 3h10m
                   ├─ Deployment/hello-rep-beijing  updated   2022-11-03 11:26:03 Ready: 1/1  Up-to-date: 1  Available: 1  Age: 3h10m
                   └─ Deployment/hello-rep-hangzhou updated   2022-11-03 11:26:03 Ready: 1/1  Up-to-date: 1  Available: 1  Age: 3h10m

Notice

There are three policies that can use in deploy step: topology, override and replication. They can be used together to both replicate component and dispatch them to different clusters. Here is the rules when they are use together:

  1. The applying order of policies is topology -> override -> replication. More information can be found in Multi cluster Application
    • topology pick up which cluster to dispatch. If not used, application deploy resources to local cluster by default.
    • override modifies the component properties. If not used, no properties will be changed.
    • replication will turn one component into multiple ones.

:::note By default, the hub cluster where KubeVela locates is registered as the local cluster. You can use it like a managed cluster in spite that you cannot detach it or modify it. :::

  1. override and replication can be used together. But override will affect all replication of the component. It is mainly used to modify component properties for different clusters.