4.1 Ingress Controller 简介
在前面介绍 Service 时讲解过,Ingress 可以为集群提供外部客户端的 HTTP/HTTPS 访问功能,它需要 IngressController 搭配 Ingress 资源对象共同实现。
现在 Ingress 控制器有多种方案可以实现,下面简单的列出来供大家参考:
- Kubernetes Ingress Controller:官方推荐的控制器,成熟、易于使用、可以满足大多数情况。
- HAProxy Ingress:提供“软”配置更新、基于 DNS 的服务发现和通过 API 进行动态配置,还支持完全自定义配置文件模板。
- Ambassador:是 kubernetes 原生 API 微服务网关,可以与其他服务网(比如 Istio)一起使用。
- Voyager:是一个通用的解决方案,核心优势是在 4 层和 7 层上的流量负载均衡。
- Contour:可以通过 CRD 管理 Ingress 资源,并提供了一组扩展的负载均衡算法。 ...
由于篇幅限制,以上列出的控制器在这里都不会详细介绍,如果大家有兴趣的话可以自行探索。在本实验中会介绍:
- NGINX Ingress Controller
- Kong Ingress
- Traefik
- Istio Ingress
相信在学习了上述 4 种控制器后,大家也可以按照同样的方式了解其它的装饰器。
4.2 NGINX Ingress Controller
NGINX Ingress Controller 是采用 Go 语言实现的一款 Controller 插件,它是由 Nginx 公司开发的产品 NGINX Ingress Controller for Kubernetes,分别有两个版本:NGINX 社区版和 NGINX Plus 商业版。
NGINX Ingress Controller 具有高稳定性、持续向后兼容性、且没有第三方模块。社区版与官方的 Kubernetes Ingress Controller 相比较而言保证了更快的响应速度,如果大家想要了解更多的区别可以参考文档 Differences Between nginxinc/kubernetes-ingress and kubernetes/ingress-nginx Ingress Controllers。而 NGINX Plus 商业版相比于免费版本而言实现了更多的附加功能,比如:实时监控、主动健康检查、Session 保持等。
总体而言,NGINX Ingress 主要的优势在于对 TCP/UDP 流量的全面支持,但是缺乏流量的分配功能。如果项目对于服务的可靠性和功能实现有较高要求的话,可以选择 NGINX Plus 商业版。
下面介绍免费版的安装方式。由于需要部署多个 YAML 文件,所以在环境中将所需的文件全部打包为 zip 压缩包,大家使用命令执行下载即可,如果想要安装最新版,可以参考 Installing the Ingress Controller。
首先下载所需的文件:
wget https://labfile.oss.aliyuncs.com/courses/1457/nginx-ingress-controller.zip
unzip nginx-ingress-controller.zip
解压缩文件以后可以看到目录下有两个文件夹:deployments(用于部署的文件) 和 examples(用于测试的例子)。
执行创建:
$ cd nginx-ingress-controller
# 为 IngressController 创建 nginx-ingress 命令空间和服务账户
$ kubectl create -f deployments/ns-and-sa.yaml
namespace/nginx-ingress created
serviceaccount/nginx-ingress created
# 对于没有定义 ingress 规则的请求,服务默认返回 404 Not Found 页面,出于测试目的,这里使用自签名的证书和密钥生成了 default-server-secret,大家也可以使用自己的密钥
$ kubectl create -f deployments/default-server-secret.yaml
secret/default-server-secret created
# 创建 ConfigMap 可以自定义 nginx 的配置(大家可以按需编辑这个文件)
$ kubectl create -f deployments/nginx-config.yaml
configmap/nginx-config created
# 在集群中启动 RBAC,创建集群角色并绑定到服务账户
$ kubectl create -f deployments/rbac.yaml
clusterrole.rbac.authorization.k8s.io/nginx-ingress created
clusterrolebinding.rbac.authorization.k8s.io/nginx-ingress created
# 使用 DaemonSet 在每个 Node 节点部署一个 IngressController,在 spec.template.spec 中设置 hostNetwork=true,将容器的端口映射到节点上,这样就可以通过 NodeIP:ContainerPort 直接访问 Ingress
$ kubectl create -f deployments/nginx-ingress.yaml
daemonset.apps/nginx-ingress created
# 为 IngressController 创建 NodePort 类型的服务
$ kubectl create -f deployments/nodeport.yaml
service/nginx-ingress created
查看最终创建的资源对象:
$ kubectl get all -n nginx-ingress
NAME READY STATUS RESTARTS AGE
pod/nginx-ingress-nglnh 1/1 Running 0 38s
pod/nginx-ingress-zvvps 1/1 Running 0 38s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/nginx-ingress NodePort 10.96.158.24 <none> 80:30826/TCP,443:30079/TCP 18m
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
daemonset.apps/nginx-ingress 2 2 2 2 2 <none> 38s
现在运行例子,对 NGINX Ingress Controller 进行测试。
# 将 Ingress 的 NodeIP 地址保存到 IC_IP 环境变量中
$ export IC_IP=192.168.0.33
# 将 Ingress 的 HTTPS 环境变量端口保存到 IC_HTTPS_PORT 环境变量中
$ export IC_HTTPS_PORT=443
# 创建 coffee 和 tea 的 deployment 和 service
$ kubectl create -f examples/cafe.yaml -n nginx-ingress
deployment.apps/coffee created
service/coffee-svc created
deployment.apps/tea created
service/tea-svc created
# 使用 SSL 证书和密钥创建 cafe-secret
$ kubectl create -f examples/cafe-secret.yaml -n nginx-ingress
secret/cafe-secret created
# 创建 Ingress 规则,当访问 https://cafe.example.com:443/tea 时由后端 tea-svc 提供服务,访问 https://cafe.example.com:443/coffee 由后端 coffee-svc 提供服务
$ kubectl create -f examples/cafe-ingress.yaml -n nginx-ingress
ingress.extensions/cafe-ingress created
例子部署完成,执行测试:
# 通过 curl 访问服务,--resolve 参数设置请求头,--insecure 参数用于关闭自签名证书的验证
# 先访问 coffee service
$ curl --resolve cafe.example.com:$IC_HTTPS_PORT:$IC_IP https://cafe.example.com:$IC_HTTPS_PORT/coffee --insecure
4.3 Kong Ingress
Kong Ingress 是由 Kong lnc 开发,它也有两个版本:免费版和商业版。Kong Ingress 是基于 Nginx 构建,在其基础上增加了扩展其功能的 Lua 模块。
作为一款成熟的 IngressController,它的主要优点是在 Ingress 中可以配置大量的插件(拥有最丰富的插件集),用于扩展日志记录、分析、跟踪等功能,管理进出的流量,直接在入口层保护、监控和扩展服务。
Kong Ingress Controller 在 Kubernetes 集群内通过创建的 Ingress 资源对象配置 Kong。
Kong Ingress Controller 依然由两部分组成:
- Kong:核心代理,处理所有的流量。
- Controller:控制器,将配置从 kubernetes 同步到 Kong。
以下是工作原理图:

