Sunday, April 26, 2020

Test drive Azure Application Gateway ingress controller in Azure Kubernetes Service (AKS)

Architecture Diagram


Azure Application Gateway ingress Controller in AKS


Overview

This blog is inspired by one of my recent partner engagements. There’s a fantastic article here about this new Azure solution announcement.  Let's understand the need for ingress controllers first.  In my previous post, we took a closer look at Kubenet networking and services in AKS. When you create a Service of the type LoadBalancer, an underlying load balancer resource is created in Azure. The load balancer is configured to distribute traffic to the pods on a given port. This Load Balancer works at layer 4 and the service is unaware of the higher layer applications (http/https).  Ingress controller works at layer 7 and can use more intelligent rules to distribute application traffic and also conserver public IP space.  The common use case is to route traffic to different applications based on the inbound URL.


In this post we drill a little deeper into the architecture, take a closer look at two types of Ingress services – Simple Fanout and Name Based Virtual hosting and take it for a test drive. Application gateway as ingress controller has direct access to all kubernetes pods and performs the layer 7 functions. In the previous blog I covered the in-cluster ingress controller with nginx and AKS.



Test Drive 

Follow the link to test drive application gateway ingress controller in Azure Kubernetes service.  Create your own sample deployments using the sample yaml manifests.

Fanout

http://colors.penguintrails.com
http://colors.penguintrails.com/red
http://colors.penguintrails.com/green
http://colors.penguintrails.com/blue
http://colors.penguintrails.com/white

Virtual Host

http://red.penguintrails.com
http://green.penguintrails.com
http://blue.penguintrails.com
default-white



Github

Pre-requisites:



  1. A Working AKS cluster with Application Gateway. Detailed documentation here.
  2.  Link to my github repo here. Git clone my repository and off you go..


#
# Create Namespace
kubectl create namespace colors-ns
#
# Deployments
#
kubectl apply -f red-deployment.yaml
kubectl apply -f green-deployment.yaml
kubectl apply -f blue-deployment.yaml
kubectl apply -f white-deployment.yaml
#
# Ingress
#
kubectl apply -f colors-fanout.yaml
kubectl apply -f colors-virtual-host.yaml

Pre-requisites

From Azure Documentation here

Ingress Concepts

Some ingress concepts here

Simple fanout


A fanout configuration routes traffic from a single IP address to more than one Service, based on the HTTP URI being requested. An Ingress allows you to keep the number of load balancers down to a minimum. For example, a setup like:

foo.bar.com -> 178.91.123.132 -> / foo    service1:4200
                                                       / bar    service2:8080

Name based virtual hosting


Name-based virtual hosts support routing HTTP traffic to multiple host names at the same IP address.

foo.bar.com --|                             |-> foo.bar.com service1:80
                       | 178.91.123.132  |
bar.foo.com --|                             |-> bar.foo.com service2:80



Validations

Lets follow the red-service all the way.

Fanout 


kubectl describe ingress colors-fanout-ingress -n colors-ns
Name:             colors-fanout-ingress
Namespace:        colors-ns
Address:          52.149.191.58
Default backend:  default-http-backend:80 (<none>)
Rules:
  Host                      Path  Backends
  ----                      ----  --------
  colors.penguintrails.com
                            /red     red-service:8080 (15.0.0.23:8080,15.0.0.50:8080,15.0.0.79:8080)
                            /green   green-service:8080 (15.0.0.18:8080,15.0.0.46:8080,15.0.0.92:8080)
                            /blue    blue-service:8080 (15.0.0.5:8080,15.0.0.65:8080,15.0.0.78:8080)
                                     white-service:8080 (15.0.0.15:8080,15.0.0.61:8080,15.0.0.90:8080)
Annotations:
  <snip>


Virtual Host

