Use ingress to expose pod services inside the kubernetes cluster

What are Ingress and Ingress Controller?

We provide the services inside the kubernetes cluster to the outside world to access the following problems:

1. Pod drift problem

Kubernetes has powerful replica control capabilities, which can ensure that a new replica (Pod) is automatically started from other machines when any replica (Pod) hangs, and it can also be dynamically expanded. In layman's terms, this Pod may appear on any node at any time. It may also die on any node at any time; then naturally as the Pod is created and destroyed, the Pod IP will definitely change dynamically; then how to expose this dynamic Pod IP? Here, with the help of Kubernetes Service mechanism, Service can select a group of Pods with specified labels in the form of labels, and monitor and automatically load their Pod IP, then we only expose Service IP for external exposure; this is NodePort Mode: Open a port on each node, and then forward it to the internal Pod IP, as shown in the following figure:

Access method at this time: http://nodeip :nodeport/

image


2. Port management issues

The problem with exposing services in the NodePort method is that once more services become available, the ports opened by NodePort on each node will be extremely large and difficult to maintain; at this time, can we use an Nginx to directly forward it internally? As we all know, Pod and Pod can communicate with each other, and Pod can share the network name space of the host machine, that is to say, when sharing the network name space, what the Pod listens to is the port on the Node. So how can this be achieved? The simple implementation is to use DaemonSet to listen to 80 on each Node, and then write the rules, because Nginx is bound to the host's port 80 (just like NodePort), and it is in the cluster, then it is forwarded directly to the corresponding Service IP. That's it, as shown in the following figure:

image


3. Domain name allocation and dynamic update issues

From the above method, using Nginx-Pod seems to have solved the problem, but in fact there is a big flaw in it: how to modify the Nginx configuration every time a new service is added? We know that using Nginx can distinguish different services by virtual host domain name, and each service defines different load balancing pools through upstream, plus the reverse proxy of location for load balancing. In daily use, only nginx needs to be modified. conf can be achieved, then how to achieve this way of scheduling in K8S? Assuming that the initial service of the back-end service is only ecshop, and bbs and member services are added later, how to add these two services to Nginx-Pod for scheduling? You can't manually change or Rolling Update front-end Nginx Pod every time! At this time, Ingress appeared. If you don't count the above Nginx, Ingress contains two major components: Ingress Controller and Ingress.

image

The simple understanding of Ingress is that you originally need to change the Nginx configuration, and then configure which Service the various domain names correspond to. Now you abstract this action and turn it into an Ingress object. You can create it with yaml. Don't change Nginx every time, just change it. yaml can then be created/updated; then the question is: "What should Nginx do?"

Ingress Controller is the solution to the "Nginx processing method"; Ingress Controoler interacts with the Kubernetes API to dynamically perceive the changes in the Ingress rules in the cluster, then reads it, generates a piece of Nginx configuration according to its own template, and writes it to Nginx In the Pod, finally reload, the workflow is as follows:

image

In fact, Ingress is also one of the standard resource types of the Kubernetes API. It is actually a set of rules that forward requests to the specified Service resource based on the DNS name (host) or URL path. It is used to forward the request traffic outside the cluster to the service publishing completed inside the cluster. What we need to understand is that the Ingress resource itself cannot perform "traffic penetration". It is just a collection of rules. These collection rules also need the assistance of other functions, such as monitoring a socket, and then routing according to the matching of these rules Forwarding, these components that can monitor sockets for Ingress resources and forward traffic are Ingress Controllers.

Note: The Ingress controller is different from the Deployment controller in that the Ingress controller does not directly run as part of the kube-controller-manager. It is only an accessory to the Kubernetes cluster, similar to CoreDNS, and needs to be deployed separately on the cluster.


4. What are Ingress Controllers?

Ingress Controller is a seven-layer load balancing scheduler. Client requests first arrive at this seven-layer load balancing scheduler, and the seven-layer load balancer reverses proxy to the backend pod. Common seven-layer load balancers include nginx and traefik. Wait, take the familiar nginx as an example. If the request arrives in nginx, it will be forwarded to the back-end pod through the upstream reverse proxy, but the ip address of the back-end pod is always changing, so a service needs to be added before the back-end pod. This service only plays a role of grouping, so we only need to fill in the service address for upstream .

What are the common seven-layer load balancing schedulers:

nginx: Need to manually load the configuration file

traefik: The configuration file is automatically loaded on a regular basis without manual intervention. This kind of scheduler is almost always used in microservices


5. What is Ingress?

Official: https://kubernetes.io/docs/concepts/services-networking/ingress/

