摘要:默認監聽在端口,所以我們把宿主機的端口映射到容器的端口用下面的命令可以看到正在運行中的容器這時如果你用瀏覽器訪問,就能看到我們剛才創建的頁面。這時如果刷新瀏覽器,就可以看到更新的內容。
早在 Docker 正式發布幾個月的時候,LeanCloud 就開始在生產環境大規模使用 Docker,在過去幾年里 Docker 的技術棧支撐了我們主要的后端架構。這是一篇寫給程序員的 Docker 和 Kubernetes 教程,目的是讓熟悉技術的讀者在盡可能短的時間內對 Docker 和 Kubernetes 有基本的了解,并通過實際部署、升級、回滾一個服務體驗容器化生產環境的原理和好處。本文假設讀者都是開發者,并熟悉 Mac/Linux 環境,所以就不介紹基礎的技術概念了。命令行環境以 Mac 示例,在 Linux 下只要根據自己使用的發行版和包管理工具做調整即可。
Docker 速成首先快速地介紹一下 Docker:作為示例,我們在本地啟動 Docker 的守護進程,并在一個容器里運行簡單的 HTTP 服務。先完成安裝:
$ brew cask install docker
上面的命令會從 Homebrew 安裝 Docker for Mac,它包含 Docker 的后臺進程和命令行工具。Docker 的后臺進程以一個 Mac App 的形式安裝在 /Applications 里,需要手動啟動。啟動 Docker 應用后,可以在 Terminal 里確認一下命令行工具的版本:
$ docker --version Docker version 18.03.1-ce, build 9ee9f40
上面顯示的 Docker 版本可能和我的不一樣,但只要不是太老就好。我們建一個多帶帶的目錄來存放示例所需的文件。為了盡量簡化例子,我們要部署的服務是用 Nginx 來 serve 一個簡單的 HTML 文件 html/index.html。
$ mkdir docker-demo $ cd docker-demo $ mkdir html $ echo "Hello Docker!
" > html/index.html
接下來在當前目錄創建一個叫 Dockerfile 的新文件,包含下面的內容:
FROM nginx COPY html/* /usr/share/nginx/html
每個 Dockerfile 都以 FROM ... 開頭。FROM nginx 的意思是以 Nginx 官方提供的鏡像為基礎來構建我們的鏡像。在構建時,Docker 會從 Docker Hub 查找和下載需要的鏡像。Docker Hub 對于 Docker 鏡像的作用就像 GitHub 對于代碼的作用一樣,它是一個托管和共享鏡像的服務。使用過和構建的鏡像都會被緩存在本地。第二行把我們的靜態文件復制到鏡像的 /usr/share/nginx/html 目錄下。也就是 Nginx 尋找靜態文件的目錄。Dockerfile 包含構建鏡像的指令,更詳細的信息可以參考這里。
然后就可以構建鏡像了:
$ docker build -t docker-demo:0.1 .
請確保你按照上面的步驟為這個實驗新建了目錄,并且在這個目錄中運行 docker build。如果你在其它有很多文件的目錄(比如你的用戶目錄或者 /tmp )運行,docker 會把當前目錄的所有文件作為上下文發送給負責構建的后臺進程。
這行命令中的名稱 docker-demo 可以理解為這個鏡像對應的應用名或服務名,0.1 是標簽。Docker 通過名稱和標簽的組合來標識鏡像。可以用下面的命令來看到剛剛創建的鏡像:
$ docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE docker-demo 0.1 efb8ca048d5a 5 minutes ago 109MB
下面我們把這個鏡像運行起來。Nginx 默認監聽在 80 端口,所以我們把宿主機的 8080 端口映射到容器的 80 端口:
$ docker run --name docker-demo -d -p 8080:80 docker-demo:0.1
用下面的命令可以看到正在運行中的容器:
$ docker container ps CONTAINER ID IMAGE ... PORTS NAMES c495a7ccf1c7 docker-demo:0.1 ... 0.0.0.0:8080->80/tcp docker-demo
這時如果你用瀏覽器訪問 http://localhost:8080,就能看到我們剛才創建的「Hello Docker!」頁面。
在現實的生產環境中 Docker 本身是一個相對底層的容器引擎,在有很多服務器的集群中,不太可能以上面的方式來管理任務和資源。所以我們需要 Kubernetes 這樣的系統來進行任務的編排和調度。在進入下一步前,別忘了把實驗用的容器清理掉:
$ docker container stop docker-demo $ docker container rm docker-demo安裝 Kubernetes
介紹完 Docker,終于可以開始試試 Kubernetes 了。我們需要安裝三樣東西:Kubernetes 的命令行客戶端 kubctl、一個可以在本地跑起來的 Kubernetes 環境 Minikube、以及給 Minikube 使用的虛擬化引擎 xhyve。
$ brew install kubectl $ brew cask install minikube $ brew install docker-machine-driver-xhyve
Minikube 默認的虛擬化引擎是 VirtualBox,而 xhyve 是一個更輕量、性能更好的替代。它需要以 root 權限運行,所以安裝完要把所有者改為 root:wheel,并把 setuid 權限打開:
$ sudo chown root:wheel /usr/local/opt/docker-machine-driver-xhyve/bin/docker-machine-driver-xhyve $ sudo chmod u+s /usr/local/opt/docker-machine-driver-xhyve/bin/docker-machine-driver-xhyve
然后就可以啟動 Minikube 了:
$ minikube start --vm-driver xhyve
你多半會看到一個警告說 xhyve 會在未來的版本被 hyperkit 替代,推薦使用 hyperkit。不過在我寫這個教程的時候 docker-machine-driver-hyperkit 還沒有進入 Homebrew, 需要手動編譯和安裝,我就偷個懶,仍然用 xhyve。以后只要在安裝和運行的命令中把 xhyve 改為 hyperkit 就可以。
如果你在第一次啟動 Minikube 時遇到錯誤或被中斷,后面重試仍然失敗時,可以嘗試運行 minikube delete 把集群刪除,重新來過。
Minikube 啟動時會自動配置 kubectl,把它指向 Minikube 提供的 Kubernetes API 服務。可以用下面的命令確認:
$ kubectl config current-context minikubeKubernetes 架構簡介
典型的 Kubernetes 集群包含一個 master 和很多 node。Master 是控制集群的中心,node 是提供 CPU、內存和存儲資源的節點。Master 上運行著多個進程,包括面向用戶的 API 服務、負責維護集群狀態的 Controller Manager、負責調度任務的 Scheduler 等。每個 node 上運行著維護 node 狀態并和 master 通信的 kubelet,以及實現集群網絡服務的 kube-proxy。
作為一個開發和測試的環境,Minikube 會建立一個有一個 node 的集群,用下面的命令可以看到:
$ kubectl get nodes NAME STATUS AGE VERSION minikube Ready 1h v1.10.0部署一個單實例服務
我們先嘗試像文章開始介紹 Docker 時一樣,部署一個簡單的服務。Kubernetes 中部署的最小單位是 pod,而不是 Docker 容器。實時上 Kubernetes 是不依賴于 Docker 的,完全可以使用其他的容器引擎在 Kubernetes 管理的集群中替代 Docker。在與 Docker 結合使用時,一個 pod 中可以包含一個或多個 Docker 容器。但除了有緊密耦合的情況下,通常一個 pod 中只有一個容器,這樣方便不同的服務各自獨立地擴展。
Minikube 自帶了 Docker 引擎,所以我們需要重新配置客戶端,讓 docker 命令行與 Minikube 中的 Docker 進程通訊:
$ eval $(minikube docker-env)
在運行上面的命令后,再運行 docker image ls 時只能看到一些 Minikube 自帶的鏡像,就看不到我們剛才構建的 docker-demo:0.1 鏡像了。所以在繼續之前,要重新構建一遍我們的鏡像,這里順便改一下名字,叫它 k8s-demo:0.1。
$ docker build -t k8s-demo:0.1 .
然后創建一個叫 pod.yml 的定義文件:
apiVersion: v1 kind: Pod metadata: name: k8s-demo spec: containers: - name: k8s-demo image: k8s-demo:0.1 ports: - containerPort: 80
這里定義了一個叫 k8s-demo 的 Pod,使用我們剛才構建的 k8s-demo:0.1 鏡像。這個文件也告訴 Kubernetes 容器內的進程會監聽 80 端口。然后把它跑起來:
$ kubectl create -f pod.yml pod "k8s-demo" created
kubectl 把這個文件提交給 Kubernetes API 服務,然后 Kubernetes Master 會按照要求把 Pod 分配到 node 上。用下面的命令可以看到這個新建的 Pod:
$ kubectl get pods NAME READY STATUS RESTARTS AGE k8s-demo 1/1 Running 0 5s
因為我們的鏡像在本地,并且這個服務也很簡單,所以運行 kubectl get pods 的時候 STATUS 已經是 running。要是使用遠程鏡像(比如 Docker Hub 上的鏡像),你看到的狀態可能不是 Running,就需要再等待一下。
雖然這個 pod 在運行,但是我們是無法像之前測試 Docker 時一樣用瀏覽器訪問它運行的服務的。可以理解為 pod 都運行在一個內網,我們無法從外部直接訪問。要把服務暴露出來,我們需要創建一個 Service。Service 的作用有點像建立了一個反向代理和負載均衡器,負責把請求分發給后面的 pod。
創建一個 Service 的定義文件 svc.yml:
apiVersion: v1 kind: Service metadata: name: k8s-demo-svc labels: app: k8s-demo spec: type: NodePort ports: - port: 80 nodePort: 30050 selector: app: k8s-demo
這個 service 會把容器的 80 端口從 node 的 30050 端口暴露出來。注意文件最后兩行的 selector 部分,這里決定了請求會被發送給集群里的哪些 pod。這里的定義是所有包含「app: k8s-demo」這個標簽的 pod。然而我們之前部署的 pod 并沒有設置標簽:
$ kubectl describe pods | grep Labels Labels:
所以要先更新一下 pod.yml,把標簽加上(注意在 metadata: 下增加了 labels 部分):
apiVersion: v1 kind: Pod metadata: name: k8s-demo labels: app: k8s-demo spec: containers: - name: k8s-demo image: k8s-demo:0.1 ports: - containerPort: 80
然后更新 pod 并確認成功新增了標簽:
$ kubectl apply -f pod.yml pod "k8s-demo" configured $ kubectl describe pods | grep Labels Labels: app=k8s-demo
然后就可以創建這個 service 了:
$ kubectl create -f svc.yml service "k8s-demo-svc" created
用下面的命令可以得到暴露出來的 URL,在瀏覽器里訪問,就能看到我們之前創建的網頁了。
$ minikube service k8s-demo-svc --url http://192.168.64.4:30050橫向擴展、滾動更新、版本回滾
在這一節,我們來實驗一下在一個高可用服務的生產環境會常用到的一些操作。在繼續之前,先把剛才部署的 pod 刪除(但是保留 service,下面還會用到):
$ kubectl delete pod k8s-demo pod "k8s-demo" deleted
在正式環境中我們需要讓一個服務不受單個節點故障的影響,并且還要根據負載變化動態調整節點數量,所以不可能像上面一樣逐個管理 pod。Kubernetes 的用戶通常是用 Deployment 來管理服務的。一個 deployment 可以創建指定數量的 pod 部署到各個 node 上,并可完成更新、回滾等操作。
首先我們創建一個定義文件 deployment.yml:
apiVersion: extensions/v1beta1 kind: Deployment metadata: name: k8s-demo-deployment spec: replicas: 10 template: metadata: labels: app: k8s-demo spec: containers: - name: k8s-demo-pod image: k8s-demo:0.1 ports: - containerPort: 80
注意開始的 apiVersion 和之前不一樣,因為 Deployment API 沒有包含在 v1 里,replicas: 10 指定了這個 deployment 要有 10 個 pod,后面的部分和之前的 pod 定義類似。提交這個文件,創建一個 deployment:
$ kubectl create -f deployment.yml deployment "k8s-demo-deployment" created
用下面的命令可以看到這個 deployment 的副本集(replica set),有 10 個 pod 在運行。
$ kubectl get rs NAME DESIRED CURRENT READY AGE k8s-demo-deployment-774878f86f 10 10 10 19s
假設我們對項目做了一些改動,要發布一個新版本。這里作為示例,我們只把 HTML 文件的內容改一下, 然后構建一個新版鏡像 k8s-demo:0.2:
$ echo "Hello Kubernetes!
" > html/index.html $ docker build -t k8s-demo:0.2 .
然后更新 deployment.yml:
apiVersion: extensions/v1beta1 kind: Deployment metadata: name: k8s-demo-deployment spec: replicas: 10 minReadySeconds: 10 strategy: type: RollingUpdate rollingUpdate: maxUnavailable: 1 maxSurge: 1 template: metadata: labels: app: k8s-demo spec: containers: - name: k8s-demo-pod image: k8s-demo:0.2 ports: - containerPort: 80
這里有兩個改動,第一個是更新了鏡像版本號 image: k8s-demo:0.2,第二是增加了 minReadySeconds: 10 和 strategy 部分。新增的部分定義了更新策略:minReadySeconds: 10 指在更新了一個 pod 后,需要在它進入正常狀態后 10 秒再更新下一個 pod;maxUnavailable: 1 指同時處于不可用狀態的 pod 不能超過一個;maxSurge: 1 指多余的 pod 不能超過一個。這樣 Kubernetes 就會逐個替換 service 后面的 pod。運行下面的命令開始更新:
$ kubectl apply -f deployment.yml --record=true deployment "k8s-demo-deployment" configured
這里的 --record=true 讓 Kubernetes 把這行命令記到發布歷史中備查。這時可以馬上運行下面的命令查看各個 pod 的狀態:
$ kubectl get pods NAME READY STATUS ... AGE k8s-demo-deployment-774878f86f-5wnf4 1/1 Running ... 7m k8s-demo-deployment-774878f86f-6kgjp 0/1 Terminating ... 7m k8s-demo-deployment-774878f86f-8wpd8 1/1 Running ... 7m k8s-demo-deployment-774878f86f-hpmc5 1/1 Running ... 7m k8s-demo-deployment-774878f86f-rd5xw 1/1 Running ... 7m k8s-demo-deployment-774878f86f-wsztw 1/1 Running ... 7m k8s-demo-deployment-86dbd79ff6-7xcxg 1/1 Running ... 14s k8s-demo-deployment-86dbd79ff6-bmvd7 1/1 Running ... 1s k8s-demo-deployment-86dbd79ff6-hsjx5 1/1 Running ... 26s k8s-demo-deployment-86dbd79ff6-mkn27 1/1 Running ... 14s k8s-demo-deployment-86dbd79ff6-pkmlt 1/1 Running ... 1s k8s-demo-deployment-86dbd79ff6-thh66 1/1 Running ... 26s
從 AGE 列就能看到有一部分 pod 是剛剛新建的,有的 pod 則還是老的。下面的命令可以顯示發布的實時狀態:
$ kubectl rollout status deployment k8s-demo-deployment Waiting for rollout to finish: 1 old replicas are pending termination... Waiting for rollout to finish: 1 old replicas are pending termination... deployment "k8s-demo-deployment" successfully rolled out
由于我輸入得比較晚,發布已經快要結束,所以只有三行輸出。下面的命令可以查看發布歷史,因為第二次發布使用了 --record=true 所以可以看到用于發布的命令。
$ kubectl rollout history deployment k8s-demo-deployment deployments "k8s-demo-deployment" REVISION CHANGE-CAUSE 12 kubectl apply --filename=deploy.yml --record=true
這時如果刷新瀏覽器,就可以看到更新的內容「Hello Kubernetes!」。假設新版發布后,我們發現有嚴重的 bug,需要馬上回滾到上個版本,可以用這個很簡單的操作:
$ kubectl rollout undo deployment k8s-demo-deployment --to-revision=1 deployment "k8s-demo-deployment" rolled back
Kubernetes 會按照既定的策略替換各個 pod,與發布新版本類似,只是這次是用老版本替換新版本:
$ kubectl rollout status deployment k8s-demo-deployment Waiting for rollout to finish: 4 out of 10 new replicas have been updated... Waiting for rollout to finish: 6 out of 10 new replicas have been updated... Waiting for rollout to finish: 8 out of 10 new replicas have been updated... Waiting for rollout to finish: 1 old replicas are pending termination... deployment "k8s-demo-deployment" successfully rolled out
在回滾結束之后,刷新瀏覽器就可以確認網頁內容又改回了「Hello Docker!」。
結語我們從不同層面實踐了一遍鏡像的構建和容器的部署,并且部署了一個有 10 個容器的 deployment, 實驗了滾動更新和回滾的流程。Kubernetes 提供了非常多的功能,本文只是以走馬觀花的方式做了一個快節奏的 walkthrough,略過了很多細節。雖然你還不能在簡歷上加上「精通 Kubernetes」,但是應該可以在本地的 Kubernetes 環境測試自己的前后端項目,遇到具體的問題時求助于 Google 和官方文檔即可。在此基礎上進一步熟悉應該就可以在別人提供的 Kubernetes 生產環境發布自己的服務。
LeanCloud 的大部分服務都運行在基于 Docker 的基礎設施上,包括各個 API 服務、中間件、后端任務等。大部分使用 LeanCloud 的開發者主要工作在前端,不過云引擎是我們的產品中讓容器技術離用戶最近的。云引擎提供了容器帶來的隔離良好、擴容簡便等優點,同時又直接支持各個語言的原生依賴管理,為用戶免去了鏡像構建、監控、恢復等負擔,很適合希望把精力完全投入在開發上的用戶。
LeanCloud 在招聘以下職位:市場團隊負責人
后端軟件工程師(Clojure、Python、Java)
Android 軟件工程師
具體的需求以及其他正在招聘的職位請見我們的工作機會頁面。除了在官網上可以看到的已經發布的產品外,我們也在開發讓人興奮的新產品,有很多有意義、有價值的工作。
如果轉載本文,請包含原文鏈接和招聘信息。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/27387.html
摘要:如今,多樣化的攻擊手段層出不窮,傳統安全解決方案越來越難以應對網絡安全攻擊。自適應安全平臺集成了預測預防檢測和響應的能力,為您提供精準持續可視化的安全防護。 近一年來,Docker 已經逐漸成為 container 界的事實標準,成為技術人員不可或缺的技能之一,就像 Docker 宣稱的那樣,「Build,Ship,and Run Any App,Anywhere」,容器極大簡化了環境...
摘要:本文內容節選自由主辦的第七屆,架構師高欣分享的的實踐實錄。當然,在部署完成后,我們要做一個監測以便掌握它的運行狀況。規劃配置運行環境在正式部署前,還要考慮如何規劃并配置好運行環境。在使用部署時,可以利用這些命令做驗證,檢驗部署是否正常。 showImg(https://segmentfault.com/img/bVblRHj?w=2880&h=1920); 本文內容節選自由msup主辦...
摘要:大會以機器學習資料中心和云端安全為主要議題,為未來發展做戰略規劃。在年,谷歌開發了一個內部深度學習基礎設施叫做,這個設施允許谷歌人創建更大的神經網絡和擴容實訓成千上萬個核心。 導言 Google近日3月23-24日在美國舊金山舉辦首次谷歌云平臺(Google Cloud Platform) GCP NEXT大會,參會人數超過2000人。GCP NEXT大會以機器學習、資料中心和云端安全...
閱讀 2426·2021-10-11 10:57
閱讀 1277·2021-10-09 09:59
閱讀 1991·2019-08-30 15:53
閱讀 3210·2019-08-30 15:53
閱讀 1006·2019-08-30 15:45
閱讀 735·2019-08-30 15:44
閱讀 3439·2019-08-30 14:24
閱讀 951·2019-08-30 14:21