Replacing a properties file within a kubernetes container

Viewed 930

While spinning a Nifi cluster on Azure Kubernetes Service, I faced issue while mounting the nifi.properties file on using configMap. While using the following configuration for mounting a file, I am getting the following error.

sed: can't move '/opt/nifi/conf/nifi.propertiesnCjDfm' to '/opt/nifi/conf/nifi.properties': Resource busy

This error seems to be happening due to the nifi instance already utilizing the file before kubernetes had a chance to replace it.

I am looking for an alternative or a better way to configure nifi cluster and managing its configuration. Currently I was attempting to use ConfigMap to store the nifi.properties or any other files necessary.

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: nifi
  namespace: nifi-ns
  ...
spec:
  template:
    spec:
      containers:
      - name: nifi
        image: xemuliam/nifi:1.9.1
        ...
        volumeMounts:
        ...
        - mountPath: /opt/nifi/conf/nifi.properties
          subPath: nifi.properties
          name: file
      volumes:
      - name: file
        configMap:
            name: nifi-properties-cm
            items:
            - key: nifi.properties
              path: nifi.properties

Following is my configMap:

apiVersion: v1
kind: ConfigMap
metadata:
  name: nifi-properties-cm
  namespace: nifi-ns
data:
  nifi.properties: |
    # Core Properties #
    nifi.flow.configuration.file=./conf/flow.xml.gz
    ...

I've tried mounting the file like above also tried to mount the entire conf folder (I donot like this way as the only configuration I will really wanna change is the nifi.properties)

I know I could always customize the image and give a custom entrypoint to achieve the same effect but I'd like to try and solve the problem using kubernetes alone. Is there any other way I can solve this? Is there any suggested best practice or best way of solving this problem?

UPDATE:

Based on the comments provided below, I've tried creating an init container and copying a file to a shared volume but that does not help as it overwrites the folder within container and makes the pod fail.

Here is the config used:

apiVersion: v1
kind: Pod
metadata:
  name: test
  labels:
    name: test
spec:
  initContainers:
  - name: busybox
    image: busybox
    command: ["/bin/sh", "-c", "cp /usr/nifi.properties /opt/nifi/conf/nifi.properties"]
    volumeMounts:
    - mountPath: /usr/nifi.properties
      name: file
      subPath: nifi.properties
    - mountPath: /opt/nifi/conf
      name: config
  containers:
  - name: test
    image: xemuliam/nifi:1.9.1
    resources:
      limits:
        memory: "128Mi"
        cpu: "500m"
    ports:
    - containerPort: 80
    volumeMounts:
      - mountPath: /opt/nifi/conf
        name: config
  volumes:
  - name: file
    configMap:
        name: nifi-properties-cm
  - name: config
    emptyDir: {}

Here is the application logs I receive:

Exception in thread "main" java.io.FileNotFoundException: /opt/nifi/conf/bootstrap.conf (No such file or directory)
    at java.io.FileInputStream.open0(Native Method)
    at java.io.FileInputStream.open(FileInputStream.java:195)
    at java.io.FileInputStream.<init>(FileInputStream.java:138)
    at org.apache.nifi.bootstrap.RunNiFi.loadServices(RunNiFi.java:267)
    at org.apache.nifi.bootstrap.RunNiFi.<init>(RunNiFi.java:152)
    at org.apache.nifi.bootstrap.RunNiFi.main(RunNiFi.java:212)
1 Answers

You can use the configmap with nifi.properties as initual value and copy this file into your filesystem. Use an init container in your pod you can copy it, something like the example below

initContainers:
- name: copy
 image: busybox:1.28
 command: ["/bin/sh", "-c", "cp /config/configmap/nifi.properties /config/local/"]
 volumeMounts:
 - name: configmap
   mountPath: /config/configmap/
 - name: local
   mountPath: /config/local/
      

Then your nifi pod can use copied file

Related