AMI Builder Pipeline

Triển khai AMI Builder Pipeline

Ở phần này, chúng ta sẽ tiến hành xây dựng một AMI Pipeline thông qua EC2 Image Builder.

EC2 Image Builder là dịch vụ giúp chúng ta đơn giản hoá các tác vụ từ khởi tạo, bảo trì, kiểm thử và phân phối các Linux/Windows Images.

  • Có thể dùng cho AMI của EC2, container image trên Amazon ECR, cũng như VM image cho môi trường on-premises.
  • Giảm thiểu thời gian và công sức thực hiện các tác vụ lặp lại.

ami-pipeline-architecture

Sau khi hoàn thành phần này, chúng ta sẽ có thể

  • Tự xây dựng được một AMI Pipeline.
  • Tự tạo ra các AMI mới chứa các bản vá lỗi mới nhất.
  • Sẵn sàng thay thế các AMI cũ và triển khai cho môi trường ứng dụng hiện tại.

CloudFormation Stack

Để tiến hành triển khai hạ tầng, chúng ta sẽ sử dụng dịch vụ AWS CloudFormation thông qua AWS Console hoặc AWS CLI.

Thành PhầnGiá Trị (Bắt buộc)
Stack Namepattern3-pipeline
Templatepattern3-pipeline.yml - tải ở mục Template bên dưới
BaselineVpcStackpattern3-base

Bạn hãy tải template ở đây:

Template nhận các tham số sau:

Tham sốMặc địnhÝ nghĩa
BaselineVpcStack(bắt buộc)Tên Stack của phần Hạ tầng Cơ bản, dùng để lấy VPC và Private Subnet
MasterAMI/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-x86_64SSM Public Parameter trỏ đến AMI Amazon Linux 2023 mới nhất
Ver1.0.0Phiên bản của Component và Image Recipe
BuildInstanceTypet3.mediumLoại instance dùng để build AMI
EnableInspectorScanningfalseBật quét lỗ hổng bằng Amazon Inspector cho AMI đầu ra

AWS CLI

Sau đây là các bước khởi tạo thông qua AWS CLI:

  1. Khởi tạo CloudFormation Stack.
    aws cloudformation create-stack --stack-name pattern3-pipeline --template-body file://pattern3-pipeline.yml --parameters ParameterKey=BaselineVpcStack,ParameterValue=pattern3-base --capabilities CAPABILITY_IAM --region ap-southeast-2
    

cloudformation-cli-create-stack

  1. Chờ Stack khởi tạo xong. Bước này khá nhanh, khoảng 1 đến 2 phút, vì chúng ta chỉ đang tạo định nghĩa của pipeline chứ chưa build AMI.

    aws cloudformation wait stack-create-complete --stack-name pattern3-pipeline --region ap-southeast-2
    
  2. Xác nhận CloudFormation Stack đã khởi tạo hoàn tất với StackStatus là CREATE_COMPLETE.

    aws cloudformation describe-stacks --stack-name pattern3-pipeline --region ap-southeast-2 --query "Stacks[0].StackStatus" --output text
    

cloudformation-cli-create-stack

  1. Ghi chú lại các giá trị tại Output, đặc biệt là Pattern3ImagePipeline (ARN của pipeline) và Pattern3ParentImageId.
    aws cloudformation describe-stacks --stack-name pattern3-pipeline --region ap-southeast-2 --query "Stacks[0].Outputs" --output table
    

cloudformation-describe-stack

Bạn có thể kiểm tra AMI Amazon Linux 2023 nào đang được dùng làm Parent Image bằng lệnh sau. Giá trị này phải khớp với Pattern3ParentImageId ở Output:

aws ssm get-parameter --name /aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-x86_64 --region ap-southeast-2 --query "Parameter.Value" --output text
cloudformation-describe-stack

Nếu bạn đã triển khai bằng CloudFormation, có thể bỏ qua các mục thủ công bên dưới và đi thẳng tới Thực thi Builder Pipeline.

Xây dựng thủ công từ Console

Phần này dành cho bạn muốn hiểu rõ từng thành phần của một AMI Pipeline. Chúng ta sẽ lần lượt thực hiện các bước sau đây:

  1. Tạo một S3 bucket cho tác vụ logging.
  2. Tạo một IAM Role dành cho EC2 Image Builder.
  3. Tạo một Security Group cho build instance.
  4. Tạo một Image Builder Component.
  5. Tạo một Image Builder Recipe.
  6. Tạo một Infrastructure Configuration.
  7. Tạo một Image Builder Pipeline.

Tạo S3 Bucket

