k8s.go 2.05 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
// k8s contains containerd discovery and Kubernetes path classification helpers.
package checkpoint

import (
	"context"
	"fmt"

	"github.com/containerd/containerd"
	"github.com/containerd/containerd/namespaces"
	specs "github.com/opencontainers/runtime-spec/specs-go"
)

const (
	// K8sNamespace is the containerd namespace used by Kubernetes.
	K8sNamespace = "k8s.io"

	// ContainerdSocket is the default containerd socket path.
	ContainerdSocket = "/run/containerd/containerd.sock"
)

type SourcePodManifest struct {
	ContainerID  string `yaml:"containerId"`
	PID          int    `yaml:"pid"`
	SourceNode   string `yaml:"sourceNode"`
	PodName      string `yaml:"podName"`
	PodNamespace string `yaml:"podNamespace"`
}

func NewSourcePodManifest(params CheckpointRequest, pid int) SourcePodManifest {
	return SourcePodManifest{
		ContainerID:  params.ContainerID,
		PID:          pid,
		SourceNode:   params.NodeName,
		PodName:      params.PodName,
		PodNamespace: params.PodNamespace,
	}
}

type DiscoveryClient struct {
	client *containerd.Client
}

func NewDiscoveryClient() (*DiscoveryClient, error) {
	client, err := containerd.New(ContainerdSocket)
	if err != nil {
		return nil, fmt.Errorf("failed to connect to containerd at %s: %w", ContainerdSocket, err)
	}
	return &DiscoveryClient{client: client}, nil
}

func (c *DiscoveryClient) Close() error {
	if c.client != nil {
		return c.client.Close()
	}
	return nil
}

func (c *DiscoveryClient) ResolveContainer(ctx context.Context, containerID string) (int, *specs.Spec, error) {
	ctx = namespaces.WithNamespace(ctx, K8sNamespace)

	container, err := c.client.LoadContainer(ctx, containerID)
	if err != nil {
		return 0, nil, fmt.Errorf("failed to load container %s: %w", containerID, err)
	}

	task, err := container.Task(ctx, nil)
	if err != nil {
		return 0, nil, fmt.Errorf("failed to get task for container %s: %w", containerID, err)
	}

	pid := task.Pid()

	spec, err := container.Spec(ctx)
	if err != nil {
		return 0, nil, fmt.Errorf("failed to get spec for container %s: %w", containerID, err)
	}

	return int(pid), spec, nil
}