MK
摩柯社区 - 一个极简的技术知识社区
AI 面试

Kubernetes 的 Ingress 资源详解与配置示例

2021-09-204.1k 阅读

Kubernetes Ingress 概述

在 Kubernetes 集群中,服务(Service)是暴露应用的重要方式。然而,传统的 Kubernetes Service 类型,如 ClusterIP、NodePort 和 LoadBalancer,在处理外部流量的复杂路由需求时存在局限性。例如,ClusterIP 仅在集群内部可访问,NodePort 虽然能在节点的特定端口暴露服务,但端口分配和管理不够灵活,LoadBalancer 则依赖云提供商提供负载均衡器,成本较高且不适用于所有环境。

Ingress 资源正是为了解决这些问题而引入的。Ingress 本质上是一个规则集合,它定义了从集群外部到集群内部服务的 HTTP 和 HTTPS 路由。通过 Ingress,我们可以根据请求的域名、路径等信息,将外部流量精确地路由到不同的后端服务,实现更灵活的流量管理。

Ingress 控制器

仅仅定义 Ingress 资源是不够的,Kubernetes 集群需要一个 Ingress 控制器来实际执行这些路由规则。Ingress 控制器是一个运行在集群中的 Pod,它负责监听 Ingress 资源的变化,并根据这些规则配置负载均衡器,以实现流量的正确转发。

常见的 Ingress 控制器有:

  1. Nginx Ingress Controller:基于 Nginx 服务器,性能卓越,支持丰富的功能,如 SSL 终止、URL 重写等,是使用最广泛的 Ingress 控制器之一。
  2. Traefik Ingress Controller:以动态配置和自动发现服务而闻名,能够根据 Kubernetes 集群中服务的变化自动更新路由配置。
  3. HAProxy Ingress Controller:基于 HAProxy 负载均衡器,具有高效的 TCP 和 UDP 流量处理能力。

不同的 Ingress 控制器在功能和配置上略有差异,但基本原理相同,都是将 Ingress 资源的规则转换为实际的负载均衡配置。

Ingress 资源的基本结构

一个典型的 Ingress 资源清单文件包含以下几个关键部分:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: example-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - host: example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: example-service
            port:
              number: 80
  1. apiVersion:指定使用的 Kubernetes API 版本,目前 Ingress 资源常用的版本是 networking.k8s.io/v1
  2. kind:表明资源类型为 Ingress
  3. metadata:包含资源的名称和注解(annotations)。注解用于向 Ingress 控制器传递额外的配置信息,不同的 Ingress 控制器支持不同的注解。例如,上述示例中 nginx.ingress.kubernetes.io/rewrite-target 注解用于告诉 Nginx Ingress 控制器对请求路径进行重写。
  4. spec:定义 Ingress 的具体规则。rules 字段是一个数组,每个元素代表一条路由规则。在上述示例中,规则指定当请求的主机名为 example.com 且路径为 / 时,将流量转发到名为 example-service 的服务的 80 端口。pathType 字段指定路径匹配的类型,Prefix 表示前缀匹配,即只要请求路径以指定路径开头就会匹配。

基于域名的路由

基于域名的路由是 Ingress 最常见的应用场景之一。假设我们有两个不同的应用,分别为 app1app2,它们都运行在 Kubernetes 集群中,且各自有对应的服务 app1-serviceapp2-service。我们希望通过不同的域名来访问这两个应用,例如 app1.example.com 访问 app1app2.example.com 访问 app2

首先,创建两个服务的 Deployment 和 Service 资源:

# app1-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: app1-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: app1
  template:
    metadata:
      labels:
        app: app1
    spec:
      containers:
      - name: app1
        image: app1-image:latest
        ports:
        - containerPort: 80

# app1-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: app1-service
spec:
  selector:
    app: app1
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80

类似地,创建 app2 的 Deployment 和 Service 资源。

然后,定义 Ingress 资源进行基于域名的路由:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: app-ingress
spec:
  rules:
  - host: app1.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: app1-service
            port:
              number: 80
  - host: app2.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: app2-service
            port:
              number: 80

这样,当用户访问 app1.example.com 时,流量会被路由到 app1-service,进而到达 app1 的 Pod;访问 app2.example.com 时,流量会被路由到 app2-service

基于路径的路由

除了基于域名的路由,Ingress 还支持基于路径的路由。假设我们有一个应用,它包含不同的功能模块,如用户模块和订单模块,我们希望通过不同的路径来访问这些模块。例如,/users 路径访问用户模块,/orders 路径访问订单模块,且这两个模块分别由不同的服务 users-serviceorders-service 提供。

创建服务的 Deployment 和 Service 资源:

# users-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: users-deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      app: users
  template:
    metadata:
      labels:
        app: users
    spec:
      containers:
      - name: users
        image: users-image:latest
        ports:
        - containerPort: 80

