Mergulhe profundamente na malha ambiente - caminho de tráfego

O Ambient Mesh foi anunciado há algum tempo e existem alguns artigos descrevendo seu uso e arquitetura. Este artigo classificará profundamente o caminho do tráfego do plano de dados no modo ambiente para ajudá-lo a entender completamente o esquema de implementação do plano de dados ambiente.

Antes de ler este artigo, leia a introdução ao Ambient Mesh: https://istio.io/latest/blog/2022/introducing-ambient-mesh/ para entender a arquitetura básica do Ambient Mesh.

Para facilitar a leitura e a prática síncrona, o ambiente usado neste artigo é implantado de acordo com a forma como o Ambient usa: https://istio.io/latest/blog/2022/get-started-ambient/.

01

a partir
do momento em que o pedido é iniciado

Para explorar o caminho do tráfego, primeiro analisamos o acesso mútuo entre dois serviços em modo ambiente (somente modo L4, nós diferentes).

Depois que o modo ambiente for ativado no namespace padrão, todos os serviços terão a capacidade de governança de grade.

Nossa análise começa com este comando: kubectl exec deploy/sleep -- curl -s [http://productpage:9080/](http://productpage:9080/) | head -n1

No modo Sidecar, o Istio intercepta o tráfego por meio do iptables. Quando o curl é executado no sleep Pod, o tráfego é encaminhado pelo iptables para a porta 15001 do Sidecar para processamento. Mas no modo ambiente, não há sidecar no pod e o pod não precisa ser reiniciado quando o modo ambiente é ativado, então como garantir que sua solicitação seja processada pelo ztunnel?

02

Interceptação de tráfego de saída

Para entender a solução para interceptação de tráfego de saída, podemos primeiro olhar para os componentes do plano de controle:

kebe@pc $ kubectl -n istio-system get poNAME                                   READY   STATUS    RESTARTS   AGEistio-cni-node-5rh5z                   1/1     Running   0          20histio-cni-node-qsvsz                   1/1     Running   0          20histio-cni-node-wdffp                   1/1     Running   0          20histio-ingressgateway-5cfcb57bd-kx9hx   1/1     Running   0          20histiod-6b84499b75-ncmn7                1/1     Running   0          20hztunnel-nptf6                          1/1     Running   0          20hztunnel-vxv4b                          1/1     Running   0          20hztunnel-xkz4s                          1/1     Running   0          20h

istio-cni torna-se o componente padrão no modo ambiente. No modo Sidecar, o istio-cni é principalmente um plug-in CNI para evitar o vazamento de permissão causado pelo uso do contêiner istio-init para processar as regras do iptables. No entanto, no modo Ambient, o Sidecar não é teoricamente necessário, então por que o istio-cni é necessário? ?

Podemos dar uma olhada no log:

kebe@pc $ kubectl -n istio-system logs istio-cni-node-qsvsz...2022-10-12T07:34:33.224957Z  info  ambient  Adding route for reviews-v1-6494d87c7b-zrpks/default: [table 100 10.244.1.4/32 via 192.168.126.2 dev istioin src 10.244.1.1]2022-10-12T07:34:33.226054Z  info  ambient  Adding pod 'reviews-v2-79857b95b-m4q2g/default' (0ff78312-3a13-4a02-b39d-644bfb91e861) to ipset2022-10-12T07:34:33.228305Z  info  ambient  Adding route for reviews-v2-79857b95b-m4q2g/default: [table 100 10.244.1.5/32 via 192.168.126.2 dev istioin src 10.244.1.1]2022-10-12T07:34:33.229967Z  info  ambient  Adding pod 'reviews-v3-75f494fccb-92nq5/default' (e41edf7c-a347-45cb-a144-97492faa77bf) to ipset2022-10-12T07:34:33.232236Z  info  ambient  Adding route for reviews-v3-75f494fccb-92nq5/default: [table 100 10.244.1.6/32 via 192.168.126.2 dev istioin src 10.244.1.1]

Podemos ver que para Pods no modo ambiente, istio-cni faz duas coisas:

  1. Adicionar pods ao ipset

  2. Adicionada uma regra de roteamento à tabela 100 (usada posteriormente)

Podemos verificar o conteúdo do ipset no nó onde ele está localizado (observe que o tipo cluster é usado aqui e o docker exec precisa ser usado para entrar no host primeiro):

kebe@pc $ docker exec -it ambient-worker2 bashroot@ambient-worker2:/# ipset listName: ztunnel-pods-ipsType: hash:ipRevision: 0Header: family inet hashsize 1024 maxelem 65536Size in memory: 520References: 1Number of entries: 5Members:10.244.1.510.244.1.710.244.1.810.244.1.410.244.1.6

Descobrimos que existe um ipset no nó onde o Pod está localizado, no qual vários IPs são salvos, e esses IPs são IPs do Pod:

kebe@pc $ kubectl get po -o wideNAME                              READY   STATUS    RESTARTS   AGE   IP           NODE              NOMINATED NODE   READINESS GATESdetails-v1-76778d6644-wn4d2       1/1     Running   0          20h   10.244.1.9   ambient-worker2   <none>           <none>notsleep-6d6c8669b5-pngxg         1/1     Running   0          20h   10.244.2.5   ambient-worker    <none>           <none>productpage-v1-7c548b785b-w9zl6   1/1     Running   0          20h   10.244.1.7   ambient-worker2   <none>           <none>ratings-v1-85c74b6cb4-57m52       1/1     Running   0          20h   10.244.1.8   ambient-worker2   <none>           <none>reviews-v1-6494d87c7b-zrpks       1/1     Running   0          20h   10.244.1.4   ambient-worker2   <none>           <none>reviews-v2-79857b95b-m4q2g        1/1     Running   0          20h   10.244.1.5   ambient-worker2   <none>           <none>reviews-v3-75f494fccb-92nq5       1/1     Running   0          20h   10.244.1.6   ambient-worker2   <none>           <none>sleep-7b85956664-z6qh7            1/1     Running   0          20h   10.244.2.4   ambient-worker    <none>           <none>

Portanto, este ipset salva a lista de todos os IPs do Pod no modo ambiente no nó atual.

Onde esse ipset pode ser usado?

Podemos olhar para as regras do iptables e encontrar:

root@ambient-worker2:/# iptables-save*mangle...-A POSTROUTING -j ztunnel-POSTROUTING...-A ztunnel-PREROUTING -p tcp -m set --match-set ztunnel-pods-ips src -j MARK --set-xmark 0x100/0x100

Com isso, sabemos que quando um Pod em modo ambiente (em ztunnel-pods-ips ipset) em um nó inicia uma requisição, sua conexão será marcada com 0x100/0x100.

Geralmente, neste caso, estará relacionado ao roteamento, vamos dar uma olhada nas regras de roteamento:

root@ambient-worker2:/# ip rule0:  from all lookup local100:  from all fwmark 0x200/0x200 goto 32766101:  from all fwmark 0x100/0x100 lookup 101102:  from all fwmark 0x40/0x40 lookup 102103:  from all lookup 10032766:  from all lookup main32767:  from all lookup default

Pode-se observar que o tráfego marcado com 0x100/0x100 passará pela tabela de roteamento da tabela 101. Podemos visualizar a tabela de roteamento:

root@ambient-worker2:/# ip r show table 101default via 192.168.127.2 dev istioout10.244.1.2 dev veth5db63c11 scope link

Pode-se ver que o gateway padrão foi substituído por 192.168.127.2 e a placa de rede istioout foi removida.

Mas há um problema aqui. O IP 192.168.127.2 não pertence a nenhum dos Node IP, Pod IP e Cluster IP. A placa de rede istioout não deveria existir por padrão, então quem criou esse IP? Como o tráfego precisa ser enviado para o ztunnel no final, podemos examinar a configuração do ztunnel para ver se encontramos a resposta. ​​​​​​

kebe@pc $ kubectl -n istio-system get po ztunnel-vxv4b -o yamlapiVersion: v1kind: Podmetadata:  ...  name: ztunnel-vxv4b  namespace: istio-system  ...spec:  ...  initContainers:  - command:      ...      OUTBOUND_TUN=istioout      ...      OUTBOUND_TUN_IP=192.168.127.1      ZTUNNEL_OUTBOUND_TUN_IP=192.168.127.2
      ip link add name p$INBOUND_TUN type geneve id 1000 remote $HOST_IP      ip addr add $ZTUNNEL_INBOUND_TUN_IP/$TUN_PREFIX dev p$INBOUND_TUN
      ip link add name p$OUTBOUND_TUN type geneve id 1001 remote $HOST_IP      ip addr add $ZTUNNEL_OUTBOUND_TUN_IP/$TUN_PREFIX dev p$OUTBOUND_TUN
      ip link set p$INBOUND_TUN up      ip link set p$OUTBOUND_TUN up      ...

Como acima, o ztunnel será responsável por criar a placa de rede istioout, e podemos ver a placa de rede correspondente no nó. ​​​​​​

root@ambient-worker2:/# ip a11: istioout: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UNKNOWN group default    link/ether 0a:ea:4e:e0:8d:26 brd ff:ff:ff:ff:ff:ff    inet 192.168.127.1/30 brd 192.168.127.3 scope global istioout       valid_lft forever preferred_lft forever

Onde está o IP do gateway de 192.168.127.2? Ele é alocado dentro do ztunnel.

kebe@pc $ kubectl -n istio-system exec -it ztunnel-nptf6 -- ip aDefaulted container "istio-proxy" out of: istio-proxy, istio-init (init)2: eth0@if3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default    link/ether 46:8a:46:72:1d:3b brd ff:ff:ff:ff:ff:ff link-netnsid 0    inet 10.244.2.3/24 brd 10.244.2.255 scope global eth0       valid_lft forever preferred_lft forever    inet6 fe80::448a:46ff:fe72:1d3b/64 scope link       valid_lft forever preferred_lft forever4: pistioout: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UNKNOWN group default qlen 1000    link/ether c2:d0:18:20:3b:97 brd ff:ff:ff:ff:ff:ff    inet 192.168.127.2/30 scope global pistioout       valid_lft forever preferred_lft forever    inet6 fe80::c0d0:18ff:fe20:3b97/64 scope link       valid_lft forever preferred_lft forever

Pode-se ver agora que o tráfego irá para o ztunnel, mas neste momento nenhuma outra operação é realizada no tráfego, ele é simplesmente roteado para o ztunnel, como o Envoy no ztunnel pode processar o tráfego?

Vamos continuar olhando a configuração do ztunnel, ele escreveu muitas regras do iptables, podemos entrar no ztunnel para ver as regras específicas:​​​​​​​​

kebe@pc $ kubectl -n istio-system exec -it ztunnel-nptf6 -- iptables-saveDefaulted container "istio-proxy" out of: istio-proxy, istio-init (init)...*mangle-A PREROUTING -i pistioout -p tcp -j TPROXY --on-port 15001 --on-ip 127.0.0.1 --tproxy-mark 0x400/0xfff...COMMIT

Pode ser visto claramente que quando o tráfego entra no ztunnel, TPROXY será usado para transferir o tráfego para a porta 15001 para processamento. Aqui, 15001 é a porta que o Envoy realmente escuta para processar o tráfego de saída do pod. Sobre TPROXY, você pode aprender informações relevantes por si mesmo. Este artigo não os repetirá.

Portanto, para resumir, quando o Pod está no modo ambiente, seu caminho de tráfego de saída é aproximadamente:

  1. Inicie o tráfego de processos no pod.

  2. O tráfego flui pela rede do nó onde está localizado e é marcado pelo iptables do nó.

  3. A tabela de roteamento no nó encaminhará o tráfego para o pod ztunnel do nó atual.

  4. Quando o tráfego chegar ao ztunnel, será feito um proxy transparente pelo TPROXY por meio do iptables, e o tráfego será encaminhado para a porta 15001 do Envoy no Pod atual para processamento.

Até agora, podemos ver que no modo ambiente, o processamento do tráfego de saída do pod é relativamente complexo e o caminho é relativamente longo , ao contrário do modo sidecar, que conclui diretamente o encaminhamento do tráfego dentro do pod.

03

Interceptação de tráfego de entrada

Com a experiência acima, não é difícil descobrir que, no modo ambiente, a interceptação do tráfego ocorre principalmente por meio do roteamento MARK + TPROXY, e o tráfego de entrada deve ser semelhante.

Vamos usar o método de análise mais simples para dar uma olhada e analisá-lo. Quando um processo em um nó ou um programa em outro host acessa um Pod no nó atual, o tráfego passará pela tabela de roteamento do host. Vamos verificar quando o acesso correspondente à página do produto - Informações de roteamento em v1-7c548b785b-w9zl6(10.244.1.7):

root@ambient-worker2:/# ip r get 10.244.1.710.244.1.7 via 192.168.126.2 dev istioin table 100 src 10.244.1.1 uid 0    cache

Podemos ver que ao acessar 10.244.1.7, o tráfego será roteado para 192.168.126.2, e esta regra é adicionada pelo istio-cni acima.

O mesmo IP 192.168.126.2 pertence ao ztunnel:

kebe@pc $ kubectl -n istio-system exec -it ztunnel-nptf6 -- ip aDefaulted container "istio-proxy" out of: istio-proxy, istio-init (init)2: eth0@if3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default    link/ether 46:8a:46:72:1d:3b brd ff:ff:ff:ff:ff:ff link-netnsid 0    inet 10.244.2.3/24 brd 10.244.2.255 scope global eth0       valid_lft forever preferred_lft forever    inet6 fe80::448a:46ff:fe72:1d3b/64 scope link       valid_lft forever preferred_lft forever3: pistioin: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UNKNOWN group default qlen 1000    link/ether 7e:b2:e6:f9:a4:92 brd ff:ff:ff:ff:ff:ff    inet 192.168.126.2/30 scope global pistioin       valid_lft forever preferred_lft forever    inet6 fe80::7cb2:e6ff:fef9:a492/64 scope link       valid_lft forever preferred_lft forever

Seguindo o mesmo método de análise, vejamos as regras do iptables:

kebe@pc $ kubectl -n istio-system exec -it ztunnel-nptf6 -- iptables-save...-A PREROUTING -i pistioin -p tcp -m tcp --dport 15008 -j TPROXY --on-port 15008 --on-ip 127.0.0.1 --tproxy-mark 0x400/0xfff-A PREROUTING -i pistioin -p tcp -j TPROXY --on-port 15006 --on-ip 127.0.0.1 --tproxy-mark 0x400/0xfff...

Se você acessar diretamente a porta PodIP+Pod no nó, ela será encaminhada para a porta 15006 do ztunnel, que é a porta onde o Istio processa o tráfego de entrada.

Quanto ao tráfego cuja porta de destino é a porta 15008, esta é a porta usada pelo ztunnel para o túnel de tráfego da Camada 4. Falaremos sobre isso mais tarde.

04


Para o próprio processamento de tráfego do Envoy

Sabemos que no modo Sidecar, Envoy e business containers rodam na mesma rede NS. Para o tráfego de business containers, precisamos interceptar todo o tráfego para garantir o controle total do tráfego, mas é necessário no modo Ambient?

A resposta é não, porque o Envoy foi separado em outros Pods e o tráfego enviado pelo Envoy não requer processamento especial. Em outras palavras, para o ztunnel, precisamos apenas lidar com o tráfego de entrada, então as regras no ztunnel parecem relativamente simples.

05

continua

Acima, analisamos principalmente a solução para interceptação de tráfego de pod no modo ambiente, mas ainda não envolvida no processamento de 70% do tráfego, e o princípio específico da implementação do ztunnel. Posteriormente, analisaremos o caminho de processamento detalhado do tráfego no ztunnel e no waypoint proxy.


 autor deste artigo 

Kebe Liu

Especialista técnico em grade de serviço "DaoCloud Daoke", membro do comitê de direção da comunidade Istio, colaborador do código Istio e Kubernetes, iniciador do projeto de código aberto Merbridge

Acho que você gosta

Origin blog.csdn.net/DaoCloud_daoke/article/details/127498148
Recomendado
Clasificación