0
0
Lập trình
Flame Kris
Flame Krisbacodekiller

Cấu hình EKS Managed Node Groups Sử Dụng Proxy Với Terraform

Đăng vào 5 tháng trước

• 12 phút đọc

Giới thiệu

Trong môi trường doanh nghiệp, chính sách bảo mật và mạng là rất quan trọng. Thông thường, các máy chủ, bao gồm cả các node Kubernetes, được đặt trong các subnet riêng tư mà không có truy cập Internet trực tiếp. Thay vào đó, tất cả lưu lượng ra ngoài phải được định tuyến qua một proxy HTTP/HTTPS được quản lý và giám sát trung tâm. Mặc dù điều này nâng cao bảo mật, nhưng nó tạo ra một thách thức trong việc cấu hình cho các dịch vụ như Amazon EKS, cần phải kéo hình ảnh container, giao tiếp với APIs của AWS, và thực hiện các tác vụ khởi động khác.

Bài viết này sẽ hướng dẫn bạn cách cấu hình các nhóm node được quản lý (Managed Node Groups) của Amazon EKS để sử dụng proxy thông qua Terraform, đảm bảo rằng hệ điều hành, runtime container (containerd), và các thành phần Kubernetes đều nhận biết proxy ngay từ khi khởi động.

Thách thức cốt lõi: Nhận thức đầy đủ về proxy

Chỉ việc thiết lập các biến môi trường HTTP_PROXYHTTPS_PROXY là không đủ. Một node EKS hiện đại, được xây dựng trên Amazon Linux 2 EKS Optimized AMI, có một số thành phần chính cần phải được cấu hình độc lập:

  1. Hệ điều hành cơ bản: Để sử dụng trong các phiên shell và các tiện ích hệ thống chung.
  2. Runtime container (containerd): Đây là một yếu tố quan trọng. Nếu không có cài đặt proxy, containerd sẽ không thể kéo bất kỳ hình ảnh nào từ các registry công cộng như Docker Hub hoặc ngay cả các registry riêng tư bên ngoài VPC, chẳng hạn như Amazon ECR.
  3. Quy trình khởi động EKS (nodeadm): Trình khởi động mới cho EKS AMIs cần phải giao tiếp với control plane của EKS. Giao tiếp này nên vượt qua proxy.
  4. Quản lý gói (yum): Nếu bạn cần cài đặt bất kỳ gói nào bổ sung trong dữ liệu người dùng của bạn, yum cũng cần được cấu hình để sử dụng proxy.

Giải pháp là sử dụng một script cloud-init chạy trước logic khởi động chính của EKS, đảm bảo rằng toàn bộ môi trường được cấu hình đúng trước khi bất kỳ quy trình Kubernetes nào được khởi động.

Hiểu về hook khởi động: cloudinit_pre_nodeadm

Trước khi đi vào mã, điều cần thiết là phải hiểu cơ chế mà chúng ta đang sử dụng. Tên cloudinit_pre_nodeadm có thể chia thành hai khái niệm chính:

  • cloud-init: Đây là tiêu chuẩn ngành cho việc khởi tạo giai đoạn đầu của các phiên bản đám mây. Khi một phiên bản EC2 mới khởi động lần đầu tiên, nó chạy cloud-init, thực hiện một loạt hướng dẫn do người dùng cung cấp (dữ liệu người dùng) để cấu hình hệ điều hành, cài đặt gói, tạo file và thiết lập người dùng trước khi máy được coi là đã "sẵn sàng".
  • nodeadm: Bắt đầu từ EKS Optimized Amazon Linux 2023 AMI, nodeadm là tác nhân khởi động chính thức chịu trách nhiệm cấu hình một node và tham gia vào một cụm EKS. Nó thực hiện các nhiệm vụ như lấy chứng chỉ cụm, cấu hình kubelet và áp dụng nhãn và taint cho node. Nó đã thay thế script bootstrap.sh cũ.

Tham số cloudinit_pre_nodeadm, được cung cấp bởi module terraform-aws-modules/eks/aws, là một hook mạnh mẽ cho phép bạn chạy một script cloud-init tùy chỉnh tại một thời điểm chính xác: sau khi khởi tạo OS cơ bản nhưng trước khi dịch vụ nodeadm được khởi động.

Thời điểm này rất quan trọng. Bằng cách thực hiện script của chúng tôi trước nodeadm, chúng tôi đảm bảo rằng môi trường mạng cơ bản—bao gồm cả cài đặt proxy—đã có sẵn. Khi nodeadm, containerd, và kubelet cuối cùng khởi động, chúng sẽ thừa hưởng cấu hình đúng từ môi trường, cho phép chúng hoạt động bình thường trong mạng hạn chế.

Giải pháp: Sử dụng cloudinit_pre_nodeadm trong Terraform

Giải pháp của chúng tôi sẽ truyền CIDR dịch vụ Kubernetes từ cấu hình Terraform của chúng tôi trực tiếp vào script dữ liệu người dùng. Điều này loại bỏ các giá trị mã hóa cứng và làm cho giải pháp có thể tái sử dụng qua các cụm khác nhau.

