理论基础

Ingress 公开了从集群外部到集群内服务的 HTTP 和 HTTPS 路由。 流量路由由 Ingress 资源上定义的规则控制。
下面是一个将所有流量都发送到同一 Service 的简单 Ingress 示例:
image.png
使用Ingress的重要原因是,每个service如果希望暴露给集群外部都需要一个负载均衡器以及一个独有的公网IP地址,而Ingress只需要一个公网IP地址就能为许多服务提供访问。如下图所示:
image.png
要使用Ingress,必须要有Ingress控制器,K8S支持多种Ingress控制器,常用的有HAProxy 与 Nginx控制器。

安装Ingress 控制器

方法一)

参考文档:
helm安装: https://github.com/kubernetes/ingress-nginx

  1. 公网安装最新版本,需要从k8s.gcr.io下载镜像: ```bash helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx helm repo update helm show values ingress-nginx/ingress-nginx >ingress-values.yaml

helm install myingress ingress-nginx/ingress-nginx —values ingress-values.yaml -n ingress-nginx

  1. 2. K8S 1.22版本,按照以下方式安装。镜像已经预先下载,配置文件使用Daemonset方式安装,指定service类型为LoadBalancer
  2. ```bash
  3. kubectl create ns ingress-nginx
  4. cp /resources/helm/helm /bin/
  5. helm install ingress-nginx /resources/helm/ingress-nginx/ -n ingress-nginx
  6. kubectl get all -n ingress-nginx
  1. K8S 1.20版本按照以下方式安装: ``` kubectl create ns ingress-nginx cp /resources/helm/helm /bin/ helm install ingress-nginx /resources/helm/ingress-nginx-3.15.2.tgz -n ingress-nginx kubectl get all -n ingress-nginx
  1. <a name="2VMPD"></a>
  2. ## 方法二)
  3. yaml:<br />[https://docs.nginx.com/nginx-ingress-controller/installation/installation-with-manifests/](https://docs.nginx.com/nginx-ingress-controller/installation/installation-with-manifests/)<br />(不支持defaultBackend语法)<br />1) 安装

$ kubectl apply -f ns-and-sa.yaml $ kubectl apply -f rbac.yaml $ kubectl apply -f default-server-secret.yaml $ kubectl apply -f nginx-config.yaml $ kubectl apply -f ingress-class.yaml $ kubectl apply -f nginx-ingress-daemonset.yaml

  1. **If you created a daemonset**, ports 80 and 443 of the Ingress controller container are mapped to the same ports of the node where the container is running. To access the Ingress controller, use those ports and an IP address of any node of the cluster where the Ingress controller is running.<br />**If you created a deployment**, below are two options for accessing the Ingress controller pods.
  2. 2 验证

[root@clientvm ~]# kubectl get all -n nginx-ingress NAME READY STATUS RESTARTS AGE pod/nginx-ingress-4njn9 1/1 Running 0 44m pod/nginx-ingress-6htv2 1/1 Running 0 44m pod/nginx-ingress-8nd6w 1/1 Running 0 44m

NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE daemonset.apps/nginx-ingress 3 3 3 3 3 44m

  1. <a name="xvibk"></a>
  2. # Ingress使用范例
  3. <a name="XykrH"></a>
  4. ## 1)创建两个测试用的Pod

[root@clientvm ~]# kubectl run nginx1 —image=nginx —image-pull-policy=’IfNotPresent’ pod/nginx1 created [root@clientvm ~]# kubectl run nginx2 —image=nginx —image-pull-policy=’IfNotPresent’ pod/nginx2 created

[root@clientvm service]# kubectl get pod NAME READY STATUS RESTARTS AGE nginx1 1/1 Running 0 81m nginx2 1/1 Running 0 81m nginx3-default 1/1 Running 0 3m19s

[root@clientvm ~]# kubectl expose pod nginx1 —port=80 —target-port=80 service/nginx1 exposed [root@clientvm ~]# kubectl expose pod nginx2 —port=80 —target-port=80 service/nginx2 exposed

[root@clientvm service]# kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 443/TCP 128m nginx1 ClusterIP 10.107.202.107 80/TCP 81m nginx2 ClusterIP 10.100.175.93 80/TCP 81m

  1. <a name="wIWA1"></a>
  2. ##
  3. <a name="gdwJ7"></a>
  4. ## 2) 修改Nginx Web页面

[root@clientvm ~]# kubectl exec nginx1 -it — bash root@nginx1:/# echo AAAAAA >/usr/share/nginx/html/index.html root@nginx1:/# exit exit [root@clientvm ~]# kubectl exec nginx2 -it — bash root@nginx2:/# echo BBBBBB >/usr/share/nginx/html/index.html root@nginx2:/# exit exit

  1. Masterworker主机上验证

[root@master ~]# curl 10.105.82.83 AAAAAA [root@master ~]# curl 10.103.158.125 BBBBBB

  1. <a name="BGRWX"></a>
  2. ## 3) 创建Ingress
  3. ![image.png](https://cdn.nlark.com/yuque/0/2020/png/1700126/1607915468616-3f75a7cf-2214-4d7b-b06c-72d1da3540b6.png#crop=0&crop=0&crop=1&crop=1&height=214&id=zS7JH&margin=%5Bobject%20Object%5D&name=image.png&originHeight=427&originWidth=1271&originalType=binary&ratio=1&rotation=0&showTitle=false&size=59761&status=done&style=none&title=&width=635.5)
  4. <a name="1AUMu"></a>
  5. ### 3.1 虚拟主机

[root@clientvm service]# cat ingress-multi-hosts.yaml apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: name-virtual-host-ingress spec: ingressClassName: nginx defaultBackend: service: name: nginx1 port: number: 80 rules:

  • host: nginx1.example.com http: paths:
    • path: / pathType: Prefix backend: service:
      1. name: nginx1
      2. port:
      3. number: 80
  • host: nginx2.example.com http: paths:
    • pathType: Prefix path: “/“ backend: service:
      1. name: nginx2
      2. port:
      3. number: 80
      [root@clientvm service]# kubectl apply -f ingress-multi-hosts.yaml

[root@clientvm service]# kubectl get ingress Warning: extensions/v1beta1 Ingress is deprecated in v1.14+, unavailable in v1.22+; use networking.k8s.io/v1 Ingress NAME CLASS HOSTS ADDRESS PORTS AGE name-virtual-host-ingress nginx nginx1.example.com,nginx2.example.com 80 15m

  1. 测试:<br />在clientvm上使用vi修改LB的文件,使用ingress serviceHostPort替换以下的80端口:

[root@clientvm ~]# setenforce 0 [root@clientvm service]# tail -4 /etc/haproxy/haproxy.cfg balance roundrobin server worker1 worker1:80 check server worker2 worker2:80 check [root@clientvm service]# systemctl restart haproxy.service

  1. worker1修改/etc/hosts,增加一行

[root@worker1 ~]# cat /etc/hosts …… 192.168.241.134 clientvm.example.com clientvm nginx1.example.com nginx2.example.com

  1. 验证:

[root@worker1 ~]# curl http://nginx1.example.com/ AAAAAA [root@worker1 ~]# curl http://nginx2.example.com/ BBBBBB

  1. <a name="sG72b"></a>
  2. ### 3.2 基于Path的虚拟主机

[root@clientvm service]# cat ingress-service-path.yaml apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: simple-fanout-example spec: ingressClassName: nginx rules:

  • host: clientvm.example.com http: paths:
    • path: /nginx1 pathType: Prefix backend: service:
      1. name: nginx1
      2. port:
      3. number: 80
    • path: /nginx2 pathType: Prefix backend: service:
      1. name: nginx2
      2. port:
      3. number: 80

[root@clientvm service]# kubectl apply -f ingress-service-path.yaml ingress.networking.k8s.io/simple-fanout-example created

[root@clientvm service]# kubectl get ingress Warning: extensions/v1beta1 Ingress is deprecated in v1.14+, unavailable in v1.22+; use networking.k8s.io/v1 Ingress NAME CLASS HOSTS ADDRESS PORTS AGE simple-fanout-example nginx clientvm.example.com 80 6s

  1. 如果配置的Ingress使用如下声明,则不需要再每一个Pod中创建匹配的目录
  2. ```bash
  3. annotations:
  4. nginx.ingress.kubernetes.io/rewrite-target: /

