Enhance the containers topology with information directly joined from endpoints, via IP address foreign key.

This commit is contained in:
Tom Wilkie
2015-08-24 12:52:57 +00:00
parent 1a286eac04
commit 55c77c6a37
3 changed files with 98 additions and 5 deletions

View File

@@ -168,6 +168,78 @@ func MapHostIdentity(m report.NodeMetadata) RenderableNodes {
return RenderableNodes{id: NewRenderableNode(id, major, minor, rank, m)}
}
// MapEndpoint2IP maps endpoint nodes to their IP address, for joining
// with container nodes. We drop endpoint nodes with pids, as they
// will be joined to containers through the process topology, and we
// don't want to double count edges.
func MapEndpoint2IP(m report.NodeMetadata) RenderableNodes {
_, ok := m.Metadata[process.PID]
if ok {
return RenderableNodes{}
}
addr, ok := m.Metadata[endpoint.Addr]
if !ok {
return RenderableNodes{}
}
return RenderableNodes{addr: NewRenderableNode(addr, "", "", "", m)}
}
// IPPseudoNode maps endpoint pseudo nodes to regular IP address nodes, or
// the internet node.
func IPPseudoNode(srcNodeID, _ string, _ bool, local report.Networks) (RenderableNode, bool) {
// Use the addresser to extract the IP of the missing node
srcNodeAddr := report.EndpointIDAddresser(srcNodeID)
// If the dstNodeAddr is not in a network local to this report, we emit an
// internet node
if !local.Contains(srcNodeAddr) {
return newPseudoNode(TheInternetID, TheInternetMajor, ""), true
}
return NewRenderableNode(srcNodeAddr.String(), "", "", "", report.MakeNodeMetadata()), true
}
// MapContainer2IP maps container nodes to their IP addresses (outputs
// multiple nodes). This allows container to be joined directly with
// the endpoint topology.
func MapContainer2IP(m report.NodeMetadata) RenderableNodes {
result := RenderableNodes{}
addrs, ok := m.Metadata[docker.ContainerIPs]
if !ok {
return result
}
for _, addr := range strings.Fields(addrs) {
n := NewRenderableNode(addr, "", "", "", m)
n.NodeMetadata.Counters[containersKey] = 1
result[addr] = n
}
return result
}
// MapIP2Container maps IP nodes produced from MapContainer2IP back to
// container nodes. If there is more than one container with a given
// IP, it is dropped.
func MapIP2Container(n RenderableNode) RenderableNodes {
// If an IP is shared between multiple containers, we can't
// reliably attribute an connection based on its IP
if n.NodeMetadata.Counters[containersKey] > 1 {
return RenderableNodes{}
}
// Propogate the internet pseudo node.
if n.ID == TheInternetID {
return RenderableNodes{n.ID: n}
}
// If this node is not a container, exclude it.
// This excludes all the nodes we've dragged in from endpoint
// that we failed to join to a container.
id, ok := n.NodeMetadata.Metadata[docker.ContainerID]
if !ok {
return RenderableNodes{}
}
return RenderableNodes{id: newDerivedNode(id, n)}
}
// MapEndpoint2Process maps endpoint RenderableNodes to process
// RenderableNodes.
//

View File

@@ -195,16 +195,14 @@ func (m LeafMap) Render(rpt report.Report) RenderableNodes {
srcRenderableIDs, ok := source2mapped[srcNodeID]
if !ok {
// One of the entries in dsts must be a non-pseudo node
var existingDstNodeID string
// One of the entries in dsts must be a non-pseudo node, unless
// it was dropped by the mapping function.
for _, dstNodeID := range dsts {
if _, ok := source2mapped[dstNodeID]; ok {
existingDstNodeID = dstNodeID
srcRenderableIDs = mkPseudoNode(srcNodeID, dstNodeID, true)
break
}
}
srcRenderableIDs = mkPseudoNode(srcNodeID, existingDstNodeID, true)
}
if len(srcRenderableIDs) == 0 {
continue

View File

@@ -99,11 +99,34 @@ var ContainerRenderer = MakeReduce(
},
},
},
LeafMap{
Selector: report.SelectContainer,
Mapper: MapContainerIdentity,
Pseudo: PanicPseudoNode,
},
// This mapper brings in short lived connections by joining with container IPs.
// We need to be careful to ensure we only include each edge once. Edges brought in
// by the above renders will have a pid, so its enough to filter out any nodes with
// pids.
Map{
MapFunc: MapIP2Container,
Renderer: FilterUnconnected(
MakeReduce(
LeafMap{
Selector: report.SelectContainer,
Mapper: MapContainer2IP,
Pseudo: PanicPseudoNode,
},
LeafMap{
Selector: report.SelectEndpoint,
Mapper: MapEndpoint2IP,
Pseudo: IPPseudoNode,
},
),
),
},
)
// ContainerImageRenderer is a Renderer which produces a renderable container