Redian新闻
>
istio sidecar 工作方式

istio sidecar 工作方式

公众号新闻

istio 是什么

Istio 是一个开放源代码的服务网格,它为基于微服务的应用程序提供了一种统一的方式来连接、保护、监控和管理服务。Istio 主要解决的是在微服务架构中的服务间通信的复杂性问题,它通过提供服务间的负载均衡、服务到服务的认证、监控以及服务的弹性(例如重试、熔断等)来实现。

sidecar 是什么

sidecar 是一种设计模式,它将挂在业务容器旁边作为辅助,当业务接受流量和传出流量的时候,都先经过 sidecar 然后在到达业务容器或者发出。sidecar 可以看作是一个代理,或者是一个专门为我一个服务而工作的 gateway。这样,服务的熔断、限流、监控、日志等功能都可以在 sidecar 中实现,而不需要在业务容器中实现。从而实现了业务容器的轻量化,只需要关注业务逻辑。

在 istio 中,sidecar 使用的是 envoy,envoy 是一个高性能的代理,它支持 http1.1, http2, grpc, tcp 等协议,支持负载均衡,熔断,限流,监控等功能。envoy 是一个 c++ 项目,它的性能非常好。通过 istiod 控制平面,使用 grpc stream 的方式更新 envoy 的配置,从而实现了动态配置。

如果在 pod test 中访问 test namespace 下的 nginx service,那么流量会经过自己的 sidecar,然后到达 nginx 的 sidecar,最后到达 nginx 的容器。nginx 回复同样如此,先到达 sidecar,然后到达 test 的 sidecar,最后到达 test 的容器。

启动方式

在 kubernetes 中,当 namespace 存在 istio-injection=enabled label,那么在该 namespace 中的 pod 在启动的时候,istio 就会利用 mutating addmission webhook 的方式,自动修改 pod spec ,把 containers 中加入 sidecar 容器。当然,它也加入了一个 initcontainer,目的是做一些网络配置,能做到这个的原因是,kubernetes 的 pod 的多个 container 是使用同一个 linux network namespace, 所以 initcontainer 修改的网络配置对所有的 container 都生效。

流量劫持方式

在 test 访问 nginx 的例子中,我们可以看到 nginx 的容器是启动在 80 端口上的,流量也是访问的 80, sidecar 是怎么劫持到的呢?而且,在 test pod 中,我们访问的是 nginx 的 service,流量又是怎么劫持到 sidecar 的呢?

刚刚说过,pod 除了被插入了一个 sidecar 容器,还被插入了一个 initcontainer,我们启动一个 nginx pod 和 service 看一下。

apiVersion: apps/v1kind: Deploymentmetadata:  name: nginx  namespace: testspec:  replicas: 1  selector:    matchLabels:      app: nginx  template:    metadata:      labels:        app: nginx    spec:      containers:      - name: nginx        image: nginx:latest        ports:        - containerPort: 80---apiVersion: v1kind: Servicemetadata:  name: nginx  namespace: testspec:  selector:    app: nginx  ports:  - protocol: TCP    port: 80    targetPort: 80  type: ClusterIP

kubectl create ns test

kubectl label namespace test istio-injection=enabled # 开启 istio 注入

kubectl -n test apply -f nginx.yaml

现在我们看一下 nginx pod 被插入的 sidecar 和 initcontainer


## sidecar

- args:

- proxy

- sidecar

- --domain

- $(POD_NAMESPACE).svc.cluster.local

- --proxyLogLevel=warning

- --proxyComponentLogLevel=misc:error

- --log_output_level=default:info

# ...

## intcontainer

- args:

- istio-iptables

- -p

- "15001"

- -z

- "15006"

- -u

- "1337"

- -m

- REDIRECT

- -i

- '*'

- -x

- ""

- -b

- '*'

- -d

- 15090,15021,15020

- --log_output_level=default:info

可以看到,initcontainer 是自动执行了一系列的脚本,这个脚本我们并不知道是做啥的,但是从名字可以看出来是 iptables 的操作,那么我们看一下 iptables 的规则

