Hello, I'm trying to go middlemanager-less in k8s...
# troubleshooting
l
Hello, I'm trying to go middlemanager-less in k8s with Druid v34 but I'm having issues with Peon startup the job fails with:
Copy code
2026-04-16T15:13:13,086 INFO [main] org.apache.druid.cli.CliPeon - Task file not found, trying to pull task payload from deep storage
Exception in thread "main" java.lang.RuntimeException: java.lang.RuntimeException: com.google.inject.CreationException: Unable to create injector, see the following errors:

1) [Guice/ErrorInCustomProvider]: IllegalStateException: Optional.get() cannot be called on an absent value
  at CliPeon$1.readTask(CliPeon.java:314)
      \_ installed by: Modules$OverrideModule -> Modules$OverrideModule -> CliPeon$1
  at CliPeon$1.getBroadcastDatasourcesToLoad(CliPeon.java:356)
      \_ for 1st parameter
  at CliPeon$1.getBroadcastDatasourcesToLoad(CliPeon.java:356)
      \_ installed by: Modules$OverrideModule -> Modules$OverrideModule -> CliPeon$1
  at DataSourceTaskIdHolder.broadcastDatasourceLoadingSpec(DataSourceTaskIdHolder.java:45)
      \_ for field broadcastDatasourceLoadingSpec
  at MetricsModule.configure(MetricsModule.java:94)
      \_ installed by: Modules$OverrideModule -> Modules$OverrideModule -> MetricsModule
  while locating DataSourceTaskIdHolder
  at MetricsModule.getMonitorScheduler(MetricsModule.java:114)
      \_ installed by: Modules$OverrideModule -> Modules$OverrideModule -> MetricsModule
  while locating MonitorScheduler
  at MetricsModule.configure(MetricsModule.java:99)
      \_ installed by: Modules$OverrideModule -> Modules$OverrideModule -> MetricsModule
  while locating MonitorScheduler annotated with @Named("ForTheEagerness")

Learn more:
  <https://github.com/google/guice/wiki/ERROR_IN_CUSTOM_PROVIDER>

1 error

======================
Full classname legend:
======================
CliPeon$1:              "org.apache.druid.cli.CliPeon$1"
DataSourceTaskIdHolder: "org.apache.druid.server.metrics.DataSourceTaskIdHolder"
MetricsModule:          "org.apache.druid.server.metrics.MetricsModule"
Modules$OverrideModule: "com.google.inject.util.Modules$OverrideModule"
MonitorScheduler:       "org.apache.druid.java.util.metrics.MonitorScheduler"
Named:                  "com.google.inject.name.Named"
========================
End of classname legend:
========================
This is task pod template:
Copy code
apiVersion: v1
kind: ConfigMap
metadata:
  name: druid-analytics-task-template-default
  namespace: druid
