Skip to content

Commit 3dc203a

Browse files
authored
Merge pull request #1 from yanmxa/patch_sidecar
patch sidecar
2 parents 1312044 + 33ebb17 commit 3dc203a

6 files changed

Lines changed: 65 additions & 7 deletions

File tree

federated-learning-controller/deploy/obs/hack/certs/generate-certs.sh

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,16 @@ kubectl --context kind-hub create secret tls otel-signer -n open-cluster-managem
3737

3838
# replace root-ca.crt in deploy/resources/addon-template.yaml
3939
awk '{print " " $0}' root-ca.crt > root-ca.crt.tmp
40-
sed -i "/PROM_WEB_ROOT_CA/{
40+
# Cross-platform sed -i compatibility
41+
if [[ "$OSTYPE" == "darwin"* ]]; then
42+
sed -i '' "/PROM_WEB_ROOT_CA/{
4143
r root-ca.crt.tmp
4244
d
4345
}" ../../otel-addon/resources/addon-template.yaml
46+
else
47+
sed -i "/PROM_WEB_ROOT_CA/{
48+
r root-ca.crt.tmp
49+
d
50+
}" ../../otel-addon/resources/addon-template.yaml
51+
fi
4452
rm root-ca.crt.tmp

federated-learning-controller/examples/flower/app-torch/app_torch/client_app.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,14 +56,14 @@ def evaluate(self, parameters, config):
5656
loss, accuracy = test(self.net, self.device, self.valloader)
5757
print(f"Evaluation Loss: {loss}, Accuracy: {accuracy}")
5858
metrics = {
59-
"evaluation_loss": loss,
59+
"loss": loss,
6060
"accuracy": accuracy,
6161
}
6262
labels = {
6363
"round": config["server_round"],
6464
}
6565
write_metrics(metrics, labels)
66-
return loss, len(self.valloader.dataset), {"accuracy": accuracy}
66+
return loss, len(self.valloader.dataset), {"accuracy": accuracy, "loss": loss}
6767

6868
def client_fn(context: Context):
6969
# Load model and data

federated-learning-controller/examples/flower/app-torch/app_torch/server_app.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,9 @@ def parse_arguments():
4040
def client_weighted_average(metrics: List[Tuple[int, Metrics]]) -> Metrics:
4141
"""Compute weighted average of client accuracy."""
4242
accuracies = [num_examples * metric["accuracy"] for num_examples, metric in metrics]
43+
losses = [num_examples * metric["loss"] for num_examples, metric in metrics]
4344
examples = [num_examples for num_examples, _ in metrics]
44-
return {"accuracy": sum(accuracies) / sum(examples)}
45+
return {"accuracy": sum(accuracies) / sum(examples), "loss": sum(losses) / sum(examples)}
4546

4647
def fit_evaluate_config(server_round: int):
4748
config = {

federated-learning-controller/internal/controller/manifests/client/manifestwork.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ spec:
3939
labels:
4040
job-name: {{ .ClientJobName }} # Ensure labels match the selector
4141
spec:
42+
shareProcessNamespace: true
4243
volumes:
4344
- name: metric-data
4445
emptyDir: {}

federated-learning-controller/internal/controller/manifests/server/server-job.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ spec:
1212
labels:
1313
job-name: {{ .Name }} # Ensure labels match the selector
1414
spec:
15+
shareProcessNamespace: true
1516
containers:
1617
- name: flower-server
1718
image: {{ .Image }}

federated-learning-controller/internal/sidecar/main.go

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,17 @@ package main
22

33
import (
44
"context"
5-
"fl_sidecar/exporter"
6-
"fl_sidecar/watcher"
75
"flag"
86
"fmt"
97
"log"
108
"os"
9+
"os/exec"
1110
"os/signal"
1211
"syscall"
12+
"time"
13+
14+
"fl_sidecar/exporter"
15+
"fl_sidecar/watcher"
1316
)
1417

1518
// Command-line flags
@@ -65,12 +68,32 @@ func main() {
6568

6669
log.Printf("Start watching file %s", metricFile)
6770

71+
// Check if main container process is still running periodically
72+
go func() {
73+
for {
74+
// Check if main container is still running (when shareProcessNamespace is enabled)
75+
if checkMainContainerExited() {
76+
log.Println("Main container exited, exiting sidecar...")
77+
cancel()
78+
return
79+
}
80+
81+
select {
82+
case <-ctx.Done():
83+
return
84+
default:
85+
// Check every 5 seconds
86+
time.Sleep(5 * time.Second)
87+
}
88+
}
89+
}()
90+
6891
// Main loop to process file updates and handle shutdown
6992
for {
7093
select {
7194
case content, ok := <-updateChan:
7295
if !ok {
73-
log.Fatalf("Watcher channel closed")
96+
log.Println("Watcher channel closed")
7497
return
7598
}
7699

@@ -84,6 +107,30 @@ func main() {
84107
}
85108
}
86109

110+
// checkMainContainerExited checks if the main container (flower-server or flower-client) process has exited
111+
// This works when shareProcessNamespace is enabled in the pod spec
112+
func checkMainContainerExited() bool {
113+
// Check if the main flower server or client process is still running
114+
// Try different patterns for server and client containers
115+
patterns := []string{
116+
".*server.*--num-rounds", // Server process pattern
117+
".*client.*--data-config", // Client process pattern
118+
".*client.*--server-address", // Alternative client pattern
119+
}
120+
121+
for _, pattern := range patterns {
122+
cmd := exec.Command("pgrep", "-f", pattern)
123+
err := cmd.Run()
124+
if err == nil {
125+
// Found a matching process, main container is still running
126+
return false
127+
}
128+
}
129+
130+
// No matching processes found, main container has likely exited
131+
return true
132+
}
133+
87134
// parseAndPushMtrics parses the content of the metric file and pushes the metrics to the reporter.
88135
func parseAndPushMtrics(reporter *exporter.Reporter, content []byte) {
89136
metrics, labels, err := exporter.ParseContetnt(content)

0 commit comments

Comments
 (0)