K8s学习笔记——5.ingress
半野

Ingress

Ingress 可以说是 Service 的 “Service”。

Service 是工作在第四层的负载均衡对象,流量管理比较简单,只能对TCP、UDP流量进行转发与控制。在现实情况下,我们更多的可能是需要在第七层对流量进行控制,例如根据url的Path,分发到不同的业务、服务,这种情况下,直接使用 Service 就力不能及了,所以 K8s 就在 Service 之上又提出了一个新的概念:Ingress。

Ingress 是 K8s 集群中流量的总入口,负责管理集群中所有的南北向流量(南北向流量与东西向流量:网络中的东西向和南北向是什么意思呀?有什么区别? - 知乎 (zhihu.com)),相较于直接将 Service 向集群外暴露,使用 Ingress 是一个更加合适的做法。

Ingress的示例如下:

1
`apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: ngx-ingress spec: ingressClassName: nginx rules: - host: abc.com http: paths: - path: /pages pathType: Exact backend: service: name: front-end-svc port: number: 80 status: loadBalancer: {} `

Ingress 的 yaml 模板,同样可以通过 K8s 自动生成:

1
`kubectl create ing ngx-ingress --class=nginx --rule="abc.com/pages=front-app-svc:80" --dry-run=client -o yaml `

–class=nginx 用于指定 Ingress 绑定到 Ingress Class(Ingress Class是什么,请往下看)。

–rule 用于指定流量的转发规则。

Ingress 的 yaml 描述得很清晰:

配置了一个规则(rules 的 size 为1),对于 abc.com 域名,将完整匹配(pathType: Exact) /pages (path)路径下的请求,转发到 front-end-svc Service 的 80 端口。

通过这个描述,我们可以看到,Ingress 与反向代理没什么区别。至于其中另外一个关键字段 ingressClassName,则是用来指定Ingress Class 的。

除了完整匹配,Ingress 的 pathType 也支持前缀匹配 Prefix。

2.Ingress Controller

在 Ingress 中,我们只是定义了流量转发的规则,如何使得规则生效,则还需要一个 Ingress Controller。

如果说 Ingress 是 Nginx 的 config 文件,那么 Ingress Controller 则是 Nginx。由于像 nginx 一样角色的反向代理太多了,例如 caddy、kong、haproxy 等,而且市面上不乏成熟度高、性能好的产品,所以这部分 K8s 并没有实现,而且由社区来驱动。使用时,需要使用方自行安装。

以 ingress-nginx-controller 为例,我们可以通过以下命令进行安装:

1
`kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.3.0/deploy/static/provider/baremetal/deploy.yaml `

这个 Ingress Controller 是由 K8s 社区维护的, yaml 是由 ingress-nginx-controller 官方提供的示例。此外,nginx 官方也有维护一个 nginx 的 Ingress Controller:https://github.com/nginxinc/kubernetes-ingress。

上述方式,是将 Ingress Controller 作为 Deployment 安装的。什么意思呢?Nginx 本身也是一个应用,我们在 K8s 集群中安装 ingress-nginx,自然也是要将其作为 Pod 的方式运行的。

Ingress Controller 的流量转发规则,是由某个具体的应用提供的,例如Nginx,我们完全可以将 Nginx 作为一个 Service 直接部署到K8s集群中,手动配置Nginx config文件来配置流量代理规则。事实上,Ingress最终实现的结果也是这样的,但是 Nginx config 中的配置,不需要用户手动配置了,它可以直接从 k8s api-server 获取。只要我们将 ingress-nginx 中 Service 的端口向集群外进行暴露,即可在外部访问到K8s集群中的资源:

imageimage

当然,我们现有的基础设施中,可能已经有很完善的Nginx集群,也可以将Nginx部署在K8s的外部。

安装 ingress-nginx 控制器后,K8s 会创建一个 ingress-nginx 的 namespace,并在这个 namespace 下创建一系列资源,如 ingress-nginx-controller Deployment、ingress-nginx-controller Service 等。使用官网提供的该 yaml 文件,创建的 ingress-nginx-controller Service 的 type 是 NodePort,但是并没有指定本地的 NodePort,我们可以对其进行修改,否则K8s是使用一个随机端口。具体修改的位置在 334 行的Servic 定义处(ingress-nginx controller v1.3)。

