Kubernetes是Google開源的容器集羣管理系統。它構建於docker技術之上,爲容器化的應用提供資源調度、部署運行、服務發現、擴 容縮容等整一套功能,本質上可看做是基於容器技術的mini-PaaS平臺。本文旨在梳理Kubernetes的架構、概念及基本工做流,而且經過運行一 個簡單的示例應用來介紹如何使用Kubernetes。前端
以下圖所示是我初步閱讀文檔和源代碼以後整理的整體概覽,基本上能夠從以下三個維度來認識Kubernetes。linux
Kubernetes以RESTFul形式開放接口,用戶可操做的REST對象有三個:git
pod:是Kubernetes最基本的部署調度單元,能夠包含container,邏輯上表示某種應用的一個實例。好比一個web站點應用由前端、後端及數據庫構建而成,這三個組件將運行在各自的容器中,那麼咱們能夠建立包含三個container的pod。github
service:是pod的路由代理抽象,用於解決pod之間的服務發現問題。由於pod的運行狀態可動態變 化(好比切換機器了、縮容過程當中被終止了等),因此訪問端不能以寫死IP的方式去訪問該pod提供的服務。service的引入旨在保證pod的動態變化 對訪問端透明,訪問端只須要知道service的地址,由service來提供代理。golang
replicationController:是pod的複製抽象,用於解決pod的擴容縮容問題。一般,分 布式應用爲了性能或高可用性的考慮,須要複製多份資源,而且根據負載狀況動態伸縮。經過replicationController,咱們能夠指定一個應 用須要幾份複製,Kubernetes將爲每份複製建立一個pod,而且保證明際運行pod數量老是與該複製數量相等(例如,當前某個pod宕機時,自動 建立新的pod來替換)。web
能夠看到,service和replicationController只是創建在pod之上的抽象,最終是要做用於pod的,那麼它們如何跟 pod聯繫起來呢?這就要引入label的概念:label其實很好理解,就是爲pod加上可用於搜索或關聯的一組key/value標籤,而 service和replicationController正是經過label來與pod關聯的。以下圖所示,有三個pod都有label 爲"app=backend",建立service和replicationController時能夠指定一樣的 label:"app=backend",再經過label selector機制,就將它們與這三個pod關聯起來了。例如,當有其餘frontend pod訪問該service時,自動會轉發到其中的一個backend pod。redis
以下圖所示是官方文檔裏的集羣架構圖,一個典型的master/slave模型。docker
master運行三個組件:數據庫
apiserver:做爲kubernetes系統的入口,封裝了核心對象的增刪改查操做,以RESTFul接口方式提供給外部客戶和內部組件調用。它維護的REST對象將持久化到etcd(一個分佈式強一致性的key/value存儲)。json
scheduler:負責集羣的資源調度,爲新建的pod分配機器。這部分工做分出來變成一個組件,意味着能夠很方便地替換成其餘的調度器。
controller-manager:負責執行各類控制器,目前有兩類:
endpoint-controller:按期關聯service和pod(關聯信息由endpoint對象維護),保證service到pod的映射老是最新的。
replication-controller:按期關聯replicationController和pod,保證replicationController定義的複製數量與實際運行pod的數量老是一致的。
slave(稱做minion)運行兩個組件:
kubelet:負責管控docker容器,如啓動/中止、監控運行狀態等。它會按期從etcd獲取分配到本機的pod,並根據pod信息啓動或中止相應的容器。同時,它也會接收apiserver的HTTP請求,彙報pod的運行狀態。
proxy:負責爲pod提供代理。它會按期從etcd獲取全部的service,並根據service信息建立代理。當某個客戶pod要訪問其餘pod時,訪問請求會通過本機proxy作轉發。
上文已經提到了Kubernetes中最基本的三個操做對象:pod, replicationController及service。 下面分別從它們的對象建立出發,經過時序圖來描述Kubernetes各個組件之間的交互及其工做流。
最後,讓咱們進入實戰模式,這裏跑一個最簡單的單機示例(全部組件運行在一臺機器上),旨在打通基本流程。
第一步,咱們須要Kuberntes各組件的二進制可執行文件。有如下兩種方式獲取: - 下載源代碼本身編譯:
git clone https://github.com/GoogleCloudPlatform/kubernetes.git
cd kubernetes/build
./release.sh
直接下載人家已經編譯打包好的tar文件:
wget https://storage.googleapis.com/kubernetes/binaries.tar.gz
本身編譯源碼須要先安裝好golang,編譯完以後在kubernetes/_output/release-tars文件夾下能夠獲得打包文件。直接下載的方式不須要安裝其餘軟件,但可能得不到最新的版本。
第二步,咱們還須要etcd的二進制可執行文件,經過以下方式獲取:
wget https://github.com/coreos/etcd/releases/download/v0.4.6/etcd-v0.4.6-linux-amd64.tar.gz
tar xvf etcd-v0.4.6-linux-amd64.tar.gz
第三步,就能夠啓動各個組件了:
etcd
cd etcd-v0.4.6-linux-amd64
./etcd
apiserver
./apiserver \
-address=127.0.0.1 \
-port=8080 \
-portal_net="172.0.0.0/16" \
-etcd_servers=http://127.0.0.1:4001 \
-machines=127.0.0.1 \
-v=3 \
-logtostderr=false \
-log_dir=./log
scheduler
./scheduler -master 127.0.0.1:8080 \
-v=3 \
-logtostderr=false \
-log_dir=./log
controller-manager
./controller-manager -master 127.0.0.1:8080 \
-v=3 \
-logtostderr=false \
-log_dir=./log
kubelet
./kubelet \
-address=127.0.0.1 \
-port=10250 \
-hostname_override=127.0.0.1 \
-etcd_servers=http://127.0.0.1:4001 \
-v=3 \
-logtostderr=false \
-log_dir=./log
搭好了運行環境後,就能夠提交pod了。首先編寫pod描述文件,保存爲redis.json:
{
"id": "redis",
"desiredState": {
"manifest": {
"version": "v1beta1",
"id": "redis",
"containers": [{
"name": "redis",
"p_w_picpath": "dockerfile/redis",
"p_w_picpathPullPolicy": "PullIfNotPresent",
"ports": [{
"containerPort": 6379,
"hostPort": 6379
}]
}]
}
},
"labels": {
"name": "redis"
}
}
而後,經過命令行工具kubecfg提交:
./kubecfg -c redis.json create /pods
提交完後,經過kubecfg查看pod狀態:
# ./kubecfg list /pods
ID Image(s) Host Labels Status
---------- ---------- ---------- ---------- ----------
redis dockerfile/redis 127.0.0.1/ name=redis Running
Status是Running表示pod已經在容器裏運行起來了,能夠用"docker ps"命令來查看容器信息:
# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ae83d1e4b1ec dockerfile/redis:latest "redis-server /etc/r 19 seconds ago Up 19 seconds k8s_redis.caa18858_redis.default.etcd_1414684622_1b43fe35
####建立replicationController
{
"id": "redisController",
"apiVersion": "v1beta1",
"kind": "ReplicationController",
"desiredState": {
"replicas": 1,
"replicaSelector": {"name": "redis"},
"podTemplate": {
"desiredState": {
"manifest": {
"version": "v1beta1",
"id": "redisController",
"containers": [{
"name": "redis",
"p_w_picpath": "dockerfile/redis",
"p_w_picpathPullPolicy": "PullIfNotPresent",
"ports": [{
"containerPort": 6379,
"hostPort": 6379
}]
}]
}
},
"labels": {"name": "redis"}
}},
"labels": {"name": "redis"}
}
而後,經過命令行工具kubecfg提交:
./kubecfg -c redisController.json create /replicationControllers
提交完後,經過kubecfg查看replicationController狀態:
# ./kubecfg list /replicationControllers
ID Image(s) Selector Replicas
---------- ---------- ---------- ----------
redisController dockerfile/redis name=redis 1
同時,1個pod也將被自動建立出來,即便咱們故意刪除該pod,replicationController也將保證建立1個新pod。