-
由
虚拟的现实创建于9月 06, 2024 需要 3 分钟阅读时间
Ingress Controller 是一个统称,并不只有一个,例如:
- Ingress NGINX: Kubernetes 官方维护的方案,基于 nginx 实现。
- Nginx Ingress: nginx 官方实现的。
- F5 BIG-IP Controller: F5 所开发的 Controller,它能够让管理员通过 CLI 或 API 让 Kubernetes 与 OpenShift 管理 F5 BIG-IP 设备。
- Ingress Kong: 著名的开源 API Gateway 方案所维护的 Kubernetes Ingress Controller。
- Traefik>: 是一套开源的 Golang 实现的 HTTP 反向代理与负载均衡器,而它也支持 Ingress。
- haproxy-ingress: 一套以 HAProxy 为底的 Ingress Controller。
- Cilium Gateway: 基于 Cilium 网关和 eBPF 技术构建的高级 Ingress 控制器。
- Envoy Gateway: 基于 Envoy 代理的入口控制器,用于路由和管理外部流量.
- Higress: Higress 是基于阿里内部多年的 Envoy Gateway 实践沉淀,以开源 Istio 与 Envoy 为核心构建的云原生 API 网关。
怎么暴漏多个 http 服务
现实生活中,大部分流量都是 http ,而通常情况下 K8S 的 Overlay 网络是 K8S 节点才能访问的,例如 PodIP 是 10.224.1.198,非 K8S worker 访问这个 IP 路由到自己网关,然后网关路由出去,也就是无法访问到 PodIP,这个和 vmware workstation 的 nat 网络虚拟机一样,你局域网内其他机器无法访问你 vmware 上的虚机。
假设有两个 Service 需要映射出去:
- account-user 对外成 /userInfo web 路由
- book-server 对外成 /bookList web 路由
反向代理
你第一时间想到的是 node 上跑个 nginx 反向代理 Service

nginx 写配置文件, resolver 写 coredns SVC_IP:
http {
resolver 10.96.0.10 valid=5s;
server {
listen 80;
location /userInfo {
proxy_pass http://account-user.prod.svc.cluster.local;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location /bookList {
proxy_pass http://book-server.prod.svc.cluster.local;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
}
优化
后面你意识到这样每次都是走 Service,能否 proxy_pass 写的是 service 名字,lua 去请求 https://kubernetes.default.svc.cluster.local 把 PodIP 维护在 upstream 列表里。
annotation
再后面,你意识到写文件非常繁琐,不知道哪些 Service 被代理了,你意识到 k8s 有 annotation 这个东西,能够在这里写注释自己 nginx + lua 读取,你可能写到 svc 的 annotation 上。也就是下面类似:
apiVersion: v1 kind: Service metadata: annotations: conf:| more_set_headers "Request-Id: $req_id"; ... ...
nginx + lua 连接 kube-apiserver,获取所有 Service 的 annotation 生成配置文件。
CRD 和 Ingress Controller 工作原理
随着你对 k8s 的 api 越来越熟悉,意识到写 svc 上似乎太繁琐,这样不方便 kubectl 增删改查,可不可以创建自己的资源对象,类似 Kind: Pod 那样有 kind: Proxy,实际上这就是 Kind: ingress 由来。把反向代理配置文件抽象成 K8S 的 yaml 配置:
# 这里是举例,不保证时效性 apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: my-ingress annotations: nginx.ingress.kubernetes.io/proxy-body-size: "0" nginx.ingress.kubernetes.io/proxy-read-timeout: "600" nginx.ingress.kubernetes.io/proxy-send-timeout: "600" spec: ingressClassName: nginx rules: - host: api.domain.com http: paths: - backend: serviceName: api servicePort: 80 - host: test.domain.com http: paths: - path: /web/* backend: serviceName: web servicePort: 8080 - host: backoffice.domain.com http: paths: - backend: serviceName: backoffice servicePort: 8080
例如访问到 Ingress Controller 的 http 流量:
- curl -H 'host: api.domain.com' http://<ingress-controller-SLB_IP> 会反向代理到 api 这个 service 后的 Pod 的 80 端口
- curl -H 'host: test.domain.com' http://<ingress-controller-SLB_IP>/web/v1 会反向代理到 web 这个 service 后的 Pod 的 8080 端口
- curl -H 'host: backoffice.domain.com' http://<ingress-controller-SLB_IP> 会反向代理到 backoffice 这个 service 后的 Pod 的 8080 端口
也就是和 nginx 反向代理类似,如果你进入到 ingress nginx 内,会发现上面的 Ingress 最终还是在容器内生成 nginx 配置文件:
$ kubectl -n ingress-nginx exec nginx-ingress-controller-6cdcfd8ff9-t5sxl -- cat /etc/nginx/nginx.conf
...
## start server nginx.testdomain.com
server {
server_name nginx.testdomain.com ;
listen 80;
set $proxy_upstream_name "-";
location / {
set $namespace "default";
set $ingress_name "nginx-ingress";
set $service_name "nginx";
set $service_port "80";
set $location_path "/";
........
## end server nginx.testdomain.com
...
要注意的一点是虽然写的是反向代理 service 名字,但是实际是直接反向代理到 service 的 endpoint 上的。
高可用
网络方面
- Ingress Controller 使用 NodePort 对接外部 SLB
- hostNetwork 下对接外部 SLB,例如需要代理 TCP 流量
- hostPort 对接外部 SLB
+-------+
| |
-+---------->+ |
/ +-------+ node1
/
/
/ +-------+
+--------+ / | |
| client +-----------> SLB -------------->+ |
+--------+ \ +-------+ node2
\
\
\ +-------+
------------->+ |
| |
+-------+ node3
部署方式:
- daemonSet + nodeSeletor
- deploy设置replicas数量 + nodeSeletor + pod互斥
多个 Ingres Controller(注意 ingress yaml 的 ingressClassName)
+---------------------------+
| |
-+---------->+ hostNetwork的ingress nginx|
/ +---------------------------+ node1
/
/
/ +---------------------------+
+--------+ / | |
| client +-----------> F5 -------------->+ hostNetwork的ingress nginx|
+--------+ \ +---------------------------+ node1
\
\
\ +---------------------------+
------------->+hostNetwork的ingress nginx |
| |
+---------------------------+ node3
+---------------------------+
| |
-+---------->+ hostNetwork的Higress |
/ +---------------------------+ node4
/
/
/ +---------------------------+
+--------+ / | |
| client +-----------> SLB(or VIP) -------->+ hostNetwork的Higress |
+--------+ \ +---------------------------+ node5
\
\
\ +---------------------------+
------------->+ hostNetwork的Higress |
| |
+---------------------------+ node6
- 无标签
0 评论