本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。
将工作负载从 Azure DevOps 管道部署到私有的 Amazon EKS
Mahendra Revanasiddappa,亚马逊 Web Services
摘要
此模式演示了如何实现从 Azure DevOps 管道到私有亚马逊 Elastic Kubernetes Service (Amazon EKS) 集群的持续集成和持续交付 (CI/CD)。它解决了组织所面临的关键挑战,这些组织正在通过过渡到 Amazon EKS 集群的私有 API 服务器终端节点来增强其安全态势。
公共端点将 Kubernetes API 服务器直接暴露在互联网上,从而形成了恶意行为者可能瞄准的更大的攻击面。切换到私有终端节点后,只能在客户的虚拟私有云 (VPC) 内访问集群的控制平面。
尽管将 Amazon EKS 集群过渡到私有 API 终端节点可以显著增强安全性,但它会给 Azure DevOps 等外部 CI/CD 平台带来连接挑战。只能从集群的 VPC 或对等网络中访问私有终端节点。因此,在 AWS 私有网络之外运行的标准微软托管的 Azure DevOps 代理无法直接访问 Kubernetes API 服务器。这打破了依赖于在这些代理上运行的 kubectl 或 Helm 等工具的典型部署工作流程,因为它们无法与集群建立连接。
为了克服这个问题,这种模式展示了一种有效的方法,即在私有 Amazon EKS 集群中使用自托管 Azure DevOps 代理。该解决方案提供了卓越的成本优化、运营效率和可扩展性,同时保留了安全要求。这种方法特别有利于寻求在不影响性能或安全性的前提下简化多云 DevOps 流程的企业。
先决条件和限制
先决条件
限制
架构
此模式会创建以下内容:
亚马逊 ECR 存储库 ——亚马逊弹性容器注册表 (Amazon ECR) Registry 存储库将 Docker 映像与 Azure DevOps 代理和部署的示例应用程序一起存储。
Azure DevOps 代理池-Azure DevOps 自托管代理池注册在私有 Amazon EKS 集群上运行的代理。
IAM 角色-Azure 服务连接的 AWS Identity and Access Management (IAM) 角色,用于为在私有 Amazon EKS 集群上运行的代理提供所需的访问权限。
Azure DevOps 服务连接-Azure DevOps 账户中的服务连接,用于使用 IAM 角色,为管道作业提供访问所需的访问权限 AWS 服务。
下图显示了在私有 Amazon EKS 集群上部署自托管 Azure DevOps 代理并在同一集群上部署示例应用程序的架构。
图表显示了以下工作流:
将自托管的 Azure DevOps 代理部署为在 Amazon EKS 集群中的部署。
Azure DevOps 代理使用个人访问令牌 (PAT) 进行身份验证,连接到 Azure DevOps 帐户上的代理池。
Azure Pipelines 使用 GitHub 存储库中的代码配置要部署的管道。
管道在工作流配置中配置的代理池中的代理上运行。Azure DevOps 代理通过不断轮询到 Azure DevOps 帐户来获取管道的作业信息。
Azure DevOps 代理在管道作业中构建 Docker 映像,并将该映像推送到 Amazon ECR 存储库。
Azure DevOps 代理将示例应用程序部署到名为的命名webapp
空间中的私有 Amazon EKS 集群上。
工具
其他工具
代码存储库
最佳实践
操作说明
Task | 描述 | 所需技能 |
---|
查找 Azure DevOps 组织指南。 | 登录你的 Azure DevOps 帐户,然后使用以下 URL 查找组织 GUID:https://dev.azure.com/{DevOps_Org_ID}/_apis/projectCollections?api-version=6.0 在网址中,{DevOps_org_ID} 替换为你的 Azure DevOps 组织 ID。 | AWS DevOps |
在中配置 IdP。 AWS 账户 | 要在中为 Azure 服务连接配置身份提供者 (IdP),请使用以下步骤: AWS 账户 登录并打开 IAM 控制台,网址为https://console.aws.amazon.com/iam/。 AWS Management Console 在左侧窗格中,选择身份提供商。 选择 Add Provider(添加提供程序)。 选择 OpenID Connect 作为提供者类型。 在提供者网址中,输入 Azure DevOps 发行者网址。Azure DevOps 的每个租户都有唯一的OrganizationGUID ,通常使用以下格式:https://vstoken.dev.azure.com/{OrganizationGUID} {OrganizationGUID} 替换为你的 Azure DevOps 组织 ID。 对于受众,请输入 api: //Azure ADToken 交易所。这是 Azure 的固定值 DevOps。 选择 Add Provider(添加提供程序)。 记下新创建的提供商的 ARN,供您在下一个任务中使用。
有关更多详细信息,请参阅如何 DevOps 使用 OpenID Connect AWS 从 Azure 联合到。 | AWS DevOps |
在中创建 IAM 策略 AWS 账户。 | 要创建 IAM 策略以向 Azure DevOps 管道使用的 IAM 角色提供所需权限,请使用以下步骤: 在 IAM 控制台的左侧窗格中,选择策略。 选择创建策略。 在 “指定权限” 中,在 “策略编辑器” 中,选择 JSON。将默认 JSON 策略替换为以下 JSON:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Statement1",
"Effect": "Allow",
"Action": [
"ecr:*",
"eks:DescribeCluster",
"eks:ListClusters"
],
"Resource": "*"
}
]
}
选择下一步。 在策略名称中,输入 IAM 策略的名称。此模式使用名称 ado- policy。 选择创建策略。
| AWS DevOps |
在中创建 IAM 角色 AWS 账户。 | 要在中为 Azure 服务连接配置 IAM 角色,请使用以下步骤: AWS 账户 在 IAM 控制台的左侧窗格中,选择角色。 选择创建角色。 对于可信实体类型,请选择 Web 身份。 从下拉列表中选择正确的 IdP。IdP 名称以开头。vstoken.dev.azure.com/{OrganizationGUID} 在 “受众” 下拉列表中,选择 api: //Azure ADToken Exchange。 要将此角色限制为仅一个服务连接,请添加一个条件。在 “条件” 下,选择 “添加条件”,在 “密钥” 中选择 vstoken.dev.azure.com/ {OrganizationGuid}: s ub。在条件中,选择StringEquals。对于 “值”,使用以下格式:sc://{OrganizationName}/{ProjectName}/{ServiceConnectionName} 。对于ServiceConnectionName ,请使用 aws-sc。您将在下一个任务中创建此服务连接。 选择下一步。 对于添加权限,请选择 ado- policy,这是您在之前的任务中创建的策略。 选择 “下一步”,在 “角色名称” 中输入 ado-role。对于选择可信实体,请使用以下信任策略:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::{account_id}:oidc-provider/vstoken.dev.azure.com/{OrganizationGUID}"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"vstoken.dev.azure.com/{OrganizationGUID}:aud": "api://AzureADTokenExchange",
"vstoken.dev.azure.com/{OrganizationGUID}:sub": "sc://{OrganizationName}/{ProjectName}/{ServiceConnectionName}"
}
}
}
]
}
在政策中,为以下占位符提供您的信息: {account_id} - AWS 账户 身份证
{OrganizationGUID} -Azure DevOps 组织指南
{OrganizationName} -Azure DevOps 组织名称
{ProjectName} -Azure DevOps 项目名称
{ServiceConnectionName} -Azure DevOps 服务连接名称。使用 aws-sc。您将在下一个任务中创建此服务连接。
| AWS DevOps |
在 Azure DevOps 帐户中创建服务连接。 | 要配置 Azure 服务连接,请使用以下步骤: 在你的 Azure DevOps 项目中,选择项目设置、服务连接。 选择 “新建服务连接”,将服务连接的类型选择为aws ,然后选择 “下一步”。 对于要代入的角色,请输入 IAM 角色 ad o-role 的 arn。您在之前的任务中创建了 ado- role 在中创建 IAM 角色。 AWS 账户 选中 “使用 OIDC” 复选框。 在服务连接名称中,在任务属性中输入 aws-sc。 选择保存。
有关更多详细信息,请参阅 Microsoft 文档中的创建服务连接。 | AWS DevOps |
将 IAM 角色添加到 Amazon EKS 配置文件。 | IAM 角色必须具有必要的权限才能在 Amazon EKS 集群上执行所需的操作。由于 IAM 角色是一个管道角色,因此 IAM 角色必须能够管理集群上几乎所有类型的资源。因此,system:masters 群组权限适用于此角色。 要在 Kubernetes aws-auth ConfigMap 中添加所需的配置,请使用以下代码: - groups:
- system:masters
rolearn: arn:aws:iam::{account_id}:role/ADO-role
username: ADO-role
{account_id} 用您的 AWS 账户 身份证替换。
有关更多信息,请参阅亚马逊 EKS 文档中的亚马逊 EKS 如何与 IAM 配合使用。 | AWS DevOps |
Task | 描述 | 所需技能 |
---|
创建自托管代理池。 | 要在 Azure DevOps 帐户中配置自托管代理池,请使用以下步骤: 登录到你的 Azure DevOps 帐户组织。 选择 Azure DevOps 组织。 选择你的 Azure DevOps 项目。 选择 Project settings (项目设置)。 选择代理池。 选择 “添加池”。 选择自托管。 在名称中,输入 eks-agent。 选中 “向所有管道授予访问权限” 复选框。 选择创建。
有关更多详细信息,请参阅 Microsoft 文档中的创建和管理代理池。 | |
Task | 描述 | 所需技能 |
---|
创建 Amazon ECR 存储库。 | 用于在私有 Amazon EKS 集群上部署 Azure DevOps 代理和示例应用程序 (webapp ) 的 Docker 映像必须存储在 Amazon ECR 存储库中。要创建 Amazon ECR 存储库,请使用以下步骤: 有关更多详细信息,请参阅 Amazon ECR 文档中的创建用于存储图像的 Amazon ECR 私有存储库。 | AWS DevOps |
创建一个 Dockerfile 来构建 Azure 代理 DevOps 。 | 创建一个 Dockerfile 来生成安装了 Azure DevOps 代理的 Docker 镜像。将以下内容存储在名为的文件中Dockerfile :
FROM ubuntu:22.04
ENV TARGETARCH="linux-x64"
RUN apt update && apt upgrade -y && apt install -y curl git jq libicu70 unzip wget
RUN curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
RUN unzip awscliv2.zip
RUN ./aws/install
RUN rm -rf aws awscliv2.zip
RUN curl -sSL https://get.docker.com/ | sh
RUN curl -sL https://aka.ms/InstallAzureCLIDeb | bash
RUN mkdir -p azp
WORKDIR /azp/
COPY ./start.sh ./
RUN chmod +x ./start.sh
RUN useradd -m -d /home/agent agent
RUN chown -R agent:agent /azp /home/agent
RUN groupadd -f docker
RUN usermod -aG docker agent
USER agent
ENTRYPOINT [ "./start.sh" ]
| AWS DevOps |
为 Azure DevOps 代理创建脚本。 | 要创建start.sh 脚本,请使用以下步骤: 转到微软文档中的创建和构建 Dockerfile 过程,然后滚动到步骤 5。将以下内容保存到 ~/azp-agent-in-docker/start.sh ,确保使用 Unix 样式 (LF) 行尾。 复制脚本的内容,并将其保存在与 Dockerfile 同一个目录下的文件start.sh 中。
| AWS DevOps |
使用 Azure DevOps 代理构建 Docker 镜像。 | 要创建 Docker 镜像来安装 Azure DevOps 代理,请使用你之前创建的 Dockerfile 来构建镜像。在存储 Dockerfile 的同一目录中,运行以下命令: aws ecr get-login-password --region region | docker login --username AWS --password-stdin aws_account_id.dkr.ecr.region.amazonaws.com
docker build --platform linux/amd64 -t ado-agent:latest .
docker tag ado-agent:latest aws_account_id.dkr.ecr.region.amazonaws.com/webapp:latest
docker push aws_account_id.dkr.ecr.region.amazonaws.com/webapp:latest
用您的 AWS 账户 ID 替换aws_account_id 和region ,然后 AWS 区域。 | AWS DevOps |
Task | 描述 | 所需技能 |
---|
生成 Azure 个人访问令牌。 | 在私有 Amazon EKS 集群上运行的代理需要个人访问令牌 (PAT),这样它才能使用 Azure DevOps 账户进行身份验证。要生成 PAT,请使用以下步骤: 使用你计划在 Azure DevOps 组织中使用的用户帐户登录 (https://dev.azure.com/{Your_Organization} )。
在您的主页上,打开您的用户设置,然后选择个人访问令牌。 选择 “新代币”。 输入令牌的名称。 选择 “显示所有示波器”。 在 “代理池” 中,选中 “读取并管理” 复选框。 选择创建。 要在私有 Amazon EKS 集群上创建密钥,请使用以下配置:
apiVersion: v1
kind: Secret
metadata:
name: azdevops-pat
namespace: default
type: Opaque
stringData:
AZP_TOKEN: <PAT Token>
将配置存储在名为的文件中ado-secret.yaml 。<PAT Token> 替换为您刚才创建的个人访问令牌。要创建密钥,请运行以下命令:
kubectl create -f ado-secret.yaml
有关更多详细信息,请参阅 Microsoft 文档中的使用个人访问令牌 (PAT) 注册代理。 | AWS DevOps |
使用 Kubernetes 清单文件进行代理部署。 | 要在私有 Amazon EKS 集群上部署 Azure DevOps 代理,请复制以下清单文件并将该文件存储为agent-deployment.yaml : apiVersion: apps/v1
kind: Deployment
metadata:
name: azure-pipelines-agent-eks
labels:
app: azure-pipelines-agent
spec:
replicas: 1
selector:
matchLabels:
app: azure-pipelines-agent
template:
metadata:
labels:
app: azure-pipelines-agent
spec:
containers:
- name: docker
image: docker:dind
securityContext:
privileged: true
volumeMounts:
- name: shared-workspace
mountPath: /workspace
- name: dind-storage
mountPath: /var/lib/docker
env:
- name: DOCKER_TLS_CERTDIR
value: ""
- name: azure-pipelines-agent
image: aws_account_id.dkr.ecr.region.amazonaws.com/webapp:latest
env:
- name: AZP_URL
value: "<Azure account URL>"
- name: AZP_POOL
value: "eks-agent"
- name: AZP_TOKEN
valueFrom:
secretKeyRef:
name: azdevops-pat
key: AZP_TOKEN
- name: AZP_AGENT_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: DOCKER_HOST
value: tcp://localhost:2375
volumeMounts:
- mountPath: /workspace
name: shared-workspace
volumes:
- name: dind-storage
emptyDir: {}
- name: shared-workspace
emptyDir: {}
将aws_account_id 和<Azure account URL> 替换为你的 AWS 账户 ID 和 Azure DevOps 帐户网址。 | AWS DevOps |
在私有 Amazon EKS 集群上部署代理。 | 要在私有 Amazon EKS 集群上部署 Azure DevOps 代理,请使用以下命令: kubectl create -f agent-deployment.tf
| AWS DevOps |
验证代理是否正在运行。 | 要验证 Azure DevOps 代理是否正在运行,请使用以下命令: kubectl get deploy azure-pipelines-agent-eks
预期输出应类似于以下内容:
NAME READY UP-TO-DATE AVAILABLE AGE
azure-pipelines-agent-eks 1/1 1 1 58s
确保READY 列已显示1/1 。 | AWS DevOps |
验证代理是否已在 Azure DevOps 代理池中注册。 | 要验证代理是否已部署在私有 Amazon EKS 集群上并已在代理池中注册eks-agent ,请使用以下步骤: 登录到你的 Azure DevOps 组织 (https://dev.azure.com/{Your_Organization} )。 选择 Project settings (项目设置)。 选择代理池。 选择 eks-agent 池,然后选中 “代理” 选项卡。
您应该看到列出的代理的状态为 “在线”,并且该代理的名称应以 azure-pipelines-agent-eks-* 开头。 | AWS DevOps |
Task | 描述 | 所需技能 |
---|
将示例应用程序存储库分支到您的 GitHub 账户。 | 将以下 AWS 示例存储库分支到您的 GitHub 账户: https://github.com/aws-samples/deploy-kubernetes-resources-to-amazon-eks-using-azure-devops | AWS DevOps |
创建管道。 | 要在你的 Azure DevOps 帐户中创建管道,请使用以下步骤: 使用你计划在 Azure DevOps 组织中使用的用户帐户登录 (https://dev.azure.com/{Your_Organization} )。 导航到您的项目和管道控制台。 选择 “新建管道”。 对于 “您的代码在哪里”,选择GitHub。 提供管道连接到您的 GitHub 账户所需的凭证 选择存储库 deploy-kubernetes-resources-to-amazon-eks-using-azure-devops。 在 “配置管道” 中,选择 “现有 Azure 管道 YAML 文件”。 在 “选择现有 YAML 文件” 中,为 Branch 选择 main,为路径选择 azure_p ipelines.yaml。 选择继续。 要查看您的管道 YAML,请将awsRegion 和awsEKSClusterName 的输入参数值替换为您的信息:
pool:
name: eks-agent
#pool: self-hosted # If you are running self-hosted Azure DevOps Agents
stages:
# Refering the pipeline template, input parameter that are not specified will be added with defaults
- template: ./pipeline_templates/main_template.yaml
parameters:
serviceConnectionName: aws-sc
awsRegion: <your region>
awsEKSClusterName: <name of your EKS cluster>
projectName: webapp
| AWS DevOps |
验证示例应用程序是否已部署。 | 管道完成后,通过检查 Amazon ECR 存储库和 Amazon EKS 集群,验证示例应用程序是否成功部署。 要验证 Amazon ECR 存储库中的项目,请使用以下步骤: 导航到 webapp Amazon ECR 存储库。 确认是否存在以下新构件:
例如,20250501.1-image 和 20250501.1-helm 。 要验证命名空间中私有 Amazon EKS 集群上的部署webapp ,请使用以下命令: kubectl get deploy -n webapp
预期的输出如下所示:
NAME READY UP-TO-DATE AVAILABLE
webapp 1/1 1 1
注意:如果这是您首次运行管道,则可能需要对服务连接和代理池进行授权。在 Azure DevOps 管道界面中查找权限请求,然后批准它们以继续。 | AWS DevOps |
故障排除
事务 | 解决方案 |
---|
当 Amazon ECR 存储库名称不匹配时,管道失败 webapp | 示例应用程序希望 Amazon ECR 存储库名称与中的projectName: webapp azure_pipeline.yml 参数相匹配。 要解决此问题,请将您的 Amazon ECR 存储库重命名为webapp ,或更新以下内容: |
错误:无法访问 Kubernetes 集群:服务器已要求客户端提供凭据 | 如果您在 Azure 管道的 “提取并部署 Helm Chart” 步骤中遇到此错误,则根本原因通常源于 Amazon EKS 集群中的 IAM 角色配置不正确aws-auth ConfigMap 。 要解决此问题,请检查以下内容: |
相关资源
AWS 博客
AWS 服务 文档
微软文档