9-k8s筆記-Kubernetes開發指南


第9章 Kubernetes開發指南
9.1 REST簡述
9.2 Kubernetes API詳解
9.2.1 Kubernetes API概述
9.2.2 Kubernetes API版本的演進策略
9.2.3 API Groups(API組)
9.2.4 API REST的方法說明
9.2.5 API Server響應說明
9.3 使用Java程序訪問Kubernetes API
9.3.1 Jersey
9.3.2 Fabric8
9.3.3 使用說明
9.3.4 其他客戶端庫
9.4 Kubernetes API的擴展
9.4.1 使用CRD擴展API資源
9.4.2 使用API聚合機制擴展API資源

本章將引入REST的概念,詳細說明Kubernetes API的概念和使用方法,並舉例說明如何基於Jersey和Fabric8框架訪問Kubernetes API,
深入分析基於這兩個框架訪問Kubernetes API的優缺點,最后對Kubernetes API的擴展進行詳細說明。
下面從REST開始說起。

9.1 REST簡述
REST(Representational State Transfer,表述性狀態傳遞)是由Roy Thomas Fielding博士
在他的論文Architectural Styles and the Design of Network-based Software Architectures中提出的一個術語。
REST本身只是為分布式超媒體系統設計的一種架構風格,而不是標准。
基於Web的架構實際上就是各種規范的集合,比如HTTP是一種規范,客戶端服務器模式是另一種規范。
每當我們在原有規范的基礎上增加新的規范時,就會形成新的架構。
而REST正是這樣一種架構,它結合了一系列規范,形成了一種新的基於Web的架構風格。
傳統的Web應用大多是B/S架構,涉及如下規范。
(1)客戶端-服務器:這種規范的提出,改善了用戶接口跨多個平台的可移植性,並且通過簡化服務器組件,改善了系統的可伸縮性。
最為關鍵的是通過分離用戶接口和數據存儲,使得不同的用戶終端共享相同的數據成為可能。
(2)無狀態性:無狀態性是在客戶端-服務器規范的基礎上添加的又一層規范,
它要求通信必須在本質上是無狀態的,即從客戶端到服務器的每個request都必須包含理解該request必需的所有信息。
這個規范改善了系統的可見性(無狀態性使得客戶端和服務器端不必保存對方的詳細信息,服務器只需要處理當前的request,而不必了解所有request的歷史)、
可靠性(無狀態性減少了服務器從局部錯誤中恢復的任務量)、可伸縮性(無狀態性使得服務器端可以很容易釋放資源,因為服務器端不必在多個request中保存狀態)。
同時,這種規范的缺點也是顯而易見的,不能將狀態數據保存在服務器上,導致增加了在一系列request中發送重復數據的開銷,嚴重降低了效率。
(3)緩存:為了改善無狀態性帶來的網絡的低效性,客戶端緩存規范出現。
緩存規范允許隱式或顯式地標記一個response中的數據,賦予了客戶端緩存response數據的功能,這樣就可以為以后的request共用緩存的數據消除部分或全部交互,提高了網絡效率。
但是客戶端緩存了信息,所以客戶端數據與服務器數據不一致的可能性增加,從而降低了可靠性。

B/S架構的優點是部署非常方便,在用戶體驗方面卻不很理想。為了改善這種狀況,REST規范出現。
REST規范在原有B/S架構的基礎上增加了三個新規范:統一接口、分層系統和按需代碼。
(1)統一接口:REST架構風格的核心特征就是強調組件之間有一個統一的接口,
表現為在REST世界里,網絡上的所有事物都被抽象為資源,REST通過通用的鏈接器接口對資源進行操作。
這樣設計的好處是保證系統提供的服務都是解耦的,可極大簡化系統,改善系統的交互性和可重用性。
(2)分層系統:分層系統規則的加入提高了各種層次之間的獨立性,為整個系統的復雜性設置了邊界,
通過封裝遺留的服務,使新的服務器免受遺留客戶端的影響,也提高了系統的可伸縮性。
(3)按需代碼:REST允許對客戶端的功能進行擴展。
比如,通過下載並執行applet或腳本形式的代碼來擴展客戶端的功能。
但這在改善系統可擴展性的同時降低了可見性,所以它只是REST的一個可選約束。

REST架構是針對Web應用而設計的,其目的是為了降低開發的復雜性,提高系統的可伸縮性。
REST提出了如下設計准則:
(1)網絡上的所有事物都被抽象為資源(Resource)。
(2)每個資源都對應唯一的資源標識符(Resource Identifier)。
(3)通過通用的連接器接口(Generic Connector Interface)對資源進行操作。
(4)對資源的各種操作都不會改變資源標識符。
(5)所有操作都是無狀態的(Stateless)。
REST中的資源指的不是數據,而是數據和表現形式的組合,
比如“最新訪問的10位會員”和“最活躍的10位會員”在數據上可能有重疊或者完全相同,而它們由於表現形式不同,被歸為不同的資源,這也就是為什么REST的全名是Representational State Transfer。
資源標識符就是URI(Uniform Resource Identifier),不管是圖片、Word還是視頻文件,甚至只是一種虛擬的服務,也不管是XML、TXT還是其他文件格式,全部通過URI對資源進行唯一標識。
REST是基於HTTP的,任何對資源的操作行為都通過HTTP來實現。
以往的Web開發大多數用的是HTTP中的GET和POST方法,很少使用其他方法,這實際上是對HTTP的片面理解造成的。
HTTP不僅僅是一個簡單的運載數據的協議,還是一個具有豐富內涵的網絡軟件的協議,它不僅能對互聯網資源進行唯一定位,還能告訴我們如何對該資源進行操作。
HTTP把對一個資源的操作限制在4種方法(GET、POST、PUT和DELETE)中,這正是對資源CRUD操作的實現。
由於資源和URI是一一對應的,在執行這些操作時URI沒有變化,和以往的Web開發有很大的區別,所以極大地簡化了Web開發,也使得URI可以被設計成能更直觀地反映資源的結構。
這種URI的設計被稱作RESTful的URI,為開發人員引入了一種新的思維方式:通過URL來設計系統結構。
當然,這種設計方式對於一些特定情況也是不適用的,也就是說不是所有URI都適用於RESTful。
REST之所以可以提高系統的可伸縮性,就是因為它要求所有操作都是無狀態的。
沒有了上下文(Context)的約束,做分布式和集群時就更為簡單,也可以讓系統更為有效地利用緩沖池(Pool),
並且由於服務器端不需要記錄客戶端的一系列訪問,也就減少了服務器端的性能損耗。
Kubernetes API也符合RESTful規范,下面對其進行介紹。

