五、K8s服务发布

发布于:2025-07-01 ⋅ 阅读:(18) ⋅ 点赞:(0)

五、K8s服务发布

文章目录

1、服务发布场景

1.1 服务发布分类总结
  • 用户访问
  • 服务间访问
  • 基础组件访问
1.2 K8s服务发布架构-无注册中心

在这里插入图片描述

1.3 K8s服务发布架构-有注册中心

在这里插入图片描述

1.4 Service是如何代理Pod的

Label:K8s任何资源都有标签的概念,用于给同类的资源进行分组。比如一个集群有很多个节点,可以根据不同的地域、网段、节点类型进行分组,方便管理。

Selector:(标签选择器)可以通过同一类资源的不同标签进行精确的查询数据。比如想要查询某个命名空间下所有具有app=payment标签的Pod,可以使用Selector进行过滤。

1.5 什么是Service

Service是K8s开箱即用的一个用于提供负载均衡、服务发现等能力的资源。

Service为Pod提供了一个抽象层,将一组具有相同功能的Pod抽象为一个逻辑上的服务。无论匹配的Pod如何变化,比如重启、迁扩缩容等,Service都能保持一个稳定的访问接口,从而让我们无需关心服务所在的具体位置、IP等细节。

  • 主要功能:
    • 服务之间的服务发现
    • 代理一个或一组Pod
    • 代理IP或域名
1.6 什么是Endpoints

Endpoints可以理解为Service的一部分,主要用于记录Service对应的所有Pod的IP地址和端口信息。Service通过Endpoints来找到并访问后端的Pod。

Endpoints资源记录了Pod的IP地址和端口列表,当后端Pod产生变化时,K8s的控制器会更新Endpoints里面的配置信息,从而保证Service能够正确的路由到关联且正常运行的Pod中。

只有当Service名称和端口信息与Endpoints一样时,Service和Endpoints才会自动建立关联。

2、K8s服务发布:东西流量管理Service

# 创建一个测试资源:
[root@k8s-master01 ~]# kubectl create deploy counter --image=crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/counter:v1

[root@k8s-master01 ~]# kubectl create deploy nginx --image=crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/nginx:1.15
2.1 Label 和 Selector
2.1.1 添加标签(Label)
# 指定单个资源添加标签:
[root@k8s-master01 ~]# kubectl label deploy nginx version=1

# 查看标签
[root@k8s-master01 ~]# kubectl get deploy nginx --show-labels
NAME    READY   UP-TO-DATE   AVAILABLE   AGE   LABELS
nginx   1/1     1            1           58s   app=nginx,version=1


# 指定多个资源添加标签:
[root@k8s-master01 ~]# kubectl label deploy --all test=true
[root@k8s-master01 ~]# kubectl get deploy --show-labels
NAME      READY   UP-TO-DATE   AVAILABLE   AGE    LABELS
counter   1/1     1            1           2m9s   app=counter,test=true
nginx     1/1     1            1           2m3s   app=nginx,test=true,version=1


# 根据已有标签过滤之后再添加标签:
[root@k8s-master01 ~]# kubectl label deploy -l app=counter svc=true
[root@k8s-master01 ~]# kubectl get deploy --show-labels
NAME      READY   UP-TO-DATE   AVAILABLE   AGE     LABELS
counter   1/1     1            1           3m56s   app=counter,svc=true,test=true
nginx     1/1     1            1           3m50s   app=nginx,test=true,version=1


# 同时添加多个标签:
[root@k8s-master01 ~]# kubectl label deploy -l app=nginx a=b c=d

[root@k8s-master01 ~]# kubectl get deploy --show-labels
NAME      READY   UP-TO-DATE   AVAILABLE   AGE     LABELS
counter   1/1     1            1           5m35s   app=counter,svc=true,test=true
nginx     1/1     1            1           5m29s   a=b,app=nginx,c=d,test=true,version=1
2.1.2 修改标签(Label)
# 已经存在的标签名,不允许直接进行修改:
# 如需修改,可以使用--overwrite 参数:
[root@k8s-master01 ~]# kubectl label deploy -l app=nginx version=2 --overwrit

[root@k8s-master01 ~]# kubectl get deploy --show-labels
NAME      READY   UP-TO-DATE   AVAILABLE   AGE    LABELS
counter   1/1     1            1           8m6s   app=counter,svc=true,test=true
nginx     1/1     1            1           8m     a=b,app=nginx,c=d,test=true,version=2
2.1.3 删除标签(Label)
# 删除 Key 为 version 的标签:
[root@k8s-master01 ~]#  kubectl label deploy -l app=nginx a- c-

[root@k8s-master01 ~]# kubectl get deploy --show-labels
NAME      READY   UP-TO-DATE   AVAILABLE   AGE   LABELS
counter   1/1     1            1           12m   app=counter,svc=true,test=true
nginx     1/1     1            1           12m   app=nginx,test=true,version=2
2.1.4 Selector 选择器
# 首先使用--show-labels 查看指定资源目前已有的 Label
[root@k8s-master01 ~]# kubectl get deploy --show-labels
NAME      READY   UP-TO-DATE   AVAILABLE   AGE   LABELS
counter   1/1     1            1           24m   app=counter,svc=true,test=true
nginx     1/1     1            1           23m   app=nginx,test=true,version=2

# 查询 app 为 nginx 的 Deployment
[root@k8s-master01 ~]# kubectl get deploy -l app=nginx --show-labels
NAME    READY   UP-TO-DATE   AVAILABLE   AGE   LABELS
nginx   1/1     1            1           24m   app=nginx,test=true,version=2

# 查询 app 为 nginx 或 counter 的 Deployment
[root@k8s-master01 ~]# kubectl get deploy -l 'app in (nginx,counter)' --show-labels
NAME      READY   UP-TO-DATE   AVAILABLE   AGE   LABELS
counter   1/1     1            1           26m   app=counter,svc=true,test=true
nginx     1/1     1            1           26m   app=nginx,test=true,version=2

# 查询 app 为 nginx 或 counter 但不包括 version=v2 的 Deployment
[root@k8s-master01 ~]# kubectl get deploy -l 'app in (nginx,counter)' -l version!=2 --show-labels
NAME      READY   UP-TO-DATE   AVAILABLE   AGE   LABELS
counter   1/1     1            1           27m   app=counter,svc=true,test=true
2.1.5 使用案例

公司与 xx 银行有一条专属的高速光纤通道,此通道只能与 192.168.7.0 网段进行通信,因此只能将与 xx 银行通信的应用部署到 192.168.7.0 网段所在的节点上,此时可以对节点添加 Label:

# 查看pod部署情况(都在node01节点上面)
[root@k8s-master01 ~]# kubectl get po -owide
NAME                       READY   STATUS    RESTARTS   AGE   IP              NODE         NOMINATED NODE   READINESS GATES
....
nginx-5f58c9c676-kvhb7     1/1     Running   0          32m   172.16.85.224   k8s-node01   <none>           <none>

# 为node02节点打上标签
[root@k8s-master01 ~]# kubectl label node k8s-node02 region=subnet7
[root@k8s-master01 ~]# kubectl get node -l region=subnet7
NAME         STATUS   ROLES    AGE   VERSION
k8s-node02   Ready    <none>   9d    v1.32.5

# 最后在 Deployment 或其他控制器中指定将 Pod 部署到该节点
[root@k8s-master01 ~]# kubectl edit deploy nginx
...
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: nginx
    spec:
      nodeSelector:
        region: subnet7     # 只会部署属于这个标签的节点上
      containers:
      - image: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/nginx:1.15
        imagePullPolicy: IfNotPresent
...

# 查看部署节点
[root@k8s-master01 ~]# kubectl get po -owide
NAME                       READY   STATUS    RESTARTS   AGE   IP              NODE         NOMINATED NODE   READINESS GATES
....
nginx-654b5496df-cv47v     1/1     Running   0          15s   172.16.58.241   k8s-node02   <none>           <none>
2.2 定义 Service
# 创建 Service 可以使用 expose 命令
[root@k8s-master01 ~]# kubectl expose deploy nginx --port 80
[root@k8s-master01 ~]# kubectl get svc nginx
NAME    TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)   AGE
nginx   ClusterIP   10.98.222.5   <none>        80/TCP    7s

# 查看其yaml配置
[root@k8s-master01 ~]# kubectl get svc nginx -oyaml
apiVersion: v1
kind: Service
metadata:
  creationTimestamp: "2025-06-12T13:01:11Z"
  labels:
    app: nginx
    test: "true"
    version: "2"
  name: nginx
  namespace: default
  resourceVersion: "205211"
  uid: ea457597-c462-4206-87e0-554920fd7a7d
