我已经在Windows下像这样设置了本地K8s集群:

  • 为桌面安装docker
  • 在桌面版docker中使用
  • ,启用kubernetes
  • 安装Nginx入口 Controller

  • kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.29.0/deploy/static/mandatory.yaml
    kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.29.0/deploy/static/provider/cloud-generic.yaml
    
  • 将以下域添加到主机(C:\Windows\System32\drivers\etc\hosts)
  • 127.0.0.1  localhost api.shopozor
    
    我在这里没有做任何特别的事情,我将所有设置都保留为默认设置。
    然后,我使用以下yaml将hasura部署到群集中(为了简洁起见,我没有显示postgres部署):
    ---
    # Source: api/templates/secrets.yaml
    apiVersion: v1
    kind: Secret
    metadata:
      name: api
      labels:
        app.kubernetes.io/name: api
        helm.sh/chart: api-0.0.0
        app.kubernetes.io/instance: api
        app.kubernetes.io/version: "0.0"
        app.kubernetes.io/managed-by: Helm
    type: Opaque
    data:
      admin-secret: "c2VjcmV0"
    ---
    # Source: api/templates/service.yaml
    apiVersion: v1
    kind: Service
    metadata:
      name: api
      labels:
        app.kubernetes.io/name: api
        helm.sh/chart: api-0.0.0
        app.kubernetes.io/instance: api
        app.kubernetes.io/version: "0.0"
        app.kubernetes.io/managed-by: Helm
    spec:
      type: ClusterIP
      ports:
        - port: 8080
          targetPort: 8080
          # TODO: we cannot use string port because devspace doesn't support it in its UI
          # targetPort: http
          protocol: TCP
          name: http
      selector:
        app.kubernetes.io/name: api
        app.kubernetes.io/instance: api
    ---
    # Source: api/templates/deployment.yaml
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: api
      labels:
        app.kubernetes.io/name: api
        helm.sh/chart: api-0.0.0
        app.kubernetes.io/instance: api
        app.kubernetes.io/version: "0.0"
        app.kubernetes.io/managed-by: Helm
    spec:
      replicas: 1
      selector:
        matchLabels:
          app.kubernetes.io/name: api
          app.kubernetes.io/instance: api
      template:
        metadata:
          labels:
            app.kubernetes.io/name: api
            app.kubernetes.io/instance: api
        spec:
          serviceAccountName: api
          securityContext:
            {}
          initContainers:
          # App has to wait for the database to be online "depends_on" workaround
          - name: wait-for-db
            image: darthcabs/tiny-tools:1
            args:
            - /bin/bash
            - -c
            - >
              set -x;
              while [[ "$(nc -zv 'postgres' 5432 &> /dev/null; echo $?)" != 0 ]]; do
                echo '.'
                sleep 15;
              done
          containers:
          - name: api
            securityContext:
                {}
            image: shopozor/graphql-engine:EM5Aya
            imagePullPolicy:
            env:
            - name: POSTGRES_USER
              valueFrom:
                secretKeyRef:
                  name: shared-postgresql
                  key: postgresql-username
            - name: POSTGRES_DATABASE
              value: shopozor
            - name: POSTGRES_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: shared-postgresql
                  key: postgresql-password
            - name: POSTGRES_HOST
              value: postgres
            - name: POSTGRES_PORT
              value: "5432"
            - name: HASURA_GRAPHQL_SERVER_PORT
              value: "8080"
            - name: HASURA_GRAPHQL_ENABLE_CONSOLE
              value: "true"
            - name: HASURA_GRAPHQL_ENABLED_LOG_TYPES
              value: startup, http-log, webhook-log, websocket-log, query-log
            - name: HASURA_GRAPHQL_ENABLE_TELEMETRY
              value: "false"
            - name: HASURA_GRAPHQL_CORS_DOMAIN
              value: "*"
            - name: HASURA_GRAPHQL_DISABLE_CORS
              value: "false"
            - name: HASURA_GRAPHQL_UNAUTHORIZED_ROLE
              value: incognito
            - name: HASURA_GRAPHQL_ADMIN_SECRET
              valueFrom:
                secretKeyRef:
                  name: api
                  key: admin-secret
            - name: HASURA_GRAPHQL_JWT_SECRET
              value: "{\"type\": \"HS256\", \"key\": \"my-access-token-signing-key-secret\", \"audience\": [\"58640fbe-9a6c-11ea-bb37-0242ac130002\", \"6e707590-9a6c-11ea-bb37-0242ac130002\"], \"claims_namespace\": \"https://hasura.io/jwt/claims\", \"claims_format\": \"json\", \"issuer\": \"shopozor.com\" }"
            - name: HASURA_GRAPHQL_DATABASE_URL
              value: postgres://$(POSTGRES_USER):$(POSTGRES_PASSWORD)@$(POSTGRES_HOST):$(POSTGRES_PORT)/$(POSTGRES_DATABASE)
            - name: FUNCTION_NAMESPACE
              value: dev
            ports:
            - name: http
              containerPort: 8080
              protocol: TCP
            livenessProbe:
              httpGet:
                path: /healthz
                port: http
            readinessProbe:
              httpGet:
                path: /healthz
                port: http
            resources:
                {}
    ---
    # Source: api/templates/ingress.yaml
    apiVersion: networking.k8s.io/v1beta1
    kind: Ingress
    metadata:
      name: api
      labels:
        app.kubernetes.io/name: api
        helm.sh/chart: api-0.0.0
        app.kubernetes.io/instance: api
        app.kubernetes.io/version: "0.0"
        app.kubernetes.io/managed-by: Helm
      annotations:
        kubernetes.io/ingress.class: nginx
    spec:
      rules:
        - host: "api.shopozor"
          http:
            paths:
              - path: /
                backend:
                  serviceName: api
                  servicePort: 8080
    
    现在,我有一个nuxt前端,试图利用hasura的websocket。我以标准方式配置了阿波罗
    //---
    // nuxt.config.js
    [...]
      // Give apollo module options
      apollo: {
        cookieAttributes: {
          expires: 7
        },
        includeNodeModules: true,
        authenticationType: 'Basic',
        clientConfigs: {
          default: '~/apollo/clientConfig.js'
        }
      },
    [...]
    //---
    // apollo/clientConfig.js
    import { InMemoryCache } from 'apollo-cache-inmemory'
    export default function (context) {
      return {
        httpLinkOptions: {
          uri: 'http://api.shopozor/v1/graphql',
          credentials: 'same-origin'
        },
        cache: new InMemoryCache(),
        wsEndpoint: 'ws://localhost:8080/v1/graphql'
      }
    }
    
    注意,我目前不需要特定的标题。我应该能够在没有授权 token 的情况下访问websocket。
    现在,当我启动我的应用程序时,websocket连接将尝试初始化。如果我将hasura服务移植到了我,那么上面的配置就可以了。 websocket连接似乎正在工作。至少,hasura日志显示
    2020-07-16T06:49:59.937386882Z {"type":"websocket-log","timestamp":"2020-07-16T06:49:59.937+0000","level":"info","detail":{"event":{"type":"accepted"},"connection_info":{"websocket_id":"8437b784-1fce-4430-9ca9-a9e7517307f0","token_expiry":null,"msg":null},"user_vars":null}}
    
    但是,如果我更改上述配置中的wsEndpoint以使用进入hasura实例的入口,
    wsEndpoint: 'ws://api.shopozor/v1/graphql'
    
    那就不行了相反,我不断得到404 Not Found。但是,我可以通过http://api.shopozor访问hasura控制台。 hasura日志显示
    2020-07-16T10:37:53.564657244Z {"type":"websocket-log","timestamp":"2020-07-16T10:37:53.564+0000","level":"error","detail":{"event":{"type":"rejected","detail":{"path":"$","error":"only '/v1/graphql', '/v1alpha1/graphql' are supported on websockets","code":"not-found"}},"connection_info":{"websocket_id":"5e031467-fb5c-460d-b2a5-11f1e21f22e7","token_expiry":null,"msg":null},"user_vars":null}}
    
    因此,我在Google上搜索了很多东西,找到了一些我应该在入口中使用的注释信息,但没有任何效果。我在这里想念什么?我是否需要特定的Nginx入口 Controller 配置?我需要将某些特殊注释传递给我的hasura入口吗?我需要做些什么才能使其正常工作?
    编辑
    为了回答这篇文章的问题,这是我对集群应用的hasura的入侵:
    apiVersion: extensions/v1beta1
    kind: Ingress
    metadata:
      annotations:
        kubernetes.io/ingress.class: nginx
        meta.helm.sh/release-name: api
        meta.helm.sh/release-namespace: dev
      labels:
        app.kubernetes.io/instance: api
        app.kubernetes.io/managed-by: Helm
        app.kubernetes.io/name: api
        app.kubernetes.io/version: '0.0'
        helm.sh/chart: api-0.0.0
      name: api
    spec:
      rules:
        - host: api.shopozor
          http:
            paths:
              - backend:
                  serviceName: api
                  servicePort: 8080
                path: /
    
    编辑2
    在我的hasura实例的以下入口中
    apiVersion: extensions/v1beta1
    kind: Ingress
    metadata:
      annotations:
        kubernetes.io/ingress.class: nginx
        meta.helm.sh/release-name: api
        meta.helm.sh/release-namespace: dev
        nginx.ingress.kubernetes.io/configuration-snippet: |
          proxy_http_version 1.1;
          proxy_set_header Upgrade "websocket";
          proxy_set_header Connection "Upgrade";
      labels:
        app.kubernetes.io/instance: api
        app.kubernetes.io/managed-by: Helm
        app.kubernetes.io/name: api
        app.kubernetes.io/version: '0.0'
        helm.sh/chart: api-0.0.0
      name: api
    spec:
      rules:
        - host: api.shopozor
          http:
            paths:
              - backend:
                  serviceName: api
                  servicePort: 8080
                path: /
    
    前端应用程序对于websockets仍然存在相同的问题。此外,它不再能够真正连接到hasura。相反,我收到以下错误:
     ERROR  Network error: Unexpected token < in JSON at position 0                                                                                                                                         23:17:06
    
      at new ApolloError (D:\workspace\shopozor\services\node_modules\apollo-client\bundle.umd.js:92:26)
      at D:\workspace\shopozor\services\node_modules\apollo-client\bundle.umd.js:1588:34
      at D:\workspace\shopozor\services\node_modules\apollo-client\bundle.umd.js:2008:15
      at Set.forEach (<anonymous>)
      at D:\workspace\shopozor\services\node_modules\apollo-client\bundle.umd.js:2006:26
      at Map.forEach (<anonymous>)
      at QueryManager.broadcastQueries (D:\workspace\shopozor\services\node_modules\apollo-client\bundle.umd.js:2004:20)
      at D:\workspace\shopozor\services\node_modules\apollo-client\bundle.umd.js:1483:29
      at runMicrotasks (<anonymous>)
      at processTicksAndRejections (internal/process/task_queues.js:97:5)
    
    Global error handler                                                                                                                                                                                    23:17:06
    
     ERROR  Network error: Unexpected token < in JSON at position 0                                                                                                                                         23:17:06
    
      at new ApolloError (D:\workspace\shopozor\services\node_modules\apollo-client\bundle.umd.js:92:26)
      at D:\workspace\shopozor\services\node_modules\apollo-client\bundle.umd.js:1486:27
      at runMicrotasks (<anonymous>)
      at processTicksAndRejections (internal/process/task_queues.js:97:5)
    
    以及
    client.js?06a0:49 ApolloError: Network error: Unexpected token < in JSON at position 0
        at new ApolloError (D:\workspace\shopozor\services\node_modules\apollo-client\bundle.umd.js:92:26)
        at D:\workspace\shopozor\services\node_modules\apollo-client\bundle.umd.js:1486:27
        at runMicrotasks (<anonymous>)
        at processTicksAndRejections (internal/process/task_queues.js:97:5) {
      graphQLErrors: [],
      networkError: SyntaxError [ServerParseError]: Unexpected token < in JSON at position 0
          at JSON.parse (<anonymous>)
          at D:\workspace\shopozor\services\node_modules\apollo-link-http-common\lib\index.js:35:25
          at runMicrotasks (<anonymous>)
          at processTicksAndRejections (internal/process/task_queues.js:97:5) {
        name: 'ServerParseError',
        response: Body {
          url: 'http://api.shopozor/v1/graphql/',
          status: 404,
          statusText: 'Not Found',
          headers: [Headers],
          ok: false,
          body: [PassThrough],
          bodyUsed: true,
          size: 0,
          timeout: 0,
          _raw: [Array],
          _abort: false,
          _bytes: 153
        },
        statusCode: 404,
        bodyText: '<html>\r\n' +
          '<head><title>404 Not Found</title></head>\r\n' +
          '<body>\r\n' +
          '<center><h1>404 Not Found</h1></center>\r\n' +
          '<hr><center>nginx/1.17.8</center>\r\n' +
          '</body>\r\n' +
          '</html>\r\n'
      },
      message: 'Network error: Unexpected token < in JSON at position 0',
      extraInfo: undefined
    }
    
    index.js?a6d6:111 OPTIONS http://api.shopozor/v1/graphql/ net::ERR_ABORTED 404 (Not Found)
    
    Access to fetch at 'http://api.shopozor/v1/graphql/' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
    
    没有新的注释
    nginx.ingress.kubernetes.io/configuration-snippet: |
          proxy_http_version 1.1;
          proxy_set_header Upgrade "websocket";
          proxy_set_header Connection "Upgrade";
    
    在我的hasura入口上,除了websockets,前端和hasura之间的连接工作正常。
    编辑3
    我尝试了以下两个入口,但没有成功:
    apiVersion: extensions/v1beta1
    kind: Ingress
    metadata:
      annotations:
        kubernetes.io/ingress.class: nginx
        meta.helm.sh/release-name: api
        meta.helm.sh/release-namespace: dev
        nginx.ingress.kubernetes.io/proxy-read-timeout: '3600'
        nginx.ingress.kubernetes.io/proxy-send-timeout: '3600'
        nginx.ingress.kubernetes.io/configuration-snippet: |
          proxy_http_version 1.1;
          proxy_set_header Upgrade "websocket";
          proxy_set_header Connection "Upgrade";
      labels:
        app.kubernetes.io/instance: api
        app.kubernetes.io/managed-by: Helm
        app.kubernetes.io/name: api
        app.kubernetes.io/version: '0.0'
        helm.sh/chart: api-0.0.0
      name: api
    spec:
      rules:
        - host: api.shopozor
          http:
            paths:
              - backend:
                  serviceName: api
                  servicePort: 8080
                path: /
    

    apiVersion: extensions/v1beta1
    kind: Ingress
    metadata:
      annotations:
        kubernetes.io/ingress.class: nginx
        meta.helm.sh/release-name: api
        meta.helm.sh/release-namespace: dev
        nginx.ingress.kubernetes.io/proxy-read-timeout: '3600'
        nginx.ingress.kubernetes.io/proxy-send-timeout: '3600'
      labels:
        app.kubernetes.io/instance: api
        app.kubernetes.io/managed-by: Helm
        app.kubernetes.io/name: api
        app.kubernetes.io/version: '0.0'
        helm.sh/chart: api-0.0.0
      name: api
    spec:
      rules:
        - host: api.shopozor
          http:
            paths:
              - backend:
                  serviceName: api
                  servicePort: 8080
                path: /
    
    在后一种情况下,我只会得到错误
    WebSocket connection to 'ws://api.shopozor/v1/graphql/' failed: Error during WebSocket handshake: Unexpected response code: 404
    
    而graphql端点正常运行。在前一种情况下,我无法访问hasura实例上的任何内容,并且上面遇到了websocket握手问题(因此,没有graphql和websocket无法正常工作)。
    编辑4
    如果我这样做,请使用我的api入口配置(不像上面那样附加任何其他nginx注释:nginx.ingress.kubernetes.io/proxy-read-timeout nginx.ingress.kubernetes.io/proxy-send-timeoutnginx.ingress.kubernetes.io/configuration-snippet):
    curl -i -N -H "Connection: Upgrade" \
     -H "Upgrade: websocket" \
     -H "Origin: http://localhost:3000" \
     -H "Host: api.shopozor" \
     -H "Sec-Websocket-Version: 13" \
     -H "Sec-WebSocket-Key: B8KgbaRLCMNCREjE5Kvg1w==" \
     -H "Sec-WebSocket-Protocol: graphql-ws" \
     -H "Accept-Encoding: gzip, deflate" \
     -H "Accept-Language: en-US,en;q=0.9" \
     -H "Cache-Control: no-cache" \
     -H "Pragma: no-cache" \
     -H "Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits" \
     -H "User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.49 Safari/537.36" \
     http://api.shopozor/v1/graphql
    
    然后hasura很高兴:
    2020-07-28T07:42:28.903877263Z {"type":"websocket-log","timestamp":"2020-07-28T07:42:28.894+0000","level":"info","detail":{"event":{"type":"accepted"},"connection_info":{"websocket_id":"94243bde-41c4-42c8-8d8f-355c47a3492e","token_expiry":null,"msg":null},"user_vars":null}}
    
    我上面 curl 的标题与我的前端应用发送的标题完全相同。关于我在做什么错的任何线索吗?前端调用和此curl的区别在于,在前端中,我将websocket端点定义为ws://api.shopozor/v1/graphql,而我对http://api.shopozor/v1/graphql进行了 curl 。我无法在apollo vue中将wsEndpoint设置为http://api.shopozor/v1/graphql。我得到一个错误。

    最佳答案

    听起来您正在使用nginx入口 Controller 和WebSockets are supported out of the box
    您可以尝试以下注释💡:

    nginx.ingress.kubernetes.io/configuration-snippet: |
       proxy_http_version 1.1;
       proxy_set_header Upgrade "websocket";
       proxy_set_header Connection "Upgrade";
    
    或/和其他注释,因为docs📄建议将其用于WebSockets:
    nginx.ingress.kubernetes.io/proxy-read-timeout: 3600
    nginx.ingress.kubernetes.io/proxy-send-timeout: 3600
    
    注意:我刚才回答了similar question⌛⌚。

    10-08 06:22