예제 #1
0
 def test_node_id_to_project_id(self):
   """Tests node_id_to_project_id()."""
   self.assertEqual(
       'rising-apricot-840',
       utilities.node_id_to_project_id(
           'k8s-guestbook-node-1.c.rising-apricot-840.internal'))
   self.assertEqual(
       'rising-apricot-840',
       utilities.node_id_to_project_id(
           'Node:k8s-guestbook-node-1.c.rising-apricot-840.internal'))
   self.assertEqual(
       '_unknown_',
       utilities.node_id_to_project_id('k8s-guestbook-node-1'))
   self.assertEqual(
       'spartan-alcove-89517',
       utilities.node_id_to_project_id(
           'kubernetes-minion-dlc9.c.spartan-alcove-89517.google.com.'
           'internal'))
   self.assertEqual(
       '_unknown_', utilities.node_id_to_project_id('x.y.z.w'))
   self.assertEqual(
       '_unknown_', utilities.node_id_to_project_id('Node:x.y.z.w'))
   self.assertEqual(
       '_unknown_', utilities.node_id_to_project_id('Node:'))
   with self.assertRaises(AssertionError):
     utilities.node_id_to_project_id('')
예제 #2
0
 def test_node_id_to_project_id(self):
   """Tests node_id_to_project_id()."""
   self.assertEqual(
       'rising-apricot-840',
       utilities.node_id_to_project_id(
           'k8s-guestbook-node-1.c.rising-apricot-840.internal'))
   self.assertEqual(
       'rising-apricot-840',
       utilities.node_id_to_project_id(
           'Node:k8s-guestbook-node-1.c.rising-apricot-840.internal'))
   self.assertEqual(
       '_unknown_',
       utilities.node_id_to_project_id('k8s-guestbook-node-1'))
   self.assertEqual(
       'spartan-alcove-89517',
       utilities.node_id_to_project_id(
           'kubernetes-minion-dlc9.c.spartan-alcove-89517.google.com.'
           'internal'))
   self.assertEqual(
       '_unknown_', utilities.node_id_to_project_id('x.y.z.w'))
   self.assertEqual(
       '_unknown_', utilities.node_id_to_project_id(''))
   self.assertEqual(
       '_unknown_', utilities.node_id_to_project_id('Node:x.y.z.w'))
   self.assertEqual(
       '_unknown_', utilities.node_id_to_project_id('Node:'))
예제 #3
0
def get_nodes_with_metrics(gs):
  """Gets the list of all nodes in the current cluster with their metrics.

  Args:
    gs: global state.

  Returns:
    list of wrapped node objects.
    Each element in the list is the result of
    utilities.wrap_object(node, 'Node', ...)

  Raises:
    CollectorError in case of failure to fetch data from Kubernetes.
    Other exceptions may be raised due to exectution errors.
  """
  nodes_list = get_nodes(gs)

  for node in nodes_list:
    assert utilities.is_wrapped_object(node, 'Node')
    project_id = utilities.node_id_to_project_id(node['id'])
    # The project_id may be '_unknown_'. This is not a big
    # deal, since the aggregator knows the project ID.
    metrics.annotate_node(project_id, node)

  return nodes_list
예제 #4
0
def get_nodes_with_metrics(gs):
    """Gets the list of all nodes in the current cluster with their metrics.

  Args:
    gs: global state.

  Returns:
    list of wrapped node objects.
    Each element in the list is the result of
    utilities.wrap_object(node, 'Node', ...)

  Raises:
    CollectorError in case of failure to fetch data from Kubernetes.
    Other exceptions may be raised due to exectution errors.
  """
    nodes_list = get_nodes(gs)

    for node in nodes_list:
        assert utilities.is_wrapped_object(node, 'Node')
        project_id = utilities.node_id_to_project_id(node['id'])
        # The project_id may be '_unknown_'. This is not a big
        # deal, since the aggregator knows the project ID.
        metrics.annotate_node(project_id, node)

    return nodes_list
예제 #5
0
def get_containers_with_metrics(gs, docker_host):
  """Gets the list of all containers in 'docker_host' with metric annotations.

  Args:
    gs: global state.
    docker_host: the Docker host running the containers.

  Returns:
    list of wrapped container objects.
    Each element in the list is the result of
    utilities.wrap_object(container, 'Container', ...)

  Raises:
    CollectorError: in case of failure to fetch data from Docker.
    Other exceptions may be raised due to exectution errors.
  """
  # Create a lookup table from pod IDs to pods.
  # This lookup table is needed when annotating containers with
  # metrics. Also compute the project's name.
  containers_list = get_containers(gs, docker_host)
  if not containers_list:
    return []

  pod_id_to_pod = {}
  project_id = '_unknown_'

  # Populate the pod ID to pod lookup table.
  # Compute the project_id from the name of the first pod.
  for pod in kubernetes.get_pods(gs, docker_host):
    assert utilities.is_wrapped_object(pod, 'Pod')
    pod_id_to_pod[pod['id']] = pod
    if project_id != '_unknown_':
      continue
    pod_hostname = utilities.get_attribute(
        pod, ['properties', 'spec', 'host'])
    if utilities.valid_string(pod_hostname):
      project_id = utilities.node_id_to_project_id(pod_hostname)

  # We know that there are containers in this docker_host.
  if not pod_id_to_pod:
    # there are no pods in this docker_host.
    msg = 'Docker host %s has containers but no pods' % docker_host
    gs.logger_exception(msg)
    raise collector_error.CollectorError(msg)

  # Annotate the containers with their metrics.
  for container in containers_list:
    assert utilities.is_wrapped_object(container, 'Container')

    parent_pod_id = utilities.get_parent_pod_id(container)
    if not utilities.valid_string(parent_pod_id):
      msg = ('missing or invalid parent pod ID in container %s' %
             container['id'])
      gs.logger_error(msg)
      raise collector_error.CollectorError(msg)

    if parent_pod_id not in pod_id_to_pod:
      msg = ('could not locate parent pod %s for container %s' %
             (parent_pod_id, container['id']))
      gs.logger_error(msg)
      raise collector_error.CollectorError(msg)

    # Note that the project ID may be '_unknown_'.
    # This is not a big deal, because the aggregator knows the project ID.
    metrics.annotate_container(
        project_id, container, pod_id_to_pod[parent_pod_id])

  return containers_list
