本文采用本地k8s v1.10.3版本開發,如果還沒有搭建可參照 kubernetes學習筆記 (一):搭建本地k8s開發環境進行搭建
搭建本地Docker鏡像倉庫
docker pull docker.io/registry 拉取registry的鏡像到本機docker run -d -p 5000:5000 --name=registry --restart=always --privileged=true --log-driver=none -v /home/data/registrydata:/tmp/registry registry 運行剛剛拉取的registry在Docker for Mac中找到Docker -> Preferences -> Daemon,在insecure registries中填入自己剛剛搭建的本地倉庫 http://localhost:5000準備一個Docker鏡像
隨意使用什么語言寫一個http接口,例如Nodejs: @Get(
'whoami')async
whoAmI() {debug(
'whoAmI called with %O', {});
return { serverType: Config.SERVER_TYPE };}
復制代碼編寫對應的DockerFileFROM node:8
WORKDIR /rootRUN mkdir -p /root/appCOPY package.json /root/app/
COPY dist /root/app/distWORKDIR /root/appRUN npm config
set registry https://registry.npm.taobao.org/ ;\npm config
set disturl https://npm.taobao.org/dist/ ;\npm i --productionCMD [
"node",
"/root/app/dist/main.js" ]EXPOSE 80
復制代碼編譯、打標簽,并推送到本地倉庫中echo 'Building to dits ...'
tsc
echo 'Docker building image ...'
docker build --rm -t localhost:5000/gateapp:0.0.1 .
echo 'Pushing ...'
docker push localhost:5000/gateapp
echo 'Docker list images ...'
docker images
復制代碼最后你會看到localhost:5000/gateapp:0.0.1的鏡像已經在你的機器中啦,下面會用到
Kubernetes中的重要概念
Cluster: Cluster是計算、存儲和網絡資源的集合,Kubernetes利用這些資源運行各種基于容器的應用Master: Master是Kubernetes的大腦,它的主要職責是調度,即決定將應用放在那里運行。Node: Node的職責是運行容器應用。Node由Master管理,Node負責監控并匯報容器的狀態,同時根據Master的要求管理容器的生命周期。Pod: Pod是Kubernetes中最小工作單元。每個Pod包含一個或多個容器。Pod中的容器會作為一個整體被Master調度到一個Node上運行。Controller:Kubernetes通常不會直接創建Pod,而是通過Controller來管理Pod。Controller中定義了Pod的部署特性,比如有幾個副本、在什么樣的Node上運行等。為了滿足不同的業務場景,Kubernetes提供了多種Controller,包括Deployment、ReplicaSet、DaemonSet、StatefuleSet、Job等,后面會逐個學習這些ControllerService:Service定義外界訪問一組特定Pod的方式。創建Deployment部署應用
新建一個yaml文件,如:apiVersion: extensions/v1beta1
kind: Deployment
metadata:name: gate-deployment-dev
spec:replicas: 2 template:metadata:labels:app: gate-app-devspec:containers:- name: gateappimage: localhost:5000/gateapp:0.0.1 env: - name: NODE_ENVvalue:
'development'- name: HTTP_PORTvalue:
'80'
復制代碼 通過kubectl apply -f xxx.yaml就可以部署上面的Deployment的了,也可以打開Kubernetes的Dashboard點擊創建,輸入yaml文件中的內容進行創建。經過一段時間后,在Dashboard面板中可以看到,1個部署 gate-deployment-dev,一個副本集 gate-deployment-dev-775d556ffb,兩個容器組 gate-deployment-dev-775d556ffb-2tlgn、gate-deployment-dev-775d556ffb-sfqrq,可以點擊查看每個資源的信息,大部分內容都是自解釋的。
在部署Deployment后,Kubernetes大致執行了以下幾個過程:
- 用戶創建Deployment
- Deployment創建了一個副本集(ReplicaSet)gate-deployment-dev-775d556ffb
- ReplicaSet創建了兩個Pod,與我們定義的replicas: 2 一致
創建Service
此時上面的鏡像提供的接口還不能供外界訪問,需要創建一個對應的Service
新創建一個yaml文件或者在上一個yaml文件中添加 --- 隔開編輯以下內容:apiVersion: v1
kind: Service
metadata:name: gate-svc-dev
spec:
type: NodePort selector:app: gate-app-dev ports:- protocol: TCP port: 80 nodePort: 30000 targetPort: 80
復制代碼 kubectl apply -f xxx.yaml 或者在Dashboard中創建
觀察Dashboard面板,會發現多了一個名字叫gate-svc-dev的服務,提供了監聽了30000端口
curl http://localhost:30000/whoami 可以看到接口已經可以訪問了
需要注意的是:
-
為什么需要Service?
Deployment等其他Controller動態創建和銷毀Pod來保證應用的健壯性,也就是Pod是脆弱的,應用是健壯的,我們不該期望Pod的健壯性。每個Pod都有自己的ClusterIp地址,當Pod發生故障被新的Pod替代時,ClusterIp很有可能發生變化,所以如果直接讓外界訪問Pod就有問題了。
-
Service和Pod如何映射?
通過上面的yaml定義可以看出,Service通過 label標簽選擇器選擇對應的一堆Pod。當請求被發送到Service上時,Service采用了某種分配策略把流量轉發到了某一個Pod上面進行處理。
-
Service有哪些類型?
- ClusterIp:Service通過Cluster內部的IP對外提供服務,只有Cluster內的節點和Pod可以訪問,這是默認的類型。
- NodePort: Service通過Cluster節點的靜態端口對外提供服務。Cluster外部可以通過<NodeIp>:<NodePort>訪問Service
- LoadBalancer: cloud provider特有的對外提供服務,后續線上部署時會講到
滾動更新
滾動更新是一次只更新一小部分副本,成功后再更新更多的副本,最終完成所有副本的更新。滾動更新最大的好處就是零停機,保證了業務的連續性。
對本地代碼進行一點改動編譯、打標簽,并推送到本地倉庫中echo 'Building to dits ...'
tsc
echo 'Docker building image ...'
docker build --rm -t localhost:5000/gateapp:0.0.2 .
echo 'Pushing ...'
docker push localhost:5000/gateapp
echo 'Docker list images ...'
docker images
復制代碼這時候可以看到有0.0.1 和 0.0.2兩個版本的鏡像
在Dashboard中編輯Deployment,把image: localhost:5000/gateapp:0.0.1改成image: localhost:5000/gateapp:0.0.2,點擊更新
等待一段時間,再觀察所有的Pod都被更新成0.0.2版本的了,是不是很方便!
反復執行上面的步驟,不難發現更新過程中Kubernets都做了什么:
- Deployment的鏡像被更新為0.0.2版本
- 新創建了一個名稱為gate-deployment-dev-594468997c的ReplicaSet副本集,鏡像為0.0.2
- 新的ReplicaSet增加了一個Pod
- 舊的ReplicaSet減少了一個Pod
- 逐漸的新的ReplicaSet接管了所有舊ReplicaSet的Pod,滾動更新完成
自定義滾動更新行為
strategy:rollingUpdate: maxSurge: 10% maxUnavailble: 10% replicas: 2
復制代碼- maxSurge:此參數控制滾動更新中副本總數超過DESIRED的數量或最大比例,數值越大 滾動更新時新創建的副本數量越多
- maxUnavailble:此參數控制滾動更新中,不可用的副本占DESIRED的最大數量或最大利弊,數值越大 滾動更新時銷毀的舊副本數量越多
復制代碼 那如果更新過程出錯了怎么辦?請接著往下看
健康檢查
Kubernetes有很強大的自愈能力,默認的實現方式是重啟發生故障的容器,此外用戶可以使用Liveness、 Readiness的探測機制設置更為精細的健康檢查,進而真正實現零停機部署、避免部署無效的鏡像、更加安全的滾動升級
編輯之前的Deployment.yaml,例如: image: localhost:5000/gateapp:0.0.13readinessProbe: httpGet:scheme: HTTP path: /healthyport: 80 initialDelaySeconds: 10 periodSecods: 5
復制代碼-
readinessProbe即是使用Readiness健康探測機制,當檢查不通過時(例如接口返回的狀態碼不是200-400之間),Kubernetes就不會把容器添加到Service中供外界訪問,觀察Pod的狀態為Not Ready。 initialDelaySeconds是決定容器啟動多久后開始檢查,通常要比啟動時間再長一些;periodSecods是多久檢查一次,連續3次探測失敗后,Ready將變成不可用,Kubernets把這個Pod從Service中下線
-
LiveNess的配置項和Readiness的一樣,不同之處在于探測失敗后的行為。前者會重啟容器,后者會設置Pod不可用,并從Service中下線。
-
LiveNess和Readiness的探測是獨立使用的,二者沒有依賴,可以單獨使用也可以同時使用。一般情況下使用LiveNess判斷容器是否需要重啟實現自愈;Readiness判斷容器是否已經準備好對外提供服務。
自定義健康檢查的代碼: 自定義/healthy get接口,比如數據庫連接等等 @Get(
'healthy')async checkHealthy(@Res() res: Response) {
let isHealthy =
false;// some code to check healthy beginisHealthy =
true;// check endconst data = {isHealthy,};debug(
'執行健康檢查結果 %O', data);res.status(isHealthy ? HttpStatus.OK : HttpStatus.INTERNAL_SERVER_ERROR).json(data);}
復制代碼一起來學習Kubernetes
相信看完以上的文章,你也會認為Kubernetes真的非常強大,是非常值得學習的。筆者也是小白一個,從0開始學習的,如果你也想一起,可以加入我們的群。
總結
以上是生活随笔為你收集整理的kubernetes学习笔记 (二):k8s初体验的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。