过去几年,人们对 Kubernetes 的兴趣稳步增长,许多企业正在其生产环境中将其与微服务架构一起采用。然而,采用分布式服务带来了新的挑战。了解和调试基于微服务的应用程序中发生的情况可能很困难,尤其是在存在大量服务的情况下。为了发现故障或性能问题,您需要一个分布式跟踪工具,当数据在构成应用程序的微服务之间传递时,该工具可以端到端地跟踪请求。
OpenTracing 是分布式跟踪的规范和 API 集。在上一篇文章中,我们展示了如何使用 OpenTracing 社区创建的开源模块 (nginx-opentracing),为由 NGINX Open Source 和 NGINX Plus 代理和负载平衡的应用程序启用分布式跟踪。在撰写本文时,开放跟踪提供了九种编程语言的库。
没有w,当使用 Kubernetes 的 NGINX 和 NGINX Plus 入口控制器来平衡集群中的流量时,我们还添加了对 Kubernetes 集群中 HTTP 和 gRPC 请求的 OpenTracing 的本机支持。
使用 OpenTracing 有多种用例,这里我们重点关注通过请求上下文传播来跟踪服务器端点。在分布式环境中,集群内的每个应用程序都被视为不同的服务器。想象一下两个应用程序或服务都参与处理来自客户端的请求。例如,在下图所示的拓扑中,App1 是处理 HTTP 请求并将其重定向到 App2 的 Web 服务器。这两个应用程序都在由 NGINX Ingress Controller 进行负载平衡的 Kubernetes 集群内运行,并且启用了 OpenTracing,因此我们可以跟踪来自 Ingress Controller 的请求通过 App1 并到达 App2。
有关组件 i 执行的每个操作的信息系统(例如服务)在 OpenTracing 所谓的跨度中捕获,将跨度链接在一起使我们能够在请求通过集群中的微服务的过程中识别和跟踪请求。
注意:在撰写本文时,OpenTracing 仅在 NGINX Ingress Controller 的边缘版本中可用。
将 OpenTracing 构建到 NGINX 入口控制器映像中
要将 OpenTracing 与我们的 Ingress Controller 结合使用,您需要将 OpenTracing 模块合并到 NGINX 或 NGINX Plus Ingress Controller 的 Docker 映像中,并指定您正在使用的跟踪器。
在 Ingress Controller 的 GitHub 存储库中,我们为 NGINX 和 NGINX Plus 提供单独的 Dockerfile。它们都将开源 OpenTracing 模块合并到 Docker 镜像中,但方式不同:
- 对于NGINX,DockerfileWithOpentracing从GitHub下载OpenTracing模块并在第一阶段手动编译它Docker 构建的一部分。
- 对于 NGINX Plus,DockerfileWithOpentracingForPlus 使用包管理器检索 NGINX 从开源 OpenTracing 模块构建并维护的动态模块。
执行以下步骤:
使用 Ingress Controller 存储库中的说明构建 Docker 映像。在步骤 3 中,指定适当的 Dockerfile。
对于 NGINX:
$ 清理干净
$ make DOCKERFILE=DockerfileWithOpentracing PREFIX=您的私有注册表/nginx-ingress
对于 NGINX Plus:
$ 清理干净
$ make DOCKERFILE=DockerfileWithOpentracingForPlus PREFIX=您的私人注册表/nginx-plus-ingress
使用 Ingre 中的说明安装映像ss 控制器存储库。
在运行说明第 3 部分中的 kubectl apply 命令之前,请记住更新 YAML 文件以指定包含 OpenTracing 的新建映像:
容器:
– 图片:IMAGE_WITH_OPENTRACING
部署 Jaeger Tracer
在本博客中,为了简单起见,我们使用默认的跟踪器 Jaeger,并将其部署在集群内部,但它也可以部署在外部。 Ingress Controller pod 和使用 OpenTracing 的应用程序 pod 必须有权访问跟踪器。
同样为了简单起见,我们使用 Jaeger 提供的一体化模板在集群中设置一个非生产 Jaeger 实例。最终的部署(适合开发环境)创建一个 Jaeger Pod 以及访问该 Pod 所需的一组服务;它在默认命名空间中设置最新的 Jaeger 版本,具有内存存储和有限的功能y。
$ kubectl create -f https://raw.githubusercontent.com/jaegertracing/jaeger-kubernetes/master/all-in-one/jaeger-all-in-one-template.yml
在生产中,我们建议使用 Jaeger Operator 进行安装。有关 Jaeger 的更多信息,请参阅 Jaeger 网站。
启用 OpenTracing
NGINX Ingress Controller 的以下 ConfigMap (nginx-config.yaml) 在全局范围内启用 OpenTracing。它在数据部分添加了三个新的 ConfigMap 键:
- opentracing 密钥为集群中创建的所有 Ingress 资源启用 OpenTracing。
- opentracing-tracer 键指定跟踪器库的路径,该库会在您构建 Ingress Controller 映像时下载并复制到该映像中。
- opentracing-tracer-config 键嵌入跟踪器配置。 service_name 字段定义与实际跨度关联的服务,reporter 字段指定跟踪器的地址和端口(在我们的例子中,是跟踪器的地址和端口)Jaeger 服务由上一节中的一体化模板部署)。 Sampler字段指定客户端采样配置;为简单起见,我们配置“常量”采样器 (const),它对所有轨迹进行采样。
种类:ConfigMap
api版本:v1
元数据:
名称:nginx-config
命名空间:nginx-ingress
数据:
开放跟踪:“真实”
opentracing-tracer:“/usr/local/lib/libjaegertracing_plugin.so”
opentracing-tracer-config: |
{
“service_name”: “nginx-ingress”,
“采样器”:{
“类型”:“常量”,
“参数”:1
},
“记者”:{
“localAgentHostPort”:“jaeger-agent.default.svc.cluster.local:6831”
}
}
要应用配置,只需运行:
$ kubectl apply –f nginx-config.yaml
部署示例应用程序
为了简单起见,我们使用 NGINX 实例作为后端应用程序。我们有两个不同的应用程序,其中 App1 配置为将所有 HTTP 流量重定向到 App2。
这两个应用程序都使用 ConfigMap 和卷来配置在 Pod 内运行的 NGINX 实例。其中一个 ConfigMap 具有 NGINX 配置。另一个用于指定每个 NGINX 实例的跟踪器配置(我们将配置包含在每个应用程序中,因为如前所述,应用程序 Pod 需要访问跟踪器才能发送有关请求的信息)。
部署 App1
这是第一个应用程序 (app1.yaml) 的 YAML 清单:
api版本:v1
种类:ConfigMap
元数据:
名称:app1-config
数据:
nginx.conf: |-
用户 nginx;
工作进程 1;
load_module 模块/ngx_http_opentracing_module.so;
error_log /var/log/nginx/error.log 警告;
pid /var/run/nginx.pid;
事件{
工人连接1024;
}
http{
opentracing_load_tracer /usr/local/lib/libjaegertracing_plugin.so
/etc/jaeger-config.json;
打开跟踪;
服务器{
听80;
服务器名称 example.com;
地点 / {
opentracing_propagate_context;
proxy_set_header 主机 $host;
proxy_pass http://app2-svc:80;
}
}
}
—
api版本:v1
种类:ConfigMap
元数据:
名称: jaeger-config-app1
数据:
jaeger-config.json: |-
{
“服务名称”:“应用程序1”,
“采样器”:{
“类型”:“常量”,
“参数”:1
},
“记者”:{
“localAgentHostPort”:“jaeger-agent.default.svc.cluster.local:6831”
}
}
—
api版本:apps/v1
种类:部署
元数据:
名称:应用程序1
规格:
副本:1
选择器:
匹配标签:
应用程序:应用程序1
模板:
元数据:
标签:
应用程序:应用程序1
规格:
容器:
– 名称:app1
图片:opentracing/nginx-opentracing
端口:
– 集装箱端口:80
体积安装:
– 名称:配置-app1
挂载路径:/etc/nginx/nginx.conf子路径:nginx.conf
只读:真
– 名称:config-jaeger
挂载路径:/etc/jaeger-config.json
子路径:jaeger-config.json
只读:真
卷:
– 名称:配置-app1
配置映射:
名称:app1-config
– 名称:config-jaeger
配置映射:
名称: jaeger-config-app1
—
api版本:v1
种类: 服务
元数据:
名称:app1-svc
规格:
端口:
– 端口:80
目标端口:80
选择器:
应用程序:应用程序1
要部署第一个应用程序,请运行以下命令:
$ kubectl apply –f app1.yaml
部署App2
这是第二个应用程序 (app2.yaml) 的 YAML 清单:
api版本:v1
种类:ConfigMap
元数据:
名称:app2-config
数据:
nginx.conf: |-
用户 nginx;
工作进程 1;
load_module 模块/ngx_http_opentracing_module.so;
error_log /var/log/nginx/error.log 警告;
pid /var/run/nginx.pid;
事件{
工人连接1024;}
http{
opentracing_load_tracer /usr/local/lib/libjaegertracing_plugin.so
/etc/jaeger-config.json;
打开跟踪;
服务器 {
听80;
服务器名称 example.com;
地点 / {
opentracing_propagate_context;
opentracing_tag应用程序app2;
return 200 “成功!\n”;
}
}
}
—
api版本:v1
种类:ConfigMap
元数据:
名称: jaeger-config-app2
数据:
jaeger-config.json: |-
{
“服务名称”:“应用程序2”,
“采样器”:{
“类型”:“常量”,
“参数”:1
},
“记者”:{
“localAgentHostPort”:“jaeger-agent.default.svc.cluster.local:6831”
}
}
—
api版本:apps/v1
种类:部署
元数据:
名称:应用程序2
规格:
副本:1
选择器:
匹配标签:
应用程序:应用程序2
模板:
元数据:
标签:
应用程序:应用程序2
规格:
容器:
– 名称:app2图片:opentracing/nginx-opentracing
端口:
– 集装箱端口:80
体积安装:
– 名称:配置-app2
挂载路径:/etc/nginx/nginx.conf
子路径:nginx.conf
只读:真
– 名称:config-jaeger
挂载路径:/etc/jaeger-config.json
子路径:jaeger-config.json
只读:真
卷:
– 名称:配置-app2
配置映射:
名称:app2-config
– 名称:config-jaeger
配置映射:
名称: jaeger-config-app2
—
api版本:v1
种类: 服务
元数据:
名称:app2-svc
规格:
端口:
– 端口:80
目标端口:80
选择器:
应用程序:应用程序2
要部署第二个应用程序,请运行以下命令:
$ kubectl apply -f app2.yaml
部署入口资源
为了能够从集群外部访问 App1,我们创建以下 Ingress 资源 (opentracing-ingress.yaml):
api版本:扩展/v1beta1
种类: 入口
元数据:
娜我:opentracing-ingress
注释:
nginx.org/location-snippets:|
opentracing_propagate_context;
规格:
规则:
– 主机:example.com
http:
路径:
– 小路: /
后端:
服务名称:app1-svc
服务端口:80
请注意我们如何使用 nginx.org/location-snippets 注释在入口控制器级别启用跟踪上下文传播。片段注释是一种将自定义代码添加到 Ingress Controller 中的最终 NGINX 配置的方法。
最后,我们通过运行以下命令来应用 Ingress 资源:
$ kubectl apply -f opentracing-ingress.yaml
我们验证 App1 和 App2 都在运行:
$ kubectl 获取 Pod
名称就绪状态重新开始年龄
app1-68fd9db45c-szqpr 1/1 运行 0 53m
app2-67c7788789-lvbgw 1/1 运行 0 53m
跟踪请求
现在,我们只需通过 Ingress Controller 向 App1 发出请求,其中
- 我C_HTTP_PORT 是 Ingress Controller Pod 中的 HTTP 端口(默认为 80)
- IC_IP_ADDRESS 是 Ingress Controller Pod 的 IP 地址。如果您使用 minikube,这是 minikube IP 地址。
$curl –resolve example.com:IC_HTTP_PORT:IC_IP_ADDRESS http://example.com:IC_HTTP_PORT/ –insecure
成功!
查看跟踪
我们运行以下命令来启用对 Jaeger UI 的访问,其中 JAEGER_POD 是我们根据部署 Jaeger Tracer 中的一体化模板创建的 pod 的“类型/名称”值:
$ kubectl 端口转发 JAEGER_POD 16686:16686
每个请求都会创建一个新的跟踪。要查看我们刚刚发出的请求的跟踪,我们在浏览器中打开 Jaeger UI(网址为 http://localhost:16686),在左列的“服务”字段中输入 nginx-egress,然后单击底部的“查找跟踪”按钮列的。
单击搜索窗口右栏中的 nginx-ingress 以选择跟踪。橱窗里打开(如下),我们可以看到请求的三个跨度:棕色代表 Ingress 控制器,蓝色代表 App1,黄色代表 App2。
单击某个范围可显示有关它的更多详细信息,包括 HTTP 状态代码、主机名、IP 地址和 Jaeger 版本。
结论
在 Kubernetes 中为您的服务启用 OpenTracing 可帮助您和您的团队了解应用程序中发生的情况并更快地调试问题。
此外,能够跟踪从 Ingress Controller Pod 开始的请求,让您可以全面了解从集群外部发送的请求在通过每个服务时的情况。
了解 NGINX Plus 中的增强功能如何促进您的 Kubernetes 部署 – 立即开始 30 天免费试用或联系我们讨论您的使用案例。
发表回复