spec:
  clusterIP: 10.98.222.5            # Service 的 IP,不需要手动指定
  clusterIPs:
  - 10.98.222.5
  internalTrafficPolicy: Cluster
  ipFamilies:
  - IPv4
  ipFamilyPolicy: SingleStack
  ports:                            # Service 端口配置
  - port: 80                        # Service 端口
    protocol: TCP                   # 代理协议(能够支持 TCP、UDP、SCTP 等协议,默认为 TCP 协议)
    targetPort: 80                  # 目标端口,程序端口
  selector:                         # 代理到哪些 Pod
    app: nginx
  sessionAffinity: None             # 会话保持配置
  type: ClusterIP                   # Service 类型
status:
  loadBalancer: {}

Service 支持将一个接收端口映射到任意的 targetPort,如果 targetPort 为空,targetPort 将被设置为与 Port 字段相同的值。targetPort 可以设置为一个字符串,引用 Pod 的一个端口的名称,这样的话即使更改了 Pod 的端口,也不会对 Service 的访问造成影响。

# 创建服务
[root@k8s-master01 ~]# kubectl create deploy nginx --replicas=3 --port=80 --image=crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/nginx:stable --dry-run=client -oyaml > nginx.yaml

[root@k8s-master01 ~]# cat nginx.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: nginx
  name: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: nginx
    spec:
      containers:
      - image: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/nginx:stable
        name: nginx
        ports:
        - containerPort: 80
        resources: {}
status: {}

[root@k8s-master01 ~]# kubectl create -f nginx.yaml 

[root@k8s-master01 ~]# kubectl get po
NAME                    READY   STATUS    RESTARTS   AGE
nginx-b5d5f997c-6v2w7   1/1     Running   0          5s
nginx-b5d5f997c-v9scx   1/1     Running   0          5s
nginx-b5d5f997c-xpbf9   1/1     Running   0          5s
# Service 名访问测试:
[root@k8s-master01 ~]# kubectl create deploy cluster-test --image=crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/debug-tools:latest -- sleep 3600

[root@k8s-master01 ~]# kubectl get po
NAME                            READY   STATUS    RESTARTS   AGE
cluster-test-78df88bdc8-b55mb   1/1     Running   0          5m37s

[root@k8s-master01 ~]# kubectl exec -ti cluster-test-78df88bdc8-b55mb -- bash
(13:57 cluster-test-78df88bdc8-b55mb:/) nslookup nginx
Server:		10.96.0.10
Address:	10.96.0.10#53

Name:	nginx.default.svc.cluster.local
Address: 10.98.222.5

(13:57 cluster-test-78df88bdc8-b55mb:/) curl nginx
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
2.3 Service 类型
  • Kubernetes Service 主要包括以下几种类型:
    • ClusterIP:在集群内部使用,默认值,只能从集群中访问。
    • NodePort:在所有安装了 Kube-Proxy 的节点上打开一个端口,此端口可以代理至后端Pod,可以通过 NodePort 从集群外部访问集群内的服务,格式为 NodeIP:NodePort。
    • ExternalName:通过返回定义的 CNAME 别名,没有设置任何类型的代理,需要 1.7 或更高版本 kube-dns 支持。
    • LoadBalancer:使用云提供商的负载均衡器公开服务,成本较高。
2.4 NodePort 类型

如果将 Service 的 type 字段设置为 NodePort,则 Kubernetes 将从 --service-node-port-range 参数指定的范围(默认为 30000-32767)中自动分配端口,也可以手动指定 NodePort,创建该 Service 后,集群每个节点都将暴露一个端口,通过某个宿主机的 IP+端口即可访问到后端的应用。

# 定义一个 NodePort 类型的 Service 格式如下:
[root@k8s-master01 ~]# kubectl get svc nginx -oyaml > nginx-nodeport.yaml
[root@k8s-master01 ~]# vim nginx-nodeport.yaml 
[root@k8s-master01 ~]# cat nginx-nodeport.yaml 
apiVersion: v1
kind: Service
metadata:
  name: nginx-nodeport
  namespace: default
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: nginx
  type: NodePor
# 创建Service 
[root@k8s-master01 ~]# kubectl create -f nginx-nodeport.yaml 

[root@k8s-master01 ~]# kubectl get svc nginx-nodeport
NAME             TYPE       CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
nginx-nodeport   NodePort   10.107.186.200   <none>        80:31538/TCP   11s

# 检查对外访问 
[root@k8s-master01 ~]# curl 192.168.200.50:31538
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

浏览器访问

在这里插入图片描述

2.5 ExternalName 代理域名
2.5.1 基本使用

ExternalName Service 是 Service 的特例,它没有 Selector,也没有定义任何端口和 Endpoint,它通过返回该外部服务的别名来提供服务,和域名解析的 CNAME 类似。

比如可以定义一个 Service,后端设置为一个外部域名,这样通过 Service 的名称即可访问到该域名。使用 nslookup 解析以下文件定义的 Service,集群的 DNS 服务将返回一个值为www.taobao.com 的 CNAME 记录:

apiVersion: v1
kind: Service
metadata:
  name: my-externalname
spec:
  type: ExternalName
  externalName: www.taobao.com
2.5.2 使用案例

使用案例:假设某个项目具备 DEV/UAT 两个环境,每个环境需要链接指定的数据库等基础组件。基础组件同样也是在 K8s 中按照不同的环境进行划分和部署,比如 DEV 环境所用的基础组件均在 basic-component-dev 命名空间下,以此类推。

为了降低配置文件的维护复杂度,准备使用 ExternalName 类型的 Service 对基础组件的连接地址进行映射,这样就可以用同名的 Service 区分不同的环境,从而降低配置文件维护的复杂度。比如配置了在同一个项目的不同环境里面都配置一个同名的 Redis Service,类型为ExternalName,并且按照不同环境指向不同的基础组件地址,这样每个项的不同环境,都可以用 Redis 这一个地址就可以访问到不同基础组件。

1、部署两个redis服务,分别在不同的命名空间(我们管这些redis叫目标服务)

# 环境准备:
# 创建 Namespace
[root@k8s-master01 ~]# kubectl create ns basic-component-dev
[root@k8s-master01 ~]# kubectl create ns basic-component-uat

[root@k8s-master01 ~]# kubectl get ns
NAME                   STATUS   AGE
basic-component-dev    Active   9s
basic-component-uat    Active   4s


# 创建服务
[root@k8s-master01 ~]# kubectl create deploy redis -n basic-component-dev --image=crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/redis:7.2.5
[root@k8s-master01 ~]# kubectl create deploy redis -n basic-component-uat --image=crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/redis:7.2.5

[root@k8s-master01 ~]# kubectl get po -n basic-component-dev
NAME                     READY   STATUS    RESTARTS   AGE
redis-564b7bcf74-qnm89   1/1     Running   0          71s
[root@k8s-master01 ~]# kubectl get po -n basic-component-uat
NAME                     READY   STATUS    RESTARTS   AGE
redis-564b7bcf74-tzm99   1/1     Running   0          66s


# 创建 Service
[root@k8s-master01 ~]# kubectl expose deploy redis --port 6379 -n basic-component-dev
[root@k8s-master01 ~]# kubectl expose deploy redis --port 6379 -n basic-component-uat

[root@k8s-master01 ~]# kubectl get svc -n basic-component-dev
NAME    TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)    AGE
redis   ClusterIP   10.104.193.4   <none>        6379/TCP   76s
[root@k8s-master01 ~]# kubectl get svc -n basic-component-uat
NAME    TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
redis   ClusterIP   10.100.159.225   <none>        6379/TCP   75s

2、随意创建一个redis服务(任意空间),并修改key值后续做测试使用(仅作连接测试使用)

# 访问测试:
# 创建一个专门用于测试的 Redis 客户端
[root@k8s-master01 ~]# kubectl create deploy redis-cli --image=crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/redis:7.2.5
[root@k8s-master01 ~]# kubectl get po
NAME                            READY   STATUS    RESTARTS        AGE
....
redis-cli-7d5cc47ff9-7kk7t      1/1     Running   0               4s


# 测试每个环境的 Redis 基础组件
[root@k8s-master01 ~]# kubectl exec -it redis-cli-7d5cc47ff9-7kk7t -- bash
root@redis-cli-7d5cc47ff9-7kk7t:/data# redis-cli -h redis.basic-component-dev
redis.basic-component-dev:6379> set a dev
OK
redis.basic-component-dev:6379> get a
"dev"
 
root@redis-cli-7d5cc47ff9-7kk7t:/data# redis-cli -h redis.basic-component-uat
redis.basic-component-uat:6379> set a uat
OK
redis.basic-component-uat:6379> get a
"uat"

3、创建两个新命名空间,并为目标服务的redis做代理(此空间下的服务叫源服务)

创建项目的两个环境:
[root@k8s-master01 ~]# kubectl create ns projecta-dev
[root@k8s-master01 ~]# kubectl create ns projecta-uat