kubectl describe ingress colors-virtual-host-ingress -n colors-ns
Name:             colors-virtual-host-ingress
Namespace:        colors-ns
Address:          52.149.191.58
Default backend:  default-http-backend:80 (<none>)
Rules:
  Host                     Path  Backends
  ----                     ----  --------
  red.penguintrails.com
                              red-service:8080 (15.0.0.23:8080,15.0.0.50:8080,15.0.0.79:8080)
  green.penguintrails.com
                              green-service:8080 (15.0.0.18:8080,15.0.0.46:8080,15.0.0.92:8080)
  blue.penguintrails.com
                              blue-service:8080 (15.0.0.5:8080,15.0.0.65:8080,15.0.0.78:8080)
  *
                              white-service:8080 (15.0.0.15:8080,15.0.0.61:8080,15.0.0.90:8080)
Annotations:
 <snip>





AKS Nodes

kubectl get nodes -o wide
NAME                                STATUS   ROLES   AGE   VERSION    INTERNAL-IP   EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION      CONTAINER-RUNTIME
aks-agentpool-41427971-vmss000000   Ready    agent   9d    v1.15.10   15.0.0.4      <none>        Ubuntu 16.04.6 LTS   4.15.0-1071-azure   docker://3.0.10+azure
aks-agentpool-41427971-vmss000001   Ready    agent   9d    v1.15.10   15.0.0.35     <none>        Ubuntu 16.04.6 LTS   4.15.0-1071-azure   docker://3.0.10+azure
aks-agentpool-41427971-vmss000002   Ready    agent   9d    v1.15.10   15.0.0.66     <none>        Ubuntu 16.04.6 LTS   4.15.0-1071-azure   docker://3.0.10+azure

AKS Pods and Service 


kubectl get pods,service,ingress -o wide -n colors-ns                                                            

kubectl get pods,service,ingress -o wide -n colors-ns
NAME                                    READY   STATUS    RESTARTS   AGE    IP          NODE                                NOMINATED NODE   READINESS GATES
pod/blue-deployment-69d4cf87cd-6bz5p    1/1     Running   0          106m   15.0.0.65   aks-agentpool-41427971-vmss000001   <none>           <none>
pod/blue-deployment-69d4cf87cd-sx5l9    1/1     Running   0          106m   15.0.0.78   aks-agentpool-41427971-vmss000002   <none>           <none>
pod/blue-deployment-69d4cf87cd-vksvv    1/1     Running   0          106m   15.0.0.5    aks-agentpool-41427971-vmss000000   <none>           <none>
pod/green-deployment-5dbccd4bb9-25fk6   1/1     Running   0          108m   15.0.0.18   aks-agentpool-41427971-vmss000000   <none>           <none>
pod/green-deployment-5dbccd4bb9-59rk9   1/1     Running   0          108m   15.0.0.92   aks-agentpool-41427971-vmss000002   <none>           <none>
pod/green-deployment-5dbccd4bb9-kk9rq   1/1     Running   0          108m   15.0.0.46   aks-agentpool-41427971-vmss000001   <none>           <none>
pod/red-deployment-74b4d99d5c-2m6m9     1/1     Running   0          111m   15.0.0.23   aks-agentpool-41427971-vmss000000   <none>           <none>
pod/red-deployment-74b4d99d5c-5btzj     1/1     Running   0          111m   15.0.0.79   aks-agentpool-41427971-vmss000002   <none>           <none>
pod/red-deployment-74b4d99d5c-bxt4n     1/1     Running   0          111m   15.0.0.50   aks-agentpool-41427971-vmss000001   <none>           <none>
pod/white-deployment-69f8898c-28gjn     1/1     Running   0          104m   15.0.0.90   aks-agentpool-41427971-vmss000002   <none>           <none>
pod/white-deployment-69f8898c-84ssm     1/1     Running   0          104m   15.0.0.15   aks-agentpool-41427971-vmss000000   <none>           <none>
pod/white-deployment-69f8898c-shmhs     1/1     Running   0          104m   15.0.0.61   aks-agentpool-41427971-vmss000001   <none>           <none>

NAME                    TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)    AGE    SELECTOR

