Skip to content

kubernetes-1.20 ingress-nginx 配置案例

一、基础概念和背景

技术背景:

k8s的service资源类型负责处理四层负载,解决了pod漂移问题,但是随着服务的增多,nodeport的方式会导致要配置使用很多的端口,进而出现端口管理维护的问题,最初就有了使用nginx来代理端口访问的处理方案,通过nginx做反向代理,可以无需使用过多的宿主机端口,但是将nginx部署在pod中运行的话,后续服务以及域名的变更配置会要求频繁的修改nginx配置文件,为了进一步解决问题,这才有了Ingress Controoler ,通过与 Kubernetes API交互,动态的去感知集群中 Ingress 规则变化,然后读取他,按照他自己模板生成一段 Nginx 配置,再写到 Nginx Pod 里。

案例需求:

通过http或者https的方式,配合ingress-nginx以不同的url后缀区分访问k8s中部署的服务。

本次案例搭建的测试应用服务为kunpeng search 和 metabase。

1.1、ingress

  • ingress服务:指的是k8s中的一个api对象,一般用yaml配置。作用是定义请求如何转发到service的规则,可以理解为配置模板。
ingress 是一个API对象,和其他对象一样,通过yaml文件来配置,作用是定义请求如何转发到 service 的规则
ingress 通过 http或https 暴露集群内部 service,给 service 提供外部URL、负载均衡、SSL/TLS能力以及基于host的方向代理
ingress-controller 是具体实现反向代理及负载均衡的程序,对 ingress 定义的规则进行解析,根据配置的规则来实现请求转发
ingress 要依靠 ingress-controller 来具体实现以上功能

官方解释:入口|Kubernetes

1.2、ingress-controller

  • ingress controller:具体实现反向代理及负载均衡的程序,对ingress定义的规则进行解析,根据配置的规则来实现请求转发。
ingress-controller 并不是 k8s 自带的组件,实际上 ingress-controller 只是一个统称,用户可以选择不同的 ingress-controller 实现,目前,由 k8s 维护的 ingress-controller 只有google云的 GCE 与 ingress-nginx 两个,其他还有很多第三方维护的 ingress-controller,具体可以参考官方文档。类似的还有:Traefik、HAProxy、Istio.
但是不管哪一种 ingress-controller,实现的机制都大同小异,只是在具体配置上有差异。一般来说,ingress-controller 的形式都是一个 pod,里面跑着 daemon 程序和反向代理程序。daemon 负责不断监控集群的变化,根据 ingress 对象生成配置并应用新配置到反向代理,比如 nginx-ingress 就是动态生成 nginx 配置,动态更新 upstream,并在需要的时候reload程序应用新配置。本例子以 k8s 官方维护的 nginx-ingress 进行演示

官方解释:入口控制器|Kubernetes

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

二、ingress-controller部署

这里选用kubernetes/ingress-nginx作为ingress-controller进行部署

部署参考官方文档,使用官方提供的yaml文件进行部署,文件中有2个镜像是国内网络无法拉取的需要提前单独拉取下来并修改yaml文件中的进行镜像标签

2.1、下载deploy.yaml模板

首先进入官方项目仓库查看需部署的对应版本

Support Versions table

Ingress-NGINX version k8s supported version Alpine Version Nginx Version
v1.1.3 1.23, 1.22, 1.21, 1.20, 1.19 3.14.4 1.19.10†
v1.1.2 1.23, 1.22, 1.21, 1.20, 1.19 3.14.2 1.19.9†
v1.1.1 1.23, 1.22, 1.21, 1.20, 1.19 3.14.2 1.19.9†
v1.1.0 1.22, 1.21, 1.20, 1.19 3.14.2 1.19.9†
v1.0.5 1.22, 1.21, 1.20, 1.19 3.14.2 1.19.9†
v1.0.4 1.22, 1.21, 1.20, 1.19 3.14.2 1.19.9†
v1.0.3 1.22, 1.21, 1.20, 1.19 3.14.2 1.19.9†
v1.0.2 1.22, 1.21, 1.20, 1.19 3.14.2 1.19.9†
v1.0.1 1.22, 1.21, 1.20, 1.19 3.14.2 1.19.9†
v1.0.0 1.22, 1.21, 1.20, 1.19 3.13.5 1.20.1
v0.50.0 1.21, 1.20, 1.19 3.14.2 1.19.9†
v0.49.3 1.21, 1.20, 1.19 3.14.2 1.19.9†
v0.49.2 1.21, 1.20, 1.19 3.14.2 1.19.9†
v0.49.1 1.21, 1.20, 1.19 3.14.2 1.19.9†
v0.49.0 1.21, 1.20, 1.19 3.13.5 1.20.1
v0.48.1 1.21, 1.20, 1.19 3.13.5 1.20.1

