NGINX-INGRESS详解

NGINX-INGRESS详解_第1张图片

概述

k8s 中所有的资源都有对应的控制器在操控这个资源,管理资源的生命周期,实现”声明式“效果。Deployment、Service、Replicaset等资源的控制器封装在k8s内置的 controller-manager进程中。

对于外部请求如何进入集群内部,K8s 官方定义了 Ingress 这个资源,但是官方并没有提供 Ingress 的控制器,使用时必须手动安装一个 官方文档 ingress controller。云厂商有自己的 ingress controller,开源界也有一下 ingress controller :

所有的 Ingress 都包括数据面和控制面,控制面负责监听 k8s 资源,生成配置,下发给数据面。

Nginx Ingress 作为使用广泛的 Ingress,底层基于 Nginx,动态生成 nginx.conf 文件,实现将请求重定向到pod内部的目的。

nginx 的优点在于周边生态丰富,和传统运维无缝集成,不需要更多的学习成本。但是缺点在于热加载的支持不友好,需要重启服务。云原生时代 envoy 逐渐占据风头,出现大量基于 envoy 的 Ingress。

安装部署

有两种方式安装 nginx-ingress:helm 和 kubectl apply

helm安装官方

  helm upgrade --install ingress-nginx ingress-nginx \
  --repo https://kubernetes.github.io/ingress-nginx \
  --namespace ingress-nginx --create-namespace

kubectl apply

kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.1.0/deploy/static/provider/cloud/deploy.yaml

工作过程:
Ingress 公开从集群外部到集群内服务的 HTTP 和 HTTPS 路由。 流量路由由 Ingress 资源上定义的规则控制。

下面是一个将所有流量都发送到同一 Service 的简单 Ingress 示例:
NGINX-INGRESS详解_第2张图片
Ingress 可为 Service 提供外部可访问的 URL、负载均衡流量、终止 SSL/TLS,以及基于名称的虚拟托管。 Ingress 控制器 通常负责通过负载均衡器来实现 Ingress,尽管它也可以配置边缘路由器或其他前端来帮助处理流量。

Ingress 不会公开任意端口或协议。 将 HTTP 和 HTTPS 以外的服务公开到 Internet 时,通常使用 Service.Type=NodePort 或 Service.Type=LoadBalancer 类型的 Service。(后续会链接ingress及ingress controllers)

生成配置

  • 动态生成 nginx 需要的配置文件 nginx.conf
  • 默认nginx配置修改需要重启才生效。而 nginx-ingress 如果只是更新了 upstream 信息,是不需要重启服务的。这是通过 lua-nginx-model 来实现的

nginx建模过程

  • 通过 k8s infomrer 机制监听 k8s 资源:比如 Ingress、Service、Endpoint、Secret、Configmap,以生成配置文件。
  • 没有办法知道哪次修改会影响最终配置,因此每次变更都会从零重建模型,并和当前模型比较。

    • 如果模型不变,就不会重新生成nginx.conf 配置文件,避免重启。
    • 如果只是 Endpoints 变化,用post请求发送一个 endpoint 列表给运行在 nginx里面的 lua handler。也可以避免重新生成配置文件和服务重启。
    • 如果以上情况都不是,会创建新的模型的配置文件,并触发nginx 重启。
  • 使用时,应该避免不必要的配置变更和冲突定义,以减少服务重启。
  • 配置文件是通过 go template 渲染出来的。

nginx-reload触发

  • 新的 Ingress 资源创建。
  • 添加 TLS 到现有的 Ingress 中。
  • 修改非 upstream_configuration 相关的 annotation(load-balance 注解不会触发 reload)。
  • Ingress 中的 Path 添加或者修改。
  • Ingress 或者 Service 资源被移除。
  • Ingress 中配置的 Service 或 Secret 资源变成可用状态。
  • Secret 更新。
  • .......

排错

  • 检查ingress 资源事件

    kubectl get ing -n 
    kubectl describe ing  -n 
  • 编写ingress 资源事件

    kubectl get ing -n 
    kubectl edit ingress  -n 
    kubectl describe ing  -n  #查看状态
  • 检查日志事件

    kubectl get pods -n 
    kubectl logs -n  
  • 检查nginx主配置文件

    kubectl get pods -n 
    kubectl exec -it -n   -- cat /etc/nginx/nginx.conf
    /etc/nginx $ pwd
    /etc/nginx
    /etc/nginx $ nginx -t #语法检测
    nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
    nginx: configuration file /etc/nginx/nginx.conf test is successful
  • 检查后端SVC

    kubectl get svc -A -n 
    kubectl get svc -A |grep svc 

日志格式

