为什么我的服务“无法启动 Kestrel”仅在 EKS 中?

问题描述

我有一个非常奇怪和烦人的 Kubernetes 问题。我开发了登录服务(如 this),并且在我的 Windows 笔记本电脑上运行它时没有错误。此外,在使用 Docker Desktop 激活的本地 Kubernetes 单节点集群上运行它时,它也运行良好。在我的情况下,Docker 桌面使用带有 WSL (2) 集成的 Linux 容器。它希望我的 EKS 集群上的行为是相同的,而这根本没有发生。先说一下相关文件

这是我的部署文件

apiVersion: apps/v1
kind: Deployment
Metadata:
  name: xxxxxxxx
spec:
  selector:
   matchLabels:
    app: xxxxxxxx
  replicas: 3
  template:
    Metadata:
      labels:
        app: xxxxxxxx
    spec:
      containers:
      - name: xxxxxxxx
        image: yyyyyy.dkr.ecr.qqqqq.amazonaws.com/xxxxxxxx:2676
        livenessProbe:
          httpGet:
            path: /health/live
            port: 80
          initialDelaySeconds: 30
          timeoutSeconds: 5
        readinessProbe:
          httpGet:
            path: /health/ready
            port: 80
          initialDelaySeconds: 30
          timeoutSeconds: 5
        ports:
        - containerPort: 80
        env:
        - name: "ASPNETCORE_ENVIRONMENT"
          value: "KubernetesDevelopment"
        volumeMounts:
        - name: secrets
          mountPath: /secret
          readOnly: true
        resources:
          requests:
            memory: "64Mi"
            cpu: "250m"
          limits:
            memory: "128Mi"
            cpu: "500m"
      volumes:
      - name: secrets
        secret:
          secretName: secret-appsettings
      imagePullSecrets:
       - name: awspull
 

这是我的 Dockerfile:

FROM mcr.microsoft.com/dotnet/aspnet:5.0.4-alpine3.13 AS base
workdir /app
EXPOSE 80
EXPOSE 443

FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build
workdir /src
copY ["QQQQQ.API/QQQQQ.API.csproj","QQQQQ.API/"]
RUN dotnet restore "QQQQQ.API/QQQQQ.API.csproj"
copY . .
workdir "/src/QQQQQ.API"
RUN dotnet build "QQQQQ.API.csproj" -c Release -o /app/build

FROM build AS publish
RUN dotnet publish "QQQQQ.API.csproj" -c Release -o /app/publish

