理论基础
Ingress 公开了从集群外部到集群内服务的 HTTP 和 HTTPS 路由。 流量路由由 Ingress 资源上定义的规则控制。
下面是一个将所有流量都发送到同一 Service 的简单 Ingress 示例:
使用Ingress的重要原因是,每个service如果希望暴露给集群外部都需要一个负载均衡器以及一个独有的公网IP地址,而Ingress只需要一个公网IP地址就能为许多服务提供访问。如下图所示:
要使用Ingress,必须要有Ingress控制器,K8S支持多种Ingress控制器,常用的有HAProxy 与 Nginx控制器。
安装Ingress 控制器
方法一)
参考文档:
helm安装: https://github.com/kubernetes/ingress-nginx
- 公网安装最新版本,需要从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
2. K8S 1.22版本,按照以下方式安装。镜像已经预先下载,配置文件使用Daemonset方式安装,指定service类型为LoadBalancer:
```bash
kubectl create ns ingress-nginx
cp /resources/helm/helm /bin/
helm install ingress-nginx /resources/helm/ingress-nginx/ -n ingress-nginx
kubectl get all -n ingress-nginx
- 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
<a name="2VMPD"></a>
## 方法二)
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
**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) 验证
[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
<a name="xvibk"></a>
# Ingress使用范例
<a name="XykrH"></a>
## 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
<a name="wIWA1"></a>
##
<a name="gdwJ7"></a>
## 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
到Master或worker主机上验证
[root@master ~]# curl 10.105.82.83 AAAAAA [root@master ~]# curl 10.103.158.125 BBBBBB
<a name="BGRWX"></a>
## 3) 创建Ingress
![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)
<a name="1AUMu"></a>
### 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:
name: nginx1
port:
number: 80
- path: /
pathType: Prefix
backend:
service:
- host: nginx2.example.com
http:
paths:
- pathType: Prefix
path: “/“
backend:
service:
name: nginx2
port:
number: 80
- pathType: Prefix
path: “/“
backend:
service:
[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
测试:<br />在clientvm上使用vi修改LB的文件,使用ingress 的service的HostPort替换以下的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
到worker1修改/etc/hosts,增加一行
[root@worker1 ~]# cat /etc/hosts …… 192.168.241.134 clientvm.example.com clientvm nginx1.example.com nginx2.example.com
验证:
[root@worker1 ~]# curl http://nginx1.example.com/ AAAAAA [root@worker1 ~]# curl http://nginx2.example.com/ BBBBBB
<a name="sG72b"></a>
### 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:
name: nginx1
port:
number: 80
- path: /nginx2
pathType: Prefix
backend:
service:
name: nginx2
port:
number: 80
- path: /nginx1
pathType: Prefix
backend:
service:
[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
如果配置的Ingress使用如下声明,则不需要再每一个Pod中创建匹配的目录
```bash
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
验证:
分别在两个Pod上创建目录
[root@clientvm service]# kubectl exec nginx1 -it -- bash
root@nginx1:/# cd /usr/share/nginx/html
root@nginx1:/usr/share/nginx/html# mkdir nginx1
root@nginx1:/usr/share/nginx/html# echo AAAAAAAAAAAAAAAA >nginx1/index.html
root@nginx1:/usr/share/nginx/html# exit
exit
[root@clientvm service]# kubectl exec nginx2 -it -- bash
root@nginx2:/# cd /usr/share/nginx/html/
root@nginx2:/usr/share/nginx/html# mkdir nginx2
root@nginx2:/usr/share/nginx/html# echo BBBBBBBBBB >nginx2/index.html
root@nginx2:/usr/share/nginx/html# exit
exit
[root@worker1 ~]# curl clientvm.example.com/nginx1/
AAAAAAAAAAAAAAAA
[root@worker1 ~]# curl clientvm.example.com/nginx2/
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版本以后
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
......
spec:
rules:
- host: rewrite.bar.com
http:
paths:
- backend:
serviceName: http-svc
servicePort: 80
path: /something(/|$)(.*)
(.*)捕获的任何字符都将被分配给占位符$2,然后将其作为重写目标注释中的参数使用
上面的输入定义将导致以下重写:
rewrite.bar.com/something
rewrites torewrite.bar.com/
rewrite.bar.com/something/
rewrites torewrite.bar.com/
rewrite.bar.com/something/new
rewrites torewrite.bar.com/new
rewrite.bar.com/
将会匹配错误,因为没有匹配上预定义path /something
范例 2:
在上例的基础上增加如下
annotations:
nginx.ingress.kubernetes.io/app-root: /something/
任何对http://rewrite.bar.com/ 的访问都定向到http://rewrite.bar.com/something/
范例 3:
annotations:
kubernetes.io/ingress.class: "nginx"
使用ingress class: nginx
此功能在1.22版本上已经废弃,被替换为
spec:
ingressClassName: nginx