3.Ingress Class

有了流量代理规则(Ingress )和流量代理规则控制器(Ingress Controller),我们依然还不能对集群内的流量进行比较好的管控,因为对于大型公司来说,会存在有很多 Ingress 规则,都使用同一个Ingress,必然会难以管理,所以 K8s 提供了一个 Ingress Class 对象,用以对 Ingress 进行分类和管理。

Ingress Class 处于 Ingress Controller 和 Ingress 之间,是流量规则和控制器的协调人,Ingress Controller 通过绑定 Ingress Class 间接持有 Ingress ,而 Ingress 通过绑定 Class 使得 Ingress Controller 知晓流量规则,这样控制器就和流量规则就不存在强绑定,用户也可以转向管理 Ingress Class,用它来定义不同的业务逻辑分组,简化 Ingress 规则的复杂度。

imageimage

Ingress Class 和 Ingress Controller 是怎么绑定的呢?以 ingress-nginx 默认的 yaml 文件为例,Ingress Controller 中通过 args 关联 Ingress Class;Ingress Class 中通过 spec.controller 绑定 Ingress Controller。

imageimage

Ingress Class 和 Ingress Controller 中都不涉及 Ingress 的信息,因此实现了 Ingress Controller 和 Ingress 解耦。

Ingress 关联到 Ingress Class,仅仅需要在 Ingress 中通过 spec.ingressClassName 绑定即可。

imageimage

4.实操

4.1.准备应用与Service

新建两个应用镜像,分别用于提供前端和后端服务,并为之创建 K8s Service:back-app-svc、front-app-svc。

image

back-app-svc 具备两个Pod,提供一个API接口,返回当前时间和一个static的Guid;

front-app-svc 是一个前端页面,并可以调用 back-app-svc,展示 back-app-svc 返回的内容。

4.2.创建Ingress Controller & Ingress Class

直接使用 ingress-nginx 提供的 deploy.yaml即可:

1
`kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.3.0/deploy/static/provider/baremetal/deploy.yaml `

deploy.yaml 中同时定义了一个 Ingress Class nginx,所以我们不必再单独创建一个 Ingress Class。

通过查看 ingress-nginx-controller Service,我们可以获取到 ingress-nginx-controller 对外暴露的端口。

1
`kk get svc -n ingress-nginx `

image

注意,由于GFW的问题,可能会遇到Github、镜像等无法访问的问题。

4.3.创建Ingress

使用前面所述的命令,创建一个 Ingress 的 yaml 模板:

1
`$ kubectl create ing ngx-ingress --class=nginx --rule="abc.com/pages=front-app-svc:80" --dry-run=client -o yaml `

然后,对其进行修改,修改后如下:

1
`apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: ngx-ingress spec: ingressClassName: nginx rules: - host: abc.com http: paths: - path: /pages/ pathType: Exact backend: service: name: front-app-svc port: number: 80 - path: /api pathType: Prefix backend: service: name: back-app-svc port: number: 80 `

然后,我们使用 kubectl apply 命令,即可创建一个 Ingress。如果创建失败,可能是由于Ingress Controller尚未完全创建成功。

现在 Ingress、Ingress Class、Ingress Controller都已经创建完毕,可以在应用中使用了。

4.4.访问应用

在WSL中,我们通过curl访问 abc.com 这个域名,可以发现终端上按照预期输出了back-app-svc、front-app-svc的内容。

1
`curl --resolve abc.com:30080:127.0.0.1 abc.com:30080/api/guid curl --resolve abc.com:30080:127.0.0.1 abc.com:30080/pages/ `

image

在WSL中,通过ifconfig拿到WSL的IP地址为:172.19.190.93

imageimage

在物理机上,我们编辑”C:\Windows\System32\drivers\etc\hosts”,添加一条DNS记录:

1
`172.19.190.93 abc.com `

现在,通过浏览器也可以访问到我们的服务了,而且还具备负载均衡的能力:

image

imageimage

由 Hexo 驱动 & 主题 Keep
总字数 105.7k 访客数 访问量