[root@k8s-master01 ~]# kubectl get ns
NAME                   STATUS   AGE
....
projecta-dev           Active   11s
projecta-uat           Active   4s


# 在每个项目的环境下,创建一个 externalName 类型的Service,用于连接到不同环境的基础组件:
[root@k8s-master01 ~]# vim externalname.yaml 
[root@k8s-master01 ~]# cat externalname.yaml 
apiVersion: v1
kind: Service
metadata:
  name: redis
  namespace: projecta-dev
spec:
  type: ExternalName
  externalName: redis.basic-component-dev.svc.cluster.local
---
apiVersion: v1
kind: Service
metadata:
  name: redis
  namespace: projecta-uat
spec:
  type: ExternalName
  externalName: redis.basic-component-uat.svc.cluster.local

[root@k8s-master01 ~]# kubectl create -f externalname.yaml 

4、在两个源服务命名空间下分别创建一个redis服务

# 接下来在每个项目的环境下,创建两个 Redis 客户端,用于模拟需要链接 Redis 的应用程序:
[root@k8s-master01 ~]# kubectl create deploy usercenter --image=crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/redis:7.2.5 -n projecta-dev
[root@k8s-master01 ~]# kubectl create deploy usercenter --image=crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/redis:7.2.5 -n projecta-uat

[root@k8s-master01 ~]# kubectl get po -n projecta-dev
NAME                         READY   STATUS    RESTARTS   AGE
usercenter-f5f49fcfc-8zdsb   1/1     Running   0          36s
[root@k8s-master01 ~]# kubectl get po -n projecta-uat
NAME                         READY   STATUS    RESTARTS   AGE
usercenter-f5f49fcfc-j9gjz   1/1     Running   0          31s

5、分别让源空间下的redis服务(开发/测试)去访问目标服务下的redis

# 测试每个环境下的 externalName:
# 开发环境
[root@k8s-master01 ~]# kubectl exec -it usercenter-f5f49fcfc-8zdsb -n projecta-dev -- bash
root@usercenter-f5f49fcfc-8zdsb:/data# redis-cli -h redis
redis:6379> get a
"dev"

# UAT 环境
root@usercenter-f5f49fcfc-8zdsb:/data# 
root@usercenter-f5f49fcfc-8zdsb:/data# exit
exit
[root@k8s-master01 ~]# kubectl exec -it usercenter-f5f49fcfc-j9gjz -n projecta-uat -- bash
root@usercenter-f5f49fcfc-j9gjz:/data# redis-cli -h redis
redis:6379> get a
"uat"
2.6 使用 Service 代理 K8s 外部服务

使用场景:

  • 希望在生产环境中使用某个固定的名称而非 IP 地址访问外部的中间件服务;
  • 希望 Service 指向另一个 Namespace 中或其他集群中的服务;
  • 正在将工作负载转移到 Kubernetes 集群,但是一部分服务仍运行在 Kubernetes 集群之外的 backend。
[root@k8s-master01 ~]# vim baidu.yaml 
[root@k8s-master01 ~]# cat baidu.yaml 
apiVersion: v1
kind: Service
metadata:
  labels:
    app: baidu
  name: baidu
spec:
  ports:
  - name: http
    port: 80
    protocol: TCP
    targetPort: 80
  sessionAffinity: None
  type: ClusterIP
---
apiVersion: v1
kind: Endpoints            
metadata:
  labels:
    app: baidu
  name: baidu
subsets:
- addresses:
  - ip: 182.61.201.211      # 此为baidu.com真实IP
  ports:
  - name: http
    port: 80
    protocol: TCP
  
[root@k8s-master01 ~]# kubectl create -f baidu.yaml 

Endpoint IP 地址不能是loopback(127.0.0.0/8)、link-local(169.254.0.0/16)或者 linklocal多播地址(224.0.0.0/24)。

[root@k8s-master01 ~]# kubectl get svc baidu
NAME    TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
baidu   ClusterIP   10.101.43.61   <none>        80/TCP    6m48s
[root@k8s-master01 ~]# kubectl get ep baidu
NAME    ENDPOINTS           AGE
baidu   182.61.201.211:80   6m54s

[root@k8s-master01 ~]# curl 10.101.43.61:80
<html>
<meta http-equiv="refresh" content="0;url=http://www.baidu.com/">
</html>

访问没有 Selector 的 Service 与有 Selector 的 Service 的原理相同,通过 Service 名称即可访问,请求将被路由到用户定义的 Endpoints

2.7 多端口 Service

有的程序可能会监听多个端口,Service 也支持同时代理多个端口。比如在 K8s 中部署一个RabbitMQ,它具有两个端口,5672 是程序连接用于数据交互的接口,15672 是 RabbitMQ 管理页面的端口。

首先在 K8s 上部署一个 RabbitMQ:
[root@k8s-master01 ~]# kubectl create deploy rabbitmq --image=crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/rabbitmq:3-management
[root@k8s-master01 ~]# kubectl get po 
NAME                            READY   STATUS    RESTARTS      AGE
rabbitmq-58479c594b-pqlpb       1/1     Running   0             2m17s


# 接下来可以创建一个 Service,把 5672 指向 Pod 的 5672,15672 指向 15672:
[root@k8s-master01 ~]# vim rabbitmq.yaml 
[root@k8s-master01 ~]# cat rabbitmq.yaml 
apiVersion: v1
kind: Service
metadata:
  labels:
    app: rabbitmq
  name: rabbitmq
spec:
  ports:
  - name: amqp
    port: 5672
    protocol: TCP
    targetPort: 5672
  - name: http
    port: 15672
    protocol: TCP
    targetPort: 15672
  selector:
    app: rabbitmq
  type: NodePort

# 创建service
[root@k8s-master01 ~]# kubectl create -f rabbitmq.yaml 

[root@k8s-master01 ~]# kubectl get svc rabbitmq
NAME       TYPE       CLUSTER-IP    EXTERNAL-IP   PORT(S)                          AGE
rabbitmq   NodePort   10.97.66.74   <none>        5672:31856/TCP,15672:31239/TCP   7m51s

浏览器登录

在这里插入图片描述

2.8 会话保持
# K8s 的 Service 支持会话保持,但是目前仅支持基于客户端 IP 的会话保持:
[root@k8s-master01 ~]# kubectl edit svc nginx
apiVersion: v1
kind: Service
metadata:
  labels:
    app: nginx
  name: nginx
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: nginx
  sessionAffinity: ClientIP   # ClientIP:配置基于 IP 的会话保持,None:不开启会话保持
  sessionAffinityConfig:            # 会话保持配置
    clientIP:
        timeoutSeconds: 10800       # 会话保持配置时间
  type: ClusterIP
2.9 Headless Service
2.9.1 定义
  • Headless Service 是 Kubernetes 中一种特殊类型的 Service,它会直接暴露 Pod 的 IP 地址和DNS 记录给客户端,适用于有状态应用的服务发现和负载均衡以及需要直接访问 Pod IP 的应用场景。
  • Headless Service 不需要分配 ClusterIP,而是通过 DNS 记录直接返回 Pod 的 IP 地址,所以和普通 Service 最大的区别就是使用 nslookup 解析一个 Headless Service 返回的是 Pod IP, 而普通 Service 返回的是 Service 的 IP。
2.9.2 使用场景
  • 有状态应用的服务发现和负载均衡:有状态应用(如数据库、消息队列等)通常需要为每个 Pod 分配一个唯一的标识符(如 Pod 名称或 IP 地址),以便其他服务或其他节点可以连接到某个实例。Headless Service 可以满足这一需求,通过直接暴露 Pod 的 IP 地址和 DNS 记录,实现服务发现和负载均衡。
  • 需要直接访问 Pod IP 的应用:在某些情况下,客户端可能需要直接访问 Pod 的 IP 地址,而不需要通过 Service 的负载均衡机制,此时也可以通过 Headless Service 实现。
  • 分布式系统:在分布式系统中,各个节点之间需要直接通信,并且每个节点都有自己的身份和状态。Headless Service 可以为每个节点分配一个唯一的 DNS 实体名称,支持节点之间的直接交互和负载均衡
2.9.3 工作原理

当创建一个 Headless Service 时,Kubernetes 会执行以下操作:

  • 创建 DNS 记录:为每个 Pod 创建一个 DNS 记录,该记录的名称基于 Service 名称、Pod名称和命名空间定义,格式为<pod-name>.<service-name>.<namespace>.svc.cluster.local
  • 暴露 Pod IP:客户端可以通过查询 DNS 记录获取 Pod 的 IP 地址,并直接访问某个 Pod。比如创建一个名为 my-headless-service 的 Headless Service,这个 Service 匹配了 app=myapp 标签的 Pod,该服务具有三个副本,每个副本的名字是 pod-0、pod-1 和pod-2。此时可以通过如下 DNS 名字进行访问:
    • pod-0.my-headless-service.default.svc.cluster.local
    • pod-1.my-headless-service.default.svc.cluster.local
    • pod-2.my-headless-service.default.svc.cluster.local
