Nginx 教程

Nginx 教程 Nginx 简介 Nginx 源码架构分析 Nginx 编译安装 Nginx(Tengine) 编译安装 Nginx(OpenResty) 编译安装 Nginx 配置简述 Nginx Docker 容器化配置

Nginx 核心配置指令

Nginx 核心配置指令 Nginx 配置文件 Nginx 进程配置指令 Nginx 端口监听:listen Nginx 主机名server_name Nginx 处理HTTP请求 Nginx 路由匹配规则:localhost Nginx 重定向配置:rewrite Nginx 根目录配置:root Nginx 访问路径别名:alias Nginx 文件判断:try_files Nginx 零复制:sendfile Nginx 日志记录配置

Nginx HTTP模块

Nginx 镜像模块 Nginx 请求头控制模块 Nginx IP访问控制模块 Nginx 用户cookie模块 Nginx 并发连接数限制模块 Nginx 首页处理模块 Nginx 请求频率限制模块 Nginx 页面缓存时间配置 Nginx gzip压缩及相关配置

Nginx Web服务

Nginx 静态资源服务器搭建 Nginx 文件下载服务器搭建 Nginx 伪动态SSI服务器 Nginx HTTPS服务器搭建 Nginx FastCGI模块配置简述 Nginx PHP服务器环境搭建 Nginx 基于FastCGI负载均衡 Nginx CGI网关接口 Nginx uWSGI模块配置 Nginx Python项目部署 Nginx 伪流媒体服务器搭建 Nginx HTTP2模块配置简述 Nginx WebDAV模块配置简述

Nginx 代理服务器

Nginx HTTP代理服务器 Nginx stream模块简述 Nginx TCP/UDP代理简述 Nginx 基于SSL的TCP代理服务器 Nginx gRPC代理服务器

Nginx 缓存

Nginx Web缓存配置 Nginx 代理缓存配置 Nginx Memcached 缓存模块 Nginx 反向代理缓存服务器配置 Nginx 客户端缓存控制

Nginx 负载均衡

Nginx 负载均衡模块 Nginx 负载均衡策略 Nginx 长连接负载均衡 Nginx upstream容错机制 Nginx upstream动态更新 Nginx TCP/UDP负载均衡

Nginx 日志管理监控

Nginx 日志分析简述 Nginx 访问日志配置 Nginx 错误日志配置 Nginx 日志归档配置 Nginx 日志分析工具 ELK Nginx 监控工具 Prometheus

Nginx 集群

LVS(Linux虚拟服务器)简介 Keepalived 配置简述 Nginx 集群负载搭建 Nginx 集群配置管理规划 Nginx 配置归档工具GitLab Nginx 配置修改工具Ansible Jenkins 安装与配置简述 Nginx 集群配置管理实例

Nginx 在 k8s 的应用

Kubernetes(k8s)系统简述 Kubernetes(k8s)集群部署 Kubernetes(k8s)网络通信 Nginx Ingress 简介 Nginx Ingress 安装部署 Nginx Ingress 配置映射 Nginx Ingress 注解


Nginx Ingress安装部署

Helm 是一个非常方便的 Kubernetes 应用部署工具,支持 Nginx Ingress 的快速部署和卸载。通过 Helm 可快速将 Nginx Ingress 部署在 Kubernetes 集群中,Helm 中 Nginx Ingress 的 1.19.1 版本 Chart 部分参数如下表所示。

参数 参数值选项 默认值 功能说明
controller.service.type ClusterIP 或 NodePort 或 LoadBalancer LoadBalancer 设置资源对象 Service 的服务类型
controller.hostNetwork true 或 false false 设置资源对象 Pod 是否以 hostNet-work方式运行
controller.service.externalIPs -- -- 设置资源对象 Service externalIPs 的 IP 地址
controller.kind Deployment 或 Daemon-Set Deployment 设置部署方式
controller.service.external-TrafficPolicy Local 或 Cluster Cluster 设置 Pod 流量调度方式
rbac.create true 或 false false 是否为 nginx-ingress 创建 RBAC 资源
controller.autoscaling.enabled true 或 false false 是否启用多副本支持,启用后最小副本数为 1,最大值为 11
controller.autoscaling.min-Replicas -- 1 设置创建的最小副本数
controller.metrics.enabled true 或 false false 是否启用 Prometheus Exporter
controller.containerPort.http -- 80 Nginx Ingress 的默认 HTTP 端口
controller.containerPort.https -- 443 Nginx Ingress 的默认 HTTP 端口

Nginx Ingress 的默认部署方式是 Deployment,只会部署一个副本,Service 对外发布类型是 LoadBalancer,安装参数如下:

helm install --name nginx-ingress stable/nginx-ingress --set rbac.create=true

具体说明如下:
  • Helm 安装的应用名称为 nginx-ingress;
  • rbac.create 参数用以为 nginx-ingress 创建 RBAC 资源,获取与接口服务的访问授权。

1、Nginx Ingress部署

