Five minutes of K8S practice - using Ingress

2023.09.15

Five minutes of K8S practice - using Ingress

Ingress usually acts as a gateway. When we use Istio later, we can also use the controller provided by Istio to replace Ingress-nginx, which can more conveniently manage internal and external network traffic.

background

Technology, life, opinions, originality. Original public account; mainly focuses on Go, JVM, concurrency, distribution, network and other related technologies.

In the first two chapters, we deployed the application to k8s, and different services can also be called through service. Now there is another step to expose our application to the public network and provide domain name access.

This step is similar to how we configured Nginx and bound domain names before. The service that provides this capability is called Ingress in k8s.

From this description, we can actually see that Ingress is a partial operation and maintenance job, but it does not prevent us as R&D from understanding this part of the content; understanding how the entire system operates is also a skill that R&D should master.

Install the Ingress controller

Before officially using Ingress, you need to install an Ingress controller for k8s. We install the officially provided Ingress-nginx controller here.

Of course, there are also various controllers provided by communities or companies:

picturepicture

There are two installation methods: helm or directly apply a resource file.

We will explain helm separately in a later chapter.

Just use the resource file to install it directly. I have uploaded it to GitHub and can be accessed here: https://github.com/crossoverJie/k8s-combat/blob/main/deployment/ingress-nginx.yaml

In fact, this file is copied directly from the official one, and you can also use this path to install it directly:

kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.8.2/deploy/static/provider/cloud/deploy.yaml
  • 1.

The content of the yaml file is the same.

However, please note that the container status may remain in the Pending state after installation. When viewing the container's events, you will find that the image pull failed.

k describe pod ingress-nginx-controller-7cdfb9988c-lbcst -n ingress-nginx
  • 1.

describe is a command used to view details of k8s objects.

In the yaml file just now, you can see that there are several images that need to be pulled. We can first manually pull the images locally:

picturepicture

docker pull registry.k8s.io/ingress-nginx/controller:v1.8.2
  • 1.

If it still cannot be pulled, you can try to configure several domestic mirror source mirror pulls:

picturepicture

The k8s that comes with docker-desktop is what I use here. I recommend readers and friends to also use this tool.

CreateIngress

After successful installation using the yaml just now, a Pod will be created under the ingress-nginx namespace. If the status is Running through the get command, the installation is successful.

$ k get pod -n ingress-nginx
NAME                            READY   STATUS    RESTARTS      AGE
ingress-nginx-controller-7cdf   1/1     Running   2 (35h ago)   3d
  • 1.
  • 2.
  • 3.

Namespace is also a built-in object of k8s. It can be simply understood as group management of resources. We can usually use it to distinguish different environments, such as dev/test/prod, etc. Resources in different namespaces will not interfere with each other, and Independent.

Then you can create the Ingress resource:

apiVersion: networking.k8s.io/v1  
kind: Ingress  
metadata:  
  name: k8s-combat-ingress  
spec:  
  ingressClassName: nginx  
  rules:  
    - host: www.service1.io  
      http:  
        paths:  
          - backend:  
              service:  
                name: k8s-combat-service  
                port:  
                  number: 8081  
            path: /  
            pathType: Prefix  
    - host: www.service2.io  
      http:  
        paths:  
          - backend:  
              service:  
                name: k8s-combat-service-2  
                port:  
                  number: 8081  
            path: /  
            pathType: Prefix
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • twenty one.
  • twenty two.
  • twenty three.
  • twenty four.
  • 25.
  • 26.
  • 27.

It is easy to understand after looking at this content. An Ingress object is created, and the focus is how the rules here are defined.

In k8s, we will come into contact with various Kinds in the future.

The ingressClassName: nginx here is also the name defined in the controller just installed, and is defined by this resource.

apiVersion: networking.k8s.io/v1  
kind: IngressClass  
metadata:  
  labels:  
    app.kubernetes.io/component: controller  
    app.kubernetes.io/instance: ingress-nginx  
    app.kubernetes.io/name: ingress-nginx  
    app.kubernetes.io/part-of: ingress-nginx  
    app.kubernetes.io/version: 1.8.2  
  name: nginx
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.

Our rule is very simple, which is to route two different domain names to two different services.

Here, for the convenience of testing, a k8s-combat-service-2 service is created. It is the same as k8s-combat-service, but the name is changed.

test

Also for the convenience of testing, I added a new interface in the application image to return the hostname of the current Pod.

http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {  
   name, _ := os.Hostname()  
   fmt.Fprint(w, name)  
})
  • 1.
  • 2.
  • 3.
  • 4.

Since I don't actually have the two domain names www.service1.io/www.service2.io, I can only configure the host locally for simulation.

10.0.0.37 www.service1.io
10.0.0.37 www.service2.io
  • 1.
  • 2.

The k8s I'm testing is deployed on a restricted Mac at home, so here's the IP address.

When we repeatedly request this interface twice, we will get two different hostnames, which means that our request rotation is loaded into the two Pods proxied by these two services.

❯ curl http://www.service1.io/
k8s-combat-service-79c5579587-b6nlj%
❯ curl http://www.service1.io/
k8s-combat-service-79c5579587-bk7nw%
❯ curl http://www.service2.io/
k8s-combat-service-2-7bbf56b4d9-dkj9b%
❯ curl http://www.service2.io/
k8s-combat-service-2-7bbf56b4d9-t5l4g
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.

We can also use describe directly to view our ingress definition and routing rules:

picturepicture

$ k describe ingress k8s-combat-ingress
Name:             k8s-combat-ingress
Labels:           <none>
Namespace:        default
Address:          localhost
Ingress Class:    nginx
Default backend:  <default>
Rules:
  Host             Path  Backends
  ----             ----  --------
  www.service1.io
                   /   k8s-combat-service:8081 (10.1.0.65:8081,10.1.0.67:8081)
  www.service2.io
                   /   k8s-combat-service-2:8081 (10.1.0.63:8081,10.1.0.64:8081)
Annotations:       <none>
Events:            <none>
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.

If we manually add a domain name resolution:

10.0.0.37 www.service3.io
❯ curl http://www.service3.io/
<html>
<head><title>404 Not Found</title></head>
<body>
<center><h1>404 Not Found</h1></center>
<hr><center>nginx</center>
</body>
</html>
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.

It will directly 404 because no rules for this domain name were found.

Access principle

picturepicture

The entire request path is shown in the figure above. In fact, our Ingress is also essentially a service (so it can also start multiple copies for load), but its type is LoadBalancer. Usually this type of service will be bundled by cloud vendors. Set an external IP so that you can access Ingress through this external IP.

The service of our application is ClusterIP, which can only be accessed within the application.

picturepicture

We can also see from the service information that the external IP bound to our ingress service is localhost (for local reasons).

Summarize

Ingress usually acts as a gateway. When we use Istio later, we can also use the controller provided by Istio to replace Ingress-nginx, which can more conveniently manage internal and external network traffic.

All the source code of this article can be accessed here: https://github.com/crossoverJie/k8s-combat