简介
在kubernetes中对外暴露服务的方式有两种:service(NodePort或者外部LoadBalancer)和ingress,其中service是提供四层的负载均衡,通过iptables DNAT或lvs nat模式实现后端Pod的代理请求。如需实现http,域名,URI,证书等请求方式,service是无法实现的,需要借助于ingress来来实现,本文将来介绍ingress相关的内容。
ingress是一种通过http协议暴露kubernetes内部服务的api对象,即充当Edge Router边界路由器的角色对外基于七层的负载均衡调度机制,能够提供以下几个功能:
- 负载均衡,将请求自动负载均衡到后端的Pod上;
- SSL加密,客户端到Ingress Controller为https加密,到后端Pod为明文的http;
- 基于名称的虚拟主机,提供基于域名或URI更灵活的路由方式

实现Ingress包含的组件有:
- Ingress,客户端,负责定义ingress配置,将请求转发给Ingress Controller;
- Ingress Controller,Ingress控制器,实现七层转发的Edge Router,通过调用k8s的api动态感知集群中Pod的变化而动态更新配置文件并重载, Controller需要部署在k8s集群中以实现和集群中的pod通信,通常以DaemonSets或Deployments的形式部署,并对外暴露80和443端口,对于DaemonSets来说,一般是以hostNetwork或者hostPort的形式暴露,Deployments则以NodePort的方式暴露,控制器的多个节点则借助外部负载均衡ExternalLB以实现统一接入;
- Ingress配置规则,Controller控制器通过service服务发现机制动态实现后端Pod路由转发规则的实现;
- Service,kuberntes中四层的负载均衡调度机制,Ingress借助service的服务发现机制实现集群中Pod资源的动态感知;
- Pod,后端实际负责响应请求容器,由控制器如Deployment创建,通过标签Labels和service关联,服务发现。
简而言之,ingress控制器借助service的服务发现机制实现配置的动态更新以实现Pod的负载均衡机制实现,由于涉及到Ingress Controller的动态更新,目前社区Ingress Controller大体包含两种类型的控制器:
- 传统的七层负载均衡如Nginx,HAproxy,开发了适应微服务应用的插件,具有成熟,高性能等优点;
- 新型微服务负载均衡如Traefik,Envoy,Istio,专门适用于微服务+容器化应用场景,具有动态更新特点;
| 类型 | 常见类型 | 优点 | 缺点 |
|---|---|---|---|
| 传统负载均衡 | nginx,haproxy | 成熟,稳定,高性能 | 动态更新需reload配置文件 |
| 微服务负载均衡 | Traefik,Envoy,Istio | 天生为微服务而生,动态更新 | 性能还有待提升 |
Nginx Ingress
Nginx Ingress Controller是实现ingress的具体实现,利用openresty开发,基于deployments部署;其监听ingress资源变化,根据ingress配置生成若干server段,每一个server段对应一个应用的Domain,反向代理到对应service的若干POD,所有配置均生成到nginx.conf并自动热加载。
安装
首先需要安装Nginx Ingress Controller控制器,控制器安装方式包含两种:DaemonSets和Deployments。
- DaemonSets通过hostPort的方式暴露80和443端口,可通过Node的调度由专门的节点实现部署
- Deployments则通过NodePort的方式实现控制器端口的暴露,借助外部负载均衡实现高可用负载均衡
打开 https://kubernetes.github.io/ingress-nginx/ ,参考官方文档,以下是快速部署方法:
1 | kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.28.0/deploy/static/mandatory.yaml |
注意:镜像 quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.28.0 很慢,可以提前下载好。
部署成功之后,就可以看到以下的nginx-ingress-controller了。
1 | [root@master ingress-nginx]# kubectl get pods -n ingress-nginx nginx-ingress-controller-5556bd798f-dngnv |
用法简介
Ingress资源时基于HTTP虚拟主机或URL的转发规则,需要强调的是,这是一条转发规则。它在资源配置清单中的spec字段中嵌套了rules、backend和tls等字段进行定义。如下示例中定义了一个Ingress资源,其包含了一个转发规则:将发往myapp.magedu.com的请求,代理给一个名字为myapp的Service资源。
1 | apiVersion: extensions/v1beta1 |
Ingress 中的spec字段是Ingress资源的核心组成部分,主要包含以下3个字段:
- rules:用于定义当前Ingress资源的转发规则列表;由rules定义规则,或没有匹配到规则时,所有的流量会转发到由backend定义的默认后端。
- backend:默认的后端用于服务那些没有匹配到任何规则的请求;定义Ingress资源时,必须要定义backend或rules两者之一,该字段用于让负载均衡器指定一个全局默认的后端。
- tls:TLS配置,目前仅支持通过默认端口443提供服务,如果要配置指定的列表成员指向不同的主机,则需要通过SNI TLS扩展机制来支持该功能。
backend对象的定义由2个必要的字段组成:serviceName和servicePort,分别用于指定流量转发的后端目标Service资源名称和端口。
rules对象由一系列的配置的Ingress资源的host规则组成,这些host规则用于将一个主机上的某个URL映射到相关后端Service对象,其定义格式如下:
1 | spec: |
实例1:绑定域名
创建一个名为nginx-1.7.9的Deployment,一个名为nginx-svc179的SVC,再创建一个ingress,可以通过域名 179.fdm.com 来访问这个Deployment,yaml全文如下:
1 | apiVersion: apps/v1 |
创建完成之后,查看状态:
1 | [root@master ingress-nginx]# kubectl get ingresses,svc,deployment |
做好强制解析,就可以使用 http://179.fdm.com:31863/ 了。这里为什么是端口31863呢?这是 ingress-nginx 所使用的端口。
1 | [root@master ingress-nginx]# curl -I http://179.fdm.com:31863 --resolve 179.fdm.com:31863:192.168.1.60 |
我们可以进入 ingress-nginx 看一下规则。
1 | [root@master ingress-nginx]# kubectl exec -n ingress-nginx -it nginx-ingress-controller-5556bd798f-dngnv -- /bin/bash |
注意,现在的nginx ingress版本是看不到upstream_balancer了,由通过lua动态加载了。
实例2:TLS加密
生成TLS证书
1 | [root@master ingress-nginx]# openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=nginxsvc/O=nginxsvc" |
还是使用之前创建好的deployment,再加一个SSL证书,Yaml如下:
1 | apiVersion: extensions/v1beta1 |
这样就可以通过 https//auth.fdm.com:30442 来访问了。