Nginx Ingress 以 Pod 形式运行在 Kubernetes 集群中,用户可根据 Kubernetes 的网络通信特点以及实际场景选择灵活的部署方式进行 Nginx Ingress 的部署,此处分别以基于资源对象 Service 的 NodePort 方式和 Pod 的 hostNetwork 方式举例介绍。

1) Service的NodePort方式

以 NodePort 类型部署 Nginx Ingress,需要使用参数进行指定 controller.service.type 为 NodePort。为便于管理,可以为 Nginx Ingress 创建单独使用的命名空间 nginx-ingress,部署拓扑如下图所示。

NodePort方式
图:NodePort方式

部署命令如下:
# 安装nginx-ingress
helm install --name nginx-ingress \
             --namespace nginx-ingress \
             stable/nginx-ingress \
             --set "rbac.create=true,controller.autoscaling.enabled=true,controller. autoscaling.minReplicas=2,controller.service.type=NodePort,con-troller.service.externalTrafficPolicy=Local"

# 也可以在创建后调整副本数
kubectl scale --replicas=3 deployment/nginx-ingress
具体说明如下:
  • Helm 安装的应用名称为 nginx-ingress,命名空间为 nginx-ingress;
  • 以默认的 Deployment 方式部署,设置 Pod 副本数为 2,并以 Service 的 NodePort 方式对外发布服务,设置流量调度策略为 Local;
  • Kubernetes 将为 nginx-ingress Service 随机创建范围在 30000~32767 之间的 Node-Port 端口;
  • 用户将 Kubernetes 中节点 IP 和 NodePort 手动添加到传输层负载均衡中的虚拟服务器集群中;
  • 外部请求发送到传输层负载均衡虚拟服务器,传输层负载将请求数据转发到 Kubernetes 集群节点的 NodePort;
  • NodePort 类型的 Service 将请求负载到对应的 Nginx Pod;
  • Nginx 将用户请求进行应用层负载转发到配置的应用 Pod;
  • 在该部署方式下,Nginx Pod 需要使用 Local 的流量调度策略,获取客户端的真实 IP。

2) Pod的hostNetwork方式

主机网络(hostNetwork)方式可以使 Pod 与宿主机共享网络命名空间,外网传输效率最高。因 Pod 直接暴露外网,虽然存在一定的安全问题,但不存在客户端源 IP 隐藏的问题,部署拓扑如下图所示。

hostNetwork方式
图:hostNetwork方式

部署命令如下:
# 以Deployment方式部署
helm install --name nginx-ingress \
             --namespace nginx-ingress \
             stable/nginx-ingress \
             --set "rbac.create=true,controller.service.type=ClusterIP,controller. hostNetwork=true"
具体说明如下:
  • Deployment 方式部署时,Nginx Ingress 的 Service 设置类型为 ClusterIP,仅提供内部服务端口;
  • 用户将 Kubernetes 中节点 IP 及 80、443 端口手动添加到传输层负载均衡中的虚拟服务器集群中;
  • 用户请求经传输层负载均衡设备转发到 Nginx,Nginx 将用户请求负载到 Kubernetes 集群内的 Pod 应用。

也可以使用 DaemonSet 部署方式,在集群中的每个节点自动创建并运行一个 Nginx Ingress Pod,实现 Nginx Ingress 的自动扩展。
# 以DaemonSet方式部署nginx-ingress并成为集群唯一入口
helm install --name nginx-ingress \
             --namespace nginx-ingress \
             stable/nginx-ingress \
             --set "rbac.create=true,controller.kind=DaemonSet,controller.service.type=ClusterIP,controller.hostNetwork=true"

3) SSL终止(SSL Termination)和SSL透传(SSL Passthrough)

SSL 终止模式下,客户端的 TLS 数据会在代理服务器 Nginx 中解密,解密的数据由代理服务器直接或再次 TLS 加密后传递给被代理服务器,这种模式下,相对增加代理服务器的计算负担,但方便了 SSL 证书的统一管理。

SSL 透传模式下,Nginx 不会对客户端的 HTTPS 请求进行解密,加密的请求会被直接转发到后端的被代理服务器,这种方式常被应用到后端的 HTTPS 服务器需要对客户端进行客户端证书验证的场景,相对也会降低 Nginx 对 TLS 证书加解密的负担。由于请求数据是保持加密传输的,HTTP 消息头将无法修改,所以消息头字段 X-forwarded-* 的客户端 IP 无法被添加。Nginx Ingress 默认部署方式没有开启 SSL 透传的支持,需要在部署时使用参数 --enable-ssl-passthrough 进行开启。
# 修改部署资源对象nginx-ingress-controller
kubectl edit Deployment/nginx-ingress-controller -n nginx-ingress

# 在规范部分添加容器启动参数--enable-ssl-passthrough
    spec:
        containers:
        - args:
          - /nginx-ingress-controller
          - --default-backend-service=nginx-ingress/nginx-ingress-default-backend
          - --election-id=ingress-controller-leader
          - --ingress-class=nginx
          - --configmap=nginx-ingress/nginx-ingress-controller
          - --enable-ssl-passthrough

4) 卸载Nginx Ingress

Nginx 的配置是以资源对象 ConfigMap 和 Ingress 方式存储在 etcd 服务中的,所以即便删除或重新部署 Nginx Ingress 也不会影响之前的配置。

