Knative Serving in Java: Complete Guide

Introduction

Knative Serving is a Kubernetes-based platform for deploying and managing serverless workloads. It provides auto-scaling (including to zero), traffic routing, and revision management for your Java applications.

Core Concepts

  • Service: Manages the entire lifecycle of your workload
  • Configuration: Describes the desired state of your application
  • Revision: Immutable snapshot of your application code and configuration
  • Route: Maps network endpoints to revisions

Setup and Dependencies

1. Maven Dependencies

<properties>
<knative.version>1.10.0</knative.version>
<fabric8.version>6.9.2</fabric8.version>
<spring-boot.version>3.2.0</spring-boot.version>
</properties>
<dependencies>
<!-- Knative Serving Client -->
<dependency>
<groupId>io.fabric8</groupId>
<artifactId>knative-client</artifactId>
<version>${knative.version}</version>
</dependency>
<!-- Kubernetes Client -->
<dependency>
<groupId>io.fabric8</groupId>
<artifactId>kubernetes-client</artifactId>
<version>${fabric8.version}</version>
</dependency>
<!-- Spring Boot Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>${spring-boot.version}</version>
</dependency>
<!-- Spring Boot Actuator for Health Checks -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<version>${spring-boot.version}</version>
</dependency>
<!-- Micrometer for Metrics -->
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>
<!-- Test Dependencies -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>${spring-boot.version}</version>
<scope>test</scope>
</dependency>
</dependencies>

2. Spring Boot Application

package com.example.knative;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@SpringBootApplication
public class KnativeJavaApplication {
public static void main(String[] args) {
SpringApplication.run(KnativeJavaApplication.class, args);
}
}
@RestController
class HelloController {
private int requestCount = 0;
@GetMapping("/")
public String hello() {
requestCount++;
return String.format("Hello from Knative! Request #%d on pod %s", 
requestCount, System.getenv().getOrDefault("HOSTNAME", "unknown"));
}
@GetMapping("/health")
public String health() {
return "OK";
}
@GetMapping("/metrics")
public String metrics() {
return String.format("requests_total %d", requestCount);
}
}

Knative Service Management

3. Knative Service Service

