0
0
Lập trình
Admin Team
Admin Teamtechmely

Kết Nối Amazon S3 với EKS: Hướng Dẫn Chi Tiết bằng Terraform

Đăng vào 1 ngày trước

• 9 phút đọc

Giới thiệu

Trong bài viết này, chúng ta sẽ tìm hiểu cách tích hợp Amazon S3 như một giải pháp lưu trữ với Amazon EKS bằng cách sử dụng Terraform và các tài liệu Kubernetes YAML. Chúng ta sẽ triển khai một container Nginx đơn giản phục vụ các tệp web được lưu trữ trong một bucket S3.

Cách tiếp cận này tận dụng driver Mountpoint cho S3 CSI, cho phép các workload Kubernetes truy cập các đối tượng Amazon S3 bằng các giao diện POSIX tiêu chuẩn.

Hiểu về Amazon S3 cho Kubernetes

Amazon S3 là gì?

Amazon Simple Storage Service (Amazon S3) là một dịch vụ lưu trữ đối tượng được thiết kế cho khả năng mở rộng, độ bền và tính sẵn sàng. Khác với lưu trữ khối truyền thống (như EBS) hoặc lưu trữ tệp (như EFS), S3 lưu trữ dữ liệu dưới dạng các đối tượng trong các bucket, điều này làm cho nó lý tưởng cho nội dung tĩnh, nhật ký và sao lưu.

Sơ đồ kiến trúc

Kiến trúc của việc kết nối lưu trữ Amazon S3 với một cluster EKS xoay quanh driver S3 CSI (Container Storage Interface) và tích hợp Mountpoint cho S3.

Ở lớp cơ sở, một bucket S3 đóng vai trò là kho lưu trữ đối tượng ở phía backend, nơi dữ liệu ứng dụng được giữ. Trong Kubernetes, một StorageClass định nghĩa cách thức lưu trữ được cấp phát và tiêu thụ. Tuy nhiên, với S3, hiện tại chỉ hỗ trợ cấp phát tĩnh—có nghĩa là một PersistentVolume (PV) phải được tạo thủ công và ánh xạ vào một bucket S3 hiện có, sau đó một PersistentVolumeClaim (PVC) sẽ liên kết với PV đó để các workload có thể truy cập.

Khi một pod được triển khai, Kubernetes sẽ gắn PVC vào hệ thống tệp của container thông qua driver S3 CSI, mà nội bộ sử dụng Mountpoint cho S3 để cung cấp quyền truy cập tương tự như hệ thống tệp vào các đối tượng trong bucket.

Mặc dù cấp phát động—nơi PVC tự động kích hoạt việc tạo ra các volume lưu trữ mới—là điều phổ biến cho các driver như EBS và EFS, nhưng hiện tại nó chưa có sẵn cho S3. Điều này khiến việc cấp phát tĩnh trở thành lựa chọn duy nhất, yêu cầu các quản trị viên phải định nghĩa trước ánh xạ giữa các PV và các bucket S3. Bảo mật được xử lý thông qua IAM Roles for Service Accounts (IRSA), đảm bảo rằng các pod chỉ có quyền tối thiểu cần thiết để truy cập vào các bucket S3 cụ thể.

Lợi ích chính khi sử dụng S3 với EKS

  • Khả năng mở rộng: Dung lượng lưu trữ gần như không giới hạn.
  • Độ bền: Đảm bảo độ bền 11 9’s.
  • Chi phí hiệu quả: Chỉ phải trả cho những gì bạn sử dụng mà không cần cấp phát trước.
  • Tích hợp: Tích hợp dễ dàng với các dịch vụ AWS như Athena, Glue và CloudFront.

Một số cân nhắc quan trọng cho EKS

  • Yêu cầu driver CSI: Driver Mountpoint cho S3 CSI phải được cài đặt.
  • Hỗ trợ danh tính pod: Hiện tại, IRSA (IAM Roles for Service Accounts) là yêu cầu. Danh tính pod chưa được hỗ trợ.
  • Giới hạn: Chỉ hỗ trợ cấp phát tĩnh tính đến thời điểm này. Cấp phát động đang được lên kế hoạch.
  • Hạn chế tài nguyên: Theo dõi các giới hạn như số lượng mô tả tệp mở và băng thông mạng khi mở rộng các workload.

Bước 1: Cấp phát Cluster EKS với Terraform trong VPC

Bước đầu tiên trong việc tích hợp Amazon S3 với EKS là cấp phát một cluster Kubernetes hoạt động an toàn trong một VPC riêng biệt. Chúng ta sẽ sử dụng các mô-đun cộng đồng Terraform AWS được sử dụng rộng rãi cho cả thiết lập VPC và EKS. Vui lòng tham khảo mô-đun chính trong repo GitHub.

Bước 2: Tạo bucket S3

Bucket S3: Bucket S3 được mã hóa với phiên bản và quyền truy cập

