@@ -2,10 +2,15 @@ package util
2
2
3
3
import (
4
4
"context"
5
+ "sync"
5
6
6
7
"github.com/pkg/errors"
8
+ corev1 "k8s.io/api/core/v1"
9
+ "k8s.io/client-go/tools/record"
7
10
8
11
networkingv1alpha1 "github.com/imroc/tke-extend-network-controller/api/v1alpha1"
12
+ "github.com/imroc/tke-extend-network-controller/internal/portpool"
13
+ "github.com/imroc/tke-extend-network-controller/pkg/clb"
9
14
"github.com/imroc/tke-extend-network-controller/pkg/util"
10
15
"sigs.k8s.io/controller-runtime/pkg/client"
11
16
"sigs.k8s.io/controller-runtime/pkg/log"
@@ -14,24 +19,83 @@ import (
14
19
type PortPool struct {
15
20
* networkingv1alpha1.CLBPortPool
16
21
client.Client
22
+ record.EventRecorder
23
+ mu sync.Mutex
24
+ creating bool
17
25
}
18
26
19
- func (p * PortPool ) TryNotifyCreateLB (ctx context.Context ) (int , error ) {
27
+ func (p * PortPool ) TryCreateLB (ctx context.Context ) (portpool.CreateLbResult , error ) {
28
+ if p .creating {
29
+ return portpool .CreateLbResultCreating , nil
30
+ }
31
+ log .FromContext (ctx ).V (10 ).Info ("TryCreateLB" )
20
32
pp := & networkingv1alpha1.CLBPortPool {}
21
33
if err := p .Get (ctx , client .ObjectKeyFromObject (p .CLBPortPool ), pp ); err != nil {
22
- return 0 , errors .WithStack (err )
34
+ return portpool .CreateLbResultError , errors .WithStack (err )
35
+ }
36
+ // 还未初始化的端口池,不能创建负载均衡器
37
+ if pp .Status .State == "" || pp .Status .State == networkingv1alpha1 .CLBPortPoolStatePending {
38
+ return portpool .CreateLbResultForbidden , nil
39
+ }
40
+ // 没有显式启用自动创建的端口池,不能创建负载均衡器
41
+ if pp .Spec .AutoCreate == nil || ! pp .Spec .AutoCreate .Enabled {
42
+ log .FromContext (ctx ).V (10 ).Info ("not able to create lb cuz auto create is not enabled" )
43
+ return portpool .CreateLbResultForbidden , nil
23
44
}
24
- if ! CanCreateLB (ctx , pp ) {
25
- return - 1 , nil
45
+ p .mu .Lock ()
46
+ defer p .mu .Unlock ()
47
+ if len (pp .Status .LoadbalancerStatuses ) > len (p .CLBPortPool .Status .LoadbalancerStatuses ) {
48
+ p .CLBPortPool = pp
26
49
}
27
- if pp .Status .State == networkingv1alpha1 .CLBPortPoolStateScaling { // 已经在扩容了
28
- return 2 , nil
50
+ // 自动创建的 CLB 数量达到配置上限的端口池,不能创建负载均衡器
51
+ if ! util .IsZero (pp .Spec .AutoCreate .MaxLoadBalancers ) { // 要读结构体中的,cache 获取到不一定是实时最新的
52
+ // 检查是否已创建了足够的 CLB
53
+ num := uint16 (0 )
54
+ for _ , lbStatus := range p .CLBPortPool .Status .LoadbalancerStatuses {
55
+ if lbStatus .AutoCreated != nil && * lbStatus .AutoCreated && lbStatus .State != networkingv1alpha1 .LoadBalancerStateNotFound {
56
+ num ++
57
+ }
58
+ }
59
+ // 如果已创建数量已满,则直接返回
60
+ if num >= * pp .Spec .AutoCreate .MaxLoadBalancers {
61
+ log .FromContext (ctx ).V (10 ).Info ("max auto-created loadbalancers is reached" , "num" , num , "max" , * pp .Spec .AutoCreate .MaxLoadBalancers )
62
+ return portpool .CreateLbResultForbidden , nil
63
+ }
64
+ }
65
+ p .creating = true
66
+ defer func () {
67
+ p .creating = false
68
+ }()
69
+ p .EventRecorder .Event (pp , corev1 .EventTypeNormal , "CreateLoadBalancer" , "try to create clb" )
70
+ lbId , err := clb .CreateCLB (ctx , pp .GetRegion (), clb .ConvertCreateLoadBalancerRequest (pp .Spec .AutoCreate .Parameters ))
71
+ if err != nil {
72
+ p .EventRecorder .Eventf (pp , corev1 .EventTypeWarning , "CreateLoadBalancer" , "create clb failed: %s" , err .Error ())
73
+ return portpool .CreateLbResultError , errors .WithStack (err )
74
+ }
75
+ p .EventRecorder .Eventf (pp , corev1 .EventTypeNormal , "CreateLoadBalancer" , "create clb success: %s" , lbId )
76
+ if err := portpool .Allocator .AddLbId (pp .Name , lbId ); err != nil {
77
+ return portpool .CreateLbResultError , errors .WithStack (err )
78
+ }
79
+ addLbIdToStatus := func () error {
80
+ pp := & networkingv1alpha1.CLBPortPool {}
81
+ if err := p .Client .Get (ctx , client .ObjectKeyFromObject (p .CLBPortPool ), pp ); err != nil {
82
+ return errors .WithStack (err )
83
+ }
84
+ pp .Status .State = networkingv1alpha1 .CLBPortPoolStateActive // 创建成功,状态改为 Active,以便再次可分配端口
85
+ pp .Status .LoadbalancerStatuses = append (pp .Status .LoadbalancerStatuses , networkingv1alpha1.LoadBalancerStatus {
86
+ LoadbalancerID : lbId ,
87
+ AutoCreated : util .GetPtr (true ),
88
+ })
89
+ if err := p .Client .Status ().Update (ctx , pp ); err != nil {
90
+ return errors .WithStack (err )
91
+ }
92
+ p .CLBPortPool = pp
93
+ return nil
29
94
}
30
- pp .Status .State = networkingv1alpha1 .CLBPortPoolStateScaling
31
- if err := p .Client .Status ().Update (ctx , pp ); err != nil {
32
- return 0 , errors .WithStack (err )
95
+ if err := util .RetryIfPossible (addLbIdToStatus ); err != nil {
96
+ return portpool .CreateLbResultError , errors .WithStack (err )
33
97
}
34
- return 1 , nil // 成功通知扩容
98
+ return portpool . CreateLbResultSuccess , nil
35
99
}
36
100
37
101
func (p * PortPool ) GetStartPort () uint16 {
@@ -52,10 +116,11 @@ func (p *PortPool) GetSegmentLength() uint16 {
52
116
return * p .Spec .SegmentLength
53
117
}
54
118
55
- func NewPortPool (pp * networkingv1alpha1.CLBPortPool , c client.Client ) * PortPool {
119
+ func NewPortPool (pp * networkingv1alpha1.CLBPortPool , c client.Client , recorder record. EventRecorder ) * PortPool {
56
120
return & PortPool {
57
- CLBPortPool : pp ,
58
- Client : c ,
121
+ CLBPortPool : pp ,
122
+ Client : c ,
123
+ EventRecorder : recorder ,
59
124
}
60
125
}
61
126
0 commit comments