2.9.4 Headless Service 使用
# 创建一个 StatefulSet 和 Headless Service:
[root@k8s-master01 ~]# vim headless.yaml 
[root@k8s-master01 ~]# cat headless.yaml 
apiVersion: v1
kind: Service
metadata:
  labels:
    app: headless
  name: headless
spec:
  ports:
  - port: 80
  clusterIP: None
  selector:
    app: headless
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: headless
spec:
  serviceName: "headless"
  replicas: 3
  selector:
    matchLabels:
      app: headless
  template:
    metadata:
      labels:
        app: headless
    spec:
      containers:
      - image: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/nginx:stable
        name: headless
        ports:
        - containerPort: 80
# 创建
[root@k8s-master01 ~]# kubectl create -f headless.yaml 

[root@k8s-master01 ~]# kubectl get po 
NAME                            READY   STATUS    RESTARTS       AGE
cluster-test-78df88bdc8-b55mb   1/1     Running   5 (4m7s ago)   5h8m
headless-0                      1/1     Running   0              13s
headless-1                      1/1     Running   0              11s
headless-2                      1/1     Running   0              9s

# 发现没有分配IP
[root@k8s-master01 ~]# kubectl get svc headless
NAME       TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
headless   ClusterIP   None         <none>        80/TCP    23s
# 首先查看下三个pod分别分配的地址
[root@k8s-master01 ~]# kubectl get po -l app=headless -owide
NAME         READY   STATUS    RESTARTS   AGE     IP              NODE         NOMINATED NODE   READINESS GATES
headless-0   1/1     Running   0          3m23s   172.16.85.235   k8s-node01   <none>           <none>
headless-1   1/1     Running   0          3m21s   172.16.58.243   k8s-node02   <none>           <none>
headless-2   1/1     Running   0          3m19s   172.16.85.236   k8s-node01   <none>           <none>

# 随意进入一个pod下
[root@k8s-master01 ~]# kubectl exec -it cluster-test-78df88bdc8-b55mb -- bash
# 可以直连IP地址
(19:04 cluster-test-78df88bdc8-b55mb:/) nslookup headless-0.headless
Server:		10.96.0.10
Address:	10.96.0.10#53

Name:	headless-0.headless.default.svc.cluster.local
Address: 172.16.85.235

(19:05 cluster-test-78df88bdc8-b55mb:/) nslookup headless-1.headless
Server:		10.96.0.10
Address:	10.96.0.10#53

Name:	headless-1.headless.default.svc.cluster.local
Address: 172.16.58.243

(19:06 cluster-test-78df88bdc8-b55mb:/) nslookup headless-2.headless
Server:		10.96.0.10
Address:	10.96.0.10#53

Name:	headless-2.headless.default.svc.cluster.local
Address: 172.16.85.236

# 负载均衡
(19:06 cluster-test-78df88bdc8-b55mb:/) nslookup headless           
Server:		10.96.0.10
Address:	10.96.0.10#53

Name:	headless.default.svc.cluster.local
Address: 172.16.85.235
Name:	headless.default.svc.cluster.local
Address: 172.16.58.243
Name:	headless.default.svc.cluster.local
Address: 172.16.85.236
2.10 Service 代理模式
2.10.1 Iptables 代理模式

Iptables 是 Linux 原生提供的一个功能强大的防火墙工具,可以用来设置、维护和检查 IPv4数据包,并且支持源目地址转换等规则。在 iptables 代理模式下,kube-proxy 通过监听 Kubernetes API Server 中 Service 和 Endpoint 对象的变化,动态地更新节点上的 iptables 规则,以实现请求的转发。

工作流程:

  • 当 Service 被创建或更新时,kube-proxy 会读取 Service 和 Endpoint 对象的信息,并生成相应的 iptables 规则
  • 这些 iptables 规则被添加到内核的 netfilter 处理链中,以拦截和转发目标为 Service IP 地址的流量
  • 当客户端访问 Service 的 IP 地址时,iptables 规则会将流量随机重定向到后端的一个或多个Pod

优点与缺点:

  • 优点:iptables 是 Linux 内核的一部分,性能稳定、可靠,iptables 规则易于理解和维护,功能多。
  • 缺点:随着 Service 数量的增加,iptables 规则的数量也会急剧增加,进而导致性能下降。iptables的更新操作可能会暂时锁定整个 iptables 规则表,影响网络性能。
2.10.2 IPVS 代理模式

IPVS(IP Virtual Server)是一种基于内核的负载均衡器,提供了比 iptables 更高的转发性能。在 IPVS 代理模式下,kube-proxy 通过配置 IPVS 负载均衡器规则来代替使用 iptables。IPVS 使用更高效的数据结构(如 Hash 表)来存储和查找规则,可以在大量 Service 的情况下也能保持高性能。

工作流程:

  • 当 Service 被创建或更新时,kube-proxy 会读取 Service 和 Endpoint 对象的信息,并配置IPVS 负载均衡策略
  • IPVS 负载均衡器会根据配置的调度算法(如轮询、最少连接等)将请求转发到后端的一个或多个 Pod 上
  • 当客户端访问 Service 的 IP 地址时,请求会直接被 IPVS 处理并转发到后端 Pod

优点与缺点:

  • 优点:IPVS 专为负载均衡设计,性能优于 iptables。并且支持多种调度算法,可以根据实际需求选择合适的算法,同时 IPVS 的更新操作对性能的影响较小
  • 缺点:在某些情况下,IPVS 可能需要依赖 iptables 来实现一些额外的功能(如源地址 NAT)

IPVS 负载均衡算法:

  • 轮询:rr,按顺序轮流将请求转发到后端的各个 Pod 上,实现请求的均匀分配
  • 最少链接:lc,将新的请求转发到当前连接数最少的 Pod 上,以平衡各 Pod 的负载
  • 源地址哈希:sh,根据请求的源 IP 地址进行哈希计算,将相同源地址的请求转发到同一个 Pod 上,实现会话保持
  • 目的地址哈希:dh,根据请求的目的 IP 地址(即 Service 的 Cluster IP)和端口进行哈希计算,选择后端 Pod
  • 无需队列等待:nq,如果后端 Pod 的队列为空,则直接选择该 Pod;如果所有 Pod 的队列都非空,则采用其他策略(如轮询或最少连接)来选择 Pod
  • 最短期望延迟:sed,考虑 Pod 的当前连接数和连接请求的平均处理时间,选择预计处理时间最短的 Pod 来接收新请求

3、K8s服务发布:南北流量管理Ingress

3.1 什么是Ingress

Ingress为K8s集群中的服务提供了一个统一的入口,可以提供负载均衡、SSL终止和基于名称(域名)的虚拟主机、应用的灰度发布等功能,在生产环境中常用的Ingress控制器有Treafik、Nginx、HAProxy、Istio等。

相对于Service,Ingress工作在七层(部分Ingress控制支持2和6层),所以可以支持HTTP协议的代理,也就是基于域名的匹配规则。

K8s使用域名发布服务的流程

在这里插入图片描述

Ingress Controller生产级高可用架构

在这里插入图片描述

3.2 Ingress Controller 生产级高可用推荐安装方式

官方 安装文档:

# 部分配置
kind: DaemonSet
spec:
  hostNetwork: true
  dnsPolicy: ClusterFirstWithHostNet
nodeSelector:
  kubernetes.io/os: linux
  ingress: "true"
# 修改节点标签,配置为 ingress 专用节点
[root@k8s-master01 ~]# kubectl label node k8s-node02 ingress=true

# 创建 Ingress
[root@k8s-master01 ~]# kubectl create -f ingress-nginx-daemonset.yaml

# 检查pod
[root@k8s-master01 ~]# kubectl get po -n ingress-nginx
NAME                                   READY   STATUS      RESTARTS   AGE
....
ingress-nginx-controller-rv2xj         1/1     Running     0          3m54s
# 部署后可以在 node02 节点上看到 nginx 进程
[root@k8s-node02 ~]#  netstat -lntp | grep nginx
tcp        0      0 0.0.0.0:443             0.0.0.0:*               LISTEN      1159164/ngin: mast 
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      1159164/ngin: mast 
tcp        0      0 127.0.0.1:10245         0.0.0.0:*               LISTEN      1159101/ngin-ingre 
tcp        0      0 127.0.0.1:10247         0.0.0.0:*               LISTEN      1159164/ngin: mast 
tcp        0      0 127.0.0.1:10246         0.0.0.0:*               LISTEN      1159164/ngin: mast 
tcp        0      0 0.0.0.0:8181            0.0.0.0:*               LISTEN      1159164/ngin: mast 
tcp6       0      0 :::443                  :::*                    LISTEN      1159164/ngin: mast 
tcp6       0      0 :::10254                :::*                    LISTEN      1159101/ngin-ingre 
tcp6       0      0 :::80                   :::*                    LISTEN      1159164/ngin: mast 
tcp6       0      0 :::8443                 :::*                    LISTEN      1159101/ngin-ingre 
tcp6       0      0 :::8181                 :::*                    LISTEN      1159164/ngin: mast 
3.3 Ingress 资源定义
apiVersion: networking.k8s.io/v1    # k8s >= 1.22 必须 v1
kind: Ingress
metadata:
  name: nginx-ingress
