Kubernetes外部服务管理Ingress介绍

前言

在 Kubernetes 集群中,管理外部服务的访问和流量路由至关重要。通过使用 Ingress 控制器,我们能够实现对外部服务的有效管理,配置灵活的路由规则,并实现负载均衡和流量控制。

目录

一、Ingress 介绍

1. Ingress 概述

2. 对外暴露几种方案(发布方式)

2.1 NodePort

2.2 LoadBalancer

2.3 externalIPs

2.4 Ingress

3. Ingress 组成

3.1 Ingress-nginx 资源规则

3.2 ingress-controller

4. Ingress 工作原理

5. ingress 暴露服务的方式

5.1 方式一:Deployment+LoadBalancer 模式的 Service

5.2 方式二:DaemonSet+HostNetwork+nodeSelector

5.3 方式三:Deployment+NodePort模式的Service

二、部署 nginx-ingress-controller

1. 方式二:DaemonSet+HostNetwork+nodeSelector

1.1 部署 ingress-controller pod 及相关资源

1.2 修改 ClusterRole 资源配置 

1.3 指定 nginx-ingress-controller 运行在 node02 节点

1.4 修改 Deployment 为 DaemonSet ,指定节点运行,并开启 hostNetwork 网络 

1.5 加载镜像

1.6 启动 nginx-ingress-controller

1.7 创建 ingress 规则

1.7.1 创建一个 deploy 和 svc

1.7.2 创建 ingress

1.8 测试访问

1.9 查看 nginx-ingress-controller

2. 方式三:Deployment+NodePort模式的Service

2.1 下载 nginx-ingress-controller 和 ingress-nginx 暴露端口配置文件

2.2 加载镜像

2.3 启动 nginx-ingress-controller

三、Ingress HTTP 代理访问

1. 创建 deployment、Service、Ingress Yaml 资源

2. 进入容器编辑页面内容

3. 访问页面

四、Ingress HTTP 代理访问多域名服务路由

五、Ingress  HTTPS 代理访问

1. 创建ssl证书

2. 创建 secret 资源进行存储

3. 创建 deployment、Service、Ingress Yaml 资源

4. 启动资源

5. 访问资源

六、Nginx 进行 BasicAuth

1. 生成用户密码认证文件,创建 secret 资源进行存储

2. 创建一个 Secret 对象

3. 创建 ingress 资源

4. 添加宿主机域名解析www.abc.com,访问测试

七、Nginx 重写 

1. metadata.annotations 配置说明

2. 示例 


一、Ingress 介绍

1. Ingress 概述

service 的作用体现在两个方面:

  • 对集群内部,它不断跟踪pod的变化,更新 endpoint 中对应 pod 的对象,提供了 ip 不断变化的 pod 的服务发现机制;
  • 对集群外部,他类似负载均衡器,可以在集群内外部对 pod 进行访问。

Ingress 是 Kubernetes 中用于管理对集群内服务的外部访问的 API 对象。它允许您将 HTTP 和 HTTPS 路由流量到集群中的服务,通过定义规则,Ingress 可以将传入的请求路由到适当的服务。 

2. 对外暴露几种方案(发布方式)

外部访问内部图示:

在 Kubernetes 中,Pod 的 IP 地址和 service 的 ClusterIP 仅可以在集群网络内部使用,对于集群外的应用是不可见的。为了使外部的应用能够访问集群内的服务,Kubernetes 目前提供了以下几种方案:

2.1 NodePort

将service暴露在节点网络上,NodePort背后就是Kube-Proxy,Kube-Proxy是沟通service网络、Pod网络和节点网络的桥梁。
测试环境使用还行,当有几十上百的服务在集群中运行时,NodePort的端口管理就是个灾难。因为每个端口只能是一种服务,端口范围只能是 30000-32767。

2.2 LoadBalancer

通过设置LoadBalancer映射到云服务商提供的LoadBalancer地址。这种用法仅用于在公有云服务提供商的云平台上设置 Service 的场景。受限于云平台,且通常在云平台部署LoadBalancer还需要额外的费用。
在service提交后,Kubernetes就会调用CloudProvider在公有云上为你创建一个负载均衡服务,并且把被代理的Pod的IP地址配置给负载均衡服务做后端。

2.3 externalIPs

service允许为其分配外部IP,如果外部IP路由到集群中一个或多个Node上,Service会被暴露给这些externalIPs。通过外部IP进入到集群的流量,将会被路由到Service的Endpoint上。

示例:

① 创建控制器定义容器,并对外暴露端口

[root@master01 ingress]# kubectl create deployment app01 --image=nginx:1.14 --replicas=1 --port=80
deployment.apps/app01 created
[root@master01 ingress]# kubectl get pod
NAME                     READY   STATUS    RESTARTS   AGE
app01-68d9b5486f-d6s4x   1/1     Running   0          3s
[root@master01 ingress]# kubectl expose deployment app01 --port=80 --target-port=80
service/app01 exposed

② 编辑 "app01" 的 Service 的配置文件 

