
1. 創建集群
Kubernetes集群
Kubernetes協調一個高可用的計算機集群,作為一個單獨的單元來一起工作。有了這種抽象,在Kubernetes中你就可以將容器化的應用程序部署到集群中,而不必將它們特定地綁定到單獨的機器上。為了利用這種新的部署模型,應用程序需要以一種將它們與單個主機解耦的方式打包:它們需要被容器化。與過去的部署模型(PS:應用程序被直接安裝到特定的機器上)相比,容器化應用程序更加靈活和可用。Kubernetes以更高效的方式自動化分發和調度應用容器。Kubernetes是一個開源平台,可以投入生產。
Kubernetes集群由兩類資源組成:
- Master 協調整個集群
- Nodes 運行應用程序的Workers
集群大概是這樣的:

Master負責管理集群。Master協調集群中的所有活動,比如調度應用程序、維護應用程序所需的狀態、擴展應用程序和推送新的更新。
在一個Kubernetes集群中,節點是一個虛擬機或物理機,它是作為worker存在的。每個節點都有一個Kubelet,它是一個代理,用於管理該節點和master之間的通信。生產環境中,Kubernetes集群應該至少有三個節點。
當你部署應用程序到Kubernetes上時,你實際上是告訴master啟動應用程序容器。master調度容器在集群節點上運行。節點和master之間的通信通過Kubernetes API來完成。終端用戶還可以直接使用Kubernetes API與集群交互。
Kubernetes集群可以部署在物理機器或虛擬機器上。要學習Kubernetes的開發,可以使用Minikube。Minikube是一個輕量級Kubernetes實現,它在本地機器上創建一個虛擬機,並部署一個只包含一個節點的簡單集群。
本節回顧(划重點)
Kubernetes是用於協調一個高可用的計算機集群作為一個整體單元的開源平台,它的主要工作是協調應用程序容器的放置和執行。也就是說,Kubernetes屏蔽了底層的細節,使得一個集群看起來就跟一台機器一樣,就是這么整齊划一。理解了這一層以后,就很好理解為什么它可以跨集群節點自動調度了。(PS:想到一個例子,閱兵的時候,兵哥哥們組成一個方陣,步調一致,動作整齊划一,那么多人走在一起就像一個人一樣。如果我們把一台機器想象成一個方陣中的一個兵哥哥的話,那么一個集群就是一個方陣,這個方陣改怎么走就是Kubernetes要做的事情。)

一個集群中有一個Master和多個Node。Master管理集群,負責集群中的所有活動。Node負責具體任務的執行,它是worker。每個Node上都有一個Kubelet,用於和Master通信。
敲黑板,划重點:
1、Kubernetes coordinates a highly available cluster of computers that are connected to work as a single unit. 2、Kubernetes automates the distribution and scheduling of application containers across a cluster in a more efficient way. 3、Kubernetes is a production-grade, open-source platform that orchestrates the placement (scheduling) and execution of application containers within and across computer clusters. 4、Kubernetes集群中有兩種類型的資源:Master 和 Nodes 5、The Master is responsible for managing the cluster. 6、A node is a VM or a physical computer that serves as a worker machine in a Kubernetes cluster. 7、Masters manage the cluster and the nodes are used to host the running applications.
2. 部署應用
Kubernetes Deployments
為了將容器化的應用部署到Kubernetes集群中,需要創建一個Kubernetes Deployment配置。Deployment指示Kubernetes如何創建和更新應用程序的實例。一旦創建了Deployment,Kubernetes master調度就會將應用程序實例放到集群中的各個節點上。
應用程序實例被創建以后,Kubernetes Deployment Controller將會持續監視這些實例。如果承載實例的節點宕機或被刪除,部署控制器將使用集群中另一個節點上的實例替換該實例。這就提供了一種自我修復機制來處理機器故障或維護。
在預先編排的世界中,安裝腳本通常用於啟動應用程序,但它們無法從機器故障中恢復。通過創建應用程序實例並讓它們跨節點運行,Kubernetes部署為應用程序管理提供了一種完全不同的方法。
可以使用Kubernetes命令行接口Kubectl來創建和管理部署。Kubectl使用Kubernetes API與集群交互。
創建部署的時候,需要為應用程序指定容器鏡像和要運行的副本數量。當然,后續可以通過更新部署來更改該信息。

