本教程是将以下内容中的概念付诸实践的四篇教程之一:2022年3月微服务专题:Kubernetes网络:
- 通过自动扩缩容降低Kubernetes延迟(本文)
- 通过速率限制保护Kubernetes API
- 保护Kubernetes应用免受SQL注入攻击
- 通过金丝雀部署提高正常运行时间和韧性
想了解如何使用NGINX支持更多Kubernetes网络用例的详细指南?下载免费电子书《使用NGINX管理Kubernetes流量:实用指南》。
贵组织在Kubernetes中构建了一款应用,现在越来越受欢迎!每日访问量从寥寥数人增至数百人,有时甚至达到数千人。但问题也随之而来……流量增长遭遇瓶颈,导致客户访问时出现延迟和超时。如果无法改善体验,用户将不再使用这款应用。
您勇敢的Kubernetes工程师已经找到了解决方案。部署Ingress控制器来路由流量,并设置自动扩缩策略,使Ingress控制器Pod的数量能够根据流量波动即时增减。现在,Ingress控制器Pod可以从容应对流量激增,“延迟,再见!”,并在流量下降时缩容以节省资源,“成本节省,你好!”做得好!
实验与教程概述
本博客是“2022年3月微服务”第1单元实验的配套内容,主题为“面向高流量网站设计Kubernetes集群架构”,演示如何使用NGINX Ingress Controller公开应用,并根据高流量自动扩缩Ingress Controller Pod。
要完成本教程,需要准备一台满足以下条件的计算机:
- 2 个或更多 CPU
- 2 GB可用内存
- 20 GB可用磁盘空间
- 互联网连接
- 容器或虚拟机管理器,例如Docker、Hyperkit、Hyper‑V、KVM、Parallels、Podman、VirtualBox或VMware Fusion/Workstation
- minikube 已安装
- Helm 已安装
- 一种可启动浏览器窗口的配置。如果无法启动,则需要确定如何通过浏览器访问相关服务。
为充分利用实验和教程,建议在开始前:
本教程使用以下技术:
- NGINX Ingress Controller(基于NGINX Open Source)
- Helm
- KEDA
- Locust
- minikube
- Podinfo
- Prometheus
每项挑战的说明均包含用于配置应用的YAML文件全文。也可以从我们的GitHub仓库复制这些内容。每个YAML文件的文本旁均提供GitHub链接。
本教程包含4项挑战:
挑战 1:在Kubernetes集群上配置一个简单应用
在本挑战中,您将创建minikube集群,并安装Podinfo作为示例应用。
创建Minikube集群
创建一个minikube集群。几秒钟后,系统会显示一条消息,确认部署成功。
$ minikube start 🏄 Done! kubectl is now configured to use "minikube" cluster and "default" namespace by default 安装Podinfo应用
Podinfo是一个“使用Go构建的Web应用,用于展示在Kubernetes中运行微服务的最佳实践”。由于它占用的资源较少,我们将其用作示例应用。
- 使用任意文本编辑器创建一个名为“1-deployment.yaml”的YAML文件,并添加以下内容(也可以从GitHub复制)。该文件定义了一个包含单个副本的Deployment和一个Service。
apiVersion: apps/v1 kind: Deployment
metadata:
name: podinfo
spec:
selector:
matchLabels:
app: podinfo
template:
metadata:
labels:
app: podinfo
spec:
containers:
- name: podinfo
image: stefanprodan/podinfo
ports:
- containerPort: 9898
---
apiVersion: v1
kind: Service
metadata:
name: podinfo
spec:
ports:
- port: 80
targetPort: 9898
nodePort: 30001
selector:
app: podinfo
type: LoadBalancer - 部署应用:
$ kubectl apply -f 1-deployment.yaml deployment.apps/podinfo created
service/podinfo created- 确认Podinfo Pod已部署,依据是
Running值显示在STATUS列中。
$ kubectl get podsNAME READY STATUS RESTARTS AGE
podinfo-5d76864686-rd2s5 1/1 Running 0 3m38s- 在浏览器中打开Podinfo。页面上的“greetings from podinfo”表示Podinfo正在运行。
$ minikube service podinfo挑战2:使用NGINX Ingress Controller将流量路由到应用
在本挑战中,您将部署NGINX Ingress Controller,并将其配置为把流量路由到Podinfo应用。
部署NGINX Ingress Controller
安装NGINX Ingress Controller最快捷的方式是使用Helm。
- 将NGINX仓库添加到Helm:
$ helm repo add nginx-stable https://helm.nginx.com/stable - 下载并安装基于NGINX Open Source的NGINX Ingress Controller,该控制器由F5 NGINX维护。输出的最后一行用于确认安装成功。
$ helm install main nginx-stable/nginx-ingress \ --set controller.watchIngressWithoutClass=true \ --set controller.service.type=NodePort \ --set controller.service.httpPort.nodePort=30005
NAME: main
LAST DEPLOYED: Tue Mar 15 09:49:17 2022
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES: The NGINX Ingress Controller has been installed.- 确认NGINX Ingress Controller Pod已部署,依据是
Running值显示在STATUS列中(为便于阅读,输出分为两行显示)。
$ kubectl get podsNAME READY STATUS ...
main-nginx-ingress-779b74bb8b-mtdkr 1/1 Running ...
podinfo-5d76864686-fjncl 1/1 Running ...
... RESTARTS AGE
... 0 18s
... 0 2m36s将流量路由到您的应用
- 使用任意文本编辑器创建一个名为2-ingress.yaml的YAML文件,并填入以下内容(也可以从GitHub复制)。该文件定义了将流量路由到Podinfo所需的Ingress清单。
apiVersion: networking.k8s.io/v1 kind: Ingress
metadata:
name: podinfo
spec:
ingressClassName: nginx
rules:
- host: "example.com"
http:
paths:
- backend:
service:
name: podinfo
port:
number: 80
path: /
pathType: Prefix - 部署Ingress资源:
$ kubectl apply -f 2-ingress.yaml ingress.networking.k8s.io/podinfo created 挑战 3:生成并监控流量
在本挑战中,您将观察NGINX Ingress Controller在不同流量负载下的性能。准备工作包括:列出指标,即NGINX Ingress Controller提供的指标;部署Prometheus;以及安装Locust。然后,使用Locust模拟流量激增,并在Prometheus中跟踪其对性能的影响。
正如您已经了解到的,Ingress控制器是一个常规的Kubernetes Pod,其中包含一个反向代理(在本例中为NGINX)以及一些用于与Kubernetes集成的代码。如果应用收到大量流量,可能需要增加NGINX Ingress Controller Pod的副本数量,以避免NGINX Ingress Controller因负载过高而导致延迟。
列出可用指标
要确定何时扩缩容以及扩缩容的幅度,需要掌握有关NGINX Ingress Controller性能的准确信息。本教程使用NGINX的活动连接数指标(nginx_connections_active)来确定何时扩缩容。接下来,验证NGINX Ingress Controller是否跟踪该指标。
NGINX Ingress Controller可公开多个指标:本教程使用基于NGINX Open Source的模型,可公开8个指标;基于NGINX Plus的模型则可公开80多个指标。
- 获取NGINX Ingress Controller Pod的IP地址,以便查询其指标列表。该地址显示在
IP字段中,此处为172.17.0.4。(为便于阅读,省略了RESTARTS和AGE列,并将输出分为两行显示。)
$ kubectl get pods -o wide NAME READY STATUS ...
main-nginx-ingress-779b74bb8b-6hdwx 1/1 Running ...
podinfo-5d76864686-nl8ws 1/1 Running ...
... IP NODE NOMINATED NODE READINESS GATES
... 172.17.0.4 minikube <none> <none>
... 172.17.0.3 minikube <none> <none>- 在Kubernetes集群内的主机上创建一个带有shell的临时BusyBox Pod:
$ kubectl run -ti --rm=true busybox --image=busyboxIf you don't see a command prompt, try pressing enter.
/ # - 列出NGINX Ingress Controller生成的指标,并确认其中包含
nginx_connections_active。将<IP_address>替换为步骤1中获取的值。
/# wget -qO- <IP_address>:9113/metrics- 退出shell,返回Kubernetes服务器。
/# exit 部署Prometheus
现在,您已经知道NGINX Ingress Controller会跟踪nginx_connections_active指标,接下来需要使用工具来收集(“抓取”)这些指标。本教程使用Prometheus。
对于NGINX Ingress Controller,使用Helm可以快速安装Prometheus。
- 将Prometheus存储库添加到Helm:
$ helm repo add prometheus-community https://prometheus-community.github.io/helm-charts- 下载并安装Prometheus:
$ helm install prometheus prometheus-community/prometheus \ --set server.service.type=NodePort --set server.service.nodePort=30010- 验证安装情况。安装通常最多需要60秒才能完成。在以下示例输出中,验证命令是在
helminstall命令运行几秒后执行的,因此可以看到安装仍在进行,部分Prometheus Pod的ContainerCreating状态显示在STATUS字段中。当所有Pod的状态均为Running时,安装即完成。(为便于阅读,输出分为两行显示。)
$ kubectl get podsNAME READY ...
main-nginx-ingress-779b74bb8b-mtdkr 1/1 ...
podinfo-5d76864686-fjncl 1/1 ...
prometheus-alertmanager-d6d94cf4b-85ww5 0/2 ...
prometheus-kube-state-metrics-7cd8f95cb-86hhs 0/1 ...
prometheus-node-exporter-gqxfz 1/1 ...
prometheus-pushgateway-56745d8d8b-qnwcb 0/1 ...
prometheus-server-b78c9449f-kwhzp 0/2 ...
... STATUS RESTARTS AGE
... Running 0 3m23s
... Running 0 5m41s
... ContainerCreating 0 7s
... Running 0 7s
... Running 0 7s
... ContainerCreating 0 7s
... ContainerCreating 0 7s- 打开Prometheus。在minikube环境中运行以下命令,即可在默认浏览器中打开Prometheus仪表板。
$ minikube service prometheus-server- 如下所示的页面表示服务器运行正常。