当前环境k8s版本为1.20 这里选用的ingress-nginx版本为v1.1.2

进入对应版本源码目录下载deploy.yaml文件

wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.1.2/deploy/static/provider/cloud/deploy.yaml

2.2、修改yaml替换镜像

查看yaml文件找到image 标签拉取的镜像分别有

 k8s.gcr.io/ingress-nginx/controller:v1.1.2
 k8s.gcr.io/ingress-nginx/kube-webhook-certgen:v1.1.1

由于网络原因国内拉取不到该镜像,可以从阿里云镜像仓库单独获取

docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/nginx-ingress-controller:v1.1.2
docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/kube-webhook-certgen:v1.1.1
docker tag registry.cn-hangzhou.aliyuncs.com/google_containers/nginx-ingress-controller:v1.1.2 nginx-ingress-controller:v1.1.2
docker tag registry.cn-hangzhou.aliyuncs.com/google_containers/kube-webhook-certgen:v1.1.1 kube-webhook-certgen:v1.1.1

接下来修改yaml文件替换docker镜像,并修改其他配置,修改处查看diff

[root@ecs-1213 shilitao]# cat diff.log
--- ingress_deploy_bak.yaml     2022-04-02 10:02:18.563209218 +0800
+++ ingress_deploy.yaml 2022-04-01 16:22:08.866556657 +0800
@@ -380,7 +380,7 @@
     app.kubernetes.io/component: controller
     app.kubernetes.io/instance: ingress-nginx
     app.kubernetes.io/name: ingress-nginx
-  type: LoadBalancer
+  type: NodePort
 ---
 apiVersion: v1
 kind: Service
@@ -457,7 +457,7 @@
               fieldPath: metadata.namespace
         - name: LD_PRELOAD
           value: /usr/local/lib/libmimalloc.so
-        image: k8s.gcr.io/ingress-nginx/controller:v1.1.2@sha256:28b11ce69e57843de44e3db6413e98d09de0f6688e33d4bd384002a44f78405c
+        image: nginx-ingress-controller:v1.1.2
         imagePullPolicy: IfNotPresent
         lifecycle:
           preStop:
@@ -477,9 +477,11 @@
         name: controller
         ports:
         - containerPort: 80
+          hostPort: 80
           name: http
           protocol: TCP
         - containerPort: 443
+          hostPort: 443
           name: https
           protocol: TCP
         - containerPort: 8443
@@ -561,7 +563,7 @@
           valueFrom:
             fieldRef:
               fieldPath: metadata.namespace
-        image: k8s.gcr.io/ingress-nginx/kube-webhook-certgen:v1.1.1@sha256:64d8c73dca984af206adf9d6d7e46aa550362b1d7a01f3a0a91b20cc67868660
+        image: kube-webhook-certgen:v1.1.1
         imagePullPolicy: IfNotPresent
         name: create
         securityContext:
@@ -617,7 +619,7 @@
           valueFrom:
             fieldRef:
               fieldPath: metadata.namespace
-        image: k8s.gcr.io/ingress-nginx/kube-webhook-certgen:v1.1.1@sha256:64d8c73dca984af206adf9d6d7e46aa550362b1d7a01f3a0a91b20cc67868660
+        image: kube-webhook-certgen:v1.1.1
         imagePullPolicy: IfNotPresent
         name: patch
         securityContext:

除了修改容器标签还要修改ingress-nginx-controller的service中的类型为NodePort或者ingress 使用到物理机的80/443 端口,所以增加hostport相应配置,两种方式都可以实现访问,这里为了演示都进行了配置。

2.3、修改完成后部署

