认识 Ingress-nginx

我们先来看一下官网对于 ingress 的解释:

Ingress 提供从集群外部到集群内服务的 HTTP 和 HTTPS 路由。流量路由由 Ingress 资源所定义的规则来控制。下面是 Ingress 的一个简单示例,可将所有流量都发送到同一 Service:

ingress-diagram

通俗的理解,我们可以将 ingress 理解为 cloud 项目里的网关,通过判断请求信息、请求路径后,转发到对应的服务内。

常见的 ingress 控制器有 ingress-nginx、Traefik、HAProxy Ingress 等等,但使用最多的还是 nginx,本文也会以 ingress-nginx 来做演示

PS:ingress-nginx 是 kubernetes 社区维护的,而 kubernetes-ingress 是 nginx 官方维护的,本文使用前者!

minikube

安装 Ingress-nginx 控制器

运行下面的命令进行安装

1
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/cloud/deploy.yaml

开启 ingress

1
minikube addons enable ingress

通过命令 kubectl get pods -n ingress-nginx 查看,展示下面的 3 个 Pod 表示成功。

image-20240326151728730

为什么 admission-create 和 admission-path 的状态为 Completed?

首先我们需要知道这两个 Pods 的作用:

nginx-admission-create:用来创建一个或多个 admission 配置,以及验证并更新 kubernetes 资源

ingress-nginx-admission-patch:负责更新已存在的 admission 配置。

这两个 Pod 的任务结束后就会进入 Completed 状态。此时任务完成,Pods 结束生命,标记为 Completed 状态

controller 是做什么的?

ingress-nginx-controller:ingress 控制器实际运行的地方,具体的作用有如下 2 点。1:监听 ingress 资源,当检测到新的 ingress 资源或现有的 ingress 资源发生变动时,会同步更新内部配置;2:路由请求,会对请求进行对应的校验、然后转发到对应的 Service 里

使用 Ingress-nginx 进行请求转发

因为 ingress 要将请求转发到 Service,所以在使用 ingress 进行路由时,首先需要确保已经创建了对应 Pods 和 Service 并且正常运行,已经正常创建的可以跳转到第 3 步直接创建 ingress

  1. 创建 Deployment

    创建 Deployment,副本片为 2,使用我自己的一个 boot 项目

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    apiVersion: apps/v1
    kind: Deployment
    metadata:
    name: boot-deployment
    spec:
    replicas: 2
    selector:
    matchLabels:
    app: sora-boot
    template:
    metadata:
    labels:
    app: sora-boot
    spec:
    containers:
    - name: sora
    image: sora33/k8s:v2.0

    执行命令 kubectl apply -f ${文件名) 来完成 Deployment 的创建

  2. 创建 Service

    定义 Service 的名字,绑定标签为 sora-boot 的 Pods,同时映射端口信息,配置负载均衡方式

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    apiVersion: v1
    kind: Service
    metadata:
    name: sora-boot-service
    spec:
    selector:
    app: sora-boot
    ports:
    - protocol: TCP
    name : sora-boot
    port: 1234
    targetPort: 1234
    type: LoadBalancer

    继续创建一个 Service

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    apiVersion: v1
    kind: Service
    metadata:
    name: sora-boot-service2
    spec:
    selector:
    app: sora-boot
    ports:
    - protocol: TCP
    name : sora-boot
    port: 1234
    targetPort: 1234
    type: LoadBalancer

    执行命令 kubectl apply -f ${文件名) 来完成 Service 的创建

  3. 创建 Ingress

    metadata:定义 ingress 的名字,同时通过 nginx.ingress.kubernetes.io/rewrite-target 重写路径,将 $1($1 是正则表达式的捕获组引用,值对应 path 的 (.*))作为路径转发到后端。例如现在我的请求路径是 /boot/async/work1,那么会将该路径重写为 /async/work1,同时转发到名为 sora-boot-service 的 Service 里。

    spec:指定 ingressClassName 控制器为 nginx,下面是 rules,也就是路由规则列表。

    ​ host:指定域名,只有匹配该值时,才进入规则。值是域名,所以我们需要提前设置好一个测试域名,修改我们本地的 hosts 文件就可以,具体路径为 /etc/hosts

    ​ 如下,添加一个测试域名,并指向本机(注意:这里 linux 和 mac 不一样,linux 需要设置为 minikube 的 ip!!!mac 直接设置为 127.0.0.1)

    image-20240326160015312

    image-20240326155247476

    ​ path:匹配路径,下图为匹配到以 boot 开头的请求转发到 sora-boot-service 服务,boot2 开头的请求转发到 sora-boot-service2 服务,并指定对应的端口号

    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
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    name: sora-ingress
    annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$1
    spec:
    ingressClassName: nginx
    rules:
    - host: www.test33.com
    http:
    paths:
    - path: /boot/(.*)
    pathType: Prefix
    backend:
    service:
    name: sora-boot-service
    port:
    number: 1234
    - path: /boot2/(.*)
    pathType: Prefix
    backend:
    service:
    name: sora-boot-service2
    port:
    number: 1234

    执行命令 kubectl apply -f ${文件名) 来完成 ingress 的创建

  4. 查看 ingress