helm delete --purge nginx-ingress

2、管理工具

Nginx Ingress 提供了基于 kubectl 工具的管理插件 ingress-nginx,用于 Nginx Ingress 的日常维护。插件 ingress-nginx 安装方法如下:
# 安装插件ingress-nginx
kubectl krew install ingress-nginx

常见命令参数如下:

# 显示所有的Ingress实例摘要
kubectl ingress-nginx ingresses

# 查看所有的后端Service配置
kubectl ingress-nginx backends -n nginx-ingress

# 查看Nginx的所有配置
kubectl ingress-nginx conf -n nginx-ingress

# 查看指定主机名的Nginx配置
kubectl ingress-nginx conf -n nginx-ingress --host auth.nginxbar.org

# 查看Nginx服务器的配置目录
kubectl ingress-nginx exec -i -n nginx-ingress -- ls /etc/nginx

# 查看Nginx服务器的日志
kubectl ingress-nginx logs -n nginx-ingress

3、日志管理

Nginx Ingress 是以 Pod 方式运行的,在默认配置下,Nginx 的日志输出到 stdout 及 stderr。Kubernetes 下有很多日志收集解决方案,此处推荐使用 Filebeat 进行容器日志收集,并将容器日志实时发送到 ELK 集群,ELK 环境部署可参见《Nginx日志分析工具(ELK)配置》一节,日志收集方案逻辑如下图所示。

日志收集方案逻辑
图:日志收集方案逻辑

具体说明如下:
  • Docker 的默认日志驱动是 json-driver,每个容器的日志输出到 stdout 及 stderr 中时,Docker 的日志驱动会将容器日志以 *-json.log 的命名方式保存在 /var/lib/docker/containers/ 目录下;
  • 在 Kubernetes 集群中以 DaemonSet 方式部署 Filebeat 应用,会在每个 Node 节点运行一个 Filebeat 应用 Pod,进行每个 Node 节点的容器日志采集;
  • Filebeat 采集的日志可以直接发送给 Logstash 服务器,也可以发送给 Kafka 后由 Logstash 服务器进行异步获取;
  • 所有日志被 Logstash 转到 Elasticsearch 集群进行存储;
  • 使用者通过 Kibana 进行日志查看和分析。

1) 部署Filebeat

# 获取官方的Filebeat资源配置文件
curl -L -O https://raw.githubusercontent.com/elastic/beats/7.3/deploy/kubernetes/filebeat-kubernetes.yaml

# 修改filebeat输出目标为Logstash
sed -i "s/   cloud.id/          #cloud.id/g" filebeat-kubernetes.yaml
sed -i "s/   cloud.auth/        #cloud.auth/g" filebeat-kubernetes.yaml

sed -i "s/    output.elasticsearch:/    output.logstash:/g" filebeat-kubernetes.yaml
sed -i 's/    hosts:.*/     hosts: ["10\.10\.4\.37:5045"]/g' filebeat-kubernetes.yaml
sed -i "s/    username/ #username/g" filebeat-kubernetes.yaml
sed -i "s/    password/ #password/g" filebeat-kubernetes.yaml

kubectl create -f filebeat-kubernetes.yaml

2) 配置Logstash

按照 kubernetes.labels.app 创建容器日志在 Elasticsearch 中的索引,配置文件内容如下:
cat>logstash/pipeline/k8s.conf<<EOF
input {
    beats {
        port => 5045
        codec =>"json"
    }
}
filter {
    mutate {
        # 添加字段kubernetes_apps默认值为kubernetes_noapps
        add_field => { "kubernetes_apps" => "kubernetes_noapps" }
    }
    if [kubernetes][labels][app] {
        mutate {
            # 当存在kubernetes.labels.app时,将该字段复制为字段kubernetes_apps
            copy => {
            "[kubernetes][labels][app]" => "kubernetes_apps"
            }
        }
    }
}
output {
    elasticsearch {
        # 将log输出到ES服务器
        hosts => ["http://10.10.4.37:9200"]
        # 根据字段kubernetes_apps的值创建ES索引
        index => "k8slog-%{kubernetes_apps}-%{[@metadata][version]}-%{+YYYY.MM.dd}"
    }
}
EOF
Helm 默认会为安装的应用添加 app 标签,通过 Helm 安装 Nginx Ingress 的 app 标签值为 nginx-ingress,因此 Elasticsearch 中自动创建的索引名前缀为 k8slog-nginx-ingress-*。

4、监控管理

Nginx Ingress 中已经集成了 Nginx 的 Prometheus Exporter,可以直接使用 Prometheus 或 Zabbix 获取监控数据。Nginx 监控支持可以在部署的时候使用部署参数 controller.metrics.enabled=true 启用。
# 启用监控
helm install --name nginx-ingress \
             --namespace nginx-ingress \
             stable/nginx-ingress \
             --set "rbac.create=true,controller.kind=DaemonSet,controller.service.type=ClusterIP,controller.hostNetwork=true,controller.metrics.enabled=true"

curl http://节点IP:9913/metrics