+2

Mình gặp phải vấn đề khi sử dụng Load Balancer trong EKS

Thuộc series Cùng nhau học EKS nào

Giới thiệu

Ở bài đầu tiên thì mình đã dựng cụm EKS cơ bản, nhưng worker expose ra public internet, sau đó bài 2 mình triển khai private worker, đã an toàn hơn và giờ chúng ta sẽ setup để chỉ expose những thứ cần expose trong cụm EKS ra ngoài thôi nhé. Với kubernetes các bạn đã biết Service được dùng để expose workload trong cụm cho các tài nguyên khác trong cụm truy cập, hoặc cùng internal network với các worker và ra public internet với serviceType: LoadBalancer, tìm hiểu về các loại Service sẽ không nằm trong phạm vi bài viết này, bài này sẽ tập chung vào tìm hiểu về load load balancer và sử dụng nó trong cụm EKS.

Và trong quá trình tìm hiểu mình đã gặp phải vấn đề cũng như lưu ý khi sử dụng load balancer trong cụm EKS.

Ý tưởng ban đầu

Về ý tưởng dựng cụm thì mình bê nguyên ý tưởng từ bài trước Triển khai private worker cho EKS: link code aws-eks-example/one: Sẽ có public private subnet, worker nằm trong private subnet, load balancer nằm ở public subnet và forward vào worker nằm trong private subnet và thế là từ bên ngoài chúng ta có thể truy cập được internet.

image.png

Về các bước thì sẽ như sau

  1. Dựng cụm EKS (network, control plane, worker node group)
  2. Test load balancer

Dựng cụm EKS (here we go again)

Link code aws-eks-example/one , bạn nào có sẵn code từ bài trước rồi thì chỉ cần terraform apply lại thôi.

Chi tiết giải thích các bạn có thể xem ở bài trước Tôi bắt đầu học EKSTriển khai private worker cho EKS.

Các bạn clone về

git clone https://github.com/tuana9a/aws-eks-example.git

xong rùi thì

cd one
terraform init
terraform apply # yes

Mất đâu đó khoảng 10p, 15p là xong

image.png

Lên giao diện aws console kiểm tra

image.png

Sau đó lấy kubeconfig bằng lệnh

aws eks update-kubeconfig --name one

Test load balancer

Theo doc network-load-balancing.html thì sẽ có một legacy controller mặc định cấp Classic Load Balancers cho bạn với các tính năng của một load balancer để balance traffic, như vậy là bạn đã có thể dùng được serviceType: LoadBalancer, vậy thử test xem sao nào

Cùng apply thử nginx deployment và tạo serviceType: LoadBalancer cho nginx xem sao, mình tạo một file mới test-classic-lb.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-classic
  namespace: default
spec:
  replicas: 1 # Lưu ý mình chỉ set 1 pod ở đây
  selector:
    matchLabels:
      app: nginx-classic
  template:
    metadata:
      labels:
        app: nginx-classic
    spec:
      containers:
        - name: nginx
          image: nginx
          ports:
            - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-classic
  namespace: default
spec:
  type: LoadBalancer
  ports:
    - port: 80
      targetPort: 80
      protocol: TCP
  selector:
    app: nginx
kubectl apply -f test-classic-lb.yaml

Sau đó chạy lệnh để xem thông tin của service

kubectl -n default get svc nginx-classic

Và đây là kết quả

image.png

Vậy là đã có EXTERNAL-IP mình ban đầu nghĩ nó là public ip, nhưng mà nó lại là dns, hmm, ko sao thử dùng cái đó để truy cập từ trình duyệt, hoặc mình dùng curl trong terminal xem sao

curl http://a6bf66000690b464db68d82682bfdddd-1150002586.ap-southeast-1.elb.amazonaws.com

Và mong rằng trang web "Welcome to nginx!" sẽ hiện ra.

image.png

Đíu được

curl: (52) Empty reply from server

Mình thử thêm vài lần và truy cập thử từ trình duyệt xem sao

image.png

Cũng đíu được, ây da, tại sao nhỉ, lại phải debug rùi.

Tìm nguyên nhân

Mình lên aws console kiểm tra, các bạn search load balancer và vào cái của EC2

image.png

Thấy ngay thằng đầu tiên

image.png

Tích chọn vào xem sao.

Và, wtf 0 of 1 instance in service

image.png

Click thử sang tab Target instances - Là các instances sẽ hứng requests

image.png

Ồ, bắt đầu thấy nguyên nhân, mở rộng cột Health status description ra đọc xem sao

image.png

È È È Instance is in the EC2 Availability Zone for which the load balancer is not configured to route traffic to.

Liên quan gì đó tới availability zone, hmm, bên cạnh thì instance này đang nằm ở az: ap-southeast-1b, quay về tab Details check xem load balancer này đang nằm ở đâu

image.png

Ồ đang nằm ở ap-southeast-1a vậy là khác az, à cái này là chủ định của mình khi mình triển khai EKS private worker thì gồm:

Thử các giải pháp có thể