hcl Copy
resource "aws_s3_bucket" "main" {
  bucket = var.bucket_name
  tags = {
    Name        = var.bucket_name
    Environment = var.environment
    Terraform   = "true"
  }
}

Phiên bản bucket S3

hcl Copy
resource "aws_s3_bucket_versioning" "main" {
  bucket = aws_s3_bucket.main.id
  versioning_configuration {
    status = var.versioning_enabled ? "Enabled" : "Disabled"
  }
}

Mã hóa bucket S3

hcl Copy
resource "aws_s3_bucket_server_side_encryption_configuration" "main" {
  bucket = aws_s3_bucket.main.id
  rule {
    apply_server_side_encryption_by_default {
      sse_algorithm = "AES256"
    }
    bucket_key_enabled = true
  }
}

Khối quyền truy cập công khai cho bucket S3

hcl Copy
resource "aws_s3_bucket_public_access_block" "main" {
  bucket = aws_s3_bucket.main.id
  block_public_acls       = true
  block_public_policy     = true
  ignore_public_acls      = true
  restrict_public_buckets = true
}

IAM Role: Cho driver S3 CSI

hcl Copy
resource "aws_iam_role" "s3_csi_driver_role" {
  name = "${var.cluster_name}-s3-csi-driver-role"
  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Effect = "Allow"
        Principal = {
          Federated = "arn:aws:iam::${data.aws_caller_identity.current.account_id}:oidc-provider/${replace(data.aws_eks_cluster.cluster.identity[0].oidc[0].issuer, "https://", "")}"
        }
        Action = "sts:AssumeRoleWithWebIdentity"
        Condition = {
          StringEquals = {
            "${replace(data.aws_eks_cluster.cluster.identity[0].oidc[0].issuer, "https://", "")}:sub" = "system:serviceaccount:kube-system:s3-csi-driver-sa"
            "${replace(data.aws_eks_cluster.cluster.identity[0].oidc[0].issuer, "https://", "")}:aud" = "sts.amazonaws.com"
          }
        }
      }
    ]
  })
  tags = {
    Name        = "${var.cluster_name}-s3-csi-driver-role"
    Environment = var.environment
    Terraform   = "true"
  }
}

Chính sách driver S3 CSI (Dựa trên tài liệu AWS)

hcl Copy
resource "aws_iam_policy" "s3_csi_driver_policy" {
  name        = "${var.cluster_name}-s3-csi-driver-policy"
  description = "Chính sách IAM cho driver S3 CSI dựa trên tài liệu AWS"
  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Effect = "Allow"
        Action = [
          "s3:ListBucket"
        ]
        Resource = aws_s3_bucket.main.arn
      },
      {
        Effect = "Allow"
        Action = [
          "s3:GetObject",
          "s3:PutObject",
          "s3:AbortMultipartUpload",
          "s3:DeleteObject"
        ]
        Resource = "${aws_s3_bucket.main.arn}/*"
      }
    ]
  })
  tags = {
    Name        = "${var.cluster_name}-s3-csi-driver-policy"
    Environment = var.environment
    Terraform   = "true"
  }
}

Gắn chính sách driver S3 CSI

hcl Copy
resource "aws_iam_role_policy_attachment" "s3_csi_driver_policy" {
  role       = aws_iam_role.s3_csi_driver_role.name
  policy_arn = aws_iam_policy.s3_csi_driver_policy.arn
}

Add-on Mountpoint cho S3: Driver S3 CSI cho tích hợp Kubernetes

hcl Copy
resource "aws_eks_addon" "s3_mountpoint_csi_driver" {
  cluster_name             = module.eks.cluster_name
  addon_name               = "aws-mountpoint-s3-csi-driver"
  service_account_role_arn = module.s3.s3_csi_driver_role_arn
  depends_on = [module.s3]
  tags = {
    Name        = "${var.cluster_name}-s3-mountpoint-csi-driver"
    Environment = var.environment
    Terraform   = "true"
  }
}

Bước 3: Mô hình triển khai lưu trữ S3

Vì chỉ hỗ trợ cấp phát tĩnh cho S3 ngày nay, chúng ta sẽ định nghĩa các PersistentVolumes (PV) tham chiếu một bucket S3.

storage-class.yaml - StorageClass cho driver S3 CSI

yaml Copy
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: s3-csi-sc
provisioner: s3.csi.aws.com
parameters:
  bucketName: ${S3_BUCKET_NAME}
  prefix: "k8s-storage/"
volumeBindingMode: Immediate
allowVolumeExpansion: false

persistent-volume.yaml - PersistentVolume cho bucket S3 (chỉ cấp phát tĩnh)

yaml Copy
apiVersion: v1
kind: PersistentVolume
metadata:
  name: s3-pv
