Skip to content

Commit 4863c4c

Browse files
ivanmatmatioktalz
authored andcommitted
MINOR: prometheus access outside pod
1 parent 1dfb597 commit 4863c4c

File tree

6 files changed

+145
-3
lines changed

6 files changed

+145
-3
lines changed

pkg/annotations/cfgSnippet.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ func (a *CfgSnippet) Process(k store.K8s, annotations ...map[string]string) erro
188188
processConfigSnippet(a.backend, origin, data)
189189
}
190190
} else {
191-
if a.service != nil && anns[0] != "" {
191+
if a.service != nil && a.service.Name != "" && !a.service.Faked && anns[0] != "" {
192192
origin := a.service.Namespace + "/" + a.service.Name
193193
comment := COMMMENT_SERVICE_PREFIX + a.backend + "/" + origin + COMMENT_ENDING
194194
data := strings.Split(strings.Trim(anns[0], "\n"), "\n")

pkg/controller/builder.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import (
2929

3030
"github.com/haproxytech/kubernetes-ingress/pkg/annotations"
3131
gateway "github.com/haproxytech/kubernetes-ingress/pkg/gateways"
32+
"github.com/haproxytech/kubernetes-ingress/pkg/handler"
3233
"github.com/haproxytech/kubernetes-ingress/pkg/haproxy"
3334
"github.com/haproxytech/kubernetes-ingress/pkg/haproxy/api"
3435
"github.com/haproxytech/kubernetes-ingress/pkg/haproxy/env"
@@ -198,7 +199,7 @@ func addControllerMetricData(builder *Builder, chShutdown chan struct{}) {
198199
runningServices += " pprof"
199200
}
200201
if builder.osArgs.PrometheusEnabled {
201-
rtr.GET("/metrics", fasthttpadaptor.NewFastHTTPHandler(promhttp.Handler()))
202+
rtr.GET(handler.PROMETHEUS_URL_PATH, fasthttpadaptor.NewFastHTTPHandler(promhttp.Handler()))
202203
runningServices += ", prometheus"
203204
}
204205
rtr.GET("/healtz", requestHandler)

pkg/controller/handler.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,12 @@ func (c *HAProxyController) initHandlers() {
5656

5757
defer func() { c.updateHandlers = append(c.updateHandlers, handler.Refresh{}) }()
5858

59-
c.beforeUpdateHandlers = []UpdateHandler{}
59+
c.beforeUpdateHandlers = []UpdateHandler{
60+
handler.PrometheusEndpoint{
61+
EventChan: c.eventChan,
62+
PodNs: c.podNamespace,
63+
},
64+
}
6065
// Need to be before Refresh. If after, maps are refreshed without pprof content
6166
if c.osArgs.PprofEnabled {
6267
c.beforeUpdateHandlers = append(c.beforeUpdateHandlers, handler.Pprof{})

pkg/handler/prometheus.go

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
package handler
2+
3+
import (
4+
"strings"
5+
6+
"github.com/haproxytech/kubernetes-ingress/pkg/annotations"
7+
"github.com/haproxytech/kubernetes-ingress/pkg/haproxy"
8+
"github.com/haproxytech/kubernetes-ingress/pkg/haproxy/instance"
9+
"github.com/haproxytech/kubernetes-ingress/pkg/k8s"
10+
"github.com/haproxytech/kubernetes-ingress/pkg/store"
11+
)
12+
13+
type PrometheusEndpoint struct {
14+
EventChan chan k8s.SyncDataEvent
15+
PodNs string
16+
}
17+
18+
//nolint:golint, stylecheck
19+
const (
20+
PROMETHEUS_BACKEND_NAME = "haproxy-controller_prometheus_http"
21+
PROMETHEUS_URL_PATH = "/metrics"
22+
)
23+
24+
func (handler PrometheusEndpoint) Update(k store.K8s, h haproxy.HAProxy, a annotations.Annotations) (err error) {
25+
if handler.PodNs == "" {
26+
return
27+
}
28+
29+
status := store.EMPTY
30+
var secret *store.Secret
31+
_, errBackend := h.BackendGet(PROMETHEUS_BACKEND_NAME)
32+
backendExists := errBackend == nil
33+
34+
annSecret := annotations.String("prometheus-endpoint-auth-secret", k.ConfigMaps.Main.Annotations)
35+
var secretExists, secretChanged, userListChanged bool
36+
userListExists, _ := h.UserListExistsByGroup("haproxy-controller-prometheus")
37+
38+
// Does the secret exist in store ? ...
39+
if annSecret != "" {
40+
secretFQN := strings.Split(annSecret, "/")
41+
if len(secretFQN) == 2 {
42+
ns := k.Namespaces[secretFQN[0]]
43+
if ns != nil {
44+
secret = ns.Secret[secretFQN[1]]
45+
secretExists = secret != nil && secret.Status != store.DELETED
46+
secretChanged = secret.Status == store.MODIFIED
47+
}
48+
}
49+
userListChanged = secretChanged || !userListExists
50+
} else {
51+
userListChanged = userListExists
52+
}
53+
54+
if !backendExists {
55+
status = store.ADDED
56+
}
57+
58+
if !userListChanged && status == store.EMPTY && (!secretExists || (secretExists && secret.Status == store.EMPTY)) {
59+
return
60+
}
61+
62+
prometheusSvcName := "prometheus"
63+
svc := &store.Service{
64+
Namespace: handler.PodNs,
65+
Name: prometheusSvcName,
66+
Status: status,
67+
Annotations: k.ConfigMaps.Main.Annotations,
68+
Ports: []store.ServicePort{
69+
{
70+
Name: "http",
71+
Protocol: "http",
72+
Port: 8765,
73+
Status: status,
74+
},
75+
},
76+
Faked: true,
77+
}
78+
endpoints := &store.Endpoints{
79+
Namespace: handler.PodNs,
80+
Service: prometheusSvcName,
81+
SliceName: prometheusSvcName,
82+
Status: status,
83+
Ports: map[string]*store.PortEndpoints{
84+
"http": {
85+
Port: int64(h.Env.ControllerPort),
86+
Addresses: map[string]struct{}{"127.0.0.1": {}},
87+
},
88+
},
89+
}
90+
91+
if status != store.EMPTY {
92+
k.EventService(k.GetNamespace(svc.Namespace), svc)
93+
k.EventEndpoints(k.GetNamespace(endpoints.Namespace), endpoints, func(*store.RuntimeBackend, bool) error { return nil })
94+
}
95+
96+
ing := &store.Ingress{
97+
Status: status,
98+
Faked: true,
99+
IngressCore: store.IngressCore{
100+
Namespace: handler.PodNs,
101+
Name: "prometheus",
102+
Rules: map[string]*store.IngressRule{"": {
103+
Paths: map[string]*store.IngressPath{
104+
PROMETHEUS_URL_PATH: {
105+
SvcNamespace: svc.Namespace,
106+
SvcName: svc.Name,
107+
Path: PROMETHEUS_URL_PATH,
108+
SvcPortString: "http",
109+
PathTypeMatch: store.PATH_TYPE_IMPLEMENTATION_SPECIFIC,
110+
},
111+
},
112+
}},
113+
},
114+
}
115+
116+
if secretExists {
117+
ing.Annotations = map[string]string{
118+
"auth-type": "basic-auth",
119+
"auth-secret": annSecret,
120+
}
121+
}
122+
123+
if userListChanged || status != store.EMPTY || secretExists && secret.Status != store.EMPTY {
124+
k.EventIngress(k.GetNamespace(ing.Namespace), ing)
125+
}
126+
127+
instance.ReloadIf(status != store.EMPTY, "creation/modification of prometheus endpoint")
128+
129+
return nil
130+
}

pkg/ingress/ingress.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,10 @@ func New(k store.K8s, resource *store.Ingress, class string, emptyClass bool, a
4949
// ingress.class annotation should have precedence over the IngressClass mechanism implemented
5050
// in "networking.k8s.io".
5151
func (i Ingress) Supported(k8s store.K8s, a annotations.Annotations) (supported bool) {
52+
if i.resource != nil && i.resource.Faked {
53+
return true
54+
}
55+
5256
var igClassAnn, igClassSpec string
5357
igClassAnn = a.String("ingress.class", i.resource.Annotations)
5458
if igClassResource := k8s.IngressClasses[i.resource.Class]; igClassResource != nil {

pkg/store/types.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ type Service struct {
7171
Status Status
7272
Ports []ServicePort
7373
Addresses []string // Used only for publish-service
74+
Faked bool
7475
}
7576

7677
// RuntimeBackend holds the runtime state of an HAProxy backend
@@ -139,6 +140,7 @@ type Ingress struct {
139140
Addresses []string
140141
Ignored bool // true if resource ignored because of non matching Controller Class
141142
ClassUpdated bool
143+
Faked bool
142144
}
143145

144146
// IngressTLS describes the transport layer security associated with an Ingress.

0 commit comments

Comments
 (0)