[root@ecs-1213 nginx]# mv deploy.yaml ingress-nginx-controller.yaml
[root@ecs-1213 nginx]# kubectl apply -f ingress-nginx-controller.yaml
namespace/ingress-nginx created
serviceaccount/ingress-nginx created
serviceaccount/ingress-nginx-admission created
role.rbac.authorization.k8s.io/ingress-nginx created
role.rbac.authorization.k8s.io/ingress-nginx-admission created
clusterrole.rbac.authorization.k8s.io/ingress-nginx created
clusterrole.rbac.authorization.k8s.io/ingress-nginx-admission created
rolebinding.rbac.authorization.k8s.io/ingress-nginx created
rolebinding.rbac.authorization.k8s.io/ingress-nginx-admission created
clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx created
clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx-admission created
configmap/ingress-nginx-controller created
service/ingress-nginx-controller created
service/ingress-nginx-controller-admission created
deployment.apps/ingress-nginx-controller created
job.batch/ingress-nginx-admission-create created
job.batch/ingress-nginx-admission-patch created
ingressclass.networking.k8s.io/nginx created
validatingwebhookconfiguration.admissionregistration.k8s.io/ingress-nginx-admission created
[root@ecs-1213 nginx]# kubectl get all -n ingress-nginx
NAME                                            READY   STATUS      RESTARTS   AGE
pod/ingress-nginx-admission-create-dp5gd        0/1     Completed   0          36s
pod/ingress-nginx-admission-patch-w4c5f         0/1     Completed   1          36s
pod/ingress-nginx-controller-78d8d9f697-g6zfd   1/1     Running     0          36s

NAME                                         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
service/ingress-nginx-controller             NodePort    10.110.248.97   <none>        80:30747/TCP,443:32755/TCP   36s
service/ingress-nginx-controller-admission   ClusterIP   10.97.90.192    <none>        443/TCP                      36s

NAME                                       READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/ingress-nginx-controller   1/1     1            1           36s

NAME                                                  DESIRED   CURRENT   READY   AGE
replicaset.apps/ingress-nginx-controller-78d8d9f697   1         1         1       36s

NAME                                       COMPLETIONS   DURATION   AGE
job.batch/ingress-nginx-admission-create   1/1           2s         36s
job.batch/ingress-nginx-admission-patch    1/1           3s         36s
[root@ecs-1213 nginx]#

查看资源状态运行正常即部署完成,接下来可以配置两个测试服务并配置ingress规则进一步测试。

三、部署测试应用

3.1、部署测试应用鲲鹏search的前端页面

  • 应用背景:在部署环境中已经存在foliant search的服务,经过服务搭建测试也对该服务有了一定认识,根据服务之间的关系可知,foliant转换后的静态文件资源挂载在httpd的容器中可对外提供web访问,其中search页面的静态资源挂载在httpd容器中,页面中包含css和js文件,连接跳转foliant处理后的页面资源,同时连接es的索引。

nginx也可以代理静态页面资源提供http服务访问,下面将直接通过k8s部署nginx服务代理kunpeng search的静态页面作为测试应用。

  • 准备部署文件

```yaml [root@ecs-1213 nginx]# cat nginx-app-svc.yaml


kind: Deployment apiVersion: apps/v1 metadata: name: nginx spec: replicas: 1 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.21.6 ports: - containerPort: 80 protocol: TCP volumeMounts: - mountPath: /usr/share/nginx/html/ name: search volumes: - name: search hostPath: path: /data/shilitao/nginx/webapp_example type: Directory


kind: Service apiVersion: v1 metadata: name: nginx labels: name: nginx spec: # type: ClusterIP ports: - protocol: TCP # nodePort: 31010 targetPort: 80 #容器端口 port: 32230 #pod端口 selector: app: nginx ```

  • 挂载search页面资源到容器目录,注释service中暴露端口的方式,后期使用ingress进行配置

bash [root@ecs-1213 nginx]# kubectl apply -f nginx-app-svc.yaml deployment.apps/nginx created service/nginx created

将服务部署到default命名空间进行测试,部署完毕可以在内部进行访问测试服务是否正常

[root@ecs-1213 nginx]# kubectl get svc
NAME         TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)          AGE
kubernetes   ClusterIP   10.96.0.1      <none>        443/TCP          110d
nginx        ClusterIP   10.99.139.43   <none>        32230/TCP        2m32s
[root@ecs-1213 nginx]# curl 10.99.139.43:32230
<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <title>Search</title>
    <link rel="stylesheet" href="foliant_elasticsearch.css">
    <script src="foliant_elasticsearch.js"></script>
</head>