本節回顧(划重點)
Deployment就是將容器化的應用程序部署到Kubernetes集群中。這個很好理解,就是我們平時開發完打jar包部署到服務器上。
敲黑板,划重點:
1、A Deployment is responsible for creating and updating instances of your application.
2、Applications need to be packaged into one of the supported container formats in order to be deployed on Kubernetes.
3. 查看應用
3.1. Pods
創建部署時,Kubernetes會創建一個Pod來承載應用程序實例。一個Pod是一個Kubernetes抽象,它表示一組(一個或多個)應用程序容器(例如:Docker),以及這些容器的一些共享資源。這些資源包括:
- Shared storage, as Volumes
- Networking, as a unique cluster IP address
- Information about how to run each container, such as the container image version or specific ports to use
Pod為一個特定應用程序的“邏輯主機”建模,並可以包含不同的應用程序容器,這些容器是相對緊密耦合的。例如,一個Pod可能包含Node.js應用程序的容器和一個不同的容器,后者提供Node.js web服務器要發布的數據。Pod中的容器共享一個IP地址和端口空間,總是同時定位和同時調度,並在同一節點上的共享上下文中運行。
Pods是Kubernetes平台上的原子單位。當我們在Kubernetes上創建部署的時候,這個部署會創建包含容器的Pods(而不是直接創建容器)。每個Pod都綁定到預定的節點,並一直保持到終止(根據重啟策略)或刪除。萬一節點出現故障,集群中其他可用節點上調度相同的Pods將會被調度。

3.2. Nodes
Pod總是在節點上運行。節點是Kubernetes中的工作機,根據集群的不同,它可以是虛擬機,也可以是物理機。每個節點由Master管理。一個節點可以有多個pod, Kubernetes Master跨集群節點自動處理調度pod。Master的自動調度考慮到每個節點上的可用資源。
每個Kubernetes節點至少運行:
- Kubelet, a process responsible for communication between the Kubernetes Master and the Node; it manages the Pods and the containers running on a machine.
- A container runtime (like Docker, rkt) responsible for pulling the container image from a registry, unpacking the container, and running the application.
常用的kubelet命令:
# list resources
kubectl get
# show detailed information about a resource
kubectl describe
# print the logs from a container in a pod
kubectl logs
# execute a command on a container in a pod
kubectl exec
本節回顧(划重點)
一個Pod是一組應用程序容器,包括運行這組容器所需的共享存儲、IP等資源。可以這樣理解,將一組容器打包在一起就是一個Pod。
Pod總是運行在Node上的。Node是一台物理或虛擬機。
如果容器之間是緊密耦合的,並且需要共享磁盤等資源,那么應該將它們放在單個(同一個)Pod中。
綜上所述,我們不難理解:
- Node是一台物理機或虛擬機,是真正干活的工作機(worker)
- 多個應用程序容器組成Pod
- Pod運行在Node上
- 多個Node組成一個集群
- Master負責管理集群,可以跨集群節點調度
也就是說,在節點上我們看到的是一個一個的Pod,而Pod里面是一個一個的容器
敲黑板,划重點:
1、A Pod is a group of one or more application containers (such as Docker or rkt) and includes shared storage (volumes), IP address and information about how to run them.
2、Containers should only be scheduled together in a single Pod if they are tightly coupled and need to share resources such as disk.
3、A node is a worker machine in Kubernetes and may be a VM or physical machine, depending on the cluster. Multiple Pods can run on one Node.
4. 發布應用
Pods也是有生命周期的。當一個工作節點(worker node)死亡時,該節點上運行的Pods也會隨之丟失。然后,副本集可能通過創建新pod來動態地將集群恢復到所需的狀態,以保持應用程序的運行。Kubernetes集群中的每個Pod都有一個惟一的IP地址,即使是在同一個節點上的Pods,因此需要一種方法來自動協調Pods之間的變化,以保證應用程序正常運行。
Kubernetes中的Service是一個抽象,它定義了一組邏輯Pods和訪問它們的策略。Services支持有依賴關系的Pods之間的松散耦合。與所有Kubernetes對象一樣,Service是使用YAML(首選)或JSON定義的。哪些Pods被選中用來組成一個Service通常是由標簽選擇器決定的。
盡管每個Pod都有唯一的IP地址,但是如果沒有Service,這些IP不會暴露在集群之外。Service允許應用程序接收流量。通過在ServiceSpec中指定類型,可以以不同的方式公開服務:
- ClusterIP (default) - 在集群中的內網IP上公開服務。這種類型使得服務只能從集群內部訪問。
- NodePort - 使用NAT在集群中每個選定節點的相同端口上公開服務。使用<NodeIP>:<NodePort>從集群外部訪問服務。
- LoadBalancer - 在當前雲中創建一個外部負載均衡器(如果支持),並為服務分配一個固定的外網IP。
- ExternalName - 通過返回帶有名稱的CNAME記錄,使用任意名稱(在規范中由externalName指定)公開服務。
4.1. Services and Labels
Service在一組Pod之間路由流量。Services是允許Pod在Kubernetes中死亡和復制而又不影響應用程序的抽象。Pods之間的發現和路由,由Kubernetes Services來處理。
Services通過使用標簽和選擇器匹配Pods。標簽是附加到對象上的鍵/值對,可以以多種方式使用:
- 為開發、測試和生產指定對象
- 嵌入版本標記
- 使用標記對對象進行分類
標簽可以在對象創建時或以后附加到對象,可以隨時修改它們。
本節回顧(划重點)
Kubernetes服務是一個抽象層,它定義一組Pods作為一個邏輯單元並為這些Pod啟用外部流量公開,負載平衡和服務發現。
多個容器組成一個Pod,多個Pod組成一個服務。服務是一種更高層次的抽象,它通過標簽和選擇器匹配一些Pods,這些被選中的Pods形成一個服務,共同對外提供服務。
再對比一下Pod和Service的定義:
A Pod is a Kubernetes abstraction that represents a group of one or more application containers (such as Docker or rkt), and some shared resources for those containers.
A Service in Kubernetes is an abstraction which defines a logical set of Pods and a policy by which to access them.
敲黑板,划重點
1、A Kubernetes Service is an abstraction layer which defines a logical set of Pods and enables external traffic exposure, load balancing and service discovery for those Pods.
2、You can create a Service at the same time you create a Deployment by using
--expose in kubectl.
3、A Service routes traffic across a set of Pods.
4、Services match a set of Pods using labels and selectors.
5. 擴展應用(擴容、伸縮)
5.1. Scaling an application
部署只創建了一個Pod來運行我們的應用程序。當流量增加時,我們需要擴展應用程序以滿足用戶需求。
擴展是通過更改部署中的副本數量來實現的。

