Five minutes of K8S practice - using Ingress
Five minutes of K8S practice - using Ingress
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:
picture
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:
picture
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:
picture
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:
picture
$ 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
picture
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.
picture
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