成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

K8s 多集群編排平臺(tái) Karmada 入門

云計(jì)算 云原生
Karmada 旨在為多云和混合云場景下的多集群應(yīng)用程序管理提供即插即用的自動(dòng)化,具有集中式多云管理、高可用性、故障恢復(fù)和流量調(diào)度等關(guān)鍵功能。

Karmada(Kubernetes Armada)是 CNCF 孵化的一個(gè) Kubernetes 管理系統(tǒng),使您能夠在多個(gè) Kubernetes 集群和云中運(yùn)行云原生應(yīng)用程序,而無需更改應(yīng)用程序。通過使用 Kubernetes 原生 API 并提供先進(jìn)的調(diào)度功能,Karmada 實(shí)現(xiàn)了真正的開放式、多云 Kubernetes。

Karmada 旨在為多云和混合云場景下的多集群應(yīng)用程序管理提供即插即用的自動(dòng)化,具有集中式多云管理、高可用性、故障恢復(fù)和流量調(diào)度等關(guān)鍵功能。

特性

  • 兼容 K8s 原生 API

            從單集群到多集群的無侵入式升級(jí)

            現(xiàn)有 K8s 工具鏈的無縫集成

  • 開箱即用
  • 針對(duì)場景內(nèi)置策略集,包括:Active-active、Remote DR、Geo Redundant 等。
  • 在多集群上進(jìn)行跨集群應(yīng)用程序自動(dòng)伸縮、故障轉(zhuǎn)移和負(fù)載均衡。
  • 避免供應(yīng)商鎖定
  • 與主流云提供商集成
  • 在集群之間自動(dòng)分配、遷移
  • 未綁定專有供應(yīng)商編排
  • 集中式管理
  • 位置無關(guān)的集群管理
  • 支持公有云、本地或邊緣上的集群。
  • 豐富多集群調(diào)度策略
  • 集群親和性、實(shí)例在多集群中的拆分調(diào)度/再平衡,
  • 多維 HA:區(qū)域/AZ/集群/提供商
  • 開放和中立
  • 由互聯(lián)網(wǎng)、金融、制造業(yè)、電信、云提供商等聯(lián)合發(fā)起。
  • 目標(biāo)是與 CNCF 一起進(jìn)行開放治理。

Karmada 架構(gòu)

Karmada 的架構(gòu)非常類似于單個(gè) Kubernetes 集群,他們都有一個(gè)控制平面、一個(gè) APIServer、一個(gè)調(diào)度器和一組控制器,而且 Karmada 完全兼容 K8s 的原生 API 操作,便于各種 K8s 集群的接入。

Karmada 架構(gòu)

所以同樣 Karmada 的核心是其控制平面,一個(gè)完整且可工作的 Karmada 控制平面由以下組件組成。其中 karmada-agent 可以是可選的,這取決于集群注冊(cè)模式。

karmada-apiserver

APIServer 是 Karmada 控制平面的一個(gè)組件,對(duì)外暴露 Karmada API 以及 Kubernetes 原生 API,APIServer 是 Karmada 控制平面的前端。

Karmada APIServer 是直接使用 Kubernetes 的 kube-apiserver 實(shí)現(xiàn)的,因此 Karmada 與 Kubernetes API 自然兼容。這也使得 Karmada 更容易實(shí)現(xiàn)與 Kubernetes 生態(tài)系統(tǒng)的集成,例如允許用戶使用 kubectl 來操作 Karmada、與 ArgoCD 集成、與 Flux 集成等等。

karmada-aggregated-apiserver

聚合 API 服務(wù)器是使用 Kubernetes API 聚合層技術(shù)實(shí)現(xiàn)的擴(kuò)展 API 服務(wù)器。它提供了集群 API 以及相應(yīng)的子資源,例如 cluster/status 和 cluster/proxy,實(shí)現(xiàn)了聚合 Kubernetes API Endpoint 等可以通過 karmada-apiserver 訪問成員集群的高級(jí)功能。

kube-controller-manager

kube-controller-manager 由一組控制器組成,Karmada 只是從 Kubernetes 的官方版本中挑選了一些控制器,以保持與原生控制器一致的用戶體驗(yàn)和行為。值得注意的是,并非所有的原生控制器都是 Karmada 所需要的。

注意:當(dāng)用戶向 Karmada APIServer 提交 Deployment 或其他 Kubernetes 標(biāo)準(zhǔn)資源時(shí),它們只記錄在 Karmada 控制平面的 etcd 中。隨后,這些資源會(huì)向成員集群同步。然而,這些部署資源不會(huì)在 Karmada 控制平面集群中進(jìn)行 reconcile 過程(例如創(chuàng)建 Pod)。

karmada-controller-manager

Karmada 控制器管理器運(yùn)行了各種自定義控制器進(jìn)程。控制器負(fù)責(zé)監(jiān)視 Karmada 對(duì)象,并與底層集群的 API 服務(wù)器通信,以創(chuàng)建原生的 Kubernetes 資源。

karmada-scheduler

karmada-scheduler 負(fù)責(zé)將 Kubernetes 原生 API 資源對(duì)象(以及 CRD 資源)調(diào)度到成員集群。

調(diào)度器依據(jù)策略約束和可用資源來確定哪些集群對(duì)調(diào)度隊(duì)列中的資源是可用的,然后調(diào)度器對(duì)每個(gè)可用集群進(jìn)行打分排序,并將資源綁定到最合適的集群。

karmada-webhook

karmada-webhook 是用于接收 karmada/Kubernetes API 請(qǐng)求的 HTTP 回調(diào),并對(duì)請(qǐng)求進(jìn)行處理。你可以定義兩種類型的 karmada-webhook,即驗(yàn)證性質(zhì)的 webhook 和修改性質(zhì)的 webhook。修改性質(zhì)的準(zhǔn)入 webhook 會(huì)先被調(diào)用。它們可以更改發(fā)送到 Karmada API 服務(wù)器的對(duì)象以執(zhí)行自定義的設(shè)置默認(rèn)值操作。

在完成了所有對(duì)象修改并且 Karmada API 服務(wù)器也驗(yàn)證了所傳入的對(duì)象之后,驗(yàn)證性質(zhì)的 webhook 會(huì)被調(diào)用,并通過拒絕請(qǐng)求的方式來強(qiáng)制實(shí)施自定義的策略。

etcd

一致且高可用的鍵值存儲(chǔ),用作 Karmada 的所有 Karmada/Kubernetes 資源對(duì)象數(shù)據(jù)的后臺(tái)數(shù)據(jù)庫。

如果你的 Karmada 使用 etcd 作為其后臺(tái)數(shù)據(jù)庫,請(qǐng)確保你針對(duì)這些數(shù)據(jù)有一份備份計(jì)劃。

karmada-agent

Karmada 有 Push 和 Pull 兩種集群注冊(cè)模式,karmada-agent 應(yīng)部署在每個(gè) Pull 模式的成員集群上。它可以將特定集群注冊(cè)到 Karmada 控制平面,并將工作負(fù)載清單從 Karmada 控制平面同步到成員集群。此外,它也負(fù)責(zé)將成員集群及其資源的狀態(tài)同步到 Karmada 控制平面。

插件(Addons)

  • karmada-scheduler-estimator

Karmada 調(diào)度估計(jì)器為每個(gè)成員集群運(yùn)行精確的調(diào)度預(yù)估,它為調(diào)度器提供了更準(zhǔn)確的集群資源信息。

注意:早期的 Karmada 調(diào)度器只支持根據(jù)集群資源的總量來決策可調(diào)度副本的數(shù)量。在這種情況下,當(dāng)集群資源的總量足夠但每個(gè)節(jié)點(diǎn)資源不足時(shí),會(huì)發(fā)生調(diào)度失敗。為了解決這個(gè)問題,引入了估計(jì)器組件,該組件根據(jù)資源請(qǐng)求計(jì)算每個(gè)節(jié)點(diǎn)的可調(diào)度副本的數(shù)量,從而計(jì)算出真正的整個(gè)集群的可調(diào)度副本的數(shù)量。

  • karmada-descheduler

Karmada 重調(diào)度組件負(fù)責(zé)定時(shí)檢測所有副本(默認(rèn)為兩分鐘),并根據(jù)成員集群中副本實(shí)例狀態(tài)的變化觸發(fā)重新調(diào)度。

該組件是通過調(diào)用 karmada-scheduler-estimator 來感知有多少副本實(shí)例狀態(tài)發(fā)生了變化,并且只有當(dāng)副本的調(diào)度策略為動(dòng)態(tài)劃分時(shí),它才會(huì)發(fā)揮作用。

  • karmada-search

Karmada 搜索組件以聚合服務(wù)的形式,提供了在多云環(huán)境中進(jìn)行全局搜索和資源代理等功能。

