您好,登錄后才能下訂單哦!
Kubernetes為每個Pod都分配了唯一的IP地址,稱之為Pod IP,一個Pod里的多個容器共享Pod IP地址。Kubernetes要求底層網絡支持集群內任意兩個Pod之間的TCP/IP直接通信,這通常采用虛擬二層網絡技術來實現,例如Flannel、Open vSwitch等。因此,在Kubernetes里,一個Pod里的容器與另外主機上的Pod容器能夠直接通信。
Pod有兩種類型:普通的Pod和靜態Pod(Static Pod),靜態Pod不存放在etcd存儲里,而是存放在某個具體的Node上的一個具體文件中,并且只在此Node上啟動運行。普通的Pod一旦被創建,就會被存儲到etcd中,隨后會被Kubernetes Master調度到某個具體的Node上并進行綁定(Binding),該Node上的kubelet進程會將其實例化成一組相關的Docker容器并啟動起來。當Pod里的某個容器停止時,Kubernetes會自動檢測到這個問題并且重新啟動這個Pod(重啟Pod里的所有容器);如果Pod所在的Node宕機,則會將這個Node上的所有Pod重新調度到其他節點上運行。
Pod、容器與Node的關系如下圖:
Kubernetes里的所有資源對象都可以采用yaml或者JSON格式的文件來定義或描述,下面是一個簡單的Pod資源定義文件:
apiVersion: v1
kind: Pod
metadata:
name: myweb
labels:
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'
kind為pod表明這是一個Pod的定義,metadata里的name屬性為Pod的名字,metadata里還能定義資源對象的標簽(Label),這里聲明myweb擁有一個name=myweb的標簽(Label)。Pod里包含的容器組的定義則在spec一節中聲明,這里定義了一個名字為myweb,對應鏡像為kubeguide/tomcat-app: v1的容器,該容器注入了名為MYSQL_SERVICE_HOST='mysql'和MYSQL_SERVICE_PORT='3306'的環境變量(env關鍵字),并且在8080端口(containerPort)上啟動容器進程。Pod的IP加上這里的容器端口,就組成了一個新的概念——Endpoint,它代表著此Pod里的一個服務進程的對外通信地址。一個Pod也存在著具有多個Endpoint的情況,比如我們把Tomcat定義為一個Pod時,可以對外暴露管理端口與服務端口這兩個Endpoint。
Docker里的Volume在Kubernetes里也有對應的概念——Pod Volume,Pod Volume有一些擴展,比如可以用分布式文件系統GlusterFS等實現后端存儲功能;Pod Volume是定義在Pod之上,然后被各個容器掛載到自己的文件系統中的。對于Pod Volume的定義我們后面會講到。
這里順便提一下Event概念,Event是一個事件的記錄,記錄了事件的最早產生時間、最后重現時間、重復次數、發起者、類型,以及導致此事件的原因等眾多信息。Event通常會關聯到某個具體的資源對象上,是排查故障的重要參考信息,當我們發現某個Pod遲遲無法創建時,可以用kubectl describe pod xxx來查看它的描述信息,用來定位問題的原因。
每個Pod都可以對其能使用的服務器上的計算資源設置限額,當前可以設置限額的計算資源有CPU和Memory兩種,其中CPU的資源單位為CPU(Core)的數量,是一個絕對值。
對于容器來說一個CPU的配額已經是相當大的資源配額了,所以在Kubernetes里,通常以千分之一的CPU配額為最小單位,用m來表示。通常一個容器的CPU配額被定義為100-300m,即占用0.1-0.3個CPU。與CPU配額類似,Memory配額也是一個絕對值,它的單位是內存字節數。
對計算資源進行配額限定需要設定以下兩個參數:
通常我們應該把Requests設置為一個比較小的數值,滿足容器平時的工作負載情況下的資源需求,而把Limits設置為峰值負載情況下資源占用的最大量。下面是一個資源配額的簡單定義:
spec:
containers:
- name: db
image: mysql
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"
最小0.25個CPU及64MB內存,最大0.5個CPU及128MB內存。
Label相當于我們熟悉的“標簽”,給某個資源對象定義一個Label,就相當于給它打了一個標簽,隨后可以通過Label Selector(標簽選擇器)查詢和篩選擁有某些Label的資源對象,Kubernetes通過這種方式實現了類似SQL的簡單又通用的對象查詢機制。
Label Selector相當于SQL語句中的where查詢條件,例如,name=redis-slave這個Label Selector作用于Pod時,相當于select * from pod where pod’s name = ‘redis-slave’這樣的語句。Label Selector的表達式有兩種:基于等式的(Equality-based)和基于集合的(Set-based)。下面是基于等式的匹配例子。
name=redis-slave:匹配所有標簽為name=redis-slave的資源對象。
env != production:匹配所有標簽env不等于production的資源對象。
下面是基于集合的匹配例子
還可以通過多個Label Selector表達式的組合實現復雜的條件選擇,多個表達式之間用“,”進行分隔即可,幾個條件之間是“AND”的關系,即同時滿足多個條件,例如:
name=redis-slave, env!=production
name not in (php-frontend), env!=production
以Pod為例,Label定義在metadata中:
apiVersion: v1
kind: Pod
metadata:
name: myweb
labels:
app: myweb
RC和Service在spec中定義Selector與Pod進行關聯:
apiVersion: v1
kind: ReplicationController
metadata:
name: myweb
spec:
replicas: 1
selector:
app: myweb
template:
…………
Deployment、ReplicaSet、DaemonSet和Job則可以在Selector中使用基于集合的篩選條件:
selector:
matchLabels:
app: myweb
matchExpressions:
- {key: tier, operator: In, values: [frontend]}
- {key: environment, operator: NotIn, values: [dev]}
matchLabels用于定義一組Label,與直接寫在Selector中作用相同;matchExpressions用于定義一組基于集合的篩選條件,可用的條件運算符包括:In、NotIn、Exists和DoesNotExist。
如果同時設置了matchLabels和matchExpressions,則兩組條件為“AND”關系,即所有條件需要同時滿足才能完成Selector的篩選。
Label Selector在Kubernetes中的重要使用場景如下:
下面舉個復雜點的例子,假設我們為Pod定義了3個Label:release、env和role,不同的Pod定義了不同的Label。如下圖所示,如果我們設置了“role=frontend”的Label Selector,則會選取到Node 1和Node 2上的Pod。
如果我們設置“release=beta”的Label Selector,則會選取到Node 2和Node 3上的Pod,如下圖所示。
總結:使用Label可以給對象創建多組標簽,Label和Label Selector共同構成了Kubernetes系統中最核心的應用模型,使得被管理對象能夠被精細地分組管理,同時實現了整個集群的高可用性。
RC的作用是聲明Pod的副本數量在任意時刻都符合某個預期值,所以RC的定義包括如下幾個部分。
下面是一個完整的RC定義的例子,即確保擁有tier=frontend標簽的這個Pod(運行Tomcat容器)在整個Kubernetes集群中始終有三個副本:
apiVersion: v1
kind: ReplicationController
metadata:
name: frontend
spec:
replicas: 3
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
當我們定義了一個RC并提交到Kubernetes集群中后,Master節點上的Controller Manager組件就得到通知,定期巡檢系統中當前存活的目標Pod,并確保目標Pod實例的數量剛好等于此RC的期望值。如果有過多的Pod副本在運行,系統就會停掉多余的Pod;如果運行的Pod副本少于期望值,即如果某個Pod掛掉,系統就會自動創建新的Pod以保證數量等于期望值。
通過RC,Kubernetes實現了用戶應用集群的高可用性,并且大大減少了運維人員在傳統IT環境中需要完成的許多手工運維工作(如主機監控腳本、應用監控腳本、故障恢復腳本等)。
下面我們來看下Kubernetes如何通過RC來實現Pod副本數量自動控制的機制,假如我們有3個Node節點,在RC里定義了redis-slave這個Pod需要保持兩個副本,系統將會在其中的兩個Node上創建副本,如下圖所示。
假如Node2上的Pod2意外終止,根據RC定義的replicas數量2,Kubernetes將會自動創建并啟動一個新的Pod,以保證整個集群中始終有兩個redis-slave Pod在運行。
系統可能選擇Node1或者Node3來創建一個新的Pod,如下圖。
通過修改RC的副本數量,可以實現Pod的動態縮放(Scaling)功能。kubectl scale rc redis-slave --replicas=3
此時Kubernetes會在3個Node中選取一個Node創建并運行一個新的Pod3,使redis-slave Pod副本數量始終保持3個。
由于Replication Controller與Kubernetes代碼中的模塊Replication Controller同名,同時這個詞也無法準確表達它的意思,所以從Kubernetes v1.2開始,它就升級成了另外一個新的對象——Replica Set,官方解釋為“下一代的RC”。它與RC當前存在的唯一區別是:Replica Set支持基于集合的Label selector(Set-based selector),而RC只支持基于等式的Label selector(equality-based selector),所以Replica Set的功能更強大。下面是Replica Set的定義例子(省去了Pod模板部分的內容):
apiVersion: extensions/v1beta1
kind: ReplicaSet
metadata:
name: frontend
spec:
selector:
matchLabels:
tier: frontend
matchExpressions:
- {key: tier, operator: In, values: [frontend]}
template:
…………
Replica Set很少單獨使用,它主要被Deployment這個更高層的資源對象所使用,從而形成一整套Pod創建、刪除、更新的編排機制。
RC和RS的特性與作用如下:
Deployment相對于RC的最大區別是我們可以隨時知道當前Pod“部署”的進度。一個Pod的創建、調度、綁定節點及在目標Node上啟動對應的容器這一完整過程需要一定的時間,所以我們期待系統啟動N個Pod副本的目標狀態,實際上是一個連續變化的“部署過程”導致的最終狀態。
Deployment的典型使用場景有以下幾個:
Deployment的定義與Replica Set的定義類似,只是API聲明與Kind類型不同。
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: nginx-deployment
apiVersion: v1
kind: ReplicaSet
metadata:
name: nginx-repset
下面是Deployment定義的一個完整例子:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: frontend
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-demo
image: tomcat
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
可以通過命令kubectl get deployment來查看Deployment的信息,其中的幾個參數解釋如下:
Pod的管理對象,除了RC、ReplicaSet、Deployment,還有DaemonSet、StatefulSet、Job等,分別用于不同的應用場景。
HPA與RC、Deployment一樣,也屬于Kubernetes資源對象。通過追蹤分析RC或RS控制的所有目標Pod的負載變化情況,來確定是否需要針對性地調整目標Pod的副本數。
HPA有以下兩種方式作為Pod負載的度量指標:
CPUUtilizationPercentage是一個算術平均值,即目標Pod所有副本自帶的CPU利用率的平均值。一個Pod自身的CPU利用率是該Pod當前CPU的使用量除以它的Pod Request的值,比如我們定義一個Pod的Pod Request為0.4,而當前Pod的CPU使用量為0.2,則它的CPU使用率為50%,這樣我們就可以算出來一個RC或RS控制的所有Pod副本的CPU利用率的算術平均值了。如果某一時刻CPUUtilizationPercentage的值超過80%,則意味著當前的Pod副本數很可能不足以支撐接下來更多的請求,需要進行動態擴容,而當請求高峰時段過去后,Pod的CPU利用率又會降下來,此時對應的Pod副本數應該自動減少到一個合理的水平。
下面是HPA定義的一個具體的例子:
apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
name: php-apache
namespace: default
spec:
maxReplicas: 10
minReplicas: 2
scaleTargetRef:
kind: Deployment
name: php-apache
targetCPUUtilizationPercentage: 90
通過HPA控制php-apache的Pod副本,當Pod副本的CPUUtilizationPercentage的值超過90%時,會進行自動擴容增加Pod副本的數量,擴容或縮容時Pod的副本數量要介于2-10之間。
除了通過yaml文件來定義HPA對象之外,還可以通過命令的方式創建:kubectl autoscale deployment php-apache --cpu-percent=90 --min=1 --max=10
Pod的管理對象RC、Deployment、DaemonSet和Job都是面向無狀態的服務,但實際中有很多服務是有狀態的,比如Mysql集群、MongoDB集群、ZooKeeper集群等,可以使用StatefulSet來管理有狀態的服務。
StatefulSet有如下一些特性:
StatefulSet除了要與PV卷捆綁使用以存儲Pod的狀態數據,還要與Headless Service配合使用,即在每個StatefulSet的定義中要聲明它屬于哪個Headless Service。Headless Service與普通Service的區別在于,它沒有Cluster IP,如果解析Headless Service的DNS域名,則返回的是該Service對應的全部Pod的Endpoint列表。StatefulSet在Headless Service的基礎上又為StatefulSet控制的每個Pod實例創建了一個DNS域名,這個域名的格式為:
$(podname).$(headless service name)
比如一個3節點的kafka的StatefulSet集群,對應的Headless Service的名字為kafka,StatefulSet的名字為kafka,則StatefulSet里面的3個Pod的DNS名稱分別為kafka-0.kafka、kafka-1.kafka、kafka-3.kafka,這些DNS名稱可以直接在集群的配置文件中固定下來。
1.概述
Service其實就是我們經常提起的微服務架構中的一個“微服務”,Pod、RC等資源對象其實都是為它作“嫁衣”的。Pod、RC或RS與Service的邏輯關系如下圖所示。
通過上圖我們看到,Kubernetes的Service定義了一個服務的訪問入口地址,前端的應用(Pod)通過這個入口地址訪問其背后的一組由Pod副本組成的集群實例,Service與其后端Pod副本集群之間則是通過Label Selector來實現“無縫對接”的。而RC的作用實際上是保證Service的服務能力和服務質量始終處于預期的標準。
通過分析、識別并建模系統中的所有服務為微服務——Kubernetes Service,最終我們的系統由多個提供不同業務能力而又彼此獨立的微服務單元所組成,服務之間通過TCP/IP進行通信,從而形成了強大而又靈活的彈性集群,擁有了強大的分布式能力、彈性擴展能力、容錯能力。因此,我們的系統架構也變得簡單和直觀許多。
既然每個Pod都會被分配一個單獨的IP地址,而且每個Pod都提供了一個獨立的Endpoint(Pod IP+ContainerPort)以被客戶端訪問,多個Pod副本組成了一個集群來提供服務,那么客戶端如何來訪問它們呢?一般的做法是部署一個負載均衡器(軟件或硬件),但這樣無疑增加了運維的工作量。在Kubernetes集群里使用了Service(服務),它提供了一個虛擬的IP地址(Cluster IP)和端口號,Kubernetes集群里的任何服務都可以通過Cluster IP+端口的方式來訪問此服務,至于訪問請求最后會被轉發到哪個Pod,則由運行在每個Node上的kube-proxy負責。kube-proxy進程其實就是一個智能的軟件負載均衡器,它負責把對Service的請求轉發到后端的某個Pod實例上,并在內部實現服務的負載均衡與會話保持機制。
下面是一個Service的簡單定義:
apiVersion: v1
kind: Service
metadata:
name: tomcat-service
spec:
ports:
- port: 8080
selector:
tier: frontend
上述內容定義了一個名為“tomcat-service”的Service,它的服務端口為8080,擁有“tier=frontend”這個Label的所有Pod實例。
很多服務都存在多個端口的問題,通常一個端口提供業務服務,另外一個端口提供管理服務,比如Mycat、Codis等常見中間件。Kubernetes Service支持多個Endpoint,要求每個Endpoint定義一個名字來區分,下面是tomcat多端口的Service定義樣例。
apiVersion: v1
kind: Service
metadata:
name: tomcat-service
spec:
ports:
- port: 8080
name: service-port
- port: 8005
name: shutdown-port
selector:
tier: frontend
多端口為什么需要給每個端口命名呢?這就涉及Kubernetes的服務發現機制了。
2.Kubernetes的服務發現機制
每個Kubernetes中的Service都有一個唯一的Cluster IP及唯一的名字,而名字是由我們自己定義的,那我們是否可以通過Service的名字來訪問呢?
最早時Kubernetes采用了Linux環境變量的方式來實現,即每個Service生成一些對應的Linux環境變量(ENV),并在每個Pod的容器啟動時,自動注入這些環境變量,以實現通過Service的名字來建立連接的目的。
考慮到通過環境變量獲取Service的IP與端口的方式仍然不方便、不直觀,后來Kubernetes通過Add-On增值包的方式引入了DNS系統,把服務名作為DNS域名,這樣程序就可以直接使用服務名來建立連接了。
關于DNS的部署,后續博文我會單獨講解,有興趣的朋友可以關注我的博客。
3.外部系統訪問Service的問題
Kubernetes集群里有三種IP地址,分別如下:
外部訪問Kubernetes集群里的某個節點或者服務時,必須要通過Node IP進行通信。
Pod IP是Docker Engine根據docker0網橋的IP地址段進行分配的一個虛擬二層網絡IP地址,Pod與Pod之間的訪問就是通過這個虛擬二層網絡進行通信的,而真實的TCP/IP流量則是通過Node IP所在的物理網卡流出的。
Service的Cluster IP具有以下特點:
我們的應用如果想讓外部訪問,最常用的作法是使用NodePort方式。
apiVersion: v1
kind: Service
metadata:
name: tomcat-service
spec:
type: NodePort
ports:
- port: 8080
nodePort: 31002
selector:
tier: frontend
NodePort的實現方式是在Kubernetes集群里的每個Node上為需要外部訪問的Service開啟一個對應的TCP監聽端口,外部系統只要用任意一個Node的IP地址+具體的NodePort端口號即可訪問此服務。
NodePort還沒有完全解決外部訪問Service的所有問題,比如負載均衡問題,常用的做法是在Kubernetes集群之外部署一個負載均衡器。
Load balancer組件獨立于Kubernetes集群之外,可以是一個硬件負載均衡器,也可以是軟件方式實現,例如HAProxy或者Nginx。這種方式,無疑是增加了運維的工作量及出錯的概率。
于是Kubernetes提供了自動化的解決方案,如果我們使用谷歌的GCE公有云,那么只需要將type: NodePort改成type: LoadBalancer,此時Kubernetes會自動創建一個對應的Load balancer實例并返回它的IP地址供外部客戶端使用。其他公有云提供商只要實現了支持此特性的驅動,則也可以達到上述目的。
Volume是Pod中能夠被多個容器訪問的共享目錄。Volume定義在Pod上,被一個Pod里的多個容器掛載到具體的文件目錄下,當容器終止或者重啟時,Volume中的數據也不會丟失。Kubernetes支持多種類型的Volume,例如GlusterFS、Ceph等分布式文件系統。
除了可以讓一個Pod里的多個容器共享文件、讓容器的數據寫到宿主機的磁盤上或者寫文件到網絡存儲中,Kubernetes還提供了容器配置文件集中化定義與管理,通過ConfigMap對象來實現。
Kubernetes支持多種Volume類型,下面我們一一進行介紹。
1.emptyDir
emptyDir是在Pod分配到Node時創建的,它的初始內容為空,并且無須指定宿主機上對應的目錄文件,它是Kubernetes自動分配的一個目錄,當Pod從Node上移除時,emptyDir中的數據也會被永久刪除。
emptyDir的用途如下:
emptyDir的定義如下:
template:
metadata:
labels:
app: app-demo
tier: frontend
spec:
volumes:
- name: datavol
emptyDir: {}
containers:
- name: tomcat-demo
image: tomcat
volumeMounts:
- mountPath: /mydata-data
name: datavol
imagePullPolicy: IfNotPresent
2.hostPath
使用hostPath掛載宿主機上的文件或目錄,主要用于以下幾個方面:
使用hostPath時,需要注意以下幾點:
hostPath的定義如下:
volumes:
- name: "persistent-storage"
hostPath:
path: "/data"
3.gcePersistentDisk
使用這種類型的Volume表示使用谷歌公有云提供的永久磁盤(Persistent Disk,PD)存放數據,使用gcePersistentDisk有以下一些限制條件:
通過gcloud命令創建一個PD:gcloud compute disks create --size=500GB --zone=us-centrall-a my-data-disk
定義gcePersistentDisk類型的Volume的示例如下:
volumes:
- name: test-volume
gcPersistentDisk:
pdName: my-data-disk
fsType: ext4
4.awsElasticBlockStore
與GCE類似,該類型的Volume使用亞馬遜公有云提供的EBS Volume存儲數據,需要先創建一個EBS Volume才能使用awsElasticBlockStore。
使用awsElasticBlockStore的一些限制條件如下:
通過aws ec2 create-volume命令創建一個EBS volume:aws ec2 create-volume --availability-zone eu-west-la --size 10 --volume-type gp2
定義awsElasticBlockStore類型的Volume的示例如下:
volumes:
- name: test-volume
awsElasticBlockStore:
volumeID: aws://<availability-zone>/<volume-id>
fsType: ext4
5.NFS
使用NFS網絡文件系統提供的共享目錄存儲數據時,我們需要在系統中部署一個NFS Server。
定義NFS類型的Volume的示例如下:
volumes:
- name: nfs-volume
nfs:
server: nfs-server.localhost
path: "/"
6.其他類型的Volume
上面提到的Volume是定義在Pod上的,屬于“計算資源”的一部分,而實際上,“網絡存儲”是相對獨立于“計算資源”而存在的一種實體資源。比如在使用云主機的情況下,我們通常會先創建一個網絡存儲,然后從中劃出一個“網盤”并掛載到云主機上。Persistent Volume(簡稱PV)和與之相關聯的Persistent Volume Claim(簡稱PVC)實現了類似的功能。
PV與Volume的區別如下:
下面是NFS類型PV的yaml定義內容,聲明了需要5G的存儲空間:
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv003
spec:
capacity:
storage: 5Gi
accessModes:
- ReadWriteOnce
nfs:
path: /somepath
server: 172.17.0.2
PV的accessModes屬性有以下類型:
如果Pod想申請使用PV資源,則首先需要定義一個PersistentVolumeClaim(PVC)對象:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: myclaim
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
然后在Pod的volume定義中引用上述PVC即可
volumes:
- name: mypd
persistentVolumeClaim:
claimName: myclaim
PV是有狀態的對象,它有以下幾種狀態:
通過將Kubernetes集群內部的資源對象“分配”到不同的Namespace中,形成邏輯上分組的不同項目、小組或用戶組,便于不同的分組在共享使用整個集群的資源的同時還能被分別管理。
Kubernetes集群在啟動后,會創建一個名為“default”的Namespace,通過kubectl可以查看到:kubectl get namespaces
如果不特別指明Namespace,則用戶創建的Pod、RC、RS、Service都獎被系統創建到這個默認的名為default的Namespace中。
下面是Namespace的定義示例:
apiVersion: v1
kind: Namespace
metadata:
name: development
定義一個Pod,并指定它屬于哪個Namespace:
apiVersion: v1
kind: Pod
metadata:
name: busybox
namespace: development
spec:
containers:
- image: busybox
command:
- sleep
- "3600"
name: busybox
使用kubectl get命令查看Pod狀態信息時,需要加上--namespace參數,指定查看哪個namespace下的資源對象,不加這個參數則默認查看 default下的資源對象。kubectl get pods --namespace=development
當我們給每個租戶創建一個Namespace來實現多租戶的資源隔離時,還能結合Kubernetes的資源配額管理,限定不同租戶能占用的資源,例如CPU使用量、內存使用量等。
Annotation與Label類似,也使用key/value鍵值對的形式進行定義。不同的是Label具有嚴格的命名規則,它定義的是Kubernetes對象的元數據(Metadata),并且用于Label Selector。而Annotation則是用戶任意定義的“附加”信息,以便于外部工具進行查找。通常Kubernetes的模塊會通過Annotation的方式標記資源對象的一些特殊信息。
使用Annotation來記錄的信息如下:
注:本文內容摘自《Kubernetes權威指南:從Docker到Kubernetes實踐全接觸(紀念版》,并精減了部分內部,而且對部分內容做了相應的調整,可以幫助大家加深對Kubernetes的各種資源對象的理解和定義方法,關注我的博客,跟我一起開啟k8s的學習之旅吧。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。