Tác giả: pmm (Đồng tác giả: Henrique Santana, Chuyên gia Container, AWS và Luis Felipe, Kiến trúc sư Giải pháp Chính, AWS)
Ngày phát hành: 25 MAR 2025
Chuyên mục: Amazon Elastic Kubernetes Service, Containers, Technical How-to
Giới thiệu
Nhiều tổ chức đã xây dựng cơ sở hạ tầng của họ bằng cách sử dụng Amazon Elastic Compute Cloud (Amazon EC2) và Network Load Balancer (NLB), thường đi kèm với các chính sách security được xây dựng xung quanh các địa chỉ IP tĩnh của NLB. Khi các tổ chức này áp dụng container hóa và chuyển sang Amazon Elastic Kubernetes Service (Amazon EKS) cho các ứng dụng hiện đại của họ, họ phải đối mặt với thách thức đáng kể trong việc bảo toàn cấu hình endpoint hiện có. Điều này có thể khiến quá trình hiện đại hóa trở nên phức tạp và rủi ro, vì việc thay đổi thiết lập load balancer có thể làm gián đoạn kết nối của client hoặc đòi hỏi những thay đổi lớn về DNS.
Tin tốt là quá trình chuyển đổi này không nhất thiết phải là một nỗ lực “được ăn cả ngã về không”. Trong bài viết này, chúng tôi khám phá một mô hình triển khai hybrid (lai) cung cấp lộ trình di chuyển mượt mà, rủi ro thấp từ Amazon EC2 sang Amazon EKS. Việc sử dụng TargetGroupBinding từ AWS Load Balancer Controller cho phép các tổ chức dần dần chuyển lưu lượng truy cập từ các instance EC2 sang các pod Amazon EKS trong khi vẫn duy trì các địa chỉ IP tĩnh NLB hiện có của họ. Cách tiếp cận này không chỉ bảo toàn yêu cầu về IP tĩnh mà còn cung cấp một con đường thực tế để hiện đại hóa. Hơn nữa, điều này giúp các tổ chức xác thực các tải công việc được container hóa của họ mà không làm gián đoạn các kết nối client hiện có hoặc đòi hỏi thay đổi DNS.
Trong bài viết này, chúng tôi sẽ đi sâu vào cách bạn có thể triển khai mô hình này và hiện đại hóa cơ sở hạ tầng của mình trong khi vẫn duy trì tính liên tục trong kinh doanh.
Triển khai hybrid
Tương tự như các mô hình triển khai blue/green, cách tiếp cận triển khai hybrid của chúng tôi hỗ trợ chạy ứng dụng đồng thời trên Amazon EKS và Amazon EC2 trong suốt quá trình di chuyển. Chìa khóa của chiến lược này là khả năng định tuyến lưu lượng truy cập thông qua load balancer hiện có của bạn đến cả hai môi trường triển khai bằng cách sử dụng TargetGroupBinding, dẫn đến một quy trình di chuyển được kiểm soát.
TargetGroupBinding sử dụng Custom Resources (CR) của Kubernetes để tự động quản lý mối quan hệ giữa các tải công việc được container hóa và các target group của bạn. Việc tạo một target group mới cho tải công việc được container hóa cho phép bạn duy trì quyền kiểm soát độc lập đối với việc phân phối lưu lượng truy cập trong khi vẫn sử dụng cơ sở hạ tầng NLB hiện có của bạn.
Hình sau cho thấy kiến trúc hybrid này. Đường dẫn màu xanh lá cây đại diện cho luồng lưu lượng truy cập hiện tại đến các instance EC2, hoặc Elastic Container Service (Amazon ECS), trong khi đường dẫn màu xanh lam cho thấy cách lưu lượng truy cập có thể được định tuyến đến các tải công việc Amazon EKS mới thông qua cùng một NLB:

