How to pass arguments in kubernetes to start a rq-worker container

9/22/2021

I'm working on a microservice architectural project in which I use rq-workers. I have used docker-compose file to start and connect the rq-worker with redis successfully but I'm not sure how to replicate it in kubernetes. No matter whatever I try with command and args, I'm thrown a status of Crashloopbackoff. Please guide me as to what I'm missing.Below are my docker-compose and rq-worker deployment files.

rq-worker and redis container config:

...
  rq-worker:
    build: ./simba-app
    command: rq worker --url redis://redis:6379 queue
    depends_on:
      - redis
    volumes:
    - sharedvolume:/simba-app/app/docs

  redis:
    image: redis:4.0.6-alpine
    ports:
      - "6379:6379"
    volumes:
      - ./redis:/data
...

rq-worker.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: rq-worker
  labels:
    app: rq-worker
spec:
  selector:
    matchLabels:
      app: rq-worker
  template:
    metadata:
      labels:
        app: rq-worker
    spec:
      containers:
      - name: rq-worker
        image: some-image
        command: ["/bin/sh", "-c"]
        #command: ["rqworker", "--url", "redis://redis:6379", "queue"]
        args:
          - rqworker
          - --url
          - redis://redis:6379
          - queue   
      imagePullSecrets:
      - name: regcred
---

Thanks in advance!

Edit: I checked the logs using kubectl logs <pod-name> and found the following logs:

Error 99 connecting to localhost:6379. Cannot assign requested address.

First of all, I'm using the 'service name' and not 'localhost' in my code to connect rq and redis. No idea why I'm seeing 'localhost' in my logs. (Note: The kubernetes service name for redis is same as that used in my docker-compose file)

redis-deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis
  labels:
    app: redis
spec:
  selector:
    matchLabels:
      app: redis
  template:
    metadata:
      labels:
        app: redis
    spec:
      containers:
      - name: redis
        image: redis:4.0.6-alpine
        ports:
        - containerPort: 6379
---

apiVersion: v1
kind: Service
metadata:
  name: redis
spec:
  type: ClusterIP
  selector:
    app: redis
  ports:
   - port: 6379
     targetPort: 6379
-- Arsh
docker
kubernetes

1 Answer

9/22/2021

You do not need the /bin/sh -c wrapper here. Your setup reads the first args: word, rqworker, and parses it as a shell command, and executes it; the remaining words are lost.

The most straightforward thing to do is to make your command, split into words as-is, as the Kubernetes command:

      containers:
      - name: rq-worker
        image: some-image
        command:
          - rqworker
          - --url
          - redis://redis:6379
          - queue   

(This matches the commented-out string in your example.)

A common Docker pattern is to use an ENTRYPOINT to do first-time setup and to make CMD be a complete shell command that's run at the end of the setup script. In Kubernetes, command: overrides Docker ENTRYPOINT; if your image has this pattern, then you need to not use a command:, but instead to put this command as you have it as args:.

The only time you do need an sh -c wrapper is in unusual cases where you need to run multiple commands, expand environment variables, or otherwise use shell-only features. In this case the command itself must be in a single word in the command: or args:.

command:
  - /bin/sh
  - -c
  - rqworker --url redis://redis:6379 queue
-- David Maze
Source: StackOverflow