Bởi tính chất của dịch vụ S3, khi đặt tên cho S3 Bucket, chúng ta cần phải tuân theo một số quy tắc được đặc tả tại URL sau.

  1. Tạo ra một chuỗi UUID đặc thù với kí tự in thường.
uuidgen | awk -F- '{print tolower($1$2$3)}'
([guid]::NewGuid().ToString('N')).Substring(0,12).ToLower()

s3-uuid

  1. Tạo S3 Bucket với tên là tổ hợp giữa chuỗi pattern3-logging và chuỗi UUID trên, rồi chặn toàn bộ truy cập public. Bucket này chỉ chứa log nội bộ nên không có lý do gì để mở ra Internet.
BUCKET="pattern3-logging-$(uuidgen | awk -F- '{print tolower($1$2$3)}')"
echo "Bucket: $BUCKET"

aws s3 mb "s3://${BUCKET}" --region ap-southeast-2

aws s3api put-public-access-block --bucket "$BUCKET" --public-access-block-configuration "BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true" --region ap-southeast-2
$BUCKET = "pattern3-logging-" + ([guid]::NewGuid().ToString('N')).Substring(0,12).ToLower()
Write-Output "Bucket: $BUCKET"

aws s3 mb "s3://$BUCKET" --region ap-southeast-2

aws s3api put-public-access-block --bucket $BUCKET --public-access-block-configuration "BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true" --region ap-southeast-2

s3-create

Hãy ghi lại tên bucket, bạn sẽ cần nó ở bước tạo IAM Role và bước cấu hình logging cho pipeline.

Chi tiết về việc khởi tạo S3 bucket có tại Creating a bucket.

Tạo IAM Role

IAM Role này sẽ được sử dụng cho EC2 Image Builder với vai trò là một instance profile cho EC2 instance được khởi tạo tạm thời. EC2 instance này sẽ thực hiện tác vụ OS Patching.

Sau đây là quá trình tạo ra một IAM Role:

  1. Đăng nhập vào AWS Console và truy cập đến dịch vụ IAM theo đường dẫn - https://console.aws.amazon.com/iam/.
  2. Ở thanh điều hướng bên tay trái, chọn Roles và nhấn nút Create role.

iam-roles

  1. Ở màn hình Select trusted entity, chọn AWS service và chọn Use case là EC2, sau đó nhấn Next.

iam-create-role

  1. Ở màn hình Add permissions, tìm và chọn lần lượt các policy dưới đây:
    1. EC2InstanceProfileForImageBuilder
    2. AmazonSSMManagedInstanceCore
  2. Nhấn Next để sang màn hình Name, review, and create.
  3. Điền tên pattern3-recipe-instance-role cùng với miêu tả cụ thể.

iam-create-role-review

  1. Tiến hành tạo bằng cách nhấn Create role.
  2. Sau khi tạo thành công, trong danh sách các IAM roles, chọn pattern3-recipe-instance-role.
  3. Ở tab Permissions, chọn Add permissions và chọn Create inline policy.

iam-role-add-inline-policy

  1. Chuyển sang chế độ JSON và dùng đặc tả sau. Thay thế <S3_BUCKET_NAME> bằng tên S3 Bucket ở bước trước.
{
   "Version": "2012-10-17",
   "Statement": [
      {
         "Sid": "WriteBuildLogs",
         "Effect": "Allow",
         "Action": "s3:PutObject",
         "Resource": "arn:aws:s3:::<S3_BUCKET_NAME>/*"
      },
      {
         "Sid": "DescribeBucket",
         "Effect": "Allow",
         "Action": [
            "s3:GetBucketLocation",
            "s3:ListBucket"
         ],
         "Resource": "arn:aws:s3:::<S3_BUCKET_NAME>"
      }
   ]
}

iam-policy-editor

  1. Nhấn Next.
  2. Điền tên policy và nhấn Create policy để hoàn tất.

iam-role-inline-policy-summary

Hãy chú ý phạm vi quyền ở đặc tả trên. Build instance chỉ cần ghi log lên đúng một bucket, nên policy chỉ mở s3:PutObject trên bucket đó. Tránh dùng "Action": "s3:*" hay gán managed policy AmazonS3FullAccess, vì như vậy là cấp quyền rộng hơn nhu cầu thực tế.

Tạo Security Group

Chúng ta sẽ cần một EC2 Security Group cho EC2 instance tạm thời. Security Group không cần bất kỳ một Inbound Rule nào, tuy nhiên cần đảm bảo Outbound Rule mặc định để build instance có thể truy cập Internet qua NAT Gateway nhằm tải các bản vá.

  1. Truy cập vào dịch vụ Amazon EC2.
  2. Ở thanh điều hướng bên tay trái, chọn Security Groups.