package com.example.knative.service;
import io.fabric8.knative.serving.v1.Service;
import io.fabric8.knative.serving.v1.ServiceBuilder;
import io.fabric8.knative.serving.v1.ServiceList;
import io.fabric8.kubernetes.client.KubernetesClient;
import io.fabric8.kubernetes.client.KubernetesClientException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@Service
public class KnativeServiceManager {
private static final Logger log = LoggerFactory.getLogger(KnativeServiceManager.class);
private final KubernetesClient kubernetesClient;
private final String namespace;
public KnativeServiceManager(KubernetesClient kubernetesClient,
@Value("${knative.namespace:default}") String namespace) {
this.kubernetesClient = kubernetesClient;
this.namespace = namespace;
}
public Service createKnativeService(String name, String image, 
Map<String, String> envVars, 
ResourceRequirements resources) {
log.info("Creating Knative Service: {} with image: {}", name, image);
Service knativeService = new ServiceBuilder()
.withNewMetadata()
.withName(name)
.withNamespace(namespace)
.addToLabels("app", name)
.addToLabels("managed-by", "java-operator")
.addToAnnotations("autoscaling.knative.dev/metric", "concurrency")
.addToAnnotations("autoscaling.knative.dev/target", "100")
.addToAnnotations("autoscaling.knative.dev/minScale", "1")
.addToAnnotations("autoscaling.knative.dev/maxScale", "10")
.endMetadata()
.withNewSpec()
.withNewTemplate()
.withNewMetadata()
.addToAnnotations("autoscaling.knative.dev/initialScale", "1")
.endMetadata()
.withNewSpec()
.addNewContainer()
.withName(name)
.withImage(image)
.withEnv(createEnvVars(envVars))
.withNewResources()
.withRequests(createResourceMap(resources.getRequests()))
.withLimits(createResourceMap(resources.getLimits()))
.endResources()
.withNewReadinessProbe()
.withNewHttpGet()
.withPath("/health")
.withPort(new IntOrString(8080))
.endHttpGet()
.withInitialDelaySeconds(5)
.withPeriodSeconds(10)
.endReadinessProbe()
.withNewLivenessProbe()
.withNewHttpGet()
.withPath("/health")
.withPort(new IntOrString(8080))
.endHttpGet()
.withInitialDelaySeconds(15)
.withPeriodSeconds(20)
.endLivenessProbe()
.endContainer()
.endSpec()
.endTemplate()
.endSpec()
.build();
return kubernetesClient.resources(Service.class)
.inNamespace(namespace)
.resource(knativeService)
.create();
}
public Optional<Service> getService(String name) {
try {
Service service = kubernetesClient.resources(Service.class)
.inNamespace(namespace)
.withName(name)
.get();
return Optional.ofNullable(service);
} catch (KubernetesClientException e) {
log.error("Error retrieving Knative Service: {}", name, e);
return Optional.empty();
}
}
public List<Service> listServices() {
ServiceList serviceList = kubernetesClient.resources(Service.class)
.inNamespace(namespace)
.list();
return serviceList.getItems();
}
public List<Service> listServicesByLabel(String labelSelector) {
ServiceList serviceList = kubernetesClient.resources(Service.class)
.inNamespace(namespace)
.withLabelSelector(labelSelector)
.list();
return serviceList.getItems();
}
public boolean deleteService(String name) {
try {
return kubernetesClient.resources(Service.class)
.inNamespace(namespace)
.withName(name)
.delete();
} catch (KubernetesClientException e) {
log.error("Error deleting Knative Service: {}", name, e);
return false;
}
}
public Service updateServiceImage(String name, String newImage) {
return kubernetesClient.resources(Service.class)
.inNamespace(namespace)
.withName(name)
.edit(s -> new ServiceBuilder(s)
.editSpec()
.editTemplate()
.editSpec()
.editFirstContainer()
.withImage(newImage)
.endContainer()
.endSpec()
.endTemplate()
.endSpec()
.build());
}
public Service scaleService(String name, Integer minScale, Integer maxScale) {
return kubernetesClient.resources(Service.class)
.inNamespace(namespace)
.withName(name)
.edit(s -> {
ServiceBuilder builder = new ServiceBuilder(s);
if (minScale != null) {
builder.editMetadata()
.addToAnnotations("autoscaling.knative.dev/minScale", minScale.toString())
.endMetadata();
}
if (maxScale != null) {
builder.editMetadata()
.addToAnnotations("autoscaling.knative.dev/maxScale", maxScale.toString())
.endMetadata();
}
return builder.build();
});
}
private List<io.fabric8.kubernetes.api.model.EnvVar> createEnvVars(Map<String, String> envVars) {
return envVars.entrySet().stream()
.map(entry -> new io.fabric8.kubernetes.api.model.EnvVarBuilder()
.withName(entry.getKey())
.withValue(entry.getValue())
.build())
.toList();
}
private Map<String, Quantity> createResourceMap(Map<String, String> resources) {
return resources.entrySet().stream()
.collect(Collectors.toMap(
Map.Entry::getKey,
entry -> new Quantity(entry.getValue())
));
}
}

4. Resource Requirements Model

package com.example.knative.model;
import java.util.Map;
public class ResourceRequirements {
private Map<String, String> requests;
private Map<String, String> limits;
public ResourceRequirements() {}
public ResourceRequirements(Map<String, String> requests, Map<String, String> limits) {
this.requests = requests;
this.limits = limits;
}
// Getters and Setters
public Map<String, String> getRequests() { return requests; }
public void setRequests(Map<String, String> requests) { this.requests = requests; }
public Map<String, String> getLimits() { return limits; }
public void setLimits(Map<String, String> limits) { this.limits = limits; }
// Static factory methods
public static ResourceRequirements small() {
return new ResourceRequirements(
Map.of("cpu", "100m", "memory", "128Mi"),
Map.of("cpu", "500m", "memory", "512Mi")
);
}
public static ResourceRequirements medium() {
return new ResourceRequirements(
Map.of("cpu", "500m", "memory", "512Mi"),
Map.of("cpu", "1000m", "memory", "1Gi")
);
}
public static ResourceRequirements large() {
return new ResourceRequirements(
Map.of("cpu", "1000m", "memory", "1Gi"),
Map.of("cpu", "2000m", "memory", "2Gi")
);
}
}

