dockerd.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  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. }
  54. for _, m := range c.Mounts {
  55. res.volumes[m.Destination] = common.ParseKubernetesVolumeSource(m.Source)
  56. }
  57. if c.LogPath != "" && c.HostConfig.LogConfig.Type == "json-file" {
  58. res.logPath = c.LogPath
  59. res.logDecoder = logparser.DockerJsonDecoder{}
  60. }
  61. if c.NetworkSettings != nil {
  62. addrs := map[netaddr.IPPort]struct{}{}
  63. for port, bindings := range c.NetworkSettings.Ports {
  64. if port.Proto() != "tcp" {
  65. continue
  66. }
  67. for _, b := range bindings {
  68. if ipp, err := netaddr.ParseIPPort(b.HostIP + ":" + b.HostPort); err == nil {
  69. addrs[ipp] = struct{}{}
  70. }
  71. }
  72. }
  73. if len(addrs) > 0 {
  74. s := make([]netaddr.IPPort, 0, len(addrs))
  75. for addr := range addrs {
  76. if common.PortFilter.ShouldBeSkipped(addr.Port()) {
  77. continue
  78. }
  79. s = append(s, addr)
  80. }
  81. res.hostListens["dockerd"] = s
  82. }
  83. for name, network := range c.NetworkSettings.Networks {
  84. res.networks[name] = ContainerNetwork{
  85. NetworkID: network.NetworkID,
  86. }
  87. }
  88. }
  89. return res, nil
  90. }
  91. func FindNetworkLoadBalancerNs(networkId string) netns.NsHandle {
  92. basePath := "/run/docker/netns"
  93. files, err := os.ReadDir(proc.HostPath(basePath))
  94. if err != nil {
  95. return -1
  96. }
  97. for _, f := range files {
  98. if !f.Type().IsRegular() || !strings.HasPrefix(f.Name(), "lb_") {
  99. continue
  100. }
  101. idPrefix := strings.Split(f.Name(), "_")[1]
  102. if strings.HasPrefix(networkId, idPrefix) {
  103. ns, _ := netns.GetFromPath(proc.HostPath(path.Join(basePath, f.Name())))
  104. return ns
  105. }
  106. }
  107. return -1
  108. }