@@ -260,22 +260,16 @@ func agentJoinServer(opts *agent.Options) error {
260260
261261// agentJoinKubernetes applies a Deployment + RBAC to the target cluster so the
262262// agent runs as a persistent in-cluster workload.
263+ //
264+ // Two auth modes are supported:
265+ // - Join-token mode (--token): Deployment runs with --token flag; no kubeconfig Secret needed.
266+ // - Kubeconfig mode (--hub-kubeconfig): Deployment mounts a Secret containing the hub kubeconfig.
263267func agentJoinKubernetes (opts * agent.Options ) error {
264- if opts .HubKubeconfig == "" {
265- return fmt .Errorf ("--hub-kubeconfig is required for kubernetes-type join" )
268+ if opts .HubKubeconfig == "" && opts . Token == "" {
269+ return fmt .Errorf ("--hub-kubeconfig or --token is required for kubernetes-type join" )
266270 }
267271
268- // Resolve the hub kubeconfig to absolute path so the mounted Secret is portable.
269- absKubeconfig , err := filepath .Abs (opts .HubKubeconfig )
270- if err != nil {
271- return fmt .Errorf ("resolving hub kubeconfig path: %w" , err )
272- }
273-
274- // Read kubeconfig content to embed as a Secret.
275- kubeconfigData , err := os .ReadFile (absKubeconfig )
276- if err != nil {
277- return fmt .Errorf ("reading hub kubeconfig: %w" , err )
278- }
272+ usingToken := opts .Token != ""
279273
280274 // Determine the target cluster kubeconfig for kubectl.
281275 kubectlArgs := []string {}
@@ -296,21 +290,6 @@ metadata:
296290 return fmt .Errorf ("creating kedge-system namespace: %w" , err )
297291 }
298292
299- // Create Secret with hub kubeconfig.
300- secretName := "kedge-agent-" + opts .EdgeName + "-hub-kubeconfig"
301- secretManifest := fmt .Sprintf (`apiVersion: v1
302- kind: Secret
303- metadata:
304- name: %s
305- namespace: kedge-system
306- type: Opaque
307- stringData:
308- hub.kubeconfig: |
309- %s` , secretName , indentLines (string (kubeconfigData ), " " ))
310- if err := kubectlApplyManifest (kubectlArgs , secretManifest ); err != nil {
311- return fmt .Errorf ("creating hub kubeconfig secret: %w" , err )
312- }
313-
314293 // ServiceAccount.
315294 saManifest := fmt .Sprintf (`apiVersion: v1
316295kind: ServiceAccount
@@ -322,13 +301,88 @@ metadata:
322301 return fmt .Errorf ("creating ServiceAccount: %w" , err )
323302 }
324303
325- // Deployment.
326304 image := "ghcr.io/faroshq/kedge-agent:latest"
327- deployArgs := fmt .Sprintf ("agent run --hub-kubeconfig=/etc/kedge/hub.kubeconfig --edge-name=%s --type=kubernetes --hub-insecure-skip-tls-verify" , opts .EdgeName )
328- if opts .Cluster != "" {
329- deployArgs += " --cluster=" + opts .Cluster
330- }
331- deployManifest := fmt .Sprintf (`apiVersion: apps/v1
305+
306+ var deployManifest string
307+
308+ if usingToken {
309+ // Token-based bootstrap: pass --token directly in Deployment args.
310+ // The agent exchanges the join token for a kubeconfig on first connect;
311+ // no hub kubeconfig Secret is required.
312+ hubURL := opts .HubURL
313+ if hubURL == "" {
314+ return fmt .Errorf ("--hub-url is required when using --token for kubernetes-type join" )
315+ }
316+ deployArgs := fmt .Sprintf ("agent run --hub-url=%s --edge-name=%s --type=kubernetes --token=%s" ,
317+ hubURL , opts .EdgeName , opts .Token )
318+ if opts .InsecureSkipTLSVerify {
319+ deployArgs += " --hub-insecure-skip-tls-verify"
320+ }
321+ if opts .Cluster != "" {
322+ deployArgs += " --cluster=" + opts .Cluster
323+ }
324+ deployManifest = fmt .Sprintf (`apiVersion: apps/v1
325+ kind: Deployment
326+ metadata:
327+ name: kedge-agent-%s
328+ namespace: kedge-system
329+ labels:
330+ app: kedge-agent
331+ kedge.faros.sh/edge-name: %s
332+ spec:
333+ replicas: 1
334+ selector:
335+ matchLabels:
336+ app: kedge-agent
337+ kedge.faros.sh/edge-name: %s
338+ template:
339+ metadata:
340+ labels:
341+ app: kedge-agent
342+ kedge.faros.sh/edge-name: %s
343+ spec:
344+ serviceAccountName: kedge-agent-%s
345+ containers:
346+ - name: agent
347+ image: %s
348+ command: ["/kedge"]
349+ args: [%s]
350+ ` ,
351+ opts .EdgeName , opts .EdgeName , opts .EdgeName , opts .EdgeName ,
352+ opts .EdgeName , image ,
353+ formatDeployArgs (deployArgs ))
354+ } else {
355+ // Kubeconfig-based: mount a Secret containing the hub kubeconfig.
356+ absKubeconfig , err := filepath .Abs (opts .HubKubeconfig )
357+ if err != nil {
358+ return fmt .Errorf ("resolving hub kubeconfig path: %w" , err )
359+ }
360+ kubeconfigData , err := os .ReadFile (absKubeconfig )
361+ if err != nil {
362+ return fmt .Errorf ("reading hub kubeconfig: %w" , err )
363+ }
364+ secretName := "kedge-agent-" + opts .EdgeName + "-hub-kubeconfig"
365+ secretManifest := fmt .Sprintf (`apiVersion: v1
366+ kind: Secret
367+ metadata:
368+ name: %s
369+ namespace: kedge-system
370+ type: Opaque
371+ stringData:
372+ hub.kubeconfig: |
373+ %s` , secretName , indentLines (string (kubeconfigData ), " " ))
374+ if err := kubectlApplyManifest (kubectlArgs , secretManifest ); err != nil {
375+ return fmt .Errorf ("creating hub kubeconfig secret: %w" , err )
376+ }
377+
378+ deployArgs := fmt .Sprintf ("agent run --hub-kubeconfig=/etc/kedge/hub.kubeconfig --edge-name=%s --type=kubernetes" , opts .EdgeName )
379+ if opts .InsecureSkipTLSVerify {
380+ deployArgs += " --hub-insecure-skip-tls-verify"
381+ }
382+ if opts .Cluster != "" {
383+ deployArgs += " --cluster=" + opts .Cluster
384+ }
385+ deployManifest = fmt .Sprintf (`apiVersion: apps/v1
332386kind: Deployment
333387metadata:
334388 name: kedge-agent-%s
@@ -363,17 +417,20 @@ spec:
363417 secret:
364418 secretName: %s
365419` ,
366- opts .EdgeName , opts .EdgeName , opts .EdgeName , opts .EdgeName ,
367- opts .EdgeName , image ,
368- formatDeployArgs (deployArgs ),
369- secretName )
420+ opts .EdgeName , opts .EdgeName , opts .EdgeName , opts .EdgeName ,
421+ opts .EdgeName , image ,
422+ formatDeployArgs (deployArgs ),
423+ secretName )
424+ }
425+
370426 if err := kubectlApplyManifest (kubectlArgs , deployManifest ); err != nil {
371427 return fmt .Errorf ("creating Deployment: %w" , err )
372428 }
373429
374- fmt .Printf ("Agent installed as Kubernetes Deployment in kedge-system.\n " )
375- fmt .Printf (" Check status: kubectl -n kedge-system get deployment kedge-agent-%s\n " , opts .EdgeName )
376- fmt .Printf (" View logs: kubectl -n kedge-system logs -l kedge.faros.sh/edge-name=%s -f\n " , opts .EdgeName )
430+ fmt .Printf ("✓ kedge-agent deployed to Kubernetes\n " )
431+ fmt .Printf (" Namespace: kedge-system\n " )
432+ fmt .Printf (" Check status: kubectl get pods -n kedge-system\n " )
433+ fmt .Printf (" Logs: kubectl logs -n kedge-system deploy/kedge-agent-%s -f\n " , opts .EdgeName )
377434 return nil
378435}
379436
0 commit comments