Skip to content

Commit 8af77ef

Browse files
authored
Expose API/stub_status on a custom port (#344)
Also allow disabling the API. NGINX Plus will listen on a socket, so the IC can still connect to modify upstream servers. Added command-line arguments: - nginx-status - nginx-status-port
1 parent be3cdbd commit 8af77ef

File tree

11 files changed

+129
-20
lines changed

11 files changed

+129
-20
lines changed

docs/cli-arguments.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ Usage of ./nginx-ingress:
3939
Format: <namespace>/<name>
4040
-nginx-plus
4141
Enable support for NGINX Plus
42+
-nginx-status
43+
Enable the NGINX stub_status, or the NGINX Plus API. (default true)
44+
-nginx-status-port int
45+
Set the port where the NGINX stub_status or the NGINX Plus API is exposed. [1023 - 65535] (default 8080)
4246
-proxy string
4347
Use a proxy server to connect to Kubernetes API started by "kubectl proxy" command. For testing purposes only.
4448
The Ingress controller does not start NGINX and does not write any generated NGINX configuration files to disk

docs/installation.md

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,10 +144,21 @@ The public IP can be reported in the status of an ingress resource. To enable:
144144
145145
Read more about the type LoadBalancer [here](https://kubernetes.io/docs/concepts/services-networking/service/#type-loadbalancer).
146146
147-
## 5. Access the Live Activity Monitoring Dashboard
147+
## 5. Access the Live Activity Monitoring Dashboard / Stub_status Page
148+
For NGINX, you can access the [stub_status page](http://nginx.org/en/docs/http/ngx_http_stub_status_module.html):
149+
1. Stub_status is enabled by default. Ensure that the `nginx-status` command-line argument is not set to false.
150+
2. Stub_status is available on port 8080 by default. It is customizable by the `nginx-status-port` command-line argument. If yours is not on 8080, modify the kubectl proxy command below.
151+
1. Use the `kubectl port-forward` command to forward connections to port 8080 on your local machine to port 8080 of an NGINX Ingress controller pod (replace `<nginx-ingress-pod>` with the actual name of a pod):.
152+
```
153+
$ kuebctl port-forward <nginx-ingress-pod> 8080:8080 --namespace=nginx-ingress
154+
```
155+
Open your browser at http://127.0.0.1:8080/stub_status to access the status.
156+
148157
149158
For NGINX Plus, you can access the live activity monitoring dashboard:
150-
1. Use `kubectl port-forward` command to forward connections to port 8080 on your local machine to port 8080 of an NGINX Plus Ingress controller pod (replace <nginx-plus-ingress-pod> with the actual name of a pod):
159+
1. The dashboard is enabled by default. Ensure that the `nginx-status` command-line argument is not set to false.
160+
1. The dashboard is available on port 8080 by default. It is customizable by the `nginx-status-port` command-line argument. If yours is not on 8080, modify the kubectl proxy command below.
161+
1. Use the `kubectl port-forward` command to forward connections to port 8080 on your local machine to port 8080 of an NGINX Plus Ingress controller pod (replace `<nginx-plus-ingress-pod>` with the actual name of a pod):
151162
```
152163
$ kubectl port-forward <nginx-plus-ingress-pod> 8080:8080 --namespace=nginx-ingress
153164
```

examples/complete-example/README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ certificate and the --resolve option to set the Host header of a request with ``
5555
Server name: tea-7cd44fcb4d-xfw2x
5656
...
5757
```
58-
59-
1. If you're using NGINX Plus, you can open the live activity monitoring dashboard:
60-
1. Follow the [instructions](../../docs/installation.md#5-access-the-live-activity-monitoring-dashboard) to access the dashboard.
61-
1. If you go to the Upstream tab, you'll see: ![dashboard](dashboard.png)
58+
59+
1. You can view an NGINX status page, either stub_status for NGINX, or the Live Activity Monitoring Dashboard for NGINX Plus:
60+
1. Follow the [instructions](../../docs/installation.md#5-access-the-live-activity-monitoring-dashboard--stub_status-page) to access the status page.
61+
1. For NGINX Plus, If you go to the Upstream tab, you'll see: ![dashboard](dashboard.png)

nginx-controller/controller/controller_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -926,7 +926,7 @@ func TestFindIngressesForSecret(t *testing.T) {
926926
t.Run(test.desc, func(t *testing.T) {
927927
fakeClient := fake.NewSimpleClientset()
928928

929-
templateExecutor, err := nginx.NewTemplateExecutor("../nginx/templates/nginx-plus.tmpl", "../nginx/templates/nginx-plus.ingress.tmpl", true)
929+
templateExecutor, err := nginx.NewTemplateExecutor("../nginx/templates/nginx-plus.tmpl", "../nginx/templates/nginx-plus.ingress.tmpl", true, true, 8080)
930930
if err != nil {
931931
t.Fatalf("templateExecuter could not start: %v", err)
932932
}

nginx-controller/main.go

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
package main
22

33
import (
4+
"context"
45
"flag"
56
"fmt"
7+
"net"
68
"net/http"
79
"os"
810
"os/signal"
@@ -78,6 +80,12 @@ The external address of the service is used when reporting the status of Ingress
7880

7981
leaderElectionEnabled = flag.Bool("enable-leader-election", false,
8082
"Enable Leader election to avoid multiple replicas of the controller reporting the status of Ingress resources -- only one replica will report status. See -report-ingress-status flag.")
83+
84+
nginxStatusPort = flag.Int("nginx-status-port", 8080,
85+
"Set the port where the NGINX stub_status or the NGINX Plus API is exposed. [1023 - 65535]")
86+
87+
nginxStatus = flag.Bool("nginx-status", true,
88+
"Enable the NGINX stub_status, or the NGINX Plus API.")
8189
)
8290

8391
func main() {
@@ -89,6 +97,11 @@ func main() {
8997
os.Exit(0)
9098
}
9199

100+
portValidationError := validateStatusPort(*nginxStatusPort)
101+
if portValidationError != nil {
102+
glog.Fatalf("Invalid value for nginx-status-port: %v", portValidationError)
103+
}
104+
92105
glog.Infof("Starting NGINX Ingress controller Version=%v GitCommit=%v\n", version, gitCommit)
93106

94107
var err error
@@ -131,7 +144,7 @@ func main() {
131144
nginxIngressTemplatePath = *ingressTemplatePath
132145
}
133146

134-
templateExecutor, err := nginx.NewTemplateExecutor(nginxConfTemplatePath, nginxIngressTemplatePath, *healthStatus)
147+
templateExecutor, err := nginx.NewTemplateExecutor(nginxConfTemplatePath, nginxIngressTemplatePath, *healthStatus, *nginxStatus, *nginxStatusPort)
135148
if err != nil {
136149
glog.Fatalf("Error creating TemplateExecutor: %v", err)
137150
}
@@ -206,7 +219,9 @@ func main() {
206219
var nginxAPI *plus.NginxAPIController
207220
if *nginxPlus {
208221
time.Sleep(500 * time.Millisecond)
209-
nginxAPI, err = plus.NewNginxAPIController(&http.Client{}, "http://127.0.0.1:8080/api", local)
222+
httpClient := getSocketClient()
223+
apiURL := fmt.Sprintf("http://127.0.0.1:%v/api", *nginxStatusPort)
224+
nginxAPI, err = plus.NewNginxAPIController(&httpClient, apiURL, local)
210225
if err != nil {
211226
glog.Fatalf("Failed to create NginxAPIController: %v", err)
212227
}
@@ -272,3 +287,21 @@ func handleTermination(lbc *controller.LoadBalancerController, ngxc *nginx.Nginx
272287
glog.Infof("Exiting with a status: %v", exitStatus)
273288
os.Exit(exitStatus)
274289
}
290+
291+
// getSocketClient gets an http.Client with the a unix socket transport.
292+
func getSocketClient() http.Client {
293+
return http.Client{
294+
Transport: &http.Transport{
295+
DialContext: func(_ context.Context, _, _ string) (net.Conn, error) {
296+
return net.Dial("unix", "/var/run/nginx-plus-api.sock")
297+
},
298+
},
299+
}
300+
}
301+
302+
func validateStatusPort(nginxStatusPort int) error {
303+
if nginxStatusPort < 1023 || nginxStatusPort > 65535 {
304+
return fmt.Errorf("port outside of valid port range [1023 - 65535]: %v", nginxStatusPort)
305+
}
306+
return nil
307+
}

nginx-controller/main_test.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package main
2+
3+
import (
4+
"testing"
5+
)
6+
7+
func TestValidateStatusPort(t *testing.T) {
8+
badPorts := []int{80, 443, 1, 1022, 65536}
9+
for _, badPort := range badPorts {
10+
err := validateStatusPort(badPort)
11+
if err == nil {
12+
t.Errorf("Expected error for port %v\n", badPort)
13+
}
14+
}
15+
16+
goodPorts := []int{8080, 8081, 8082, 1023, 65535}
17+
for _, goodPort := range goodPorts {
18+
err := validateStatusPort(goodPort)
19+
if err != nil {
20+
t.Errorf("Error for valid port: %v err: %v\n", goodPort, err)
21+
}
22+
}
23+
24+
}

nginx-controller/nginx/configurator_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -483,7 +483,7 @@ func createExpectedConfigForMergeableCafeIngress() IngressNginxConfig {
483483
}
484484

485485
func createTestConfigurator() *Configurator {
486-
templateExecutor, _ := NewTemplateExecutor("templates/nginx-plus.tmpl", "templates/nginx-plus.ingress.tmpl", true)
486+
templateExecutor, _ := NewTemplateExecutor("templates/nginx-plus.tmpl", "templates/nginx-plus.ingress.tmpl", true, true, 8080)
487487
ngxc := NewNginxController("/etc/nginx", true)
488488
apiCtrl, _ := plus.NewNginxAPIController(&http.Client{}, "", true)
489489
return NewConfigurator(ngxc, NewDefaultConfig(), apiCtrl, templateExecutor)

nginx-controller/nginx/nginx.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,8 @@ type NginxMainConfig struct {
145145
ErrorLogLevel string
146146
StreamLogFormat string
147147
HealthStatus bool
148+
NginxStatus bool
149+
NginxStatusPort int
148150
MainSnippets []string
149151
HTTPSnippets []string
150152
StreamSnippets []string

nginx-controller/nginx/template_executor.go

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,14 @@ import (
99
// TemplateExecutor executes NGINX configuration templates
1010
type TemplateExecutor struct {
1111
HealthStatus bool
12+
NginxStatus bool
13+
NginxStatusPort int
1214
mainTemplate *template.Template
1315
ingressTemplate *template.Template
1416
}
1517

1618
// NewTemplateExecutor creates a TemplateExecutor
17-
func NewTemplateExecutor(mainTemplatePath string, ingressTemplatePath string, healthStatus bool) (*TemplateExecutor, error) {
19+
func NewTemplateExecutor(mainTemplatePath string, ingressTemplatePath string, healthStatus bool, nginxStatus bool, nginxStatusPort int) (*TemplateExecutor, error) {
1820
// template name must be the base name of the template file https://golang.org/pkg/text/template/#Template.ParseFiles
1921
nginxTemplate, err := template.New(path.Base(mainTemplatePath)).ParseFiles(mainTemplatePath)
2022
if err != nil {
@@ -26,7 +28,13 @@ func NewTemplateExecutor(mainTemplatePath string, ingressTemplatePath string, he
2628
return nil, err
2729
}
2830

29-
return &TemplateExecutor{mainTemplate: nginxTemplate, ingressTemplate: ingressTemplate, HealthStatus: healthStatus}, nil
31+
return &TemplateExecutor{
32+
mainTemplate: nginxTemplate,
33+
ingressTemplate: ingressTemplate,
34+
HealthStatus: healthStatus,
35+
NginxStatus: nginxStatus,
36+
NginxStatusPort: nginxStatusPort,
37+
}, nil
3038
}
3139

3240
// UpdateMainTemplate updates the main NGINX template
@@ -54,6 +62,8 @@ func (te *TemplateExecutor) UpdateIngressTemplate(templateString *string) error
5462
// ExecuteMainConfigTemplate generates the content of the main NGINX configuration file
5563
func (te *TemplateExecutor) ExecuteMainConfigTemplate(cfg *NginxMainConfig) ([]byte, error) {
5664
cfg.HealthStatus = te.HealthStatus
65+
cfg.NginxStatus = te.NginxStatus
66+
cfg.NginxStatusPort = te.NginxStatusPort
5767

5868
var configBuffer bytes.Buffer
5969
err := te.mainTemplate.Execute(&configBuffer, cfg)

nginx-controller/nginx/templates/nginx-plus.tmpl

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -84,11 +84,11 @@ http {
8484
return 404;
8585
}
8686
}
87-
8887

88+
{{- if .NginxStatus }}
8989
# NGINX Plus APIs
9090
server {
91-
listen 8080;
91+
listen {{.NginxStatusPort}};
9292

9393
root /usr/share/nginx/html;
9494

@@ -97,11 +97,21 @@ http {
9797
location = /dashboard.html {
9898
}
9999

100+
allow 127.0.0.1;
101+
deny all;
102+
103+
location /api {
104+
api write=off;
105+
}
106+
}
107+
{{- end }}
108+
109+
# NGINX Plus API over unix socket
110+
server {
111+
listen unix:/var/run/nginx-plus-api.sock;
112+
access_log off;
113+
100114
location /api {
101-
limit_except GET {
102-
allow 127.0.0.1;
103-
deny all;
104-
}
105115
api write=on;
106116
}
107117
}
@@ -123,4 +133,4 @@ stream {
123133
{{range $value := .StreamSnippets}}
124134
{{$value}}
125135
{{end}}
126-
}
136+
}

0 commit comments

Comments
 (0)