在 kubernetes 集群中可以以内存模式(DB-less)运行 Kong,因为所有的配置信息都存储在 Kubernetes control-plane 中。这样就不需要担心与数据库相关的各种问题。
下面在环境中安装部署并运行一个简单的例子进行测试。由于相关的文件比较多,将它们全部打包为 kong-ingress-controller.zip 压缩包,大家执行下载即可。如果想要自己尝试安装最新版本的,可以参考 Deploying Kong for Kubernetes。
首先下载资源文件:
wget https://labfile.oss.aliyuncs.com/courses/1457/kong-ingress-controller.zip
unzip kong-ingress-controller.zip
在文件夹中 all-in-one-dbless.yaml 就是用于相关资源对象创建的。
执行 Kong Ingress Controller 的部署:
$ cd kong-ingress-controller
# 注意:这里将文件中 Service 中的 LoadBalancer 改为了 NodePort,方便本地访问测试
$ kubectl create -f all-in-one-dbless.yaml
namespace/kong created
customresourcedefinition.apiextensions.k8s.io/kongconsumers.configuration.konghq.com created
customresourcedefinition.apiextensions.k8s.io/kongcredentials.configuration.konghq.com created
customresourcedefinition.apiextensions.k8s.io/kongingresses.configuration.konghq.com created
customresourcedefinition.apiextensions.k8s.io/kongplugins.configuration.konghq.com created
serviceaccount/kong-serviceaccount created
clusterrole.rbac.authorization.k8s.io/kong-ingress-clusterrole created
clusterrolebinding.rbac.authorization.k8s.io/kong-ingress-clusterrole-nisa-binding created
configmap/kong-server-blocks created
service/kong-proxy created
service/kong-validation-webhook created
deployment.apps/ingress-kong created
查看创建的资源对象:
$ kubectl get all -n kong
NAME READY STATUS RESTARTS AGE
pod/ingress-kong-8cc96c55-dms2f 2/2 Running 0 93s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kong-proxy NodePort 10.96.11.13 <none> 80:30973/TCP,443:31027/TCP 93s
service/kong-validation-webhook ClusterIP 10.96.197.167 <none> 443/TCP 93s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/ingress-kong 1/1 1 1 93s
NAME DESIRED CURRENT READY AGE
replicaset.apps/ingress-kong-8cc96c55 1 1 1 93s
$ kubectl get pod -o wide -n kong
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
ingress-kong-8cc96c55-dms2f 2/2 Running 0 9m29s 192.168.0.33 kubesphere03 <none> <none>
测试与 Kong 的连接,检查部署是否正确:
$ curl -I 192.168.0.33:8000
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Connection: keep-alive
Date: Tue, 11 Nov 2019 15:47:48 GMT
X-Kong-Upstream-Latency: 1
X-Kong-Proxy-Latency: 0
Via: kong/1.3.1
部署例子测试,安装一个 echo-server 应用程序用于测试,这个应用程序只返回来自 HTTP 请求相关的 pod 和详细信息:
$ kubectl create -f k8s-echo-server.yaml -n kong
service/echo created
deployment.apps/echo created
$ kubectl get pods,svc -n kong
NAME READY STATUS RESTARTS AGE
pod/echo-86b6455554-8dms8 1/1 Running 0 50s
pod/echo-86b6455554-dh68j 1/1 Running 0 50s
pod/echo-86b6455554-g5zzl 1/1 Running 0 50s
pod/echo-86b6455554-m99xc 1/1 Running 0 50s
pod/ingress-kong-8cc96c55-dms2f 2/2 Running 0 25m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/echo ClusterIP 10.96.67.24 <none> 8080/TCP,80/TCP 50s
service/kong-proxy NodePort 10.96.11.13 <none> 80:30973/TCP,443:31027/TCP 25m
service/kong-validation-webhook ClusterIP 10.96.197.167 <none> 443/TCP 25m
创建一个 Ingress 规则来代理之前创建的 echo-server 服务:
# 这里没有创建域名,所有对 NodeIP:ContainerPort/foo 的访问请求都会被转发到后端 echo:80 服务上
$ kubectl create -f ingress.yaml -n kong
ingress.extensions/demo created
$ kubectl get ingress -n kong
NAME HOSTS ADDRESS PORTS AGE
demo * 192.168.0.32,192.168.0.33 80 49s
# 进行测试,看到类似如下的返回就说明 Ingress 规则配置正确
$ curl 192.168.0.33:8000/foo
Hostname: echo-86b6455554-m99xc
Pod Information:
node name: kubesphere02
pod name: echo-86b6455554-m99xc
pod namespace: kong
pod IP: 10.20.138.45
...
上面提到过 Kong Ingress Controller 优点在于可以配置插件,现在来配置一款限制速率的服务插件。服务级别的插件是指:当来自客户端的任何请求被发送给 kubernetes 集群中特定的某个后端服务时,无论入口 url 是什么,Kong 都会执行这个插件。
使用服务插件:
# 创建 KongPlugin 资源对象
$ kubectl create -f kong-plugin.yaml -n kong
kongplugin.configuration.konghq.com/rl-by-ip created
# 修改 echo 服务配置,添加 annotations 注解说明需要应用 rl-by-ip 插件
$ kubectl patch svc echo -p '{"metadata":{"annotations":{"plugins.konghq.com": "rl-by-ip\n"}}}' -n kong
service/echo patched
配置完成后,任何发送到 echo 服务的请求都会受到 kong 强制执行的速率限制的保护:
$ curl -I 192.168.0.33:8000/foo
HTTP/1.1 200 OK
Content-Type: text/plain; charset=UTF-8
Connection: keep-alive
Date: Tue, 11 Nov 2019 16:15:28 GMT
Server: echoserver
X-RateLimit-Limit-minute: 5
X-RateLimit-Remaining-minute: 4
X-Kong-Upstream-Latency: 0
X-Kong-Proxy-Latency: 2
Via: kong/1.3.1
所以最终形成的配置如下所示:
# 来自客户端对于 /foo 的请求,先经过 Kong rate-limit 插件的处理,然后再转发给后端的 echo server
HTTP requests with /foo -> Kong enforces rate-limit -> echo server
4.4 Traefik
Traefik 是一款开源的反向代理与负载均衡工具,它可以与大多数的微服务系统直接整合,实现自动化动态配置。