# users-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: users-service
spec:
  selector:
    app: users
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80

同样,创建 orders 的相关资源。

定义 Ingress 资源实现基于路径的路由:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: path-ingress
spec:
  rules:
  - host: example.com
    http:
      paths:
      - path: /users
        pathType: Prefix
        backend:
          service:
            name: users-service
            port:
              number: 80
      - path: /orders
        pathType: Prefix
        backend:
          service:
            name: orders-service
            port:
              number: 80

当用户访问 example.com/users 时,流量会被路由到 users-service;访问 example.com/orders 时,流量会被路由到 orders-service

Ingress 中的 TLS 配置

在实际应用中,安全是至关重要的。Ingress 支持配置 TLS 来加密传输中的数据,确保通信的安全性。要配置 TLS,需要先准备好证书和私钥。可以通过 Let's Encrypt 等证书颁发机构获取免费的证书。

假设我们已经有了证书文件 tls.crt 和私钥文件 tls.key,我们可以将它们创建为 Kubernetes 的 Secret:

kubectl create secret tls example-tls --cert=tls.crt --key=tls.key

然后,在 Ingress 资源中引用这个 Secret 来启用 TLS:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: tls-ingress
spec:
  tls:
  - hosts:
    - example.com
    secretName: example-tls
  rules:
  - host: example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: example-service
            port:
              number: 80

在上述配置中,tls 字段指定了 TLS 相关的配置,hosts 字段指定证书适用的主机名,secretName 引用了之前创建的包含证书和私钥的 Secret。这样,当用户通过 HTTPS 访问 example.com 时,Ingress 控制器会使用配置的证书进行加密通信。

Ingress 注解的深入探讨

如前文所述,注解是 Ingress 资源中非常重要的部分,它允许我们向 Ingress 控制器传递额外的配置信息。不同的 Ingress 控制器支持不同的注解,下面以 Nginx Ingress 控制器为例,介绍一些常用的注解。

  1. rewrite-target:用于重写请求路径。例如:
annotations:
  nginx.ingress.kubernetes.io/rewrite-target: /new-path

这会将所有匹配的请求路径重写为 /new-path

  1. ssl-redirect:控制是否将 HTTP 请求重定向到 HTTPS。设置为 true 时,所有 HTTP 请求会被自动重定向到 HTTPS:
annotations:
  nginx.ingress.kubernetes.io/ssl-redirect: "true"
  1. proxy-read-timeout:设置后端服务的读取超时时间。例如:
annotations:
  nginx.ingress.kubernetes.io/proxy-read-timeout: "60"

将读取超时时间设置为 60 秒。

  1. auth-tls-secret:用于配置基于 TLS 的客户端认证。例如:
annotations:
  nginx.ingress.kubernetes.io/auth-tls-secret: "namespace/client-auth-secret"

引用名为 client-auth-secret 的 Secret 进行客户端认证。

合理使用这些注解可以根据具体需求对 Ingress 的行为进行精细调整。

高级 Ingress 配置示例

  1. URL 重写与重定向:假设我们有一个旧的应用路径 /old,现在希望将所有访问 /old 的请求重定向到新路径 /new,并且将 HTTP 重定向到 HTTPS。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: rewrite-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /new
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
  rules:
  - host: example.com
    http:
      paths:
      - path: /old
        pathType: Prefix
        backend:
          service:
            name: example-service
            port:
              number: 80
  1. 负载均衡算法调整:Nginx Ingress 控制器默认使用轮询(Round Robin)算法进行负载均衡,但某些情况下我们可能希望使用 IP 哈希算法,以确保同一个客户端的请求始终被转发到同一个后端 Pod。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ip-hash-ingress
  annotations:
    nginx.ingress.kubernetes.io/load-balance-upstream: "ip_hash"
spec:
  rules:
  - host: example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: example-service
            port:
              number: 80
  1. 基于权重的负载均衡:假设有两个版本的服务 v1-servicev2-service,我们希望将 70% 的流量导向 v1-service,30% 的流量导向 v2-service
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: weighted-ingress
spec:
  rules:
  - host: example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: v1-service
            port:
              number: 80
        weight: 70
      - path: /
        pathType: Prefix
        backend:
          service:
            name: v2-service
            port:
              number: 80
        weight: 30

通过这些高级配置,可以满足更复杂的流量管理和应用需求。

Ingress 资源的故障排查

