k8s进阶:Ingress-Nginx

Ingress-Nginx 和 Nginx-Ingress

Ingress-Nginx

是kubernetes社区基于nginx开发的ingress控制器

作为官方的默认控制器,享有最优的支持

补充了一组实现额外功能的lua插件

Github

说明文档

Nginx-ingress

nginx官方开发的ingress控制器

很高的稳定性和持续的向后兼容,没有任何第三方模块,消除了lua代码保证较高的速度

Github

说明文档

更多

本文说的是Ingress-nginx

Ingress-nginx

service提供四层基于tcp/ip的代理,负载均衡和转发,ingress则提供七层的代理,负载均衡和转发,请求进入kubernetes集群会首先通过ingress-controller,匹配配置的ingress路径规则,转发到具体的service,再转发到具体的pod上.

ingress和ingress-controller

ingress

是k8s的一种资源对象,通过http/https暴露集群内部service,给service提供外部URL,loadbalance或基于vhost的代理.

ingress-controller

并不是k8s自带的组件,ingress-controller是一个统称,有各种各样的controller,本文说的-ingress-nginx是kubernetes社区指定的控制器,所以支持也是最好.

不管那种ingress-controller,实现的机制基本一样,只是配置有区别.

一般来说,ingress-controller的形式是一个pod,里面跑daemon程序或反向代理程序.

  • daemon负责不断监控集群的变化,根据ingress生成配置并应到新配置到反向代理.

比如ingress-nginx就是动态生成nginx配置,动态生成upstream,并在需要的时候冲i性能加载应用新配置.

三种部署方式

1. Deployment+LoadBalance-svc

以deployment的方式部署controller,再跑LB类型的是svc,这种方式适合部署在公有云,或者paas平台(比如openstack).

一般来说,公有云会为LB类型的svc创建一个负载均衡器,还会绑定一个公网地址,只要解析域名到这个公网地址,就可以实现服务的对外暴露.

2. Deployment+NodePort-svc

同样deployment方式部署controller,但是svc采用NodePort,svc会在每个node上监听一个端口,此时需要在集群前部部署一个负载均衡器

实际上nodePort本身是一层转发,所以这种方式转发层数比其他方式都多,大流量访问时可能会产生性能问题

默认nodeport不能使用80/443,那么请求节点看上去就不太专业

3. DaemonSet+HostNetwork+NodeSelector

使用DaemonSet结合NodeSelecter部署controller,同时使用hostnetwork让controller共享宿主机的网络名称空间,此时直接使用宿主机的80/443就能访问服务,controller所在的宿主机就是流量入口.

这种方式链路最简单,少了一层nodeport的转发性能更好.

直接使用宿主机的网络命名空间,一个node只能部署一个controller.

生产中一般都会部署多台node作为controller,前面再加个负载均衡器.

部署

生产中常用的方式为DaemonSet+HostNetwork+NodeSelecter,本文也将以这种方式记录部署步骤.

关于版本

ingress-nginx: v1.0.0 支持k8s: v1.19+,本文也是使用该版本

k8s: v1.22+需要使用更高版本的ingress-nginx

下载yaml

1
wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.0.0/deploy/static/provider/baremetal/deploy.yaml

修改镜像文件