Dưới đây là đoạn mã Terraform thực hiện cấu hình proxy hoàn chỉnh.

hcl Copy
module "eks" {
  source  = "terraform-aws-modules/eks/aws"
  version = "~> 21.0"

  # Định nghĩa CIDR dịch vụ cho cụm
  cluster_service_ipv4_cidr = "10.100.0.0/16"

  # ... các cấu hình cụm EKS khác ...

  eks_managed_node_groups = {
    main_nodes = {
      # ... các cấu hình nhóm node khác như instance_types, min_size, v.v. ...

      cloudinit_pre_nodeadm = [
        {
          content_type = "text/x-shellscript"
          content      = <<-EOT
            #!/bin/bash
            set -ex

            # Định nghĩa endpoint proxy của bạn
            PROXY="http://your-proxy-url:3128" # cổng proxy tiêu chuẩn

            # Sử dụng IMDSv2 để lấy an toàn metadata phiên bản
            TOKEN=`curl -s -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"`
            MAC=$(curl -s -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/mac)
            VPC_CIDR=$(curl -s -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/network/interfaces/macs/$MAC/vpc-ipv4-cidr-blocks | xargs | tr ' ' ',')
            K8S_SERVICE_CIDR="${module.eks.cluster_service_ipv4_cidr}"

            # Định nghĩa danh sách NO_PROXY của bạn. Điều này rất quan trọng cho giao tiếp dịch vụ nội bộ và AWS.
            NO_PROXY="$VPC_CIDR,$K8S_SERVICE_CIDR,localhost,127.0.0.1,169.254.169.254,.amazonaws.com,.svc.cluster.local,.svc,.cluster.local"

            # 1. Cấu hình cài đặt proxy toàn hệ thống
            echo "Thiết lập /etc/environment"
            cat << EOF > /etc/environment
            HTTP_PROXY=$PROXY
            HTTPS_PROXY=$PROXY
            NO_PROXY=$NO_PROXY
            http_proxy=$PROXY
            https_proxy=$PROXY
            no_proxy=$NO_PROXY
            EOF

            # 2. Cấu hình proxy cho containerd thông qua override systemd
            echo "Cấu hình dịch vụ containerd"
            mkdir -p /etc/systemd/system/containerd.service.d
            cat << EOF > /etc/systemd/system/containerd.service.d/http-proxy.conf
            [Service]
            EnvironmentFile=/etc/environment
            EOF

            # 3. Cấu hình proxy cho nodeadm thông qua override systemd
            echo "Cấu hình dịch vụ nodeadm"
            mkdir -p /etc/systemd/system/nodeadm.service.d
            cat << EOF > /etc/systemd/system/nodeadm.service.d/http-proxy.conf
            [Service]
            EnvironmentFile=/etc/environment
            EOF

            # 4. Cấu hình proxy cho yum
            echo "Cấu hình yum"
            echo "proxy=$PROXY" >> /etc/yum.conf

            # 5. Tải lại daemon systemd và khởi động lại containerd để áp dụng thay đổi
            echo "Tải lại systemd và khởi động lại containerd"
            systemctl daemon-reload
            systemctl restart containerd
          EOT
        }
      ]
    }
  }

  # ... các cấu hình module khác ...
}

Phân tích script

Hãy cùng phân tích nội dung của script cloud-init để hiểu từng bước:

  • set -ex: Đây là một phương pháp tốt theo tiêu chuẩn cho scripting shell. set -e đảm bảo rằng script sẽ thoát ngay lập tức nếu một lệnh thất bại, và set -x in mỗi lệnh trước khi nó được thực thi, cung cấp đầu ra debug rõ ràng trong các log hệ thống.
  • Lấy metadata với IMDSv2: Script động lấy CIDR VPC trực tiếp từ dịch vụ metadata của EC2. Điều này rất quan trọng cho biến NO_PROXY, đảm bảo rằng bất kỳ lưu lượng nào hướng tới các tài nguyên khác trong VPC đều không bị proxy. Nó sử dụng phương pháp IMDSv2 an toàn hơn, yêu cầu một mã phiên.
  • Định nghĩa NO_PROXY: Biến NO_PROXY cũng quan trọng như HTTP_PROXY. Nó chỉ định danh sách các miền và dải IP được phân tách bằng dấu phẩy mà không sử dụng proxy. Danh sách của chúng tôi bao gồm:
    • CIDR VPC $VPC_CIDR lấy động cho tất cả lưu lượng nội bộ VPC.
    • CIDR dịch vụ Kubernetes được truyền từ module qua $K8S_SERVICE_CIDR (ví dụ: 10.100.0.0/16).
    • localhost và địa chỉ dịch vụ metadata (169.254.169.254).
    • Các endpoint dịch vụ AWS và Kubernetes chính để đảm bảo giao tiếp trực tiếp với control plane và các API AWS khác. Lưu ý việc thêm .amazonaws.com để đảm bảo các dịch vụ như ECR, S3 và EC2 được truy cập trực tiếp thông qua VPC Endpoints nếu có.
  • /etc/environment: File này cung cấp các biến môi trường toàn hệ thống cho tất cả người dùng và quy trình. Đây là nền tảng của cấu hình của chúng tôi.
  • Overrides systemd: Cách hiện đại và chính xác để sửa đổi một dịch vụ systemd như containerd hoặc nodeadm là tạo một file override. Chúng tôi tạo http-proxy.conf cho cả hai dịch vụ. Chỉ thị EnvironmentFile=/etc/environment yêu cầu systemd tải tất cả các biến từ file cấu hình toàn cầu của chúng tôi trước khi khởi động dịch vụ. Điều này sạch hơn và dễ bảo trì hơn so với việc sửa đổi các file dịch vụ chính trực tiếp.
  • yum.conf: Một dòng đơn giản được thêm vào /etc/yum.conf làm cho trình quản lý gói nhận biết proxy.
  • Tải lại và khởi động lại: Cuối cùng, systemctl daemon-reload buộc systemd phải đọc lại các file cấu hình của nó, và systemctl restart containerd áp dụng các biến môi trường mới cho runtime container ngay lập tức. nodeadm sẽ lấy cấu hình của nó khi nó chạy ngay sau khi script này hoàn tất.

