前言

在使用 EKS 的情況下,基本上都會有為 Pod 建立 Ingress / Service 來讓服務可以被存取的需求。在 EKS 的場景中,通常都會透過 aws-load-balancer-controller[1](這也是 AWS 官方建議的方式)來建立 ALB / NLB。然而,在預設的情況下,一個 Ingress 會對應到一個 ALB。一個 Service 會對應到一個 NLB。但是很多時候會為了節省成本(或是業務確實沒有那麼大流量的需求)來減少 ALB / NLB 的數量。這邊介紹一些可以共用 ALB / NLB 的方式。

ALB

在使用 aws-load-balancer-controller 的情況下,可以透過 IngressGroup[2] 這個功能來達成共用 ALB 的需求。具體做法是透過為 Ingress 資源添加 alb.ingress.kubernetes.io/group.name annotations。以下為範例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: orange-purple-ingress
namespace: orange-purple-ns
labels:
app: color-2
annotations:
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/target-type: ip
alb.ingress.kubernetes.io/group.name: app-color-lb
spec:
ingressClassName: alb
rules:
- http:
paths:
- path: /orange
pathType: Prefix
backend:
service:
name: orange-service
port:
number: 80

NLB

在使用 aws-load-balancer-controller 的情況下,官方目前並沒有一個推薦的方式可以做到這件事情。以下提供一些做法:

  1. 自行建立 NLB / Listener / Targetgroup 等資源,並在 EKS 叢集當中建立 TargetGroupBinding[3] 資源,讓叢集當中多個 Service 可以共用同一個 NLB。以下為範例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
apiVersion: elbv2.k8s.aws/v1beta1
kind: TargetGroupBinding
metadata:
name: red-tgb
namespace: red-ns
spec:
serviceRef:
name: red-service
port: 80
targetGroupARN: <target-group-arn>
networking:
ingress:
- from:
- ipBlock:
cidr: "0.0.0.0/0"
ports:
- port: 80
  1. 上面的方式雖然可行,但是 NLB 就會脫離 EKS 叢集的掌控。如果想要讓 NLB 也可以被叢集管理,可以透過為 Service 建立不同的 port,並且讓不同的 port 對應到不同的 Deployment[4]。值得注意的是,這個方式似乎一定要使用 named ports。以下為範例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend
spec:
replicas: 1
selector:
matchLabels:
app: exampleapp
role: fe
template:
metadata:
labels:
app: exampleapp
role: fe
spec:
containers:
- name: nginx
image: patientplatypus/kubeplayfrontend
ports:
- name: frontend
containerPort: 3000
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend
spec:
replicas: 1
selector:
matchLabels:
app: exampleapp
role: be
template:
metadata:
labels:
app: exampleapp
role: be
spec:
containers:
- name: nginx
image: patientplatypus/kubeplaybackend
ports:
- name: backend
containerPort: 5000
---
apiVersion: v1
kind: Service
metadata:
name: entrypt
spec:
type: LoadBalancer
ports:
- name: backend
port: 8080
targetPort: backend
- name: frontend
port: 8081
targetPort: frontend
selector:
app: exampleapp

參考

[1] https://kubernetes-sigs.github.io/aws-load-balancer-controller/v2.8/
[2] https://kubernetes-sigs.github.io/aws-load-balancer-controller/v2.8/guide/ingress/annotations/#ingressgroup
[3] https://kubernetes-sigs.github.io/aws-load-balancer-controller/v2.8/guide/targetgroupbinding/targetgroupbinding/#targetgroupbinding
[4] https://github.com/kubernetes/kubernetes/issues/24875#issuecomment-794596576