如果用过node的话,会发现它的环境配置管理在docker容器集群中使用起来比较方便。

以koa为例,在config下定义好custom-environment-variables.json相关环境变量,比如:

{
  "mysql_host": "MYSQL_HOST",
  "mysql_user": "MYSQL_USER",
  "mysql_password": "MYSQL_PASSWORD",
  "mysql_db": "MYSQL_DB",
  "redis": "REDIS"
}

之后在k8s中配置好对应的环境变量,node就会读取配置的环境变量来运行了,如图:

个人比较喜欢这种方式,相比于我们在框架中定义多种环境配置文件而言,此方式更简洁优雅。

既然node都能做到,PHP也肯定可以的啦。

$_ENV配置

要实现这个效果,简单的方法就是使用$_ENV来读取环境变量。

PHP目前主流的运行方式有两种:swoole和php-fpm。 对于swoole而言,大部分的swoole框架是支持读取$_ENV的,
直接按框架方法读取即可,无需额外修改。这里介绍下php-fpm模式下的$_ENV配置。

1.修改php.ini配置

在php.ini的配置文件中找到variables_order这行配置,将GPCS改为EGPCS

2.修改php-fpm配置

在php-fpm的找到clear_env配置,将yes改为no,如果没有,则在[www]配置域下增加这行配置clear_env = no

框架配置

以laravel的数据库配置为例,将database.conf中对应的配置改为如下:

'mysql' => [
    'driver' => 'mysql',
    'url' => env('DATABASE_URL'),
    'host' => $_ENV['DB_HOST']?$_ENV['DB_HOST']:env('DB_HOST', '127.0.0.1'),
    'port' => $_ENV['DB_PORT']?$_ENV['DB_PORT']:env('DB_PORT', '3306'),
    'database' => $_ENV['DB_DATABASE']?$_ENV['DB_DATABASE']:env('DB_DATABASE', 'forge'),
    'username' => $_ENV['DB_USERNAME']?$_ENV['DB_USERNAME']:env('DB_USERNAME', 'forge'),
    'password' => $_ENV['DB_PASSWORD']?$_ENV['DB_PASSWORD']:env('DB_PASSWORD', ''),
    'unix_socket' => env('DB_SOCKET', ''),
    'charset' => 'utf8mb4',
    'collation' => 'utf8mb4_unicode_ci',
    'prefix' => '',
    'prefix_indexes' => true,
    'strict' => true,
    'engine' => null,
    'options' => extension_loaded('pdo_mysql') ? array_filter([
        PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
    ]) : [],
]

也就是将配置读取的顺序改为:先读取系统环境变量的配置,如果没有则读框架env的配置。

k8s集群配置

在k8s集群对应的应用中添加对应的环境变量,即可实现这个效果了。

crontab下不生效的问题

docker的crontab下默认没有读取这些环境变量,可以利用. <(xargs -0 bash -c 'printf "export %q\n" "$@"' -- < /proc/1/environ)这类的命令导出环境变量,在执行crontab时导入。
准备一个shell脚本放在根目录下:

xargs -0 bash -c 'printf "export %q\n" "$@"' -- < /proc/1/environ | grep -E "TZ|DB|REDIS|URL"  > /etc/environment

dockerfile的crontab改为如下方式:

COPY env.sh /data/

RUN && chmod +x  /data/env.sh \
    && echo "* * * * * root /data/env.sh ; . /etc/environment; /usr/local/bin/php /data/artisan schedule:run >> /dev/null 2>&1" >> /etc/crontab

值得一提的是,在dockerfile中,如果要grep一些写到某个文件时,需注意保证可以grep到信息,而不是空的,即grep后的状态码是0。否则docker无法构建,报错returned a non-zero code: 1

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