0x07 Kubernetes中ingress-nginx优化配置 描述: 在K8s集群中部署安装 ingress-nginx 后默认并未进行相应的优化配置,本小结将针对于生产环境的中的 ingress-nginx 控制器进行优化。
我们可以从 ingress-nginx-controller 资源的 Pod 、ConfigMap 、以及业务的 ingress 规则入手。
ingress-nginx-controller Pod 温馨提示: 我们需要针对承载 ingress-nginx 的相关 Pod 容器进行内核参数优化。
$ kubectl get deployments.apps -n ingress-nginx ingress-nginx-controller
NAME READY UP-TO-DATE AVAILABLE AGE
ingress-nginx-controller 9/9 9 9 5d20h
$ kubectl get deployments.apps -n ingress-nginx ingress-nginx-controller -o yaml
# 在 spec.template.spec 对象下添加一个初始化 initContainers 容器
initContainers:
- name: sysctl
image: alpine:3.10
imagePullPolicy: IfNotPresent
command:
- sh
- -c
- |
mount -o remount rw /proc/sys
sysctl -w net.core.somaxconn=65535
sysctl -w net.ipv4.tcp_tw_reuse=1
sysctl -w net.ipv4.ip_local_port_range="1024 65535"
sysctl -w fs.file-max=1048576
sysctl -w fs.inotify.max_user_instances=16384
sysctl -w fs.inotify.max_user_watches=524288
sysctl -w fs.inotify.max_queued_events=16384
securityContext:
privileged: true ingress-nginx-controller ConfigMap 温馨提示: 我们需要按照需要将下述K/V配置项插入到 ingress-nginx 的 configMap 里的 data 对象下。
ingress-nginx 资源查看
# 查看 Ingress-nginx 全局配置参数:
kubectl get cm -n ingress-nginx nginx-ingress-controller -o yaml
# 修改 Ingress-nginx 全局配置参数:
kubectl edit cm -n ingress-nginx nginx-ingress-controller 优化配置
# 负载工作机制,轮询
load-balance: "round_robin"
# 错误日志等级设置 (debug, info, notice, warn, error, crit, alert, or emerg)
error-log-level: "notice"
# 启用Gzip资源压缩 (3k以上)
use-gzip: "true"
gzip-level: "2"
gzip-min-length: "3072"
gzip-types: "text/html text/plain text/css text/javascript application/javascript application/x-javascript application/xml application/x-httpd-php application/x-font-ttf application/json image/x-icon image/svg+xml image/avif image/webp font/ttf font/opentype"
# 不建议进行照片压缩 image/jpeg image/gif image/png 可能反而会增加其体积
# 启用Brotli资源压缩(同等条件下优于Gzip,任选一个)
enable-brotli: "true"
brotli-level: 5
brotli-min-length: 3072
brotli-types: "text/plain text/css text/javascript application/javascript application/x-javascript application/xml application/x-httpd-php application/x-font-ttf image/x-icon image/svg+xml image/avif image/webp font/ttf font/opentype"
# 不建议进行照片压缩 image/jpeg image/gif image/png 可能反而会增加其体积
# 启用http2支持(实际上默认是开启的,如果过关闭请将其设置为true)
use-http2: "true"
# ssl 会话复用
ssl_session_cache: "shared:SSL:10m;"
ssl-session-timeout: "10m"
# worker 每个工作进程可以打开的最大文件数与同时打开最大连接数设置
worker-processes: "auto"
max-worker-open-files: "10240"
max-worker-connections: "32767"
# 连接复用
enable-multi-accept: "true"
# keep-alive 连接超时和最大请求数调整
keep-alive: "75"
keep-alive-requests: "10000"
# upstream-keepalive 与上游Pod连接超时与最大请求数调整
upstream-keepalive-time: "30m"
upstream-keepalive-timeout: "60"
upstream-keepalive-requests: "10000"
upstream-keepalive-connections: "512"
# proxy-connect 设置 ingress-nginx 与 pstream pod 之间连接请求超时实践。
# 设置与代理服务器建立连接的超时时间(不能超过75s)
proxy-connect-timeout: "30"
# 设置将请求传输到代理服务器的超时时间(以秒为单位)(超时仅在两个连续的写操作之间设置,而不是为整个请求的传输设置)
proxy-send-timeout: "120"
# 设置从代理服务器读取响应的超时时间(以秒为单位)
proxy-read-timeout: "120" 开发测试:
# 启用 nginx Opentracing 扩展, 默认值:禁用
enable-opentracing: true 温馨提示:
在 Nginx 中的 upstream 主要是配置均衡池和调度方法.在 Nginx 中的 proxy_pass 主要是配置代理服务器ip或服务器组的名字.温馨提示: 在高并发场景下,我们需配置upstream-keepalive-*相关参数, 使得 nginx 尽可能快速处理 HTTP 请求(尽量少释放并重建 TCP 连接),同时控制 nginx 内存使用量。
温馨提示: ingress nginx 与 upstream pod 建立 TCP 连接并进行通信,其中涉及 3 个超时配置我们需要重点关注。
proxy-read-timeout 选项 设置 nginx 与 upstream pod 之间读操作的超时时间,默认设置为 60s,当业务方服务异常导致响应耗时飙涨时,异常请求会长时间夯住 ingress 网关,我们在拉取所有服务正常请求的 P99.99 耗时之后,将网关与 upstream pod 之间读写超时均缩短到 3s,使得 nginx 可以及时掐断异常请求,避免长时间被夯住。proxy-connect-timeout 选项 设置 nginx 与 upstream pod 连接建立的超时时间,默认设置为 5s,由于在 nginx 和业务均在内网同机房通信,我们将此超时时间缩短到 1s。ingress Rule 描述: 通常我们需要为单个业务进行相应配置, 此时我们便需要再业务的ingress部署清单中进行修正。
例如: 编辑 blog.weiyigeek.top 虚拟主机站点的 ingress 规则 (kubectl edit ingress -n weiyigeek blog.weiyigeek.top)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
# 解决: 413 Request Entity Too Large 问题
ingress.kubernetes.io/proxy-body-size: "128m"
# 解决:后端大文件上传问题
nginx.ingress.kubernetes.io/client-body-buffer-size: 64m
nginx.ingress.kubernetes.io/proxy-max-temp-file-size: 128m
# 解决: 上传文件较慢问题
nginx.ingress.kubernetes.io/proxy-buffer-size: 64m
nginx.ingress.kubernetes.io/proxy-buffering: "on"
nginx.ingress.kubernetes.io/proxy-buffers-number: "4"
# 解决: 504 网关超时即后端backend超时问题
nginx.ingress.kubernetes.io/proxy-connect-timeout: 60
nginx.ingress.kubernetes.io/proxy-read-timeout: 180s
nginx.ingress.kubernetes.io/proxy-send-timeout: 60s
# 解决: 处理Nginx代理转发与后端服务文件上传缓存区设置(原生命令)
nginx.ingress.kubernetes.io/server-snippet: |
location ~ /fastfile {
client_max_body_size 1024m; # 允许客户端请求的最大单文件字节数,若超过所设定的大小,返回413错误.人话:能上传多大文件
client_header_timeout 60; # 读取请求头的超时时间,若超过所设定的大小,返回408错误。
client_body_timeout 60; # 读取请求实体的超时时间,若超过所设定的大小,返回413错误。
client_body_buffer_size 10m; # 缓冲区代理缓冲用户端请求的最大字节数,人话:一次能接受多少文件,建议根据带宽上限设置,减少磁盘读写,加快速度
proxy_connect_timeout 60; # Nginx与后端代理连接超时时间,http请求无法立即被容器(tomcat, netty等)处理,被放在nginx的待处理池中等待被处理。
proxy_read_timeout 180; # 后端服务器响应时间(代理接收超时)时间,http请求被容器(tomcat, netty等)处理后,nginx会等待处理结果,也就是容器返回的response。
proxy_send_timeout 30; # http请求被服务器处理完后,把数据传返回给Nginx的用时,默认60秒。
proxy_buffer_size 1024k; # 设置代理服务器(nginx)保存用户头信息的缓冲区大小
proxy_buffers 6 500k; # proxy_buffers缓冲区,网页平均在32k以下的话>,这样设置
proxy_busy_buffers_size 1024k; # 高负荷下缓冲大小(proxy_buffers*2)
proxy_temp_file_write_size 1024k; # 设定缓存文件夹大小 ,大于这个值将从upstream服务器传输
} 0x08 Kubernetes中ingress-nginx安全配置 描述: 在 K8s 集群中部署安装 ingress-nginx 后默认并未根据应用安全需要进行相应的安全配置,本小结将针对于生产环境的中的 ingress-nginx 控制器以及应用常见进行安全安全配置。
1.配置指定的 Ingress Class
描述: 如果一个K8S集群中部署了多个ingress controller时,我们可以在创建ingress的时候,通过ingressClassName指定ingress class,如下所示:
$ kubectl get ingress -n web www-weiyigeek -o yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: blog-weiyigeek-top
annotations:
# ....Kubernetes 注释添加到特定的 Ingress 对象自定义其行为....
nginx.ingress.kubernetes.io/rewrite-target: /
labels:
app: blog
ref: blog.weiyigeek.top
spec:
ingressClassName: nginx # 关键点
rules:
- host: weiyigeek.top
http:
paths:
- backend:
service:
name: blog
port:
number: 8080
path: /
pathType: ImplementationSpecific 2.安全配置之强制跳转HTTPS
描述: 通过这个annotation可以强制 https,如果是http请求,会通过308 redirect 到 https.
示例:
metadata:
annotations:
# 通过重定向实施服务器端 HTTPS
# 启用了TLS,则控制器会将 (308) 重定向到 HTTPS
nginx.ingress.kubernetes.io/ssl-redirect: "true"
# 强制重定向到 HTTPS
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
# 保留 URI 中的尾部斜杠
redirectnginx.ingress.kubernetes.io/preserve-trailing-slash: "true" 3.安全配置之跨域访问cors
描述: 当将Ingress-Nginx作为API网关,必须进行跨域配置否则会对业务造成影响,例如我们公司的CDN业务必须设置跨域方面配置。
示例:
metadata:
annotations:
# 启用cors跨域 (字面意义)
nginx.ingress.kubernetes.io/enable-cors: "true"
# 设置控制 CORS 的可接受来源,遵循以下格式 http(s)://origin-site.com[:port]
nginx.ingress.kubernetes.io/cors-allow-origin:"https://*.weiyigeek.top"
# 设置支持跨域请求的方法 (GET, PUT, POST, DELETE, PATCH, OPTIONS)
nginx.ingress.kubernetes.io/cors-allow-methods: "GET, PUT, POST, OPTIONS"
# 设置支持跨域请求的标头 (DNT,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization)
nginx.ingress.kubernetes.io/cors-allow-headers: "X-Forwarded-For, X-App-Weiyigeek"
# 设置支持响应公开那些指定表头
nginx.ingress.kubernetes.io/cors-expose-headers: "*, X-CustomResponseHeader"
# 设置在 CORS 操作期间传递凭据 (为了安全设置false除非业务确实需要)
nginx.ingress.kubernetes.io/cors-allow-credentials: "false"
# 设置控制可以缓存预检请求的时间长度 1728000
nginx.ingress.kubernetes.io/cors-max-age: 600 4.安全配置之防止DDOS请求限流
描述: 通常针对于文件下载服务器我们需要进行一系列的配置, 我们可以通过 rps 限制每秒请求数,rpm 限制每分钟请求数,connections限制连接数, 如若超过将返回 503 。
示例:
metadata:
annotations:
# 每分钟从给定 IP 接受的请求数。突发流量限制设置为此限制乘以突发乘数,默认乘数为 5。(顺序3)
nginx.ingress.kubernetes.io/limit-rps: "5"
# 每秒从给定 IP 接受的请求数,突发流量限制设置为此限制乘以突发乘数,默认乘数为 5。(顺序2)
nginx.ingress.kubernetes.io/limit-rpm: "300"
# 允许来自单个 IP 地址的并发连接数,超过此限制时返回 503 错误。(顺序1)
nginx.ingress.kubernetes.io/limit-connections: "10"
# 突发大小限制速率的乘数。默认突发乘数为 5
nginx.ingress.kubernetes.io/limit-burst-multiplier:"5"
# 配置白名单不受速率限制。(局部)
nginx.ingress.kubernetes.io/limit-whitelist: "10.0.0.0/24,172.10.0.1" 5.安全配置之请求访问白名单
描述: 配置白名单比黑名单更加安全,与最小所需权限一样,主要是用于安全限制,只允许特定的客户端请求,但由于现在网络中NAT的广泛应用,但是参数使用的场景比较有限,例如针对于内网采集监控服务调用,即将其访问请求IP加入到白名单中,才不受安全策略限制影响。
示例:
metadata:
annotations:
# 通过注释指定允许的客户端 IP 源范围,该值是以逗号分隔的CIDR列表。(全局)
ingress.kubernetes.io/whitelist-source-range: "10.0.0.0/24,172.10.0.1" 6.安全配置之请求访问日志记录
描述: 为了等保合规通常需要将各类日志存储 180 天及以上,所以ingress也是非常重要,当业务被攻击时我们可以快速溯源追踪,以及其行为分析。
示例:
metadata:
annotations:
# 启用访问日志,默认情况处于启用状态.但在某些情况下可能需要为给定入口禁用访问日志设置为False即可。
nginx.ingress.kubernetes.io/enable-access-log: "true"
# 启用重写日志,默认情况处于未启用状态,如启用重写日志在通知级别发送到error_log文件。
nginx.ingress.kubernetes.io/enable-rewrite-log: "true" 7.安全配置之Nginx指定代理响应标头
描述: 在使用 ingress-nginx 场景中免不了配置使用代理或响应表头,例如常见的X-Frame-Options规定了允许那些站点嵌入配置目标iframe站点。
示例:
metadata:
annotations:
# 用于插入 server 块中的代码段
nginx.ingress.kubernetes.io/server-snippet: |
# 隐藏nginx版本
server_tokens off;
# Frame 安全控制 添加 X-Frame-Options 头
add_header X-Frame-Options SAMEORIGIN;
# MIME 模拟探测 、XXS-Protection、Spider Robots 爬取策略限制
more_set_headers 'x-content-type-options: nosniff
' 'x-xss-protection: 1; mode=block' 'X-Robots-Tag: none;';
# 用于插入 location 块代码段
nginx.ingress.kubernetes.io/configuration-snippet: |
# 自定义访问后端服务时所带头
proxy_set_header My-Custom-Header $http_my_custom_header;
# 将 X-FORWARDED-FOR 字段获取到外部IP带入后端服务
proxy_set_header X-FORWARDED-FOR $http_X_FORWARDED_FOR; 8.安全配置之Nginx禁止访问某一目录
描述: 在使用 ingress-nginx 场景中,如何禁止客户端访问 ingress 站点某一目录下的所有资源,我们可以配置 server-snippet 注释,例如。
示例:
metadata:
annotations:
# 用于插入 server 块中的代码段,禁止访问 站点的 /itwork/ 目录下资源
nginx.ingress.kubernetes.io/server-snippet: |
location /itwork/ { deny all;return 403;} 9.安全配置之请求访问认证
描述: 针对于某些未有认证的API接口应用,可以通过在 Ingress 规则中添加额外的注释来添加身份验证。
metadata:
annotations:
# 认证类型 [basic|digest]
nginx.ingress.kubernetes.io/auth-type:
# 包含用户/密码定义的密码的名称,使用configMap存储htpasswd生成热认证
# $ htpasswd -c auth weiyigee
# $ kubectl create secret generic basic-auth --from-file=auth
nginx.ingress.kubernetes.io/auth-secret: basic-auth
# 认证密钥有两种形式:
# auth-secret 默认,密钥中的 htpasswd 文件位于密钥中auth
# auth-map 密钥是用户名,值是散列密码
nginx.ingress.kubernetes.io/auth-secret-type:auth-file
# 设置认证提示
nginx.ingress.kubernetes.io/auth-realm: "身份认证" 10.安全配置之启用SSL握手加密套件
描述: 通常为了应用安全我们会为其添加证书,但是一些已知脆弱性的SSL加密方式会影响到应用信息安全,例如 RC4 与 MD5 等
示例:
# 方式1.ConfigMap
$ kubectl edit cm -n ingress-nginx ingress-nginx-controller
apiVersion: v1
data:
# 指定可以用的加密套件
ssl-ciphers: "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE:ECDH:AES:HIGH:EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:!NULL:!aNULL:!eNULL:!EXPORT:!PSK:!ADH:!DH:!DES:!MD5:!RC4"
# ssl 协议
ssl-protocols: "TLSv1.1 TLSv1.2 TLSv1.3"
# ssl 会话复用
ssl_session_cache: "shared:SSL:10m;"
ssl-session-timeout: "10m"
# 方式2.Annotations
metadata:
annotations:
# 配置指定在使用 SSLv3 和 TLS 协议时,服务器密码应优先于客户端密码。
nginx.ingress.kubernetes.io/ssl-prefer-server-ciphers: "true"
# 指定加密套件
nginx.ingress.kubernetes.io/ssl-ciphers: "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE:ECDH:AES:HIGH:EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:!NULL:!aNULL:!eNULL:!EXPORT:!PSK:!ADH:!DH:!DES:!MD5:!RC4;" 11.安全配置之启用 modsecurity waf模块
描述: ModSecurity (http://modsecurity.org/) 是一个开源的Web Application防火墙, 可以为一组特定的入口位置启用它。必须首先通过在 ConfigMap 中启用 ModSecurity 来启用 ModSecurity 模块。
请注意,这将为所有路径启用 ModSecurity,并且必须手动禁用每个路径。
# 方式1.ConfigMap
$ kubectl edit cm -n ingress-nginx ingress-nginx-controller
apiVersion: v1
data:
# 启用 modsecurity waf模块拦截常规Web攻击
enable-modsecurity: "true"
# 方式2.Annotations
metadata:
annotations:
# 启用 modsecurity
nginx.ingress.kubernetes.io/enable-modsecurity: "true"
# 设置以下注释来启用 OWASP 核心规则集
nginx.ingress.kubernetes.io/enable-owasp-core-rules: "true"
# 设置以下内容从nginx传递事务ID
nginx.ingress.kubernetes.io/modsecurity-transaction-id: "$request_id"
# 通过代码段添加自己的一组 modsecurity 规则:
nginx.ingress.kubernetes.io/modsecurity-snippet: |
Include /etc/nginx/owasp-modsecurity-crs/nginx-modsecurity.conf
SecRuleEngine On
SecDebugLog /tmp/modsec_debug.log OWASP 核心规则集 :https://www.modsecurity.org/CRS/Documentation/
建议的配置参考 :https://github.com/SpiderLabs/ModSecurity/blob/v3/master/modsecurity.conf-recommended