log_format upstreaminfo
    '$remote_addr - $remote_user [$time_local] "$request" '
    '$status $body_bytes_sent "$http_referer" "$http_user_agent" '
    '$request_length $request_time [$proxy_upstream_name] [$proxy_alternative_upstream_name] $upstream_addr '
    '$upstream_response_length $upstream_response_time $upstream_status $req_id';
  • $proxy_protocol_addr 启用代理协议时的远程地址
  • $remote_addr 客户端的源IP地址
  • $remote_user 随基本身份验证提供的用户名
  • $time_local 通用日志格式的本地时间
  • $request 完整的原始请求行
  • $status 响应状态
  • $body_bytes_sent 发送到客户端的字节数,不包括响应头
  • $http_referer Referer 标头的值
  • $http_user_agent User-Agent 标头的值
  • $request_length 请求长度(包括请求行、请求头和请求体)
  • $request_time 从客户端读取第一个字节后经过的时间
  • $upstream_addr 上游服务器的 IP 地址和端口(或域套接字的路径)。如果在请求处理期间联系了多个服务器,则它们的地址用逗号分隔。
  • $upstream_response_length 从上游服务器获得的响应的长度
  • $upstream_response_time 以毫秒为单位从上游服务器接收响应所花费的时间
  • $upstream_status 从上游服务器获取的响应的状态码
  • $req_id X-Request-IDHTTP 标头的值。如果未设置标头,则为随机生成的 ID。
  • $proxy_upstream_name 上游的名称。格式是upstream---

Debug日志

使用 --v=XX 参数可以增加日志等级,修改 deployment 文件

kubectl get deploy -n 
kubectl edit deploy -n  
 备注:增加 --v=X 到 - args 
  • --v=2 显示配置文件差异的细节
  • --v=3 显示 svc、ingress、endpoint细节,并且打印出 json 格式的 nginx 配置文件
  • --v=5 以 Debug 模型运行 nginx

基本配置

  • 支持 配置 ingressClassName
  • 支持配置 ingressclass.kubernetes.io/is-default-class: "true" 注解 官方注解详情

    • 用于:IngressClass
    • 当单个 IngressClass 资源将此注解设置为 "true"时,新的未指定 Ingress 类的 Ingress 资源将被设置为此默认类。

注意:kubernetes.io/ingress.class (官方已弃用)
说明: 从 v1.18 开始,不推荐使用此注解以鼓励使用 spec.ingressClassName。

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: iminimal-ingress
spec:
  ingressClassName: nginx
  rules:
  - host: nginx.test.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: test
            port:
              number: 80
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: iminimal-ingress
  annotations:
    # use the shared ingress-nginx
#默认入口使用ingressclass.kubernetes.io/is-default-class: "true" 注解
      kubernetes.io/ingress.class: "nginx" #咱这里使用的kubernetes.io/ingress.class 多个入口 
spec:
  rules:
  - host: nginx.test.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: test
            port:
              number: 80
       

注解说明

注解的 key 和 value 只支持 string,因此 bool 或者 int 必须使用引号。比如 “ture”、“100”、“false”
注解的前缀默认是 “nginx.ingress.kubernetes.io",可以通过 --annotations-prefix 命令修改

工作中用到的注解 官方注解

  • 自定义最大车身尺寸
    请求中的大小超过客户端请求正文的最大允许大小时,将向客户端返回 413 错误

    nginx.ingress.kubernetes.io/proxy-body-size: 8m
  • 自定义超时
    注意⚠️:所有超时值都是无单位的,以秒为单位。

    nginx.ingress.kubernetes.io/proxy-connect-timeout : "10"
    nginx.ingress.kubernetes.io/proxy-send-timeout :  "90"
    nginx.ingress.kubernetes.io/proxy-read-timeout : "120"
  • 通过重定向执行服务器端 HTTPS

默认情况下,如果为该入口启用了 TLS,则控制器会将 (308) 重定向到 HTTPS。如果要全局禁用此行为,可以ssl-redirect: "false"在 NGINX ConfigMap中使用。

要为特定入口资源配置此功能,可以使用以下命令

nginx.ingress.kubernetes.io/ssl-redirect: "false"

在集群外部使用 SSL 卸载(例如 AWS ELB)时,即使没有可用的 TLS 证书,强制重定向到 HTTPS 也可能很有用。这可以通过使用以下命令特定资源中的注释来实现。

nginx.ingress.kubernetes.io/force-ssl-redirect: "true"

如果要使用 保留 URI 中的尾部斜杠,请为该特定资源ssl-redirect设置注释。

nginx.ingress.kubernetes.io/preserve-trailing-slash: "true" 
  • 连接代理标头

使用此注解将覆盖 NGINX 设置的默认连接头。要在 Ingress 规则中使用自定义值,请定义注释:

nginx.ingress.kubernetes.io/connection-proxy-header: "close"

如有@侵权,请联系 [email protected] 改版。

你可能感兴趣的:(kubernetes容器)