擴展部署將確保創建新Pod並將其調度到具有可用資源的節點上。縮放會將Pod的數量增加到新的所需狀態。Kubernetes還支持Pods的自動縮放。縮放到零也是可能的,它將終止指定Deployment的所有Pod。
運行一個應用程序的多個實例將需要一種將流量分配給所有實例的方法。 服務具有集成的負載均衡器,可以將網絡流量分發到公開部署的所有Pod。服務將使用端點連續監視正在運行的Pod,以確保流量僅發送到可用Pod。
一旦運行了一個應用程序的多個實例,就可以在不停機的情況下進行滾動更新。
本節回顧(划重點)
Scale(伸縮)是通過改變副本數量來實現的。伸縮會將Pod的數量增加到新的所需的狀態。當應用從一個實例變成多個實例后,服務自帶的負載均衡器會將流量分發到所有公開的Pods上。
敲黑板,划重點:
1、Scaling is accomplished by changing the number of replicas in a Deployment.
2、You can create from the start a Deployment with multiple instances using the --replicas parameter for the kubectl run command.
6. 更新應用
6.1. Rolling updates
用戶期望應用程序一直可用,而開發人員期望每天多次部署它們的新版本。在Kubernetes中,這是通過滾動更新來完成的。 滾動更新允許通過用新的Pod實例增量更新Pod實例,從而在零停機時間內進行Deployment的更新。新的Pod將被調度到具有可用資源的節點上。
默認情況下,在更新過程中不可用的Pod的最大數量和可以創建的新Pod的最大數量為1。這兩個選項都可以配置為數字或百分比(按Pod)。 在Kubernetes中,對更新進行版本控制,並且任何部署更新都可以還原為先前(穩定)的版本。