其中,全局搜索能力是用來跨多個(gè)集群緩存資源對(duì)象和事件,以及通過搜索 API 對(duì)外提供圖形化的檢索服務(wù);資源代理能力使用戶既可以訪問 Karmada 控制平面所有資源,又可以訪問成員集群中的所有資源。

CLI 工具

  • karmadactl

Karmada 提供了一個(gè)命令行工具 karmadactl,用于使用 Karmada API 與 Karmada 的控制平面進(jìn)行通信。

你可以使用 karmadactl 執(zhí)行成員集群的添加/剔除,將成員集群標(biāo)記/取消標(biāo)記為不可調(diào)度,等等。

  • kubectl karmada

kubectl karmada 以 kubectl 插件的形式提供功能,但它的實(shí)現(xiàn)與 karmadactl 完全相同。

安裝

首先要注意我們使用 Karmada 管理的多集群包含兩類:

  • host 集群:即由 karmada 控制面構(gòu)成的集群,接受用戶提交的工作負(fù)載部署需求,將之同步到 member 集群,并從 member 集群同步工作負(fù)載后續(xù)的運(yùn)行狀況。
  • member 集群:由一個(gè)或多個(gè) K8s 集群構(gòu)成,負(fù)責(zé)運(yùn)行用戶提交的工作負(fù)載

所以首先我們需要準(zhǔn)備幾個(gè) K8s 集群用于測試,其中 host 集群就是我們要安裝 Karmada 的集群,這里我們可以使用 KinD 部署一個(gè) host 集群以及兩個(gè) member 集群,用于測試 Karmada 的多集群管理功能,當(dāng)然首先需要在你的測試環(huán)境中安裝 Docker 和 KinD。

$ docker version
Client:
 Cloud integration: v1.0.29
 Version:           20.10.21
 API version:       1.41
 Go version:        go1.18.7
 Git commit:        baeda1f
 Built:             Tue Oct 25 18:01:18 2022
 OS/Arch:           darwin/arm64
 Context:           orbstack
 Experimental:      true

Server: Docker Engine - Community
 Engine:
  Version:          25.0.5
  API version:      1.44 (minimum version 1.24)
  Go version:       go1.21.8
  Git commit:       e63daec
  Built:            Tue Mar 19 15:05:27 2024
  OS/Arch:          linux/arm64
  Experimental:     false
 containerd:
  Version:          v1.7.13
  GitCommit:        7c3aca7a610df76212171d200ca3811ff6096eb8
 runc:
  Version:          1.1.12
  GitCommit:        51d5e94601ceffbbd85688df1c928ecccbfa4685
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0
$ kind version
kind v0.20.0 go1.20.4 darwin/arm64

然后,我們可以使用 Karmada 官方提供的 create-cluster.sh 腳本來創(chuàng)建兩個(gè) member 集群。

$ git clone https://github.com/karmada-io/karmada.git
$ cd karmada
# 創(chuàng)建 host 集群
$ hack/create-cluster.sh host $HOME/.kube/host.config
$ kubectl get nodes --context host --kubeconfig /Users/cnych/.kube/host.config
NAME                 STATUS   ROLES           AGE   VERSION
host-control-plane   Ready    control-plane   63s   v1.27.3
# 創(chuàng)建 member1 集群
$ hack/create-cluster.sh member1 $HOME/.kube/member1.config
$ kubectl get nodes --context member1 --kubeconfig /Users/cnych/.kube/member1.config
NAME                    STATUS   ROLES           AGE    VERSION
member1-control-plane   Ready    control-plane   115s   v1.27.3
# 創(chuàng)建 member2 集群
$ hack/create-cluster.sh member2 $HOME/.kube/member2.config
$ kubectl get nodes --context member2 --kubeconfig /Users/cnych/.kube/member2.config
NAME                    STATUS   ROLES           AGE   VERSION
member2-control-plane   Ready    control-plane   29s   v1.27.3

到這里我們就準(zhǔn)備好了一個(gè) host 集群和兩個(gè) member 集群,接下來我們就可以在 host 集群上安裝 Karmada 了。安裝 Karmada 的方法有很多,可以直接使用官方的 CLI 工具,也可以使用 Helm Chart 方式,還可以使用 Operator 方式等等,如果需要定制化安裝,使用 Helm Chart 的方式會(huì)更加靈活。由于官方提供的 CLI 工具并不只是用于安裝 Karmada,還可以用于管理 Karmada 集群,所以無論如何我們都可以先安裝 CLI 工具 - karmadactl,karmadactl 是允許你控制 Karmada 控制面的 Karmada 命令行工具,此外還提供一個(gè) kubectl 插件 kubectl-karmada,盡管這兩個(gè)工具的名字不同,但其關(guān)聯(lián)的命令和選項(xiàng)完全相同,所以無論使用哪一個(gè)都是一樣的,在實(shí)際使用中,你可以根據(jù)自己的需求選擇一個(gè) CLI 工具。

直接使用下面的命令即可一鍵安裝 karmadactl:

$ sudo ./hack/install-cli.sh
[INFO]  Downloading metadata https://api.github.com/repos/karmada-io/karmada/releases/latest
[INFO]  Using 1.9.1 as release
[INFO]  Downloading hash https://github.com/karmada-io/karmada/releases/download/v1.9.1/karmadactl-darwin-arm64.tgz.sha256
[INFO]  Downloading binary https://github.com/karmada-io/karmada/releases/download/v1.9.1/karmadactl-darwin-arm64.tgz
[INFO]  Verifying binary download
[INFO]  Installing karmadactl to /usr/local/bin/karmadactl
$ karmadactl version
karmadactl version: version.Info{GitVersion:"v1.9.1", GitCommit:"b57bff17d6133deb26d9c319714170a915d4fa54", GitTreeState:"clean", BuildDate:"2024-04-30T02:03:53Z", GoVersion:"go1.20.11", Compiler:"gc", Platform:"darwin/arm64"}

安裝 kubectl-karmada 與安裝 karmadactl 相同,你只需要添加一個(gè) kubectl-karmada 參數(shù)即可:

$ sudo ./hack/install-cli.sh kubectl-karmada
[INFO]  Downloading metadata https://api.github.com/repos/karmada-io/karmada/releases/latest
[INFO]  Using 1.9.1 as release
[INFO]  Downloading hash https://github.com/karmada-io/karmada/releases/download/v1.9.1/kubectl-karmada-darwin-arm64.tgz.sha256
[INFO]  Downloading binary https://github.com/karmada-io/karmada/releases/download/v1.9.1/kubectl-karmada-darwin-arm64.tgz
[INFO]  Verifying binary download
[INFO]  Installing kubectl-karmada to /usr/local/bin/kubectl-karmada
$ kubectl karmada version
kubectl karmada version: version.Info{GitVersion:"v1.9.1", GitCommit:"b57bff17d6133deb26d9c319714170a915d4fa54", GitTreeState:"clean", BuildDate:"2024-04-30T02:03:52Z", GoVersion:"go1.20.11", Compiler:"gc", Platform:"darwin/arm64"}

接下來我們就可以在 host 集群上安裝 Karmada 了,我們已將 host 集群的 kubeconfig 文件放到了 $HOME/.kube/config。直接執(zhí)行以下命令即可進(jìn)行安裝:

# --kube-image-mirror-country 用于指定鏡像國內(nèi)源
# --etcd-storage-mode 用于指定 etcd 存儲(chǔ)模式,支持 emptyDir、hostPath、PVC,默認(rèn)為 hostPath
$ sudo kubectl karmada init --kube-image-mirror-country=cn --etcd-storage-mode PVC --storage-classes-name standard --kubecnotallow=$HOME/.kube/host.config
I0516 15:56:35.549617   98690 deploy.go:244] kubeconfig file: /Users/cnych/.kube/host.config, kubernetes: https://192.168.247.4:6443
I0516 15:56:35.586638   98690 deploy.go:264] karmada apiserver ip: [192.168.247.4]
I0516 15:56:36.330162   98690 cert.go:246] Generate ca certificate success.
I0516 15:56:36.368464   98690 cert.go:246] Generate karmada certificate success.
I0516 15:56:36.453671   98690 cert.go:246] Generate apiserver certificate success.
I0516 15:56:36.535924   98690 cert.go:246] Generate front-proxy-ca certificate success.
I0516 15:56:36.666694   98690 cert.go:246] Generate front-proxy-client certificate success.
I0516 15:56:36.716602   98690 cert.go:246] Generate etcd-ca certificate success.
I0516 15:56:36.772838   98690 cert.go:246] Generate etcd-server certificate success.
I0516 15:56:36.905275   98690 cert.go:246] Generate etcd-client certificate success.
I0516 15:56:36.905808   98690 deploy.go:360] download crds file:https://github.com/karmada-io/karmada/releases/download/v1.9.1/crds.tar.gz
Downloading...[ 100.00% ]
Download complete.
I0516 15:56:39.224167   98690 deploy.go:620] Create karmada kubeconfig success.
I0516 15:56:39.300133   98690 idempotency.go:267] Namespace karmada-system has been created or updated.
I0516 15:56:39.352865   98690 idempotency.go:291] Service karmada-system/etcd has been created or updated.
I0516 15:56:39.353105   98690 deploy.go:426] Create etcd StatefulSets
I0516 15:57:02.386423   98690 deploy.go:435] Create karmada ApiServer Deployment
I0516 15:57:02.412127   98690 idempotency.go:291] Service karmada-system/karmada-apiserver has been created or updated.
I0516 15:57:33.480629   98690 deploy.go:450] Create karmada aggregated apiserver Deployment
I0516 15:57:33.488145   98690 idempotency.go:291] Service karmada-system/karmada-aggregated-apiserver has been created or updated.
I0516 15:57:48.545482   98690 idempotency.go:267] Namespace karmada-system has been created or updated.
I0516 15:57:48.547067   98690 deploy.go:85] Initialize karmada bases crd resource `/etc/karmada/crds/bases`
I0516 15:57:48.549059   98690 deploy.go:240] Attempting to create CRD
I0516 15:57:48.569222   98690 deploy.go:250] Create CRD cronfederatedhpas.autoscaling.karmada.io successfully.
# ......省略部分輸出
I0516 15:57:49.963201   98690 deploy.go:96] Initialize karmada patches crd resource `/etc/karmada/crds/patches`
I0516 15:57:50.372020   98690 deploy.go:108] Create MutatingWebhookConfiguration mutating-config.
I0516 15:57:50.379939   98690 webhook_configuration.go:362] MutatingWebhookConfiguration mutating-config has been created or updated successfully.
I0516 15:57:50.379957   98690 deploy.go:113] Create ValidatingWebhookConfiguration validating-config.
I0516 15:57:50.387416   98690 webhook_configuration.go:333] ValidatingWebhookConfiguration validating-config has been created or updated successfully.
I0516 15:57:50.387434   98690 deploy.go:119] Create Service 'karmada-aggregated-apiserver' and APIService 'v1alpha1.cluster.karmada.io'.
I0516 15:57:50.390795   98690 idempotency.go:291] Service karmada-system/karmada-aggregated-apiserver has been created or updated.
I0516 15:57:50.394479   98690 check.go:42] Waiting for APIService(v1alpha1.cluster.karmada.io) condition(Available), will try
I0516 15:57:51.506085   98690 tlsbootstrap.go:49] [bootstrap-token] configured RBAC rules to allow Karmada Agent Bootstrap tokens to post CSRs in order for agent to get long term certificate credentials
I0516 15:57:51.508289   98690 tlsbootstrap.go:63] [bootstrap-token] configured RBAC rules to allow the csrapprover controller automatically approve CSRs from a Karmada Agent Bootstrap Token
I0516 15:57:51.511340   98690 tlsbootstrap.go:77] [bootstrap-token] configured RBAC rules to allow certificate rotation for all agent client certificates in the member cluster
I0516 15:57:51.635344   98690 deploy.go:143] Initialize karmada bootstrap token
I0516 15:57:51.656584   98690 deploy.go:468] Create karmada kube controller manager Deployment
I0516 15:57:51.671152   98690 idempotency.go:291] Service karmada-system/kube-controller-manager has been created or updated.
I0516 15:57:58.728859   98690 deploy.go:482] Create karmada scheduler Deployment
I0516 15:58:10.763913   98690 deploy.go:493] Create karmada controller manager Deployment
I0516 15:58:22.787659   98690 deploy.go:504] Create karmada webhook Deployment
I0516 15:58:22.798328   98690 idempotency.go:291] Service karmada-system/karmada-webhook has been created or updated.

------------------------------------------------------------------------------------------------------
 █████   ████   █████████   ███████████   ██████   ██████   █████████   ██████████     █████████
??███   ███?   ███?????███ ??███?????███ ??██████ ██████   ███?????███ ??███????███   ███?????███
 ?███  ███    ?███    ?███  ?███    ?███  ?███?█████?███  ?███    ?███  ?███   ??███ ?███    ?███
 ?███████     ?███████████  ?██████████   ?███??███ ?███  ?███████████  ?███    ?███ ?███████████
 ?███??███    ?███?????███  ?███?????███  ?███ ???  ?███  ?███?????███  ?███    ?███ ?███?????███
 ?███ ??███   ?███    ?███  ?███    ?███  ?███      ?███  ?███    ?███  ?███    ███  ?███    ?███
 █████ ??████ █████   █████ █████   █████ █████     █████ █████   █████ ██████████   █████   █████
?????   ???? ?????   ????? ?????   ????? ?????     ????? ?????   ????? ??????????   ?????   ?????
------------------------------------------------------------------------------------------------------
Karmada is installed successfully.

Register Kubernetes cluster to Karmada control plane.

Register cluster with 'Push' mode

Step 1: Use "kubectl karmada join" command to register the cluster to Karmada control plane. --cluster-kubeconfig is kubeconfig of the member cluster.
(In karmada)~# MEMBER_CLUSTER_NAME=$(cat ~/.kube/config  | grep current-context | sed 's/: /\n/g'| sed '1d')
(In karmada)~# kubectl karmada --kubeconfig /etc/karmada/karmada-apiserver.config  join ${MEMBER_CLUSTER_NAME} --cluster-kubecnotallow=$HOME/.kube/config

Step 2: Show members of karmada
(In karmada)~# kubectl --kubeconfig /etc/karmada/karmada-apiserver.config get clusters


Register cluster with 'Pull' mode

Step 1: Use "kubectl karmada register" command to register the cluster to Karmada control plane. "--cluster-name" is set to cluster of current-context by default.
(In member cluster)~# kubectl karmada register 192.168.247.4:32443 --token rflrr9.iisxtboo8dsz8jsv --discovery-token-ca-cert-hash sha256:008fb63e3b17c3e399f9688eca0978ab3a50dbe5d5b8d4f32c6bfd1fab12a1d8

Step 2: Show members of karmada
(In karmada)~# kubectl --kubeconfig /etc/karmada/karmada-apiserver.config get clusters

安裝正常的話會(huì)看到如上所示的輸出信息。默認(rèn) Karmada 會(huì)安裝在 host 集群的 karmada-system 命名空間中:

$ kubectl get pods -n karmada-system --kubeconfig ~/.kube/host.config
NAME                                            READY   STATUS    RESTARTS   AGE
etcd-0                                          1/1     Running   0          35m
karmada-aggregated-apiserver-5fddf66847-nnfzv   1/1     Running   0          34m
karmada-apiserver-6b6f5b45-fkbk4                1/1     Running   0          35m
karmada-controller-manager-bbdf689db-rc67z      1/1     Running   0          34m
karmada-scheduler-78f854fbd4-m24c8              1/1     Running   0          34m
karmada-webhook-77b9945cf9-mkjrk                1/1     Running   0          33m
kube-controller-manager-5c4975bf8d-6tx5r        1/1     Running   0          34m

如上所示 Karmada 控制平面相關(guān) Pod 都已經(jīng)正常運(yùn)行,接下來我們就可以將兩個(gè) member 集群注冊(cè)到 Karmada 控制平面中了,注冊(cè)集群有兩種方式,一種是 Push 模式,一種是 Pull 模式:

  • Push:Karmada 控制平面將直接訪問成員集群的 kube-apiserver 以獲取集群狀態(tài)并部署清單。
  • Pull:Karmada 控制平面不會(huì)訪問成員集群,而是將其委托給名為 Karmada-agent 的額外組件。

我們這里的集群都使用的 KinD 搭建的,所以使用 Push 模式更方便,對(duì)于無法直接訪問成員集群的環(huán)境下面可以使用 Pull 模式。

我們可以使用 kubectl karmada join 命令來注冊(cè)集群到 Karmada 控制平面。

sudo kubectl karmada --kubeconfig /etc/karmada/karmada-apiserver.config join member1 --cluster-kubecnotallow=$HOME/.kube/member1.config
sudo kubectl karmada --kubeconfig /etc/karmada/karmada-apiserver.config join member2 --cluster-kubecnotallow=$HOME/.kube/member2.config

注冊(cè)成功后可以查看注冊(cè)的集群列表:

$ sudo kubectl --kubeconfig /etc/karmada/karmada-apiserver.config get clusters
NAME      VERSION   MODE   READY   AGE
member1   v1.27.3   Push   True    12m
member2   v1.27.3   Push   True    2s

到這里我們就完成了 Karmada 的安裝和集群注冊(cè),接下來我們就可以使用 Karmada 來管理多集群了。

資源分發(fā)

接下來我們創(chuàng)建一個(gè) Deployment 資源,然后使用 Karmada 將其分發(fā)到 member1 和 member2 集群中。首先創(chuàng)建如下所示的 Deployment 資源:

# nginx-demo.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:1.7.9

要注意我們需要使用 Karmada 控制平面的 kubeconfig 文件來創(chuàng)建資源對(duì)象,因?yàn)?Karmada 控制平面會(huì)將資源對(duì)象分發(fā)到成員集群中,所以在應(yīng)用資源對(duì)象時(shí)需要使用 --kubeconfig /etc/karmada/karmada-apiserver.config 參數(shù)。

# karmada-apiserver 是與 Karmada 控制面交互時(shí)要使用的主要 kubeconfig
$ kubectl apply -f nginx-demo.yaml --kubeconfig /etc/karmada/karmada-apiserver.config
$ kubectl get pods --kubeconfig ~/.kube/member1.config
No resources found in default namespace.
$ kubectl get pods --kubeconfig ~/.kube/member2.config
No resources found in default namespace.

現(xiàn)在成員集群 member1 和 member2 下面并沒有對(duì)應(yīng)的對(duì)象。要進(jìn)行資源分發(fā)我們需要使用一個(gè)名為 PropagationPolicy(或者 ClusterPropagationPolicy)的資源對(duì)象,該資源對(duì)象定義了如何將資源分發(fā)到成員集群中。比如我們要將上面的 Deployment 對(duì)象分發(fā)到 member1 和 member2 集群中,我們可以創(chuàng)建如下所示的 PropagationPolicy 對(duì)象:

# nginx-propagation.yaml
apiVersion: policy.karmada.io/v1alpha1
kind: PropagationPolicy
metadata:
  name: nginx-propagation
spec:
  resourceSelectors:
    - apiVersion: apps/v1
      kind: Deployment
      name: nginx
  placement:
    clusterAffinity:
      clusterNames:
        - member1
        - member2
    replicaScheduling:
      replicaDivisionPreference: Weighted
      replicaSchedulingType: Divided
      weightPreference:
        staticWeightList:
          - targetCluster:
              clusterNames:
                - member1
            weight: 1
          - targetCluster:
              clusterNames:
                - member2
            weight: 1

在上面的 PropagationPolicy 對(duì)象中,首先我們通過 resourceSelectors 屬性指定了要分發(fā)的資源對(duì)象,然后通過 placement 字段,指定了資源對(duì)象的分發(fā)策略。

其中 .spec.placement.clusterAffinity 字段表示對(duì)特定集群集合的調(diào)度限制,沒有該限制,任何集群都可以成為調(diào)度候選者,該字段包含以下幾個(gè)屬性:

  • LabelSelector:用于選擇集群的標(biāo)簽,matchLabels 和 matchExpressions 兩種方式都支持。
  • FieldSelector:按字段選擇成員集群的過濾器。
  • ClusterNames:直接指定所選的集群。
  • ExcludeClusters:排除指定的集群。

比如我們這里直接通過 clusterNames 屬性指定了 member1 和 member2 集群,這意味著 Deployment 對(duì)象 nginx 可以被分發(fā)到 member1 和 member2 集群中。

此外我們還可以設(shè)置 ClusterAffinities 字段來聲明多個(gè)集群組。調(diào)度器將按照它們?cè)谝?guī)范中出現(xiàn)的順序逐一評(píng)估這些組,不滿足調(diào)度限制的組將被忽略,這意味著該組中的所有集群都不會(huì)被選擇。如果沒有一個(gè)組滿足調(diào)度限制,則調(diào)度失敗,這意味著不會(huì)選擇任何集群。

另外還要注意 ClusterAffinities 不能與 ClusterAffinity 共存。如果 ClusterAffinity 和 ClusterAffinities 均未設(shè)置,則任何集群都可以作為調(diào)度候選者。

比如現(xiàn)在我們有兩個(gè)分組的集群,其中本地?cái)?shù)據(jù)中心的私有集群可以是主要的集群,云提供商提供的托管集群可以是次組。因此,Karmada 調(diào)度程序更愿意將工作負(fù)載調(diào)度到主集群組,并且只有在主組不滿足限制(例如缺乏資源)的情況下才會(huì)考慮第二組集群,那么就可以配置如下所示的 PropagationPolicy 對(duì)象:

apiVersion: policy.karmada.io/v1alpha1
kind: PropagationPolicy
metadata:
  name: test-propagation
spec:
  #...
  placement:
    clusterAffinities: # 逐一評(píng)估這些組
      - affinityName: local-clusters
        clusterNames:
          - local-member1
          - local-member2
      - affinityName: cloud-clusters
        clusterNames:
          - public-cloud-member1
          - public-cloud-member2
    #...

又比如對(duì)于災(zāi)難恢復(fù)的場景,集群可以分為 primary 集群和 backup 集群,工作負(fù)載將首先調(diào)度到主集群,當(dāng)主集群發(fā)生故障(例如數(shù)據(jù)中心斷電)時(shí),Karmada 調(diào)度程序可以遷移工作負(fù)載到備份集群。這種情況下可以配置如下所示的 PropagationPolicy 對(duì)象:

apiVersion: policy.karmada.io/v1alpha1
kind: PropagationPolicy
metadata:
  name: test-propagation
spec:
  #...
  placement:
    clusterAffinities:
      - affinityName: primary-clusters
        clusterNames:
          - member1
      - affinityName: backup-clusters
        clusterNames:
          - member1
          - member2
    #...

現(xiàn)在我們已經(jīng)指定了分發(fā)的集群,那么具體應(yīng)該如何調(diào)度呢?哪一個(gè)集群應(yīng)該有多少副本呢?這就需要指定調(diào)度策略了。和原生 Kubernetes 類似,Karmada 支持多種調(diào)度策略,比如支持容忍污點(diǎn)、權(quán)重等。

通過 .spec.placement.clusterTolerations 字段可以設(shè)置容忍度,與 kubernetes 一樣,容忍需要與集群上的污點(diǎn)結(jié)合使用。在集群上設(shè)置一個(gè)或多個(gè)污點(diǎn)后,無法在這些集群上調(diào)度或運(yùn)行工作負(fù)載,除非策略明確聲明可以容忍這些污點(diǎn)。Karmada 目前支持效果為 NoSchedule 和 NoExecute 的污點(diǎn)。我們可以使用 karmadactl taint 命令來設(shè)置集群的污點(diǎn):

# 為集群 foo 設(shè)置包含鍵 dedicated、值 special-user 和效果 NoSchedule 的污點(diǎn)
# 如果具有該鍵和效果的污點(diǎn)已經(jīng)存在,則其值將按指定替換
karmadactl taint clusters foo dedicated=special-user:NoSchedule

為了調(diào)度到上述集群,我們需要在 PropagationPolicy 中聲明以下內(nèi)容:

apiVersion: policy.karmada.io/v1alpha1
kind: PropagationPolicy
metadata:
  name: nginx-propagation
spec:
  #...
  placement:
    clusterTolerations:
      - key: dedicated
        value: special-user
        Effect: NoSchedule

我們常常使用 NoExecute 污點(diǎn)來實(shí)現(xiàn)多集群故障轉(zhuǎn)移。

然后更多的時(shí)候我們需要設(shè)置副本調(diào)度策略,我們可以通過 .spec.placement.replicaScheduling 字段來設(shè)置副本調(diào)度策略,該字段表示將規(guī)范中具有副本的資源傳播到成員集群時(shí)處理副本數(shù)量的調(diào)度策略。Karmada 一共提供了兩種副本調(diào)度類型,用于確定 Karmada 傳播資源時(shí)如何調(diào)度副本:

  • Duplicated:從資源中將相同的副本復(fù)制到每個(gè)候選成員集群。
  • Divided:根據(jù)有效候選成員集群的數(shù)量將副本劃分為若干部分,每個(gè)集群的確切副本由 ReplicaDivisionPreference 確定。

ReplicaDivisionPreference 用于描述當(dāng) ReplicaSchedulingType 為 Divided 時(shí)副本如何被劃分,也提供了兩種副本劃分方式:

  • Aggregated:將副本盡可能少地劃分到集群,同時(shí)在劃分過程中尊重集群的資源可用性。
  • Weighted:根據(jù) WeightPreference 按權(quán)重劃分副本,一共有兩種方式。StaticWeightList 根據(jù)權(quán)重靜態(tài)分配副本到目標(biāo)集群,可以通過 ClusterAffinity 選擇目標(biāo)集群。DynamicWeight 指定生成動(dòng)態(tài)權(quán)重列表的因子,如果指定,StaticWeightList 將被忽略。

上面我們創(chuàng)建的 Nginx 的 PropagationPolicy 對(duì)象中,我們指定了 ReplicaDivisionPreference 為 Weighted,ReplicaSchedulingType 為 Divided,weightPreference 為 1,表示兩個(gè)集群的權(quán)重相同,這意味著副本將均勻地傳播到 member1 和 member2。

我們這里直接應(yīng)用傳播策略資源對(duì)象即可:

$ sudo kubectl apply -f samples/nginx/propagationpolicy.yaml --kubeconfig /etc/karmada/karmada-apiserver.config
propagationpolicy.policy.karmada.io/nginx-propagation created
$ sudo kubectl get propagationpolicy --kubeconfig /etc/karmada/karmada-apiserver.config
NAME                AGE
nginx-propagation   31s

當(dāng)創(chuàng)建 PropagationPolicy 對(duì)象后,Karmada 控制平面 watch 到過后就會(huì)自動(dòng)將資源對(duì)象分發(fā)到成員集群中,我們可以查看 Deployment 對(duì)象的狀態(tài):

$ sudo kubectl describe deploy nginx --kubeconfig /etc/karmada/karmada-apiserver.config
# ......
Events:
  Type    Reason                  Age                    From                                Message
  ----    ------                  ----                   ----                                -------
  Normal  ApplyPolicySucceed      2m17s (x2 over 2m17s)  resource-detector                   Apply policy(default/nginx-propagation) succeed
  Normal  SyncWorkSucceed         2m17s (x3 over 2m17s)  binding-controller                  Sync work of resourceBinding(default/nginx-deployment) successful.
  Normal  ScheduleBindingSucceed  2m17s                  default-scheduler                   Binding has been scheduled successfully.
  Normal  SyncSucceed             2m17s                  execution-controller                Successfully applied resource(default/nginx) to cluster member2
  Normal  SyncSucceed             2m17s                  execution-controller                Successfully applied resource(default/nginx) to cluster member1
  Normal  AggregateStatusSucceed  2m2s (x9 over 2m17s)   resource-binding-status-controller  Update resourceBinding(default/nginx-deployment) with AggregatedStatus successfully.

可以看到 Deployment 對(duì)象已經(jīng)成功分發(fā)到了 member1 和 member2 集群中,我們也可以查看 member1 和 member2 集群中的 Pod 對(duì)象來進(jìn)行驗(yàn)證:

$ kubectl get pods --kubeconfig ~/.kube/member1.config
NAME                     READY   STATUS    RESTARTS   AGE
nginx-77b4fdf86c-54qhc   1/1     Running   0          2m59s
$ kubectl get pods --kubeconfig ~/.kube/member2.config
NAME                     READY   STATUS    RESTARTS   AGE
nginx-77b4fdf86c-9x98b   1/1     Running   0          3m24s

和我們聲明的副本調(diào)度策略一樣,兩個(gè) Pod 對(duì)象均勻地分布在 member1 和 member2 集群中。

分發(fā) CRD

除了內(nèi)置的資源對(duì)象之外,Karmada 還支持分發(fā)自定義資源對(duì)象(CRD)。這里我們以 Karmada 倉庫中的 guestbook 為例進(jìn)行說明。

首先進(jìn)入 Karmada 倉庫的 guestbook 目錄下:

?  cd samples/guestbook
?  guestbook git:(master) ll
total 48
-rw-r--r--  1 cnych  staff   1.8K May 16 11:26 README.md
-rw-r--r--  1 cnych  staff   135B May 16 11:26 guestbook.yaml
-rw-r--r--  1 cnych  staff   353B May 16 11:26 guestbooks-clusterpropagationpolicy.yaml
-rw-r--r--  1 cnych  staff   2.7K May 16 11:26 guestbooks-crd.yaml
-rw-r--r--  1 cnych  staff   455B May 16 11:26 guestbooks-overridepolicy.yaml
-rw-r--r--  1 cnych  staff   255B May 16 11:26 guestbooks-propagationpolicy.yaml

然后在 Karmada 的控制平面上創(chuàng)建 Guestbook CRD:

sudo kubectl apply -f guestbooks-crd.yaml --kubeconfig /etc/karmada/karmada-apiserver.config

該 CRD 應(yīng)該被應(yīng)用到 karmada-apiserver。

然后我們可以創(chuàng)建一個(gè) ClusterPropagationPolicy 對(duì)象,將 Guestbook CRD 分發(fā)到 member1,如下所示:

# guestbooks-clusterpropagationpolicy.yaml
apiVersion: policy.karmada.io/v1alpha1
kind: ClusterPropagationPolicy
metadata:
  name: example-policy
spec:
  resourceSelectors:
    - apiVersion: apiextensions.k8s.io/v1
      kind: CustomResourceDefinition
      name: guestbooks.webapp.my.domain
  placement:
    clusterAffinity:
      clusterNames:
        - member1

需要注意的是 CustomResourceDefinition 是全局資源,所以我們使用 ClusterPropagationPolicy 對(duì)象來分發(fā),該對(duì)象的配置和 PropagationPolicy 對(duì)象類似,注意 resourceSelectors 字段中的 apiVersion 和 kind 需要設(shè)置為 apiextensions.k8s.io/v1 和 CustomResourceDefinition,name 字段需要設(shè)置為 Guestbook CRD 的名稱。

然后我們直接創(chuàng)建 ClusterPropagationPolicy 對(duì)象即可:

sudo kubectl apply -f guestbooks-clusterpropagationpolicy.yaml --kubeconfig /etc/karmada/karmada-apiserver.config

應(yīng)用后正常就會(huì)將 Guestbook CRD 對(duì)象分發(fā)到 member1 集群中。

$ sudo kubectl karmada get crd --kubeconfig /etc/karmada/karmada-apiserver.config
NAME                          CLUSTER   CREATED AT             ADOPTION
guestbooks.webapp.my.domain   member1   2024-05-18T11:56:10Z   Y
$ kubectl get crd --kubeconfig ~/.kube/member1.config
NAME                          CREATED AT
guestbooks.webapp.my.domain   2024-05-18T11:56:10Z
$ kubectl get crd --kubeconfig ~/.kube/member2.config
No resources found

接下來我們就可以部署分發(fā) Guestbook CRD 對(duì)象了,我們可以創(chuàng)建一個(gè) Guestbook CR 對(duì)象:

# guestbook.yaml
apiVersion: webapp.my.domain/v1
kind: Guestbook
metadata:
  name: guestbook-sample
spec:
  size: 2
  configMapName: test
  alias: Name

同樣在 Karmada 控制平面上應(yīng)用該 Guestbook CR 對(duì)象即可:

$ sudo kubectl apply -f guestbook.yaml --kubeconfig /etc/karmada/karmada-apiserver.config

然后就可以創(chuàng)建 PropagationPolicy 對(duì)象,將 guestbook-sample 分發(fā)到 member1 集群:

# guestbooks-propagationpolicy.yaml
apiVersion: policy.karmada.io/v1alpha1
kind: PropagationPolicy
metadata:
  name: example-policy
spec:
  resourceSelectors:
    - apiVersion: webapp.my.domain/v1
      kind: Guestbook
  placement:
    clusterAffinity:
      clusterNames:
        - member1

上面的 PropagationPolicy 對(duì)象和我們之前創(chuàng)建的類似,只是這里的 resourceSelectors 字段中的 apiVersion 和 kind 需要設(shè)置為 webapp.my.domain/v1 和 Guestbook(我們自己的 CRD)。同樣直接應(yīng)用該 PropagationPolicy 對(duì)象即可:

$ sudo kubectl apply -f guestbooks-propagationpolicy.yaml --kubeconfig /etc/karmada/karmada-apiserver.config

應(yīng)用后就可以將 guestbook-sample 這個(gè) Guestbook CR 對(duì)象分發(fā)到 member1 集群中了。

$ kubectl get guestbook --kubeconfig ~/.kube/member1.config
NAME               AGE
guestbook-sample   39s

可以看到 CRD 的分發(fā)和普通資源對(duì)象的分發(fā)原理是一樣的,只是需要先將 CRD 對(duì)象分發(fā)到成員集群中。

有的時(shí)候我們可能需要對(duì)分發(fā)的資源到不同集群進(jìn)行一些覆蓋操作,這個(gè)時(shí)候我們就可以使用 OverridePolicy 和 ClusterOverridePolicy 對(duì)象,用于聲明資源傳播到不同集群時(shí)的覆蓋規(guī)則。

比如我們創(chuàng)建一個(gè) OverridePolicy 對(duì)象,用于覆蓋 member1 中 guestbook-sample 的 size 字段,如下所示:

apiVersion: policy.karmada.io/v1alpha1
kind: OverridePolicy
metadata:
  name: guestbook-sample
spec:
  resourceSelectors:
    - apiVersion: webapp.my.domain/v1
      kind: Guestbook
  overrideRules:
    - targetCluster:
        clusterNames:
          - member1
      overriders:
        plaintext:
          - path: /spec/size
            operator: replace
            value: 4
          - path: /metadata/annotations
            operator: add
            value: { "OverridePolicy": "test" }

上面的對(duì)象中通過 resourceSelectors 字段指定了要覆蓋的資源對(duì)象,然后通過 overrideRules 字段指定了覆蓋規(guī)則,targetCluster 字段指定了目標(biāo)集群,overriders 字段指定了覆蓋規(guī)則,這里我們將 guestbook-sample 的 size 字段覆蓋為 4,同時(shí)添加了一個(gè) OverridePolicy: test 的注解。

我們直接應(yīng)用該 OverridePolicy 對(duì)象即可:

$ sudo kubectl apply -f guestbooks-overridepolicy.yaml --kubeconfig /etc/karmada/karmada-apiserver.config

創(chuàng)建完成后可以查看 member1 集群中的 guestbook-sample 對(duì)象來進(jìn)行驗(yàn)證:

$ kubectl get guestbook guestbook-sample --kubeconfig ~/.kube/member1.config -oyaml
apiVersion: webapp.my.domain/v1
kind: Guestbook
metadata:
  annotations:
    OverridePolicy: test
# ......
  name: guestbook-sample
  namespace: default
  resourceVersion: "82669"
  uid: 5893b85d-3946-44a0-b210-d67bd021cb65
spec:
  alias: Name
  configMapName: test
  size: 4

可以看到 guestbook-sample 對(duì)象的 size 字段已經(jīng)被覆蓋為 4,同時(shí)添加了一個(gè) OverridePolicy: test 的注解,證明覆蓋操作成功。

Karmada 提供了多種聲明覆蓋規(guī)則的方案:

  • ImageOverrider:覆蓋工作負(fù)載的鏡像。
  • CommandOverrider:覆蓋工作負(fù)載的命令。
  • ArgsOverrider:覆蓋工作負(fù)載的參數(shù)。
  • LabelsOverrider:覆蓋工作負(fù)載的標(biāo)簽。
  • AnnotationsOverrider:覆蓋工作負(fù)載的注釋。
  • PlaintextOverrider:用于覆蓋任何類型資源的通用工具。

PlaintextOverrider

上面我們使用的是 PlaintextOverrider 覆蓋規(guī)則,可以覆蓋任何類型資源的字段。PlaintextOverrider 可以根據(jù)路徑、運(yùn)算符和值覆蓋目標(biāo)字段,就像 kubectl patch 一樣。允許的操作如下:

  • add:向資源追加一個(gè)或多個(gè)元素。
  • remove:從資源中刪除一個(gè)或多個(gè)元素。
  • replace:替換資源中的一個(gè)或多個(gè)元素。

ImageOverrider

ImageOverrider 用于覆蓋工作負(fù)載的鏡像,用于覆蓋格式為 [registry/]repository[:tag|@digest](例如 /spec/template/spec/containers/0/image )的鏡像。允許的操作如下:

  • add:將注冊(cè)表、存儲(chǔ)庫或 tag/digest 附加到容器中的鏡像。
  • remove:從容器中的鏡像中刪除注冊(cè)表、存儲(chǔ)庫或 tag/digest。
  • replace:替換容器中鏡像的注冊(cè)表、存儲(chǔ)庫或 tag/digest。

比如我們需要?jiǎng)?chuàng)建一個(gè)如下所示的 Deployment 對(duì)象:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
  #...
spec:
  template:
    spec:
      containers:
        - image: myapp:1.0.0
          name: myapp

當(dāng)工作負(fù)載傳播到特定集群時(shí)添加注冊(cè)表,可以使用如下所示的 OverridePolicy 對(duì)象:

apiVersion: policy.karmada.io/v1alpha1
kind: OverridePolicy
metadata:
  name: example
spec:
  #...
  overrideRules:
    - overriders:
        imageOverrider:
          - component: Registry
            operator: add
            value: test-repo

上面的覆蓋規(guī)則表示添加 test-repo 這個(gè)鏡像倉庫到 myapp 的鏡像中,這樣在傳播到集群時(shí)就會(huì)變成 test-repo/myapp:1.0.0。

containers:
  - image: test-repo/myapp:1.0.0
    name: myapp

replace 和 remove 操作也是類似的,只是分別用于替換和刪除鏡像中的某些字段。

跨集群彈性伸縮

在 Karmada 中,我們可以使用 FederatedHPA 來實(shí)現(xiàn)跨多個(gè)集群擴(kuò)展/縮小工作負(fù)載的副本,旨在根據(jù)需求自動(dòng)調(diào)整工作負(fù)載的規(guī)模。

FederatedHPA

當(dāng)負(fù)載增加時(shí),如果 Pod 的數(shù)量低于配置的最大值,則 FederatedHPA 擴(kuò)展工作負(fù)載(例如 Deployment、StatefulSet 或其他類似資源)的副本數(shù)。當(dāng)負(fù)載減少時(shí),如果 Pod 的數(shù)量高于配置的最小值,則 FederatedHPA 縮小工作負(fù)載的副本數(shù)。

FederatedHPA 是作為 Karmada API 資源和控制器實(shí)現(xiàn)的,該資源確定了控制器的行為。FederatedHPA 控制器運(yùn)行在 Karmada 控制平面中,定期調(diào)整其目標(biāo)(例如 Deployment)的所需規(guī)模,以匹配觀察到的指標(biāo),例如平均 CPU 利用率、平均內(nèi)存利用率或任何其他自定義指標(biāo)。

FederatedHPA實(shí)現(xiàn)原理

為了實(shí)現(xiàn)跨集群的自動(dòng)擴(kuò)縮容,Karmada 引入了 FederatedHPA 控制器和 karmada-metrics-adapter,它們的工作方式如下:

  • HPA 控制器定期通過指標(biāo) API metrics.k8s.io 或 custom.metrics.k8s.io 使用標(biāo)簽選擇器查詢指標(biāo)。
  • karmada-apiserver 獲取指標(biāo) API 查詢結(jié)果,然后通過 API 服務(wù)注冊(cè)將其路由到 karmada-metrics-adapter。
  • karmada-metrics-adapter 將從目標(biāo)集群(Pod 所在的集群)查詢指標(biāo)。收集到指標(biāo)后,它會(huì)對(duì)這些指標(biāo)進(jìn)行聚合并返回結(jié)果。
  • HPA 控制器將根據(jù)指標(biāo)計(jì)算所需的副本數(shù),并直接擴(kuò)展/縮小工作負(fù)載的規(guī)模。然后,karmada-scheduler 將這些副本調(diào)度到成員集群中。

注意:要使用此功能,Karmada 版本必須為 v1.6.0 或更高版本。

下面我們就來演示如何使用 FederatedHPA 控制器來實(shí)現(xiàn)跨集群的自動(dòng)擴(kuò)縮容。首先至少需要兩個(gè)成員集群,我們需要在成員集群中安裝 ServiceExport 和 ServiceImport 來啟用多集群服務(wù)。在 Karmada 控制平面上安裝 ServiceExport 和 ServiceImport 后(init 安裝后會(huì)自動(dòng)安裝),我  們可以創(chuàng)建 ClusterPropagationPolicy 將這兩個(gè) CRD 傳播到成員集群。

# propagate-service-export-import.yaml
# propagate ServiceExport CRD
apiVersion: policy.karmada.io/v1alpha1
kind: ClusterPropagationPolicy
metadata:
  name: serviceexport-policy
spec:
  resourceSelectors:
    - apiVersion: apiextensions.k8s.io/v1
      kind: CustomResourceDefinition
      name: serviceexports.multicluster.x-k8s.io
  placement:
    clusterAffinity:
      clusterNames:
        - member1
        - member2
---
# propagate ServiceImport CRD
apiVersion: policy.karmada.io/v1alpha1
kind: ClusterPropagationPolicy
metadata:
  name: serviceimport-policy
spec:
  resourceSelectors:
    - apiVersion: apiextensions.k8s.io/v1
      kind: CustomResourceDefinition
      name: serviceimports.multicluster.x-k8s.io
  placement:
    clusterAffinity:
      clusterNames:
        - member1
        - member2

直接應(yīng)用該 ClusterPropagationPolicy 對(duì)象即可:

$ sudo kubectl apply -f propagate-service-export-import.yaml --kubeconfig /etc/karmada/karmada-apiserver.config

應(yīng)用后就可以在 member1 和 member2 集群中創(chuàng)建 ServiceExport 和 ServiceImport 對(duì)象了。

另外我們還需要為成員集群安裝 metrics-server 來提供 metrics API,通過運(yùn)行以下命令來安裝:

hack/deploy-k8s-metrics-server.sh $HOME/.kube/member1.config member1
hack/deploy-k8s-metrics-server.sh $HOME/.kube/member2.config member2

最后我們還需要在 Karmada 控制平面中安裝 karmada-metrics-adapter 以提供指標(biāo) API,通過運(yùn)行以下命令來安裝它:

sudo hack/deploy-metrics-adapter.sh ~/.kube/host.config host /etc/karmada/karmada-apiserver.config karmada-apiserver

需要注意使用 karmada init 安裝的 Karmada 控制平面,需要將 karmada-cert 這個(gè) Secret 對(duì)象重新拷貝創(chuàng)建一個(gè)名為 karmada-cert-secret 的 Secret 對(duì)象。

部署后在 Karmada 控制平面中就會(huì)有 karmada-metrics-adapter 這個(gè) Pod 對(duì)象。

接下來我們?cè)?member1 和 member2 中部署 Deployment(1 個(gè)副本)和 Service 對(duì)象,如下所示:

# nginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - image: nginx
          name: nginx
          resources:
            requests:
              cpu: 25m
              memory: 64Mi
            limits:
              cpu: 25m
              memory: 64Mi
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  ports:
    - port: 80
      targetPort: 80
  selector:
    app: nginx
---
apiVersion: policy.karmada.io/v1alpha1
kind: PropagationPolicy
metadata:
  name: nginx-propagation
spec:
  resourceSelectors:
    - apiVersion: apps/v1
      kind: Deployment
      name: nginx
    - apiVersion: v1
      kind: Service
      name: nginx-service
  placement:
    clusterAffinity:
      clusterNames:
        - member1
        - member2
    replicaScheduling:
      replicaDivisionPreference: Weighted
      replicaSchedulingType: Divided
      weightPreference:
        staticWeightList:
          - targetCluster:
              clusterNames:
                - member1
            weight: 1
          - targetCluster:
              clusterNames:
                - member2
            weight: 1

直接應(yīng)用上面的資源對(duì)象即可:

$ sudo kubectl apply -f nginx.yaml --kubeconfig /etc/karmada/karmada-apiserver.config
deployment.apps/nginx configured
service/nginx-service created
propagationpolicy.policy.karmada.io/nginx-propagation configured
$ sudo kubectl karmada get pods --kubeconfig /etc/karmada/karmada-apiserver.config
NAME                     CLUSTER   READY   STATUS    RESTARTS   AGE
nginx-5c54b4855f-ztmnk   member1   1/1     Running   0          43s
$ sudo kubectl karmada get svc --kubeconfig /etc/karmada/karmada-apiserver.config
NAME            CLUSTER   TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE     ADOPTION
nginx-service   member2   ClusterIP   100.171.35.78    <none>        80/TCP    52s     Y
nginx-service   member1   ClusterIP   100.91.124.245   <none>        80/TCP    52s     Y

然后讓我們?cè)?Karmada 控制平面中部署一個(gè) FederatedHPA 對(duì)象,用來自動(dòng)擴(kuò)縮容,如下所示:

# nginx-federatedhpa.yaml
apiVersion: autoscaling.karmada.io/v1alpha1
kind: FederatedHPA
metadata:
  name: nginx
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: nginx
  minReplicas: 1
  maxReplicas: 10
  behavior:
    scaleDown:
      stabilizationWindowSeconds: 10
    scaleUp:
      stabilizationWindowSeconds: 10
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 10

上面的 FederatedHPA 對(duì)象中,我們指定了 scaleTargetRef 字段為 Deployment 對(duì)象 nginx,minReplicas 和 maxReplicas 分別為 1 和 10,metrics 字段中指定了 CPU 利用率為 10% 時(shí)進(jìn)行擴(kuò)縮容。同樣直接應(yīng)用該 FederatedHPA 對(duì)象即可:

$ sudo kubectl apply -f nginx-federatedhpa.yaml --kubeconfig /etc/karmada/karmada-apiserver.config
$ sudo kubectl get fhpa --kubeconfig /etc/karmada/karmada-apiserver.config
NAME    REFERENCE-KIND   REFERENCE-NAME   MINPODS   MAXPODS   REPLICAS   AGE
nginx   Deployment       nginx            1         10        1          19s

我們還需要一個(gè)多集群服務(wù)將請(qǐng)求路由到 member1 和 member2 集群中的 pod。首先在 Karmada 控制平面上創(chuàng)建 ServiceExport 對(duì)象,然后創(chuàng)建 PropagationPolicy 以將 ServiceExport 對(duì)象傳播到 member1 和 member2 集群。

# nginx-serviceexport.yaml
apiVersion: multicluster.x-k8s.io/v1alpha1
kind: ServiceExport
metadata:
  name: nginx-service
---
apiVersion: policy.karmada.io/v1alpha1
kind: PropagationPolicy
metadata:
  name: serve-export-policy
spec:
  resourceSelectors:
    - apiVersion: multicluster.x-k8s.io/v1alpha1
      kind: ServiceExport
      name: nginx-service
  placement:
    clusterAffinity:
      clusterNames:
        - member1
        - member2

然后在 Karmada 控制平面上創(chuàng)建 ServiceImport 對(duì)象,然后創(chuàng)建 PropagationPolicy 以將 ServiceImport 對(duì)象傳播到 member1 集群。

# nginx-serviceimport.yaml
apiVersion: multicluster.x-k8s.io/v1alpha1
kind: ServiceImport
metadata:
  name: nginx-service
spec:
  type: ClusterSetIP
  ports:
    - port: 80
      protocol: TCP
---
apiVersion: policy.karmada.io/v1alpha1
kind: PropagationPolicy
metadata:
  name: serve-import-policy
spec:
  resourceSelectors:
    - apiVersion: multicluster.x-k8s.io/v1alpha1
      kind: ServiceImport
      name: nginx-service
  placement:
    clusterAffinity:
      clusterNames:
        - member1

直接應(yīng)用上面的資源對(duì)象即可:

$ sudo kubectl apply -f nginx-serviceexport.yaml --kubeconfig /etc/karmada/karmada-apiserver.config
$ sudo kubectl apply -f nginx-serviceimport.yaml --kubeconfig /etc/karmada/karmada-apiserver.config

部署完成后,可以查看多集群服務(wù):

$ sudo kubectl karmada get svc --kubeconfig /etc/karmada/karmada-apiserver.config
NAME                    CLUSTER   TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE     ADOPTION
nginx-service           member2   ClusterIP   100.171.35.78    <none>        80/TCP    6m36s   Y
derived-nginx-service   member1   ClusterIP   100.91.3.68      <none>        80/TCP    17s     Y
nginx-service           member1   ClusterIP   100.91.124.245   <none>        80/TCP    6m36s   Y

接下來我們?cè)?member1 集群使用 hey 工具來進(jìn)行 http 負(fù)載測試,模擬請(qǐng)求增加,從而觸發(fā) Pod 的 CPU 使用率增加:

$ wget https://hey-release.s3.us-east-2.amazonaws.com/hey_linux_amd64
$ chmod +x hey_linux_amd64
$ docker cp hey_linux_amd64 member1-control-plane:/usr/local/bin/hey

然后我們可以使用 hey 請(qǐng)求多集群服務(wù)以增加 nginx pod 的 CPU 使用率。

$ docker exec member1-control-plane hey -c 1000 -z 1m http://100.91.3.68

Summary:
  Total:        61.4678 secs
  Slowest:      4.7916 secs
  Fastest:      0.0244 secs
  Average:      0.9024 secs
  Requests/sec: 1090.3758

  Total data:   41219145 bytes
  Size/request: 615 bytes

Response time histogram:
  0.024 [1]     |
  0.501 [23047] |■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
  0.978 [23117] |■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
  1.455 [8696]  |■■■■■■■■■■■■■■■
  1.931 [5681]  |■■■■■■■■■■
  2.408 [3352]  |■■■■■■
  2.885 [1534]  |■■■
  3.361 [832]   |■
  3.838 [375]   |■
  4.315 [318]   |■
  4.792 [70]    |


Latency distribution:
  10% in 0.2733 secs
  25% in 0.4264 secs
  50% in 0.6478 secs
  75% in 1.1603 secs
  90% in 1.9114 secs
  95% in 2.3694 secs
  99% in 3.4382 secs

Details (average, fastest, slowest):
  DNS+dialup:   0.0019 secs, 0.0244 secs, 4.7916 secs
  DNS-lookup:   0.0000 secs, 0.0000 secs, 0.0000 secs
  req write:    0.0006 secs, 0.0000 secs, 0.1423 secs
  resp wait:    0.7861 secs, 0.0002 secs, 4.6641 secs
  resp read:    0.0553 secs, 0.0000 secs, 1.3870 secs

Status code distribution:
  [200] 67023 responses

等一會(huì)兒,副本就會(huì)開始擴(kuò)容了,我們可以查看 FederatedHPA 對(duì)象的狀態(tài)來了解副本的變化:

$ sudo kubectl describe fhpa nginx --kubeconfig /etc/karmada/karmada-apiserver.config
Name:         nginx
Namespace:    default
Labels:       <none>
Annotations:  <none>
API Version:  autoscaling.karmada.io/v1alpha1
Kind:         FederatedHPA
# ...
Spec:
  Behavior:
    Scale Down:
      Policies:
        Period Seconds:              15
        Type:                        Percent
        Value:                       100
      Select Policy:                 Max
      Stabilization Window Seconds:  10
    Scale Up:
      Policies:
        Period Seconds:              15
        Type:                        Pods
        Value:                       4
        Period Seconds:              15
        Type:                        Percent
        Value:                       100
      Select Policy:                 Max
      Stabilization Window Seconds:  10
  Max Replicas:                      10
  Metrics:
    Resource:
      Name:  cpu
      Target:
        Average Utilization:  10
        Type:                 Utilization
    Type:                     Resource
  Min Replicas:               1
  Scale Target Ref:
    API Version:  apps/v1
    Kind:         Deployment
    Name:         nginx
Status:
  Conditions:
    Last Transition Time:  2024-05-19T01:43:16Z
    Message:               recommended size matches current size
    Reason:                ReadyForNewScale
    Status:                True
    Type:                  AbleToScale
    Last Transition Time:  2024-05-19T01:43:16Z
    Message:               the HPA was able to successfully calculate a replica count from cpu resource utilization (percentage of request)
    Reason:                ValidMetricFound
    Status:                True
    Type:                  ScalingActive
    Last Transition Time:  2024-05-19T01:45:16Z
    Message:               the desired replica count is less than the minimum replica count
    Reason:                TooFewReplicas
    Status:                True
    Type:                  ScalingLimited
  Current Metrics:
    Resource:
      Current:
        Average Utilization:  0
        Average Value:        0
      Name:                   cpu
    Type:                     Resource
  Current Replicas:           1
  Desired Replicas:           1
  Last Scale Time:            2024-05-19T01:45:16Z
Events:
  Type    Reason             Age   From                     Message
  ----    ------             ----  ----                     -------
  Normal  SuccessfulRescale  2m7s  federatedHPA-controller  New size: 5; reason: cpu resource utilization (percentage of request) above target
  Normal  SuccessfulRescale  112s  federatedHPA-controller  New size: 10; reason: cpu resource utilization (percentage of request) above target
  Normal  SuccessfulRescale  67s   federatedHPA-controller  New size: 3; reason: All metrics below target
  Normal  SuccessfulRescale  52s   federatedHPA-controller  New size: 1; reason: All metrics below target

同時(shí)可以查看 member1 和 member2 集群中的 Pod 對(duì)象:

$ sudo kubectl karmada get pods --kubeconfig /etc/karmada/karmada-apiserver.config
NAME                     CLUSTER   READY   STATUS    RESTARTS   AGE
nginx-5c54b4855f-4p6wq   member1   1/1     Running   0          40s
nginx-5c54b4855f-kdwpc   member1   1/1     Running   0          2m6s
nginx-5c54b4855f-l4vm4   member1   1/1     Running   0          40s
nginx-5c54b4855f-t4ghv   member1   1/1     Running   0          25s
nginx-5c54b4855f-vbj9c   member1   1/1     Running   0          25s
nginx-5c54b4855f-hx2xn   member2   1/1     Running   0          25s
nginx-5c54b4855f-kfnbh   member2   1/1     Running   0          40s
nginx-5c54b4855f-rmbv9   member2   1/1     Running   0          40s
nginx-5c54b4855f-wfd92   member2   1/1     Running   0          25s
nginx-5c54b4855f-wwsvq   member2   1/1     Running   0          25s

可以看到 Pod 的副本數(shù)已經(jīng)擴(kuò)容到 10 個(gè)了。同樣當(dāng)負(fù)載測試結(jié)束后,Pod 的副本數(shù)會(huì)自動(dòng)縮小為 1 個(gè)副本。

$ sudo kubectl karmada get pods --kubeconfig /etc/karmada/karmada-apiserver.config
NAME                     CLUSTER   READY   STATUS    RESTARTS   AGE
nginx-5c54b4855f-kdwpc   member1   1/1     Running   0          5m25s

到這里我們就完成了使用 FederatedHPA 進(jìn)行跨集群的自動(dòng)擴(kuò)縮容,除此之外我們還可以使用 CronFederatedHPA 用于定期自動(dòng)縮放操作,它可以縮放具有 scale 子資源的工作負(fù)載或 Karmada FederatedHPA。典型的場景是在可預(yù)見的流量高峰到來前提前擴(kuò)容工作負(fù)載。例如,如果我知道每天早上 9 點(diǎn)會(huì)突發(fā)流量洪峰,我們就可以提前半個(gè)小時(shí)擴(kuò)容相關(guān)服務(wù),以處理高峰負(fù)載并確保服務(wù)持續(xù)可用性。在 Karmada 控制平面內(nèi)運(yùn)行的 CronFederatedHPA 控制器根據(jù)預(yù)定義的 cron 計(jì)劃來伸縮工作負(fù)載的副本或 FederatedHPA 的最小/最大副本數(shù)。

比如我們有一個(gè)如下所示的 CronFederatedHPA 對(duì)象:

apiVersion: autoscaling.karmada.io/v1alpha1
kind: CronFederatedHPA
metadata:
  name: nginx-cronfhpa
  namespace: default
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: nginx
  rules:
    - name: "scale-up"
      schedule: "*/1 * * * *"
      targetReplicas: 5
      suspend: false

其中表達(dá)式 */1 * * * * 的意思是 nginx deployment 的副本應(yīng)該每分鐘更新為 5 個(gè),確保了處理接下來的流量突發(fā)流量洪峰。

除了這些使用場景之外,Karmada 還有很多實(shí)踐場景,比如跨集群的災(zāi)備、多集群網(wǎng)絡(luò)、多集群服務(wù)治理、多集群 CI/CD 等等,這些場景都可以通過 Karmada 來實(shí)現(xiàn),更多最佳實(shí)踐方案可以參考 Karmada 官方文檔以了解更多。

參考鏈接:https://karmada.io/zh/docs/。

責(zé)任編輯:姜華 來源: k8s技術(shù)圈
相關(guān)推薦

2023-09-07 08:58:36

K8s多集群

2020-05-12 10:20:39

K8s kubernetes中間件

2023-07-10 07:22:16

2023-09-06 08:12:04

k8s云原生

2023-09-03 23:58:23

k8s集群容量

2023-03-05 21:50:46

K8s集群容量

2022-04-29 10:40:38

技術(shù)服務(wù)端K8s

2022-02-08 15:59:29

k3sk8sDevOps

2021-04-22 09:46:35

K8SCluster Aut集群

2022-09-29 10:32:33

vivoKarmada集群

2022-04-22 13:32:01

K8s容器引擎架構(gòu)

2022-11-06 21:31:11

云原生Sentinel集群模式

2023-03-01 07:42:12

HBase編排部署數(shù)據(jù)

2022-01-02 08:42:50

架構(gòu)部署容器

2022-12-28 10:52:34

Etcd備份

2024-05-27 00:00:10

KubernetesK8s云原生

2021-11-04 07:49:58

K8SStatefulSetMySQL

2020-06-30 08:08:25

k8s監(jiān)控

2023-09-08 08:09:12

k8sservice服務(wù)

2020-02-29 15:23:15

Kubernetes集群程序
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 精品少妇v888av | 亚洲小视频在线观看 | 特级黄一级播放 | 91n成人 | 在线一区二区三区 | 亚洲国产视频一区二区 | 欧美成人免费在线视频 | 久久综合激情 | av在线天天 | 天天操天天干天天爽 | 日韩av免费看 | 超碰在线播 | 国产目拍亚洲精品99久久精品 | 日日摸天天添天天添破 | 日韩一区二区三区视频 | 国产一区二区电影 | 日韩成人中文字幕 | 亚洲一区在线观看视频 | 一区二区精品 | 黄网站在线播放 | 欧美国产日韩一区 | 久久久影院 | 成人免费视频网站在线观看 | 91久久| 欧美激情久久久 | 精品网站999 | a级毛片基地 | 亚洲国产精品区 | 久久久久国产精品 | jdav视频在线观看免费 | 国产网站在线免费观看 | 国内精品久久久久久影视8 最新黄色在线观看 | 亚洲成人a v| 性一爱一乱一交一视频 | 精品视频一区在线 | 午夜免费观看 | 久久久久久国产精品免费免费 | 亚洲精品永久免费 | 一区二区成人 | 日韩中文一区 | 精品国产99|