[root@master01 ingress]# kubectl edit svc app01 
  externalIPs:
  - 192.168.190.88

③ 查看 Service 列表

[root@master01 ingress]# kubectl get svc
NAME               TYPE        CLUSTER-IP      EXTERNAL-IP      PORT(S)           AGE
app01              ClusterIP   10.96.82.195    192.168.190.88   80/TCP            8m43s

 ④ 访问页面

2.4 Ingress

只需一个或者少量的公网IP和LB,即可同时将多个HTTP服务暴露到外网,七层反向代理。
可以简单理解为service的service,它其实就是一组基于域名和URL路径,把用户的请求转发到一个或多个service的规则。

原始架构与 Ingress 对比:

原来ens33是service端去暴露端口的,安全性低、不易管理,会面临k8s端口不够用的问题。

NodePort 和 Ingress 是 Kubernetes 中用于公开服务的两种不同方式:

NodePort:

  • NodePort 允许从集群外部访问您的服务。它会在每个节点上打开一个端口,并将该端口映射到 Service 的端口上。这意味着可以通过节点的 IP 地址和 NodePort 来访问 Service。
  • 通常用于需要直接暴露到外部的服务,但不适合大规模使用,因为需要管理大量的端口映射。

Ingress:

  • Ingress 是一种对外暴露服务的高级方式,它允许您将 HTTP 和 HTTPS 路由流量到集群中的服务。通过定义规则,Ingress 可以将传入的请求路由到适当的服务,实现灵活的流量控制。
  • Ingress 需要配合 Ingress Controller 使用,通常基于反向代理实现。它提供了更复杂的路由、负载均衡和 SSL 终止等功能。

3. Ingress 组成

3.1 Ingress-nginx 资源规则

可以理解为 nginx 的配置文件。ingress是一个API对象,通过yaml文件来配置,ingress对象的作用是定义请求如何转发到service的规则,可以理解为配置模板。

ingress通过http或https暴露集群内部service,给service提供外部URL、负载均衡、SSL/TLS以及基于域名的反向代理。ingress要依靠 ingress-controller 来具体实现以上功能。

3.2 ingress-controller

可以当做反向代理或者说是转发器。ingress-controller是具体实现反向代理及负载均衡的程序,对ingress定义的规则进行解析,根据配置的规则来实现请求转发。

实际上负责实现 Ingress 规则并处理外部流量的组件。Ingress Controller 监视 Kubernetes API 中的 Ingress 资源变化,并根据这些资源的配置来配置后端负载均衡器、反向代理或其它网络设备,以实现外部访问服务的目的。

Ingress-Nginx github 地址:https://github.com/kubernetes/ingress-nginx
Ingress-Nginx 官方网站:https://kubernetes.github.io/ingress-nginx/

总结:

  • ingress-controller才是负责具体转发的组件,通过各种方式将它暴露在集群入口,外部对集群的请求流量会先到 ingress-controller;
  • 而ingress对象是用来告诉ingress-controller该如何转发请求,比如哪些域名、哪些URL要转发到哪些service等等。 

4. Ingress 工作原理

(1)ingress-controller通过和 kubernetes APIServer 交互,动态的去感知集群中ingress规则变化;
(2)然后读取它,按照自定义的规则,规则就是写明了哪个域名对应哪个service,生成一段nginx配置;
(3)再写到nginx-ingress-controller的pod里,这个ingress-controller的pod里运行着一个Nginx服务,控制器会把生成的 nginx配置写入 /etc/nginx.conf文件中;
(4)然后reload一下使配置生效。以此达到域名区分配置和动态更新的作用。 

5. ingress 暴露服务的方式

5.1 方式一:Deployment+LoadBalancer 模式的 Service

如果要把ingress部署在公有云,那用这种方式比较合适。用Deployment部署ingress-controller,创建一个 type为 LoadBalancer 的 service 关联这组 pod。大部分公有云,都会为 LoadBalancer 的 service 自动创建一个负载均衡器,通常还绑定了公网地址。 只要把域名解析指向该地址,就实现了集群服务的对外暴露。

5.2 方式二:DaemonSet+HostNetwork+nodeSelector

用DaemonSet结合nodeselector来部署ingress-controller到特定的node上,然后使用HostNetwork直接把该pod与宿主机node的网络打通,直接使用宿主机的80/433端口就能访问服务。这时,ingress-controller所在的node机器就很类似传统架构的边缘节点,比如机房入口的nginx服务器。该方式整个请求链路最简单,性能相对NodePort模式更好。缺点是由于直接利用宿主机节点的网络和端口,一个node只能部署一个ingress-controller pod。 比较适合大并发的生产环境使用。

5.3 方式三:Deployment+NodePort模式的Service

同样用deployment模式部署ingress-controller,并创建对应的service,但是type为NodePort。这样,ingress就会暴露在集群节点ip的特定端口上。由于nodeport暴露的端口是随机端口,一般会在前面再搭建一套负载均衡器来转发请求。该方式一般用于宿主机是相对固定的环境ip地址不变的场景。
NodePort方式暴露ingress虽然简单方便,但是NodePort多了一层NAT,在请求量级很大时可能对性能会有一定影响。

 

二、部署 nginx-ingress-controller

1. 方式二:DaemonSet+HostNetwork+nodeSelector

1.1 部署 ingress-controller pod 及相关资源

[root@master01 ~]# mkdir /opt/ingress;cd /opt/ingress
[root@master01 ingress]# ls
mandatory.yaml

官方下载地址:
wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.25.0/deploy/static/mandatory.yaml

上面可能无法下载,可用国内的 gitee
wget https://gitee.com/mirrors/ingress-nginx/raw/nginx-0.25.0/deploy/static/mandatory.yaml
wget https://gitee.com/mirrors/ingress-nginx/raw/nginx-0.30.0/deploy/static/mandatory.yaml

mandatory.yaml文件中包含了很多资源的创建,包括namespace、ConfigMap、role,ServiceAccount等等所有部署ingress-controller需要的资源。

1.2 修改 ClusterRole 资源配置 

[root@master01 ingress]# vim mandatory.yaml
 84   - apiGroups:
 85       - "extensions"
 86       - "networking.k8s.io"  #(0.25版本)增加networking.k8s.io Ingress资源的api 

100   - apiGroups:
101       - "extensions"
102       - "networking.k8s.io"  #(0.25版本)增加networking.k8s.io/v1 Ingress资源的api

1.3 指定 nginx-ingress-controller 运行在 node02 节点

采用方式二:DaemonSet+HostNetwork+nodeSelector

[root@master01 ingress]# kubectl label node node02 nj=zs

[root@master01 ingress]# kubectl get nodes --show-labels
NAME       STATUS     ROLES                  AGE   VERSION    LABELS
master01   Ready      control-plane,master   18d   v1.20.11   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=master01,kubernetes.io/os=linux,node-role.kubernetes.io/control-plane=,node-role.kubernetes.io/master=
node01     NotReady   <none>                 18d   v1.20.11   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,fql=a,kubernetes.io/arch=amd64,kubernetes.io/hostname=node01,kubernetes.io/os=linux
node02     NotReady   <none>                 18d   v1.20.11   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,fql=b,kubernetes.io/arch=amd64,kubernetes.io/hostname=node02,kubernetes.io/os=linux,nj=zs

1.4 修改 Deployment 为 DaemonSet ,指定节点运行,并开启 hostNetwork 网络 

[root@master01 ingress]# vim mandatory.yaml
191 kind: DaemonSet           # 修改 kind
199  # replicas: 1            # 删除Replicas
212     spec:
213       hostNetwork: true   # 使用主机网络
214       nodeSelector:       # 选择节点运行
215         nj: zs

1.5 加载镜像

在所有 node02 节点上传 nginx-ingress-controller 镜像压缩包 ingree.contro.tar.gz 到 /opt/ingress 目录,并解压和加载镜像。

[root@node02 data]# ls
ingree.contro.tar.gz
[root@node02 data]# tar xf ingree.contro.tar.gz 
[root@node02 data]# ls
ingree.contro.tar  ingree.contro.tar.gz
[root@node02 data]# docker load -i ingree.contro.tar
Loaded image: quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.25.0

1.6 启动 nginx-ingress-controller

[root@master01 ingress]# kubectl apply -f mandatory.yaml 
namespace/ingress-nginx created
configmap/nginx-configuration created
configmap/tcp-services created
configmap/udp-services created
serviceaccount/nginx-ingress-serviceaccount created
Warning: rbac.authorization.k8s.io/v1beta1 ClusterRole is deprecated in v1.17+, unavailable in v1.22+; use rbac.authorization.k8s.io/v1 ClusterRole
clusterrole.rbac.authorization.k8s.io/nginx-ingress-clusterrole created
Warning: rbac.authorization.k8s.io/v1beta1 Role is deprecated in v1.17+, unavailable in v1.22+; use rbac.authorization.k8s.io/v1 Role
role.rbac.authorization.k8s.io/nginx-ingress-role created
Warning: rbac.authorization.k8s.io/v1beta1 RoleBinding is deprecated in v1.17+, unavailable in v1.22+; use rbac.authorization.k8s.io/v1 RoleBinding
rolebinding.rbac.authorization.k8s.io/nginx-ingress-role-nisa-binding created
Warning: rbac.authorization.k8s.io/v1beta1 ClusterRoleBinding is deprecated in v1.17+, unavailable in v1.22+; use rbac.authorization.k8s.io/v1 ClusterRoleBinding
clusterrolebinding.rbac.authorization.k8s.io/nginx-ingress-clusterrole-nisa-binding created
daemonset.apps/nginx-ingress-controller created

① nginx-ingress-controller 已经运行 node02 节点

[root@master01 ingress]# kubectl get pod -n ingress-nginx -o wide
NAME                             READY   STATUS    RESTARTS   AGE   IP                NODE     NOMINATED NODE   READINESS GATES
nginx-ingress-controller-c5xfb   1/1     Running   0          11s   192.168.190.102   node02   <none>           <none>
# 如果是0/1去node节点查看一下80端口是否有pod占用

[root@node02 data]# netstat -antulp | grep :80
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      129841/nginx: mast

[root@master01 ingress]# kubectl get cm,daemonset -n ingress-nginx -o wide
NAME                                        DATA   AGE
configmap/ingress-controller-leader-nginx   0      69s
configmap/nginx-configuration               0      73s
configmap/tcp-services                      0      73s
configmap/udp-services                      0      73s

NAME                                      DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE   CONTAINERS                 IMAGES                                                                  SELECTOR
daemonset.apps/nginx-ingress-controller   1         1         1       1            1           nj=zs           72s   nginx-ingress-controller   quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.25.0   app.kubernetes.io/name=ingress-nginx,app.kubernetes.io/part-of=ingress-nginx

② 到 node02 节点查看

[root@node02 data]# netstat -lntp | grep nginx
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      129841/nginx: maste 
tcp        0      0 0.0.0.0:8181            0.0.0.0:*               LISTEN      129841/nginx: maste 
tcp        0      0 0.0.0.0:443             0.0.0.0:*               LISTEN      129841/nginx: maste 
tcp6       0      0 :::10254                :::*                    LISTEN      129805/nginx-ingre

由于配置了 hostnetwork,nginx 已经在 node 主机本地监听 80/443/8181 端口。其中 8181 是 nginx-controller 默认配置的一个 default backend(Ingress 资源没有匹配的 rule 对象时,流量就会被导向这个 default backend)。

这样,只要访问 node 主机有公网 IP,就可以直接映射域名来对外网暴露服务了。如果要 nginx 高可用的话,可以在多个 node上部署,并在前面再搭建一套 LVS+keepalived 做负载均衡。

1.7 创建 ingress 规则

1.7.1 创建一个 deploy 和 svc
[root@master01 ingress]# kubectl create deployment myapp-demo01 --image=nginx:1.14 --replicas=3 --port=80
deployment.apps/myapp-demo01 created
[root@master01 ingress]# kubectl get pod
NAME                           READY   STATUS    RESTARTS   AGE
myapp-demo01-98f9b7bf7-kftxn   1/1     Running   0          2s
myapp-demo01-98f9b7bf7-sgzfn   1/1     Running   0          2s
myapp-demo01-98f9b7bf7-tsjvv   1/1     Running   0          2s

[root@master01 ingress]# kubectl delete svc --all

[root@master01 ingress]# kubectl expose deployment myapp-demo01 --port=80 --target-port=80
service/myapp-demo01 exposed
[root@master01 ingress]# kubectl get svc
NAME           TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
myapp-demo01   ClusterIP   10.96.227.130   <none>        80/TCP    3s

[root@master01 ingress]# curl 10.96.227.130 -I
HTTP/1.1 200 OK

到这里,四层转发已经没有问题了;接下来就是要把 ingress-controller 关联 service。即七层关联四层。

1.7.2 创建 ingress

方法一:(extensions/v1beta1 Ingress 在1.22版本即将弃用)

[root@master01 ingress]# vim ingress-app.yaml
apiVersion: extensions/v1beta1
kind: Ingress              # 这是一个 Ingress 资源,用于定义对集群中服务的外部访问规则
metadata:                  # 元数据
  name: nginx-app-ingress  # 资源的名称
spec:                      # 规定了 Ingress 资源的规格,包括访问规则
  rules:                   # 定义了访问规则,指定了如何路由到后端服务
  - host: www.aaa.com      # 指定了这条规则适用于主机 www.aaa.com
    http:                  # 定义了 HTTP 访问规则
      paths:               # 指定了路径匹配规则
      - path: /            # 表示所有以 / 开头的路径都会匹配到这个规则,这里是网站的根路径
        backend:           # 指定了后端服务的配置
          serviceName: myapp-demo01 # 后端服务的名称为 myapp-demo01,这是要将流量转发到的服务的名称
          servicePort: 80 

方法二:

[root@master01 ingress]# vim ingress-app01.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx-app-ingress
spec:
  rules:                   # 定义了访问规则,指定了如何路由到后端服务
  - host: www.aaa.com      # 指定了这条规则适用于主机 www.aaa.com
    http:                  # 定义了 HTTP 访问规则
      paths:               # 指定了路径匹配规则
      - path: /            # 网站路径,所有以 / 开头的路径都会匹配到这个规则
        pathType: Prefix   # 路径匹配,基于前缀;exect 完全匹配
        backend:           # 指定了后端服务的配置
          service:         # 定义了后端服务的名称和端口号
            name: myapp-demo01  # 后端服务的名称为 myapp-demo01,这是要将流量转发到的服务
            port:
              number: 80

启动 Ingress

[root@master01 ingress]# kubectl apply -f ingress-app.yaml
Warning: extensions/v1beta1 Ingress is deprecated in v1.14+, unavailable in v1.22+; use networking.k8s.io/v1 Ingress
ingress.extensions/nginx-app-ingress created
[root@master01 ingress]# kubectl get pods
NAME                           READY   STATUS    RESTARTS   AGE
myapp-demo01-98f9b7bf7-kftxn   1/1     Running   0          12m
myapp-demo01-98f9b7bf7-sgzfn   1/1     Running   0          12m
myapp-demo01-98f9b7bf7-tsjvv   1/1     Running   0          12m
[root@master01 ingress]# kubectl get ingress
NAME                CLASS    HOSTS         ADDRESS   PORTS   AGE
nginx-app-ingress   <none>   www.aaa.com             80      28s

1.8 测试访问

本地 host 添加域名解析:

[root@master01 ingress]# echo 192.168.190.102 www.aaa.com >> /etc/hosts

访问页面:

[root@master01 ingress]# curl www.aaa.com -I
HTTP/1.1 200 OK

1.9 查看 nginx-ingress-controller

[root@master01 ingress]# kubectl get pod -n ingress-nginx -o wide
NAME                             READY   STATUS    RESTARTS   AGE   IP                NODE     NOMINATED NODE   READINESS GATES
nginx-ingress-controller-c5xfb   1/1     Running   0          32m   192.168.190.102   node02   <none>           <none>

[root@master01 ingress]# kubectl exec -it nginx-ingress-controller-c5xfb -n ingress-nginx /bin/bash 
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
www-data@node02:/etc/nginx$ cat /etc/nginx/nginx.conf

2. 方式三:Deployment+NodePort模式的Service

2.1 下载 nginx-ingress-controller 和 ingress-nginx 暴露端口配置文件

[root@master01 ingress]# kubectl delete -f ingress-app.yaml
[root@master01 ingress]# kubectl delete -f mandatory.yaml 

[root@master01 ingress]# mkdir nodeport;cd nodeport

官方下载地址:
wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.30.0/deploy/static/mandatory.yaml
wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.30.0/deploy/static/provider/baremetal/service-nodeport.yaml

国内 gitee 资源地址:
wget https://gitee.com/mirrors/ingress-nginx/raw/nginx-0.30.0/deploy/static/mandatory.yaml
wget https://gitee.com/mirrors/ingress-nginx/raw/nginx-0.30.0/deploy/static/provider/baremetal/service-nodeport.yaml

[root@master01 nodeport]# rz -E
rz waiting to receive.
[root@master01 nodeport]# ls
ingress-nginx.yaml  mandatory.yaml  service-nodeport.yaml

2.2 加载镜像

在所有 node 节点上传镜像包 ingress-controller-0.30.0.tar 到 /opt/ingress-nodeport 目录,并加载镜像。

[root@node01 data]# rz -E
rz waiting to receive.
[root@node01 data]# ls
ingree.contro-0.30.0.tar.gz
[root@node01 data]# tar xf ingree.contro-0.30.0.tar.gz 
[root@node01 data]# ls
ingree.contro-0.30.0.tar  ingree.contro-0.30.0.tar.gz
[root@node01 data]# docker load -i ingree.contro-0.30.0.tar

[root@node02 data]# docker load -i ingree.contro-0.30.0.tar

2.3 启动 nginx-ingress-controller

[root@master01 nodeport]# kubectl apply -f mandatory.yaml
[root@master01 nodeport]# kubectl apply -f service-nodeport.yaml

[root@master01 nodeport]# kubectl get svc,pod -n ingress-nginx 
NAME                    TYPE       CLUSTER-IP    EXTERNAL-IP   PORT(S)                      AGE
service/ingress-nginx   NodePort   10.96.69.94   <none>        80:32269/TCP,443:32017/TCP   69s

NAME                                            READY   STATUS    RESTARTS   AGE
pod/nginx-ingress-controller-54b86f8f7b-2gm9j   1/1     Running   0          100s

如果K8S Pod 调度失败,在 kubectl describe pod资源时显示:
Warning  FailedScheduling  18s (x2 over 18s)  default-scheduler  0/2 nodes are available: 2 node(s) didn't match node selector

解决方案:

① 给需要调度的node加上对应标签
# 相对上面这个Yaml文件的例子
kubectl label nodes node_name kubernetes.io/os=linux

② 删除Yaml文件中的nodeSelector,如果对节点没有要求的话,直接删除节点选择器即可

三、Ingress HTTP 代理访问

Ingress HTTP代理访问通常用于在Kubernetes集群中管理入站和出站流量。通过设置Ingress代理,可以实现对集群中部署的服务进行访问控制、负载均衡、SSL终止等功能。 

1. 创建 deployment、Service、Ingress Yaml 资源

