1. 程式人生 > 其它 >Knative1.0技術初探——serving、istio的安裝與函式部署

Knative1.0技術初探——serving、istio的安裝與函式部署

Preface

關於knative的介紹,參考:初識 Knative - 技術教程 (knative-sample.com)

11月4日,knative終於釋出了其第一個穩定版本:Knative 1.0。這是從2018年7月knative第一次釋出時,到現在已經歷經3年的時間了。本次釋出的主要特點有:

  • 支援多個 HTTP 路由層(包括 Istio、Contour、Kourier 和 Ambassador),當然主選應該還是istio;
  • 支援多個事件儲存層來處理事件的訂閱機制,比如Kafka、MQ等等;
  • 抽象了一個"duck type"型別,允許處理具有公共欄位的Kubernetes資源;
  • Knative Build獨立了出來,演化成了一個單獨的CI/CD專案:Tekon;
  • 使用Brokers and Triggers,簡化了事件的釋出和訂閱機制,解耦生產者和消費者;
  • 支援將事件元件傳送到非 Knative 元件,包括叢集外元件或主機上的特定 URL;
  • 支援自動配置TLS證書,通過DNS或HTTP01方式;
  • 新增Parallel 和 Sequence 元件,用於編寫某些複合事件工作流;
  • 支援基於併發或 RPS 的水平 Pod 自動縮放;
  • 使用 DomainMapping 簡化服務的管理和釋出 。

更多內容見官方檔案:Knative 1.0 is out! - Knative

安裝

tips:官網上installing描述不夠準確,還有helloworld的例子也有坑。我前前後後花了一週左右的時間才搞定,有點無語。

安裝前準備

配置

建議Linux環境進行安裝,我本地使用ubuntu。

  • cpu: 8核及以上
  • 記憶體:8GB及以上
  • 磁碟:40GB及以上
  • 網路:能訪問外網

環境

  1. docker

    這個不需多說,容器引擎docker。

    安裝比較簡單,直接安裝官方文件操作即可:https://docs.docker.com/get-started/

    tips: 最好再建立一個自己的docker up,可用於存放個人映象。

  2. k8s

    本地學習建議安裝minukube,直接安裝k8s難度太大了。

    minikube安裝比較簡單,參考:Minikube - Kubernetes本地實驗環境-阿里雲開發者社群 (aliyun.com)

  3. golang

    直接去官網下載最新的golang版本,解壓新增環境變數即可。

    官方手冊:https://golang.org/doc/install

其他

由於需要拉取k8s映象庫,國內是訪問不了的。辦法有:

安裝Knative-serving

官方的手冊:https://knative.dev/docs/install/serving/install-serving-with-yaml/

官方的文件有些坑,我後面再說。

安裝步驟如下:

安裝serving的元件

tips:官網的安裝方式是直接:

kubectl apply -f https://github.com/knative/serving/releases/download/knative-v1.0.0/serving-core.yaml

我建議你先把url的檔案下載到本地,然後再kubectl apply -f。這樣好處有:1. 方便你安裝失敗了回退;2. 方便你手動替換裡面拉取不到的映象檔案。

  1. serving-crds.yaml

    安裝crd的資源,該檔案只有一些基礎配置,沒有要拉取的映象檔案

    $ wget https://github.com/knative/serving/releases/download/knative-v1.0.0/serving-crds.yaml $ kubectl apply -f serving-crds.yaml
    
  2. serving-core.yaml

    這個檔案就是serving的核心元件。

    $ wget https://github.com/knative/serving/releases/download/knative-v1.0.0/serving-core.yaml $ kubectl apply -f serving-core.yaml
    

    該檔案裡面有6個元件,也就是要拉取這6個元件的映象,通過kubectl get pod -n knative-serving你可以看到:

    $ kubectl get pod -n knative-serving NAME                                     READY   STATUS   RESTARTS       AGE activator-68b7698d74-gkgnd               1/1     Running   3 (148m ago)   22h autoscaler-6c8884d6ff-b5rkt              1/1     Running   3 (148m ago)   22h controller-76cf997d95-c28ft              1/1     Running   3 (148m ago)   22h domain-mapping-57fdbf97b-gj96k           1/1     Running   3 (148m ago)   22h domainmapping-webhook-579dcb874d-x4zc2   1/1     Running   4 (148m ago)   21h webhook-7df8fd847b-c85tx                 1/1     Running   4 (148m ago)   22h
    

    如果狀態STATUS不是Running,那麼你得需要通過kubectl describe ...命令來找原因。通常來說:ErrImagePull或CrashLoopBackOff等狀態,一般是映象拉取不到的問題。解決方式:比如自己通過阿里雲映象服務來拉取yaml裡面的檔案,然後製作映象,再替換掉yaml檔案裡對應元件的映象地址。(下同)