与 Kubernetes Ingress Controller 相比,Traefik 本身就能够实时与 ApiServer 交互,获取后端 Service、Pod 的变化,自动更新配置并热加载。因此,Traefik 会更加快速、方便,支持更多特性使得反向代理和负载均衡更直接、高效。
下面在环境中进行配置并使用一个简单的 nginx 例子进行测试,由于需要使用较多文件,这里全部打包为 traefik-ingress-controller.zip 压缩包,如果大家想要获取最新的安装文件,可以参考 Kubernetes Ingress Controller。
下载所需的文件并解压缩:
wget https://labfile.oss.aliyuncs.com/courses/1457/traefik-ingress-controller.zip
unzip traefik-ingress-controller.zip
执行创建:
$ cd traefik-ingress-controller
# rbac 绑定
$ kubectl create -f traefik-rbac.yaml
clusterrole.rbac.authorization.k8s.io/traefik-ingress-controller created
clusterrolebinding.rbac.authorization.k8s.io/traefik-ingress-controller created
# 部署 traefik
$ kubectl create -f traefik-deployment.yaml
serviceaccount/traefik-ingress-controller created
deployment.apps/traefik-ingress-controller created
service/traefik-ingress-service created
检查资源对象是否创建成功:
$ kubectl get pods -n kube-system -l k8s-app=traefik-ingress-lb
NAME READY STATUS RESTARTS AGE
traefik-ingress-controller-7fbd75d9b4-rvvzd 1/1 Running 0 26s
traefik-ingress-controller-7fbd75d9b4-s99lr 1/1 Running 0 26s
$ kubectl get svc -n kube-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
...
traefik-ingress-service NodePort 10.96.152.22 <none> 80:30069/TCP,8080:31838/TCP 52s
# 80 端口是用于 http 访问
$ curl 192.168.0.33:80
<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><meta http-equiv="cache-control" content="max-age=0"/><meta http-equiv="cache-control" content="no-cache"/><meta http-equiv="expires" content="0"/><meta http-equiv="expires" content="Tue, 01 Jan 1980 1:00:00 GMT"/><meta http-equiv="pragma" content="no-cache"/><base href="/" data-inject-target="BASE_URL"/><link rel="shortcut icon" href="./favicon.ico"><title>Jaeger UI</title><script>// Jaeger UI config data is embedded by the query-service. This is...
# 8080 端口是用于 Admin 管理
$ curl 192.168.0.33:8080
<a href="/dashboard/">Found</a>.
在浏览器访问地址 192.168.0.33:8080,跳转到 dashboard 页面,效果如下所示:

部署一个 nginx 例子进行测试,其中 ingress 规则中设置域名为 traefik.example.com:
$ kubectl create -f nginx.yaml
service/nginx-svc created
deployment.apps/ngx-pod created
ingress.extensions/ngx-ing created
刷新 dashboard 页面,效果如下所示:

在浏览器访问 traefik.example.com:

还可以看到 dashboard 的健康检查:

评论区