如何在Kubernetes中拉取外部亚马逊ECR私有镜像?
这个场景我碰到过好多次了,其实Kubernetes本身就有原生的方案来解决跨AWS账户拉取ECR镜像的问题,不需要依赖Rancher的专用容器,下面给你拆解两种常用的方法:
方法一:手动创建镜像拉取Secret(适合快速验证或小型集群)
ECR镜像拉取需要AWS临时凭证,我们可以把这些凭证封装成Kubernetes的docker-registry类型Secret,让Pod拉取镜像时使用:
准备外部AWS账户的权限
首先在目标ECR所在的AWS账户中,创建一个IAM用户(或复用现有角色),给它分配拉取ECR镜像所需的权限:ecr:GetDownloadUrlForLayerecr:BatchGetImageecr:BatchCheckLayerAvailabilityecr:GetAuthorizationToken
保存这个IAM用户的Access Key ID和Secret Access Key。
生成Kubernetes Secret
用AWS CLI获取目标ECR的临时登录凭证(注意先配置外部账户的AWS CLI profile),然后创建Secret:# 先配置外部账户的profile(如果没配置过) aws configure --profile external-ecr-account # 创建Secret kubectl create secret docker-registry ecr-external \ --docker-server=<外部ECR的地址,格式:123456789012.dkr.ecr.us-east-1.amazonaws.com> \ --docker-username=AWS \ --docker-password=$(aws ecr get-login-password --region <你的区域> --profile external-ecr-account) \ --docker-email=any-email@example.com这里
docker-username固定为AWS,邮箱可以随便填,不影响功能。在Pod/Deployment中引用Secret
在你的Deployment或Pod定义里添加imagePullSecrets字段,指定刚才创建的Secret:apiVersion: apps/v1 kind: Deployment metadata: name: my-external-app spec: replicas: 1 selector: matchLabels: app: my-external-app template: metadata: labels: app: my-external-app spec: imagePullSecrets: - name: ecr-external containers: - name: app-container image: <外部ECR地址>/your-image:latest注意:ECR的临时凭证有效期是12小时,所以这个Secret需要定期刷新。你可以用Kubernetes CronJob写个脚本自动更新,比如每11小时执行一次更新命令。
方法二:用IRSA自动获取凭证(适合EKS集群,更安全)
如果你的Kubernetes集群是AWS EKS,推荐用IAM Roles for Service Accounts (IRSA),不需要手动管理Secret,Pod会自动获取临时凭证,而且权限更细粒度:
在外部AWS账户创建信任角色
在目标ECR所在的账户中,创建一个IAM角色,信任策略允许你的EKS集群的OIDC提供商访问。信任策略示例:{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Federated": "arn:aws:iam::<你的EKS账户ID>:oidc-provider/oidc.eks.<区域>.amazonaws.com/id/<你的EKS集群OIDC ID>" }, "Action": "sts:AssumeRoleWithWebIdentity", "Condition": { "StringEquals": { "oidc.eks.<区域>.amazonaws.com/id/<你的EKS集群OIDC ID>:sub": "system:serviceaccount:<你的命名空间>:<要创建的SA名称>" } } } ] }给这个角色添加ECR拉取的权限(和方法一的权限一样)。
在EKS集群创建ServiceAccount
回到你的EKS集群,创建一个ServiceAccount,关联刚才在外部账户创建的IAM角色ARN:apiVersion: v1 kind: ServiceAccount metadata: name: external-ecr-sa namespace: default annotations: eks.amazonaws.com/role-arn: arn:aws:iam::<外部账户ID>:role/<外部账户的角色名称>Pod使用该ServiceAccount
在Deployment中指定这个ServiceAccount,Pod就会自动获取外部账户的临时凭证,直接拉取ECR镜像,不需要配置imagePullSecrets:apiVersion: apps/v1 kind: Deployment metadata: name: my-irsa-app spec: replicas: 1 selector: matchLabels: app: my-irsa-app template: metadata: labels: app: my-irsa-app spec: serviceAccountName: external-ecr-sa containers: - name: app-container image: <外部ECR地址>/your-image:latest
这种方法完全不需要手动管理凭证,AWS会自动刷新临时凭证,安全性更高,是生产环境的推荐方案。
内容的提问来源于stack exchange,提问作者Fred Mériot

