Skip to content

Commit e7dddb6

Browse files
authored
Merge pull request #5318 from AndiDog/s3-user-data
✨ Support storing Ignition user data in S3 bucket for `AWSMachinePool`
2 parents 517ae6c + e84e321 commit e7dddb6

28 files changed

+1017
-223
lines changed

api/v1beta2/awsmachine_types.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,16 @@ const (
2929

3030
// DefaultIgnitionVersion represents default Ignition version generated for machine userdata.
3131
DefaultIgnitionVersion = "2.3"
32+
33+
// DefaultIgnitionStorageType represents the default storage type of Ignition userdata
34+
DefaultIgnitionStorageType = IgnitionStorageTypeOptionClusterObjectStore
35+
36+
// DefaultMachinePoolIgnitionStorageType represents the default storage type of Ignition userdata for machine pools.
37+
//
38+
// This is only different from DefaultIgnitionStorageType because of backward compatibility. Machine pools used to
39+
// default to store Ignition user data directly on the EC2 instance. Since the choice between remote storage (S3)
40+
// and direct storage was introduced, the default was kept, but might change in newer API versions.
41+
DefaultMachinePoolIgnitionStorageType = IgnitionStorageTypeOptionUnencryptedUserData
3242
)
3343

3444
// SecretBackend defines variants for backend secret storage.

api/v1beta2/awsmachine_webhook.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -414,12 +414,11 @@ func (r *AWSMachine) Default() {
414414
}
415415

416416
if r.ignitionEnabled() && r.Spec.Ignition.Version == "" {
417-
if r.Spec.Ignition == nil {
418-
r.Spec.Ignition = &Ignition{}
419-
}
420-
421417
r.Spec.Ignition.Version = DefaultIgnitionVersion
422418
}
419+
if r.ignitionEnabled() && r.Spec.Ignition.StorageType == "" {
420+
r.Spec.Ignition.StorageType = DefaultIgnitionStorageType
421+
}
423422
}
424423

425424
func (r *AWSMachine) validateAdditionalSecurityGroups() field.ErrorList {

api/v1beta2/tags.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,12 @@ const (
195195
// of the bootstrap secret that was used to create the user data for the latest launch
196196
// template version.
197197
LaunchTemplateBootstrapDataSecret = NameAWSProviderPrefix + "bootstrap-data-secret"
198+
199+
// LaunchTemplateBootstrapDataHash is the tag we use to store the hash of the raw bootstrap data.
200+
// If bootstrap data is stored in S3, this hash relates to that data, not to the EC2 instance
201+
// user data which only references the S3 object. We store this tag on launch template versions
202+
// so that S3 bootstrap data objects can be deleted when they get outdated.
203+
LaunchTemplateBootstrapDataHash = NameAWSProviderPrefix + "bootstrap-data-hash"
198204
)
199205

200206
// ClusterTagKey generates the key for resources associated with a cluster.

cmd/clusterawsadm/cloudformation/bootstrap/cluster_api_controller.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -296,11 +296,13 @@ func (t Template) ControllersPolicy() *iamv1.PolicyDocument {
296296
Action: iamv1.Actions{
297297
"s3:CreateBucket",
298298
"s3:DeleteBucket",
299-
"s3:GetObject",
300-
"s3:PutObject",
301299
"s3:DeleteObject",
300+
"s3:GetObject",
301+
"s3:ListBucket",
302302
"s3:PutBucketPolicy",
303303
"s3:PutBucketTagging",
304+
"s3:PutLifecycleConfiguration",
305+
"s3:PutObject",
304306
},
305307
})
306308
}

cmd/clusterawsadm/cloudformation/bootstrap/fixtures/with_s3_bucket.yaml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -302,11 +302,13 @@ Resources:
302302
- Action:
303303
- s3:CreateBucket
304304
- s3:DeleteBucket
305-
- s3:GetObject
306-
- s3:PutObject
307305
- s3:DeleteObject
306+
- s3:GetObject
307+
- s3:ListBucket
308308
- s3:PutBucketPolicy
309309
- s3:PutBucketTagging
310+
- s3:PutLifecycleConfiguration
311+
- s3:PutObject
310312
Effect: Allow
311313
Resource:
312314
- arn:*:s3:::cluster-api-provider-aws-*

