github.com/NVIDIA/aistore@v1.3.23-0.20240517131212-7df6609be51d/cmn/k8s/init.go (about)

     1  // Package k8s: initialization, client, and misc. helpers
     2  /*
     3   * Copyright (c) 2018-2024, NVIDIA CORPORATION. All rights reserved.
     4   */
     5  package k8s
     6  
     7  import (
     8  	"errors"
     9  	"os"
    10  	"strings"
    11  
    12  	"github.com/NVIDIA/aistore/api/env"
    13  	"github.com/NVIDIA/aistore/cmn/debug"
    14  	"github.com/NVIDIA/aistore/cmn/nlog"
    15  	v1 "k8s.io/api/core/v1"
    16  )
    17  
    18  const (
    19  	defaultPodNameEnv   = "HOSTNAME"
    20  	defaultNamespaceEnv = "POD_NAMESPACE"
    21  )
    22  
    23  const (
    24  	Default = "default"
    25  	Pod     = "pod"
    26  	Svc     = "svc"
    27  )
    28  
    29  const nonK8s = "non-Kubernetes deployment"
    30  
    31  var (
    32  	NodeName string // assign upon successful initialization
    33  
    34  	ErrK8sRequired = errors.New("the operation requires Kubernetes")
    35  )
    36  
    37  func Init() {
    38  	_initClient()
    39  	client, err := GetClient()
    40  	if err != nil {
    41  		nlog.Infoln(nonK8s, "(init k8s-client returned:", _short(err)+")")
    42  		return
    43  	}
    44  
    45  	var (
    46  		pod      *v1.Pod
    47  		nodeName = os.Getenv(env.AIS.K8sNode)
    48  		podName  = os.Getenv(env.AIS.K8sPod)
    49  	)
    50  	if podName != "" {
    51  		debug.Func(func() {
    52  			pn := os.Getenv(defaultPodNameEnv)
    53  			debug.Assertf(pn == "" || pn == podName, "%q vs %q", pn, podName)
    54  		})
    55  	} else {
    56  		podName = os.Getenv(defaultPodNameEnv)
    57  	}
    58  	nlog.Infof("Checking K8s pod: %q, node: %q", podName, nodeName)
    59  
    60  	// node name specified - proceed directly to check
    61  	if nodeName != "" {
    62  		goto checkNode
    63  	}
    64  	if podName == "" {
    65  		nlog.Infoln("K8s environment (above) not set =>", nonK8s)
    66  		return
    67  	}
    68  
    69  	// check POD
    70  	pod, err = client.Pod(podName)
    71  	if err != nil {
    72  		nlog.Errorf("Failed to get K8s pod %q: %v", podName, err)
    73  		return
    74  	}
    75  	nodeName = pod.Spec.NodeName
    76  	nlog.Infoln("K8s spec: NodeName", nodeName, "Hostname", pod.Spec.Hostname, "HostNetwork", pod.Spec.HostNetwork)
    77  	_ppvols(pod.Spec.Volumes)
    78  
    79  checkNode: // always check Node
    80  	node, err := client.Node(nodeName)
    81  	if err != nil {
    82  		nlog.Errorf("Failed to get K8s node %q: %v", nodeName, err)
    83  		return
    84  	}
    85  
    86  	NodeName = node.Name
    87  	nlog.Infoln("K8s node: Name", NodeName, "Namespace", node.Namespace)
    88  }
    89  
    90  func _ppvols(volumes []v1.Volume) {
    91  	for i := range volumes {
    92  		name := "  " + volumes[i].Name
    93  		if claim := volumes[i].VolumeSource.PersistentVolumeClaim; claim != nil {
    94  			nlog.Infof("%s (%v)", name, claim)
    95  		} else {
    96  			nlog.Infoln(name)
    97  		}
    98  	}
    99  }
   100  
   101  func IsK8s() bool { return NodeName != "" }
   102  
   103  func _short(err error) string {
   104  	const sizeLimit = 20
   105  	msg := err.Error()
   106  	idx := strings.IndexByte(msg, ',')
   107  	switch {
   108  	case len(msg) < sizeLimit:
   109  		return msg
   110  	case idx > sizeLimit:
   111  		return msg[:idx]
   112  	default:
   113  		return msg[:sizeLimit]
   114  	}
   115  }