data:
  pod_template.yaml: |-
    apiVersion: v1
    kind: PodTemplate
    metadata:
      name: druid-task-default
      labels:
        app: druid
        component: task
        druid_cr: analytics
        task-tmpl: default
    template:
      spec:
        serviceAccountName: druid-analytics-overlord
        restartPolicy: Never
        securityContext:
          fsGroup: 1000
          runAsGroup: 1000
          runAsUser: 1000

        containers:
          - name: main
            image: redacted
            imagePullPolicy: IfNotPresent
            command:
              - sh
              - -c
            args:
              - |
                /peon.sh /druid/data 1
            env:
              - name: POD_NAME
                valueFrom:
                  fieldRef:
                    apiVersion: v1
                    fieldPath: metadata.name
              - name: POD_NAMESPACE
                valueFrom:
                  fieldRef:
                    apiVersion: v1
                    fieldPath: metadata.namespace
              - name: AWS_JAVA_V1_DISABLE_DEPRECATION_ANNOUNCEMENT
                value: "true"
            envFrom:
              - secretRef:
                  name: druid-credentials
              - secretRef:
                  name: druid-kafka-credentials
              - secretRef:
                  name: druid-s3-credentials

            ports:
              - containerPort: 8100
                name: druid-port
                protocol: TCP

            resources:
              limits:
                cpu: 2000m
                memory: 5Gi
              requests:
                cpu: 2000m
                memory: 5Gi

            volumeMounts:
              - name: common-config-volume
                mountPath: /opt/druid/conf/druid/cluster/_common
                readOnly: true
              - name: task-peon-config-volume
                mountPath: /opt/druid/conf/druid/cluster/master/coordinator-overlord
                readOnly: true
              - name: var-volume
                mountPath: /opt/druid/var
              - name: data-volume
                mountPath: /druid/data


        volumes:
          # configmaps
          - name: common-config-volume
            configMap:
              name: analytics-druid-common-config
              defaultMode: 420
          - name: task-peon-config-volume
            configMap:
              defaultMode: 420
              name: druid-analytics-task-template-default
          # storage
          - name: var-volume
            emptyDir: {}
          - name: data-volume
            emptyDir: {}

        affinity:
          nodeAffinity:
            requiredDuringSchedulingIgnoredDuringExecution:
              nodeSelectorTerms:
                - matchExpressions:
                    - key: node-type
                      operator: In
                      values:
                        - druid-data-mm
        tolerations:
          - key: druid
            value: data-mm
            operator: Equal
            effect: NoSchedule

        topologySpreadConstraints:
          - topologyKey: "<http://topology.kubernetes.io/zone|topology.kubernetes.io/zone>"
            maxSkew: 1
            whenUnsatisfiable: ScheduleAnyway
            labelSelector:
              matchLabels:
                app: druid
                component: task
                druid_cr: analytics


  jvm.config: |-
    -server
    -Xms1600M
    -Xmx1600M
    -XX:MaxDirectMemorySize=3G
    -Duser.timezone=UTC
    -Dfile.encoding=UTF-8
    -Djava.io.tmpdir=/opt/druid/var/tmp/
    -Djava.util.logging.manager=org.apache.logging.log4j.jul.LogManager
    -Dorg.jboss.logging.provider=slf4j
    -Dnet.spy.log.LoggerImpl=net.spy.memcached.compat.log.SLF4JLogger
    -Dlog4j.shutdownCallbackRegistry=org.apache.druid.common.config.Log4jShutdown
    -Dlog4j.shutdownHookEnabled=true
    -XX:+ExitOnOutOfMemoryError
    -XX:+UseG1GC
    --add-exports=java.base/jdk.internal.ref=ALL-UNNAMED
    --add-exports=java.base/jdk.internal.misc=ALL-UNNAMED
    --add-opens=java.base/java.lang=ALL-UNNAMED
    --add-opens=java.base/java.io=ALL-UNNAMED
    --add-opens=java.base/java.nio=ALL-UNNAMED
    --add-opens=java.base/jdk.internal.ref=ALL-UNNAMED
    --add-opens=java.base/sun.nio.ch=ALL-UNNAMED


  runtime.properties: |

      druid.service=druid/peon
      druid.port=8100
      druid.plaintextPort=8100

      # Extensions

      druid.extensions.loadList=["druid-basic-security", "druid-datasketches", "druid-distinctcount", "druid-kafka-indexing-service", "druid-kubernetes-overlord-extensions", "druid-lookups-cached-global", "druid-multi-stage-query", "druid-parquet-extensions", "druid-protobuf-extensions", "druid-s3-extensions", "postgresql-metadata-storage", "statsd-emitter"]

      druid.peon.mode=remote
      druid.indexer.runner.type=k8s
      druid.indexer.task.encapsulatedTask=true
      druid.processing.intermediaryData.storage.type=deepstore

      # <https://druid.apache.org/docs/latest/configuration/index.html#middlemanager-configuration>
      druid.indexer.task.baseTaskDir=/druid/data

      # HTTP server
      # <https://druid.apache.org/docs/latest/configuration/index.html#indexer-concurrent-requests>
      # Sum of `druid.broker.http.numConnections` across all the brokers in the cluster
      druid.server.http.numThreads=130

      # Processing threads and buffers
      druid.processing.numThreads=2
      druid.processing.numMergeBuffers=2
      druid.processing.buffer.sizeBytes=200MiB

      # Monitoring
      druid.emitter=statsd
      druid.emitter.statsd.hostname=otel-collector.otel-collector.svc.cluster.local
      druid.emitter.statsd.port=8125
      druid.emitter.statsd.dimensionMapPath=/opt/druid/conf/druid/cluster/_common/metricsMappingStatsD.json
      druid.emitter.statsd.includeHost=true
      druid.emitter.statsd.dogstatsd=true
      druid.emitter.statsd.dogstatsdServiceAsTag=true

      # Query processing
      druid.processing.tmpDir=/druid/data/tmp/queries

      #<https://druid.apache.org/docs/latest/configuration/#peon-caching>
      druid.realtime.cache.useCache=true

      # Query Performance
      # Default timeout (120 seconds) can be overridden at query context
      druid.server.http.defaultQueryTimeout=120000
      # GroupBy merging buffer per-query spilling to disk (2GB)
      druid.query.groupBy.maxOnDiskStorage=2000000000

  log4j2.xml: |-
    <?xml version="1.0" encoding="UTF-8" ?>
    <Configuration status="WARN">
      <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
          <PatternLayout pattern="%d{ISO8601} %p [%t] %c -%notEmpty{ [%markerSimpleName]} %m%n"/>
        </Console>
      </Appenders>

    <Loggers>
        <!-- AsyncLogger instead of Logger -->
        <AsyncLogger name="org.apache.druid.curator.inventory.CuratorInventoryManager" level="debug" additivity="false">
          <AppenderRef ref="Console"/>
        </AsyncLogger>
        <AsyncLogger name="org.apache.druid.client.BatchServerInventoryView" level="debug" additivity="false">
          <AppenderRef ref="Console"/>
        </AsyncLogger>
        <!-- Make extra sure nobody adds logs in a bad way that can hurt performance -->
        <AsyncLogger name="org.apache.druid.client.ServerInventoryView" level="debug" additivity="false">
          <AppenderRef ref="Console"/>
        </AsyncLogger>
        <AsyncLogger name ="org.apache.druid.java.util.http.client.pool.ChannelResourceFactory" level="info" additivity="false">
          <AppenderRef ref="Console"/>
        </AsyncLogger>
        <AsyncLogger name="org.apache.druid.jetty.RequestLog" additivity="false" level="info">
          <AppenderRef ref="Console"/>
        </AsyncLogger>
        <Root level="info">
          <AppenderRef ref="Console"/>
        </Root>
      </Loggers>
    </Configuration>