ec2-security-groups

  1. Nhấn chọn Create security group.
  2. Ở phần thông tin cơ bản, điền lần lượt tên pattern3-pipeline-instance-security-group và miêu tả.
  3. Ở phần VPC, chọn VPC được tạo bởi Stack pattern3-base.
  4. Đối với Inbound Rule và Outbound Rule, giữ nguyên mặc định và không thêm bất kỳ giá trị nào.
  5. Nhấn Create security group để khởi tạo.

ec2-create-security-group ec2-create-security-group

Tạo một Builder Component

Chúng ta sẽ tiến hành tạo một Component của dịch vụ EC2 Image Builder.

  1. Truy cập vào dịch vụ EC2 Image Builder.
  2. Tại thanh điều hướng bên tay trái, chọn Components.
  3. Nhấn nút Create component.
  4. Tiến hành chọn các giá trị như sau:
    1. Image Operating System (OS): Linux.
    2. Compatible OS versions: Amazon Linux 2023.
    3. Component name: pattern3-pipeline-ConfigureOSComponent.
    4. Component version: 1.0.0.
    5. Description: Component to update the OS with latest package versions.

ec2-image-builder-create-component-details

Ảnh minh hoạ có thể hiển thị Amazon Linux 2. Bạn hãy chọn Amazon Linux 2023, vì Amazon Linux 2 đã kết thúc hỗ trợ.

  1. Ở phần Definition document, chọn Define document content.
  2. Sao chép và điền đặc tả sau:
    name: ConfigureOS
    description: Update the operating system to the latest available packages
    schemaVersion: 1.0
    phases:
      - name: build
        steps:
          - name: UpdateOS
            action: UpdateOS
    

ec2-image-builder-create-component-definition-document

  1. Nhấn nút Create component để tiến hành khởi tạo.

ec2-image-builder-components

Ở phần thực hành này, chúng ta chỉ đơn giản đặc tả với hành động UpdateOS nhằm cập nhật toàn bộ package của hệ điều hành. Trên Amazon Linux 2023, UpdateOS sẽ chạy dnf thay vì yum như trên Amazon Linux 2, nhưng đặc tả component thì không cần thay đổi. Bạn có thể tham khảo thêm các action module khác tại Action modules reference.

Tạo một Builder Recipe

Trước khi định nghĩa Builder Pipeline, chúng ta cần phải có một Builder Recipe.

  1. Truy cập vào dịch vụ EC2 Image Builder.
  2. Tại thanh điều hướng bên tay trái, chọn Image recipes.
  3. Nhấn nút Create image recipe.
  4. Ở phần Recipe details, điền các giá trị như sau:
    1. Name: pattern3-pipeline-ImageRecipe.
    2. Version: 1.0.0.
    3. Description: Pattern3 Configure OS Recipe.
  5. Ở phần Base image, chọn Select managed images, sau đó:
    1. Image operating system (OS): Amazon Linux.
    2. Image origin: Quick start (Amazon-managed).
    3. Image name: chọn dòng Amazon Linux 2023 x86.
    4. Auto-versioning options: chọn Use latest available OS version để mỗi lần build đều lấy bản AL2023 mới nhất.

ec2-image-builder-create-image-recipe-source-image ec2-image-builder-create-image-recipe-source-image

Đừng chọn Enter custom AMI ID rồi điền một AMI ID cố định. Một AMI ID cố định sẽ cũ dần và có thể bị AWS đánh dấu deprecated, khiến pipeline khởi đầu từ một image đã lạc hậu. Chọn managed image kèm Use latest available OS version giúp mỗi lần build đều bắt đầu từ bản Amazon Linux 2023 mới nhất, đúng tinh thần của một bài thực hành về vá lỗi.

  1. Ở phần Instance configuration, giữ nguyên mặc định. Storage đề xuất chuyển Volume type sang gp3 để rẻ và nhanh hơn gp2.
  2. Ở phần Components, chọn Component đã tạo ở bước trước. Bạn có thể tìm nhanh bằng bộ lọc Owned by me.

ec2-image-builder-create-image-recipe-components

  1. Nhấn nút Create recipe để tiến hành khởi tạo.

ec2-image-builder-image-recipes

Tạo Infrastructure Configuration

