EKS使用Ingress+NLB对外暴露服务

一、为什么不想使用AWS的Ingress

公司k8s使用的是AWS的EKS,相应的Ingress等服务也是AWS经过修改的版本,使用Ingress + ALB方式对外暴露服务,由于AWS的ALB白名单只支持5个地址(Ingress一条规则配置的域名+白名单IP不得超过5个,虽然配置都在Ingress但实际操作的还是Ingress后端的ALB服务)。

这样,相当于1个域名最多只能配置4个白名单地址,奇怪的是AWS的负载均衡器居然不支持扩容白名单配额,这样的话就只能自己建一个了;于是打算向Ingress+NLB方案靠拢,因为自建Ingress它的白名单是写到nginx配置里的,这样只需要负载均衡器将客户端IP传过来就可以了。

下面就通过自建Ingress,我们一起来熟悉它的部署和使用。

二、K8s中对外暴露服务的方式

1.1、NodePort Service

NodePort Service 顾名思义,实质上就是通过在集群的每个 node 上暴露一个端口,然后将这个端口映射到某个具体的 service 来实现的,虽然每个 node 的端口有很多(0~65535),但是由于安全性和易用性(服务多了就乱了,还有端口冲突问题)实际使用可能并不多

1.2、LoadBlancer Service

LoadBlancer Service 是 kubernetes 深度结合云平台的一个组件;当使用 LoadBlancer Service 暴露服务时,实际上是通过向底层云平台申请创建一个负载均衡器来向外暴露服务;目前 LoadBlancer Service 支持的云平台已经相对完善,比如国外的 GCE、DigitalOcean,国内的 阿里云,私有云 Openstack 等等,由于 LoadBlancer Service 深度结合了云平台,所以只能在一些云平台上来使用

1.3、Ingress

Ingress 这个东西是 1.2 后才出现的,通过 Ingress 用户可以实现使用 nginx 等开源的反向代理负载均衡器实现对外暴露服务,以下详细说一下 Ingress,毕竟 traefik 用的就是 Ingress

使用 Ingress 时一般会有三个组件:

  • 反向代理负载均衡器
  • Ingress Controller
  • Ingress

1.3.1、反向代理负载均衡器

反向代理负载均衡器很简单,说白了就是 nginx、apache 什么的;在集群中反向代理负载均衡器可以自由部署,可以使用 Replication Controller、Deployment、DaemonSet 等等,不过个人喜欢以 DaemonSet 的方式部署,感觉比较方便

1.3.2、Ingress Controller

Ingress Controller 实质上可以理解为是个监视器,Ingress Controller 通过不断地跟 kubernetes API 打交道,实时的感知后端 service、pod 等变化,比如新增和减少 pod,service 增加与减少等;当得到这些变化信息后,Ingress Controller 再结合下文的 Ingress 生成配置,然后更新反向代理负载均衡器,并刷新其配置,达到服务发现的作用

1.3.3、Ingress

Ingress 简单理解就是个规则定义;比如说某个域名对应某个 service,即当某个域名的请求进来时转发给某个 service;这个规则将与 Ingress Controller 结合,然后 Ingress Controller 将其动态写入到负载均衡器配置中,从而实现整体的服务发现和负载均衡

有点懵逼,那就看图

三、Ingress当前的实现方式

图片1

Ingress的实现方式这么多,应该怎么选型呢?

别急,在选型前不妨先看看大姥对Ingress的性能测试:https://www.cnblogs.com/leozhanggg/p/13189173.html

这里我选择使用nginx-ingress,原因无它,性能非常接近原生nginx。

四、部署Ingress

Ingress GitHub地址:https://github.com/kubernetes/ingress-nginx/tree/nginx-0.30.0

选择最新的tag,当前使用的是0.30.0

4.1 部署deploy

克隆下来代码库后先切换到最新的tag,当前使用tag的是0.30.0

1
2
3
4
5
6
$ git clone https://github.com/kubernetes/ingress-nginx.git
$ cd ingress-nginx/
$ git checkout nginx-0.30.0
$ git branch
* (HEAD detached at nginx-0.30.0)
master

接下来部署deploy/static目录下所有的.yaml

1
2
3
4
$ cd deploy/static/
$ ls
configmap.yaml namespace.yaml rbac.yaml
mandatory.yaml provider/ with-rbac.yaml