spec:
  ingressClassName: nginx           # 指定该 Ingress 被哪个 Controller 解析
  rules:                            # 定义路由匹配规则,可以配置多个
  - host:  nginx.test.com           # 定义域名  
    http:  
      paths:          # 详细的路由配置,可以配置多个
      - backend:      # 指定该路由的后端
         service:
           name: nginx
           port:
             number: 80
        path: /                             # 指定 PATH
        pathType: ImplementationSpecific    # 指定匹配规则
  • pathType:路径的匹配方式,目前有 ImplementationSpecific、Exact 和 Prefix 方式
    • Exact:精确匹配,比如配置的 path 为/bar,那么/bar/将不能被路由;
    • Prefix:前缀匹配,基于以 / 分隔的 URL 路径。比如 path 为/abc,可以匹配到/abc/bbb等,比较常用的配置;
    • ImplementationSpecific:这种类型的路由匹配根据 Ingress Controller 来实现,可以当做一个单独的类型,也可以当做 Prefix 和 Exact。ImplementationSpecific 是 1.18 版本引入 Prefix 和 Exact 的默认配置
3.4 Ingress 入门

Ingress Nginx 配置文档

3.4.1 使用域名发布 K8s 的服务
# 使用域名发布 K8s 的服务
# 创建一个 web 服务:
[root@k8s-master01 ~]# kubectl create deploy nginx --replicas=3 --image=crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/nginx:1.15

[root@k8s-master01 ~]# kubectl get pod
NAME                            READY   STATUS    RESTARTS      AGE
nginx-5f58c9c676-ctgpp          1/1     Running   0             4s
nginx-5f58c9c676-ffc26          1/1     Running   0             4s
nginx-5f58c9c676-ns9q5          1/1     Running   0             4s


# 暴露服务:
[root@k8s-master01 ~]# kubectl expose deploy nginx --port 80

[root@k8s-master01 ~]# kubectl get svc nginx
NAME    TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
nginx   ClusterIP   10.102.199.81   <none>        80/TCP    13s
# 创建 Ingress:
[root@k8s-master01 ~]# vim web-ingress.yaml
[root@k8s-master01 ~]# cat web-ingress.yaml 
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx-ingress
spec:
  ingressClassName: nginx           
  rules:
  - host: nginx.test.com
    http:
      paths:
      - backend:
         service:
           name: nginx
           port:
             number: 80
        path: /
        pathType: ImplementationSpecific 

[root@k8s-master01 ~]# kubectl create -f web-ingress.yaml 
[root@k8s-master01 ~]# kubectl get ingress
NAME            CLASS   HOSTS            ADDRESS          PORTS   AGE
nginx-ingress   nginx   nginx.test.com   192.168.200.52   80      39s
# 将域名IP解析到hosts文件当中
[root@k8s-master01 ~]# echo "192.168.200.52 nginx.test.com" >> /etc/hosts

# 访问测试
[root@k8s-master01 ~]# curl nginx.test.com
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
3.4.2 Ingress 特例:不配置域名发布服务(不推荐)
# 创建 Ingress:
[root@k8s-master01 ~]# vim ingress-no-host.yaml 
[root@k8s-master01 ~]# cat ingress-no-host.yaml 
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx-ingress-no-host
spec:
  ingressClassName: nginx
  rules:        # 这里就把域名去掉了,其他不变
  - http:
      paths:
      - backend:
         service:
           name: nginx
           port:
             number: 80
        path: /no-host      # 测试路径
        pathType: ImplementationSpecific 

[root@k8s-master01 ~]# kubectl create -f ingress-no-host.yaml 

[root@k8s-master01 ~]# kubectl get ingress
NAME                    CLASS   HOSTS            ADDRESS          PORTS   AGE
nginx-ingress           nginx   nginx.test.com   192.168.200.52   80      16m
nginx-ingress-no-host   nginx   *                                 80      9s
# 直接访问不通
[root@k8s-master01 ~]# curl 192.168.200.52
<html>
<head><title>404 Not Found</title></head>
<body>
<center><h1>404 Not Found</h1></center>
<hr><center>nginx</center>
</body>
</html>

# 这个访问不同是因为路径是瞎写的
[root@k8s-master01 ~]# curl 192.168.200.52/no-host
<html>
<head><title>404 Not Found</title></head>
<body>
<center><h1>404 Not Found</h1></center>
<hr><center>nginx/1.15.12</center>      # 出现了版本号,说明是可以被Controller路由的
</body>
</html>

3.5 Ingress 实战
3.5.1 配置练习环境
# 创建一个用于学习 Ingress 的 Namespace,之后所有的操作都在此 Namespace 进行:
[root@k8s-master01 ~]# kubectl create ns study-ingress
[root@k8s-master01 ~]# kubectl get ns study-ingress
NAME            STATUS   AGE
study-ingress   Active   9s


# 创建一个 Nginx 模拟 Web 服务:
[root@k8s-master01 ~]# kubectl create deploy nginx --replicas=3 --image=crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/nginx:1.15 -n study-ingress

[root@k8s-master01 ~]# kubectl get po -n study-ingress
NAME                     READY   STATUS    RESTARTS   AGE
nginx-5f58c9c676-fkwrk   1/1     Running   0          64s
nginx-5f58c9c676-kkb75   1/1     Running   0          64s
nginx-5f58c9c676-wj9r6   1/1     Running   0          64s


# 创建 Service:
[root@k8s-master01 ~]# kubectl expose deploy nginx --port 80 -n study-ingress

[root@k8s-master01 ~]# kubectl get svc -n study-ingress
NAME    TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
nginx   ClusterIP   10.96.210.213   <none>        80/TCP    6s
3.5.2 使用 HTTPS 发布服务

生产环境对外的服务,一般需要配置 https 协议,使用 Ingress 也可以非常方便的添加 https的证书。

由于我们是学习环境,并没有权威证书,所以需要使用 OpenSSL 生成一个测试证书。如果
是生产环境,证书为在第三方公司购买的证书,无需自行生成:

# 创建证书
[root@k8s-master01 ~]# openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=nginx.test.com"

[root@k8s-master01 ~]# kubectl create secret tls ca-secret --cert=tls.crt --key=tls.key -n study-ingress

[root@k8s-master01 ~]# kubectl get secret -n study-ingress
NAME        TYPE                DATA   AGE
ca-secret   kubernetes.io/tls   2      13s
# 配置 Ingress 添加 TLS 配置:
[root@k8s-master01 ~]# vim ingress-ssl.yaml
[root@k8s-master01 ~]# cat ingress-ssl.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: https-ingress
  namespace: study-ingress
spec:
  ingressClassName: nginx       # ingress class 的名字
  rules:
  - host: nginx.test.com
    http:
      paths:
      - backend:
         service:
           name: nginx
           port:
             number: 80
        path: /
        pathType: ImplementationSpecific 
  tls:
  - hosts:                      # 证书所授权的域名列表
    - nginx.test.com
    secretName: ca-secret       # 证书的 Secret 名字
    
[root@k8s-master01 ~]# kubectl create -f ingress-ssl.yaml

[root@k8s-master01 ~]# kubectl get ingress -n study-ingress
NAME            CLASS   HOSTS            ADDRESS          PORTS     AGE
https-ingress   nginx   nginx.test.com   192.168.200.52   80, 443   32s
# 访问测试
[root@k8s-master01 ~]# curl http://nginx.test.com -I
HTTP/1.1 308 Permanent Redirect
Date: Thu, 12 Jun 2025 23:48:24 GMT
Content-Type: text/html
Content-Length: 164
Connection: keep-alive
Location: https://nginx.test.com

浏览器访问(需要在电脑hosts文件做映射)

在这里插入图片描述

3.5.3 域名添加用户名密码认证

有些开源工具本身不提供密码认证,如果暴露出去会有很大风险,对于这类工具可以使用 Nginx 的 basic-auth 设置密码访问,具体方法如下,由于需要使用 htpasswd 工具,所以需要安装httpd:

# 安装httpd
[root@k8s-master01 ~]# yum install httpd -y

# 使用 htpasswd 创建 test 用户的密码
[root@k8s-master01 ~]# htpasswd -c auth test
New password: 
Re-type new password: 
Adding password for user test

# 基于之前创建的密码文件创建 Secret
[root@k8s-master01 ~]# kubectl create secret generic basic-auth --from-file=auth -n study-ingress

[root@k8s-master01 ~]# kubectl get secret -n study-ingress
NAME         TYPE                DATA   AGE
basic-auth   Opaque              1      12s
ca-secret    kubernetes.io/tls   2      60m
# 创建包含密码认证的 Ingress
[root@k8s-master01 ~]# vim ingress-auth.yaml 
[root@k8s-master01 ~]# cat ingress-auth.yaml 
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: auth-ingress
  namespace: study-ingress
  annotations:
    # 需要密码认证的消息提醒
    nginx.ingress.kubernetes.io/auth-realm: Please Input Your Username and Password
    # 密码文件的 Secret 名称
    nginx.ingress.kubernetes.io/auth-secret: basic-auth
    # 认证类型,可以是 basic 和 digest
    nginx.ingress.kubernetes.io/auth-type: basic
spec:
  ingressClassName: nginx
  rules:
  - host: auth.test.com
    http:
      paths:
      - backend:
         service:
           name: nginx
           port:
             number: 80
        path: /
        pathType: ImplementationSpecific 
  tls:
  - hosts:
    - auth.test.com
    secretName: ca-secret
    
[root@k8s-master01 ~]# kubectl create -f ingress-auth.yaml 

浏览器访问(需要在电脑hosts文件做映射)

在这里插入图片描述

3.5.4 开启会话保持
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx-ingress
  namespace: study-ingress
  annotations:
    nginx.ingress.kubernetes.io/proxy-body-size: 16m
    nginx.ingress.kubernetes.io/affinity: "cookie"
    nginx.ingress.kubernetes.io/session-cookie-name: "route"
    # 过期时间,expires 兼容旧版浏览器
    nginx.ingress.kubernetes.io/session-cookie-expires: "172800"
    nginx.ingress.kubernetes.io/session-cookie-max-age: "172800"
    # 后端负载扩容后,是否需要重新分配流量,balanced: 重新分配 persistent: 保持粘
性
    nginx.ingress.kubernetes.io/affinity-mode: persistent
spec:
  ingressClassName: nginx
  rules:
  - host: nginx.test.com
    http:
      paths:
      - backend:
         service:
           name: nginx
           port:
             number: 80
        path: /
        pathType: ImplementationSpecific 
  tls:
  - hosts:
    - nginx.test.com
    secretName: ca-secret
3.5.5 配置流式返回 SSE(代理大模型服务)
# 如果后端服务需要持续的输出数据,或者需要长连接,此时需要更改请求头升级链接为长连接:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: https-ingress
  namespace: study-ingress
  annotations:
    nginx.ingress.kubernetes.io/proxy-http-version: "1.1"
    nginx.ingress.kubernetes.io/proxy-buffering: "off"
    # snippet 通常用于配置一些不支持或者复杂的参数,比如配置请求头,或者逻辑控制
    nginx.ingress.kubernetes.io/configuration-snippet: |
      proxy_set_header Updrade $http_updrade;
      proxy_set_header Connection 'upgrade';
spec:
  ingressClassName: nginx
  rules:
  - host: nginx.test.com
    http:
      paths:
      - backend:
         service:
           name: nginx
           port:
             number: 80
        path: /
        pathType: ImplementationSpecific
  tls:
  - hosts:
    - nginx.test.com
    secretName: ca-secret
3.5.6 域名重定向 Redirect

在使用 Nginx 作为代理服务器时,Redirect 可用于域名的重定向,比如访问 old.com 被重定向到 new.com。Ingress 也可以实现 Redirect 功能,接下来用 nginx.redirect.com 作为旧域名,baidu.com 作为新域名进行演示:

[root@k8s-master01 ~]# vim ingress-redirect.yaml 
[root@k8s-master01 ~]# cat ingress-redirect.yaml 
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: redirect-ingress
  namespace: study-ingress
  annotations:
    # 重定向到 https://www.baidu.com
    nginx.ingress.kubernetes.io/permanent-redirect: https://www.baidu.com
    nginx.ingress.kubernetes.io/permanent-redirect-code: "308"
spec:
  ingressClassName: nginx
  rules:
  - host: nginx.redirect.com
    http:
      paths:
      - backend:
         service:
           name: nginx
           port:
             number: 80
        path: /
        pathType: ImplementationSpecific
        
[root@k8s-master01 ~]# kubectl create -f ingress-redirect.yaml
[root@k8s-master01 ~]# kubectl get ingress -n study-ingress
NAME                  CLASS   HOSTS                ADDRESS          PORTS     AGE
redirect-ingress      nginx   nginx.redirect.com   192.168.200.52   80        2m

# 使用 curl 访问域名 nginx.redirect.com,可以看到308(使用浏览器会自动跳转到百度的首页):
[root@k8s-master01 ~]# curl -I nginx.redirect.com
HTTP/1.1 308 Permanent Redirect
Date: Fri, 13 Jun 2025 02:01:56 GMT
Content-Type: text/html
Content-Length: 164
Connection: keep-alive
Location: https://www.baidu.com
3.5.7 访问地址重写 Rewrite
# 创建一个应用模拟后端服务:
[root@k8s-master01 ~]# kubectl create deploy backend-api --image=crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/nginx:backend-api -n study-ingress

[root@k8s-master01 ~]# kubectl get po -n study-ingress
NAME                          READY   STATUS    RESTARTS   AGE
backend-api-b98656967-4wsfn   1/1     Running   0          12s


# 创建 Service 暴露该应用
[root@k8s-master01 ~]#  kubectl expose deploy backend-api --port 80 -n study-ingress

# 查看该 Service 的地址,并且通过/api-a 访问测试:
[root@k8s-master01 ~]# kubectl get svc -n study-ingress
NAME          TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
backend-api   ClusterIP   10.105.239.55   <none>        80/TCP    15s
# 配置 Ingress,假设需要配置一个/api-a 代理到该服务:
[root@k8s-master01 ~]# vim ingress-backend.yaml 
[root@k8s-master01 ~]# cat ingress-backend.yaml 
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: backend-api
  namespace: study-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
  ingressClassName: nginx
  rules:
  - host: nginx.rewrite.com
    http:
      paths:
      - backend:
         service:
           name: backend-api
           port:
             number: 80
        path: /api-a(/|$)(.*)
        pathType: ImplementationSpecific


[root@k8s-master01 ~]# kubectl create -f ingress-backend.yaml 
[root@k8s-master01 ~]# kubectl get ingress -n study-ingress
NAME                  CLASS   HOSTS                ADDRESS          PORTS     AGE
backend-api        nginx   nginx.rewrite.com    192.168.200.52   80        7s

浏览器访问(需要在电脑hosts文件做映射)

在这里插入图片描述

3.5.8 访问速率限制

有时候可能需要限制速率以降低后端压力,或者限制单个 IP 每秒的访问速率防止攻击。此时可以使用 Nginx 的 rate limit 进行配置。

# 首先没有加速率限制,使用 ab 进行访问,Failed 为 0:
[root@k8s-master01 ~]# ab -c 10 -n 100 https://auth.test.com/ | grep requests
Complete requests:      100
Failed requests:        0
[root@k8s-master01 ~]# vim ingress-auth.yaml 
[root@k8s-master01 ~]# cat ingress-auth.yaml 
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: auth-ingress
  namespace: study-ingress
  annotations:
    nginx.ingress.kubernetes.io/auth-realm: Please Input Your Username and Password
    nginx.ingress.kubernetes.io/auth-secret: basic-auth
    nginx.ingress.kubernetes.io/auth-type: basic
    nginx.ingress.kubernetes.io/limit-connections: "1"      # 添加速率限制,限制只能有一个连接
spec:
  ingressClassName: nginx
  rules:
  - host: auth.test.com
    http:
      paths:
      - backend:
         service:
           name: nginx
           port:
             number: 80
        path: /
        pathType: ImplementationSpecific 
        
[root@k8s-master01 ~]# kubectl replace -f ingress-auth.yaml
# 再次使用 ab 测试,Failed 为 5:
[root@k8s-master01 ~]# ab -c 10 -n 100 https://auth.test.com/ | grep requests
Complete requests:      100
Failed requests:        5


# 还有很多其它方面的限制,常用的配置如下:
#限制每秒的连接,单个 IP:
nginx.ingress.kubernetes.io/limit-rps

#限制每分钟的连接,单个 IP:
nginx.ingress.kubernetes.io/limit-rpm

