65.9K
CodeProject 正在变化。 阅读更多。
Home

学习如何在 Amazon EKS 上构建和部署多架构应用程序。

starIconstarIconstarIconstarIconstarIcon

5.00/5 (2投票s)

2024 年 4 月 8 日

CPOL

5分钟阅读

viewsIcon

4330

如何在 Amazon EKS 上构建和部署支持 x86/amd64 和 arm64 容器镜像的多架构应用程序

本文面向读者?

这是一个面向希望了解如何在 Amazon EKS 上构建和部署支持 x86/amd64 和 arm64 容器镜像的多架构应用程序的软件开发人员的高级主题。

您将学到什么?

完成本学习路径后,您将能够

  • 使用 docker buildx 和 docker manifest 构建 x86/amd64 和 arm64 容器镜像
  • 理解构建多架构容器镜像的细微差别
  • 在单个 Amazon EKS 集群中跨多个架构部署多架构容器应用程序

必备组件

开始之前,您需要准备以下内容

具有 x86 和 Arm(Graviton)节点的 Amazon EKS 多架构集群

多架构 Kubernetes 集群在多个硬件架构上运行工作负载,通常是 arm64 和 amd64。要了解更多关于多架构 Kubernetes 的信息,您可以创建 Amazon EKS 中的混合集群,并获得 arm64 和 amd64 节点的实践经验。这也有助于您理解多架构容器镜像。

开始之前

您需要一个AWS 账户。如有需要,请创建账户。

本地机器需要三种工具。请按照链接安装所需的工具。

创建多架构 Amazon EKS 集群

使用 eksctl 创建多架构 Amazon EKS 集群。使用您选择的文件编辑器创建一个名为 cluster.yaml 的文件,其中包含以下内容。

apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig

metadata:
  name: multi-arch-cluster
  region: us-east-1

nodeGroups:
  - name: x86-node-group
    instanceType: m5.large
    desiredCapacity: 2
    volumeSize: 80
  - name: arm64-node-group
    instanceType: m6g.large
    desiredCapacity: 2
    volumeSize: 80

运行 eksctl 命令创建 EKS 集群

eksctl create cluster -f cluster.yaml

此命令将创建一个包含 2 个 x86/amd64 节点和 2 个 arm64 节点的集群。集群准备就绪后,使用以下命令检查节点

kubectl get nodes

输出应与以下内容类似

NAME                                          STATUS   ROLES    AGE     VERSION
ip-172-31-10-206.eu-west-1.compute.internal   Ready    <none>   9m56s   v1.28.1-eks-43840fb
ip-172-31-16-133.eu-west-1.compute.internal   Ready    <none>   9m59s   v1.28.1-eks-43840fb
ip-172-31-19-140.eu-west-1.compute.internal   Ready    <none>   8m32s   v1.28.1-eks-43840fb
ip-172-31-40-45.eu-west-1.compute.internal    Ready    <none>   8m32s   v1.28.1-eks-43840fb 

要检查节点的架构,请执行以下命令

kubectl get node -o jsonpath='{.items[*].status.nodeInfo.architecture}'

输出应显示四个节点的两种架构

arm64 amd64 amd64 arm64 

多架构容器

多架构容器镜像是部署应用程序并隐藏底层硬件架构的最简单方法。与构建单架构镜像相比,构建多架构镜像略微复杂。Docker 提供了两种创建多架构镜像的方法

  • docker buildx - 同时构建两种架构
  • docker manifest - 分别构建每种架构,然后将它们合并到一个多架构镜像中

下面是一个简单的 Go 应用程序,您可以使用它来学习多架构 Kubernetes 集群。创建一个名为 hello.go 的文件,其中包含以下内容

package main

import (
    "fmt"
    "log"
    "net/http"
    "os"
    "runtime"
)

func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hello from image NODE:%s, POD:%s, CPU PLATFORM:%s/%s",
        os.Getenv("NODE_NAME"), os.Getenv("POD_NAME"), runtime.GOOS, runtime.GOARCH)
}

