重构事件驱动 Runner 并接入 OpenSandbox VM #30

Merged
panxiao81 merged 24 commits from refactor/go-task-scheduler into main 2026-09-21 06:11:41 +00:00
4 changed files with 16 additions and 10 deletions
Showing only changes of commit 44909c2ee1 - Show all commits
+7 -2
View File
@@ -41,6 +41,7 @@ type controllerConfig struct {
FacadeListen, FacadeURL, FacadeSPIFFEID string FacadeListen, FacadeURL, FacadeSPIFFEID string
CapabilityKey []byte CapabilityKey []byte
PodNamespace, PodImage, PodServiceAccount, SPIRECluster, SPIREClass string PodNamespace, PodImage, PodServiceAccount, SPIRECluster, SPIREClass string
SPIREAgentID string
PodExecutorUID, PodCapacity int PodExecutorUID, PodCapacity int
OpenSandboxURL, OpenSandboxAPIKey, OpenSandboxPool string OpenSandboxURL, OpenSandboxAPIKey, OpenSandboxPool string
VMTimeout, VMCapacity int VMTimeout, VMCapacity int
@@ -132,7 +133,8 @@ func runController(ctx context.Context) error {
backend := podbackend.Backend{API: client, Config: podbackend.Config{ backend := podbackend.Backend{API: client, Config: podbackend.Config{
Namespace: config.PodNamespace, Image: config.PodImage, ServiceAccount: config.PodServiceAccount, Namespace: config.PodNamespace, Image: config.PodImage, ServiceAccount: config.PodServiceAccount,
ExecutorArgs: []string{"executor"}, TrustDomain: config.TrustDomain, ExecutorArgs: []string{"executor"}, TrustDomain: config.TrustDomain,
SPIRECluster: config.SPIRECluster, SPIREClass: config.SPIREClass, ExecutorUID: config.PodExecutorUID, SPIRECluster: config.SPIRECluster, SPIREClass: config.SPIREClass,
SPIREAgentID: config.SPIREAgentID, ExecutorUID: config.PodExecutorUID,
}} }}
component, err := workerComponent(ctx, workerJS, config, taskassignment.BackendPod, config.PodCapacity, taskworker.Worker{Backend: backend, Bootstrap: bootstrap}, registry) component, err := workerComponent(ctx, workerJS, config, taskassignment.BackendPod, config.PodCapacity, taskworker.Worker{Backend: backend, Bootstrap: bootstrap}, registry)
if err != nil { if err != nil {
@@ -221,7 +223,7 @@ func loadControllerConfig() (controllerConfig, error) {
NATSCA: os.Getenv("NATS_CA_FILE"), Stream: env("NATS_STREAM", "CI_RUNNER"), SubjectBase: env("NATS_SUBJECT_BASE", "ci.runner"), NATSCA: os.Getenv("NATS_CA_FILE"), Stream: env("NATS_STREAM", "CI_RUNNER"), SubjectBase: env("NATS_SUBJECT_BASE", "ci.runner"),
FacadeListen: env("RUNNER_FACADE_LISTEN", ":8443"), FacadeURL: os.Getenv("RUNNER_FACADE_URL"), FacadeSPIFFEID: os.Getenv("RUNNER_FACADE_SPIFFE_ID"), CapabilityKey: []byte(capabilityKey), FacadeListen: env("RUNNER_FACADE_LISTEN", ":8443"), FacadeURL: os.Getenv("RUNNER_FACADE_URL"), FacadeSPIFFEID: os.Getenv("RUNNER_FACADE_SPIFFE_ID"), CapabilityKey: []byte(capabilityKey),
PodNamespace: env("POD_NAMESPACE", "gitea-actions"), PodImage: os.Getenv("POD_EXECUTOR_IMAGE"), PodServiceAccount: env("POD_SERVICE_ACCOUNT", "gitea-task-executor"), PodNamespace: env("POD_NAMESPACE", "gitea-actions"), PodImage: os.Getenv("POD_EXECUTOR_IMAGE"), PodServiceAccount: env("POD_SERVICE_ACCOUNT", "gitea-task-executor"),
SPIRECluster: env("SPIRE_CLUSTER", "homelab"), SPIREClass: env("SPIRE_CLASS", "spire-mgmt-spire"), PodExecutorUID: envInt("POD_EXECUTOR_UID", 2000), PodCapacity: envInt("POD_CAPACITY", 4), SPIRECluster: env("SPIRE_CLUSTER", "homelab"), SPIREClass: env("SPIRE_CLASS", "spire-mgmt-spire"), SPIREAgentID: os.Getenv("SPIRE_AGENT_ID"), PodExecutorUID: envInt("POD_EXECUTOR_UID", 2000), PodCapacity: envInt("POD_CAPACITY", 4),
OpenSandboxURL: os.Getenv("OPENSANDBOX_API"), OpenSandboxPool: env("OPENSANDBOX_POOL", "ci-vm"), VMTimeout: envInt("VM_TIMEOUT_SECONDS", 14400), VMCapacity: envInt("VM_CAPACITY", 1), OpenSandboxURL: os.Getenv("OPENSANDBOX_API"), OpenSandboxPool: env("OPENSANDBOX_POOL", "ci-vm"), VMTimeout: envInt("VM_TIMEOUT_SECONDS", 14400), VMCapacity: envInt("VM_CAPACITY", 1),
} }
if config.WorkloadAPIAddr == "" || config.FacadeURL == "" || config.FacadeSPIFFEID == "" { if config.WorkloadAPIAddr == "" || config.FacadeURL == "" || config.FacadeSPIFFEID == "" {
@@ -230,6 +232,9 @@ func loadControllerConfig() (controllerConfig, error) {
if slices.Contains(selection, controller.PodWorker) && config.PodImage == "" { if slices.Contains(selection, controller.PodWorker) && config.PodImage == "" {
return controllerConfig{}, errors.New("POD_EXECUTOR_IMAGE is required for pod-worker") return controllerConfig{}, errors.New("POD_EXECUTOR_IMAGE is required for pod-worker")
} }
if slices.Contains(selection, controller.PodWorker) && config.SPIREAgentID == "" {
return controllerConfig{}, errors.New("SPIRE_AGENT_ID is required for pod-worker")
}
if slices.Contains(selection, controller.VMWorker) { if slices.Contains(selection, controller.VMWorker) {
if config.OpenSandboxURL == "" { if config.OpenSandboxURL == "" {
return controllerConfig{}, errors.New("OPENSANDBOX_API is required for vm-worker") return controllerConfig{}, errors.New("OPENSANDBOX_API is required for vm-worker")
@@ -28,6 +28,7 @@ func TestLoadControllerConfigUsesFileSecrets(t *testing.T) {
t.Setenv("RUNNER_FACADE_URL", "https://gitea-runner-facade.gitea-actions.svc:8443") t.Setenv("RUNNER_FACADE_URL", "https://gitea-runner-facade.gitea-actions.svc:8443")
t.Setenv("RUNNER_FACADE_SPIFFE_ID", "spiffe://ddupan.top/ns/gitea-actions/sa/gitea-dynamic-runner") t.Setenv("RUNNER_FACADE_SPIFFE_ID", "spiffe://ddupan.top/ns/gitea-actions/sa/gitea-dynamic-runner")
t.Setenv("POD_EXECUTOR_IMAGE", "zot.ddupan.top/ci/gitea-runner@sha256:abc") t.Setenv("POD_EXECUTOR_IMAGE", "zot.ddupan.top/ci/gitea-runner@sha256:abc")
t.Setenv("SPIRE_AGENT_ID", "spiffe://ddupan.top/spire/agent/k8s_psat/homelab/node-uid")
config, err := loadControllerConfig() config, err := loadControllerConfig()
if err != nil { if err != nil {
+4 -6
View File
@@ -65,6 +65,7 @@ type Config struct {
TrustDomain string TrustDomain string
SPIRECluster string SPIRECluster string
SPIREClass string SPIREClass string
SPIREAgentID string
ExecutorUID int ExecutorUID int
} }
@@ -134,12 +135,9 @@ func (b Backend) BindIdentity(ctx context.Context, executor *taskworker.Executor
assignmentLabel: executor.Name, assignmentLabel: executor.Name,
}, },
ClassName: b.Config.SPIREClass, ClassName: b.Config.SPIREClass,
ParentID: fmt.Sprintf( ParentID: b.Config.SPIREAgentID,
"spiffe://%s/spire/agent/k8s_psat/%s/pod/%s",
b.Config.TrustDomain, b.Config.SPIRECluster, executor.IdentityTarget,
),
SPIFFEID: identity.SPIFFEID, SPIFFEID: identity.SPIFFEID,
Selectors: []string{fmt.Sprintf("unix:uid:%d", b.Config.ExecutorUID)}, Selectors: []string{"k8s:pod-uid:" + executor.IdentityTarget},
}) })
} }
@@ -168,7 +166,7 @@ func (b Backend) Delete(ctx context.Context, executor *taskworker.Executor) erro
} }
func (b Backend) validate() error { func (b Backend) validate() error {
if b.API == nil || b.Config.Namespace == "" || b.Config.Image == "" || b.Config.ServiceAccount == "" || b.Config.TrustDomain == "" || b.Config.SPIRECluster == "" || b.Config.SPIREClass == "" || b.Config.ExecutorUID < 1 { if b.API == nil || b.Config.Namespace == "" || b.Config.Image == "" || b.Config.ServiceAccount == "" || b.Config.TrustDomain == "" || b.Config.SPIRECluster == "" || b.Config.SPIREClass == "" || b.Config.SPIREAgentID == "" || b.Config.ExecutorUID < 1 {
return errors.New("Pod API and complete executor/SPIRE configuration are required") return errors.New("Pod API and complete executor/SPIRE configuration are required")
} }
return nil return nil
+4 -2
View File
@@ -46,7 +46,9 @@ func backend(api API) Backend {
Namespace: "gitea-actions", Image: "zot/ci-executor:main", Namespace: "gitea-actions", Image: "zot/ci-executor:main",
ServiceAccount: "gitea-task-executor", ExecutorArgs: []string{"executor"}, ServiceAccount: "gitea-task-executor", ExecutorArgs: []string{"executor"},
TrustDomain: "ddupan.top", SPIRECluster: "homelab", TrustDomain: "ddupan.top", SPIRECluster: "homelab",
SPIREClass: "spire-mgmt-spire", ExecutorUID: 2000, SPIREClass: "spire-mgmt-spire",
SPIREAgentID: "spiffe://ddupan.top/spire/agent/k8s_psat/homelab/node-uid",
ExecutorUID: 2000,
}} }}
} }
@@ -101,7 +103,7 @@ func TestBindIdentityCreatesEntryPinnedToPodUID(t *testing.T) {
if err := backend(api).BindIdentity(context.Background(), executor, assignment().Identity); err != nil { if err := backend(api).BindIdentity(context.Background(), executor, assignment().Identity); err != nil {
t.Fatal(err) t.Fatal(err)
} }
if api.entry.Name != executor.Name || api.entry.SPIFFEID != assignment().Identity.SPIFFEID || api.entry.ParentID != "spiffe://ddupan.top/spire/agent/k8s_psat/homelab/pod/pod-uid" || len(api.entry.Selectors) != 1 || api.entry.Selectors[0] != "unix:uid:2000" { if api.entry.Name != executor.Name || api.entry.SPIFFEID != assignment().Identity.SPIFFEID || api.entry.ParentID != "spiffe://ddupan.top/spire/agent/k8s_psat/homelab/node-uid" || len(api.entry.Selectors) != 1 || api.entry.Selectors[0] != "k8s:pod-uid:pod-uid" {
t.Fatalf("entry=%#v", api.entry) t.Fatalf("entry=%#v", api.entry)
} }
} }