kubernetes GKE错误:listen EACCES:在任何端口上拒绝许可

weylhg0b  于 2023-10-17  发布在  Kubernetes
关注(0)|答案(3)|浏览(155)

我试图在GKE上启动我的js.js应用程序,但是无论我指定哪个端口,我总是得到这样的错误:

Error: listen EACCES: permission denied tcp://10.3.253.94:3000
    at Server.setupListenHandle [as _listen2] (net.js:1296:21)
    at listenInCluster (net.js:1361:12)
    at Server.listen (net.js:1458:5)
    at Function.listen (/srv/node_modules/express/lib/application.js:618:24)
    at Object.<anonymous> (/srv/src/index.js:42:5)
    at Module._compile (internal/modules/cjs/loader.js:1137:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1157:10)
    at Module.load (internal/modules/cjs/loader.js:985:32)
    at Function.Module._load (internal/modules/cjs/loader.js:878:14)
    at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:71:12)

我尝试了多个端口(8080,8000,3000)。我在Docker镜像中将用户设置为root
下面是我的设置:

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: api
  name: api
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app: api
  template:
    metadata:
      labels:
        app: api
    spec:
      dnsPolicy: ClusterFirst
      restartPolicy: Always
      containers:
        - image: gcr.io/ellioseven-kbp/journal-api:1.0.14
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 3000
          name: api
apiVersion: v1
kind: Service
metadata:
  labels:
    app: api
  name: api
  namespace: default
spec:
  ports:
    - port: 3000
      protocol: TCP
      targetPort: 3000
  selector:
    app: api
  type: NodePort
FROM node:12-alpine
ENV PATH /srv/node_modules/.bin:$PATH
ENV API_PORT 3000
ENV REDIS_HOST redis
COPY . /srv
WORKDIR /srv
ENV PATH /srv/node_modules/.bin:$PATH
RUN yarn install
CMD yarn start
EXPOSE 3000
USER root
const port = process.env.API_PORT || 3000
app.listen(port, () => console.log("Listening on " + port))

我在试图解决这个问题时完全不知所措,任何帮助都将不胜感激。

zdwk9cvp

zdwk9cvp1#

问题在environment variable conflicting with the service name上。
根据Kubernetes文档
对于Map到名为bar的容器的名为foo的服务,定义了以下变量:

FOO_SERVICE_HOST=<the host the service is running on>
FOO_SERVICE_PORT=<the port the service is running on>

更改服务名称或环境变量
例如,使用API_PORT_NUMBER而不是API_PORT

ecfdbz9o

ecfdbz9o2#

看起来它不能只绑定到3000端口。它可以是以下任何一种:

  • 不绑定到0.0.0.0。您可以尝试:
app.listen('3000','0.0.0.0',()=>{
    console.log("server is listening on 3000 port");
})
  • 您在容器中以非特权用户身份运行。看看你是否可以启动一个测试pod,并在它启动后运行命令。
apiVersion: apps/v1
  kind: Deployment
  metadata:
    labels:
      app: api
    name: api
    namespace: default
  spec:
    replicas: 1
    selector:
      matchLabels:
        app: api
    template:
      metadata:
        labels:
          app: api
      spec:
        dnsPolicy: ClusterFirst
        restartPolicy: Always
        containers:
          - image: gcr.io/ellioseven-kbp/journal-api:1.0.14
            imagePullPolicy: IfNotPresent
            command: [ "/bin/bash", "-c", "--" ] 👈
            args: [ "while true; do sleep 30; done;" ] 👈
            ports:
              - containerPort: 3000
            name: api

然后,您可以连接到Pod并尝试启动应用程序

kubectl exec -it <pod-name> bash

✌️

3duebb1j

3duebb1j3#

我在EKS上也遇到了同样的问题。与您的情况相同,问题是由于服务名称中的自动环境变量注入。
回到您的问题上下文,服务名是api,选择器指向pod api
K8将使用以下服务环境变量注入服务主机和端口(请参阅群集信息)

API_SERVICE_HOST=<the host the service is running on>
API_SERVICE_PORT=<the port the service is running on>

但是等等,这还不是全部!**. K8还创建与Docker Engine的“遗留容器链接”功能兼容的变量。
来自k8s服务网络-环境变量来源:
当Pod在Node上运行时,kubelet会为每个active Service添加一组环境变量。它添加了{SVCNAME}_SERVICE_HOST和{SVCNAME}_SERVICE_PORT变量,其中服务名称为大写,破折号转换为下划线。它还支持与Docker Engine的"legacy container links"功能兼容的变量(请参阅makeLinkVariables)。
因此,这里是api服务的环境变量的完整列表,它将被自动创建并注入到api pod中(您也可以在上面的原始K8s文档中看到redis-primary服务的示例)。

API_SERVICE_HOST = 10.3.253.94
API_SERVICE_PORT = 3000

API_PORT=tcp://10.3.253.94:3000   # @thang: This is the env var that cause the exception
API_PORT_3000_TCP=tcp://10.3.253.94:3000
API_PORT_3000_TCP_PROTO=tcp
API_PORT_3000_TCP_PORT=3000
API_PORT_3000_TCP_ADDR=10.3.253.94

正如您所看到的,自动生成的env包含API_PORT变量,它与您的env name变量名冲突
ENV API_PORT 3000
这种env命名冲突导致pod解析错误的API_PORT值并抛出pod启动异常。
为了解决这个问题,(正如上面@Anonymous回答所指出的那样),您必须:

  • api服务重命名为另一个名称,以避免env变量模式冲突
  • 或者为端口使用不同的env变量名,例如:API_PORT_NUMBER

相关问题