--- reviewers: - bprashanth title: Ingress content_template: templates/concept weight: 40 --- {{% capture overview %}} {{< glossary_definition term_id="ingress" length="all" >}} {{% /capture %}} {{% capture body %}} ## 专用术语 在本文档中,您将看到一些有时在其他地方可互换使用的术语,这些术语可能会引起混淆。 本节试图澄清它们 * 节点:Kubernetes 集群中的单个虚拟或物理机器。 * 集群:互联网防火墙保护下的一组节点,它们是 Kubernetes 管理的主要计算资源。 * 边缘路由器:为集群强制执行防火墙策略的路由器。这可以是由云提供商管理的网关或物理硬件。 * 集群网络:一组逻辑或物理的链接,根据 [Kubernetes 网络模型](/docs/concepts/cluster-administration/networking/) 在集群内实现通信。集群网络的例子包括 覆盖网络,例如 [flannel](https://github.com/coreos/flannel#flannel);或者SDN,例如 [OVS](https://www.openvswitch.org/)。 * 服务:Kubernetes [服务](/docs/concepts/services-networking/service/) 使用标签选择器标识一组 Pod。除非另有说明,否则假定服务只具有在集群网络中可路由的虚拟 IP。 ## Ingress 是什么? 通常,服务 和 Pod 具有仅能在集群网络内路由的 IP 地址。在边缘路由器结束的所有流量都被丢弃或转发到别处。从概念上讲,这可能看起来像: ```none internet | ------------ [ Services ] ``` Ingress 是允许连接到集群 Service 的规则集合。 ``` 互联网 | [ Ingress ] --|-----|-- [ Services ] ``` 它可以被配置为提供外部可访问的URL、负载均衡流量、终止SSL、提供基于名称的虚拟托管等等。 用户通过向 API 服务器 POST Ingress 资源来请求 Ingress。 [Ingress 控制器](#ingress-controllers) 负责实现 Ingress,它通常使用负载均衡器,不过它也可以配置边缘路由器或其他前端,从而帮助用户以 HA 方式处理流量。 ## 环境准备 在开始使用 Ingress 资源之前,有一些事情您应该了解。 Ingress 是 beta 资源,在 1.1 之前的任何 Kubernetes 版本中都不可用。 您需要一个 Ingress 控制器来满足 Ingress,否则简单地创建资源将不起作用。 GCE/Google Kubernetes Engine 是在主节点上部署 Ingress 控制器。 您可以在 Pod 中部署任意数量的自定义 Ingress 控制器。 您必须使用适当的类来注释每个 Ingress,如[这里](https://git.k8s.io/ingress-nginx/docs/user-guide/multiple-ingress.md#multiple-ingress-controllers) 和 [这里](https://git.k8s.io/ingress-gce/examples/PREREQUISITES.md#ingress-class) 所示。 一定要检查一下这个控制器的 [beta 限制](https://github.com/kubernetes/ingress-gce/blob/master/BETA_LIMITATIONS.md#glbc-beta-limitations)。 在 GCE/Google Kubernetes Engine 之外的环境中,需要将[控制器部署](https://git.k8s.io/ingress-nginx/README.md) 为 Pod。 ## Ingress 资源 最小的 Ingress 可能看起来像这样: ```yaml apiVersion: extensions/v1beta1 kind: Ingress metadata: name: test-ingress annotations: nginx.ingress.kubernetes.io/rewrite-target: / spec: rules: - http: paths: - path: /testpath backend: serviceName: test servicePort: 80 ``` *如果尚未配置 [Ingress 控制器](#ingress-controllers),则向 API 服务器 POST 操作将没有任何效果。* __1-6 行__: 与其他 Kubernetes 对象配置一样,Ingress 需要 `apiVersion`、`kind`、和 `metadata` 字段。 有关使用配置文件的一般信息,请参见 [部署应用](/docs/tasks/run-application/run-stateless-application-deployment/)、 [配置容器](/docs/tasks/configure-pod-container/configure-pod-configmap/)、 [管理资源](/docs/concepts/cluster-administration/manage-deployment/) 和 [ingress 配置重写](https://github.com/kubernetes/ingress-nginx/blob/master/docs/examples/rewrite/README.md)。 __7-9 行__: Ingress [spec](https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status) 具有配置负载均衡器或代理服务器所需的所有信息。 最重要的是,它包含与所有传入请求相匹配的规则列表。目前,Ingress 资源仅支持 HTTP 规则。 __10-11 行__: 每个 HTTP 规则都包含以下信息:主机(例如:foo.bar.com,在本例中默认为 * ),路径列表(例如:/testpath),每个路径都有一个关联的后端(test:80)。 在负载均衡器将流量路由到后端之前,主机和路径都必须与传入请求的规则匹配。 __12-14 行__: 如[services doc](/docs/concepts/services-net./service/)中所述,后端(endpoint)是 “Service:port” 的组合。 Ingress 流量通常被直接发送到与后端相匹配的端点。 __全局参数__: 为了简单起见,Ingress 示例没有全局参数,有关资源的完整定义请参见 [API引用](https://releases.k8s.io/{{< param "githubbranch" >}}/staging/src/k8s.io/api/extensions/v1beta1/types.go)。 您可以指定全局默认的后端,这样的话,当请求与 spec 中的路径不匹配时,就会被转发到 Ingress 控制器的默认后端。 ## Ingress 控制器 为了使 Ingress 资源正常工作,集群必须有 Ingress 控制器运行。 这不同于其他类型的控制器,它们通常作为 `kube-controller-manager` 二进制文件的一部分运行,并且通常作为集群创建的一部分自动启动。 请选择最适合您的集群的 Ingress 控制器,或者实现一个新的 Ingress 控制器。 * Kubernetes 当前支持并维护 [GCE](https://git.k8s.io/ingress-gce/README.md) 和 [nginx](https://git.k8s.io/ingress-nginx/README.md) 控制器。 * F5 Networks 为 [F5 BIG-IP Controller for Kubernetes](http://clouddocs.f5.com/products/connectors/k8s-bigip-ctlr/latest) 提供[支持和维护](https://support.f5.com/csp/article/K86859508)。 * [Kong](https://konghq.com/) 为 [Kong Ingress Controller for Kubernetes](https://konghq.com/blog/kubernetes-ingress-controller-for-kong/) 提供 [社区版](https://discuss.konghq.com/c/kubernetes) 或 [商业版](https://konghq.com/api-customer-success/) 支持和维护。 * [Traefik](https://github.com/containous/traefik) 是个全功能的 Ingress 控制器。 ([Let's Encrypt](https://letsencrypt.org), secrets, http2, websocket...), 它也伴随着 [Containous](https://containo.us/services) 的商业支持。 * [NGINX, Inc.](https://www.nginx.com/) 为 [NGINX Ingress Controller for Kubernetes](https://www.nginx.com/products/nginx/kubernetes-ingress-controller) 提供支持和维护。 * [HAProxy](http://www.haproxy.org/) 是 Ingress 控制器 [jcmoraisjr/haproxy-ingress](https://github.com/jcmoraisjr/haproxy-ingress) 的基础, 在这个博客中有提到它 [HAProxy Ingress Controller for Kubernetes](https://www.haproxy.com/blog/haproxy_ingress_controller_for_kubernetes/)。 * [Istio](https://istio.io/) 是 Ingress 控制器 [Control Ingress Traffic](https://istio.io/docs/tasks/traffic-management/ingress/) 的基础。 {{< note >}} **注意:** 请检查你的控制器的文档以找到其特定的支持策略。 {{< /note >}} ## 在您开始之前 下面的文档描述了通过Ingress资源公开的一组跨平台特性。 理想情况下,所有 Ingress 控制器都应该满足这个规范,但是我们还没有。 我们现在支持并维护 [GCE](https://git.k8s.io/ingress-gce/README.md) 和 [nginx](https://git.k8s.io/ingress-nginx/README.md) 控制器。 如果您使用 F5 BIG-IP 控制器,请参考 [使用 BIG-IP 控制器作为 Kubernetes Ingress 控制器](http://clouddocs.f5.com/containers/latest/kubernetes/kctlr-k8s-ingress-ctlr.html)。 {{< note >}} **注意:** 请您一定要查看您的控制器的特定文档,以便您能理解这些警告。 {{< /note >}} ## Ingress 的类型 ### 单服务 Ingress 现有的 Kubernetes 概念允许您暴露单个 Service (查看 [替代方案](#alternatives)),同样您也可以使用 Ingress 来实现,具体方法是指定一个没有规则的 *默认后端(default backend)*。 {{< codenew file="service/networking/ingress.yaml" >}} 如果您用 `kubectl create -f`创建它,你应该看到: ```shell kubectl get ingress test-ingress ``` ```shell NAME HOSTS ADDRESS PORTS AGE test-ingress * 107.178.254.228 80 59s ``` 其中 `107.178.254.228` 是 Ingress 控制器为该 Ingress 分配的 IP 该。 ### 简单分列 如前所述,Kubernetes 中 Pod 的 IP 仅在集群网络上可见,所以我们需要在集群网络的边缘接收下行流量并将其代理到正确的端点。 这个组件通常是一个高可用的负载均衡器。Ingress 允许您将负载均衡器的数量降至最低。例如,这样的设置: ```shell foo.bar.com -> 178.91.123.132 -> / foo s1:80 / bar s2:80 ``` 可能需要一个 Ingress 就像: ```yaml apiVersion: extensions/v1beta1 kind: Ingress metadata: name: test annotations: nginx.ingress.kubernetes.io/rewrite-target: / spec: rules: - host: foo.bar.com http: paths: - path: /foo backend: serviceName: s1 servicePort: 80 - path: /bar backend: serviceName: s2 servicePort: 80 ``` 当您使用 `kubectl create -f` 创建 Ingress 时: ```shell kubectl describe ingress test ``` ```shell Name: test Namespace: default Address: 178.91.123.132 Default backend: default-http-backend:80 (10.8.2.3:8080) Rules: Host Path Backends ---- ---- -------- foo.bar.com /foo s1:80 (10.8.0.90:80) /bar s2:80 (10.8.0.91:80) Annotations: nginx.ingress.kubernetes.io/rewrite-target: / Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal ADD 22s loadbalancer-controller default/test ``` Ingress 控制器将提供实现特定的负载均衡器来满足 Ingress,只要 Service (`s1`,`s2`) 存在。 当它这样做了,你会在地址栏看到负载平衡器的地址。 {{< note >}} **注意:** 如果需要,你需要创建一个默认的 HTTP 后端 [Service](/docs/concepts/services-networking/service/)。 {{< /note >}} ### 基于名称的虚拟托管 基于名称的虚拟主机为同一个 IP 地址使用多个主机名。 ```none foo.bar.com --| |-> foo.bar.com s1:80 | 178.91.123.132 | bar.foo.com --| |-> bar.foo.com s2:80 ``` 下面的 Ingress 让后台的负载均衡器基于 [Host header](https://tools.ietf.org/html/rfc7230#section-5.4) 路由请求。 ```yaml apiVersion: extensions/v1beta1 kind: Ingress metadata: name: test spec: rules: - host: foo.bar.com http: paths: - backend: serviceName: s1 servicePort: 80 - host: bar.foo.com http: paths: - backend: serviceName: s2 servicePort: 80 ``` __默认后端__: 一个没有规则的 Ingress,如前面部分所示,它将所有流量发送到单个默认后端。 通过指定一组规则*和*默认后端,您可以使用相同的技术来告诉负载均衡器在哪里找到网站的 404 页面。 如果 Ingress 中的主机与请求头中的主机不匹配,和/或没有路径与请求的 URL 匹配,则流量被路由到默认后端。 ### TLS 您可以通过指定包含TLS私钥和证书的 [secret](/docs/concepts/configuration/secret) 来加密 Ingress。 目前,Ingress 只支持单个 TLS 端口,443,并假定 TLS 终止。 如果 Ingress 中的 TLS 配置部分指定了不同的主机,那么它们将根据通过 SNI TLS 扩展指定的主机名(如果 Ingress 控制器支持 SNI)在同一端口上进行复用。 TLS Secret 必须包含名为 `tls.crt` 和 `tls.key` 的密钥,这些密钥包含用于 TLS 的证书和私钥,例如: ```yaml apiVersion: v1 data: tls.crt: base64 encoded cert tls.key: base64 encoded key kind: Secret metadata: name: testsecret namespace: default type: Opaque ``` 在 Ingress 中引用此 Secret 将会告诉 Ingress 控制器使用 TLS 保护从客户端到负载均衡器的通道: ```yaml apiVersion: extensions/v1beta1 kind: Ingress metadata: name: no-rules-map spec: tls: - secretName: testsecret backend: serviceName: s1 servicePort: 80 ``` 注意,各种 Ingress 控制器所支持的 TLS 功能之间存在间隙。请参阅有关文件 [nginx](https://git.k8s.io/ingress-nginx/README.md#https), [GCE](https://git.k8s.io/ingress-gce/README.md#frontend-https), 或任何其他平台特定的 Ingress 控制器,以了解 TLS 如何在您的环境中工作。 ### 负载均衡 Ingress控制器使用一些适用于所有 Ingress 的负载均衡策略设置进行自举,例如负载平衡算法、后端权重方案等。 更高级的负载平衡概念(例如,持久会话、动态权重)尚未通过Ingress公开。 您仍然可以通过 [Service 负载均衡器](https://github.com/kubernetes/ingress-nginx) 获得这些特性。 随着时间的推移,我们计划将跨平台应用的负载平衡模式提取到 Ingress 资源中。 值得注意的是,即使健康检查不是通过 Ingress 直接暴露的,但是在 Kubernetes 中存在并行概念,比如 [就绪检查](/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/),它允许您实现相同的最终结果。 请检查控制器说明文档,以了解他们是怎样实现健康检查的 ( [nginx](https://git.k8s.io/ingress-nginx/README.md), [GCE](https://git.k8s.io/ingress-gce/README.md#health-checks))。 ## 更新 Ingress 假设您想向现有的 Ingress 中添加新主机,可以通过编辑资源来更新它: ```shell kubectl describe ingress test ``` ```shell Name: test Namespace: default Address: 178.91.123.132 Default backend: default-http-backend:80 (10.8.2.3:8080) Rules: Host Path Backends ---- ---- -------- foo.bar.com /foo s1:80 (10.8.0.90:80) Annotations: nginx.ingress.kubernetes.io/rewrite-target: / Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal ADD 35s loadbalancer-controller default/test ``` ```shell kubectl edit ingress test ``` 这应该弹出一个编辑器与现有的 yaml,修改它来增加新的主机: ```yaml spec: rules: - host: foo.bar.com http: paths: - backend: serviceName: s1 servicePort: 80 path: /foo - host: bar.baz.com http: paths: - backend: serviceName: s2 servicePort: 80 path: /foo .. ``` 保存 yaml 将更新 API 服务器中的资源,这应该会告诉 Ingress 控制器来重新配置负载均衡器。 ```shell kubectl describe ingress test ``` ```shell Name: test Namespace: default Address: 178.91.123.132 Default backend: default-http-backend:80 (10.8.2.3:8080) Rules: Host Path Backends ---- ---- -------- foo.bar.com /foo s1:80 (10.8.0.90:80) bar.baz.com /foo s2:80 (10.8.0.91:80) Annotations: nginx.ingress.kubernetes.io/rewrite-target: / Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal ADD 45s loadbalancer-controller default/test ``` 您可以通过 `kubectl replace -f` 命令调用修改后的 Ingress yaml 文件来获得同样的结果。 ## 跨可用区失败 用于跨故障域传播流量的技术在云提供商之间是不同的。详情请查阅相关 Ingress 控制器的文档。 有关在联邦集群中部署 Ingress 的详细信息,请参阅联邦 [文档](/docs/concepts/cluster-administration/federation/)。 ## 未来的工作 *各种 HTTPS/TLS 模式的支持(例如:SNI、重加密) *通过声明请求IP或主机名 *合并 L4 和 L7 Ingress *更多 Ingress 控制器 请跟踪 [L7 and Ingress proposal](https://github.com/kubernetes/kubernetes/pull/12827)以了解关于资源演化的更多细节,以及 [Ingress repository](https://github.com/kubernetes/ingress/tree/master) 以了解关于各种 Ingress 控制器演进的更多细节。 ## 替代方案 不直接使用 Ingress 资源,也有多种方法暴露 Service: * 使用 [Service.Type=LoadBalancer](/docs/concepts/services-networking/service/#loadbalancer) * 使用 [Service.Type=NodePort](/docs/concepts/services-networking/service/#nodeport) * 使用 [端口代理](https://git.k8s.io/contrib/for-demos/proxy-to-service) {{% /capture %}} {{% capture whatsnext %}} {{% /capture %}}