Advanced Knative Features

5. Traffic Management and Canary Deployments

package com.example.knative.traffic;
import io.fabric8.knative.serving.v1.Route;
import io.fabric8.knative.serving.v1.RouteBuilder;
import io.fabric8.knative.serving.v1.TrafficTarget;
import io.fabric8.kubernetes.client.KubernetesClient;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class TrafficManager {
private final KubernetesClient kubernetesClient;
private final String namespace;
public TrafficManager(KubernetesClient kubernetesClient) {
this.kubernetesClient = kubernetesClient;
this.namespace = kubernetesClient.getNamespace();
}
public Route splitTraffic(String serviceName, String latestRevision, 
String stableRevision, int latestPercentage) {
List<TrafficTarget> trafficTargets = List.of(
new TrafficTargetBuilder()
.withRevisionName(latestRevision)
.withPercent(Integer.valueOf(latestPercentage))
.build(),
new TrafficTargetBuilder()
.withRevisionName(stableRevision)
.withPercent(Integer.valueOf(100 - latestPercentage))
.build()
);
Route route = new RouteBuilder()
.withNewMetadata()
.withName(serviceName)
.withNamespace(namespace)
.endMetadata()
.withNewSpec()
.withTraffic(trafficTargets)
.endSpec()
.build();
return kubernetesClient.resources(Route.class)
.inNamespace(namespace)
.resource(route)
.create();
}
public Route configureBlueGreen(String serviceName, String activeRevision, 
String previewRevision) {
List<TrafficTarget> trafficTargets = List.of(
new TrafficTargetBuilder()
.withRevisionName(activeRevision)
.withPercent(Integer.valueOf(100))
.build(),
new TrafficTargetBuilder()
.withRevisionName(previewRevision)
.withPercent(Integer.valueOf(0))
.withTag("preview")
.build()
);
Route route = new RouteBuilder()
.withNewMetadata()
.withName(serviceName)
.withNamespace(namespace)
.endMetadata()
.withNewSpec()
.withTraffic(trafficTargets)
.endSpec()
.build();
return kubernetesClient.resources(Route.class)
.inNamespace(namespace)
.resource(route)
.create();
}
public Route shiftTraffic(String serviceName, String targetRevision, int percentage) {
Route currentRoute = kubernetesClient.resources(Route.class)
.inNamespace(namespace)
.withName(serviceName)
.get();
if (currentRoute == null) {
throw new RuntimeException("Route not found: " + serviceName);
}
List<TrafficTarget> updatedTraffic = currentRoute.getSpec().getTraffic().stream()
.map(tt -> {
if (tt.getRevisionName().equals(targetRevision)) {
return new TrafficTargetBuilder(tt)
.withPercent(Integer.valueOf(percentage))
.build();
} else {
return new TrafficTargetBuilder(tt)
.withPercent(Integer.valueOf(100 - percentage))
.build();
}
})
.toList();
return kubernetesClient.resources(Route.class)
.inNamespace(namespace)
.withName(serviceName)
.edit(r -> new RouteBuilder(r)
.editSpec()
.withTraffic(updatedTraffic)
.endSpec()
.build());
}
}

6. Revision Management

