關(guān)于 Kubernetes中一些基本概念和術(shù)語筆記
一、簡述
Kubernetes中的大部分概念如Node, Pod,Replication Controller, Service等都可以看作一種“資源對象”,幾乎所有的資源對象都可以通過Kubernetes提供的kubect工具(或者API編程調(diào)用)執(zhí)行增、刪、改、查等操作并將其保存在etcd中持久化存儲。從這個角度來看, Kubernetes其實是一個高度自動化的資源控制系統(tǒng),它通過`跟蹤對比etcd庫里保存的“資源期望狀態(tài)”與當(dāng)前環(huán)境中的“實際資源狀態(tài)”的差異來實現(xiàn)自動控制和自動糾錯的高級功能。
K8s中相關(guān)資源:隨版本變化
┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-pod-create]
└─$kubectl api-resources
NAME(名字) | SHORTNAMES(簡稱) | APIVERSION(版本) | NAMESPACED(命名空間隔離) | KIND(種類) |
---|---|---|---|---|
bindings | v1 | true | Binding | |
componentstatuses | cs | v1 | false | ComponentStatus |
configmaps | cm | v1 | true | ConfigMap |
endpoints | ep | v1 | true | Endpoints |
events | ev | v1 | true | Event |
limitranges | limits | v1 | true | LimitRange |
namespaces | ns | v1 | false | Namespace |
nodes | no | v1 | false | Node |
persistentvolumeclaims | pvc | v1 | true | PersistentVolumeClaim |
persistentvolumes | pv | v1 | false | PersistentVolume |
pods | po | v1 | true | Podpodtemplates |
replicationcontrollers | rc | v1 | true | ReplicationController |
resourcequotas | quota | v1 | true | ResourceQuota |
secrets | v1 | true | Secret | |
serviceaccounts | sa | v1 | true | ServiceAccount |
services | svc | v1 | true | Service |
mutatingwebhookconfigurations | admissionregistration.k8s.io/v1 | false | MutatingWebhookConfiguration | |
validatingwebhookconfigurations | admissionregistration.k8s.io/v1 | false | ValidatingWebhookConfiguration | |
customresourcedefinitions | crd,crds | apiextensions.k8s.io/v1 | false | CustomResourceDefinition |
apiservices | apiregistration.k8s.io/v1 | false | APIService | |
controllerrevisions | apps/v1 | true | ControllerRevision | |
daemonsets | ds | apps/v1 | true | DaemonSet |
deployments | deploy | apps/v1 | true | Deployment |
replicasets | rs | apps/v1 | true | ReplicaSet |
statefulsets | sts | apps/v1 | true | StatefulSet |
tokenreviews | authentication.k8s.io/v1 | false | TokenReview | |
localsubjectaccessreviews | authorization.k8s.io/v1 | true | LocalSubjectAccessReview | |
selfsubjectaccessreviews | authorization.k8s.io/v1 | false | SelfSubjectAccessReview | |
selfsubjectrulesreviews | authorization.k8s.io/v1 | false | SelfSubjectRulesReview | |
subjectaccessreviews | authorization.k8s.io/v1 | false | SubjectAccessReview | |
horizontalpodautoscalers | hpa | autoscaling/v1 | true | HorizontalPodAutoscaler |
cronjobs | cj | batch/v1 | true | CronJob |
jobs | batch/v1 | true | Jobcertificatesigningrequests | |
leases | coordination.k8s.io/v1 | true | Lease | |
bgpconfigurations | crd.projectcalico.org/v1 | false | BGPConfiguration | |
bgppeers | crd.projectcalico.org/v1 | false | BGPPeer | |
blockaffinities | crd.projectcalico.org/v1 | false | BlockAffinity | |
clusterinformations | crd.projectcalico.org/v1 | false | ClusterInformation | |
felixconfigurations | crd.projectcalico.org/v1 | false | FelixConfiguration | |
globalnetworkpolicies | crd.projectcalico.org/v1 | false | GlobalNetworkPolicy | |
globalnetworksets | crd.projectcalico.org/v1 | false | GlobalNetworkSet | |
hostendpoints | crd.projectcalico.org/v1 | false | HostEndpoint | |
ipamblocks | crd.projectcalico.org/v1 | false | IPAMBlock | |
ipamconfigs | crd.projectcalico.org/v1 | false | IPAMConfig | |
ipamhandles | crd.projectcalico.org/v1 | false | IPAMHandle | |
ippools | crd.projectcalico.org/v1 | false | IPPool | |
kubecontrollersconfigurations | crd.projectcalico.org/v1 | false | KubeControllersConfiguration | |
networkpolicies | crd.projectcalico.org/v1 | true | NetworkPolicy | |
networksets | crd.projectcalico.org/v1 | true | NetworkSet | |
endpointslices | discovery.k8s.io/v1 | true | EndpointSlice | |
events | ev | events.k8s.io/v1 | true | Event |
flowschemas | flowcontrol.apiserver.k8s.io/v1beta1 | false | FlowSchema | |
prioritylevelconfigurations | flowcontrol.apiserver.k8s.io/v1beta1 | false | PriorityLevelConfiguration | |
nodes | metrics.k8s.io/v1beta1 | false | NodeMetrics | |
pods | metrics.k8s.io/v1beta1 | true | PodMetrics | |
ingressclasses | networking.k8s.io/v1 | false | IngressClass | |
ingresses | ing | networking.k8s.io/v1 | true | Ingress |
networkpolicies | netpol | networking.k8s.io/v1 | true | NetworkPolicy |
runtimeclasses | node.k8s.io/v1 | false | RuntimeClass | |
poddisruptionbudgets | pdb | policy/v1 | true | PodDisruptionBudget |
podsecuritypolicies | psp | policy/v1beta1 | false | PodSecurityPolicy |
clusterrolebindings | rbac.authorization.k8s.io/v1 | false | ClusterRoleBinding | |
clusterroles | rbac.authorization.k8s.io/v1 | false | ClusterRole | |
rolebindings | rbac.authorization.k8s.io/v1 | true | RoleBinding | |
roles | rbac.authorization.k8s.io/v1 | true | Role | |
priorityclasses | pc | scheduling.k8s.io/v1 | false | PriorityClass |
csidrivers | storage.k8s.io/v1 | false | CSIDriver | |
csinodes | storage.k8s.io/v1 | false | CSINode | |
csistoragecapacities | storage.k8s.io/v1beta1 | true | CSIStorageCapacity | |
storageclasses | sc | storage.k8s.io/v1 | false | StorageClass |
volumeattachments | storage.k8s.io/v1 | false | VolumeAttachment |
二、Kubernetes集群的兩種管理角色: Master和Node
Master和Node |
---|
![]() |
1、Master角色
Kubernetes里的Master指的是 集群控制節(jié)點,每個Kubernetes集群里需要有一個Master節(jié)點來負(fù)責(zé)整個集群的管理和控制,基本上Kubernetes的所有控制命令都發(fā)給它,它來負(fù)責(zé)具體的執(zhí)行過程,我們后面執(zhí)行的所有命令基本都是在Master節(jié)點上運(yùn)行的。
Master節(jié)點通常會占據(jù)一個獨立的服務(wù)器(高可用部署建議用3臺服務(wù)器),其主要原因是它太重要了,是整個集群的“首腦”,如果宕機(jī)或者不可用,那么對集群內(nèi)容器應(yīng)用的管理都將失效。Master節(jié)點上運(yùn)行著以下一組關(guān)鍵進(jìn)程。
Master節(jié)點上關(guān)鍵進(jìn)程 | -- |
---|---|
Kubernetes API Server (kube-apiserver) | 提供了HTTP Rest接口的關(guān)鍵服務(wù)進(jìn)程,是Kubernetes里所有資源的增、刪、改、查等操作的唯一入口,也是集群控制的入口進(jìn)程。 |
Kubernetes Controller Manager (kube-controller-manager) | Kubernetes里所有資源對象的自動化控制中心,可以理解為資源對象的“大總管”。 |
Kubernetes Scheduler (kube-scheduler) | 負(fù)責(zé)資源調(diào)度(Pod調(diào)度)的進(jìn)程,相當(dāng)于公交公司的“調(diào)度室”。 |
etcd | 在Master節(jié)點上還需要啟動一個etcd服務(wù),因為Kubernetes里的所有資源對象的數(shù)據(jù)全部是保存在etcd中的。 |
除了Master, Kubernetes集群中的其他機(jī)器被稱為Node節(jié)點
2、Node角色
在較早的版本中也被稱為Miniono與Master一樣, Node節(jié)點可以是一臺物理主機(jī),也可以是一臺虛擬機(jī)。 Node節(jié)點才是Kubermetes集群中的工作負(fù)載節(jié)點,每個Node都會被Master分配一些工作負(fù)載(Docker容器),當(dāng)某個Node宕機(jī)時,其上的工作負(fù)載會被Master自動轉(zhuǎn)移到其他節(jié)點上去。
每個Node節(jié)點上都運(yùn)行著以下一組關(guān)鍵進(jìn)程。
每個Node節(jié)點上都運(yùn)行關(guān)鍵進(jìn)程 | -- |
---|---|
kubelet | 負(fù)責(zé)Pod對應(yīng)的容器的創(chuàng)建、啟停等任務(wù),同時與Master節(jié)點密切協(xié)作,實現(xiàn)集群管理的基本功能。 |
kube-proxy | 實現(xiàn)Kubernetes Service的通信與負(fù)載均衡機(jī)制的重要組件。) |
Docker Engine | (docker): Docker引擎,負(fù)責(zé)本機(jī)的容器創(chuàng)建和管理工作。 |
Node節(jié)點可以在運(yùn)行期間動態(tài)增加到Kubernetes集群中,前提是這個節(jié)點上已經(jīng)正確安裝、配置和啟動了上述關(guān)鍵進(jìn)程,在默認(rèn)情況下kubelet會向Master注冊自己,這也是Kubernetes推薦的Node管理方式。
一旦Node被納入集群管理范圍, kubelet進(jìn)程就會定時向Master節(jié)點匯報自身的情報,例如操作系統(tǒng)、Docker版本、機(jī)器的CPU和內(nèi)存情況,以及當(dāng)前有哪些Pod在運(yùn)行等,這樣Master可以獲知每個Node的資源使用情況,并實現(xiàn)高效均衡的資源調(diào)度策略。而某個Node超過指定時間不上報信息時,會被Master判定為“失聯(lián)", Node的狀態(tài)被標(biāo)記為不可用(Not Ready),隨后Master會觸發(fā)“工作負(fù)載大轉(zhuǎn)移”的自動流程。
查看集群中的Node節(jié)點和節(jié)點的詳細(xì)信息
┌──[root@vms81.liruilongs.github.io]-[~]
└─$kubectl get nodes
NAME STATUS ROLES AGE VERSION
vms81.liruilongs.github.io Ready control-plane,master 47d v1.22.2
vms82.liruilongs.github.io Ready worker1 47d v1.22.2
vms83.liruilongs.github.io NotReady worker2 47d v1.22.2
┌──[root@vms81.liruilongs.github.io]-[~]
└─$kubectl describe node vms82.liruilongs.github.io # Node基本信息:名稱、標(biāo)簽、創(chuàng)建時間等。 Name: vms82.liruilongs.github.io
Roles: worker1
Labels: beta.kubernetes.io/arch=amd64
beta.kubernetes.io/os=linux
disktype=node1
kubernetes.io/arch=amd64
kubernetes.io/hostname=vms82.liruilongs.github.io
kubernetes.io/os=linux
node-role.kubernetes.io/worker1=
Annotations: dest: 這是一個工作節(jié)點
kubeadm.alpha.kubernetes.io/cri-socket: /var/run/dockershim.sock
node.alpha.kubernetes.io/ttl: 0
projectcalico.org/IPv4Address: 192.168.26.82/24
projectcalico.org/IPv4IPIPTunnelAddr: 10.244.171.128
volumes.kubernetes.io/controller-managed-attach-detach: true CreationTimestamp: Thu, 07 Oct 2021 01:15:45 +0800
Taints: <none>
Unschedulable: false Lease:
HolderIdentity: vms82.liruilongs.github.io
AcquireTime: <unset>
RenewTime: Tue, 23 Nov 2021 23:08:16 +0800 # Node當(dāng)前的運(yùn)行狀態(tài), Node啟動以后會做一系列的自檢工作: # 比如磁盤是否滿了,如果滿了就標(biāo)注OutODisk=True # 否則繼續(xù)檢查內(nèi)存是否不足(如果內(nèi)存不足,就標(biāo)注MemoryPressure=True) # 最后一切正常,就設(shè)置為Ready狀態(tài)(Ready=True) # 該狀態(tài)表示Node處于健康狀態(tài), Master將可以在其上調(diào)度新的任務(wù)了(如啟動Pod) Conditions:
Type Status LastHeartbeatTime LastTransitionTime Reason
Message
---- ------ ----------------- ------------------ ------
-------
NetworkUnavailable False Tue, 23 Nov 2021 23:02:52 +0800 Tue, 23 Nov 2021 23:02:52 +0800 CalicoIsUp
Calico is running on this node
MemoryPressure False Tue, 23 Nov 2021 23:05:32 +0800 Tue, 23 Nov 2021 22:45:03 +0800 KubeletHasSufficientMemory kubelet has sufficient memory available
DiskPressure False Tue, 23 Nov 2021 23:05:32 +0800 Tue, 23 Nov 2021 22:45:03 +0800 KubeletHasNoDiskPressure kubelet has no disk pressure
PIDPressure False Tue, 23 Nov 2021 23:05:32 +0800 Tue, 23 Nov 2021 22:45:03 +0800 KubeletHasSufficientPID kubelet has sufficient PID available
Ready True Tue, 23 Nov 2021 23:05:32 +0800 Tue, 23 Nov 2021 22:45:03 +0800 KubeletReady
kubelet is posting ready status # Node的主機(jī)地址與主機(jī)名。 Addresses:
InternalIP: 192.168.26.82
Hostname: vms82.liruilongs.github.io # Node上的資源總量:描述Node可用的系統(tǒng)資源,包括CPU、內(nèi)存數(shù)量、最大可調(diào)度Pod數(shù)量等,注意到目前Kubernetes已經(jīng)實驗性地支持GPU資源分配了(alpha.kubernetes.io/nvidia-gpu=0) Capacity:
cpu: 2
ephemeral-storage: 153525Mi
hugepages-1Gi: 0
hugepages-2Mi: 0
memory: 4030172Ki
pods: 110 # Node可分配資源量:描述Node當(dāng)前可用于分配的資源量。 Allocatable:
cpu: 2
ephemeral-storage: 144884367121
hugepages-1Gi: 0
hugepages-2Mi: 0
memory: 3927772Ki
pods: 110 # 主機(jī)系統(tǒng)信息:包括主機(jī)的唯一標(biāo)識UUID, Linux kernel版本號、操作系統(tǒng)類型與版本、Kubernetes版本號、kubelet與kube-proxy的版本號等。 System Info:
Machine ID: 1ee67b1c4230405a851cf0107d6e89f5
System UUID: C0EA4D56-ED9A-39CF-6942-5B66704F6E6F
Boot ID: b0e42864-9778-4ded-af4c-a88a64f988db
Kernel Version: 3.10.0-693.el7.x86_64
OS Image: CentOS Linux 7 (Core)
Operating System: linux
Architecture: amd64
Container Runtime Version: docker://20.10.9
Kubelet Version: v1.22.2
Kube-Proxy Version: v1.22.2
PodCIDR: 10.244.1.0/24
PodCIDRs: 10.244.1.0/24 # 當(dāng)前正在運(yùn)行的Pod列表概要信息 Non-terminated Pods: (3 in total)
Namespace Name CPU Requests CPU Limits Memory Requests Memory Limits Age
--------- ---- ------------ ---------- --------------- ------------- ---
kube-system calico-node-ntm7v 250m (12%) 0 (0%) 0 (0%) 0 (0%) 47d
kube-system kube-proxy-nzm24 0 (0%) 0 (0%) 0 (0%) 0 (0%) 35d
kube-system metrics-server-bcfb98c76-wxv5l 0 (0%) 0 (0%) 0 (0%) 0 (0%) 27m # 已分配的資源使用概要信息,例如資源申請的最低、最大允許使用量占系統(tǒng)總量的百分比。 Allocated resources:
(Total limits may be over 100 percent, i.e., overcommitted.)
Resource Requests Limits
-------- -------- ------
cpu 250m (12%) 0 (0%)
memory 0 (0%) 0 (0%)
ephemeral-storage 0 (0%) 0 (0%)
hugepages-1Gi 0 (0%) 0 (0%)
hugepages-2Mi 0 (0%) 0 (0%) # Node相關(guān)的Event信息。 Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal NodeHasSufficientMemory 23m (x3 over 3d4h) kubelet Node vms82.liruilongs.github.io status is now: NodeHasSufficientMemory
Normal NodeHasNoDiskPressure 23m (x3 over 3d4h) kubelet Node vms82.liruilongs.github.io status is now: NodeHasNoDiskPressure
Normal NodeHasSufficientPID 23m (x3 over 3d4h) kubelet Node vms82.liruilongs.github.io status is now: NodeHasSufficientPID
Normal NodeReady 23m (x2 over 3d4h) kubelet Node vms82.liruilongs.github.io status is now: NodeReady
┌──[root@vms81.liruilongs.github.io]-[~]
└─$
總結(jié)一下,我們要操作k8s,在管理節(jié)點那我們怎么操作,我們通過kube-apiserver來接受用戶的請求,通過kubu-scheduler來負(fù)責(zé)資源的調(diào)度,是使用work1計算節(jié)點來處理還是使用work2計算節(jié)點來處理,然后在每個節(jié)點上要運(yùn)行一個代理服務(wù)kubelet,用來控制每個節(jié)點的操作,但是每個節(jié)點的狀態(tài),是否健康我們不知道,這里我們需要kube-controller-manager
3、 Pod資源對象
Pod是Kubernetes的最重要也最基本的概念,
每個Pod都有一個特殊的被稱為“根容器”的Pause容器。Pause容器對應(yīng)的鏡像屬于Kubernetes平臺的一部分,除了Pause容器,每個Pod還包含一個或多個緊密相關(guān)的用戶業(yè)務(wù)容器。
Pause容器
為什么Kubernetes會設(shè)計出一個全新的Pod的概念并且Pod有這樣特殊的組成結(jié)構(gòu)? |
---|
原因之一:在一組容器作為一個單元的情況下,我們難以對“整體”簡單地進(jìn)行判斷及有效地進(jìn)行行動。引入業(yè)務(wù)無關(guān)并且不易死亡的Pause容器作為Pod的根容器,以它的狀態(tài)代表整個容器組的狀態(tài),就簡單、巧妙地解決了這個難題。 |
原因之二: Pod里的多個業(yè)務(wù)容器共享Pause容器的IP,共享Pause容器掛接的Volume,這樣既簡化了密切關(guān)聯(lián)的業(yè)務(wù)容器之間的通信問題,也很好地解決了它們之間的文件共享問題。 |
Pod IP
Kubernetes 為每個Pod都分配了唯一的IP地址,稱之為Pod IP,一個Pod里的多個容器共享Pod IP地址。 Kuberetes要求底層網(wǎng)絡(luò)支持集群內(nèi)任意兩個Pod之間的TCP/P直接通信,這通常采用虛擬二層網(wǎng)絡(luò)技術(shù)來實現(xiàn)(鏈路層網(wǎng)橋),
在Kubernetes里,一個Pod里的容器與另外主機(jī)上的Pod容器能夠直接通信。
普通的Pod及靜態(tài)Pod (Static Pod)
Pod其實有兩種類型:普通的Pod及靜態(tài)Pod (Static Pod),如果使用kubeadm的方式部署,靜態(tài)pod在node節(jié)點和master節(jié)點創(chuàng)建略有不同
Pod兩種類型 | 描述 |
---|---|
靜態(tài)Pod (Static Pod) | 并 不存放在Kubernetes的etcd存儲 里,而是存放在某個具體的Node上的一個具體文件中,并且只在此Node上啟動運(yùn)行。 |
普通的Pod | 一旦被創(chuàng)建,就會被放入到etcd中存儲,隨后會被Kubernetes Masten調(diào)度到某個具體的Node上并進(jìn)行綁定(Binding),隨后該P(yáng)od被對應(yīng)的Node上的kubelet進(jìn)程實例化成一組相關(guān)的Docker容器并啟動起來。 |
正常情況下,pod是在master上統(tǒng)一管理的,所謂靜態(tài)pod就是,即不是由master上創(chuàng)建調(diào)度的,是屬于node自身特的pod,在node上只要啟動kubelet之后,就會自動的創(chuàng)建的pod。這里理解的話,結(jié)合java靜態(tài)熟悉,靜態(tài)方法理解,即的node節(jié)點初始化的時候需要創(chuàng)建的一些pod
比如 kubeadm的安裝k8s的話,所以的服務(wù)都是通過容器的方式運(yùn)行的。相比較二進(jìn)制的方式方便很多,這里的話,那么涉及到master節(jié)點的相關(guān)組件在沒有k8s環(huán)境時是如何運(yùn)行,構(gòu)建master節(jié)點的,這里就涉及到靜態(tài)pod的問題。
在默認(rèn)情況下,當(dāng)Pod里的某個容器停止時,Kubernetes會自動檢測到這個問題并且重新啟動這個Pod (重啟Pod里的所有容器),如果Pod所在的Node宕機(jī),則會將這個Node上的所有Pod重新調(diào)度到其他節(jié)點上.
Kubernetes里的所有資源對象都可以采用yaml或者JSON格式的文件來定義或描述,下面是我們在之前Hello World例子里用到的myweb這個Pod的資源定義文件:
apiVersion: v1 kind: Pod # Pod 定義 metadata: name: myweb # Pod 名字 lables: name: myweb spec: # 包含的容器組 containers: - name: myweb image: kubeguide/tomcat-app:v1 ports: - containerPort: 8080 env: - name: MYSQL_SERVICE_HOST value: 'mysql' - name: MYSQL_SERVICE_PORT value: '3306'
Kubernetes的Event概念, Event是一個事件的記錄,記錄了事件的最早產(chǎn)生時間、最后重現(xiàn)時間、重復(fù)次數(shù)、發(fā)起者、類型,以及導(dǎo)致此事件的原因等眾多信息。Event通常會關(guān)聯(lián)到某個具體的資源對象上,是排查故障的重要參考信息,
Pod同樣有Event記錄,當(dāng)我們發(fā)現(xiàn)某個Pod遲遲無法創(chuàng)建時,可以用kubectl describe pod xxxx來查看它的描述信息,用來定位問題的原因
在Kubernetes里,一個計算資源進(jìn)行配額限定需要設(shè)定以下兩個參數(shù)。
計算資源進(jìn)行配額限定 |
---|
Requests:該資源的最小申請量,系統(tǒng)必須滿足要求。 |
Limits:該資源最大允許使用的量,不能被突破,當(dāng)容器試圖使用超過這個量的資源時,可能會被Kubernetes Kill并重啟。 |
通常我們會把Request設(shè)置為一個比較小的數(shù)值,符合容器平時的工作負(fù)載情況下的資源需求,而把Limit設(shè)置為峰值負(fù)載情況下資源占用的最大量。
比如下面這段定義,表明MysQL容器申請最少0.25個CPU及64MiB內(nèi)存,在運(yùn)行過程中MySQL容器所能使用的資源配額為0.5個CPU及128MiB內(nèi)存:
.... resources: requests: memory: "64Mi" cpu: "250m" limits: memory: "128Mi" cpu: "500m" ...
Pod Pod 周邊對象的示意圖
4 、Lable 標(biāo)簽
Label是Kubernetes系統(tǒng)中另外一個核心概念。一個Label是一個key-value的鍵值對。其中key與value由用戶自己指定。
Label可以附加到各種資源對象上,例如Node、Pod、Service、RC等,一個資源對象可以定義任意數(shù)量的Label,同一個Label也可以被添加到任意數(shù)量的資源對象上去, Label通常在資源對象定義時確定,也可以在對象創(chuàng)建后動態(tài)添加,或者刪除。
可以通過給指定的資源對象捆綁一個或多個不同的Label來實現(xiàn)多維度的資源分組管理功能,以便于靈活、方便地進(jìn)行資源分配、調(diào)度、配置、部署等管理工作。
例如:部署不同版本的應(yīng)用到不同的環(huán)境中;或者監(jiān)控和分析應(yīng)用(日志記錄、監(jiān)控、告警)等。一些常用的Label示例如下。
版本標(biāo)簽: "release" : "stable", "release":"canary"....
環(huán)境標(biāo)簽: "environment":"dev", "environment":"ga","environment":"production"·
架構(gòu)標(biāo)簽: "ier":"frontend," "tier":"backend", "tier":"midleware" 分區(qū)標(biāo)簽: "artition":"customerA", "partition": "customerB".
質(zhì)量管控標(biāo)簽: "track": "daily","track":"weeky"
可以通過多個Label Selector表達(dá)式的組合實現(xiàn)復(fù)雜的條件選擇,多個表達(dá)式之間用“,”進(jìn)行分隔即可,幾個條件之間是“AND"的關(guān)系,即同時滿足多個條件,比如下面的例子:
name=標(biāo)簽名 env != 標(biāo)簽名 name in (標(biāo)簽1,標(biāo)簽2) name not in(標(biāo)簽1) name in (redis-master, redis-slave):匹配所有具有標(biāo)簽`name=redis-master`或者`name=redis-slave`的資源對象。 name not in (phn-frontend):匹配所有不具有標(biāo)簽name=php-frontend的資源對象。 name=redis-slave, env!=production name notin (php-frontend),env!=production
apiVersion: v1 kind: Pod metadata: name: myweb lables: app: myweb # 管理對象RC和Service 在 spec 中定義Selector 與 Pod 進(jìn)行關(guān)聯(lián)。 apiVersion: v1 kind: ReplicationController metadata: name: myweb spec: replicas: 1 selector: app: myweb template: ...略... apiVersion" v1 kind: Service metadata: name: myweb spec: selector: app: myweb ports: port: 8080
新出現(xiàn)的管理對象如Deployment, ReplicaSet, DaemonSet和Job則可以在Selector中使用基于集合的篩選條件定義,例如:
selector: matchLabels: app: myweb matchExpressions: - {key: tire,operator: In,values: [frontend]} - {key: environment, operator: NotIn, values: [dev]}
matchLabels用于定義一組Label,與直接寫在Selector中作用相同; matchExpressions用于定義一組基于集合的篩選條件,可用的條件運(yùn)算符包括: In, NotIn, Exists和DoesNotExist.
如果同時設(shè)置了matchLabels和matchExpressions,則兩組條件為"AND"關(guān)系,即所有條件需要同時滿足才能完成Selector的篩選。
Label Selector在Kubernetes中的重要使用場景有以下幾處:
kube-controller進(jìn)程通過資源對象RC上定義的Label Selector來篩選要監(jiān)控的Pod副本的數(shù)量,從而實現(xiàn)Pod副本的數(shù)量始終符合預(yù)期設(shè)定的全自動控制流程
kube-proxy進(jìn)程通過Service的Label Selector來選擇對應(yīng)的Pod, 自動建立起每個Service到對應(yīng)Pod的請求轉(zhuǎn)發(fā)路由表,從而實現(xiàn)Service的智能負(fù)載均衡機(jī)制
通過對某些Node定義特定的Label,并且在Pod定義文件中使用NodeSelector這種標(biāo)簽調(diào)度策略, kube-scheduler進(jìn)程可以實現(xiàn)Pod “定向調(diào)度”的特性。
apiVersion: v1 kind: Pod metadata: creationTimestamp: null labels: run: podnodea name: podnodea spec: containers: - image: nginx imagePullPolicy: IfNotPresent name: podnodea resources: {} affinity: nodeAffinity: #主機(jī)親和性 requiredDuringSchedulingIgnoredDuringExecution: #硬策略 nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/hostname operator: In values: - vms85.liruilongs.github.io - vms84.liruilongs.github.io dnsPolicy: ClusterFirst restartPolicy: Always status: {}
5、 Replication Controller
RC是Kubernetes系統(tǒng)中的核心概念之一,簡單來說,它其實是定義了一個期望的場景,即聲明某種Pod的副本數(shù)量在任意時刻都符合某個預(yù)期值,所以RC的定義包括如下幾個部分。
RC的定義 |
---|
Pod 期待的副本數(shù)(replicas) |
用于篩選目標(biāo) Pod 的Label Selector |
當(dāng) Pod 的副本數(shù)量小于預(yù)期數(shù)量時,用于創(chuàng)建新Pod的Pod模板(template)。 |
下面是一個完整的RC定義的例子,即確保擁有tier-frontend標(biāo)簽的這個Pod (運(yùn)行Tomcat容器)在整個Kubernetes集群中始終只有一個副本:
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: tomcat imagePullPolicy: IfNotPresent env: - name: GET_HOSTS_FROM value: dns ports: - containerPort: 80
當(dāng)我們定義了一個RC并提交到Kubernetes集群中以后, Master節(jié)點上的Controller Manager組件就得到通知,定期巡檢系統(tǒng)中當(dāng)前存活的目標(biāo)Pod,并確保目標(biāo)Pod實例的數(shù)量剛好等于此RC的期望值,如果有過多的Pod副本在運(yùn)行,系統(tǒng)就會停掉一些Pod,否則系統(tǒng)就會再自動創(chuàng)建一些Pod
通過RC, Kubernetes實現(xiàn)了用戶應(yīng)用集群的高可用性,并且大大減少了系統(tǒng)管理員在傳統(tǒng)IT環(huán)境中需要完成的許多手工運(yùn)維工作(如主機(jī)監(jiān)控腳本、應(yīng)用監(jiān)控腳本、故障恢復(fù)腳本等)
下面我們以3個Node節(jié)點的集群為例,說明Kubernetes如何通過RC來實現(xiàn)Pod副本數(shù)量自動控制的機(jī)制。假如我們的RC里定義redis-slave這個Pod需要保持3個副本,系統(tǒng)將可能在其中的兩個Node上創(chuàng)建Pod,圖1.9描述了在兩個Node上創(chuàng)建redis-slave Pod的情形。
在運(yùn)行時,我們可以通過 修改RC的副本數(shù)量,來實現(xiàn)Pod的動態(tài)縮放(Scaling)功能,這可以通過執(zhí)行kubectl scale命令來一鍵完成:
kubectl scale rc redsi-slave --replicas=3
需要注意的是,刪除RC并不會影響通過該RC已創(chuàng)建好的Pod,為了刪除所有Pod,可以設(shè)置replicas的值為0,然后更新該RC。另外, kubectl提供了stop和delete命令來一次性刪除RC和RC控制的全部Pod。
應(yīng)用升級時,通常會通過Build一個新的Docker鏡像,并用新的鏡像版本來替代舊的版本的方式達(dá)到目的。在系統(tǒng)升級的過程中,我們希望是平滑的方式,比如當(dāng)前系統(tǒng)中10個對應(yīng)的舊版本的Pod,最佳的方式是舊版本的Pod每次停止一個,同時創(chuàng)建一個新版本的Pod,在整個升級過程中,此消彼長,而運(yùn)行中的Pod數(shù)量始終是10個,通過RC的機(jī)制, Kubernetes很容易就實現(xiàn)了這種高級實用的特性,被稱為“滾動升級” (Rolling Update)
6、 Deployment
Deployment是Kubernetes v1.2引入的新概念,引入的目的是為了更好地解決Pod的編排問題。
Deployment相對于RC的一個最大升級是我們可以隨時知道當(dāng)前Pod “部署”的進(jìn)度。實際上由于一個Pod的創(chuàng)建、調(diào)度、綁定節(jié)點及在目標(biāo)Node上啟動對應(yīng)的容器這一完整過程需要一定的時間,所以我們期待系統(tǒng)啟動N個Pod副本的目標(biāo)狀態(tài),實際上是一個連續(xù)變化的“部署過程"導(dǎo)致的最終狀態(tài)。
Deployment的典型使用場景有以下幾個。
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版本。 |
暫停Deployment以便于一次性修改多個PodTemplateSpec的配置項,之后再恢復(fù)Deployment,進(jìn)行新的發(fā)布。 |
擴(kuò)展Deployment以應(yīng)對高負(fù)載。 |
查看Deployment的狀態(tài),以此作為發(fā)布是否成功的指標(biāo)。 |
清理不再需要的舊版本ReplicaSets。 |
Deployment的定義與Replica Set的定義很類似,除了API聲明與Kind類型等有所區(qū)別:
apiversion: extensions/vlbetal apiversion: v1 kind: Deployment kind: ReplicaSet metadata: metadata: name: nginx-deployment name: nginx-repset
創(chuàng)建一個 tomcat-deployment.yaml Deployment 描述文件:
apiVersion: extensions/v1betal kind: Deployment metadata: name: frontend spec: replicas: 1 selector: matchLabels: tier: frontend matchExpressions: - {key: tier, operator: In,value: [frontend]} template: metadata: labels: app: app-demo tier: frontend spec: containers: - name: tomcat-demo images: tomcat imagePullPolicy: IfNotPresent ports: - containerPort: 8080
運(yùn)行如下命令創(chuàng)建 Deployment:
kubectl create -f tomcat-deploment.yaml
對上述輸出中涉及的數(shù)量解釋如下。
數(shù)量 | 解釋 |
---|---|
DESIRED | Pod副本數(shù)量的期望值,即Deployment里定義的Replica. |
CURRENT | 當(dāng)前Replica的值,實際上是Deployment所創(chuàng)建的Replica Set里的Replica值,這個值不斷增加,直到達(dá)到DESIRED為止,表明整個部署過程完成。 |
UP-TO-DATE | 最新版本的Pod的副本數(shù)量,用于指示在滾動升級的過程中,有多少個Pod副本已經(jīng)成功升級。 |
AVAILABLE | 當(dāng)前集群中可用的Pod副本數(shù)量,即集群中當(dāng)前存活的Pod數(shù)量。 |
運(yùn)行下述命令查看對應(yīng)的Replica Set,我們看到它的命名與Deployment的名字有關(guān)系:
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$kubectl get rs -A
NAMESPACE NAME DESIRED CURRENT READY AGE
kube-system calico-kube-controllers-78d6f96c7b 1 1 1 47d
kube-system coredns-545d6fc579 0 0 0 47d
kube-system coredns-7f6cbbb7b8 2 2 2 36d
kube-system kuboard-78dccb7d9f 1 1 1 11d
kube-system metrics-server-bcfb98c76
7、 Horizontal Pod Autoscaler
HPA與之前的RC、 Deployment一樣,也屬于一種Kubernetes資源對象。通過 追蹤分析RC控制的所有目標(biāo)Pod的負(fù)載變化情況,來確定是否需要針對性地調(diào)整目標(biāo)Pod的副本數(shù),這是HPA的實現(xiàn)原理 。當(dāng)前, HPA可以有以下兩種方式作為Pod負(fù)載的度量指標(biāo)。
Horizontal Pod Autoscaler |
---|
CPUUtilizationPercentage. |
應(yīng)用程序自定義的度量指標(biāo),比如服務(wù)在每秒內(nèi)的相應(yīng)的請求數(shù)(TPS或QPS) |
apiversion: autoscaling/v1 kind: HorizontalPodAutoscaler metadata: name: php-apache namespace: default spec maxReplicas: 10 minReplicas: 1 scaleTargetRef: kind: Deployment name: php-apache targetcpuutilizationPercentage: 90
CPUUtilizationPercentage是一個算術(shù)平均值,即目標(biāo)Pod所有副本自身的CPU利用率的平均值。一個Pod自身的CPU利用率是該P(yáng)od當(dāng)前CPU的使用量除以它的Pod Request的值,比,如我們定義一個Pod的Pod Request為0.4,而當(dāng)前Pod的CPU使用量為0.2,則它的CPU使用率為50%
根據(jù)上面的定義,我們可以知道這個HPA控制的目標(biāo)對象為一個名叫php-apache Deployment里的Pod副本,當(dāng)這些Pod副本的CPUUtilizationPercentage的值超過90%時會觸發(fā)自動動態(tài)擴(kuò)容行為,擴(kuò)容或縮容時必須滿足的一個約束條件是Pod的副本數(shù)要介于1與10之間。
除了可以通過直接定義yaml文件并且調(diào)用kubectrl create的命令來創(chuàng)建一個HPA資源對象的方式,我們還能通過下面的簡單命令行直接創(chuàng)建等價的HPA對象:
kubectl autoscale deployment php-apache --cpu-percent=90--min-1 --max=10
8、 StatefulSet
在Kubernetes系統(tǒng)中, Pod的管理對象RC, Deployment, DaemonSet和Job都是面向無狀態(tài)的服務(wù)。 但現(xiàn)實中有很多服務(wù)是有狀態(tài)的,特別是一些復(fù)雜的中間件集群,例如MysQL集·群、MongoDB集群、ZooKeeper集群等,這些應(yīng)用集群有以下一些共同點:
共同點 | |
---|---|
每個節(jié)點都有固定的身份ID,通過這個ID,集群中的成員可以相互發(fā)現(xiàn)并且通信。 | |
集群的規(guī)模是比較固定的,集群規(guī)模不能隨意變動。 | |
集群里的每個節(jié)點都是有狀態(tài)的,通常會持久化數(shù)據(jù)到永久存儲中。 | |
如果磁盤損壞,則集群里的某個節(jié)點無法正常運(yùn)行,集群功能受損 | 。 |
如果用RC/Deployment控制Pod副本數(shù)的方式來實現(xiàn)上述有狀態(tài)的集群,則我們會發(fā)現(xiàn)第1點是無法滿足的,因為Pod的名字是隨機(jī)產(chǎn)生的, Pod的IP地址也是在運(yùn)行期才確定且可能有變動的,我們事先無法為每個Pod確定唯一不變的ID,
為了能夠在其他節(jié)點上恢復(fù)某個失敗的節(jié)點,這種集群中的Pod需要掛接某種共享存儲,為了解決這個問題, Kubernetes從v1.4版本開始引入了PetSet這個新的資源對象,并且在v1.5版本時更名為StatefulSet, StatefulSet從本質(zhì)上來說,可以看作DeploymentRC的一個特殊變種,它有如下一些特性。)
特性 |
---|
StatefulSet里的每個Pod都有穩(wěn)定、唯一的網(wǎng)絡(luò)標(biāo)識,可以用來發(fā)現(xiàn)集群內(nèi)的其他成員。假設(shè)StatefulSet的名字叫kafka,那么第1個Pod 叫 kafka-0,第2個叫kafk-1,以此類推。) |
StatefulSet控制的Pod副本的啟停順序是受控的,操作第n個Pod時,前n-1個Pod已經(jīng)是運(yùn)行且準(zhǔn)備好的狀態(tài)) |
StatefulSet里的Pod采用穩(wěn)定的持久化存儲卷,通過PV/PVC來實現(xiàn),刪除Pod時默認(rèn)不會刪除與StatefulSet相關(guān)的存儲卷(為了保證數(shù)據(jù)的安全)。 |
statefulSet除了要與PV卷捆綁使用以存儲Pod的狀態(tài)數(shù)據(jù),還要與Headless Service配合使用,即在每個StatefulSet的定義中要聲明它屬于哪個Headless Service. Headless Service與普通Service的關(guān)鍵區(qū)別在于,它沒有Cluster IP,如果解析Headless Service的DNS域名,則返回的是該Service對應(yīng)的全部Pod的Endpoint列表。StatefulSet在Headless Service的基礎(chǔ)上又為StatefulSet控制的每個Pod實例創(chuàng)建了一個DNS域名,這個域名的格式為:
$(podname).$(headless service name)
9、 Service (服務(wù))
Service也是Kubernetes里的最核心的資源對象之一, Kubernetes里的每個Service其實就是我們經(jīng)常提起的微服務(wù)架構(gòu)中的一個“微服務(wù)”,之前我們所說的Pod, RC等資源對象其實都是為這節(jié)所說的“服務(wù)”-Kubernetes Service作“嫁衣”的。Pod,RC與Service的邏輯關(guān)系。
Kubernetes的Service定義了一個服務(wù)的訪問入口地址,前端的應(yīng)用(Pod)通過這個入口地址訪問其背后的一組由Pod副本組成的集群實例, Service與其后端Pod副本集群之間則是通過Label Selector來實現(xiàn)“無縫對接”的。而RC的作用實際上是保證Service的服務(wù)能力和服務(wù)質(zhì)量始終處干預(yù)期的標(biāo)準(zhǔn)。
每個Pod都會被分配一個單獨的IP地址,而且每個Pod都提供了一個獨立的Endpoint(Pod IP+ContainerPort)以被客戶端訪問,現(xiàn)在多個Pod副本組成了一個集群來提供服務(wù).客戶端如何來訪問它們呢?一般的做法是部署一個負(fù)載均衡器(軟件或硬件),
Kubernetes中運(yùn)行在每個Node上的kube-proxy進(jìn)程其實就是一個智能的軟件負(fù)載均衡器,它負(fù)責(zé)把對Service的請求轉(zhuǎn)發(fā)到后端的某個Pod實例上,并在內(nèi)部實現(xiàn)服務(wù)的負(fù)載均衡與會話保持機(jī)制。
Kubernetes發(fā)明了一種很巧妙又影響深遠(yuǎn)的設(shè)計:
Service不是共用一個負(fù)載均衡器的IP地址,而是每個Service分配了一個全局唯一的虛擬IP地址,這個虛擬IP被稱為Cluster IP,這樣一來,每個服務(wù)就變成了具備唯一IP地址的“通信節(jié)點”,服務(wù)調(diào)用就變成了最基礎(chǔ)的TCP網(wǎng)絡(luò)通信問題。
我們知道, Pod的Endpoint地址會隨著Pod的銷毀和重新創(chuàng)建而發(fā)生改變,因為新Pod的IP地址與之前舊Pod的不同。而 Service一旦被創(chuàng)建, Kubernetes就會自動為它分配一個可用的Cluster IP,而且在Service的整個生命周期內(nèi),它的Cluster IP不會發(fā)生改變。于是,服務(wù)發(fā)現(xiàn)這個棘手的問題在Kubernetes的架構(gòu)里也得以輕松解決:只要用Service的Name與Service的Cluster IP地址做一個DNS域名映射即可完美解決問題。
┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-pod-create]
└─$kubectl get svc myweb -o yaml
apiVersion: v1
kind: Service
metadata:
creationTimestamp: "2021-10-16T14:25:08Z" name: myweb
namespace: liruilong-pod-create
resourceVersion: "339816" uid: 695aa461-166c-4937-89ed-7b16ac49c96b
spec:
clusterIP: 10.109.233.35
clusterIPs:
- 10.109.233.35
externalTrafficPolicy: Cluster
ipFamilies:
- IPv4
ipFamilyPolicy: SingleStack
ports:
- nodePort: 30001
port: 8080
protocol: TCP
targetPort: 8080
selector:
app: myweb
sessionAffinity: None type: NodePort
status:
loadBalancer: {}
Kubernetes Service支持多個Endpoint(端口),在存在多個Endpoint的情況下,要求每個Endpoint定義一個名字來區(qū)分。下面是Tomcat多端口的Service定義樣例:
spec: ports: - port: 8080 name: service-port - port: 8005 name: shutdown-port
多端口為什么需要給每個端口命名呢?這就涉及Kubernetes的服務(wù)發(fā)現(xiàn)機(jī)制了
Kubernetes 的服務(wù)發(fā)現(xiàn)機(jī)制
Kubernetes 的服務(wù)發(fā)現(xiàn)機(jī)制 |
---|
最早時Kubernetes采用了Linux環(huán)境變量的方式解決這個問題,即每個Service生成一些對應(yīng)的Linux環(huán)境變量(ENV),并在每個Pod的容器在啟動時,自動注入這些環(huán)境變量 |
后來Kubernetes通過Add-On增值包的方式引入了DNS系統(tǒng),把服務(wù)名作為DNS域名,這樣一來,程序就可以直接使用服務(wù)名來建立通信連接了。目前Kubernetes上的大部分應(yīng)用都已經(jīng)采用了DNS這些新興的服務(wù)發(fā)現(xiàn)機(jī)制 |
外部系統(tǒng)訪問 Service 的問題
Kubernetes里的“三種IP" | 描述 |
---|---|
Node IP | Node 節(jié)點的IP地址,Node IP是Kubernetes集群中每個節(jié)點的物理網(wǎng)卡的IP地址,這是一個真實存在的物理網(wǎng)絡(luò),所有屬于這個網(wǎng)絡(luò)的服務(wù)器之間都能通過這個網(wǎng)絡(luò)直接通信,不管它們中是否有部分節(jié)點不屬于這個Kubernetes集群。這也表明了Kubernetes集群之外的節(jié)點訪問Kubernetes集群之內(nèi)的某個節(jié)點或者TCP/IP服務(wù)時,必須要通過Node IP進(jìn)行通信。 |
Pod IP | Pod 的 IP 地址:Pod IP是每個Pod的IP地址,它是Docker Engine根據(jù)dockero網(wǎng)橋的IP地址段進(jìn)行分配的,通常是一個虛擬的二層網(wǎng)絡(luò),前面我們說過, Kubernetes要求位于不同Node上的Pod能夠彼此直接通信,所以Kubernetes里一個Pod里的容器訪問另外一個Pod里的容器,就是通過Pod IP所在的虛擬二層網(wǎng)絡(luò)進(jìn)行通信的,而真實的TCP/IP流量則是通過Node IP所在的物理網(wǎng)卡流出的。 |
Cluster IP | Service 的IP地址,Cluster IP僅僅作用于Kubernetes Service這個對象,并由Kubernetes管理和分配IP地址(來源于Cluster IP地址池)。Cluster IP無法被Ping,因為沒有一個“實體網(wǎng)絡(luò)對象”來響應(yīng)。Cluster IP只能結(jié)合Service Port組成一個具體的通信端口,單獨的Cluster IP不具備TCPIP通信的基礎(chǔ),并且它們屬于Kubernetes集群這樣一個封閉的空間,集群之外的節(jié)點如果要訪問這個通信端口,則需要做一些額外的工作。在Kubernetes集群之內(nèi), Node IP網(wǎng)、Pod IP網(wǎng)與Cluster IP網(wǎng)之間的通信,采用的是Kubermetes自己設(shè)計的一種編程方式的特殊的路由規(guī)則,與我們所熟知的IP路由有很大的不同。 |
外部系統(tǒng)訪問 Service,采用NodePort是解決上述問題的最直接、最有效、最常用的做法。具體做法如下,以tomcat-service為例,我們在Service的定義里做如下擴(kuò)展即可:
... spec: type: NodePort posts: - port: 8080 nodePort: 31002 selector: tier: frontend ...
即這里我們可以通過nodePort:31002 來訪問Service,NodePort的實現(xiàn)方式是在Kubernetes集群里的每個Node上為需要外部訪問的Service開啟個對應(yīng)的TCP監(jiān)聽端口,外部系統(tǒng)只要用任意一個Node的IP地址+具體的NodePort端口即可訪問此服務(wù),在任意Node上運(yùn)行netstat命令,我們就可以看到有NodePort端口被監(jiān)聽:
Service 負(fù)載均衡問題
但NodePort還沒有完全解決外部訪問Service的所有問題,比如負(fù)載均衡問題,假如我們的集群中有10個Node,則此時最好有一個負(fù)載均衡器,外部的請求只需訪問此負(fù)載均衡器的IP地址,由負(fù)載均衡器負(fù)責(zé)轉(zhuǎn)發(fā)流量到后面某個Node的NodePort上。如圖
NodePort的負(fù)載均衡 |
---|
![]() |
Load balancer組件獨立于Kubernetes集群之外,通常是一個硬件的負(fù)載均衡器,或者是以軟件方式實現(xiàn)的,例如HAProxy或者Nginx。對于每個Service,我們通常需要配置一個對應(yīng)的Load balancer實例來轉(zhuǎn)發(fā)流量到后端的Node上 |
Kubernetes提供了自動化的解決方案,如果我們的集群運(yùn)行在谷歌的GCE公有云上,那么只要我們把Service的type-NodePort改為type-LoadBalancer,此時Kubernetes會自動創(chuàng)建一個對應(yīng)的Load balancer實例并返回它的IP地址供外部客戶端使用。 |
10、 Volume (存儲卷)
Volume是Pod中能夠被多個容器訪問的共享目錄。Kuberetes的Volume概念、用途和目的與Docker的Volume比較類似,但兩者不能等價。
Volume (存儲卷) |
---|
Kubernetes中的Volume定義在Pod上,然后被一個Pod里的多個容器掛載到具體的文件目錄下; |
Kubernetes中的Volume與Pod的生命周期相同,但與容器的生命周期不相關(guān),當(dāng)容器終止或者重啟時, Volume中的數(shù)據(jù)也不會丟失。 |
Kubernetes支持多種類型的Volume,例如GlusterFS, Ceph等先進(jìn)的分布式文件系統(tǒng)。 |
Volume的使用也比較簡單,在大多數(shù)情況下,我們先在Pod上聲明一個Volume,然后在容器里引用該Volume并Mount到容器里的某個目錄上。舉例來說,我們要給之前的Tomcat Pod增加一個名字為datavol的Volume,并且Mount到容器的/mydata-data目錄上,則只要對Pod的定義文件做如下修正即可(注意黑體字部分):
template: metadata: labels: app: app-demo tier: frontend spec: volumes: - name: datavol emptyDir: {} containers: - name: tomcat-demo image: tomcat volumeMounts: - mountPath: /myddata-data name: datavol imagePullPolicy: IfNotPresent
除了可以讓一個Pod里的多個容器共享文件、讓容器的數(shù)據(jù)寫到宿主機(jī)的磁盤上或者寫文件到網(wǎng)絡(luò)存儲中, Kubernetes的Volume還擴(kuò)展出了一種非常有實用價值的功能,即
容器配置文件集中化定義與管理,這是通過ConfigMap這個新的資源對象來實現(xiàn)的.
Kubernetes提供了非常豐富的Volume類型,下面逐一進(jìn)行說明。
1. emptyDir
一個emptyDir Volume是在Pod分配到Node時創(chuàng)建的。從它的名稱就可以看出,它的初始內(nèi)容為空,并且無須指定宿主機(jī)上對應(yīng)的目錄文件,因為這是 Kubernetes自動分配的一個目錄,當(dāng)Pod從Node上移除時, emptyDir中的數(shù)據(jù)也會被永久刪除。emptyDir的一些用途如下。
emptyDir的一些用途 |
---|
臨時空間,例如用于某些應(yīng)用程序運(yùn)行時所需的臨時目錄,且無須永久保留。 |
長時間任務(wù)的中間過程CheckPoint的臨時保存目錄。 |
一個容器需要從另一個容器中獲取數(shù)據(jù)的目錄(多容器共享目錄) |
2. hostPath
hostPath為在Pod上掛載宿主機(jī)上的文件或目錄,它通??梢杂糜谝韵聨追矫?。
|容器應(yīng)用程序生成的日志文件需要永久保存時,可以使用宿主機(jī)的高速文件系統(tǒng)進(jìn)行存儲。|
需要訪問宿主機(jī)上Docker引擎內(nèi)部數(shù)據(jù)結(jié)構(gòu)的容器應(yīng)用時,可以通過定義hostPath為宿主機(jī)/var/lib/docker目錄,使容器內(nèi)部應(yīng)用可以直接訪問Docker的文件系統(tǒng)。
在使用這種類型的Volume時,需要注意以下幾點。
在不同的Node上具有相同配置的Pod可能會因為宿主機(jī)上的目錄和文件不同而導(dǎo)致對Volume上目錄和文件的訪問結(jié)果不一致。)
如果使用了資源配額管理,則Kubernetes無法將hostPath在宿主機(jī)上使用的資源納入管理。在下面的例子中使用宿主機(jī)的/data目錄定義了一個hostPath類型的Volume:
volumes: - name: "persistent-storage" hostPath: path: "/data"
3. gcePersistentDisk
使用這種類型的Volume表示使用谷歌公有云提供的永久磁盤(PersistentDisk, PD)存放Volume的數(shù)據(jù),它與emptyDir不同, PD上的內(nèi)容會被永久存,當(dāng)Pod被刪除時, PD只是被卸載(Unmount),但不會被刪除。需要注意是,你需要先創(chuàng)建一個永久磁盤(PD),才能使用gcePersistentDisk.
4. awsElasticBlockStore
與GCE類似,該類型的Volume使用亞馬遜公有云提供的EBS Volume存儲數(shù)據(jù),需要先創(chuàng)建一個EBS Volume才能使用awsElasticBlockStore.
5. NFS
使用NFS網(wǎng)絡(luò)文件系統(tǒng)提供的共享目錄存儲數(shù)據(jù)時,我們需要在系統(tǒng)中部署一個NFSServer,定義NES類型的Volume的示例如下
yum -y install nfs-utils
... volumes: - name: test-volume nfs: server: nfs.server.locathost path: "/" ....
11、 Persistent Volume
Volume是定義在Pod上的,屬于“計算資源”的一部分,而實際上, “網(wǎng)絡(luò)存儲”是相對獨立于“計算資源”而存在的一種實體資源。比如在使用虛擬機(jī)的情況下,我們通常會先定義一個網(wǎng)絡(luò)存儲,然后從中劃出一個“網(wǎng)盤”并掛接到虛擬機(jī)上
Persistent Volume(簡稱PV)和與之相關(guān)聯(lián)的Persistent Volume Claim (簡稱PVC)也起到了類似的作用。PV可以理解成 Kubernetes集群中的某個網(wǎng)絡(luò)存儲中對應(yīng)的一塊存儲,它與Volume很類似,但有以下區(qū)別。
Persistent Volume與Volume的區(qū)別 |
---|
PV只能是網(wǎng)絡(luò)存儲,不屬于任何Node,但可以在每個Node上訪問。 |
PV并不是定義在Pod上的,而是獨立于Pod之外定義。 |
PV目前支持的類型包括: gcePersistentDisk、 AWSElasticBlockStore, AzureFileAzureDisk, FC (Fibre Channel). Flocker, NFS, isCSI, RBD (Rados Block Device)CephFS. Cinder, GlusterFS. VsphereVolume. Quobyte Volumes, VMware Photon.PortworxVolumes, ScalelO Volumes和HostPath (僅供單機(jī)測試)。 |
apiversion: v1 kind: PersistentVolume metadata: name: pv0003 spec: capacity: storage: 5Gi accessModes: - ReadWriteOnce nfs: path: /somepath server: 172.17.0.2
PV的accessModes屬性, 目前有以下類型:
- ReadWriteOnce:讀寫權(quán)限、并且只能被單個Node掛載。
- ReadOnlyMany:只讀權(quán)限、允許被多個Node掛載。
- ReadWriteMany:讀寫權(quán)限、允許被多個Node掛載。
如果某個Pod想申請某種類型的PV,則首先需要定義一個PersistentVolumeClaim (PVC)對象:
kind: Persistentvolumeclaim apiversion: v1 metadata: name: myclaim spec: accessModes: - Readwriteonce resources: requests: storage: BGi
引用PVC
volumes: - name: mypd persistentvolumeclaim: claimName: myclaim
|PV是有狀態(tài)的對象,它有以下幾種狀態(tài)。|
|:--|
|Available:空閑狀態(tài)。|
|Bound:已經(jīng)綁定到某個Pvc上。|
|Released:對應(yīng)的PVC已經(jīng)刪除,但資源還沒有被集群收回。|
|Failed: PV自動回收失敗。|
12、 Namespace (命名空間)
Namespace (命名空間)是Kubernetes系統(tǒng)中非常重要的概念, Namespace在很多情況下用于實現(xiàn) 多租戶的資源隔離。Namespace通過將集群內(nèi)部的資源對象“分配”到不同的Namespace 中,形成邏輯上分組的不同項目、小組或用戶組,便于不同的分組在共享使用整個集群的資源的同時還能被分別管理。Kubernetes集群在啟動后,會創(chuàng)建一個名為"default"的Namespace,通過kubectl可以查看到:
不同的namespace之間互相隔離 | |
---|---|
查看所有命名空間 | kubectl get ns |
查看當(dāng)前命名空間 | kubectl config get-contexts |
設(shè)置命名空間 | kubectl config set-context 集群名 --namespace=命名空間 |
kub-system 本身的各種 pod,是kubamd默認(rèn)的空間。pod使用命名空間相互隔離
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$kubectl get namespaces
NAME STATUS AGE
default Active 13h
kube-node-lease Active 13h
kube-public Active 13h
kube-system Active 13h
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$kubectl get ns
NAME STATUS AGE
default Active 13h
kube-node-lease Active 13h
kube-public Active 13h
kube-system Active 13h
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$
命名空間基本命令
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$kubectl create ns liruilong
namespace/liruilong created
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$kubectl get ns
NAME STATUS AGE
default Active 13h
kube-node-lease Active 13h
kube-public Active 13h
kube-system Active 13h
liruilong Active 4s
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$kubectl create ns k8s-demo
namespace/k8s-demo created
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$kubectl get ns
NAME STATUS AGE
default Active 13h
k8s-demo Active 3s
kube-node-lease Active 13h
kube-public Active 13h
kube-system Active 13h
liruilong Active 20s
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$kubectl delete ns k8s-demo
namespace "k8s-demo" deleted
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$kubectl get ns
NAME STATUS AGE
default Active 13h
kube-node-lease Active 13h
kube-public Active 13h
kube-system Active 13h
liruilong Active 54s
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$
命名空間切換
┌──[root@vms81.liruilongs.github.io]-[~/.kube]
└─$vim config
┌──[root@vms81.liruilongs.github.io]-[~/.kube]
└─$kubectl config get-contexts
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
* context1 cluster1 kubernetes-admin1
context2 cluster2 kubernetes-admin2
┌──[root@vms81.liruilongs.github.io]-[~/.kube]
└─$kubectl config set-context context2 --namespace=kube-system
Context "context2" modified.
┌──[root@vms81.liruilongs.github.io]-[~/.kube]
└─$kubectl config get-contexts
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
* context1 cluster1 kubernetes-admin1
context2 cluster2 kubernetes-admin2 kube-system
┌──[root@vms81.liruilongs.github.io]-[~/.kube]
└─$kubectl config set-context context1 --namespace=kube-public
Context "context1" modified.
或者可以這樣切換名稱空間
kubectl config set-context $(kubectl config current-context) --namespace=<namespace>
kubectl config view | grep namespace
kubectl get pods
創(chuàng)建pod時指定命名空間
apiVersion: v1 kind: Pod metadata: creationTimestamp: null labels: run: pod-static name: pod-static namespeace: default spec: containers: - image: nginx imagePullPolicy: IfNotPresent name: pod-demo resources: {} dnsPolicy: ClusterFirst restartPolicy: Always status: {}
當(dāng)我們給每個租戶創(chuàng)建一個Namespace來實現(xiàn)多租戶的資源隔離時,還能結(jié)合Kubernetes"的資源配額管理,限定不同租戶能占用的資源,例如CPU使用量、內(nèi)存使用量等。
13、 Annotation (注解)
Annotation與Label類似,也使用key/value鍵值對的形式進(jìn)行定義。
不同的是Label具有嚴(yán)格的命名規(guī)則,它定義的是Kubernetes對象的元數(shù)據(jù)(Metadata),并且用于Label Selector.
Annotation則是用戶任意定義的“附加”信息,以便于外部工具進(jìn)行查找, Kubernetes的模塊自身會通過Annotation的方式標(biāo)記資源對象的一些特殊信息。
┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-pod-create]
└─$kubectl annotate nodes vms82.liruilongs.github.io "dest=這是一個工作節(jié)點" node/vms82.liruilongs.github.io annotated
┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-pod-create]
└─$kubectl describe nodes vms82.liruilongs.github.io
Name: vms82.liruilongs.github.io
Roles: worker1
Labels: beta.kubernetes.io/arch=amd64
beta.kubernetes.io/os=linux
disktype=node1
kubernetes.io/arch=amd64
kubernetes.io/hostname=vms82.liruilongs.github.io
kubernetes.io/os=linux
node-role.kubernetes.io/worker1=
Annotations: dest: 這是一個工作節(jié)點
kubeadm.alpha.kubernetes.io/cri-socket: /var/run/dockershim.sock
node.alpha.kubernetes.io/ttl: 0
projectcalico.org/IPv4Address: 192.168.26.82/24
projectcalico.org/IPv4IPIPTunnelAddr: 10.244.171.128
volumes.kubernetes.io/controller-managed-attach-detach: true .....................
通常來說,用Annotation來記錄的信息如下 |
---|
build信息、 release信息、Docker鏡像信息等,例如時間戳、release id號、PR號、鏡像hash值、 docker registry地址等。 |
日志庫、監(jiān)控庫、分析庫等資源庫的地址信息。 |
程序調(diào)試工具信息,例如工具名稱、版本號等。 |
團(tuán)隊的聯(lián)系信息,例如電話號碼、負(fù)責(zé)人名稱、網(wǎng)址等。 |