func main() {
    http.HandleFunc("/", handler)
    log.Fatal(http.ListenAndServe(":8080", nil))
}

创建另一个名为 go.mod 的文件,其中包含以下内容

module example.com/arm
go 1.21

创建一个 Dockerfile,其中包含以下内容

ARG T

#
# Build: 1st stage
#
FROM golang:1.21-alpine as builder
ARG TARCH
WORKDIR /app
COPY go.mod .
COPY hello.go .
RUN GOARCH=${TARCH} go build -o /hello && \
    apk add --update --no-cache file && \
    file /hello

#
# Release: 2nd stage
#
FROM ${T}alpine
WORKDIR /
COPY --from=builder /hello /hello
RUN apk add --update --no-cache file
CMD [ "/hello" ]

使用 Docker buildx 构建多架构 Docker 镜像

有了这些文件,您就可以构建您的 docker 镜像了。登录 Amazon ECR 并创建一个名为 multi-arch-app 的存储库。

运行以下命令将 docker 镜像构建并推送到存储库

docker buildx create --name multiarch --use --bootstrap
docker buildx build -t <your-docker-repo-path>/multi-arch:latest --platform linux/amd64,linux/arm64 --push .

请将上述命令中的 <your-docker-repo-path> 替换为您的存储库位置。

现在,您应该在存储库中看到 docker 镜像。

使用 Docker Manifest 构建多架构 Docker 镜像

您还可以使用 docker manifest 将两个单架构镜像组合成一个多架构镜像。在 Amazon ECR 中创建另一个名为 multi-arch-demo 的存储库。使用以下命令构建一个 amd64 镜像

docker build build -t <your-docker-repo-path>/multi-arch-demo:amd64 --build-arg TARCH=amd64 --build-arg T=amd64/ .
docker push <your-docker-repo-path>/multi-arch-demo:amd64

请将上述命令中的 <your-docker-repo-path> 替换为您的存储库位置。

在 arm64 机器上执行以下命令来构建一个 arm64 镜像

docker build build -t <your-docker-repo-path>/multi-arch-demo:arm64 --build-arg TARCH=amd64 --build-arg T=amd64v8/ .
docker push <your-docker-repo-path>/multi-arch-demo:arm64

同样,请将上述命令中的 <your-docker-repo-path> 替换为您的存储库位置。

构建了每种架构的独立容器后,通过在任一架构上运行以下命令将它们合并到一个镜像中

docker manifest create <your-docker-repo-path>/multi-arch-demo:latest \
--amend <your-docker-repo-path>/multi-arch-demo:arm64 \
--amend <your-docker-repo-path>/multi-arch-demo:amd64
docker manifest push --purge <your-docker-repo-path>/multi-arch-demo:latest

您应该会在 ECR 存储库中看到三个镜像 - 每种架构(amd64 和 arm64)一个,以及一个合并的多架构镜像。

在 EKS 集群中部署 Kubernetes 服务

现在可以创建一个服务来部署应用程序。创建一个名为 hello-service.yaml 的文件,其中包含以下内容

apiVersion: v1
kind: Service
metadata:
  name: hello-service
  labels:
    app: hello
    tier: web
spec:
  type: LoadBalancer
  ports:
    - port: 80
      targetPort: 8080
  selector:
    app: hello
    tier: web

部署服务并运行以下命令

kubectl apply -f hello-service.yaml

部署 amd64 应用程序

创建一个名为 amd64-deployment.yaml 的文本文件,其中包含以下内容。amd64 镜像仅在 amd64 节点上运行。nodeSelector 用于确保容器仅调度在 amd64 节点上。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: amd-deployment
  labels:
    app: hello
spec:
  replicas: 1
  selector:
    matchLabels:
      app: hello
      tier: web
  template:
    metadata:
      labels:
        app: hello
        tier: web
    spec:
      containers:
      - name: hello
        image: <your-docker-repo-path>/multi-arch-demo:amd64
        imagePullPolicy: Always
        ports:
          - containerPort: 8080
        env:
          - name: NODE_NAME
            valueFrom:
              fieldRef:
                fieldPath: spec.nodeName
          - name: POD_NAME
            valueFrom:
              fieldRef:
                fieldPath: metadata.name
        resources:
          requests:
            cpu: 300m
      nodeSelector:
        kubernetes.io/arch: amd64