这里我们容器内没有 iptables,所以我们在宿主机上查看 在nginx pod 所在的主机上查看,先确定 nginx 这个container 的 pid。


# 从 pod 的 status 中的容器的 uid

kubectl get pod -n test nginx-7c79c4bf97-7985c -o jsonpath='{.status.containerStatuses[0].container

ID}'

docker://b0d6c9060661e0912a35d33ff220e67a628c9fc5300ca3c67dc30f9e40c9e0ce%

# 我这里是用 docker 作为 container runtime 的

# 如果你是 containerd 的话 需要执行 ctr -n k8s.io info [container_id] |grep -i pod

docker inspect b0d6c9060661e0912a35d33ff220e67a628c9fc5300ca3c67dc30f9e40c9e0ce | grep -i pid # 在 nginx 所在的主机上执行

"Pid": 4652

# 在主机上使用 nseneter 进入容器的 network namespace 查看 iptables 规则

nsenter -t 4652 -n -- iptables-save

# Warning: iptables-legacy tables present, use iptables-legacy-save to see them

# 说明这个容器使用的是 iptables-legacy 我们按提示执行

nsenter -t 4652 -n -- iptables-legacy-save

# Generated by iptables-save v1.8.7 on Sun May 12 05:53:29 2024

*nat

:PREROUTING ACCEPT [54:3240]

:INPUT ACCEPT [54:3240]

:OUTPUT ACCEPT [49:4198]

:POSTROUTING ACCEPT [49:4198]

:ISTIO_INBOUND - [0:0]

:ISTIO_IN_REDIRECT - [0:0]

:ISTIO_OUTPUT - [0:0]

:ISTIO_REDIRECT - [0:0]

# 所有入栈流量都走 ISTIO_INBOUND 链

-A PREROUTING -p tcp -j ISTIO_INBOUND

# 所有出栈流量都走 ISTIO_OUTPUT 链

-A OUTPUT -p tcp -j ISTIO_OUTPUT

# 忽略(也就是不劫持)目标端口是 15008 15090 15021 15020 的流量

# 15008:隧道端口 15090:prometheus 端口 15021:健康检查 15020:管理端口

# 官方文档端口介绍 https://istio.io/latest/docs/ops/deployment/requirements/#ports-used-by-istio

-A ISTIO_INBOUND -p tcp -m tcp --dport 15008 -j RETURN

-A ISTIO_INBOUND -p tcp -m tcp --dport 15090 -j RETURN

-A ISTIO_INBOUND -p tcp -m tcp --dport 15021 -j RETURN

-A ISTIO_INBOUND -p tcp -m tcp --dport 15020 -j RETURN

# 如果是 tcp 协议就走 ISTIO_IN_REDIRECT 链

-A ISTIO_INBOUND -p tcp -j ISTIO_IN_REDIRECT

# 如果是 tcp 就使用 dnat 把流量转发到15006端口(也就是修改tcp的目标端口)也就是交给envoy处理

-A ISTIO_IN_REDIRECT -p tcp -j REDIRECT --to-ports 15006

# 回环地址 不处理

-A ISTIO_OUTPUT -s 127.0.0.6/32 -o lo -j RETURN

# 从 lo(回环) 口出来的 目标不是本机 owner是 envoy(--uid-owner 1337) 目标端口是 15008 的 转到 ISTIO_IN_REDIRECT 链处理

-A ISTIO_OUTPUT ! -d 127.0.0.1/32 -o lo -p tcp -m tcp ! --dport 15008 -m owner --uid-owner 1337 -j ISTIO_IN_REDIRECT

# 从 lo 口出来的 owner 不是 envoy(不是 envoy 发出的) 不处理

-A ISTIO_OUTPUT -o lo -m owner ! --uid-owner 1337 -j RETURN

# owner 是 envoy 的不处理 (不能劫持自己发出去的流量)

-A ISTIO_OUTPUT -m owner --uid-owner 1337 -j RETURN

# 从 lo(回环) 口出来的 目标不是本机 owner是 envoy(--gid-owner 1337) 目标端口是 15008 的 转到 ISTIO_IN_REDIRECT 链处理