创建完成后,我们来查看 ingress 的信息,使用下面的命令启动 K8s 控制台

1
minikube dashboard

我们可以看到 ingress 的 class 名字,以及规则对应的路径,匹配类型以及路由到的具体服务

image-20240326155420684

注意:下面的部分,mac 因为网络的原因,需要额外开启一个终端页面启用隧道(注意输入密码)

1
minikube tunnel

image-20240326160244570

最后我们来通过 ingress 访问项目,请求前缀分别为 boot 和 boot2,这里因为两个 Service 实际指向的都是标签为 sora-boot 的 Pods,所以输出会一样,可以自己再创建一个不同的 Pod 来测试

image-20240326155549994

Kuboard

通过 Kuboard 可视化集群管理工具,我们可以通过页面创建并更新容器。通过 Kuboard 创建之前我希望可以看一下上面 minikube 的流程,因为实际上底层是一样的,并且上面也解答了很多原理性的东西~

安装 Ingress-nginx 控制器

集群管理菜单中选择网络,点击安装、输入一个 Ingress 名称,副本数可以自己按需求设定。

image-20240403140932907

点击我们创建好的 Ingress 名称进入管理页面,可以看到目前 Pods 都已就绪

image-20240403141120303

这里注意看顶部,会提示我们配置 2 个端口转发,这里很重要,如果不配置,Ingress 会无法使用!

image-20240403141158738

这里需要通过 nginx 实现,所以需要下载一个 nginx。nginx 的下载可参考我之前的一个文章:nginx 下载 (这里我们安装在任意一个子节点上即可!!!不能安装在 master 节点!)

安装完成后修改 /usr/local/nginx/conf 下的 nginx.conf 文件。需要在 http 模块下加入 2 个 server,注意默认会有一个监听 80 的端口,我们只需要在此基础上改就可以,注意将对应的 80 和 443 改为 Ingress 页面给你提示的端口号。然后进入 /usr/local/nginx.sbin 通过 ./nginx 启动 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
server {
listen 80;
server_name localhost;

#charset koi8-r;

#access_log logs/host.access.log main;

location / {
# root html;
# index index.html index.htm;
proxy_pass http://localhost:30668;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
server {
listen 443;
server_name localhost;

#charset koi8-r;

#access_log logs/host.access.log main;

location / {
# root html;
# index index.html index.htm;
proxy_pass http://localhost:32403;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}

使用 Ingress-nginx 进行请求转发

创建两个负载

因为我们需要测试 Ingress 的流量转发,所以需要 2 个完全不同的容器。如图,我用了一个 nginx 容器和一个 portainer 容器来测试

image-20240403142639793

如果刚开始用 Kuboard 不知道如何创建的话,这里我创建一个 Deployment 来演示一下:

选择一个命名空间,创建工作负载,类型从 DeploymentStatefulSet 选择一个就可以。一般无状态应用选择前者,有状态则选择后者。输入负载名称,调整副本数。

image-20240403142928541

在容器信息页面输入镜像名,注意这里是镜像名!!!选择策略并映射端口号,将容器的 80 映射到宿主机的 32002 端口上。宿主机的端口范围 30000-32767

image-20240403143054130

完成后点击上方保存,接着同样创建第二个负载,可以使用 portainer/portainer 这个镜像,这是一个监控 docker 的开源工具

开启服务

进入工作负载,点击编辑,我们勾选服务,如下配置服务的端口为 80,对应容器的 80 端口,同时工作端口为 30883。

image-20240403143809543

之后同样为另一个负载也开启服务

开启路由

在开启路由前,首先我们需要配置自己的域名,这里我用 www.test33.com 当然你也可以自定义名字

1
2
# 编辑hosts
vim /etc/hosts

image-20240403145535170

回到之前开启服务的页面,继续勾选服务下方的路由,配置如下,域名输入我们刚刚配置的域名,配置前缀为 /nginx 开头的请求,将其转发到 nginx 负载的 80 端口上

image-20240403145253190

之后同样为另一个负载也开启路由

访问测试

现在我们通过域名 + 前缀匹配的方式测试 Ingress 是否生效,如下图,都成功进入对应的主页

nginx:

image-20240403145730737

portainer:

image-20240403145821733