Hình 1: Sơ đồ luồng lưu lượng truy cập cho thấy quá trình di chuyển từ Amazon EC2 (màu xanh lá cây) sang Amazon EKS (màu xanh lam)
Bài viết này tập trung vào việc di chuyển từ Amazon EC2 sang Amazon EKS. Tuy nhiên, mô hình này rất linh hoạt. Cách tiếp cận tương tự có thể được áp dụng khi di chuyển từ các kiến trúc triển khai khác, bao gồm các kiến trúc không container hóa, on-premises (tại chỗ) hoặc Amazon ECS. Hơn nữa, mô hình này tỏ ra hữu ích khi nâng cấp các cluster Kubernetes hiện có lên các phiên bản mới hơn, mang lại những lợi ích tương tự về việc di chuyển có kiểm soát.
Ưu điểm khi sử dụng cách tiếp cận triển khai hybrid
Cách tiếp cận triển khai hybrid mang lại những ưu điểm sau:
- Di chuyển có kiểm soát: Định tuyến lưu lượng truy cập dần dần đến các tải công việc Amazon EKS trong khi vẫn duy trì dịch vụ thông qua cơ sở hạ tầng Amazon EC2 hiện có của bạn, giảm đáng kể rủi ro di chuyển.
- Rollback đơn giản: Nhanh chóng chuyển hướng lưu lượng truy cập trở lại các instance EC2 nếu có vấn đề phát sinh, cung cấp khả năng rollback đáng tin cậy trong quá trình di chuyển.
- Thử nghiệm A/B: So sánh hiệu suất giữa các triển khai Amazon EC2 và Amazon EKS trong điều kiện thực tế, cung cấp các quyết định dựa trên dữ liệu về cấu hình và phân bổ tài nguyên hiệu quả nhất.
- Linh hoạt: Sử dụng thế mạnh của cả hai môi trường triển khai trong quá trình chuyển đổi, giúp tối ưu hóa vị trí tải công việc dựa trên các yêu cầu cụ thể.
- Giảm thiểu gián đoạn dịch vụ: Giảm thiểu rủi ro thời gian ngừng hoạt động bằng cách vận hành đồng thời cả hai môi trường trong quá trình di chuyển.
- Giảm thiểu rủi ro: Xác thực các triển khai container hóa bằng lưu lượng truy cập thực tế trong khi vẫn duy trì tùy chọn dự phòng, đảm bảo tính liên tục trong kinh doanh.
Điều kiện tiên quyết cho việc di chuyển
Bài viết này được viết dựa trên giả định rằng bạn có hiểu biết cơ bản về container hóa Docker và các khái niệm Kubernetes (pods, events, namespaces, deployments, v.v.).
Trước khi bắt đầu quá trình di chuyển, hãy đảm bảo bạn đã chuẩn bị sẵn các thành phần sau:
- Cơ sở hạ tầng hiện có: Trong ví dụ của chúng tôi, một ứng dụng mẫu Retail Store đang chạy trên Amazon EC2.
- Yêu cầu về Container: Một ứng dụng đã được kiểm thử và container hóa, với image container đã được đẩy lên một registry container, chẳng hạn như Amazon Elastic Container Registry (Amazon ECR).
- Môi trường Amazon EKS: Cluster Amazon EKS với phiên bản Kubernetes được hỗ trợ trên nhiều Availability Zones (AZs).
- Công cụ:
- kubectl đã được cài đặt và cấu hình để tương tác với cluster Amazon EKS.
- AWS Command Line Interface (AWS CLI) đã được cài đặt và cấu hình với AWS Identity and Access Management (IAM) thích hợp.
- AWS Load Balancer Controller đã được cài đặt trên cluster Amazon EKS.
Di chuyển ứng dụng của bạn bằng cách sử dụng triển khai hybrid với NLB
Chúng tôi có một ứng dụng đang chạy trên các instance EC2 được quản lý bởi các nhóm Amazon EC2 Auto Scaling. Môi trường mục tiêu của chúng tôi là một cluster Amazon EKS nơi chúng tôi đã cài đặt và cấu hình AWS Load Balancer Controller. Để di chuyển, chúng tôi áp dụng một cách tiếp cận hơi khác so với mô hình thông thường. Thay vì di chuyển bằng cách sử dụng các load balancer mới hoặc thực hiện các thay đổi cơ sở hạ tầng đáng kể, chúng tôi triển khai một quá trình di chuyển có kiểm soát nhằm duy trì NLB hiện có trong khi dần dần chuyển lưu lượng truy cập sang cluster Amazon EKS. Cách tiếp cận này bảo toàn các kết nối client hiện tại, giảm thiểu gián đoạn dịch vụ và duy trì tính sẵn sàng cao trong suốt quá trình chuyển đổi.
Để đạt được điều này, thay vì sử dụng loại Kubernetes Service LoadBalancer tiêu chuẩn, chúng tôi chọn một cách tiếp cận được kiểm soát hơn bằng cách sử dụng các target group được tạo thủ công và TargetGroupBinding, đây là một CR được cung cấp bởi AWS Load Balancer Controller. Điều này cung cấp khả năng quản lý độc lập các target group và kiểm soát chi tiết hơn về cách lưu lượng truy cập được định tuyến đến các ứng dụng, điều này rất có giá trị khi tích hợp với cơ sở hạ tầng hiện có. Điều này mang lại sự linh hoạt cần thiết cho các kịch bản di chuyển phức tạp, nơi việc duy trì các cấu hình load balancer cụ thể là rất quan trọng, cung cấp khả năng kiểm soát chính xác đối với cấu hình target group và duy trì các tài nguyên load balancer hiện có để di chuyển liền mạch.
Một chi tiết quan trọng khi làm việc với NLB là việc xử lý kết nối trong quá trình thay đổi target group. Khi sửa đổi target group, các kết nối mới được định tuyến đến các target mới trong khi các kết nối hiện có vẫn giữ nguyên với các target ban đầu của chúng. Để minh họa điều này, hãy xem xét nó tương tự như một nhà hàng thay ca. Khách hàng mới (kết nối) được chuyển đến đội ngũ mới, nhưng khách hàng hiện tại (các kết nối đã thiết lập) tiếp tục với các máy chủ ban đầu của họ cho đến khi họ hoàn thành phiên một cách tự nhiên. Hành vi này vẫn tồn tại ngay cả khi Connection termination on deregistration được bật trên target group. Điều này là do khi sử dụng thao tác modifyListener, thao tác DeregisterTargets không được gọi. Hiểu rõ hành vi này là điều cần thiết để lập kế hoạch chuyển đổi ứng dụng suôn sẻ, và nó đặc biệt quan trọng đối với các kết nối TCP hoặc tải công việc UDP tồn tại lâu dài.
Di chuyển từng bước
Bước đầu tiên là tạo một target group mới:
TARGET_GROUP_ARN=$(aws elbv2 create-target-group \
--name eks-green \
--protocol TCP \
--port 80 \
--target-type ip \
--vpc-id <VPCID> \
--query 'TargetGroups[0].TargetGroupArn' \
--output text)
Amazon Resource Name (ARN) của target group được lưu vào biến TARGET_GROUP_ARN. Sau đó, xác minh rằng cả hai target group (Amazon EC2 và Amazon EKS) đều được cấu hình với Terminate connections on deregistration là true.
aws elbv2 describe-target-group-attributes \
--target-group-arn $TARGET_GROUP_ARN \
--query 'Attributes[*]' --output text | \
grep deregistration_delay.connection_termination.enabled
Quan sát đầu ra sau:
deregistration_delay.connection_termination.enabled true
Nếu đầu ra của lệnh trả về thuộc tính false, điều đó có nghĩa là thuộc tính này chưa được bật. Để bật, hãy sử dụng lệnh sau:
aws elbv2 modify-target-group-attributes \
--target-group-arn $TARGET_GROUP_ARN \
--attributes 'Key=deregistration_delay.connection_termination.enabled,Value=true' \
--query 'Attributes[*]' --output text | \
grep deregistration_delay.connection_termination.enabled
Ở giai đoạn này, lưu lượng truy cập vẫn được định tuyến đến ứng dụng đang chạy trên Amazon EC2. Bây giờ bạn có thể triển khai ứng dụng được container hóa trên cluster Amazon EKS:
kubectl create deployment myapp \
--image public.ecr.aws/aws-containers/retail-store-sample-ui:0.8.1 \
--replicas 2 --port=8080
Chúng ta có thể expose ứng dụng bằng cách tạo một service. Dưới đây là file YAML cho service:
cat << EOF > service.yaml
apiVersion: v1
kind: Service
metadata:
labels:
app: myapp
name: ui-service
namespace: default
spec:
ports:
- port: 80
targetPort: 8080
selector:
app: myapp
type: ClusterIP
EOF
Chúng ta có thể áp dụng nó:
kubectl apply -f service.yaml
Với ứng dụng đang chạy và được expose dưới dạng Kubernetes service, hãy tạo một listener mới cho NLB hiện có:
aws elbv2 create-listener \
--load-balancer-arn <NLB-ARN> \
--protocol TCP --port 81 \
--default-actions Type=forward,TargetGroupArn=$TARGET_GROUP_ARN
Hiện tại bạn có một listener trên port 80. Listener này tiếp tục chuyển tiếp lưu lượng truy cập đến target group được liên kết với các instance EC2. Listener mới được tạo sẽ chuyển tiếp lưu lượng truy cập đến target group được liên kết với Amazon EKS. Nó chưa có bất kỳ target nào cho đến khi bạn sử dụng TargetGroupBinding để liên kết service với target group mới. Chúng ta có thể tạo nó:
cat << EOF > tg-binding.yaml
apiVersion: elbv2.k8s.aws/v1beta1
kind: TargetGroupBinding
metadata:
name: ui-tgbinding
spec:
serviceRef:
name: ui-service # Service name
port: 80 # Service port
targetGroupARN: $TARGET_GROUP_ARN
EOF
Áp dụng manifest:
kubectl apply -f tg-binding.yaml
Bạn có thể xác minh rằng các target đã được đăng ký đúng cách vào target group Amazon EKS. Cung cấp đủ thời gian để các target vượt qua kiểm tra sức khỏe (health checks), sau đó xác minh rằng các target mới có thể phục vụ lưu lượng truy cập thành công. Nếu kiểm tra sức khỏe thất bại, hãy xác minh rằng Security Group của node Amazon EKS cho phép lưu lượng truy cập cần thiết. Để xác nhận chức năng hoạt động đúng, hãy thử truy cập ứng dụng thông qua listener mới để đảm bảo rằng nó đang được phục vụ theo đúng ý định trước khi tiếp tục.
Trước khi bắt đầu di chuyển, bạn cần tạo một listener khác trỏ đến target group Amazon EC2 hiện có:
aws elbv2 create-listener \
--load-balancer-arn <NLB-ARN> \
--protocol TCP --port 82 \
--default-actions Type=forward,TargetGroupArn=<EC2-TARGET-GROUP-ARN>
Sau bước này, NLB có ba listener (port 80, 81 và 82), trong đó bạn đã tạo thêm hai listener để vận hành quá trình di chuyển lưu lượng truy cập suôn sẻ. Các số port được sử dụng trong bài viết này chỉ là ví dụ và bạn có thể chọn các số port phản ánh nhu cầu ứng dụng của mình. Chúng tôi khuyên bạn nên kiểm tra xem lưu lượng truy cập đến các target group hiện có có đang được phục vụ trên listener mới hay không. Điều này đảm bảo rằng cấu hình NLB đã sẵn sàng để tiến hành các bước tiếp theo.
Di chuyển lưu lượng truy cập từ Amazon EC2 sang target group Amazon EKS
Cả hai target group đều khỏe mạnh (healthy), và tất cả các listener đã sẵn sàng xử lý lưu lượng truy cập, vì vậy đã đến lúc di chuyển lưu lượng truy cập. Đầu tiên, cấu hình listener hiện có trên port 80 để gửi lưu lượng truy cập đến target group eks-green.
aws elbv2 modify-listener \
--listener-arn <NLB-Listen-80> \
--default-actions Type=forward,TargetGroupArn=$TARGET_GROUP_ARN
Thay đổi cấu hình này đảm bảo rằng tất cả các luồng mới đều được định tuyến đến target group mới. Vì các target đã vượt qua kiểm tra sức khỏe khi được liên kết với listener trên port 81, điều này giúp tăng tốc quá trình này.
Thay đổi listener này có thể mất vài phút để lan truyền. Do đó, chúng tôi khuyên bạn nên theo dõi lưu lượng truy cập đến các target trong target group mới trước khi tiến hành các bước tiếp theo. Trong thời gian này, điều quan trọng là phải theo dõi hành vi và các chỉ số hiệu suất của ứng dụng. Bạn có thể theo dõi trạng thái sức khỏe của target bằng cách sử dụng lệnh sau:
aws elbv2 describe-target-health \
--target-group-arn $TARGET_GROUP_ARN
Mặc dù các kết nối hiện có sẽ không bị ảnh hưởng, các kết nối mới sẽ ngừng định tuyến đến target group cũ hơn sau khi quá trình di chuyển lưu lượng truy cập hoàn tất. Sau khi xác nhận rằng các target mới đang xử lý lưu lượng truy cập thành công và các target hiện có trước đó không còn phục vụ lưu lượng truy cập nữa, hãy truy xuất danh sách các target từ target group Amazon EC2 hiện có trước đó để chuẩn bị cho việc hủy đăng ký (deregistration):
aws elbv2 describe-target-health \
--target-group-arn <EC2-TARGET-GROUP-ARN> \
--query 'TargetHealthDescriptions[*].Target.Id' \
--output text
Lệnh này xuất ra danh sách các ID instance. Đối với mỗi ID instance, hãy chạy lệnh deregister-targets:
aws elbv2 deregister-targets \
--target-group-arn <EC2-TARGET-GROUP-ARN> \
--targets Id=<InstanceID>
Bước hủy đăng ký là quan trọng vì target group Amazon EC2 vẫn được liên kết với NLB thông qua listener port 82. Khi được thực hiện, lệnh gọi deregister-targets sẽ thực thi Connection termination on deregistration, chấm dứt các kết nối hiện có đến các target cũ. Khi client kết nối lại, chúng sẽ được định tuyến đến các target của target group Amazon EKS mới.
Quy trình rollback về target group ban đầu (Nếu cần)
Nếu bạn cần rollback về target group Amazon EC2 ban đầu, hãy làm theo các bước sau:
- Đăng ký lại tất cả các target ban đầu vào target group Amazon EC2:
aws elbv2 register-targets \
--target-group-arn <EC2-TARGET-GROUP-ARN> \
--targets Id=<InstanceID1> Id=<InstanceID2>
- Chờ các target vượt qua kiểm tra sức khỏe. Theo dõi trạng thái sức khỏe của chúng:
aws elbv2 describe-target-health \
--target-group-arn <EC2-TARGET-GROUP-ARN>
- Cấu hình lại listener trên port 80 trên NLB để gửi lưu lượng truy cập đến target group Amazon EC2:
aws elbv2 modify-listener \
--listener-arn <NLB-Listen-80> \
--default-actions Type=forward,TargetGroupArn=<EC2-TARGET-GROUP-ARN>
Dọn dẹp sau di chuyển
Nếu quá trình di chuyển đã thành công (không cần rollback), bạn có thể tiến hành các thao tác dọn dẹp. Điều này bao gồm việc xóa hai listener bổ sung mà bạn đã tạo trên port 81 và 82, vì chúng chỉ cần thiết cho quá trình di chuyển. Cuối cùng, bạn có thể xóa target group Amazon EC2 một cách an toàn, vì nó không còn nhận bất kỳ lưu lượng truy cập nào nữa.
aws elbv2 delete-listener \
--listener-arn <Listen-Port81-ARN>
aws elbv2 delete-listener \
--listener-arn <Listen-Port82-ARN>
aws elbv2 delete-target-group \
--target-group-arn <EC2-TG-ARN>
Kết luận
Mô hình triển khai hybrid sử dụng NLB và TargetGroupBinding cung cấp một cách tiếp cận thực tế, rủi ro thấp để di chuyển các ứng dụng sang Amazon EKS từ nhiều nguồn khác nhau, bao gồm Amazon EC2, cơ sở hạ tầng on-premises hoặc các giải pháp điều phối container khác. Việc duy trì cấu hình NLB hiện có, đồng thời dần dần chuyển lưu lượng truy cập sang các tải công việc được container hóa, cho phép phương pháp này hỗ trợ quá trình chuyển đổi liền mạch và cung cấp khả năng rollback tích hợp sẵn. Mặc dù chúng tôi đã tập trung vào việc di chuyển từ Amazon EC2 sang Amazon EKS, tính linh hoạt của mô hình này mở rộng sang nhiều kịch bản khác nhau, bao gồm cả việc chuyển đổi từ cơ sở hạ tầng on-premises hoặc các giải pháp điều phối container khác.
Những cải tiến gần đây đối với AWS Load Balancer Controller, đặc biệt là việc giới thiệu MultiCluster target groups, tiếp tục mở rộng các khả năng này. Giờ đây, các tổ chức có thể quản lý các tải công việc trên nhiều cluster Kubernetes và tích hợp với các tài nguyên không phải cluster, tạo điều kiện cho các chiến lược di chuyển phức tạp hơn và kiến trúc ứng dụng phân tán. Cách tiếp cận hybrid này đóng vai trò là một bản thiết kế đáng tin cậy cho việc hiện đại hóa, cung cấp các công cụ cần thiết để duy trì tính liên tục trong kinh doanh và giảm thiểu rủi ro, đồng thời mang lại sự linh hoạt để thích ứng với các yêu cầu cơ sở hạ tầng đang phát triển.
Để tiếp tục hành trình di chuyển của bạn, chúng tôi khuyên bạn nên đọc bài viết đi kèm của chúng tôi: Di chuyển từ Kubernetes tự quản lý sang Amazon EKS: Dưới đây là một số cân nhắc chính. Bài viết này cung cấp thêm thông tin chi tiết và các best practice bổ sung cho chiến lược triển khai hybrid được thảo luận ở đây, đặc biệt nếu bạn đang chuyển từ môi trường Kubernetes tự quản lý sang Amazon EKS.