Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kubernetes multiple ingress objects with same configs

Suppose I create multiple ingress objects in k8s which point to the same service, same path and are exactly the same, only they have different names eg-. ingress-1 and ingress-2. How are the requests handled in this case? Are the requests duplicated or either ingress handles the request?

PS;- I know this doesn't make much sense but I am testing something out.

like image 802
Divyaanand Sinha Avatar asked Mar 03 '20 06:03

Divyaanand Sinha


Video Answer


2 Answers

Let's check how it works!

I have default nginx deployment

# kubectl -n test get pods -o wide | grep nginx
nginx-65f88748fd-6w6fj           1/1     Running   0          26h     10.8.253.25    k8s-vm02   <none>           <none>
nginx-65f88748fd-8fp7p           1/1     Running   0          26h     10.8.252.205   k8s-vm01   <none>           <none>
nginx-65f88748fd-c7j29           1/1     Running   0          26h     10.8.253.24    k8s-vm02   <none>           <none>
nginx-65f88748fd-frsbq           1/1     Running   0          26h     10.8.252.201   k8s-vm01   <none>           <none>
nginx-65f88748fd-p4zvm           1/1     Running   0          26h     10.8.252.204   k8s-vm01   <none>           <none>
nginx-65f88748fd-pd8gv           1/1     Running   0          25h     10.8.253.27    k8s-vm02   <none>           <none>
nginx-65f88748fd-rkcjl           1/1     Running   0          26h     10.8.252.206   k8s-vm01   <none>           <none>
nginx-65f88748fd-rn49k           1/1     Running   0          26h     10.8.253.26    k8s-vm02   <none>           <none>
nginx-65f88748fd-w9dz8           1/1     Running   0          26h     10.8.252.203   k8s-vm01   <none>           <none>
nginx-65f88748fd-xh42v           1/1     Running   0          25h     10.8.253.28    k8s-vm02   <none>           <none>

service

# kubectl -n test get svc
NAME    TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
nginx   ClusterIP   10.8.254.218   <none>        80/TCP    12d

and 2 similar Ingress resources in the same namespace

# kubectl -n test get ing
NAME             HOSTS            ADDRESS   PORTS   AGE
test-ingress-1   nginx.test.com             80      20m
test-ingress-2   nginx.test.com             80      20m

Their YAML's:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  namespace: test
  name: test-ingress-1
  annotations:
    kubernetes.io/ingress.class: "service"
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - host: nginx.test.com
    http:
      paths:
      - path: /foo
        backend:
          serviceName: nginx
          servicePort: 80

and

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  namespace: test
  name: test-ingress-2
  annotations:
    kubernetes.io/ingress.class: "service"
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - host: nginx.test.com
    http:
      paths:
      - path: /foo
        backend:
          serviceName: nginx
          servicePort: 80

one more thing about ingress.class: "service" - there are more then 1 ingress controllers in my environment and this particular ingress-controller

nginx-ingress-service-6gkhh                1/1     Running   0          4m20s   10.8.255.243   k8s-vm02   <none>           <none>

has been created specially for demonstrating this example, so pay no attention for it

Anyway, is Ingress resource nginx.test.com/foo working now?

# curl -H "Host: nginx.test.com" http://10.8.255.243:80/foo
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

Yes, it is. What's under the hood? Nginx config inside ingress-controller has only one server_name nginx.test.com no matter how many similar Ingress resources we have

