gaga5lala
gaga5lala

Reputation: 1228

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

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

Upvotes: 2

Views: 6415

Answers (2)

gaga5lala
gaga5lala

Reputation: 1228

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!

Upvotes: 3

Amanpreet Singh
Amanpreet Singh

Reputation: 178

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.

Upvotes: 3

Related Questions