-A ISTIO_OUTPUT ! -d 127.0.0.1/32 -o lo -p tcp -m tcp ! --dport 15008 -m owner --gid-owner 1337 -j ISTIO_IN_REDIRECT

# 从 lo(回环) 口出来的 owner 不是 envoy 不处理

-A ISTIO_OUTPUT -o lo -m owner ! --gid-owner 1337 -j RETURN

# owner 是 envoy 不处理

-A ISTIO_OUTPUT -m owner --gid-owner 1337 -j RETURN

# 目标地址是 127.0.0.1 不处理

-A ISTIO_OUTPUT -d 127.0.0.1/32 -j RETURN

# 剩下转到 ISTIO_REDIRECT 链

-A ISTIO_OUTPUT -j ISTIO_REDIRECT

# 如果是 tcp 就使用 dnat 把流量转发到 15001 端口(也就是修改tcp的目标端口)也就是交给envoy处理

-A ISTIO_REDIRECT -p tcp -j REDIRECT --to-ports 15001

COMMIT

# Completed on Sun May 12 05:53:29 2024

为什么 --uid-owner 1337 和 --gid-owner 1337 就代表 owner 是 envoy 呢?

因为 envot (istio proxy) 是以 uid 和 gid 起来的。


kubectl get pod -n test nginx-7c79c4bf97-7985c -o jsonpath='{.spec.containers[1].name}'

istio-proxy

kubectl get pod -n test nginx-7c79c4bf97-7985c -o jsonpath='{.spec.containers[1].securityContext.ru

nAsGroup}'

1337

kubectl get pod -n test nginx-7c79c4bf97-7985c -o jsonpath='{.spec.containers[1].securityContext.runAsUser}'

1337

每个 pod 中的 iptables 都是一样的,这样我们就知道了 test pod 是怎么劫持的,比如现在在 test pod container 中 curl nginx.test 首先查询 dns nginx.test 对应的 ip 是 10.102.168.134, 访问也就是向 http://10.102.168.134:80 发请求。

  1. test pod 是发出去的包 所以 iptables 走 OUTPUT 链 http 是 tcp 协议的 所以走 ISTIO_OUTPUT 链

  2. 这个流量不是 lo 口的,目标地址不是 127.0.0.1, owner 也不是 envoy ,所以给 ISTIO_REDIRECT 链处理

  3. ISTIO_REDIRECT 中 我们是 tcp 所以 dnat 到端口 15001 (也就是 envoy)做处理

  4. test envoy gateway 会转发到 http://10.244.0.73:80(pod ip) (具体是怎么转发的后续会介绍到)

  5. 流量是进入到 nginx pod 中 所以 iptables 的 PREROUTING 链 http 是 tcp 协议的,所以走 ISTIO_INBOUND 链

  6. 目标端口是 80 不是15008 15090 15021 15020 所以走 ISTIO_IN_REDIRECT 链

  7. ISTIO_IN_REDIRECT 会 dnat 到端口 15006 也就是 envoy 做处理

  8. envoy 会转发到自己的 nginx container 容器中 (具体是怎么转发的后续会介绍到)

所以可以看到,流量从 test pod 的 test container 出来之后,会被自己的 envoy(istio-proxy sidecar) 劫持,然后7层转发到 10.244.0.73 (nigix pod IP地址)。然后 nginx pod 中的 envoy container 会劫持这个流量交给自己,然后7层代理到 nginx container。流量回复回去是一个道理。

xDS

在上方的流程中 test envoy 劫持到 http://10.102.168.134:80 会转发到 http://10.244.0.73:80,那么他是怎么知道要转发到这里去的呢?如果是 nginx 我们会配置 upstream,然后执行 nginx -s reload,这是 nginx 不支持动态加载方式。envoy 是支持动态加载的,对外提供 API,我们调用 API 就可以动态的修改配置。这个 API 就是 xDS API。它包括了以下API:

  1. CDS(Cluster Discovery Service): 用于发现集群信息,比如集群的名字,集群的地址等。

  2. EDS(Endpoint Discovery Service): 用于发现集群中的 endpoint 信息,比如集群中的服务的地址,端口等。

  3. LDS(Listener Discovery Service): 用于发现监听器信息,比如监听器的名字,监听器的地址等。

  4. RDS(Route Discovery Service): 用于发现路由信息,比如路由的名字,路由的规则等。

  5. SDS(Secret Discovery Service): 用于发现证书信息,比如证书的名字,证书的内容等。

  6. HDS(Health Discovery Service): 用于发现健康检查信息,比如健康检查的名字,健康检查的规则等。

  7. ADS(Aggregated Discovery Service): 用于聚合以上所有的服务,提供一个统一的服务。

