Start Debugging

gRPC в контейнерах кажется сложным в .NET 9 и .NET 10: 4 ловушки, которые можно исправить

Четыре частые ловушки при размещении gRPC в контейнерах с .NET 9 и .NET 10: несовпадение протокола HTTP/2, путаница с терминацией TLS, сломанные health-проверки и неверная настройка прокси -- с исправлением для каждой.

Сегодня снова всплыло в r/dotnet: “Почему так сложно размещать gRPC-сервисы в контейнерах?”. Короткий ответ: gRPC категоричен в отношении HTTP/2, а контейнеры делают сетевую границу более явной. Вы вынуждены решить, где терминируется TLS, какие порты говорят на HTTP/2 и какой прокси стоит спереди.

Исходное обсуждение: https://www.reddit.com/r/dotnet/comments/1q93h2h/why_is_hosting_grpc_services_in_containers_so_hard/

Ловушка 1: порт контейнера доступен, но не говорит на HTTP/2

gRPC требует HTTP/2 от начала до конца. Если прокси понижает до HTTP/1.1, вы получаете загадочные сбои “unavailable”, которые выглядят как баги приложения.

В .NET 9 / .NET 10 явно укажите намерение сервера:

using Microsoft.AspNetCore.Server.Kestrel.Core;

var builder = WebApplication.CreateBuilder(args);

builder.WebHost.ConfigureKestrel(options =>
{
    // Inside a container you usually run plaintext HTTP/2 and terminate TLS at the proxy.
    options.ListenAnyIP(8080, listen =>
    {
        listen.Protocols = HttpProtocols.Http2;
    });
});

builder.Services.AddGrpc();

var app = builder.Build();
app.MapGrpcService<GreeterService>();
app.MapGet("/", () => "gRPC service. Use a gRPC client.");
app.Run();

Ловушка 2: терминация TLS не определена (а gRPC-клиентам это важно)

Многие команды считают, что “контейнер = TLS”. На практике терминировать TLS на границе проще:

Если вы всё-таки терминируете TLS в Kestrel, вам также нужны сертификаты внутри контейнера и нужный открытый порт. Это работоспособно, просто больше движущихся частей.

Ловушка 3: health-проверки опрашивают не то

HTTP-пробы Kubernetes и базовые пробы балансировщиков нагрузки часто работают по HTTP/1.1. Если вы опрашиваете gRPC-эндпоинт напрямую, он может падать, даже когда сервис здоров.

Два практических решения:

Ловушка 4: прокси и значения HTTP/2 по умолчанию вас кусают

Самый простой способ заставить gRPC “казаться сложным” — поставить впереди прокси, который не настроен на HTTP/2 в сторону upstream. Убедитесь, что ваш прокси явно настроен:

Именно на этом последнем пункте многие конфигурации Nginx по умолчанию ломаются с gRPC.

Конфигурация контейнера, которая остаётся скучной

Если хочется единой точки отсчёта, прежде чем трогать Kubernetes, начните с локальной проверки: запустите контейнер, постучитесь к нему через grpcurl, затем поставьте прокси спереди и убедитесь, что HTTP/2 по-прежнему согласовывается от начала до конца.

Дополнительно: https://learn.microsoft.com/aspnet/core/grpc/

Comments

Sign in with GitHub to comment. Reactions and replies thread back to the comments repo.

< Назад