Skip to content

Commit 5ebe4f3

Browse files
fhpa-usage tutorial construction
Signed-off-by: Krishiv-Mahajan <mahajankrishiv10@gmail.com>
1 parent 206330c commit 5ebe4f3

29 files changed

Lines changed: 791 additions & 0 deletions

File tree

karmada-FHPA-example/finish.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Summary
2+
3+
In this scenario, we installed metrics-server on member clusters and enabled the karmada-metrics-adapter on the control plane to provide CPU metrics for autoscaling, created a FederatedHPA resource to monitor CPU utilization across all member clusters and automatically adjust the number of replicas based on workload demand. To test the scaling behavior, we generated CPU load using the `williamyeh/hey` load-generator pod and observed the FederatedHPA trigger a scale-up event. After stopping the load generation, we also observed the FederatedHPA scale the workload back down automatically once CPU usage returned to normal.

karmada-FHPA-example/foreground.sh

Lines changed: 268 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,268 @@
1+
#!/usr/bin/env bash
2+
3+
set -o errexit
4+
set -o nounset
5+
set -o pipefail
6+
7+
# variable define
8+
kind_version=v0.17.0
9+
host_cluster_ip=172.30.1.2 #host node where Karmada is located
10+
member_cluster_ip=172.30.2.2
11+
local_ip=127.0.0.1
12+
KUBECONFIG_PATH=${KUBECONFIG_PATH:-"${HOME}/.kube"}
13+
14+
function installKind() {
15+
cat << EOF > installKind.sh
16+
set -e
17+
wget https://github.com/kubernetes-sigs/kind/releases/download/${kind_version}/kind-linux-amd64
18+
chmod +x kind-linux-amd64
19+
sudo mv kind-linux-amd64 /usr/local/bin/kind
20+
EOF
21+
}
22+
23+
function createCluster() {
24+
cat << EOF > createCluster.sh
25+
set -e
26+
kind delete cluster --name=member1 || true
27+
kind create cluster --name=member1 --config=cluster1.yaml
28+
# Patch kindnet to use less CPU
29+
kubectl --kubeconfig \$HOME/.kube/config patch daemonset kindnet -n kube-system --type='json' -p='[{"op": "add", "path": "/spec/template/spec/containers/0/resources", "value": {"requests": {"cpu": "50m"}, "limits": {"cpu": "200m"}}}]'
30+
# Patch coredns
31+
kubectl --kubeconfig \$HOME/.kube/config patch deployment coredns -n kube-system --type='json' -p='[{"op": "replace", "path": "/spec/template/spec/containers/0/resources/requests/cpu", "value": "30m"}, {"op": "replace", "path": "/spec/template/spec/containers/0/resources/limits/cpu", "value": "100m"}]'
32+
mv \$HOME/.kube/config ~/config-member1
33+
34+
kind delete cluster --name=member2 || true
35+
kind create cluster --name=member2 --config=cluster2.yaml
36+
kubectl --kubeconfig \$HOME/.kube/config patch daemonset kindnet -n kube-system --type='json' -p='[{"op": "add", "path": "/spec/template/spec/containers/0/resources", "value": {"requests": {"cpu": "50m"}, "limits": {"cpu": "200m"}}}]'
37+
kubectl --kubeconfig \$HOME/.kube/config patch deployment coredns -n kube-system --type='json' -p='[{"op": "replace", "path": "/spec/template/spec/containers/0/resources/requests/cpu", "value": "30m"}, {"op": "replace", "path": "/spec/template/spec/containers/0/resources/limits/cpu", "value": "100m"}]'
38+
mv \$HOME/.kube/config config-member2
39+
40+
# modify ip
41+
sed -i "s/${local_ip}/${member_cluster_ip}/g" config-member1
42+
# set StrictHostKeyChecking to no to avoid prompting, the same below
43+
scp -o StrictHostKeyChecking=no config-member1 root@${host_cluster_ip}:$HOME/.kube/config-member1
44+
sed -i "s/${local_ip}/${member_cluster_ip}/g" config-member2
45+
scp -o StrictHostKeyChecking=no config-member2 root@${host_cluster_ip}:$HOME/.kube/config-member2
46+
EOF
47+
}
48+
49+
function cluster1Config() {
50+
cat << EOF > cluster1.yaml
51+
kind: Cluster
52+
apiVersion: kind.x-k8s.io/v1alpha4
53+
networking:
54+
apiServerAddress: "${member_cluster_ip}"
55+
apiServerPort: 6443
56+
serviceSubnet: "10.250.0.0/16"
57+
podSubnet: "10.251.0.0/16"
58+
nodes:
59+
- role: control-plane
60+
EOF
61+
}
62+
63+
function cluster2Config() {
64+
cat << EOF > cluster2.yaml
65+
kind: Cluster
66+
apiVersion: kind.x-k8s.io/v1alpha4
67+
networking:
68+
apiServerAddress: "${member_cluster_ip}"
69+
apiServerPort: 6444
70+
serviceSubnet: "10.250.0.0/16"
71+
podSubnet: "10.251.0.0/16"
72+
nodes:
73+
- role: control-plane
74+
EOF
75+
}
76+
77+
function installMetrics() {
78+
cat << 'EOF' > installMetricsServer.sh
79+
# Install metrics-server on member clusters
80+
_tmp=$(mktemp -d)
81+
82+
cleanup() {
83+
rm -rf "${_tmp}"
84+
}
85+
trap cleanup EXIT
86+
87+
METRICS_SERVER_URL="https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml"
88+
if command -v curl &>/dev/null && curl -fsSL "${METRICS_SERVER_URL}" -o "${_tmp}/components.yaml"; then
89+
:
90+
elif command -v wget &>/dev/null && wget -qO "${_tmp}/components.yaml" "${METRICS_SERVER_URL}"; then
91+
:
92+
else
93+
echo "ERROR: failed to download metrics-server components.yaml. Please ensure curl or wget is installed and network access is available."
94+
exit 1
95+
fi
96+
97+
sed -i'' -e 's/args:/args:\n - --kubelet-insecure-tls=true/' "${_tmp}/components.yaml"
98+
99+
kubectl --kubeconfig=$HOME/.kube/config-member1 apply -f "${_tmp}/components.yaml"
100+
kubectl --kubeconfig=$HOME/.kube/config-member2 apply -f "${_tmp}/components.yaml"
101+
EOF
102+
chmod +x installMetricsServer.sh
103+
104+
cat << 'EOF' > installMetricsAdapter.sh
105+
# Install karmada-metrics-adapter on the Karmada control plane
106+
# This bridges metrics from member clusters to the FederatedHPA controller
107+
karmadactl addons enable karmada-metrics-adapter --kubeconfig=$HOME/.kube/config
108+
EOF
109+
chmod +x installMetricsAdapter.sh
110+
111+
112+
}
113+
114+
function nginxDeployment() {
115+
cat << EOF > nginxDeployment.yaml
116+
apiVersion: apps/v1
117+
kind: Deployment
118+
metadata:
119+
name: nginx
120+
labels:
121+
app: nginx
122+
spec:
123+
replicas: 1
124+
selector:
125+
matchLabels:
126+
app: nginx
127+
template:
128+
metadata:
129+
labels:
130+
app: nginx
131+
spec:
132+
containers:
133+
- image: nginx
134+
name: nginx
135+
resources:
136+
requests:
137+
cpu: 10m
138+
memory: 32Mi
139+
limits:
140+
cpu: 100m
141+
memory: 64Mi
142+
---
143+
apiVersion: v1
144+
kind: Service
145+
metadata:
146+
name: nginx-service
147+
spec:
148+
ports:
149+
- port: 80
150+
targetPort: 80
151+
selector:
152+
app: nginx
153+
EOF
154+
}
155+
156+
function propagationPolicy() {
157+
cat << EOF > propagationPolicy.yaml
158+
apiVersion: policy.karmada.io/v1alpha1
159+
kind: PropagationPolicy
160+
metadata:
161+
name: nginx-propagation
162+
spec:
163+
resourceSelectors:
164+
- apiVersion: apps/v1
165+
kind: Deployment
166+
name: nginx
167+
- apiVersion: v1
168+
kind: Service
169+
name: nginx-service
170+
placement:
171+
clusterAffinity:
172+
clusterNames:
173+
- kind-member1
174+
- kind-member2
175+
replicaScheduling:
176+
replicaDivisionPreference: Weighted
177+
replicaSchedulingType: Divided
178+
weightPreference:
179+
staticWeightList:
180+
- targetCluster:
181+
clusterNames:
182+
- kind-member1
183+
weight: 1
184+
- targetCluster:
185+
clusterNames:
186+
- kind-member2
187+
weight: 1
188+
EOF
189+
}
190+
191+
function federatedHPA() {
192+
cat << EOF > federatedHPA.yaml
193+
apiVersion: autoscaling.karmada.io/v1alpha1
194+
kind: FederatedHPA
195+
metadata:
196+
name: nginx-fhpa
197+
spec:
198+
scaleTargetRef:
199+
apiVersion: apps/v1
200+
kind: Deployment
201+
name: nginx
202+
minReplicas: 1
203+
maxReplicas: 4
204+
behavior:
205+
scaleDown:
206+
stabilizationWindowSeconds: 10
207+
scaleUp:
208+
stabilizationWindowSeconds: 0
209+
metrics:
210+
- type: Resource
211+
resource:
212+
name: cpu
213+
target:
214+
type: Utilization
215+
averageUtilization: 10
216+
EOF
217+
}
218+
219+
function multiClusterService() {
220+
cat << EOF > multiClusterService.yaml
221+
apiVersion: networking.karmada.io/v1alpha1
222+
kind: MultiClusterService
223+
metadata:
224+
name: nginx-service
225+
spec:
226+
types:
227+
- CrossCluster
228+
consumerClusters:
229+
- name: kind-member1
230+
- name: kind-member2
231+
providerClusters:
232+
- name: kind-member1
233+
- name: kind-member2
234+
EOF
235+
}
236+
237+
function copyConfigFilesToNode() {
238+
scp -o StrictHostKeyChecking=no \
239+
installKind.sh \
240+
createCluster.sh \
241+
cluster1.yaml \
242+
cluster2.yaml \
243+
root@${member_cluster_ip}:~
244+
}
245+
246+
kubectl delete node node01 || true
247+
kubectl taint node controlplane node-role.kubernetes.io/control-plane:NoSchedule-
248+
249+
# prepare helper scripts and cluster config files
250+
installKind
251+
createCluster
252+
cluster1Config
253+
cluster2Config
254+
copyConfigFilesToNode
255+
256+
installMetrics
257+
258+
# generate nginx and FHPA config files
259+
mkdir -p ~/fhpa
260+
cd ~/fhpa
261+
nginxDeployment
262+
propagationPolicy
263+
federatedHPA
264+
multiClusterService
265+
cd ~
266+
267+
# clean screen
268+
clear
6.66 KB
Loading

