Skip to content

Commit

Permalink
Renames the label designating Nodes that are running in the control p…
Browse files Browse the repository at this point in the history
…lane

This accommodates the change made in v1.20 which became the standard in 1.24.

This will require users to have Kubernetes v1.24 or higher; while NLK will run on lower versions, the control plane Nodes will not be excluded.
  • Loading branch information
ciroque committed Feb 14, 2025
1 parent 6a7497e commit cbc295e
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 15 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ The NGINX Loadbalancer for Kubernetes, or _NLK_, is a Kubernetes controller that

### What you will need

- [ ] A Kubernetes cluster running on-premise.
- [ ] A On-Premise Kubernetes cluster running version 1.24 or higher.
- [ ] One or more NGINX Plus hosts running outside your Kubernetes cluster (NGINX Plus hosts must have the ability to route traffic to the cluster).

There is a more detailed [Installation Reference](docs/README.md) available in the `docs/` directory.
Expand Down
34 changes: 27 additions & 7 deletions internal/communication/roundtripper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,13 @@ package communication
import (
"bytes"
"context"
"github.com/nginxinc/kubernetes-nginx-ingress/internal/configuration"
"k8s.io/client-go/kubernetes/fake"
"fmt"
netHttp "net/http"
"net/http/httptest"
"testing"

"github.com/nginxinc/kubernetes-nginx-ingress/internal/configuration"
"k8s.io/client-go/kubernetes/fake"
)

func TestNewRoundTripper(t *testing.T) {
Expand Down Expand Up @@ -47,32 +50,49 @@ func TestNewRoundTripper(t *testing.T) {
}

func TestRoundTripperRoundTrip(t *testing.T) {
// Create a mock HTTP server
mockServer := httptest.NewServer(netHttp.HandlerFunc(func(w netHttp.ResponseWriter, r *netHttp.Request) {
w.Header().Set("Content-Type", "application/json")
w.Header().Set("x-mock-header", "test-value")
w.WriteHeader(netHttp.StatusOK)
fmt.Fprintln(w, `{"message": "mock response"}`)
}))
defer mockServer.Close()

// Initialize dependencies
k8sClient := fake.NewSimpleClientset()
settings, err := configuration.NewSettings(context.Background(), k8sClient)
if err != nil {
t.Fatalf("Unexpected error creating settings: %v", err)
}

headers := NewHeaders()
transport := NewTransport(NewTlsConfig(settings))
roundTripper := NewRoundTripper(headers, transport)

request, err := NewRequest("GET", "http://example.com", nil)
// Use the mock server URL
request, err := NewRequest("GET", mockServer.URL, nil)
if err != nil {
t.Fatalf(`Unexpected error: %v`, err)
t.Fatalf("Unexpected error: %v", err)
}

request.Header.Set("Content-Type", "application/json")
request.Header.Set("x-nginx-loadbalancer-kubernetes", "nlk")

// Perform the request
response, err := roundTripper.RoundTrip(request)
if err != nil {
t.Fatalf(`Unexpected error: %v`, err)
t.Fatalf("Unexpected error: %v", err)
}

if response == nil {
t.Fatalf(`response should not be nil`)
t.Fatalf("Response should not be nil")
}

// Validate response headers
headerLen := len(response.Header)
if headerLen <= 2 {
t.Fatalf(`response.Header should have at least 2 elements, found %d`, headerLen)
t.Fatalf("Response headers should have at least 2 elements, found %d", headerLen)
}
}

Expand Down
15 changes: 8 additions & 7 deletions internal/observation/watcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ package observation
import (
"errors"
"fmt"
"time"

"github.com/nginxinc/kubernetes-nginx-ingress/internal/configuration"
"github.com/nginxinc/kubernetes-nginx-ingress/internal/core"
"github.com/sirupsen/logrus"
Expand All @@ -16,7 +18,6 @@ import (
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/client-go/informers"
"k8s.io/client-go/tools/cache"
"time"
)

// Watcher is responsible for watching for changes to Kubernetes resources.
Expand Down Expand Up @@ -163,7 +164,7 @@ func (w *Watcher) initializeEventListeners() error {
return nil
}

// notMasterNode retrieves the IP Addresses of the nodes in the cluster. Currently, the master node is excluded. This is
// notControlPlaneNode retrieves the IP Addresses of the nodes in the cluster. Currently, the master node is excluded. This is
// because the master node may or may not be a worker node and thus may not be able to route traffic.
func (w *Watcher) retrieveNodeIps() ([]string, error) {
started := time.Now()
Expand All @@ -180,7 +181,7 @@ func (w *Watcher) retrieveNodeIps() ([]string, error) {
for _, node := range nodes.Items {

// this is kind of a broad assumption, should probably make this a configurable option
if w.notMasterNode(node) {
if w.notControlPlaneNode(node) {
for _, address := range node.Status.Addresses {
if address.Type == v1.NodeInternalIP {
nodeIps = append(nodeIps, address.Address)
Expand All @@ -194,11 +195,11 @@ func (w *Watcher) retrieveNodeIps() ([]string, error) {
return nodeIps, nil
}

// notMasterNode determines if the node is a master node.
func (w *Watcher) notMasterNode(node v1.Node) bool {
logrus.Debug("Watcher::notMasterNode")
// notControlPlaneNode determines if the node is a master node.
func (w *Watcher) notControlPlaneNode(node v1.Node) bool {
logrus.Debug("Watcher::notControlPlaneNode")

_, found := node.Labels["node-role.kubernetes.io/master"]
_, found := node.Labels["node-role.kubernetes.io/control-plane"]

return !found
}

0 comments on commit cbc295e

Please sign in to comment.