Skip to content

Commit

Permalink
feat: add support for cluster class
Browse files Browse the repository at this point in the history
Signed-off-by: Carlos Salas <[email protected]>
  • Loading branch information
salasberryfin committed Feb 23, 2024
1 parent a6238db commit 15f7962
Show file tree
Hide file tree
Showing 23 changed files with 2,153 additions and 147 deletions.
58 changes: 57 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ Set the following environment variables:
- CABPR_WK_REPLICAS
- KUBERNETES_VERSION

for example :
for example:

```bash
export CABPR_NAMESPACE=example
Expand Down Expand Up @@ -197,6 +197,62 @@ To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.

:tada: CONGRATULATIONS ! :tada: You created your first RKE2 cluster with CAPD as an infrastructure provider.

### Using ClusterClass for cluster creation

This provider supports using [ClusterClass](https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20210526-cluster-class-and-managed-topologies.md), a Cluster API feature that implements an extra level of abstraction on top of the existing Cluster API functionality. The `ClusterClass` object is used to define a collection of template resources (control plane and machine deployment) which are used to generate one or more clusters of the same flavor.

If you are interested in leveraging this functionality, you can refer to the examples [here](./samples/docker/clusterclass/):
- [clusterclass-quick-start.yaml](./samples/docker/clusterclass/clusterclass-quick-start.yaml): creates a sample `ClusterClass` and necessary resources.
- [rke2-sample.yaml](./samples/docker/clusterclass/rke2-sample.yaml): creates a workload cluster using the `ClusterClass`.

As with other sample templates, you will need to set a number environment variables:
- CLUSTER_NAME
- CABPR_CP_REPLICAS
- CABPR_WK_REPLICAS
- KUBERNETES_VERSION
- KIND_IP

for example :

```bash
export CLUSTER_NAME=capd-rke2-clusterclass
export CABPR_CP_REPLICAS=3
export CABPR_WK_REPLICAS=2
export KUBERNETES_VERSION=v1.25.11
export KIND_IP=192.168.20.20
```

**Remember that, since we are using Kind, the value of `KIND_IP` must be an IP address in the range of the `kind` network.**
You can check the range Docker assigns to this network by inspecting it:

```bash
docker network inspect kind
```

The next step is to substitue the values in the YAML using the following commands:

```bash
cat clusterclass-quick-start.yaml | clusterctl generate yaml > clusterclass-example.yaml
```

At this moment, you can take some time to study the resulting YAML, then you can apply it to the management cluster:

```bash
kubectl apply -f clusterclass-example.yaml
```

This will create a new `ClusterClass` template that can be used to provision one or multiple workload clusters of the same flavor.
To do so, you can follow the same procedure and substitute the values in the YAML for the cluster definition:

```bash
cat rke2-sample.yaml | clusterctl generate yaml > rke2-clusterclass-example.yaml
```

And then apply the resulting YAML file to create a cluster from the existing `ClusterClass`.
```bash
kubectl apply -f rke2-clusterclass-example.yaml
```

## Testing the DEV main branch
These instructions are for development purposes initially and will be changed in the future for user facing instructions.

Expand Down
1 change: 1 addition & 0 deletions bootstrap/api/v1beta1/rke2config_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ type RKE2AgentConfig struct {
LoadBalancerPort int `json:"loadBalancerPort,omitempty"`

// Version specifies the rke2 version.
// This field will be deprecated in newer versions of the API and RKE2ControlPlaneSpec.Version will be used instead.
//+optional
Version string `json:"version,omitempty"`

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -850,7 +850,9 @@ spec:
for all system images.
type: string
version:
description: Version specifies the rke2 version.
description: Version specifies the rke2 version. This field will
be deprecated in newer versions of the API and RKE2ControlPlaneSpec.Version
will be used instead.
type: string
type: object
files:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -869,7 +869,9 @@ spec:
be used for all system images.
type: string
version:
description: Version specifies the rke2 version.
description: Version specifies the rke2 version. This
field will be deprecated in newer versions of the API
and RKE2ControlPlaneSpec.Version will be used instead.
type: string
type: object
files:
Expand Down
2 changes: 1 addition & 1 deletion bootstrap/config/crd/kustomization.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
commonLabels:
cluster.x-k8s.io/v1beta1: v1alpha1
cluster.x-k8s.io/v1beta1: v1alpha1_v1beta1

# This kustomization.yaml is not intended to be run by itself,
# since it depends on service name and namespace that are out of this kustomize package.
Expand Down
1 change: 1 addition & 0 deletions bootstrap/config/crd/patches/webhook_in_rke2configs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ spec:
path: /convert
conversionReviewVersions:
- v1
- v1beta1
63 changes: 62 additions & 1 deletion controlplane/api/v1alpha1/conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ package v1alpha1
import (
"fmt"

apiconversion "k8s.io/apimachinery/pkg/conversion"
utilconversion "sigs.k8s.io/cluster-api/util/conversion"

controlplanev1 "github.com/rancher-sandbox/cluster-api-provider-rke2/controlplane/api/v1beta1"
"sigs.k8s.io/controller-runtime/pkg/conversion"
)
Expand All @@ -28,11 +31,20 @@ func (src *RKE2ControlPlane) ConvertTo(dstRaw conversion.Hub) error {
if !ok {
return fmt.Errorf("not a RKE2ControlPlane: %v", dst)
}

if err := Convert_v1alpha1_RKE2ControlPlane_To_v1beta1_RKE2ControlPlane(src, dst, nil); err != nil {
return err
}

// Manually restore data.
restored := &controlplanev1.RKE2ControlPlane{}
if ok, err := utilconversion.UnmarshalData(src, restored); err != nil || !ok {
return err
}

dst.Spec.MachineTemplate = restored.Spec.MachineTemplate
dst.Spec.Version = restored.Spec.Version
dst.Status = restored.Status

return nil
}

Expand All @@ -46,6 +58,11 @@ func (dst *RKE2ControlPlane) ConvertFrom(srcRaw conversion.Hub) error {
return err
}

// Preserve Hub data on down-conversion
if err := utilconversion.MarshalData(src, dst); err != nil {
return err
}

return nil
}

Expand Down Expand Up @@ -85,6 +102,15 @@ func (src *RKE2ControlPlaneTemplate) ConvertTo(dstRaw conversion.Hub) error {
return err
}

// Manually restore data.
restored := &controlplanev1.RKE2ControlPlaneTemplate{}
if ok, err := utilconversion.UnmarshalData(src, restored); err != nil || !ok {
return err
}

dst.Spec.Template = restored.Spec.Template
dst.Status = restored.Status

return nil
}

Expand All @@ -98,6 +124,11 @@ func (dst *RKE2ControlPlaneTemplate) ConvertFrom(srcRaw conversion.Hub) error {
return err
}

// Preserve Hub data on down-conversion
if err := utilconversion.MarshalData(src, dst); err != nil {
return err
}

return nil
}

Expand Down Expand Up @@ -126,3 +157,33 @@ func (dst *RKE2ControlPlaneTemplateList) ConvertFrom(srcRaw conversion.Hub) erro

return nil
}

func Convert_v1beta1_RKE2ControlPlaneSpec_To_v1alpha1_RKE2ControlPlaneSpec(in *controlplanev1.RKE2ControlPlaneSpec, out *RKE2ControlPlaneSpec, s apiconversion.Scope) error {
// Version was added in v1beta1.
// MachineTemplate was added in v1beta1.
return autoConvert_v1beta1_RKE2ControlPlaneSpec_To_v1alpha1_RKE2ControlPlaneSpec(in, out, s)
}

func Convert_v1beta1_RKE2ControlPlaneStatus_To_v1alpha1_RKE2ControlPlaneStatus(in *controlplanev1.RKE2ControlPlaneStatus, out *RKE2ControlPlaneStatus, s apiconversion.Scope) error {
return autoConvert_v1beta1_RKE2ControlPlaneStatus_To_v1alpha1_RKE2ControlPlaneStatus(in, out, s)
}

func Convert_v1alpha1_RKE2ControlPlaneStatus_To_v1beta1_RKE2ControlPlaneStatus(in *RKE2ControlPlaneStatus, out *controlplanev1.RKE2ControlPlaneStatus, s apiconversion.Scope) error {
return autoConvert_v1alpha1_RKE2ControlPlaneStatus_To_v1beta1_RKE2ControlPlaneStatus(in, out, s)
}

func Convert_v1beta1_RKE2ControlPlaneTemplateSpec_To_v1alpha1_RKE2ControlPlaneTemplateSpec(in *controlplanev1.RKE2ControlPlaneTemplateSpec, out *RKE2ControlPlaneTemplateSpec, s apiconversion.Scope) error {
return autoConvert_v1beta1_RKE2ControlPlaneTemplateSpec_To_v1alpha1_RKE2ControlPlaneTemplateSpec(in, out, s)
}

func Convert_v1alpha1_RKE2ControlPlaneTemplateSpec_To_v1beta1_RKE2ControlPlaneTemplateSpec(in *RKE2ControlPlaneTemplateSpec, out *controlplanev1.RKE2ControlPlaneTemplateSpec, s apiconversion.Scope) error {
return autoConvert_v1alpha1_RKE2ControlPlaneTemplateSpec_To_v1beta1_RKE2ControlPlaneTemplateSpec(in, out, s)
}

func Convert_v1alpha1_RKE2ControlPlaneTemplateStatus_To_v1beta1_RKE2ControlPlaneStatus(in *RKE2ControlPlaneTemplateStatus, out *controlplanev1.RKE2ControlPlaneStatus, s apiconversion.Scope) error {
return nil
}

func Convert_v1beta1_RKE2ControlPlaneStatus_To_v1alpha1_RKE2ControlPlaneTemplateStatus(in *controlplanev1.RKE2ControlPlaneStatus, out *RKE2ControlPlaneTemplateStatus, s apiconversion.Scope) error {
return nil
}
3 changes: 0 additions & 3 deletions controlplane/api/v1alpha1/rke2controlplanetemplate_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,6 @@ import (
type RKE2ControlPlaneTemplateSpec struct {
// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
// Important: Run "make" to regenerate code after modifying this file

// Foo is an example field of RKE2ControlPlaneTemplate. Edit rke2controlplanetemplate_types.go to remove/update
Foo string `json:"foo,omitempty"`
}

// RKE2ControlPlaneTemplateStatus defines the observed state of RKE2ControlPlaneTemplate.
Expand Down
Loading

0 comments on commit 15f7962

Please sign in to comment.