本文基於 knative 文檔中的 Orchestrating a source-to-URL deployment on Kubernetes 的簡單例子,經過從源碼到 URL 的部署流程一窺 Knative 給 Kubernetes 帶來的改變。node
源碼的構建是由 Knative build 子系統完成的,一般咱們須要在構建配置中定義一些構建步驟(step),經過這些構建步驟一步步地處理源碼,詳細能夠參考 Knative Build resources。但 Knative 也支持使用多種構建模板,下文就介紹如何使用 kaniko 構建模板完成示例代碼的構建。git
本示例藉助 kaniko build template 來在你的 Kubernetes 集羣上執行一次「從源碼到容器」的構建。github
kaniko 是谷歌開源的用於從 Dockerfile 構建容器鏡像的工具。它的特色在於不依賴 Docker daemon,並在用戶空間內執行 Dockerfile 中的每一行命令。這使得在一些不能方便地或安全地運行 Docker daemon 的環境中,如標準 Kubernetes 集羣中,也能構建容器鏡像。docker
使用 kubectl 來安裝 kaniko:編程
kubectl apply --filename https://raw.githubusercontent.com/knative/build-templates/master/kaniko/kaniko.yaml
複製代碼
爲了將從源代碼構建獲得的容器推送到 Docker Hub,須要在 Kubernetes 上登記密鑰用於認證 Docker Hub。json
關於 Knative 中的認證,這是詳細的說明,下面是幾個關鍵步驟:api
建立一個 Secret
配置,用於存放你的 Docker Hub 認證信息。將文件保存爲 docker-secret.yaml
:安全
apiVersion: v1
kind: Secret
metadata:
name: basic-user-pass
annotations:
build.knative.dev/docker-0: https://index.docker.io/v1/
type: kubernetes.io/basic-auth
data:
# Use 'echo -n "username" | base64' to generate this string
username: BASE64_ENCODED_USERNAME
# Use 'echo -n "password" | base64' to generate this string
password: BASE64_ENCODED_PASSWORD
複製代碼
上面的配置中,username
和 password
都是須要 base64 加密的。在 macOS 或 Linux 系統中,用下面的命令能夠生成 base64 編碼的值:bash
echo -n "username" | base64 -w 0
echo -n "password" | base64 -w 0
複製代碼
注意:若是在 macOS 上提示 "invalid option -w" 錯誤,試着改爲
base64 -b 0
。網絡
建立一個Service Account
配置,用於將構建進程連接到Secret
。將文件保存爲service-account.yaml
:
apiVersion: v1
kind: ServiceAccount
metadata:
name: build-bot
secrets:
- name: basic-user-pass
複製代碼
建立好配置文件後,經過kubectl
將它們應用到你的集羣:
kubectl apply -f docker-secret.yaml
kubectl apply -f service-account.yaml
複製代碼
本示例使用 github.com/mchmarny/si… 做爲一個基礎 Go 應用,但你也能夠替換爲你本身的 GitHub 項目。惟一要注意的是,項目必須包含一個Dockerfile
來描述如何爲應用構建一個容器。
須要建立一個 service 配置來定義服務如何部署,包括源代碼在哪兒、使用哪一個構建模板。建立service.yaml
並複製以下定義。將{DOCKER_USERNAME}
替換爲你本身的 Docker Hub 用戶名:
apiVersion: serving.knative.dev/v1alpha1
kind: Service
metadata:
name: app-from-source
namespace: default
spec:
runLatest:
configuration:
build:
apiVersion: build.knative.dev/v1alpha1
kind: Build
spec:
serviceAccountName: build-bot
source:
git:
url: https://github.com/mchmarny/simple-app.git
revision: master
template:
name: kaniko
arguments:
- name: IMAGE
value: docker.io/{DOCKER_USERNAME}/app-from-source:latest
revisionTemplate:
spec:
container:
image: docker.io/{DOCKER_USERNAME}/app-from-source:latest
imagePullPolicy: Always
env:
- name: SIMPLE_MSG
value: "Hello from the sample app!"
複製代碼
使用kubectl
應用配置,並觀察結果:
kubectl apply -f service.yaml
kubectl get po --watch
複製代碼
輸出相似於:
NAME READY STATUS RESTARTS AGE
app-from-source-00001-zhddx 0/1 Init:2/3 0 7s
app-from-source-00001-zhddx 0/1 PodInitializing 0 37s
app-from-source-00001-zhddx 0/1 Completed 0 38s
app-from-source-00001-deployment-6d6ff665f9-xfhm5 0/3 Pending 0 0s
app-from-source-00001-deployment-6d6ff665f9-xfhm5 0/3 Pending 0 0s
app-from-source-00001-deployment-6d6ff665f9-xfhm5 0/3 Init:0/1 0 0s
app-from-source-00001-deployment-6d6ff665f9-xfhm5 0/3 Init:0/1 0 2s
app-from-source-00001-deployment-6d6ff665f9-xfhm5 0/3 PodInitializing 0 3s
app-from-source-00001-deployment-6d6ff665f9-xfhm5 2/3 Running 0 6s
app-from-source-00001-deployment-6d6ff665f9-xfhm5 3/3 Running 0 11s
複製代碼
能看到先是app-from-source-00001
啓動,執行「從源碼到鏡像」的過程,再啓動app-from-source-00001-deployment
拉取鏡像,提供服務。
須要特別說明的是,筆者這個步驟失敗了屢次,都是
app-from-source-00001
初始化過程意外退出。經過kubectl describe
查看詳細信息,提示構建超時(默認構建超時是10分鐘)。構建過程須要拉取一些鏡像,推測可能因爲網絡緣由,該步驟耗時過長。能夠在構建過程當中,經過kubectl describe po app-from-source-00001-zhddx
查看相關 Event,找到構建具體是在哪一步耗時過長。筆者最後多試幾回成功了:)
當你看到 deployment pod 變爲Running
狀態時,Ctrl+C
退出觀察。此時你的容器已經完成構建和部署了!
要檢查服務的狀態,能夠
kubectl get ksvc app-from-source --output yaml
複製代碼
當你建立服務時,Knative 隨即執行如下步驟:
revision
指定的代碼並構建到容器中revision
route
、ingress
、service
和負載均衡服務要獲取你的集羣的入口 IP,使用以下命令。若是你的集羣是新建的,服務獲取一個外部 IP 地址可能會花一些時間:
# In Knative 0.2.x and prior versions, the `knative-ingressgateway` service was used instead of `istio-ingressgateway`.
INGRESSGATEWAY=knative-ingressgateway
# The use of `knative-ingressgateway` is deprecated in Knative v0.3.x.
# Use `istio-ingressgateway` instead, since `knative-ingressgateway`
# will be removed in Knative v0.4.
if kubectl get configmap config-istio -n knative-serving &> /dev/null; then
INGRESSGATEWAY=istio-ingressgateway
fi
kubectl get svc $INGRESSGATEWAY --namespace istio-system
複製代碼
須要注意的是,minikube 搭建的集羣經過上面的方式是獲取不到外部 IP 的。應該執行:
echo $(minikube ip):$(kubectl get svc $INGRESSGATEWAY --namespace istio-system --output 'jsonpath={.spec.ports[?(@.port==80)].nodePort}')
複製代碼
要找到服務的 URL,輸入:
kubectl get ksvc app-from-source --output=custom-columns=NAME:.metadata.name,DOMAIN:.status.domain
複製代碼
如今你能夠向你的應用發送一個請求來看看結果。將{IP_ADDRESS}
替換爲你上一步得到的地址:
curl -H "Host: app-from-source.default.example.com" http://{IP_ADDRESS}
複製代碼
要從你的集羣移除示例應用,刪除服務記錄:
kubectl delete -f service.yaml
複製代碼