@@ -2,10 +2,15 @@ package util
22
33import (
44 "context"
5+ "sync"
56
67 "github.com/pkg/errors"
8+ corev1 "k8s.io/api/core/v1"
9+ "k8s.io/client-go/tools/record"
710
811 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"
914 "github.com/imroc/tke-extend-network-controller/pkg/util"
1015 "sigs.k8s.io/controller-runtime/pkg/client"
1116 "sigs.k8s.io/controller-runtime/pkg/log"
@@ -14,24 +19,83 @@ import (
1419type PortPool struct {
1520 * networkingv1alpha1.CLBPortPool
1621 client.Client
22+ record.EventRecorder
23+ mu sync.Mutex
24+ creating bool
1725}
1826
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" )
2032 pp := & networkingv1alpha1.CLBPortPool {}
2133 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
2344 }
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
2649 }
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
2994 }
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 )
3397 }
34- return 1 , nil // 成功通知扩容
98+ return portpool . CreateLbResultSuccess , nil
3599}
36100
37101func (p * PortPool ) GetStartPort () uint16 {
@@ -52,10 +116,11 @@ func (p *PortPool) GetSegmentLength() uint16 {
52116 return * p .Spec .SegmentLength
53117}
54118
55- func NewPortPool (pp * networkingv1alpha1.CLBPortPool , c client.Client ) * PortPool {
119+ func NewPortPool (pp * networkingv1alpha1.CLBPortPool , c client.Client , recorder record. EventRecorder ) * PortPool {
56120 return & PortPool {
57- CLBPortPool : pp ,
58- Client : c ,
121+ CLBPortPool : pp ,
122+ Client : c ,
123+ EventRecorder : recorder ,
59124 }
60125}
61126
0 commit comments