#限制客户端每秒传输的字节数,单位为 K,需要开启 proxy-buffering:
nginx.ingress.kubernetes.io/limit-rate

# 速率限制白名单
nginx.ingress.kubernetes.io/limit-whitelist
3.5.9 Ingress Nginx 黑/白名单

1、配置黑名单

# 使用 nginx.ingress.kubernetes.io/denylist-source-range 添加黑名单,支持 IP、网段,多个黑名单逗号分隔:
[root@k8s-master01 ~]# cat ingress-ssl.yaml 
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: https-ingress
  namespace: study-ingress
  annotations:
    nginx.ingress.kubernetes.io/denylist-source-range: 192.168.200.50   # 添加黑名单
spec:
  ingressClassName: nginx
  rules:
  - host: nginx.test.com
    http:
      paths:
      - backend:
         service:
           name: nginx
           port:
             number: 80
        path: /
        pathType: ImplementationSpecific 
  tls:
  - hosts:
    - nginx.test.com
    secretName: ca-secret
 
# 更新该 Ingress  
[root@k8s-master01 ~]# kubectl replace -f ingress-ssl.yaml
# 访问测试
[root@k8s-master01 ~]# curl -I https://nginx.test.com -k
HTTP/2 403 
date: Fri, 13 Jun 2025 03:17:14 GMT
content-type: text/html
content-length: 146
strict-transport-security: max-age=15724800; includeSubDomains

2、配置白名单

# 白名单表示只允许某个 IP 可以访问,直接在 yaml 文件中配置即可,比如只允许
192.168.200.50 访问,只需要添加一个 nginx.ingress.kubernetes.io/whitelist-source-range 注释即可:

[root@k8s-master01 ~]# vim ingress-ssl.yaml 
[root@k8s-master01 ~]# cat ingress-ssl.yaml 
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: https-ingress
  namespace: study-ingress
  annotations:
    nginx.ingress.kubernetes.io/whitelist-source-range: 192.168.200.51  # 添加白名单
spec:
  ingressClassName: nginx
  rules:
  - host: nginx.test.com
    http:
      paths:
      - backend:
         service:
           name: nginx
           port:
             number: 80
        path: /
        pathType: ImplementationSpecific 
  tls:
  - hosts:
    - nginx.test.com
    secretName: ca-secret

# 更新该 Ingress  
[root@k8s-master01 ~]# kubectl replace -f ingress-ssl.yaml 
# 白名单IP访问:
[root@k8s-node01 ~]# curl -I https://nginx.test.com -k
HTTP/2 200 
date: Fri, 13 Jun 2025 03:28:54 GMT
content-type: text/html
content-length: 612
last-modified: Tue, 16 Apr 2019 13:08:19 GMT
etag: "5cb5d3c3-264"
accept-ranges: bytes
strict-transport-security: max-age=15724800; includeSubDomains

# 其他IP访问:
[root@k8s-master01 ~]# curl -I https://nginx.test.com -k
HTTP/2 403 
date: Fri, 13 Jun 2025 03:28:51 GMT
content-type: text/html
content-length: 146
strict-transport-security: max-age=15724800; includeSubDomains

3、全局黑白名单

# Ingress-nginx 支持全局的黑白名单(白名单慎用),只需要在 ingress nginx 的配置文件中添加即可,添加后无需重启 Controller,加一个全局黑名单:
[root@k8s-master01 ~]# kubectl edit cm ingress-nginx-controller -n ingress-nginx
apiVersion: v1
data:
  allow-snippet-annotations: "true"
  denylist-source-range: 192.168.200.52
....

# 配置全局黑名单后,访问任何域名都会被拒绝:
[root@k8s-node02 ~]# curl -I https://nginx.test.com -k
HTTP/2 403 
date: Fri, 13 Jun 2025 03:36:05 GMT
content-type: text/html
content-length: 146
strict-transport-security: max-age=15724800; includeSubDomains
# 添加一个全局白名单:
[root@k8s-master01 ~]# kubectl edit cm ingress-nginx-controller -n ingress-nginx
apiVersion: v1
data:
  allow-snippet-annotations: "true"
  whitelist-source-range: 192.168.200.50
....

# 只有白名单里面的IP是通的
[root@k8s-master01 ~]# curl -I https://nginx.test.com -k
HTTP/2 200 
date: Fri, 13 Jun 2025 03:38:22 GMT
content-type: text/html
content-length: 612
last-modified: Tue, 16 Apr 2019 13:08:19 GMT
etag: "5cb5d3c3-264"
accept-ranges: bytes
strict-transport-security: max-age=15724800; includeSubDomains

# 其他非白名单在内的IP均不可访问
[root@k8s-node01 ~]# curl -I https://nginx.test.com -k
HTTP/2 403 
date: Fri, 13 Jun 2025 03:38:19 GMT
content-type: text/html
content-length: 146
strict-transport-security: max-age=15724800; includeSubDomains

[root@k8s-node02 ~]# curl -I https://nginx.test.com -k
HTTP/2 403 
date: Fri, 13 Jun 2025 03:38:13 GMT
content-type: text/html
content-length: 146
strict-transport-security: max-age=15724800; includeSubDomains
3.5.10 自定义错误页

官 方 文 档

每个项目在对外发布时,难免不了会有一些未知的错误,比如 404/502/503 等,为了给客户更加友好的提示,可以使用 default backend 自定义错误页

[root@k8s-master01 ~]# cat custom-default-backend.yaml 
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-errors
  labels:
    app.kubernetes.io/name: nginx-errors
    app.kubernetes.io/part-of: ingress-nginx
spec:
  selector:
    app.kubernetes.io/name: nginx-errors
    app.kubernetes.io/part-of: ingress-nginx
  ports:
  - port: 80
    targetPort: 8080
    name: http
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-errors
  labels:
    app.kubernetes.io/name: nginx-errors
    app.kubernetes.io/part-of: ingress-nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app.kubernetes.io/name: nginx-errors
      app.kubernetes.io/part-of: ingress-nginx
  template:
    metadata:
      labels:
        app.kubernetes.io/name: nginx-errors
        app.kubernetes.io/part-of: ingress-nginx
    spec:
      containers:
      - name: nginx-error-server
        image: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/custom-error-pages:v1.0.1 
        ports:
        - containerPort: 8080
        # Setting the environment variable DEBUG we can see the headers sent 
        # by the ingress controller to the backend in the client response.
        # env:
        # - name: DEBUG
        #   value: "true"

        # Mounting custom error page from configMap
        # volumeMounts:
        # - name: custom_error_pages
        #   mountPath: /www

      # Mounting custom error page from configMap
      # volumes:
      # - name: custom_error_pages
      #   configMap:
      #     name: custom_error_pages
      #     items:
      #     - key: "404"
      #       path: "404.html"
      #     - key: "503"
      #       path: "503.html"
# 首先需要安装 default backend 服务:
[root@k8s-master01 ~]# kubectl create -f custom-default-backend.yaml -n ingress-nginx

[root@k8s-master01 ~]# kubectl get po -n ingress-nginx
NAME                                   READY   STATUS      RESTARTS   AGE
nginx-errors-5c658df8bf-f9xcz          1/1     Running     0          21s

# 更改 ingress-nginx 的启动参数,支持自定义错误页:
[root@k8s-master01 ~]# kubectl edit ds -n ingress-nginx
....
    spec:
      containers:
      - args:
        - --default-backend-service=ingress-nginx/nginx-errors
....

# 配置 ConfigMap,定义哪些错误码被重定向到自定义错误页
[root@k8s-master01 ~]# kubectl edit cm ingress-nginx-controller -n ingress-nginx
apiVersion: v1
data:
  custom-http-errors: "404,502,503"
....

更新完成以后访问一个不存在的页面,比如之前定义的 nginx.test.com。访问一个不存在的页面 123,就会返回 Error Server 中的页面:

在这里插入图片描述

3.5.11 匹配请求头区分不同客户端
# 首先部署移动端应用:
[root@k8s-master01 ~]# kubectl create deploy phone --image=crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/nginx:phone -n study-ingress

[root@k8s-master01 ~]# kubectl get po -n study-ingress
NAME                          READY   STATUS    RESTARTS      AGE
phone-6b5ddd45c9-zm96z        1/1     Running   0             10s

# 创建手机端 Ingress:
[root@k8s-master01 ~]# vim ingress-phone.yaml 
[root@k8s-master01 ~]# cat ingress-phone.yaml 
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: phone
  namespace: study-ingress
spec:
  ingressClassName: nginx
  rules:
  - host: m.test.com
    http:
      paths:
      - backend:
         service:
           name: phone
           port:
             number: 80
        path: /
        pathType: ImplementationSpecific 