<body class="foliant_elasticsearch">
    <h1>Kunpeng Search</h1>
    <div>
        <input id="foliant_elasticsearch_input" type="text" oninput="performSearch(this.value);">
    </div>
    <div id="foliant_elasticsearch_total"></div>
    <div id="foliant_elasticsearch_results"></div>
</body>

</html>

测试正常。

3.2、部署Metabase应用

  • 应用背景:目前环境中有做好的Metabase镜像可以直接启动进行测试,默认启动使用的内置数据库,启动后可以访问服务初始化页面。

  • 准备部署文件

```yaml [root@ecs-1213 nginx]# cat metabase-app-svc.yaml


apiVersion: apps/v1 kind: Deployment metadata: name: metabase2 namespace: default spec: replicas: 1 selector: matchLabels: app: metabase2 template: metadata: labels: app: metabase2 spec: containers: - name: metabase image: metabase/metabase:v0.39.4_zhai_aarch64 imagePullPolicy: IfNotPresent ports: - containerPort: 3000


apiVersion: v1 kind: Service metadata: name: metabase2 namespace: default spec: # type: NodePort selector: app: metabase2 ports: - name: http port: 32240 # nodePort: 32240 targetPort: 3000 ```

同样注释service中端口的暴露方式

```bash [root@ecs-1213 nginx]# kubectl apply -f metabase-app-svc.yaml deployment.apps/metabase2 created service/metabase2 created [root@ecs-1213 nginx]# kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 443/TCP 110d metabase2 ClusterIP 10.107.42.1 32240/TCP 18s nginx ClusterIP 10.99.139.43 32230/TCP 10m [root@ecs-1213 nginx]# curl 10.107.42.1:32240

Metabase ``` ​ 测试访问正常。 ## 四、编写ingress对象配置文件 测试应用已搭建完成,配置ingress对象可以制定访问各个服务的端口或者路径的规则,ingress controller 对ingress定义的规则进行解析,根据配置的规则来实现请求转发。 ### 4.1、配置文件编写
[root@ecs-1213 nginx]# cat nginx_ingress.yaml
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx-app-ingress
  annotations:
    kubernetes.io/ingress.class: "nginx"  #指定使用后端ingress controller的类别,如果后端有多个ingress controller的时候很重要
    nginx.ingress.kubernetes.io/use-regex: "true" #指定rules的path可以使用正则表达式,如果没有使用正则表达式,此项则可不使用
    nginx.ingress.kubernetes.io/rewrite-target: /$2 #必须重定向流量的目标 URI  正则匹配的参数,$1表示第一个()内的正则匹配内容,$2为第二个,以此类推
spec:
  rules:
  - host:
    http:
      paths:
      - pathType: Prefix                  #基于以 / 分隔的 URL 路径前缀匹配
        path: /nginx(/|$)(.*)             #(/|$)匹配/或者字符串结束 (.*)配置所有字符
        backend:
          service:
            name: nginx
            port:
              number: 32230               #nginx-service的nodeport端口
      - pathType: Prefix
        path: /metabase(/|$)(.*)
        backend:
          service:
            name: metabase2
            port:
              number: 32240               #metabase-service的nodeport端口
  defaultBackend:                         #默认的页面也就是nginx80端口页面,如果以上规则都未匹配到将会转到以下服务
    service:
      name: metabase2
      port:
        number: 32240
