精品欧美一区二区三区在线观看 _久久久久国色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技術棧公眾號

亚洲欧洲久久| 国产精品小说在线| 人妻无码一区二区三区| 丝袜美腿一区| 亚洲视频精选在线| 九九九九精品| 7777久久亚洲中文字幕| 国内在线观看一区二区三区| 亚洲欧美一区二区三区四区| 久久久久久久久久久久久久久国产| caoporn97在线视频| 99精品久久只有精品| 国产欧美日韩专区发布| 国产精品第九页| 日韩欧美网站| 亚洲精品99久久久久| 极品粉嫩美女露脸啪啪| 国产乱码午夜在线视频| 中文字幕一区二区在线观看| 精品视频一区在线| 国产日韩一级片| 久久黄色网页| 久久久中文字幕| 国产wwwwxxxx| 中日韩免视频上线全都免费| 日韩欧美三级在线| 中文字幕国内自拍| 性欧美freesex顶级少妇| 亚洲人成影院在线观看| 日韩一区二区电影在线观看| 天天摸天天碰天天爽天天弄| 国产一二三精品| 国产精品色午夜在线观看| www.av视频在线观看| 午夜片欧美伦| www.国产一区| 色www亚洲国产阿娇yao| 亚洲丝袜美腿一区| 亚洲精品国偷自产在线99热| 免费黄视频在线观看| 亚洲人成777| 欧美色老头old∨ideo| 97成人在线观看视频| caoprom在线| 亚洲国产视频一区| 国产高清不卡无码视频| 动漫一区在线| 亚洲欧洲中文日韩久久av乱码| 日本在线播放不卡| 免费观看成年在线视频网站| 97久久精品人人做人人爽| 成人在线看片| 蜜臀av中文字幕| 成人自拍视频在线| yellow视频在线观看一区二区| 国产特级aaaaaa大片| 久久99精品久久久久久| 国产精品自产拍在线观看| 亚洲 小说区 图片区| 性色av一区二区怡红| 51视频国产精品一区二区| 亚洲欧美在线观看视频| 中文亚洲欧美| 热门国产精品亚洲第一区在线| 啦啦啦免费高清视频在线观看| 一本色道久久综合亚洲精品高清| 91成品人片a无限观看| 天天操天天爽天天干| 另类av一区二区| 国产精品7m视频| 在线观看中文字幕2021| 精品一区二区三区蜜桃| 91最新在线免费观看| 超碰福利在线观看| 99精品欧美一区二区三区小说 | 国产女无套免费视频| 国产呦精品一区二区三区网站| 91久久精品美女高潮| www.亚洲黄色| 久久尤物电影视频在线观看| 水蜜桃一区二区| 美女免费久久| 亚洲一区免费观看| 日韩精品视频久久| 久久久久久一区二区三区四区别墅| 7777精品伊人久久久大香线蕉经典版下载 | 国产女主播自拍| 久久uomeier| 欧美老女人第四色| 制服丝袜在线第一页| 九九精品在线| 久久在线视频在线| 性无码专区无码| 久久精品国产999大香线蕉| 91手机在线观看| 精品视频一二三| 亚洲精品免费在线| 久久美女福利视频| 电影91久久久| 亚洲欧美另类人妖| 青春草免费视频| 老司机午夜精品视频| 亚洲综合中文字幕在线观看| 欧美777四色影视在线| 综合色天天鬼久久鬼色| 国产精品va无码一区二区| 久久久加勒比| 亚洲欧美中文日韩在线| 免费在线黄色片| 日本欧美一区二区三区| 好看的日韩精品视频在线| 午夜在线视频播放| 色天使色偷偷av一区二区| 丰满少妇中文字幕| 北条麻妃国产九九九精品小说 | 九九热精彩视频| 青娱乐精品在线视频| 国产美女在线精品免费观看| 黄色免费在线看| 欧美综合一区二区三区| 日本一区二区在线观看视频| 午夜av一区| 国产精品美女久久久久久免费| 五月婷婷激情在线| 亚洲一区二区成人在线观看| 亚洲精品视频三区| 精品国产乱码久久久久久果冻传媒| 久久免费精品日本久久中文字幕| 国产男女裸体做爰爽爽| 中文字幕欧美日本乱码一线二线| 国产黄页在线观看| 成人春色在线观看免费网站| 毛片精品免费在线观看| 伊人精品在线视频| 久久嫩草精品久久久久| 国产伦精品一区二区三区四区视频_| 久久天堂久久| 操91在线视频| 国产精品人人妻人人爽| 中文字幕中文乱码欧美一区二区| 性欧美极品xxxx欧美一区二区| 台湾色综合娱乐中文网| 欧美亚洲激情在线| 五月婷婷在线观看视频| 午夜精品一区在线观看| 999精品免费视频| 亚洲国产导航| 久99久视频| 欧美久久天堂| 日韩激情av在线免费观看| 国产乡下妇女做爰毛片| 成a人片亚洲日本久久| 水蜜桃色314在线观看| 国产精品色在线网站| 久久久久久午夜| 特黄视频在线观看| 大桥未久av一区二区三区| 黄色正能量网站| 老司机精品视频网站| 亚洲国产一区二区精品视频 | 懂色av中文字幕一区二区三区| 免费看污污视频| 1204国产成人精品视频| 国色天香2019中文字幕在线观看| 神马一区二区三区| 欧美性猛交xxxx乱大交| 国产一区二区三区四区五区六区| 日本亚洲三级在线| 综合久久国产| 丁香综合av| 91高潮在线观看| 国产精品天堂| 91精品国产综合久久久久久漫画| 久久久久久久久久久久久女过产乱| 国产精品一二一区| 97视频在线免费| 九九热爱视频精品视频| 国产精品专区第二| 成人av影院在线观看| 亚洲精品久久久久久久久久久| caoporn国产| 日韩一区欧美一区| 毛茸茸free性熟hd| 日本视频一区二区| 日韩精品福利片午夜免费观看| 国产乱人伦精品一区| 日本成人免费在线| 国产欧美黑人| 日韩高清有码在线| 国产一区二区三区四区视频 | 日韩欧美美女在线观看| 国产精品爽黄69天堂a| 色呦呦在线看| 亚洲欧美中文日韩在线v日本| 国产精品无码免费播放| 精品久久香蕉国产线看观看gif| 欧美激情视频二区| 成人中文字幕在线| 青青草原国产在线视频| 日韩午夜免费视频| 制服诱惑一区| 亚洲性视频大全| 99se婷婷在线视频观看| 日韩在线免费| 午夜精品国产精品大乳美女| 一本一道波多野毛片中文在线| 亚洲电影在线看| 国产又爽又黄免费软件| 欧美午夜久久久| 亚洲麻豆一区| 亚洲国产午夜伦理片大全在线观看网站 | 一区二区精品视频在线观看| 五月天婷婷综合| www欧美com| 久久久精品综合| 四虎成人免费视频| 国内精品免费在线观看| 亚洲成人av免费看| 亚洲影音先锋| 国产美女永久无遮挡| 欧美hentaied在线观看| 久久久久久久久一区| 亚洲乱码一区| 91综合免费在线| 四虎地址8848精品| 国产精品久久久久av免费| aaa在线播放视频| 欧美人与性动交a欧美精品| 免费在线午夜视频| 色多多国产成人永久免费网站| 免费一级在线观看播放网址| 亚洲国产欧美一区| 亚洲狼人综合网| 日韩视频免费观看高清完整版| 亚洲无码精品在线播放| 欧洲视频一区二区| 一级黄色大片视频| 色一区在线观看| 天天干天天干天天操| 欧美日韩国产一区二区三区| 久久久久无码精品国产| 亚洲最色的网站| 免费无遮挡无码永久在线观看视频| 中文字幕视频一区| 国产高清视频免费在线观看| 中文字幕精品一区二区精品绿巨人| 久久久久久亚洲中文字幕无码| 久久综合久久综合九色| 极品粉嫩小仙女高潮喷水久久| 不卡视频免费播放| 亚洲国产精品成人综合久久久| 91蜜桃婷婷狠狠久久综合9色| 日本护士做爰视频| www成人在线观看| 精品无码人妻一区二区免费蜜桃| 久久久蜜臀国产一区二区| 娇妻被老王脔到高潮失禁视频| 久久综合久久鬼色| 欧美a在线播放| 亚洲色图制服丝袜| 在线观看成人毛片| 亚洲成人精品一区| 日韩一级片中文字幕| 欧美午夜精品免费| 国产影视一区二区| 欧美www视频| 你懂的在线视频| 中文字幕精品—区二区| 九色porny丨首页在线| 欧美大片在线影院| 精精国产xxxx视频在线野外 | 久久精品久久久久久久| 欧美艳星brazzers| 国产日产亚洲系列最新| 亚洲国产精久久久久久| 免费毛片在线| 欧美尺度大的性做爰视频| 美女高潮视频在线看| 国产成人精品日本亚洲| 国产不卡精品| 久久久久久艹| 999久久久精品国产| 中文字幕人妻熟女人妻洋洋| 免费看黄裸体一级大秀欧美| 日本激情视频在线播放| 国产成人综合在线观看| 短视频在线观看| 亚洲三级免费观看| 男人的天堂一区二区| 欧美久久久久久久久中文字幕| 欧美一级性视频| 中文字幕亚洲第一| 国产精品电影| 国产专区欧美专区| 日韩高清在线免费观看| 一区二区视频国产| 国产欧美69| japan高清日本乱xxxxx| 国产欧美精品一区二区色综合 | 欧美日产国产精品| 日本人妻丰满熟妇久久久久久| 中文字幕在线观看日韩| 啊啊啊久久久| 亚洲一区免费网站| 成人久久综合| www.av毛片| 狠狠狠色丁香婷婷综合激情| 疯狂揉花蒂控制高潮h| 亚洲精选视频免费看| 懂色av蜜臀av粉嫩av喷吹| 亚洲大胆人体av| 影音先锋中文在线视频| 国产日韩在线视频| 国产探花在线精品| 日本www在线播放| 成人天堂资源www在线| 国产老头老太做爰视频| 91成人在线精品| 天堂网av在线播放| 欧美激情在线狂野欧美精品| 国产精品视频首页| 亚洲午夜在线观看| 日本va欧美va精品| 实拍女处破www免费看| 亚洲成人综合视频| 午夜久久久久久久久久| 久久亚洲精品一区二区| 久久日本片精品aaaaa国产| 奇米视频888战线精品播放| 99亚洲伊人久久精品影院红桃| 美女日批在线观看| 亚洲蜜臀av乱码久久精品| 亚洲熟女乱色一区二区三区久久久| 亚洲免费高清视频| 亚洲欧洲自拍| 蜜桃久久精品乱码一区二区| 亚洲美洲欧洲综合国产一区| 色悠悠在线视频| 亚洲一区二区三区不卡国产欧美 | 国产午夜精品理论片a级探花| 黄色污污视频在线观看| av在线不卡一区| 欧美三区视频| 国产亚洲精品成人a| 亚洲va韩国va欧美va| 欧美一区二区黄片| 性色av一区二区咪爱| 免费看成人人体视频| 91好吊色国产欧美日韩在线| 99精品久久久久久| 欧美亚洲另类小说| 在线视频日韩精品| 日本午夜免费一区二区| 国产又粗又爽又黄的视频| 国产麻豆欧美日韩一区| 强行糟蹋人妻hd中文| 亚洲第一男人av| 中文字幕一区久| 亚洲国产高清国产精品| 激情五月激情综合网| 激情综合五月网| 亚洲精品国产电影| 日韩久久一区二区三区| 亚洲日本无吗高清不卡| 国产一区二区三区不卡在线观看| 久久精品视频免费在线观看| 亚洲аv电影天堂网| 日本成人三级电影| 伊人色综合影院| 成人福利电影精品一区二区在线观看 | 人妻va精品va欧美va| 日本一本a高清免费不卡| 不卡视频在线| 九色91porny| 欧美午夜精品在线| 免费黄色电影在线观看| 国产精品高清一区二区三区| 久久久久免费| 中文字幕五月天| 亚洲国产小视频在线观看| av成人亚洲| 国产日韩欧美精品在线观看| 国产亚洲精品免费| www.成人免费视频| 欧美中文在线观看| 91精品啪在线观看国产18| 黄色国产在线视频| 欧美亚洲禁片免费| 爱看av在线| 午夜欧美性电影| av中文字幕一区| 一级爱爱免费视频| 91国在线精品国内播放| 久久精品国产www456c0m| 国产精品入口麻豆| 欧美日韩一二三| 老司机深夜福利在线观看| 一卡二卡3卡四卡高清精品视频| 床上的激情91.| 亚洲视频一区二区三区四区|