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


  • 无标签
写评论...