Infrastructure Configuration mô tả nơi AMI được build: loại instance, VPC, subnet, security group và nơi ghi log. Đây là tài nguyên độc lập, phải tạo trước khi tạo pipeline.

  1. Truy cập vào dịch vụ EC2 Image Builder.
  2. Tại thanh điều hướng bên tay trái, chọn Infrastructure configuration, sau đó nhấn Create infrastructure configuration.
  3. Ở phần General, điền:
    1. Name: pattern3-pipeline-InfraConfig.
    2. Description: Build infrastructure for pattern3 image pipeline.
    3. IAM role: chọn pattern3-recipe-instance-role đã tạo trước đó.

ec2-image-builder-create-pipeline-define-infra-config-iam-type

  1. Ở phần AWS infrastructure, điền:
    1. Instance type: t3.medium.
    2. SNS topic: bỏ trống.
    3. VPC, subnet, and security groups: chọn VPC của Stack pattern3-base, chọn một Private Subnet, và chọn security group pattern3-pipeline-instance-security-group.

ec2-image-builder-create-pipeline-define-infra-config-iam-type

Nếu bạn để trống mục VPC và subnet thì Image Builder sẽ dùng default VPC và default subnet của tài khoản. Bài thực hành sẽ vẫn build ra AMI, nhưng build instance không còn nằm trong hạ tầng bạn đã tạo ở phần 2, và kiến trúc không còn khớp với sơ đồ. Hãy chọn tường minh.

  1. Ở phần Troubleshooting settings:
    1. Giữ Terminate instance on failure được bật.
    2. Key pair: bỏ trống, chúng ta không dùng SSH.
    3. S3 location for logs: chọn S3 bucket đã tạo ở bước trước.

ec2-image-builder-create-pipeline-define-infra-config-vpc-s3

  1. Nhấn Create infrastructure configuration.

Build instance bắt buộc phải nằm trong Private Subnet có đường ra Internet qua NAT Gateway. Instance này cần kết nối tới Systems Manager và tới repository của Amazon Linux 2023 để tải các bản vá. Nếu đặt vào một subnet không có đường ra, pipeline sẽ treo ở bước Building rồi thất bại vì SSM Agent không đăng ký được.

Lấy VPC ID và Subnet ID từ Output của Stack pattern3-base:

aws cloudformation describe-stacks --stack-name pattern3-base --region ap-southeast-2 --query "Stacks[0].Outputs" --output table

Tạo một Builder Pipeline

  1. Tại thanh điều hướng bên tay trái, chọn Image pipelines, sau đó nhấn Create pipeline.

  2. Mục General:

    1. Pipeline name: pattern3-pipeline-ImagePipeline.
    2. Description: Pattern 3 pipeline to update OS.

ec2-image-builder-create-pipeline-details

  1. Mục Build schedule, Schedule type: chọn Manual.

Mặc định của trang là On schedule, chạy tự động mỗi tuần. Bạn phải đổi sang Manual, vì hai lý do: ở phần 5 chúng ta sẽ kích hoạt pipeline bằng Systems Manager, và một pipeline chạy định kỳ sẽ âm thầm tạo AMI kèm EBS Snapshot mới mỗi tuần, phát sinh chi phí ngay cả khi bạn đã học xong.

  1. Mục Recipe:

    1. Recipe name: chọn pattern3-pipeline-ImageRecipe từ danh sách.
    2. Versioning options: chọn Use latest version available để pipeline tự dùng bản recipe mới nhất. Nếu muốn cố định thì chọn Specify recipe version rồi chọn 1.0.0.
  2. Mục Workflow: giữ Use default workflows.

ec2-image-builder-create-pipeline-details

  1. Mục Infrastructure configuration: chọn Select a configuration, rồi chọn pattern3-pipeline-InfraConfig đã tạo ở bước trước.
  1. Mục Distribution settings: giữ Create with default settings. AMI sẽ được tạo tại Region hiện tại là ap-southeast-2, đúng như dòng Distribution details hiển thị. ec2-image-builder-create-pipeline-details

  2. Mục Advanced settings, mở rộng ra nếu muốn tinh chỉnh. Với bài thực hành bạn có thể giữ nguyên toàn bộ:

    1. Image tags và Tags: tuỳ chọn. Nếu muốn dễ tìm tài nguyên về sau, thêm tag ResourceType = awsstudygroup-000099-imagebuilder.
    2. Auto-disable policy: giữ mặc định 5 consecutive failures. Chính sách này chỉ áp dụng cho lần chạy theo lịch, không áp dụng cho Run pipeline thủ công.
    3. Image log group và Pipeline log group: bỏ trống để Image Builder dùng CloudWatch log group mặc định.
    4. Enhanced metadata (AMI only): mặc định Disabled, giữ nguyên cũng được. Chọn Enabled nếu bạn muốn Image Builder thu thập metadata qua SSM Inventory để kiểm tra tính tương thích của component.
    5. EC2 image scanning: đang bị làm mờ và khoá ở Disabled. Muốn bật quét lỗ hổng thì phải kích hoạt security scanning settings ở cấp tài khoản trước, việc này dùng Amazon Inspector và nằm ngoài phạm vi bài thực hành.
    6. ECR container scanning: bỏ qua, chúng ta không build container image.
  3. Nhấn Create pipeline ở cuối trang.

