乐趣区

关于云计算:Kubernetes-中数据包的生命周期-第-4-部分

本文翻译自:[Life of a Packet in Kubernetes — Part 4 [1]](https://dramasamy.medium.com/…)
作者:Dinesh Kumar Ramasamy
本文在原文的根底上做了适当的批改,如有疑问请查阅原文。

本文是 Kubernetes 中数据包的生命周期系列文章的第 4 局部,咱们将会介绍 Kubernetes 中的 Ingress 资源对象和 Ingress Controller。Ingress Controller 是一个控制器,它监督 Kubernetes API Server 对 Ingress 资源的变更并相应地更新负载均衡器的配置。

## 1 Nginx Controller 和 LoadBalancer/Proxy

Ingress Controller 通常是以 Pod 的模式运行在 Kubernetes 集群中,它依据 Ingress 资源配置负载均衡器。负载均衡器能够是运行在集群中的软件负载均衡器,也能够是在内部运行的硬件或云负载均衡器。不同的负载均衡器须要应用不同的 Ingress Controller。

Ingress 实质上是 Kubernetes 对反向代理的一个高级形象,形容了一系列流量治理的办法,特地是针对 HTTP(S)。通过 Ingress,咱们能够定义路由转发的规定,而无需创立一堆负载均衡器或在每个节点上裸露服务。能够为服务提供内部可拜访的 URLs,流量的负载平衡,SSL/TLS 终结,并提供基于名称的虚拟主机和基于内容的路由。

## 2 配置选项
在 Kubernetes 中应用 Ingress Class 标记 Ingress 资源对象所属的 Ingress Controller。这容许多个 Ingress Controller 在同一个 Kubernetes 集群中共存,每个 Ingress Controller 只会解决属于它的配置。

基于前缀的路由

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
 name: prefix-based
 annotations:
   kubernetes.io/ingress.class: "nginx-ingress-inst-1" # 标记所属的 Ingress Controller
spec:
 rules:
 - http:
     paths:
     - path: /video
       pathType: Prefix
       backend:
         service:
           name: video
           port:
             number: 80
     - path: /store
       pathType: Prefix
       backend:
         service:
           name: store
           port:
             number: 80

在 Kubernetes 1.18 版本引入 IngressClass 资源和 ingressClassName 字段之前,Ingress Class 是通过 Ingress 中的一个 kubernetes.io/ingress.class 注解来指定的。这个注解从未被正式定义过,然而失去了 Ingress Controller 的广泛支持。

Ingress 中新的 ingressClassName 字段是该注解的替代品,但并非齐全等价。该注解通常用于援用实现该 Ingress 的控制器的名称,而这个新的字段则是对一个蕴含额定 Ingress 配置的 IngressClass 资源的援用,包含 Ingress Controller 的名称。

# IngressClass 资源
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
labels:
  app.kubernetes.io/component: controller
name: nginx-ingress-inst-1 # IngressClass 名字
annotations:
  ingressclass.kubernetes.io/is-default-class: "true" # 设置为默认的 IngressClass,当 Ingress 中没有设置 ingressClassName 字段或者 kubernetes.io/ingress.class 注解时将会应用这个 IngressClass
spec:
controller: k8s.io/ingress-nginx
---
# 在 Ingress 中指定 ingressClassName
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: prefix-based
spec:
ingressClassName: "nginx-ingress-inst-1" # 标记所属的 Ingress,援用 IngressClass 资源
rules:
- http:
    paths:
    - path: /video
      pathType: Prefix
      backend:
        service:
          name: video
          port:
            number: 80
    - path: /store
      pathType: Prefix
      backend:
        service:
          name: store
          port:
            number: 80

基于主机的路由

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
 name: host-based
 annotations:
   kubernetes.io/ingress.class: "nginx-ingress-inst-1"
spec:
 rules:
 - host: "video.example.com" # 域名
   http:
     paths:
     - pathType: Prefix
       path: "/"
       backend:
         service:
           name: video
           port:
             number: 80
 - host: "store.example.com"
   http:
     paths:
     - pathType: Prefix
       path: "/"
       backend:
         service:
           name: store
           port:
             number: 80

基于主机 + 前缀的路由

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
 name: host-prefix-based
 annotations:
   kubernetes.io/ingress.class: "nginx-ingress-inst-1"
spec:
 rules:
 - host: foo.com
   http:
     paths:
     - backend:
         serviceName: foovideo
         servicePort: 80
       path: /video
     - backend:
         serviceName: foostore
         servicePort: 80
       path: /store
 - host: bar.com
   http:
     paths:
     - backend:
         serviceName: barvideo
         servicePort: 80
       path: /video
     - backend:
         serviceName: barstore
         servicePort: 80
       path: /store

Ingres 是 Kubernetes 的内置对象,为了让 Ingress 资源工作,集群中必须有一个正在运行的 Ingress Controller。Ingress Controller 须要实现 Ingress API 的相干接口。社区中有很多 Ingress Controller 的实现,本文将会介绍 NginxContour

前文提到,Kubernetes Ingress 是一个 API 对象,它形容了如何对外公布部署在 Kubernetes 集群中的服务。因而,要使 Ingress Controller 可能工作,你须要实现 Ingress API 来读取和解决 Ingress 资源的信息。

Ingress API 对象只是元数据信息,真正的工作是由 Ingress Controller 来实现的。有许多 [Ingress Controller [2]](https://kubernetes.io/docs/co…) 可供使用,重要是依据具体场景抉择适合的 Ingress Controller。

也能够在同一个集群中部署多个 Ingress Controller,并为每个 Ingress 设置所属的 Ingress Controller。通常,咱们会针对同一集群中的不同场景组合应用这些控制器。例如,咱们可能有一个控制器用于解决进入集群的内部流量,其中包含与 SSL 证书的绑定,而另一个没有 SSL 绑定的控制器用于解决集群内的流量。

## 3 部署选项
### 3.1 Contour + Envoy

Contour Ingress Controller 蕴含以下两局部:

  • Envoy(数据立体),提供高性能反向代理。
  • Contour(管制立体),读取 Ingress 资源信息并对 Envoy 进行配置。

Contour 和 Envoy 容器是离开部署的,Contour 以 Deployment 的形式运行,Envoy 以 Daemonset 的形式运行,当然其余形式部署也是能够的。Contour 是调用 Kubernetes API 的客户端。Contour 监督 Ingress,HTTPProxy, Secret, Service 和 Endpoint 对象,并转换为 Envoy 的相干配置:例如,Service 对应 CDS,Ingress 对应 RDS,Endpoint 对应 EDS 等等。

下图显示了启用主机网络(hostNetwork: true)的 EnvoyProxy (0.0.0.0:80)。

3.2 Nginx

Nginx Ingress Controller 的指标是组装一个配置文件(nginx.conf)。当配置文件产生任何更改时须要从新加载 Nginx。须要留神的是,如果只有 upstream(应用程序的 Endpoint)变动的话,此时无需从新加载 Nginx。咱们能够应用 [lua-nginx-module [3]](https://github.com/openresty/…) 来实现这一点。

每当 Endpoint 更改时,控制器都会从 Service 中获取 Endpoint 并生成相应的后端对象。而后将这些对象发送到在 Nginx 中运行的 Lua 处理程序。Lua 代码将这些后端对象存储在共享内存区域中。对于在 [balancer_by_lua [4]](https://github.com/openresty/…) 上下文中的申请,Lua 代码会检测到有哪些上游 Enpdoint,并利用配置的负载平衡算法来抉择 Endpoint。其余的工作由 Nginx 负责。这样咱们能够防止在 Endpoint 更改时从新加载 Nginx。在频繁部署应用程序的绝对较大的集群中,此性能能够节俭 Nginx 大量的从新加载,从而防止影响响应提早、负载平衡品质(每次从新加载后 Nginx 都会重置负载平衡状态)等问题。

3.3 Nginx + Keepalived — 高可用部署

[keepalived [5]](https://keepalived.readthedoc…) 守护过程可用于监控服务或零碎,并在呈现问题时主动实现故障转移。咱们配置一个能够在工作节点之间漂移的[浮动 IP [6]](https://www.digitalocean.com/…)。当工作节点宕机时,浮动 IP 会主动漂移到另一个工作节点上,新的工作节点接管拜访流量。

3.4 MetalLB — 带有 LoadBalancer 服务的 Nginx(实用于含有大量公网地址的公有集群)

MetalLB 是裸机 Kubernetes 集群中负载均衡器的实现。简略来说,它容许你在非云提供商提供的 Kubernetes 集群中创立类型为 LoadBalancer 的 Kubernetes Service。在云提供商提供的 Kubernetes 集群中,由云提供商负责调配 LoadBalancer Service 的 IP 地址,并在云提供商的负载平衡设施上公布服务(例如 AWS 的 ELB,阿里云的 SLB 等)。在裸机 Kubernetes 集群中,MetalLB 负责调配 IP 地址。一旦 MetalLB 为服务调配了内部 IP 地址,它须要让集群内部的网络晓得这个 IP“存在“于集群中。MetalLB 应用规范的路由协定实现这一点:ARP,NDP 或者 BGP。

在 Layer 2 模式下,集群中的一台机器取得 IP 地址的所有权并应用规范地址发现协定(IPv4 应用 [ARP [7]](https://en.wikipedia.org/wiki…),IPv6 应用 [NDP [8]](https://en.wikipedia.org/wiki…))。在 Layer 2 模式下,所有 LoadBalancer 类型的 Service 的 IP 同一时间都是绑定在同一台节点的网卡上,存在单点网络瓶颈。

在 BGP 模式下,集群中的所有机器都与内部路由器建设 [BGP [9]](https://en.wikipedia.org/wiki…) 街坊关系,并通知路由器如何将流量转发到 Service IP。基于 BGP 的策略机制,应用 BGP 能够实现跨多个节点真正的负载平衡,以及细粒度的流量管制。

MetalLB 运行时有两种工作负载:

  • Controler:以 Deployment 形式部署,是集群范畴的 MetalLB 控制器,用于监听 Service 的变更,调配 / 回收 IP 地址。
  • Speaker:以 DaemonSet 形式部署,对外播送 Service 的 IP 地址。

4 参考资料

  • [1] 原文链接: https://dramasamy.medium.com/…
  • [2] Ingress Controller: https://kubernetes.io/docs/co…
  • [3] lua-nginx-module: https://github.com/openresty/…
  • [4] balancer_by_lua: https://github.com/openresty/…
  • [5] keepalived: https://keepalived.readthedoc…
  • [6] floating IP address: https://www.digitalocean.com/…
  • [7] ARP: https://en.wikipedia.org/wiki…
  • [8] NDP: https://en.wikipedia.org/wiki…

    • [9] BGP: https://en.wikipedia.org/wiki…

5 欢送关注

退出移动版