验证:
分别在两个Pod上创建目录

  1. [root@clientvm service]# kubectl exec nginx1 -it -- bash
  2. root@nginx1:/# cd /usr/share/nginx/html
  3. root@nginx1:/usr/share/nginx/html# mkdir nginx1
  4. root@nginx1:/usr/share/nginx/html# echo AAAAAAAAAAAAAAAA >nginx1/index.html
  5. root@nginx1:/usr/share/nginx/html# exit
  6. exit
  7. [root@clientvm service]# kubectl exec nginx2 -it -- bash
  8. root@nginx2:/# cd /usr/share/nginx/html/
  9. root@nginx2:/usr/share/nginx/html# mkdir nginx2
  10. root@nginx2:/usr/share/nginx/html# echo BBBBBBBBBB >nginx2/index.html
  11. root@nginx2:/usr/share/nginx/html# exit
  12. exit
  1. [root@worker1 ~]# curl clientvm.example.com/nginx1/
  2. AAAAAAAAAAAAAAAA
  3. [root@worker1 ~]# curl clientvm.example.com/nginx2/
  4. BBBBBBBBBB

annotations的作用

Ingress 经常使用注解(annotations)来配置一些选项,具体取决于 Ingress 控制器,例如 重写目标注解。 不同的 Ingress 控制器 支持不同的注解。查看文档以供你选择 Ingress 控制器,以了解支持哪些注解。

参考:https://github.com/kubernetes/ingress-nginx/blob/master/docs/examples/rewrite/README.md

范例 1:
ingress-nginx Version 0.22.0版本以后

  1. annotations:
  2. nginx.ingress.kubernetes.io/rewrite-target: /$2
  3. ......
  4. spec:
  5. rules:
  6. - host: rewrite.bar.com
  7. http:
  8. paths:
  9. - backend:
  10. serviceName: http-svc
  11. servicePort: 80
  12. path: /something(/|$)(.*)

(.*)捕获的任何字符都将被分配给占位符$2,然后将其作为重写目标注释中的参数使用
上面的输入定义将导致以下重写:

  • rewrite.bar.com/something rewrites to rewrite.bar.com/
  • rewrite.bar.com/something/ rewrites to rewrite.bar.com/
  • rewrite.bar.com/something/new rewrites to rewrite.bar.com/new
  • rewrite.bar.com/ 将会匹配错误,因为没有匹配上预定义path /something

范例 2:
在上例的基础上增加如下

  1. annotations:
  2. nginx.ingress.kubernetes.io/app-root: /something/

任何对http://rewrite.bar.com/ 的访问都定向到http://rewrite.bar.com/something/

范例 3:

  1. annotations:
  2. kubernetes.io/ingress.class: "nginx"

使用ingress class: nginx
此功能在1.22版本上已经废弃,被替换为

  1. spec:
  2. ingressClassName: nginx