精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

K8s 多集群編排平臺 Karmada 入門

云計算 云原生
Karmada 旨在為多云和混合云場景下的多集群應用程序管理提供即插即用的自動化,具有集中式多云管理、高可用性、故障恢復和流量調度等關鍵功能。

Karmada(Kubernetes Armada)是 CNCF 孵化的一個 Kubernetes 管理系統,使您能夠在多個 Kubernetes 集群和云中運行云原生應用程序,而無需更改應用程序。通過使用 Kubernetes 原生 API 并提供先進的調度功能,Karmada 實現了真正的開放式、多云 Kubernetes。

Karmada 旨在為多云和混合云場景下的多集群應用程序管理提供即插即用的自動化,具有集中式多云管理、高可用性、故障恢復和流量調度等關鍵功能。

特性

  • 兼容 K8s 原生 API

            從單集群到多集群的無侵入式升級

            現有 K8s 工具鏈的無縫集成

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

Karmada 架構

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

Karmada 架構

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

karmada-apiserver

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

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

karmada-aggregated-apiserver

聚合 API 服務器是使用 Kubernetes API 聚合層技術實現的擴展 API 服務器。它提供了集群 API 以及相應的子資源,例如 cluster/status 和 cluster/proxy,實現了聚合 Kubernetes API Endpoint 等可以通過 karmada-apiserver 訪問成員集群的高級功能。

kube-controller-manager

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

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

karmada-controller-manager

Karmada 控制器管理器運行了各種自定義控制器進程。控制器負責監視 Karmada 對象,并與底層集群的 API 服務器通信,以創建原生的 Kubernetes 資源。

karmada-scheduler

karmada-scheduler 負責將 Kubernetes 原生 API 資源對象(以及 CRD 資源)調度到成員集群。

調度器依據策略約束和可用資源來確定哪些集群對調度隊列中的資源是可用的,然后調度器對每個可用集群進行打分排序,并將資源綁定到最合適的集群。

karmada-webhook

karmada-webhook 是用于接收 karmada/Kubernetes API 請求的 HTTP 回調,并對請求進行處理。你可以定義兩種類型的 karmada-webhook,即驗證性質的 webhook 和修改性質的 webhook。修改性質的準入 webhook 會先被調用。它們可以更改發送到 Karmada API 服務器的對象以執行自定義的設置默認值操作。

在完成了所有對象修改并且 Karmada API 服務器也驗證了所傳入的對象之后,驗證性質的 webhook 會被調用,并通過拒絕請求的方式來強制實施自定義的策略。

etcd

一致且高可用的鍵值存儲,用作 Karmada 的所有 Karmada/Kubernetes 資源對象數據的后臺數據庫。

如果你的 Karmada 使用 etcd 作為其后臺數據庫,請確保你針對這些數據有一份備份計劃。

karmada-agent

Karmada 有 Push 和 Pull 兩種集群注冊模式,karmada-agent 應部署在每個 Pull 模式的成員集群上。它可以將特定集群注冊到 Karmada 控制平面,并將工作負載清單從 Karmada 控制平面同步到成員集群。此外,它也負責將成員集群及其資源的狀態同步到 Karmada 控制平面。

插件(Addons)

  • karmada-scheduler-estimator

Karmada 調度估計器為每個成員集群運行精確的調度預估,它為調度器提供了更準確的集群資源信息。

注意:早期的 Karmada 調度器只支持根據集群資源的總量來決策可調度副本的數量。在這種情況下,當集群資源的總量足夠但每個節點資源不足時,會發生調度失敗。為了解決這個問題,引入了估計器組件,該組件根據資源請求計算每個節點的可調度副本的數量,從而計算出真正的整個集群的可調度副本的數量。

  • karmada-descheduler

Karmada 重調度組件負責定時檢測所有副本(默認為兩分鐘),并根據成員集群中副本實例狀態的變化觸發重新調度。

該組件是通過調用 karmada-scheduler-estimator 來感知有多少副本實例狀態發生了變化,并且只有當副本的調度策略為動態劃分時,它才會發揮作用。

  • karmada-search

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

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

CLI 工具

  • karmadactl

Karmada 提供了一個命令行工具 karmadactl,用于使用 Karmada API 與 Karmada 的控制平面進行通信。

你可以使用 karmadactl 執行成員集群的添加/剔除,將成員集群標記/取消標記為不可調度,等等。

  • kubectl karmada

kubectl karmada 以 kubectl 插件的形式提供功能,但它的實現與 karmadactl 完全相同。

安裝

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

  • host 集群:即由 karmada 控制面構成的集群,接受用戶提交的工作負載部署需求,將之同步到 member 集群,并從 member 集群同步工作負載后續的運行狀況。
  • member 集群:由一個或多個 K8s 集群構成,負責運行用戶提交的工作負載

所以首先我們需要準備幾個 K8s 集群用于測試,其中 host 集群就是我們要安裝 Karmada 的集群,這里我們可以使用 KinD 部署一個 host 集群以及兩個 member 集群,用于測試 Karmada 的多集群管理功能,當然首先需要在你的測試環境中安裝 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 腳本來創建兩個 member 集群。

$ git clone https://github.com/karmada-io/karmada.git
$ cd karmada
# 創建 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
# 創建 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
# 創建 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

到這里我們就準備好了一個 host 集群和兩個 member 集群,接下來我們就可以在 host 集群上安裝 Karmada 了。安裝 Karmada 的方法有很多,可以直接使用官方的 CLI 工具,也可以使用 Helm Chart 方式,還可以使用 Operator 方式等等,如果需要定制化安裝,使用 Helm Chart 的方式會更加靈活。由于官方提供的 CLI 工具并不只是用于安裝 Karmada,還可以用于管理 Karmada 集群,所以無論如何我們都可以先安裝 CLI 工具 - karmadactl,karmadactl 是允許你控制 Karmada 控制面的 Karmada 命令行工具,此外還提供一個 kubectl 插件 kubectl-karmada,盡管這兩個工具的名字不同,但其關聯的命令和選項完全相同,所以無論使用哪一個都是一樣的,在實際使用中,你可以根據自己的需求選擇一個 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 相同,你只需要添加一個 kubectl-karmada 參數即可:

$ 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。直接執行以下命令即可進行安裝:

# --kube-image-mirror-country 用于指定鏡像國內源
# --etcd-storage-mode 用于指定 etcd 存儲模式,支持 emptyDir、hostPath、PVC,默認為 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

安裝正常的話會看到如上所示的輸出信息。默認 Karmada 會安裝在 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 控制平面相關 Pod 都已經正常運行,接下來我們就可以將兩個 member 集群注冊到 Karmada 控制平面中了,注冊集群有兩種方式,一種是 Push 模式,一種是 Pull 模式:

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

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

我們可以使用 kubectl karmada join 命令來注冊集群到 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

注冊成功后可以查看注冊的集群列表:

$ 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 的安裝和集群注冊,接下來我們就可以使用 Karmada 來管理多集群了。

資源分發

接下來我們創建一個 Deployment 資源,然后使用 Karmada 將其分發到 member1 和 member2 集群中。首先創建如下所示的 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 文件來創建資源對象,因為 Karmada 控制平面會將資源對象分發到成員集群中,所以在應用資源對象時需要使用 --kubeconfig /etc/karmada/karmada-apiserver.config 參數。

# karmada-apiserver 是與 Karmada 控制面交互時要使用的主要 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.

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

# 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 對象中,首先我們通過 resourceSelectors 屬性指定了要分發的資源對象,然后通過 placement 字段,指定了資源對象的分發策略。

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

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

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

此外我們還可以設置 ClusterAffinities 字段來聲明多個集群組。調度器將按照它們在規范中出現的順序逐一評估這些組,不滿足調度限制的組將被忽略,這意味著該組中的所有集群都不會被選擇。如果沒有一個組滿足調度限制,則調度失敗,這意味著不會選擇任何集群。

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

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

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

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

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
    #...

現在我們已經指定了分發的集群,那么具體應該如何調度呢?哪一個集群應該有多少副本呢?這就需要指定調度策略了。和原生 Kubernetes 類似,Karmada 支持多種調度策略,比如支持容忍污點、權重等。

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

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

為了調度到上述集群,我們需要在 PropagationPolicy 中聲明以下內容:

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

我們常常使用 NoExecute 污點來實現多集群故障轉移。

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

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

ReplicaDivisionPreference 用于描述當 ReplicaSchedulingType 為 Divided 時副本如何被劃分,也提供了兩種副本劃分方式:

  • Aggregated:將副本盡可能少地劃分到集群,同時在劃分過程中尊重集群的資源可用性。
  • Weighted:根據 WeightPreference 按權重劃分副本,一共有兩種方式。StaticWeightList 根據權重靜態分配副本到目標集群,可以通過 ClusterAffinity 選擇目標集群。DynamicWeight 指定生成動態權重列表的因子,如果指定,StaticWeightList 將被忽略。

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

我們這里直接應用傳播策略資源對象即可:

$ 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

當創建 PropagationPolicy 對象后,Karmada 控制平面 watch 到過后就會自動將資源對象分發到成員集群中,我們可以查看 Deployment 對象的狀態:

$ 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 對象已經成功分發到了 member1 和 member2 集群中,我們也可以查看 member1 和 member2 集群中的 Pod 對象來進行驗證:

$ 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

和我們聲明的副本調度策略一樣,兩個 Pod 對象均勻地分布在 member1 和 member2 集群中。

分發 CRD

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

首先進入 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 的控制平面上創建 Guestbook CRD:

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

該 CRD 應該被應用到 karmada-apiserver。

然后我們可以創建一個 ClusterPropagationPolicy 對象,將 Guestbook CRD 分發到 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 對象來分發,該對象的配置和 PropagationPolicy 對象類似,注意 resourceSelectors 字段中的 apiVersion 和 kind 需要設置為 apiextensions.k8s.io/v1 和 CustomResourceDefinition,name 字段需要設置為 Guestbook CRD 的名稱。

然后我們直接創建 ClusterPropagationPolicy 對象即可:

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

應用后正常就會將 Guestbook CRD 對象分發到 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

接下來我們就可以部署分發 Guestbook CRD 對象了,我們可以創建一個 Guestbook CR 對象:

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

同樣在 Karmada 控制平面上應用該 Guestbook CR 對象即可:

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

然后就可以創建 PropagationPolicy 對象,將 guestbook-sample 分發到 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 對象和我們之前創建的類似,只是這里的 resourceSelectors 字段中的 apiVersion 和 kind 需要設置為 webapp.my.domain/v1 和 Guestbook(我們自己的 CRD)。同樣直接應用該 PropagationPolicy 對象即可:

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

應用后就可以將 guestbook-sample 這個 Guestbook CR 對象分發到 member1 集群中了。

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

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

有的時候我們可能需要對分發的資源到不同集群進行一些覆蓋操作,這個時候我們就可以使用 OverridePolicy 和 ClusterOverridePolicy 對象,用于聲明資源傳播到不同集群時的覆蓋規則。

比如我們創建一個 OverridePolicy 對象,用于覆蓋 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" }

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

我們直接應用該 OverridePolicy 對象即可:

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

創建完成后可以查看 member1 集群中的 guestbook-sample 對象來進行驗證:

$ 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 對象的 size 字段已經被覆蓋為 4,同時添加了一個 OverridePolicy: test 的注解,證明覆蓋操作成功。

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

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

PlaintextOverrider

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

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

ImageOverrider

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

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

比如我們需要創建一個如下所示的 Deployment 對象:

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

當工作負載傳播到特定集群時添加注冊表,可以使用如下所示的 OverridePolicy 對象:

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

上面的覆蓋規則表示添加 test-repo 這個鏡像倉庫到 myapp 的鏡像中,這樣在傳播到集群時就會變成 test-repo/myapp:1.0.0。

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

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

跨集群彈性伸縮

在 Karmada 中,我們可以使用 FederatedHPA 來實現跨多個集群擴展/縮小工作負載的副本,旨在根據需求自動調整工作負載的規模。

FederatedHPA

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

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

FederatedHPA實現原理

為了實現跨集群的自動擴縮容,Karmada 引入了 FederatedHPA 控制器和 karmada-metrics-adapter,它們的工作方式如下:

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

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

下面我們就來演示如何使用 FederatedHPA 控制器來實現跨集群的自動擴縮容。首先至少需要兩個成員集群,我們需要在成員集群中安裝 ServiceExport 和 ServiceImport 來啟用多集群服務。在 Karmada 控制平面上安裝 ServiceExport 和 ServiceImport 后(init 安裝后會自動安裝),我  們可以創建 ClusterPropagationPolicy 將這兩個 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

直接應用該 ClusterPropagationPolicy 對象即可:

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

應用后就可以在 member1 和 member2 集群中創建 ServiceExport 和 ServiceImport 對象了。

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

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 以提供指標 API,通過運行以下命令來安裝它:

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

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

部署后在 Karmada 控制平面中就會有 karmada-metrics-adapter 這個 Pod 對象。

接下來我們在 member1 和 member2 中部署 Deployment(1 個副本)和 Service 對象,如下所示:

# 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

直接應用上面的資源對象即可:

$ 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

然后讓我們在 Karmada 控制平面中部署一個 FederatedHPA 對象,用來自動擴縮容,如下所示:

# 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 對象中,我們指定了 scaleTargetRef 字段為 Deployment 對象 nginx,minReplicas 和 maxReplicas 分別為 1 和 10,metrics 字段中指定了 CPU 利用率為 10% 時進行擴縮容。同樣直接應用該 FederatedHPA 對象即可:

$ 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

我們還需要一個多集群服務將請求路由到 member1 和 member2 集群中的 pod。首先在 Karmada 控制平面上創建 ServiceExport 對象,然后創建 PropagationPolicy 以將 ServiceExport 對象傳播到 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 控制平面上創建 ServiceImport 對象,然后創建 PropagationPolicy 以將 ServiceImport 對象傳播到 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

直接應用上面的資源對象即可:

$ 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

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

$ 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

接下來我們在 member1 集群使用 hey 工具來進行 http 負載測試,模擬請求增加,從而觸發 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 請求多集群服務以增加 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

等一會兒,副本就會開始擴容了,我們可以查看 FederatedHPA 對象的狀態來了解副本的變化:

$ 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

同時可以查看 member1 和 member2 集群中的 Pod 對象:

$ 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 的副本數已經擴容到 10 個了。同樣當負載測試結束后,Pod 的副本數會自動縮小為 1 個副本。

$ 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 進行跨集群的自動擴縮容,除此之外我們還可以使用 CronFederatedHPA 用于定期自動縮放操作,它可以縮放具有 scale 子資源的工作負載或 Karmada FederatedHPA。典型的場景是在可預見的流量高峰到來前提前擴容工作負載。例如,如果我知道每天早上 9 點會突發流量洪峰,我們就可以提前半個小時擴容相關服務,以處理高峰負載并確保服務持續可用性。在 Karmada 控制平面內運行的 CronFederatedHPA 控制器根據預定義的 cron 計劃來伸縮工作負載的副本或 FederatedHPA 的最小/最大副本數。

比如我們有一個如下所示的 CronFederatedHPA 對象:

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

其中表達式 */1 * * * * 的意思是 nginx deployment 的副本應該每分鐘更新為 5 個,確保了處理接下來的流量突發流量洪峰。

除了這些使用場景之外,Karmada 還有很多實踐場景,比如跨集群的災備、多集群網絡、多集群服務治理、多集群 CI/CD 等等,這些場景都可以通過 Karmada 來實現,更多最佳實踐方案可以參考 Karmada 官方文檔以了解更多。

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

責任編輯:姜華 來源: k8s技術圈
相關推薦

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-03-05 21:50:46

K8s集群容量

2023-09-03 23:58:23

k8s集群容量

2022-04-29 10:40:38

技術服務端K8s

2022-02-08 15:59:29

k3sk8sDevOps

2021-04-22 09:46:35

K8SCluster Aut集群

2022-04-22 13:32:01

K8s容器引擎架構

2022-09-29 10:32:33

vivoKarmada集群

2022-11-06 21:31:11

云原生Sentinel集群模式

2023-03-01 07:42:12

HBase編排部署數據

2022-12-28 10:52:34

Etcd備份

2024-05-27 00:00:10

KubernetesK8s云原生

2022-01-02 08:42:50

架構部署容器

2021-11-04 07:49:58

K8SStatefulSetMySQL

2020-06-30 08:08:25

k8s監控

2023-09-08 08:09:12

k8sservice服務

2020-02-29 15:23:15

Kubernetes集群程序
點贊
收藏

51CTO技術棧公眾號

亚洲欧美国产精品专区久久 | 黄色一级大片在线免费看国产| 亚洲三级精品| 欧美性生活久久| 超碰成人在线免费观看| 免费看日韩av| 免费观看在线色综合| 九九视频直播综合网| 国产男女猛烈无遮挡a片漫画 | 一区二区三区欧美日| 精品国产乱码久久久久久蜜柚| 国产一级黄色av| 亚洲日产av中文字幕| 色呦呦网站一区| 8x8x华人在线| eeuss影院在线播放| 国产99久久久久久免费看农村| 久热99视频在线观看| 国产在线观看无码免费视频| 欧美极品videos大乳护士| 中文字幕不卡在线观看| 国产乱码精品一区二区三区卡 | 偷偷色噜狠狠狠狠的777米奇| 青青草原av在线| 成人国产视频在线观看| 国产在线视频91| 国产无套丰满白嫩对白| 久久99国内| 亚洲成**性毛茸茸| 自拍一级黄色片| 成人网ww555视频免费看| 中文字幕在线一区| 日韩成人av网站| 四虎在线视频免费观看| 视频小说一区二区| 欧美性猛交xxxx乱| 日本免费网站在线观看| 老司机午夜精品| 亚洲一区av在线播放| 国产精九九网站漫画| 日韩成人综合网| www国产精品| 久久亚洲精品小早川怜子| 国精产品一区一区三区有限在线| 日韩综合第一页| 亚洲精品毛片| 欧美怡红院视频| 国产男女激情视频| 竹内纱里奈兽皇系列在线观看| 国产欧美一区二区三区网站 | 在线观看不卡| 九九热99久久久国产盗摄| 久久精品在线观看视频| 日韩一区亚洲二区| 在线观看日韩av| 欧洲熟妇的性久久久久久| 日本一区二区三区电影免费观看| 欧美日韩中文在线| 欧美日韩在线一| 色是在线视频| 色女孩综合影院| www日韩在线观看| 成人在线不卡| 欧美乱妇一区二区三区不卡视频| 五月丁香综合缴情六月小说| 波多野结衣在线观看| 亚洲一区二区三区中文字幕| 日韩欧美国产综合在线| 在线亚洲人成| 欧美专区日韩专区| 免费成人黄色大片| 涩涩屋成人免费视频软件| 精品日韩99亚洲| 强迫凌虐淫辱の牝奴在线观看| 91精品国产色综合久久不卡粉嫩| 色视频欧美一区二区三区| 乱子伦视频在线看| 亚洲风情在线资源| 欧美性xxxxxx少妇| 一本色道久久88亚洲综合88 | 中文字幕一区二区三区乱码图片 | 久久久久久美女精品| 欧美高清激情视频| 中文字幕人妻一区二| 欧美日韩三级| 日本一本a高清免费不卡| 最好看的日本字幕mv视频大全| 国产精品日韩| 国产精品丝袜高跟| 自拍偷拍精品视频| 国产精品18久久久久久久久久久久 | 久操免费在线| 亚洲国产精品久久久久秋霞影院 | 在线日本成人| 国产成人一区二| 国产片在线播放| 精品一区二区在线视频| 高清国产在线一区| 国产黄在线看| 亚洲国产精品成人综合| 日韩精品免费一区| 中文字幕免费高清电视剧网站在线观看 | 韩日精品视频| 国产成人在线精品| 国产成人精品一区二区无码呦| 国产美女视频91| 精品一区国产| 一二三四区在线观看| 一本色道久久综合精品竹菊| 色欲无码人妻久久精品| 波多野结衣在线观看一区二区三区 | 美国黄色一级视频| 蜜臀av免费一区二区三区| 国产午夜精品一区二区三区| 欧美大片一区二区三区| 亚洲小说欧美另类婷婷| 中文字幕第20页| 成人黄色片视频网站| 中文字幕国产精品久久| 在线观看欧美精品| 国产成人午夜高潮毛片| 精品国产一区二区三区2021| 午夜dj在线观看高清视频完整版 | 久久综合久久综合亚洲| 国产欧美日韩在线播放| yw193.com尤物在线| 亚洲自拍偷拍综合| 亚洲怡红院在线| 久久最新网址| 97视频人免费观看| 亚洲乱码国产乱码精品精软件| 粉嫩在线一区二区三区视频| 一区二区三区四区五区视频| 韩国美女久久| 亚洲国产精品人人爽夜夜爽| 久久久久人妻一区精品色欧美| 在线亚洲自拍| 国产精品视频500部| 麻豆tv入口在线看| 欧美精品在欧美一区二区少妇| 91亚洲免费视频| 国内黄色精品| 国产成人在线视频| 九色视频网站在线观看| 亚洲日本在线a| 日本三级免费网站| 亚洲福利网站| 日本精品久久久| 日本电影一区二区在线观看| 婷婷综合另类小说色区| 久久人人妻人人人人妻性色av| 亚洲一区av| 亚洲女色av| 欧美卡一卡二| 神马亚洲视频| 久草视频国产在线| 在线成人免费av| 精品成人免费视频| 国产深喉视频一区二区| 久久久久亚洲av无码a片| 9久久婷婷国产综合精品性色 | 日韩影片中文字幕| 黄色片视频在线观看| youjizz在线视频| 男女av免费观看| 精品视频第一区| 欧美专区在线播放| 97久久精品人搡人人玩| 亚洲欧美综合v| 亚洲福利在线播放| 日韩欧美大尺度| 亚洲最新视频在线观看| 成人av在线观| 日本在线不卡一区| 欧美精选一区| 亚洲精品**不卡在线播he| 一区二区亚洲视频| 牛牛影视久久网| 欧美三级电影网址| 日韩性xxx| 久久久久人妻一区精品色欧美| 野花视频免费在线观看| 成人一级片免费看| 999视频在线| 中文字幕永久在线观看| 亚洲天堂自拍偷拍| av大片在线观看| 另类中文字幕国产精品| 成人av在线播放| 警花av一区二区三区 | 日韩精品网站| 免费成人美女在线观看.| 国产免费成人在线视频| 亚洲精品视频在线观看网站| 91 com成人网| 亚洲美女福利视频网站| 欧美一区第一页| 日韩精品一区二区三区外面| 亚洲日本精品国产第一区| 日本一区二区久久精品| 久久久久久人妻一区二区三区| av免费在线播放网站| 91视频福利网| 国产小视频精品| 男人天堂亚洲二区| 少妇高潮一区二区三区99| 成人av动漫| xxx在线免费观看| 日本在线视频www鲁啊鲁| 黄色在线播放| 欧美日本高清| 国产日产一区二区| 精品国产一区二区三区四| 日本激情视频在线| 大又大又粗又硬又爽少妇毛片| 国产精品久久久视频| 亚洲无码久久久久久久| 成人影院www在线观看| 久久9999免费视频| 国语精品一区| 久久这里都是精品| 欧美少妇bbb| 久久精品国产91精品亚洲| 豆国产97在线| 新呦u视频一区二区| 国产成人无码精品久久二区三| 国产wwwwxxxx| 捆绑调教日本一区二区三区| 久久精品电影网站| 东凛在线观看| 国产精品久久久久久久久晋中 | 欧美一区二区三区四区五区六区| 97热精品视频官网| 久久精品丝袜高跟鞋| 亚洲国产一区二区精品视频| 美女黄色免费看| 野战少妇38p| 日本一区二区三区久久| 丰满诱人av在线播放| 精品一区欧美| 国产一级精品在线| 色狠狠色狠狠综合| 久久久久国色av免费观看性色| 国产精品日韩欧美| 欧美一级视频在线播放| 国产精品麻豆一区| 天堂91在线| 日韩精品一区二区三区中文在线| 久久久久久久久久久久久久| a在线欧美一区| 日韩一区二区三区在线| 欧美在线性爱视频| 欧美日韩激情视频在线观看 | 国产女精品视频网站免费| 日本福利视频在线| 国产精品.www| 欧美xxxx免费虐| 嗯用力啊快一点好舒服小柔久久| 亚洲一级毛片| 亚洲精选视频在线| 九九九久久久久久| 成人av资源网| 北京富婆泄欲对白| 天天躁日日躁狠狠躁喷水| 秋霞伦理一区| 日韩精品久久| 国产一区视频在线看| 精品成人国产在线观看男人呻吟| 五月婷婷欧美视频| www国产精品com| 激情小说综合区| 黄色a一级视频| 国产成人a v| 国产成人精品一区二三区在线观看 | 九九九免费视频| 少女频道在线观看免费播放电视剧 | 亚洲欧洲综合在线| 台湾天天综合人成在线| 久久99精品网久久| 欧美日韩国产精品自在自线| 欧美激情日韩图片| 成人免费无码av| 中文字幕一区2区3区| 国产美女视频一区二区| 日本不卡高清视频| 日韩免费成人网| 亚洲aⅴ天堂av在线电影软件| jlzzjizz在线播放观看| av在线中文| 国产精品久久久免费| 一区二区三区在线看| 国产成一区二区| 成人午夜激情av| 日韩精品手机在线| √天堂8资源中文在线| 亚洲精品色图| 欧美天堂在线观看| 精品视频在线导航| 91成人在线观看国产| 熟妇人妻va精品中文字幕 | 国产精品视频二区三区| 欧美日韩91| 欧美一级在线免费| 一区二区不卡在线| 91麻豆精品在线| 欧美性理论片在线观看片免费| 亚洲欧美日韩一区在线观看| 精品久久久久久久久久ntr影视| 最近中文字幕日韩精品 | 久久久国产精品x99av | 69国产精品视频免费观看| 91精品久久久久久综合五月天| 国产精品自拍毛片| 久久99热精品这里久久精品| 天天干天天草天天| www.在线视频| 成人在线视频一区| 欧美在线一级va免费观看| 右手影院亚洲欧美| 日本中文字幕一区二区| 国产精品色在线| 99理论电影网| 久久精品—区二区三区舞蹈| 九色成人搞黄网站| 国产精品拍天天在线| 91亚洲精品久久久| 天天干天天干天天干天天| 国产尤物久久久| 欧美一级黄色大片| 日本wwww视频| 国产精品刘玥久久一区| 99久久伊人精品| 大胆人体色综合| 青青草原av在线播放| 黄色av免费在线| 91丨porny丨最新| 51国偷自产一区二区三区 | 羞羞视频在线免费国产| hitomi一区二区三区精品| 国产精品视频导航| 日韩美女黄色片| 欧美一区二区| 91精品国产综合久久小美女| 99re在线国产| 久草视频在线免费| 亚洲麻豆av| 欧美成人免费网| 国产又粗又猛又爽又黄的视频小说 | 韩国美女主播一区| 成人免费黄色小视频| 精品福利久久久| 精品动漫一区二区三区在线观看| 97免费视频观看| 免费网站成人| 久久午夜色播影院免费高清| 欧美在线精品免播放器视频| 欧美日韩大片在线观看| 欧美一区二区三区久久精品茉莉花| 欧美一级二级三级乱码| 污污视频网站在线| 亚洲精品国产九九九| 日韩三级电影网址| 国产a√精品区二区三区四区| 欧美电影免费观看高清完整| 欧美日韩国产综合视频在线观看中文| 久久久久综合一区二区三区| 日本韩国精品一区二区| 国产欧美日产一区| 3d蒂法精品啪啪一区二区免费| www欧美在线| 久久精品久久精品| 午夜精品国产精品大乳美女| 人妻丰满熟妇aⅴ无码| 日韩一区二区三区四区五区 | 欧美在线观看视频| 性xxxxxxxxx| www.精品国产| 精品视频在线免费| 一级片黄色免费| 日韩av在线中文字幕| 国产精品久久久久久搜索| 四虎影视精品成人| 亚洲色图在线播放| 色综合电影网| 乱人伦视频在线| 欧美一区二区大片| 青青青手机在线视频| 国产精品久久久亚洲一区| 91视频免费进入| 男人天堂手机在线| 在线观看一区不卡| 欧美xxxx×黑人性爽| 激情丁香综合| 国产精品免费一区二区三区观看 | 日韩免费成人av| 性欧美长视频| 久久精品国产综合精品| 国产美女高潮在线观看| 五月天婷婷综合| aaaaaav|