### 4.2、相关参数解释 - defaultBackend:没有设置规则的 Ingress 将所有流量发送到同一个默认后端,而 `.spec.defaultBackend` 则是在这种情况下处理请求的那个默认后端。 `defaultBackend` 通常是 [Ingress 控制器](https://kubernetes.io/zh/docs/concepts/services-networking/ingress-controllers)的配置选项,而非在 Ingress 资源中指定。 如果未设置任何的 `.spec.rules`,那么必须指定 `.spec.defaultBackend`。 如果未设置 `defaultBackend`,那么如何处理所有与规则不匹配的流量将交由 Ingress 控制器决定(请参考你的 Ingress 控制器的文档以了解它是如何处理那些流量的)。 如果没有 `hosts` 或 `paths` 与 Ingress 对象中的 HTTP 请求匹配,则流量将被路由到默认后端。 https://kubernetes.io/zh/docs/concepts/services-networking/ingress/#default-backend - Ingress 中的每个路径都需要有对应的路径类型(Path Type)。未明确设置 `pathType` 的路径无法通过合法性检查。当前支持的路径类型有三种:ImplementationSpecific:对于这种路径类型,匹配方法取决于 IngressClass。 具体实现可以将其作为单独的 `pathType` 处理或者与 `Prefix` 或 `Exact` 类型作相同处理。 Exact:精确匹配 URL 路径,且区分大小写。 Prefix:基于以 `/` 分隔的 URL 路径前缀匹配。匹配区分大小写,并且对路径中的元素逐个完成。 路径元素指的是由 `/` 分隔符分隔的路径中的标签列表。 如果每个 *p* 都是请求路径 *p* 的元素前缀,则请求与路径 *p* 匹配。 - ingress文件的配置更新: 通过命令`kubectl edit ingress test`打开yaml文件直接进行编辑,保存之后配置将自动生效。 - host 字段配置域名,可以是精确匹配(例如“`foo.bar.com`”)或者使用通配符来匹配 (例如“`*.foo.com`” - 注解Annotations:可以使用 Kubernetes 注释将任意非识别元数据附加到对象,这里附注的有nginx配置的元数据,用以设置当前 Ingress 资源实例中 Nginx 虚拟主机的相关配置,对应配置的是 Nginx 当前虚拟主机的 server 指令域内容。其他的Nginx Ingress注解Annotations 参数可参考:[Nginx Ingress注解Annotations_微学苑 (weixueyuan.net)](https://www.weixueyuan.net/a/884.html) ### 4.3、使用IP进行访问测试 配置文件编写完成可以应用配置生效 - 由于ingress-nginx-controller的service已经定义了nodeport的端口,所以可以通过该宿主机的IP地址加nodeport端口访问ingress-nginx-controller,然后根据请求的url后缀匹配我们pod上的服务,例如: k8s集群内访问地址http://10.108.14.78:80是ingress-nginx-controller的service,增加后缀/nginx 或者 /metabase 会访问到相应的服务 k8s集群外部访问地址http://1.1.1.1:30343是ingress-nginx-controller的service对外nodeport服务地址,增加后缀/nginx 或者 /metabase 会访问到相应的服务 - ingress-nginx-controller的yaml配置文件中还配置了hostport的80和443端口,所以这里也是可以通过直接访问该主机的80端口就能够访问ingress-nginx-controller的service,即: 访问http://1.1.1.1是ingress-nginx-controller的service,增加后缀/nginx 或者 /metabase 会访问到相应的服务
[root@ecs-1213 nginx]# kubectl apply -f nginx_ingress.yaml
ingress.networking.k8s.io/nginx-app-ingress configured
[root@ecs-1213 nginx]# kubectl get ing
NAME                CLASS    HOSTS   ADDRESS        PORTS   AGE
nginx-app-ingress   <none>   *       10.108.14.78   80      3d16h
[root@ecs-1213 nginx]# kubectl describe ingress nginx-app-ingress
Name:             nginx-app-ingress
Namespace:        default
Address:          10.108.14.78
Default backend:  nginx:32230 (10.32.0.10:80)
Rules:
  Host        Path  Backends
  ----        ----  --------
  *
              /nginx(/|$)(.*)      nginx:32230 (10.32.0.10:80)
              /metabase(/|$)(.*)   metabase2:32240 (10.32.0.8:3000)
Annotations:  kubernetes.io/ingress.class: nginx
              nginx.ingress.kubernetes.io/rewrite-target: /$2
              nginx.ingress.kubernetes.io/use-regex: true
Events:       <none>
[root@ecs-1213 nginx]# kubectl get svc -n ingress-nginx
NAME                                 TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)                      AGE
ingress-nginx-controller             NodePort    10.108.14.78     <none>        80:30343/TCP,443:30600/TCP   3d16h
ingress-nginx-controller-admission   ClusterIP   10.108.133.238   <none>        443/TCP                      3d16h
[root@ecs-1213 nginx]#[root@ecs-1213 nginx]# curl http://10.108.14.78:80/nginx/
<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <title>Search</title>
    <link rel="stylesheet" href="foliant_elasticsearch.css">
    <script src="foliant_elasticsearch.js"></script>
</head>

<body class="foliant_elasticsearch">
    <h1>Kunpeng Search</h1>
    <div>
        <input id="foliant_elasticsearch_input" type="text" oninput="performSearch(this.value);">
    </div>
    <div id="foliant_elasticsearch_total"></div>
    <div id="foliant_elasticsearch_results"></div>