listener + route 是用来表达监听哪个端口和哪些路由的,是 envoy 进入流量的入口。cluster + endpoint 是用来表达集群和集群中的服务的,是 envoy 转发流量的目的地。

数据来源

那这些 xDS 的配置来自哪呢?

这些 envoy 配置都来自于 istiod,istiod 是 istio 的控制平面,它会使用 grpc stream 的方式,动态的更新 envoy 的配置。istiod 会监听 kubernetes 的资源变化,比如 service, endpoint 和 istio 自己 CRD 等,组合成一个配置,然后定时的推送给 envoy。这样就实现了动态配置。

比如我们这个 service 的配置,查看 service 和 endpoints 就知道 service clusterIp 对应的 pod ip。


kubectl -n test get svc nginx

NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE

nginx ClusterIP 10.102.168.134 <none> 80/TCP 112m

kubectl -n test get endpoints nginx

NAME ENDPOINTS AGE

nginx 10.244.0.73:80 112m

这样我们就知道了 nginx service 对应的 clusterIp 是 10.102.168.134, 而对应的 pod ip 是 10.244.0.73。然后 istiod 把这个配置推送给所有 sidecar,这样 test pod 中的 envoy 就知道了要把流量转发到 10.244.0.73 了。

流量流程图

在 test pod 的 test 容器中 执行 curl http://nginx.test 流量的流程图如下

配置查看

我们可以通过调用 pod 中的 envoy 的 admin api 来查看配置


kubectl port-forward pod/nginx-7c79c4bf97-7985c 15000:15000

curl http://localhost:15000/config_dump

打印出的 json 格式的配置文件,它而很大看起来很不方便,幸好 istio 给我们提供了一个工具 istioctl,我们可以使用 istioctl 来查看配置。

因为我们流量是从 test pod 到 nginx pod,所以所限我们查看 test pod 中的 envoy 的配置。

1.首先我们看下 listerner 15001 的配置 因为从 iptables 我们知道 出去的流量会被劫持到 15001


istioctl -n test proxy-config listener test-f5b5d48b5-qdzft --port 15001

ADDRESSES PORT MATCH DESTINATION

0.0.0.0 15001 ALL PassthroughCluster

0.0.0.0 15001 Addr: *:15001 Non-HTTP/Non-TCP

首先会监听 15001 端口,这个是真是监听的端口。它会转发到虚拟端口(Virtual Port),虚拟端口不会真是监听操作系统端口,它只是envoy的逻辑端口。那我们怎么知道流量转发到哪个虚拟端口了?请求的端口是什么,就转发到哪个了。比如我们请求的是 nginx 80 端口,就会转发到 80 虚拟端口

2.查看 listener 的虚拟端口,nginx service ip 10.102.168.134 prot 80


istioctl -n test proxy-config listener test-f5b5d48b5-qdzft --port 80 --address 10.102.168.134

ADDRESSES PORT MATCH DESTINATION

10.102.168.134 80 Trans: raw_buffer; App: http/1.1,h2c Route: nginx.test.svc.cluster.local:80

10.102.168.134 80 ALL Cluster: outbound|80||nginx.test.svc.cluster.local

第一条是明文而且是 http/1.1 或者 h2c 无加密的 http/2)协议的流量会被转发到 nginx.test.svc.cluster.local:80

3.查看 route 配置


istioctl -n test proxy-config route test-f5b5d48b5-qdzft |grep nginx.test.svc.cluster.local