package com.example.knative.revision;
import io.fabric8.knative.serving.v1.Revision;
import io.fabric8.knative.serving.v1.RevisionList;
import io.fabric8.kubernetes.client.KubernetesClient;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Optional;
@Service
public class RevisionManager {
private final KubernetesClient kubernetesClient;
private final String namespace;
public RevisionManager(KubernetesClient kubernetesClient) {
this.kubernetesClient = kubernetesClient;
this.namespace = kubernetesClient.getNamespace();
}
public List<Revision> listRevisionsForService(String serviceName) {
RevisionList revisionList = kubernetesClient.resources(Revision.class)
.inNamespace(namespace)
.withLabel("serving.knative.dev/service", serviceName)
.list();
return revisionList.getItems();
}
public Optional<Revision> getRevision(String revisionName) {
Revision revision = kubernetesClient.resources(Revision.class)
.inNamespace(namespace)
.withName(revisionName)
.get();
return Optional.ofNullable(revision);
}
public boolean deleteRevision(String revisionName) {
return kubernetesClient.resources(Revision.class)
.inNamespace(namespace)
.withName(revisionName)
.delete();
}
public List<Revision> listOldRevisions(String serviceName, int keepCount) {
List<Revision> allRevisions = listRevisionsForService(serviceName);
// Sort by creation timestamp (newest first)
allRevisions.sort((r1, r2) -> 
r2.getMetadata().getCreationTimestamp()
.compareTo(r1.getMetadata().getCreationTimestamp()));
// Return old revisions beyond the keep count
return allRevisions.stream()
.skip(keepCount)
.toList();
}
public void cleanupOldRevisions(String serviceName, int keepCount) {
List<Revision> oldRevisions = listOldRevisions(serviceName, keepCount);
for (Revision revision : oldRevisions) {
String revisionName = revision.getMetadata().getName();
log.info("Deleting old revision: {}", revisionName);
deleteRevision(revisionName);
}
}
}

Spring Boot Auto-Configuration

7. Knative Auto-Configuration

package com.example.knative.config;
import io.fabric8.knative.client.KnativeClient;
import io.fabric8.kubernetes.client.Config;
import io.fabric8.kubernetes.client.ConfigBuilder;
import io.fabric8.kubernetes.client.DefaultKubernetesClient;
import io.fabric8.kubernetes.client.KubernetesClient;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@EnableConfigurationProperties(KnativeProperties.class)
public class KnativeAutoConfiguration {
@Bean
public KubernetesClient kubernetesClient(KnativeProperties properties) {
Config config = new ConfigBuilder()
.withMasterUrl(properties.getMasterUrl())
.withNamespace(properties.getNamespace())
.withOauthToken(properties.getOauthToken())
.withTrustCerts(true)
.withRequestTimeout(properties.getRequestTimeout())
.withConnectionTimeout(properties.getConnectionTimeout())
.build();
return new DefaultKubernetesClient(config);
}
@Bean
public KnativeClient knativeClient(KubernetesClient kubernetesClient) {
return kubernetesClient.adapt(KnativeClient.class);
}
}

8. Configuration Properties

package com.example.knative.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix = "knative")
public class KnativeProperties {
private String namespace = "default";
private String masterUrl;
private String oauthToken;
private int requestTimeout = 10000;
private int connectionTimeout = 10000;
// Auto-scaling defaults
private int minScale = 0;
private int maxScale = 10;
private int targetConcurrency = 100;
// Getters and Setters
public String getNamespace() { return namespace; }
public void setNamespace(String namespace) { this.namespace = namespace; }
public String getMasterUrl() { return masterUrl; }
public void setMasterUrl(String masterUrl) { this.masterUrl = masterUrl; }
public String getOauthToken() { return oauthToken; }
public void setOauthToken(String oauthToken) { this.oauthToken = oauthToken; }
public int getRequestTimeout() { return requestTimeout; }
public void setRequestTimeout(int requestTimeout) { this.requestTimeout = requestTimeout; }
public int getConnectionTimeout() { return connectionTimeout; }
public void setConnectionTimeout(int connectionTimeout) { this.connectionTimeout = connectionTimeout; }
public int getMinScale() { return minScale; }
public void setMinScale(int minScale) { this.minScale = minScale; }
public int getMaxScale() { return maxScale; }
public void setMaxScale(int maxScale) { this.maxScale = maxScale; }
public int getTargetConcurrency() { return targetConcurrency; }
public void setTargetConcurrency(int targetConcurrency) { this.targetConcurrency = targetConcurrency; }
}

REST Controller for Knative Management

9. Knative REST API

