如何在GitLab CI/CD流水线中无需自定义镜像实现kubectl访问AWS EKS集群的认证及替代方案
Great question! I’ve dealt with this exact GitLab CI + EKS authentication headache before, so let’s walk through your options to skip custom images and explore alternatives to kubectl.
You don’t need to roll your own image to use kubectl with EKS in GitLab CI. Here are two reliable, low-effort approaches:
Option 1: Use AWS CLI v2 + Kubectl’s Built-In AWS Credential Support
Starting with Kubernetes 1.21, kubectl natively supports using the AWS CLI to fetch EKS authentication tokens—no separate aws-iam-authenticator binary required. You can use official public images and install the missing tools on the fly:
- Pick a base image: Use
amazon/aws-cli:latest(has AWS CLI pre-installed) orbitnami/kubectl:latest(has kubectl pre-installed). - Configure AWS credentials: For security, use GitLab’s AWS OIDC integration to let the CI job assume an IAM role without hardcoding access keys. Alternatively, set
AWS_ACCESS_KEY_IDandAWS_SECRET_ACCESS_KEYas masked GitLab variables. - Generate a dynamic kubeconfig with
aws eks update-kubeconfig—this command creates a config that tells kubectl to use the AWS CLI for token retrieval.
Example GitLab CI job:
eks-cluster-ops: image: amazon/aws-cli:latest variables: AWS_DEFAULT_REGION: us-east-1 EKS_CLUSTER_NAME: my-production-cluster before_script: # Install kubectl in the AWS CLI image - curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" - chmod +x kubectl - mv kubectl /usr/local/bin/ # Assume IAM role via GitLab OIDC (skip if using static credentials) - aws sts assume-role-with-web-identity --role-arn $AWS_ROLE_ARN --role-session-name gitlab-ci-runner --web-identity-token $CI_JOB_JWT_V2 > /tmp/creds.json - export AWS_ACCESS_KEY_ID=$(jq -r .Credentials.AccessKeyId /tmp/creds.json) - export AWS_SECRET_ACCESS_KEY=$(jq -r .Credentials.SecretAccessKey /tmp/creds.json) - export AWS_SESSION_TOKEN=$(jq -r .Credentials.SessionToken /tmp/creds.json) # Generate kubeconfig - aws eks update-kubeconfig --name $EKS_CLUSTER_NAME script: - kubectl get nodes - kubectl apply -f ./k8s-manifests/
Option 2: Use the Official eksctl Public Image
The weaveworks/eksctl:latest image comes pre-loaded with eksctl, kubectl, and the AWS CLI—everything you need for EKS operations. No extra installation steps required:
Example GitLab CI job:
eks-manage: image: weaveworks/eksctl:latest variables: AWS_DEFAULT_REGION: us-east-1 EKS_CLUSTER_NAME: my-production-cluster before_script: # Configure AWS credentials (OIDC or static keys) - aws eks update-kubeconfig --name $EKS_CLUSTER_NAME script: - kubectl get pods --all-namespaces - eksctl scale nodegroup --cluster $EKS_CLUSTER_NAME --name my-node-group --nodes 3
If you want to avoid kubectl entirely, here are two approaches that fit well with your existing Terraform-based pipeline:
Option 1: Extend Terraform with the Kubernetes Provider
Since you’re already using Terraform to deploy EKS, you can add the Kubernetes provider to your Terraform config to manage cluster resources directly. This keeps all infrastructure and application deployment logic in one place, with Terraform’s state tracking to avoid drift.
Example Terraform snippet:
# Fetch EKS cluster details (assuming you already have this in your config) data "aws_eks_cluster" "my_cluster" { name = "my-production-cluster" } # Configure Kubernetes provider to authenticate via AWS CLI provider "kubernetes" { host = data.aws_eks_cluster.my_cluster.endpoint cluster_ca_certificate = base64decode(data.aws_eks_cluster.my_cluster.certificate_authority.0.data) exec { api_version = "client.authentication.k8s.io/v1beta1" command = "aws" args = [ "eks", "get-token", "--cluster-name", data.aws_eks_cluster.my_cluster.name, ] } } # Deploy a sample namespace and deployment resource "kubernetes_namespace" "app" { metadata { name = "my-app" } } resource "kubernetes_deployment" "app" { metadata { name = "my-nginx-app" namespace = kubernetes_namespace.app.metadata[0].name } spec { replicas = 2 selector { match_labels = { app = "nginx" } } template { metadata { labels = { app = "nginx" } } spec { container { image = "nginx:stable" name = "nginx" port { container_port = 80 } } } } } }
Just run terraform apply in your existing Terraform CI job to deploy cluster resources—no kubectl needed.
Option 2: Adopt a GitOps Tool (Argo CD/Flux CD)
For continuous deployment, deploy a GitOps tool like Argo CD or Flux CD to your EKS cluster. Then, your GitLab CI pipeline only needs to push updated resource manifests to a Git repository; the GitOps tool will automatically sync those changes to the cluster.
Your GitLab CI job can be as simple as:
gitops-push: image: alpine/git:latest script: - git add ./k8s-manifests/ - git commit -m "Update app version to v1.2.3" - git push origin main
The GitOps tool will detect the new commit and apply the changes to EKS, eliminating the need for kubectl in your CI pipeline entirely.
内容的提问来源于stack exchange,提问作者Quenten Schoonderwoerd