Ingress official website definition: ingress can forward requests that enter the cluster to some services in the cluster, so that the service can be exposed to the outside of the cluster. Ingress can configure the service in the cluster to a URL that can be accessed from the external network, load balance traffic, and provide virtual hosts based on domain name access. Ingress is a resource in k8s. When the back-end pod ip address associated with the service changes, it will change These changes are stored in ingress and injected into the seven-layer load balancing scheduler ingress controller by ingress, that is, the information is passed into the configuration file of the seven-layer load balancing scheduler, and reloaded to make the configuration effective, Ingress can be used To specify which Service the HTTP/S request should be forwarded to, for example, let the request fall on a different Service according to the different Host and URL paths in the request


6. Summary:

Ingress Controller:

Ingress Controller can be understood as a controller. It continuously interacts with the Kubernetes API to obtain real-time changes to the back-end Service and Pod, such as adding and deleting, and then generates a configuration based on the rules defined by Ingress, and then dynamically updates the above Nginx or trafik load balancer, and refresh the configuration to take effect, to achieve the role of automatic service discovery.

Ingress:

Ingress is a definition rule through which a request for a certain domain name is forwarded to the specified Service in the cluster. It can be defined through a Yaml file, and one or more Ingress rules can be defined for one or more services.


7. Steps to use the seven-layer load balancing scheduler

(1) Deploy the ingress controller, our ingress controller uses traefik

(2) Create a service to group pods

(3) Create a pod application, you can create a pod through the controller

(4) Create ingress http, test access to k8s internal pod through http

(5) Create ingress https, test access to k8s internal pod through https


8. The way the client accesses the backend pod through the seven-layer scheduler

When using the seven-layer load balancing scheduler ingress controller, when the client accesses the application inside the kubernetes cluster, the packet flow is shown in the following process:

client--->Nodeip:port----->IngressController--->service--->pod

image

How to create Ingress resources

Ingress resources are forwarding rules based on HTTP virtual hosts or URLs. It should be emphasized that this is a forwarding rule . It is defined by nesting fields such as rules, backend, and tls in the spec field in the resource configuration list. In the following example, an Ingress resource is defined, which contains a forwarding rule: the request sent to tomcat.lucky.com is proxied to a Service resource named myapp.

apiVersion: extensions/v1beta1    kind: Ingress    metadata:        name: ingress-myapp     namespace: default       annotations:              kubernetes.io/ingress.class: "nginx"spec:       rules:     - host: tomcat.lucky.com       http:      paths:             - path:               backend:              serviceName: myapp          servicePort: 80

The spec field in Ingress is the core component of Ingress resources, and it mainly contains the following 3 fields:

rules: A list of forwarding rules used to define the current Ingress resource; when rules are defined by rules, or no rules are matched, all traffic will be forwarded to the default backend defined by backend.

backend:默认的后端用于服务那些没有匹配到任何规则的请求;定义Ingress资源时,必须要定义backend或rules两者之一,该字段用于让负载均衡器指定一个全局默认的后端。

tls:TLS配置,目前仅支持通过默认端口443提供服务,如果要配置指定的列表成员指向不同的主机,则需要通过SNI TLS扩展机制来支持该功能。

backend对象的定义由2个必要的字段组成:serviceName和servicePort,分别用于指定流量转发的后端目标Service资源名称和端口。rules对象由一系列的配置的Ingress资源的host规则组成,这些host规则用于将一个主机上的某个URL映射到相关后端Service对象,其定义格式如下:

spec:  rules:  - hosts: <string>    http:      paths:      - path:        backend:          serviceName: <string>          servicePort: <string>

需要注意的是,.spec.rules.host属性值,目前暂不支持使用IP地址定义,也不支持IP:Port的格式,该字段留空,代表着通配所有主机名。tls对象由2个内嵌的字段组成,仅在定义TLS主机的转发规则上使用。

hosts:包含 于 使用 的 TLS 证书 之内 的 主机 名称 字符串 列表, 因此, 此处 使用 的 主机 名 必须 匹配 tlsSecret 中的 名称。

secretName: 用于 引用 SSL 会话 的 secret 对象 名称, 在 基于 SNI 实现 多 主机 路 由 的 场景 中, 此 字段 为 可选。

Ingress资源类型

Ingress的资源类型有以下4种:

1、单Service资源型Ingress2、基于URL路径进行流量转发3、基于主机名称的虚拟主机4、TLS类型的Ingress资源

单Service资源型Ingress

暴露单个服务的方法有多种,如NodePort、LoadBanlancer等等,当然也可以使用Ingress来进行暴露单个服务,只需要为Ingress指定default backend即可,如下示例:

apiVersion: extensions/v1beta1kind: Ingressmetadata:  name: my-ingressspec:  backend:    serviceName: my-svc    servicePort: 80

Ingress控制器会为其分配一个IP地址接入请求流量,并将其转发至后端my-svc

