@@ -45,6 +45,17 @@ const (
45
45
ingressChartRepo = "https://kubernetes.github.io/ingress-nginx"
46
46
ingressChartName = "ingress-nginx/ingress-nginx"
47
47
ingressControllerName = "ingress-nginx-controller"
48
+ ingressNodePort = 30791
49
+
50
+ // Chaos Mesh constants
51
+ chaosMeshNamespace = "chaos-mesh"
52
+ chaosMeshReleaseName = "chaos-mesh"
53
+ chaosMeshChartRepo = "https://charts.chaos-mesh.org"
54
+ chaosMeshChartName = "chaos-mesh/chaos-mesh"
55
+ chaosMeshChartVersion = "2.7.2"
56
+ chaosMeshControllerName = "chaos-controller-manager"
57
+ chaosMeshDashboardName = "chaos-dashboard"
58
+ chaosMeshDashboardHost = "chaos-mesh.localhost"
48
59
)
49
60
50
61
//go:embed yaml/tmpnet-rbac.yaml
@@ -57,6 +68,7 @@ func StartKindCluster(
57
68
configPath string ,
58
69
startMetricsCollector bool ,
59
70
startLogsCollector bool ,
71
+ installChaosMesh bool ,
60
72
) error {
61
73
configContext := KindKubeconfigContext
62
74
@@ -116,6 +128,12 @@ func StartKindCluster(
116
128
return fmt .Errorf ("failed to create defaults ConfigMap: %w" , err )
117
129
}
118
130
131
+ if installChaosMesh {
132
+ if err := deployChaosMesh (ctx , log , configPath , configContext ); err != nil {
133
+ return fmt .Errorf ("failed to deploy chaos mesh: %w" , err )
134
+ }
135
+ }
136
+
119
137
return nil
120
138
}
121
139
@@ -342,7 +360,7 @@ func deployIngressController(ctx context.Context, log logging.Logger, configPath
342
360
"--wait" ,
343
361
"--set" , "controller.service.type=NodePort" ,
344
362
// This port value must match the port configured in scripts/kind-with-registry.sh
345
- "--set" , "controller.service.nodePorts.http=30791" ,
363
+ "--set" , fmt . Sprintf ( "controller.service.nodePorts.http=%d" , ingressNodePort ) ,
346
364
"--set" , "controller.admissionWebhooks.enabled=false" ,
347
365
"--set" , "controller.config.proxy-read-timeout=600" ,
348
366
"--set" , "controller.config.proxy-send-timeout=600" ,
@@ -448,7 +466,7 @@ func createDefaultsConfigMap(ctx context.Context, log logging.Logger, configPath
448
466
Namespace : namespace ,
449
467
},
450
468
Data : map [string ]string {
451
- ingressHostKey : "localhost:30791" ,
469
+ ingressHostKey : fmt . Sprintf ( "localhost:%d" , ingressNodePort ) ,
452
470
},
453
471
}
454
472
@@ -459,3 +477,148 @@ func createDefaultsConfigMap(ctx context.Context, log logging.Logger, configPath
459
477
460
478
return nil
461
479
}
480
+
481
+ // deployChaosMesh deploys Chaos Mesh using Helm.
482
+ func deployChaosMesh (ctx context.Context , log logging.Logger , configPath string , configContext string ) error {
483
+ log .Info ("checking if chaos mesh is already running" )
484
+
485
+ isRunning , err := isChaosMeshRunning (ctx , log , configPath , configContext )
486
+ if err != nil {
487
+ return fmt .Errorf ("failed to check chaos mesh status: %w" , err )
488
+ }
489
+ if isRunning {
490
+ log .Info ("chaos mesh already running" )
491
+ return nil
492
+ }
493
+
494
+ log .Info ("deploying chaos mesh using Helm" )
495
+
496
+ // Add the helm repo for chaos-mesh
497
+ if err := runHelmCommand (ctx , "repo" , "add" , "chaos-mesh" , chaosMeshChartRepo ); err != nil {
498
+ return fmt .Errorf ("failed to add chaos mesh helm repo: %w" , err )
499
+ }
500
+ if err := runHelmCommand (ctx , "repo" , "update" ); err != nil {
501
+ return fmt .Errorf ("failed to update helm repos: %w" , err )
502
+ }
503
+
504
+ // Install Chaos Mesh with all required settings including ingress
505
+ args := []string {
506
+ "install" ,
507
+ chaosMeshReleaseName ,
508
+ chaosMeshChartName ,
509
+ "--namespace" , chaosMeshNamespace ,
510
+ "--create-namespace" ,
511
+ "--version" , chaosMeshChartVersion ,
512
+ "--wait" ,
513
+ "--set" , "chaosDaemon.runtime=containerd" ,
514
+ "--set" , "chaosDaemon.socketPath=/run/containerd/containerd.sock" ,
515
+ "--set" , "dashboard.persistentVolume.enabled=true" ,
516
+ "--set" , "dashboard.persistentVolume.storageClass=standard" ,
517
+ "--set" , "dashboard.securityMode=false" ,
518
+ "--set" , "controllerManager.leaderElection.enabled=false" ,
519
+ "--set" , "dashboard.ingress.enabled=true" ,
520
+ "--set" , "dashboard.ingress.ingressClassName=nginx" ,
521
+ "--set" , "dashboard.ingress.hosts[0].name=" + chaosMeshDashboardHost ,
522
+ }
523
+
524
+ if err := runHelmCommand (ctx , args ... ); err != nil {
525
+ return fmt .Errorf ("failed to install chaos mesh: %w" , err )
526
+ }
527
+
528
+ // Wait for Chaos Mesh to be ready
529
+ if err := waitForChaosMesh (ctx , log , configPath , configContext ); err != nil {
530
+ return fmt .Errorf ("chaos mesh deployment failed: %w" , err )
531
+ }
532
+
533
+ // Log access information
534
+ log .Info ("Chaos Mesh installed successfully" ,
535
+ zap .String ("dashboardURL" , fmt .Sprintf ("http://%s:%d" , chaosMeshDashboardHost , ingressNodePort )),
536
+ zap .String ("portForwardCmd" , "kubectl port-forward -n chaos-mesh svc/chaos-dashboard 2333:2333" ),
537
+ )
538
+ log .Warn ("Chaos Mesh dashboard security is disabled - use only for local development" )
539
+
540
+ return nil
541
+ }
542
+
543
+ // isChaosMeshRunning checks if Chaos Mesh is already running.
544
+ func isChaosMeshRunning (ctx context.Context , log logging.Logger , configPath string , configContext string ) (bool , error ) {
545
+ clientset , err := GetClientset (log , configPath , configContext )
546
+ if err != nil {
547
+ return false , err
548
+ }
549
+
550
+ // Check if controller manager deployment exists
551
+ _ , err = clientset .AppsV1 ().Deployments (chaosMeshNamespace ).Get (ctx , chaosMeshControllerName , metav1.GetOptions {})
552
+ return ! apierrors .IsNotFound (err ), nil
553
+ }
554
+
555
+ // waitForChaosMesh waits for Chaos Mesh components to be ready.
556
+ func waitForChaosMesh (ctx context.Context , log logging.Logger , configPath string , configContext string ) error {
557
+ clientset , err := GetClientset (log , configPath , configContext )
558
+ if err != nil {
559
+ return fmt .Errorf ("failed to get clientset: %w" , err )
560
+ }
561
+
562
+ // Wait for controller manager
563
+ log .Info ("waiting for chaos mesh controller manager to be ready" )
564
+ err = wait .PollUntilContextCancel (ctx , statusCheckInterval , true /* immediate */ , func (ctx context.Context ) (bool , error ) {
565
+ deployment , err := clientset .AppsV1 ().Deployments (chaosMeshNamespace ).Get (ctx , chaosMeshControllerName , metav1.GetOptions {})
566
+ if err != nil {
567
+ log .Debug ("failed to get chaos mesh controller manager deployment" ,
568
+ zap .String ("namespace" , chaosMeshNamespace ),
569
+ zap .String ("deployment" , chaosMeshControllerName ),
570
+ zap .Error (err ),
571
+ )
572
+ return false , nil
573
+ }
574
+ if deployment .Status .ReadyReplicas == 0 {
575
+ log .Debug ("waiting for chaos mesh controller manager to become ready" ,
576
+ zap .String ("namespace" , chaosMeshNamespace ),
577
+ zap .String ("deployment" , chaosMeshControllerName ),
578
+ zap .Int32 ("readyReplicas" , deployment .Status .ReadyReplicas ),
579
+ zap .Int32 ("replicas" , deployment .Status .Replicas ),
580
+ )
581
+ return false , nil
582
+ }
583
+
584
+ log .Info ("chaos mesh controller manager is ready" ,
585
+ zap .String ("namespace" , chaosMeshNamespace ),
586
+ zap .String ("deployment" , chaosMeshControllerName ),
587
+ zap .Int32 ("readyReplicas" , deployment .Status .ReadyReplicas ),
588
+ )
589
+ return true , nil
590
+ })
591
+ if err != nil {
592
+ return fmt .Errorf ("controller manager not ready: %w" , err )
593
+ }
594
+
595
+ // Wait for dashboard
596
+ log .Info ("waiting for chaos mesh dashboard to be ready" )
597
+ return wait .PollUntilContextCancel (ctx , statusCheckInterval , true /* immediate */ , func (ctx context.Context ) (bool , error ) {
598
+ deployment , err := clientset .AppsV1 ().Deployments (chaosMeshNamespace ).Get (ctx , chaosMeshDashboardName , metav1.GetOptions {})
599
+ if err != nil {
600
+ log .Debug ("failed to get chaos mesh dashboard deployment" ,
601
+ zap .String ("namespace" , chaosMeshNamespace ),
602
+ zap .String ("deployment" , chaosMeshDashboardName ),
603
+ zap .Error (err ),
604
+ )
605
+ return false , nil
606
+ }
607
+ if deployment .Status .ReadyReplicas == 0 {
608
+ log .Debug ("waiting for chaos mesh dashboard to become ready" ,
609
+ zap .String ("namespace" , chaosMeshNamespace ),
610
+ zap .String ("deployment" , chaosMeshDashboardName ),
611
+ zap .Int32 ("readyReplicas" , deployment .Status .ReadyReplicas ),
612
+ zap .Int32 ("replicas" , deployment .Status .Replicas ),
613
+ )
614
+ return false , nil
615
+ }
616
+
617
+ log .Info ("chaos mesh dashboard is ready" ,
618
+ zap .String ("namespace" , chaosMeshNamespace ),
619
+ zap .String ("deployment" , chaosMeshDashboardName ),
620
+ zap .Int32 ("readyReplicas" , deployment .Status .ReadyReplicas ),
621
+ )
622
+ return true , nil
623
+ })
624
+ }
0 commit comments