《kubernetes權(quán)威指南》是本不可多得的好書鹊碍,這里記錄一下自己的讀書筆記以及按照書中搭建的源代碼僵缺。
kubernetes官方文檔:https://kubernetes.io/docs/home/
kubernetes中文手冊:https://www.kubernetes.org.cn/docs
kubernetes中文文檔:https://linfan1.gitbooks.io/kubernetes-chinese-docs/content
What is Kubernetes?
英文原文:
Kubernetes is an open-source platform designed to automate deploying, scaling, and operating application containers.
With Kubernetes, you are able to quickly and efficiently respond to customer demand:
Deploy your applications quickly and predictably.
Scale your applications on the fly.
Roll out new features seamlessly.
Limit hardware usage to required resources only.
Our goal is to foster an ecosystem of components and tools that relieve the burden of running applications in public and private clouds.
官方定義的說法是Kubernetes一個用于容器集群的自動化部署胡桃、擴(kuò)容以及運維的開源平臺。使用Kubernetes磕潮,你可以快速高效地響應(yīng)客戶需求:
- 動態(tài)地對應(yīng)用進(jìn)行擴(kuò)容翠胰。
- 無縫地發(fā)布新特性。
- 僅使用需要的資源以優(yōu)化硬件使用自脯。
個人把k8s比喻成一艘裝滿集裝箱的帆船之景,可以裝滿很多的集裝箱。
在集群的管理方面冤今,kubernetes將集群中的機器劃分為一個master節(jié)點和一群工作節(jié)點nodes.
- master上運行與集群管理相關(guān)的一組進(jìn)程:kube-apiserver,kube-controller-manager,kube-scheduler
- node上運行與kubectl,kube-proxy等服務(wù)進(jìn)程
- etcd 作為高性能存儲服務(wù)
etcd 的學(xué)習(xí)可以參考 gitbook 上面某大神的一本書 一 etcd3學(xué)習(xí)筆記闺兢。
二話不說 書本上從一個簡單的例子開始實踐一下
單機部署一個mysql+myweb(tomcat)應(yīng)用棧
技術(shù)準(zhǔn)備:Centos7 OSX
- 關(guān)閉centos7防火墻
systemctl stop firewalld
systemctl disable firewalld
- 安裝etcd鍵值數(shù)據(jù)庫以及k8s
yum update -y
yum install etcd kubernetes -y
此時安裝好的etcd和kubernetes版本為:
kubectl :v1.5.2
docker : v1.12.6
etcd : v3.2.9
- 修改配置文件(1)
- docker配置文件/etc/sysconfig/docker
Options的內(nèi)容加上:OPTIONS='--selinux-enabled=false --insecure-registry gcr.io'
- 修改配置文件(2)
- Kubernetes apiserver配置文件為/etc/kubernetes/apiserver
把--admission_control參數(shù)的ServiceAccount參數(shù)刪除
- 按順序啟動服務(wù)
systemctl start etcd
systemctl start docker
systemctl start kube-apiserver
systemctl start kube-controller-manager
systemctl start kube-scheduler
systemctl start kubelet
systemctl start kube-proxy
準(zhǔn)備工作
1.換源
curl -sSL https://get.daocloud.io/daotools/set_mirror.sh | sh -s http://3b13d85e.m.daocloud.io
systemctl restart docker
2.提前下載好所需標(biāo)準(zhǔn)鏡像
#mysql鏡像
docker pull daocloud.io/library/mysql:latest
#tomcat鏡像
docker pull kubeguide/tomcat-app:v2
啟用mysql容器服務(wù)
1.定義一個RC文件,命名為mysql-rc.yaml,編輯:
apiVersion: v1
kind: ReplicationController
metadata:
name: mysql
spec:
replicas: 1
#定義RC標(biāo)簽選擇
selector:
app: mysql
#定義Pod模板
template:
metadata:
labels:
app: mysql
spec:
#Pod內(nèi)容器定義
containers:
- name: mysql
image: daocloud.io/library/mysql
ports:
- containerPort: 3306
env:
- name: MYSQL_ROOT_PASSWORD
value: "123456"
創(chuàng)建好文件后戏罢,發(fā)布到k8s集群中
[root@taroballs ~]# kubectl create -f mysql-rc.yaml
replicationcontroller "mysql" created
查看剛剛創(chuàng)建的RC
[root@kubecon ~]# kubectl get rc
NAME DESIRED CURRENT READY AGE
mysql 1 1 1 11s
查看Pod的創(chuàng)建情況
[root@kubecon ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
mysql-bh44q 1/1 Running 0 16s
2.定義一個Service屋谭,文件命名為mysql-svc.yaml
apiVersion: v1
kind: Service
metadata:
name: mysql
spec:
ports:
- port: 3306
selector:
app: mysql
保存后同樣發(fā)布到k8s集群中
[root@taroballs ~]# kubectl create -f mysql-svc.yaml
service "mysql" created
查看創(chuàng)建好的Service
[root@kubecon ~]# kubectl get svc
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes 10.254.0.1 <none> 443/TCP 13h
mysql 10.254.248.1 <none> 3306/TCP 5s
#請注意 mysql服務(wù)被分配到了一個10.254.248.1的ClusterIP地址,此地址為虛地址龟糕,這樣其他的Pod就可以通過Service的ClusterIP+端口號6379來訪問它了
創(chuàng)建Tomcat應(yīng)用棧
1.同樣桐磁,定義一個RC文件,命名為myweb-rc.yaml讲岁,后面會講到如何編寫不用擔(dān)心:
apiVersion: v1
kind: ReplicationController
metadata:
name: myweb
spec:
# Pod的數(shù)量
replicas: 1
# spec.selector與spec.template.metadata.labels我擂,這兩個字段必須相同衬以,否則下一步創(chuàng)建RC會失敗。
selector:
app: myweb
template:
metadata:
labels:
app: myweb
# 容器組的定義
spec:
containers:
# 容器名稱
- name: myweb
# 容器對應(yīng)的鏡像
image: kubeguide/tomcat-app:v2
ports:
# 在8080端口上啟動容器進(jìn)程校摩,PodIP與容器端口組成Endpoint看峻,代表著一個服務(wù)進(jìn)程對外通信的地址
- containerPort: 8080
env:
#此處如果在未安裝域名解析的情況下,會無法將mysql對應(yīng)的IP解析到env環(huán)境變量中衙吩,因此先注釋掉互妓!
# - name: MYSQL_SERVICE_HOST
# value: 'mysql'
- name: MYSQL_SERVICE_PORT
value: '3306'
把它發(fā)布到集群當(dāng)中:
[root@kubecon ~]# kubectl create -f tomcat-rc.yaml
replicationcontroller "myweb" created
查看RC是否存在
[root@kubecon ~]# kubectl get rc
NAME DESIRED CURRENT READY AGE
mysql 1 1 1 1h
myweb 1 1 1 15s
查看Pod是否運行
[root@kubecon ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
mysql-bh44q 1/1 Running 0 1h
myweb-dctwr 1/1 Running 0 19s
2.定義一個Service文件,命名為myweb-svc.yaml
apiVersion: v1
kind: Service
metadata:
name: myweb
spec:
type: NodePort
ports:
- port: 8080
nodePort: 30001
selector:
app: myweb
同樣的坤塞,把它發(fā)布到集群中
[root@kubecon ~]# kubectl create -f tomcat-svc.yaml
service "myweb" created
查看是否存在這個Service
[root@kubecon ~]# kubectl get svc
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes 10.254.0.1 <none> 443/TCP 15h
mysql 10.254.248.1 <none> 3306/TCP 1h
myweb 10.254.134.126 <nodes> 8080:30001/TCP 4s
如果都能完成的話 就到了激動人心的時刻了,打開瀏覽器訪問http://yourip:30001
View on http://yourip:30001/demo/
如果看到這個界面說明你成功了
嘗試一下插入一條數(shù)據(jù)
術(shù)語:
Master
- Kubernetes API Server (kube-apiserver)提供HTTP Rest接口實現(xiàn)對集群中所有資源的增刪改查
- Kubernetes Controller Manager (kube-controller-manager) 集群所有資源的自動化控制中心冯勉,“總管”
- Kubernetes Scheduler (kuber-scheduler) 負(fù)責(zé)資源調(diào)度(Pod調(diào)度)
Node
Node才是kubernetes集群中的工作負(fù)載節(jié)點
kubelet:負(fù)責(zé)Pod對應(yīng)的容器創(chuàng)建/啟停,實現(xiàn)集群管理等基本功能(最常用)
-
kube-proxy: 實現(xiàn)k8s集群的通信于負(fù)載均衡
Node特性:
- 默認(rèn)情況下node中kubelet會在集群中向master主節(jié)點介紹并注冊自己
- 一旦被納入集群摹芙,kubelet就會定時向Master匯報自己的資源情況
-
超時上報定為失聯(lián):若某Node超過指定時間都不上報信息灼狰,Master會將此Node定義為”失聯(lián)“即"Not Ready"
查看當(dāng)前主機有多少個Node節(jié)點:
[root@kubecon ~]# kubectl get nodes
NAME STATUS AGE
127.0.0.1 Ready 15h
#由于筆者只有一臺ecs >-<.
查看某個node的詳細(xì)信息:
[root@kubecon ~]# kubectl describe node 127.0.0.1
Name: 127.0.0.1
Role:
Labels: beta.kubernetes.io/arch=amd64
beta.kubernetes.io/os=linux
kubernetes.io/hostname=127.0.0.1
Taints: <none>
CreationTimestamp: Wed, 03 Jan 2018 22:12:05 +0800
Phase:
Conditions:
Type Status LastHeartbeatTime LastTransitionTime Reason Message
---- ------ ----------------- ------------------ ------ -------
OutOfDisk False Thu, 04 Jan 2018 13:24:24 +0800 Wed, 03 Jan 2018 22:12:05 +0800 KubeletHasSufficientDisk kubelet has sufficient disk space available
MemoryPressure False Thu, 04 Jan 2018 13:24:24 +0800 Wed, 03 Jan 2018 22:12:05 +0800 KubeletHasSufficientMemory kubelet has sufficient memory available
DiskPressure False Thu, 04 Jan 2018 13:24:24 +0800 Wed, 03 Jan 2018 22:12:05 +0800 KubeletHasNoDiskPressure kubelet has no disk pressure
Ready True Thu, 04 Jan 2018 13:24:24 +0800 Wed, 03 Jan 2018 22:12:05 +0800 KubeletReady kubelet is posting ready status
Addresses: 127.0.0.1,127.0.0.1,127.0.0.1
Capacity:
alpha.kubernetes.io/nvidia-gpu: 0
cpu: 1
memory: 1883496Ki
pods: 110
Allocatable:
alpha.kubernetes.io/nvidia-gpu: 0
cpu: 1
memory: 1883496Ki
pods: 110
System Info:
Machine ID: 963c2c41b08343f7b063dddac6b2e486
System UUID: 82E60F76-EF44-4B56-8865-9B667778593F
Boot ID: a48df7fa-e8ea-4300-8323-437c83f20321
Kernel Version: 3.10.0-693.11.1.el7.x86_64
OS Image: CentOS Linux 7 (Core)
Operating System: linux
Architecture: amd64
Container Runtime Version: docker://1.12.6
Kubelet Version: v1.5.2
Kube-Proxy Version: v1.5.2
ExternalID: 127.0.0.1
Non-terminated Pods: (2 in total)
Namespace Name CPU Requests CPU Limits Memory Requests Memory Limits
--------- ---- ------------ ---------- --------------- -------------
default mysql-bh44q 0 (0%) 0 (0%) 0 (0%) 0 (0%)
default myweb-dctwr 0 (0%) 0 (0%) 0 (0%) 0 (0%)
Allocated resources:
(Total limits may be over 100 percent, i.e., overcommitted.
CPU Requests CPU Limits Memory Requests Memory Limits
------------ ---------- --------------- -------------
0 (0%) 0 (0%) 0 (0%) 0 (0%)
Events:
FirstSeen LastSeen Count From SubObjectPath Type Reason Message
--------- -------- ----- ---- ------------- -------- ------ -------
13m 13m 2 {kubelet 127.0.0.1} Warning MissingClusterDNS kubelet does not have ClusterDNS IP configured and cannot create Pod using "ClusterFirst" policy. pod: "myweb-1ndjf_default(984cd373-f10d-11e7-952b-00163e04f964)". Falling back to DNSDefault policy.
11m 11m 2 {kubelet 127.0.0.1} Warning MissingClusterDNS kubelet does not have ClusterDNS IP configured and cannot create Pod using "ClusterFirst" policy. pod: "myweb-vblfl_default(f8b588aa-f10d-11e7-952b-00163e04f964)". Falling back to DNSDefault policy.
10m 10m 2 {kubelet 127.0.0.1} Warning MissingClusterDNS kubelet does not have ClusterDNS IP configured and cannot create Pod using "ClusterFirst" policy. pod: "myweb-dctwr_default(07cd7332-f10e-11e7-952b-00163e04f964)". Falling back to DNSDefault policy.
Pod:
Kubernetes中,所有的容器都運行在pod中浮禾,一個pod來容納一個單獨的容器交胚,或者多個合作的容器。
為什么要引入Pod容器伐厌?
1.以“容器組”為單位整體能夠簡單對業(yè)務(wù)進(jìn)行封裝管理以及判斷
2.Pod里多個業(yè)務(wù)共享Pause容器的IP以及Volume使得管理極其方便
Pod特性:
- 每個Pod都有一個特殊的被稱為”根容器“的Pause容器
- 每個Pod都包含一個或多個業(yè)務(wù)容器
- 每個Pod都分配了唯一的IP地址PodIP承绸,一個Pod中多個容器共享PodIP
- 一個Pod里的容器與另外主機上的Pod容器能夠直接通信裸影;
- 如果Pod所在的Node宕機挣轨,會將這個Node上的所有Pod重新調(diào)度到其他節(jié)點上;
- 一個pod也能包含零個或者更多的的volume轩猩,volume是對一個容器私有的目錄或者可以在pod中的容器間共享卷扮。
普通Pod及靜態(tài)Pod
差別 | 普通Pod | 靜態(tài)Pod |
---|---|---|
存放位置 | 一創(chuàng)建就存在etcd | 放在某個具體node的具體文件中 |
使用方式 | 被Master調(diào)度到某node上進(jìn)行綁定 | 只在此具體文件所在的node上啟動運行 |
EndPoint的概念
PodIP+containerPort--->EndPoint
Pod的IP加上容器開啟的端口,代表著一個服務(wù)進(jìn)程與外界通信的地址
資源限制
每個Pod可以設(shè)置限額的計算機資源有CPU和Memory均践;
- Requests晤锹,資源的最小申請量;
- Limits彤委,資源最大允許使用的量
可以通過設(shè)置這兩個參數(shù)來限制Pod使用的資源
如果一個容器失敗鞭铆,它會被Kubernetes的node上的kubectl自動重啟
簡單來說,Pod就是集裝箱中的一個一個小的房間
Event
Event :是一個事件記錄焦影,記錄了事件最早產(chǎn)生的時間车遂、最后重復(fù)時間、重復(fù)次數(shù)斯辰、發(fā)起者舶担、類型,以及導(dǎo)致此事件的原因等信息彬呻。Event通常關(guān)聯(lián)到具體資源對象上衣陶,式排查故障的重要參考信息柄瑰;
Pod錯誤排查
當(dāng)我們發(fā)現(xiàn)某個Pod遲遲無法創(chuàng)建時,我們可以使用
kubectl describe pod xxxx
來查看它的描述信息.用來定位問題的范圍~
[root@kubecon ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
mysql-bwnlk 0/1 ContainerCreating 0 1m
pod服務(wù)一直處于 ContainerCreating狀態(tài),即出現(xiàn)了錯誤
[root@kubecon ~]# kubectl describe po mysql-bwnlk
Name: mysql-bwnlk
Namespace: default
Node: 127.0.0.1/127.0.0.1
Start Time: Thu, 04 Jan 2018 10:20:45 +0800
Labels: app=mysql
Status: Pending
IP:
Controllers: ReplicationController/mysql
Containers:
mysql:
Container ID:
Image: daocloud.io/library/mysql
Image ID:
Port: 3306/TCP
State: Waiting
Reason: ContainerCreating
Ready: False
Restart Count: 0
Volume Mounts: <none>
Environment Variables:
MYSQL_ROOT_PASSWORD: 123456
Conditions:
Type Status
Initialized True
Ready False
PodScheduled True
No volumes.
QoS Class: BestEffort
Tolerations: <none>
Events:
FirstSeen LastSeen Count From SubObjectPath Type Reason Message
--------- -------- ----- ---- ------------- -------- ------ -------
3m 3m 1 {default-scheduler } Normal Scheduled Successfully assigned mysql-bwnlk to 127.0.0.1
3m 20s 5 {kubelet 127.0.0.1} Warning FailedSync Error syncing pod, skipping: failed to "StartContainer" for "POD" with ErrImagePull: "image pull failed for registry.access.redhat.com/rhel7/pod-infrastructure:latest, this may be because there are no credentials on this request. details: (open /etc/docker/certs.d/registry.access.redhat.com/redhat-ca.crt: no such file or directory)"
2m 8s 10 {kubelet 127.0.0.1} Warning FailedSync Error syncing pod, skipping: failed to "StartContainer" for "POD" with ImagePullBackOff: "Back-off pulling image \"registry.access.redhat.com/rhel7/pod-infrastructure:latest\""
Label
Label是一種可以附加到各種資源對象上(Pod,Node,RC,Service等)剪况,通常在資源定義時確定也可以在對象創(chuàng)建后動態(tài)添加的實現(xiàn)資源分組動態(tài)功能的對象教沾。
Label特性:
- 一個資源對象可以定義任意數(shù)量的Label。
- 給某個資源定義一個Label译断,相當(dāng)于給該對象打上了標(biāo)簽珍剑,
- 通過給指定的資源對象捆綁一個或多個不同的Label來實現(xiàn)多維度的資源分組管理功能庄撮,能夠更加靈活、方便的進(jìn)行資源分配、調(diào)度拷况、配置、部署等管理工作
- 可以通過Label Selector(標(biāo)簽選擇器)查詢和篩選擁有某些Label的資源對象透且。
Label Selector
用于查詢和篩選擁有某些Labels的資源對象
類似于SQL語句
Label Selector示例:select * from pod where pod’s name=’XXX’,env=’YYY’性誉,支持操作符有=、!=杨蛋、in兜材、not in;
Label常用場景
- kube-controller進(jìn)程通過RC上的Label Selector來篩選監(jiān)控所期望的Pod數(shù)量
- kube-proxy通過Service上的Label Selector來選擇對應(yīng)的Pod以便建立起對應(yīng)Pod的請求路由轉(zhuǎn)發(fā)表
Replication controller副本管理器
RC是一種用來聲明某種Pod的副本數(shù)量在任何時刻都符合某個預(yù)期值的場景文件逞力。
Kubernetes的API對象用來管理Pod副本的行為的文件被稱作replication controller曙寡,它用模板的形式定義了pod,然后系統(tǒng)根據(jù)模板實例化出一些pod(特別是由用戶)
換句話說寇荧,我們通過定義一個RC文件來實現(xiàn)Pod的創(chuàng)建過程及副本數(shù)量的自動控制
RC的定義
- Replicas: Pod 的期待的副本數(shù)(replicas)
- Label Selector: 用于篩選目標(biāo) Pod
- Template: 當(dāng)副本數(shù)小于期望時举庶,用于創(chuàng)建新pod的模板
RC特性
- 定期巡檢:定期巡檢當(dāng)前存活的目標(biāo)Pod
- 擴(kuò)容和縮容,通過改變RC的Replicas副本數(shù)量可以實現(xiàn)Pod的縮容和擴(kuò)容
- 滾動升級揩抡,通過改變RC中的鏡像版本可以實現(xiàn)Pod的滾動升級功能
先來個例子實戰(zhàn)一下
#定義文件tomcat-frontend-rc.yaml
apiVersion: v1
kind: ReplicationController
metadata:
name: frontend
spec:
replicas: 1
selector:
tier: frontend
template:
metadata:
labels:
app: app-demo
tier: frontend
spec:
containers:
- name: tomcat-demo
image: daocloud.io/library/tomcat
imagePullPolicy: IfNotPresent
env:
- name: GET_HOSTS_FROM
value: dns
ports:
- containerPort: 80
將它發(fā)布到集群中
[root@kubecon ~]# kubectl create -f tomcat-frontend-rc.yaml
replicationcontroller "frontend" created
[root@kubecon ~]# kubectl get rc
NAME DESIRED CURRENT READY AGE
frontend 1 1 1 5s
[root@kubecon ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
frontend-8cg3k 1/1 Running 0 8s
[root@kubecon ~]# kubectl get endpoints
NAME ENDPOINTS AGE
kubernetes 172.18.231.136:6443 6m
Replica Set
下一代的Replication Controller
差別 | Replica Set | Replication Controller |
---|---|---|
base | 基于集合的Label Selector | 基于等式的Label Selector |
future | 下一代的RC,現(xiàn)主要被Deployment運用 | 將被取代 |
RS的特性與RC特性相類似,不再贅述.
Deployment 升級版RC
與RC區(qū)別户侥,兩者相似度>90%
- 相對于RC一個最大升級是我們可以隨時知道當(dāng)前Pod“部署”的進(jìn)度。
- Deployment使用了Replica Set
- 除非需要自定義升級功能或根本不需要升級Pod峦嗤,一般情況下蕊唐,我們推薦使用Deployment而不直接使用Replica Set;
Deployment 擁有更加靈活強大的升級烁设、回滾功能替梨。在新的版本中,官方推薦使用Replica Set和Deployment來代替RC
Deployment使用場景
- 創(chuàng)建一個Deployment對象來生成對應(yīng)的Replica Set并完成Pod副本的創(chuàng)建過程装黑;
- 檢查更新Deployment的狀態(tài)來查看部署動作是否完成(Pod副本的數(shù)量是否達(dá)到預(yù)期的值)副瀑;
- 更新Deployment以創(chuàng)建新的Pod;(比如鏡像升級)
- 如果當(dāng)前Deployment不穩(wěn)定曹体,則回滾到一個早先的Deployment版本俗扇;
- 掛起或者恢復(fù)一個Deployment;
下面以一個例子實戰(zhàn)下Deployment
構(gòu)建Tomcat_Deployment
定義一個文件 命名為:tomcat-deployment.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: tomcat-deployment
spec:
replicas: 1
selector:
matchLabels:
tier: frontend
matchExpressions:
- {key: tier, operator: In, values: [frontend]}
template:
metadata:
labels:
app: app-demo
tier: frontend
spec:
containers:
- name: tomcat-dome
image: tomcat
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
發(fā)布到Kubernetes集群
[root@kubecon ~]# kubectl create -f tomcat-deployment.yaml
deployment "tomcat-deployment" created
[root@kubecon ~]# kubectl get deployments
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
tomcat-deployment 1 1 1 1 4s
- DESIRED箕别,Pod副本數(shù)量的期望值铜幽,及Deployment里定義的Replica滞谢;
- CURRENT,當(dāng)前Replica實際值除抛;
- UP-TO-DATE狮杨,最新版本的Pod的副本數(shù)量,用于指示在滾動升級的過程中到忽,有多少個Pod副本已經(jīng)成功升級橄教;
- AVAILABLE,當(dāng)前集群中可用的Pod的副本數(shù)量喘漏;
查看對應(yīng)的Replica Set
[root@kubecon ~]# kubectl get rs
NAME DESIRED CURRENT READY AGE
tomcat-deployment-142787937 1 1 1 1m
#看一下這里Pod的命名以Deployment對應(yīng)的Replica Set的名字為前綴护蝶;
查看Pod的水平擴(kuò)展過程
[root@kubecon ~]# kubectl get rs
NAME DESIRED CURRENT READY AGE
tomcat-deployment-142787937 1 1 1 1m
[root@kubecon ~]# kubectl describe deployments
Name: tomcat-deployment
Namespace: default
CreationTimestamp: Thu, 04 Jan 2018 18:48:31 +0800
Labels: app=app-demo
tier=frontend
Selector: tier=frontend,tier in (frontend)
Replicas: 1 updated | 1 total | 1 available | 0 unavailable
StrategyType: RollingUpdate
MinReadySeconds: 0
RollingUpdateStrategy: 1 max unavailable, 1 max surge
Conditions:
Type Status Reason
---- ------ ------
Available True MinimumReplicasAvailable
OldReplicaSets: <none>
NewReplicaSet: tomcat-deployment-142787937 (1/1 replicas created)
Events:
FirstSeen LastSeen Count From SubObjectPath Type Reason Message
--------- -------- ----- ---- ------------- -------- ------ -------
1m 1m 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set tomcat-deployment-142787937 to 1
Horizontal Pod Autoscaler(HPA)智能擴(kuò)容
HPA的引入
- 雖然說可以手工執(zhí)行kubectl scale命令,從而實現(xiàn)Pod橫向自動擴(kuò)容
- 但是我們目標(biāo)是實現(xiàn)自動化翩迈、智能化擴(kuò)容或縮容持灰。
分布式系統(tǒng)能夠根據(jù)當(dāng)前系統(tǒng)的負(fù)載變化情況自動觸發(fā)水平擴(kuò)展或擴(kuò)容的行為
實現(xiàn)原理:通過追蹤分析RC控制的所有目標(biāo)Pod的負(fù)載變化情況來確定是否需要針對性地調(diào)節(jié)目標(biāo)Pod的副本數(shù),相當(dāng)與調(diào)節(jié)器负饲。
HPA擴(kuò)容的Pod負(fù)載度量指標(biāo):
- CPUUtilizationPercentage
通常使用一分鐘內(nèi)的算術(shù)平均值堤魁,可以通過Heapster擴(kuò)展組件獲取這個值。一個Pod自身的CPU利用率是該Pod當(dāng)前CPU的使用量除以它的Pod Request的值返十。例如Pod Request定義值為0.4妥泉,當(dāng)前Pod使用量為0.2,則它的CPU使用率為50%洞坑。如果某一刻CPUUtilizationPercentage超過80%則意為著當(dāng)前pod不足以支撐故需要擴(kuò)容來實現(xiàn)動態(tài)負(fù)載 - 第二個指標(biāo):應(yīng)用程序自定義的度量指標(biāo)盲链,比如服務(wù)在每秒內(nèi)的相應(yīng)的請求數(shù)(TPS或QPS)
下面以一個HPA實例來實戰(zhàn)下
構(gòu)建HPA定義文件,命名為php-apache.yaml
apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
name: php-apache
namespace: default
spec:
maxReplicas: 10
minReplicas: 1
scaleTargetRef:
kind: Deployment
name: php-apache
targetCPUUtilizationPercentage: 90
#這個HPA控制的目標(biāo)對象為一個名叫php-apache的Deployment里的Pod副本检诗,當(dāng)這些Pod副本的CPUUtilizationPercentage超過90%時會觸發(fā)自動擴(kuò)容行為匈仗,擴(kuò)容或縮容時必須滿足的一個約束條件是Pod的副本數(shù)要介于1與10之間瓢剿;
發(fā)布到集群中
[root@kubecon ~]# kubectl create -f php-apache.yaml
horizontalpodautoscaler "php-apache" created
也可以通過簡單命令行方式創(chuàng)建等價HPA對象
[root@kubecon ~]# kubectl get deployments
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
frontend 1 1 1 0 22m
[root@kubecon ~]# kubectl autoscale deployment frontend --cpu-percent=90 --min=1 --max=10
deployment "frontend" autoscaled
Service
Service是一個“微服務(wù)”的代名詞逢慌,通過分析、識別并建模系統(tǒng)中的所有服務(wù)為微服務(wù)——Kubernetes Service间狂,最終構(gòu)成多個提供不同業(yè)務(wù)能力而又彼此獨立的微服務(wù)單元攻泼,服務(wù)之間通過TCP/IP進(jìn)行通信,從而形成了我們強大而又靈活的彈性網(wǎng)絡(luò)鉴象,擁有了強大的分布式能力忙菠、彈性擴(kuò)展能力、容錯能力纺弊。
我們的業(yè)務(wù)系統(tǒng)就是由一或多個“微服務(wù)”Service構(gòu)成的牛欢。相當(dāng)與帆船上一個一個的集裝箱
由圖中我們可以看到,Kubernetes的Service定義了一個服務(wù)的訪問入口地址:
- 前段的應(yīng)用frontend Pod通過這個入口地址訪問其背后的一組由副本組成的集群實例
- Service與后端Pod副本集群之間則是通過Label Selector來實現(xiàn)“無縫對接”
- RC的作用保證Service的服務(wù)能力和質(zhì)量始終處于預(yù)期的標(biāo)準(zhǔn)
問題引入:客戶端訪問Pod
既然每個Pod都會被分配到一個獨立的IP地址淆游,而且每個Pod都提供了一個獨立的Endpoint(Pod IP+ContainerPort)以被客戶端訪問傍睹,那么問題來了隔盛,現(xiàn)在多個Pod副本組成了一個集群來提供服務(wù),那么客戶端如何來訪問它們呢拾稳?
一般的做法是部署一個負(fù)載均衡器來訪問它們吮炕,為這組Pod開啟一個對外的服務(wù)端口如8000,并且將這些Pod的Endpoint列表加入8000端口的轉(zhuǎn)發(fā)列表中访得,客戶端可以通過負(fù)載均衡器的對外IP地址+服務(wù)端口來訪問此服務(wù)龙亲。而客戶端請求會被轉(zhuǎn)發(fā)到哪個Pod,則有均很負(fù)載器覺得悍抑。
Kubernetes中運行在Node上的kube-proxy其實就是一個智能的軟件負(fù)載均衡器鳄炉,它負(fù)責(zé)把對Service的請求轉(zhuǎn)發(fā)到后端的某個Pod實例上,并且在內(nèi)部實現(xiàn)服務(wù)的負(fù)載均衡與會話保持機制搜骡。
k8s發(fā)明了一種巧妙的設(shè)計:Service不是共用一個負(fù)載均衡器的IP地址迎膜,而是每個Servcie分配一個全局唯一的虛擬IP地址,這個虛擬IP被稱為Cluster IP浆兰。
這樣一來 每個服務(wù)就變成了具備唯一IP地址的“通信節(jié)點”磕仅,服務(wù)調(diào)用也成了最基礎(chǔ)的TCP通信問題。
來一個小小的例子是實戰(zhàn)一下~
首先定義一個Service文件簸呈,命名為tomcat-service.yaml
apiVersion: v1
kind: Service
metadata:
name: tomcat-service
spec:
# 服務(wù)如果想被外部調(diào)用榕订,必須配置type
type: NodePort
ports:
- port: 8080
name: service-port
# 服務(wù)如果想被外部調(diào)用,必須配置nodePort
nodePort: 31002
- port: 8005
name: shutdown-port
selector:
tier: frontend
發(fā)布到Kubernetes集群
[root@kubecon ~]# kubectl create -f tomcat-service.yaml
service "tomcat-service" created
查看Endpoint列表
[root@kubecon ~]# kubectl get endpoints
NAME ENDPOINTS AGE
kubernetes 172.18.231.136:6443 24m
tomcat-service 172.17.0.2:8080,172.17.0.3:8080,172.17.0.2:8005 + 1 more... 2m
查看svc列表
[root@kubecon ~]# kubectl get svc
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes 10.254.0.1 <none> 443/TCP 26m
tomcat-service 10.254.80.192 <nodes> 8080:31002/TCP,8005:30541/TCP 4m
#EndPoint=podIP+containerPort
查看Service的ClusterIP可以看到
[root@kubecon ~]# kubectl get svc tomcat-service -o yaml
apiVersion: v1
kind: Service
metadata:
creationTimestamp: 2018-01-04T10:51:35Z
name: tomcat-service
namespace: default
resourceVersion: "1562"
selfLink: /api/v1/namespaces/default/services/tomcat-service
uid: 3bf83ae4-f13d-11e7-ade2-00163e04f964
spec:
clusterIP: 10.254.80.192
ports:
- name: service-port
nodePort: 31002
port: 8080 #虛擬端口
protocol: TCP
targetPort: 8080 #Expose端口蜕便,提供TCP/IP接入
#若沒有指定targetPort則默認(rèn)與port相同
- name: shutdown-port
nodePort: 30541
port: 8005
protocol: TCP
targetPort: 8005
selector:
tier: frontend
sessionAffinity: None
type: NodePort
status:
loadBalancer: {}
注意劫恒,存在Service對應(yīng)多個端口的問題
很多服務(wù)都存在多個端口的問題,比如有些業(yè)務(wù)一個端口提供業(yè)務(wù)服務(wù)轿腺,另外一個端口提供管理服務(wù)两嘴,比如 Mycat、Codis 等常見的中間件族壳。Kubernetes Service 支持多個 Endpoint憔辫,在存在多個 Endpoint 的情況下,要求每個 Endpoint 定義一個名字來區(qū)分仿荆。下面是 Tomcat 多端口的 Service 定義樣例:
要求每個EndPoint定義一個名字區(qū)分
- name: service-port <----------------|
nodePort: 31002
port: 8080
protocol: TCP
targetPort: 8080
- name: shutdown-port <---------------|
nodePort: 30541
port: 8005
protocol: TCP
targetPort: 8005
Kubernetes服務(wù)發(fā)現(xiàn)機制
- 每個 Kubernetes 中的 Service 都有一個唯一的 Cluster IP 及唯一的名字
- 名字是由卡發(fā)著自己定義的贰您,部署時也沒必要改變
最早時 Kubernetes 采用了 Linux 環(huán)境變量的方式解決這個問題,即每個 Service 生成一些對應(yīng)的 Linux 環(huán)境變量(ENV)拢操,并在每個 Pod 的容器在啟動時锦亦,自動注入這些環(huán)境變量
#下是 tomcat-service 產(chǎn)生的環(huán)境變量條目
TOMCAT_SERVICE_SERVICE_HOST=10.102.107.188
TOMCAT_SERVICE_SERVICE_PORT_SERVICE_PORT=8080
TOMCAT_SERVICE_SERVICE_PORT_SHUTDOWN_PORT=8005
TOMCAT_SERVICE_PORT_8080_TCP_PORT=8080
可以看到,每個 Service 的 Ip 地址及端口都是標(biāo)準(zhǔn)的命名規(guī)范的令境,遵循這個命名規(guī)范杠园,就可以通過代碼訪問系統(tǒng)環(huán)境變量的方式得到所需的信息,實現(xiàn)服務(wù)調(diào)用舔庶。
外部系統(tǒng)訪問 Service 問題
區(qū)別三種IP:
差別 | Node IP | Pod IP | ClusterIP |
---|---|---|---|
含義 | 每個節(jié)點的物理網(wǎng)卡的 IP 地址 | 每個 Pod 的 IP 地址 | 一個虛擬的 IP地址 |
源自 | 物理主機網(wǎng)卡 | Docker Engine 根據(jù) docker0 網(wǎng)橋的 IP 地址段進(jìn)行分配的抛蚁,通常是一個虛擬的二層網(wǎng)絡(luò) | Kubernetes Service”偽造“ 和定義的 |
作用域 | 服務(wù)器之間 | 虛擬二層網(wǎng)絡(luò)玲昧,不同 Pod 之間通信 | 僅作用于 Kubernetes Service 這個對象 |
是否能夠ping通 | 是 | 是 | 否,沒有一個 ”實體網(wǎng)絡(luò)對象“ 來響應(yīng)篮绿。 |
- Cluster IP 只能結(jié)合 Service Port 組成一個具體的通信端口孵延,單獨的 Cluster IP 不具備 TCP/IP 通信的基礎(chǔ),并且它們屬于 Kubernetes 集群這樣一個封閉的空間亲配,集群之外的節(jié)點如果要訪問這個通信端口尘应,則需要做一些額外的工作。
- 在 Kubernetes 集群內(nèi)吼虎,Node IP 網(wǎng)犬钢、Pod IP 網(wǎng)與 Cluster IP 網(wǎng)之間的通信,采用的是 Kubernetes 自己設(shè)計的一種編程方式的特殊的路由規(guī)則思灰,與自身熟知的 IP 路由有很大的不同玷犹。
Service 的 Cluster Ip 屬于 Kubernetes 集群內(nèi)部的地址,無法在集群外部直接使用這個地址洒疚。
問題來了:存在有一部分服務(wù)是要提供給 Kubernetes 集群外部的應(yīng)用或者用戶來使用的歹颓,典型的例子就是 Web 端的服務(wù)模塊,比如上面的 tomcat-service油湖,那么用戶怎么訪問它巍扛?
采用 NodePort 。
具體做法如下乏德,以 tomcat-service 為例:
apiVersion: v1
kind: Service
metadata:
name: tomcat-service
spec:
type: NodePort
ports:
- port: 8080
nodePort: 31002
#nodePort: 31002 這個屬性表名手動指定 tomcat-service 的 NodePort 為 31002
selector:
tier: frontend
NodePort 的實現(xiàn)方式是在 Kubernetes 集群里的每個 Node 上為需要外部訪問的 Service 開啟一個對應(yīng)的 TCP 監(jiān)聽端口撤奸,外部系統(tǒng)只要用任意一個 Node 的 Ip 地址加具體的 NodePort 端口號即可訪問此服務(wù)
查看NodePort端口是否被監(jiān)聽:
[root@kubecon ~]# kubectl get svc
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes 10.254.0.1 <none> 443/TCP 2h
tomcat-service 10.254.80.192 <nodes> 8080:31002/TCP,8005:30541/TCP 2h
[root@kubecon ~]# netstat -lnput | grep 31002
tcp6 0 0 :::31002 :::* LISTEN 1608/kube-proxy
那么問題又來了,NodePort 還沒完全解決外部訪問 Service 的所有問題喊括,比如負(fù)載均衡問題:
假如集群中有 10 個 Node胧瓜,則此時最好有一個負(fù)載均衡,外部的請求只需訪問此負(fù)載均衡器的 IP 地址郑什,由負(fù)載均衡器負(fù)責(zé)轉(zhuǎn)發(fā)流量到后面某個 Node 的 NodePort 上
上圖中的 Load Balancer 組件獨立于 Kubernetes 集群之外府喳,通常是一個硬件的負(fù)載均衡器,或者是以軟件方式實現(xiàn)的蹦误,例如 HAProxy 或者 Nginx劫拢。
對于每個 Service,我們通常需要配置一個對應(yīng)的 Load Balancer 示例來轉(zhuǎn)發(fā)流量到后端的 Node 上强胰,這的確增加了工作量及出錯的概率。
Volume存儲卷
差別 | Docker Volume | Kubernetes Volume |
---|---|---|
定義在 | 容器上 | Pod之上 |
生命周期 | 與容器相關(guān) | 與 Pod 的生命周期相同妹沙,但與容器的聲明周期不相干關(guān)偶洋。當(dāng)容器中止或者啟動時,Volume 中的數(shù)據(jù)也不會丟失距糖。 |
Volume 是 Pod 中能夠被多個容器訪問的共享目錄玄窝。
差別 | Docker Volume | Kubernetes Volume |
---|---|---|
定義在 | 容器上 | Pod之上 |
生命周期 | 與容器相關(guān) | 與 Pod 的生命周期相同牵寺,但與容器的聲明周期不相干關(guān)。當(dāng)容器中止或者啟動時恩脂,Volume 中的數(shù)據(jù)也不會丟失帽氓。 |
先來個例子實戰(zhàn)下~
#先在 Pod 上聲明一個 Volume,然后在容器里引用該 Volume 并 Mount 到容器里的某個目錄上
#給之前的 Tomcat Pod 增加一個名字為 datavol 的 Volume俩块,并且 Mount 到容器的 /mydata-data 目錄上
apiVersion: v1
kind: ReplicationController
metadata:
name: frontend
spec:
replicas: 1
selector:
tier: frontend
template:
metadata:
labels:
app: app-demo
tier: frontend
spec:
containers:
- name: tomcat-demo
image: daocloud.io/library/tomcat
#add
volumeMounts:
- mountPath: /mydata-data
name: datavol
imagePullPolicy: IfNotPresent
env:
- name: GET_HOSTS_FROM
value: dns
ports:
- containerPort: 80
#add
volumes:
- name: datavol
emptyDir: {}
發(fā)布到集群中
[root@kubecon ~]# kubectl create -f tomcat-frontend-rc.yaml
replicationcontroller "frontend" created
獲取容器id查看是否掛載成功
[root@kubecon ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
frontend-c750f 1/1 Running 0 8m
[root@kubecon ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
cbe157bfaeab daocloud.io/library/tomcat "catalina.sh run" 8 minutes ago Up 8 minutes k8s_tomcat-demo.66724613_frontend-c750f_default_3491a794-f153-11e7-ade2-00163e04f964_157daa35
c94aedb5ef0e registry.access.redhat.com/rhel7/pod-infrastructure:latest "/usr/bin/pod" 8 minutes ago Up 8 minutes k8s_POD.a8590b41_frontend-c750f_default_3491a794-f153-11e7-ade2-00163e04f964_2080adb3
[root@kubecon ~]# docker inspect cbe
[
{
"Id": "cbe157bfaeab28190481a974fe6b1c1f9830584210520f664538fccaaa98ec54",
"Created": "2018-01-04T13:28:53.583903204Z",
...................................
"Mounts": [
{
"Source": "/var/lib/kubelet/pods/3491a794-f153-11e7-ade2-00163e04f964/volumes/kubernetes.io~empty-dir/datavol",
"Destination": "/mydata-data",
"Mode": "",
"RW": true,
"Propagation": "rprivate"
},
................................
#可以很明顯的看到/datavol掛載到了/mydata-data
#然后可以看到使用的是empty-dir
Kubernetes 支持多種類型的 Volume黎休,例如 GlusterFS、Ceph 等先進(jìn)的分布式文件存儲玉凯。
常見的幾種Volume類型:
EmptyDir
- 一個 EmptyDir Volume 是在 Pod 分配到 Node 時創(chuàng)建的势腮。
- 從它的名稱就可以看出,它的初始化內(nèi)容為空漫仆,并且無須指定宿主機上對應(yīng)的目錄文件
- Pod 從 Node 上移除時捎拯,emptyDir 中的數(shù)據(jù)也會被永久刪除
emptyDir 的使用場景如下:
1.臨時空間,例如用于某些應(yīng)用程序運行時所需的臨時目錄盲厌,且無須永久保留署照。
2.長時間任務(wù)的中間過程 CheckPoint 的臨時保存目錄。
3.一個容器需要從另一個容器中獲取數(shù)據(jù)的目錄(多容器共享目錄)吗浩。
例如前一個例子就使用了EmptyDir:
volumes:
- name: data
emptyDir: {}
HostPath
- hostPath 為在 Pod 上掛載宿主機上的文件或目錄
HostPath 的使用場景如下:
1.容器應(yīng)用程序生成的日志文件需要永久保存時藤树,可以使用宿主機的高速文件系統(tǒng)進(jìn)行存儲。
2.需要訪問宿主機上 Docker 引擎內(nèi)部數(shù)據(jù)結(jié)構(gòu)的容器應(yīng)用時拓萌,可以通過定義 hostPath 為宿主機 /var/lib/docker 目錄岁钓,使容器內(nèi)部應(yīng)用可以直接訪問 Docker 的文件系統(tǒng)。
Pay Attention:
1.存在訪問結(jié)果不一致的情況:
2.存在資源管理配額不納入的情況:
例子:
#定義pod文件busybox-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: busybox
labels:
name: busybox
spec:
containers:
- image: busybox
command:
- sleep
- "3600"
imagePullPolicy: IfNotPresent
name: busybox
volumeMounts:
- mountPath: /busybox-data
name: data
volumes:
- hostPath:
path: /tmp/data
name: data
docker inspect查看掛載
"Mounts": [
{
"Source": "/tmp/data",
"Destination": "/busybox-data",
"Mode": "",
"RW": true,
"Propagation": "rprivate"
},
{
"Source": "/var/lib/kubelet/pods/7eb594fd-f157-11e7-ade2-00163e04f964/etc-hosts",
"Destination": "/etc/hosts",
"Mode": "",
"RW": true,
"Propagation": "rprivate"
},
{
"Source": "/var/lib/kubelet/pods/7eb594fd-f157-11e7-ade2-00163e04f964/containers/busybox/7b91bd28",
"Destination": "/dev/termination-log",
"Mode": "",
"RW": true,
"Propagation": "rprivate"
}
],
不建議使用
gcePersistentDisk&awsElasticBlockStore
一個是Google Cloud Platform的一個是Aws ec2的
NFS
使用 NFS 網(wǎng)絡(luò)文件系統(tǒng)提供的共享存儲數(shù)據(jù)時微王,需要在系統(tǒng)中部署一個 NFS Server屡限。定義 NFS 類型的 Volume 示例如下:
Namespace命名空間
- Namespace 在很多情況下用于實現(xiàn)多租戶的資源隔離。
- Namespace 通過將集群內(nèi)部的資源對象 “分配” 到不同的 Namespace 中炕倘,形成邏輯上分組的不同項目钧大、小組或用戶組,便于不同的分組在共享使用整個集群的資源的同時還能被分別管理罩旋。
Kubernetes 集群在啟動后啊央,會創(chuàng)建一個名為 “default” 的 Namespace,通過 kubectl 可以查看到:
[root@kubecon ~]# kubectl get namespace
NAME STATUS AGE
default Active 3h
kube-system Active 3h
注意涨醋,如果不特別指明 Namespace瓜饥,則用戶創(chuàng)建的 Pod、RC浴骂、Service 都將被系統(tǒng)創(chuàng)建到這個默認(rèn)的名為 default 的 Namespace 中乓土。
Namespace 的定義很簡單。如果所示的 yaml 定義名為 development 的 Namespace。
小小實戰(zhàn)下
#development-ns.yaml
apiVersion: v1
kind: Namespace
metadata:
name: development
一旦創(chuàng)建了 Namespace趣苏,在創(chuàng)建資源對象時就可以指定這個資源對象屬于哪個 Namespace狡相。
定義一個名為 busybox 的 Pod,放入 development 這個 Namespace 里
apiVersion: v1
kind: Pod
metadata:
name: busybox
namespace: development
spec:
containers:
- image: busybox
command:
- sleep
- "3600"
name: bosybox
發(fā)布到集群中并查看狀態(tài)
[root@kubecon ~]# kubectl apply -f development-ns.yaml
namespace "development" created
[root@kubecon ~]# kubectl apply -f busybox-pod.yaml
pod "busybox" created
[root@kubecon ~]# kubectl get pod
No resources found.
#因為如果不加參數(shù)食磕,則 kubectl get 命令將僅顯示屬于 default namespace 的資源對象尽棕。
[root@kubecon ~]# kubectl get pod --namespace=development
NAME READY STATUS RESTARTS AGE
busybox 1/1 Running 0 13s
#在 kubectl 命令中加入 --namespace 參數(shù)來查看某個命名空間中的對象
Annotation
Annotation 與 Label 類似,不同的是 Label 具有嚴(yán)格的命名規(guī)則,它定義的是 Kubernetes 對象的元數(shù)據(jù)(Metadata)彬伦,并且用于 Label Selector滔悉。而 Annotation 則是用戶定義的 “附件” 信息,以便于外部工具進(jìn)行查找.
Annotation 的應(yīng)用場景:
- build 信息媚朦、release 信息氧敢、Docker 鏡像信息等,例如時間戳询张、release id 號孙乖、PR 號、鏡像 hash 值份氧、docker registry 地址等唯袄。
- 日志庫、監(jiān)控庫蜗帜、分析庫等資源庫的地址信息恋拷。
- 程序調(diào)試工具信息,例如工具名稱厅缺、版本號等蔬顾。
- 團(tuán)隊的聯(lián)系信息,例如電話號碼湘捎、負(fù)責(zé)人名稱诀豁、網(wǎng)址等。
總結(jié):Node窥妇、Pod舷胜、Replication Controller和Service等都可以看作是一種“資源對象”,幾乎所有的資源對象都可以通過Kubernetes提供的kubectl工具執(zhí)行增活翩、刪烹骨、改、查等操作并將其保存在ectd中持久化存儲材泄。 *k8s相當(dāng)于裝滿集裝箱的貨船沮焕,Pod相當(dāng)于船上一個個的集裝箱 ,docker容器就是集裝箱里擺放的一件件貨物脸爱,而Service相當(dāng)于一堆堆貼好標(biāo)簽Label要運去哪兒的集裝箱集合遇汞,Replication Controller相當(dāng)于確定集裝箱Pods應(yīng)該要有多少份,deployment是改進(jìn)版的RC簿废,它通過RS實時確定各個集裝箱Pod的上船進(jìn)度等空入,NameSpace指船上存放的地方是A區(qū)(汽車類)還是B區(qū)糧米類。
好了族檬,今天就到這了歪赢,寫了一天了,希望筆記對自己以及大家都有幫助~>-<.