</body>

</html>
[root@ecs-1213 nginx]# curl http://1.1.1.1/nginx/
<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <title>Search</title>
    <link rel="stylesheet" href="foliant_elasticsearch.css">
    <script src="foliant_elasticsearch.js"></script>
</head>

<body class="foliant_elasticsearch">
    <h1>Kunpeng Search</h1>
    <div>
        <input id="foliant_elasticsearch_input" type="text" oninput="performSearch(this.value);">
    </div>
    <div id="foliant_elasticsearch_total"></div>
    <div id="foliant_elasticsearch_results"></div>
</body>

</html>
## 五、搭配域名进行访问 以上通过IP能够访问ingress-nginx-controller并根据后缀匹配相应的服务,那么就说明服务已经搭建完成可以正常使用,下面就可以通过配置ingress的yaml文件中spec.rules.host的的字段,设置域名进行访问,这里的域名可以精确设置,也可以使用通配符匹配,下面简要记录一下域名的准备流程和后续配置。 ### 5.1、域名准备 可以在域名注册服务商处注册域名,相应的域名会收取不同的费用,最便宜的一年几块钱。 阿里、腾讯、华为等公有云都有域名注册服务,可以直接进行域名申请注册,注册成功之后,需要进行实名认证以及办理域名网站备案,否则域名是无法被解析使用的。 下面是腾讯云域名管理添加解析记录的过程: - 添加域名解析 登录管理腾讯云的管理控制台,进入域名注册栏、找到我的域名、点击解析 ![](./media/202204/image-20220406110149534_1650270578.png) 点击解析后跳转到域名管理控制台-我的域名-记录管理页面,在这里可以添加新的解析记录到公网IP,如下 ![](./media/202204/image-20220406110353761_1650270597.png) ![](./media/202204/image-20220406110443278_1650270613.png) ![](./media/202204/image-20220406110502155_1650270624.png) 新添加的解析地址为1.1.1.1 主机记录为test 那么访问域名test.shilitao.top 就会解析到该地址 以上为域名解析配置案例,下面测试用的域名为haha.online 已解析到地址1.1.1.1 ### 5.2、修改ingress配置文件
[root@ecs-1213 nginx]# kubectl edit ingress nginx-app-ingress
ingress.networking.k8s.io/nginx-app-ingress edited

---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx-app-ingress
  annotations:
    kubernetes.io/ingress.class: "nginx"
    nginx.ingress.kubernetes.io/use-regex: "true"
    nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
  rules:
  - host: haha.online      #增加域名设置
    http:
      paths:
      - pathType: Prefix
        path: /nginx(/|$)(.*)
        backend:
          service:
            name: nginx
            port:
              number: 32230
      - pathType: Prefix
        path: /metabase(/|$)(.*)
        backend:
          service:
            name: metabase2
            port:
              number: 32240
  defaultBackend:
    service:
      name: nginx
      port:
        number: 32230