package com.example.knative.controller;
import com.example.knative.model.ResourceRequirements;
import com.example.knative.service.KnativeServiceManager;
import com.example.knative.traffic.TrafficManager;
import io.fabric8.knative.serving.v1.Service;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
@RestController
@RequestMapping("/api/knative")
public class KnativeController {
private final KnativeServiceManager serviceManager;
private final TrafficManager trafficManager;
public KnativeController(KnativeServiceManager serviceManager, 
TrafficManager trafficManager) {
this.serviceManager = serviceManager;
this.trafficManager = trafficManager;
}
@PostMapping("/services")
public ResponseEntity<Service> createService(
@RequestParam String name,
@RequestParam String image,
@RequestBody(required = false) Map<String, String> envVars,
@RequestParam(defaultValue = "small") String size) {
ResourceRequirements resources = getResourceRequirements(size);
Service service = serviceManager.createKnativeService(
name, image, envVars != null ? envVars : Map.of(), resources);
return ResponseEntity.ok(service);
}
@GetMapping("/services")
public ResponseEntity<List<Service>> listServices() {
return ResponseEntity.ok(serviceManager.listServices());
}
@GetMapping("/services/{name}")
public ResponseEntity<Service> getService(@PathVariable String name) {
return serviceManager.getService(name)
.map(ResponseEntity::ok)
.orElse(ResponseEntity.notFound().build());
}
@DeleteMapping("/services/{name}")
public ResponseEntity<Void> deleteService(@PathVariable String name) {
boolean deleted = serviceManager.deleteService(name);
return deleted ? ResponseEntity.ok().build() : ResponseEntity.notFound().build();
}
@PatchMapping("/services/{name}/image")
public ResponseEntity<Service> updateServiceImage(
@PathVariable String name,
@RequestParam String newImage) {
Service updated = serviceManager.updateServiceImage(name, newImage);
return ResponseEntity.ok(updated);
}
@PatchMapping("/services/{name}/scale")
public ResponseEntity<Service> updateScaling(
@PathVariable String name,
@RequestParam(required = false) Integer minScale,
@RequestParam(required = false) Integer maxScale) {
Service updated = serviceManager.scaleService(name, minScale, maxScale);
return ResponseEntity.ok(updated);
}
@PostMapping("/services/{name}/traffic/split")
public ResponseEntity<Route> splitTraffic(
@PathVariable String name,
@RequestParam String latestRevision,
@RequestParam String stableRevision,
@RequestParam int latestPercentage) {
Route route = trafficManager.splitTraffic(
name, latestRevision, stableRevision, latestPercentage);
return ResponseEntity.ok(route);
}
@PostMapping("/services/{name}/traffic/shift")
public ResponseEntity<Route> shiftTraffic(
@PathVariable String name,
@RequestParam String targetRevision,
@RequestParam int percentage) {
Route route = trafficManager.shiftTraffic(name, targetRevision, percentage);
return ResponseEntity.ok(route);
}
private ResourceRequirements getResourceRequirements(String size) {
return switch (size.toLowerCase()) {
case "small" -> ResourceRequirements.small();
case "medium" -> ResourceRequirements.medium();
case "large" -> ResourceRequirements.large();
default -> ResourceRequirements.small();
};
}
}

Event-Driven Knative Services

10. Knative Eventing Integration

package com.example.knative.eventing;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.ServerResponse;
import static org.springframework.web.reactive.function.server.RouterFunctions.route;
import static org.springframework.web.reactive.function.server.ServerResponse.ok;
@Configuration
public class EventingConfiguration {
@Bean
public RouterFunction<ServerResponse> eventRoutes(EventProcessor eventProcessor) {
return route()
.POST("/event", request -> request.bodyToMono(CloudEvent.class)
.flatMap(eventProcessor::processEvent)
.flatMap(result -> ok().contentType(MediaType.APPLICATION_JSON).bodyValue(result)))
.build();
}
}
@Component
class EventProcessor {
public Mono<EventResult> processEvent(CloudEvent event) {
return Mono.fromCallable(() -> {
// Process the cloud event
String eventType = event.getType();
Object data = event.getData();
log.info("Processing event type: {}, data: {}", eventType, data);
// Business logic here
return new EventResult("processed", "Event processed successfully");
});
}
}
class CloudEvent {
private String type;
private String source;
private Object data;
// Getters and setters
public String getType() { return type; }
public void setType(String type) { this.type = type; }
public String getSource() { return source; }
public void setSource(String source) { this.source = source; }
public Object getData() { return data; }
public void setData(Object data) { this.data = data; }
}
class EventResult {
private String status;
private String message;
public EventResult(String status, String message) {
this.status = status;
this.message = message;
}
// Getters
public String getStatus() { return status; }
public String getMessage() { return message; }
}

