Skip to content

Commit a224187

Browse files
committed
MAJOR: add default server service behavior to k8s services
if no default service is defined, one will be created locally. it will behave the same way as other default services - 200 on healtz - 404 on all other endpoints
1 parent 2db8997 commit a224187

File tree

8 files changed

+151
-12
lines changed

8 files changed

+151
-12
lines changed

main.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"fmt"
2020
"os"
2121
"os/signal"
22+
"strconv"
2223
"strings"
2324
"syscall"
2425

@@ -74,6 +75,7 @@ func main() {
7475
defaultBackendSvc := fmt.Sprint(osArgs.DefaultBackendService)
7576
defaultCertificate := fmt.Sprint(osArgs.DefaultCertificate)
7677
annotations.SetDefaultValue("default-backend-service", defaultBackendSvc)
78+
annotations.SetDefaultValue("default-backend-port", strconv.Itoa(osArgs.DefaultBackendPort))
7779
annotations.SetDefaultValue("ssl-certificate", defaultCertificate)
7880

7981
// Start Controller
@@ -138,7 +140,11 @@ func logInfo(logger utils.Logger, osArgs utils.OSArgs) {
138140
logger.Printf("Ingress class: %s", osArgs.IngressClass)
139141
logger.Printf("Empty Ingress class: %t", osArgs.EmptyIngressClass)
140142
logger.Printf("Publish service: %s", osArgs.PublishService)
141-
logger.Printf("Default backend service: %s", osArgs.DefaultBackendService)
143+
if osArgs.DefaultBackendService.String() != "" {
144+
logger.Printf("Default backend service: %s", osArgs.DefaultBackendService)
145+
} else {
146+
logger.Printf("Using local backend service on port: %s", osArgs.DefaultBackendPort)
147+
}
142148
logger.Printf("Default ssl certificate: %s", osArgs.DefaultCertificate)
143149
if !osArgs.DisableHTTP {
144150
logger.Printf("Frontend HTTP listening on: %s:%d", osArgs.IPV4BindAddr, osArgs.HTTPBindPort)

pkg/controller/builder.go

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -120,23 +120,23 @@ func (builder *Builder) Build() *HAProxyController {
120120
}
121121

122122
chShutdown := make(chan struct{})
123-
rtr := router.New()
124123
if builder.osArgs.ControllerPort != 0 {
124+
rtr := router.New()
125125
var runningServices string
126126
if builder.osArgs.PprofEnabled {
127127
rtr.GET("/debug/pprof/{profile:*}", pprofhandler.PprofHandler)
128-
runningServices += " pprof,"
128+
runningServices += " pprof"
129129
}
130130
if builder.osArgs.PrometheusEnabled {
131131
rtr.GET("/metrics", fasthttpadaptor.NewFastHTTPHandler(promhttp.Handler()))
132-
runningServices += " prometheus,"
132+
runningServices += ", prometheus"
133133
}
134-
runningServices += " default service"
135134
rtr.GET("/healtz", requestHandler)
136135
// all others will be 404
137136
go func() {
138137
server := fasthttp.Server{
139-
Handler: rtr.Handler,
138+
Handler: rtr.Handler,
139+
NoDefaultServerHeader: true,
140140
}
141141
go func() {
142142
<-chShutdown
@@ -152,6 +152,29 @@ func (builder *Builder) Build() *HAProxyController {
152152
}()
153153
}
154154

155+
if builder.osArgs.DefaultBackendService.String() == "" {
156+
rtr := router.New()
157+
rtr.GET("/healtz", requestHandler)
158+
// all others will be 404
159+
go func() {
160+
server := fasthttp.Server{
161+
Handler: rtr.Handler,
162+
NoDefaultServerHeader: true,
163+
}
164+
go func() {
165+
<-chShutdown
166+
if err := server.Shutdown(); err != nil {
167+
logger.Errorf("Could not gracefully shutdown controller data server: %v\n", err)
168+
} else {
169+
logger.Errorf("Gracefully shuting down controller data server")
170+
}
171+
}()
172+
logger.Infof("running default backend server on :%d", builder.osArgs.DefaultBackendPort)
173+
err := server.ListenAndServe(":" + strconv.Itoa(builder.osArgs.DefaultBackendPort))
174+
logger.Error(err)
175+
}()
176+
}
177+
155178
haproxy, err := haproxy.New(builder.osArgs, builder.haproxyEnv, builder.haproxyCfgFile, builder.haproxyProcess, builder.haproxyClient, builder.haproxyRules)
156179
logger.Panic(err)
157180

pkg/controller/global.go

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -148,15 +148,15 @@ func (c *HAProxyController) defaultsCfg() (reload bool) {
148148
// handleDefaultService configures HAProy default backend provided via cli param "default-backend-service"
149149
func (c *HAProxyController) handleDefaultService() (reload bool) {
150150
var svc *service.Service
151-
ns, name, err := common.GetK8sPath("default-backend-service", c.store.ConfigMaps.Main.Annotations)
151+
namespace, name, err := common.GetK8sPath("default-backend-service", c.store.ConfigMaps.Main.Annotations)
152152
if err != nil {
153153
logger.Errorf("default service: %s", err)
154154
}
155155
if name == "" {
156-
return
156+
return c.handleDefaultServicePort()
157157
}
158158
ingressPath := &store.IngressPath{
159-
SvcNamespace: ns,
159+
SvcNamespace: namespace,
160160
SvcName: name,
161161
IsDefaultBackend: true,
162162
}
@@ -166,7 +166,42 @@ func (c *HAProxyController) handleDefaultService() (reload bool) {
166166
if err != nil {
167167
logger.Errorf("default service: %s", err)
168168
}
169-
return
169+
return false
170+
}
171+
172+
// handleDefaultServicePort configures local HAProy default backend provided via cli param "default-backend-port"
173+
func (c *HAProxyController) handleDefaultServicePort() (reload bool) {
174+
var svc *service.Service
175+
_, portStr, err := common.GetK8sPath("default-backend-port", c.store.ConfigMaps.Main.Annotations)
176+
if err != nil {
177+
logger.Errorf("default backend port: %s", err)
178+
}
179+
if portStr == "" {
180+
return
181+
}
182+
defaultLocalBackend := "default_local_backend"
183+
ingressPath := &store.IngressPath{
184+
SvcNamespace: "",
185+
SvcName: defaultLocalBackend,
186+
SvcPortString: portStr,
187+
IsDefaultBackend: true,
188+
}
189+
190+
err = c.haproxy.BackendCreate(models.Backend{
191+
Name: defaultLocalBackend,
192+
})
193+
if err != nil {
194+
logger.Errorf("default backend port: %s", err)
195+
}
196+
backend, _ := c.haproxy.BackendGet(defaultLocalBackend)
197+
198+
if svc, err = service.NewLocal(c.store, ingressPath, backend, c.store.ConfigMaps.Main.Annotations); err == nil {
199+
reload, err = svc.SetDefaultBackend(c.store, c.haproxy, []string{c.haproxy.FrontHTTP, c.haproxy.FrontHTTPS}, c.annotations)
200+
}
201+
if err != nil {
202+
logger.Errorf("default service port: %s", err)
203+
}
204+
return true
170205
}
171206

172207
// handleDefaultCert configures default/fallback HAProxy certificate to use for client HTTPS requests.

pkg/controller/handler.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,12 @@ func (c *HAProxyController) initHandlers() {
5454
if c.osArgs.PprofEnabled {
5555
c.updateHandlers = append(c.updateHandlers, handler.Pprof{})
5656
}
57+
if c.osArgs.DefaultBackendService.String() == "" {
58+
c.updateHandlers = append(c.updateHandlers, handler.DefaultLocalService{
59+
Name: "default_local_backend",
60+
Port: c.osArgs.DefaultBackendPort,
61+
})
62+
}
5763
c.updateHandlers = append(c.updateHandlers, handler.Refresh{})
5864
}
5965

@@ -69,7 +75,8 @@ func (c *HAProxyController) startupHandlers() error {
6975
HTTPSPort: c.osArgs.HTTPSBindPort,
7076
IPv4Addr: c.osArgs.IPV4BindAddr,
7177
IPv6Addr: c.osArgs.IPV6BindAddr,
72-
}}
78+
},
79+
}
7380
for _, handler := range handlers {
7481
_, err := handler.Update(c.store, c.haproxy, c.annotations)
7582
if err != nil {

pkg/handler/default-local-service.go

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// Copyright 2019 HAProxy Technologies LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package handler
16+
17+
import (
18+
"strconv"
19+
20+
"github.com/haproxytech/client-native/v3/models"
21+
22+
"github.com/haproxytech/kubernetes-ingress/pkg/annotations"
23+
"github.com/haproxytech/kubernetes-ingress/pkg/haproxy"
24+
"github.com/haproxytech/kubernetes-ingress/pkg/store"
25+
)
26+
27+
type DefaultLocalService struct {
28+
Name string
29+
Port int
30+
}
31+
32+
func (handler DefaultLocalService) Update(k store.K8s, api haproxy.HAProxy, ann annotations.Annotations) (reload bool, err error) {
33+
_, err = api.ServerGet("ingress_controller", handler.Name)
34+
if err != nil {
35+
/*err = api.BackendCreate(models.Backend{
36+
Name: DefaultLocalBackend,
37+
Mode: "http",
38+
})
39+
if err != nil {
40+
return false, err
41+
}*/
42+
err = api.BackendServerCreate(handler.Name, models.Server{
43+
Name: "ingress_controller",
44+
Address: "127.0.0.1:" + strconv.Itoa(handler.Port),
45+
})
46+
if err != nil {
47+
return false, err
48+
}
49+
logger.Debug("DefaultLocalService backend created")
50+
}
51+
return false, nil
52+
}

pkg/service/endpoints.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ func (s *Service) HandleHAProxySrvs(store store.K8s, client api.HAProxyClient) (
3030
var srvsScaled bool
3131
backend, err := s.getRuntimeBackend(store)
3232
if err != nil {
33+
if s.backend != nil && s.backend.Name == "default_local_backend" {
34+
return
35+
}
3336
logger.Warningf("Ingress '%s/%s': %s", s.resource.Namespace, s.resource.Name, err)
3437
if servers, _ := client.BackendServersGet(s.backend.Name); servers != nil {
3538
client.BackendServerDeleteAll(s.backend.Name)

pkg/service/service.go

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,18 @@ func New(k store.K8s, path *store.IngressPath, certs certs.Certificates, tcpServ
6363
}, nil
6464
}
6565

66+
// NewLocal returns a Service instance to handle the k8s IngressPath resource given in params.
67+
func NewLocal(k store.K8s, path *store.IngressPath, backend *models.Backend, annList ...map[string]string) (*Service, error) {
68+
return &Service{
69+
path: path,
70+
resource: &store.Service{
71+
Annotations: map[string]string{},
72+
},
73+
annotations: annList,
74+
backend: backend,
75+
}, nil
76+
}
77+
6678
func (s *Service) GetResource() *store.Service {
6779
return s.resource
6880
}
@@ -140,7 +152,7 @@ func (s *Service) HandleBackend(store store.K8s, client api.HAProxyClient, a ann
140152
return
141153
}
142154

143-
// getBackendModel checks for a corresponding custom resource before falling back to annoations
155+
// getBackendModel checks for a corresponding custom resource before falling back to annotations
144156
func (s *Service) getBackendModel(store store.K8s, a annotations.Annotations) (backend *models.Backend, err error) {
145157
// Backend mode
146158
mode := "http"

pkg/utils/flags.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ type OSArgs struct { //nolint:maligned
6969
Help []bool `short:"h" long:"help" description:"show this help message"`
7070
Version []bool `short:"v" long:"version" description:"version"`
7171
DefaultBackendService NamespaceValue `long:"default-backend-service" default:"" description:"default service to serve 404 page. If not specified HAProxy serves http 400"`
72+
DefaultBackendPort int `long:"default-backend-port" description:"port to use for default service" default:"6061"`
7273
DefaultCertificate NamespaceValue `long:"default-ssl-certificate" default:"" description:"secret name of the certificate"`
7374
ConfigMap NamespaceValue `long:"configmap" description:"configmap designated for HAProxy" default:""`
7475
ConfigMapTCPServices NamespaceValue `long:"configmap-tcp-services" description:"configmap used to define tcp services" default:""`

0 commit comments

Comments
 (0)