main.go
1 // Copyright 2025 Alibaba Group Holding Ltd. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package main 16 17 import ( 18 "context" 19 "fmt" 20 "net/http" 21 "os" 22 "os/signal" 23 "syscall" 24 "time" 25 26 "k8s.io/klog/v2" 27 28 "github.com/alibaba/OpenSandbox/sandbox-k8s/internal/task-executor/config" 29 "github.com/alibaba/OpenSandbox/sandbox-k8s/internal/task-executor/manager" 30 "github.com/alibaba/OpenSandbox/sandbox-k8s/internal/task-executor/runtime" 31 "github.com/alibaba/OpenSandbox/sandbox-k8s/internal/task-executor/server" 32 store "github.com/alibaba/OpenSandbox/sandbox-k8s/internal/task-executor/storage" 33 ) 34 35 func main() { 36 // Load configuration 37 cfg := config.NewConfig() 38 cfg.LoadFromEnv() 39 cfg.LoadFromFlags() 40 if err := cfg.InitKlog(); err != nil { 41 fmt.Println("failed to init klog") 42 os.Exit(1) 43 } 44 klog.InfoS("task-executor starting", "dataDir", cfg.DataDir, "listenAddr", cfg.ListenAddr, "sidecarMode", cfg.EnableSidecarMode) 45 46 // Initialize TaskStore 47 taskStore, err := store.NewFileStore(cfg.DataDir) 48 if err != nil { 49 klog.ErrorS(err, "failed to create task store") 50 os.Exit(1) 51 } 52 klog.InfoS("task store initialized", "dataDir", cfg.DataDir) 53 54 // Initialize Executor 55 exec, err := runtime.NewExecutor(cfg) 56 if err != nil { 57 klog.ErrorS(err, "failed to create executor") 58 os.Exit(1) 59 } 60 61 // Initialize TaskManager 62 taskManager, err := manager.NewTaskManager(cfg, taskStore, exec) 63 if err != nil { 64 klog.ErrorS(err, "failed to create task manager") 65 os.Exit(1) 66 } 67 68 // Start TaskManager 69 taskManager.Start(context.Background()) 70 klog.InfoS("task manager started") 71 72 // Initialize HTTP Handler and Router 73 handler := server.NewHandler(taskManager, cfg) 74 router := server.NewRouter(handler) 75 76 // Create HTTP Server 77 svr := &http.Server{ 78 Addr: cfg.ListenAddr, 79 Handler: router, 80 ReadTimeout: cfg.ReadTimeout, 81 WriteTimeout: cfg.WriteTimeout, 82 } 83 84 // Start HTTP server in goroutine 85 go func() { 86 klog.InfoS("HTTP server listening", "address", cfg.ListenAddr) 87 if err := svr.ListenAndServe(); err != nil && err != http.ErrServerClosed { 88 klog.ErrorS(err, "HTTP server error") 89 os.Exit(1) 90 } 91 }() 92 93 // Wait for interrupt signal 94 quit := make(chan os.Signal, 1) 95 signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM) 96 <-quit 97 98 klog.InfoS("shutting down task-executor gracefully...") 99 100 // Shutdown context with timeout 101 shutdownCtx, shutdownCancel := context.WithTimeout(context.Background(), 30*time.Second) 102 defer shutdownCancel() 103 104 // 1. Stop HTTP server first 105 if err := svr.Shutdown(shutdownCtx); err != nil { 106 klog.ErrorS(err, "HTTP server shutdown error") 107 } else { 108 klog.InfoS("HTTP server stopped") 109 } 110 111 // 2. Stop TaskManager 112 taskManager.Stop() 113 klog.InfoS("task manager stopped") 114 115 klog.InfoS("task-executor stopped successfully") 116 }