예제 #6
0
def _do_compute_master_pods(gs, cluster_guid, nodes_list, oldest_timestamp, g):
  """Adds pods running on the master node to the graph.

  These pods do not have a valid parent node, because the nodes list
  does not include the master node.

  This routine adds a dummy master node, and then adds the pods running
  on the master node to the graph. It does not add information about
  containers, processes, or images of these nodes, because there is no
  minion collector running on the master node.

  Note that in some configurations (for example, GKE), there is no
  master node.

  Args:
    gs: the global state.
    cluster_guid: the cluster's ID.
    nodes_list: a list of wrapped Node objects.
    oldest_timestamp: the timestamp of the oldest Node object.
    g: the context graph under construction.
  """
  assert isinstance(gs, global_state.GlobalState)
  assert utilities.valid_string(cluster_guid)
  assert isinstance(nodes_list, types.ListType)
  assert utilities.valid_string(oldest_timestamp)
  assert isinstance(g, ContextGraph)

  # Compute the set of known Node names.
  known_node_ids = set()
  project_id = '_unknown_'
  for node in nodes_list:
    assert utilities.is_wrapped_object(node, 'Node')
    known_node_ids.add(node['id'])
    project_id = utilities.node_id_to_project_id(node['id'])

  # Compute the set of Nodes referenced by pods but not in the known set.
  # The set of unknown node names may be empty.
  assert utilities.valid_string(project_id)
  missing_node_ids = set()
  for pod in kubernetes.get_pods(gs):
    assert utilities.is_wrapped_object(pod, 'Pod')
    # pod.properties.spec.nodeName may be missing if the pod is waiting.
    parent_node_id = utilities.get_attribute(
        pod, ['properties', 'spec', 'nodeName'])
    if not utilities.valid_string(parent_node_id):
      continue

    if parent_node_id in known_node_ids:
      continue

    # Found a pod that does not belong to any of the known nodes.
    missing_node_ids.add(parent_node_id)

  # Process the pods in each of the missing nodes.
  for node_id in missing_node_ids:
    # Create a dummy node object just as a placeholder for metric
    # annotations.
    node = utilities.wrap_object(
        {}, 'Node', node_id, time.time(),
        label=utilities.node_id_to_host_name(node_id))

    # The project_id may be '_unknown_'. This is not a big
    # deal, since the aggregator knows the project ID.
    metrics.annotate_node(project_id, node)
    node_guid = 'Node:' + node_id
    g.add_resource(node_guid, node['annotations'], 'Node', oldest_timestamp, {})
    g.add_relation(cluster_guid, node_guid, 'contains')  # Cluster contains Node
    for pod in kubernetes.get_pods(gs, node_id):
      _do_compute_pod(gs, cluster_guid, node_guid, pod, g)
예제 #7
0
def get_containers_with_metrics(gs, docker_host):
    """Gets the list of all containers in 'docker_host' with metric annotations.

  Args:
    gs: global state.
    docker_host: the Docker host running the containers.

  Returns:
    list of wrapped container objects.
    Each element in the list is the result of
    utilities.wrap_object(container, 'Container', ...)

  Raises:
    CollectorError: in case of failure to fetch data from Docker.
    Other exceptions may be raised due to exectution errors.
  """
    # Create a lookup table from pod IDs to pods.
    # This lookup table is needed when annotating containers with
    # metrics. Also compute the project's name.
    containers_list = get_containers(gs, docker_host)
    if not containers_list:
        return []

    pod_id_to_pod = {}
    project_id = '_unknown_'

    # Populate the pod ID to pod lookup table.
    # Compute the project_id from the name of the first pod.
    for pod in kubernetes.get_pods(gs, docker_host):
        assert utilities.is_wrapped_object(pod, 'Pod')
        pod_id_to_pod[pod['id']] = pod
        if project_id != '_unknown_':
            continue
        pod_hostname = utilities.get_attribute(pod,
                                               ['properties', 'spec', 'host'])
        if utilities.valid_string(pod_hostname):
            project_id = utilities.node_id_to_project_id(pod_hostname)

    # We know that there are containers in this docker_host.
    if not pod_id_to_pod:
        # there are no pods in this docker_host.
        msg = 'Docker host %s has containers but no pods' % docker_host
        gs.logger_exception(msg)
        raise collector_error.CollectorError(msg)

    # Annotate the containers with their metrics.
    for container in containers_list:
        assert utilities.is_wrapped_object(container, 'Container')

        parent_pod_id = utilities.get_parent_pod_id(container)
        if not utilities.valid_string(parent_pod_id):
            msg = ('missing or invalid parent pod ID in container %s' %
                   container['id'])
            gs.logger_error(msg)
            raise collector_error.CollectorError(msg)

        if parent_pod_id not in pod_id_to_pod:
            msg = ('could not locate parent pod %s for container %s' %
                   (parent_pod_id, container['id']))
            gs.logger_error(msg)
            raise collector_error.CollectorError(msg)

        # Note that the project ID may be '_unknown_'.
        # This is not a big deal, because the aggregator knows the project ID.
        metrics.annotate_container(project_id, container,
                                   pod_id_to_pod[parent_pod_id])

    return containers_list