Production-Grade Container Orchestration - Automated container deployment, scaling, and management.
生產級別的容器編排系統——自動化的容器部署、擴展和管理。html
因爲最近在學習微服務,因此就基於以前docker的基礎上把玩一下k8s(Kubernetes),以瞭解基本概念和核心功能。node
k8s涉及到不少基本概念,能夠看十分鐘帶你理解Kubernetes核心概念快速瞭解。
下面這張圖包含了k8s了核心組成模塊:
git
這裏就簡單羅列如下:github
梳理完基本概念,咱們來動手玩一玩吧。有三種玩法:一種就是跟隨k8s官方的在線實驗室進行實操;第二種就是基於Docker For Windows 中集成的k8s進行玩耍;第三種就是安裝MiniKube
搗鼓。這裏選擇第二種進行講解。web
PS:不少初學者在環境準備階段遭遇挫折的後就直接放棄了,筆者爲了搭建這個k8s環境也耗費了很多時日,其中包含一次重裝系統,汗!但願下面的步驟助你k8s之行有個好的開端。docker
首先確保你已安裝Docker for Windows。
由於那道牆,在Docker For Windows Client中啓用Kubernetes,並無想象的那麼順利。最後參照這篇文章成功啓用:爲中國用戶在 Docker for Mac/Windows 中開啓 Kubernetes。
若是安裝了最新版本的docker for windows 客戶端(v2.0.0.3),可參考如下步驟:shell
https://registry.docker-cn.com
git clone https://github.com/AliyunContainerService/k8s-for-docker-desktop.git
cd k8s-for-docker-desktop
git checkout v2.0.0.2
(這一步很重要!!!)./load_images.ps1
kubectl cluster-info
,輸出如下,表示正常啓動。Kubernetes master is running at https://localhost:6445 KubeDNS is running at https://localhost:6445/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
環境搭建成功,你就成功了一半,請再接再礪動手完成如下實驗!windows
1:首先咱們執行dotnet new mvc -n K8s.NET.Demo
建立一個ASP.NET Core Mvc應用K8s.NET.Demo
修改HomeController
以下所示:api
public class HomeController : Controller { public IActionResult Index () { var hostname = Dns.GetHostName (); ViewBag.HostName = hostname; ViewBag.HostIp = Dns.GetHostAddresses (hostname).FirstOrDefault (ip => ip.AddressFamily == AddressFamily.InterNetwork); return View (); } public IActionResult Privacy () { return View (); } public IActionResult CheckHealth () { if (new Random ().Next (100) > 50) { return Ok ("OK"); } else { return BadRequest (); } } [ResponseCache (Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] public IActionResult Error () { return View (new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier }); } }
修改Index.cshtml
以下:數組
@{ ViewData["Title"] = "Home Page"; } <div class="text-center"> <h1 class="display-4">Welcome</h1> <h1>Host Name:@ViewBag.HostName</h1> <h1>Host IP:@ViewBag.HostIp</h1> <p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p> </div>
2:而後添加Dockerfile
:
FROM microsoft/dotnet:sdk AS build-env WORKDIR /app # Copy csproj and restore as distinct layers COPY *.csproj ./ RUN dotnet restore # Copy everything else and build COPY . ./ RUN dotnet publish -c Release -o out # Build runtime image FROM microsoft/dotnet:aspnetcore-runtime WORKDIR /app COPY --from=build-env /app/out . ENTRYPOINT ["dotnet", "K8s.NET.Demo.dll"]
3:而後執行docker build -t k8s.net.demo .
構造鏡像,構形成功後執行docker images
便可查看到名爲k8s.net.demo
的鏡像。
添加k8s-web-pod.yaml
文件以下:
apiVersion: v1 kind: Pod # 定義Kubernetes資源的類型爲Pod metadata: name: k8s-net-pod # 定義資源的名稱 labels: # 爲Pod貼上標籤,後面會介紹其用處 app: k8s-net-pod spec: # 定義資源的狀態,對於Pod來講,最重要屬性就是containers containers: # containers一個數組類型,若是你但願部署多個容器,能夠添加多項 - name: web # 定義本Pod中該容器的名稱 image: k8s.net.demo # 定義Pod啓動的容器鏡像地址 imagePullPolicy: IfNotPresent # k8s默認值爲Always,老是從遠端拉取鏡像,經過設置IfNotPresent或Never來使用本地鏡像 ports: - containerPort: 80 # 定義容器監聽的端口(與Dockerfile中的EXPOSE相似,只是爲了提供文檔信息) livenessProbe: # 存活探針定義 httpGet: path: /Home/CheckHealth # 存活探針請求路徑 port: 80 #存活探針請求端口
執行如下命令完成pod的建立:
$ kubectl create -f k8s-web-pod.yaml pod "k8s-web-pod.yaml" created $ kubectl get pod NAME READY STATUS RESTARTS AGE k8s-net-pod 1/1 Running 0 1m
要想與 pod 進行通訊,能夠經過kubectl port-forward
配置端口轉發,來完成。
$ kubectl port-forward k8s-net-pod 8090:80 Forwarding from 127.0.0.1:8090 -> 80 Forwarding from [::1]:8090 -> 80
瀏覽器訪問http://localhost:8090/,效果以下圖所示:
至此咱們成功跑起了第一個pod。
這時你可能會問,這和我直接用docker run -d -p 8091:80 k8s.net.demo
運行一個容器有什麼區別呢?並無看到k8s強大在哪裏啊?!
別急,你如今再執行一次kubectl get pod
,我來告訴你答案。
$ kubectl get po NAME READY STATUS RESTARTS AGE k8s-net-pod 1/1 Running 17 1h
看到RESTARTS列沒有,它是用來講明pod重啓了多少次。使用docker運行容器,若是容器掛掉,docker是不會負責給你重啓容器的。
而在k8s中,只須要配置存活探針,k8s就會自動探測容器的運行狀態,進行自動重啓。而存活探針僅須要在yaml文件中指定livenessProbe
節點便可。(PS:/home/checkhealth 使用隨機數來模擬容器應用運行狀態,當隨機數小於50,就返回BadRequest。)
而這,只是k8s的冰山一角。
Pod運行於集羣內部,雖然使用kubect port-forward
能夠映射端口在本機訪問,但對於外部依舊沒法訪問,若是須要暴露供外部直接訪問,則須要建立 service。
咱們能夠經過kubectl expose pod
直接將當前運行的pod實例暴露出去。
$ kubectl expose pod k8s-net-pod --name k8s-net-service --type=NodePort service "k8s-net-service" exposed $ kubectl get service NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE k8s-net-service NodePort 10.98.62.192 <none> 80:30942/TCP 7m
如上,它有一個CLUSTER-IP爲10.98.62.192
,所以咱們能夠在集羣內使用10.98.62.192:80
來訪問該服務,若是是在集羣外部,可使用NodeIP:30942
(節點所在服務器IP)來訪問。
另一種方式就是建立描述文件來建立了,添加k8s-net-service.yaml
文件:
apiVersion: v1 kind: Service # 定義Kubernetes資源的類型爲Service metadata: name: k8s-net-service # 定義資源的名稱 spec: selector: # 指定對應的Pod app: k8s-net-pod # 指定Pod的標籤爲k8s-net-pod ports: - protocol: TCP # 協議類型 port: 80 # 指定Service訪問的端口 targetPort: 80 # 指定Service轉發請求的端口 nodePort: 30000 type: NodePort # 指定Service的類型,在這裏使用NodePort來對外訪問
執行kubectl create -f k8s-net-service.yaml
來建立service。
$ kubectl create -f k8s-net-service.yaml service "k8s-net-service" created $ kubectl get service NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE k8s-net-service NodePort 10.98.62.192 <none> 80:30942/TCP 23m k8s-net-service NodePort 10.97.110.150 <none> 80:30000/TCP 34s kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 1d
是時候來體驗下k8s強大的自動伸縮功能了。k8s中經過建立ReplicaSet
或Deployment
來管理 pod,進而完成自動化擴展和管理。
PS: 也可使用ReplicaController,但推薦使用ReplicaSet,由於其標籤匹配功能更強大。
首先定義 ReplicaSet 描述文件k8s-net-replicaset.yaml
:
apiVersion: apps/v1beta2 # rs 的版本號爲apps/v1beta2 kind: ReplicaSet # 定義Kubernetes資源的類型爲ReplicaSet metadata: name: k8s-net-replicaset # 定義資源的名稱 spec: replicas: 3 # 指定pod實例的個數 selector: # pod選擇器 matchLabels: # 指定匹配的標籤 app: k8s-net-pod # 指定Pod的標籤爲k8s-net-pod template: # 建立新的pod模板配置 metadata: labels: app: k8s-net-pod # 指定使用哪一個pod spec: containers: - name: k8s-net-replicaset image: k8s.net.demo # 指定使用的鏡像 imagePullPolicy: IfNotPresent # k8s默認值爲Always,老是從遠端拉取鏡像,經過設置IfNotPresent或Never來使用本地鏡像
執行如下命令建立 ReplicaSet,並觀察自動建立的pod實例。
$ kubectl create -f k8s-net-replicaset.yaml replicaset.apps "k8s-net-replicaset" created $ kubectl get rs NAME DESIRED CURRENT READY AGE k8s-net-replicaset 3 3 3 8s $ kubectl get pod NAME READY STATUS RESTARTS AGE k8s-net-pod 1/1 Running 61 12h k8s-net-replicaset-bxw9c 1/1 Running 0 35s k8s-net-replicaset-k6kf7 1/1 Running 0 35s $ kubectl delete po k8s-net-replicaset-bxw9c pod "k8s-net-replicaset-bxw9c" deleted $ kubectl get po NAME READY STATUS RESTARTS AGE k8s-net-pod 1/1 Running 61 12h k8s-net-replicaset-bxw9c 0/1 Terminating 0 2m k8s-net-replicaset-k6kf7 1/1 Running 0 2m k8s-net-replicaset-xvb9l 1/1 Running 0 6s
從上面看到,k8s-net-replicaset
以k8s-net-pod
爲模板建立了額外兩個pod副本,當咱們嘗試刪除其中一個副本後,再次查看pod列表,replicaset會自動幫咱們從新建立一個pod。
那咱們嘗試把剛建立的k8s-net-replicaset
暴露爲Service,看看實際運行是什麼效果吧。依次執行如下命令:
$ kubectl expose replicaset k8s-net-replicaset --type=LoadBalancer --port=8091 --target-port=80 --name k8s-net-rs -service service "k8s-net-rs-service" exposed $ kubectl get service NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE k8s-net-rs-service LoadBalancer 10.99.134.237 localhost 8091:32641/TCP 8s k8s-net-service NodePort 10.104.21.80 <none> 80:30000/TCP 12h kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 12h
而後瀏覽器訪問http://localhost:8091/,嘗試屢次刷新瀏覽器,顯示效果以下,咱們發現ReplicaSet已幫咱們作好了負載均衡。
假如如今網站訪問量劇增,3個實例任然沒法有效支撐,能夠不中止應用的狀況下作到水平伸縮嗎?Of course, Yes!
僅需執行kubectl scale
命令進行擴展便可。
$ kubectl get pod NAME READY STATUS RESTARTS AGE k8s-net-replicaset-g4n6g 1/1 Running 0 13m k8s-net-replicaset-lkrf7 1/1 Running 0 13m k8s-net-replicaset-tf992 1/1 Running 0 13m $ kubectl scale replicaset k8s-net-replicaset --replicas=6 replicaset.extensions "k8s-net-replicaset" scaled $ kubectl get pod NAME READY STATUS RESTARTS AGE k8s-net-replicaset-cz2bs 0/1 ContainerCreating 0 3s k8s-net-replicaset-g4n6g 1/1 Running 0 13m k8s-net-replicaset-lkrf7 1/1 Running 0 13m k8s-net-replicaset-pjl9m 0/1 ContainerCreating 0 3s k8s-net-replicaset-qpn2l 0/1 ContainerCreating 0 3s k8s-net-replicaset-tf992 1/1 Running 0 13m
從以上的輸出能夠看,咱們一句命令就擴展pod實例到6個,是否是很簡單?!
你可能又問了,我如今訪問高峯過了,我怎麼快速縮放應用呢?啊,和上面同樣的,你把--replicas
參數改小點就是了,就像這樣kubectl scale replicaset k8s-net-replicaset --replicas=3
。
本文從使用docker建立image,到使用k8s建立第一個pod,到暴露第一個Service,再到使用ReplicaSet 進行容器伸縮,基本串通了k8s的核心基礎概念,從而對k8s有了基礎的認知,但願對你的K8S之路有所幫助。
因爲篇幅有限,筆者也是初玩,k8s的不少功能並未一一羅列,那就留着下次分享吧。
若是要問我,k8s有什麼好書推薦,首推《Kubernetes In Action》,國內已經有中文版了,翻譯的不錯!
本文示例代碼已上傳至GitHub: K8S.NET.Demo。