Skip to content

Commit 7aec8c2

Browse files
authored
perf: add access url (#2341)
Signed-off-by: 张启航 <[email protected]>
1 parent 7ad7b71 commit 7aec8c2

File tree

2 files changed

+124
-17
lines changed

2 files changed

+124
-17
lines changed

api/controller/apigateway/api_gateway_loadbalancer.go

Lines changed: 122 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
package apigateway
2020

2121
import (
22+
"context"
2223
"fmt"
2324
"net/http"
2425
"strings"
@@ -38,6 +39,56 @@ import (
3839
"k8s.io/apimachinery/pkg/util/intstr"
3940
)
4041

42+
// getNodeIPs 获取集群节点的IP地址列表
43+
func getNodeIPs(k8sComponent *k8s.Component) ([]string, error) {
44+
nodeList, err := k8sComponent.Clientset.CoreV1().Nodes().List(context.TODO(), v1.ListOptions{})
45+
if err != nil {
46+
return nil, err
47+
}
48+
49+
var nodeIPs []string
50+
for _, node := range nodeList.Items {
51+
// 优先使用外网IP,如果没有则使用内网IP
52+
var nodeIP string
53+
for _, address := range node.Status.Addresses {
54+
if address.Type == corev1.NodeExternalIP && address.Address != "" {
55+
nodeIP = address.Address
56+
break
57+
}
58+
}
59+
if nodeIP == "" {
60+
for _, address := range node.Status.Addresses {
61+
if address.Type == corev1.NodeInternalIP && address.Address != "" {
62+
nodeIP = address.Address
63+
break
64+
}
65+
}
66+
}
67+
if nodeIP != "" {
68+
nodeIPs = append(nodeIPs, nodeIP)
69+
}
70+
}
71+
return nodeIPs, nil
72+
}
73+
74+
// generateAccessURLs 生成访问地址列表
75+
func generateAccessURLs(nodeIPs []string, ports []model.LoadBalancerPort) []string {
76+
var accessURLs []string
77+
for _, nodeIP := range nodeIPs {
78+
for _, port := range ports {
79+
if port.NodePort > 0 {
80+
protocol := "http"
81+
if strings.ToUpper(port.Protocol) == "UDP" {
82+
protocol = "udp"
83+
}
84+
url := fmt.Sprintf("%s://%s:%d", protocol, nodeIP, port.NodePort)
85+
accessURLs = append(accessURLs, url)
86+
}
87+
}
88+
}
89+
return accessURLs
90+
}
91+
4192
// CreateLoadBalancer 创建LoadBalancer服务
4293
func (g Struct) CreateLoadBalancer(w http.ResponseWriter, r *http.Request) {
4394
tenant := r.Context().Value(ctxutil.ContextKey("tenant")).(*dbmodel.Tenants)
@@ -117,12 +168,12 @@ func (g Struct) CreateLoadBalancer(w http.ResponseWriter, r *http.Request) {
117168
labels["service_id"] = serviceID
118169
}
119170
labels["service_alias"] = createLBReq.ServiceName
120-
// 记录端口信息(多个端口用逗号分隔
121-
var ports []string
171+
// 记录端口信息(多个端口用下划线分隔,符合K8s标签规范
172+
var portStrings []string
122173
for _, port := range createLBReq.Ports {
123-
ports = append(ports, fmt.Sprintf("%d", port.Port))
174+
portStrings = append(portStrings, fmt.Sprintf("%d", port.Port))
124175
}
125-
labels["ports"] = strings.Join(ports, ",")
176+
labels["ports"] = strings.Join(portStrings, "_")
126177

127178
// 创建注解
128179
annotations := make(map[string]string)
@@ -149,13 +200,39 @@ func (g Struct) CreateLoadBalancer(w http.ResponseWriter, r *http.Request) {
149200
return
150201
}
151202

203+
// 转换端口信息,包含NodePort
204+
var responsePorts []model.LoadBalancerPort
205+
for _, port := range createdService.Spec.Ports {
206+
responsePorts = append(responsePorts, model.LoadBalancerPort{
207+
Port: int(port.Port),
208+
TargetPort: port.TargetPort.IntValue(),
209+
Protocol: string(port.Protocol),
210+
Name: port.Name,
211+
NodePort: port.NodePort,
212+
})
213+
}
214+
215+
// 获取节点IP列表
216+
nodeIPs, err := getNodeIPs(k8s.Default())
217+
if err != nil {
218+
logrus.Warnf("get node IPs error %s", err.Error())
219+
// 不影响主要功能,继续执行
220+
}
221+
222+
// 生成访问地址
223+
var accessURLs []string
224+
if len(nodeIPs) > 0 {
225+
accessURLs = generateAccessURLs(nodeIPs, responsePorts)
226+
}
227+
152228
// 构造响应
153229
response := &model.LoadBalancerResponse{
154230
Name: createdService.Name,
155231
Namespace: createdService.Namespace,
156232
ServiceName: createLBReq.ServiceName,
157-
Ports: createLBReq.Ports,
233+
Ports: responsePorts,
158234
ExternalIPs: createdService.Spec.ExternalIPs,
235+
AccessURLs: accessURLs,
159236
Annotations: createdService.Annotations,
160237
Status: "Creating",
161238
CreatedAt: createdService.CreationTimestamp.Format(time.RFC3339),
@@ -208,29 +285,43 @@ func (g Struct) GetLoadBalancer(w http.ResponseWriter, r *http.Request) {
208285
return
209286
}
210287

288+
// 获取节点IP列表(只获取一次,避免重复调用)
289+
nodeIPs, err := getNodeIPs(k8s.Default())
290+
if err != nil {
291+
logrus.Warnf("get node IPs error %s", err.Error())
292+
}
293+
211294
var responses []*model.LoadBalancerResponse
212295
for _, service := range list.Items {
213296
if service.Spec.Type != corev1.ServiceTypeLoadBalancer {
214297
continue
215298
}
216299

217-
// 转换端口信息
218-
var ports []model.LoadBalancerPort
300+
// 转换端口信息,包含NodePort
301+
var servicePorts []model.LoadBalancerPort
219302
for _, port := range service.Spec.Ports {
220-
ports = append(ports, model.LoadBalancerPort{
303+
servicePorts = append(servicePorts, model.LoadBalancerPort{
221304
Port: int(port.Port),
222305
TargetPort: port.TargetPort.IntValue(),
223306
Protocol: string(port.Protocol),
224307
Name: port.Name,
308+
NodePort: port.NodePort,
225309
})
226310
}
227311

312+
// 生成访问地址
313+
var accessURLs []string
314+
if len(nodeIPs) > 0 {
315+
accessURLs = generateAccessURLs(nodeIPs, servicePorts)
316+
}
317+
228318
response := &model.LoadBalancerResponse{
229319
Name: service.Name,
230320
Namespace: service.Namespace,
231321
ServiceName: service.Labels["service_alias"],
232-
Ports: ports,
322+
Ports: servicePorts,
233323
ExternalIPs: service.Spec.ExternalIPs,
324+
AccessURLs: accessURLs,
234325
Annotations: service.Annotations,
235326
Status: "Creating",
236327
CreatedAt: service.CreationTimestamp.Format(time.RFC3339),
@@ -384,12 +475,12 @@ func (g Struct) UpdateLoadBalancer(w http.ResponseWriter, r *http.Request) {
384475
}
385476
service.Spec.Ports = servicePorts
386477

387-
// 更新标签中的端口信息
388-
var ports []string
478+
// 更新标签中的端口信息(多个端口用下划线分隔,符合K8s标签规范)
479+
var updatePortStrings []string
389480
for _, port := range updateLBReq.Ports {
390-
ports = append(ports, fmt.Sprintf("%d", port.Port))
481+
updatePortStrings = append(updatePortStrings, fmt.Sprintf("%d", port.Port))
391482
}
392-
service.Labels["ports"] = strings.Join(ports, ",")
483+
service.Labels["ports"] = strings.Join(updatePortStrings, "_")
393484
}
394485

395486
// 更新注解
@@ -410,24 +501,38 @@ func (g Struct) UpdateLoadBalancer(w http.ResponseWriter, r *http.Request) {
410501
return
411502
}
412503

413-
// 转换端口信息
414-
var ports []model.LoadBalancerPort
504+
// 转换端口信息,包含NodePort
505+
var updatedPorts []model.LoadBalancerPort
415506
for _, port := range updatedService.Spec.Ports {
416-
ports = append(ports, model.LoadBalancerPort{
507+
updatedPorts = append(updatedPorts, model.LoadBalancerPort{
417508
Port: int(port.Port),
418509
TargetPort: port.TargetPort.IntValue(),
419510
Protocol: string(port.Protocol),
420511
Name: port.Name,
512+
NodePort: port.NodePort,
421513
})
422514
}
423515

516+
// 获取节点IP列表
517+
nodeIPs, err := getNodeIPs(k8s.Default())
518+
if err != nil {
519+
logrus.Warnf("get node IPs error %s", err.Error())
520+
}
521+
522+
// 生成访问地址
523+
var accessURLs []string
524+
if len(nodeIPs) > 0 {
525+
accessURLs = generateAccessURLs(nodeIPs, updatedPorts)
526+
}
527+
424528
// 构造响应
425529
response := &model.LoadBalancerResponse{
426530
Name: updatedService.Name,
427531
Namespace: updatedService.Namespace,
428532
ServiceName: updatedService.Labels["service_alias"],
429-
Ports: ports,
533+
Ports: updatedPorts,
430534
ExternalIPs: updatedService.Spec.ExternalIPs,
535+
AccessURLs: accessURLs,
431536
Annotations: updatedService.Annotations,
432537
Status: "Creating",
433538
CreatedAt: updatedService.CreationTimestamp.Format(time.RFC3339),

api/model/gateway_model.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,7 @@ type LoadBalancerPort struct {
392392
TargetPort int `json:"target_port" validate:"required"` // 目标端口
393393
Protocol string `json:"protocol" validate:"required"` // 协议类型 TCP/UDP
394394
Name string `json:"name,omitempty"` // 端口名称
395+
NodePort int32 `json:"node_port,omitempty"` // NodePort 端口(如果有)
395396
}
396397

397398
// CreateLoadBalancerStruct 创建LoadBalancer的请求结构体
@@ -414,6 +415,7 @@ type LoadBalancerResponse struct {
414415
ServiceName string `json:"service_name"`
415416
Ports []LoadBalancerPort `json:"ports"`
416417
ExternalIPs []string `json:"external_ips,omitempty"`
418+
AccessURLs []string `json:"access_urls,omitempty"` // 访问地址列表,格式:http://nodeip:nodeport(port)
417419
Annotations map[string]string `json:"annotations,omitempty"`
418420
Status string `json:"status"`
419421
CreatedAt string `json:"created_at"`

0 commit comments

Comments
 (0)