@@ -3,20 +3,22 @@ package tg
3
3
import (
4
4
"context"
5
5
"fmt"
6
-
7
- "github.com/kubernetes-sigs/aws-alb-ingress-controller/internal/albctx"
8
-
9
- "github.com/kubernetes-sigs/aws-alb-ingress-controller/internal/k8s"
6
+ "strconv"
10
7
11
8
"github.com/aws/aws-sdk-go/service/elbv2"
12
9
"github.com/kubernetes-sigs/aws-alb-ingress-controller/internal/alb/tags"
10
+ "github.com/kubernetes-sigs/aws-alb-ingress-controller/internal/albctx"
13
11
"github.com/kubernetes-sigs/aws-alb-ingress-controller/internal/aws"
14
12
"github.com/kubernetes-sigs/aws-alb-ingress-controller/internal/ingress/annotations"
13
+ "github.com/kubernetes-sigs/aws-alb-ingress-controller/internal/ingress/annotations/healthcheck"
15
14
"github.com/kubernetes-sigs/aws-alb-ingress-controller/internal/ingress/backend"
16
15
"github.com/kubernetes-sigs/aws-alb-ingress-controller/internal/ingress/controller/store"
16
+ "github.com/kubernetes-sigs/aws-alb-ingress-controller/internal/k8s"
17
17
util "github.com/kubernetes-sigs/aws-alb-ingress-controller/pkg/util/types"
18
+ "github.com/pkg/errors"
18
19
extensions "k8s.io/api/extensions/v1beta1"
19
20
"k8s.io/apimachinery/pkg/types"
21
+ "k8s.io/apimachinery/pkg/util/intstr"
20
22
)
21
23
22
24
// The port used when creating targetGroup serves as a default value for targets registered without port specified.
@@ -67,19 +69,27 @@ func (controller *defaultController) Reconcile(ctx context.Context, ingress *ext
67
69
if err != nil {
68
70
return TargetGroup {}, fmt .Errorf ("failed to load serviceAnnotation due to %v" , err )
69
71
}
72
+
70
73
protocol := aws .StringValue (serviceAnnos .TargetGroup .BackendProtocol )
71
74
targetType := aws .StringValue (serviceAnnos .TargetGroup .TargetType )
75
+
76
+ healthCheckPort , err := controller .resolveServiceHealthCheckPort (ingress .Namespace , backend .ServiceName , intstr .Parse (* serviceAnnos .HealthCheck .Port ), targetType )
77
+
78
+ if err != nil {
79
+ return TargetGroup {}, fmt .Errorf ("failed to resolve healthcheck port due to %v" , err )
80
+ }
81
+
72
82
tgName := controller .nameTagGen .NameTG (ingress .Namespace , ingress .Name , backend .ServiceName , backend .ServicePort .String (), targetType , protocol )
73
83
tgInstance , err := controller .findExistingTGInstance (ctx , tgName )
74
84
if err != nil {
75
85
return TargetGroup {}, fmt .Errorf ("failed to find existing targetGroup due to %v" , err )
76
86
}
77
87
if tgInstance == nil {
78
- if tgInstance , err = controller .newTGInstance (ctx , tgName , serviceAnnos ); err != nil {
88
+ if tgInstance , err = controller .newTGInstance (ctx , tgName , serviceAnnos , healthCheckPort ); err != nil {
79
89
return TargetGroup {}, fmt .Errorf ("failed to create targetGroup due to %v" , err )
80
90
}
81
91
} else {
82
- if tgInstance , err = controller .reconcileTGInstance (ctx , tgInstance , serviceAnnos ); err != nil {
92
+ if tgInstance , err = controller .reconcileTGInstance (ctx , tgInstance , serviceAnnos , healthCheckPort ); err != nil {
83
93
return TargetGroup {}, fmt .Errorf ("failed to modify targetGroup due to %v" , err )
84
94
}
85
95
}
@@ -97,20 +107,21 @@ func (controller *defaultController) Reconcile(ctx context.Context, ingress *ext
97
107
if err = controller .targetsController .Reconcile (ctx , tgTargets ); err != nil {
98
108
return TargetGroup {}, fmt .Errorf ("failed to reconcile targetGroup targets due to %v" , err )
99
109
}
110
+
100
111
return TargetGroup {
101
112
Arn : tgArn ,
102
113
TargetType : targetType ,
103
114
Targets : tgTargets .Targets ,
104
115
}, nil
105
116
}
106
117
107
- func (controller * defaultController ) newTGInstance (ctx context.Context , name string , serviceAnnos * annotations.Service ) (* elbv2.TargetGroup , error ) {
118
+ func (controller * defaultController ) newTGInstance (ctx context.Context , name string , serviceAnnos * annotations.Service , healthCheckPort string ) (* elbv2.TargetGroup , error ) {
108
119
albctx .GetLogger (ctx ).Infof ("creating target group %v" , name )
109
120
resp , err := controller .cloud .CreateTargetGroupWithContext (ctx , & elbv2.CreateTargetGroupInput {
110
121
Name : aws .String (name ),
111
122
HealthCheckPath : serviceAnnos .HealthCheck .Path ,
112
123
HealthCheckIntervalSeconds : serviceAnnos .HealthCheck .IntervalSeconds ,
113
- HealthCheckPort : serviceAnnos . HealthCheck . Port ,
124
+ HealthCheckPort : aws . String ( healthCheckPort ) ,
114
125
HealthCheckProtocol : serviceAnnos .HealthCheck .Protocol ,
115
126
HealthCheckTimeoutSeconds : serviceAnnos .HealthCheck .TimeoutSeconds ,
116
127
TargetType : serviceAnnos .TargetGroup .TargetType ,
@@ -128,14 +139,15 @@ func (controller *defaultController) newTGInstance(ctx context.Context, name str
128
139
return tgInstance , nil
129
140
}
130
141
131
- func (controller * defaultController ) reconcileTGInstance (ctx context.Context , instance * elbv2.TargetGroup , serviceAnnos * annotations.Service ) (* elbv2.TargetGroup , error ) {
142
+ func (controller * defaultController ) reconcileTGInstance (ctx context.Context , instance * elbv2.TargetGroup , serviceAnnos * annotations.Service , healthCheckPort string ) (* elbv2.TargetGroup , error ) {
132
143
if controller .TGInstanceNeedsModification (ctx , instance , serviceAnnos ) {
133
144
albctx .GetLogger (ctx ).Infof ("modify target group %v" , aws .StringValue (instance .TargetGroupArn ))
145
+
134
146
output , err := controller .cloud .ModifyTargetGroupWithContext (ctx , & elbv2.ModifyTargetGroupInput {
135
147
TargetGroupArn : instance .TargetGroupArn ,
136
148
HealthCheckPath : serviceAnnos .HealthCheck .Path ,
137
149
HealthCheckIntervalSeconds : serviceAnnos .HealthCheck .IntervalSeconds ,
138
- HealthCheckPort : serviceAnnos . HealthCheck . Port ,
150
+ HealthCheckPort : aws . String ( healthCheckPort ) ,
139
151
HealthCheckProtocol : serviceAnnos .HealthCheck .Protocol ,
140
152
HealthCheckTimeoutSeconds : serviceAnnos .HealthCheck .TimeoutSeconds ,
141
153
Matcher : & elbv2.Matcher {HttpCode : serviceAnnos .TargetGroup .SuccessCodes },
@@ -150,6 +162,43 @@ func (controller *defaultController) reconcileTGInstance(ctx context.Context, in
150
162
return instance , nil
151
163
}
152
164
165
+ // resolveServiceHealthCheckPort checks if the service-port annotation is a string. If so, it tries to look up a port with the same name
166
+ // on the service and use that port's NodePort as the health check port.
167
+ func (controller * defaultController ) resolveServiceHealthCheckPort (namespace string , serviceName string , servicePortAnnotation intstr.IntOrString , targetType string ) (string , error ) {
168
+
169
+ if servicePortAnnotation .Type == intstr .Int {
170
+ //Nothing to do if it's an Int - return original value
171
+ return servicePortAnnotation .String (), nil
172
+ }
173
+
174
+ servicePort := servicePortAnnotation .String ()
175
+
176
+ //If the annotation uses the default port ("traffic-port"), do not try to look up a port by that name.
177
+ if servicePort == healthcheck .DefaultPort {
178
+ return servicePort , nil
179
+ }
180
+
181
+ serviceKey := namespace + "/" + serviceName
182
+ service , err := controller .store .GetService (serviceKey )
183
+
184
+ if err != nil {
185
+ return servicePort , errors .Wrap (err , "failed to resolve healthcheck service name" )
186
+ }
187
+
188
+ resolvedServicePort , err := k8s .LookupServicePort (service , servicePortAnnotation )
189
+ if err != nil {
190
+ return servicePort , errors .Wrap (err , "failed to resolve healthcheck port for service" )
191
+ }
192
+ if targetType == elbv2 .TargetTypeEnumInstance {
193
+ if resolvedServicePort .NodePort == 0 {
194
+ return servicePort , fmt .Errorf ("failed to find valid NodePort for service %s with port %s" , serviceName , resolvedServicePort .Name )
195
+ }
196
+ return strconv .Itoa (int (resolvedServicePort .NodePort )), nil
197
+ }
198
+ return resolvedServicePort .TargetPort .String (), nil
199
+
200
+ }
201
+
153
202
func (controller * defaultController ) TGInstanceNeedsModification (ctx context.Context , instance * elbv2.TargetGroup , serviceAnnos * annotations.Service ) bool {
154
203
needsChange := false
155
204
if ! util .DeepEqual (instance .HealthCheckPath , serviceAnnos .HealthCheck .Path ) {
0 commit comments