Carvel is a suite of reliable, single-purpose, composable tools for building, configuring, and deploying applications to Kubernetes. This guide covers integrating Carvel tools with Java applications for superior Kubernetes deployment experiences.
Core Concepts
What is Carvel?
- Suite of Kubernetes application management tools
- Composable, single-purpose tools
- GitOps-friendly approach
- Alternative to Helm/Kustomize
Key Carvel Tools:
- ytt: YAML templating tool
- kbld: Image building and resolution
- kapp: Application deployment tool
- imgpkg: Image packaging for configuration
- vendir: Declarative directory contents
Dependencies and Setup
1. Installation
# Install Carvel tools on macOS brew tap vmware-tanzu/carvel brew install ytt kbld kapp imgpkg vendir # Install on Linux wget -O- https://carvel.dev/install.sh | bash # Verify installation ytt version kbld version kapp version
2. Project Structure
java-carvel-app/ ├── build/ │ └── carvel/ ├── k8s/ │ ├── base/ │ ├── overlays/ │ └── values/ ├── src/ ├── build.gradle ├── Dockerfile └── carvel-build.sh
Core Implementation
1. Basic Kubernetes Manifests
# k8s/base/deployment.yml apiVersion: apps/v1 kind: Deployment metadata: name: java-app labels: app: java-app spec: replicas: 2 selector: matchLabels: app: java-app template: metadata: labels: app: java-app spec: containers: - name: java-app image: placeholder # Will be replaced by kbld ports: - containerPort: 8080 env: - name: JAVA_OPTS value: "-XX:+UseContainerSupport -XX:MaxRAMPercentage=75.0" resources: requests: memory: "512Mi" cpu: "250m" limits: memory: "1024Mi" cpu: "500m" livenessProbe: httpGet: path: /actuator/health/liveness port: 8080 initialDelaySeconds: 30 periodSeconds: 10 readinessProbe: httpGet: path: /actuator/health/readiness port: 8080 initialDelaySeconds: 5 periodSeconds: 5 --- apiVersion: v1 kind: Service metadata: name: java-app-service spec: selector: app: java-app ports: - port: 80 targetPort: 8080 type: ClusterIP
2. ytt Templating for Java Apps
# k8s/base/config.yml #@ load("@ytt:data", "data") #@ load("@ytt:struct", "struct") #@ def app_config(): apiVersion: v1 kind: ConfigMap metadata: name: java-app-config data: application.yml: | server: port: 8080 spring: application: name: #@ data.values.app_name datasource: url: #@ data.values.database.url username: #@ data.values.database.username password: #@ data.values.database.password jpa: hibernate: ddl-auto: validate show-sql: false management: endpoints: web: exposure: include: health,info,metrics endpoint: health: show-details: always probes: enabled: true #@ end #@ def secret_template(): apiVersion: v1 kind: Secret metadata: name: java-app-secrets type: Opaque data: database.password: #@ data.values.database.password_b64 encryption.key: #@ data.values.encryption_key_b64 #@ end --- #@ app_config() --- #@ secret_template() 3. Values Configuration
# k8s/values/defaults.yml #@data/values --- app_name: "java-carvel-app" environment: "development" replicas: 2 database: url: "jdbc:postgresql://localhost:5432/myapp" username: "appuser" password: "defaultpass" password_b64: "ZGVmYXVsdHBhc3M=" encryption_key_b64: "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXo=" resources: requests: memory: "512Mi" cpu: "250m" limits: memory: "1024Mi" cpu: "500m"
4. Environment Overlays
# k8s/overlays/staging/values.yml #@data/values --- app_name: "java-carvel-app-staging" environment: "staging" replicas: 3 database: url: "jdbc:postgresql://postgresql-staging:5432/myapp" username: "appuser" password: "stagingpass" password_b64: "c3RhZ2luZ3Bhc3M=" resources: requests: memory: "1Gi" cpu: "500m" limits: memory: "2Gi" cpu: "1000m"
# k8s/overlays/production/values.yml #@data/values --- app_name: "java-carvel-app-production" environment: "production" replicas: 5 database: url: "jdbc:postgresql://postgresql-production:5432/myapp" username: "appuser" password: "prodpass" password_b64: "cHJvZHBhc3M=" resources: requests: memory: "2Gi" cpu: "1000m" limits: memory: "4Gi" cpu: "2000m"
5. Build Configuration with kbld
# build/carvel/kbld-config.yml apiVersion: kbld.k14s.io/v1alpha1 kind: Config sources: - image: java-app path: . docker: build: dockerfile: Dockerfile target: builder destinations: - image: ghcr.io/myorg/java-carvel-app overrides: - image: placeholder newImage: java-app preresolved: true
6. Dockerfile for Carvel Integration
# Multi-stage build optimized for Carvel FROM eclipse-temurin:17-jdk-alpine as builder WORKDIR /app # Copy build files COPY gradlew . COPY gradle gradle COPY build.gradle settings.gradle ./ # Download dependencies RUN ./gradlew dependencies --no-daemon # Copy source and build COPY src src RUN ./gradlew bootJar --no-daemon # Extract layers for better container startup RUN java -Djarmode=tools -jar build/libs/*.jar extract --destination build/extracted # Runtime image FROM eclipse-temurin:17-jre-alpine RUN addgroup -S appuser && adduser -S appuser -G appuser USER appuser WORKDIR /app # Copy extracted layers COPY --from=builder /app/build/extracted/dependencies/ ./ COPY --from=builder /app/build/extracted/spring-boot-loader/ ./ COPY --from=builder /app/build/extracted/snapshot-dependencies/ ./ COPY --from=builder /app/build/extracted/application/ ./ EXPOSE 8080 ENTRYPOINT ["java", "org.springframework.boot.loader.JarLauncher"]
Build and Deployment Scripts
1. Carvel Build Script
#!/bin/bash # carvel-build.sh set -e APP_NAME="java-carvel-app" IMAGE_REPO="ghcr.io/myorg" TAG="${1:-latest}" ENVIRONMENT="${2:-development}" echo "Building Java application with Carvel tools..." echo "Environment: $ENVIRONMENT" echo "Tag: $TAG" # Build JAR echo "=== Building Java Application ===" ./gradlew clean bootJar # Build Docker image echo "=== Building Docker Image ===" docker build -t ${APP_NAME}:${TAG} . # Use kbld to resolve images and create lock file echo "=== Processing Kubernetes Manifests ===" mkdir -p build/carvel kbld -f build/carvel/kbld-config.yml \ --images-annotation=false \ > build/carvel/kbld-resolved.yml # Package application bundle with imgpkg echo "=== Creating Application Bundle ===" imgpkg push -b ${IMAGE_REPO}/${APP_NAME}-bundle:${TAG} \ --file build/carvel/kbld-resolved.yml echo "Build completed successfully!" echo "Bundle: ${IMAGE_REPO}/${APP_NAME}-bundle:${TAG}" 2. Deployment Script
#!/bin/bash # carvel-deploy.sh set -e APP_NAME="java-carvel-app" IMAGE_REPO="ghcr.io/myorg" TAG="${1:-latest}" ENVIRONMENT="${2:-development}" KAPP_NAMESPACE="${3:-default}" echo "Deploying Java application with Carvel..." echo "Environment: $ENVIRONMENT" echo "Namespace: $KAPP_NAMESPACE" # Create namespace if it doesn't exist kubectl create namespace $KAPP_NAMESPACE --dry-run=client -o yaml | kubectl apply -f - # Pull bundle and deploy with kapp echo "=== Deploying Application ===" # Template with ytt and deploy with kapp kapp deploy -a ${APP_NAME}-${ENVIRONMENT} \ --into-ns $KAPP_NAMESPACE \ --file <(ytt -f k8s/base \ -f k8s/overlays/${ENVIRONMENT} \ -f build/carvel/kbld-resolved.yml \ -v environment=${ENVIRONMENT}) \ --diff-changes \ --yes echo "Deployment completed successfully!" echo "To inspect: kapp inspect -a ${APP_NAME}-${ENVIRONMENT}" echo "To view logs: kubectl logs -l app=${APP_NAME} -n ${KAPP_NAMESPACE}" 3. Complete Build Pipeline
#!/bin/bash # carvel-pipeline.sh set -e # Configuration APP_NAME="java-carvel-app" IMAGE_REPO="ghcr.io/myorg" VERSION=${1:-$(git rev-parse --short HEAD)} ENVIRONMENTS=("development" "staging" "production") echo "Starting Carvel pipeline for version: $VERSION" # Build application echo "=== Phase 1: Application Build ===" ./carvel-build.sh $VERSION # Deploy to environments for ENV in "${ENVIRONMENTS[@]}"; do echo "=== Deploying to $ENV ===" # For production, require manual approval if [ "$ENV" == "production" ]; then read -p "Deploy to production? (y/n): " -n 1 -r echo if [[ ! $REPLY =~ ^[Yy]$ ]]; then echo "Skipping production deployment" continue fi fi ./carvel-deploy.sh $VERSION $ENV $APP_NAME-$ENV done echo "Pipeline completed successfully!" Advanced Carvel Patterns
1. Multi-Application Configuration
# k8s/base/database.yml #@ load("@ytt:data", "data") #@ if data.values.enable_database: apiVersion: apps/v1 kind: Deployment metadata: name: postgresql labels: app: postgresql component: database spec: replicas: 1 selector: matchLabels: app: postgresql template: metadata: labels: app: postgresql spec: containers: - name: postgresql image: postgres:13 env: - name: POSTGRES_DB value: #@ data.values.database.name - name: POSTGRES_USER value: #@ data.values.database.username - name: POSTGRES_PASSWORD valueFrom: secretKeyRef: name: java-app-secrets key: database.password ports: - containerPort: 5432 volumeMounts: - name: postgresql-data mountPath: /var/lib/postgresql/data resources: requests: memory: "256Mi" cpu: "100m" limits: memory: "512Mi" cpu: "200m" volumes: - name: postgresql-data persistentVolumeClaim: claimName: postgresql-pvc --- apiVersion: v1 kind: Service metadata: name: postgresql spec: selector: app: postgresql ports: - port: 5432 targetPort: 5432 --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: postgresql-pvc spec: accessModes: - ReadWriteOnce resources: requests: storage: 10Gi #@ end 2. Feature Flags with ytt
# k8s/base/features.yml #@ load("@ytt:data", "data") #@ def feature_flags(): apiVersion: v1 kind: ConfigMap metadata: name: feature-flags data: features.yml: | features: new-payment-service: enabled: #@ data.values.features.new_payment_service experimental-ui: enabled: #@ data.values.features.experimental_ui maintenance-mode: enabled: #@ data.values.features.maintenance_mode logging: level: #@ data.values.logging.level #@ end --- #@ feature_flags() 3. Java-Specific Health Checks
# k8s/base/healthchecks.yml #@ load("@ytt:overlay", "overlay") #@ def add_healthchecks(): #@overlay/match by=overlay.subset({"kind": "Deployment"}) --- spec: template: spec: containers: #@overlay/match by=overlay.subset({"name": "java-app"}) - name: java-app livenessProbe: httpGet: path: /actuator/health/liveness port: 8080 initialDelaySeconds: 90 periodSeconds: 10 timeoutSeconds: 5 failureThreshold: 3 readinessProbe: httpGet: path: /actuator/health/readiness port: 8080 initialDelaySeconds: 30 periodSeconds: 5 timeoutSeconds: 3 failureThreshold: 3 startupProbe: httpGet: path: /actuator/health/readiness port: 8080 initialDelaySeconds: 10 periodSeconds: 5 timeoutSeconds: 3 failureThreshold: 30 #@ end --- #@ add_healthchecks() 4. Resource Management
# k8s/base/resources.yml #@ load("@ytt:overlay", "overlay") #@ load("@ytt:data", "data") #@ def add_resources(): #@overlay/match by=overlay.subset({"kind": "Deployment"}) --- spec: template: spec: containers: #@overlay/match by=overlay.subset({"name": "java-app"}) - name: java-app resources: requests: memory: #@ data.values.resources.requests.memory cpu: #@ data.values.resources.requests.cpu limits: memory: #@ data.values.resources.limits.memory cpu: #@ data.values.resources.limits.cpu env: - name: JAVA_OPTS value: #@ "-XX:+UseContainerSupport -XX:MaxRAMPercentage=75.0 -Xmx" + data.values.resources.limits.memory.replace("Mi", "m").replace("Gi", "g") #@ end --- #@ add_resources() CI/CD Integration
1. GitHub Actions with Carvel
# .github/workflows/carvel-pipeline.yml name: Carvel Java Pipeline on: push: branches: [ main, develop ] pull_request: branches: [ main ] env: APP_NAME: java-carvel-app IMAGE_REPO: ghcr.io/${{ github.repository }} jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Set up JDK 17 uses: actions/setup-java@v3 with: java-version: '17' distribution: 'temurin' - name: Run tests run: ./gradlew test build: needs: test runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Install Carvel tools run: | wget -O- https://carvel.dev/install.sh | bash ytt version kbld version kapp version - name: Build with Carvel run: | chmod +x carvel-build.sh ./carvel-build.sh ${{ github.sha }} - name: Push to GitHub Container Registry run: | echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin docker push $IMAGE_REPO/$APP_NAME-bundle:${{ github.sha }} deploy-staging: needs: build runs-on: ubuntu-latest environment: staging steps: - uses: actions/checkout@v4 - name: Install Carvel tools run: wget -O- https://carvel.dev/install.sh | bash - name: Deploy to staging run: | chmod +x carvel-deploy.sh ./carvel-deploy.sh ${{ github.sha }} staging $APP_NAME-staging env: KUBE_CONFIG: ${{ secrets.STAGING_KUBE_CONFIG }} 2. GitLab CI with Carvel
# .gitlab-ci.yml variables: APP_NAME: "java-carvel-app" stages: - test - build - deploy .test_template: &test_template stage: test image: eclipse-temurin:17 before_script: - chmod +x gradlew script: - ./gradlew test test: <<: *test_template build: stage: build image: docker:20.10 services: - docker:20.10-dind before_script: - apk add --no-cache curl - wget -O- https://carvel.dev/install.sh | bash script: - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY - chmod +x carvel-build.sh - ./carvel-build.sh $CI_COMMIT_SHA only: - main - develop deploy-staging: stage: deploy image: alpine:3.16 before_script: - apk add --no-cache curl kubectl - wget -O- https://carvel.dev/install.sh | bash script: - echo "$KUBE_CONFIG_STAGING" | base64 -d > /tmp/kubeconfig - export KUBECONFIG=/tmp/kubeconfig - chmod +x carvel-deploy.sh - ./carvel-deploy.sh $CI_COMMIT_SHA staging $APP_NAME-staging environment: name: staging only: - main
Monitoring and Operations
1. Application Monitoring
# k8s/base/monitoring.yml #@ load("@ytt:data", "data") #@ if data.values.monitoring.enabled: apiVersion: v1 kind: Service metadata: name: java-app-metrics labels: app: java-app component: metrics spec: selector: app: java-app ports: - name: metrics port: 8080 targetPort: 8080 --- apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: name: java-app-monitor labels: app: java-app spec: selector: matchLabels: app: java-app endpoints: - port: metrics path: /actuator/prometheus interval: 30s #@ end 2. Logging Configuration
# k8s/base/logging.yml #@ load("@ytt:overlay", "overlay") #@ def add_logging(): #@overlay/match by=overlay.subset({"kind": "Deployment"}) --- spec: template: metadata: annotations: fluentbit.io/parser: java spec: containers: #@overlay/match by=overlay.subset({"name": "java-app"}) - name: java-app env: - name: LOGGING_LEVEL value: #@ data.values.logging.level - name: LOGGING_PATTERN value: "%d{yyyy-MM-dd HH:mm:ss} - %logger{36} - %msg%n" #@ end --- #@ add_logging() 3. kapp Application Management
#!/bin/bash # carvel-manage.sh APP_NAME="java-carvel-app" ENVIRONMENT="${1:-development}" ACTION="${2:-status}" case $ACTION in "status") kapp inspect -a ${APP_NAME}-${ENVIRONMENT} ;; "logs") kubectl logs -l app=${APP_NAME} -n ${APP_NAME}-${ENVIRONMENT} --tail=100 ;; "restart") kapp deploy -a ${APP_NAME}-${ENVIRONMENT} --yes ;; "delete") kapp delete -a ${APP_NAME}-${ENVIRONMENT} --yes ;; "diff") kapp deploy -a ${APP_NAME}-${ENVIRONMENT} --diff-changes --yes ;; *) echo "Usage: $0 [environment] [status|logs|restart|delete|diff]" ;; esac Best Practices for Java Applications
1. JVM Optimization in Kubernetes
# k8s/base/jvm-optimization.yml #@ load("@ytt:overlay", "overlay") #@ load("@ytt:data", "data") #@ def jvm_optimization(): #@overlay/match by=overlay.subset({"kind": "Deployment"}) --- spec: template: spec: containers: #@overlay/match by=overlay.subset({"name": "java-app"}) - name: java-app env: - name: JAVA_TOOL_OPTIONS value: #@ | -XX:+UseContainerSupport -XX:MaxRAMPercentage=75.0 -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -Xlog:gc*:file=/tmp/gc.log:time,uptime,level,tags:filecount=5,filesize=10m -Djava.security.egd=file:/dev/./urandom -Dspring.profiles.active=#@ data.values.environment - name: SPRING_PROFILES_ACTIVE value: #@ data.values.environment #@ end --- #@ jvm_optimization() 2. Security Hardening
# k8s/base/security.yml #@ load("@ytt:overlay", "overlay") #@ def security_hardening(): #@overlay/match by=overlay.subset({"kind": "Deployment"}) --- spec: template: spec: securityContext: runAsNonRoot: true runAsUser: 1000 runAsGroup: 1000 fsGroup: 1000 containers: #@overlay/match by=overlay.subset({"name": "java-app"}) - name: java-app securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: true runAsNonRoot: true runAsUser: 1000 volumeMounts: - name: tmp mountPath: /tmp - name: logs mountPath: /app/logs volumes: - name: tmp emptyDir: {} - name: logs emptyDir: {} #@ end --- #@ security_hardening() 3. Database Migration Job
# k8s/base/migration.yml #@ load("@ytt:data", "data") #@ if data.values.run_migrations: apiVersion: batch/v1 kind: Job metadata: name: java-app-migration labels: app: java-app component: migration spec: template: metadata: labels: app: java-app component: migration spec: containers: - name: migration image: #@ data.values.image command: ["java", "-jar", "/app/app.jar", "--spring.profiles.active=migration"] env: - name: SPRING_PROFILES_ACTIVE value: "migration" - name: SPRING_DATASOURCE_URL value: #@ data.values.database.url - name: SPRING_DATASOURCE_USERNAME value: #@ data.values.database.username - name: SPRING_DATASOURCE_PASSWORD valueFrom: secretKeyRef: name: java-app-secrets key: database.password resources: requests: memory: "512Mi" cpu: "250m" limits: memory: "1Gi" cpu: "500m" restartPolicy: Never backoffLimit: 2 #@ end Troubleshooting and Debugging
1. Debug Scripts
#!/bin/bash # carvel-debug.sh APP_NAME="java-carvel-app" ENVIRONMENT="${1:-development}" echo "=== Debugging $APP_NAME in $ENVIRONMENT ===" echo "1. Application Status" kapp inspect -a ${APP_NAME}-${ENVIRONMENT} echo -e "\n2. Pod Status" kubectl get pods -n ${APP_NAME}-${ENVIRONMENT} echo -e "\n3. Recent Events" kubectl get events -n ${APP_NAME}-${ENVIRONMENT} --sort-by=.lastTimestamp | tail -10 echo -e "\n4. Application Logs" kubectl logs -l app=${APP_NAME} -n ${APP_NAME}-${ENVIRONMENT} --tail=50 echo -e "\n5. Resource Usage" kubectl top pods -n ${APP_NAME}-${ENVIRONMENT} 2>/dev/null || echo "Metrics not available" echo -e "\n6. Configuration" kubectl get configmap java-app-config -n ${APP_NAME}-${ENVIRONMENT} -o yaml 2. Validation Script
#!/bin/bash # carvel-validate.sh echo "=== Validating Carvel Configuration ===" # Validate ytt templates echo "1. Validating ytt templates..." ytt -f k8s/base -f k8s/values/defaults.yml > /dev/null echo "✓ ytt templates are valid" # Validate Kubernetes manifests echo "2. Validating Kubernetes manifests..." ytt -f k8s/base -f k8s/values/defaults.yml | kubectl apply --dry-run=client -f - echo "✓ Kubernetes manifests are valid" # Check for required values echo "3. Checking required configurations..." if [ -z "$IMAGE_REPO" ]; then echo "✗ IMAGE_REPO is not set" exit 1 fi echo "✓ Required configurations are set" echo "Validation completed successfully!"
Migration from Traditional Tools
1. Migration from Helm
# Convert Helm values to ytt values helm template my-app ./chart --values values.yaml --dry-run > helm-output.yaml # Create equivalent ytt structure mkdir -p k8s/{base,overlays,values} # Manually convert Helm templates to ytt templates 2. Migration from Kustomize
# Kustomize patches can be converted to ytt overlays # kustomization.yaml patches become ytt overlay files
Conclusion
Carvel provides Java applications with:
- Reliable Templating: Type-safe YAML templating with ytt
- Image Management: Deterministic image resolution with kbld
- Safe Deployments: Atomic application deployment with kapp
- Configuration Packaging: Immutable configuration bundles with imgpkg
- GitOps Ready: Composable tools that work well with GitOps workflows
By implementing Carvel tooling for Java applications, you achieve:
- Reproducible builds across environments
- Safe, atomic deployments with rollback capabilities
- Configuration as code with proper templating
- Better separation of concerns between dev and ops
- Superior Kubernetes experience compared to traditional tools
The combination of Carvel's composable tools with Java's robust ecosystem creates a powerful platform for modern cloud-native application deployment and management.
Pyroscope Profiling in Java
Explains how to use Pyroscope for continuous profiling in Java applications, helping developers analyze CPU and memory usage patterns to improve performance and identify bottlenecks.
https://macronepal.com/blog/pyroscope-profiling-in-java/
OpenTelemetry Metrics in Java: Comprehensive Guide
Provides a complete guide to collecting and exporting metrics in Java using OpenTelemetry, including counters, histograms, gauges, and integration with monitoring tools. (MACRO NEPAL)
https://macronepal.com/blog/opentelemetry-metrics-in-java-comprehensive-guide/
OTLP Exporter in Java: Complete Guide for OpenTelemetry
Explains how to configure OTLP exporters in Java to send telemetry data such as traces, metrics, and logs to monitoring systems using HTTP or gRPC protocols. (MACRO NEPAL)
https://macronepal.com/blog/otlp-exporter-in-java-complete-guide-for-opentelemetry/
Thanos Integration in Java: Global View of Metrics
Explains how to integrate Thanos with Java monitoring systems to create a scalable global metrics view across multiple Prometheus instances.
https://macronepal.com/blog/thanos-integration-in-java-global-view-of-metrics
Time Series with InfluxDB in Java: Complete Guide (Version 2)
Explains how to manage time-series data using InfluxDB in Java applications, including storing, querying, and analyzing metrics data.
https://macronepal.com/blog/time-series-with-influxdb-in-java-complete-guide-2
Time Series with InfluxDB in Java: Complete Guide
Provides an overview of integrating InfluxDB with Java for time-series data handling, including monitoring applications and managing performance metrics.
https://macronepal.com/blog/time-series-with-influxdb-in-java-complete-guide
Implementing Prometheus Remote Write in Java (Version 2)
Explains how to configure Java applications to send metrics data to Prometheus-compatible systems using the remote write feature for scalable monitoring.
https://macronepal.com/blog/implementing-prometheus-remote-write-in-java-a-complete-guide-2
Implementing Prometheus Remote Write in Java: Complete Guide
Provides instructions for sending metrics from Java services to Prometheus servers, enabling centralized monitoring and real-time analytics.
https://macronepal.com/blog/implementing-prometheus-remote-write-in-java-a-complete-guide
Building a TileServer GL in Java: Vector and Raster Tile Server
Explains how to build a TileServer GL in Java for serving vector and raster map tiles, useful for geographic visualization and mapping applications.
https://macronepal.com/blog/building-a-tileserver-gl-in-java-vector-and-raster-tile-server
Indoor Mapping in Java
Explains how to create indoor mapping systems in Java, including navigation inside buildings, spatial data handling, and visualization techniques.
Pyroscope Profiling in Java
Explains how to use Pyroscope for continuous profiling in Java applications, helping developers analyze CPU and memory usage patterns to improve performance and identify bottlenecks.
https://macronepal.com/blog/pyroscope-profiling-in-java/
OpenTelemetry Metrics in Java: Comprehensive Guide
Provides a complete guide to collecting and exporting metrics in Java using OpenTelemetry, including counters, histograms, gauges, and integration with monitoring tools. (MACRO NEPAL)
https://macronepal.com/blog/opentelemetry-metrics-in-java-comprehensive-guide/
OTLP Exporter in Java: Complete Guide for OpenTelemetry
Explains how to configure OTLP exporters in Java to send telemetry data such as traces, metrics, and logs to monitoring systems using HTTP or gRPC protocols. (MACRO NEPAL)
https://macronepal.com/blog/otlp-exporter-in-java-complete-guide-for-opentelemetry/
Thanos Integration in Java: Global View of Metrics
Explains how to integrate Thanos with Java monitoring systems to create a scalable global metrics view across multiple Prometheus instances.
https://macronepal.com/blog/thanos-integration-in-java-global-view-of-metrics
Time Series with InfluxDB in Java: Complete Guide (Version 2)
Explains how to manage time-series data using InfluxDB in Java applications, including storing, querying, and analyzing metrics data.
https://macronepal.com/blog/time-series-with-influxdb-in-java-complete-guide-2
Time Series with InfluxDB in Java: Complete Guide
Provides an overview of integrating InfluxDB with Java for time-series data handling, including monitoring applications and managing performance metrics.
https://macronepal.com/blog/time-series-with-influxdb-in-java-complete-guide
Implementing Prometheus Remote Write in Java (Version 2)
Explains how to configure Java applications to send metrics data to Prometheus-compatible systems using the remote write feature for scalable monitoring.
https://macronepal.com/blog/implementing-prometheus-remote-write-in-java-a-complete-guide-2
Implementing Prometheus Remote Write in Java: Complete Guide
Provides instructions for sending metrics from Java services to Prometheus servers, enabling centralized monitoring and real-time analytics.
https://macronepal.com/blog/implementing-prometheus-remote-write-in-java-a-complete-guide
Building a TileServer GL in Java: Vector and Raster Tile Server
Explains how to build a TileServer GL in Java for serving vector and raster map tiles, useful for geographic visualization and mapping applications.
https://macronepal.com/blog/building-a-tileserver-gl-in-java-vector-and-raster-tile-server
Indoor Mapping in Java
Explains how to create indoor mapping systems in Java, including navigation inside buildings, spatial data handling, and visualization techniques.