在实际使用 Ingress 资源时,可能会遇到各种问题,以下是一些常见的故障排查方法:

  1. 检查 Ingress 资源状态:使用 kubectl describe ingress <ingress - name> 命令查看 Ingress 资源的详细信息,包括创建时间、更新时间、规则配置以及可能的错误信息。如果 Ingress 资源配置有误,这里会显示相关的错误提示,如注解格式错误、服务不存在等。
  2. 查看 Ingress 控制器日志:不同的 Ingress 控制器有不同的查看日志方式。例如,对于 Nginx Ingress 控制器,可以通过 kubectl logs -f <nginx - ingress - pod - name> 命令查看其日志。日志中会记录控制器处理 Ingress 资源的详细过程,包括规则加载、配置更新以及可能出现的错误,如无法连接后端服务、证书加载失败等。
  3. 检查 DNS 配置:如果是基于域名的路由,确保 DNS 配置正确。可以通过 nslookupdig 命令检查域名是否正确解析到集群的入口地址。如果 DNS 配置有误,用户将无法正确访问应用。
  4. 确认后端服务状态:使用 kubectl describe service <service - name>kubectl describe pod <pod - name> 命令检查后端服务和 Pod 的状态。确保服务能够正常运行,Pod 没有处于错误状态,端口配置正确,并且服务的选择器能够正确匹配到相应的 Pod。

通过以上步骤,可以逐步排查并解决 Ingress 资源在使用过程中出现的问题。

多 Ingress 控制器的使用场景

在某些复杂的 Kubernetes 集群环境中,可能需要使用多个 Ingress 控制器。例如,当集群中有不同类型的应用,对性能、功能有不同的要求时。假设集群中有一组对性能要求极高的微服务应用,适合使用 Nginx Ingress 控制器来提供高效的 HTTP 流量处理;同时,还有一组需要处理大量 TCP 和 UDP 流量的应用,HAProxy Ingress 控制器可能更合适。

要使用多个 Ingress 控制器,首先需要分别部署不同的 Ingress 控制器。以 Nginx 和 HAProxy 为例,分别按照官方文档部署相应的控制器。

然后,在定义 Ingress 资源时,可以通过 ingressClassName 字段指定使用哪个 Ingress 控制器。例如:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx - ingress
spec:
  ingressClassName: nginx
  rules:
  - host: microservices.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: microservice - service
            port:
              number: 80
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: haproxy - ingress
spec:
  ingressClassName: haproxy
  rules:
  - host: tcp - udp.example.com
    tcp:
      - backend:
          service:
            name: tcp - service
            port:
              number: 9000
    udp:
      - backend:
          service:
            name: udp - service
            port:
              number: 9001

通过这种方式,可以根据不同应用的需求,灵活选择合适的 Ingress 控制器来处理流量。

Ingress 与 Service Mesh 的结合

随着微服务架构的发展,Service Mesh(服务网格)逐渐成为处理复杂微服务通信的重要工具。Ingress 可以与 Service Mesh 很好地结合,提供更强大的流量管理和安全功能。

以 Istio 为例,Istio 是一个流行的 Service Mesh 框架。Istio 的 Ingress Gateway 可以作为 Kubernetes Ingress 的一种替代方案,提供更高级的流量管理功能,如流量镜像、熔断、重试等。

要将 Istio 与 Ingress 结合,首先需要在集群中安装 Istio。然后,创建 Istio Ingress Gateway:

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: example - gateway
spec:
  selector:
    istio: ingressgateway
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - example.com

接着,定义 Istio VirtualService 来配置路由规则,类似于 Ingress 资源的规则:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: example - virtual - service
spec:
  hosts:
  - example.com
  gateways:
  - example - gateway
  http:
  - match:
    - uri:
        prefix: /
    route:
    - destination:
        host: example - service
        port:
          number: 80

通过这种结合方式,不仅可以利用 Istio 的强大功能进行服务间的流量管理,还可以通过 Ingress 或 Istio Ingress Gateway 实现外部到集群内部服务的流量入口管理,为微服务架构提供更全面的流量控制和安全保障。

Ingress 在混合云与多云环境中的应用

在混合云(同时使用公有云和私有云)或多云(使用多个公有云)环境中,Ingress 资源同样起着重要的作用。它可以作为统一的流量入口,将来自不同云环境的外部流量路由到相应的后端服务。

例如,假设我们的应用部分部署在公有云 A,部分部署在私有云,且都在同一个 Kubernetes 集群中进行管理。我们可以在公有云 A 上配置 Ingress 控制器,如 Nginx Ingress 控制器,作为整个应用的外部流量入口。通过 Ingress 资源的规则配置,将不同路径或域名的请求路由到公有云 A 上的服务,以及通过网络连接到私有云中的服务。

在多云环境中,类似地,可以在每个云平台上部署 Ingress 控制器,并通过 Ingress 资源的统一配置,实现跨云的流量管理。这需要在不同云环境之间建立安全可靠的网络连接,以确保流量能够顺利在各个云环境中的服务之间传递。同时,还需要考虑不同云平台的网络特性和限制,合理配置 Ingress 资源和 Ingress 控制器,以达到最佳的性能和可用性。