config/crd/bases/infrastructure.cluster.x-k8s.io_awsmachinepools.yaml

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -889,6 +889,101 @@ spec:
889889
after it enters the InService state.
890890
If no value is supplied by user a default value of 300 seconds is set
891891
type: string
892+
ignition:
893+
description: Ignition defined options related to the bootstrapping
894+
systems where Ignition is used.
895+
properties:
896+
proxy:
897+
description: |-
898+
Proxy defines proxy settings for Ignition.
899+
Only valid for Ignition versions 3.1 and above.
900+
properties:
901+
httpProxy:
902+
description: |-
903+
HTTPProxy is the HTTP proxy to use for Ignition.
904+
A single URL that specifies the proxy server to use for HTTP and HTTPS requests,
905+
unless overridden by the HTTPSProxy or NoProxy options.
906+
type: string
907+
httpsProxy:
908+
description: |-
909+
HTTPSProxy is the HTTPS proxy to use for Ignition.
910+
A single URL that specifies the proxy server to use for HTTPS requests,
911+
unless overridden by the NoProxy option.
912+
type: string
913+
noProxy:
914+
description: |-
915+
NoProxy is the list of domains to not proxy for Ignition.
916+
Specifies a list of strings to hosts that should be excluded from proxying.
917+
918+
Each value is represented by:
919+
- An IP address prefix (1.2.3.4)
920+
- An IP address prefix in CIDR notation (1.2.3.4/8)
921+
- A domain name
922+
- A domain name matches that name and all subdomains
923+
- A domain name with a leading . matches subdomains only
924+
- A special DNS label (*), indicates that no proxying should be done
925+
926+
An IP address prefix and domain name can also include a literal port number (1.2.3.4:80).
927+
items:
928+
description: IgnitionNoProxy defines the list of domains
929+
to not proxy for Ignition.
930+
maxLength: 2048
931+
type: string
932+
maxItems: 64
933+
type: array
934+
type: object
935+
storageType:
936+
default: ClusterObjectStore
937+
description: |-
938+
StorageType defines how to store the boostrap user data for Ignition.
939+
This can be used to instruct Ignition from where to fetch the user data to bootstrap an instance.
940+
941+
When omitted, the storage option will default to ClusterObjectStore.
942+
943+
When set to "ClusterObjectStore", if the capability is available and a Cluster ObjectStore configuration
944+
is correctly provided in the Cluster object (under .spec.s3Bucket),
945+
an object store will be used to store bootstrap user data.
946+
947+
When set to "UnencryptedUserData", EC2 Instance User Data will be used to store the machine bootstrap user data, unencrypted.
948+
This option is considered less secure than others as user data may contain sensitive informations (keys, certificates, etc.)
949+
and users with ec2:DescribeInstances permission or users running pods
950+
that can access the ec2 metadata service have access to this sensitive information.
951+
So this is only to be used at ones own risk, and only when other more secure options are not viable.
952+
enum:
953+
- ClusterObjectStore
954+
- UnencryptedUserData
955+
type: string
956+
tls:
957+
description: |-
958+
TLS defines TLS settings for Ignition.
959+
Only valid for Ignition versions 3.1 and above.
960+
properties:
961+
certificateAuthorities:
962+
description: |-
963+
CASources defines the list of certificate authorities to use for Ignition.
964+
The value is the certificate bundle (in PEM format). The bundle can contain multiple concatenated certificates.
965+
Supported schemes are http, https, tftp, s3, arn, gs, and `data` (RFC 2397) URL scheme.
966+
items:
967+
description: IgnitionCASource defines the source of the
968+
certificate authority to use for Ignition.
969+
maxLength: 65536
970+
type: string
971+
maxItems: 64
972+
type: array
973+
type: object
974+
version:
975+
default: "2.3"
976+
description: Version defines which version of Ignition will be
977+
used to generate bootstrap data.
978+
enum:
979+
- "2.3"
980+
- "3.0"
981+
- "3.1"
982+
- "3.2"
983+
- "3.3"
984+
- "3.4"
985+
type: string
986+
type: object
892987
lifecycleHooks:
893988
description: AWSLifecycleHooks specifies lifecycle hooks for the autoscaling
894989
group.