[root@k8s-master01 ~]# kubectl create -f ingress-phone.yaml
[root@k8s-master01 ~]# kubectl get ingress -n study-ingress
NAME            CLASS   HOSTS            ADDRESS          PORTS     AGE
phone           nginx   m.test.com       192.168.200.52   80        49s
# 部署电脑端应用:
[root@k8s-master01 ~]#  kubectl create deploy laptop --image=crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/nginx:laptop -n study-ingress

[root@k8s-master01 ~]# kubectl get po -n study-ingress
NAME                      READY   STATUS    RESTARTS   AGE
laptop-7566dbdb8c-dc5w8   1/1     Running   0          17s

# 创建 Service
[root@k8s-master01 ~]# kubectl expose deploy laptop --port 80 -n study-ingress
service/laptop exposed
[root@k8s-master01 ~]# kubectl get svc -n study-ingress
NAME     TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
laptop   ClusterIP   10.99.239.61    <none>        80/TCP    26s

# 之后创建电脑端的 Ingress,注意 Ingress annotations 的 nginx.ingress.kubernetes.io/serversnippet 配置。Snippet 配置是专门用于一些复杂的 Nginx 配置,和 Nginx 配置通用。匹配移动端实例如下:
[root@k8s-master01 ~]# vim ingress-laptop.yaml 
[root@k8s-master01 ~]# cat ingress-laptop.yaml 
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: laptop
  namespace: study-ingress
  annotations:
    nginx.ingress.kubernetes.io/server-snippet: |
      set $agentflag 0;
      if ($http_user_agent ~* "(Android|iPhone|WindowsPhone|UC|Kindle)" ){
        set $agentflag 1;
      }
      if ( $agentflag = 1 ) {
        return 301 http://m.test.com;
      }
spec:
  ingressClassName: nginx
  rules:
  - host: test.com
    http:
      paths:
      - backend:
         service:
           name: laptop
           port:
             number: 80
        path: /
        pathType: ImplementationSpecific
        
[root@k8s-master01 ~]# kubectl create -f ingress-laptop.yaml
[root@k8s-master01 ~]# kubectl get ingress -n study-ingress
NAME            CLASS   HOSTS            ADDRESS          PORTS     AGE
laptop          nginx   test.com         192.168.200.52   80        28s

首先通过浏览器访问 test.com,可以看到页面是 Laptop:

在这里插入图片描述

接下来使用浏览器的开发者工具将终端类型改为 iPhone,或者直接用 iPhone 手机访问(线上业务一般配置的都有 DNS,可以直接解析域名,测试环境可能需要自己单独配置),如下图所示:

在这里插入图片描述

3.5.12 灰度/金丝雀/蓝绿发布

1、创建 v1 版本

# 首先创建模拟 Production(生产)环境的 Namespace 和服务:
[root@k8s-master01 ~]# kubectl create ns production

# 创建 v1 版本的应用
[root@k8s-master01 ~]# kubectl create deploy canary-v1 --image=crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/canary:v1 -n production
[root@k8s-master01 ~]# kubectl get po -n production
NAME                         READY   STATUS    RESTARTS   AGE
canary-v1-5dd7b4fbf6-b9gtk   1/1     Running   0          17s

# 建立service
[root@k8s-master01 ~]# kubectl expose deploy canary-v1 --port 8080 -n production
[root@k8s-master01 ~]# kubectl get svc -n production
NAME        TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
canary-v1   ClusterIP   10.98.156.116   <none>        8080/TCP   10s
# 创建 V1 的 Ingress:
[root@k8s-master01 ~]# vim ingress-canary-v1.yaml 
[root@k8s-master01 ~]# cat ingress-canary-v1.yaml 
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: canary-v1
  namespace: production
spec:
  ingressClassName: nginx
  rules:
  - host: canary.com
    http:
      paths:
      - backend:
         service:
           name: canary-v1
           port:
             number: 8080
        path: /
        pathType: Prefix

[root@k8s-master01 ~]# kubectl create -f ingress-canary-v1.yaml
[root@k8s-master01 ~]# kubectl get ingress -n production
NAME        CLASS   HOSTS        ADDRESS          PORTS   AGE
canary-v1   nginx   canary.com   192.168.200.52   80      51s

使用浏览器访问该服务,可以看到 Canary v1 的页面

在这里插入图片描述

2、创建 v3 版本

# 首先创建模拟 canary(生产)环境的 Namespace 和服务:
[root@k8s-master01 ~]# kubectl create ns canary

# 创建 v2 版本的应用
[root@k8s-master01 ~]# kubectl create deploy canary-v2 --image=crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/canary:v2 -n canary
[root@k8s-master01 ~]# kubectl get po -n canary
NAME                        READY   STATUS    RESTARTS   AGE
canary-v2-c4f4ffddb-jdjlj   1/1     Running   0          7s

# 建立service
[root@k8s-master01 ~]# kubectl expose deploy canary-v2 --port 8080 -n canary
[root@k8s-master01 ~]# kubectl get svc -n canary
NAME        TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)    AGE
canary-v2   ClusterIP   10.98.59.177   <none>        8080/TCP   17s

3、Canary 版本切入部分流量
创建 v2 版本的 Ingress 时,需要添加两个注释,一个是 nginx.ingress.kubernetes.io/canary,表明是灰度环境,nginx.ingress.kubernetes.io/canary-weight 表明切多少流量到该环境,本示例为50%:

[root@k8s-master01 ~]# vim ingress-canary-v2.yaml 
[root@k8s-master01 ~]# cat ingress-canary-v2.yaml 
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: canary-v2
  namespace: canary
  annotations:
    nginx.ingress.kubernetes.io/canary: "true"
    nginx.ingress.kubernetes.io/canary-weight: "50"
spec:
  ingressClassName: nginx
  rules:
  - host: canary.com
    http:
      paths:
      - backend:
         service:
           name: canary-v2
           port:
             number: 8080
        path: /
        pathType: ImplementationSpecific

此时通过 nginx.ingress.kubernetes.io/canary-weight: "50"设置的权重是 50,即 v1:v2 为 5:5。再次访问可以看到页面会来回显示 v1 和 v2:

在这里插入图片描述

4、测试灰度发布
接下来使用 Ruby 脚本进行测试,此脚本会输出 v1 和 v2 的访问次数比值:

[root@k8s-master01 ~]# vim test-canary.rb
[root@k8s-master01 ~]# cat test-canary.rb 
counts = Hash.new(0)

100.times do
  output = `curl -s canary.com | grep 'Canary' | awk '{print $2}' | awk -F"<" '{print $1}'`
  counts[output.strip.split.last] += 1
end

puts counts
# 安装 ruby 并测试,可以看到大致的比例是 5:5
[root@k8s-master01 ~]# yum install ruby -y

[root@k8s-master01 ~]# ruby test-canary.rb
{"v2"=>49, "v1"=>51}
[root@k8s-master01 ~]# ruby test-canary.rb
{"v1"=>38, "v2"=>62}
[root@k8s-master01 ~]# ruby test-canary.rb
{"v1"=>54, "v2"=>46}
3.6 Ingress 常见报错排查

404 表示访问的路由不存在,通常问题如下:

  • Ingress 路径配置的不正确
  • Ingress 的配置未被 Controller 解析
  • 未使用正确的域名和路径访问
  • 代理的服务没有该路径
  • 请求的方法不同

413(Request Entity Too Large)报错
有时候需要上传一些大文件给程序,但是 nginx 默认允许的最大文件大小只有 8M,不足以满足生产最大上传需求,此时可以通过 nginx.ingress.kubernetes.io/proxy-body-size 参数进行更改(也可以在 ConfigMap 中全局添加):

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx
  namespace: study-ingress
  annotations:
    nginx.ingress.kubernetes.io/proxy-body-size: 32m
 spec:
....

503 一般是代理的服务不可用导致的,通常问题如下:

  • Ingress 代理配置错误,比如 Service 名字或端口写错
  • Ingress 代理的 Service 不存在
  • Ingress 代理的 Service 后端 Pod 不正常

504 一般是代理的服务处理请求的时间过长,导致 Nginx 等待超时,此时需要确认服务的处
理时长,或者查看服务是否有问题

CORS 跨域报错:CORS错误。说明被跨域给拦截了,可以添加跨域配置

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: longtime
  namespace: study-ingress
  annotations:
    # 允许跨域的请求方法
    nginx.ingress.kubernetes.io/cors-allow-methods: "PUT, GET, POST,OPTIONS, DELETE"
    # 允许携带的请求头
    nginx.ingress.kubernetes.io/cors-allow-headers: "X-Forwarded-For, Xapp123-XPTO"
    # 允许跨域的域名
    nginx.ingress.kubernetes.io/cors-allow-origin: "*"
 spec:
....

此博客来源于:https://edu.51cto.com/lecturer/11062970.html


网站公告

今日签到

点亮在社区的每一天
去签到