9.2 Kubernetes API詳解
9.2.1 Kubernetes API概述
Kubernetes API是集群系統中的重要組成部分,Kubernetes中各種資源(對象)的數據都通過該API接口被提交到后端的持久化存儲(etcd)中,
Kubernetes集群中的各部件之間通過該API接口實現解耦合,同時Kubernetes集群中一個重要且便捷的管理工具kubectl也是通過訪問該API接口實現其強大的管理功能的。
Kubernetes API中的資源對象都擁有通用的元數據,資源對象也可能存在嵌套現象,比如在一個Pod里面嵌套多個Container。
創建一個API對象是指通過API調用創建一條有意義的記錄,該記錄一旦被創建,Kubernetes就將確保對應的資源對象會被自動創建並托管維護。
在Kubernetes系統中,在大多數情況下,API定義和實現都符合標准的HTTP REST格式,
比如通過標准的HTTP動詞(POST、PUT、GET、DELETE)來完成對相關資源對象的查詢、創建、修改、刪除等操作。
但同時,Kubernetes也為某些非標准的REST行為實現了附加的API接口,例如Watch某個資源的變化、進入容器執行某個操作等。
另外,某些API接口可能違背嚴格的REST模式,因為接口返回的不是單一的JSON對象,而是其他類型的數據,比如JSON對象流或非結構化的文本日志數據等。
Kubernetes開發人員認為,任何成功的系統都會經歷一個不斷成長和不斷適應各種變更的過程。
因此,他們期望Kubernetes API是不斷變更和增長的。
同時,他們在設計和開發時,有意識地兼容了已存在的客戶需求。
通常,我們不希望將新的API資源和新的資源域頻繁地加入系統,資源或域的刪除需要一個嚴格的審核流程。
Kubernetes API文檔官網為https://kubernetes.io/docs/reference,可以通過相關鏈接查看不同版本的API文檔,
例如Kubernetes 1.14版本的鏈接為https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.14。
在Kubernetes 1.13版本及之前的版本中,Master的API Server服務提供了Swagger格式的API網頁。
Swagger UI是一款REST API文檔在線自動生成和功能測試軟件,關於Swagger的內容請訪問官網http://swagger.io。
我們通過設置kube-apiserver服務的啟動參數--enable-swagger-ui=true來啟用Swagger UI頁面,其訪問地址為http://<master-ip>:<master-port>/swagger-ui/。
假設API Server啟動了192.168.18.3服務器上的8080端口,則可以通過訪問http://192.168.18.3:8080/swagger-ui/來查看API列表,如圖9.1所示。
單擊api/v1可以查看所有API的列表,如圖9.2所示。
以創建一個Pod為例,找到Rest API的訪問路徑為“POST /api/v1/namespaces/{namespace}/pods”,如圖9.3所示。
單擊鏈接展開,即可查看詳細的API接口說明,如圖9.4所示。
單擊Model鏈接,則可以查看文本格式顯示的API接口描述,如圖9.5所示。
我們看到,在Kubernetes API中,一個API的頂層(Top Level)元素由kind、apiVersion、metadata、spec和status這5部分組成,接下來分別對這5部分進行說明。
1.kind
kind表明對象有以下三大類別:
(1)對象(objects):代表系統中的一個永久資源(實體),例如Pod、RC、Service、Namespace及Node等。
通過操作這些資源的屬性,客戶端可以對該對象進行創建、修改、刪除和獲取操作。
(2)列表(list):一個或多個資源類別的集合。所有列表都通過items域獲得對象數組,例如PodLists、ServiceLists、NodeLists。
大部分被定義在系統中的對象都有一個返回所有資源集合的端點,以及零到多個返回所有資源集合的子集的端點。
某些對象有可能是單例對象(singletons),例如當前用戶、系統默認用戶等,這些對象沒有列表。
(3)簡單類別(simple):該類別包含作用在對象上的特殊行為和非持久實體。
該類別限制了使用范圍,它有一個通用元數據的有限集合,例如Binding、Status。
2.apiVersion
apiVersion表明API的版本號,當前版本默認只支持v1。
3.Metadata
Metadata是資源對象的元數據定義,是集合類的元素類型,包含一組由不同名稱定義的屬性。
在Kubernetes中每個資源對象都必須包含以下3種Metadata:
(1)namespace:對象所屬的命名空間,如果不指定,系統則會將對象置於名為default的系統命名空間中。
(2)name:對象的名稱,在一個命名空間中名稱應具備唯一性。
(3)uid:系統為每個對象都生成的唯一ID,符合RFC 4122規范的定義。
此外,每種對象都還應該包含以下幾個重要元數據:
(1)labels:用戶可定義的“標簽”,鍵和值都為字符串的map,是對象進行組織和分類的一種手段,通常用於標簽選擇器,用來匹配目標對象。
(2)annotations:用戶可定義的“注解”,鍵和值都為字符串的map,被Kubernetes內部進程或者某些外部工具使用,用於存儲和獲取關於該對象的特定元數據。
(3)resourceVersion:用於識別該資源內部版本號的字符串,在用於Watch操作時,可以避免在GET操作和下一次Watch操作之間造成的信息不一致,客戶端可以用它來判斷資源是否改變。
該值應該被客戶端看作不透明,且不做任何修改就返回給服務端。客戶端不應該假定版本信息具有跨命名空間、跨不同資源類別、跨不同服務器的含義。
(4)creationTimestamp:系統記錄創建對象時的時間戳,符合RFC 3339規范。
(5)deletionTimestamp:系統記錄刪除對象時的時間戳,符合RFC 3339規范。
(6)selfLink:通過API訪問資源自身的URL,例如一個Pod的link可能是“/api/v1/namespaces/ default/pods/frontend-o8bg4”。
4.spec
spec是集合類的元素類型,用戶對需要管理的對象進行詳細描述的主體部分都在spec里給出,它會被Kubernetes持久化到etcd中保存,
系統通過spec的描述來創建或更新對象,以達到用戶期望的對象運行狀態。
spec的內容既包括用戶提供的配置設置、默認值、屬性的初始化值,也包括在對象創建過程中由其他相關組件(例如schedulers、auto-scalers)創建或修改的對象屬性,比如Pod的Service IP地址。
如果spec被刪除,那么該對象將會從系統中刪除。
5.Status
Status用於記錄對象在系統中的當前狀態信息,它也是集合類元素類型,status在一個自動處理的進程中被持久化,可以在流轉的過程中生成。
如果觀察到一個資源丟失了它的狀態(Status),則該丟失的狀態可能被重新構造。
以Pod為例,Pod的status信息主要包括conditions、containerStatuses、hostIP、phase、podIP、startTime等,其中比較重要的兩個狀態屬性如下:
(1)phase:描述對象所處的生命周期階段,phase的典型值是Pending(創建中)、Running、Active(正在運行中)或Terminated(已終結),
這幾種狀態對於不同的對象可能有輕微的差別,此外,關於當前phase附加的詳細說明可能包含在其他域中。
(2)condition:表示條件,由條件類型和狀態值組成,目前僅有一種條件類型:Ready,對應的狀態值可以為True、False或Unknown。
一個對象可以具備多種condition,而condition的狀態值也可能不斷發生變化,condition可能附帶一些信息,例如最后的探測時間或最后的轉變時間。
Kubernetes從1.14版本開始,使用OpenAPI(https://www.openapis.org)的格式對API進行查詢,其訪問地址為http://<master-ip>: <master-port>/openapi/v2。
例如,使用命令行工具curl進行查詢:
# curl http://<master-ip>: <master-port>/openapi/v2 | jq
# curl http://192.168.18.3: 8080/openapi/v2 | jq

9.2.2 Kubernetes API版本的演進策略
為了在兼容舊版本的同時不斷升級新的API,Kubernetes提供了多版本API的支持能力,每個版本的API都通過一個版本號路徑前綴進行區分,例如/api/v1beta3。
在通常情況下,新舊幾個不同的API版本都能涵蓋所有的Kubernetes資源對象,在不同的版本之間,這些API接口存在一些細微差別。
Kubernetes開發團隊基於API級別選擇版本而不是基於資源和域級別,
是為了確保API能夠清晰、連續地描述一個系統資源和行為的視圖,能夠控制訪問的整個過程和控制實驗性API的訪問。
API的版本號通常用於描述API的成熟階段,例如:
v1表示GA穩定版本;
v1beta3表示Beta版本(預發布版本);
v1alpha1表示Alpha版本(實驗性的版本)。
當某個API的實現達到一個新的GA穩定版本時(如v2),舊的GA版本(如v1)和Beta版本(例如v2beta1)將逐漸被廢棄。
Kubernetes建議廢棄的時間如下:
對於舊的GA版本(如v1),Kubernetes建議廢棄的時間應不少於12個月或3個大版本Release的時間,選擇最長的時間。
對舊的Beta版本(如v2beta1),Kubernetes建議廢棄的時間應不少於9個月或3個大版本Release的時間,選擇最長的時間。
對舊的Alpha版本,則無須等待,可以直接廢棄。
完整的API更新和廢棄策略請參考官方網站https://kubernetes.io/docs/reference/usingapi/deprecation-policy/的說明。

9.2.3 API Groups(API組)
為了更容易對API進行擴展,Kubernetes使用API Groups(API組)進行標識。
API Groups以REST URL中的路徑進行定義。
當前支持兩類API groups:
Core Groups(核心組),也可以稱之為Legacy Groups,作為Kubernetes最核心的API,其特點是沒有“組”的概念,例如“v1”,在資源對象的定義中表示為“apiVersion:v1”。
具有分組信息的API,以/apis/$GROUP_NAME/$VERSION URL路徑進行標識,在資源對象的定義中表示為“apiVersion: $GROUP_NAME/$VERSION”,
例如:“apiVersion: batch/v1”“apiVersion: extensions:v1beta1”“apiVersion: apps/v1beta1”等,
詳細的API列表請參見官網https://kubernetes.io/docs/reference,目前根據Kubernetes的不同版本有不同的API說明頁面。
例如,Pod的API說明如圖9.6所示,由於Pod屬於核心資源對象,所以不存在某個擴展API Group,頁面顯示為Core,在Pod的定義中為“apiVersion: v1”。
StatefulSet則屬於名為apps的API組,版本號為v1,在StatefulSet的定義中為“apiVersion: apps/v1”,如圖9.7所示。
如果要啟用或禁用特定的API組,則需要在API Server的啟動參數中設置--runtime-config進行聲明,
例如,--runtime-config=batch/v2alpha1表示啟用API組“batch/v2alpha1”;也可以設置--runtime-config=batch/v1=false表示禁用API組“batch/v1”。
多個API組的設置以逗號分隔。
在當前的API Server服務中,DaemonSets、Deployments、HorizontalPodAutoscalers、Ingress、Jobs和ReplicaSets所屬的API組是默認啟用的。

9.2.4 API REST的方法說明
API資源使用REST模式,對資源對象的操作方法如下:
(1)GET /<資源名的復數格式>:獲得某一類型的資源列表,例如GET /pods返回一個Pod資源列表。
(2)POST /<資源名的復數格式>:創建一個資源,該資源來自用戶提供的JSON對象。
(3)GET /<資源名復數格式>/<名稱>:通過給出的名稱獲得單個資源,例如GET/pods/first返回一個名為first的Pod。
(4)DELETE /<資源名復數格式>/<名稱>:通過給出的名稱刪除單個資源,
在刪除選項(DeleteOptions)中可以指定優雅刪除(Grace Deletion)的時間(GracePeriodSeconds),該選項表明了從服務端接收到刪除請求到資源被刪除的時間間隔(單位為s)。
不同的類別(Kind)可能為優雅刪除時間(Grace Period)聲明默認值。用戶提交的優雅刪除時間將覆蓋該默認值,包括值為0的優雅刪除時間。
(5)PUT /<資源名復數格式>/<名稱>:通過給出的資源名和客戶端提供的JSON對象來更新或創建資源。
(6)PATCH /<資源名復數格式>/<名稱>:選擇修改資源詳細指定的域。
對於PATCH操作,目前Kubernetes API通過相應的HTTP首部“Content-Type”對其進行識別。
目前支持以下三種類型的PATCH操作:
(1)JSON Patch, Content-Type: application/json-patch+json。
在RFC6902的定義中,JSON Patch是執行在資源對象上的一系列操作,例如 {"op": "add", "path": "/a/b/c", "value": ["foo","bar"]}。
詳情請查看RFC6902說明,網址為https://tools.ietf.org/html/rfc6902。
(2)Merge Patch, Content-Type: application/merge-json-patch+json。
在RFC7386的定義中,Merge Patch必須包含對一個資源對象的部分描述,這個資源對象的部分描述就是一個JSON對象。
該JSON對象被提交到服務端,並和服務端的當前對象合並,從而創建一個新的對象。
詳情請查看RFC73862說明,網址為https://tools.ietf.org/html/rfc7386。
(3)Strategic Merge Patch, Content-Type: application/strategic-merge-patch+json。
Strategic Merge Patch是一個定制化的Merge Patch實現。接下來將詳細講解Strategic Merge Patch。
在標准的JSON Merge Patch中,JSON對象總被合並(Merge),但是資源對象中的列表域總被替換,用戶通常不希望如此。
例如,我們通過下列定義創建一個Pod資源對象:
spec:
containers:
- name: nginx
image: nginx-1.0
接着,我們希望添加一個容器到這個Pod中,代碼和上傳的JSON對象如下:
PATH /api/vi/namespaces/default/pods/pod-name
spec:
containers:
- name: log-tailer
image: log-tailer-1.0
如果我們使用標准的Merge Patch,則其中的整個容器列表將被單個“log-tailer”容器所替換,然而我們的目的是使兩個容器列表合並。
為了解決這個問題,Strategic Merge Patch添加元數據到API對象中,並通過這些新元數據來決定哪個列表被合並,哪個列表不被合並。
當前這些元數據作為結構標簽,對於API對象自身來說是合法的。
對於客戶端來說,這些元數據作為Swagger annotations也是合法的。
在上述例子中向containers中添加了patchStrategy域,且它的值為merge,通過添加patchMergeKey,它的值為name。
也就是說,containers中的列表將會被合並而不是替換,合並的依據為name域的值。
此外,Kubernetes API添加了資源變動的觀察者模式的API接口。
GET /watch/<資源名復數格式>:隨時間變化,不斷接收一連串的JSON對象,這些JSON對象記錄了給定資源類別內所有資源對象的變化情況。
GET /watch/<資源名復數格式>/<name>:隨時間變化,不斷接收一連串的JSON對象,這些JSON對象記錄了某個給定資源對象的變化情況。
上述接口改變了返回數據的基本類別,watch動詞返回的是一連串JSON對象,而不是單個JSON對象。
並不是所有對象類別都支持觀察者模式的API接口,在后續的章節中將會說明哪些資源對象支持這種接口。
另外,Kubernetes還增加了HTTP Redirect與HTTP Proxy這兩種特殊的API接口,前者實現資源重定向訪問,后者則實現HTTP請求的代理。

9.2.5 API Server響應說明
API Server在響應用戶請求時附帶一個狀態碼,該狀態碼符合HTTP規范。
表9.1列出了API Server可能返回的狀態碼。
狀態碼 編碼 描述
200 OK 表明請求完全成功
201 Create 表明創建類的請求完全成功
204 NoContent 表明請求完全成功,同時HTTP響應不包含響應體。在響應OPTIONS方法的HTTP請求時返回。
307 TemporaryRedirect 表明請求資源的地址被改變,建議客戶端使用Location首部給出的臨時URL來定位資源
400 BadRequest 表明請求是非法的,建議用戶不要重試,修改該請求
401 Unauthorized 表明請求能夠到達服務端,且服務端能夠理解用戶請求,但是拒絕做更多的事情,因為客戶端必須提供認證信息。
如果客戶端提供了認證信息,則返回該狀態碼,表明服務端指出所提供的認證信息不合適或非法。
403 Forbidden 表明請求能夠到達服務端,且服務端能夠理解用戶請求,但是拒絕做更多的事情,因為該請求被設置成拒絕訪問。建議用戶不要重試,修改該請求。
404 NotFound 表明所請求得資源不存在。建議用戶不要重試,修改該請求。
405 MethodNotAllowed 表明所請求中帶有該資源不支持的方法。建議用戶不要重試,修改該請求。
409 Conflict 表明客戶端嘗試創建的資源已經存在,或者由於沖突,請求的更新操作不能被完成
422 UnprocessableEntity 表明由於所提供的作為請求部分的數據非法,創建或修改操作不能被完成。
429 TooManyRequests 表明超出了客戶端訪問頻率的限制或者服務端接收到多於它能處理的請求。建議客戶端讀取相應的Retry-After首部,然后等待該首部指出的時間后再重試。
500 InternalServerError 表明服務端能被請求訪問到,但是不能理解用戶的請求;或者在服務端內產生非預期的一個錯誤,而且該錯誤無法被認知;
或者服務端不能在一個合理的時間內完成處理(這可能是服務器臨時負載過重造成的,或和其他服務器通信時的一個臨時通信故障造成的)
503 ServiceUnavailable 表明被請求的服務無效。建議用戶不要重試,修改該請求。
504 ServiceTimeout 表明請求在給定的時間內無法完成。客戶端僅在為請求指定超時(Timeout)參數時得到該響應。
在調用API接口發生錯誤時,Kubernetes將會返回一個狀態類別(Status Kind)。
下面是兩種常見的錯誤場景:
(1)當一個操作不成功時(例如,當服務端返回一個非2xx HTTP狀態碼時)。
(2)當一個HTTP DELETE方法調用失敗時。
狀態對象被編碼成JSON格式,同時該JSON對象被作為請求的響應體。
該狀態對象包含人和機器使用的域,在這些域中包含來自API的關於失敗原因的詳細信息。
狀態對象中的信息補充了對HTTP狀態碼的說明。
例如:
# curl -v -k -H "Authorization: Bearer admin" https://10.240.122.184:443/api/v1/namespaces/default/pods/grafana
輸出:
{
"apiVersion": "v1",
"kind": "Status",
"metadata": {},
"status": "Failure",
"message": "pods \"grafana \"not found",
"reason": "NotFound",
"details": {
"name": "grafana",
"kind": "pods"
},
"code": 404
}
其中:
status域包含兩個可能的值:Success或Failure。
message域包含對錯誤的描述信息。
reason域包含說明該操作失敗原因的描述。
details可能包含和reason域相關的擴展數據。每個reason域都可以定義它的擴展的details域。該域是可選的,返回數據的格式是不確定的,不同的reason類型返回的details域的內容不一樣。

9.3 使用Java程序訪問Kubernetes API
本節介紹如何使用Java程序訪問Kubernetes API。
在Kubernetes官網上列出了多個訪問Kubernetes API的開源項目,其中有兩個是用Java語言開發的開源項目,一個是OSGI,另一個是Fabric8。
在本節所列的兩個Java開發例子中,一個是基於Jersey的,另一個是基於Fabric8的。

9.3.1 Jersey
Jersey是一個RESTful請求服務Java框架。與Struts類似,它可以和Hibernate、Spring框架整合。
我們不僅能很方便地通過它開發RESTful Web Service,還可以將它作為客戶端方便地訪問RESTful Web Service服務端。
如果沒有一個好的工具包,則很難開發一個能夠用不同的媒介(Media)類型無縫地暴露你的數據,以及很好地抽象客戶端、服務端通信的底層通信的RESTful Web Services。
為了能夠簡化使用Java開發RESTful Web Service及其客戶端的流程,業界設計了JAX-RS API。
Jersey RESTful Web Services框架是一個開源的高質量的框架,它為用Java語言開發RESTful Web Service及其客戶端而生,支持JAX-RS APIs。
Jersey不僅支持JAX-RS APIs,而且在此基礎上擴展了API接口,這些擴展更加方便並簡化了RESTful Web Services及其客戶端的開發。
由於Kubernetes API Server是RESTful Web Service,因此此處選用Jersey框架開發RESTful Web Service客戶端,用來訪問Kubernetes API。
在本例中選用的Jersey框架的版本為1.19,所涉及的Jar包如圖9.8所示。
對Kubernetes API的訪問包含如下3個方面:
(1)指明訪問資源的類型。
(2)訪問時的一些選項(參數),比如命名空間、對象的名稱、過濾方式(標簽和域)、子目錄、訪問的目標是否是代理和是否用watch方式訪問等。
(3)訪問的方法,比如增、刪、改、查。
在使用Jersey框架訪問Kubernetes API之前,我們需要為這3個方面定義3個對象。
第1個定義的對象是ResourceType,它定義了訪問資源的類型;
第2個定義的對象是Params,它定義了訪問API時的一些選項,以及通過這些選項如何生成完整的URL;
第3個定義的對象是RestfulClient,它是一個接口,該接口定義了訪問API的方法(Method)。
(1)ResourceType是一個ENUM類型的對象,定義了Kubernetes的各種資源對象類型,代碼如下:
(2)Params定義訪問API時的選項及通過這些選項如何生成完整的URL,代碼如下:
Params對象包含的屬性說明如表9.2所示。
(3)接口對象RestfulClient定義了訪問API接口的所有方法,其代碼如下:
其中,get和list方法對應Kubernetes API的GET方法;create方法對應API中的POST方法;
delete方法對應API中的DELETE方法;update方法對應API中的PATCH方法;
replace方法對應API中的PUT方法;options方法對應API中的OPTIONS方法;head方法對應API中的HEAD方法。
該接口基於Jersey框架的實現類如下:
在該對象中包含如下代碼:
該段代碼的作用是使Jersey客戶端支持除標准REST方法外的方法,比如PATCH方法。
該段代碼能訪問除watcher外的所有Kubernetes API接口,在后續的章節中會舉例說明如何訪問Kubernetes API。

9.3.2 Fabric8
Fabric8包含多款工具包,Kubernetes Client只是其中之一,也是在Kubernetes官網中提到的Java Client API之一。
本例代碼涉及的Jar包如圖9.9所示。
因為該工具包已經對訪問Kubernetes API客戶端做了較好的封裝,因此其訪問代碼比較簡單,其具體的訪問過程會在后續的章節舉例說明。
Fabric 8的Kubernetes API客戶端工具包只能訪問Node、Service、Pod、Endpoints、Events、Namespace、PersistenetVolumeclaims、PersistenetVolume、
ReplicationController、ResourceQuota、Secret和ServiceAccount這幾種資源類型,
不能使用OPTIONS和HEAD方法訪問資源,且不能以代理方式訪問資源,但其對以watcher方式訪問資源做了很好的支持。

9.3.3 使用說明
首先,舉例說明對API資源的基本訪問,也就是對資源的增、刪、改、查,以及替換資源的status。
其中會單獨對Node和Pod的特殊接口做舉例說明。
表9.3列出了各資源對象的基本接口。
首先,舉例說明如何通過API接口來創建資源對象。
我們需要創建訪問API Server的客戶端,其中,http://192.168.1.128:8080為API Server的地址。
基於Jersey框架的代碼如下:
RestfulClient_restfulClient = new JerseyRestfulClient("http://192.168.1.128:8080/api/v1");
基於Fabric8框架的代碼如下:
Config_conf = new Config();
KubernetesClient_kube = new DefultKubernetesClient("http://192.168.1.128:8080");
分別通過上面的兩個客戶端創建Namespace資源對象,
基於Jersey框架的代碼如下:
其中,“namespace.json”為創建Namespace資源對象的JSON定義,代碼如下:
基於Fabric8框架的代碼如下:
由於Fabric8框架對Kubernetes API對象做了很好的封裝,對其中的大量對象都做了定義,
所以用戶可以通過其提供的資源對象去定義Kubernetes API對象,例如上面例子中的Namespace對象。
Fabric8框架中的kubernetes-model工具包用於API對象的封裝。
在上面的例子中,通過Fabric8框架提供的類創建了一個名為ns-fabric8的命名空間對象。
接下來會通過基於Jeysey框架的代碼創建兩個Pod資源對象。
在兩個例子中,一個是在上面創建的“ns-sample”Namespace中創建Pod資源對象,另一個是為后續創建“cluster service”創建的Pod資源對象。
由於基於Fabric8框架創建Pod資源對象的方法很簡單,因此不再用Fabric8框架對上述兩個例子做說明。
通過基於Jersey框架創建這兩個Pod資源對象的代碼如下:
其中,podInNs.json和pod4ClusterService.json是創建兩個Pod資源對象的定義。
podInNs.json文件的內容如下:
pod4ClusterService.json文件的內容如下:
下面的例子代碼用於獲取Pod資源列表,
其中,第1部分代碼用於獲取所有的Pod資源對象,第2、3部分代碼主要用於說明如何使用標簽選擇Pod資源對象,
最后一部分代碼用於舉例說明如何使用field選擇Pod資源對象。
代碼如下:
接下來的例子代碼用於替換一個Pod對象,在通過Kubernetes API替換一個Pod資源對象時需要注意如下兩點:
(1)在替換該資源對象前,先從API中獲取該資源對象的JSON對象,然后在該JSON對象的基礎上修改需要替換的部分。
(2)在Kubernetes API提供的接口中,PUT方法(replace)只支持替換容器的image部分。
代碼如下:
其中,pod4Replace.json的內容如下:
接下來的兩個例子實現了在9.2.4節中提到的兩種Merge方式:Merge Patch和Strategic Merge Patch。
Merge Patch的示例如下:
其中,pod4MergeJsonPatch.json的內容如下:
Strategic Merge Patch的示例如下:
其中,pod4StrategicMerge.json的內容如下:
接下來實現了修改Pod資源對象的狀態,代碼如下:
其中,pod4Status.json的內容如下:
接下來實現了查看Pod的log日志功能,代碼如下:
下面通過API訪問Node的多種接口,代碼如下:
最后,舉例說明如何通過API刪除資源對象pod,代碼如下:
通過API接口除了能夠對資源對象實現前面列出的基本操作,還涉及兩類特殊接口,一類是WATCH,一類是PROXY。
這兩類特殊接口所包含的接口如表9.4所示。
下面基於Fabric8實現對資源對象的監聽,代碼如下:
接下來基於Jersey框架實現通過Proxy方式訪問Pod。
由於API Server針對Pod資源提供了兩種Proxy訪問接口,所以下面分別用兩段代碼進行示例說明。代碼如下:

9.3.4 其他客戶端庫
為了讓開發人員更方便地訪問Kubernetes的RESTful API,Kubernetes社區推出了針對Go、Python、Java、dotNet、JavaScript等編程語言的客戶端庫,
這些庫由特別興趣小組(SIG)API Machinary維護,其官方網站為https://github.com/kubernetes/community/tree/master/sig-api-machinery。
目前Kubernetes官方支持的客戶端庫如表9.5所示。
此外,Kubernetes社區也在開發和維護基於其他開發語言的客戶端庫,如9.6所示。

9.4 Kubernetes API的擴展
隨着Kubernetes的發展,用戶對Kubernetes的擴展性也提出了越來越高的要求。
從1.7版本開始,Kubernetes引入擴展API資源的能力,
使得開發人員在不修改Kubernetes核心代碼的前提下可以對Kubernetes API進行擴展,仍然使用Kubernetes的語法對新增的API進行操作,
這非常適用於在Kubernetes上通過其API實現其他功能(例如第三方性能指標采集服務)或者測試實驗性新特性(例如外部設備驅動)。
在Kubernetes中,所有對象都被抽象定義為某種資源對象,同時系統會為其設置一個API入口(API Endpoint),
對資源對象的操作(如新增、刪除、修改、查看等)都需要通過Master的核心組件API Server調用資源對象的API來完成。
與API Server的交互可以通過kubectl命令行工具或訪問其RESTful API進行。
每個API都可以設置多個版本,在不同的API URL路徑下區分,例如“/api/v1”或“/apis/extensions/v1beta1”等。
使用這種機制后,用戶可以很方便地定義這些API資源對象(YAML配置),並將其提交給Kubernetes(調用RESTful API),來完成對容器應用的各種管理工作。
Kubernetes系統內置的Pod、RC、Service、ConfigMap、Volume等資源對象已經能夠滿足常見的容器應用管理要求,
但如果用戶希望將其自行開發的第三方系統納入Kubernetes,並使用Kubernetes的API對其自定義的功能或配置進行管理,就需要對API進行擴展了。
目前Kubernetes提供了以下兩種機制供用戶擴展API:
(1)使用CRD機制:復用Kubernetes的API Server,無須編寫額外的API Server。
用戶只需要定義CRD,並且提供一個CRD控制器,就能通過Kubernetes的API管理自定義資源對象了,同時要求用戶的CRD對象符合API Server的管理規范。
(2)使用API聚合機制:用戶需要編寫額外的API Server,可以對資源進行更細粒度的控制(例如,如何在各API版本之間切換),要求用戶自行處理對多個API版本的支持。
本節主要對CRD和API聚合這兩種API擴展機制的概念和用法進行詳細說明。

9.4.1 使用CRD擴展API資源
CRD是Kubernetes從1.7版本開始引入的特性,在Kubernetes早期版本中被稱為TPR(ThirdPartyResources,第三方資源)。
TPR從Kubernetes 1.8版本開始被停用,被CRD全面替換。
CRD本身只是一段聲明,用於定義用戶自定義的資源對象。
但僅有CRD的定義並沒有實際作用,用戶還需要提供管理CRD對象的CRD控制器(CRD Controller),才能實現對CRD對象的管理。
CRD控制器通常可以通過Go語言進行開發,並需要遵循Kubernetes的控制器開發規范,基於客戶端庫client-go進行開發,
需要實現Informer、ResourceEventHandler、Workqueue等組件具體的功能處理邏輯,
詳細的開發過程請參考官方示例(https://github.com/kubernetes/sample-controller)
和client-go庫(https://github.com/kubernetes/sample-controller/blob/master/docs/controller-client-go.md)的詳細說明。
1.創建CRD的定義
與其他資源對象一樣,對CRD的定義也使用YAML配置進行聲明。
以Istio系統中的自定義資源VirtualService為例,配置文件crd-virtualservice.yaml的內容如下:
CRD定義中的關鍵字段如下:
(1)group:設置API所屬的組,將其映射為API URL中“/apis/”的下一級目錄,設置networking.istio.io生成的API URL路徑為“/apis/networking.istio.io”。
(2)scope:該API的生效范圍,可選項為Namespaced(由Namespace限定)和Cluster(在集群范圍全局生效,不局限於任何Namespace),默認值為Namespaced。
(3)versions:設置此CRD支持的版本,可以設置多個版本,用列表形式表示。
目前還可以設置名為version的字段,只能設置一個版本,在將來的Kubernetes版本中會被棄用,建議使用versions進行設置。
如果該CRD支持多個版本,則每個版本都會在API URL“/apis/networking.istio.io”的下一級進行體現,例如“/apis/networking.istio.io/v1”或“/apis/networking.istio.io/v1alpha3”等。
每個版本都可以設置下列參數:
name:版本的名稱,例如v1、v1alpha3等。
served:是否啟用,在被設置為true時表示啟用。
storage:是否進行存儲,只能有一個版本被設置為true。
(4)names:CRD的名稱,包括單數、復數、kind、所屬組等名稱的定義,可以設置如下參數。
kind:CRD的資源類型名稱,要求以駝峰式命名規范進行命名(單詞的首字母都大寫),例如VirtualService。
listKind:CRD列表,默認被設置為<kind>List格式,例如VirtualServiceList。
singular:單數形式的名稱,要求全部小寫,例如virtualservice。
plural:復數形式的名稱,要求全部小寫,例如virtualservices。
shortNames:縮寫形式的名稱,要求全部小寫,例如vs。
categories:CRD所屬的資源組列表。例如,VirtualService屬於istio-io組和networking-istio-io組,用戶通過查詢istio-io組和networking-istio-io組,也可以查詢到該CRD實例。
使用kubectl create命令完成CRD的創建:
# kubectl create -f crd-virtualservice.yaml
在CRD創建成功后,由於本例的scope設置了Namespace限定,所以可以通過API Endpoint“/apis/networking.istio.io/v1alpha3/namespaces/<namespace>/virtualservices/”管理該CRD資源。
用戶接下來就可以基於該CRD的定義創建相應的自定義資源對象了。

2.基於CRD的定義創建自定義資源對象
基於CRD的定義,用戶可以像創建Kubernetes系統內置的資源對象(如Pod)一樣創建CRD資源對象。
在下面的例子中,virtualservice-helloworld.yaml定義了一個類型為VirtualService的資源對象:
apiVersion: networking.istio.io/vlalpha3
king: VirtualService
metadata:
name: helloworld
spec:
...
除了需要設置該CRD資源對象的名稱,還需要在spec段設置相應的參數。
在spec中可以設置的字段是由CRD開發者自定義的,需要根據CRD開發者提供的手冊進行配置。
這些參數通常包含特定的業務含義,由CRD控制器進行處理。
使用kubectl create命令完成CRD資源對象的創建:
# kubectl create -f virtualservice-helloworld.yaml
然后,用戶就可以像操作Kubernetes內置的資源對象(如Pod、RC、Service)一樣去操作CRD資源對象了,包括查看、更新、刪除和watch等操作。
查看CRD資源對象:
# kubectl get virtualservice
也可以通過CRD所屬的categories進行查詢:
# kubectl get istio-io

3.CRD的高級特性
隨着Kubernetes的演進,CRD也在逐步添加一些高級特性和功能,包括subresources子資源、校驗(Validation)機制、自定義查看CRD時需要顯示的列,以及finalizer預刪除鈎子。
(1)CRD的subresources子資源
Kubernetes從1.11版本開始,在CRD的定義中引入了名為subresources的配置,可以設置的選項包括status和scale兩類:
stcatus:啟用/status路徑,其值來自CRD的.status字段,要求CRD控制器能夠設置和更新這個字段的值。
scale:啟用/scale路徑,支持通過其他Kubernetes控制器(如HorizontalPodAutoscaler控制器)與CRD資源對象實例進行交互。
用戶通過kubectl scale命令也能對該CRD資源對象進行擴容或縮容操作,要求CRD本身支持以多個副本的形式運行。
下面是一個設置了subresources的CRD示例:
基於該CRD的定義,創建一個自定義資源對象my-crontab.yaml:
apiVersion: "stable.example.com/v1"
king: CronTab
metadata:
name: my-new-cron-object
spec:
cronSpec: "* * * * */5"
image: my-awesome-cron-image
replicas: 3
之后就能通過API Endpoint查看該資源對象的狀態了:
/apis/stable.example.com/v1/namespaces/<namespace>/crontabs/status
並查看該資源對象的擴縮容(scale)信息:
/apis/stable.example.com/v1/namespaces/<namespace>/crontabs/scale
用戶還可以使用kubectl scale命令對Pod的副本數量進行調整,例如:
# kubectl scale --replicas=5 crontabs/my-new-cron-object

(2)CRD的校驗(Validation)機制
Kubernetes從1.8版本開始引入了基於OpenAPI v3 schema或validatingadmissionwebhook的校驗機制,用於校驗用戶提交的CRD資源對象配置是否符合預定義的校驗規則。
該機制到Kubernetes 1.13版本時升級為Beta版。
要使用該功能,需要為kube-apiserver服務開啟--feature-gates=CustomResourceValidation=true特性開關。
下面的例子為CRD定義中的兩個字段(cronSpec和replicas)設置了校驗規則:
校驗規則如下:
spec.cronSpec:必須為字符串類型,並且滿足正則表達式的格式。
spec.replicas:必須將其設置為1~10的整數。
對於不符合要求的CRD資源對象定義,系統將拒絕創建。
例如,下面的my-crontab.yaml示例違反了CRD中validation設置的校驗規則,即cronSpec沒有滿足正則表達式的格式,replicas的值大於10:
apiVersion: "stable.example.com/v1"
king: CronTab
metadata:
name: my-new-cron-object
spec:
cronSpec: "* * * * */5"
image: my-awesome-cron-image
replicas: 15
創建時,系統將報出validation失敗的錯誤信息:
# kubectl create -f my-crontab.yaml

(3)自定義查看CRD時需要顯示的列
從Kubernetes 1.11版本開始,通過kubectl get命令能夠顯示哪些字段由服務端(API Server)決定,
還支持在CRD中設置需要在查看(get)時顯示的自定義列,在spec.additionalPrinterColumns字段設置即可。
在下面的例子中設置了3個需要顯示的自定義列Spec、Replicas和Age,並在JSONPath字段設置了自定義列的數據來源:
通過kubectl get命令查看CronTab資源對象,會顯示出這3個自定義的列:
# kubectl get crontab my-new-cron-object

(4)Finalizer(CRD資源對象的預刪除鈎子方法)
Finalizer設置的方法在刪除CRD資源對象時進行調用,以實現CRD資源對象的清理工作。
在下面的例子中為CRD“CronTab”設置了一個finalizer(也可以設置多個),其值為URL“finalizer.stable.example.com”:
apiVersion: "stable.example.com/v1"
king: CronTab
metadata:
finalizers:
- finalizer.stable.example.com
在用戶發起刪除該資源對象的請求時,Kubernetes不會直接刪除這個資源對象,而是在元數據部分設置時間戳“metadata.deletionTimestamp”的值,標記為開始刪除該CRD對象。
然后控制器開始執行finalizer定義的鈎子方法“finalizer.stable.example.com”進行清理工作。
對於耗時較長的清理操作,還可以設置metadata.deletionGracePeriodSeconds超時時間,在超過這個時間后由系統強制終止鈎子方法的執行。
在控制器執行完鈎子方法后,控制器應負責刪除相應的finalizer。
當全部finalizer都觸發控制器執行鈎子方法並都被刪除之后,Kubernetes才會最終刪除該CRD資源對象。

4.小結
CRD極大擴展了Kubernetes的能力,使用戶像操作Pod一樣操作自定義的各種資源對象。
CRD已經在一些基於Kubernetes的第三方開源項目中得到廣泛應用,
包括CSI存儲插件、Device Plugin(GPU驅動程序)、Istio(Service Mesh管理)等,已經逐漸成為擴展Kubernetes能力的標准。

9.4.2 使用API聚合機制擴展API資源
API聚合機制是Kubernetes 1.7版本引入的特性,能夠將用戶擴展的API注冊到kube-apiserver上,仍然通過API Server的HTTP URL對新的API進行訪問和操作。
為了實現這個機制,Kubernetes在kube-apiserver服務中引入了一個API聚合層(API Aggregation Layer),用於將擴展API的訪問請求轉發到用戶服務的功能。
設計API聚合機制的主要目標如下:
增加API的擴展性:使得開發人員可以編寫自己的API Server來發布他們的API,而無須對Kubernetes核心代碼進行任何修改。
無須等待Kubernetes核心團隊的繁雜審查:允許開發人員將其API作為單獨的API Server發布,使集群管理員不用對Kubernetes核心代碼進行修改就能使用新的API,也就無須等待社區繁雜的審查了。
支持實驗性新特性API開發:可以在獨立的API聚合服務中開發新的API,不影響系統現有的功能。
確保新的API遵循Kubernetes的規范:如果沒有API聚合機制,開發人員就可能會被迫推出自己的設計,可能不遵循Kubernetes規范。
總的來說,API聚合機制的目標是提供集中的API發現機制和安全的代理功能,將開發人員的新API動態地、無縫地注冊到Kubernetes API Server中進行測試和使用。

下面對API聚合機制的使用方式進行詳細說明。
1.在Master的API Server中啟用API聚合功能
為了能夠將用戶自定義的API注冊到Master的API Server中,首先需要配置kube-apiserver服務的以下啟動參數來啟用API聚合功能。
--requestheader-client-ca-file=/etc/kubernetes/ssl_keys/ca.crt:客戶端CA證書。
--requestheader-allowed-names=:允許訪問的客戶端common names列表,通過header中--requestheader-username-headers參數指定的字段獲取。
客戶端common names的名稱需要在client-ca-file中進行設置,將其設置為空值時,表示任意客戶端都可訪問。
--requestheader-extra-headers-prefix=X-Remote-Extra-:請求頭中需要檢查的前綴名。
--requestheader-group-headers=X-Remote-Group:請求頭中需要檢查的組名。
--requestheader-username-headers=X-Remote-User:請求頭中需要檢查的用戶名。
--proxy-client-cert-file=/etc/kubernetes/ssl_keys/kubelet_client.crt:在請求期間驗證Aggregator的客戶端CA證書。
--proxy-client-key-file=/etc/kubernetes/ssl_keys/kubelet_client.key:在請求期間驗證Aggregator的客戶端私鑰。
如果kube-apiserver所在的主機上沒有運行kube-proxy,即無法通過服務的ClusterIP進行訪問,那么還需要設置以下啟動參數:
--enable-aggregator-routing=true
在設置完成重啟kube-apiserver服務,就啟用API聚合功能了。

2.注冊自定義APIService資源
在啟用了API Server的API聚合功能之后,用戶就能將自定義API資源注冊到Kubernetes Master的API Server中了。
用戶只需配置一個APIService資源對象,就能進行注冊了。
APIService示例的YAML配置文件如下:
apiVersion: apiregistration.k8s.io/v1beta1
king: APIService
metadata:
name: v1beta1.custom.metrics.k8s.io
spec:
...
在這個APIService中設置的API組名為custom.metrics.k8s.io,版本號為v1beta1,這兩個字段將作為API路徑的子目錄注冊到API路徑“/apis/”下。
注冊成功后,就能通過Master API路徑“/apis/custom.metrics.k8s.io/v1beta1”訪問自定義的API Server了。
在service段中通過name和namespace設置了后端的自定義API Server,本例中的服務名為custom-metrics-server,命名空間為custom-metrics。
通過kubectl create命令將這個APIService定義發送給Master,就完成了注冊操作。
之后,通過Master API Server對“/apis/custom.metrics.k8s.io/v1beta1”路徑的訪問都會被API聚合層代理轉發到后端服務custom-metrics-server.custom-metrics.svc上了。

3.實現和部署自定義API Server
僅僅注冊APIService資源還是不夠的,用戶對“/apis/custom.metrics.k8s.io/v1beta1”路徑的訪問實際上都被轉發給了custom-metrics-server.custom-metrics.svc服務。
這個服務通常能以普通Pod的形式在Kubernetes集群中運行。
當然,這個服務需要由自定義API的開發者提供,並且需要遵循Kubernetes的開發規范,
詳細的開發示例可以參考官方給出的示例(https://github.com/kubernetes/sample-apiserver)。
下面是部署自定義API Server的常規操作步驟:
(1)確保APIService API已啟用,這需要通過kube-apiserver的啟動參數--runtime-config進行設置,默認是啟用的。
(2)建議創建一個RBAC規則,允許添加APIService資源對象,因為API擴展對整個Kubernetes集群都生效,所以不推薦在生產環境中對API擴展進行開發或測試。
(3)創建一個新的Namespace用於運行擴展的API Server。
(4)創建一個CA證書用於對自定義API Server的HTTPS安全訪問進行簽名。
(5)創建服務端證書和秘鑰用於自定義API Server的HTTPS安全訪問。服務端證書應該由上面提及的CA證書進行簽名,也應該包含含有DNS域名格式的CN名稱。
(6)在新的Namespace中使用服務端證書和秘鑰創建Kubernetes Secret對象。
(7)部署自定義API Server實例,通常可以以Deployment形式進行部署,並且將之前創建的Secret掛載到容器內部。該Deployment也應被部署在新的Namespace中。
(8)確保自定義的API Server通過Volume加載了Secret中的證書,這將用於后續的HTTPS握手校驗。
(9)在新的Namespace中創建一個Service Account對象。
(10)創建一個ClusterRole用於對自定義API資源進行操作。
(11)使用之前創建的ServiceAccount為剛剛創建的ClusterRole創建一個ClusterRolebinding。
(12)使用之前創建的ServiceAccount為系統ClusterRole“system:auth-delegator”創建一個ClusterRolebinding,以使其可以將認證決策代理轉發給Kubernetes核心API Server。
(13)使用之前創建的ServiceAccount為系統Role“extension-apiserver-authenticationreader”創建一個Rolebinding,以允許自定義API Server訪問名為“extension-apiserverauthentication”的系統ConfigMap。
(14)創建APIService資源對象。
(15)訪問APIService提供的API URL路徑,驗證對資源的訪問能否成功。
下面以部署Metrics Server為例,說明一個聚合API的實現方式。
隨着API聚合機制的出現,Heapster也進入棄用階段,逐漸被Metrics Server替代。
Metrics Server通過聚合API提供Pod和Node的資源使用數據,供HPA控制器、VPA控制器及kubectl top命令使用。
Metrics Server的源碼可以在GitHub代碼庫(https://github.com/kubernetes-incubator/metrics-server)找到,
在部署完成后,Metrics Server將通過Kubernetes核心API Server的“/apis/metrics.k8s.io/v1beta1”路徑提供Pod和Node的監控數據。
首先,部署Metrics Server實例,在下面的YAML配置中包含一個ServiceAccount、一個Deployment和一個Service的定義:
然后,創建Metrics Server所需的RBAC權限配置:
最后,定義APIService資源,主要設置自定義API的組(group)、版本號(version)及對應的服務(metrics-server.kube-system):
在所有資源都成功創建之后,在命名空間kube-system中會看到新建的metrics-server Pod。
通過Kubernetes Master API Server的URL“/apis/metrics.k8s.io/v1beta1”就能查詢到Metrics Server提供的Pod和Node的性能數據了:
# curl http://192.168.18.3:8080/apis/metrics.k8s.io/v1beta1/nodes


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM