NGINX Ingress官方的YAML文件是以Deployment方式运行的,这样就会有坑,Pod会到处跑,即使加上nodeSecetor,也是会有可能一个主机跑两个,而另外的主机不跑。实际需求中,我们希望在固定的主机上运行它,再在它的前端加一层代理,将外部流量引入进来。

示意拓朴图:

1
2
3
4
         |----K8S-Master03
 ---->SLB|----K8S-Master02    
         |----K8S-Master01

准备工作

1
2
3
4
5
6
7
8
# 打上label,打上label后的节点将会运行ingress
kubectl label node NodeName ingress=true

# 获取部署YAML,master分支一般是最新的稳定版,确认是否支持当前的K8S版本
# 如果不支持,就去下release对应版本
https://github.com/kubernetes/ingress-nginx/blob/master/deploy/static/provider/baremetal/deploy.yaml

# 将以上网页原原始内容下载至本地

修改deploy.yaml文件

增加自定义的配置内容

完整的参数参考: 官网

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
data:
  # 可选增加以下,将日志发送至Rsyslog服务
  disable-access-log: "false"
  service-upstream: "true"
  enable-underscores-in-headers: "true"
  # 启用gzip,默认为false
  use-gzip: "true"
  gzip-level: "2"
  # 以下是默认,可以不指定
  gzip-types: "application/atom+xml application/javascript application/x-javascript application/json application/rss+xml application/vnd.ms-fontobject application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/svg+xml image/x-icon text/css text/plain text/x-component"
  worker-cpu-affinity: "auto"
  proxy-body-size: "500m"
  worker-cpu-affinity: "auto"
  # RealIP
  enable-real-ip: "true"
  compute-full-forwarded-for: "true"
  forwarded-for-header: "X-Forwarded-For"
  use-forwarded-headers: "true"
  # Raw/Plaintext UDP
  access-log-path: "syslog:server=128.0.255.10:514"
  log-format-upstream: '{"time_str": "$time_iso8601",
                       "time_msec": $msec,
                       "remote_addr": "$proxy_protocol_addr",
                       "x-forward-for": "$http_x_forwarded_for",
                       "request_time": $request_time,
                       "upstream_response_time": $upstream_response_time,
                       "upstream_status": $upstream_status,
                       "status": $status,
                       "hostname": "$host",
                       "path": "$uri",
                       "namespace": "$namespace",
                       "service_name": "$service_name",
                       "upstream_addr": "$upstream_addr"}'

Deployment修改为DaemonSet

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# 约306行
...
kind: DaemonSet
  ....
  #约359行, 虽然加了TZ=Asia/Shanghai,但系统时间还是UTC时间。日志时间改成当前时区时间
  env:
  - name: POD_NAME
    value: ingress-nginx
  - name: POD_NAMESPACE
    value: ingress-nginx 
  - name: TZ
    value: Asia/Shanghai

ServiceType修改成NodePort

1
2
3
...
type: NodePort
...

增加节点容忍

不然Master节点不会被调度

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# 约401行
...
serviceAccountName: ingress-nginx
# 加入
nodeSelector:
  ingress: "true"
tolerations:
  - key: "node-role.kubernetes.io/master"
    operator: "Equal"
    value: ""
    effect: "NoSchedule"
...

应用

1
2
3
4
5
kubectl apply -f deploy.yaml

# 验证
kubectl get ds -n ingress-nginx
kubectl get pod -n ingress-nginx -o wide

其他说明

获取真实用户IP

如果后端应用需要获取真实IP地址的需求,则需要在应用中获取X-Original-Forwarded-For值,如果在Ingress前面还加了一层NGINX, 则NGINX则要加上如下代码:

1
2
3
4
5
6
7
8
server {
  ...
  proxy_set_header X-Forwarded-For $real_ip;
  ...
  location / {
    ...
  }
}

手工创建Ingress

Ingress NGINX发现v1.1.0之后,创建时一定要指定IngressClass,虽然会创建成功,但实际不创建规则。 默认会创建名为nginxIngressClass,新创建的Ingress指定它就可好了

1
2
3
4
5
# 获取当前的IngressClass,该属性没有namespaces的概念
kubectl get IngressClass  

# 手工创建一个,后续可以导出为YAML弄成模板
kubectl create ing IngressName --calss=nginx --rule="www.example.com/svcName:Port"

指定默认的IngressClass

如果不想每次创建指定IngressClass,可以指定默认的IngressClass

1
2
3
4
kubectl edit IngressClass

# metadata.annotations: 下面增加
ingressclass.kubernetes.io/is-default-class: "true"