参考文档:


Ingress 是 Kubernetes 的一种 API 对象,将集群内部的 Service 通过 HTTP/HTTPS 方式暴露到集群外部,并通过规则定义 HTTP/HTTPS 的路由。Ingress 具备如下特性:集群外部可访问的 URL、负载均衡、SSL Termination、按域名路由(name-based virtual hosting)。

Ingress Controller (通常需要负载均衡器配合)负责实现 Ingress API 对象所声明的能力。如下图所示:

  1. Ingress Controller 监听所有 worker 节点上的 80/443 端口
  2. Ingress Controller 将所有对域名为 a.kuboard.cn 的 HTTP/HTTPS 请求路由到 Service B 的 9080 端口
  3. Service B 将请求进一步转发到其标签所选择的 Pod 容器组(通过 targetPort 指定容器组上的端口号)

该图中,请求被转发的过程为:

  1. 假设您将 a.kuboard.cn 的 DNS 解析到了集群中的一个 worker 节点的 IP 地址 192.168.2.69。(如果您的 worker 节点有外网地址,请使用外网地址,这样您可以从外网访问您的服务)
  2. 从客户端机器执行命令 curl http://a.kuboard.cn/abc/,该请求您将被转发到 192.168.2.69 这个地址的 80 端口,并被 Ingress Controller 接收
  3. Ingress Controller 根据请求的域名 a.kuboard.cn 和路径 abc 匹配集群中所有的 Ingress 信息,并最终找到 Ingress B 中有这个配置,其对应的 Service 为 Service B 的 9080 端口
  4. Ingress Controller 通过 kube-proxy 将请求转发到 Service B 对应的任意一个 Pod 上 与 Service B 的 9080 端口对应的容器端口上。(从 Ingress Controller 到 Pod 的负载均衡由 kube-proxy + Service 实现)

image.png

Ingress Controller


如上所述,您必须在 Kubernetes 集群中安装了 Ingress Controller,您配置的 Ingress 才能生效。

划重点 Ingress 只是 Kubernetes 中的一种配置信息;Ingress Controller 才是监听 80/443 端口,并根据 Ingress 上配置的路由信息执行 HTTP 路由转发的组件。

Ingress Controller 有多种实现可供选择,请参考 Kubernetes 官方文档 Additional controllers(opens new window),比较常用的有 Traefic(opens new window)Nginx Ingress Controller for Kubernetes(opens new window)等。

如果您参考 https://kuboard.cn 网站上提供的文档安装了 Kubernetes,您应该已经完成了 Nginx Ingress Controller for Kubernetes(opens new window)在您 Kubernetes 集群中的安装。该 Ingress Controller 以 DaemonSet 的类型部署到 Kubernetes,且监听了 hostPort 80/443,YAML 片段如下所示:

如果您打算使用其他 Ingress Controller,您可以 卸载 Nginx Ingress Controller;如果您尚未安装任何 Ingress Controller,请参考 安装 Nginx Ingress Controller,以便可以完成本教程的后续内容。

  1. apiVersion: extensions/v1beta1
  2. kind: DaemonSet
  3. metadata:
  4. name: nginx-ingress
  5. namespace: nginx-ingress
  6. # ...
  7. spec:
  8. selector:
  9. matchLabels:
  10. app: nginx-ingress
  11. template:
  12. metadata:
  13. labels:
  14. app: nginx-ingress
  15. spec:
  16. serviceAccountName: nginx-ingress
  17. containers:
  18. - image: nginx/nginx-ingress:1.5.3
  19. name: nginx-ingress
  20. ports:
  21. - name: http
  22. containerPort: 80
  23. hostPort: 80
  24. - name: https
  25. containerPort: 443
  26. hostPort: 443

TIP

  • Ingress Controller 并非只能监听 80/443 端口,您可以根据自己网络拓扑的需要,选择合适的端口
  • 根据您安装 Ingress Controller 的方式不同,您的 Ingress Controller 并不一定监听了所有 worker 节点的 80/443 端口(本教程不涉及此主题)
  • 您也可以在 Kubernetes 集群中安装多种 Ingress Controller,请参考 Using multiple Ingress controllers(opens new window)

融入到网络拓扑中


如前所述,Kubernetes Ingress 只能监听到节点的 80/443 端口,且 Ingress 可以完成 L7 路由的功能。由于 Kubernetes Ingress 配置更便捷,推荐使用 Kubernetes Ingress 替代常规的互联网应用架构中的 Nginx 反向代理。那么,如何使部署在内网的 Kubernetes 集群上的 Ingress Controller 的 80/443 端口可以在外网访问到呢?

本教程推荐如下两种做法,结合您自己对安全性、可靠性等因素的考量,您可以演化出适合自己的拓扑结构。

暴露单worker节点

如下图所示,暴露单个 worker 节点的步骤如下:

  • 为您 Kubernetes 集群中的某一个 worker 节点配置外网 IP 地址 Z.Z.Z.Z
  • 将您在 Ingress 中使用到的域名(假设是a.demo.kuboard.cn)解析到该外网 IP 地址 Z.Z.Z.Z
  • 设置合理的安全组规则(开放该外网 IP 地址 80/443 端口的入方向访问)

