Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] cluster api spectro ignition support #13

Open
wants to merge 9 commits into
base: archive-3oct2023-spectro-master
Choose a base branch
from
41 changes: 40 additions & 1 deletion bootstrap/kubeadm/api/v1alpha3/kubeadmbootstrapconfig_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,18 @@ import (
)

// Format specifies the output format of the bootstrap data
// +kubebuilder:validation:Enum=cloud-config
// +kubebuilder:validation:Enum=cloud-config;ignition
type Format string

const (
// CloudConfig make the bootstrap data to be of cloud-config format
CloudConfig Format = "cloud-config"

// Ignition make the bootstrap data to be of Ignition format.
Ignition Format = "ignition"
)


// KubeadmConfigSpec defines the desired state of KubeadmConfig.
// Either ClusterConfiguration and InitConfiguration should be defined or the JoinConfiguration should be defined.
type KubeadmConfigSpec struct {
Expand Down Expand Up @@ -95,8 +99,43 @@ type KubeadmConfigSpec struct {
// For more information, refer to https://github.com/kubernetes-sigs/cluster-api/pull/2763#discussion_r397306055.
// +optional
UseExperimentalRetryJoin bool `json:"useExperimentalRetryJoin,omitempty"`

// Ignition contains Ignition specific configuration.
//
// If set, bootstrap data will be generated in Ignition format instead of cloud-init.
//
// +optional
Ignition *IgnitionSpec `json:"ignitionConfig,omitempty"`
}

// IgnitionSpec contains Ignition specific configuration.
type IgnitionSpec struct {
// ContainerLinuxConfig contains CLC specific configuration.
//
// +optional
ContainerLinuxConfig *ContainerLinuxConfig `json:"containerLinuxConfig,omitempty"`
}

// ContainerLinuxConfig contains CLC specific configuration.
//
// We use structured type here to keep space for adding additional fields, for example 'version'.
type ContainerLinuxConfig struct {
// AdditionalConfig contains additional configuration which will be appended/merged [1] to the
// Ingnition configuration generated by the bootstrapper controller.
//
// Format of data is documented here [2].
//
// [1] https://coreos.github.io/ignition/operator-notes/#config-merging
// [2] https://kinvolk.io/docs/flatcar-container-linux/latest/provisioning/cl-config/
//
// +optional
AdditionalConfig string `json:"additionalConfig,omitempty"`

// Strict controls if AdditionalConfig should be strictly parsed. If so, warnings are treated as errors.
Strict bool `json:"strict,omitempty"`
}


// KubeadmConfigStatus defines the observed state of KubeadmConfig
type KubeadmConfigStatus struct {
// Ready indicates the BootstrapData field is ready to be consumed
Expand Down
40 changes: 40 additions & 0 deletions bootstrap/kubeadm/api/v1alpha3/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -1305,7 +1305,26 @@ spec:
description: Format specifies the output format of the bootstrap data
enum:
- cloud-config
- ignition
type: string
ignitionConfig:
description: "Ignition contains Ignition specific configuration. \n
If set, bootstrap data will be generated in Ignition format instead
of cloud-init."
properties:
containerLinuxConfig:
description: ContainerLinuxConfig contains CLC specific configuration.
properties:
additionalConfig:
description: AdditionalConfig contains additional configuration
which will be added bootstrap data in CLC format.
type: string
strict:
description: Strict controls if AdditionalConfig should be
strictly parsed. If so, warnings are treated as errors.
type: boolean
type: object
type: object
initConfiguration:
description: InitConfiguration along with ClusterConfiguration are
the configurations necessary for the init command
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1372,7 +1372,29 @@ spec:
data
enum:
- cloud-config
- ignition
type: string
ignitionConfig:
description: "Ignition contains Ignition specific configuration.
\n If set, bootstrap data will be generated in Ignition
format instead of cloud-init."
properties:
containerLinuxConfig:
description: ContainerLinuxConfig contains CLC specific
configuration.
properties:
additionalConfig:
description: AdditionalConfig contains additional
configuration which will be added bootstrap data
in CLC format.
type: string
strict:
description: Strict controls if AdditionalConfig should
be strictly parsed. If so, warnings are treated
as errors.
type: boolean
type: object
type: object
initConfiguration:
description: InitConfiguration along with ClusterConfiguration
are the configurations necessary for the init command
Expand Down
77 changes: 69 additions & 8 deletions bootstrap/kubeadm/controllers/kubeadmconfig_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import (
clusterv1 "sigs.k8s.io/cluster-api/api/v1alpha3"
bootstrapv1 "sigs.k8s.io/cluster-api/bootstrap/kubeadm/api/v1alpha3"
"sigs.k8s.io/cluster-api/bootstrap/kubeadm/internal/cloudinit"
"sigs.k8s.io/cluster-api/bootstrap/kubeadm/internal/ignition"
"sigs.k8s.io/cluster-api/bootstrap/kubeadm/internal/locking"
kubeadmv1beta1 "sigs.k8s.io/cluster-api/bootstrap/kubeadm/types/v1beta1"
bsutil "sigs.k8s.io/cluster-api/bootstrap/util"
Expand Down Expand Up @@ -427,7 +428,7 @@ func (r *KubeadmConfigReconciler) handleClusterNotInitialized(ctx context.Contex
return ctrl.Result{}, err
}

cloudInitData, err := cloudinit.NewInitControlPlane(&cloudinit.ControlPlaneInput{
controlPlaneInput := &cloudinit.ControlPlaneInput{
BaseUserData: cloudinit.BaseUserData{
AdditionalFiles: files,
NTP: scope.Config.Spec.NTP,
Expand All @@ -441,9 +442,28 @@ func (r *KubeadmConfigReconciler) handleClusterNotInitialized(ctx context.Contex
InitConfiguration: initdata,
ClusterConfiguration: clusterdata,
Certificates: certificates,
})
}

var cloudInitData []byte

switch scope.Config.Spec.Format {
case bootstrapv1.Ignition:
ign, _, err := ignition.NewInitControlPlane(&ignition.ControlPlaneInput{
ControlPlaneInput: controlPlaneInput,
Ignition: scope.Config.Spec.Ignition,
})
if err != nil {
scope.Error(err, "Failed to generate Ignition user data for bootstrap control plane")
return ctrl.Result{}, err
}

cloudInitData = ign
default:
cloudInitData, err = cloudinit.NewInitControlPlane(controlPlaneInput)
}

if err != nil {
scope.Error(err, "Failed to generate cloud init for bootstrap control plane")
scope.Error(err, "Failed to generate user data for bootstrap control plane")
return ctrl.Result{}, err
}

Expand Down Expand Up @@ -502,7 +522,7 @@ func (r *KubeadmConfigReconciler) joinWorker(ctx context.Context, scope *Scope)
return ctrl.Result{}, err
}

cloudJoinData, err := cloudinit.NewNode(&cloudinit.NodeInput{
nodeInput := &cloudinit.NodeInput{
BaseUserData: cloudinit.BaseUserData{
AdditionalFiles: files,
NTP: scope.Config.Spec.NTP,
Expand All @@ -515,7 +535,27 @@ func (r *KubeadmConfigReconciler) joinWorker(ctx context.Context, scope *Scope)
UseExperimentalRetry: scope.Config.Spec.UseExperimentalRetryJoin,
},
JoinConfiguration: joinData,
})
}

var cloudJoinData []byte

switch scope.Config.Spec.Format {
case bootstrapv1.Ignition:
ign, _, err := ignition.NewNode(&ignition.NodeInput{
NodeInput: nodeInput,
Ignition: scope.Config.Spec.Ignition,
})

if err != nil {
scope.Error(err, "Failed to generate Ignition user data for the worker node")
return ctrl.Result{}, err
}

cloudJoinData = ign
default:
cloudJoinData, err = cloudinit.NewNode(nodeInput)
}

if err != nil {
scope.Error(err, "Failed to create a worker join configuration")
return ctrl.Result{}, err
Expand Down Expand Up @@ -579,7 +619,7 @@ func (r *KubeadmConfigReconciler) joinControlplane(ctx context.Context, scope *S
return ctrl.Result{}, err
}

cloudJoinData, err := cloudinit.NewJoinControlPlane(&cloudinit.ControlPlaneJoinInput{
controlPlaneJoinInput := &cloudinit.ControlPlaneJoinInput{
JoinConfiguration: joinData,
Certificates: certificates,
BaseUserData: cloudinit.BaseUserData{
Expand All @@ -593,7 +633,27 @@ func (r *KubeadmConfigReconciler) joinControlplane(ctx context.Context, scope *S
KubeadmVerbosity: verbosityFlag,
UseExperimentalRetry: scope.Config.Spec.UseExperimentalRetryJoin,
},
})
}

var cloudJoinData []byte

switch scope.Config.Spec.Format {
case bootstrapv1.Ignition:
ign, _, err := ignition.NewJoinControlPlane(&ignition.ControlPlaneJoinInput{
ControlPlaneJoinInput: controlPlaneJoinInput,
Ignition: scope.Config.Spec.Ignition,
})

if err != nil {
scope.Error(err, "Failed to generate Ignition user data for join control plane")
return ctrl.Result{}, err
}

cloudJoinData = ign
default:
cloudJoinData, err = cloudinit.NewJoinControlPlane(controlPlaneJoinInput)
}

if err != nil {
scope.Error(err, "Failed to create a control plane join configuration")
return ctrl.Result{}, err
Expand Down Expand Up @@ -861,7 +921,8 @@ func (r *KubeadmConfigReconciler) storeBootstrapData(ctx context.Context, scope
},
},
Data: map[string][]byte{
"value": data,
"value": data,
"format": []byte(scope.Config.Spec.Format),
},
Type: clusterv1.ClusterSecretType,
}
Expand Down
Loading