Kubernetes学习指南(四)–创建对外服务的HTTP和HTTPS路由 Nginx-Ingress
Ingress 公开了从集群外部到集群内Services
的HTTP
和HTTPS
路由,访问流量路由由Ingress资源上定义的规则控制。
Ingress: HTTP 7层路由机制
使用Ingress
进行负载均衡时,Ingress Controller
将基于Ingress
规则将客户端请求直接转发到Service
对应的后端Endpoint
(即Pod
)上,这样会跳过kube-proxy
的转发功能.
如果Ingress Controller
提供的是对外服务,则实际上实现的就是边缘路由器(边缘路由器是在网络的边界点用于与其他网络(例如Intemet)相连接的路由器)的功能.
Internet
|
[ mywebsite.com (Ingress Controller) ]
-----------|-----------|------------|
/api /web /cmd
| | |
| | |
↓ ↓ ↓
[ API WEB CMD ]
- 对
http://mywebsite.com/api
的访问将被路由到后端API
的Service
- 对
http://mywebsite.com/web
的访问将被路由到后端WEB
的Service
- 对
http://mywebsite.com/cmd
的访问将被路由到后端CMD
的Service
创建Ingress Controller
环境准备
开始之前先明确机器所处环境,如果是在GCE,Azure,AWS等云服务提供商,可以直接使用云服务提供商的LoadBalancer,具体可以参考此链接.
以下例子是基于裸机(公网IP + 内网互联)组成,使用谷歌提供的Nginx-ingress-controller
来创建Ingress Controller
Ingress Controller
服务
在Kubernetes
中,Ingress Controller
将以Pod
的形式运行,监控Apiserver
的Ingress
接口,如果Service
有发生CRUD
,则Ingress Controller
自动更新转发规则.
实现的基本逻辑如下:
- 创建相对应权限的
Role
,监听Apiserver
,获取全部Ingress
的定义 - 基于
Ingress
的定义,生成Nginx
所需的配置文件/etc/nginx/nginx.conf
- 执行
nginx -s reload
命令,重新加载nginx.conf
配置文件的内容
本例使用谷歌提供的NGINX Ingress Controller 镜像来创建Ingress Controller
该Ingress Controller
以Daemonset
的形式进行创建,在每个Node
上都创建一个Nginx
服务,用来监听HTTP
(80) HTTPS
(443) 注:如果你的网络域有云厂商提供的负载均衡,请参考 https://kubernetes.github.io/ingress-nginx/deploy/
中不同厂商的特定步骤
创建Nginx Ingress Controller
下载部署文件
wget -O nginx-ingress-controller.yaml https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.29.0/deploy/static/mandatory.yaml
## 或者直接下载修改完成的部署文件
wget -O nginx-ingress-controller.yaml https://raw.githubusercontent.com/charSLee013/Kubernetes-learn/master/chapter04/nginx-ingress-controller.yaml
修改如下:
args:
...
...
- --default-backend-service=$(POD_NAMESPACE)/nginx-errors ## 默认错误导向
- --v=3 ## debug模式,仅在调试下使用
- 默认的
backend
,用于在客户端访问的URL
地址不存在时能返回一个正确应答404应发. - 开启debug模式
--v=3
,只适用于开发环境 - 注释了
LimitRange
的性能限制,增大性能上限
部署命令
# kubectl apply -f https://raw.githubusercontent.com/charSLee013/Kubernetes-learn/master/chapter04/nginx-ingress-controller.yaml
namespace/ingress-nginx created
configmap/nginx-configuration created
configmap/tcp-services created
configmap/udp-services created
serviceaccount/nginx-ingress-serviceaccount created
clusterrole.rbac.authorization.k8s.io/nginx-ingress-clusterrole created
role.rbac.authorization.k8s.io/nginx-ingress-role created
rolebinding.rbac.authorization.k8s.io/nginx-ingress-role-nisa-binding created
clusterrolebinding.rbac.authorization.k8s.io/nginx-ingress-clusterrole-nisa-binding created
daemonset.apps/nginx-ingress-controller created
service/ingress-nginx created
service/nginx-errors created
deployment.apps/nginx-errors created
验证服务是否正常工作
- 检查
nginx-ingress
和nginx-errors
是否启动成功
# kubectl get daemonset -n ingress-nginx -o wide
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE CONTAINERS IMAGES SELECTOR
nginx-ingress-controller 3 3 3 3 3 <none> 4m4s nginx-ingress-controller quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.26.2 app.kubernetes.io/name=ingress-nginx,app.kubernetes.io/part-of=ingress-nginx
READY
数量应该为Node
机器总数
- 如果有启动失败,可以通过
Kubectl logs <POD_NAME>
查看日志
#for p in `kubectl get pod -n ingress-nginx | grep "nginx-ingress-controller" | awk '{print $1}'`;do kubectl logs $p -n ingress-nginx;read -p "Enter Next Page" ;done;
...
...
I0216 21:39:18.514040 6 queue.go:122] skipping ingress-nginx/ingress-nginx sync (1581889155180651743 > 1581889128183115981)
I0216 21:39:18.514044 6 queue.go:122] skipping ingress-nginx/ingress-nginx sync (1581889155180651743 > 1581889131836726290)
I0216 21:39:18.514049 6 queue.go:122] skipping ingress-nginx/ingress-nginx sync (1581889155180651743 > 1581889132062227536)
Enter Next Page
- 用
curl
访问任意Node
的80
端口
#curl http://<外网IP地址>:80
<span>The page you're looking for could not be found.</span>
由于我们没有对 /
路径做任何转发规则,所以返回的default-bakcend-service
(nginx-errors
) 的应答
定义nginx-ingress
域名路由转发策略
本例对mywebsite.com
网站的访问设置Ingress
策略,定义对其demo.mywebsite.com
路径的转发到后端default/php-apache
的规则
后端default/php-apache
部署可以参考此文章
cat <<EOF > php-apache-ingress.yaml
# vi php-apache-ingress.yaml
---
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: test-simple
namespace: default ## namespace必须跟转发后端处于同一个命名空间内
annotations:
kubernetes.io/ingress.class: "nginx"
## 将 /foo 重定向 成 /
## 默认情况下 demo.com/foo -> service/foo
## 重写后成为 demo.com/foo -> service/
nginx.ingress.kubernetes.io/rewrite-target: /$1
# 开启use-regex,启用path的正则匹配
# nginx.ingress.kubernetes.io/use-regex: "true"
spec:
rules:
- host: demo.mywebsite.com ## 这里改成你的域名
http:
paths:
- path: /
backend:
serviceName: "php-apache"
servicePort: 80
EOF
kubectl apply -f php-apache-ingress.yaml
然后添加A记录指向Node
机器的外网IP,我这里以cloudflare
为例子
注意:要为所有的Node
的机器添加A
记录转发,有多台Node
机器情况下可以根据实际情况做DNS
负载
客户端访问http://demo.mywebsite.com
在客户端访问刚刚创建好的ingress
策略
curl -I http://demo.mywebsite.com/
HTTP/1.1 200 OK
Date: Sun, 16 Feb 2020 23:41:35 GMT
Content-Type: text/html; charset=UTF-8
Connection: keep-alive
Set-Cookie: __cfduid=d7de162fc1194de497afc9f33c02f2ce91581896495; expires=Tue, 17-Mar-20 23:41:35 GMT; path=/; domain=.mywebsite.com; HttpOnly; SameSite=Lax
Vary: Accept-Encoding
X-Powered-By: PHP/5.6.14
CF-Cache-Status: DYNAMIC
Server: cloudflare
CF-RAY: 56635f8a0dfddd2e-SIN
HTTP
路由设置成功,但由于我们没有设置TLS
证书,当以HTTPS
访问的时候会报错
如果域名是在cloudflare
上管理的,可以在SSL/TLS
功能内开启全网TLS
加密功能
如图所示,一定要选择Full
一键安装nginx ingress
kubectl apply -f https://raw.githubusercontent.com/charSLee013/Kubernetes-learn/master/chapter04/nginx-ingress-controller.yaml
更多学习文章在点击访问