文档 安装 Kubernetes 单Master节点 中使用的就是这种拓扑结构。这种方式下,Ingress Controller 存在单点故障的可能性。

image.png

使用外部负载均衡器

如下图所示,使用外部负载均衡器的步骤如下:

  • 创建一个集群外部的负载均衡器,该负载均衡器拥有一个外网 IP 地址 Z.Z.Z.Z,并监听 80/443 端口的 TCP 协议
  • 将负载均衡器在 80/443 端口上监听到的 TCP 请求转发到 Kubernetes 集群中所有(或某些)worker 节点的 80/443 端口,可开启按源IP地址的会话保持
  • 将您在 Ingress 中使用到的域名(假设是a.demo.kuboard.cn)解析到该负载均衡器的外网 IP 地址 Z.Z.Z.Z

    文档 安装 Kubernetes 高可用 中使用的就是这种拓扑结构。

image.png

实战:通过 Ingress 使您的应用程序在互联网可用


前提

  • 假设您已经完成了 公布应用程序 中的实战部分
  • 假设您已经将 Ingress 融入到您的网络拓扑中,并且将 *.demo.kuboard.cn (请使用您自己的域名)解析到对应的外网 IP 地址

使用kubectl

创建文件 nginx-deployment.yaml

  1. vim nginx-deployment.yaml

文件内容如下

  1. apiVersion: apps/v1
  2. kind: Deployment
  3. metadata:
  4. name: nginx-deployment
  5. labels:
  6. app: nginx
  7. spec:
  8. replicas: 1
  9. selector:
  10. matchLabels:
  11. app: nginx
  12. template:
  13. metadata:
  14. labels:
  15. app: nginx
  16. spec:
  17. containers:
  18. - name: nginx
  19. image: nginx:1.7.9

创建文件 nginx-service.yaml

  1. vim nginx-service.yaml

文件内容如下

  1. apiVersion: v1
  2. kind: Service
  3. metadata:
  4. name: nginx-service
  5. labels:
  6. app: nginx
  7. spec:
  8. selector:
  9. app: nginx
  10. ports:
  11. - name: nginx-port
  12. protocol: TCP
  13. port: 80
  14. nodePort: 32600
  15. targetPort: 80
  16. type: NodePort

创建文件 nginx-ingress.yaml

  1. vim nginx-ingress.yaml

文件内容如下

  1. apiVersion: networking.k8s.io/v1beta1
  2. kind: Ingress
  3. metadata:
  4. name: my-ingress-for-nginx # Ingress 的名字,仅用于标识
  5. spec:
  6. rules: # Ingress 中定义 L7 路由规则
  7. - host: a.demo.kuboard.cn # 根据 virtual hostname 进行路由(请使用您自己的域名)
  8. http:
  9. paths: # 按路径进行路由
  10. - path: /
  11. backend:
  12. serviceName: nginx-service # 指定后端的 Service 为之前创建的 nginx-service
  13. servicePort: 80

执行命令

  1. kubectl apply -f nginx-deployment.yaml
  2. kubectl apply -f nginx-service.yaml
  3. kubectl apply -f nginx-ingress.yaml

检查执行结果

  1. kubectl get ingress -o wide

可查看到名称为 my-ingress-for-nginx 的 Ingress。
从互联网访问

  1. # 请使用您自己的域名
  2. curl a.demo.kuboard.cn

使用Kuboard

  • 在 default 名称空间 点击左侧菜单栏中的 创建工作负载,如下图所示:image.png填写表单如下: | 字段名称 | 填写内容 | 备注 | | —- | —- | —- | | 服务类型 | Deployment | | | 服务分层 | 展现层 | | | 服务名称 | web-nginx | | | 服务描述 | nginx部署 | | | 副本数量 | 1 | 可以填写其他正整数 |

  • 切换到 容器信息 Tab 页,如下图所示:image.png填写表单如下: | 字段名称 | 填写内容 | 备注 | | —- | —- | —- | | 容器名称 | nginx | | | 镜像 | nginx:1.7.9 | | | 抓取策略 | Always | |

  • 切换到 服务/应用路由 Tab 页,如下图所示:image.png填写表单如下: | 字段名称 | 填写内容 | 备注 | | —- | —- | —- | | 服务 | NodePort(VPC内访问)
    协议: TCP,port: 80,nodePort: 32601,targetPort: 80 | 服务对应 Kubernetes Service对象,
    工作负载编辑器为其使用与 Deployment 相同的名字 web-nginx | | 应用路由 | 域名: a.demo.kuboard.cn
    映射URL: /
    服务端口:80 | 应用路由对应 Kubernetes Ingress对象,
    工作负载编辑器为其使用与 Deployment 相同的名字 web-nginx |

TIP Kuboard 工作负载编辑器假设 kubernetes 中三个主要对象 Deployment/Service/Ingress 名称相同,并放在同一个编辑器界面中处理。

  • 点击 保存
  • 点击 应用
  • 从互联网访问在浏览器打开 http://a.demo.kuboard.cn (请使用您自己的域名)