<p>I'm writing up a deployment for graylog 5.1, however the problem I'm running into is that graylog needs to write into its graylog.conf and log4j2.xml and I'm pulling those from a config map that I've created.</p>
<p>The problem is they are always created as read-only and graylog cannot write into them, I read that it can be solved by create an initContainer that fix this by copying configMap into an emptyDir and then mounting that dir into the container's path: /usr/share/graylog/data/config. But for the life of me I cannot figure out how to do this.</p>
<p>Here's an example of the graylog-deployment.yaml:</p>
<pre><code>---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: graylog
spec:
  replicas: 1
  selector:
    matchLabels:
      app: graylog
  template:
    metadata:
      labels:
        app: graylog
    spec:
      volumes:
      - name: graylog-config
        configMap:
            name: graylog-config
      initContainers:
      - name: copy-config-files
        image: alpine
        command: [&quot;/bin/sh&quot;, &quot;-c&quot;]
        args:
        - |
          mkdir -p /tmp/config
          cp /usr/share/graylog/data/config/* /tmp/config/
          chmod -R 0775 /tmp/config/
        volumeMounts:
        - name: graylog-config
          mountPath: /tmp/config
      containers:
      - name: graylog
        image: graylog/graylog:5.1
        ports:
        - containerPort: 9000
        - containerPort: 1514
        - containerPort: 12201
        resources:
          requests:
            memory: &quot;512Mi&quot;  # Set the minimum memory required
            cpu: &quot;250m&quot;      # Set the minimum CPU required
          limits:
            memory: &quot;1Gi&quot;    # Set the maximum memory allowed
            cpu: &quot;1&quot;         # Set the maximum CPU allowed
        env:
        - name: GRAYLOG_MONGODB_URI
          value: &quot;mongodb://mongodb:27017/graylog&quot;
        - name: GRAYLOG_ELASTICSEARCH_HOSTS
          value: &quot;http://elasticsearch:9200&quot;
        - name: GRAYLOG_ROOT_PASSWORD_SHA2 #admin pass
          value: ****
        volumeMounts:
        - name: graylog-claim
          mountPath: /usr/share/graylog/data
        - name: graylog-config
          mountPath: /usr/share/graylog/data/config
  volumeClaimTemplates:
  - metadata:
      name: graylog-claim
    spec:
      accessModes: [ &quot;ReadWriteOnce&quot; ]
      storageClassName: microk8s-hostpath
      resources:
        requests:
          storage: 2Gi
</code></pre>
<p>However, this does not work, initContainer never finishes and I get an ouput saying that it's a read-only. I have tried many different approaches and I cannot seem to get it right.</p>
<p>Any help is greatly appreciated, I'm at a loss here.</p>
<p>I tried using emptyDir: {} approach but still the same result.
I have tried with chmoding but that also doesn't work since it's a read-only files that are created: log4j2.xml and graylog.conf:</p>
<pre><code>apiVersion: v1
kind: ConfigMap
metadata:
  name: graylog-config
data:
  log4j2.xml: |-
    &lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
    &lt;Configuration packages=&quot;org.graylog2.log4j&quot; shutdownHook=&quot;disable&quot;&gt;
        &lt;Appenders&gt;
            &lt;Console name=&quot;STDOUT&quot; target=&quot;SYSTEM_OUT&quot;&gt;
                &lt;PatternLayout pattern=&quot;%d %-5p: %c - %m%n&quot;/&gt;
            &lt;/Console&gt;

            &lt;!-- Internal Graylog log appender. Please do not disable. This makes internal log messages available via REST calls. --&gt;
            &lt;Memory name=&quot;graylog-internal-logs&quot; bufferSize=&quot;500&quot;/&gt;
        &lt;/Appenders&gt;
        &lt;Loggers&gt;
            &lt;!-- Application Loggers --&gt;
            &lt;Logger name=&quot;org.graylog2&quot; level=&quot;info&quot;/&gt;
            &lt;Logger name=&quot;com.github.joschi.jadconfig&quot; level=&quot;warn&quot;/&gt;
            &lt;!-- Prevent DEBUG message about Lucene Expressions not found. --&gt;
            &lt;Logger name=&quot;org.elasticsearch.script&quot; level=&quot;warn&quot;/&gt;
            &lt;!-- Disable messages from the version check --&gt;
            &lt;Logger name=&quot;org.graylog2.periodical.VersionCheckThread&quot; level=&quot;off&quot;/&gt;
            &lt;!-- Silence chatty natty --&gt;
            &lt;Logger name=&quot;com.joestelmach.natty.Parser&quot; level=&quot;warn&quot;/&gt;
            &lt;!-- Silence Kafka log chatter --&gt;
            &lt;Logger name=&quot;org.graylog.shaded.kafka09.log.Log&quot; level=&quot;warn&quot;/&gt;
            &lt;Logger name=&quot;org.graylog.shaded.kafka09.log.OffsetIndex&quot; level=&quot;warn&quot;/&gt;
            &lt;Logger name=&quot;org.apache.kafka.clients.consumer.ConsumerConfig&quot; level=&quot;warn&quot;/&gt;
            &lt;!-- Silence useless session validation messages --&gt;
            &lt;Logger name=&quot;org.apache.shiro.session.mgt.AbstractValidatingSessionManager&quot; level=&quot;warn&quot;/&gt;
            &lt;!-- Silence Azure SDK messages --&gt;
            &lt;Logger name=&quot;com.azure&quot; level=&quot;warn&quot;/&gt;
            &lt;Logger name=&quot;reactor.core.publisher.Operators&quot; level=&quot;off&quot;/&gt;
            &lt;Logger name=&quot;com.azure.messaging.eventhubs.PartitionPumpManager&quot; level=&quot;off&quot;/&gt;
            &lt;Logger name=&quot;com.azure.core.amqp.implementation.ReactorReceiver&quot; level=&quot;off&quot;/&gt;
            &lt;Logger name=&quot;com.azure.core.amqp.implementation.ReactorDispatcher&quot; level=&quot;off&quot;/&gt;
            &lt;Root level=&quot;warn&quot;&gt;
                &lt;AppenderRef ref=&quot;STDOUT&quot;/&gt;
                &lt;AppenderRef ref=&quot;graylog-internal-logs&quot;/&gt;
            &lt;/Root&gt;
        &lt;/Loggers&gt;
    &lt;/Configuration&gt;
  graylog.conf: |-
    ############################
    # GRAYLOG CONFIGURATION FILE
    ############################
    is_master = true
    node_id_file = /usr/share/graylog/data/config/node-id
    password_secret = hs1hvm7Wi7GaChG5iDsHkvYlOnkayN4YBFeFhMosBgLNwCztbKRIZfcWA4zgx6RL9JF3I5v0mRJMNOYmF9vvuo30G2vuwAYW
    root_password_sha2 = 8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918
    bin_dir = /usr/share/graylog/bin
    data_dir = /usr/share/graylog/data
    plugin_dir = /usr/share/graylog/plugin
    http_bind_address = 0.0.0.0:9000
    elasticsearch_hosts = http://elasticsearch:9200
    rotation_strategy = count
    elasticsearch_max_docs_per_index = 20000000
    elasticsearch_max_number_of_indices = 20
    retention_strategy = delete
    elasticsearch_shards = 4
    elasticsearch_replicas = 0
    elasticsearch_index_prefix = graylog
    allow_leading_wildcard_searches = false
    allow_highlighting = false
    elasticsearch_analyzer = standard
    output_batch_size = 500
    output_flush_interval = 1
    output_fault_count_threshold = 5
    output_fault_penalty_seconds = 30
    processbuffer_processors = 5
    outputbuffer_processors = 3
    processor_wait_strategy = blocking
    ring_size = 65536
    inputbuffer_ring_size = 65536
    inputbuffer_processors = 2
    inputbuffer_wait_strategy = blocking
    message_journal_enabled = true
    message_journal_dir = data/journal
    lb_recognition_period_seconds = 3
    mongodb_uri = mongodb://mongo/graylog
    mongodb_max_connections = 1000
    mongodb_threads_allowed_to_block_multiplier = 5
    proxied_requests_thread_pool_size = 32
</code></pre>

Shdow89
<p>I think you forgot to mount the <code>emptyDir</code> as your final directory.</p>
<p>I use the following steps as shown in the below excerpt:</p>
<ol>
<li>Create a <code>emptyDir</code> volume (e.g., <code>final-dir</code>)</li>
<li>Add it as <code>volumeMount</code> to both your <code>initContainer</code> (e.g., mounted to <code>/dest</code>) and your <code>container</code>(e.g., mounted to <code>/some/path/your_file</code>)</li>
<li>Add a <code>volume</code> for your <code>configMap</code> and mount it in your <code>initContainer</code> (e.g., mounted to <code>/src</code>)</li>
<li>Execute the <code>cp</code> command in your <code>initContainer</code> (e.g., <code>/src/your_file /dest/your_file</code>)</li>
</ol>
<p>Hope this helps.</p>
<pre class="lang-yaml prettyprint-override"><code>---
apiVersion: apps/v1
kind: Deployment
metadata:
  ..
spec:
  ...
  template:
    ...
    spec:
      initContainers:
        - name: copy-configmap
          image: alpine
          command: ['sh', '-c', 'cp /src/your_file /dest/your_file']
          volumeMounts:
            - name: temp-dir
              mountPath: /src
            - name: final-dir
              mountPath: /dest
      containers:
      - name: your-container-name 
        ...
        volumeMounts:
          - name: final-dir
            mountPath: /some/path/your_file
            subPath: your_file
      volumes:
        - name: final-dir
          emptyDir: {}
        - name: temp-dir
          configMap:
            name: your-configMap-name
...
</code></pre>