- 在搜索栏中输入
nginx_ingress_nginx_connections_active,查看活动连接指标的当前值。此时会看到1个活动连接,这是因为已部署1个NGINX Ingress Controller Pod。
安装Locust
在下一部分中,将使用Locust这一开源负载测试工具来模拟流量激增,以便在Prometheus中观察NGINX Ingress Controller的性能。现在部署Locust。
- 使用任意文本编辑器创建一个名为“3-locust.yaml”的YAML文件,并添加以下内容(也可以从GitHub复制)。Deployment和Service对象用于定义Locust Pod。ConfigMap对象用于定义一个名为“locustfile.py”的脚本,该脚本会生成发送到Pod的请求,并包含正确的标头。
apiVersion: v1
kind: ConfigMap
metadata:
name: locust-script
data:
locustfile.py: |-
from locust import HttpUser, task, between
class QuickstartUser(HttpUser):
wait_time = between(0.7, 1.3)
@task
def hello_world(self):
self.client.get("/", headers={"Host": "example.com"})
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: locust
spec:
selector:
matchLabels:
app: locust
template:
metadata:
labels:
app: locust
spec:
containers:
- name: locust
image: locustio/locust
ports:
- containerPort: 8089
volumeMounts:
- mountPath: /home/locust
name: locust-script
volumes:
- name: locust-script
configMap:
name: locust-script
---
apiVersion: v1
kind: Service
metadata:
name: locust
spec:
ports:
- port: 8089
targetPort: 8089
nodePort: 30015
selector:
app: locust
type: LoadBalancer - 部署Locust:
$ kubectl apply -f 3-locust.yaml configmap/locust-script created
deployment.apps/locust created
service/locust created 模拟流量激增并观察其对性能的影响
- 在浏览器中打开Locust。
$ minikube service locust-