karmada-FHPA-example/index.json

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
{
2+
"title": "FederatedHPA: Autoscaling Across Clusters",
3+
"description": "Learn how to use Karmada FederatedHPA to automatically scale workloads across multiple clusters based on CPU metrics",
4+
"details": {
5+
"intro": {
6+
"text": "intro.md",
7+
"foreground": "foreground.sh"
8+
},
9+
"steps": [
10+
{
11+
"title": "Environment overview",
12+
"text": "step1/text.md",
13+
"verify": "step1/verify.sh"
14+
},
15+
{
16+
"title": "Install karmadactl",
17+
"text": "step2/text.md",
18+
"verify": "step2/verify.sh"
19+
},
20+
{
21+
"title": "Initialize Karmada control plane",
22+
"text": "step3/text.md",
23+
"verify": "step3/verify.sh"
24+
},
25+
{
26+
"title": "Prepare member clusters",
27+
"text": "step4/text.md",
28+
"verify": "step4/verify.sh"
29+
},
30+
{
31+
"title": "Join member clusters to the host cluster",
32+
"text": "step5/text.md",
33+
"verify": "step5/verify.sh"
34+
},
35+
{
36+
"title": "Install metrics-server on member clusters",
37+
"text": "step6/text.md",
38+
"verify": "step6/verify.sh"
39+
},
40+
{
41+
"title": "Install karmada-metrics-adapter",
42+
"text": "step7/text.md",
43+
"verify": "step7/verify.sh"
44+
},
45+
{
46+
"title": "Deploy nginx workload",
47+
"text": "step8/text.md",
48+
"verify": "step8/verify.sh"
49+
},
50+
{
51+
"title": "Create PropagationPolicy",
52+
"text": "step9/text.md",
53+
"verify": "step9/verify.sh"
54+
},
55+
{
56+
"title": "Configure Multi-Cluster Routing",
57+
"text": "step10/text.md",
58+
"verify": "step10/verify.sh"
59+
},
60+
{
61+
"title": "Deploy FederatedHPA",
62+
"text": "step11/text.md",
63+
"verify": "step11/verify.sh"
64+
},
65+
{
66+
"title": "Trigger load and observe autoscaling",
67+
"text": "step12/text.md",
68+
"verify": "step12/verify.sh"
69+
}
70+
],
71+
"finish": {
72+
"text": "finish.md"
73+
}
74+
},
75+
"backend": {
76+
"imageid": "kubernetes-kubeadm-2nodes"
77+
}
78+
}

