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
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.
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!