fix: fixup multi problem
This commit is contained in:
@@ -17,6 +17,7 @@ import (
|
||||
k8sErrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
metricsclient "k8s.io/metrics/pkg/client/clientset/versioned"
|
||||
)
|
||||
|
||||
// HelmProvisioner : implémente Provisioner en appelant l'exécutable Helm.
|
||||
@@ -24,7 +25,8 @@ import (
|
||||
type HelmProvisioner struct {
|
||||
cfg *config.Config
|
||||
k8sClient *kubernetes.Clientset
|
||||
chartsDir string // chemin vers le dossier des charts (ex: /charts)
|
||||
metricsClient *metricsclient.Clientset // optionnel : nil si metrics-server indisponible
|
||||
chartsDir string // chemin vers le dossier des charts (ex: /charts)
|
||||
frontendImage string
|
||||
backendImage string
|
||||
baseDomain string
|
||||
@@ -34,9 +36,11 @@ type HelmProvisioner struct {
|
||||
// NewHelmProvisioner crée un nouveau provisioner Helm.
|
||||
// chartsDir : chemin absolu vers le dossier contenant les charts (backend/, frontend/)
|
||||
// helmPath : chemin vers l'exécutable helm (optionnel, default: "helm")
|
||||
// metricsClient : client metrics.k8s.io pour l'usage CPU/mémoire live (optionnel, peut être nil).
|
||||
func NewHelmProvisioner(
|
||||
cfg *config.Config,
|
||||
k8sClient *kubernetes.Clientset,
|
||||
metricsClient *metricsclient.Clientset,
|
||||
chartsDir string,
|
||||
helmPath string,
|
||||
) (*HelmProvisioner, error) {
|
||||
@@ -55,6 +59,7 @@ func NewHelmProvisioner(
|
||||
return &HelmProvisioner{
|
||||
cfg: cfg,
|
||||
k8sClient: k8sClient,
|
||||
metricsClient: metricsClient,
|
||||
chartsDir: chartsDir,
|
||||
frontendImage: cfg.FrontendImage,
|
||||
backendImage: cfg.BackendImage,
|
||||
@@ -336,6 +341,38 @@ func (h *HelmProvisioner) waitForRollout(namespace string) error {
|
||||
}
|
||||
}
|
||||
|
||||
// componentResourceLimits : limites CPU/mémoire configurées dans chaque chart
|
||||
// (deploy/chart-gestion/*/values.yaml), utilisées pour calculer un % d'usage.
|
||||
var componentResourceLimits = map[string]struct {
|
||||
cpuMilli int64
|
||||
memMi int64
|
||||
}{
|
||||
"backend": {cpuMilli: 500, memMi: 256},
|
||||
"frontend": {cpuMilli: 200, memMi: 128},
|
||||
"postgresql": {cpuMilli: 1000, memMi: 1024},
|
||||
"redis": {cpuMilli: 500, memMi: 512},
|
||||
}
|
||||
|
||||
// componentKey identifie le composant (backend/frontend/postgresql/redis) à
|
||||
// partir du nom de pod généré par Helm (ex: "demo-xxx-backend-...-6d59f4-abcde").
|
||||
func componentKey(podName string) string {
|
||||
switch {
|
||||
case strings.Contains(podName, "backend"):
|
||||
return "backend"
|
||||
case strings.Contains(podName, "frontend"):
|
||||
return "frontend"
|
||||
case strings.Contains(podName, "postgresql"):
|
||||
return "postgresql"
|
||||
case strings.Contains(podName, "redis"):
|
||||
return "redis"
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
// GetResourceState : phase + usage CPU/mémoire live de chaque pod d'une démo.
|
||||
// L'usage (metrics-server) est best-effort : s'il est indisponible, seule la
|
||||
// phase du pod est renseignée plutôt que de faire échouer tout l'appel.
|
||||
func (h *HelmProvisioner) GetResourceState(
|
||||
ctx context.Context,
|
||||
namespace string,
|
||||
@@ -349,23 +386,47 @@ func (h *HelmProvisioner) GetResourceState(
|
||||
return ResourceState{}, err
|
||||
}
|
||||
|
||||
usage := map[string][2]int64{} // pod name -> [cpuMilli, memMi]
|
||||
if h.metricsClient != nil {
|
||||
if list, err := h.metricsClient.MetricsV1beta1().PodMetricses(namespace).List(ctx, metav1.ListOptions{}); err == nil {
|
||||
for _, m := range list.Items {
|
||||
var cpu, mem int64
|
||||
for _, c := range m.Containers {
|
||||
cpu += c.Usage.Cpu().MilliValue()
|
||||
mem += c.Usage.Memory().Value() / (1024 * 1024)
|
||||
}
|
||||
usage[m.Name] = [2]int64{cpu, mem}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var state ResourceState
|
||||
|
||||
for _, pod := range pods.Items {
|
||||
status := string(pod.Status.Phase)
|
||||
key := componentKey(pod.Name)
|
||||
if key == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
switch {
|
||||
case strings.Contains(pod.Name, "backend"):
|
||||
state.APIState = status
|
||||
cs := ComponentState{Phase: string(pod.Status.Phase)}
|
||||
if limits, ok := componentResourceLimits[key]; ok {
|
||||
cs.CPULimitMilli = limits.cpuMilli
|
||||
cs.MemoryLimitMi = limits.memMi
|
||||
}
|
||||
if u, ok := usage[pod.Name]; ok {
|
||||
cs.CPUMilli = u[0]
|
||||
cs.MemoryMi = u[1]
|
||||
}
|
||||
|
||||
case strings.Contains(pod.Name, "frontend"):
|
||||
state.WebState = status
|
||||
|
||||
case strings.Contains(pod.Name, "postgresql"):
|
||||
state.DBState = status
|
||||
|
||||
case strings.Contains(pod.Name, "redis"):
|
||||
state.DBMemoryState = status
|
||||
switch key {
|
||||
case "backend":
|
||||
state.API = cs
|
||||
case "frontend":
|
||||
state.Web = cs
|
||||
case "postgresql":
|
||||
state.DB = cs
|
||||
case "redis":
|
||||
state.DBM = cs
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,11 +27,21 @@ type ExternalResource struct {
|
||||
|
||||
func (ExternalResource) TableName() string { return "external_pool" }
|
||||
|
||||
type ResourceState struct {
|
||||
APIState string `gorm:"size:20;not null" json:"api_state"`
|
||||
WebState string `gorm:"size:20;not null" json:"web_state"`
|
||||
DBState string `gorm:"size:20;not null" json:"db_state"`
|
||||
DBMemoryState string `gorm:"size:20;not null" json:"dbm_state"`
|
||||
// ComponentState : état live d'un composant (pod) d'une démo — phase k8s +
|
||||
// usage CPU/mémoire actuel rapporté par metrics-server, avec les limites
|
||||
// configurées dans le chart Helm correspondant (pour calculer un pourcentage).
|
||||
type ComponentState struct {
|
||||
Phase string `json:"phase"` // Running, Pending, Failed, Unknown, "" si pod introuvable
|
||||
CPUMilli int64 `json:"cpu_milli"` // usage CPU actuel, en millicores
|
||||
CPULimitMilli int64 `json:"cpu_limit_milli"` // limite CPU configurée, en millicores
|
||||
MemoryMi int64 `json:"memory_mi"` // usage mémoire actuel, en Mi
|
||||
MemoryLimitMi int64 `json:"memory_limit_mi"` // limite mémoire configurée, en Mi
|
||||
}
|
||||
|
||||
func (ResourceState) TableName() string { return "ressource_state" }
|
||||
// ResourceState : état live des 4 composants d'une démo.
|
||||
type ResourceState struct {
|
||||
API ComponentState `json:"api"`
|
||||
Web ComponentState `json:"web"`
|
||||
DB ComponentState `json:"db"`
|
||||
DBM ComponentState `json:"dbm"`
|
||||
}
|
||||
|
||||
@@ -8,19 +8,18 @@ import (
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/rest"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
metricsclient "k8s.io/metrics/pkg/client/clientset/versioned"
|
||||
)
|
||||
|
||||
func NewClient(cfg *config.Config) (*kubernetes.Clientset, error) {
|
||||
var (
|
||||
k8sCfg *rest.Config
|
||||
err error
|
||||
)
|
||||
|
||||
func restConfig(cfg *config.Config) (*rest.Config, error) {
|
||||
if cfg.Kubeconfig != "" {
|
||||
k8sCfg, err = clientcmd.BuildConfigFromFlags("", cfg.Kubeconfig)
|
||||
} else {
|
||||
k8sCfg, err = rest.InClusterConfig()
|
||||
return clientcmd.BuildConfigFromFlags("", cfg.Kubeconfig)
|
||||
}
|
||||
return rest.InClusterConfig()
|
||||
}
|
||||
|
||||
func NewClient(cfg *config.Config) (*kubernetes.Clientset, error) {
|
||||
k8sCfg, err := restConfig(cfg)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("k8s config: %w", err)
|
||||
}
|
||||
@@ -32,3 +31,19 @@ func NewClient(cfg *config.Config) (*kubernetes.Clientset, error) {
|
||||
|
||||
return client, nil
|
||||
}
|
||||
|
||||
// NewMetricsClient crée un client pour l'API metrics.k8s.io (metrics-server),
|
||||
// utilisée pour lire l'usage CPU/mémoire en direct des pods.
|
||||
func NewMetricsClient(cfg *config.Config) (*metricsclient.Clientset, error) {
|
||||
k8sCfg, err := restConfig(cfg)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("k8s config: %w", err)
|
||||
}
|
||||
|
||||
client, err := metricsclient.NewForConfig(k8sCfg)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("metrics clientset: %w", err)
|
||||
}
|
||||
|
||||
return client, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user