Ingress Nginx部署

使用Ingress功能需要如下步骤:

1、安装部署ingress controller Pod2、部署后端服务3、部署ingress-nginx service4、部署ingress

1.安装Ingress Controller

1)把Ingress相关的yaml文件传到k8s的master节点的/root/test目录

mkdir /root/test

需要上传到这个目录下的yaml文件为

Ingress相关的yaml文件在百度网盘,地址如下:

链接:https://pan.baidu.com/s/1SF9Ni0CK0QmTFDEglmejiA 提取码:61co

2)创建ingress-nginx名称空间

kubectl apply -f namespace.yaml

3)创建ingress controller的pod

kubectl apply -f .

4)测试部署是否成功

kubectl get all -n ingress-nginx

显示如下,说明部署成功了:

NAME                                            READY   STATUS    RESTARTS   AGEpod/default-http-backend-78d75577fd-g4b8n       1/1     Running   0          3m2spod/nginx-ingress-controller-7c7d57b55d-ng2gr   1/1     Running   0          3m2s
NAME                           TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGEservice/default-http-backend   ClusterIP   10.106.23.48   <none>        80/TCP    3m2s
NAME                                       READY   UP-TO-DATE   AVAILABLE   AGEdeployment.apps/default-http-backend       1/1     1            1           3m2sdeployment.apps/nginx-ingress-controller   1/1     1            1           3m2s
NAME                                                  DESIRED   CURRENT   READY   AGEreplicaset.apps/default-http-backend-78d75577fd       1         1         1       3m2sreplicaset.apps/nginx-ingress-controller-7c7d57b55d   1         1         1       3m2s

2.部署后端服务

1)部署后端服务

mkdir /root/test/ingress  && cd  /root/test/ingress

cat deploy-demo.yaml

apiVersion: v1kind: Servicemetadata:  name: myapp  namespace: defaultspec:  selector:    app: myapp    release: canary  ports:  - name: http    targetPort: 80    port: 80---apiVersion: apps/v1kind: Deploymentmetadata:  name: myapp-backend-pod  namespace: defaultspec:  replicas: 3  selector:    matchLabels:      app: myapp      release: canary  template:    metadata:      labels:        app: myapp        release: canary    spec:      containers:      - name: myapp        image: ikubernetes/myapp:v2        ports:        - name: http          containerPort: 80

2)更新yaml文件

kubectl apply -f deploy-demo.yaml

3)查看pod是否部署成功

kubectl get pods

显示如下,说明部署成功:

myapp-backend-pod-559ff5c66-6jgjs     1/1     Running   0          6smyapp-backend-pod-559ff5c66-fthgt     1/1     Running   0          6smyapp-backend-pod-559ff5c66-xtz6z     1/1     Running   0          6s


3.部署ingress-nginx service

通过ingress-controller对外提供服务,现在还需要手动给ingress-controller建立一个service,接收集群外部流量。方法如下:

1)下载ingress-controller的yaml文件

cat service-nodeport.yaml

apiVersion: v1kind: Servicemetadata:  name: ingress-nginx  namespace: ingress-nginx  labels:    app: ingress-nginxspec:  type: NodePort  ports:    - name: http      port: 80      targetPort: 80      protocol: TCP      nodePort: 30080    - name: https      port: 443      targetPort: 443      protocol: TCP      nodePort: 30443  selector:    app: ingress-nginx

2)创建ingress-controller的service

kubectl apply -f service-nodeport.yaml

查看service是否创建成功

kubectl get svc -n ingress-nginx

显示如下,说明创建成功:

ingress-nginx          NodePort    10.101.70.164   <none>        80:30080/TCP,443:30443/TCP   90s

3)浏览器访问ingress-controller的service

192.168.0.6:30080

注:192.168.0.6是k8s的master节点ip

此时应该是404 ,调度器是正常工作的,但是后端服务没有关联

image

4.部署ingress

(1)编写ingress的配置清单

cat ingress-myapp.yaml

apiVersion: extensions/v1beta1          #api版本kind: Ingress           #清单类型metadata:                       #元数据  name: ingress-myapp    #ingress的名称  namespace: default     #所属名称空间  annotations:           #注解信息    kubernetes.io/ingress.class: "nginx"spec:      #规格  rules:   #定义后端转发的规则  - host: tomcat.lucky.com    #通过域名进行转发    http:      paths:             - path:       #配置访问路径,如果通过url进行转发,需要修改;空默认为访问的路径为"/"        backend:    #配置后端服务          serviceName: myapp          servicePort: 80


2)更新yaml文件

kubectl apply -f ingress-myapp.yaml

3)查看ingress-myapp的详细信息

kubectl describe ingress ingress-myapp

显示如下:

Name:             ingress-myappNamespace:        defaultAddress:          Default backend:  default-http-backend:80 (<error: endpoints "default-http-backend" not found>)Rules:  Host              Path  Backends  ----              ----  --------  tomcat.lucky.com                         myapp:80 (10.244.1.57:80,10.244.1.58:80,10.244.1.59:80)Annotations:        kubernetes.io/ingress.class: nginxEvents:  Type    Reason  Age   From                      Message  ----    ------  ----  ----                      -------  Normal  CREATE  44s   nginx-ingress-controller  Ingress default/ingress-myapp

4)修改本地host文件,下面的ip是k8s的master节点ip

192.168.0.6  tomcat.lucky.com

5)浏览器访问tomcat.lucky.com:30080

出现如下:

image

5.部署ingress-测试代理tomcat服务

1)部署tomcat服务

cat tomcat-demo.yaml

apiVersion: v1kind: Servicemetadata:  name: tomcat  namespace: defaultspec:  selector:    app: tomcat    release: canary  ports:  - name: http    targetPort: 8080    port: 8080  - name: ajp    targetPort: 8009    port: 8009---apiVersion: apps/v1kind: Deploymentmetadata:  name: tomcat-deploy  namespace: defaultspec:  replicas: 3  selector:    matchLabels:      app: tomcat      release: canary  template:    metadata:      labels:        app: tomcat        release: canary    spec:      containers:      - name: tomcat        image: tomcat:8.5.34-jre8-alpine           ports:        - name: http          containerPort: 8080          name: ajp          containerPort: 8009


2)更新yaml文件

kubectl apply -f tomcat-demo.yaml

3)查看tomcat的pod是否部署成功

kubectl get pods

显示如下,说明创建成功:

tomcat-deploy-8655579b6c-5dfqw        1/1     Running   0          83stomcat-deploy-8655579b6c-9d79c        1/1     Running   0          83stomcat-deploy-8655579b6c-qmc62        1/1     Running   0          83s


4)编写tomcat的ingress规则,并创建ingress资源

cat ingress-tomcat.yaml

apiVersion: extensions/v1beta1kind: Ingressmetadata:  name: tomcat  namespace: default  annotations:    kubernetes.io/ingress.class: "nginx"spec:  rules:  - host: tomcat.lucky6.com    #主机域名    http:      paths:      - path:        backend:          serviceName: tomcat          servicePort: 8080


更新yaml文件:

kubectl apply -f ingress-tomcat.yaml

修改本地host文件,下面的ip是k8s的master节点ip

192.168.0.6  tomcat.lucky6.com

5)浏览器访问tomcat.lucky6.com:30080

可看到出现如下界面:

image

6)总结

从前面的部署过程中,可以再次进行总结部署的流程如下:

①下载Ingress-controller相关的YAML文件,并给Ingress-controller创建独立的名称空间;

②部署后端的服务,如myapp,并通过service进行暴露;

③部署Ingress-controller的service,以实现接入集群外部流量;

④部署Ingress,进行定义规则,使Ingress-controller和后端服务的Pod组进行关联。

构建TLS站点

(1)准备证书,在k8s的master节点操作

openssl genrsa -out tls.key 2048


openssl req -new -x509 -key tls.key -out tls.crt -subj /C=CN/ST=Beijing/L=Beijing/O=DevOps/CN=tomcat.lucky.com


(2)生成secret,在k8s的master节点操作

kubectl create secret tls tomcat-ingress-secret --cert=tls.crt --key=tls.key


(3)查看secret

kubectl get secret

显示如下:

tomcat-ingress-secret   kubernetes.io/tls                     2      56s

(4)查看tomcat-ingress-secret详细信息

kubectl describe secret tomcat-ingress-secret


显示如下:


Name:         tomcat-ingress-secretNamespace:    defaultLabels:       <none>Annotations:  <none>Type:  kubernetes.io/tlsData====tls.key:  1679 bytestls.crt:  1294 bytes


(5)创建ingress

cat ingress-tomcat-tls.yaml

apiVersion: extensions/v1beta1kind: Ingressmetadata:  name: ingress-tomcat-tls  namespace: default  annotations:    kubernetes.io/ingress.class: "nginx"spec:  tls:  - hosts:    - tomcat.lucky.com    secretName: tomcat-ingress-secret  rules:  - host: tomcat.lucky.com    http:      paths:      - path:        backend:          serviceName: tomcat          servicePort: 8080


Update yaml file

kubectl apply -f ingress-tomcat-tls.yaml

(6) Visit test:

https://tomcat.lucky.com:30443/

The above is the best Firefox browser to access, choose to accept the risk and continue, the following interface will appear

image


Guess you like

Origin blog.51cto.com/15127502/2655043