- 在各字段中输入以下值:
- 用户数:1000
- 生成速率:10
- 主机:http://main-nginx-ingress
- 点击“开始群发流量”按钮,将流量发送到Podinfo应用。
- 返回Prometheus仪表板,查看NGINX Ingress Controller的响应情况。您可能需要重新查询
nginx_ingress_nginx_connections_active,才能看到变化。如下方屏幕输出所示,随着大量连接建立,单个NGINX Ingress Controller Pod难以在不增加延迟的情况下处理增长的流量。Prometheus图表显示,每个NGINX Ingress Controller Pod约有100个活动连接时,延迟会开始激增。您可以根据此信息判断何时需要增加NGINX Ingress Controller Pod的数量,以避免延迟增加。
挑战 4:自动扩缩 NGINX Ingress Controller
在最后一项挑战中,您将构建一个配置,使资源能够随着流量增加而自动扩缩容。本教程使用KEDA实现自动扩缩容,因此首先需要安装KEDA并创建策略,定义何时以及如何进行扩缩容。与挑战3一样,随后使用Locust模拟流量激增,并使用Prometheus观察启用自动扩缩容后NGINX Ingress Controller的性能。
安装 KEDA
KEDA是一款Kubernetes事件驱动型自动扩缩器,集成了指标服务器(用于存储和转换Kubernetes指标的组件),并可直接使用Prometheus及其他工具中的指标。它使用这些指标创建水平Pod自动扩缩器(HPA),将Prometheus收集的指标接入并提供给Kubernetes。

