Knative Service 是如何指定端口和協議的

若是使用 Knative Serving 部署一個 Nginx 你可能會發現服務起來了,可是沒法訪問到 Nginx 中的服務。固然這不是 Nginx 的問題,這是由於 Knative 對 Container 的端口有要求。默認 Nginx 的服務端口是 80 ,而 Knative Serving queue 8012 默認是代理到容器的 8080 端口。因此若是業務容器監聽的不是 8080 端口默認配置就不能對外暴露服務。具體的 spec 定義見這裏: https://github.com/kubedemo/serving/blob/v0.6.0/docs/spec/spec.mdmysql

注:固然 若是想要監聽多個端口也是不行的,雖然容器可以啓動成功,都是沒法經過 Service 暴露服務,從而沒法經過 Istio gateway 暴露到外面,因此也就不能提供服務。

當你在查看上述 Spec 定義的時候你可能已經注意到了下面這兩行註釋。爲何會保留這幾個端口呢?git

下面我經過一張圖來解釋一下 Knative Serving 流量轉發鏈路:github

如上圖所示,業務流量並非從 Gateway 直接打到業務容器中的,而是通過 queue 容器轉發的。queue 容器默認會監聽 8012 和 8013 分別用於轉發 http1 的流量和 http2 的流量。具體代碼參見:web

queue 容器在建立的時候會設定一個叫作 USER_PORT 的環境變量,queue 是經過這個環境變量來獲取應該轉發到業務容器的哪一個端口的。因此只要咱們可以修改 USER_PORT 這個環境變量咱們就能自定義監聽端口了。 USER_PORT 是經過 getUserPort 函數獲取的,具體函數定義以下:sql

代碼讀到這裏就已經很明朗了,建立 Knative Service 的時候能夠指定 Ports 端口,而後能夠經過端口的 containerPort 字段指定自定義端口。不過須要注意的是 Knative 只支持一個容器端口,因此雖然 Ports 是一個數組,但也只能設置一個。api

實例以下:數組

apiVersion: serving.knative.dev/v1alpha1
kind: Service
metadata:
  name: wordpress-serving
  namespace: default
spec:
  template:
    metadata:
      labels:
        app: wordpress
      annotations:
        autoscaling.knative.dev/target: "100"
    spec:
      containers:
        - image: registry.cn-hangzhou.aliyuncs.com/knative-sample/wordpress:5.2-20190524100810
          ports:
            - name: http1
              containerPort: 80
          env:
          - name: WORDPRESS_DB_HOST
            value: rm-2xx.mysql.rds.aliyuncs.com:3306
          - name: WORDPRESS_DB_USER
            value: wordpress
          - name: WORDPRESS_DB_PASSWORD
            value: xxx
          imagePullPolicy: Always

上面在分析的過程當中提到了 HTTP2 協議,若是當前提供的是 grpc 類型的服務就須要使用 http2 協議。app

若是使用的是 HTTP2 協議那麼也去請求就須要轉發到 queue 的 8013 端口上,而後由 8013 轉發給容器的業務端口。那麼如何指定咱們使用的協議呢?less

在前面的分析中咱們得出的結論是經過 port[0].containerPort 來指定自定義端口,其實也能夠指定 port[0].name 字段。而 Revision Controller 生成 Deployment 部署服務的時候就是這個 name 字段來判斷應該使用 http1(8012端口) 協議仍是 http2(8013端口) 協議的。wordpress

  • http1 表明使用 http1(8012端口) 協議,同時 http1 也是默認策略,也就是說若是未指定那麼默認也是 http1 協議
  • h2c 表明使用 http2(8013端口) 協議

代碼分析以下:

https://github.com/kubedemo/serving/blob/release-0.6/pkg/apis/serving/v1alpha1/revision_lifecycle.go#L104

那麼怎樣才能指定容器的自定義端口呢?經過查閱代碼可知

https://github.com/kubedemo/serving/blob/release-0.6/pkg/reconciler/serverlessservice/resources/services.go#L32

小結

Knative Service 能夠給容器添加 ports 字段,而且 ports 只能設置一個端口。ports 有兩個關鍵字段 Name 和 ContainerPort

ports:
            - name: http1
              containerPort: 80
  • name 字段表示使用的協議,有效值有 http1 和 h2c 兩個,其中:

    • http1 表示使用 http1 協議,好比 web 服務和 websock 均可以使用 http1
    • grpc 須要設置成 h2c
  • containerPort 字段就是容器提供服務的惟一端口。業務端口能夠設置 1-65535 這個範圍中除了 80十二、801三、802二、8091 和 8092 之外的任意端口

阿里雲雙11億元補貼提早領,進入抽取iPhone 11 Pro:https://www.aliyun.com/1111/2019/home?utm_content=g_1000083110


本文做者:冬島

閱讀原文

本文爲雲棲社區原創內容,未經容許不得轉載。

相關文章
相關標籤/搜索