diff --git a/nodeadm/internal/kubelet/daemon.go b/nodeadm/internal/kubelet/daemon.go index 1f965abad..5cb1a229c 100644 --- a/nodeadm/internal/kubelet/daemon.go +++ b/nodeadm/internal/kubelet/daemon.go @@ -35,7 +35,7 @@ func (k *kubelet) Configure(cfg *api.NodeConfig) error { if err := k.writeKubeconfig(cfg); err != nil { return err } - if err := k.writeImageCredentialProviderConfig(); err != nil { + if err := k.writeImageCredentialProviderConfig(cfg.Status.KubeletVersion); err != nil { return err } if err := writeClusterCaCert(cfg.Spec.Cluster.CertificateAuthority); err != nil { diff --git a/nodeadm/internal/kubelet/image-credential-provider.go b/nodeadm/internal/kubelet/image-credential-provider.go index ea14f63b6..5ed10a256 100644 --- a/nodeadm/internal/kubelet/image-credential-provider.go +++ b/nodeadm/internal/kubelet/image-credential-provider.go @@ -8,6 +8,8 @@ import ( "path/filepath" "time" + "golang.org/x/mod/semver" + "github.com/awslabs/amazon-eks-ami/nodeadm/internal/util" "go.uber.org/zap" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -30,7 +32,7 @@ const ( var imageCredentialProviderConfigPath = path.Join(imageCredentialProviderRoot, imageCredentialProviderConfig) -func (k *kubelet) writeImageCredentialProviderConfig() error { +func (k *kubelet) writeImageCredentialProviderConfig(kubeletVersion string) error { // fallback default for image credential provider binary if not overridden ecrCredentialProviderBinPath := path.Join(imageCredentialProviderRoot, "ecr-credential-provider") if binPath, set := os.LookupEnv(ecrCredentialProviderBinPathEnvironmentName); set { @@ -41,7 +43,7 @@ func (k *kubelet) writeImageCredentialProviderConfig() error { return err } - config, err := generateImageCredentialProviderConfig(ecrCredentialProviderBinPath) + config, err := generateImageCredentialProviderConfig(kubeletVersion, ecrCredentialProviderBinPath) if err != nil { return err } @@ -52,25 +54,34 @@ func (k *kubelet) writeImageCredentialProviderConfig() error { return util.WriteFileWithDir(imageCredentialProviderConfigPath, config, imageCredentialProviderPerm) } -func generateImageCredentialProviderConfig(ecrCredentialProviderBinPath string) ([]byte, error) { +func generateImageCredentialProviderConfig(kubeletVersion, ecrCredentialProviderBinPath string) ([]byte, error) { + ecrMatchImages := []string{ + "*.dkr.ecr.*.amazonaws.com", + "*.dkr-ecr.*.on.aws", + "*.dkr.ecr.*.amazonaws.com.cn", + "*.dkr-ecr.*.on.amazonwebservices.com.cn", + "*.dkr.ecr-fips.*.amazonaws.com", + "*.dkr-ecr-fips.*.on.aws", + "*.dkr.ecr.*.c2s.ic.gov", + "*.dkr.ecr.*.sc2s.sgov.gov", + "*.dkr.ecr.*.cloud.adc-e.uk", + "*.dkr.ecr.*.csp.hci.ic.gov", + "*.dkr.ecr.*.amazonaws.eu", + "public.ecr.aws", + } + if semver.Compare(kubeletVersion, "v1.32.0") >= 0 { + // currently only v1.32.0+ of ecr-credential-provider supports this + // https://github.com/kubernetes/cloud-provider-aws/pull/1332 + // it is safe to add for all versions since kubelet tries all providers + // and falls back to unauthenticated on failure, but matching it + // when it is known not to work adds unnecessary latency (albeit slight) + ecrMatchImages = append(ecrMatchImages, "ecr-public.aws.com") + } cfg := configv1.CredentialProviderConfig{ Providers: []configv1.CredentialProvider{ { - Name: filepath.Base(ecrCredentialProviderBinPath), - MatchImages: []string{ - "*.dkr.ecr.*.amazonaws.com", - "*.dkr-ecr.*.on.aws", - "*.dkr.ecr.*.amazonaws.com.cn", - "*.dkr-ecr.*.on.amazonwebservices.com.cn", - "*.dkr.ecr-fips.*.amazonaws.com", - "*.dkr-ecr-fips.*.on.aws", - "*.dkr.ecr.*.c2s.ic.gov", - "*.dkr.ecr.*.sc2s.sgov.gov", - "*.dkr.ecr.*.cloud.adc-e.uk", - "*.dkr.ecr.*.csp.hci.ic.gov", - "*.dkr.ecr.*.amazonaws.eu", - "public.ecr.aws", - }, + Name: filepath.Base(ecrCredentialProviderBinPath), + MatchImages: ecrMatchImages, APIVersion: "credentialprovider.kubelet.k8s.io/v1", DefaultCacheDuration: &metav1.Duration{Duration: 12 * time.Hour}, }, diff --git a/nodeadm/test/e2e/cases/image-credential-provider/expected-image-credential-provider-config-1.31.json b/nodeadm/test/e2e/cases/image-credential-provider/expected-image-credential-provider-config-1.31.json new file mode 100644 index 000000000..a4cab31e4 --- /dev/null +++ b/nodeadm/test/e2e/cases/image-credential-provider/expected-image-credential-provider-config-1.31.json @@ -0,0 +1,25 @@ +{ + "apiVersion": "kubelet.config.k8s.io/v1", + "kind": "CredentialProviderConfig", + "providers": [ + { + "name": "ecr-credential-provider", + "matchImages": [ + "*.dkr.ecr.*.amazonaws.com", + "*.dkr-ecr.*.on.aws", + "*.dkr.ecr.*.amazonaws.com.cn", + "*.dkr-ecr.*.on.amazonwebservices.com.cn", + "*.dkr.ecr-fips.*.amazonaws.com", + "*.dkr-ecr-fips.*.on.aws", + "*.dkr.ecr.*.c2s.ic.gov", + "*.dkr.ecr.*.sc2s.sgov.gov", + "*.dkr.ecr.*.cloud.adc-e.uk", + "*.dkr.ecr.*.csp.hci.ic.gov", + "*.dkr.ecr.*.amazonaws.eu", + "public.ecr.aws" + ], + "defaultCacheDuration": "12h0m0s", + "apiVersion": "credentialprovider.kubelet.k8s.io/v1" + } + ] +} \ No newline at end of file diff --git a/nodeadm/test/e2e/cases/image-credential-provider/expected-image-credential-provider-config.json b/nodeadm/test/e2e/cases/image-credential-provider/expected-image-credential-provider-config.json index a4cab31e4..8fac6a9c3 100644 --- a/nodeadm/test/e2e/cases/image-credential-provider/expected-image-credential-provider-config.json +++ b/nodeadm/test/e2e/cases/image-credential-provider/expected-image-credential-provider-config.json @@ -16,7 +16,8 @@ "*.dkr.ecr.*.cloud.adc-e.uk", "*.dkr.ecr.*.csp.hci.ic.gov", "*.dkr.ecr.*.amazonaws.eu", - "public.ecr.aws" + "public.ecr.aws", + "ecr-public.aws.com" ], "defaultCacheDuration": "12h0m0s", "apiVersion": "credentialprovider.kubelet.k8s.io/v1" diff --git a/nodeadm/test/e2e/cases/image-credential-provider/run.sh b/nodeadm/test/e2e/cases/image-credential-provider/run.sh index 2b77dbb26..86cf4cfe4 100755 --- a/nodeadm/test/e2e/cases/image-credential-provider/run.sh +++ b/nodeadm/test/e2e/cases/image-credential-provider/run.sh @@ -9,7 +9,13 @@ source /helpers.sh mock::aws wait::dbus-ready -mock::kubelet 1.32.0 +mock::kubelet 1.31.0 + +nodeadm init --skip run --config-source file://config.yaml + +assert::json-files-equal /etc/eks/image-credential-provider/config.json expected-image-credential-provider-config-1.31.json + +mock::kubelet 1.36.0 nodeadm init --skip run --config-source file://config.yaml