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

  1. 最后一步是PodInject,顾名思义,其作用是进行Pod注入
// PodInject will inject all fields to the podfunc (pi *PodInject) execute(ipd *InjectProcessData) admission.Response {log.Info("=============== PodInject ================")ipd.injectFileds.Inject(ipd.pod)// Pod注入完成后,添加sidecar.skywalking.apache.org/succeed=true注解ipd.injectFileds.injectSucceedAnnotation(&ipd.pod.Annotations)log.Info("inject successfully!")// 序列化Pod,返回给k8sreturn PatchReq(ipd.pod, ipd.req)}// Inject will do real injectionfunc (s *SidecarInjectField) Inject(pod *corev1.Pod) {log.Info(fmt.Sprintf("inject pod : %s", pod.GenerateName))// 将之前执行得到的InitContainer与pod配置的InitContainer合并在一起 , 也就是说pod initcontainer可以有多个if pod.Spec.InitContainers != nil {pod.Spec.InitContainers = append(pod.Spec.InitContainers, s.Initcontainer)} else {pod.Spec.InitContainers = []corev1.Container{s.Initcontainer}}// add volume to specif pod.Spec.Volumes == nil {pod.Spec.Volumes = []corev1.Volume{}}pod.Spec.Volumes = append(pod.Spec.Volumes, s.SidecarVolume)if len(s.ConfigmapVolume.Name) > 0 && len(s.ConfigmapVolume.ConfigMap.Name) > 0 {pod.Spec.Volumes = append(pod.Spec.Volumes, s.ConfigmapVolume)}//选择要注入的目标容器targetContainers := s.findInjectContainer(pod.Spec.Containers)//循环目标容器进行注入for i := range targetContainers {log.Info(fmt.Sprintf("inject container : %s", targetContainers[i].Name))if (*targetContainers[i]).VolumeMounts == nil {(*targetContainers[i]).VolumeMounts = []corev1.VolumeMount{}}// 注入voLume与configmap(*targetContainers[i]).VolumeMounts = append((*targetContainers[i]).VolumeMounts, s.SidecarVolumeMount)if len(s.ConfigmapVolumeMount.Name) > 0 && len(s.ConfigmapVolumeMount.MountPath) > 0 {(*targetContainers[i]).VolumeMounts = append((*targetContainers[i]).VolumeMounts, s.ConfigmapVolumeMount)}//java agent参数,其值为上面的JvmAgentConfigStrif (*targetContainers[i]).Env != nil {(*targetContainers[i]).Env = append((*targetContainers[i]).Env, s.Env)} else {(*targetContainers[i]).Env = []corev1.EnvVar{s.Env}}//注入环境变量,如果container本身存在,则忽略var envsTBA []corev1.EnvVarfor j, envInject := range s.Envs {isExists := falsefor _, envExists := range targetContainers[i].Env {if strings.EqualFold(envExists.Name, envInject.Name) {isExists = truebreak}}if !isExists {envsTBA = append(envsTBA, s.Envs[j])}}if len(s.Envs) > 0 {(*targetContainers[i]).Env = append((*targetContainers[i]).Env, envsTBA...)}}}
除了Pod注入 , SWCK项目还有其它Operator, 包括Storage,OAP,UI,Adapter等,有兴趣的话可自行探索 。总体来说swck利用k8s的自定义资源以及自定义控制器 , 为skywalking部署到kubernetes提供了适配,使skywalking能够快速部署到kubernetes这个基座上 。
注意事项
  1. SwAgent只能在业务空间起作用,不能在skywalking-swck-system生效
因为webhook触发调用handler后,在查找SwAgent时 , 只会查找与Pod在一个命名空间中的Swagent. 如果想将SwAgent放到skywalking-swck-system命令空间,需要修改operator
  1. 删除资源时JavaAgent状态中统计的注入的容器数量不变化
因为MutatingWebhookConfiguration只监听了Pod的Create与Update事件 。
  1. 调试需要问题
  • 本地启用webhook前提下无法启动operator
因为启动webhook时,需要在本地启动webhook server,与k8s集群通过https通信, 本地需要添加tls.crt以及tls.key文件 。而这两个文件从k8s获取 。具体方法是查看skywalking-swck-controller-manager使用到的secret
kubectl get secret skywalking-swck-controller-manager-cert -n skywalking-swck-system -o jsonpath='{.data.tls\.crt}'| base64 --decode > tls.crtkubectl get secret skywalking-swck-controller-manager-cert -n skywalking-swck-system -o jsonpath='{.data.tls\.key}'| base64 --decode > tls.key```

推荐阅读