# kubectl -n kube-system exec nginx-ingress-service-6gkhh -- cat /etc/nginx/nginx.conf
...
## start server nginx.test.com
    server {
        server_name nginx.test.com ;

        listen 80;

        listen [::]:80;

        set $proxy_upstream_name "-";

        location ~* ^/foo\/?(?<baseuri>.*) {
...
            proxy_pass http://test-nginx-80;
...
    ## end server nginx.test.com

upstreams:

    upstream test-nginx-80 {

        keepalive 32;

        server 10.8.252.203:80 max_fails=0 fail_timeout=0;
        server 10.8.253.26:80 max_fails=0 fail_timeout=0;
        server 10.8.252.201:80 max_fails=0 fail_timeout=0;
        server 10.8.253.25:80 max_fails=0 fail_timeout=0;
        server 10.8.252.204:80 max_fails=0 fail_timeout=0;
        server 10.8.253.24:80 max_fails=0 fail_timeout=0;
        server 10.8.252.205:80 max_fails=0 fail_timeout=0;
        server 10.8.252.206:80 max_fails=0 fail_timeout=0;
        server 10.8.253.27:80 max_fails=0 fail_timeout=0;
        server 10.8.253.28:80 max_fails=0 fail_timeout=0;

    }

Let's delete the test-ingress-1 Ingress resource

# kubectl -n test delete ing test-ingress-1
ingress.extensions "test-ingress-1" deleted

Ingress is still working:

# curl -H "Host: nginx.test.com" http://10.8.255.243:80/foo
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

So, you can create as many similar Ingress resources as you want (In case of using nginx-ingress-controller)

UPD: Let's create one more deployment in the same namespace:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: apache
  namespace: test
spec:
  replicas: 3
  selector:
    matchLabels:
      app: apache
  template:
    metadata:
      labels:
        app: apache
    spec:
      containers:
      - name: frontend
        image: httpd
        ports:
        - containerPort: 80

and one more service

apiVersion: v1
kind: Service
metadata:
  name: apache
  namespace: test
spec:
  ports:
  - name: 80-80
    port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: apache
  type: ClusterIP

Next let's change Ingress resource test-ingress-2:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  namespace: test
  name: test-ingress-2
  annotations:
    kubernetes.io/ingress.class: "service"
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - host: nginx.test.com
    http:
      paths:
      - path: /foo
        backend:
          serviceName: apache # <-------
          servicePort: 80

Finally namespace test includes this list of resources:

# kubectl -n test get all
NAME                                 READY   STATUS    RESTARTS   AGE
pod/apache-cfdf8d79c-2m666           1/1     Running   0          13m
pod/apache-cfdf8d79c-d995s           1/1     Running   0          13m
pod/apache-cfdf8d79c-tq8d7           1/1     Running   0          13m
pod/nginx-65f88748fd-6w6fj           1/1     Running   0          45h
pod/nginx-65f88748fd-8fp7p           1/1     Running   0          45h
pod/nginx-65f88748fd-c7j29           1/1     Running   0          45h
pod/nginx-65f88748fd-frsbq           1/1     Running   0          46h
pod/nginx-65f88748fd-p4zvm           1/1     Running   0          45h
pod/nginx-65f88748fd-pd8gv           1/1     Running   0          45h
pod/nginx-65f88748fd-rkcjl           1/1     Running   0          45h
pod/nginx-65f88748fd-rn49k           1/1     Running   0          45h
pod/nginx-65f88748fd-w9dz8           1/1     Running   0          45h
pod/nginx-65f88748fd-xh42v           1/1     Running   0          45h

NAME             TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
service/apache   ClusterIP   10.8.254.47    <none>        80/TCP    12m
service/nginx    ClusterIP   10.8.254.218   <none>        80/TCP    12d

# kubectl -n test get ing
NAME             HOSTS            ADDRESS   PORTS   AGE
test-ingress-1   nginx.test.com             80      9m15s
test-ingress-2   nginx.test.com             80      54s

the ingreess-controller's nginx.conf shows two lists of upstreams

    upstream test-apache-80 {

        keepalive 32;

        server 10.8.253.31:80 max_fails=0 fail_timeout=0;
        server 10.8.252.208:80 max_fails=0 fail_timeout=0;
        server 10.8.253.32:80 max_fails=0 fail_timeout=0;

    }

    upstream test-nginx-80 {

        keepalive 32;

        server 10.8.252.204:80 max_fails=0 fail_timeout=0;
        server 10.8.252.205:80 max_fails=0 fail_timeout=0;
        server 10.8.253.27:80 max_fails=0 fail_timeout=0;
        server 10.8.253.25:80 max_fails=0 fail_timeout=0;
        server 10.8.253.24:80 max_fails=0 fail_timeout=0;
        server 10.8.252.206:80 max_fails=0 fail_timeout=0;
        server 10.8.253.26:80 max_fails=0 fail_timeout=0;
        server 10.8.252.203:80 max_fails=0 fail_timeout=0;
        server 10.8.253.28:80 max_fails=0 fail_timeout=0;
        server 10.8.252.201:80 max_fails=0 fail_timeout=0;

    }

but it proxies requests only to one of them

    ## start server nginx.test.com
    server {
        server_name nginx.test.com ;

        listen 80;

        listen [::]:80;

        set $proxy_upstream_name "-";

        location ~* ^/foo\/?(?<baseuri>.*) {

            set $namespace      "test";
            set $ingress_name   "test-ingress-1"; <------
            set $service_name   "nginx";
            set $service_port   "80";
            set $location_path  "/foo";

...

            rewrite /foo/(.*) /$1 break;
            rewrite /foo / break;
            proxy_pass http://test-nginx-80;  <-------

            proxy_redirect                          off;
# curl -H "Host: nginx.test.com" http://10.8.255.243:80/foo
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...

Each of ingress resources appears there in accordance with the creation time. Deleting Ingress resource

ingress.networking.k8s.io "test-ingress-1" deleted

makes ingress-controller proxy traffic to Apache upstreams

# curl -H "Host: nginx.test.com" http://10.8.255.243:80/foo
<html><body><h1>It works!</h1></body></html>

to make it clear we can recreate Ingress resources in reverse order:

# kubectl -n test delete ing test-ingress-1 test-ingress-2
ingress.extensions "test-ingress-1" deleted
ingress.extensions "test-ingress-2" deleted

# kubectl -n test create -f /tmp/ing2.yaml
ingress.networking.k8s.io/test-ingress-2 created # Apache
# kubectl -n test create -f /tmp/ing1.yaml
ingress.networking.k8s.io/test-ingress-1 created # Nginx

# curl -H "Host: nginx.test.com" http://10.8.255.243:80/foo
<html><body><h1>It works!</h1></body></html> # Apache

One more note: There are some cases of reloading the ingress-controller's config, I mean when it reloads config and how it actually reloads config? But that's a totally different question...

like image 139
Konstantin Vustin Avatar answered Oct 12 '22 01:10

Konstantin Vustin


If you mean Ingress objects with the same Controller: generally nothing interesting, most of the de-dup redundant routes.

If you mean two Controllers each pointed at a different (but identical) Ingress: both Controllers set themselves up with the requested routes. They are totally independent and don't know anything about each other.

like image 38
coderanger Avatar answered Oct 12 '22 02:10

coderanger