dockerd.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. package containers
  2. import (
  3. "context"
  4. "fmt"
  5. "os"
  6. "path"
  7. "strings"
  8. "time"
  9. "github.com/coroot/coroot-node-agent/common"
  10. "github.com/coroot/coroot-node-agent/proc"
  11. "github.com/coroot/logparser"
  12. "github.com/docker/docker/client"
  13. "github.com/vishvananda/netns"
  14. "inet.af/netaddr"
  15. )
  16. const dockerdTimeout = 30 * time.Second
  17. var (
  18. dockerdClient *client.Client
  19. )
  20. func DockerdInit() error {
  21. c, err := client.NewClientWithOpts(
  22. client.WithHost("unix://" + proc.HostPath("/run/docker.sock")),
  23. )
  24. if err != nil {
  25. return err
  26. }
  27. ctx, cancelFn := context.WithTimeout(context.Background(), dockerdTimeout)
  28. defer cancelFn()
  29. if _, err := c.Ping(ctx); err != nil {
  30. return err
  31. }
  32. c.NegotiateAPIVersion(ctx)
  33. dockerdClient = c
  34. return nil
  35. }
  36. func DockerdInspect(containerID string) (*ContainerMetadata, error) {
  37. if dockerdClient == nil {
  38. return nil, fmt.Errorf("dockerd client not initialized")
  39. }
  40. ctx, cancel := context.WithTimeout(context.Background(), dockerdTimeout)
  41. defer cancel()
  42. c, err := dockerdClient.ContainerInspect(ctx, containerID)
  43. if err != nil {
  44. return nil, err
  45. }
  46. res := &ContainerMetadata{
  47. name: strings.TrimPrefix(c.Name, "/"),
  48. labels: c.Config.Labels,
  49. image: c.Config.Image,
  50. volumes: map[string]string{},
  51. hostListens: map[string][]netaddr.IPPort{},
  52. networks: map[string]ContainerNetwork{},
  53. rootfs: c.GraphDriver.Data["MergedDir"],
  54. }
  55. for _, m := range c.Mounts {
  56. res.volumes[m.Destination] = common.ParseKubernetesVolumeSource(m.Source)
  57. }
  58. if c.LogPath != "" && c.HostConfig.LogConfig.Type == "json-file" {
  59. res.logPath = c.LogPath
  60. res.logDecoder = logparser.DockerJsonDecoder{}
  61. }
  62. if c.NetworkSettings != nil {
  63. addrs := map[netaddr.IPPort]struct{}{}
  64. for port, bindings := range c.NetworkSettings.Ports {
  65. if port.Proto() != "tcp" {
  66. continue
  67. }
  68. for _, b := range bindings {
  69. if ipp, err := netaddr.ParseIPPort(b.HostIP + ":" + b.HostPort); err == nil {
  70. addrs[ipp] = struct{}{}
  71. }
  72. }
  73. }
  74. if len(addrs) > 0 {
  75. s := make([]netaddr.IPPort, 0, len(addrs))
  76. for addr := range addrs {
  77. if common.PortFilter.ShouldBeSkipped(addr.Port()) {
  78. continue
  79. }
  80. s = append(s, addr)
  81. }
  82. res.hostListens["dockerd"] = s
  83. }
  84. for name, network := range c.NetworkSettings.Networks {
  85. res.networks[name] = ContainerNetwork{
  86. NetworkID: network.NetworkID,
  87. }
  88. }
  89. }
  90. return res, nil
  91. }
  92. func FindNetworkLoadBalancerNs(networkId string) netns.NsHandle {
  93. basePath := "/run/docker/netns"
  94. files, err := os.ReadDir(proc.HostPath(basePath))
  95. if err != nil {
  96. return -1
  97. }
  98. for _, f := range files {
  99. if !f.Type().IsRegular() || !strings.HasPrefix(f.Name(), "lb_") {
  100. continue
  101. }
  102. idPrefix := strings.Split(f.Name(), "_")[1]
  103. if strings.HasPrefix(networkId, idPrefix) {
  104. ns, _ := netns.GetFromPath(proc.HostPath(path.Join(basePath, f.Name())))
  105. return ns
  106. }
  107. }
  108. return -1
  109. }