in core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/kubernetes/KubernetesClient.scala [149:218]
def run(name: String,
image: String,
memory: ByteSize = 256.MB,
environment: Map[String, String] = Map.empty,
labels: Map[String, String] = Map.empty)(implicit transid: TransactionId): Future[KubernetesContainer] = {
val (pod, pdb) = podBuilder.buildPodSpec(name, image, memory, environment, labels, config)
if (transid.meta.extraLogging) {
log.info(this, s"Pod spec being created\n${Serialization.asYaml(pod)}")
}
val namespace = kubeRestClient.getNamespace
val start = transid.started(
this,
LoggingMarkers.INVOKER_KUBEAPI_CMD("create"),
s"launching pod $name (image:$image, mem: ${memory.toMB}) (timeout: ${config.timeouts.run.toSeconds}s)",
logLevel = akka.event.Logging.InfoLevel)
//create the pod; catch any failure to end the transaction timer
Try {
val created = kubeRestClient.pods.inNamespace(namespace).create(pod)
pdb.map(
p =>
kubeRestClient.policy.podDisruptionBudget
.inNamespace(namespace)
.withName(name)
.create(p))
created
} match {
case Failure(e) =>
//call to api-server failed
val stackTrace = ExceptionUtils.getStackTrace(e)
transid.failed(
this,
start,
s"Failed create pod for '$name': ${e.getClass} (Caused by: ${e.getCause}) - ${e.getMessage}; stacktrace: $stackTrace",
ErrorLevel)
Future.failed(KubernetesPodApiException(e))
case Success(createdPod) => {
//call to api-server succeeded; wait for the pod to become ready; catch any failure to end the transaction timer
waitForPod(namespace, createdPod, start.start, config.timeouts.run)
.map { readyPod =>
transid.finished(this, start, logLevel = InfoLevel)
toContainer(readyPod)
}
.recoverWith {
case e =>
transid.failed(this, start, s"Failed create pod for '$name': ${e.getClass} - ${e.getMessage}", ErrorLevel)
//log pod events to diagnose pod readiness failures
val podEvents = kubeRestClient
.v1()
.events()
.inNamespace(namespace)
.withField("involvedObject.name", name)
.list()
.getItems
.asScala
if (podEvents.isEmpty) {
log.info(this, s"No pod events for failed pod '$name'")
} else {
podEvents.foreach { podEvent =>
log.info(
this,
s"Pod event for failed pod '$name' ${podEvent.getLastTimestamp}: ${podEvent.getMessage}")
}
}
Future.failed(e)
}
}
}
}