默认ingress-nginx的镜像使用k8s.gcr.io,由于总所周知的原因,国内大陆是下载不了的,所以需要替换docker-proxy的代理

  • controller就是控制器镜像.

    • controller有一个启动参数: –watch-ingress-without-class=true

      官方解释:

          有一些 Ingress 控制器不需要定义默认的 IngressClass。比如:Ingress-NGINX 控制器可以通过参数 –watch-ingress-without-class 来配置.不过仍然推荐设置默认的 IngressClass.

      (Ingress | Kubernetes)

      所以这里其实可以不用额外加这个参数,默认的就行.

  • 另外还有两个jobs:

    • 在ingress-nginx的配置清单中,ingress-nginx-admission-createingress-nginx-admission-patch 这两个Job是与admission webhook相关的。Admission webhooks 是 Kubernetes API server 的动态拦截器,它们在创建、修改或删除对象之前或之后运行。ingress-nginx 使用这些webhook来确保ingress 资源在被提交给API服务器之前满足特定的验证条件。

      ingress-nginx-admission-create

      这个 Job 负责创建一个admission webhook的证书和一个对应的 Kubernetes Secret。这些证书是用来加密admission webhook服务与Kubernetes API服务器之间传输的数据的。

      ingress-nginx-admission-patch

      而这个 Job 负责两件事:

      1. 将刚刚生成的证书更新到admission webhook的配置中。
      2. 更新ingress-nginx部署的配置,使得当API服务器调用admission webhook时,使用正确的证书进行通信。

      这两个Job确保了admission webhook 的安全交互,并且是自动化的,通常在你部署或升级ingress-nginx 时会一同执行。成功执行完这两个 Job 后,你的ingress-nginx controller 就能够安全有效地拦截和管理发送到 API 服务器的 ingress 资源请求了。

给node打label

1
kubectl label node <node-name> <key=value>

修改yaml

  1. deployment改为daemonset

  2. 添加hostnetwork: true

  3. 根据标签配置nodeSelector

参考:

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
apiVersion: apps/v1
kind: DaemonSet #修改
metadata:
labels:
helm.sh/chart: ingress-nginx-4.0.1
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/version: 1.0.0
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/component: controller
name: ingress-nginx-controller
namespace: ingress-nginx
spec:
selector:
matchLabels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/component: controller
revisionHistoryLimit: 10
minReadySeconds: 0
template:
metadata:
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/component: controller
spec:
dnsPolicy: ClusterFirst
containers:
- name: controller
image: willdockerhub/ingress-nginx-controller:v1.0.0
imagePullPolicy: IfNotPresent
lifecycle:
preStop:
exec:
command:
- /wait-shutdown
args:
- /nginx-ingress-controller
- --election-id=ingress-controller-leader
- --controller-class=k8s.io/ingress-nginx
- --configmap=$(POD_NAMESPACE)/ingress-nginx-controller
- --validating-webhook=:8443
- --validating-webhook-certificate=/usr/local/certificates/cert
- --validating-webhook-key=/usr/local/certificates/key
securityContext:
capabilities:
drop:
- ALL
add:
- NET_BIND_SERVICE
runAsUser: 101
allowPrivilegeEscalation: true
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: LD_PRELOAD
value: /usr/local/lib/libmimalloc.so
livenessProbe:
failureThreshold: 5
httpGet:
path: /healthz
port: 10254
scheme: HTTP
initialDelaySeconds: 10
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 1
readinessProbe:
failureThreshold: 3
httpGet:
path: /healthz
port: 10254
scheme: HTTP
initialDelaySeconds: 10
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 1
ports:
- name: http
containerPort: 80
protocol: TCP
- name: https
containerPort: 443
protocol: TCP
- name: webhook
containerPort: 8443
protocol: TCP
volumeMounts:
- name: webhook-cert
mountPath: /usr/local/certificates/
readOnly: true
resources:
requests:
cpu: 100m
memory: 90Mi
nodeSelector: #修改
ingress: nginx
hostNetwork: true #修改
serviceAccountName: ingress-nginx
terminationGracePeriodSeconds: 300
volumes:
- name: webhook-cert
secret:
secretName: ingress-nginx-admission

Apply

1
kubectl apply -f deploy.yaml

Check

1
kubectl get all -n ingress-nginx

部署pod和ingress验证

可以参考这个blog进行验证

echo-server

创建完后稍等片刻,ingress就会分配到指定node的ip,用任意一个node的ip和80端口就能访问到配置的echo-server.


k8s进阶:Ingress-Nginx
http://example.com/2023/05/21/k8s-ingress/
作者
Peter Pan
发布于
2023年5月21日
许可协议