[root@master01 nodeport]# vim ingress-nginx.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-app
spec:
  replicas: 2
  selector:
    matchLabels:
      name: nginx
  template:
    metadata:
      labels:
        name: nginx
    spec:
      containers:
        - name: nginx
          image: nginx
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-svc
spec:
  ports:
    - port: 80
      targetPort: 80
      protocol: TCP
  selector:
    name: nginx
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx-test
spec:                        # 规定了Ingress资源的规格,包括访问规则
  rules:                     # 定义了访问规则,指定了如何路由到后端服务
  - host: www.aaa.com        # 指定了这条规则适用于主机 www.aaa.com
    http:                    # 定义了 HTTP 访问规则
      paths:                 # 指定了路径匹配规则
      - path: /              # 表示所有以 / 开头的路径都会匹配到这个规则
        pathType: Prefix     # 指定了路径匹配类型为前缀匹配
        backend:             # 指定了后端服务的配置
          service:           # 定义了后端服务的名称和端口号
            name: nginx-svc  # 指定了后端服务的名称为 nginx-svc
            port:
              number: 80

[root@master01 nodeport]# kubectl apply -f ingress-nginx.yaml
[root@master01 nodeport]# kubectl get pod,svc -o wide
NAME                               READY   STATUS    RESTARTS   AGE     IP             NODE     NOMINATED NODE   READINESS GATES
pod/nginx-app-57dd86f5cc-2qgww     1/1     Running   0          2m29s   10.244.1.225   node01   <none>           <none>
pod/nginx-app-57dd86f5cc-2rhh5     1/1     Running   0          2m29s   10.244.2.61    node02   <none>           <none>

NAME                   TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE     SELECTOR
service/nginx-svc      ClusterIP   10.96.206.53    <none>        80/TCP    4m26s   name=nginx

[root@master01 nodeport]# kubectl get ingress
NAME         CLASS    HOSTS         ADDRESS       PORTS   AGE
nginx-test   <none>   www.aaa.com   10.96.69.94   80      12m

2. 进入容器编辑页面内容

[root@master01 nodeport]# kubectl exec -it nginx-app-57dd86f5cc-2qgww sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
# echo "this is web1" > /usr/share/nginx/html/index.html
# exit
[root@master01 nodeport]# kubectl exec -it nginx-app-57dd86f5cc-2rhh5 sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
# echo "this is web2" > /usr/share/nginx/html/index.html

3. 访问页面

[root@master01 nodeport]# kubectl get endpoints nginx-svc
NAME        ENDPOINTS                        AGE
nginx-svc   10.244.1.225:80,10.244.2.61:80   24m

任意node地址添加域名解析:
[root@master01 nodeport]# curl www.aaa.com:32269
this is web1
[root@master01 nodeport]# curl www.aaa.com:32269
this is web2

四、Ingress HTTP 代理访问多域名服务路由

测试和实践在Kubernetes集群中使用Ingress资源实现同一端口但不同域名的服务路由和负载均衡。具体来说,通过创建两个不同的Service资源,并使用Ingress资源来将不同域名的流量路由到这两个Service上。

① 创建虚拟主机1资源

[root@master01 nodeport]# mkdir vhost
[root@master01 nodeport]# cd vhost/

[root@master01 vhost]# vim deployment1.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deployment1
spec:
  replicas: 1
  selector:
    matchLabels:
      name: nginx1
  template:
    metadata:
      labels:
        name: nginx1
    spec:
      containers:
        - name: nginx1
          image: soscscs/myapp:v1
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: svc-1
spec:
  ports:
    - port: 80
      targetPort: 80
      protocol: TCP
  selector:
    name: nginx1

② 启动主机1资源

[root@master01 vhost]# kubectl apply -f deployment1.yaml

③ 创建虚拟主机2资源

[root@master01 vhost]# vim deployment2.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deployment2
spec:
  replicas: 1
  selector:
    matchLabels:
      name: nginx2
  template:
    metadata:
      labels:
        name: nginx2
    spec:
      containers:
        - name: nginx2
          image: soscscs/myapp:v2
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: svc-2
spec:
  ports:
    - port: 80
      targetPort: 80
      protocol: TCP
  selector:
    name: nginx2

④ 启动主机2资源

[root@master01 vhost]# kubectl apply -f deployment2.yaml

[root@master01 vhost]# kubectl get pod
NAME                           READY   STATUS    RESTARTS   AGE
deployment1-c8d988f6c-hrk88    1/1     Running   0          69s
deployment2-5588d5cdcd-k6cx6   1/1     Running   0          38s

⑤ 创建ingress资源

[root@master01 vhost]# vim ingress-nginx.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress1
spec:                        # 规定了 Ingress 资源的规格,包括访问规则
  rules:                     # 定义了访问规则,指定了如何路由到后端服务
    - host: www.fff.com      # 指定了这条规则适用于主机 www.fff.com
      http:                  # 定义了 HTTP 访问规则
        paths:               # 指定了路径匹配规则
        - path: /            # 表示所有以 / 开头的路径都会匹配到这个规则
          pathType: Prefix   # 指定了路径匹配类型为前缀匹配
          backend:           # 指定了后端服务的配置
            service:         # 定义了后端服务的名称和端口号
              name: svc-1    # 指定了后端服务的名称为 svc-1
              port:
                number: 80
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress2
spec:
  rules:
    - host: www.qqq.com
      http:
        paths:
        - path: /
          pathType: Prefix
          backend:
            service: 
              name: svc-2
              port:
                number: 80

