Skywalking Swck Agent注入实现分析( 三 )

  1. 第三个执行的是OverlaySidecar
func (os *OverlaySidecar) execute(ipd *InjectProcessData) admission.Response {log.Info("=============== OverlaySidecar ================")if !ipd.injectFileds.OverlaySidecar(*ipd.annotation, ipd.annotationOverlay, &ipd.pod.ObjectMeta.Annotations) {return PatchReq(ipd.pod, ipd.req)}return os.next.execute(ipd)}// OverlaySidecar overlays default configfunc (s *SidecarInjectField) OverlaySidecar(a Annotations, ao *AnnotationOverlay, annotation *map[string]string) bool {s.Initcontainer.Command = make([]string, 1)s.Initcontainer.Args = make([]string, 2)if nil == s.ConfigmapVolume.ConfigMap {s.ConfigmapVolume.ConfigMap = new(corev1.ConfigMapVolumeSource)}limitsStr := ""requestStr := ""// 创建sidercar注解map对象,其初始值从上一步执行结果中获取.map中的key为sidecar注解去掉前缀后的名称annoField := map[string]*string{"initcontainer.Name":&s.Initcontainer.Name,"initcontainer.Image":&s.Initcontainer.Image,"initcontainer.Command":&s.Initcontainer.Command[0],"initcontainer.args.Option":&s.Initcontainer.Args[0],"initcontainer.args.Command":&s.Initcontainer.Args[1],"initcontainer.resources.limits":&limitsStr,"initcontainer.resources.requests": &requestStr,"sidecarVolume.Name":&s.SidecarVolume.Name,"sidecarVolumeMount.MountPath":&s.SidecarVolumeMount.MountPath,"configmapVolume.ConfigMap.Name":&s.ConfigmapVolume.ConfigMap.Name,"configmapVolume.Name":&s.ConfigmapVolume.Name,"configmapVolumeMount.MountPath":&s.ConfigmapVolumeMount.MountPath,"env.Name":&s.Env.Name,"env.Value":&s.Env.Value,}// 从全量注解中获取sidercar前缀的注解,遍历,检查Pod有没有设置相应sidercar注解,如果设置了,则覆盖map中对应key原来的值anno := GetAnnotationsByPrefix(a, sidecarAnnotationPrefix)for _, v := range anno.Annotations {fieldName := strings.TrimPrefix(v.Name, sidecarAnnotationPrefix)if pointer, ok := annoField[fieldName]; ok {if !s.setValue(pointer, ao, annotation, v) {return false}}}s.SidecarVolumeMount.Name = s.SidecarVolume.Names.ConfigmapVolumeMount.Name = s.ConfigmapVolume.Names.Initcontainer.VolumeMounts = []corev1.VolumeMount{s.SidecarVolumeMount}// 设置init container的资源限制if limitsStr != "nil" {limits := make(corev1.ResourceList)err := json.Unmarshal([]byte(limitsStr), &limits)if err != nil {log.Error(err, "unmarshal limitsStr error")return false}s.Initcontainer.Resources.Limits = limits}// 设置init container需要申请的资源if requestStr != "nil" {requests := make(corev1.ResourceList)err := json.Unmarshal([]byte(requestStr), &requests)if err != nil {log.Error(err, "unmarshal requestStr error")return false}s.Initcontainer.Resources.Requests = requests}// the sidecar volume's type is determineds.SidecarVolume.VolumeSource.EmptyDir = nilreturn true}
  1. 第四个执行的是OverlayAgent
// OverlayAgent overlays the agent by getting the pod's annotations// If the agent overlay option is not set, go directly to the next step// If set the wrong value in the annotation , inject the error info and returnfunc (oa *OverlayAgent) execute(ipd *InjectProcessData) admission.Response {log.Info("=============== OverlayAgent ================")if !ipd.injectFileds.OverlayAgent(*ipd.annotation, ipd.annotationOverlay, &ipd.pod.ObjectMeta.Annotations) {ipd.log.Info("overlay agent config error!please look the error annotation!")return PatchReq(ipd.pod, ipd.req)}return oa.next.execute(ipd)}// OverlayAgent overlays agentfunc (s *SidecarInjectField) OverlayAgent(a Annotations, ao *AnnotationOverlay, annotation *map[string]string) bool {// jvmAgentConfigStr inits.JvmAgentConfigStr = ""//遍历pod的注解,如果注解的名称存在于全量注解中 , 则将Pod注解及值保存到AnnotationOverlay map对象中anno := GetAnnotationsByPrefix(a, agentAnnotationPrefix)for k, v := range *annotation {if strings.HasPrefix(k, agentAnnotationPrefix) {for _, an := range anno.Annotations {if strings.EqualFold(k, an.Name) {if !s.AgentOverlayandGetValue(ao, annotation, an) {return false}}}// 将pod注解去掉agent前缀,追加到JvmAgentConfigStr字段中configName := strings.TrimPrefix(k, agentAnnotationPrefix)config := strings.Join([]string{configName, v}, "=")// add to jvmAgentConfigStrif s.JvmAgentConfigStr != "" {s.JvmAgentConfigStr = strings.Join([]string{s.JvmAgentConfigStr, config}, ",")} else {s.JvmAgentConfigStr = config}}}return true}
  1. 第五个执行的是OverlayPlugins,与OverlayAgent逻辑类似 。
  2. 第六个执行的是GetConfigmap,其作用是检查如果pod配置了agent configmap,则检查configmap配置的值是否正确.
func (s *SidecarInjectField) ValidateConfigmap(ctx context.Context, kubeclient client.Client, namespace string,annotation *map[string]string) bool {if len(s.ConfigmapVolume.Name) == 0 || len(s.ConfigmapVolume.ConfigMap.Name) == 0 {return true}configmap := &corev1.ConfigMap{}configmapName := s.ConfigmapVolume.VolumeSource.ConfigMap.LocalObjectReference.Name// check whether the configmap is existederr := kubeclient.Get(ctx, client.ObjectKey{Namespace: namespace, Name: configmapName}, configmap)if err != nil && !errors.IsNotFound(err) {log.Error(err, "Get Configmap failed", "configmapName", configmapName, "namespace", namespace)return false}// if configmap exist , validate itif !errors.IsNotFound(err) {ok, errinfo := ValidateConfigmap(configmap)if ok {log.Info("the configmap validate true", "configmapName", configmapName)return true}log.Error(errinfo, "the configmap validate false", "configmapName", configmapName)}return true}

推荐阅读