configmap.yaml:存储配置信息,key/value值
namespace.yaml:建命名空间
mandatory.yaml:包含部署deploy相关所有资源(configmap.yaml,namespace.yaml,rbac.yaml,with-rbac.yaml)
rbac.yaml:rbac授权配置,创建Ingress需要使用的(ServiceAccount,ClusterRole,Role,RoleBinding,ClusterRoleBinding)
with-rbac.yaml:使用rbac授权的deploy配置,用于构建ingress-controller

4.2 部署service

创建service就要看你使用的是哪个云厂商了,我使用的AWS云,这里选择deploy/static/provider/aws/目录

1
2
3
4
$ cd deploy/static/provider/aws/
$ ls
patch-configmap-l4.yaml service-l4.yaml service-nlb.yaml
patch-configmap-l7.yaml service-l7.yaml

我使用的是NLB,所以这里使用service-nlb.yaml这个文件

1
$ kubectl apply -f service-nlb.yaml

service中的更多相关配置,可以参考:https://kubernetes.io/docs/concepts/services-networking/service/#ssl-support-on-aws

里面有AWS、阿里、腾讯、百度、Azure等云厂商提供的详细配置

自建集群则使用 deploy/static/provider/baremetal/service-nodeport.yaml 文件创建service

4.3 验证部署

部署完后,咱们来验证一下部署成果

查看deploy

1
2
3
$ kubectl get po -n ingress-nginx
NAME READY STATUS RESTARTS AGE
nginx-ingress-controller-7cccb55579-bxxbk 1/1 Running 0 28h

查看svc

1
2
3
$ kubectl get svc -n ingress-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx LoadBalancer 172.20.41.34 ***-**.elb.ap-southeast-2.amazonaws.com 80:32033/TCP,8443:30557/TCP 27h

访问nginx-ingress

service地址不能直接访问,我们可以随便进入到一个容器,然后在容器里访问

1
2
3
4
5
6
7
8
9
10
11
$ kubectl exec -it -n ingress-nginx nginx-ingress-controller-7cccb55579-bxxbk bash

bash-5.0$ curl 172.20.41.34
<html>
<head><title>404 Not Found</title></head>
<body>
<center><h1>404 Not Found</h1></center>
<hr><center>nginx/1.17.8</center>
</body>
</html>
bash-5.0$

返回404说明我们已经部署成功了

我这边是AWS环境,创建完以上资源会自动创建一个NLB并且跟svc中的ingress-nginx绑定。

五、对外暴露服务

一切都准备好后,我们来创建一个对外的服务进行测试

5.1 创建测试服务nginx

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
$ cat nginx.yaml

kind: Deployment
apiVersion: apps/v1
metadata:
name: nginx-deployment
namespace: ingress-nginx
labels:
app: nginx
annotations:
deployment.kubernetes.io/revision: '1'
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
creationTimestamp: null
labels:
app: nginx
spec:
containers:
- name: nginx
image: 'nginx:1.15.4'
ports:
- containerPort: 80
protocol: TCP
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
imagePullPolicy: IfNotPresent
restartPolicy: Always
terminationGracePeriodSeconds: 30
dnsPolicy: ClusterFirst
nodeSelector:
running_env: qa
securityContext: {}
schedulerName: default-scheduler
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 25%
maxSurge: 25%
revisionHistoryLimit: 10
progressDeadlineSeconds: 600
---
kind: Service
apiVersion: v1
metadata:
name: nginx-service
namespace: ingress-nginx
labels:
app: nginx
spec:
ports:
- protocol: TCP
port: 80
targetPort: 80
selector:
app: nginx
type: NodePort
sessionAffinity: None
externalTrafficPolicy: Cluster

$ kubectl apply -f nginx.yaml

5.2 创建ingress并对外暴露

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$ cat ingress-nginx_nginx.yaml

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: nginx-service.qa-01.memoirs.top
namespace: ingress-nginx
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/whitelist-source-range: '0.0.0.0/0' # 访问白名单
spec:
rules:
- host: nginx-service.qa-01.memoirs.top
http:
paths:
- backend:
serviceName: nginx-service
servicePort: 80

$ kubectl apply -f ingress-nginx_nginx.yaml

然后只需要将刚才的域名解析到之前创建的NLB上即可,如果用https访问只需要在NLB上绑定好域名证书然后将443端口和80端口一样转发到ingress-nginx的80端口就可以了。

5.3 访问服务

配置完后,我们来用域名访问一下刚才创建的nginx服务

图片1

-------------本文结束感谢您的阅读-------------