Skip to content

Commit

Permalink
if control plane node, half the root disk and make an etcd disk with it,
Browse files Browse the repository at this point in the history
add docs
  • Loading branch information
AshleyDumaine committed Feb 28, 2024
1 parent 7e71668 commit 7560cd8
Show file tree
Hide file tree
Showing 6 changed files with 124 additions and 9 deletions.
92 changes: 84 additions & 8 deletions controller/linodemachine_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ import (
"github.com/linode/cluster-api-provider-linode/cloud/services"
)

// default etcd Disk size in MB
const defaultEtcdDiskSize = 8192

var skippedMachinePhases = map[string]bool{
string(clusterv1.MachinePhasePending): true,
string(clusterv1.MachinePhaseFailed): true,
Expand Down Expand Up @@ -317,30 +320,52 @@ func (r *LinodeMachineReconciler) reconcileCreate(
linodeInstance = &linodeInstances[0]
case 0:
// get the bootstrap data for the Linode instance and set it for create config
createConfig, err := r.newCreateConfig(ctx, machineScope, tags, logger)
createOpts, err := r.newCreateConfig(ctx, machineScope, tags, logger)
if err != nil {
logger.Error(err, "Failed to create Linode machine create config")

return nil, err
}

if machineScope.LinodeCluster.Spec.VPCRef != nil {
iface, err := r.getVPCInterfaceConfig(ctx, machineScope, createConfig.Interfaces, logger)
iface, err := r.getVPCInterfaceConfig(ctx, machineScope, createOpts.Interfaces, logger)
if err != nil {
logger.Error(err, "Failed to get VPC interface config")

return nil, err
}

createConfig.Interfaces = append(createConfig.Interfaces, *iface)
createOpts.Interfaces = append(createOpts.Interfaces, *iface)
}

linodeInstance, err = machineScope.LinodeClient.CreateInstance(ctx, *createConfig)
linodeInstance, err = machineScope.LinodeClient.CreateInstance(ctx, *createOpts)
if err != nil {
logger.Error(err, "Failed to create Linode machine instance")

return nil, err
}

if kutil.IsControlPlaneMachine(machineScope.Machine) {
instanceConfig, err := r.configureDisksControlPlane(ctx, logger, machineScope, linodeInstance.ID)
if err != nil {
logger.Error(err, "Failed to configure instance disks")

return nil, err
}
if instanceConfig == nil {
logger.Error(err, "Failed to retrieve instance config")

return nil, err
}
// boot the machine now that disks are configured
err = machineScope.LinodeClient.BootInstance(ctx, linodeInstance.ID, instanceConfig.ID)
if err != nil {
logger.Error(err, "Failed to boot instance")

return nil, err
}
}

default:
err = errors.New("multiple instances")

Expand Down Expand Up @@ -378,6 +403,58 @@ func (r *LinodeMachineReconciler) reconcileCreate(
return linodeInstance, nil
}

func (r *LinodeMachineReconciler) configureDisksControlPlane(
ctx context.Context,
logger logr.Logger,
machineScope *scope.MachineScope,
linodeInstanceID int,
) (instanceConfig *linodego.InstanceConfig, err error) {
// get the default instance config
configs, err := machineScope.LinodeClient.ListInstanceConfigs(ctx, linodeInstanceID, &linodego.ListOptions{})
if err != nil || len(configs) == 0 {
logger.Error(err, "Failed to list instance configs")

return nil, err
}
instanceConfig = &configs[0]

// carve out space for the etcd disk
rootDiskID := instanceConfig.Devices.SDA.DiskID
rootDisk, err := machineScope.LinodeClient.GetInstanceDisk(ctx, linodeInstanceID, rootDiskID)
if err != nil {
logger.Error(err, "Failed to get root disk for instance")

return instanceConfig, err
}
diskSize := rootDisk.Size - defaultEtcdDiskSize
if err = machineScope.LinodeClient.ResizeInstanceDisk(ctx, linodeInstanceID, rootDiskID, diskSize); err != nil {
logger.Error(err, "Failed to resize root disk")

return instanceConfig, err
}

// create the etcd disk
etcdDisk, err := machineScope.LinodeClient.CreateInstanceDisk(
ctx,
linodeInstanceID,
linodego.InstanceDiskCreateOptions{
Label: "etcd-data",
Size: defaultEtcdDiskSize,
Filesystem: string(linodego.FilesystemExt4),
},
)
if err != nil {
logger.Error(err, "Failed to create etcd disk")

return instanceConfig, err
}

// attach etcd disk to sdc
instanceConfig.Devices.SDC = &linodego.InstanceConfigDevice{DiskID: etcdDisk.ID}

return instanceConfig, nil
}

func (r *LinodeMachineReconciler) reconcileUpdate(
ctx context.Context,
logger logr.Logger,
Expand Down Expand Up @@ -451,14 +528,13 @@ func (r *LinodeMachineReconciler) reconcileDelete(
return nil
}

err := services.DeleteNodeFromNB(ctx, logger, machineScope)
if err != nil {
if err := services.DeleteNodeFromNB(ctx, logger, machineScope); err != nil {
logger.Error(err, "Failed to remove node from Node Balancer backend")

return err
}
err = machineScope.LinodeClient.DeleteInstance(ctx, *machineScope.LinodeMachine.Spec.InstanceID)
if err != nil {

if err := machineScope.LinodeClient.DeleteInstance(ctx, *machineScope.LinodeMachine.Spec.InstanceID); err != nil {
if util.IgnoreLinodeAPIError(err, http.StatusNotFound) != nil {
logger.Error(err, "Failed to delete Linode machine instance")

Expand Down
5 changes: 4 additions & 1 deletion controller/linodemachine_controller_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ func (*LinodeMachineReconciler) newCreateConfig(ctx context.Context, machineScop

return nil, err
}

// if the machine is a control plane node, further configuration is needed before it can be booted
createConfig.Booted = util.Pointer(!kutil.IsControlPlaneMachine(machineScope.Machine))

createConfig.PrivateIP = true

bootstrapData, err := machineScope.GetBootstrapData(ctx)
Expand Down Expand Up @@ -87,7 +91,6 @@ func (*LinodeMachineReconciler) newCreateConfig(ctx context.Context, machineScop
if createConfig.Image == "" {
createConfig.Image = reconciler.DefaultMachineControllerLinodeImage
}

if createConfig.RootPass == "" {
createConfig.RootPass = uuid.NewString()
}
Expand Down
1 change: 1 addition & 0 deletions docs/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
- [Getting Started](./topics/getting-started.md)
- [Troubleshooting](./topics/troubleshooting.md)
- [Addons](./topics/addons.md)
- [Etcd](./topics/etcd.md)
- [Development](./developers/development.md)
- [Releasing](./developers/releasing.md)
- [Reference](./reference/reference.md)
9 changes: 9 additions & 0 deletions docs/src/topics/etcd.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Etcd

This guide covers etcd configuration for the control plane of provisioned CAPL clusters.

## Default configuration

By default, etcd is configured to be on a separate device from the root filesystem on
control plane nodes. The etcd disk is automatically sized at 8 GB per recommendation
from [the etcd documentation](https://etcd.io/docs/latest/dev-guide/limit/#storage-size-limit)
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,25 @@ spec:
preKubeadmCommands:
- /kubeadm-pre-init.sh '{{ ds.meta_data.label }}' "${KUBERNETES_VERSION}"
clusterConfiguration:
etcd:
local:
dataDir: /var/lib/etcd_data/etcd
extraArgs:
quota-backend-bytes: "8589934592"
apiServer:
extraArgs:
cloud-provider: external
controllerManager:
extraArgs:
cloud-provider: external
diskSetup:
filesystems:
- label: etcd_data
filesystem: ext4
device: /dev/sdc
mounts:
- - LABEL=etcd_data
- /var/lib/etcd_data
initConfiguration:
nodeRegistration:
kubeletExtraArgs:
Expand Down
13 changes: 13 additions & 0 deletions templates/flavors/default/kubeadm-control-plane.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,25 @@ spec:
preKubeadmCommands:
- /kubeadm-pre-init.sh '{{ ds.meta_data.label }}' "${KUBERNETES_VERSION}"
clusterConfiguration:
etcd:
local:
dataDir: /var/lib/etcd_data/etcd
extraArgs:
quota-backend-bytes: "8589934592"
apiServer:
extraArgs:
cloud-provider: external
controllerManager:
extraArgs:
cloud-provider: external
diskSetup:
filesystems:
- label: etcd_data
filesystem: ext4
device: /dev/sdc
mounts:
- - LABEL=etcd_data
- /var/lib/etcd_data
initConfiguration:
nodeRegistration:
kubeletExtraArgs:
Expand Down

0 comments on commit 7560cd8

Please sign in to comment.