service/blue-service    ClusterIP   10.0.9.185     <none>        8080/TCP   106m   app=blue
service/green-service   ClusterIP   10.0.201.73    <none>        8080/TCP   108m   app=green
service/red-service     ClusterIP   10.0.240.207   <none>        8080/TCP   111m   app=red
service/white-service   ClusterIP   10.0.12.67     <none>        8080/TCP   104m   app=white

NAME                                             HOSTS                                                                              ADDRESS         PORTS   AGE

ingress.extensions/colors-fanout-ingress         colors.penguintrails.com                                                           52.149.191.58   80      97m
ingress.extensions/colors-virtual-host-ingress   red.penguintrails.com,green.penguintrails.com,blue.penguintrails.com + 1 more...   52.149.191.58   80      106s


Connectivity Validations:

I've created a busybox container to run all the tests.  Let's validate connectivity to red pods and cluster serivce.

kubectl exec -it pingtest-b4b6f8cf-cxzt2 sh
/ # ip add
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
40: eth0@if41: <BROADCAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue qlen 1000
    link/ether 9e:63:52:64:73:fc brd ff:ff:ff:ff:ff:ff
    inet 15.0.0.19/16 scope global eth0

       valid_lft forever preferred_lft forever


/ # wget -qO- 15.0.0.23:8080

red
/ # wget -qO- 15.0.0.79:8080
red
/ # wget -qO- 15.0.0.50:8080
red
/ # wget -qO- 10.0.240.207:8080
red
/ # exit

App Gateway Side

Fanout: 

Listeners-Fanout



Path-Based-Rules-Fanout



Backend-pool-fanout


Red-Pool

Front-end-IP


HTTP-Setting




Virtual Host:


















Monday, April 20, 2020

Test drive Nginx ingress controller in Azure Kubernetes Service (AKS)

Architecture

Nginx ingress controller with Azure Kubernetes Service

Overview

This blog is part of a series that's inspired by one of my recent client engagements.  As I mentioned in my previous blog, Application gateway as ingress controller has direct access to all kubernetes pods and performs the layer 7 functions.  In contrast, in this next blog I cover the "in-cluster" ingress controller with nginx and AKS which performs the layer 7 functions. There is a great blog article here that explains the differences. In-cluster ingress controller creates the kubernetes services resource and the Azure Layer 4 load balancer as shown in the architecture.. In comparison to the Azure application gateway, the traffic flows an extra hop.

Test Drive 


Follow the link to test drive nginx ingress controller in Azure Kubernetes service.  Create your own sample deployments using the sample yaml manifests.
Fanout
http://akscolors.penguintrails.com  (default web site)
http://akscolors.penguintrails.com/cyan
http://akscolors.penguintrails.com/magenta
http://akscolors.penguintrails.com/yellow

Virtual Host
http://cyan.penguintrails.com
http://magenta.penguintrails.com
http://yellow.penguintrails.com
http://akscolors.eastus.cloudapp.azure.com   (default)

Github

Pre-requisites:

Working AKS cluster with nginx controller. Detailed documentation here

Link to my github repo:
https://github.com/nehalineogi/aks-nginx-ingress

Git clone my repository and off you go...
git clone https://github.com/nehalineogi/aks-nginx-ingress.git

# create ingress controller
#
# Create Namespace
kubectl create namespace ingress-ns

# Add the official stable repository
helm repo add stable https://kubernetes-charts.storage.googleapis.com/
#
# create ingress controlller
# Use Helm to deploy an NGINX ingress controller
#
helm install nginx-ingress stable/nginx-ingress \
    --namespace ingress-ns \
    --set controller.replicaCount=3 \
    --set controller.nodeSelector."beta\.kubernetes\.io/os"=linux \
    --set defaultBackend.nodeSelector."beta\.kubernetes\.io/os"=linux

#
# Deployments
#
kubectl apply -f red-deployment.yaml
kubectl apply -f green-deployment.yaml
kubectl apply -f blue-deployment.yaml
kubectl apply -f white-deployment.yaml
#
# Ingress
#fanout
kubectl apply -f colors-fanout.yaml
#virtual host
kubectl apply -f colors-virtual-host.yaml