通过在混合云与多云环境中应用 Ingress,企业可以更好地整合不同云环境中的资源,实现更灵活的应用部署和流量管理策略。

Ingress 资源的性能优化

为了确保 Ingress 在处理大量流量时的高性能,以下是一些性能优化的建议:

  1. 优化 Ingress 控制器配置:不同的 Ingress 控制器有各自的性能调优参数。例如,对于 Nginx Ingress 控制器,可以调整 worker_processesworker_connections 等参数来优化性能。增加 worker_processes 可以利用多核 CPU 的优势,提高处理能力;适当增大 worker_connections 可以允许更多的并发连接。
  2. 合理设置缓存:如果应用允许,可以在 Ingress 层设置缓存。例如,Nginx Ingress 控制器支持配置 HTTP 缓存,通过设置 proxy_cache_pathproxy_cache 等指令,可以缓存经常访问的静态资源,减少后端服务的负载,提高响应速度。
  3. 使用高效的负载均衡算法:如前文所述,根据应用的特点选择合适的负载均衡算法。对于会话亲和性要求较高的应用,IP 哈希算法可能更合适;对于普通的 Web 应用,轮询算法通常能满足需求,但在某些情况下,加权轮询算法可以根据后端服务的性能差异更合理地分配流量。
  4. 优化网络配置:确保集群内部和外部的网络配置合理。在集群内部,使用高速网络设备和合适的网络拓扑,减少网络延迟和带宽瓶颈;在外部,确保与用户的网络连接稳定,并且根据预估的流量规模申请足够的带宽。

通过以上性能优化措施,可以显著提升 Ingress 资源在高流量场景下的性能表现,为用户提供更流畅的访问体验。

Ingress 资源的安全性增强

除了配置 TLS 进行加密通信外,还可以从以下几个方面进一步增强 Ingress 资源的安全性:

  1. 访问控制:使用 Ingress 控制器支持的访问控制机制,如基于 IP 地址的访问控制。Nginx Ingress 控制器可以通过注解配置允许或拒绝特定 IP 地址的访问。例如:
annotations:
  nginx.ingress.kubernetes.io/whitelist-source-range: "192.168.1.0/24"

只允许 192.168.1.0/24 网段的 IP 地址访问。 2. Web 应用防火墙(WAF):许多 Ingress 控制器支持集成 WAF。例如,Nginx Ingress 控制器可以与 ModSecurity 等 WAF 集成,检测和阻止常见的 Web 攻击,如 SQL 注入、跨站脚本攻击(XSS)等。 3. 证书管理:定期更新 TLS 证书,确保证书的有效性和安全性。同时,使用证书透明度(Certificate Transparency)等技术,监控证书的颁发情况,防止恶意证书的颁发。 4. 最小权限原则:在配置 Ingress 资源和相关的 Secret 时,遵循最小权限原则。确保 Ingress 控制器只具有必要的权限来访问后端服务和证书等资源,减少潜在的安全风险。

通过这些安全性增强措施,可以有效提升 Ingress 资源在网络环境中的安全性,保护应用免受各种安全威胁。

Ingress 资源与自动化运维

在现代的自动化运维体系中,Ingress 资源也可以很好地融入其中。通过与自动化工具如 Ansible、Terraform 等结合,可以实现 Ingress 资源的自动化创建、更新和删除。

以 Ansible 为例,我们可以编写 Ansible Playbook 来管理 Ingress 资源。假设我们有一个名为 ingress.yml 的 Playbook:

- name: Create Ingress Resource
  hosts: k8s - master
  tasks:
  - name: Create Ingress
    k8s:
      state: present
      api_version: networking.k8s.io/v1
      kind: Ingress
      name: example - ingress
      spec:
        rules:
        - host: example.com
          http:
            paths:
            - path: /
              pathType: Prefix
              backend:
                service:
                  name: example - service
                  port:
                    number: 80

通过运行 ansible - playbook ingress.yml 命令,就可以自动在 Kubernetes 集群中创建 Ingress 资源。当应用需求发生变化时,只需要修改 Playbook 中的配置,再次运行命令即可更新 Ingress 资源。

类似地,Terraform 也可以通过编写 Terraform 配置文件来管理 Ingress 资源。通过这种方式,将 Ingress 资源的管理纳入到整个自动化运维流程中,提高运维效率,减少人为错误。

综上所述,Kubernetes 的 Ingress 资源为集群外部流量的路由和管理提供了强大而灵活的解决方案。通过深入理解其原理、配置方式以及与其他技术的结合应用,可以更好地满足不同应用场景下的需求,构建高性能、安全可靠的容器化应用架构。在实际应用中,需要根据具体的业务需求和环境特点,合理配置和优化 Ingress 资源,以充分发挥其优势。同时,随着 Kubernetes 和相关技术的不断发展,Ingress 资源也将不断演进,为容器化应用的发展提供更有力的支持。