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及以上
- 網路:能訪問外網
環境
-
docker
這個不需多說,容器引擎docker。
安裝比較簡單,直接安裝官方文件操作即可:https://docs.docker.com/get-started/
tips: 最好再建立一個自己的docker up,可用於存放個人映象。
-
k8s
本地學習建議安裝minukube,直接安裝k8s難度太大了。
minikube安裝比較簡單,參考:Minikube - Kubernetes本地實驗環境-阿里雲開發者社群 (aliyun.com)
-
golang
直接去官網下載最新的golang版本,解壓新增環境變數即可。
其他
由於需要拉取k8s映象庫,國內是訪問不了的。辦法有:
- 找個梯子,自行百度。
- 自己製作映象。比較麻煩,使用阿里雲容器映象服務,還得需要手動替換yaml裡映象地址。具體方式可參考:使用阿里雲映象服務來代理k8s映象 - 知乎 (zhihu.com)
安裝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. 方便你手動替換裡面拉取不到的映象檔案。
-
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
-
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選擇一個網路層。
-
配置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
-
安裝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
準備
- 一個簡單的spring boot工程,我的工程名:knative-demo
- maven環境
- docker hub,用來上傳我們的映象。
構建
-
可以先在自己的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!
這樣就表示我們編寫的程式碼沒問題了。
-
建立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"]
(注意替換上面你自己工程目錄路徑)。
-
構建映象,推送到你的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