原理

在Kubernetes中,initContainer 通过挂载 emptyDir 卷(或其他类型的卷,但 emptyDir 是最常用的之一,因为它简单且易于理解),可以将其镜像中的文件复制到该卷中。由于 emptyDir 卷的生命周期与Pod相同,并且会被挂载到Pod内的所有容器中,因此当主容器挂载同名的 emptyDir 卷时,它就可以访问到 initContainer 复制到该卷中的文件了。

这种机制允许在Pod的启动阶段进行初始化操作,比如配置文件的复制、依赖的安装、权限的设置等,而无需在主容器的镜像中预先包含这些文件或执行这些操作。这样可以使得主容器的镜像更加轻量级和专注于运行应用程序本身。

下面是一个简化的过程描述:

  1. Pod被创建时,Kubernetes会首先检查是否有 initContainer 需要运行。
  2. 对于每个 initContainer,Kubernetes会为其分配必要的资源,并挂载指定的卷(包括 emptyDir 卷)。
  3. initContainer 执行其指定的命令和参数,比如将文件从镜像内部复制到 emptyDir 卷中。
  4. 一旦 initContainer 成功完成其任务(即退出状态码为0),Kubernetes就会继续处理Pod中的下一个 initContainer(如果有的话),或者如果没有更多的 initContainer,则启动主容器。
  5. 主容器启动时,也会挂载相同的 emptyDir 卷(或其他指定的卷)。由于 emptyDir 卷在Pod的生命周期内是持久的,并且会被所有容器共享,因此主容器可以通过其挂载的路径访问到 initContainer 复制到该卷中的文件。

实操

了解了以上原理,要实现将skywalking无损接入部署在K8S的应用中,需要进行一下操作:

  1. 使用skywalking agent镜像作为initContainer
  2. initContainer挂载emptyDir(名称 skywalking 路径 /agent)将skyawalking agent代码复制到挂载的指定卷中(/agent)。
  3. 主容器中挂载相同emptyDir卷(名称 skywalking 路径/skywalking 这个是挂载路径可以与initContainer中不同,此时访问主容器中的/skywalking目录下文件实际上就是访问initContainer复制到/agent中的文件)
  4. 主容器配置相应的环境变量与启动参数。

YAML修改

initContainer对应yaml(仅修改部分)

initContainers:
        - args:
            - '-c'
            - cp -R /skywalking/agent /agent/
          command:
            - /bin/sh
          image: 'registry.xxx.com/xxx/skywalking:8.7.0-alpine'
          imagePullPolicy: IfNotPresent
          name: dataease-1
          resources: {}
          terminationMessagePath: /dev/termination-log
          terminationMessagePolicy: File
          volumeMounts:
            - mountPath: /agent
              name: skywalking-agent
      volumes:   
          - emptyDir: {}
            name: skywalking-agent

主容器 

containers:
        - env:
            - name: JAVA_OPTIONS
              value: >-
                -Dfile.encoding=utf-8 -Xmx10240m -XX:MaxPermSize=1024m -Xss10m 
                -javaagent:/skywalking/agent/skywalking-agent.jar
            - name: SW_AGENT_COLLECTOR_BACKEND_SERVICES
              value: >-
                skywalking-skywalking.svc.cluster.local:11800
            - name: SW_AGENT_NAME
              value: 'test::test'
          image: 'aaa.bbb.com/test:latest'
          imagePullPolicy: IfNotPresent
          name: dataease
          ports:
            - containerPort: 8080
              name: tcp
              protocol: TCP
          resources:
            limits:
              cpu: '1'
              memory: 4Gi
            requests:
              cpu: '1'
              memory: 4Gi
          volumeMounts:
            - mountPath: /skywalking
              name: skywalking-agent

上文中

SW_AGENT_COLLECTOR_BACKEND_SERVICES 为skywalking的服务端地址

SW_AGENT_NAME 为注册到skywalking的服务名称

在JAVA_OPTION中添加 javaagent:/skywalking/agent/skywalking-agent.jar指定skywalking包。

修改后,重启即可