nginx.test.svc.cluster.local:80 nginx.test.svc.cluster.local:80 * /*

80 nginx.test.svc.cluster.local:80 nginx, nginx.test + 1 more... /*

这里我们没有指定 host 所以走第一条


# istioctl -n test proxy-config route test-f5b5d48b5-qdzft --name nginx.test.svc.cluster.local:80 -oyaml

- ignorePortInHostMatching: true

maxDirectResponseBodySizeBytes: 1048576

name: nginx.test.svc.cluster.local:80

validateClusters: false

virtualHosts:

- domains:

- '*'

includeRequestAttemptCount: true

name: nginx.test.svc.cluster.local:80

routes:

- decorator:

operation: nginx.test.svc.cluster.local:80/*

match:

prefix: /

name: default

route:

cluster: outbound|80||nginx.test.svc.cluster.local

maxGrpcTimeout: 0s

retryPolicy:

hostSelectionRetryMaxAttempts: "5"

numRetries: 2

retriableStatusCodes:

- 503

retryHostPredicate:

- name: envoy.retry_host_predicates.previous_hosts

typedConfig:

'@type': type.googleapis.com/envoy.extensions.retry.host.previous_hosts.v3.PreviousHostsPredicate

retryOn: connect-failure,refused-stream,unavailable,cancelled,retriable-status-codes

timeout: 0s

可以看到,match 的路由是 prefix 是 /,也就是所有的请求都会走这个路由,这个路由会把流量转发到 outbound|80||nginx.test.svc.cluster.local 这个 cluster 中。

4.我们查看 cluster


# istioctl -n test proxy-config cluster test-f5b5d48b5-qdzft --fqdn "outbound|80||nginx.test.svc.cluster.local" -oyaml

- circuitBreakers:

thresholds:

- maxConnections: 4294967295

maxPendingRequests: 4294967295

maxRequests: 4294967295

maxRetries: 4294967295

trackRemaining: true

commonLbConfig:

localityWeightedLbConfig: {}

connectTimeout: 10s

edsClusterConfig:

edsConfig:

ads: {}

initialFetchTimeout: 0s

resourceApiVersion: V3

serviceName: outbound|80||nginx.test.svc.cluster.local

filters:

- name: istio.metadata_exchange

typedConfig:

'@type': type.googleapis.com/udpa.type.v1.TypedStruct

typeUrl: type.googleapis.com/envoy.tcp.metadataexchange.config.MetadataExchange

value:

enable_discovery: true

protocol: istio-peer-exchange

lbPolicy: LEAST_REQUEST

metadata:

filterMetadata:

istio:

services:

- host: nginx.test.svc.cluster.local

name: nginx

namespace: test

name: outbound|80||nginx.test.svc.cluster.local

transportSocketMatches:

- match:

tlsMode: istio

name: tlsMode-istio

transportSocket:

name: envoy.transport_sockets.tls

typedConfig:

'@type': type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext

commonTlsContext:

alpnProtocols:

- istio-peer-exchange

- istio

combinedValidationContext:

defaultValidationContext:

matchSubjectAltNames:

- exact: spiffe://cluster.local/ns/test/sa/default

validationContextSdsSecretConfig:

name: ROOTCA

sdsConfig:

apiConfigSource:

apiType: GRPC

grpcServices:

- envoyGrpc:

clusterName: sds-grpc

setNodeOnFirstMessageOnly: true

transportApiVersion: V3

initialFetchTimeout: 0s

resourceApiVersion: V3

tlsCertificateSdsSecretConfigs:

- name: default

sdsConfig:

apiConfigSource:

apiType: GRPC

grpcServices:

- envoyGrpc:

clusterName: sds-grpc

setNodeOnFirstMessageOnly: true

transportApiVersion: V3

initialFetchTimeout: 0s

resourceApiVersion: V3

tlsParams:

tlsMaximumProtocolVersion: TLSv1_3

tlsMinimumProtocolVersion: TLSv1_2

sni: outbound_.80_._.nginx.test.svc.cluster.local

- match: {}

name: tlsMode-disabled

transportSocket:

name: envoy.transport_sockets.raw_buffer

typedConfig:

'@type': type.googleapis.com/envoy.extensions.transport_sockets.raw_buffer.v3.RawBuffer

type: EDS

typedExtensionProtocolOptions:

envoy.extensions.upstreams.http.v3.HttpProtocolOptions:

'@type': type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions

useDownstreamProtocolConfig:

http2ProtocolOptions: {}

httpProtocolOptions: {}

可以看到,这个 cluster 是一个 EDS 类型的 cluster,它会从 edsConfig 中获取配置。

5.查看 endpoint


# istioctl -n test proxy-config endpoint test-f5b5d48b5-qdzft --cluster "outbound|80||nginx.test.svc.cluster.local" -oyaml

- addedViaApi: true

circuitBreakers:

thresholds:

- maxConnections: 4294967295

maxPendingRequests: 4294967295

maxRequests: 4294967295

maxRetries: 4294967295

- maxConnections: 1024

maxPendingRequests: 1024

maxRequests: 1024

maxRetries: 3

priority: HIGH

edsServiceName: outbound|80||nginx.test.svc.cluster.local

hostStatuses:

- address:

socketAddress:

address: 10.244.0.73

portValue: 80

healthStatus:

edsHealthStatus: HEALTHY

locality: {}

stats:

- name: cx_connect_fail

- name: cx_total

- name: rq_error

- name: rq_success

- name: rq_timeout

- name: rq_total

- name: cx_active

type: GAUGE

- name: rq_active

type: GAUGE

weight: 1

name: outbound|80||nginx.test.svc.cluster.local

observabilityName: outbound|80||nginx.test.svc.cluster.local

从 endpoint 中我们可以看到,流量会转发到 10.244.0.73:80 这个地址。因为我们这个 service 只有一个 pod,如果多个 pod 的话,会有多个 address。

envoy 会向访问 http://10.244.0.73:80,那么接下来就是 nginx pod 中的 envoy 会把流量转发到 nginx container 中。

6.server 劫持到15006


istioctl -n test proxy-config listener nginx-7c79c4bf97-7985c --port 15006

ADDRESSES PORT MATCH DESTINATION

0.0.0.0 15006 Addr: *:15006 Non-HTTP/Non-TCP

0.0.0.0 15006 Trans: tls; App: istio-http/1.0,istio-http/1.1,istio-h2; Addr: 0.0.0.0/0 InboundPassthroughClusterIpv4

0.0.0.0 15006 Trans: raw_buffer; App: http/1.1,h2c; Addr: 0.0.0.0/0 InboundPassthroughClusterIpv4

0.0.0.0 15006 Trans: tls; App: TCP TLS; Addr: 0.0.0.0/0 InboundPassthroughClusterIpv4

0.0.0.0 15006 Trans: raw_buffer; Addr: 0.0.0.0/0 InboundPassthroughClusterIpv4

0.0.0.0 15006 Trans: tls; Addr: 0.0.0.0/0 InboundPassthroughClusterIpv4

0.0.0.0 15006 Trans: tls; App: istio-http/1.0,istio-http/1.1,istio-h2; Addr: *:80 Cluster: inbound|80||

0.0.0.0 15006 Trans: raw_buffer; App: http/1.1,h2c; Addr: *:80 Cluster: inbound|80||

0.0.0.0 15006 Trans: tls; App: TCP TLS; Addr: *:80 Cluster: inbound|80||

0.0.0.0 15006 Trans: raw_buffer; Addr: *:80 Cluster: inbound|80||

0.0.0.0 15006 Trans: tls; Addr: *:80 Cluster: inbound|80||

listener 的虚拟端口


istioctl -n test proxy-config listener nginx-7c79c4bf97-7985c --port 80 --address 0.0.0.0

ADDRESSES PORT MATCH DESTINATION

0.0.0.0 80 Trans: raw_buffer; App: http/1.1,h2c Route: 80

0.0.0.0 80 ALL PassthroughCluster

所以 DESTINATION 是 Route: 80 ,所以 route 会匹配 inbound|80||

7.查看 server route


# istioctl -n test proxy-config route nginx-7c79c4bf97-7985c --name "inbound|80||" -oyaml

- name: inbound|80||

validateClusters: false

virtualHosts:

- domains:

- '*'

name: inbound|http|80

routes:

- decorator:

operation: nginx.test.svc.cluster.local:80/*

match:

prefix: /

name: default

route:

cluster: inbound|80||

maxStreamDuration:

grpcTimeoutHeaderMax: 0s

maxStreamDuration: 0s

timeout: 0s

- name: inbound|80||

validateClusters: false

virtualHosts:

- domains:

- '*'

name: inbound|http|80

routes:

- decorator:

operation: nginx.test.svc.cluster.local:80/*

match:

prefix: /

name: default

route:

cluster: inbound|80||

maxStreamDuration:

grpcTimeoutHeaderMax: 0s

maxStreamDuration: 0s

timeout: 0s

会匹配到 cluster inbound|80||,它是 inbound 类型的 route, 所以它会直接把流量转发到 80 端口。也就是 pod 中 nginx container 中的 nigix 进程。

链接:https://www.cnblogs.com/daemon365/p/18187995

(版权归原作者所有,侵删)

微信扫码关注该文公众号作者

戳这里提交新闻线索和高质量文章给我们。
相关阅读
最新 Amex Offers 汇总【Secrets & Impression by Secrets 度假村 $750返$200】“倒数第二”英文怎么说?千万不要翻译成“last second”!Life in the Background: The Extras Who Became Viral Stars解锁新方式!年轻人爱的支付方式,大家都适用!从普通员工到销售主管:二胎宝妈如何更好地兼职写作,既能兼顾好孩子,又能为工作赋能?(内附10W+文章写作方法)我在残冬中寻找初春的痕迹微软已同意向Inflection支付6.5亿美元以获得专利使用与人才团队,或是反垄断下新“收购”方式For Chinese Students, the New Tactic Against AI Checks: More AI20、长篇家庭伦理小说《嫁接 下》第六章 骑虎难下(2)瑞士高山滑雪家族企业 Nidecker 收购美国滑板品牌公司 Sole Technology「汪汪」to Vector!密歇根博士生用AI解码狗的声音 | LREC 2024全面智能化战略一年整,钉钉如何重塑工作方式?3D 版 SORA 来了!DreamTech 推出全球首个原生 3D-DiT 大模型 Direct3D在地铁里打瞌睡为什么专家建议不开心就多唱歌?研究表明:接触音乐方式可以改善工作记忆和执行力!特别是能会改善中晚年的大脑健康小心!华人常用移民方式恐遭严查!已有顾问坐牢!华人花$17万找的工作 雇主都不知道![电脑] Dell Precision 7875 工作站体验分享股价狂飙,总市值突破2.5万亿美元!CEO也赚翻了:年薪大涨60%!曾称“一周工作7天,不工作时仍会思考工作”李嘉诚被迫回归!70亿网红神盘商铺被法拍,合作方上演抢公章大戏联邦政府百色人生(三)How a Police Station Became China’s Hottest Holiday DestinationPiece by Piece, an Ancient Chinese Craft Is Shaping Future ToysLast Stop: Looking Past the Stigma Facing China’s Morticians毛泽东工作方法六十条,超实用,赶紧学起来吧!C计划转载/合作方式第一份工作被fintech startup小公司裁了Starved of Affection at Home, Teens Seek Out ‘Digital Parents’How an Elderly Actress Became China’s Biggest Matchmaker【NEU/NEC】【新建公寓】【1B1B$3700起,2B2B$4800起,3B2B$5400起】【研究生/工作人士】預測美國大選,拜登完勝川普KubeCon+CloudNativeCon+Open Source Summit+AI_Dev China 2024【限时半中介费】【步行五分钟,多睡两小时】【24小时前台安保】【杂费全包】【伯克利/NEU/NEC】【Studio/1B/2B】入戏快的写作方法有哪些?决策层定调地方金融工作方向学习工作压力大时恢复精力的最佳方式
logo
联系我们隐私协议©2024 redian.news
Redian新闻
Redian.news刊载任何文章,不代表同意其说法或描述,仅为提供更多信息,也不构成任何建议。文章信息的合法性及真实性由其作者负责,与Redian.news及其运营公司无关。欢迎投稿,如发现稿件侵权,或作者不愿在本网发表文章,请版权拥有者通知本网处理。