⑥ 查看svc、ingress信息

[root@master01 vhost]# kubectl get svc
NAME           TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
nginx-svc      ClusterIP   10.96.206.53    <none>        80/TCP    47m
svc-1          ClusterIP   10.96.43.42     <none>        80/TCP    5m35s
svc-2          ClusterIP   10.96.30.23     <none>        80/TCP    5m4s

[root@master01 vhost]# kubectl get svc -n ingress-nginx
NAME            TYPE       CLUSTER-IP    EXTERNAL-IP   PORT(S)                      AGE
ingress-nginx   NodePort   10.96.69.94   <none>        80:32269/TCP,443:32017/TCP   64m

[root@master01 vhost]# kubectl get ingress
NAME         CLASS    HOSTS         ADDRESS       PORTS   AGE
ingress1     <none>   www.fff.com   10.96.69.94   80      117s
ingress2     <none>   www.qqq.com   10.96.69.94   80      117s
nginx-test   <none>   www.aaa.com   10.96.69.94   80      49m

⑦ 进入容器编辑页面内容

[root@master01 vhost]# kubectl get pod
NAME                           READY   STATUS    RESTARTS   AGE
deployment1-c8d988f6c-hrk88    1/1     Running   0          11m
deployment2-5588d5cdcd-k6cx6   1/1     Running   0          11m

[root@master01 vhost]# kubectl exec -it deployment1-c8d988f6c-hrk88 sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
/ # echo "this is web01" > /usr/share/nginx/html/index.html
/ # exit
[root@master01 vhost]# kubectl exec -it deployment2-5588d5cdcd-k6cx6 sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
/ # echo "this is web02" > /usr/share/nginx/html/index.html
/ # exit

⑧ 测试访问

[root@master01 vhost]# vim /etc/hosts
192.168.190.102 www.aaa.com www.fff.com www.qqq.com

[root@master01 vhost]# curl www.fff.com:32269
this is web01
[root@master01 vhost]# curl www.qqq.com:32269
this is web02

五、Ingress  HTTPS 代理访问

在Kubernetes集群中使用Ingress资源实现通过HTTPS代理访问服务。

1. 创建ssl证书

生成一个自签名的TLS证书,用于在实验中配置HTTPS代理访问时使用

[root@master01 vhost]# cd ../
[root@master01 nodeport]# mkdir https
[root@master01 nodeport]# cd https/

[root@master01 https]# openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=nginxsvc/O=nginxsvc"
[root@master01 https]# ls
tls.crt  tls.key

# -x509:表示生成自签名的证书。
# -sha256:表示使用SHA-256算法进行证书签名。
# -nodes:表示生成的私钥不加密。
# -days 365:表示证书的有效期为365天。
# -newkey rsa:2048:表示生成一个2048位的RSA私钥。
# -keyout tls.key:表示将生成的私钥保存到名为tls.key的文件中。
# -out tls.crt:表示将生成的证书保存到名为tls.crt的文件中。
# -subj "/CN=nginxsvc/O=nginxsvc":表示指定证书的主题信息,其中/CN表示Common Name(通用名称),/O表示Organization(组织)。

2. 创建 secret 资源进行存储

[root@master01 https]# kubectl create secret tls tls-secret --key tls.key --cert tls.crt
secret/tls-secret created
[root@master01 https]# kubectl get secret
NAME                                 TYPE                                  DATA   AGE
tls-secret                           kubernetes.io/tls                     2      7s
[root@master01 https]# kubectl describe secret tls-secret
Name:         tls-secret
Namespace:    default
Labels:       <none>
Annotations:  <none>

Type:  kubernetes.io/tls

Data
====
tls.crt:  1143 bytes
tls.key:  1704 bytes

3. 创建 deployment、Service、Ingress Yaml 资源

[root@master01 https]# vim ingress-https.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-fql
spec:
  replicas: 1
  selector:
    matchLabels:
      name: nginx
  template:
    metadata:
      labels:
        name: nginx
    spec:
      containers:
        - name: nginx
          image: nginx
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: n-svc-https
spec:
  ports:
    - port: 80
      targetPort: 80
      protocol: TCP
  selector:
    name: nginx
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx-https
spec:
  tls:                          # 定义了TLS配置,用于配置HTTPS访问
    - hosts:
      - www.lll.com             # 指定了使用TLS的主机名为www.lll.com
      secretName: tls-secret    # 存储TLS证书和私钥的 Secret 对象的名称为tls-secret
  rules:                        # 定义了访问规则,指定了如何路由到后端服务
    - host: www.lll.com         # 这条规则适用于主机 www.lll.com
      http:                     # 定义了HTTP访问规则
        paths:                  # 指定了路径匹配规则
        - path: /               # 表示所有以 / 开头的路径都会匹配到这个规则
          pathType: Prefix      # 路径匹配类型为前缀匹配
          backend:              # 指定了后端服务的配置
            service:            # 定义了后端服务的名称和端口号
              name: n-svc-https #后端服务的名称为 n-svc-https
              port:
                number: 80

