Uwaga
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
W standardowym połączeniu protokołu TCP (Transmission Control Protocol) nie przepływa danych między elementami równorzędnymi, gdy połączenie jest bezczynne. W związku z tym aplikacje lub żądania interfejsu API korzystające z protokołu TCP do komunikowania się z serwerami obsługującymi długotrwałe żądania mogą być uzależnione od przekroczenia limitu czasu połączenia, aby znać zakończenie lub utratę połączenia. W tym artykule przedstawiono zastosowanie mechanizmu utrzymywania aktywności TCP w celu zwiększenia odporności na uszkodzenia w aplikacjach hostowanych w usłudze Azure Kubernetes Service (AKS).
Zrozumienie mechanizmu TCP keepalive
Kilka usług sieciowych platformy Azure, takich jak Azure Load Balancer (ALB), umożliwia skonfigurowanie limitu czasu po zakończeniu bezczynnego połączenia TCP. Gdy połączenie TCP pozostaje bezczynne przez dłuższy niż czas trwania limitu czasu skonfigurowanego w usłudze sieciowej, wszelkie kolejne pakiety TCP wysyłane w obu kierunkach mogą zostać porzucone. Alternatywnie mogą odbierać pakiet resetowania TCP (RST) z usługi sieciowej, w zależności od tego, czy w usłudze włączono resetowanie protokołu TCP.
Funkcja limitu czasu bezczynności w usłudze ALB została zaprojektowana w celu zoptymalizowania wykorzystania zasobów zarówno dla aplikacji klienckich, jak i serwerowych. Ten limit czasu dotyczy zarówno ruchu przychodzącego, jak i wychodzącego zarządzanego przez usługę ALB. Po przekroczeniu limitu czasu aplikacje klienckie i serwerowe mogą przestać przetwarzać żądania i zwalniać zasoby skojarzone z połączeniem. Te zasoby można następnie użyć ponownie dla innych żądań, poprawiając ogólną wydajność aplikacji.
W usłudze AKS resetowanie protokołu TCP w stanie bezczynności jest domyślnie włączone w usłudze Load Balancer z limitem czasu bezczynności przez 30 minut. Ten okres limitu czasu można dostosować przy użyciu polecenia az aks update
. Poniższy przykład ustawia limit czasu na 45 minut.
az aks update \
--resource-group myResourceGroup \
--name myAKSCluster \
--load-balancer-idle-timeout 45
Przed dostosowaniem należy dokładnie rozważyć czas trwania limitu czasu:
- Czas trwania, który jest zbyt krótki, może spowodować przedwczesne zakończenie długotrwałych operacji, co powoduje niepowodzenie żądań i słabe środowisko użytkownika. Może to również prowadzić do częstych limitów czasu, które zwiększają współczynniki błędów i sprawiają, że aplikacje wydają się zawodne.
- Czas trwania zbyt długi może opróżnić zasoby serwera, utrzymując otwarte bezczynne połączenia, zmniejszając pojemność dostępną do obsługi nowych żądań. Może również opóźnić wykrywanie problemów z serwerem, co prowadzi do dłuższych przestojów i nieefektywnego równoważenia obciążenia.
W usłudze AKS oprócz ruchu północno-południowego (ruchu przychodzącego i wychodzącego), który przechodzi przez usługę ALB, masz również ruch wschodnio-zachodni (zasobnik do zasobnika), który zazwyczaj działa w sieci klastra. Limit czasu w takich przypadkach jest definiowany przez kube-proxy
ustawienia protokołu TCP i ustawienia sysctl zasobnika TCP. Domyślnie kube-proxy
działa w trybie iptables i używa domyślnych ustawień limitu czasu PROTOKOŁU TCP zdefiniowanych w specyfikacji serwera proxy kube-proxy. Domyślne ustawienia limitu czasu protokołu TCP dla programu kube-proxy
są następujące:
- Czas wygaśnięcia tłumaczenia adresów sieciowych (NAT) dla połączeń TCP w stanie
CLOSE_WAIT
wynosi 1 godzinę. - Limit czasu bezczynności dla ustanowionych połączeń TCP wynosi 24 godziny.
W przypadku niektórych długotrwałych operacji, w których klient i serwer znajdują się zarówno wewnątrz klastra usługi AKS, jak i jeśli jeden z nich znajduje się poza nim, może być potrzebny limit czasu dłuższy niż czas trwania skonfigurowany dla usług sieciowych, takich jak usługa Azure Load Balancer lub usługa Azure NAT Gateway. Aby zapobiec zachowaniu bezczynności połączenia poza skonfigurowanym czasem trwania usługi sieciowej, rozważ użycie funkcji utrzymania aktywności protokołu TCP. Ta funkcja zapewnia dostępność zarówno serwera, jak i klienta podczas oczekiwania na odpowiedzi, dzięki czemu można ponowić próby operacji zamiast napotykać przekroczenia limitu czasu połączenia.
W przypadku połączenia TCP jeden z elementów równorzędnych może żądać elementu keepalives dla ich strony połączenia. Keepalives można skonfigurować dla klienta, serwera, obu lub żadnego z nich. Mechanizm utrzymania aktywności jest zgodny ze standardowymi specyfikacjami zdefiniowanymi w RFC1122. Sonda keepalive jest pustym segmentem lub segmentem zawierającym tylko 1 bajt. Zawiera numer sekwencji, który jest o jeden mniejszy niż największy numer potwierdzenia (ACK) otrzymany od partnera do tej pory. Pakiet sondy naśladuje odebrany pakiet. W odpowiedzi odbiorca wysyła kolejny pakiet ACK. Wskazuje to nadawcy, że połączenie jest nadal aktywne.
Specyfikacja RFC1122 wskazuje, że jeśli sonda lub ACK zostaną utracone, nie zostaną one ponownie przetransmitowane. Dlatego brak odpowiedzi na pojedynczy sygnał typu keepalive niekoniecznie oznacza, że połączenie przestało działać. W takim przypadku nadawca musi podjąć próbę wysłania sondy jeszcze kilka razy przed zakończeniem połączenia. Czas bezczynności połączenia jest resetowany, gdy ACK jest odebrany dla sondy, a następnie proces jest powtarzany. Sondy keepalive umożliwiają skonfigurowanie następujących parametrów w celu zarządzania ich zachowaniem. W usłudze AKS węzły oparte na systemie Linux mają następujące domyślne ustawienia przechowywania protokołu TCP, które są takie same jak standardowe systemy operacyjne Linux:
- Keepalive Time (w sekundach): czas trwania braku aktywności, po którym jest wysyłana pierwsza sonda keepalive. Domyślny czas trwania 7200 sekund lub 2 godziny.
- Przerwa keepalive (w sekundach): odstęp między kolejnymi sygnałami keepalive, jeśli nie otrzymano potwierdzenia. Domyślny interwał to 75 sekund.
- Sondy keepalive: maksymalna liczba nieznaczonych sond, zanim połączenie zostanie uznane za bezużyteczne. Wartość domyślna to 9.
Sondy keepalive są zarządzane w warstwie TCP. Po włączeniu sondy mogą spowodować następujące wyniki dla aplikacji żądającej:
- Normalne operacje: sondy keepalive nie wpływają na aplikację żądającego.
- Ponowne uruchomienie węzła lub awaria (sondy nie zostały potwierdzone): aplikacja otrzymuje błąd "upłynął limit czasu połączenia".
- Ponowne uruchomienie lub zawieszenie węzła równorzędnego (odpowiedź RESET RST): aplikacja otrzymuje błąd "resetowanie połączenia przez węzeł równorzędny".
- Problemy z siecią z hostem partnera: aplikacja może otrzymać komunikat o tym, że czas połączenia został przekroczony lub inny powiązany błąd.
W następnej sekcji wyjaśniono, jak zmienić ustawienia sysctl dla klastra i poda aplikacji w celu skonfigurowania TCP keepalive.
Konfigurowanie utrzymywania aktywności TCP w usłudze AKS
Usługa AKS umożliwia administratorom klastra dostosowanie systemu operacyjnego węzła i parametrów kubelet w celu dostosowania ich do wymagań dotyczących obciążeń. Podczas konfigurowania klastra lub nowej puli węzłów administratorzy mogą włączyć sysctls istotne dla swoich obciążeń. Platforma Kubernetes kategoryzuje sysctls na dwie grupy: bezpieczne i niebezpieczne.
Bezpieczne parametry sysctl to te, które są osadzone w przestrzeni nazw i prawidłowo odizolowane między podami na tym samym węźle. Ta izolacja oznacza, że skonfigurowanie bezpiecznego folderu sysctl dla jednego zasobnika nie wpływa na inne zasobniki w węźle, kondycję węzła lub zezwala zasobnikowi na przekroczenie limitów zasobów procesora CPU lub pamięci. Platforma Kubernetes domyślnie włącza bezpieczne pliki sysctls. Od wersji 1.29 platformy Kubernetes wszystkie sysctls keepalive protokołu TCP są uznawane za bezpieczne:
net.ipv4.tcp_keepalive_time
net.ipv4.tcp_fin_timeout
net.ipv4.tcp_keepalive_intvl
net.ipv4.tcp_keepalive_probes
Aby dowiedzieć się więcej o bezpiecznych i niebezpiecznych systemach i ich konfiguracji, zobacz Dostosowywanie konfiguracji węzłów dla pul węzłów usługi Azure Kubernetes Service (AKS).
Uwaga / Notatka
Od wersji Kubernetes 1.29, sysctle keepalive dla protokołu TCP są uznawane za bezpieczne i są domyślnie włączone. Nie trzeba ich jawnie włączać w klastrze.
Możesz skonfigurować mechanizmy sysctl TCP keepalive w żądanym podzie, ustawiając kontekst bezpieczeństwa w definicjach podów w następujący sposób:
apiVersion: v1
kind: Pod
metadata:
name: busybox-sysctls
spec:
securityContext:
sysctls:
- name: "net.ipv4.tcp_keepalive_time"
value: "45"
- name: "net.ipv4.tcp_keepalive_probes"
value: "5"
- name: "net.ipv4.tcp_keepalive_intvl"
value: "45"
containers:
- name: busybox
image: busybox
command: ["sleep", "3600"]
Zastosowanie specyfikacji implementuje następujące zachowanie utrzymania aktywności TCP:
-
net.ipv4.tcp_keepalive_time
Konfiguruje sondy utrzymania aktywności, które mają być wysyłane po 45 sekundach braku aktywności w połączeniu. -
net.ipv4.tcp_keepalive_probes
Konfiguruje system operacyjny tak, aby wysyłał 5 niepotwierdzonych sond keepalive zanim połączenie zostanie uznane za nieużyteczne. -
net.ipv4.tcp_keepalive_intvl
Ustawia czas trwania między wysłaniem dwóch sond keepalive do 45 sekund.
Systemy sysctls TCP keepalive są nazwane w jądrze systemu Linux, co oznacza, że mogą być ustawione indywidualnie dla każdego poda na węźle. Ta segregacja umożliwia skonfigurowanie ustawień utrzymywania połączenia za pośrednictwem kontekstu zabezpieczeń poda, który ma zastosowanie do wszystkich kontenerów w tym samym podzie.
Zasobnik jest teraz gotowy do wysyłania i reagowania na sondy utrzymania aktywności. Aby sprawdzić ustawienia, możesz wykonać polecenie sysctl
na podzie w następujący sposób:
kubectl exec -it busybox-sysctls -- sh -c "sysctl net.ipv4.tcp_keepalive_time net.ipv4.tcp_keepalive_intvl net.ipv4.tcp_keepalive_probes"
Wykonanie polecenia powinno spowodować wygenerowanie następujących danych wyjściowych:
net.ipv4.tcp_keepalive_time = 45
net.ipv4.tcp_keepalive_intvl = 45
net.ipv4.tcp_keepalive_probes = 5
W następnej sekcji opisano, w jaki sposób można zagwarantować, że aplikacje mają włączoną funkcję podtrzymywania połączenia TCP na połączeniach z klientem.
Konfigurowanie utrzymania aktywności protokołu TCP w aplikacjach
Aplikacja kliencka TCP powinna włączyć utrzymywania aktywności TCP, aby sondy keepalive były wysyłane do serwera. Większość języków programowania i struktur udostępnia opcje umożliwiające utrzymywanie aktywności tcp na połączeniach gniazd. W poniższym przykładzie użyto biblioteki socket
języka Python:
import socket
import sys
# Create a TCP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Enable TCP keepalive
sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
# Optional: Set TCP keepalive parameters (Linux specific).
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, 60) # Idle time before keepalive probes
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPINTVL, 10) # Interval between keepalive probes
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPCNT, 5) # Number of keepalive probes
# Connect to the server
server_address = ('server.example.com', 12345)
print(f'Connecting to {server_address[0]} port {server_address[1]}')
sock.connect(server_address)
try:
# Send and receive data
message = 'This is a test message.'
print(f'Sending: {message}')
sock.sendall(message.encode())
# Wait for a response
data = sock.recv(1024)
print(f'Received: {data.decode()}')
finally:
print('Closing connection')
sock.close()
W tym przykładzie:
- Aplikacja umożliwia utrzymywanie aktywności TCP.
- Sondy keepalive są wysyłane po 60 sekundach braku aktywności.
- Sondy keepalive są wysyłane w odstępach czasu 10 sekund.
- Jeśli 5 kolejnych sond zakończy się niepowodzeniem, połączenie zostanie zamknięte.
Uwaga / Notatka
Należy pamiętać, że każda konfiguracja na poziomie systemu TCP keepalive ustawiona za pośrednictwem polecenia sysctl
w usłudze kubelet jest zastępowana przez ustawienia przechowywania na żywo protokołu TCP aplikacji. Aby zachować spójne utrzymywanie aktywności w swoich aplikacjach, ustaw parametry keepalive na poziomie kubelet. Następnie włącz opcję keepalive w gnieździe bez określania specyficznych parametrów w aplikacji, aby parametry keepalive na poziomie systemu były używane dla aplikacji. Zezwalaj poszczególnym aplikacjom na zastępowanie wartości parametrów na poziomie systemu, na przykład w poprzednim przykładzie, gdy jest to absolutnie konieczne.
Jeśli używasz platformy .NET, poniższy kod generuje taki sam wynik jak w poprzednim przykładzie języka Python:
static async Task Main()
{
using SocketsHttpHandler handler = new SocketsHttpHandler();
handler.ConnectCallback = async (ctx, ct) =>
{
var s = new Socket(SocketType.Stream, ProtocolType.Tcp) { NoDelay = true };
try
{
s.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
s.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.TcpKeepAliveTime,60);
s.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.TcpKeepAliveInterval, 10);
s.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.TcpKeepAliveRetryCount, 5);
await s.ConnectAsync(ctx.DnsEndPoint, ct);
return new NetworkStream(s, ownsSocket: true);
}
catch
{
s.Dispose();
throw;
}
};
// Create an HttpClient object
using HttpClient client = new HttpClient(handler);
// Call asynchronous network methods in a try/catch block to handle exceptions
try
{
HttpResponseMessage response = await client.GetAsync("<service url>");
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine($"Read {responseBody.Length} characters");
}
catch (HttpRequestException e)
{
Console.WriteLine("\nException Caught!");
Console.WriteLine($"Message: {e.Message} ");
}
}
Aby uzyskać więcej informacji, zobacz program obsługi ConnectCallback.
HTTP/2 keepalive
Jeśli używasz protokołów komunikacyjnych opartych na protokole HTTP/2, takich jak gRPC, ustawienia przechowywania protokołu TCP nie mają wpływu na aplikacje. Protokół HTTP/2 jest zgodny ze specyfikacjami RFC7540, co nakazuje klientowi wysłanie ramki PING do serwera i natychmiastowej odpowiedzi serwera za pomocą ramki PING ACK. Protokół HTTP/2 działa w warstwie 7 stosu sieciowego i korzysta z gwarancji dostarczania danych dostarczonych przez protokół TCP, który działa w warstwie 4. Ponieważ każde żądanie HTTP/2 gwarantuje odpowiedź, jedyną konfiguracją utrzymania aktywności niezbędną dla transportu HTTP/2 jest ustawienie limitu czasu. Jeśli usługa PING ACK nie zostanie odebrana przed skonfigurowanym limitem czasu, połączenie zostanie rozłączone.
Gdy aplikacje korzystają z transportu HTTP/2, serwer jest odpowiedzialny za obsługę utrzymania aktywności połączenia oraz określenie jego zachowania. Ustawienia utrzymania aktywności klienta muszą być zgodne z ustawieniami serwera. Jeśli na przykład klient wysyła ramkę PING częściej niż zezwala serwer, serwer przerywa połączenie, odpowiadając ramką GOAWAY HTTP/2.
W przypadku aplikacji gRPC klient i serwer mogą dostosować ustawienia utrzymania aktywności, w tym możliwość dostosowywania takich wartości domyślnych jak interwał między ramkami PING, maksymalny czas, przez jaki kanał może istnieć, i inne. Aby zapoznać się z pełną listą konfigurowalnych opcji i przykładów specyficznych dla języka demonstrujących aplikacje klienckie i serwerowe korzystające z funkcji keepalive, zobacz gRPC keepalive configuration specification (Specyfikacja konfiguracji keepalive usługi gRPC).
Najlepsze rozwiązania
Chociaż sondy utrzymania aktywności mogą poprawić odporność na awarie aplikacji, mogą również zużywać większą przepustowość, co może mieć wpływ na pojemność sieci i prowadzić do dodatkowych opłat. Ponadto na urządzeniach przenośnych zwiększona aktywność sieci może mieć wpływ na żywotność baterii. Dlatego ważne jest przestrzeganie następujących najlepszych rozwiązań:
- Dostosowywanie parametrów: dostosuj ustawienia utrzymania aktywności na podstawie wymagań aplikacji i warunków sieciowych.
- Utrzymanie aktywności na poziomie aplikacji: w przypadku szyfrowanych połączeń (na przykład TLS/SSL) rozważ zaimplementowanie mechanizmów utrzymania aktywności w warstwie aplikacji, aby upewnić się, że sondy są wysyłane za pośrednictwem bezpiecznych kanałów.
- Monitorowanie i rejestrowanie: zaimplementuj rejestrowanie, aby monitorować zamknięcia połączeń wywołane przez keepalive na potrzeby rozwiązywania problemów.
- Mechanizmy awaryjne: Projektuj aplikacje tak, aby bezproblemowo obsługiwały rozłączenia, w tym logikę ponawiania prób i strategie przełączania awaryjnego.
Azure Kubernetes Service