You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

worker.go 5.1 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. package runtime
  2. import (
  3. "context"
  4. "strings"
  5. v1 "k8s.io/api/core/v1"
  6. metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  7. "k8s.io/apimachinery/pkg/labels"
  8. "k8s.io/apimachinery/pkg/util/intstr"
  9. "k8s.io/client-go/kubernetes"
  10. "k8s.io/klog/v2"
  11. k8scontroller "k8s.io/kubernetes/pkg/controller"
  12. )
  13. type WorkerMount struct {
  14. Name string
  15. // the url to be mounted
  16. URL *MountURL
  17. // for some cases, there are more than one url to be mounted
  18. URLs []MountURL
  19. // envName indicates the environment key of the mounts injected to the worker
  20. EnvName string
  21. }
  22. // WorkerParam describes the system-defined parameters of worker
  23. type WorkerParam struct {
  24. Mounts []WorkerMount
  25. Env map[string]string
  26. WorkerType string
  27. // if true, force to use hostNetwork
  28. HostNetwork bool
  29. RestartPolicy v1.RestartPolicy
  30. }
  31. // generateLabels generates labels for an object
  32. func generateLabels(object CommonInterface, workerType string) map[string]string {
  33. kind := object.GroupVersionKind().Kind
  34. group := object.GroupVersionKind().Group
  35. keyPrefix := strings.ToLower(kind + "." + group + "/")
  36. labels := make(map[string]string)
  37. labels[keyPrefix+"name"] = object.GetName()
  38. labels[keyPrefix+"uid"] = string(object.GetUID())
  39. if workerType != "" {
  40. labels[keyPrefix+"worker-type"] = strings.ToLower(workerType)
  41. }
  42. return labels
  43. }
  44. // GenerateSelector generates the selector of an object for worker
  45. func GenerateSelector(object CommonInterface) (labels.Selector, error) {
  46. ls := &metav1.LabelSelector{
  47. // select any type workers
  48. MatchLabels: generateLabels(object, ""),
  49. }
  50. return metav1.LabelSelectorAsSelector(ls)
  51. }
  52. // CreateKubernetesService creates a k8s service for an object given ip and port
  53. func CreateKubernetesService(kubeClient kubernetes.Interface, object CommonInterface, workerType string, inputPort int32, inputIP string) (int32, error) {
  54. ctx := context.Background()
  55. name := object.GetName()
  56. namespace := object.GetNamespace()
  57. kind := object.GroupVersionKind().Kind
  58. targePort := intstr.IntOrString{
  59. IntVal: inputPort,
  60. }
  61. serviceSpec := &v1.Service{
  62. ObjectMeta: metav1.ObjectMeta{
  63. Namespace: object.GetNamespace(),
  64. GenerateName: name + "-" + "service" + "-",
  65. OwnerReferences: []metav1.OwnerReference{
  66. *metav1.NewControllerRef(object, object.GroupVersionKind()),
  67. },
  68. Labels: generateLabels(object, workerType),
  69. },
  70. Spec: v1.ServiceSpec{
  71. Selector: generateLabels(object, workerType),
  72. ExternalIPs: []string{
  73. inputIP,
  74. },
  75. Type: v1.ServiceTypeNodePort,
  76. Ports: []v1.ServicePort{
  77. {
  78. Port: inputPort,
  79. TargetPort: targePort,
  80. },
  81. },
  82. },
  83. }
  84. service, err := kubeClient.CoreV1().Services(namespace).Create(ctx, serviceSpec, metav1.CreateOptions{})
  85. if err != nil {
  86. klog.Warningf("failed to create service for %v %v/%v, err:%s", kind, namespace, name, err)
  87. return 0, err
  88. }
  89. klog.V(2).Infof("Service %s is created successfully for %v %v/%v", service.Name, kind, namespace, name)
  90. return service.Spec.Ports[0].NodePort, nil
  91. }
  92. // injectWorkerParam modifies pod in-place
  93. func injectWorkerParam(pod *v1.Pod, workerParam *WorkerParam, object CommonInterface) {
  94. InjectStorageInitializer(pod, workerParam)
  95. envs := createEnvVars(workerParam.Env)
  96. for idx := range pod.Spec.Containers {
  97. pod.Spec.Containers[idx].Env = append(
  98. pod.Spec.Containers[idx].Env, envs...,
  99. )
  100. }
  101. // inject our labels
  102. if pod.Labels == nil {
  103. pod.Labels = make(map[string]string)
  104. }
  105. for k, v := range generateLabels(object, workerParam.WorkerType) {
  106. pod.Labels[k] = v
  107. }
  108. pod.GenerateName = object.GetName() + "-" + strings.ToLower(workerParam.WorkerType) + "-"
  109. pod.Namespace = object.GetNamespace()
  110. if workerParam.HostNetwork {
  111. // FIXME
  112. // force to set hostnetwork
  113. pod.Spec.HostNetwork = true
  114. }
  115. if pod.Spec.RestartPolicy == "" {
  116. pod.Spec.RestartPolicy = workerParam.RestartPolicy
  117. }
  118. }
  119. // CreatePodWithTemplate creates and returns a pod object given a crd object, pod template, and workerParam
  120. func CreatePodWithTemplate(client kubernetes.Interface, object CommonInterface, spec *v1.PodTemplateSpec, workerParam *WorkerParam) (*v1.Pod, error) {
  121. objectKind := object.GroupVersionKind()
  122. pod, _ := k8scontroller.GetPodFromTemplate(spec, object, metav1.NewControllerRef(object, objectKind))
  123. injectWorkerParam(pod, workerParam, object)
  124. createdPod, err := client.CoreV1().Pods(object.GetNamespace()).Create(context.TODO(), pod, metav1.CreateOptions{})
  125. objectName := object.GetNamespace() + "/" + object.GetName()
  126. if err != nil {
  127. klog.Warningf("failed to create pod(type=%s) for %s %s, err:%s", workerParam.WorkerType, objectKind, objectName, err)
  128. return nil, err
  129. }
  130. klog.V(2).Infof("pod %s is created successfully for %s %s", createdPod.Name, objectKind, objectName)
  131. return createdPod, nil
  132. }
  133. // createEnvVars creates EnvMap for container
  134. // include EnvName and EnvValue map for stage of creating a pod
  135. func createEnvVars(envMap map[string]string) []v1.EnvVar {
  136. var envVars []v1.EnvVar
  137. for envName, envValue := range envMap {
  138. Env := v1.EnvVar{
  139. Name: envName,
  140. Value: envValue,
  141. }
  142. envVars = append(envVars, Env)
  143. }
  144. return envVars
  145. }