Kubernetes: Building a Custom Log Exporter with NodeJS

Architecture & Workflow

  • Get the pod name from a list of pod objects
  • Finding all prods in a namespace
  • Filter all pods of a namespace that match a certain name

Part 1: Configuration

const configure = () => {
try {
kc.loadFromDefault()
k8sApi = kc.makeApiClient(k8s.CoreV1Api)
} catch (e) {
console.log(e)
}
}

Part 2: Accessing and Filtering Pods

  • podNames: From the list of pod objects, return only the names
  • getPodsInNamespace: Get all pods of the namespaces, and return only their names
  • getPodsByName: Get a list of pod names that match the specified regex pattern and in the provided namespace.
const podNames = podObjectList => {
return podObjectList.items.map(item => item.metadata.name)
}
const getPodsInNamespace = async (namespace = 'default') => {
podObjectList = (await k8sApi.listNamespacedPod(namespace)).body
return podNames(podObjectList)
}
const getPodsByName = async (pattern, namespace = 'default') => {
const pods = await getPodsInNamespace(namespace)
return pods.filter(item => item.match(pattern))
}

Part 3: Log File Merge

const getLogsFromPod = async (podName, namespace = 'default') => {
return (await k8sApi.readNamespacedPodLog(podName, namespace)).body
}
const updateLogsForPod = async (podName, namespace = 'default') => {
let storedLogText = ''
try {
storedLogText = fs.readFileSync(`logs/${podName}.log`, 'utf8')
} catch (e) {
// Do nothing
}
const liveLogText = await getLogsFromPod(podName, namespace)
fs.writeFileSync(
`logs/${podName}.log`,
mergeLogTexts(storedLogText, liveLogText)
)
return true
}
const mergeLogTexts = (log1, log2) => {
const unified = [...new Set(log1.split('\n').concat(log2.split('\n')))]
return unified.join('\n')
}

Part 4: Local Export

async function exportToLocalDir (namespacePodMapping) {
for (let [namespace, podNames] of Object.entries(namespacePodMapping)) {
podNames.forEach(async podName => {
const names = await kubeLogExporter.getPodsByName(podName, namespace)
names.forEach(podName =>
kubeLogExporter.updateLogsForPod(podName, namespace)
)
})
}
}
kubeLogExporter.exportToLocalDir({ default: [/redis/, /lighthouse/] })

Conclusion

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Sebastian

Sebastian

IT Project Manager & Developer