FROM base AS final
RUN addgroup -S lirantal && adduser -S lirantal -G lirantal
workdir /app
copY --from=publish /app/publish .
RUN chown -R lirantal:lirantal /app
USER lirantal
CMD cp /secret/*.* /app && dotnet QQQQQ.API.dll

这是已记录的内容(在我自己的本地 Kubernetes 集群上):

警告: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[60]

在目录中存储密钥 '/home/lirantal/.aspnet/DataProtection-Keys' 可能不会被持久化 容器外。受保护的数据将在以下情况下不可用 容器被破坏。

警告: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[35]

未配置 XML 加密器。钥匙 {e13ce6cb-c64d-4aaf-ad4f-1a345c73f5bc} 可以持久化到存储在 未加密形式。

信息:Microsoft.Hosting.Lifetime[0]

正在收听:http://[::]:80

信息:Microsoft.Hosting.Lifetime[0]

应用程序已启动。按 Ctrl+C 关闭

信息:Microsoft.Hosting.Lifetime[0] 托管环境:KubernetesDevelopment 信息:Microsoft.Hosting.Lifetime[0] 内容根路径:/app 警告:Microsoft.AspNetCore.HttpsPolicy.HttpsRedirectionMiddleware[3]

无法确定重定向的 https 端口。

这是在 AWS EKS 中运行时记录的内容

加载中... [40m[1m[33mwarn[39m[22m[49m: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[60] 将密钥存储在目录中 '/home/lirantal/.aspnet/DataProtection-Keys' 可能不会被持久化 容器外。受保护的数据将在以下情况下不可用 容器被破坏。 [40m[1m[33mwarn[39m[22m[49m: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[35] 否 已配置 XML 加密器。密钥 {04076fdc-f191-4253-9dc4-dbc77981d9b3} 可以以未加密的形式保存到存储中。 [41m[1m[37mcrit[39m[22m[49m: > Microsoft.AspNetCore.Server.Kestrel[0] 无法启动 Kestrel。 System.Net.sockets.socketException (13): 权限被拒绝 System.Net.sockets.socket.UpdateStatusAfterSocketErrorAndThrowException(SocketError error,String callerName) 在 System.Net.sockets.socket.dobind(EndPoint) endPointSnapshot,SocketAddress socketAddress) 在 System.Net.sockets.socket.Bind(EndPoint localEP) 在 Microsoft.AspNetCore.Server.Kestrel.Transport.sockets.socketConnectionListener.g__BindSocket|13_0(c__displayClass13_0& ) 在 Microsoft.AspNetCore.Server.Kestrel.Transport.sockets.socketConnectionListener.Bind() 在 Microsoft.AspNetCore.Server.Kestrel.Transport.sockets.socketTransportFactory.BindAsync(EndPoint 端点,CancellationToken 取消令牌)在 Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure.TransportManager.BindAsync(EndPoint 端点,ConnectionDelegate connectionDelegate,EndpointConfig 端点配置)在 Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServerImpl.c__displayClass29_01.<<StartAsync>g__OnBind|0>d.MoveNext() --- End of stack trace from prevIoUs location --- at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.AddressBinder.BindEndpointAsync(Listenoptions endpoint,AddressBindContext context) at Microsoft.AspNetCore.Server.Kestrel.Core.Listenoptions.BindAsync(AddressBindContext context) at Microsoft.AspNetCore.Server.Kestrel.Core.AnyIPListenoptions.BindAsync(AddressBindContext context) at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.AddressBinder.Addressesstrategy.BindAsync(AddressBindContext context) at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.AddressBinder.BindAsync(IEnumerable1 listenoptions、AddressBindContext 上下文)在 Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServerImpl.BindAsync(CancellationToken 取消令牌)在 Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServerImpl.StartAsync[TContext](IHttpApplication1 application,CancellationToken cancellationToken) Unhandled exception. System.Net.sockets.socketException (13): Permission denied at System.Net.sockets.socket.UpdateStatusAfterSocketErrorAndThrowException(SocketError error,String callerName) at System.Net.sockets.socket.dobind(EndPoint endPointSnapshot,SocketAddress socketAddress) at System.Net.sockets.socket.Bind(EndPoint localEP) at Microsoft.AspNetCore.Server.Kestrel.Transport.sockets.socketConnectionListener.<Bind>g__BindSocket|13_0(<>c__displayClass13_0& ) at Microsoft.AspNetCore.Server.Kestrel.Transport.sockets.socketConnectionListener.Bind() at Microsoft.AspNetCore.Server.Kestrel.Transport.sockets.socketTransportFactory.BindAsync(EndPoint endpoint,CancellationToken cancellationToken) at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure.TransportManager.BindAsync(EndPoint endPoint,ConnectionDelegate connectionDelegate,EndpointConfig endpointConfig) at Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServerImpl.<>c__displayClass29_01.d.MoveNext() --- 上一个位置的堆栈跟踪结束 --- 在 Microsoft.AspNetCore.Server.Kestrel.Core.Internal.AddressBinder.BindEndpointAsync(Listenoptions 端点,AddressBindContext 上下文)在 Microsoft.AspNetCore.Server.Kestrel.Core.Listenoptions.BindAsync(AddressBindContext 上下文)在 Microsoft.AspNetCore.Server.Kestrel.Core.AnyIPListenoptions.BindAsync(AddressBindContext 上下文)在 Microsoft.AspNetCore.Server.Kestrel.Core.Internal.AddressBinder.Addressesstrategy.BindAsync(AddressBindContext 上下文)在 Microsoft.AspNetCore.Server.Kestrel.Core.Internal.AddressBinder.BindAsync(IEnumerable1 listenoptions,AddressBindContext context) at Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServerImpl.BindAsync(CancellationToken cancellationToken) at Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServerImpl.StartAsync[TContext](IHttpApplication1 应用程序,CancellationToken 取消令牌)在 Microsoft.AspNetCore.Hosting.GenericWebHostService.StartAsync(CancellationToken 取消令牌)在 Microsoft.Extensions.Hosting.Internal.Host.StartAsync(CancellationToken 取消令牌)在 Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.RunAsync(IHost 主机,CancellationToken 令牌)在 Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.RunAsync(IHost 主机,CancellationToken 令牌)在 Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.Run(IHost 主机)在 QQQQ.API.Program.Main(String[] args) 在 /src/Kinly.SMPD.XXXXXXX.API/Program.cs:line 10

这真的很奇怪。我所做的只是输入:

kubectl apply -f deployment.yml

然后 pod 开始记录事情,这是正常的。但是,Kestrel 应该可以正常工作,但只能在我“自己的”Kubernetes 集群上运行,而不是在使用 EKS Kubernetes 集群时。怎么来的?以及如何修复?我觉得这很奇怪,因为这是我唯一的 EKS 问题。我的服务根本不记录任何错误,除非在我的 EKS 集群上运行它。所以请告诉我这是怎么可能的以及如何解决它。

解决方法

Microsoft.AspNetCore.Server.Kestrel[0] 无法启动 Kestrel。 System.Net.Sockets.SocketException (13): 权限被拒绝

看起来您的容器没有足够的权限来侦听您想要的端口。

在 Linux 中,您通常需要特权权限才能侦听端口 1024 和lover。我建议您将应用程序更改为侦听端口 8080 和 8433。您可以有一个暴露端口 80 但将其映射到 targetPort 8080 的服务。