spec:
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteMany
  persistentVolumeReclaimPolicy: Retain
  storageClassName: s3-csi-sc
  csi:
    driver: s3.csi.aws.com
    volumeHandle: s3-csi-driver-volume
    volumeAttributes:
      bucketName: ${S3_BUCKET_NAME}
      prefix: "k8s-storage/"

persistent-volume-claim.yaml - PVC sử dụng driver S3 CSI

yaml Copy
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: s3-pvc
spec:
  accessModes:
    - ReadWriteMany
  storageClassName: s3-csi-sc
  resources:
    requests:
      storage: 1Gi

nginx-pod.yaml - Pod Nginx với lưu trữ S3 gắn và tạo nội dung

yaml Copy
apiVersion: v1
kind: Pod
metadata:
  name: nginx-s3-pod
  namespace: default
  labels:
    app: nginx-s3
spec:
  securityContext:
    runAsUser: 0
    runAsGroup: 0
  containers:
  - name: nginx
    image: nginx:latest
    ports:
    - containerPort: 80
    env:
    - name: POD_NAME
      valueFrom:
        fieldRef:
          fieldPath: metadata.name
    command: ["/bin/sh", "-c"]
    args:
    - |
      echo '<h1>Hello from S3 Mountpoint!</h1><p><b>Pod:</b> '$POD_NAME'</p>' > /usr/share/nginx/html/index.html || true
      sed -i 's/user  nginx;/user  root;/' /etc/nginx/nginx.conf
      nginx -g 'daemon off;'
    volumeMounts:
    - name: s3-storage
      mountPath: /usr/share/nginx/html
  volumes:
  - name: s3-storage
    persistentVolumeClaim:
      claimName: s3-pvc

nginx-service.yaml - Dịch vụ ClusterIP để phơi bày nginx trên cổng 80

yaml Copy
apiVersion: v1
kind: Service
metadata:
  name: nginx-s3-service
spec:
  type: ClusterIP
  ports:
  - port: 80
    targetPort: 80
  selector:
    app: nginx-s3

Các bước triển khai cho việc cấp phát tĩnh

  1. Lấy tên bucket S3 từ Terraform:
bash Copy
cd infrastructure
S3_BUCKET_NAME=$(terraform output -raw s3_bucket_name 2>/dev/null || echo "")
  1. Cập nhật manifests với các giá trị S3:
bash Copy
sed "s/\${S3_BUCKET_NAME}/$S3_BUCKET_NAME/g" storage-class.yaml > storage-class-final.yaml
sed "s/\${S3_BUCKET_NAME}/$S3_BUCKET_NAME/g" persistent-volume.yaml > persistent-volume-final.yaml
  1. Áp dụng manifests:
bash Copy
kubectl apply -f storage-class-final.yaml
kubectl apply -f persistent-volume-final.yaml
kubectl apply -f persistent-volume-claim.yaml
kubectl apply -f nginx-pod.yaml
kubectl apply -f nginx-service.yaml

Tham khảo deploy.sh cho script triển khai tự động.

bash Copy
$ kubectl get sc,pv,pvc

Xác minh

bash Copy
# Kiểm tra trạng thái driver S3 CSI:
kubectl get pods -n kube-system -l app=aws-mountpoint-s3-csi-driver

# Kiểm tra trạng thái triển khai:
kubectl get pod nginx-s3-pod
kubectl get service nginx-s3-service
kubectl get pvc s3-pvc
kubectl get pv

# Kiểm tra máy chủ web nginx:
kubectl port-forward service/nginx-s3-service 8084:80
# Sau đó truy cập http://localhost:8084

# Kiểm tra sự tồn tại tệp S3
kubectl exec nginx-s3-pod -- ls -la /usr/share/nginx/html/
kubectl exec nginx-s3-pod -- cat /usr/share/nginx/html/index.html

# Kiểm tra nội dung bucket S3:
aws s3 ls s3://$S3_BUCKET_NAME/k8s-storage/

Dọn dẹp

bash Copy
kubectl delete -f nginx-service.yaml
kubectl delete -f nginx-pod.yaml
kubectl delete -f persistent-volume-claim.yaml
kubectl delete -f persistent-volume.yaml
kubectl delete -f storage-class.yaml

Sau đó, bạn có thể xóa cơ sở hạ tầng EKS bằng Terraform nếu không còn sử dụng để tiết kiệm chi phí.

Kết luận

Amazon S3 cung cấp một giải pháp lưu trữ có khả năng mở rộng và tiết kiệm chi phí cho các workload chạy trên EKS. Với driver Mountpoint cho S3 CSI, các pod Kubernetes có thể trực tiếp gắn các bucket S3 và phục vụ các tệp tĩnh một cách liền mạch. Mặc dù hiện tại chỉ giới hạn ở cấp phát tĩnh, nhưng sự tích hợp này là một cách mạnh mẽ để quản lý lưu trữ đối tượng trong các môi trường container hóa.

Tài liệu tham khảo

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