Việc triển khai thành công các node worker EKS trong một mạng bị tường lửa phía sau một proxy HTTP là một thách thức phổ biến trong doanh nghiệp, nhưng không nhất thiết phải là một vấn đề phức tạp. Bằng cách tận dụng hook cloudinit_pre_nodeadm trong module terraform-aws-modules/eks/aws, bạn có quyền kiểm soát chính xác trình tự khởi động của node.

Phương pháp này cung cấp một giải pháp tự động hóa, mạnh mẽ và có thể khai báo. Bằng cách tiêm một script động cấu hình hệ điều hành, containerd, và nodeadm trước khi các dịch vụ quan trọng này khởi động, bạn đảm bảo rằng các node tham gia vào cụm và kéo hình ảnh một cách đáng tin cậy. Phương pháp Infrastructure as Code này không chỉ giải quyết vấn đề kỹ thuật ngay lập tức mà còn tạo ra một mẫu có thể lặp lại, được kiểm soát phiên bản cho việc xây dựng các nền tảng Kubernetes an toàn và tuân thủ trên AWS.

Các thực hành tốt nhất

  • Kiểm tra cẩn thận cấu hình proxy: Trước khi triển khai, hãy đảm bảo rằng cấu hình proxy của bạn chính xác và có thể truy cập từ các node.
  • Giám sát hiệu suất: Sử dụng các công cụ giám sát để theo dõi hiệu suất của các node EKS và phát hiện sớm các vấn đề liên quan đến proxy.

Các cạm bẫy phổ biến

  • Cấu hình sai biến môi trường: Đảm bảo rằng tất cả các biến môi trường cần thiết được thiết lập chính xác để tránh lỗi không cần thiết.
  • Quá tải proxy: Nếu proxy không đủ mạnh, nó có thể trở thành một điểm nghẽn trong hệ thống.

Mẹo tối ưu hóa hiệu suất

  • Sử dụng proxy gần nhất với node: Đảm bảo rằng proxy được đặt gần với các node EKS để giảm độ trễ.
  • Thường xuyên kiểm tra tốc độ mạng: Đánh giá tốc độ mạng thường xuyên để tối ưu hóa trải nghiệm người dùng cuối.

Giải quyết sự cố

Nếu bạn gặp phải vấn đề khi các node không thể kéo hình ảnh, hãy kiểm tra:

  • Cấu hình proxy trong file /etc/environment.
  • Đảm bảo rằng không có vấn đề kết nối với proxy.

Câu hỏi thường gặp (FAQ)

1. Làm thế nào để biết proxy của tôi có hoạt động không?

Bạn có thể thử truy cập một URL từ một node trong EKS để kiểm tra.

2. Có cách nào để cấu hình proxy cho các dịch vụ khác không?

Có, bạn có thể thêm các file cấu hình giống như đã làm với containerdnodeadm cho các dịch vụ khác.

3. Tôi có thể sử dụng một proxy tự quản lý không?

Có, miễn là nó hỗ trợ giao thức HTTP/HTTPS và có thể truy cập từ VPC của bạn.

Kết luận

Việc cấu hình EKS Managed Node Groups để sử dụng proxy không phải là một nhiệm vụ phức tạp nếu bạn có một kế hoạch rõ ràng. Bằng cách làm theo hướng dẫn này và sử dụng cloudinit_pre_nodeadm, bạn có thể đảm bảo rằng các node của bạn hoạt động một cách hiệu quả và an toàn trong môi trường doanh nghiệp. Hãy bắt đầu triển khai giải pháp của bạn ngay hôm nay và cải thiện bảo mật mạng cho ứng dụng của bạn trên AWS!

Gợi ý câu hỏi phỏng vấn
Không có dữ liệu

Không có dữ liệu

Bài viết được đề xuất
Bài viết cùng tác giả

Bình luận

Chưa có bình luận nào

Chưa có bình luận nào