如何在coreOS上将etcd值输入我的systemd服务?

时间:2014-08-20 03:13:26

标签: systemd coreos etcd

我有两项服务A和B.

A在启动时在etcd中设置一个值,比如它从环境文件获取的公共IP地址:

ExecStartPost=/usr/bin/etcdctl set /A_ADDR $COREOS_PUBLIC_IPV4

B在启动时需要该值,以及它自己的IP地址。所以这样的事情会很好:

ExecStart=/usr/bin/docker run -e MY_ADDR=$COREOS_PUBLIC_IPV4 -e A_ADDR=$ETCD_A_ADDR mikedewar/B

但这显然是不可能的,因为etcd变量并不像那样存在系统环境变量。相反,我可以在我的/usr/bin/bash -c 'run stuff'中执行某种ExecStart,但它很尴尬,特别是因为我需要systemd来扩展$COREOS_PUBLIC_IPV4和我的新bash shell以展开$(etcdctl get /A_ADDR) 。它也充满了代码味道,让我觉得我错过了一些重要的东西。

有人可以告诉我"对"从etcd获取值到我的ExecStart声明的方法?

- 更新

所以我已经

ExecStart=/usr/bin/bash -c 'source /etc/environment && /usr/bin/docker run -e A_ADDR=$(/usr/bin/etcdctl get /A_ADDR) -e MY_ADDR=$COREOS_PUBLIC_IPV4 mikedewar/B'

但它非常丑陋。仍然无法相信我没有错过任何东西..

3 个答案:

答案 0 :(得分:12)

直到最近,我还在努力解决同样的问题。在阅读了CoreOS和systemd的大部分文档之后,这里有一个稍微清晰的'您正在做的事情的版本:

[Service]
EnvironmentFile=/etc/environment
ExecStart=/bin/sh -c '/usr/bin/docker run -e A_ADDR=$(/usr/bin/etcdctl get /A_ADDR) -e MY_ADDR=$COREOS_PUBLIC_IPV4 mikedewar/B'

此外,我采用了一种模式,我的服务依赖于系统化的&one;'将计算某些值并将其写入/ etc / environment的服务。这允许您将更复杂的shell脚本保留在主服务单元之外,并将其放入其自己的onehot服务单元。

以下是EnvironmentFile的文档:http://www.freedesktop.org/software/systemd/man/systemd.exec.html#EnvironmentFile=

最后,快速了解一下:如果在ExecStart / Stop命令中使用任何变量,则必须使用shell调用。执行您提供的命令时,systemd不执行shell调用,因此不会扩展变量。

答案 1 :(得分:3)

我目前正在使用这样的解决方法:

我创建了从特定etcd目录中提取数据的脚本

#! /bin/sh
for entry in `etcdctl ls /my_dir --recursive`  ; do
  echo ' -e '`grep -o '[^/]*$'  <<< ${entry}`=`etcdctl get ${entry}`
done

其输出如下:

 -e DATABASE_URL=postgres://m:m@mi.cf.us-.rds.amazonaws.com:5432/m
 -e WEB_CONCURRENCY=4

所以最后我可以在我的init文件中以这种方式放置

/bin/sh -c '/usr/bin/docker run -p 9000:9000 $(/home/core/envs.sh) me/myapp -D FOREGROUND'

这不是最优雅的方式,而且我很想知道如何改进它,但是将它作为单行代码放置需要大量的逃避。

答案 2 :(得分:1)

您可以在etcd桥接IP上通过docker0直接读取容器,而不是传递值吗?这也将允许您在响应上执行更复杂的逻辑,如果您将其存储为etcd值,则解析JSON等。