Với t3.medium, quá trình build mất khoảng 20 đến 30 phút. Bạn có thể chọn loại nhỏ hơn để tiết kiệm chi phí nhưng thời gian build sẽ lâu hơn. Phần lớn thời gian là các bước cố định của Image Builder như khởi tạo instance, chạy component, tạo snapshot và đăng ký AMI.

ec2-image-builder-image-pipelines

Thực thi Builder Pipeline

Sau khi quá trình đặc tả đã hoàn tất, chúng ta tiến hành thử nghiệm Builder Pipeline.

ec2-image-builder-image-pipelines-actions

  1. Tại danh sách Image pipelines, chọn pipeline vừa tạo, nhấn nút Actions và chọn Run pipeline. ec2-image-builder-image-pipelines-actions

  2. Một khi thực thi hoàn tất, chúng ta sẽ kiểm tra liệu AMI mới có được khởi tạo hay không.

ec2-image-builder-pipeline-result

Nếu dùng AWS CLI, bạn có thể chạy pipeline và theo dõi trạng thái như sau:

# Lay ARN pipeline truc tiep tu Image Builder, dung duoc cho ca hai cach tao
PIPELINE_ARN=$(aws imagebuilder list-image-pipelines --region ap-southeast-2 --query "imagePipelineList[?name=='pattern3-pipeline-ImagePipeline'].arn | [0]" --output text)

BUILD_ARN=$(aws imagebuilder start-image-pipeline-execution --image-pipeline-arn "$PIPELINE_ARN" --region ap-southeast-2 --query "imageBuildVersionArn" --output text)

aws imagebuilder get-image --image-build-version-arn "$BUILD_ARN" --region ap-southeast-2 --query "image.state" --output json

Trạng thái sẽ lần lượt đi qua PENDING, BUILDING, TESTING, DISTRIBUTING rồi AVAILABLE. Khi đạt AVAILABLE, bạn lấy AMI ID mới bằng:

aws imagebuilder get-image --image-build-version-arn "$BUILD_ARN" --region ap-southeast-2 --query "image.outputResources.amis[0].image" --output text
# Lay ARN pipeline truc tiep tu Image Builder, dung duoc cho ca hai cach tao
$PIPELINE_ARN = aws imagebuilder list-image-pipelines --region ap-southeast-2 --query "imagePipelineList[?name=='pattern3-pipeline-ImagePipeline'].arn | [0]" --output text

$BUILD_ARN = aws imagebuilder start-image-pipeline-execution --image-pipeline-arn "$PIPELINE_ARN" --region ap-southeast-2 --query "imageBuildVersionArn" --output text

aws imagebuilder get-image --image-build-version-arn "$BUILD_ARN" --region ap-southeast-2 --query "image.state" --output json

Trạng thái sẽ lần lượt đi qua PENDING, BUILDING, TESTING, DISTRIBUTING rồi AVAILABLE. Khi đạt AVAILABLE, bạn lấy AMI ID mới bằng:

aws imagebuilder get-image --image-build-version-arn "$BUILD_ARN" --region ap-southeast-2 --query "image.outputResources.amis[0].image" --output text

EC2 Image Builder sử dụng Automation Document của dịch vụ Systems Manager để hoàn thành quá trình khởi tạo. Chúng ta có thể truy cập vào Systems Manager để theo dõi quá trình này cũng như kiểm tra trạng thái của document ImageBuilderBuildImageDocument.

Tham khảo thêm về quá trình kiểm tra Automation Document tại Running automations.

Mỗi lần pipeline chạy thành công sẽ sinh ra một AMI kèm một EBS Snapshot. Các tài nguyên này không bị CloudFormation xoá khi bạn xoá Stack, và snapshot sẽ tiếp tục phát sinh chi phí. Phần Dọn dẹp tài nguyên có hướng dẫn xoá chúng.

Bây giờ, chúng ta sẽ sang phần kế tiếp với việc triển khai quá trình Build Automation với dịch vụ Systems Manager.