Health and Metrics

11. Knative Health Indicators

package com.example.knative.health;
import io.fabric8.knative.serving.v1.Service;
import io.fabric8.kubernetes.client.KubernetesClient;
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
public class KnativeHealthIndicator implements HealthIndicator {
private final KubernetesClient kubernetesClient;
private final String namespace;
public KnativeHealthIndicator(KubernetesClient kubernetesClient) {
this.kubernetesClient = kubernetesClient;
this.namespace = kubernetesClient.getNamespace();
}
@Override
public Health health() {
try {
List<Service> services = kubernetesClient.resources(Service.class)
.inNamespace(namespace)
.list()
.getItems();
long readyServices = services.stream()
.filter(this::isServiceReady)
.count();
Health.Builder healthBuilder = services.isEmpty() ? 
Health.unknown() : Health.up();
return healthBuilder
.withDetail("totalServices", services.size())
.withDetail("readyServices", readyServices)
.build();
} catch (Exception e) {
return Health.down(e).build();
}
}
private boolean isServiceReady(Service service) {
if (service.getStatus() == null) return false;
var conditions = service.getStatus().getConditions();
if (conditions == null) return false;
return conditions.stream()
.anyMatch(condition -> "Ready".equals(condition.getType()) && 
"True".equals(condition.getStatus()));
}
}

Application Configuration

12. application.yml

spring:
application:
name: knative-java-manager
knative:
namespace: ${KUBERNETES_NAMESPACE:default}
master-url: ${KUBERNETES_MASTER:https://kubernetes.default.svc}
oauth-token: ${KUBERNETES_TOKEN:}
min-scale: 0
max-scale: 5
target-concurrency: 100
server:
port: 8080
management:
endpoints:
web:
exposure:
include: health,info,metrics,knative
endpoint:
health:
show-details: always
knative:
enabled: true
logging:
level:
com.example.knative: DEBUG
io.fabric8: INFO

Deployment with Knative

13. knative-service.yaml

apiVersion: serving.knative.dev/v1
kind: Service
metadata:
name: knative-java-manager
namespace: default
spec:
template:
metadata:
annotations:
autoscaling.knative.dev/minScale: "1"
autoscaling.knative.dev/maxScale: "5"
autoscaling.knative.dev/target: "100"
spec:
containers:
- image: your-registry/knative-java-manager:latest
ports:
- containerPort: 8080
env:
- name: JAVA_OPTS
value: "-Xmx512m -Xms256m"
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "500m"
readinessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 15
periodSeconds: 20

Best Practices

  1. Use Scale-to-Zero Wisely: Not all applications benefit from scaling to zero
  2. Configure Proper Resource Limits: Prevent resource exhaustion
  3. Implement Health Checks: Ensure Knative can properly route traffic
  4. Use Traffic Splitting: Enable safe canary deployments
  5. Monitor Autoscaling: Adjust concurrency targets based on your application's characteristics
  6. Clean Up Old Revisions: Prevent resource accumulation

Conclusion

Knative Serving provides powerful abstractions for deploying and managing serverless Java applications on Kubernetes. The Fabric8 Java client enables programmatic management of Knative resources, allowing you to automate deployments, manage traffic routing, and implement advanced deployment strategies like canary releases and blue-green deployments.

This comprehensive Java implementation demonstrates how to leverage Knative's auto-scaling, revision management, and traffic routing capabilities while maintaining the flexibility and control needed for enterprise Java applications.

Leave a Reply

Your email address will not be published. Required fields are marked *


Macro Nepal Helper