# Cleanup:
kubectl delete namespace ingress-ns
kubectl delete clusterrole nginx-ingress
kubectl delete clusterrolebinding nginx-ingress

Concepts - Ingress Deployments

Some ingress concepts here
Simple fanout

A fanout configuration routes traffic from a single IP address to more than one Service, based on the HTTP URI being requested. An Ingress allows you to keep the number of load balancers down to a minimum. For example, a setup like:

foo.bar.com -> 178.91.123.132 -> / foo    service1:4200
                                                       / bar    service2:8080
Name based virtual hosting

Name-based virtual hosts support routing HTTP traffic to multiple host names at the same IP address.

foo.bar.com --|                             |-> foo.bar.com service1:80
                       | 178.91.123.132  |
bar.foo.com --|                             |-> bar.foo.com service2:80

AKS Side

kubectl get nodes -o wide
NAME                                STATUS   ROLES   AGE   VERSION    INTERNAL-IP     EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION      CONTAINER-RUNTIME
aks-nodepool1-96863235-vmss000000   Ready    agent   21d   v1.15.10   172.16.240.4    <none>        Ubuntu 16.04.6 LTS   4.15.0-1077-azure   docker://3.0.10+azure
aks-nodepool1-96863235-vmss000001   Ready    agent   21d   v1.15.10   172.16.240.15   <none>        Ubuntu 16.04.6 LTS   4.15.0-1071-azure   docker://3.0.10+azure
aks-nodepool1-96863235-vmss000002   Ready    agent   21d   v1.15.10   172.16.240.26   <none>        Ubuntu 16.04.6 LTS   4.15.0-1071-azure   docker://3.0.10+azure

kubectl get deploy,pods,services,ingress -o wide -n ingress-ns
NAME                                                  READY   UP-TO-DATE   AVAILABLE   AGE     CONTAINERS                      IMAGES                                                                  SELECTOR
deployment.extensions/nginx-ingress-controller        3/3     3            3           4m52s   nginx-ingress-controller        quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.30.0   app=nginx-ingress,release=nginx-ingress
deployment.extensions/nginx-ingress-default-backend   1/1     1            1           4m52s   nginx-ingress-default-backend   k8s.gcr.io/defaultbackend-amd64:1.5                                     app=nginx-ingress,release=nginx-ingress

NAME                                                 READY   STATUS    RESTARTS   AGE     IP              NODE                                NOMINATED NODE   READINESS GATES
pod/nginx-ingress-controller-f559556f9-cbmzq         1/1     Running   0          4m52s   172.16.240.14   aks-nodepool1-96863235-vmss000000   <none>           <none>
pod/nginx-ingress-controller-f559556f9-lhbfz         1/1     Running   0          4m52s   172.16.240.23   aks-nodepool1-96863235-vmss000001   <none>           <none>
pod/nginx-ingress-controller-f559556f9-tqgkl         1/1     Running   0          4m52s   172.16.240.29   aks-nodepool1-96863235-vmss000002   <none>           <none>
pod/nginx-ingress-default-backend-76b8f499cb-sw8pv   1/1     Running   0          4m52s   172.16.240.10   aks-nodepool1-96863235-vmss000000   <none>           <none>

NAME                                    TYPE           CLUSTER-IP      EXTERNAL-IP      PORT(S)                      AGE     SELECTOR
service/nginx-ingress-controller        LoadBalancer   10.20.8.97      52.170.163.131   80:31982/TCP,443:30146/TCP   4m52s   app.kubernetes.io/component=controller,app=nginx-ingress,release=nginx-ingress
service/nginx-ingress-default-backend   ClusterIP      10.20.137.158   <none>           80/TCP                       4m52s   app.kubernetes.io/component=default-backend,app=nginx-ingress,release=nginx-ingress

kubectl describe service nginx-ingress-controller -n ingress-ns
Name:                     nginx-ingress-controller
Namespace:                ingress-ns
Labels:                   app=nginx-ingress
                          chart=nginx-ingress-1.36.2
                          component=controller
                          heritage=Helm
                          release=nginx-ingress
Annotations:              <none>
Selector:                 app.kubernetes.io/component=controller,app=nginx-ingress,release=nginx-ingress
Type:                     LoadBalancer
IP:                       10.20.8.97
LoadBalancer Ingress:     52.170.163.131
Port:                     http  80/TCP
TargetPort:               http/TCP
NodePort:                 http  31982/TCP
Endpoints:                172.16.240.14:80,172.16.240.23:80,172.16.240.29:80
Port:                     https  443/TCP
TargetPort:               https/TCP
NodePort:                 https  30146/TCP
Endpoints:                172.16.240.14:443,172.16.240.23:443,172.16.240.29:443
Session Affinity:         None
External Traffic Policy:  Cluster
Events:
  Type    Reason                Age    From                Message
  ----    ------                ----   ----                -------
  Normal  EnsuringLoadBalancer  7m     service-controller  Ensuring load balancer
  Normal  EnsuredLoadBalancer   6m37s  service-controller  Ensured load balancer


kubectl describe service nginx-ingress-default-backend -n ingress-ns
Name:              nginx-ingress-default-backend
Namespace:         ingress-ns
Labels:            app=nginx-ingress
                   chart=nginx-ingress-1.36.2
                   component=default-backend
                   heritage=Helm
                   release=nginx-ingress
Annotations:       <none>
Selector:          app.kubernetes.io/component=default-backend,app=nginx-ingress,release=nginx-ingress
Type:              ClusterIP
IP:                10.20.137.158
Port:              http  80/TCP
TargetPort:        http/TCP
Endpoints:         172.16.240.10:8080
Session Affinity:  None
Events:            <none>


Azure Side (Load Balancer)

backend Pool with VMSS Nodes

Load Balancer Public IPs

Node Port for the Exposed nginx controller service

Rule showing the HTTP heath probe on the NodePort

LB Rules for tcp/80 




Deployments:


kubectl get deploy,pods,services,ingress -o wide -n colors-ns
NAME                                       READY   UP-TO-DATE   AVAILABLE   AGE   CONTAINERS    IMAGES                SELECTOR
deployment.extensions/cyan-deployment      2/2     2            2           57s   cyan-app      hashicorp/http-echo   app=cyan
deployment.extensions/magenta-deployment   2/2     2            2           53s   magenta-app   hashicorp/http-echo   app=magenta
deployment.extensions/yellow-deployment    2/2     2            2           49s   yellow-app    hashicorp/http-echo   app=yellow

NAME                                      READY   STATUS    RESTARTS   AGE   IP              NODE                                NOMINATED NODE   READINESS GATES
pod/cyan-deployment-85c5fd4b7-49n25       1/1     Running   0          56s   172.16.240.13   aks-nodepool1-96863235-vmss000000   <none>           <none>
pod/cyan-deployment-85c5fd4b7-s2gx4       1/1     Running   0          56s   172.16.240.30   aks-nodepool1-96863235-vmss000002   <none>           <none>
pod/magenta-deployment-64fcd58c6f-9m4n8   1/1     Running   0          52s   172.16.240.32   aks-nodepool1-96863235-vmss000002   <none>           <none>
pod/magenta-deployment-64fcd58c6f-ljc2n   1/1     Running   0          52s   172.16.240.5    aks-nodepool1-96863235-vmss000000   <none>           <none>
pod/yellow-deployment-5ff564c666-8s9b6    1/1     Running   0          49s   172.16.240.12   aks-nodepool1-96863235-vmss000000   <none>           <none>
pod/yellow-deployment-5ff564c666-mswkf    1/1     Running   0          49s   172.16.240.6    aks-nodepool1-96863235-vmss000000   <none>           <none>

NAME                      TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE   SELECTOR
service/cyan-service      ClusterIP   10.20.140.182   <none>        8080/TCP   56s   app=cyan
service/magenta-service   ClusterIP   10.20.101.186   <none>        8080/TCP   52s   app=magenta
service/yellow-service    ClusterIP   10.20.46.169    <none>        8080/TCP   49s   app=yellow

Validations:


I've created a busybox container to run all the tests.  Let's validate connectivity to red pods and cluster serivce.

kubectl exec -it pingtest-b4b6f8cf-5xk7v sh

/ # ifconfig
eth0      Link encap:Ethernet  HWaddr 16:2A:D2:E5:D0:13
          inet addr:172.16.240.20  Bcast:0.0.0.0  Mask:255.255.255.0
          UP BROADCAST RUNNING  MTU:1500  Metric:1
          RX packets:2273586 errors:0 dropped:0 overruns:0 frame:0
          TX packets:105 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:95504870 (91.0 MiB)  TX bytes:7271 (7.1 KiB)

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

/ # wget -qO- 172.16.240.13
wget: can't connect to remote host (172.16.240.13): Connection refused
/ # wget -qO- 172.16.240.13:8080
cyan
/ # wget -qO- 172.16.240.30:8080
cyan
/ # wget -qO- 10.20.140.182:8080
cyan

Ingress:

Fanout:
 kubectl apply -f colors-fanout.yaml
kubectl describe ingress colors-fanout-ingress -n colors-ns
Name:             colors-fanout-ingress
Namespace:        colors-ns
Address:          172.16.240.15,172.16.240.26,172.16.240.4
Default backend:  default-http-backend:80 (<none>)
Rules:
  Host                         Path  Backends
  ----                         ----  --------
  akscolors.penguintrails.com
                               /cyan      cyan-service:8080 (172.16.240.13:8080,172.16.240.30:8080)
                               /magenta   magenta-service:8080 (172.16.240.32:8080,172.16.240.5:8080)
                               /yellow    yellow-service:8080 (172.16.240.12:8080,172.16.240.6:8080)
                                          cyan-service:8080 (172.16.240.13:8080,172.16.240.30:8080)
Annotations:
  kubectl.kubernetes.io/last-applied-configuration:  {"apiVersion":"extensions/v1beta1","kind":"Ingress","metadata":{"annotations":{"kubernetes.io/ingress.class":"nginx"},"name":"colors-fanout-ingress","namespace":"colors-ns"},"spec":{"rules":[{"host":"akscolors.penguintrails.com","http":{"paths":[{"backend":{"serviceName":"cyan-service","servicePort":8080},"path":"/cyan"},{"backend":{"serviceName":"magenta-service","servicePort":8080},"path":"/magenta"},{"backend":{"serviceName":"yellow-service","servicePort":8080},"path":"/yellow"},{"backend":{"serviceName":"cyan-service","servicePort":8080},"path":null}]}}]}}

Validations:

kubectl exec -it pingtest-b4b6f8cf-5xk7v sh
/ # ifconfig
eth0      Link encap:Ethernet  HWaddr 16:2A:D2:E5:D0:13
          inet addr:172.16.240.20  Bcast:0.0.0.0  Mask:255.255.255.0
          UP BROADCAST RUNNING  MTU:1500  Metric:1
          RX packets:2275879 errors:0 dropped:0 overruns:0 frame:0
          TX packets:191 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:95605042 (91.1 MiB)  TX bytes:13569 (13.2 KiB)

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

/ # wget -qO-  --header="Host:akscolors.penguintrails.com" http://10.20.8.97/cyan
cyan
/ # wget -qO-  --header="Host:akscolors.penguintrails.com" http://10.20.8.97/magenta
magenta
/ # wget -qO-  --header="Host:akscolors.penguintrails.com" http://10.20.8.97/yellow
yellow
/ # wget -qO-  --header="Host:akscolors.penguintrails.com" http://10.20.8.97/
cyan
/ #

Virtual Host

kubectl apply -f colors-virtual-host.yaml
ingress.extensions/colors-virtual-host-ingress created
 kubectl get ingress -o wide -n colors-ns
NAME                          HOSTS                                                                                   ADDRESS                                    PORTS   AGE
colors-fanout-ingress         akscolors.penguintrails.com                                                             172.16.240.15,172.16.240.26,172.16.240.4   80      19m
colors-virtual-host-ingress   cyan.penguintrails.com,magenta.penguintrails.com,yellow.penguintrails.com + 1 more...   172.16.240.15,172.16.240.26,172.16.240.4   80      74s


 kubectl describe ingress colors-virtual-host-ingress -n colors-ns
Name:             colors-virtual-host-ingress
Namespace:        colors-ns
Address:          172.16.240.15,172.16.240.26,172.16.240.4
Default backend:  default-http-backend:80 (<none>)
Rules:
  Host                       Path  Backends
  ----                       ----  --------
  cyan.penguintrails.com
                                cyan-service:8080 (172.16.240.13:8080,172.16.240.30:8080)
  magenta.penguintrails.com
                                magenta-service:8080 (172.16.240.32:8080,172.16.240.5:8080)
  yellow.penguintrails.com
                                yellow-service:8080 (172.16.240.12:8080,172.16.240.6:8080)
  *
                                cyan-service:8080 (172.16.240.13:8080,172.16.240.30:8080)
Annotations:
  kubectl.kubernetes.io/last-applied-configuration:  {"apiVersion":"extensions/v1beta1","kind":"Ingress","metadata":{"annotations":{"kubernetes.io/ingress.class":"nginx"},"name":"colors-virtual-host-ingress","namespace":"colors-ns"},"spec":{"rules":[{"host":"cyan.penguintrails.com","http":{"paths":[{"backend":{"serviceName":"cyan-service","servicePort":8080}}]}},{"host":"magenta.penguintrails.com","http":{"paths":[{"backend":{"serviceName":"magenta-service","servicePort":8080}}]}},{"host":"yellow.penguintrails.com","http":{"paths":[{"backend":{"serviceName":"yellow-service","servicePort":8080}}]}},{"http":{"paths":[{"backend":{"serviceName":"cyan-service","servicePort":8080}}]}}]}}

  kubernetes.io/ingress.class:  nginx
Events:

Validations:
kubectl exec -it pingtest-b4b6f8cf-5xk7v sh

/ # ifconfig
eth0      Link encap:Ethernet  HWaddr 16:2A:D2:E5:D0:13
          inet addr:172.16.240.20  Bcast:0.0.0.0  Mask:255.255.255.0
          UP BROADCAST RUNNING  MTU:1500  Metric:1
          RX packets:2278466 errors:0 dropped:0 overruns:0 frame:0
          TX packets:233 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:95716051 (91.2 MiB)  TX bytes:16907 (16.5 KiB)

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

/ # wget -qO-  --header="Host:cyan.penguintrails.com" http://10.20.8.97
cyan
/ # wget -qO-  --header="Host:magenta.penguintrails.com" http://10.20.8.97
magenta
/ # wget -qO-  --header="Host:yellow.penguintrails.com" http://10.20.8.97
yellow
/ # wget -qO-  http://10.20.8.97
cyan
/ #

Outbound from the PODS:

There is an outbound rule that gets created so all egress traffic from the pods get's SNAT'd to the load balancer Public IP address


 kubectl exec -it pingtest-b4b6f8cf-5xk7v sh
/ # ifconfig
eth0      Link encap:Ethernet  HWaddr 16:2A:D2:E5:D0:13
          inet addr:172.16.240.20  Bcast:0.0.0.0  Mask:255.255.255.0
          UP BROADCAST RUNNING  MTU:1500  Metric:1
          RX packets:2217728 errors:0 dropped:0 overruns:0 frame:0
          TX packets:36 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:93146060 (88.8 MiB)  TX bytes:2347 (2.2 KiB)

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

/ # wget -qO- icanhazip.com
52.152.246.245