了解有關 Kube.NETes 可擴展性的更多信息。
Kubernetes 提供了很多好處:擁有大量參與者、自我修復能力等的巨大生態系統。不過,沒有免費的午餐。它也有缺點,其中最主要的是它的復雜性和運營成本。
但是,我使用 Kubernetes 的次數越多,我就越認為它最重要的資產是可擴展性。如果您需要平臺默認不提供的東西,可以選擇自己開發并集成它。在這篇文章中,我想列出這些擴展點。
Kubernetes 101
很多關于 Kubernetes 的解釋都集中在架構上。我相信他們進入了太多細節而錯過了大局。在這里,我只想強調基本概念。
在最基本的層面上,Kubernetes 只是一個能夠運行容器鏡像的平臺。它將其配置存儲在分布式存儲引擎中,etcd. 此配置的最重要部分專用于對象的所需狀態。例如,您僅在使用kubectl命令行調度 pod 時才更新此狀態。
稱為控制器的其他組件監視配置更改并讀取所需的狀態。然后,他們嘗試使期望狀態與實際狀態相協調。這沒有什么革命性的:Puppet 基于相同的控制回路方法,而 AFAIK,Chef。通常,控制器管理單一類型的對象,例如管理DeploymentController部署。
制作通用工具背后的想法是遵循帕累托定律:用 20% 的努力解決 80% 的問題。不幸的是,工具越通用,用戶群越廣泛,定制剩余 20% 的工作量就越大。
Kubernetes 設計人員將此問題視為廣泛采用的最關鍵障礙。因此,Kubernetes 提供了許多擴展點。
可擴展模型
在上面的部分中,我提到了調度一個 pod。Pod 是 Kubernetes 開箱即用的眾多對象之一。其他對象包括部署、作業、服務等。
一些解決方案很容易適合這個模型。例如,可以輕松創建三個 Hazelcast pod 的部署。它開箱即用:Pod 將通過網絡進行多播、找到彼此并形成一個集群。
其他解決方案不是那么均勻。在KIP-500之前,Kafka 將依賴 Zookeeper。At cluster 由至少三個 Zookeeper 節點和所需數量的 Kafka 節點組成。Kubernetes 使得在同一個 pod 上部署多個鏡像成為可能。然而,如果所有必需的組件都在同一個 pod 上,而 pod 出現故障,那它就等于沒有。我們應該將一個常規組件映射到一個 pod。
在這種情況下,我們需要一個功能齊全的 Kubernetes 清單來描述架構。由于要求不同,我們需要使其可配置。Kubernetes 的生態系統提供了多種解決方案來解決這個問題:Kustomize和Helm count 是最流行的解決方案之一。但兩者都不能在所需的抽象級別上工作,即 Kafka 集群。
因此,Kubernetes 允許設計一個新Kafka對象。這種自定義對象稱為CRD。這是一個簡單的任意Foo對象的示例:
apiVersion: apiextensions.k8s.io/v1 #1
kind: CustomResourceDefinition
metadata:
name: foos.frankel.ch #2
spec:
group: frankel.ch #3
names:
plural: foos #4
singular: foo #5
kind: Foo #6
scope: Namespaced #7
versions:
- name: v1alpha1
served: true #8
storage: true #9
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
bar:
type: string
required: ["bar"]
required: ["spec"]
- 必需的標頭
- 符合以下.
- REST API 的組名 -/apis//
- REST API 的復數名稱 -/apis///
- 用于 CLI 和顯示的單數名稱
- 在清單中使用
- 可以是Cluster或Namespaced。一個Cluster資源在集群范圍內聲明,每個集群可以有一個資源;Namespaced資源可以是多個,并且需要在一個命名空間下;默認,default
- 可以啟用/禁用一個版本
- 最新版本必須標記為存儲版本
應用此清單后,您可以管理您的Foo. 讓我們創建一個清單來創建一個新Foo對象。
apiVersion: foos.frankel.ch/v1alpha1
kind: Foo
metadata:
name: myfoo
spec:
bar: "whatever"
kubectl Apply -f foo.yml
kubectl get foo
上面的命令已經用新Foo類型更新了數據模型并創建了一個Foo對象。但實際上,我們只是etcd通過 Kubernetes API 存儲數據。在我們啟動一個控制器來監視新對象并對其進行操作之前,什么都不會發生。請注意,管理 CRD 的控制器的名稱是operator。
可擴展驗證
可以運行第三方工作負載的平臺的一個常見問題是只允許經過審查的工作負載。一些工作負載可能會消耗過多的資源;其他人可能是惡意的。
這里有兩個具體的場景:
- 作為集群操作員,您希望管理集群的有限物理資源(CPU/內存)并在所有 pod 之間共享它們。為此,您希望強制每個 pod 描述其資源需求。開發人員通過設置request和limits屬性來實現這一點。您想禁止沒有它們的 pod。
- 作為具有安全意識的操作員,您希望防止特權升級。它不應該改變 pod 的最終行為。您想將 添加allowPrivilegeEscalation=false到每個 pod。
雖然可以通過“構建”管道管理這兩種情況,但 Kubernetes 提供了一種開箱即用的解決方案。
正如我上面解釋的,Kubernetes 存儲配置是etcd在控制器觀察變化并對其采取行動的時候。為了防止不需要的行為,最安全的方法是驗證更改配置的有效負載;這是準入控制器的角色。
準入控制器是一段代碼,它在對象持久化之前截取對 Kubernetes API 服務器的請求,但在請求經過身份驗證和授權之后。控制器由以下列表組成,被編譯成 kube-apiserver 二進制文件,并且只能由集群管理員配置。在該列表中,有兩個特殊的控制器:MutatingAdmissionWebhook和ValidatingAdmissionWebhook. 它們執行在 API 中配置的變異和驗證(分別)準入控制 webhook。
--使用準入控制器
簡而言之,有兩種準入控制器可用:
- 驗證準入 webhook 允許/阻止請求更改狀態
- mutating admission webhook 改變了請求
它們按照下圖依次運行:
從Kubernetes 準入控制器指南
每個都可以解決上面突出顯示的場景。
可擴展的客戶端功能
在最基本的層面上,kubectl命令行是 REST 客戶端的高級抽象。您可以通過設置詳細選項來驗證它:
kubectl get pods --v=8
:http://kubernetes.io/docs/user-guide/identifiers#names","優先級":0},loader.go:372] Config loaded from file: /Users/nico/.kube/config
round_trippers.go:463] GET https://127.0.0.1:61378/api/v1/namespaces/default/pods?limit=500
round_trippers.go:469] Request Headers:
round_trippers.go:473] Accept: application/json;as=Table;v=v1;g=meta.k8s.io,application/json;as=Table;v=v1beta1;g=meta.k8s.io,application/json
round_trippers.go:473] User-Agent: kubectl/v1.24.2 (darwin/arm64) kubernetes/f66044f
round_trippers.go:574] Response Status: 200 OK in 8 milliseconds
round_trippers.go:577] Response Headers:
round_trippers.go:580] Cache-Control: no-cache, private
round_trippers.go:580] Content-Type: application/json
round_trippers.go:580] X-Kubernetes-Pf-Flowschema-Uid: 479e2d49-7b9f-4e4c-8fca-63c273cfb525
round_trippers.go:580] X-Kubernetes-Pf-Prioritylevel-Uid: 4787583d-e7d4-4679-a474-ebb66919a43c
round_trippers.go:580] Date: Sun, 04 Sep 2022 09:32:39 GMT
round_trippers.go:580] Audit-Id: 2f2f163d-fb6d-4149-ba44-ecf4395028aa
request.go:1073] Response Body: {"kind":"Table","apiVersion":"meta.k8s.io/v1","metadata":{"resourceVersion":"263411"},"columnDefinitions":[{"name":"Name","type":"string","format":"name","description":"Name must be unique within a namespace. Is required when creating resources, although some resources may allow a client to request the generation of an appropriate name automatically. Name is primarily intended for creation idempotence and configuration definition. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/identifiers#names","priority":0},{"name":"Ready","type":"string","format":"","description":"The aggregate readiness state of this pod for accepting traffic.","priority":0},{"name":"Status","type":"string","format":"","description":"The aggregate status of the containers in this pod.","priority":0},{"name":"Restarts","type":"string","format":"","description":"The number of times the containers in this pod have been restarted and when the last container in this pod has restarted.","priority":0},{"name":"Age","type":"st [truncated 6465 chars]
Kubernetes 的 REST API(大部分?)基于CRUD操作。有時,您需要運行多個命令才能獲得所需的結果。例如,我們想查詢哪些主體可以執行一個動作。
kubectl包括一種編寫代碼來編排這些調用的機制。該機制與 Gits 非常相似:
- 您根據特定格式編寫代碼 -插件
- 你在你的PATH變量中設置它
從這一點,kubectl可以發現它。
你可以在你的機器上管理你的插件,但這種方法不能擴展到整個組織。解決方案是插件管理器。認識Krew:
Krew 是kubectl命令行工具的插件管理器。
Krew幫助您:——Krew是什么?
- 發現kubectl插件,
- 將它們安裝在您的機器上,
- 并保持安裝的插件是最新的。
關于哪些主體可以執行一個動作,這里是如何做到的:
brew install krew #1
kubectl krew completion #2
# follow instructions to update your shell
kubectl krew update #3
kubectl krew install who-can #4
k who-can watch pod #5
- brew在 mac 上安裝
- 顯示自動完成指令
- 更新緩存的插件列表
- 安裝who-can克魯插件
- 享受!
No subjects found with permissions to watch pod assigned through RoleBindings
CLUSTERROLEBINDING SUBJECT TYPE SA-NAMESPACE
apisix-clusterrolebinding apisix-ingress-controller ServiceAccount ingress-apisix
cluster-admin system:masters Group
local-path-provisioner-bind local-path-provisioner-service-account ServiceAccount local-path-storage
system:controller:attachdetach-controller attachdetach-controller ServiceAccount kube-system
system:controller:daemon-set-controller daemon-set-controller ServiceAccount kube-system
system:controller:deployment-controller deployment-controller ServiceAccount kube-system
system:controller:endpoint-controller endpoint-controller ServiceAccount kube-system
system:controller:endpointslice-controller endpointslice-controller ServiceAccount kube-system
system:controller:ephemeral-volume-controller ephemeral-volume-controller ServiceAccount kube-system
system:controller:generic-garbage-collector generic-garbage-collector ServiceAccount kube-system
system:controller:job-controller job-controller ServiceAccount kube-system
system:controller:persistent-volume-binder persistent-volume-binder ServiceAccount kube-system
system:controller:pod-garbage-collector pod-garbage-collector ServiceAccount kube-system
system:controller:pvc-protection-controller pvc-protection-controller ServiceAccount kube-system
system:controller:replicaset-controller replicaset-controller ServiceAccount kube-system
system:controller:replication-controller replication-controller ServiceAccount kube-system
system:controller:resourcequota-controller resourcequota-controller ServiceAccount kube-system
system:controller:statefulset-controller statefulset-controller ServiceAccount kube-system
system:coreDNS coredns ServiceAccount kube-system
system:kube-controller-manager system:kube-controller-manager User
system:kube-scheduler system:kube-scheduler User
結論
在這篇文章中,我們瀏覽了 Kubernetes 中的幾個擴展點:數據模型、準入控制器和客戶端。這是一個非常簡短的介紹,無論是寬度還是深度。然而,我希望它為進一步的研究提供了一個很好的切入點。