karmada-FHPA-example/intro.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# What is Karmada?
2+
3+
Karmada (Kubernetes Armada) is a Kubernetes management system that enables you to run your cloud-native applications across multiple Kubernetes clusters and clouds, with no changes to your applications. By speaking Kubernetes-native APIs and providing advanced scheduling capabilities, Karmada enables truly open, multi-cloud Kubernetes.
4+
5+
Karmada aims to provide turnkey automation for multi-cluster application management in multi-cloud and hybrid cloud scenarios, with key features such as centralized multi-cloud management, high availability, failure recovery, and traffic scheduling.
6+
7+
# What is FederatedHPA?
8+
9+
When load increases, FederatedHPA scales up the replicas of the workload if the number of Pods is below the configured maximum. When load decreases, it scales them back down to the configured minimum.
10+
11+
In this scenario, we will create a FederatedHPA targeting CPU utilization, and trigger a CPU load to observe autoscaling across clusters.

karmada-FHPA-example/step1/text.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Environment Overview
2+
3+
The environment consists of two hosts:
4+
5+
1. `controlplane`: The host Kubernetes cluster where Karmada runs. The kubeconfig files for the host cluster are located in the `$HOME/.kube` directory.
6+
2. `node01`: Used to create member clusters.
7+
8+
| HostName | Host IP |
9+
| --- | --- |
10+
| controlplane | 172.30.1.2 |
11+
| node01 | 172.30.2.2 |
12+
13+
Note: The current terminal is on the host `controlplane`.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#!/bin/bash
2+
3+
set -e
4+
5+
# Verify node01 is reachable
6+
ssh -o StrictHostKeyChecking=no root@172.30.2.2 "echo node01 ready"

0 commit comments

Comments
 (0)