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


// register a webhook to enable the java agent injectorsetupLog.Info("registering /mutate-v1-pod webhook")mgr.GetWebhookServer().Register("/mutate-v1-pod",&webhook.Admission{Handler: &injector.JavaagentInjector{Client: mgr.GetClient()}})setupLog.Info("/mutate-v1-pod webhook is registered")swck向k8s注册了/mutate-v1-pod以及对应的handler 。我们可以想到,当create或update pod时,k8s将会调用path对应的handler处理 。4. 查看Handler: injector.JavaagentInjector
// Handle will process every coming pod under the// specified namespace which labeled "swck-injection=enabled"func (r *JavaagentInjector) Handle(ctx context.Context, req admission.Request) admission.Response {pod := &corev1.Pod{}if err := r.decoder.Decode(req, pod); err != nil {return admission.Errored(http.StatusBadRequest, err)}// set Annotations to avoid repeated judgmentsif pod.Annotations == nil {pod.Annotations = map[string]string{}}// 查找所有匹配的swAgentswAgentL := r.findMatchedSwAgentL(ctx, req, pod)//初始化所有annotations(加载所有annotations)anno, err := NewAnnotations()if err != nil {javaagentInjectorLog.Error(err, "get NewAnnotations error")}//创建AnnotationOverlay对象,它是一个map,用于保存被overlaied的annotationao := NewAnnotationOverlay()//创建SidecarInjectField对象s := NewSidecarInjectField()//构建inject链对象ip := NewInjectProcess(ctx, s, anno, ao, swAgentL, pod, req, javaagentInjectorLog, r.Client)//开始injectreturn ip.Run()}

  1. 创建inject chain对象Inject chain对象集合了此次有变更的Pod, webhook request, k8s client以及注解、swagent等对象
// NewInjectProcess create a new InjectProcessfunc NewInjectProcess(ctx context.Context, injectFileds *SidecarInjectField, annotation *Annotations,annotationOverlay *AnnotationOverlay, swAgentL *v1alpha1.SwAgentList, pod *corev1.Pod, req admission.Request, log logr.Logger,kubeclient client.Client) *InjectProcessData {return &InjectProcessData{ctx:ctx,injectFileds:injectFileds,annotation:annotation,annotationOverlay: annotationOverlay,swAgentL:swAgentL,pod:pod,req:req,log:log,kubeclient:kubeclient,}}
  1. 看下ip.Run()方法经过了前面铺垫,终于到了主题了,run方法首先按照执行顺序倒序构造了一个执行链,然后执行 。
// Run will connect the above six steps into a chain and start to execute the first stepfunc (ipd *InjectProcessData) Run() admission.Response {// set final steppodInject := &PodInject{}// set next step is PodInjectgetConfigmap := &GetConfigmap{}getConfigmap.setNext(podInject)// set next step is GetConfigmapoverlayPlugins := &OverlayPlugins{}overlayPlugins.setNext(getConfigmap)// set next step is OverlayPluginsoverlayAgent := &OverlayAgent{}overlayAgent.setNext(overlayPlugins)// set next step is OverlayAgentoverlaysidecar := &OverlaySidecar{}overlaysidecar.setNext(overlayAgent)// set next step is OverlaySwAgentCRoverlaySwAgentCR := &OverlaySwAgentCR{}overlaySwAgentCR.setNext(overlaysidecar)// set next step is OverlaySidecargetStrategy := &GetStrategy{}getStrategy.setNext(overlaySwAgentCR)// this is first step and do real injectionreturn getStrategy.execute(ipd)}
  1. 首先执行的是GetStrategy
func (gs *GetStrategy) execute(ipd *InjectProcessData) admission.Response {log.Info("=============== GetStrategy ================")ipd.injectFileds.GetInjectStrategy(*ipd.annotation, &ipd.pod.ObjectMeta.Labels, &ipd.pod.ObjectMeta.Annotations)if !ipd.injectFileds.NeedInject {log.Info("don't inject agent")return admission.Allowed("ok")}return gs.next.execute(ipd)}// GetInjectStrategy gets user's injection strategyfunc (s *SidecarInjectField) GetInjectStrategy(a Annotations, labels,annotation *map[string]string) {// set default values.NeedInject = false// set NeedInject's value , if the pod has the label "swck-java-agent-injected=true", means need injectif *labels == nil {return}if strings.EqualFold((*labels)[ActiveInjectorLabel], "true") {s.NeedInject = true}if *annotation == nil {return}// set injectContainer's valueif v, ok := (*annotation)[sidecarInjectContainerAnno]; ok {s.InjectContainer = v}}

经验总结扩展阅读