与NGINX Ingress Controller和Prometheus一样,本教程使用Helm安装KEDA。
- 将KEDA添加到Helm仓库:
$ helm repo add kedacore https://kedacore.github.io/charts
"kedacore" has been added to your repositories - 安装KEDA:
$ helm install keda kedacore/keda NAME: keda
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None- 验证KEDA是否以两个Pod运行。(为便于阅读,
NAME列中的部分值已缩短。此外,RESTARTS列已省略;所有Pod的该值均为0。)
$ kubectl get pods NAME READY STATUS AGE
keda-operator-8644dcdb79-492x5 1/1 Running 59s keda-operator-metrics-apiserver-66d... 1/1 Running 59s
locust-77c699c94d-dvb5n 1/1 Running 8m59s
main-nginx-ingress-779b74bb8b-v7ggw 1/1 Running 48m
podinfo-5d76864686-c98rb 1/1 Running 50m
prometheus-alertmanager-d6d94cf4b-8... 2/2 Running 37m
prometheus-kube-state-metrics-7cd8f... 1/1 Running 37m
prometheus-node-exporter-j4qf4 1/1 Running 37m
prometheus-pushgateway-56745d8d8b-9n4nl 1/1 Running 37m
prometheus-server-b78c9449f-6ktn9 2/2 Running 37m创建自动扩缩策略
现在,使用KEDA的ScaledObject自定义资源定义(CRD)来定义控制NGINX Ingress Controller扩缩容方式的参数。以下配置:
- 根据Prometheus收集的
nginx_connections_active指标值触发自动扩缩容 - 当每个现有pod的活动连接数达到100时,部署一个新pod
- 将NGINX Ingress Controller Pod从1个自动扩缩至最多20个
执行以下步骤:
- 使用您选择的文本编辑器创建一个名为4-scaled-object.yaml的YAML文件,并填入以下内容(也可以从GitHub复制)。该文件定义了一个KEDA
ScaledObject。
apiVersion: keda.sh/v1alpha1 kind: ScaledObject
metadata:
name: nginx-scale
spec:
scaleTargetRef:
kind: Deployment
name: main-nginx-ingress
minReplicaCount: 1
maxReplicaCount: 20
cooldownPeriod: 30
pollingInterval: 1
triggers:
- type: prometheus
metadata:
serverAddress: http://prometheus-server
metricName: nginx_connections_active_keda
query: |
sum(avg_over_time(nginx_ingress_nginx_connections_active{app="main-nginx-ingress"}[1m]))
threshold: "100" - 部署
ScaledObject:
$ kubectl apply -f 4-scaled-object.yaml scaledobject.keda.sh/nginx-scale created 模拟流量激增并观察自动扩缩容对性能的影响
为了充分测试自动扩缩容的效果,将连接数增加到挑战 3 中的两倍。
- 在浏览器中返回Locust服务器。在各字段中输入以下值,然后点击“开始生成负载”按钮:
- 用户数:2000
- 生成速率:10
- 主机:http://main-nginx-ingress
- 返回Prometheus和Locust仪表板。Prometheus图表下方的粉色框显示NGINX Ingress Controller Pod扩缩容时的数量变化。

- 切换回终端,手动检查KEDA HPA。输出中的
REPLICAS字段显示当前已部署的Pod副本数。(为便于阅读,输出分为两行显示。)
$ kubectl get hpa
NAME REFERENCE ...
keda-hpa-nginx-scale Deployment/main-nginx-ingress ...
... TARGETS MINPODS MAXPODS REPLICAS AGE
... 101500m/100 (avg) 1 20 10 2m45s后续步骤
仅根据活动连接数进行自动扩缩容存在一个潜在限制。如果NGINX Ingress Controller负载过高,以至于即使扩容后仍不得不丢弃连接,自动扩缩容器会看到活动连接数减少,将其解读为请求量下降,并减少副本数。这可能导致性能进一步下降,但结合使用多项指标可以避免这种情况。例如,nginxplus_connections_dropped(适用于基于NGINX Plus的NGINX Ingress Controller)可跟踪这些被丢弃的客户端连接。
要试用搭配NGINX Plus和NGINX App Protect的NGINX Ingress Controller,请立即开始30天免费试用,或联系我们,讨论您的用例。
要试用搭配NGINX Open Source的NGINX Ingress Controller,可以获取发布版源代码,也可以从DockerHub下载预构建容器。
相关博客文章
NGINX Plus R26 正式发布
NGINX Plus R26通过缓存JSON Web密钥集加快JWT验证,并强化TLS握手,从而提升安全性。NGINX JavaScript的新功能包括增强对异步函数的支持,以及实现WebCrypto API。
使用NGINX App Protect DoS保护gRPC应用,抵御严重的DoS攻击
gRPC具备开发人员设计和部署现代应用所需的速度与灵活性,但其开放性也使其极易受到第7层DoS攻击。NGINX App Protect DoS可保护gRPC应用免受此类破坏性攻击。
Ingress Controller 选型指南(第 2 部分):风险与面向未来的规划
了解选择错误的Ingress控制器可能带来的风险,以及如何从关键方面着手,让您的选择更好地适应未来需求。
NGINX Plus R19 正式发布
NGINX Plus R19扩展了监控功能,不仅提供更多指标,还新增了指标分析方式;增加试运行模式,用于测试限速效果;增强键值存储,以支持IP地址范围;并使限速更加动态。
NGINX现已正式加入F5
NGINX现已正式成为F5的一部分。Gus Robertson现任F5 NGINX业务部门负责人。他阐述了两家公司在人才、文化和愿景方面融合的价值,以及双方将如何携手增强NGINX的开源产品和商业产品。

