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.
Về các bước thì sẽ như sau
- Dựng cụm EKS (network, control plane, worker node group)
- 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 EKS và Triể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
Lên giao diện aws console kiểm tra
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ả
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.
Đí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
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
Thấy ngay thằng đầu tiên
Tích chọn vào xem sao.
Và, wtf 0 of 1 instance in service
Click thử sang tab Target instances
- Là các instances sẽ hứng requests
Ồ, bắt đầu thấy nguyên nhân, mở rộng cột Health status description
ra đọc xem sao
È È È 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
Ồ đ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:
- 1 public subnet ở:
ap-southeast-1a
cho load balancer, nat gateway https://github.com/tuana9a/aws-eks-example/blob/81239f3e8cf8f18419ac35abb7e8059517d4cef1/one/network.tf#L10-L19resource "aws_subnet" "one_one" { vpc_id = aws_vpc.one.id cidr_block = "10.0.1.0/24" availability_zone = "ap-southeast-1a" map_public_ip_on_launch = true tags = { Name = "one_one" } }
- 2 private subnets ở:
ap-southeast-1b
,ap-southeast-1c
cho worker node: https://github.com/tuana9a/aws-eks-example/blob/81239f3e8cf8f18419ac35abb7e8059517d4cef1/one/network.tf#L21-L39resource "aws_subnet" "one_two" { vpc_id = aws_vpc.one.id cidr_block = "10.0.2.0/24" availability_zone = "ap-southeast-1b" tags = { Name = "one_two" } }
resource "aws_subnet" "one_three" { vpc_id = aws_vpc.one.id cidr_block = "10.0.3.0/24" availability_zone = "ap-southeast-1c" tags = { Name = "one_three" } }
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
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
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
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
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
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
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
web
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 đề
Node của mình có trạng thái là NotReady
Vào EKS thì thấy trạng thái status là Unknown và Node group là DEGRADED
Click vào node group và chọn tab Health issues
thì thấy như sau
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
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