目录
文章推荐
https://onedayxyy.cn/docs/typora 《玩转Typora-永久更新地址》 QQ交流群
使用 Telemetry API 配置链路追踪
通过 Istio 的 Telemetry API 提供了配置高级链路追踪选项的功能,例如采样率和向已采集的 Span 中添加自定义标签。
使用方法和自定义指标方式类似,可以通过一个 tracing
字段进行配置。
$ kubectl explain Telemetry.spec.tracing
GROUP: telemetry.istio.io
KIND: Telemetry
VERSION: v1alpha1
FIELD: tracing <[]Object>
DESCRIPTION:
Optional.
FIELDS:
customTags <map[string]Object>
Optional.
disableSpanReporting <boolean>
Controls span reporting.
match <Object>
Allows tailoring of behavior to specific conditions.
providers <[]Object>
Optional.
randomSamplingPercentage <number>
<no description>
useRequestIdForTraceSampling <boolean>
<no description>
从上面可以看出关于链路追踪相关配置的主要字段有:
providers
:用于 span 报告的提供者名称,如果没有指定提供者,则将使用默认的跟踪提供者。注意:目前只能指定一个提供者。randomSamplingPercentage
:如果之前没有进行过采样决策,则控制选择流量进行跟踪的速率。如果已经进行了先前的采样决策,那么将使用该决策。然而,如果没有进行过采样决策(例如:请求中未包含x-b3-sampled
跟踪标头),则将以指定的百分比生成遥测数据。disableSpanReporting
:控制 span 上报。如果设置为true
,则不会上报受影响的工作负载的 span。这不会影响上下文传播或跟踪采样行为。customTags
:配置生成的 span 的其他自定义标签。match
:允许根据特定条件进行行为定制。
对于 Tracing 来说,要想使用 Telemetry API,必须先在 MeshConfig
中配置相应的 Provider,然后在 TelemetryAPI 的配置中使用命名引用这个 Provider。
- 比如我们可以添加一个名为
mytrace
的 Trace Provider,对应的配置如下所示:
# mytrace.yaml
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
profile: demo # 使用 demo profile,不能忽略
meshConfig:
enableTracing: true
defaultConfig:
tracing: {} # 禁用全局的 tracing 配置
extensionProviders:
- name: mytrace
zipkin: # add zipkin provider
service: zipkin.istio-system.svc.cluster.local
port: 9411
上面的配置对象中我们这 meshConfig
中首先将全局的 tracing
配置禁用掉,然后在 extensionProviders
下面添加了一个名为 mytrace
的 Trace Provider,对应的后端服务为 zipkin.istio-system.svc.cluster.local
,端口为 9411
,由于前面我们安装的 Jaeger 服务暴露了 9411 端口,并创建了一个名为 zipkin
的 Service 对象,所以这里我们可以直接使用 zipkin.istio-system.svc.cluster.local
来访问 Jaeger 服务,因为 Jaeger 本身也是兼容 Zipkin 协议的。
- 然后我们可以通过
istioctl
命令来安装这个配置对象:
istioctl install -f mytrace.yaml -y
- 配置生效后我们就可以来使用 Telemetry API 来配置链路追踪了,比如我们可以通过以下配置来启用我们创建的
mytrace
这个链路追踪 Provider:
#mesh-default.yaml
apiVersion: telemetry.istio.io/v1alpha1
kind: Telemetry
metadata:
name: mesh-default
namespace: istio-system
spec:
tracing:
- providers:
- name: mytrace
上面的对象我们指定的命名空间为 istio-system
,表示会对整个服务网格中的工作负载应用这个配置。
- 应用上面对象后,再次访问下 productpage 应用,然后在 Jaeger UI 中就可以看到追踪数据了。
kubectl apply -f mesh-default.yaml
我们一共请求了 3 次 /productpage
接口, Jaeger UI 中就显示了 3 个链路,证明默认情况下通过 Telemetry 方式启用的链路追踪采样率是 100%。
- 如果现在我们要将采样率设置为 50%,则可以创建一个如下所示的资源对象:
apiVersion: telemetry.istio.io/v1alpha1
kind: Telemetry
metadata:
name: mesh-default
namespace: istio-system
spec:
tracing:
- providers:
- name: mytrace
randomSamplingPercentage: 50
同样应用上面的资源对象后,这次我们一共访问 6 次 productpage 应用,最后在 Jaeger UI 只能看到 3 个链路数据了,证明采样率已经生效了。
除了配置采样率之外,我们还可以基于文本、环境变量和客户端请求等向 spans 添加自定义标签。
添加自定义标签的数量没有限制,但标签名称必须唯一。
- 比如我们可以通过以下配置向 spans 添加自定义标签:
apiVersion: telemetry.istio.io/v1alpha1
kind: Telemetry
metadata:
name: mesh-default
namespace: istio-system
spec:
tracing:
- providers:
- name: mytrace
randomSamplingPercentage: 50
customTags:
"provider":
literal:
value: "zipkin"
"cluster_id":
environment:
name: ISTIO_META_CLUSTER_ID
defaultValue: Kubernetes
"group":
header:
name: x-group
defaultValue: "unknown"
上面的对象中我们在 customTags
下面添加了一个名为 provider
的标签,它的值为 zipkin
,这个标签的值是一个
Literal
类型的值,Literal
表示一个静态的值,会被添加到每个 span 中。另外添加的 cluster_id
这个标签的值是通过环境变量 ISTIO_META_CLUSTER_ID
来获取的,最后添加的 group
这个标签的值是通过请求头 x-group
来获取的,如果请求头中没有 x-group
这个请求头,则使用默认值 unknown
。
注意基于环境变量添加自定义标签,需要在根 Istio 系统命名空间中的
istio-sidecar-injector
的 ConfigMap 中进行定义。
- 如果不通过 Telemetry API 来配置链路追踪,那么每次我们都需要去更新 Istio 的安装配置才能生效,比如要实现上面的配置,我们需要
MeshConfig
的 全局配置来实现:
# mytrace.yaml
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
profile: demo # 使用 demo profile,不能忽略
meshConfig:
enableTracing: true
defaultConfig:
tracing:
sampling: 50
zipkin:
address: zipkin.istio-system.svc.cluster.local:9411
customTags:
"provider":
literal:
value: "zipkin"
"cluster_id":
environment:
name: ISTIO_META_CLUSTER_ID
defaultValue: Kubernetes
"group":
header:
name: x-group
defaultValue: "unknown"
- 此外如果要对指定的工作负载应用链路追踪配置,以前的方式可以通过 Deployment 的注解来定义调用链的配置信息,比如对于 Productpage 应用,我们可以通过以下方式来配置:
apiVersion: apps/v1
kind: Deployment
metadata:
name: productpage-v1
labels:
app: productpage
spec:
selector:
matchLabels:
app: productpage
version: v1
template:
metadata:
labels:
app: productpage
version: v1
annotations:
proxy.istio.io/config: |
tracing:
sampling: 50
zipkin:
address: zipkin.istio-system.svc.cluster.local:9411
customTags:
"provider":
literal:
value: "zipkin"
"cluster_id":
environment:
name: ISTIO_META_CLUSTER_ID
defaultValue: Kubernetes
"group":
header:
name: x-group
defaultValue: "unknown"
# ......
这种方式虽然可以达到目的,但显然不够灵活,而且需要修改 Deployment 的配置,不够优雅,侵入性太强,而通过 Telemetry API 来配置链路追踪,就可以更加灵活地配置链路追踪了,比如同样只想对 Productpage 应用进行链路追踪,可以通过以下方式来配置:
apiVersion: telemetry.istio.io/v1alpha1
kind: Telemetry
metadata:
name: productpage
namespace: default # 指定要配置的工作负载所在命名空间
spec:
selector:
matchLabels:
app: productpage # 关联工作负载的标签
tracing:
- providers:
- name: mytrace
randomSamplingPercentage: 50
customTags:
"provider":
literal:
value: "zipkin"
"cluster_id":
environment:
name: ISTIO_META_CLUSTER_ID
defaultValue: Kubernetes
"group":
header:
name: x-group
defaultValue: "unknown"
到这里我们就了解了如何通过 Telemetry API 来配置链路追踪了,这种方式显示是更推荐的方式,更加灵活。
访问日志
访问日志提供了一种从单个工作负载实例的角度监控和理解行为的方法,同样访问日志是我们在生产环境中必不可少的一种监控手段,Istio 通过 Envoy 来提供访问日志功能,Envoy Proxy 打印访问信息到标准输出,Envoy 容器的标准输出能够通过 kubectl logs
命令打印出来。
Istio 能够以一组可配置的格式为服务流量生成访问日志,使运维人员可以完全控制日志记录的方式、内容、时间和地点。 下面是一个典型的 Istio 访问日志示例:
[2023-12-04T06:17:42.719Z] "GET /productpage HTTP/1.1" 200 - via_upstream - "-" 0 5289 23 22 "10.244.0.0" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36" "f3a98cd1-6970-42c0-9c86-d179b93aa779" "192.168.0.100:31896" "10.244.1.254:9080" inbound|9080|| 127.0.0.6:45629 10.244.1.254:9080 10.244.0.0:0 outbound_.9080_._.productpage.default.svc.cluster.local default
在现在的 Telemetry V2 版本的架构中,访问日志直接通过服务网格的数据平面 Envoy 上生成并上报给日志后端。根据后端日志采集方式的不同,会有不同的通道和方式。Envoy 可以通过控制台或者文件输出,由各种日志代理采集,也可以通过 gRPC 协议直接上报日志给标准的访问日志服务 ALS(Envoy Access Log Service),比如 Skywalking 就支持这种方式。
一般流程如下所示:
- Envoy 根据服务网格配置提取应用的访问信息
- 上报访问日志,比如通过 gRPC 协议上报给 ALS 服务
- ALS 服务 对接后端,将日志写到 Elasticsearch、Kafka 等后端服务中
- 通过 Kibanba、Grafana 等工具从后端服务检索日志
开启 Envoy 访问日志
同样的方式在 Istio 中我们可以通过 MeshConfig
和 Telemetry API 的方式来启用访问日志。
如果想通过 MeshConfig
方式来配置,需要在安装配置中添加以下字段(默认已经配置了):
spec:
meshConfig:
accessLogFile: /dev/stdout
或者,在原来的 istioctl install
命令中添加相同的设置,例如:
istioctl install <flags-you-used-to-install-Istio> --set meshConfig.accessLogFile=/dev/stdout
此外还可以通过设置 accessLogEncoding
为 JSON
或 TEXT
来配置日志的格式。另外还可以设置 accessLogFormat
来自定义访问日志的格式,如果没有指定 accessLogFormat
的话 Istio 将使用以下默认的访问日志格式:
[%START_TIME%] \"%REQ(:METHOD)% %REQ(X-ENVOY-ORIGINAL-PATH?:PATH)% %PROTOCOL%\" %RESPONSE_CODE% %RESPONSE_FLAGS% %RESPONSE_CODE_DETAILS% %CONNECTION_TERMINATION_DETAILS%
\"%UPSTREAM_TRANSPORT_FAILURE_REASON%\" %BYTES_RECEIVED% %BYTES_SENT% %DURATION% %RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)% \"%REQ(X-FORWARDED-FOR)%\" \"%REQ(USER-AGENT)%\" \"%REQ(X-REQUEST-ID)%\"
\"%REQ(:AUTHORITY)%\" \"%UPSTREAM_HOST%\" %UPSTREAM_CLUSTER% %UPSTREAM_LOCAL_ADDRESS% %DOWNSTREAM_LOCAL_ADDRESS% %DOWNSTREAM_REMOTE_ADDRESS% %REQUESTED_SERVER_NAME% %ROUTE_NAME%\n
当然我们还是强烈推荐使用 Telemetry API 来开启或关闭访问日志,如下所示:
apiVersion: telemetry.istio.io/v1alpha1
kind: Telemetry
metadata:
name: mesh-default
namespace: istio-system
spec:
accessLogging:
- providers:
- name: envoy
上面的示例使用默认的 envoy
访问日志提供程序,当然我们也可以应用于单独的命名空间或单独的工作负载,以在细粒度级别控制日志记录。
Grafana Loki
接下来我们来将访问日志发送到 Grafana Loki 进行统一的日志管理,Loki 是一个水平可扩展、高可用的多租户日志聚合系统。
- 首先我们需要先确保 Loki 已经安装,我们这里同样只是为了测试,直接使用下面的方式安装即可,如果在生产环境中使用,则需要参考官方文档进行分布式部署。
kubectl apply -f samples/addons/loki.yaml -n istio-system
注意:安装这个pod要pv环境哦
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning FailedScheduling 34s (x2 over 35s) default-scheduler 0/3 nodes are available: pod has unbound immediate PersistentVolumeClaims. preemption: 0/3 nodes are available: 3 Preemption is not helpful for scheduling..
由于 Istio 默认并没有直接支持 Loki 这个 Provider,我们可以查看 MeshConfig
的 ExtensionProvider
字段,可以看到 Istio 默认支持的 Provider 有:
字段 | 类型 | 描述 | 是否必需 |
---|---|---|---|
name | string | 必填。用于唯一标识扩展提供商的名称。 | 否 |
envoyExtAuthzHttp | EnvoyExternalAuthorizationHttpProvider (oneof) | 配置实现了 Envoy ext_authz 过滤器授权检查服务的外部授权器,使用 HTTP API。 | 否 |
envoyExtAuthzGrpc | EnvoyExternalAuthorizationGrpcProvider (oneof) | 配置实现了 Envoy ext_authz 过滤器授权检查服务的外部授权器,使用 gRPC API。 | 否 |
zipkin | ZipkinTracingProvider (oneof) | 配置使用 Zipkin API 的跟踪提供商。 | 否 |
datadog | DatadogTracingProvider (oneof) | 配置 Datadog 跟踪提供商。 | 否 |
stackdriver | StackdriverProvider (oneof) | 配置 Stackdriver 提供商。 | 否 |
skywalking | SkyWalkingTracingProvider (oneof) | 配置 Apache SkyWalking 提供商。 | 否 |
opentelemetry | OpenTelemetryTracingProvider (oneof) | 配置 OpenTelemetry 跟踪提供商。 | 否 |
prometheus | PrometheusMetricsProvider (oneof) | 配置 Prometheus 指标提供商。 | 否 |
envoyFileAccessLog | EnvoyFileAccessLogProvider (oneof) | 配置 Envoy 文件访问日志提供商。 | 否 |
envoyHttpAls | EnvoyHttpGrpcV3LogProvider (oneof) | 针对 HTTP 流量配置 Envoy 访问日志服务提供商。 | 否 |
envoyTcpAls | EnvoyTcpGrpcV3LogProvider (oneof) | 针对 TCP 流量配置 Envoy 访问日志服务提供商。 | 否 |
envoyOtelAls | EnvoyOpenTelemetryLogProvider (oneof) | 配置 Envoy Open Telemetry 访问日志服务提供商。 | 否 |
没有 Loki 这个 Provider,那么我们需要怎样才能将日志发送到 Loki 中呢?这里我们可以使用 OpenTelemetry
来收集日志,然后再通过 OpenTelemetry Collector 来将日志发送到 Loki 中。
OpenTelemetry
OpenTelemetry
(简称 OTel
) 是一个开源的可观测框架,用于生成、收集和描述应用程序的观测数据。它提供了一组 API、库、Agent 和 Collector,用于捕获分布式跟踪和度量数据,并将其发送到分析软件、存储库或其他服务,OTel
的目标是提供一套标准化、与厂商无关的 SDK、API 和工具集,用于将数据摄取、转换和发送到可观测性后端(开源或商业厂商)。
1.OpenTelemetry Collector
OpenTelemetry Collector 提供了一个与厂商无关的实现方式,用于接收、处理和导出遥测数据,它消除了运行、操作和维护多个代理/收集器的需求。
事实上收集器也并不是必需的,有的时候我们可以直接将遥测数据发送到外部的可视化工具中,比如 Jaeger、Zipkin 等等,但是这样的话我们就需要在每个应用中都进行配置,这样的话就会导致配置非常繁琐,而且也不利于统一管理,所以这里我们就可以使用 OpenTelemetry Collector 来解决这个问题。
而且 OpenTelemetry Collector 本身部署起来也非常灵活,可以将其部署为代理或网关。区别在于作为代理时,收集器实例与应用程序在同一主机上运行(sidecar 容器、daemonset 等)。此外一个或多个收集器实例也可以作为独立服务以每个集群、数据中心和地区的网关形式运行。
一般来说建议新应用选择代理部署,现有应用选择网关部署的方式,如果是 Kubernetes 环境,当然更建议部署为守护进程(代理模式)的方式。
收集器由四个组件组成,通过管道(Pipeline)进行启用:
- 接收器(Receiver)将数据发送到收集器中,可以通过推送或拉取方式发送
- 处理器(Processor)决定如何处理接收到的数据
- 导出器(Exporter)决定将数据发送到哪里,可以通过拉取或推送方式完成,上面代码中的
OTLPTraceExporter
就是一个导出器 - 连接器(Connectors):连接器既是输出者又是接收者。连接器连接两个管道:它作为一个管道末端的导出器消耗数据,并作为另一个管道开始处的接收器发出数据。它可以消耗和发出相同数据类型或不同数据类型的数据。
当然我们也可以基于社区的组件进行自定义,以增强和扩展收集器管道。例如我们可以创建一个专用的导出器来接收并摄取指标、追踪和日志。
2.OpenTelemetry Collector 部署
在了解了 OpenTelemetry 的相关概念后,接下来我们需要部署 OpenTelemetry Collector,同样我们直接使用 Istio 提供的 samples 中的配置即可:
kubectl apply -f samples/open-telemetry/loki/otel.yaml -n istio-system
该命令会部署一个 OpenTelemetry 采集器,其中比较重要的是该采集器的配置:
apiVersion: v1
kind: ConfigMap
metadata:
name: opentelemetry-collector-conf
labels:
app: opentelemetry-collector
data:
opentelemetry-collector-config: |
receivers:
otlp:
protocols:
grpc:
http:
processors:
batch:
attributes:
actions:
- action: insert
key: loki.attribute.labels
value: pod, namespace,cluster,mesh
exporters:
loki:
endpoint: "http://loki.istio-system.svc:3100/loki/api/v1/push"
logging:
loglevel: debug
extensions:
health_check:
service:
extensions:
- health_check
pipelines:
logs:
receivers: [otlp]
processors: [attributes]
exporters: [loki, logging]
上面的配置中我们主要关注 exporters
字段,其中 loki
就是我们要将日志发送到的 Loki 服务,endpoint
字段指定了 Loki 服务的地址,这里我们直接使用 Loki 的 Service 名称即可,因为 Loki 服务暴露了 3100 端口,所以我们可以直接使用 http://loki.istio-system.svc:3100/loki/api/v1/push
来访问 Loki 服务。而 receivers
字段表示接收器,这里配置的是 otlp
,表示使用 OpenTelemetry 的 OTLP 标准协议来接收数据。processors
字段表示处理器,这里我们使用了 attributes
处理器,它的作用是向日志中添加一些自定义的属性,比如 pod
、namespace
、cluster
、mesh
等等,这样我们在 Loki 中就可以通过这些属性来进行检索了。最后需要注意的是必须要在 service.pipelines
中明确声明要启用的管道以及管道中使用的接收器、处理器和导出器,否则不会生效。
现在在 Istio 根命名空间中包含如下的一些工作负载:
$ kubectl get pods -n istio-system
NAME READY STATUS RESTARTS AGE
grafana-5f9b8c6c5d-jv65v 1/1 Running 16 (5h12m ago) 32d
istio-egressgateway-556f6f58f4-mqp5z 1/1 Running 0 4h26m
istio-ingressgateway-9c8b9b586-p2w67 1/1 Running 0 4h26m
istiod-644f5d55fc-dlktv 1/1 Running 0 4h26m
jaeger-db6bdfcb4-9s8lr 1/1 Running 0 3h47m
kiali-7c9d5f9f96-cp4mb 1/1 Running 18 (5h12m ago) 32d
loki-0 1/1 Running 0 32m
opentelemetry-collector-5ccc9c9c55-msg5x 1/1 Running 0 60s
prometheus-5d5d6d6fc-lfz87 2/2 Running 2 (5h12m ago) 2d19h
接下来我们就需要在 Istio 中添加一个 OpenTelemetry 访问日志服务的 Provider,添加如下配置:
# iop.yaml
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
profile: demo
meshConfig:
extensionProviders:
- name: otel
envoyOtelAls:
service: opentelemetry-collector.istio-system.svc.cluster.local
port: 4317
logFormat:
labels:
pod: "%ENVIRONMENT(POD_NAME)%"
namespace: "%ENVIRONMENT(POD_NAMESPACE)%"
cluster: "%ENVIRONMENT(ISTIO_META_CLUSTER_ID)%"
mesh: "%ENVIRONMENT(ISTIO_META_MESH_ID)%"
在上面的配置中我们添加了一个名为 otel
的 Provider,该 Provider 是一个 envoyOtelAls
,表示使用 OpenTelemetry 的访问日志服务,对应的后端服务为 opentelemetry-collector.istio-system.svc.cluster.local
,端口为 4317
,这里我们直接使用 OpenTelemetry Collector 的 Service 名称即可。最后我们还配置了 logFormat
,表示日志的格式,这里我们添加了一些自定义的属性,比如 pod
、namespace
、cluster
、mesh
等等,然后在 OpenTelemetry 采集器中会把这些属性转换为 Loki 的标签,这样我们在 Loki 中就可以通过这些属性来进行检索了。
直接使用 istioctl
命令来安装配置该对象即可:
istioctl install -f iop.yaml -y
到这里我们的准备工作就完成了。
3.使用 Telemetry API 配置访问日志
接下来我们只需要通过 Telemetry API 来启用上面我们配置的日志 Provider 就可以开始收集日志了,如下所示:
apiVersion: telemetry.istio.io/v1alpha1
kind: Telemetry
metadata:
name: mesh-logging-default
namespace: istio-system
spec:
accessLogging:
- providers:
- name: otel
应用该资源对象后,整个服务网格的日志就都会被上报到 OTel 采集器,然后在 Loki 中就可以看到日志了。
这里我们直接打开 Grafana 的 Loki Dashboard 即可:
istioctl dashboard grafana
首先要在 Grafana 中添加 Loki 数据源:
然后接下来我们去访问 Productpage 应用产生一些日志数据,再切换回到 Grafana 中,切换到 Explore
页面,然后选择 Loki 数据源,就可以看到 Loki 中的日志了:
同样的我们还可以使用 Telemetry API 来做一些更加细粒度的配置。
比如可以使用以下配置禁用 sleep 服务的访问日志:
apiVersion: telemetry.istio.io/v1alpha1
kind: Telemetry
metadata:
name: disable-sleep-logging
namespace: default
spec:
selector:
matchLabels:
app: sleep
accessLogging:
- providers:
- name: otel
disabled: true
还可以使用 match
字段来指定要过滤的流量,比如可以使用以下配置禁用 httpbin
服务的入站访问日志:
apiVersion: telemetry.istio.io/v1alpha1
kind: Telemetry
metadata:
name: disable-httpbin-logging
spec:
selector:
matchLabels:
app: httpbin
accessLogging:
- providers:
- name: otel
match:
mode: SERVER # 入站模式
disabled: true # 禁用
此外我们可以通过 CEL
表达式过滤访问日志。只有响应码大于等于 500 时,才会显示访问日志,如下所示:
apiVersion: telemetry.istio.io/v1alpha1
kind: Telemetry
metadata:
name: filter-sleep-logging
spec:
selector:
matchLabels:
app: sleep
accessLogging:
- providers:
- name: otel
filter:
expression: response.code >= 500
比如只有响应码大于等于 400 或请求转到 BlackHoleCluster
或 PassthroughCluster
时,才显示访问日志:
apiVersion: telemetry.istio.io/v1alpha1
kind: Telemetry
metadata:
name: default-exception-logging
namespace: istio-system
spec:
accessLogging:
- providers:
- name: otel
filter:
expression: "response.code >= 400 || xds.cluster_name == 'BlackHoleCluster' || xds.cluster_name == 'PassthroughCluster' "
关于赋值表达式的使用和前面指标中的使用方式一致,这里就不再赘述了。
关于我
我的博客主旨:
- 排版美观,语言精炼;
- 文档即手册,步骤明细,拒绝埋坑,提供源码;
- 本人实战文档都是亲测成功的,各位小伙伴在实际操作过程中如有什么疑问,可随时联系本人帮您解决问题,让我们一起进步!
🍀 微信二维码
x2675263825 (舍得), qq:2675263825。
🍀 微信公众号
《云原生架构师实战》
🍀 个人博客站点
http://onedayxyy.cn/
🍀 语雀
https://www.yuque.com/xyy-onlyone
🍀 csdn
https://blog.csdn.net/weixin_39246554?spm=1010.2135.3001.5421
🍀 知乎
https://www.zhihu.com/people/foryouone
最后
好了,关于本次就到这里了,感谢大家阅读,最后祝大家生活快乐,每天都过的有意义哦,我们下期见!
码
x2675263825 (舍得), qq:2675263825。
[外链图片转存中…(img-pICMRoCb-1701909151066)]
🍀 微信公众号
《云原生架构师实战》
[外链图片转存中…(img-oiUMo0u9-1701909151066)]
🍀 个人博客站点
http://onedayxyy.cn/
[外链图片转存中…(img-7lNopM19-1701909151067)]
[外链图片转存中…(img-hwPl0lVx-1701909151068)]
🍀 语雀
https://www.yuque.com/xyy-onlyone
[外链图片转存中…(img-SN5NNJXC-1701909151068)]
🍀 csdn
https://blog.csdn.net/weixin_39246554?spm=1010.2135.3001.5421
[外链图片转存中…(img-a2YAvUYt-1701909151069)]
🍀 知乎
https://www.zhihu.com/people/foryouone
[外链图片转存中…(img-rmDZSqq2-1701909151070)]
最后
好了,关于本次就到这里了,感谢大家阅读,最后祝大家生活快乐,每天都过的有意义哦,我们下期见!