I den forrige Vi har gennemgået de grundlæggende komponenter i Service Mesh Istio, gjort os bekendt med systemet og besvaret de mest almindelige spørgsmål, der typisk opstår i starten af arbejdet med Istio. I denne del vil vi se på, hvordan man organiserer indsamlingen af tracing-informationer i netværket.

Det første, der falder mange udviklere og systemadministratorer ind, når de hører ordene Service Mesh, er tracing. Og det giver mening, da vi tilføjer en specialproxyserver til hver node i netværket, som al TCP-trafik passerer gennem. Det virker som om, at vi nu kan sende oplysninger om alle netværksinteraktioner i netværket uden problemer. Desværre opstår der i virkeligheden mange nuancer, som skal tages i betragtning. Lad os se på dem.
Misforståelse nummer et: Vi kan gratis få adgang til data om netværksbesøg.
Faktisk kan vi kun relativt gratis få forbindelse mellem noderne i vores system og rate data, der passerer mellem tjenesterne (i bund og grund kun antallet af byte pr. tidsenhed). Men i de fleste tilfælde kommunikerer vores tjenester via et eller andet applikationsprotokol, såsom HTTP, gRPC, Redis og så videre. Og selvfølgelig vil vi gerne se tracinginformationen netop for disse protokoller, vi vil se anmodningsraten i stedet for dataraten. Vi vil forstå latensen for anmodningerne i vores protokol. Endelig vil vi gerne se den fulde sti, som en anmodning tager fra den kommer ind i vores system til brugeren modtager et svar. Denne opgave er ikke så ligetil at løse.
For starters, let's consider how tracing spans are sent from an architectural perspective in Istio. As we recall from the first part, Istio has a separate component for collecting telemetry known as Mixer. However, in the current version 1.0.*, sending occurs directly from the proxy servers, namely, from the Envoy proxy. The Envoy proxy supports sending tracing spans via the Zipkin protocol out of the box. Other protocols can be integrated, but only through a plugin. With Istio, we immediately get a collected and configured Envoy proxy, which only supports the Zipkin protocol. If we want to use, for example, Jaeger protocol and send tracing spans over UDP, we will need to build our own istio-proxy image. Support for custom plugins for istio-proxy exists, but it is still in alpha version. Therefore, if we want to avoid a lot of custom configurations, the range of technologies used for storing and receiving tracing spans decreases. Among the main systems, currently, we can use Zipkin itself, or Jaeger, but send everything there using the Zipkin-compatible protocol (which is significantly less efficient). The Zipkin protocol itself assumes sending all tracing information to collectors via HTTP protocol, which is quite resource-intensive.
As I mentioned earlier, we want to trace application-level protocols. This means that the proxy servers adjacent to each service must understand what kind of interaction is occurring at the moment. By default, Istio configures all ports as plain TCP type, which means no traces will be sent. To ensure traces are sent, we must first enable this option in the main mesh config, and importantly, name all ports of the service entities in Kubernetes according to the protocol being used in the service. For example, like this:
apiVersion: v1
kind: Service
metadata:
name: nginx
spec:
ports:
- port: 80
targetPort: 80
name: http
selector:
app: nginxYou can also use composite names, such as http-magic (Istio will recognize http and identify this port as an http endpoint). The format is as follows: proto-extra.
To avoid patching a large number of configurations to define the protocol, you can use a dirty workaround: patch the Pilot component at the moment when it is performing the logic of defining the protocol I sidste ende skal vi selvfølgelig ændre denne logik til den standardmæssige og gå over til en navngivningskonvention for alle porte.
For virkelig at forstå, om protokollen er korrekt defineret, skal du gå ind i en hvilken som helst af sidecar-containere med envoy proxy og anmode om porten til admin-interfacet for envoy med location /config_dump. I den resulterende konfiguration skal du se på operation-feltet for den ønskede service. Det bruges i Istio som en identifikator for, hvor anmodningen sker. For at tilpasse værdien af denne parameter i Istio (som vi senere vil se i vores tracing-system), er det nødvendigt at angive flaget serviceCluster ved opstart af sidecar-containeren. For eksempel kan det beregnes på denne måde ud fra variablerne, der modtages fra downward API i Kubernetes:
--serviceCluster ${POD_NAMESPACE}.$(echo ${POD_NAME} | sed -e 's/-[a-z0-9]*-[a-z0-9]*$//g')
Et godt eksempel på at forstå, hvordan tracing fungerer i envoy, er .
Selve endpointet til at sende tracing spans skal også angives i flagsene til opstart af envoy proxy, for eksempel: --zipkinAddress tracing-collector.tracing:9411
Misforståelse nummer to: vi kan billigt få fulde traces af anmodningernes passage gennem systemet fra start.
Desværre er det ikke rigtigt. Komplikationen ved implementeringen afhænger af, hvordan dit servicenetværk allerede er implementeret. Hvorfor er det sådan?
Årsagen er, at for at istio-proxy kan forstå korrespondensen mellem indgående anmodninger til en service og udgående fra den samme service, er det ikke nok blot at fange al trafik. Der skal være en form for forbindelsesidentifikator. I HTTP envoy proxy benyttes der specielle headerfelter, som gør, at envoy kan forstå, hvilken specifik anmodning til servicen der genererer specifikke anmodninger til andre services. Listen over sådanne headere:
- x-request-id,
- x-b3-traceid,
- x-b3-spanid,
- x-b3-parentspanid,
- x-b3-sampled,
- x-b3-flags,
- x-ot-span-context.
Hvis du har et samlet punkt, for eksempel en grundlæggende klient, hvor sådan logik kan tilføjes, så er alt godt; du skal blot vente på, at dette bibliotek opdateres hos alle klienter. Men hvis du har et meget heterogent system uden standardisering af interaktionen mellem services over netværket, så vil det sandsynligvis være et stort problem. Uden at tilføje sådan logik vil al tracing-information kun være "enkelt niveau". Det vil sige, at vi får alle inter-service-interaktioner, men de vil ikke blive samlet til enheder af forløb gennem netværket.
Konklusion
Istio giver en praktisk løsning til indsamling af tracing-information over netværket, men det er vigtigt at forstå, at implementeringen kræver tilpasning af dit system og hensyntagen til de specifikke karakteristika ved Istio. Resultatet er, at der skal løses to hovedpunkter: definitionen af applikationsniveau-protokollen (som skal understøttes af envoy proxy) og konfigurationen af informationsoverførsel om anmodningsforbindelser fra service til service (ved hjælp af headers, i tilfælde af HTTP-protokollen). Når disse spørgsmål er løst, opnår vi et kraftfuldt værktøj, der gør det muligt at indsamle oplysninger fra netværket på en gennemsigtig måde, selv i meget heterogene systemer bygget med mange forskellige sprog og rammer.
I den næste artikel om Service Mesh vil vi se på et af de største problemer med Istio - det høje forbrug af RAM fra hver sidecar proxy-container, og diskutere, hvordan vi kan tackle det.
Kilde: habr.com