Ý tưởng là load balancer sẽ forward từ public subnet về private subnet, nhưng có vẻ như hiện tại thì do khác availability zone nên aws đang không forward được. Mình đang thử tìm xem có cách nào enable việc đó không thì tìm được cái này ở tab Attributes

image.png

Cross-zone load balancing: Off

Thử bật lên xem có được ko, bấm vào Edit ngay góc trên bên phải

image.png

Bấm Save changes và mình test lại curl và vào bằng trình duyệt

...

Vẫn không được, mình đã thử lại sau vài phút thì vẫn ko được, ây da, vẫn còn sai một chỗ nào đó, mình thấy tiếp cái tab Network mapping

image.png

Chỉ thấy có az: ap-southeast-1a, mình thử vào Edit subnets để thêm az còn lại: ap-southeast-1b, ap-southeast-1c xem được ko

image.png

The selected subnet does not have a route to an internet gateway. This means that your load balancer will not receive internet traffic. You can proceed with this selection; however, for internet traffic to reach your load balancer, you must update the subnet’s route table in the VPC console .

Ủa là sao, traffic vào được load balancer ở az a rồi tại sao ko forward tới private subnet ở az b, az c, từ public subnet sang private subnet dùng private ip để call nhau mà, why? Tạm thời để câu hỏi đó lại, mình sẽ làm theo là gắn route table ra internet gateway cho 2 private subnet như vậy thì mặc định 2 private subnet sẽ route ra internet gateway thay vì nat, như vậy thì nat đang ko dùng...

Sửa route table gắn với 2 private subnets thành route table ra public

image.png

Nội dung của route table public như sau: https://github.com/tuana9a/aws-eks-example/blob/81239f3e8cf8f18419ac35abb7e8059517d4cef1/one/network.tf#L50-L62

resource "aws_route_table" "public" {
  vpc_id = aws_vpc.one.id
  tags = {
    Name = "public"
  }
}
# by default all traffic will go to internet gateway and travel to public internet
resource "aws_route" "public" {
  route_table_id         = aws_route_table.public.id
  destination_cidr_block = "0.0.0.0/0"
  gateway_id             = aws_internet_gateway.public.id
}

Rồi, giờ quay lại web load balancer check lại xem sao

image.png

Ok đã có thể tích chọn subnets mà ko có cảnh báo gì, lúc vừa mới cập nhật route table thì cái warning đó vẫn có mình chờ vài phút thì lần này tích thì ko thấy nó vàng nữa, giờ mình Save changes thử xem nào.

Chờ một lúc và thử lại curl và vào bằng trình duyệt web xem sao

curl

image.png

web

image.png

OK vậy là được rồi.

Gặp vấn đề khác

Cơ mà mình cũng phát hiện ra vấn đề

image.png

Node của mình có trạng thái là NotReady

image.png

Vào EKS thì thấy trạng thái status là Unknown và Node group là DEGRADED

image.png

Click vào node group và chọn tab Health issues thì thấy như sau

image.png

One or more Amazon EC2 Subnets of [subnet-0112abdfa211a8d0d, subnet-0bd57b6a4f4415333] for node group one does not automatically assign public IP addresses to instances launched into it. If you want your instances to be assigned a public IP address, then you need to enable auto-assign public IP address for the subnet. See IP addressing in VPC guide: https://docs.aws.amazon.com/vpc/latest/userguide/vpc-ip-addressing.html#subnet-public-ip

Có vẻ như worker node không thông được tới control plane, có thể do ko có NAT nên traffic đi từ worker node trong private subnet ra public sẽ không được. Ây da lú thế nhỉ.

Mình có thử test tạo lại load balancer để xem vụ subnet ntn

kubectl delete -f test-classic-lb.yaml
kubectl apply -f test-classic-lb.yaml

Về subnets thì lúc tạo nó hiện luôn cả 3 subnets trong phần network mappings, nhưng phần target instances thì lại bị như sau

image.png

Ko biết lúc trước khi tạo lại nó đã bị vậy hay chưa, và kết quả khi curl và vào trình duyệt web lại bị curl: (52) Empty reply from server, kiểu worker node không register làm target instance được nên load balancer không forward được tới worker node.

Đến lúc này thì mình đang thấy việc sử dụng load balancer trong EKS phụ thuộc vào việc setup network, mặc dù đã "dùng" được load balancer nhưng mà phải sửa tay, chắp vá và khá là rối rắm. Chưa kể load balancer của mình đang dùng là legacy - đã cũ và được aws thông bảo là không còn phát triển thêm nữa.

Tổng kết

Setup chạy thì chạy được nhưng mà sẽ không dùng được trong thực tế. Việc setup network đang có vấn đề, mình cần tìm được phương án chính xác và chuẩn chỉ hơn. Thực ra mình đã tìm được và setup được rồi nhưng mà sẽ hẹn các bạn ở bài sau nhé.

Còn về phía lỗi của bài này thì mình xin phép để ngỏ cho bạn nào muốn tìm nguyên nhân sâu xa, nếu tiếp tục thì chúng ta sẽ tìm được cách fix thôi nhưng nó đang khá là chắp và nên mình sẽ không tiếp tục và cũng không khuyến khích các bạn đi theo hướng setup hiện tại.


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí