Ingress Controllers Deployment for Kubernetes addons

Keywords: Nginx Kubernetes JSON SSL

Ingress

An API object, typically HTTP, that manages external access to services in a cluster.
Ingress provides load balancing, SSL termination, and name-based virtual hosts.

What is Ingress

Ingress, Kubernetes v1.1 started to increase, exposing clusters services Routes to http and https of.The control of traffic routing rules is defined in the Ingress resource.

  internet
      |
 [ Ingress ]
 --|-----|--
 [ Services ]

Ingress provides service s with URL s accessed outside the cluster, load balancing, SSL termination, and name-based virtual hosts.( Ingress controller The function responsible for implementing Ingress, usually a load balancer, monitors changes in Ingress and service s, configures load balancing according to rules, and provides access.
Ingress does not expose any ports or protocols.Exposing services other than HTTP and HTTPS to the Internet usually uses Service.Type = NodePort or Service.Type = LoadBalancer.

The Ingress Resource

The simplest example of Ingress Resource is as follows

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: test-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - http:
      paths:
      - path: /testpath
        backend:
          serviceName: test
          servicePort: 80

Like other Kubernetes resources, Ingress requires apiVersion, type, and metadata attributes.
For additional property configurations of configurations, see deploying applicationsconfiguring containersmanaging resources.
Ingress often uses comments to configure options, depending on the Ingress controller, see examples rewrite-target annotation.
Different Ingress controller Support different comments. Read the documentation for the Ingress controller you selected to see which comments are supported.
The Ingress specification has all the information needed to configure a load balancer or proxy server.Most importantly, it contains a list of rules that match all incoming requests.Ingress resources only support rules for HTTP traffic.

Ingress Rule

Each http rule contains the following information:

  • Optional host.In this example, no host is specified, so the rule applies to all inbound HTTP traffic through the specified IP address.If a host is provided (for example, foo.bar.com), the rule applies to that host.
  • A list of paths (for example, / testpath), each of which defines a service Name and service Port associated backend.Both host and path must match the content of the incoming request so that the load balancer can refer directly to the back-end service.
  • The backend is in services Document A combination of service names and port names defined in.HTTPS (and HTTPS) requests to Ingress-matched hosts and routing rules will be sent to the listed backends.
    The default backend is typically configured in an Ingress controller that will service requests that do not match the path in the specification.

Default Backend

Ingress without rules sends all traffic to a single default backend.The default backend is usually a configuration option for the Ingress controller and is not specified in the Ingress resource.

Ingress type

1. Single Service Ingress
The existing Kubernetes concept allows exposing a single service (see alternatives ).You can also use Ingress to do this by specifying a default backend without rules.

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: test-ingress
spec:
  backend:
    serviceName: testsvc
    servicePort: 80

If you use kubectl apply -f, you will see the following information:

kubectl get ingress test-ingress
NAME           HOSTS     ADDRESS           PORTS     AGE
test-ingress   *         107.178.254.228   80        59s

Of these, 107.178.254.228 is the IP assigned by the Ingress controller to satisfy this Ingress.

2. Ingress Routing to Multiple Services

The multiservice configuration routes traffic from a single IP address to multiple services based on the requested HTTP URI.Ingress allows you to minimize the number of load balancers.For example, the settings are as follows:

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

You can define it with the following Ingress:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: simple-fanout-example
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - host: foo.bar.com
    http:
      paths:
      - path: /foo
        backend:
          serviceName: service1
          servicePort: 4200
      - path: /bar
        backend:
          serviceName: service2
          servicePort: 8080

After creating ingress using kubectl create -f:

kubectl describe ingress simple-fanout-example
Name:             simple-fanout-example
Namespace:        default
Address:          178.91.123.132
Default backend:  default-http-backend:80 (10.8.2.3:8080)
Rules:
  Host         Path  Backends
  ----         ----  --------
  foo.bar.com
               /foo   service1:4200 (10.8.0.90:4200)
               /bar   service2:8080 (10.8.0.91:8080)
Annotations:
  nginx.ingress.kubernetes.io/rewrite-target:  /
Events:
  Type     Reason  Age                From                     Message
  ----     ------  ----               ----                     -------
  Normal   ADD     22s                loadbalancer-controller  default/test

As long as the service (s1, s2) exists, the Ingress controller provides a load balancer that satisfies the specific implementation of Ingress.Once created, you can view the address of the load balancer in the Address field.

3. Name-based virtual hosts
Virtual host Ingress forwards to different backend services by name, and they share the same IP address

foo.bar.com --|                 |-> foo.bar.com s1:80
              | 178.91.123.132  |
bar.foo.com --|                 |-> bar.foo.com s2:80

Here is a sample based on Host header Ingress for routing requests:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: name-virtual-host-ingress
spec:
  rules:
  - host: foo.bar.com
    http:
      paths:
      - backend:
          serviceName: service1
          servicePort: 80
  - host: bar.foo.com
    http:
      paths:
      - backend:
          serviceName: service2
          servicePort: 80

If you create an Ingress resouce that does not define any hosts in rules, then a web request based on the IP address of the Ingress controller can match to a virtual host without a name.For example, the following Ingress resource routes the first.bar.com request to service1, the second.foo.com to service2, and the other only IP addresses that have no hostname defined (that is, no hostname defined in the header) will route to service3

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: name-virtual-host-ingress
spec:
  rules:
  - host: first.bar.com
    http:
      paths:
      - backend:
          serviceName: service1
          servicePort: 80
  - host: second.foo.com
    http:
      paths:
      - backend:
          serviceName: service2
          servicePort: 80
  - http:
      paths:
      - backend:
          serviceName: service3
          servicePort: 80

4,TLS
You can specify which contains the TLS private key and certificate. secret To reinforce Ingress.Currently, Ingress supports only one TLS port 443 and assumes TLS termination.If the TLS configuration section in Ingress specifies different hosts, they will be reused on the same port based on the host name specified through the SNI TLS extension (assuming the Ingress controller supports SNI), and TLS secret must contain keys named tls.crt and tls.key, which contain the certificate and private key used for TLS.For example:

apiVersion: v1
kind: Secret
metadata:
  name: testsecret-tls
  namespace: default
data:
  tls.crt: base64 encoded cert
  tls.key: base64 encoded key
type: kubernetes.io/tls

Referencing this secret in Ingress tells the Ingress controller to use TLS to protect the channel from the client to the load balancer.You need to make sure that the TLS Secret you create comes from a certificate that contains the CN s of sslexample.foo.com.

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: tls-example-ingress
spec:
  tls:
  - hosts:
    - sslexample.foo.com
    secretName: testsecret-tls
  rules:
    - host: sslexample.foo.com
      http:
        paths:
        - path: /
          backend:
            serviceName: service1
            servicePort: 80

Different Ingress controller s support different TLS functions.See About nginxGCE Or any other Ingress controller documentation for TLS support.

4. Load Balancing
Ingress controller bootstraps through a number of load balancing policy settings that apply to all Ingress, such as load balancing algorithms, back-end weighting schemes, and so on.Other advanced load balancing concepts, such as persistent sessions and dynamic weights, are not exposed through Ingress.However, you can still get these functions through the load balancer.
It is worth noting that even if health checks are not made public directly through Ingress, similar concepts exist in Kubernetes, such as readiness probes, which can achieve the same end result.You can refer to the controller s'documentation to see how they handle health checks. nginxGCE).

5. Update Ingress
To update an existing Ingress to add a new host, you can update it by editing the resource:

kubectl describe ingress test
Name:             test
Namespace:        default
Address:          178.91.123.132
Default backend:  default-http-backend:80 (10.8.2.3:8080)
Rules:
  Host         Path  Backends
  ----         ----  --------
  foo.bar.com
               /foo   s1:80 (10.8.0.90:80)
Annotations:
  nginx.ingress.kubernetes.io/rewrite-target:  /
Events:
  Type     Reason  Age                From                     Message
  ----     ------  ----               ----                     -------
  Normal   ADD     35s                loadbalancer-controller  default/test
kubectl edit ingress test

This should pop up an editor containing the existing yaml to modify it to include the new host:

spec:
  rules:
  - host: foo.bar.com
    http:
      paths:
      - backend:
          serviceName: s1
          servicePort: 80
        path: /foo
  - host: bar.baz.com
    http:
      paths:
      - backend:
          serviceName: s2
          servicePort: 80
        path: /foo
..

Saving yaml updates the resources in the API server, which tells the Ingress controller to reconfigure the load balancer.

kubectl describe ingress test
Name:             test
Namespace:        default
Address:          178.91.123.132
Default backend:  default-http-backend:80 (10.8.2.3:8080)
Rules:
  Host         Path  Backends
  ----         ----  --------
  foo.bar.com
               /foo   s1:80 (10.8.0.90:80)
  bar.baz.com
               /foo   s2:80 (10.8.0.91:80)
Annotations:
  nginx.ingress.kubernetes.io/rewrite-target:  /
Events:
  Type     Reason  Age                From                     Message
  ----     ------  ----               ----                     -------
  Normal   ADD     45s                loadbalancer-controller  default/test

You can do the same by modifying the Ingress yaml file and calling kubectl replace-f.

Ingress Controllers

Ingress functioning requires Ingress Controller to be running in the cluster.Ingress Controller, unlike other controllers that are automatically started at cluster creation as kube-controller-manager, requires users to choose the Ingress Controller that best suits their cluster.
Current support and maintenance for the Kubernetes project GCE and nginx controllers.
Ingress Controller is deployed as Kubernetes Pod, runs as daemon, and maintains watch Apiserver's/ingress interface to update Ingress resources to meet Ingress's requests.For example, you can use Nginx Ingress Controller:
Other Ingress Controller s include:

Using multiple Ingress controllers

You can deploy multiple in a cluster any number of ingress controllers When you deploy multiple ingress controllers in a cluster, you need to specify with a comment when creating ingress ingress.class So that the cluster can select the correct ingress controller.
When you do not specify ingress.class, cloud providers may use the default ingress entry.
In general, all Ingress controllers should meet this specification, but the various Ingress controllers operate slightly differently.

Check the Ingress controller documentation for considerations on selecting it
Let's go into details next kubernetes/ingress-nginx As an example to introduce Ingress controllers.

ingress-nginx


Kubernetes is an open source container scheduling and scheduling system originally created by Google and donated to Cloud Native Computing Foundation.The Kubernetes automatic dispatch container runs in a server cluster, freeing up the complex tasks of container organization for developers and maintenance personnel.Kubernetes is currently the most popular container scheduling and scheduling system.
NGINX Ingress Controller provides enterprise delivery services to Kubernetes applications and facilitates users of open source NGINX and NGINX Plus. Using NGINX Ingress Controller provides features such as load balancing, SSL / TLS termination, URI rewriting, and SSL / TLS encryption.NGINX Plus also provides session persistence support for stateful applications, jwt authentication for API s, and so on.

ingress-nginx installation

1. Prerequisites and Common Deployment Commands
The default configuration monitors Ingress objects for all namespaces.To change this behavior, use watch-namespace to limit the scope to a specific namespace.
If multiple Ingresss define different paths for the same host, the Ingress controllers will merge the definitions.
If you are using GKE, you need to initialize the current user as a cluster administrator using the following commands: kubectl create cluster rolebinding cluster-admin-binding \ -- cluster role cluster-admin \ -- user $(gcloud config get-value account)

yaml file:

wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/mandatory.yaml

There are two ways to deploy, one is to create a service to expose ingress-nginx using NodePort, the other is to use a local network and add a hostNetwork: true
Next, we deploy it in two ways:
1. Create ingress-nginx-service (official document)
1.1. First create the corresponding ingress correlation from the mandatory.yaml file

[root@k8s ~]# kubectl apply -f mandatory.yaml 
namespace/ingress-nginx created
deployment.extensions/default-http-backend created
service/default-http-backend created
configmap/nginx-configuration created
configmap/tcp-services created
configmap/udp-services created
serviceaccount/nginx-ingress-serviceaccount created
clusterrole.rbac.authorization.k8s.io/nginx-ingress-clusterrole created
role.rbac.authorization.k8s.io/nginx-ingress-role created
rolebinding.rbac.authorization.k8s.io/nginx-ingress-role-nisa-binding created
clusterrolebinding.rbac.authorization.k8s.io/nginx-ingress-clusterrole-nisa-binding created
deployment.extensions/nginx-ingress-controller created

Verify Installation
To check if ingress controller pods is started properly, run the following command:

kubectl get pods --all-namespaces -l app.kubernetes.io/name=ingress-nginx --watch

[root@k8s ~]# kubectl get pods --all-namespaces -l app.kubernetes.io/name=ingress-nginx --watch
NAMESPACE       NAME                                       READY   STATUS    RESTARTS   AGE
ingress-nginx   nginx-ingress-controller-65795b86d-28lfr   1/1     Running   0          2m55s

1.2, create the ingress-nginx-service.yaml file, and apply

ingress-nginx-service.yaml

apiVersion: v1
kind: Service
metadata:
  name: ingress-nginx
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
spec:
  type: NodePort
  ports:
  - name: http
    port: 80
    targetPort: 80
    nodePort: 30080
  - name: https
    port: 443
    targetPort: 443
    protocol: TCP
    nodePort: 30443
  selector:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx

[root@k8s ~]# kubectl apply -f ingress-nginx-service.yaml 
service/ingress-nginx created

1.3, Testing
Ingress Controller is deployed, now write the rules for ingress and inject them into the configuration file for ingress-nginx pod

[root@k8s ~]# cat test-nginx-service.yaml 
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: test-service-ingress
  namespace: default
spec:
  rules:
  - host: ancs.nginx.com
    http:
      paths:
       - path: 
         backend:
           serviceName: nginx
           servicePort: 80

[root@k8s ~]# kubectl apply -f test-nginx-service.yaml 
ingress.extensions/test-service-ingress created

View ingress

[root@k8s ~]# kubectl  get ingress
NAME                   HOSTS            ADDRESS   PORTS   AGE
test-service-ingress   ancs.nginx.com             80      33s

Domain Name Resolution under Machine Configuration of Accessed Clients

Now we can access the backend proxy pod through ancs.nginx.com:30080

This is accessed using http. If you want to use https, first we need to create a certificate, as follows:

Self-Visa
[root@k8s https]#  openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/C=CN/ST=Beijing/L=Beijing/O=ancs/CN=ancs.nginx.com"
Generating a 2048 bit RSA private key
......................+++
...........................+++
writing new private key to 'tls.key'
-----
[root@k8s https]# ls
tls.crt  tls.key

You can also use cfssl self-visa.It's up to you!
Create the secret resource, the certificate is generated, and then the certificate is converted to secret

[root@k8s https]#  kubectl create secret tls ancs-secret --key tls.key --cert tls.crt
secret/ancs-secret created

Modify the test-nginx-service.yaml file

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: test-service-ingress
  namespace: default
spec:
  tls:
  - hosts:
    - ancs.nginx.cn
    secretName: ancs-secret
  rules:
  - host: ancs.nginx.com
    http:
      paths:
       - path: 
         backend:
           serviceName: nginx
           servicePort: 80

Now we can access it through https

2. Increase hostNetwork: true using host network

2.1 Modify the mandatory.yaml configuration file by adding the configuration item hostNetwork to the container: true to indicate using the local network

Matters needing attention:
Before creating the ingress-nginx-controller container, you need to modify the kube-proxy configuration
Add a line to the /opt/kubernetes/cfg/kube-proxy configuration file: - masquerade-all=true and restart kube-proxy.
[root@k8s cfg]# cat kube-proxy
KUBE_PROXY_OPTS="–logtostderr=true
–v=4
–hostname-override=10.0.52.14
–cluster-cidr=10.0.0.0/24
–proxy-mode=ipvs
–masquerade-all=true
–kubeconfig=/opt/kubernetes/cfg/kube-proxy.kubeconfig"

Configuration Item - masquerade-all Meaning, see Official Description kube-proxy Which is described as:
–masquerade-all
If using the pure iptables proxy, SNAT all traffic sent via Service cluster IPs (this not commonly needed)
Chinese translation:
–masquerade-all
If a pure iptables proxy is used, SNAT sends all traffic over the service sentence group IP (which is usually not required)
What people say means is:
Add a flag to the kube-proxy to maintain disguise rules for out-of-cluster traffic.Like this:

iptables -t nat -I POSTROUTING ! -s "${CLUSTER_CIDR}" -j MASQUERADE

2.2. Start the ingress-controller container

[root@k8s ~]# kubectl apply -f mandatory.yaml 
namespace/ingress-nginx unchanged
deployment.extensions/default-http-backend unchanged
service/default-http-backend unchanged
configmap/nginx-configuration unchanged
configmap/tcp-services unchanged
configmap/udp-services unchanged
serviceaccount/nginx-ingress-serviceaccount unchanged
clusterrole.rbac.authorization.k8s.io/nginx-ingress-clusterrole unchanged
role.rbac.authorization.k8s.io/nginx-ingress-role unchanged
rolebinding.rbac.authorization.k8s.io/nginx-ingress-role-nisa-binding unchanged
clusterrolebinding.rbac.authorization.k8s.io/nginx-ingress-clusterrole-nisa-binding unchanged
deployment.extensions/nginx-ingress-controller configured
[root@k8s ~]# kubectl get pods --all-namespaces -l app.kubernetes.io/name=ingress-nginx --watch
NAMESPACE       NAME                                        READY   STATUS              RESTARTS   AGE
ingress-nginx   nginx-ingress-controller-6b8cc9b76d-98szp   0/1     ContainerCreating   0          31s
ingress-nginx   nginx-ingress-controller-6b8cc9b76d-98szp   0/1   Running   0     43s
ingress-nginx   nginx-ingress-controller-6b8cc9b76d-98szp   1/1   Running   0     47s

2.3, Ingress deployment
2.3.1, http deployment as above, just refer to the above.Description is no longer repeated.
2.3.2, https deployment (using cfssl)
Issue certificates using cfssl:

  • Generate a ca certificate
cat << EOF | tee ca-config.json
{
  "signing": {
    "default": {
      "expiry": "87600h"
    },
    "profiles": {
      "www": {
         "expiry": "87600h",
         "usages": [
            "signing",
            "key encipherment",
            "server auth",
            "client auth"
        ]
      }
    }
  }
}
EOF

cat << EOF | tee ca-csr.json
{
    "CN": "www.ancs.com",
    "key": {
        "algo": "rsa",
        "size": 2048
    },
    "names": [
        {
            "C": "CN",
            "L": "Beijing",
            "ST": "Beijing"
        }
    ]
}
EOF

cfssl gencert -initca ca-csr.json | cfssljson -bare ca -
  • Generate server certificate:
cat << EOF | tee ancs-csr.json
{
    "CN": "www.ancs.com",
    "hosts": [],
    "key": {
        "algo": "rsa",
        "size": 2048
    },
    "names": [
        {
            "C": "CN",
            "L": "Beijing",
            "ST": "Beijing"
        }
    ]
}
EOF

cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=www ancs-csr.json | cfssljson -bare www.ancs.com
  • Generate Key
[root@k8s cfssl]# kubectl create secret tls ancs-secret --cert=www.ancs.com.pem --key=www.ancs.com-key.pem
secret/ancs-secret created

  • Deploying ingress
[root@k8s ~]# cat test-https-nginx-service.yaml 
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: test-service-ingress
  namespace: default
spec:
  tls:
  - hosts:
    - ancs.nginx.cn
    secretName: ancs-secret
  rules:
  - host: ancs.nginx.com
    http:
      paths:
       - path: 
         backend:
           serviceName: nginx
           servicePort: 80
[root@k8s ~]# kubectl apply -f test-https-nginx-service.yaml 
ingress.extensions/test-service-ingress created
[root@k8s ~]# 

*Configure hosts

  • Browser Access

At this point, our ingress deployment is complete.

Posted by wacook on Mon, 02 Sep 2019 19:29:29 -0700