controllers/awsmachine_controller.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -759,7 +759,7 @@ func (r *AWSMachineReconciler) resolveUserData(ctx context.Context, machineScope
759759
if machineScope.UseIgnition(userDataFormat) {
760760
var ignitionStorageType infrav1.IgnitionStorageTypeOption
761761
if machineScope.AWSMachine.Spec.Ignition == nil {
762-
ignitionStorageType = infrav1.IgnitionStorageTypeOptionClusterObjectStore
762+
ignitionStorageType = infrav1.DefaultIgnitionStorageType
763763
} else {
764764
ignitionStorageType = machineScope.AWSMachine.Spec.Ignition.StorageType
765765
}
@@ -815,8 +815,8 @@ func (r *AWSMachineReconciler) cloudInitUserData(machineScope *scope.MachineScop
815815
// then returns the config to instruct ignition on how to pull the user data from the bucket.
816816
func (r *AWSMachineReconciler) generateIgnitionWithRemoteStorage(ctx context.Context, scope *scope.MachineScope, objectStoreSvc services.ObjectStoreInterface, userData []byte) ([]byte, error) {
817817
if objectStoreSvc == nil {
818-
return nil, errors.New("using Ignition by default requires a cluster wide object storage configured at `AWSCluster.Spec.Ignition.S3Bucket`. " +
819-
"You must configure one or instruct Ignition to use EC2 user data instead, by setting `AWSMachine.Spec.Ignition.StorageType` to `UnencryptedUserData`")
818+
return nil, errors.New("using Ignition by default requires a cluster wide object storage configured at `AWSCluster.spec.s3Bucket`. " +
819+
"You must configure one or instruct Ignition to use EC2 user data instead, by setting `AWSMachine.spec.ignition.storageType` to `UnencryptedUserData`")
820820
}
821821

822822
objectURL, err := objectStoreSvc.Create(ctx, scope, userData)

exp/api/v1beta1/conversion.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ func (src *AWSMachinePool) ConvertTo(dstRaw conversion.Hub) error {
5252
if restored.Spec.AvailabilityZoneSubnetType != nil {
5353
dst.Spec.AvailabilityZoneSubnetType = restored.Spec.AvailabilityZoneSubnetType
5454
}
55+
if restored.Spec.Ignition != nil {
56+
dst.Spec.Ignition = restored.Spec.Ignition
57+
}
5558
dst.Status.InfrastructureMachineKind = restored.Status.InfrastructureMachineKind
5659
if restored.Spec.AWSLifecycleHooks != nil {
5760
dst.Spec.AWSLifecycleHooks = restored.Spec.AWSLifecycleHooks

exp/api/v1beta1/zz_generated.conversion.go

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

exp/api/v1beta2/awsmachinepool_types.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,10 @@ type AWSMachinePoolSpec struct {
101101
// If a process is removed from this list it will automatically be resumed.
102102
SuspendProcesses *SuspendProcessesTypes `json:"suspendProcesses,omitempty"`
103103

104+
// Ignition defined options related to the bootstrapping systems where Ignition is used.
105+
// +optional
106+
Ignition *infrav1.Ignition `json:"ignition,omitempty"`
107+
104108
// AWSLifecycleHooks specifies lifecycle hooks for the autoscaling group.
105109
// +optional
106110
AWSLifecycleHooks []AWSLifecycleHook `json:"lifecycleHooks,omitempty"`

0 commit comments

Comments
 (0)