與應用程序擴展類似,如果公開部署,則該服務將在更新過程中僅將流量負載均衡到可用Pod。可用的Pod是可供應用程序用戶使用的實例。
滾動更新允許執行以下操作:
- 將應用程序從一種環境升級到另一種環境(通過容器鏡像更新)
- 回滾到以前的版本
- 持續集成和持續交付應用程序,停機時間為零
本節回顧(划重點)
滾動更新允許通過用新的Pod實例增量更新Pod實例,從而在實現在不停機(服務不中斷)的情況下內進行Deployment的更新。
如果部署是公開公開的,則該服務將在更新期間僅將流量負載平衡到可用的Pod。
總之,一句話,滾動更新可以實現平滑升級(平滑上線)。(PS:可以聯想一下Nginx)
敲黑板,划重點:
1、Rolling updates allow Deployments' update to take place with zero downtime by incrementally updating Pods instances with new ones.
2、If a Deployment is exposed publicly, the Service will load-balance the traffic only to available Pods during the update.
7. 命令和文檔
https://kubernetes.io/docs/tutorials/
# 安裝minikube
curl -Lo minikube https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
chmod +x minikube
install minikube /usr/local/bin/
minikube version
# 部署應用
minikube start
kubectl version
kubectl cluster-info
kubectl get nodes
kubectl get deployments
kubectl get pods
kubectl describe pods
kubectl get services
kubectl delete service
kubectl expose
kubectl exec
kubectl scale
kubectl rollout status
7.1. Hello Minikube

啟動集群
minikube start --image-mirror-country cn \
--vm-driver=virtualbox \
--iso-url=https://kubernetes.oss-cn-hangzhou.aliyuncs.com/minikube/iso/minikube-v1.6.0.iso \
--registry-mirror=https://9q0y37ef.mirror.aliyuncs.com

7.2. 演示
首先,構建鏡像
新建一個文件命名為server.js
var http = require('http');
var handleRequest = function(request, response) {
console.log('Received request for URL: ' + request.url);
response.writeHead(200);
response.end('Hello World!');
};
var www = http.createServer(handleRequest);
www.listen(8080);
再創建一個Dockerfile文件
FROM node:6.14.2
EXPOSE 8080
COPY server.js .
CMD node server.js
構建鏡像
docker image build . -t hello-world
docker tag hello-world:latest cheng1234/hello-world:v1.0
docker login
docker push cheng1234/hello-world:v1.0

推送到遠程鏡像倉庫,這里推到默認的Docker Hub上

半個小時以后,我后悔了,超級慢,根本推送不上去,速度慢得讓人想砸電腦,重試了好幾次。當成功推送上去的時候已經是第二天了。

后來,我想,畢竟是國外的。。。
遂決定,推送到阿里雲容器鏡像倉庫
docker login registry.cn-hangzhou.aliyuncs.com
docker tag hello-world:latest registry.cn-hangzhou.aliyuncs.com/chengjs/hello-world:1.0
docker push registry.cn-hangzhou.aliyuncs.com/chengjs/hello-world:1.0

部署服務
kubectl create deployment hello-world --image=registry.cn-hangzhou.aliyuncs.com/chengjs/hello-world:1.0
kubectl get deployments
kubectl get pods
kubectl expose deployment hello-world --type=LoadBalancer --port=8080
kubectl get services
minikube service hello-world



8. 阿里雲容器鏡像服務
https://cr.console.aliyun.com/






阿里雲
https://www.aliyun.com/product/acr
https://cr.console.aliyun.com/cn-hangzhou/instances/repositories
https://help.aliyun.com/document_detail/60743.html
https://help.aliyun.com/product/85222.html
https://developer.aliyun.com/group/kubernetes
Docker
https://docs.docker.com/engine/reference/commandline/image_build/
https://docs.docker.com/engine/reference/commandline/tag/
Kubernetes
https://kubernetes.io/docs/tutorials
https://kubernetes.io/docs/setup/best-practices/
鏡像加速器
https://www.jianshu.com/p/5a911f20d93e
https://blog.51cto.com/14423403/2417029
https://yq.aliyun.com/articles/696286
常用命令

