From 5a9e3e6bf5cb520713842d15501aea78bc8fb112 Mon Sep 17 00:00:00 2001
From: Tibi <110664232+TiberiuGC@users.noreply.github.com>
Date: Tue, 26 Mar 2024 17:21:43 +0200
Subject: [PATCH 01/11] add support for AL2023 for EKS-managed and self-managed
nodes
---
pkg/ami/auto_resolver.go | 6 +-
pkg/ami/ssm_resolver.go | 3 +
.../eksctl.io/v1alpha5/assets/schema.json | 10 +-
pkg/apis/eksctl.io/v1alpha5/types.go | 14 ++-
pkg/nodebootstrap/al2023.go | 109 ++++++++++++++++++
pkg/nodebootstrap/managed_al2.go | 24 +++-
pkg/nodebootstrap/userdata.go | 12 +-
7 files changed, 160 insertions(+), 18 deletions(-)
create mode 100644 pkg/nodebootstrap/al2023.go
diff --git a/pkg/ami/auto_resolver.go b/pkg/ami/auto_resolver.go
index 1781c3982b..70dca4d02b 100644
--- a/pkg/ami/auto_resolver.go
+++ b/pkg/ami/auto_resolver.go
@@ -23,6 +23,10 @@ const (
// MakeImageSearchPatterns creates a map of image search patterns by image OS family and class
func MakeImageSearchPatterns(version string) map[string]map[int]string {
return map[string]map[int]string{
+ api.NodeImageFamilyAmazonLinux2023: {
+ ImageClassGeneral: fmt.Sprintf("amazon-eks-node-al2023-x86_64-standard-%s-v*", version),
+ ImageClassARM: fmt.Sprintf("amazon-eks-node-al2023-arm64-standard-%s-v*", version),
+ },
api.NodeImageFamilyAmazonLinux2: {
ImageClassGeneral: fmt.Sprintf("amazon-eks-node-%s-v*", version),
ImageClassGPU: fmt.Sprintf("amazon-eks-gpu-node-%s-*", version),
@@ -59,7 +63,7 @@ func OwnerAccountID(imageFamily, region string) (string, error) {
switch imageFamily {
case api.NodeImageFamilyUbuntu2204, api.NodeImageFamilyUbuntu2004, api.NodeImageFamilyUbuntu1804:
return ownerIDUbuntuFamily, nil
- case api.NodeImageFamilyAmazonLinux2:
+ case api.NodeImageFamilyAmazonLinux2023, api.NodeImageFamilyAmazonLinux2:
return api.EKSResourceAccountID(region), nil
default:
if api.IsWindowsImage(imageFamily) {
diff --git a/pkg/ami/ssm_resolver.go b/pkg/ami/ssm_resolver.go
index ad062196bf..84e9d67257 100644
--- a/pkg/ami/ssm_resolver.go
+++ b/pkg/ami/ssm_resolver.go
@@ -54,6 +54,9 @@ func MakeSSMParameterName(version, instanceType, imageFamily string) (string, er
const fieldName = "image_id"
switch imageFamily {
+ case api.NodeImageFamilyAmazonLinux2023:
+ return fmt.Sprintf("/aws/service/eks/optimized-ami/%s/%s/%s/standard/recommended/%s",
+ version, utils.ToKebabCase(imageFamily), instanceEC2ArchName(instanceType), fieldName), nil
case api.NodeImageFamilyAmazonLinux2:
return fmt.Sprintf("/aws/service/eks/optimized-ami/%s/%s/recommended/%s", version, imageType(imageFamily, instanceType, version), fieldName), nil
case api.NodeImageFamilyWindowsServer2019CoreContainer,
diff --git a/pkg/apis/eksctl.io/v1alpha5/assets/schema.json b/pkg/apis/eksctl.io/v1alpha5/assets/schema.json
index 8bfc0edecb..06afbb7c65 100755
--- a/pkg/apis/eksctl.io/v1alpha5/assets/schema.json
+++ b/pkg/apis/eksctl.io/v1alpha5/assets/schema.json
@@ -1256,11 +1256,12 @@
},
"amiFamily": {
"type": "string",
- "description": "Valid variants are: `\"AmazonLinux2\"` (default), `\"Ubuntu2204\"`, `\"Ubuntu2004\"`, `\"Ubuntu1804\"`, `\"Bottlerocket\"`, `\"WindowsServer2019CoreContainer\"`, `\"WindowsServer2019FullContainer\"`, `\"WindowsServer2022CoreContainer\"`, `\"WindowsServer2022FullContainer\"`.",
- "x-intellij-html-description": "Valid variants are: "AmazonLinux2"
(default), "Ubuntu2204"
, "Ubuntu2004"
, "Ubuntu1804"
, "Bottlerocket"
, "WindowsServer2019CoreContainer"
, "WindowsServer2019FullContainer"
, "WindowsServer2022CoreContainer"
, "WindowsServer2022FullContainer"
.",
+ "description": "Valid variants are: `\"AmazonLinux2\"` (default), `\"AmazonLinux2023\"`, `\"Ubuntu2204\"`, `\"Ubuntu2004\"`, `\"Ubuntu1804\"`, `\"Bottlerocket\"`, `\"WindowsServer2019CoreContainer\"`, `\"WindowsServer2019FullContainer\"`, `\"WindowsServer2022CoreContainer\"`, `\"WindowsServer2022FullContainer\"`.",
+ "x-intellij-html-description": "Valid variants are: "AmazonLinux2"
(default), "AmazonLinux2023"
, "Ubuntu2204"
, "Ubuntu2004"
, "Ubuntu1804"
, "Bottlerocket"
, "WindowsServer2019CoreContainer"
, "WindowsServer2019FullContainer"
, "WindowsServer2022CoreContainer"
, "WindowsServer2022FullContainer"
.",
"default": "AmazonLinux2",
"enum": [
"AmazonLinux2",
+ "AmazonLinux2023",
"Ubuntu2204",
"Ubuntu2004",
"Ubuntu1804",
@@ -1589,11 +1590,12 @@
},
"amiFamily": {
"type": "string",
- "description": "Valid variants are: `\"AmazonLinux2\"` (default), `\"Ubuntu2204\"`, `\"Ubuntu2004\"`, `\"Ubuntu1804\"`, `\"Bottlerocket\"`, `\"WindowsServer2019CoreContainer\"`, `\"WindowsServer2019FullContainer\"`, `\"WindowsServer2022CoreContainer\"`, `\"WindowsServer2022FullContainer\"`.",
- "x-intellij-html-description": "Valid variants are: "AmazonLinux2"
(default), "Ubuntu2204"
, "Ubuntu2004"
, "Ubuntu1804"
, "Bottlerocket"
, "WindowsServer2019CoreContainer"
, "WindowsServer2019FullContainer"
, "WindowsServer2022CoreContainer"
, "WindowsServer2022FullContainer"
.",
+ "description": "Valid variants are: `\"AmazonLinux2\"` (default), `\"AmazonLinux2023\"`, `\"Ubuntu2204\"`, `\"Ubuntu2004\"`, `\"Ubuntu1804\"`, `\"Bottlerocket\"`, `\"WindowsServer2019CoreContainer\"`, `\"WindowsServer2019FullContainer\"`, `\"WindowsServer2022CoreContainer\"`, `\"WindowsServer2022FullContainer\"`.",
+ "x-intellij-html-description": "Valid variants are: "AmazonLinux2"
(default), "AmazonLinux2023"
, "Ubuntu2204"
, "Ubuntu2004"
, "Ubuntu1804"
, "Bottlerocket"
, "WindowsServer2019CoreContainer"
, "WindowsServer2019FullContainer"
, "WindowsServer2022CoreContainer"
, "WindowsServer2022FullContainer"
.",
"default": "AmazonLinux2",
"enum": [
"AmazonLinux2",
+ "AmazonLinux2023",
"Ubuntu2204",
"Ubuntu2004",
"Ubuntu1804",
diff --git a/pkg/apis/eksctl.io/v1alpha5/types.go b/pkg/apis/eksctl.io/v1alpha5/types.go
index 07c956fa21..53bc098e99 100644
--- a/pkg/apis/eksctl.io/v1alpha5/types.go
+++ b/pkg/apis/eksctl.io/v1alpha5/types.go
@@ -222,12 +222,13 @@ const (
// All valid values of supported families should go in this block
const (
// DefaultNodeImageFamily (default)
- DefaultNodeImageFamily = NodeImageFamilyAmazonLinux2
- NodeImageFamilyAmazonLinux2 = "AmazonLinux2"
- NodeImageFamilyUbuntu2204 = "Ubuntu2204"
- NodeImageFamilyUbuntu2004 = "Ubuntu2004"
- NodeImageFamilyUbuntu1804 = "Ubuntu1804"
- NodeImageFamilyBottlerocket = "Bottlerocket"
+ DefaultNodeImageFamily = NodeImageFamilyAmazonLinux2
+ NodeImageFamilyAmazonLinux2023 = "AmazonLinux2023"
+ NodeImageFamilyAmazonLinux2 = "AmazonLinux2"
+ NodeImageFamilyUbuntu2204 = "Ubuntu2204"
+ NodeImageFamilyUbuntu2004 = "Ubuntu2004"
+ NodeImageFamilyUbuntu1804 = "Ubuntu1804"
+ NodeImageFamilyBottlerocket = "Bottlerocket"
NodeImageFamilyWindowsServer2019CoreContainer = "WindowsServer2019CoreContainer"
NodeImageFamilyWindowsServer2019FullContainer = "WindowsServer2019FullContainer"
@@ -606,6 +607,7 @@ func SupportedNodeVolumeTypes() []string {
// supportedAMIFamilies are the AMI families supported by EKS
func supportedAMIFamilies() []string {
return []string{
+ NodeImageFamilyAmazonLinux2023,
NodeImageFamilyAmazonLinux2,
NodeImageFamilyUbuntu2204,
NodeImageFamilyUbuntu2004,
diff --git a/pkg/nodebootstrap/al2023.go b/pkg/nodebootstrap/al2023.go
new file mode 100644
index 0000000000..347a14b86b
--- /dev/null
+++ b/pkg/nodebootstrap/al2023.go
@@ -0,0 +1,109 @@
+package nodebootstrap
+
+import (
+ "bytes"
+ "encoding/base64"
+
+ api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5"
+ "github.com/weaveworks/eksctl/pkg/nodebootstrap/assets"
+ "github.com/weaveworks/eksctl/pkg/nodebootstrap/utils"
+)
+
+// AL2023 is a bootstrapper for both EKS-managed and self-managed AmazonLinux2023 nodegroups
+type AL2023 struct {
+ cfg *api.ClusterConfig
+ ng *api.NodeGroupBase
+ taints []api.NodeGroupTaint
+ clusterDNS string
+ UserDataMimeBoundary string
+}
+
+func NewAL2023Bootstrapper(cfg *api.ClusterConfig, np api.NodePool, clusterDNS string) *AL2023 {
+ return &AL2023{
+ cfg: cfg,
+ ng: np.BaseNodeGroup(),
+ taints: np.NGTaints(),
+ clusterDNS: clusterDNS,
+ }
+}
+
+func (m *AL2023) UserData() (string, error) {
+ var (
+ buf bytes.Buffer
+ cloudboot []string
+ )
+
+ if api.IsEnabled(m.ng.EFAEnabled) {
+ cloudboot = append(cloudboot, assets.EfaManagedBoothook)
+ }
+
+ if err := createMimeMessage(&buf, []string{}, cloudboot, m.makeNodeConfig(), m.UserDataMimeBoundary); err != nil {
+ return "", err
+ }
+
+ return base64.StdEncoding.EncodeToString(buf.Bytes()), nil
+}
+
+func (m *AL2023) makeNodeConfig() *NodeConfig {
+ nodeConfig := &NodeConfig{
+ ApiVersion: "node.eks.aws/v1alpha1",
+ Kind: "NodeConfig",
+ Spec: NodeSpec{
+ Cluster: ClusterSpec{
+ Name: m.cfg.Metadata.Name,
+ ApiServerEndpoint: m.cfg.Status.Endpoint,
+ CertificateAuthority: base64.StdEncoding.EncodeToString(m.cfg.Status.CertificateAuthorityData),
+ CIDR: m.cfg.Status.KubernetesNetworkConfig.ServiceIPv4CIDR,
+ },
+ Kubelet: KubeletSpec{
+ Config: KubeletConfig{
+ ClusterDNS: []string{m.clusterDNS},
+ },
+ Flags: []string{"--node-labels=" + formatLabels(m.ng.Labels)},
+ },
+ },
+ }
+
+ if m.ng.MaxPodsPerNode > 0 {
+ nodeConfig.Spec.Kubelet.Config.MaxPods = &m.ng.MaxPodsPerNode
+ }
+
+ if len(m.taints) > 0 {
+ nodeConfig.Spec.Kubelet.Flags = append(nodeConfig.Spec.Kubelet.Flags, utils.FormatTaints(m.taints))
+ }
+
+ return nodeConfig
+}
+
+// NodeConfig represents the core EKS node configuration
+type NodeConfig struct {
+ ApiVersion string `yaml:"apiVersion"`
+ Kind string `yaml:"kind"`
+ Spec NodeSpec `yaml:"spec"`
+}
+
+// NodeSpec encapsulates the 'spec' section of the YAML
+type NodeSpec struct {
+ Cluster ClusterSpec `yaml:"cluster"`
+ Kubelet KubeletSpec `yaml:"kubelet"`
+}
+
+// ClusterSpec holds cluster-related parameters
+type ClusterSpec struct {
+ ApiServerEndpoint string `yaml:"apiServerEndpoint"`
+ CertificateAuthority string `yaml:"certificateAuthority"`
+ CIDR string `yaml:"cidr"`
+ Name string `yaml:"name"`
+}
+
+// KubeletSpec captures Kubelet parameters and flags
+type KubeletSpec struct {
+ Config KubeletConfig `yaml:"config"`
+ Flags []string `yaml:"flags"`
+}
+
+// KubeletConfig holds the 'config' section
+type KubeletConfig struct {
+ MaxPods *int `yaml:"maxPods,omitempty"`
+ ClusterDNS []string `yaml:"clusterDNS"`
+}
diff --git a/pkg/nodebootstrap/managed_al2.go b/pkg/nodebootstrap/managed_al2.go
index 34739430f4..a047354b92 100644
--- a/pkg/nodebootstrap/managed_al2.go
+++ b/pkg/nodebootstrap/managed_al2.go
@@ -9,6 +9,7 @@ import (
"strings"
"github.com/pkg/errors"
+ "gopkg.in/yaml.v2"
api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5"
"github.com/weaveworks/eksctl/pkg/nodebootstrap/assets"
@@ -60,7 +61,7 @@ func (m *ManagedAL2) UserData() (string, error) {
return "", nil
}
- if err := createMimeMessage(&buf, scripts, cloudboot, m.UserDataMimeBoundary); err != nil {
+ if err := createMimeMessage(&buf, scripts, cloudboot, nil, m.UserDataMimeBoundary); err != nil {
return "", err
}
@@ -85,7 +86,7 @@ func makeCustomAMIUserData(ng *api.NodeGroupBase, mimeBoundary string) (string,
return "", nil
}
- if err := createMimeMessage(&buf, scripts, nil, mimeBoundary); err != nil {
+ if err := createMimeMessage(&buf, scripts, nil, nil, mimeBoundary); err != nil {
return "", err
}
@@ -100,7 +101,7 @@ set -ex
return script
}
-func createMimeMessage(writer io.Writer, scripts, cloudboots []string, mimeBoundary string) error {
+func createMimeMessage(writer io.Writer, scripts, cloudboots []string, nodeConfig *NodeConfig, mimeBoundary string) error {
mw := multipart.NewWriter(writer)
if mimeBoundary != "" {
if err := mw.SetBoundary(mimeBoundary); err != nil {
@@ -136,5 +137,22 @@ func createMimeMessage(writer io.Writer, scripts, cloudboots []string, mimeBound
return err
}
}
+
+ if nodeConfig != nil {
+ yamlData, err := yaml.Marshal(nodeConfig)
+ if err != nil {
+ return fmt.Errorf("error marshalling node configuration: %w", err)
+ }
+ part, err := mw.CreatePart(map[string][]string{
+ "Content-Type": {"application/node.eks.aws"},
+ })
+ if err != nil {
+ return err
+ }
+ if _, err = part.Write(yamlData); err != nil {
+ return err
+ }
+ }
+
return mw.Close()
}
diff --git a/pkg/nodebootstrap/userdata.go b/pkg/nodebootstrap/userdata.go
index a5ddd00a3e..15adc20c33 100644
--- a/pkg/nodebootstrap/userdata.go
+++ b/pkg/nodebootstrap/userdata.go
@@ -52,6 +52,8 @@ func NewBootstrapper(clusterConfig *api.ClusterConfig, ng *api.NodeGroup) (Boots
return NewUbuntuBootstrapper(clusterConfig, ng, clusterDNS), nil
case api.NodeImageFamilyBottlerocket:
return NewBottlerocketBootstrapper(clusterConfig, ng), nil
+ case api.NodeImageFamilyAmazonLinux2023:
+ return NewAL2023Bootstrapper(clusterConfig, ng, clusterDNS), nil
case api.NodeImageFamilyAmazonLinux2:
return NewAL2Bootstrapper(clusterConfig, ng, clusterDNS), nil
default:
@@ -62,21 +64,23 @@ func NewBootstrapper(clusterConfig *api.ClusterConfig, ng *api.NodeGroup) (Boots
// NewManagedBootstrapper creates a new bootstrapper for managed nodegroups based on the AMI family
func NewManagedBootstrapper(clusterConfig *api.ClusterConfig, ng *api.ManagedNodeGroup) (Bootstrapper, error) {
+ clusterDNS, err := GetClusterDNS(clusterConfig)
+ if err != nil {
+ return nil, err
+ }
if api.IsWindowsImage(ng.AMIFamily) {
return &ManagedWindows{
NodeGroup: ng,
}, nil
}
switch ng.AMIFamily {
+ case api.NodeImageFamilyAmazonLinux2023:
+ return NewAL2023Bootstrapper(clusterConfig, ng, clusterDNS), nil
case api.NodeImageFamilyAmazonLinux2:
return NewManagedAL2Bootstrapper(ng), nil
case api.NodeImageFamilyBottlerocket:
return NewManagedBottlerocketBootstrapper(clusterConfig, ng), nil
case api.NodeImageFamilyUbuntu1804, api.NodeImageFamilyUbuntu2004, api.NodeImageFamilyUbuntu2204:
- clusterDNS, err := GetClusterDNS(clusterConfig)
- if err != nil {
- return nil, err
- }
return NewUbuntuBootstrapper(clusterConfig, ng, clusterDNS), nil
}
return nil, nil
From b29ad527698c71f4d10c446b4a1e3caa15f156d0 Mon Sep 17 00:00:00 2001
From: Tibi <110664232+TiberiuGC@users.noreply.github.com>
Date: Wed, 27 Mar 2024 09:02:34 +0200
Subject: [PATCH 02/11] ensure AL2023 only supports containerd
---
pkg/apis/eksctl.io/v1alpha5/defaults.go | 22 ++++++++++++-------
pkg/apis/eksctl.io/v1alpha5/defaults_test.go | 11 ++++++++++
pkg/apis/eksctl.io/v1alpha5/types.go | 4 ++--
pkg/apis/eksctl.io/v1alpha5/validation.go | 9 +++++---
.../eksctl.io/v1alpha5/validation_test.go | 17 +++++++++++++-
5 files changed, 49 insertions(+), 14 deletions(-)
diff --git a/pkg/apis/eksctl.io/v1alpha5/defaults.go b/pkg/apis/eksctl.io/v1alpha5/defaults.go
index 8ac085cc80..417ea56a5a 100644
--- a/pkg/apis/eksctl.io/v1alpha5/defaults.go
+++ b/pkg/apis/eksctl.io/v1alpha5/defaults.go
@@ -249,17 +249,23 @@ func setContainerRuntimeDefault(ng *NodeGroup, clusterVersion string) {
return
}
- // since clusterVersion is standardised beforehand, we can safely ignore the error
- isDockershimDeprecated, _ := utils.IsMinVersion(DockershimDeprecationVersion, clusterVersion)
+ if ng.AMIFamily == NodeImageFamilyAmazonLinux2023 {
+ ng.ContainerRuntime = aws.String(ContainerRuntimeContainerD)
+ return
+ }
- if isDockershimDeprecated {
+ // since clusterVersion is standardised beforehand, we can safely ignore the error
+ if isDockershimDeprecated, _ := utils.IsMinVersion(DockershimDeprecationVersion, clusterVersion); isDockershimDeprecated {
ng.ContainerRuntime = aws.String(ContainerRuntimeContainerD)
- } else {
- ng.ContainerRuntime = aws.String(ContainerRuntimeDockerD)
- if IsWindowsImage(ng.AMIFamily) {
- ng.ContainerRuntime = aws.String(ContainerRuntimeDockerForWindows)
- }
+ return
}
+
+ if IsWindowsImage(ng.AMIFamily) {
+ ng.ContainerRuntime = aws.String(ContainerRuntimeDockerForWindows)
+ return
+ }
+
+ ng.ContainerRuntime = aws.String(ContainerRuntimeDockerD)
}
func setIAMDefaults(iamConfig *NodeGroupIAM) {
diff --git a/pkg/apis/eksctl.io/v1alpha5/defaults_test.go b/pkg/apis/eksctl.io/v1alpha5/defaults_test.go
index f865880db3..6d100f9e3d 100644
--- a/pkg/apis/eksctl.io/v1alpha5/defaults_test.go
+++ b/pkg/apis/eksctl.io/v1alpha5/defaults_test.go
@@ -282,6 +282,17 @@ var _ = Describe("ClusterConfig validation", func() {
Expect(*testNodeGroup.ContainerRuntime).To(Equal(ContainerRuntimeDockerForWindows))
})
})
+ When("ami family is AmazonLinux2023", func() {
+ It("defaults to containerd as a container runtime", func() {
+ testNodeGroup := NodeGroup{
+ NodeGroupBase: &NodeGroupBase{
+ AMIFamily: NodeImageFamilyAmazonLinux2023,
+ },
+ }
+ SetNodeGroupDefaults(&testNodeGroup, &ClusterMeta{Version: Version1_23}, false)
+ Expect(*testNodeGroup.ContainerRuntime).To(Equal(ContainerRuntimeContainerD))
+ })
+ })
})
Context("Kubernetes version 1.24 or greater", func() {
diff --git a/pkg/apis/eksctl.io/v1alpha5/types.go b/pkg/apis/eksctl.io/v1alpha5/types.go
index 53bc098e99..4b2345c7dd 100644
--- a/pkg/apis/eksctl.io/v1alpha5/types.go
+++ b/pkg/apis/eksctl.io/v1alpha5/types.go
@@ -604,8 +604,8 @@ func SupportedNodeVolumeTypes() []string {
}
}
-// supportedAMIFamilies are the AMI families supported by EKS
-func supportedAMIFamilies() []string {
+// SupportedAMIFamilies are the AMI families supported by EKS
+func SupportedAMIFamilies() []string {
return []string{
NodeImageFamilyAmazonLinux2023,
NodeImageFamilyAmazonLinux2,
diff --git a/pkg/apis/eksctl.io/v1alpha5/validation.go b/pkg/apis/eksctl.io/v1alpha5/validation.go
index f3b2a5c975..caf62acfbc 100644
--- a/pkg/apis/eksctl.io/v1alpha5/validation.go
+++ b/pkg/apis/eksctl.io/v1alpha5/validation.go
@@ -625,7 +625,7 @@ func validateNodeGroupBase(np NodePool, path string, controlPlaneOnOutposts bool
if ng.AMIFamily == NodeImageFamilyWindowsServer20H2CoreContainer || ng.AMIFamily == NodeImageFamilyWindowsServer2004CoreContainer {
return fmt.Errorf("AMI Family %s is deprecated. For more information, head to the Amazon documentation on Windows AMIs (https://docs.aws.amazon.com/eks/latest/userguide/eks-optimized-windows-ami.html)", ng.AMIFamily)
}
- return fmt.Errorf("AMI Family %s is not supported - use one of: %s", ng.AMIFamily, strings.Join(supportedAMIFamilies(), ", "))
+ return fmt.Errorf("AMI Family %s is not supported - use one of: %s", ng.AMIFamily, strings.Join(SupportedAMIFamilies(), ", "))
}
if controlPlaneOnOutposts && ng.AMIFamily != NodeImageFamilyAmazonLinux2 {
return fmt.Errorf("only %s is supported on local clusters", NodeImageFamilyAmazonLinux2)
@@ -883,6 +883,9 @@ func ValidateNodeGroup(i int, ng *NodeGroup, cfg *ClusterConfig) error {
}
if ng.ContainerRuntime != nil {
+ if ng.AMIFamily == NodeImageFamilyAmazonLinux2023 && *ng.ContainerRuntime != ContainerRuntimeContainerD {
+ return fmt.Errorf("only %s is supported for container runtime on %s nodes", ContainerRuntimeContainerD, NodeImageFamilyAmazonLinux2023)
+ }
if *ng.ContainerRuntime != ContainerRuntimeDockerD && *ng.ContainerRuntime != ContainerRuntimeContainerD && *ng.ContainerRuntime != ContainerRuntimeDockerForWindows {
return fmt.Errorf("only %s, %s and %s are supported for container runtime", ContainerRuntimeContainerD, ContainerRuntimeDockerD, ContainerRuntimeDockerForWindows)
}
@@ -1266,7 +1269,7 @@ func ValidateManagedNodeGroup(index int, ng *ManagedNodeGroup) error {
}
func normalizeAMIFamily(ng *NodeGroupBase) {
- for _, family := range supportedAMIFamilies() {
+ for _, family := range SupportedAMIFamilies() {
if strings.EqualFold(ng.AMIFamily, family) {
ng.AMIFamily = family
return
@@ -1436,7 +1439,7 @@ func validateNodeGroupKubeletExtraConfig(kubeletConfig *InlineDocument) error {
}
func isSupportedAMIFamily(imageFamily string) bool {
- for _, image := range supportedAMIFamilies() {
+ for _, image := range SupportedAMIFamilies() {
if imageFamily == image {
return true
}
diff --git a/pkg/apis/eksctl.io/v1alpha5/validation_test.go b/pkg/apis/eksctl.io/v1alpha5/validation_test.go
index 4526e92e3c..a7838b1888 100644
--- a/pkg/apis/eksctl.io/v1alpha5/validation_test.go
+++ b/pkg/apis/eksctl.io/v1alpha5/validation_test.go
@@ -2,6 +2,7 @@ package v1alpha5_test
import (
"fmt"
+ "strings"
"github.com/aws/aws-sdk-go-v2/aws"
@@ -114,6 +115,20 @@ var _ = Describe("ClusterConfig validation", func() {
Expect(err).To(HaveOccurred())
})
+ It("should reject docker runtime if AMI Family is AmazonLinux2023", func() {
+ cfg := api.NewClusterConfig()
+ cfg.Metadata.Version = api.Version1_23
+ ng0 := cfg.NewNodeGroup()
+ ng0.Name = "node-group"
+ ng0.AMIFamily = api.NodeImageFamilyAmazonLinux2023
+ ng0.ContainerRuntime = aws.String(api.ContainerRuntimeDockerD)
+ err := api.ValidateClusterConfig(cfg)
+ Expect(err).NotTo(HaveOccurred())
+ err = api.ValidateNodeGroup(0, ng0, cfg)
+ Expect(err).To(HaveOccurred())
+ Expect(err).To(MatchError(ContainSubstring(fmt.Sprintf("only %s is supported for container runtime on %s nodes", api.ContainerRuntimeContainerD, api.NodeImageFamilyAmazonLinux2023))))
+ })
+
It("should reject docker runtime if version is 1.24 or greater", func() {
cfg := api.NewClusterConfig()
cfg.Metadata.Version = api.Version1_24
@@ -2002,7 +2017,7 @@ var _ = Describe("ClusterConfig validation", func() {
It("fails when the AMIFamily is not supported", func() {
ng.AMIFamily = "SomeTrash"
err := api.ValidateNodeGroup(0, ng, cfg)
- Expect(err).To(MatchError("AMI Family SomeTrash is not supported - use one of: AmazonLinux2, Ubuntu2204, Ubuntu2004, Ubuntu1804, Bottlerocket, WindowsServer2019CoreContainer, WindowsServer2019FullContainer, WindowsServer2022CoreContainer, WindowsServer2022FullContainer"))
+ Expect(err).To(MatchError(fmt.Sprintf("AMI Family SomeTrash is not supported - use one of: %s", strings.Join(api.SupportedAMIFamilies(), ", "))))
})
It("fails when the AmiFamily is not supported for managed nodes with custom AMI", func() {
From 7dea971de8c875de0b9eba361bd90c7983fea01a Mon Sep 17 00:00:00 2001
From: Tibi <110664232+TiberiuGC@users.noreply.github.com>
Date: Wed, 27 Mar 2024 13:32:12 +0200
Subject: [PATCH 03/11] add GPU related validations + small nits
---
.../eksctl.io/v1alpha5/gpu_validation_test.go | 36 +++++++++++++++++++
pkg/apis/eksctl.io/v1alpha5/validation.go | 21 +++++++----
pkg/cfn/builder/managed_nodegroup.go | 4 +++
pkg/eks/nodegroup_service.go | 7 +++-
pkg/nodebootstrap/al2023.go | 2 +-
5 files changed, 61 insertions(+), 9 deletions(-)
diff --git a/pkg/apis/eksctl.io/v1alpha5/gpu_validation_test.go b/pkg/apis/eksctl.io/v1alpha5/gpu_validation_test.go
index 8523bd9519..f1f5a6f07f 100644
--- a/pkg/apis/eksctl.io/v1alpha5/gpu_validation_test.go
+++ b/pkg/apis/eksctl.io/v1alpha5/gpu_validation_test.go
@@ -39,6 +39,24 @@ var _ = Describe("GPU instance support", func() {
mng.InstanceSelector = &api.InstanceSelector{}
assertValidationError(e, api.ValidateManagedNodeGroup(0, mng))
},
+ Entry("AL2023 INF", gpuInstanceEntry{
+ amiFamily: api.NodeImageFamilyAmazonLinux2023,
+ gpuInstanceType: "inf1.xlarge",
+ expectUnsupportedErr: true,
+ instanceTypeName: "Inferentia",
+ }),
+ Entry("AL2023 TRN", gpuInstanceEntry{
+ amiFamily: api.NodeImageFamilyAmazonLinux2023,
+ gpuInstanceType: "trn1.2xlarge",
+ expectUnsupportedErr: true,
+ instanceTypeName: "Trainium",
+ }),
+ Entry("AL2023 NVIDIA", gpuInstanceEntry{
+ amiFamily: api.NodeImageFamilyAmazonLinux2023,
+ gpuInstanceType: "g4dn.xlarge",
+ expectUnsupportedErr: true,
+ instanceTypeName: "GPU",
+ }),
Entry("AL2", gpuInstanceEntry{
gpuInstanceType: "asdf",
amiFamily: api.NodeImageFamilyAmazonLinux2,
@@ -72,6 +90,24 @@ var _ = Describe("GPU instance support", func() {
assertValidationError(e, api.ValidateNodeGroup(0, ng, api.NewClusterConfig()))
},
+ Entry("AL2023 INF", gpuInstanceEntry{
+ amiFamily: api.NodeImageFamilyAmazonLinux2023,
+ gpuInstanceType: "inf1.xlarge",
+ expectUnsupportedErr: true,
+ instanceTypeName: "Inferentia",
+ }),
+ Entry("AL2023 TRN", gpuInstanceEntry{
+ amiFamily: api.NodeImageFamilyAmazonLinux2023,
+ gpuInstanceType: "trn1.2xlarge",
+ expectUnsupportedErr: true,
+ instanceTypeName: "Trainium",
+ }),
+ Entry("AL2023 NVIDIA", gpuInstanceEntry{
+ amiFamily: api.NodeImageFamilyAmazonLinux2023,
+ gpuInstanceType: "g4dn.xlarge",
+ expectUnsupportedErr: true,
+ instanceTypeName: "GPU",
+ }),
Entry("AL2", gpuInstanceEntry{
gpuInstanceType: "g4dn.xlarge",
amiFamily: api.NodeImageFamilyAmazonLinux2,
diff --git a/pkg/apis/eksctl.io/v1alpha5/validation.go b/pkg/apis/eksctl.io/v1alpha5/validation.go
index caf62acfbc..f8ba37c2c7 100644
--- a/pkg/apis/eksctl.io/v1alpha5/validation.go
+++ b/pkg/apis/eksctl.io/v1alpha5/validation.go
@@ -53,6 +53,10 @@ var (
return fmt.Errorf("the %q addon must be installed to create pod identity associations; %s", PodIdentityAgentAddon, suggestion)
}
+ ErrUnsupportedInstanceTypes = func(instanceType, amiFamily, suggestion string) error {
+ return fmt.Errorf("%s instance types are not supported for %s; %s", instanceType, amiFamily, suggestion)
+ }
+
GPUDriversWarning = func(amiFamily string) string {
return fmt.Sprintf("%s does not ship with NVIDIA GPU drivers installed, hence won't support running GPU-accelerated workloads out of the box", amiFamily)
}
@@ -641,8 +645,15 @@ func validateNodeGroupBase(np NodePool, path string, controlPlaneOnOutposts bool
}
}
+ instanceType := SelectInstanceType(np)
+
+ if ng.AMIFamily == NodeImageFamilyAmazonLinux2023 && instanceutils.IsNvidiaInstanceType(instanceType) {
+ return ErrUnsupportedInstanceTypes("GPU", NodeImageFamilyAmazonLinux2023,
+ fmt.Sprintf("EKS accelerated AMIs based on %s will be available at a later date", NodeImageFamilyAmazonLinux2023))
+ }
+
if ng.AMIFamily != NodeImageFamilyAmazonLinux2 && ng.AMIFamily != NodeImageFamilyBottlerocket && ng.AMIFamily != "" {
- if instanceutils.IsNvidiaInstanceType(SelectInstanceType(np)) {
+ if instanceutils.IsNvidiaInstanceType(instanceType) {
logger.Warning(GPUDriversWarning(ng.AMIFamily))
}
if ng.InstanceSelector != nil && !ng.InstanceSelector.IsZero() &&
@@ -652,17 +663,13 @@ func validateNodeGroupBase(np NodePool, path string, controlPlaneOnOutposts bool
}
if ng.AMIFamily != NodeImageFamilyAmazonLinux2 && ng.AMIFamily != "" {
- instanceType := SelectInstanceType(np)
- unsupportedErr := func(instanceTypeName string) error {
- return fmt.Errorf("%s instance types are not supported for %s", instanceTypeName, ng.AMIFamily)
- }
// Only AL2 supports Inferentia hosts.
if instanceutils.IsInferentiaInstanceType(instanceType) {
- return unsupportedErr("Inferentia")
+ return ErrUnsupportedInstanceTypes("Inferentia", ng.AMIFamily, fmt.Sprintf("please use %s instead", NodeImageFamilyAmazonLinux2))
}
// Only AL2 supports Trainium hosts.
if instanceutils.IsTrainiumInstanceType(instanceType) {
- return unsupportedErr("Trainium")
+ return ErrUnsupportedInstanceTypes("Trainium", ng.AMIFamily, fmt.Sprintf("please use %s instead", NodeImageFamilyAmazonLinux2))
}
}
diff --git a/pkg/cfn/builder/managed_nodegroup.go b/pkg/cfn/builder/managed_nodegroup.go
index 90bda7c9f5..b90d07eb44 100644
--- a/pkg/cfn/builder/managed_nodegroup.go
+++ b/pkg/cfn/builder/managed_nodegroup.go
@@ -268,6 +268,10 @@ func getAMIType(ng *api.ManagedNodeGroup, instanceType string) ekstypes.AMITypes
ARM ekstypes.AMITypes
ARMGPU ekstypes.AMITypes
}{
+ api.NodeImageFamilyAmazonLinux2023: {
+ X86x64: ekstypes.AMITypesAl2023X8664Standard,
+ ARM: ekstypes.AMITypesAl2023Arm64Standard,
+ },
api.NodeImageFamilyAmazonLinux2: {
X86x64: ekstypes.AMITypesAl2X8664,
X86GPU: ekstypes.AMITypesAl2X8664Gpu,
diff --git a/pkg/eks/nodegroup_service.go b/pkg/eks/nodegroup_service.go
index f4cb170f5c..bfd4034ccd 100644
--- a/pkg/eks/nodegroup_service.go
+++ b/pkg/eks/nodegroup_service.go
@@ -60,7 +60,12 @@ func (n *NodeGroupService) Normalize(ctx context.Context, nodePools []api.NodePo
if ng.LaunchTemplate == nil && ng.InstanceType == "" && len(ng.InstanceTypes) == 0 && ng.InstanceSelector.IsZero() {
ng.InstanceType = api.DefaultNodeType
}
- hasNativeAMIFamilySupport := ng.AMIFamily == api.NodeImageFamilyAmazonLinux2 || ng.AMIFamily == api.NodeImageFamilyBottlerocket || api.IsWindowsImage(ng.AMIFamily)
+ hasNativeAMIFamilySupport :=
+ ng.AMIFamily == api.NodeImageFamilyAmazonLinux2023 ||
+ ng.AMIFamily == api.NodeImageFamilyAmazonLinux2 ||
+ ng.AMIFamily == api.NodeImageFamilyBottlerocket ||
+ api.IsWindowsImage(ng.AMIFamily)
+
if !hasNativeAMIFamilySupport && !api.IsAMI(ng.AMI) {
if err := ResolveAMI(ctx, n.provider, clusterConfig.Metadata.Version, np); err != nil {
return err
diff --git a/pkg/nodebootstrap/al2023.go b/pkg/nodebootstrap/al2023.go
index 347a14b86b..2737678529 100644
--- a/pkg/nodebootstrap/al2023.go
+++ b/pkg/nodebootstrap/al2023.go
@@ -69,7 +69,7 @@ func (m *AL2023) makeNodeConfig() *NodeConfig {
}
if len(m.taints) > 0 {
- nodeConfig.Spec.Kubelet.Flags = append(nodeConfig.Spec.Kubelet.Flags, utils.FormatTaints(m.taints))
+ nodeConfig.Spec.Kubelet.Flags = append(nodeConfig.Spec.Kubelet.Flags, "--register-with-taints="+utils.FormatTaints(m.taints))
}
return nodeConfig
From 677daf0a2a322e8cbe626743da5b9116dd3b7622 Mon Sep 17 00:00:00 2001
From: Tibi <110664232+TiberiuGC@users.noreply.github.com>
Date: Thu, 28 Mar 2024 09:13:56 +0200
Subject: [PATCH 04/11] add support for upgrades
---
pkg/ami/ssm_resolver.go | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/pkg/ami/ssm_resolver.go b/pkg/ami/ssm_resolver.go
index 84e9d67257..55b3e8f2e5 100644
--- a/pkg/ami/ssm_resolver.go
+++ b/pkg/ami/ssm_resolver.go
@@ -86,6 +86,10 @@ func MakeSSMParameterName(version, instanceType, imageFamily string) (string, er
// MakeManagedSSMParameterName creates an SSM parameter name for a managed nodegroup
func MakeManagedSSMParameterName(version string, amiType ekstypes.AMITypes) (string, error) {
switch amiType {
+ case ekstypes.AMITypesAl2023X8664Standard:
+ return fmt.Sprintf("/aws/service/eks/optimized-ami/%s/%s/x86_64/standard/recommended/release_version", version, utils.ToKebabCase(api.NodeImageFamilyAmazonLinux2023)), nil
+ case ekstypes.AMITypesAl2023Arm64Standard:
+ return fmt.Sprintf("/aws/service/eks/optimized-ami/%s/%s/arm64/standard/recommended/release_version", version, utils.ToKebabCase(api.NodeImageFamilyAmazonLinux2023)), nil
case ekstypes.AMITypesAl2X8664:
imageType := utils.ToKebabCase(api.NodeImageFamilyAmazonLinux2)
return fmt.Sprintf("/aws/service/eks/optimized-ami/%s/%s/recommended/release_version", version, imageType), nil
From c21c4a605bd13c09ad07d71b02f15a5fe9921e75 Mon Sep 17 00:00:00 2001
From: Tibi <110664232+TiberiuGC@users.noreply.github.com>
Date: Thu, 28 Mar 2024 14:13:43 +0200
Subject: [PATCH 05/11] add support for EFA
---
pkg/nodebootstrap/al2023.go | 64 +++---
pkg/nodebootstrap/al2023_test.go | 184 ++++++++++++++++++
pkg/nodebootstrap/assets/assets.go | 10 +
.../assets/scripts/efa.al2023.sh | 12 ++
.../scripts/efa.managed.al2023.boothook | 9 +
pkg/nodebootstrap/userdata.go | 2 +-
6 files changed, 254 insertions(+), 27 deletions(-)
create mode 100644 pkg/nodebootstrap/al2023_test.go
create mode 100644 pkg/nodebootstrap/assets/scripts/efa.al2023.sh
create mode 100644 pkg/nodebootstrap/assets/scripts/efa.managed.al2023.boothook
diff --git a/pkg/nodebootstrap/al2023.go b/pkg/nodebootstrap/al2023.go
index 2737678529..3477ccb506 100644
--- a/pkg/nodebootstrap/al2023.go
+++ b/pkg/nodebootstrap/al2023.go
@@ -9,16 +9,40 @@ import (
"github.com/weaveworks/eksctl/pkg/nodebootstrap/utils"
)
-// AL2023 is a bootstrapper for both EKS-managed and self-managed AmazonLinux2023 nodegroups
type AL2023 struct {
- cfg *api.ClusterConfig
- ng *api.NodeGroupBase
- taints []api.NodeGroupTaint
- clusterDNS string
+ cfg *api.ClusterConfig
+ ng *api.NodeGroupBase
+ taints []api.NodeGroupTaint
+ clusterDNS string
+
+ scripts []string
+ cloudboot []string
+ nodeConfig *NodeConfig
+
UserDataMimeBoundary string
}
-func NewAL2023Bootstrapper(cfg *api.ClusterConfig, np api.NodePool, clusterDNS string) *AL2023 {
+func NewManagedAL2023Bootstrapper(cfg *api.ClusterConfig, mng *api.ManagedNodeGroup, clusterDNS string) *AL2023 {
+ al2023 := newAL2023Bootstrapper(cfg, mng, clusterDNS)
+ if api.IsEnabled(mng.EFAEnabled) {
+ al2023.cloudboot = append(al2023.cloudboot, assets.EfaManagedAL2023Boothook)
+ }
+ if api.IsAMI(mng.AMI) {
+ al2023.setNodeConfig()
+ }
+ return al2023
+}
+
+func NewAL2023Bootstrapper(cfg *api.ClusterConfig, ng *api.NodeGroup, clusterDNS string) *AL2023 {
+ al2023 := newAL2023Bootstrapper(cfg, ng, clusterDNS)
+ if api.IsEnabled(ng.EFAEnabled) {
+ al2023.scripts = append(al2023.scripts, assets.EfaAl2023Sh)
+ }
+ al2023.setNodeConfig()
+ return al2023
+}
+
+func newAL2023Bootstrapper(cfg *api.ClusterConfig, np api.NodePool, clusterDNS string) *AL2023 {
return &AL2023{
cfg: cfg,
ng: np.BaseNodeGroup(),
@@ -28,24 +52,21 @@ func NewAL2023Bootstrapper(cfg *api.ClusterConfig, np api.NodePool, clusterDNS s
}
func (m *AL2023) UserData() (string, error) {
- var (
- buf bytes.Buffer
- cloudboot []string
- )
+ var buf bytes.Buffer
- if api.IsEnabled(m.ng.EFAEnabled) {
- cloudboot = append(cloudboot, assets.EfaManagedBoothook)
+ if len(m.scripts) == 0 && len(m.cloudboot) == 0 && m.nodeConfig == nil {
+ return "", nil
}
- if err := createMimeMessage(&buf, []string{}, cloudboot, m.makeNodeConfig(), m.UserDataMimeBoundary); err != nil {
+ if err := createMimeMessage(&buf, m.scripts, m.cloudboot, m.nodeConfig, m.UserDataMimeBoundary); err != nil {
return "", err
}
return base64.StdEncoding.EncodeToString(buf.Bytes()), nil
}
-func (m *AL2023) makeNodeConfig() *NodeConfig {
- nodeConfig := &NodeConfig{
+func (m *AL2023) setNodeConfig() {
+ m.nodeConfig = &NodeConfig{
ApiVersion: "node.eks.aws/v1alpha1",
Kind: "NodeConfig",
Spec: NodeSpec{
@@ -63,32 +84,25 @@ func (m *AL2023) makeNodeConfig() *NodeConfig {
},
},
}
-
if m.ng.MaxPodsPerNode > 0 {
- nodeConfig.Spec.Kubelet.Config.MaxPods = &m.ng.MaxPodsPerNode
+ m.nodeConfig.Spec.Kubelet.Config.MaxPods = &m.ng.MaxPodsPerNode
}
-
if len(m.taints) > 0 {
- nodeConfig.Spec.Kubelet.Flags = append(nodeConfig.Spec.Kubelet.Flags, "--register-with-taints="+utils.FormatTaints(m.taints))
+ m.nodeConfig.Spec.Kubelet.Flags = append(m.nodeConfig.Spec.Kubelet.Flags, "--register-with-taints="+utils.FormatTaints(m.taints))
}
-
- return nodeConfig
}
-// NodeConfig represents the core EKS node configuration
type NodeConfig struct {
ApiVersion string `yaml:"apiVersion"`
Kind string `yaml:"kind"`
Spec NodeSpec `yaml:"spec"`
}
-// NodeSpec encapsulates the 'spec' section of the YAML
type NodeSpec struct {
Cluster ClusterSpec `yaml:"cluster"`
Kubelet KubeletSpec `yaml:"kubelet"`
}
-// ClusterSpec holds cluster-related parameters
type ClusterSpec struct {
ApiServerEndpoint string `yaml:"apiServerEndpoint"`
CertificateAuthority string `yaml:"certificateAuthority"`
@@ -96,13 +110,11 @@ type ClusterSpec struct {
Name string `yaml:"name"`
}
-// KubeletSpec captures Kubelet parameters and flags
type KubeletSpec struct {
Config KubeletConfig `yaml:"config"`
Flags []string `yaml:"flags"`
}
-// KubeletConfig holds the 'config' section
type KubeletConfig struct {
MaxPods *int `yaml:"maxPods,omitempty"`
ClusterDNS []string `yaml:"clusterDNS"`
diff --git a/pkg/nodebootstrap/al2023_test.go b/pkg/nodebootstrap/al2023_test.go
new file mode 100644
index 0000000000..bfe1016403
--- /dev/null
+++ b/pkg/nodebootstrap/al2023_test.go
@@ -0,0 +1,184 @@
+package nodebootstrap_test
+
+import (
+ "encoding/base64"
+ "fmt"
+ "strings"
+
+ "github.com/aws/aws-sdk-go-v2/aws"
+ . "github.com/onsi/ginkgo/v2"
+ . "github.com/onsi/gomega"
+ api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5"
+ "github.com/weaveworks/eksctl/pkg/nodebootstrap"
+ "github.com/weaveworks/eksctl/pkg/nodebootstrap/assets"
+)
+
+type al2023Entry struct {
+ overrideNodegroupSettings func(api.NodePool)
+ expectedUserData string
+}
+
+var _ = DescribeTable("Unmanaged AL2023", func(e al2023Entry) {
+ cfg, dns := makeDefaultClusterSettings()
+ ng := api.NewNodeGroup()
+ makeDefaultNPSettings(ng)
+
+ if e.overrideNodegroupSettings != nil {
+ e.overrideNodegroupSettings(ng)
+ }
+
+ al2023BS := nodebootstrap.NewAL2023Bootstrapper(cfg, ng, dns)
+ al2023BS.UserDataMimeBoundary = "//"
+
+ userData, err := al2023BS.UserData()
+ Expect(err).NotTo(HaveOccurred())
+ decoded, err := base64.StdEncoding.DecodeString(userData)
+ Expect(err).NotTo(HaveOccurred())
+ actual := strings.ReplaceAll(string(decoded), "\r\n", "\n")
+ Expect(actual).To(Equal(e.expectedUserData))
+},
+ Entry("default", al2023Entry{
+ expectedUserData: wrapMIMEParts(nodeConfig),
+ }),
+ Entry("efa enabled", al2023Entry{
+ overrideNodegroupSettings: func(np api.NodePool) {
+ np.BaseNodeGroup().EFAEnabled = aws.Bool(true)
+ },
+ expectedUserData: wrapMIMEParts(efaScript + nodeConfig),
+ }),
+)
+
+var _ = DescribeTable("Managed AL2023", func(e al2023Entry) {
+ cfg, dns := makeDefaultClusterSettings()
+ mng := api.NewManagedNodeGroup()
+ makeDefaultNPSettings(mng)
+ mng.Taints = append(mng.Taints, api.NodeGroupTaint{
+ Key: "special",
+ Value: "true",
+ Effect: "NoSchedule",
+ })
+
+ if e.overrideNodegroupSettings != nil {
+ e.overrideNodegroupSettings(mng)
+ }
+
+ al2023ManagedBS := nodebootstrap.NewManagedAL2023Bootstrapper(cfg, mng, dns)
+ al2023ManagedBS.UserDataMimeBoundary = "//"
+
+ userData, err := al2023ManagedBS.UserData()
+ Expect(err).NotTo(HaveOccurred())
+ decoded, err := base64.StdEncoding.DecodeString(userData)
+ Expect(err).NotTo(HaveOccurred())
+ actual := strings.ReplaceAll(string(decoded), "\r\n", "\n")
+ Expect(actual).To(Equal(e.expectedUserData))
+},
+ Entry("native AMI", al2023Entry{
+ expectedUserData: "",
+ }),
+ Entry("native AMI && EFA enabled", al2023Entry{
+ overrideNodegroupSettings: func(np api.NodePool) {
+ np.BaseNodeGroup().EFAEnabled = aws.Bool(true)
+ },
+ expectedUserData: wrapMIMEParts(efaCloudhook),
+ }),
+ Entry("custom AMI", al2023Entry{
+ overrideNodegroupSettings: func(np api.NodePool) {
+ np.BaseNodeGroup().AMI = "ami-xxxx"
+ },
+ expectedUserData: wrapMIMEParts(managedNodeConfig),
+ }),
+ Entry("custom AMI && EFA enabled", al2023Entry{
+ overrideNodegroupSettings: func(np api.NodePool) {
+ np.BaseNodeGroup().AMI = "ami-xxxx"
+ np.BaseNodeGroup().EFAEnabled = aws.Bool(true)
+ },
+ expectedUserData: wrapMIMEParts(efaCloudhook + managedNodeConfig),
+ }),
+)
+
+var (
+ makeDefaultClusterSettings = func() (*api.ClusterConfig, string) {
+ clusterConfig := api.NewClusterConfig()
+ clusterConfig.Metadata.Name = "al2023-test"
+ clusterConfig.Status = &api.ClusterStatus{
+ Endpoint: "https://test.xxx.us-west-2.eks.amazonaws.com",
+ CertificateAuthorityData: []byte("test CA"),
+ KubernetesNetworkConfig: &api.KubernetesNetworkConfig{
+ ServiceIPv4CIDR: "10.100.0.0/16",
+ },
+ }
+ return clusterConfig, "10.100.0.10"
+ }
+
+ makeDefaultNPSettings = func(np api.NodePool) {
+ baseNg := np.BaseNodeGroup()
+ baseNg.MaxPodsPerNode = 4
+ baseNg.Labels = map[string]string{
+ "alpha.eksctl.io/nodegroup-name": "al2023-mng-test",
+ }
+ }
+
+ wrapMIMEParts = func(parts string) string {
+ return `MIME-Version: 1.0
+Content-Type: multipart/mixed; boundary=//
+
+` + parts + `--//--
+`
+ }
+
+ efaCloudhook = fmt.Sprintf(`--//
+Content-Type: text/cloud-boothook
+Content-Type: charset="us-ascii"
+
+%s
+`, assets.EfaManagedAL2023Boothook)
+
+ efaScript = fmt.Sprintf(`--//
+Content-Type: text/x-shellscript
+Content-Type: charset="us-ascii"
+
+%s
+`, assets.EfaAl2023Sh)
+
+ nodeConfig = `--//
+Content-Type: application/node.eks.aws
+
+apiVersion: node.eks.aws/v1alpha1
+kind: NodeConfig
+spec:
+ cluster:
+ apiServerEndpoint: https://test.xxx.us-west-2.eks.amazonaws.com
+ certificateAuthority: dGVzdCBDQQ==
+ cidr: 10.100.0.0/16
+ name: al2023-test
+ kubelet:
+ config:
+ maxPods: 4
+ clusterDNS:
+ - 10.100.0.10
+ flags:
+ - --node-labels=alpha.eksctl.io/nodegroup-name=al2023-mng-test
+
+`
+ managedNodeConfig = `--//
+Content-Type: application/node.eks.aws
+
+apiVersion: node.eks.aws/v1alpha1
+kind: NodeConfig
+spec:
+ cluster:
+ apiServerEndpoint: https://test.xxx.us-west-2.eks.amazonaws.com
+ certificateAuthority: dGVzdCBDQQ==
+ cidr: 10.100.0.0/16
+ name: al2023-test
+ kubelet:
+ config:
+ maxPods: 4
+ clusterDNS:
+ - 10.100.0.10
+ flags:
+ - --node-labels=alpha.eksctl.io/nodegroup-name=al2023-mng-test
+ - --register-with-taints=special=true:NoSchedule
+
+`
+)
diff --git a/pkg/nodebootstrap/assets/assets.go b/pkg/nodebootstrap/assets/assets.go
index 4c6965618e..c77c5bc450 100644
--- a/pkg/nodebootstrap/assets/assets.go
+++ b/pkg/nodebootstrap/assets/assets.go
@@ -25,11 +25,21 @@ var BootstrapUbuntuSh string
//go:embed scripts/efa.al2.sh
var EfaAl2Sh string
+// EfaAl2023Sh holds the efa.al2023.sh contents
+//
+//go:embed scripts/efa.al2023.sh
+var EfaAl2023Sh string
+
// EfaManagedBoothook holds the efa.managed.boothook contents
//
//go:embed scripts/efa.managed.boothook
var EfaManagedBoothook string
+// EfaManagedAL2023Boothook holds the efa.managed.al2023.boothook contents
+//
+//go:embed scripts/efa.managed.al2023.boothook
+var EfaManagedAL2023Boothook string
+
// InstallSsmAl2Sh holds the install-ssm.al2.sh contents
//
//go:embed scripts/install-ssm.al2.sh
diff --git a/pkg/nodebootstrap/assets/scripts/efa.al2023.sh b/pkg/nodebootstrap/assets/scripts/efa.al2023.sh
new file mode 100644
index 0000000000..3aef0ce36f
--- /dev/null
+++ b/pkg/nodebootstrap/assets/scripts/efa.al2023.sh
@@ -0,0 +1,12 @@
+#!/bin/bash
+
+set -o errexit
+set -o pipefail
+set -o nounset
+
+dnf install -y wget
+wget -q --timeout=20 https://s3-us-west-2.amazonaws.com/aws-efa-installer/aws-efa-installer-latest.tar.gz -O /tmp/aws-efa-installer.tar.gz
+tar -xf /tmp/aws-efa-installer.tar.gz -C /tmp
+cd /tmp/aws-efa-installer
+./efa_installer.sh -y -g
+/opt/amazon/efa/bin/fi_info -p efa
diff --git a/pkg/nodebootstrap/assets/scripts/efa.managed.al2023.boothook b/pkg/nodebootstrap/assets/scripts/efa.managed.al2023.boothook
new file mode 100644
index 0000000000..5d2a081688
--- /dev/null
+++ b/pkg/nodebootstrap/assets/scripts/efa.managed.al2023.boothook
@@ -0,0 +1,9 @@
+cloud-init-per once dnf_wget dnf install -y wget
+cloud-init-per once wget_efa wget -q --timeout=20 https://s3-us-west-2.amazonaws.com/aws-efa-installer/aws-efa-installer-latest.tar.gz -O /tmp/aws-efa-installer-latest.tar.gz
+
+cloud-init-per once tar_efa tar -xf /tmp/aws-efa-installer-latest.tar.gz -C /tmp
+pushd /tmp/aws-efa-installer
+cloud-init-per once install_efa ./efa_installer.sh -y -g
+pop /tmp/aws-efa-installer
+
+cloud-init-per once efa_info /opt/amazon/efa/bin/fi_info -p efa
diff --git a/pkg/nodebootstrap/userdata.go b/pkg/nodebootstrap/userdata.go
index 15adc20c33..e0cabc7f4a 100644
--- a/pkg/nodebootstrap/userdata.go
+++ b/pkg/nodebootstrap/userdata.go
@@ -75,7 +75,7 @@ func NewManagedBootstrapper(clusterConfig *api.ClusterConfig, ng *api.ManagedNod
}
switch ng.AMIFamily {
case api.NodeImageFamilyAmazonLinux2023:
- return NewAL2023Bootstrapper(clusterConfig, ng, clusterDNS), nil
+ return NewManagedAL2023Bootstrapper(clusterConfig, ng, clusterDNS), nil
case api.NodeImageFamilyAmazonLinux2:
return NewManagedAL2Bootstrapper(ng), nil
case api.NodeImageFamilyBottlerocket:
From 36fa4dbbb68849703df1cf6af23d143ac1909608 Mon Sep 17 00:00:00 2001
From: Tibi <110664232+TiberiuGC@users.noreply.github.com>
Date: Thu, 28 Mar 2024 14:14:03 +0200
Subject: [PATCH 06/11] improve validations
---
pkg/apis/eksctl.io/v1alpha5/validation.go | 48 +++++++++++++++++--
.../eksctl.io/v1alpha5/validation_test.go | 30 ++++++++++++
pkg/ctl/cmdutils/nodegroup_flags.go | 2 +-
3 files changed, 75 insertions(+), 5 deletions(-)
diff --git a/pkg/apis/eksctl.io/v1alpha5/validation.go b/pkg/apis/eksctl.io/v1alpha5/validation.go
index f8ba37c2c7..a296abcb10 100644
--- a/pkg/apis/eksctl.io/v1alpha5/validation.go
+++ b/pkg/apis/eksctl.io/v1alpha5/validation.go
@@ -824,7 +824,10 @@ func ValidateNodeGroup(i int, ng *NodeGroup, cfg *ClusterConfig) error {
ng.AMIFamily, path)
}
- if ng.AMI != "" && ng.OverrideBootstrapCommand == nil && ng.AMIFamily != NodeImageFamilyBottlerocket && !IsWindowsImage(ng.AMIFamily) {
+ if ng.AMI != "" && ng.OverrideBootstrapCommand == nil &&
+ ng.AMIFamily != NodeImageFamilyAmazonLinux2023 &&
+ ng.AMIFamily != NodeImageFamilyBottlerocket &&
+ !IsWindowsImage(ng.AMIFamily) {
return errors.Errorf("%[1]s.overrideBootstrapCommand is required when using a custom AMI based on %s (%[1]s.ami)", path, ng.AMIFamily)
}
@@ -854,6 +857,16 @@ func ValidateNodeGroup(i int, ng *NodeGroup, cfg *ClusterConfig) error {
if ng.KubeletExtraConfig != nil {
return fieldNotSupported("kubeletExtraConfig")
}
+ } else if ng.AMIFamily == NodeImageFamilyAmazonLinux2023 {
+ if ng.KubeletExtraConfig != nil {
+ return fieldNotSupported("kubeletExtraConfig")
+ }
+ if ng.PreBootstrapCommands != nil {
+ return fieldNotSupported("preBootstrapCommands")
+ }
+ if ng.OverrideBootstrapCommand != nil {
+ return fieldNotSupported("overrideBootstrapCommand")
+ }
} else if ng.AMIFamily == NodeImageFamilyBottlerocket {
if ng.KubeletExtraConfig != nil {
return fieldNotSupported("kubeletExtraConfig")
@@ -1249,12 +1262,16 @@ func ValidateManagedNodeGroup(index int, ng *ManagedNodeGroup) error {
if ng.AMIFamily == "" {
return errors.Errorf("when using a custom AMI, amiFamily needs to be explicitly set via config file or via --node-ami-family flag")
}
- if ng.AMIFamily != NodeImageFamilyAmazonLinux2 && ng.AMIFamily != NodeImageFamilyUbuntu1804 && ng.AMIFamily != NodeImageFamilyUbuntu2004 && ng.AMIFamily != NodeImageFamilyUbuntu2204 {
- return errors.Errorf("cannot set amiFamily to %s when using a custom AMI for managed nodes, only %s, %s, %s and %s are supported", ng.AMIFamily, NodeImageFamilyAmazonLinux2, NodeImageFamilyUbuntu1804, NodeImageFamilyUbuntu2004, NodeImageFamilyUbuntu2204)
+ if !IsAmazonLinuxImage(ng.AMIFamily) && !IsUbuntuImage(ng.AMIFamily) {
+ return errors.Errorf("cannot set amiFamily to %s when using a custom AMI for managed nodes, only %s, %s, %s, %s and %s are supported", ng.AMIFamily,
+ NodeImageFamilyAmazonLinux2023, NodeImageFamilyAmazonLinux2, NodeImageFamilyUbuntu1804, NodeImageFamilyUbuntu2004, NodeImageFamilyUbuntu2204)
}
- if ng.OverrideBootstrapCommand == nil {
+ if ng.OverrideBootstrapCommand == nil && ng.AMIFamily != NodeImageFamilyAmazonLinux2023 {
return errors.Errorf("%[1]s.overrideBootstrapCommand is required when using a custom AMI based on %s (%[1]s.ami)", path, ng.AMIFamily)
}
+ if ng.OverrideBootstrapCommand != nil && ng.AMIFamily == NodeImageFamilyAmazonLinux2023 {
+ return errors.Errorf("%[1]s.overrideBootstrapCommand is not supported when using a custom AMI based on %s (%[1]s.ami)", path, ng.AMIFamily)
+ }
notSupportedWithCustomAMIErr := func(field string) error {
return errors.Errorf("%s.%s is not supported when using a custom AMI (%s.ami)", path, field, path)
}
@@ -1454,6 +1471,29 @@ func isSupportedAMIFamily(imageFamily string) bool {
return false
}
+func IsAmazonLinuxImage(imageFamily string) bool {
+ switch imageFamily {
+ case NodeImageFamilyAmazonLinux2023,
+ NodeImageFamilyAmazonLinux2:
+ return true
+
+ default:
+ return false
+ }
+}
+
+func IsUbuntuImage(imageFamily string) bool {
+ switch imageFamily {
+ case NodeImageFamilyUbuntu2204,
+ NodeImageFamilyUbuntu2004,
+ NodeImageFamilyUbuntu1804:
+ return true
+
+ default:
+ return false
+ }
+}
+
// IsWindowsImage reports whether the AMI family is for Windows
func IsWindowsImage(imageFamily string) bool {
switch imageFamily {
diff --git a/pkg/apis/eksctl.io/v1alpha5/validation_test.go b/pkg/apis/eksctl.io/v1alpha5/validation_test.go
index a7838b1888..8e1bada38d 100644
--- a/pkg/apis/eksctl.io/v1alpha5/validation_test.go
+++ b/pkg/apis/eksctl.io/v1alpha5/validation_test.go
@@ -171,6 +171,14 @@ var _ = Describe("ClusterConfig validation", func() {
errMsg := fmt.Sprintf("overrideBootstrapCommand is required when using a custom AMI based on %s", ng0.AMIFamily)
Expect(api.ValidateNodeGroup(0, ng0, cfg)).To(MatchError(ContainSubstring(errMsg)))
})
+ It("should not require overrideBootstrapCommand if ami is set and type is AmazonLinux2023", func() {
+ cfg := api.NewClusterConfig()
+ ng0 := cfg.NewNodeGroup()
+ ng0.Name = "node-group"
+ ng0.AMI = "ami-1234"
+ ng0.AMIFamily = api.NodeImageFamilyAmazonLinux2023
+ Expect(api.ValidateNodeGroup(0, ng0, cfg)).To(Succeed())
+ })
It("should not require overrideBootstrapCommand if ami is set and type is Bottlerocket", func() {
cfg := api.NewClusterConfig()
ng0 := cfg.NewNodeGroup()
@@ -196,6 +204,24 @@ var _ = Describe("ClusterConfig validation", func() {
ng0.OverrideBootstrapCommand = aws.String("echo 'yo'")
Expect(api.ValidateNodeGroup(0, ng0, cfg)).To(Succeed())
})
+ It("should throw an error if overrideBootstrapCommand is set and type is AmazonLinux2023", func() {
+ cfg := api.NewClusterConfig()
+ ng0 := cfg.NewNodeGroup()
+ ng0.Name = "node-group"
+ ng0.AMI = "ami-1234"
+ ng0.AMIFamily = api.NodeImageFamilyAmazonLinux2023
+ ng0.OverrideBootstrapCommand = aws.String("echo 'yo'")
+ Expect(api.ValidateNodeGroup(0, ng0, cfg)).To(MatchError(ContainSubstring(fmt.Sprintf("overrideBootstrapCommand is not supported for %s nodegroups", api.NodeImageFamilyAmazonLinux2023))))
+ })
+ It("should throw an error if overrideBootstrapCommand is set and type is Bottlerocket", func() {
+ cfg := api.NewClusterConfig()
+ ng0 := cfg.NewNodeGroup()
+ ng0.Name = "node-group"
+ ng0.AMI = "ami-1234"
+ ng0.AMIFamily = api.NodeImageFamilyBottlerocket
+ ng0.OverrideBootstrapCommand = aws.String("echo 'yo'")
+ Expect(api.ValidateNodeGroup(0, ng0, cfg)).To(MatchError(ContainSubstring(fmt.Sprintf("overrideBootstrapCommand is not supported for %s nodegroups", api.NodeImageFamilyBottlerocket))))
+ })
It("should accept ami with a overrideBootstrapCommand set", func() {
cfg := api.NewClusterConfig()
ng0 := cfg.NewNodeGroup()
@@ -2029,6 +2055,10 @@ var _ = Describe("ClusterConfig validation", func() {
err := api.ValidateManagedNodeGroup(0, mng)
Expect(err).NotTo(HaveOccurred())
+ mng.AMIFamily = api.NodeImageFamilyAmazonLinux2
+ err = api.ValidateManagedNodeGroup(0, mng)
+ Expect(err).NotTo(HaveOccurred())
+
mng.AMIFamily = api.NodeImageFamilyUbuntu1804
err = api.ValidateManagedNodeGroup(0, mng)
Expect(err).NotTo(HaveOccurred())
diff --git a/pkg/ctl/cmdutils/nodegroup_flags.go b/pkg/ctl/cmdutils/nodegroup_flags.go
index 4d93152834..fdb25e63d0 100644
--- a/pkg/ctl/cmdutils/nodegroup_flags.go
+++ b/pkg/ctl/cmdutils/nodegroup_flags.go
@@ -40,7 +40,7 @@ func AddCommonCreateNodeGroupFlags(fs *pflag.FlagSet, cmd *Cmd, ng *api.NodeGrou
ng.SSH.EnableSSM = fs.Bool("enable-ssm", false, "Enable AWS Systems Manager (SSM)")
fs.StringVar(&ng.AMI, "node-ami", "", "'auto-ssm', 'auto' or an AMI ID (advanced use)")
- fs.StringVar(&ng.AMIFamily, "node-ami-family", api.DefaultNodeImageFamily, "'AmazonLinux2' for the Amazon EKS optimized AMI, or use 'Ubuntu2204', 'Ubuntu2004' or 'Ubuntu1804' for the official Canonical EKS AMIs")
+ fs.StringVar(&ng.AMIFamily, "node-ami-family", api.DefaultNodeImageFamily, fmt.Sprintf("supported AMI families: %s", strings.Join(api.SupportedNodeVolumeTypes(), ", ")))
fs.BoolVarP(&ng.PrivateNetworking, "node-private-networking", "P", false, "whether to make nodegroup networking private")
From 5e754c26cb32d6bf0671c5f386887a9e70d68772 Mon Sep 17 00:00:00 2001
From: Tibi <110664232+TiberiuGC@users.noreply.github.com>
Date: Thu, 28 Mar 2024 18:54:09 +0200
Subject: [PATCH 07/11] fix lint and unit tests
---
pkg/apis/eksctl.io/v1alpha5/validation_test.go | 11 ++++++-----
pkg/cfn/builder/managed_nodegroup_test.go | 1 +
pkg/ctl/cmdutils/nodegroup_flags.go | 2 +-
pkg/nodebootstrap/al2023.go | 8 ++++----
4 files changed, 12 insertions(+), 10 deletions(-)
diff --git a/pkg/apis/eksctl.io/v1alpha5/validation_test.go b/pkg/apis/eksctl.io/v1alpha5/validation_test.go
index 8e1bada38d..45eea4fa7f 100644
--- a/pkg/apis/eksctl.io/v1alpha5/validation_test.go
+++ b/pkg/apis/eksctl.io/v1alpha5/validation_test.go
@@ -2055,10 +2055,6 @@ var _ = Describe("ClusterConfig validation", func() {
err := api.ValidateManagedNodeGroup(0, mng)
Expect(err).NotTo(HaveOccurred())
- mng.AMIFamily = api.NodeImageFamilyAmazonLinux2
- err = api.ValidateManagedNodeGroup(0, mng)
- Expect(err).NotTo(HaveOccurred())
-
mng.AMIFamily = api.NodeImageFamilyUbuntu1804
err = api.ValidateManagedNodeGroup(0, mng)
Expect(err).NotTo(HaveOccurred())
@@ -2074,8 +2070,13 @@ var _ = Describe("ClusterConfig validation", func() {
mng.AMIFamily = api.NodeImageFamilyBottlerocket
mng.OverrideBootstrapCommand = nil
err = api.ValidateManagedNodeGroup(0, mng)
- errorMsg := fmt.Sprintf("cannot set amiFamily to %s when using a custom AMI for managed nodes, only %s, %s, %s and %s are supported", mng.AMIFamily, api.NodeImageFamilyAmazonLinux2, api.NodeImageFamilyUbuntu1804, api.NodeImageFamilyUbuntu2004, api.NodeImageFamilyUbuntu2204)
+ errorMsg := fmt.Sprintf("cannot set amiFamily to %s when using a custom AMI for managed nodes, only %s, %s, %s, %s and %s are supported",
+ mng.AMIFamily, api.NodeImageFamilyAmazonLinux2023, api.NodeImageFamilyAmazonLinux2, api.NodeImageFamilyUbuntu1804, api.NodeImageFamilyUbuntu2004, api.NodeImageFamilyUbuntu2204)
Expect(err).To(MatchError(errorMsg))
+
+ mng.AMIFamily = api.NodeImageFamilyAmazonLinux2023
+ err = api.ValidateManagedNodeGroup(0, mng)
+ Expect(err).NotTo(HaveOccurred())
})
It("fails when the AMIFamily is WindowsServer2004CoreContainer", func() {
diff --git a/pkg/cfn/builder/managed_nodegroup_test.go b/pkg/cfn/builder/managed_nodegroup_test.go
index dc0a8ab453..b0eefe8340 100644
--- a/pkg/cfn/builder/managed_nodegroup_test.go
+++ b/pkg/cfn/builder/managed_nodegroup_test.go
@@ -204,6 +204,7 @@ func TestManagedNodeRole(t *testing.T) {
t.Run(fmt.Sprintf("%d: %s", i, tt.description), func(t *testing.T) {
require := require.New(t)
clusterConfig := api.NewClusterConfig()
+ clusterConfig.Status = &api.ClusterStatus{}
api.SetManagedNodeGroupDefaults(tt.nodeGroup, clusterConfig.Metadata, false)
p := mockprovider.NewMockProvider()
fakeVPCImporter := new(vpcfakes.FakeImporter)
diff --git a/pkg/ctl/cmdutils/nodegroup_flags.go b/pkg/ctl/cmdutils/nodegroup_flags.go
index fdb25e63d0..211c6e3afc 100644
--- a/pkg/ctl/cmdutils/nodegroup_flags.go
+++ b/pkg/ctl/cmdutils/nodegroup_flags.go
@@ -40,7 +40,7 @@ func AddCommonCreateNodeGroupFlags(fs *pflag.FlagSet, cmd *Cmd, ng *api.NodeGrou
ng.SSH.EnableSSM = fs.Bool("enable-ssm", false, "Enable AWS Systems Manager (SSM)")
fs.StringVar(&ng.AMI, "node-ami", "", "'auto-ssm', 'auto' or an AMI ID (advanced use)")
- fs.StringVar(&ng.AMIFamily, "node-ami-family", api.DefaultNodeImageFamily, fmt.Sprintf("supported AMI families: %s", strings.Join(api.SupportedNodeVolumeTypes(), ", ")))
+ fs.StringVar(&ng.AMIFamily, "node-ami-family", api.DefaultNodeImageFamily, fmt.Sprintf("supported AMI families: %s", strings.Join(api.SupportedAMIFamilies(), ", ")))
fs.BoolVarP(&ng.PrivateNetworking, "node-private-networking", "P", false, "whether to make nodegroup networking private")
diff --git a/pkg/nodebootstrap/al2023.go b/pkg/nodebootstrap/al2023.go
index 3477ccb506..d5747b25d4 100644
--- a/pkg/nodebootstrap/al2023.go
+++ b/pkg/nodebootstrap/al2023.go
@@ -67,12 +67,12 @@ func (m *AL2023) UserData() (string, error) {
func (m *AL2023) setNodeConfig() {
m.nodeConfig = &NodeConfig{
- ApiVersion: "node.eks.aws/v1alpha1",
+ APIVersion: "node.eks.aws/v1alpha1",
Kind: "NodeConfig",
Spec: NodeSpec{
Cluster: ClusterSpec{
Name: m.cfg.Metadata.Name,
- ApiServerEndpoint: m.cfg.Status.Endpoint,
+ APIServerEndpoint: m.cfg.Status.Endpoint,
CertificateAuthority: base64.StdEncoding.EncodeToString(m.cfg.Status.CertificateAuthorityData),
CIDR: m.cfg.Status.KubernetesNetworkConfig.ServiceIPv4CIDR,
},
@@ -93,7 +93,7 @@ func (m *AL2023) setNodeConfig() {
}
type NodeConfig struct {
- ApiVersion string `yaml:"apiVersion"`
+ APIVersion string `yaml:"apiVersion"`
Kind string `yaml:"kind"`
Spec NodeSpec `yaml:"spec"`
}
@@ -104,7 +104,7 @@ type NodeSpec struct {
}
type ClusterSpec struct {
- ApiServerEndpoint string `yaml:"apiServerEndpoint"`
+ APIServerEndpoint string `yaml:"apiServerEndpoint"`
CertificateAuthority string `yaml:"certificateAuthority"`
CIDR string `yaml:"cidr"`
Name string `yaml:"name"`
From f5932a022c67713757e9458f5c0dd5d5c0e790ea Mon Sep 17 00:00:00 2001
From: Tibi <110664232+TiberiuGC@users.noreply.github.com>
Date: Thu, 28 Mar 2024 18:54:20 +0200
Subject: [PATCH 08/11] update docs
---
pkg/nodebootstrap/README.md | 33 ++++++++++++++++++++++++
userdocs/src/getting-started.md | 5 +++-
userdocs/src/usage/arm-support.md | 5 +---
userdocs/src/usage/container-runtime.md | 4 +--
userdocs/src/usage/custom-ami-support.md | 4 ++-
userdocs/theme/home.html | 3 ++-
6 files changed, 45 insertions(+), 9 deletions(-)
diff --git a/pkg/nodebootstrap/README.md b/pkg/nodebootstrap/README.md
index 845d74e6ad..37eef5f547 100644
--- a/pkg/nodebootstrap/README.md
+++ b/pkg/nodebootstrap/README.md
@@ -42,6 +42,39 @@ and then call `/etc/eks/bootstrap.sh`.
For AL2, enabling either SSM or EFA will add `assets/install-ssm.al2.sh` or `assets/efa.al2.sh`.
+### AmazonLinux2023
+
+While AL2023 implements the `Bootstrapper` interface, the underlying userdata will be entirely different from other AMI families. Specifically, AL2023 introduces a new node initialization process nodeadm that uses a YAML configuration schema, dropping the use of `/etc/eks/bootstrap.sh` script. For self-managed nodes, and for EKS-managed nodes based on custom AMIs, eksctl will populate userdata in the fashion below:
+
+```
+MIME-Version: 1.0
+Content-Type: multipart/mixed; boundary=//
+
+--//
+Content-Type: application/node.eks.aws
+
+apiVersion: node.eks.aws/v1alpha1
+kind: NodeConfig
+spec:
+ cluster:
+ apiServerEndpoint: https://XXXX.us-west-2.eks.amazonaws.com
+ certificateAuthority: XXXX
+ cidr: 10.100.0.0/16
+ name: my-cluster
+ kubelet:
+ config:
+ clusterDNS:
+ - 10.100.0.10
+ flags:
+ - --node-labels=alpha.eksctl.io/cluster-name=my-cluster,alpha.eksctl.io/nodegroup-name=my-nodegroup
+ - --register-with-taints=special=true:NoSchedule (only for EKS-managed nodes)
+
+--//--
+
+```
+
+For EKS-managed nodes based on native AMIs, the userdata above is fulfilled automatically by the AWS SSM agent.
+
## Troubleshooting
### Ubuntu
diff --git a/userdocs/src/getting-started.md b/userdocs/src/getting-started.md
index 8995f58eb1..4a11e2b5f7 100644
--- a/userdocs/src/getting-started.md
+++ b/userdocs/src/getting-started.md
@@ -1,6 +1,9 @@
# Getting started
-!!! tip "New for 2023"
+!!! tip "New for 2024"
+ `eksctl` now supports AMIs based on AmazonLinux2023
+
+!!! tip "eksctl main features in 2023"
`eksctl` now supports configuring cluster access management via [AWS EKS Access Entries](/usage/access-entries).
`eksctl` now supports configuring fine-grained permissions to EKS running apps via [EKS Pod Identity Associations](/usage/pod-identity-associations)
diff --git a/userdocs/src/usage/arm-support.md b/userdocs/src/usage/arm-support.md
index d75957609d..e23df6492e 100644
--- a/userdocs/src/usage/arm-support.md
+++ b/userdocs/src/usage/arm-support.md
@@ -51,10 +51,7 @@ managedNodeGroups:
eksctl create cluster -f cluster-arm-2.yaml
```
-The AMI resolvers, `auto` and `auto-ssm`, will infer the correct AMI based on the ARM instance type.
-
-???+ note
- Note that currently there are only AmazonLinux2 EKS optimized AMIs for ARM.
+The AMI resolvers, `auto` and `auto-ssm`, will infer the correct AMI based on the ARM instance type. Only AmazonLinux2023, AmazonLinux2 and Bottlerocket families have EKS optimized AMIs for ARM.
???+ note
ARM is supported for clusters with version 1.15 and higher.
diff --git a/userdocs/src/usage/container-runtime.md b/userdocs/src/usage/container-runtime.md
index 4c9fa63ee8..1d07cd4251 100644
--- a/userdocs/src/usage/container-runtime.md
+++ b/userdocs/src/usage/container-runtime.md
@@ -1,8 +1,8 @@
# Define Container Runtime
!!! warning
- Starting with Kubernetes version `1.24`, dockershim support has been deprecated. Therefore, if you create a cluster using `eksctl` on version `1.24` or higher, the information below no longer applies, and the only supported container runtime is `containerd`. Trying to set it otherwise will return a validation error.
-
+ Starting with Kubernetes version `1.24`, dockershim support has been deprecated. Therefore, if you create a cluster using `eksctl` on version `1.24` or higher, the information below no longer applies, and the only supported container runtime is `containerd`. Trying to set it otherwise will return a validation error. Additionally, AL2023 AMIs only support `containerd` regadless of K8s version.
+
At some point, we will completely remove the option to set `containerRuntime` in config file, together with the support for older Kubernetes versions support (i.e. `1.22` or `1.23`).
For AL2 ( AmazonLinux2 ) and Windows AMIs, it's possible to set container runtime to `containerd`.
diff --git a/userdocs/src/usage/custom-ami-support.md b/userdocs/src/usage/custom-ami-support.md
index 5108599caa..d4ed34315b 100644
--- a/userdocs/src/usage/custom-ami-support.md
+++ b/userdocs/src/usage/custom-ami-support.md
@@ -16,6 +16,7 @@ The flag can take the AMI image id for an image to explicitly use. It also can t
???+ note
When setting `--node-ami` to an ID string, `eksctl` will assume that a custom AMI has been requested.
For AmazonLinux2 and Ubuntu nodes, both EKS managed and self-managed, this will mean that `overrideBootstrapCommand` is required.
+ For AmazonLinux2023, since it stops using the `/etc/eks/bootstrap.sh` script for node bootstrapping, in favour of a nodeadm initialization process (for more information, please refer to [node bootstrapping docs](https://github.com/eksctl-io/eksctl/blob/main/pkg/nodebootstrap/README.md)), `overrideBootstrapCommand` is not supported.
CLI flag examples:
```sh
@@ -55,6 +56,7 @@ The `--node-ami-family` can take following keywords:
| Keyword | Description |
|--------------------------------|:--------------------------------------------------------------------------------------------------------------:|
| AmazonLinux2 | Indicates that the EKS AMI image based on Amazon Linux 2 should be used (default). |
+| AmazonLinux2023 | Indicates that the EKS AMI image based on Amazon Linux 2023 should be used. |
| Ubuntu2204 | Indicates that the EKS AMI image based on Ubuntu 22.04 LTS (Jammy) should be used (available for EKS >= 1.29). |
| Ubuntu2004 | Indicates that the EKS AMI image based on Ubuntu 20.04 LTS (Focal) should be used (supported for EKS <= 1.29). |
| Ubuntu1804 | Indicates that the EKS AMI image based on Ubuntu 18.04 LTS (Bionic) should be used. |
@@ -84,7 +86,7 @@ managedNodeGroups:
The `--node-ami-family` flag can also be used with `eksctl create nodegroup`. `eksctl` requires AMI Family to be explicitly set via config file or via `--node-ami-family` CLI flag, whenever working with a custom AMI.
???+ note
- At the moment, EKS managed nodegroups only support the following AMI Families when working with custom AMIs: `AmazonLinux2`, `Ubuntu1804`, `Ubuntu2004` and `Ubuntu2204`
+ At the moment, EKS managed nodegroups only support the following AMI Families when working with custom AMIs: `AmazonLinux2023`, `AmazonLinux2`, `Ubuntu1804`, `Ubuntu2004` and `Ubuntu2204`
## Windows custom AMI support
Only self-managed Windows nodegroups can specify a custom AMI. `amiFamily` should be set to a valid Windows AMI family.
diff --git a/userdocs/theme/home.html b/userdocs/theme/home.html
index 83b76bcd6f..6bd0a3e3b5 100644
--- a/userdocs/theme/home.html
+++ b/userdocs/theme/home.html
@@ -532,7 +532,8 @@
eksctl create cluster