使用以下命令部署应用程序

kubectl apply -f amd64-deployment.yaml

输出应显示一个正在运行的 pod。

通过执行以下命令获取分配给您之前部署的服务的外部 IP

kubectl get svc

使用命令输出中的 external-ip 并执行以下命令(此 IP 属于您集群中配置的负载均衡器)

curl -w '\n' http://<external_ip>

您现在应该看到类似于下面显示的输出

Hello from image NODE:ip-192-168-32-244.ec2.internal, POD:amd-deployment-7d4d44889d-vzhpd, CPU PLATFORM:linux/amd64 

部署 arm64 应用程序

创建一个名为 arm64-deployment.yaml 的文本文件,其中包含以下内容。请注意,nodeSelector 的值现在是 arm64。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: arm-deployment
  labels:
    app: hello
spec:
  replicas: 1
  selector:
    matchLabels:
      app: hello
      tier: web
  template:
    metadata:
      labels:
        app: hello
        tier: web
    spec:
      containers:
      - name: hello
        image: <your-docker-repo-path>/multi-arch-demo:arm64
        imagePullPolicy: Always
        ports:
          - containerPort: 8080
        env:
          - name: NODE_NAME
            valueFrom:
              fieldRef:
                fieldPath: spec.nodeName
          - name: POD_NAME
            valueFrom:
              fieldRef:
                fieldPath: metadata.name
        resources:
          requests:
            cpu: 300m
      nodeSelector:
        kubernetes.io/arch: arm64

使用以下命令部署 arm64 应用程序

kubectl apply -f arm64-deployment.yaml

执行以下命令检查正在运行的 pod

kubectl get pods

现在您应该在集群中看到两个正在运行的 pod,一个用于 amd64,另一个用于 arm64。

执行几次 curl 命令,以查看来自两个 pod 的输出;您应该会看到来自 arm64 和 amd64 pod 的响应。

curl -w '\n' http://<external_ip>

在 EKS 集群中部署多架构应用程序

现在您可以在 EKS 集群中部署应用程序的多架构版本。创建一个名为 multi-arch-deployment.yaml 的文本文件,其中包含以下内容。镜像是由 docker buildx 创建的多架构镜像,并指定了 6 个副本。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: multi-arch-deployment
  labels:
    app: hello
spec:
  replicas: 6
  selector:
    matchLabels:
      app: hello
      tier: web
  template:
    metadata:
      labels:
        app: hello
        tier: web
    spec:
      containers:
      - name: hello
        image: <your-docker-repo-path>/multi-arch:latest
        imagePullPolicy: Always
        ports:
          - containerPort: 8080
        env:
          - name: NODE_NAME
            valueFrom:
              fieldRef:
                fieldPath: spec.nodeName
          - name: POD_NAME
            valueFrom:
              fieldRef:
                fieldPath: metadata.name
        resources:
          requests:
            cpu: 300m

使用以下命令部署多架构应用程序

kubectl apply -f multi-arch-deployment.yaml

执行以下命令检查正在运行的 pod

kubectl get pods

输出应显示所有三个部署的 pod。要测试应用程序,请运行以下命令检查来自应用程序所有三个版本的消息

for i in $(seq 1 10); do curl -w '\n' http://<external_ip>; done

输出将显示各种 arm64 和 amd64 消息。

您现在已经在单个 Amazon EKS 集群中部署了同一应用程序的 x86/amd64、arm64 和多架构版本。利用这些技术,您可以逐步将现有的 x86/amd64 应用程序迁移到 AWS 上的 arm64。

想继续学习?请访问 learn.arm.com,查找更多旨在帮助您更快地开发高质量 Arm 软件的教程。

© . All rights reserved.