4. 启动资源

[root@master01 https]# kubectl apply -f ingress-https.yaml

[root@master01 https]# kubectl get svc
NAME           TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
n-svc-https    ClusterIP   10.96.7.182     <none>        80/TCP    22s

[root@master01 https]# kubectl get svc -n ingress-nginx
NAME            TYPE       CLUSTER-IP    EXTERNAL-IP   PORT(S)                      AGE
ingress-nginx   NodePort   10.96.69.94   <none>        80:32269/TCP,443:32017/TCP   101m

[root@master01 https]# kubectl get ingress
NAME          CLASS    HOSTS         ADDRESS       PORTS     AGE
nginx-https   <none>   www.lll.com                 80, 443   5s

5. 访问资源

在宿主机的 C:\Windows\System32\drivers\etc\hosts 文件中添加 192.168.190.102 www.lll.com 记录。

六、Nginx 进行 BasicAuth

Basic认证是一种简单的HTTP身份验证方法,通过用户名和密码验证用户身份。

1. 生成用户密码认证文件,创建 secret 资源进行存储

[root@master01 https]# cd ..
[root@master01 nodeport]# mkdir basic-auth
[root@master01 nodeport]# cd basic-auth/

[root@master01 basic-auth]# yum -y install httpd-tools.x86_64
[root@master01 basic-auth]# htpasswd -c auth fql   # 认证文件名必须为 auth
[root@master01 basic-auth]# htpasswd -c auth fql
New password:                   # 密码123
Re-type new password: 
Adding password for user fql
[root@master01 basic-auth]# ls
auth

2. 创建一个 Secret 对象

[root@master01 basic-auth]# kubectl create secret generic basic-auth --from-file=auth

3. 创建 ingress 资源

[root@master01 basic-auth]# vim ingress-auth.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-auth
  annotations:
    nginx.ingress.kubernetes.io/auth-type: basic
    nginx.ingress.kubernetes.io/auth-secret: basic-auth
    nginx.ingress.kubernetes.io/auth-realm: 'Authentication Required - fql'
spec:
  rules:
  - host: www.abc.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service: 
            name: nginx-svc
            port:
              number: 80

[root@master01 basic-auth]# kubectl apply -f ingress-auth.yaml

[root@master01 basic-auth]# kubectl get ingress
NAME           CLASS    HOSTS         ADDRESS       PORTS     AGE
ingress-auth   <none>   www.abc.com   10.96.69.94   80        3m4s

4. 添加宿主机域名解析www.abc.com,访问测试

七、Nginx 重写 

在进行 Nginx Ingress 的 URL 重写实验中,可以配置 Nginx Ingress Controller,然后通过编辑 Ingress 资源规则,使用 Nginx 的 rewrite 指令来修改传入请求的 URL 路径,实现定制的路由和重定向功能。

1. metadata.annotations 配置说明

  • nginx.ingress.kubernetes.io/rewrite-target: <字符串> #必须重定向流量的目标URI
  • nginx.ingress.kubernetes.io/ssl-redirect: <布尔值> #指示位置部分是否仅可访问SSL(当Ingress包含证书时,默认为true)
  • nginx.ingress.kubernetes.io/force-ssl-redirect: <布尔值> #即使Ingress未启用TLS,也强制重定向到HTTPS
  • nginx.ingress.kubernetes.io/app-root: <字符串> #定义Controller必须重定向的应用程序根,如果它在'/'上下文中
  • nginx.ingress.kubernetes.io/use-regex: <布尔值> #指示Ingress上定义的路径是否使用正则表达式

2. 示例 

针对主机 "www.efg.com" 的请求,在经过 Nginx Ingress Controller 处理后,会被重写为指定的目标 URL www.abc.com:32269,并最终路由到名为 "nginx-svc" 的后端服务的端口 80。

① 定义 Ingress

[root@master01 basic-auth]# vim ingress-rewrite.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx-rewrite
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: http://www.fff.com:32269
spec:
  rules:
  - host: www.efg.com #由于www.efg.com只是用于跳转不需要真实站点存在,因此svc资源名称可随意定义
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service: 
            name: nginx-svc
            port:
              number: 80

② 启动 ingress

[root@master01 basic-auth]# kubectl apply -f ingress-rewrite.yaml

[root@master01 basic-auth]# kubectl get ingress
NAME            CLASS    HOSTS         ADDRESS       PORTS     AGE
nginx-rewrite   <none>   www.efg.com                 80        9s

 ④ 添加宿主机域名解析,访问测试

192.168.190.102 www.lll.com  www.abc.com www.efg.com www.fff.com

  • 30
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值