Add get_k8s_logs Operator

Add a method to retrieve logs from Kubernetes Pod

Change-Id: I02e59c164881566d4c2b0d5decbe9eb0f3f30d34
This commit is contained in:
Anthony Lin 2018-04-16 06:39:31 +00:00
parent b9b0e27de0
commit 91b60ac595
2 changed files with 120 additions and 2 deletions

View File

@ -27,11 +27,12 @@ rules:
- apiGroups:
- ""
resources:
- endpoints
- nodes
- nodes/proxy
- services
- endpoints
- pods
- pods/log
- services
verbs:
- delete
- get

View File

@ -0,0 +1,117 @@
# Copyright 2018 AT&T Intellectual Property. All other rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import logging
from kubernetes import client, config
from kubernetes.client.rest import ApiException
LOG = logging.getLogger(__name__)
_NOT_FOUND_MSG_FMT = ("No matching pods found for namespace: {}"
" pod: {} container: {}")
class K8sLoggingException(Exception):
""" We do not really want the workflow to terminate due to logs
retrieval issues and hence we will have another Exception
handling class to handle this."""
pass
def get_pod_logs(pod_name_pattern, namespace, container, since_seconds):
"""This function retrieves the logs of the kubernetes pod
:param pod_name_pattern: Pattern of Pods name, e.g. 'drydock-api' if
we want to check the logs of the Drydock API
pods. Note that we are parsing pattern as
there are usually multiple pods present (for
redundancy purposes) and we will want to show
the logs of all the relevant pods.
:param namespace: Namespace where Pods reside
:param container: The container for which to stream logs. Defaults
to only container if there is one container in
the pod.
:param since_seconds: A relative time in seconds before the current
time from which to show logs. If this value
precedes the time a pod was started, only logs
since the pod start will be returned. If this
value is in the future, no logs will be returned.
Example::
from get_k8s_logs import get_pod_logs
# Calls function to retrieve logs
get_pod_logs('airflow-worker', 'ucp', 'airflow-worker', 3600)
"""
# Note that we are using 'in_cluster_config'
config.load_incluster_config()
v1 = client.CoreV1Api()
# Initialize variable
pods_list = []
# Retrieve names of pods
try:
ret = v1.list_namespaced_pod(namespace=namespace,
watch=False)
except ApiException as e:
LOG.error(e)
msg = ("Caught %s while trying to retrieve namespaced pods from K8s"
" API. Details: %s" % (e.__class__.__name__, e))
raise K8sLoggingException(msg)
if ret:
for i in ret.items:
if pod_name_pattern in i.metadata.name:
pods_list.append(i.metadata.name)
else:
raise K8sLoggingException(_NOT_FOUND_MSG_FMT.format(namespace,
pod_name_pattern,
container))
if pods_list:
LOG.info("The following Pods matched the requested pattern %s: %s",
pod_name_pattern, ", ".join(pods_list))
else:
raise K8sLoggingException(_NOT_FOUND_MSG_FMT.format(namespace,
pod_name_pattern,
container))
# Retrieve logs from pod
for pod in pods_list:
try:
# Note that the kwarg 'pretty' takes on string value and will
# ensure that the output is pretty printed if set 'true'.
pod_logs = v1.read_namespaced_pod_log(name=pod,
namespace=namespace,
container=container,
pretty='true',
since_seconds=since_seconds)
except ApiException as e:
LOG.error(e)
msg = ("Caught %s while trying to read logs from namespaced pod=%s"
", namespace=%s, container=%s using the k8s API. Details: "
"%s" % (e.__class__.__name__, pod, namespace, container, e))
raise K8sLoggingException(msg)
LOG.info("\n\n================= Logs for container %s of pods %s in"
" namespace %s =================\n\n",
container, pod, namespace)
LOG.info(pod_logs)
LOG.info("\n\n================= End Logs for %s =================\n\n",
pod)