### 5.3、域名访问测试 域名配置完成后可以进行访问测试
[root@ecs-1213 nginx]# kubectl get ing
NAME                CLASS    HOSTS             ADDRESS        PORTS   AGE
nginx-app-ingress   <none>   haha.online   10.108.14.78   80      3d16h
访问Search (http://haha.online/nginx/) 访问Metabase (http://haha.online/metabase/) - 注意必须后缀要有 / 否则无法加载到动态资源 - 匹配不到的规则会默认转发到defaultBackend配置的service,只有静态页面资源 ![](./media/202204/image-20220406112121206_1650270642.png) ### 5.4、配置https访问 ingress是有tls配置项用于证书配置,这里在配置之前需要准备一个和域名绑定的ssl证书或者tls证书。 - 相关概念可以查看该资料,可以对https和证书有基本的了解[HTTPS、SSL、TLS三者之间的联系和区别]([HTTPS、SSL、TLS三者之间的联系和区别_天府云创的博客-CSDN博客_tls和ssl区别](https://blog.csdn.net/enweitech/article/details/81781405)) **关于证书的申请,这里可以推荐两种方式进行:** 第一种:直接通过域名管理平台申请,一般都有这种业务,由于本次测试使用的域名在腾讯云管理,关于证书这方面是有专门的ssl证书可以免费申请使用 ![](./media/202204/image-20220406150043043_1650270656.png) ![](./media/202204/image-20220406150121450_1650270666.png) ![](./media/202204/image-20220406150241113_1650270674.png) 之后根据操作提示输入相关基本信息,基本就可以一键完成证书申请,证书有限期为一年,申请成功之后可以将证书下载下来上传到服务器中,就可以进行后续k8s secret配置。 第二种:通过相关免费的证书申请平台手动去申请证书,这里演示通过网站[FreeSSL首页 - FreeSSL.cn一个提供免费HTTPS证书申请的网站](https://freessl.cn/)申请免费证书 ![](./media/202204/image-20220406154759756_1650270685.png) 输入域名点击创建后,根据要求填写域名配置 ![](./media/202204/image-20220406154848551_1650270698.png) ![](./media/202204/image-20220406154908308_1650270707.png) 然后进行第二步,上域名控制台添加解析记录,进行检测 ![](./media/202204/image-20220406154954858_1650270715.png) 检测完成后,就可以根据给出的部署命令进行证书部署了,这里推荐使用acme.sh进行部署 先安装acme.sh脚本
curl https://gitcode.net/cert/cn-acme.sh/-/raw/master/install.sh?inline=false | sh -s email=my@example.com
然后执行部署命令
acme.sh --issue -d haha.online  --dns dns_dp --server https://acme.freessl.cn/v2/DV90/directory/i1sbcebv31zxdu039l5e
![](./media/202204/image-20220406155255455_1650270729.png) 执行完毕后返回证书保存的位置,到此就完成了证书部署。 **下面创建k8s secret资源载入证书信息**
[root@ecs-1213 nginx]# kubectl create secret tls haha.online --cert=/root/.acme.sh/haha.online/haha.online.cer --key=/root/.acme.sh/haha.online/haha.online.key
secret/haha.online created
[root@ecs-1213 nginx]# kubectl get secret
NAME                  TYPE                                  DATA   AGE
default-token-gqq4x   kubernetes.io/service-account-token   3      114d
haha.online       kubernetes.io/tls                     2      15s
**修改ingress配置规则生效tls**
[root@ecs-1213 nginx]# cat nginx_ingress.yaml
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx-app-ingress
  annotations:
    kubernetes.io/ingress.class: "nginx"
    nginx.ingress.kubernetes.io/use-regex: "true"
    nginx.ingress.kubernetes.io/rewrite-target: /$2
    nginx.ingress.kubernetes.io/ssl-redirect: "false"   #关闭强制https的定向访问
spec:
  tls:                                  #配置tls
  - hosts:
    - haha.online                   #域名
    secretName: haha.online         #secret资源名称
  rules:
  - host: haha.online
    http:
      paths:
      - pathType: Prefix
        path: /nginx(/|$)(.*)
        backend:
          service:
            name: nginx
            port:
              number: 32230
      - pathType: Prefix
        path: /metabase(/|$)(.*)
        backend:
          service:
            name: metabase2
            port:
              number: 32240
  defaultBackend:
    service:
      name: nginx
      port:
        number: 32230
**访问测试** ![](./media/202204/image-20220406155958529_1650270743.png) ![](./media/202204/image-20220406160023773_1650270751.png) 这里需要注意的是kunpeng search服务本身启动的nginx容器对原有httpd服务进行了代理,所以只能访问静态页面,后面search的结果页面是httpd服务提供的,默认没有配置https, 所以搜索不到结果,可以将原有服务中的httpd服务完全替换到nginx后,就可以实现相同的效果。 - 关于证书的自动续签,可以搭建cert-manager+Let‘s Encrypt实现自动证书签发,配置参考[k8s中级篇-cert-manager+Let‘s Encrypt自动证书签发](https://blog.csdn.net/ai524719755/article/details/116712931) 访问Search (https:/haha.online/nginx/) 访问Metabase (https://haha.online/metabase/) 但是已经可以反馈到ingress通过https访问配置完成。 ## 六、利用ingress进行访问控制 ### 6.1 黑白名单控制 ingress后台是基于nginx在运作,所以nginx可以实现的功能,在ingress也是可以实现的。 有几种配置方式都可以实现。 第一种、使用configmap配置实现,配置文件参考如下
apiVersion: v1
kind: ConfigMap
metadata:
  labels:
    app.kubernetes.io/component: controller
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/managed-by: Helm
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
    app.kubernetes.io/version: 1.1.2
    helm.sh/chart: ingress-nginx-4.0.18
  name: ingress-nginx-controller
  namespace: ingress-nginx
data:
  allow-snippet-annotations: "true"  #该功能开启了在ingress配置文件中annotations的server-snippet写法,表示可以直接使用该字段插入到nginx—server块的配置
  whitelist-source-range: 'x.x.x.x/24,x.x.x.x'   #白名单
  block-cidrs: 'x.x.x.x/24,x.x.x.x'              #黑名单
第二种,上一步在configmap中设置了`allow-snippet-annotations: "true"`就可以在ingress文件进行配置,不用在cofigmap中设置`whitelist-source-range`和`block-cidrs`字段,参考如下:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: metabase-ingress
  namespace: service
  annotations:
    kubernetes.io/ingress.class: "nginx"
    nginx.ingress.kubernetes.io/use-regex: "true"
    nginx.ingress.kubernetes.io/rewrite-target: /$2
    nginx.ingress.kubernetes.io/server-snippet: |-
      deny 121.4.51.168;
      allow all;
spec:
  rules:
  - host:
    http:
      paths:
      - path: /m(/|$)(.*)
        pathType: Prefix
        backend:
          service:
            name: metabase
            port:
              number: 3000
- nginx.ingress.kubernetes.io/server-snippet (用于插入 server 块中的代码段)
    nginx.ingress.kubernetes.io/server-snippet: |-
      allow 121.4.51.168;
      deny all;
相应修改也可以实现白名单功能。 第三种、还是通过修改ingress配置实现,只是相比第二种的写法不同,例如
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: metabase-ingress
  namespace: service
  annotations:
    kubernetes.io/ingress.class: "nginx"
    nginx.ingress.kubernetes.io/use-regex: "true"
    nginx.ingress.kubernetes.io/rewrite-target: /$2
    nginx.ingress.kubernetes.io/whitelist-source-range: 'x.x.x.x/24,x.x.x.x'   #白名单
    nginx.ingress.kubernetes.io/block-cidrs: 'x.x.x.x/24,x.x.x.x'              #黑名单
spec:
  rules:
  - host:
    http:
      paths:
      - path: /m(/|$)(.*)
        pathType: Prefix
        backend:
          service:
            name: metabase
            port:
              number: 3000
### 6.2 使用基本认证功能 ingress-nginx可以实现访问页面跳出需要输入用户名和密码的认证功能,下面通过演示进行测试 首先,创建一个用户名密码,使用http的命令工具来生成
[root@k8s-master01 ingress]# htpasswd -c auth service
New password: 123456
Re-type new password: 123456
Adding password for user service
[root@k8s-master01 ingress]# ls
auth  tls.cert  tls.key
[root@k8s-master01 ingress]# cat auth 
service:$apr1$UDKoFAUq$kPM0AaEB.qTEzzwB1SHSC.
然后根据生成的auth文件创建secret
[root@k8s-master01 ingress]# kubectl create secret generic basic-auth --from-file=auth -n service 
secret/basic-auth created
最后配置ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress1
  namespace: service
  annotations:
    kubernetes.io/ingress.class: "nginx"
    nginx.ingress.kubernetes.io/use-regex: "true"
    nginx.ingress.kubernetes.io/rewrite-target: /$2
    nginx.ingress.kubernetes.io/auth-realm: Need to longin   #需要登录认证
    nginx.ingress.kubernetes.io/auth-secret: basic-auth      #认证的secret名称
    nginx.ingress.kubernetes.io/auth-type: basic             #基本认证类型
spec:
  rules:
  - host:
    http:
      paths:
      - path: /s(/|$)(.*)
        pathType: Prefix
        backend:
          service:
            name: nginx
            port:
              number: 80
  defaultBackend:
    service:
      name: gitea
      port:
        number: 3000
[root@ecs-arm-k8s-master01 shilitao]# kubectl apply -f ingress.yaml
ingress.networking.k8s.io/ingress1 configured
生效配置后进行访问测试 ![](./media/202204/image-20220415165401592_1650270776.png) 输入用户名: 密码: ,即可出现search页面 ![](./media/202204/image-20220415165552547_1650270784.png) ![](./media/202204/image-20220415165559544_1650270793.png)