Skip to content

Commit

Permalink
Added handling of ingress.class annotation for NGINX
Browse files Browse the repository at this point in the history
  • Loading branch information
pleshakov committed Oct 12, 2016
1 parent 37e66f5 commit 560b7df
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 4 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ Every time the number of pods of services you expose via Ingress changes, the In
NGINX Plus provides you with [advanced statistics](https://www.nginx.com/products/live-activity-monitoring/), which you can access either through the API or via the built-in dashboard. This can give you insights into how NGINX Plus and your applications are performing.
* **Session Persistence** When enabled, NGINX Plus makes sure that all the requests from the same client are always passed to the same backend container using the *sticky cookie* method. Refer to the [session persistence examples](examples/session-persistence) to find out how to configure it.

## Using Multiple Ingress Controllers

You can run multiple Ingress controllers at the same time. For example, if your Kubernetes cluster is deployed in cloud, you can run the NGINX controller and the corresponding cloud HTTP load balancing controller. Refer to the [example](examples/multiple-ingress-controllers) to learn more.

## Advanced load balancing (beyond Ingress)

When your requirements go beyond what Ingress offers, you can use NGINX and
Expand Down
45 changes: 45 additions & 0 deletions examples/multiple-ingress-controllers/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Using Multiple Ingress Controllers

With the *kubernetes.io/ingress.class* annotation it is possible to smoothly run multiple Ingress controllers at the same time. This could be the case when you deploy your Kubernetes cluster in a cloud provider, for example, Google Compute Engine (GCE). A cloud provider can provide its own Ingress controller enabled by default.

If the annotation is not present in an Ingress resource, which is the usual case, each Ingress controller deployed in the cluster will handle that Ingress. Using the annotation you can specify which Ingress controller must handle which Ingress resource.

To designate that a particular Ingress resource must be handled *only* by the NGINX or NGINX Plus controller add the following annotation along with the value to the Ingress resource:
```
kubernetes.io/ingress.class: "nginx"
```

In this case other Ingress controllers will ignore that Ingress.

To summarize, the NGINX or NGINX Plus controller *will* handle an Ingress resource, if one of the following is true:
* The annotation is not present in the resource
* The annotation is present and its value is either the `nginx` or the empty string

Any other value of the annotation, for example, `gce`, makes the NGINX or NGINX Plus controller ignore the Ingress resource.

Here is an example of an Ingress resource that will be handled *only* by the NGINX or NGINX Plus controller:
```yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: cafe-ingress-nginx
annotations:
kubernetes.io/ingress.class: "nginx"
spec:
tls:
- hosts:
- cafe.example.com
secretName: cafe-secret
rules:
- host: cafe.example.com
http:
paths:
- path: /tea
backend:
serviceName: tea-svc
servicePort: 80
- path: /coffee
backend:
serviceName: coffee-svc
servicePort: 80
```
27 changes: 25 additions & 2 deletions nginx-controller/controller/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ import (
"k8s.io/kubernetes/pkg/watch"
)

const (
ingressClassKey = "kubernetes.io/ingress.class"
nginxIngressClass = "nginx"
)

// LoadBalancerController watches Kubernetes API and
// reconfigures NGINX via NginxController when needed
type LoadBalancerController struct {
Expand Down Expand Up @@ -70,18 +75,28 @@ func NewLoadBalancerController(kubeClient *client.Client, resyncPeriod time.Dura
ingHandlers := framework.ResourceEventHandlerFuncs{
AddFunc: func(obj interface{}) {
addIng := obj.(*extensions.Ingress)
if !isNginxIngress(addIng) {
glog.Infof("Ignoring Ingress %v based on Annotation %v", addIng.Name, ingressClassKey)
return
}
glog.V(3).Infof("Adding Ingress: %v", addIng.Name)
lbc.ingQueue.enqueue(obj)
},
DeleteFunc: func(obj interface{}) {
remIng := obj.(*extensions.Ingress)
if !isNginxIngress(remIng) {
return
}
glog.V(3).Infof("Removing Ingress: %v", remIng.Name)
lbc.ingQueue.enqueue(obj)
},
UpdateFunc: func(old, cur interface{}) {
curIng := cur.(*extensions.Ingress)
if !isNginxIngress(curIng) {
return
}
if !reflect.DeepEqual(old, cur) {
glog.V(3).Infof("Ingress %v changed, syncing",
cur.(*extensions.Ingress).Name)
glog.V(3).Infof("Ingress %v changed, syncing", curIng.Name)
lbc.ingQueue.enqueue(cur)
}
},
Expand Down Expand Up @@ -440,3 +455,11 @@ func parseNginxConfigMaps(nginxConfigMaps string) (string, string, error) {
}
return res[0], res[1], nil
}

func isNginxIngress(ing *extensions.Ingress) bool {
if class, exists := ing.Annotations[ingressClassKey]; exists {
return class == nginxIngressClass || class == ""
}

return true
}
27 changes: 25 additions & 2 deletions nginx-plus-controller/controller/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ import (
"k8s.io/kubernetes/pkg/watch"
)

const (
ingressClassKey = "kubernetes.io/ingress.class"
nginxIngressClass = "nginx"
)

// LoadBalancerController watches Kubernetes API and
// reconfigures NGINX via NginxController when needed
type LoadBalancerController struct {
Expand Down Expand Up @@ -70,18 +75,28 @@ func NewLoadBalancerController(kubeClient *client.Client, resyncPeriod time.Dura
ingHandlers := framework.ResourceEventHandlerFuncs{
AddFunc: func(obj interface{}) {
addIng := obj.(*extensions.Ingress)
if !isNginxIngress(addIng) {
glog.Infof("Ignoring Ingress %v based on Annotation %v", addIng.Name, ingressClassKey)
return
}
glog.V(3).Infof("Adding Ingress: %v", addIng.Name)
lbc.ingQueue.enqueue(obj)
},
DeleteFunc: func(obj interface{}) {
remIng := obj.(*extensions.Ingress)
if !isNginxIngress(remIng) {
return
}
glog.V(3).Infof("Removing Ingress: %v", remIng.Name)
lbc.ingQueue.enqueue(obj)
},
UpdateFunc: func(old, cur interface{}) {
curIng := cur.(*extensions.Ingress)
if !isNginxIngress(curIng) {
return
}
if !reflect.DeepEqual(old, cur) {
glog.V(3).Infof("Ingress %v changed, syncing",
cur.(*extensions.Ingress).Name)
glog.V(3).Infof("Ingress %v changed, syncing", curIng.Name)
lbc.ingQueue.enqueue(cur)
}
},
Expand Down Expand Up @@ -440,3 +455,11 @@ func parseNginxConfigMaps(nginxConfigMaps string) (string, string, error) {
}
return res[0], res[1], nil
}

func isNginxIngress(ing *extensions.Ingress) bool {
if class, exists := ing.Annotations[ingressClassKey]; exists {
return class == nginxIngressClass || class == ""
}

return true
}

0 comments on commit 560b7df

Please sign in to comment.