1. 介绍
基于Nginx的Ingress controller有多种,比如 kong、kubernetes/ingress nginx、nginxinc/kubernetes-ingress。比较容易混淆的是后两者。
- nginxinc/kubernetes-ingress是F5 nginx官方推出的控制器,支持开源版本和商业版版本的nginx。
- kubernetes/ingress nginx 是由kubernetes社区基于nginx社区版实现的ingess控制器,由Kubernetes社区维护,F5 Nginx承诺帮助管理这个项目。
当前这篇博客的内容全部基于 F5 nginx 推出的 nginxinc/kubernetes-ingress 开源版本。需要注意的是:这篇文档是以官方文档为准,并结合自己的理解和案例进行挑重点内容进行梳理,学习过程中推荐和官方文档相互印证。
当前文档剔除了官方文档中商业版Nginx功能,并且主要针对原生**ingress**
资源为核心进行学习,个人认为CRD的学习必要性不高,需要用的时候查官方文档就可以了。
1.1. 原理
Ingress Controller 以下简称IC,本章节从集群中Nginx Ingress Controller流量转发到控制器内部实现方式都做了介绍,更多更具体的描述可参考官方文档。
1.1.1. IC 流量转发
- 管理员(admin)在集群中部署 Nginx IC ,通常会有多个副本,图中只显示了一个
- 用户A配置
a.example.com
Ingress资源,转发流量到Pod A中;用户B配置b.example.com
Ingress资源,转发流量到Pod 中 - IC Pod中IC进程监听 Ingress 资源变化,生成 Nginx 配置文件,并重载 nginx 进程
- 管理员(Admin)将域名解析到集群外部的LB上(Public Endpoint)
客户端通过域名访问到 Public Endpoint,Public Endpoint将流量转发到IC Pod中Nginx监听的套接字,Nginx再根据配置文件转发流量到 Pod A 和 Pod B
1.1.2. IC Pod 内部逻辑
通常使用Deployment或者Daemonset部署多个Pod,每个Pod 内部有三类进程:
IC :根据集群中Ingress或者其它CRD资源生成nginx配置
- Nginx Master:Nginx 的 Master 进程,用来控制Nginx Worker进程
- Nginx Worker:Nginx 的 Worker 进程,处理用户请求流量的进程
上述架构图中每个阶段的详细描述如下:
- (HTTP) IC 可以通过HTTP接口暴露自身和Nginx指标,Prometheus通过接口采集相关信息并展示。默认情况下接口为
:9113/metrics
,这个功能可以关闭 - (HTTPS) IC 通过Kubernetes API 获取资源(Ingress, nginx CRD)的更新,处理后并更新资源状态
- (HTTP) Kubelet 通过 IC 的 Readiness 接口判断 IC Pod 是否就绪
- (File I/O) IC 进程启动时,会读取来自文件系统的配置生成所需的配置模板。这些模板位于容器的 /目录中,并具有.tmpl扩展名
- (File I/O) IC将日志写入标准输出和标准错误,由容器运行时收集
- (File I/O) IC根据 Kubernetes资源生成配置文件,并写入 /etc/nginx 目录下,以
.conf
结尾 - (File I/O) IC根据 Ingress 或者其它资源 获取的TLS 证书和私钥写入 文件中
- (HTTP) IC通过
unix:/var/lib/nginx/nginx-status.sock
获取Nginx指标,并以Promethues格式暴露出去 - (HTTP) 为了确保配置文件加载成功,IC 会通过
unix:/var/lib/nginx/nginx-config-version.sock
确保至少有一个worker进程使用了最新的配置 - (N/A) IC 启动Nginx Master进程
- (Signal) IC 通过
nginx -s reload
重载Nignx 配置文件 - (Signal) IC 通过
nginx -s quit
停止Nginx进程 - (File I/O) master 将日志写入标准输出和标准错误,由容器运行时收集
- (File I/O) master 在启动和reload时从文件读取 TLS 证书和私钥
- (File I/O) master 在启动和reload时从文件读取 配置
- (Signal) master 控制worker进程的生命周期
- (File I/O) worker 将日志写入标准输出和标准错误,由容器运行时收集
- (UDP) worker 将upstream端点的响应延迟日志通过
unix:/var/lib/nginx/nginx-syslog.sock
发送给IC,由IC通过Metrics暴露 - (HTTP,HTTPS,TCP,UDP) worker 承接来自客户端的请求
- (HTTP,HTTPS,TCP,UDP) worker 将请求转发到后端的Pod上
(HTTP) admin 通过 woker 的8080端口访问nginx的状态页,默认仅
localhost
能访问1.1.3. IC 进程内部逻辑
IC 进程处理Kubernetes资源(ingress和CRD)的流程如下:用户创建Ingress或CRD资源
- IC 进程会缓存关注的资源(Ingress和其它CRD资源),通过watch Kuberntes API保持缓存的同步
- 当资源发生变化,会通知 Control Loop
- Control Loop 从缓存中获取更新的资源,比如 TLS 证书、Ingress等
- Control Loop 生成TLS证书和私钥文件
- Control Loop 生成nginx配置文件
- Control Loop 执行 nginx reload,并等待nginx完成配置文件的加载:
7.1. nginx 重载并读取 TLS 证书
7.2. nginx 重载并读取配置文件
- Control Loop 推送event并更新资源状态
IC 关注的Kuberntes资源有以下这些:
- 七层负责均衡:Ingress、VirtualServers (CR)、VirtualServerRoutes (CR)
- 七层策略:Policies (CR)
- 四层负载均衡:TransportServers (CR)
- 服务发现:Service、Endpoints、Pods
- 密钥配置:Secrets
- 全局配置:ConfigMap、GlobalConfiguration (CR)
- 其它自定义资源(默认不启用):APPolicies, APLogConfs, APUserSigs、IngressLink
2. 部署
2.1. 版本说明
在部署或升级之前,需要参考官方提供的版本支持说明。一般而言尽量使用最新版本,官方明确说明所有版本是生产可用的,并且可实现稳定升级,不会存在版本回退的兼容性问题。
在镜像选择方面,支持基于Alpine、Debian、Redhat-Ubi 三种基础进行构建的镜像。并且还提供 OpenTracing 链路跟踪模块的版本,具体如下:
Name | Base image | Third-party modules | DockerHub image | Architectures | |
---|---|---|---|---|---|
Alpine-based image | nginx:1.21.6-alpine, which is based on alpine:3.15 | nginx/nginx-ingress:2.2.0-alpine | arm/v7, arm64, amd64, ppc64le, s390x | ||
Alpine-based image with OpenTracing | nginx:1.21.6-alpine, which is based on alpine:3.15 | NGINX OpenTracing module, OpenTracing library, OpenTracing tracers for Jaeger, Zipkin and Datadog | nginx/nginx-ingress:2.2.0-alpine-ot | arm/v7, arm64, amd64, ppc64le, s390x | |
Debian-based image | nginx:1.21.6, which is based on debian:bullseye-slim | nginx/nginx-ingress:2.2.0 | arm/v7, arm64, amd64, ppc64le, s390x | ||
Debian-based image with OpenTracing | nginx:1.21.6, which is based on debian:bullseye-slim | NGINX OpenTracing module, OpenTracing library, OpenTracing tracers for Jaeger, Zipkin and Datadog | nginx/nginx-ingress:2.2.0-ot | arm/v7, arm64, amd64, ppc64le, s390x | |
Ubi-based image | redhat/ubi8 | nginx/nginx-ingress:2.2.0-ubi | arm64, amd64, s390x |
Nginx官方提供三种部署方式:
- 清单文件部署:虽然繁琐,但是自定义更加方便。由于Nginx部署方便,我更倾向于直接使用清单文件部署。
- Chart 部署:方便后续的管理
-
2.2. 使用清单文件部署
这里给出所有部署的步骤和发生修改的清单文档,但是可能和官方文档版本会有出入,部署时可以相互印证
[root@duduniao ~]# git clone https://github.com/nginxinc/kubernetes-ingress.git --branch v2.2.0
[root@duduniao ~]# cd kubernetes-ingress/deployments
# 将部署所有的基础设施部署清单都加到git仓库进行版本管理
[root@duduniao deployments]# cp -r common daemon-set rbac service /data/projects/gitlab/kubernetes-manifest/local-01/deploy-infra/nginxinc-ingress
[root@duduniao deployments]# cd /data/projects/gitlab/kubernetes-manifest/local-01/deploy-infra/nginxinc-ingress
2.2.1. 配置RBAC
[root@duduniao nginxinc-ingress]# kubectl apply -f common/ns-and-sa.yaml [root@duduniao nginxinc-ingress]# kubectl apply -f rbac/rbac.yaml
2.2.2. 创建CRD
# 创建默认的Nginx Server证书,该证书用于针对404页面响应和默认TLS证书。nginx默认提供了自签名证书 common/default-server-secret.yaml, 但是更加推荐使用自己的公司证书。 [root@duduniao nginxinc-ingress]# kubectl create secret -n nginx-ingress tls default-server-secret --cert=certs/server.crt --key=certs/server.key
[root@duduniao nginxinc-ingress]# kubectl apply -f common/nginx-config.yaml [root@duduniao nginxinc-ingress]# kubectl apply -f common/ingress-class.yaml
# nginx 的自定义配置项,默认data为空 kind: ConfigMap apiVersion: v1 metadata: name: nginx-config namespace: nginx-ingress data: client-max-body-size: 10m error-log-level: error keepalive: "8" server-tokens: "false" ssl-protocols: TLSv1.2 worker-connections: "10240" worker-processes: "2" # 当前环境的ingress controller下游是使用Nginx L4负载均衡的,为了获取到源地址,使用了 proxy protocol协议 # 因此打开了 proxy-protocol,并且日志中也指定了proxy_protocol_addr # 如果下游LB可以透传地址到当前控制器,可以取消 proxy_protocol配置 proxy-protocol: "true" log-format: '$time_local|$remote_addr|$proxy_protocol_addr|$http_x_real_ip|$http_x_forwarded_for|$resource_name|$resource_type|$resource_namespace|$service|$request_method|$server_protocol|$host|$request_uri|$http_referer|$http_user_agent|$body_bytes_sent|$status|$grpc_status'
apiVersion: networking.k8s.io/v1 kind: IngressClass metadata: name: nginx # 设置为默认的ingress class,如果注释annotations,表示不会设置为默认的ingress controller annotations: ingressclass.kubernetes.io/is-default-class: "true" spec: controller: nginx.org/ingress-controller
[root@duduniao nginxinc-ingress]# kubectl apply -f common/crds/k8s.nginx.org_virtualservers.yaml [root@duduniao nginxinc-ingress]# kubectl apply -f common/crds/k8s.nginx.org_virtualserverroutes.yaml [root@duduniao nginxinc-ingress]# kubectl apply -f common/crds/k8s.nginx.org_transportservers.yaml [root@duduniao nginxinc-ingress]# kubectl apply -f common/crds/k8s.nginx.org_policies.yaml [root@duduniao nginxinc-ingress]# kubectl apply -f common/crds/k8s.nginx.org_globalconfigurations.yaml
2.2.3. 部署控制器
部署控制器的方式有两种:
使用deployment + service(NodePort/LoadBalancer)
- 使用daemonset
一般情况,在私有云环境中,更加推荐使用daemonset,在公有云可以使用 deployment。这里以daemon为例:
[root@duduniao nginxinc-ingress]# kubectl label nodes ubuntu-2004-104 ingress-controller/nginx=yes
[root@duduniao nginxinc-ingress]# kubectl label nodes ubuntu-2004-105 ingress-controller/nginx=yes
[root@duduniao nginxinc-ingress]# kubectl label nodes ubuntu-2004-106 ingress-controller/nginx=yes
[root@duduniao nginxinc-ingress]# kubectl apply -f daemon-set/nginx-ingress.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: nginx-ingress
namespace: nginx-ingress
spec:
selector:
matchLabels:
app: nginx-ingress
template:
metadata:
labels:
app: nginx-ingress
#annotations: # 如果prometheus是通过注释采集日志,则需要打开
#prometheus.io/scrape: "true"
#prometheus.io/port: "9113"
#prometheus.io/scheme: http
spec:
serviceAccountName: nginx-ingress
containers:
- image: nginx/nginx-ingress:2.2.0 # 不带链路追踪的镜像,链路跟踪后续演示
imagePullPolicy: IfNotPresent
name: nginx-ingress
ports:
- name: http
containerPort: 80
hostPort: 80
- name: https
containerPort: 443
hostPort: 443
- name: readiness-port
containerPort: 8081
- name: prometheus
containerPort: 9113
readinessProbe:
httpGet:
path: /nginx-ready
port: readiness-port
periodSeconds: 1
securityContext:
allowPrivilegeEscalation: true
runAsUser: 101 #nginx
capabilities:
drop:
- ALL
add:
- NET_BIND_SERVICE
env:
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: TZ # 指定时区,方便查看日志
value: Asia/Shanghai
args:
- -nginx-configmaps=$(POD_NAMESPACE)/nginx-config
- -default-server-tls-secret=$(POD_NAMESPACE)/default-server-secret
- -wildcard-tls-secret=$(POD_NAMESPACE)/default-server-secret # 指定默认证书,当ingress中声明TLS却没有指定secretName时使用该证书
- -enable-prometheus-metrics # 启用prometheus指标
- -enable-snippets # 支持通过注释插入代码片段
- -health-status # 开启健康状态检查接口,方便前端LB对它健康检查
- -enable-latency-metrics # 开启延迟指标监控
nodeSelector:
ingress-controller/nginx: "yes" # 选择部署的节点,即使是daemonset也不是所有worker节点都部署
2.2.4. LB配置
实验环境下,ingress controller 下游的LB使用的是nginx,配置如下:
upstream ingress-443 {
server 10.4.7.106:443 max_fails=1 fail_timeout=30s ;
server 10.4.7.105:443 max_fails=1 fail_timeout=30s ;
server 10.4.7.104:443 max_fails=1 fail_timeout=30s ;
}
upstream ingress-80 {
server 10.4.7.106:80 max_fails=1 fail_timeout=30s ;
server 10.4.7.105:80 max_fails=1 fail_timeout=30s ;
server 10.4.7.104:80 max_fails=1 fail_timeout=30s ;
}
server {
listen 0.0.0.0:443 ;
proxy_protocol on ;
proxy_connect_timeout 2s;
proxy_next_upstream on;
proxy_next_upstream_timeout 5;
proxy_next_upstream_tries 1;
proxy_pass ingress-443;
access_log /var/log/nginx/kube-ingress.log proxy;
}
server {
listen 0.0.0.0:80 ;
proxy_protocol on ;
proxy_connect_timeout 2s;
proxy_next_upstream on;
proxy_next_upstream_timeout 5;
proxy_next_upstream_tries 1;
proxy_pass ingress-80;
access_log /var/log/nginx/kube-ingress.log proxy;
}
2.2.5. 验证
2.2.5.1. 默认404页面
直接通过LB进行访问,测试443和80是否正常,并且验证443端口是否使用了默认的证书
[root@duduniao nginxinc-ingress]# curl -I http://10.4.7.100
HTTP/1.1 404 Not Found
Server: nginx
Date: Wed, 04 May 2022 08:31:59 GMT
Content-Type: text/html
Content-Length: 146
Connection: keep-alive
[root@duduniao nginxinc-ingress]# curl -I https://10.4.7.100 -k
HTTP/1.1 404 Not Found
Server: nginx
Date: Wed, 04 May 2022 08:32:16 GMT
Content-Type: text/html
Content-Length: 146
Connection: keep-alive
# 因为是本地vmware搭建的环境,使用 hosts 配置域名解析,解析域名到 LB
[root@duduniao nginxinc-ingress]# curl https://test.huanle.com # 证书验证通过,表明默认证书配置正确
<html>
<head><title>404 Not Found</title></head>
<body>
<center><h1>404 Not Found</h1></center>
<hr><center>nginx</center>
</body>
</html>
# 上述测试中,原客户端IP 10.4.7.1 已经被成功记录到日志中
04/May/2022:16:39:49 +0800|10.4.7.100|10.4.7.1|-|-|||||HEAD|HTTP/1.1|10.4.7.100|/|-|curl/7.68.0|0|404|
04/May/2022:16:39:56 +0800|10.4.7.100|10.4.7.1|-|-|||||GET|HTTP/1.1|test.huanle.com|/|-|curl/7.68.0|146|404|
# 如果带上X-Real-IP和X-Forwarded-For验证,模拟下游其它L7负载均衡器
[root@duduniao nginxinc-ingress]# curl -H "X-Real-IP: 192.168.99.251" -H "X-Forwarded-For: 192.168.99.251, 10.4.7.1" https://test.huanle.com
04/May/2022:16:44:33 +0800|10.4.7.100|10.4.7.1|192.168.99.251|192.168.99.251, 10.4.7.1|||||GET|HTTP/1.1|test.huanle.com|/|-|curl/7.68.0|146|404|
2.2.5.2. ingress http 验证
apiVersion: apps/v1
kind: Deployment
metadata:
name: ingress-demo-01
spec:
replicas: 2
selector:
matchLabels:
app: ingress-demo-01
release: stable
strategy:
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
metadata:
labels:
app: ingress-demo-01
release: stable
spec:
containers:
- name: nginx-pod
image: linuxduduniao/nginx:v1.0.5
---
apiVersion: v1
kind: Service
metadata:
name: ingress-demo-01
spec:
selector:
app: ingress-demo-01
release: stable
ports:
- name: http
port: 80
targetPort: 80
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-demo-01
spec:
ingressClassName: nginx
rules:
- host: ingress-demo-01.huanle.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: ingress-demo-01
port:
name: http
[root@duduniao ~]# curl ingress-demo-01.huanle.com/info
2022-05-04T08:49:22+00:00|v1.0.3|ingress-demo-01-698bb5556b-4rq5j|ok
[root@duduniao ~]# curl ingress-demo-01.huanle.com/info
2022-05-04T08:49:23+00:00|v1.0.3|ingress-demo-01-698bb5556b-vbwmz|ok
04/May/2022:16:48:39 +0800|10.4.7.100|10.4.7.1|-|-|ingress-demo-01|ingress|default|ingress-demo-01|GET|HTTP/1.1|ingress-demo-01.huanle.com|/info|-|curl/7.68.0|59|200|
04/May/2022:16:49:22 +0800|10.4.7.100|10.4.7.1|-|-|ingress-demo-01|ingress|default|ingress-demo-01|GET|HTTP/1.1|ingress-demo-01.huanle.com|/info|-|curl/7.68.0|70|200|
2.2.5.3. ingress https 验证
apiVersion: apps/v1
kind: Deployment
metadata:
name: ingress-demo-02
spec:
replicas: 2
selector:
matchLabels:
app: ingress-demo-02
release: stable
strategy:
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
metadata:
labels:
app: ingress-demo-02
release: stable
spec:
containers:
- name: nginx-pod
image: linuxduduniao/nginx:v1.0.4
---
apiVersion: v1
kind: Service
metadata:
name: ingress-demo-02
spec:
selector:
app: ingress-demo-02
release: stable
ports:
- name: http
port: 80
targetPort: 80
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-demo-02
spec:
ingressClassName: nginx
rules:
- host: ingress-demo-02.huanle.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: ingress-demo-02
port:
name: http
tls:
- hosts:
- ingress-demo-02.huanle.com
secretName: huanle.com
[root@duduniao nginxinc-ingress]# curl https://ingress-demo-02.huanle.com/info
2022-05-04T10:02:13+00:00|v1.0.4|ingress-demo-02-749fd84dc-kmtf5|ok
[root@duduniao nginxinc-ingress]# curl https://ingress-demo-02.huanle.com/info
2022-05-04T10:02:13+00:00|v1.0.4|ingress-demo-02-749fd84dc-j6xz5|ok
04/May/2022:18:02:10 +0800|10.4.7.100|10.4.7.1|-|-|ingress-demo-02|ingress|default|ingress-demo-02|GET|HTTP/1.1|ingress-demo-02.huanle.com|/info|-|curl/7.68.0|69|200|
04/May/2022:18:03:02 +0800|10.4.7.100|10.4.7.1|-|-|ingress-demo-02|ingress|default|ingress-demo-02|GET|HTTP/1.1|ingress-demo-02.huanle.com|/info|-|curl/7.68.0|69|200|
3. 配置
3.1. Nginx全局配置
3.1.1. 命令行参数
在Ingress Pod启动的Yaml文件中,可以指定启动参数,nginx涉及的启动参数较多,此处挑重点描述,其它请参考官方文档。
-enable-snippets
:是否在ingress和nginx CRD资源中启用配置段功能,默认false
。需要对nginx配置项有比较深的了解才能更好的使用它,否则很容易导致配置文件加载出错。通常仅在实现复杂的功能的情况下才会考虑开启。-default-server-tls-secret
:指定默认的server端TLS证书和私钥,用于返回404页面使用。格式:namespace/secret
-wildcard-tls-secret
:用来指定默认的server端TLS证书和私钥,当ingress指定了TLS方式访问,但是没有指定secretName
时使用该通配符证书-enable-custom-resources
:是否启用自定义资源,默认为true
-health-status
:指定该参数将添加/nginx-health
location,用来给下游LB检查nginx是否正常-global-configuration
:指定启动时读取通过CRD定义的全局配置,格式:namespace/name
-ingress-template-path
:指定nginx配置文件的渲染模板,默认nginx.ingress.tmpl
-main-template-path
:指定nginx主配置文件渲染模板,默认nginx.ingress.tmpl
-nginx-configmaps
:从configmap读取nginx配置,格式namespace/name
-transportserver-template-path
:指定TransportServer资源的配置文件渲染模板,默认值nginx.transportserver.tmpl
-virtualserver-template-path
:指定VirtualServer资源的配置文件渲染模板,默认值nginx.ingress.tmpl
nginx-debug
:指定nginx启用debug模式,需要在configmap中指定error-log-level: debug
-nginx-status
:启用nginx状态页,默认true
-nginx-status-allow-cidrs
:配置允许访问状态页的IP或CIDR,默认仅locahost-enable-prometheus-metrics
:开启Prometheus指标导出功能-prometheus-metrics-listen-port
:指定Prometheus指标导出接口的监听端口,默认9113
-prometheus-tls-secret
:指定Prometheus指标导出接口的监听端口的TLS证书和私钥,格式namespace/name
,默认不加密3.1.2. ConfigMap
使用ConfigMap配置nginx的全局配置参数,在定义ingress或者其它nginx CRD资源时,可以覆盖全局配置。同样ConfigMap涉及到的参数很多,此处仅挑重点的进行标红,其它请参考官方文档。3.1.2.1. 常规自定义配置
| ConfigMap Key | Description | Default | Example | | —- | —- | —- | —- | | proxy-connect-timeout | Sets the value of the proxy_connect_timeout and grpc_connect_timeout directive. | 60s |
| | proxy-read-timeout | Sets the value of the proxy_read_timeout and grpc_read_timeout directive. | 60s |
| | proxy-send-timeout | Sets the value of the proxy_send_timeout and grpc_send_timeout directive. | 60s |
| | client-max-body-size | Sets the value of the client_max_body_size directive. | 1m |
| | proxy-buffering | Enables or disables buffering of responses from the proxied server. | True |
| | proxy-buffers | Sets the value of the proxy_buffers directive. | Depends on the platform. |
| | proxy-buffer-size | Sets the value of the proxy_buffer_size and grpc_buffer_size directives. | Depends on the platform. |
| | proxy-max-temp-file-size | Sets the value of the proxy_max_temp_file_size directive. | 1024m |
| | set-real-ip-from | Sets the value of the set_real_ip_from directive. | N/A |
| | real-ip-header | Sets the value of the real_ip_header directive. | X-Real-IP |
| | real-ip-recursive | Enables or disables the real_ip_recursive directive. | False |
| | default-server-return | Configures the return directive in the default server, which handles a client request if none of the hosts of Ingress or VirtualServer resources match. The default value configures NGINX to return a 404 error page. You can configure a fixed response or a redirect. For example, default-server-return: 302 https://nginx.org will redirect a client to https://nginx.org. | 404 |
| | server-tokens | Enables or disables the server_tokens directive. Additionally, with the NGINX Plus, you can specify a custom string value, including the empty string value, which disables the emission of the“Server” field. | True |
| | worker-processes | Sets the value of the worker_processes directive. | auto |
| | worker-rlimit-nofile | Sets the value of the worker_rlimit_nofile directive. | N/A |
| | worker-connections | Sets the value of the worker_connections directive. | 1024 |
| | worker-cpu-affinity | Sets the value of the worker_cpu_affinity directive. | N/A |
| | worker-shutdown-timeout | Sets the value of the worker_shutdown_timeout directive. | N/A |
| | server-names-hash-bucket-size | Sets the value of the server_names_hash_bucket_size directive. | 256 |
| | server-names-hash-max-size | Sets the value of the server_names_hash_max_size directive. | 1024 |
| | resolver-addresses | Sets the value of the resolver addresses. Note: If you use a DNS name (for example, kube-dns.kube-system.svc.cluster.local ) as a resolver address, NGINX Plus will resolve it using the system resolver during the start and on every configuration reload. If the name cannot be resolved or the DNS server doesn’t respond, NGINX Plus will fail to start or reload. To avoid this, we recommend using IP addresses as resolver addresses instead of DNS names. Supported in NGINX Plus only. | N/A | Support for Type ExternalName Services
. | | resolver-ipv6 | Enables IPv6 resolution in the resolver. Supported in NGINX Plus only. | True | Support for Type ExternalName Services | | resolver-valid | Sets the time NGINX caches the resolved DNS records. Supported in NGINX Plus only. | TTL value of a DNS record | Support for Type ExternalName Services | | resolver-timeout | Sets the resolver_timeout for name resolution. Supported in NGINX Plus only. | 30s | Support for Type ExternalName Services | | keepalive-timeout | Sets the value of the keepalive_timeout directive. | 65s |
| | keepalive-requests | Sets the value of the keepalive_requests directive. | 100 |
| | variables-hash-bucket-size | Sets the value of the variables_hash_bucket_size directive. | 256 |
| | variables-hash-max-size | Sets the value of the variables-hash-max-size directive. | 1024 |
|
3.1.2.2. 日志配置
ConfigMap Key | Description | Default | Example |
---|---|---|---|
error-log-level | Sets the global error log level for NGINX. | notice | |
access-log-off | Disables the access log | False | |
default-server-access-log-off | Disables the access log for the default server. If access log is disabled globally (access-log-off: “True”), then the default server access log is always disabled. | False | |
log-format | Sets the custom log format for HTTP and HTTPS traffic. For convenience, it is possible to define the log format across multiple lines (each line separated by \n). In that case, the Ingress Controller will replace every \n character with a space character. All ‘ characters must be escaped. | See the template file for the access log. | Custom Log Format . |
log-format-escaping | Sets the characters escaping for the variables of the log format. Supported values: json (JSON escaping), default (the default escaping) none (disables escaping). | default | |
stream-log-format | Sets the custom log format for TCP, UDP, and TLS Passthrough traffic. For convenience, it is possible to define the log format across multiple lines (each line separated by \n). In that case, the Ingress Controller will replace every \n character with a space character. All ‘ characters must be escaped. | See the template file . |
|
stream-log-format-escaping | Sets the characters escaping for the variables of the stream log format. Supported values: json (JSON escaping), default (the default escaping) none (disables escaping). | default |
3.1.2.3. SSL/TLS 配置
ConfigMap Key | Description | Default |
---|---|---|
redirect-to-https | Sets the 301 redirect rule based on the value of the http_x_forwarded_proto header on the server block to force incoming traffic to be over HTTPS. Useful when terminating SSL in a load balancer in front of the Ingress Controller — see 115 | False |
ssl-redirect | Sets an unconditional 301 redirect rule for all incoming HTTP traffic to force incoming traffic over HTTPS. | True |
hsts | Enables HTTP Strict Transport Security (HSTS) : the HSTS header is added to the responses from backends. The preload directive is included in the header. | False |
hsts-max-age | Sets the value of the max-age directive of the HSTS header. | 2592000 (1 month) |
hsts-include-subdomains | Adds the includeSubDomains directive to the HSTS header. | False |
hsts-behind-proxy | Enables HSTS based on the value of the http_x_forwarded_proto request header. Should only be used when TLS termination is configured in a load balancer (proxy) in front of the Ingress Controller. Note: to control redirection from HTTP to HTTPS configure the nginx.org/redirect-to-https annotation. | False |
ssl-protocols | Sets the value of the ssl_protocols directive. | TLSv1 TLSv1.1 TLSv1.2 |
ssl-prefer-server-ciphers | Enables or disables the ssl_prefer_server_ciphers directive. | False |
ssl-ciphers | Sets the value of the ssl_ciphers directive. | HIGH:!aNULL:!MD5 |
ssl-dhparam-file | Sets the content of the dhparam file. The controller will create the file and set the value of the ssl_dhparam directive with the path of the file. | N/A |
3.1.2.4. Listeners配置
ConfigMap Key | Description | Default | Example |
---|---|---|---|
http2 | Enables HTTP/2 in servers with SSL enabled. | False | |
proxy-protocol | Enables PROXY Protocol for incoming connections. | False | Proxy Protocol |
3.1.2.5. Backend配置
ConfigMap Key | Description | Default |
---|---|---|
lb-method | Sets the load balancing method. To use the round-robin method, specify “round_robin”. | “random two least_conn” |
max-fails | Sets the value of the max_fails parameter of the server directive. | 1 |
upstream-zone-size | Sets the size of the shared memory zone for upstreams. For NGINX, the special value 0 disables the shared memory zones. For NGINX Plus, shared memory zones are required and cannot be disabled. The special value 0 will be ignored. | 256k for NGINX, 512k for NGINX Plus |
fail-timeout | Sets the value of the fail_timeout parameter of the server directive. | 10s |
keepalive | Sets the value of the keepalive directive. Note that proxy_set_header Connection “”; is added to the generated configuration when the value > 0. | 0 |
3.1.2.6. Snippets & Custom 模板
ConfigMap Key | Description | Default | Example |
---|---|---|---|
main-snippets | Sets a custom snippet in main context. | N/A | |
http-snippets | Sets a custom snippet in http context. | N/A | |
location-snippets | Sets a custom snippet in location context. | N/A | |
server-snippets | Sets a custom snippet in server context. | N/A | |
stream-snippets | Sets a custom snippet in stream context. | N/A | Support for TCP/UDP Load Balancing |
main-template | Sets the main NGINX configuration template. | By default the template is read from the file in the container. | Custom Templates |
ingress-template | Sets the NGINX configuration template for an Ingress resource. | By default the template is read from the file on the container. | Custom Templates |
virtualserver-template | Sets the NGINX configuration template for an VirtualServer resource. | By default the template is read from the file on the container. | Custom Templates |
3.1.2.7. 链路追踪
ConfigMap Key | Description | Default |
---|---|---|
opentracing | Enables OpenTracing globally (for all Ingress, VirtualServer and VirtualServerRoute resources). Note: requires the Ingress Controller image with OpenTracing module and a tracer. See the docs for more information. | False |
opentracing-tracer | Sets the path to the vendor tracer binary plugin. | N/A |
opentracing-tracer-config | Sets the tracer configuration in JSON format. | N/A |
3.2. Ingress资源配置
Kubernetes原生的ingress支持的字段很少,只有域名、路径、协议、上游服务器等配置项,在实践中往往需要更加复杂的配置,比如请求头配置、长链接配置、rewrite配置等。通常情况下,使用annotations
进行配置。
3.2.1. annotations
在创建Ingress时,IC会检查所有annotations中nginx相关的注解,并且对其进行校验,如果校验失败,则不会被创建nginx配置文件,也就无法完成流量转发,此时可以通过kubectl describe ingress xxx
进行查看报错原因。但是IC并不会对所有的注解进行校验,以下是不校验的注解:
nginx.org/server-tokens
nginx.org/proxy-hide-headers
nginx.org/proxy-pass-headers
nginx.org/rewrites
3.2.1.2. Listeners
| Annotation | ConfigMap Key | Description | Default | Example | | —- | —- | —- | —- | —- | | nginx.org/listen-ports | N/A | Configures HTTP ports that NGINX will listen on. | [80] |
| | nginx.org/listen-ports-ssl | N/A | Configures HTTPS ports that NGINX will listen on. | [443] |
|
3.2.1.3. General
Annotation | ConfigMap Key | Description | Default | Example |
---|---|---|---|---|
nginx.org/proxy-connect-timeout | proxy-connect-timeout | Sets the value of the proxy_connect_timeout and grpc_connect_timeout directive. | 60s | |
nginx.org/proxy-read-timeout | proxy-read-timeout | Sets the value of the proxy_read_timeout and grpc_read_timeout directive. | 60s | |
nginx.org/proxy-send-timeout | proxy-send-timeout | Sets the value of the proxy_send_timeout and grpc_send_timeout directive. | 60s | |
nginx.org/client-max-body-size | client-max-body-size | Sets the value of the client_max_body_size directive. | 1m | |
nginx.org/proxy-buffering | proxy-buffering | Enables or disables buffering of responses from the proxied server. | True | |
nginx.org/proxy-buffers | proxy-buffers | Sets the value of the proxy_buffers directive. | Depends on the platform. | |
nginx.org/proxy-buffer-size | proxy-buffer-size | Sets the value of the proxy_buffer_size and grpc_buffer_size directives. | Depends on the platform. | |
nginx.org/proxy-max-temp-file-size | proxy-max-temp-file-size | Sets the value of the proxy_max_temp_file_size directive. | 1024m | |
nginx.org/server-tokens | server-tokens | Enables or disables the server_tokens directive. Additionally, with the NGINX Plus, you can specify a custom string value, including the empty string value, which disables the emission of the “Server” field. | True |
3.2.1.4. URI/Header
Annotation | ConfigMap Key | Description | Default | Example |
---|---|---|---|---|
nginx.org/proxy-hide-headers | proxy-hide-headers | Sets the value of one or more proxy_hide_header directives. Example: “nginx.org/proxy-hide-headers”: “header-a,header-b” | N/A | |
nginx.org/proxy-pass-headers | proxy-pass-headers | Sets the value of one or more proxy_pass_header directives. Example: “nginx.org/proxy-pass-headers”: “header-a,header-b” | N/A | |
nginx.org/rewrites | N/A | Configures URI rewriting. | N/A | Rewrites Support |
3.2.1.5. Auth / TLS
Annotation | ConfigMap Key | Description | Default |
---|---|---|---|
nginx.org/redirect-to-https | redirect-to-https | Sets the 301 redirect rule based on the value of the http_x_forwarded_proto header on the server block to force incoming traffic to be over HTTPS. Useful when terminating SSL in a load balancer in front of the Ingress Controller — see 115 | False |
ingress.kubernetes.io/ssl-redirect | ssl-redirect | Sets an unconditional 301 redirect rule for all incoming HTTP traffic to force incoming traffic over HTTPS. | True |
nginx.org/hsts | hsts | Enables HTTP Strict Transport Security (HSTS) \ : the HSTS header is added to the responses from backends. The preload directive is included in the header. | False |
nginx.org/hsts-max-age | hsts-max-age | Sets the value of the max-age directive of the HSTS header. | 2592000 (1 month) |
nginx.org/hsts-include-subdomains | hsts-include-subdomains | Adds the includeSubDomains directive to the HSTS header. | False |
nginx.org/hsts-behind-proxy | hsts-behind-proxy | Enables HSTS based on the value of the http_x_forwarded_proto request header. Should only be used when TLS termination is configured in a load balancer (proxy) in front of the Ingress Controller. Note: to control redirection from HTTP to HTTPS configure the nginx.org/redirect-to-https annotation. | False |
3.2.1.6. upstream
Annotation | ConfigMap Key | Description | Default | Example |
---|---|---|---|---|
nginx.org/lb-method | lb-method | Sets the load balancing method. To use the round-robin method, specify “round_robin”. | “random two least_conn” | |
nginx.org/ssl-services | N/A | Enables HTTPS or gRPC over SSL when connecting to the endpoints of services. | N/A | SSL Services Support |
nginx.org/grpc-services | N/A | Enables gRPC for services. Note: requires HTTP/2 (see http2 ConfigMap key); only works for Ingresses with TLS termination enabled. | N/A | GRPC Services Support |
nginx.org/websocket-services | N/A | Enables WebSocket for services. | N/A | WebSocket support |
nginx.org/max-fails | max-fails | Sets the value of the max_fails parameter of the server directive. | 1 | |
nginx.org/max-conns | N\A | Sets the value of the max_conns parameter of the server directive. | 0 | |
nginx.org/upstream-zone-size | upstream-zone-size | Sets the size of the shared memory zone for upstreams. For NGINX, the special value 0 disables the shared memory zones. For NGINX Plus, shared memory zones are required and cannot be disabled. The special value 0 will be ignored. | 256K | |
nginx.org/fail-timeout | fail-timeout | Sets the value of the fail_timeout parameter of the server directive. | 10s | |
nginx.org/keepalive | keepalive | Sets the value of the keepalive directive. Note that proxy_set_header Connection “”; is added to the generated configuration when the value > 0. | 0 |
3.2.1.7. sinppets
Annotation | ConfigMap Key | Description | Default |
---|---|---|---|
nginx.org/location-snippets | location-snippets | Sets a custom snippet in location context. | N/A |
nginx.org/server-snippets | server-snippets | Sets a custom snippet in server context. | N/A |
3.2.3. 案例
3.2.3.1. 简单demo
- 部署dashboard:参考官方文档
- 通常需要使用
kubectl proxy
才能访问,为了方便使用ingress暴露dashboard服务 ```yaml
kind: Service apiVersion: v1 metadata: labels: k8s-app: kubernetes-dashboard name: kubernetes-dashboard namespace: kubernetes-dashboard spec: ports:
- name: https
port: 8443
targetPort: 8443
selector: k8s-app: kubernetes-dashboard
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: dashboard namespace: kubernetes-dashboard annotations:
# 从nginx访问后端的svc,采用 https 协议
nginx.org/ssl-services: kubernetes-dashboard
spec: ingressClassName: nginx rules:
- host: dashboard.huanle.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: kubernetes-dashboard port: name: https
没指定 secretName时使用默认泛域名证书,通过IC命令行参数 -wildcard-tls-secret 指定
指定 tls 后,http协议会被重定向为https: return 301 https://$host:443$request_uri;
tls:
- path: /
pathType: Prefix
backend:
service:
- hosts:
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: jenkins-default namespace: devops spec: storageClassName: managed-nfs-storage accessModes:
- ReadWriteMany
resources: requests:
storage: 5Gi
apiVersion: apps/v1 kind: Deployment metadata: name: jenkins-default namespace: devops spec: replicas: 1 selector: matchLabels: app: jenkins instance: default template: metadata: labels: app: jenkins instance: default spec: containers:
- name: jenkins-server
image: jenkins/jenkins:2.344
ports:
- name: http-port
containerPort: 8080
- name: jnlp-port
containerPort: 50000
volumeMounts:
- name: jenkins-home
mountPath: /var/jenkins_home
resources:
limits:
cpu: 2048m
memory: 2048Mi
requests:
cpu: 100m
memory: 512Mi
volumes:
- name: jenkins-home
persistentVolumeClaim:
claimName: jenkins-default
apiVersion: v1 kind: Service metadata: name: jenkins-default-web namespace: devops spec: type: ClusterIP selector: app: jenkins instance: default ports:
- port: 8080 targetPort: http-port
apiVersion: v1 kind: Service metadata: name: jenkins-default-jnlp namespace: devops spec: type: ClusterIP selector: app: jenkins instance: default ports:
- port: 50000 targetPort: jnlp-port
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: jenkins-default namespace: devops annotations: nginx.org/client-max-body-size: 64m nginx.org/keepalive: “4” spec: ingressClassName: nginx rules:
- host: jenkins-default.huanle.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
tls:name: jenkins-default-web port: number: 8080
- path: /
pathType: Prefix
backend:
service:
- hosts:
- jenkins-default.huanle.com
```
3.2.3.4. 更多案例
官方提供了很多配置示例,重点关注 Rewrite,Websocket,GRPC的示例。3.3. CRD配置
3.3.1. TransportServer
TransportServer 是用来定义TCP/UDP层的转发规则,一般情况也用不上。如果是给集群内部的服务使用,那么为啥直接走SVC?
如果暴露给集群外部,那么我们为啥不用NodePort?
如果必须要走IC,那么我们为了更好的暴露端口,那么是不是使用两台专用节点部署IC,并直接使用宿主机的网络名称空间?
如果需要学习,可以参考官方文档3.3.2. VirtualServer & VirtualServerRoute
同样,我个人人为意义不大,与其学习更复杂的定义格式,不如直接使用 ingress + sinppets
- jenkins-default.huanle.com
```
4. 运维
4.1. 日志
nginx 的访问日志对部分服务而言很重要,甚至可以考虑接入到日志中心,在接入前需要考虑以下事项:
- 日志格式如何定义?可以参考 2.2.2 中 common/nginx-config.yaml 配置
- 访问日志如何区分?默认标准容器日志中混杂了error日志,access日志,IC日志,采集端需要更加定义的日志格式进行区分
- 访问日志如何落盘?默认错误日志写到
sdterr
,访问日志写到stdout
。如果要落盘就得挂盘,并写入日志 如何透传客户端IP?如果IC前端有LB,那么如何获取客户端真实IP?2.2.2 中 common/nginx-config.yaml 中proxy-protocol是一种解决方案。
4.2. 状态页
默认情况下,IC是开启状态页的,如果临时通过状态页查看当前nginx状态,可以将 nginx pod 的8080端口映射出来:
[root@duduniao jenkins]# kubectl port-forward -n nginx-ingress nginx-ingress-v99fw 8080:8080 [root@duduniao deploy-cluster]# curl 127.0.0.1:8080/stub_status Active connections: 1 server accepts handled requests 28 28 630 Reading: 0 Writing: 1 Waiting: 0
4.3. 监控
IC使用
-enable-prometheus-metrics
暴露prometheus格式的指标,默认metrics 接口为http://<pod_ip>:9113/metrics
,具体可以参考readme中指标含义描述。
Grafana 示例可以参考官方的 dashboard.json 文件
通常情况下,prometheus采集pod指标有两种自动发现方案:promethues通过注解自动添加pod到监控列表。在pod的annotations中定义,比如 2.2.3. 的 daemon-set/nginx-ingress.yaml 中注解部分
- prometheus通过ServiceMonitor添加pod到监控列表。自定义资源ServiceMonitor关联到service完成自动发现Endpoint中Pod列表