安裝網路層

一般是選擇istio作為Knative的服務網格。

需要注意:官網的上的這一步並不是安裝istio,istio還得需要單獨安裝,見下面。這一步只是為Knative-serving選擇一個網路層。

  1. 配置istio。(注:並不是安裝istio)

    $ wget https://github.com/knative/net-istio/releases/download/knative-v1.0.0/istio.yaml $ kubectl apply -l knative.dev/crd-install=true -f istio.yaml $ kubectl apply -f istio.yaml
    
  2. 安裝knative的istio的控制器controller。

    $ https://github.com/knative/net-istio/releases/download/knative-v1.0.0/net-istio.yaml $ kubectl apply -f net-istio.yaml
    

然後就可以通過如下命令看到istio-ingressgateway的服務是否正常:

$ kubectl --namespace istio-system get service istio-ingressgateway NAME                   TYPE           CLUSTER-IP     EXTERNAL-IP                   PORT(S)               AGE istio-ingressgateway   LoadBalancer   10.98.11.197   10.98.11.197    15021:31993/TCP,80:31426/TCP,443:30168/TCP,31400:30840/TCP,15443:31673/TCP   21h

在minikube上,如果發現istio-ingressgateway的狀態為pengding或者EXTERNAL-IP內容為none。還得需要開啟Minikube的負載均衡策略:

在後臺或者開一個新命令視窗,執行命令:

minikube tunnel # 或者使用強制命令: # minikube tunnel --cleanup

正如上面所說,這一步並不是安裝istio,你會看到istio-system裡的很多pod都是CrashLoopBackOff、pending狀態。

$ kubectl get pod -n istio-system NAME                                   READY   STATUS             RESTARTS     AGE istio-ingressgateway-b899b7b79-87sn6   0/1     CrashLoopBackOff   3 (41s ago)   93s istio-ingressgateway-b899b7b79-dzrrr   0/1     CrashLoopBackOff   3 (41s ago)   93s istio-ingressgateway-b899b7b79-l85lq   0/1     CrashLoopBackOff   3 (41s ago)   93s istiod-d845fbcfd-8zk9w                 1/1     Running            0             93s istiod-d845fbcfd-fsrb4                 1/1     Running            0             78s istiod-d845fbcfd-qszng                 0/1     Pending            0             78s

之前我一直以為到這裡就算是將knative-serving安裝成功了,但並不是,就是這裡的坑。

所以,istio還得需要單獨安裝。

配置DNS(可選)

可以為配置一個DNS,後面我們要部署一個helloworld服務就可以直接使用一個CNAME域名,這樣我們訪問helloworld服務時直接通過curl就可以了。

當然也可以不配置DNS,但是後面訪問helloworld服務時需要給curl帶上請求頭。(後面再詳細說)

如果需要配置,執行如下命令:

$ wget https://github.com/knative/serving/releases/download/knative-v1.0.0/serving-default-domain.yaml $ kubectl apply -f serving-default-domain.yaml

還可以安裝其他外掛,可以見官網操作手冊,比如我還安裝了 HPA。但這些都不是必須的。你可以直接跳過這步。

到這裡knative-serving就算基本安裝完畢了,此時檢視命令空間knative-serving的pod內容如下:

$ kubectl get pod -n knative-serving NAME READY   STATUS   RESTARTS       AGE activator-68b7698d74-gkgnd               1/1     Running   3 (4h20m ago)   24h autoscaler-6c8884d6ff-b5rkt              1/1     Running   3 (4h20m ago)   24h autoscaler-hpa-85b46c9646-9k6h9          2/2     Running   2 (4h20m ago)   20h controller-76cf997d95-c28ft              1/1     Running   3 (4h20m ago)   24h domain-mapping-57fdbf97b-gj96k           1/1     Running   3 (4h20m ago)   24h domainmapping-webhook-579dcb874d-x4zc2   1/1     Running   4 (4h20m ago)   23h net-istio-controller-544874485d-ztb2d    1/1     Running   2 (4h20m ago)   22h net-istio-webhook-695d588d65-s79d2       2/2     Running   8 (4h18m ago)   22h webhook-7df8fd847b-c85tx                 1/1     Running   4 (4h20m ago)   24h

安裝istio

istio的下載安裝可以直接參考官方的文件:https://istio.io/latest/docs/setup/getting-started/#download

針對istio的版本,knative的官方給的建議是1.9.5的版本。

我們就使用官方建議的istio版本來進行安裝。

下載

進入istio的下載頁:https://github.com/istio/istio/releases/tag/1.9.5

選擇合適你主機的版本下載到本地即可。

環境變數

然後直接解壓,按照正常步驟,配置環境變數。

