How can I run a cron command with environmental variables set by kubernetes secret

12/20/2016

I'm using kubernetes secret as my environment variable (http://kubernetes.io/docs/user-guide/secrets/#using-secrets-as-environment-variables).

I've check whether env vars set correctly by

kubectl exec -it my_pod bash

1.

echo $RAILS_ENV #=> staging

2.

bin/rails c;
puts ENV['RAILS_ENV'] #=> staging

It works fine for my rails application and bash command, but doesn't work when executing cron process.

I've read some post to understand cron process (e.g. https://unix.stackexchange.com/questions/27289/how-can-i-run-a-cron-command-with-existing-environmental-variables) and know that I should source .profile or .bashrc before executing cron command like.

$ crontab -l

* * * * * . $HOME/.profile; /bin/bash -l -c 'echo rails_env=$RAILS_ENV >> /tmp/cron_test.log'

* * * * * . $HOME/.bashrc; /bin/bash -l -c 'echo rails_env=$RAILS_ENV >> /tmp/cron_test.log'

but both doesn't work for me ˊˋ

result

rails_env=

Any help will be appreciated!

\===

[update: add kubernetes yaml config]

Both environment variables assign by kubernetes config and kubernetes secret can read in bash and rails application, but doesn't work in cron process.

deployment.yaml

spec:
  containers:
  - name: my_rails
  ...
    command:
    - bash
    args:
    - /tmp/run_cron.sh
  ...
    env:
      - name: RAILS_ENV
        value: staging
      - name: MYSQL_PASSWORD
        valueFrom:
          secretKeyRef:
            name: rails-secret
            key: MYSQL_PASSWORD

secret.yaml

apiVersion: v1
kind: Secret
metadata:
  name: rails-secret
type: Opaque
data:
  MYSQL_PASSWORD: ENCODED_PASSWORD
-- gaga5lala
bash
cron
debian
kubernetes
ruby-on-rails

2 Answers

12/20/2016

Instead of running cron scripts inside the container, you should probably use CronJobs, where you can set env vars from secrets in the same way you do for deployments.

-- Amanpreet Singh
Source: StackOverflow

12/21/2016

I found the solution after discussion with some guys.

The problem should be docker level not kubernetes level. https://ypereirareis.github.io/blog/2016/02/29/docker-crontab-environment-variables/

Cron process doesn't run as normal login-shell, so it didn't act as our expectation for read environment variables set by docker/k8s.

To solve the problem, we have to make cron process read environment variables first.

STEP1.

Add one line to dump environment variables at run_cron.sh

#!/bin/bash

# dump environment variables
printenv | sed 's/^\(.*\)$/export \1/g' >> /etc/profile.d/rails_env.sh

cron -f

STEP2.

Make cron read environment variables before executing command.

* * * * * . /etc/profile.d/rails_env.sh; ruby my_job.rb >> /tmp/cron.log 2>&1

or using bash --login option, which would every file under /etc/profile.d

* * * * * /bin/bash -l -c 'ruby my_job.rb >> /tmp/cron.log 2>&1'

Then cron work as expectation!

-- gaga5lala
Source: StackOverflow