Nikolay Sivko пре 3 година
родитељ
комит
a091277bc8
4 измењених фајлова са 110 додато и 4 уклоњено
  1. 1 2
      cgroup/cgroup.go
  2. 5 0
      cgroup/cgroup_test.go
  3. 93 0
      containers/crio.go
  4. 11 2
      containers/registry.go

+ 1 - 2
cgroup/cgroup.go

@@ -4,7 +4,6 @@ import (
 	"fmt"
 	"github.com/coroot/coroot-node-agent/common"
 	"github.com/coroot/coroot-node-agent/flags"
-	"io/ioutil"
 	"k8s.io/klog/v2"
 	"os"
 	"path"
@@ -89,7 +88,7 @@ func (cg *Cgroup) CreatedAt() time.Time {
 }
 
 func NewFromProcessCgroupFile(filePath string) (*Cgroup, error) {
-	data, err := ioutil.ReadFile(filePath)
+	data, err := os.ReadFile(filePath)
 	if err != nil {
 		return nil, err
 	}

+ 5 - 0
cgroup/cgroup_test.go

@@ -99,6 +99,11 @@ func TestContainerByCgroup(t *testing.T) {
 	as.Equal("63425c4a8b4291744a79dd9011fddc7a1f8ffda61f65d72196aa01d00cae2e2e", id)
 	as.Nil(err)
 
+	typ, id, err = containerByCgroup("/kubepods.slice/kubepods-burstable.slice/kubepods-burstable-pod2942c55e_c9cb_428a_93f4_eaf89c1f3ce0.slice/crio-49f9e8e5395d57c1083996c09e2e6f042d5fe1ec0310facab32f94912b35ce59.scope")
+	as.Equal(typ, ContainerTypeCrio)
+	as.Equal("49f9e8e5395d57c1083996c09e2e6f042d5fe1ec0310facab32f94912b35ce59", id)
+	as.Nil(err)
+
 	typ, id, err = containerByCgroup("/kubepods.slice/kubepods-burstable.slice/kubepods-burstable-pod3e61c214bc3ed9ff81e21474dd6cba17.slice/cri-containerd-c74b0f5062f0bc726cae1e9369ad4a95deed6b298d247f0407475adb23fa3190")
 	as.Equal(typ, ContainerTypeContainerd)
 	as.Equal("c74b0f5062f0bc726cae1e9369ad4a95deed6b298d247f0407475adb23fa3190", id)

+ 93 - 0
containers/crio.go

@@ -0,0 +1,93 @@
+package containers
+
+import (
+	"context"
+	"encoding/json"
+	"errors"
+	"fmt"
+	"github.com/coroot/coroot-node-agent/common"
+	"github.com/coroot/coroot-node-agent/proc"
+	"github.com/coroot/logparser"
+	"k8s.io/klog/v2"
+	"net"
+	"net/http"
+	"os"
+	"time"
+)
+
+const crioTimeout = 30 * time.Second
+
+var (
+	crioClient *http.Client
+	crioSocket = proc.HostPath("/var/run/crio/crio.sock")
+)
+
+type CrioContainerInfo struct {
+	Name            string            `json:"name"`
+	Image           string            `json:"image"`
+	Labels          map[string]string `json:"labels"`
+	LogPath         string            `json:"log_path"`
+	CrioAnnotations map[string]string `json:"crio_annotations"`
+}
+
+type CrioVolume struct {
+	ContainerPath string `json:"container_path"`
+	HostPath      string `json:"host_path"`
+}
+
+func CrioInit() error {
+	if _, err := os.Stat(crioSocket); err != nil {
+		return err
+	}
+	klog.Infoln("cri-o socket:", crioSocket)
+
+	crioClient = &http.Client{
+		Transport: &http.Transport{
+			DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
+				return net.DialTimeout("unix", crioSocket, crioTimeout)
+			},
+			DisableCompression: true,
+		},
+	}
+	return nil
+}
+
+func CrioInspect(containerID string) (*ContainerMetadata, error) {
+	if crioClient == nil {
+		return nil, fmt.Errorf("cri-o client is not initialized")
+	}
+	resp, err := crioClient.Get("http://localhost/containers/" + containerID)
+	if err != nil {
+		return nil, err
+	}
+	defer resp.Body.Close()
+
+	if resp.StatusCode != http.StatusOK {
+		return nil, errors.New(resp.Status)
+	}
+
+	i := &CrioContainerInfo{}
+	if err = json.NewDecoder(resp.Body).Decode(i); err != nil {
+		return nil, err
+	}
+
+	res := &ContainerMetadata{
+		name:       i.Name,
+		labels:     i.Labels,
+		volumes:    map[string]string{},
+		logPath:    i.LogPath,
+		image:      i.Image,
+		logDecoder: logparser.CriDecoder{},
+	}
+
+	var volumes []CrioVolume
+
+	if err := json.Unmarshal([]byte(i.CrioAnnotations["io.kubernetes.cri-o.Volumes"]), &volumes); err != nil {
+		klog.Warningln(err)
+	} else {
+		for _, v := range volumes {
+			res.volumes[v.ContainerPath] = common.ParseKubernetesVolumeSource(v.HostPath)
+		}
+	}
+	return res, nil
+}

+ 11 - 2
containers/registry.go

@@ -68,6 +68,9 @@ func NewRegistry(reg prometheus.Registerer, kernelVersion string) (*Registry, er
 	if err := ContainerdInit(); err != nil {
 		klog.Warningln(err)
 	}
+	if err := CrioInit(); err != nil {
+		klog.Warningln(err)
+	}
 	if err := JournaldInit(); err != nil {
 		klog.Warningln(err)
 	}
@@ -304,10 +307,13 @@ func (r *Registry) getOrCreateContainer(pid uint32) *Container {
 
 func calcId(cg *cgroup.Cgroup, md *ContainerMetadata) ContainerID {
 	if cg.ContainerType == cgroup.ContainerTypeSystemdService {
+		if strings.HasPrefix(cg.ContainerId, "/system.slice/crio-conmon-") {
+			return ""
+		}
 		return ContainerID(cg.ContainerId)
 	}
 	switch cg.ContainerType {
-	case cgroup.ContainerTypeDocker, cgroup.ContainerTypeContainerd, cgroup.ContainerTypeSandbox:
+	case cgroup.ContainerTypeDocker, cgroup.ContainerTypeContainerd, cgroup.ContainerTypeSandbox, cgroup.ContainerTypeCrio:
 	default:
 		return ""
 	}
@@ -346,13 +352,16 @@ func calcId(cg *cgroup.Cgroup, md *ContainerMetadata) ContainerID {
 
 func getContainerMetadata(cg *cgroup.Cgroup) (*ContainerMetadata, error) {
 	switch cg.ContainerType {
-	case cgroup.ContainerTypeDocker, cgroup.ContainerTypeContainerd, cgroup.ContainerTypeSandbox:
+	case cgroup.ContainerTypeDocker, cgroup.ContainerTypeContainerd, cgroup.ContainerTypeSandbox, cgroup.ContainerTypeCrio:
 	default:
 		return &ContainerMetadata{}, nil
 	}
 	if cg.ContainerId == "" {
 		return &ContainerMetadata{}, nil
 	}
+	if cg.ContainerType == cgroup.ContainerTypeCrio {
+		return CrioInspect(cg.ContainerId)
+	}
 	var dockerdErr error
 	if dockerdClient != nil {
 		md, err := DockerdInspect(cg.ContainerId)