$ export ISTIOPATH=/root/istio-1.9.5 $ export PATH=$ISTIOPATH/bin:$PATH $ istioctl version client version: 1.9.5 pilot version: 1.9.5 pilot version: 1.9.5 pilot version: 1.9.5 pilot version: 1.10.5 pilot version: 1.10.5 pilot version: 1.10.5 data plane version: 1.10.5 (2 proxies), 1.9.5 (4 proxies)

安裝

本地學習環境,所以我們直接選擇demo這個profile來進行安裝即可。

$ istioctl install --set profile=demo -y # 可能會有一些莫名的報錯,不過關係不大,只要能確認以下元件能安裝好就ok ✔ Istio core installed ✔ Istiod installed ✔ Egress gateways installed ✔ Ingress gateways installed ✔ Installation complete

啟用 sidecar

在 knative-serving 系統名稱空間上啟用 sidecar 容器

$ kubectl label namespace knative-serving istio-injection=enabled namespace/knative-serving labeled

此時istio就算安裝完畢了,此時可以看到命令空間裡istio-system的pod狀態:

$ kubectl get pod -n istio-system NAME                                   READY   STATUS   RESTARTS       AGE istio-egressgateway-64b4ccccbf-r9d2j    1/1     Running   0               4h27m istio-ingressgateway-6dc7b4b675-4k2pq   1/1     Running   0               4h27m istio-ingressgateway-6dc7b4b675-lrtk7   1/1     Running   0               4h27m istio-ingressgateway-6dc7b4b675-nl6xz   1/1     Running   0               4h27m istiod-65fbd8c54c-mc9dr                 0/1     Running   0               4h27m istiod-65fbd8c54c-pd5dq                 0/1     Running   0               4h27m istiod-65fbd8c54c-wq4dd                 0/1     Running   0               4h27m istiod-d845fbcfd-dcvs6                  1/1     Running   2 (4h35m ago)   22h istiod-d845fbcfd-q7t8k                  0/1     Running   0               4h27m istiod-d845fbcfd-rt49j                  0/1     Running   0               4h27m

再確認下命令空間裡istio-system的服務狀態:

$ kubectl get svc -n istio-system NAME                   TYPE           CLUSTER-IP     EXTERNAL-IP                   PORT(S)                                                                     AGE istio-egressgateway     ClusterIP      10.107.56.203   <none>                        80/TCP,443/TCP,15443/TCP                                                     4h27m istio-ingressgateway   LoadBalancer   10.98.11.197    10.98.11.197,192.168.80.129   15021:31993/TCP,80:31426/TCP,443:30168/TCP,31400:30840/TCP,15443:31673/TCP   22h istiod                 ClusterIP      10.97.157.147   <none>                        15010/TCP,15012/TCP,443/TCP,15014/TCP                                       22h knative-local-gateway   ClusterIP      10.108.95.163   <none>                        80/TCP                                                                       22h

HelloWorld

此時就knative-serrving安裝完畢了,然後我們就可以來為Knative部署一個hello world服務。

ATTENTION!!!這裡還有個坑,如果你直接使用官方文件上helloworld-go例子,多半跑不起來,反正我在兩臺主機上部署過,都沒成功,服務狀態最後總是revisionMiss。

而且官方demo的映象大小居然有200多M,除去golang語言本身的包,一個簡單的helloworld程式應該不至於那麼大吧,所以我嚴重懷疑官網給的demo有問題。如下:

接下來介紹自己編寫helloworld的例子。

使用現成的

如果你懶得編寫,那麼也可以使用我做好得helloworld映象。

abreaking/helloworld-go:latest

然後你就可以跳到

自己編寫

使用了我現成的helloworld映象,你可以跳過本步驟。

我們來編寫一個Java工程的spring boot服務來作為demo。

參考:Hello World - Spring Boot Java - Knative

準備

  1. 一個簡單的spring boot工程,我的工程名:knative-demo
  2. maven環境
  3. docker hub,用來上傳我們的映象。

構建

  1. 可以先在自己的idea上建立一個簡單的springboot工程。然後在該spring boot工程裡寫一個簡單的controller。

    @RestController public class KnativeServingController {    @Value("${TARGET:World}")    String target;    @RequestMapping("/")    String hello() {        return "Hello " + target + "!";   } }
    

    寫好之後記得自行測試一下,比如啟動後,直接訪問localhost:8080,能夠輸出"hello world"

    $ curl http://localhost:8080 Hello World!
    

    這樣就表示我們編寫的程式碼沒問題了。

  2. 建立Dockerfile檔案,一般是放在工程的根目錄下(即knative-demo資料夾下)。

    # Use the official maven/Java 8 image to create a build artifact: https://hub.docker.com/_/maven FROM maven:3.5-jdk-8-alpine as builder# Copy local code to the container image. WORKDIR /root/knative/helloworld-java/knative-demo COPY pom.xml . COPY src ./src# Build a release artifact. RUN mvn package -DskipTests# Use the Official OpenJDK image for a lean production stage of our multi-stage build. # https://hub.docker.com/_/openjdk # https://docs.docker.com/develop/develop-images/multistage-build/#use-multi-stage-builds FROM openjdk:8-jre-alpine# Copy the jar to the production image from the builder stage. COPY --from=builder /root/knative/helloworld-java/knative-demo/target/knative-demo-*.jar /helloworld.jar# Run the web service on container startup. CMD ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "/helloworld.jar"]
    

    (注意替換上面你自己工程目錄路徑)。

  3. 構建映象,推送到你的docker hub

    在上述Dockerfile檔案的路徑下,執行以下命令來進行build:

    # abreaking是我自己的docker hub使用者名稱,helloworld-java是自定義的映象名 docker build -t abreaking/helloworld-java .
    

    build時間有點長,完畢之後推送到你自己的docker hub倉庫裡:

    docker push abreaking/helloworld-java
    

    推送成功後,就可以在dockerhub中看到你的映象

部署應用

我們前面自己編寫的demo在knative看來,叫做函式(function),因為knative是一個faas(服務及函式)平臺。

然後我們就可以來進行部署,knative在部署應用的過程中,通常會做三件事:

  • 建立一個新的並且不可變更的版本;(這個很重要,後面涉及到一些灰度策略)
  • 在網路層面,會自動為應用建立好路由route、流量入口ingress、服務service以及負載均衡策略loadblanceer。
  • 在k8s層面,會自動為該應用的pod擴容或縮容,如果你的服務沒有被呼叫,會自動縮容到零。

編寫yaml

建立一個新的檔名service-java.yaml,內容如下:

apiVersion: serving.knative.dev/v1 kind: Service metadata:   name: helloworld-java-spring   namespace: default spec:   template:     spec:       containers:       # 這裡就是映象檔案地址         - image: docker.io/abreaking/helloworld-java           env:             - name: TARGET               value: "World"

部署

直接使用以下命令來部署該應用

$ kubectl apply -f service-java.yaml service.serving.knative.dev/helloworld-java-spring created

驗證

通過如下命令來驗證我們部署的hello world:

$ kubectl get ksvc helloworld-java-spring NAME                     URL                                                         LATESTCREATED                 LATESTREADY                   READY   REASON helloworld-java-spring   http://helloworld-java-spring.default.10.105.59.0.sslip.io   helloworld-java-spring-00001   helloworld-java-spring-00001   True    

看到狀態為true了,那麼就表示部署成功了。

如果狀態一直為revisionMissing,問題的原因可能就是該映象的本身的問題,比如映象根本就下不下來,你可以先手動doucker pull 該映象名來驗證下。

如果確認映象本身沒問題,那麼你可能需要耐心等一會(最多也就兩三分鐘吧)。

使用

上面我們可以看到該helloworld有一個url,我們直接手動執行該url即可:

$ curl http://helloworld-java-spring.default.10.105.59.0.sslip.io Hello World!

能輸出Hello World!那麼就代表整個安裝部署就算成功了。

第一次執行該url可能響應有點慢,原因很簡單:我前面說過,沒有呼叫時,應用會自動縮容到零。有呼叫時,就會先拉取程式碼、部署、啟動分配pod等過程,所以第一次啟動都會有點慢。

一些問題及處理

istio安裝失敗,一些元件pending或者crashloopoff

istio的版本還是建議高版本,直接最新即可,官方給的建議是1.9.5版本;

其次,需要注意:istio對記憶體和cpu的要求比較嚴格,建議記憶體8G及以上,CPU8核及以上。

只要版本沒問題,記憶體和CPU的配置達到要求,基本上istio安裝沒有問題。

helloworld服務啟動後,一直revisionMissing

這個問題有點無解,個人認為原因還是出在demo上,官方給的demo個人感覺還是有問題的,拉取下來居然好幾百M。

後來我解決方式是自己製作demo,替換官方給的demo映象,然後也出現過revisionMission的問題,多等了一會,然後就好了。

istio-ingressgateway服務一直pending,EXTERNAL-IP為空

這個問題是出在minikube上。先看看你的istio-ingressgateway服務的type是不是LoadBalancer,如果是,還得需要minikube做一個操作: 開啟一個新得視窗,執行命令:minikube tunnel。 然後就能解決。

參考資料

https://knative.dev/docs/serving/

https://istio.io/latest/docs/setup/install/istioctl/

本文來自部落格園,作者:軟體工程師蝸小牛,轉載請註明原文連結:https://www.cnblogs.com/SoftwareEngineerWXN/p/15533194.html