Laravel部署Kubernetes:环境变量未生效致数据库连接失败
Laravel在Kubernetes环境中未读取Kubernetes Secrets环境变量导致数据库连接失败
错误现象
访问API端点时抛出数据库连接错误:
Illuminate\Database\QueryException: SQLSTATE[HY000] [2002] Connection refused (Connection: mysql, SQL: select count(*) as aggregate from 'users' where 'email' = jhon@gmail.com)
背景信息
- 可通过服务器终端直接连接RDS实例,数据库及表结构均正常:
ubuntu@ip-xxxxxxxxxxx:/ecom-prod$ mysql -h ecom-db-identifier.xxxxxxxx.us-east-1.rds.amazonaws.com -u root -p Enter password: xxxxx Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 113 Server version: 8.0.35 Source distribution Copyright (c) 2000, 2024, Oracle and/or its affiliates. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | ecom | | sys | +--------------------+ 5 rows in set (0.29 sec) mysql> use ecom Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Database changed mysql> show tables; +------------------------+ | Tables_in_ecom | +------------------------+ | activity_log | | comments | | failed_jobs | | migrations | | password_reset_tokens | | permissions | | personal_access_tokens | | policies | | users | +------------------------+ 9 rows in set (0.28 sec)
- 容器内已确认Kubernetes Secrets的环境变量已正确加载
- 使用
php artisan tinker可正常读取数据库数据:
> App\Models\User::find(1); = App\Models\User {#5534 id: 1, name: "Test User", email: "test@example.com", #email_verified_at: "2024-03-12 15:52:14", #password: "y$.bHDGgvm4zY.ucub4L.avOcERJzaS72sC0GZna6cAhy2/3xI1Cr/e", image: null, #remember_token: "SnA9FiQFl8", created_at: "2024-03-12 15:52:14", updated_at: "2024-03-12 15:52:14", }
关键矛盾点
创建测试路由输出数据库配置时,返回的是config/database.php中的默认值,说明Laravel未读取到环境变量:
// 测试路由代码 \DB::connection(config('database.default'))->getConfig() // 返回结果 {"driver":"mysql","host":"127.0.0.1","port":"3306","database":"forge","username":"forge","password":"","unix_socket":"","charset":"utf8mb4","collation":"utf8mb4_unicode_ci","prefix":"","prefix_indexes":true,"strict":true,"engine":null,"options":[],"name":"mysql"}
问题排查与解决方案
1. 检查Laravel配置缓存
生产环境下,若执行过php artisan config:cache,Laravel会将配置文件缓存为静态文件,后续环境变量的修改不会生效。解决方法:
- 进入容器执行命令清除缓存:
php artisan config:clear - 若需要缓存配置,需在环境变量加载完成后重新执行:
php artisan config:cache - 建议在Kubernetes的容器启动命令中,先清除缓存再启动应用,或者确保缓存命令在环境变量注入后执行。
2. 确认config/database.php配置
检查数据库配置文件是否正确使用env()函数读取环境变量,例如:
'mysql' => [ 'driver' => 'mysql', 'host' => env('DB_HOST', '127.0.0.1'), 'port' => env('DB_PORT', '3306'), 'database' => env('DB_DATABASE', 'forge'), 'username' => env('DB_USERNAME', 'forge'), 'password' => env('DB_PASSWORD', ''), // 其他配置... ],
确保所有需要从环境变量获取的配置项都使用了env()函数,而非硬编码值。
3. 验证Laravel运行环境
Laravel在production环境下会自动启用配置缓存,而local环境不会。检查当前运行环境:
php artisan env
若为production,需确保配置缓存是在环境变量加载后生成的;若需要临时调试,可临时切换为local环境验证。
4. 检查Kubernetes环境变量注入
虽然容器内能看到环境变量,但需确认变量名是否与Laravel预期一致:
- 确保Secrets注入的环境变量键名为
DB_HOST、DB_PORT、DB_DATABASE、DB_USERNAME、DB_PASSWORD,与Laravel默认的环境变量名匹配,避免拼写错误(如DB_HOST写成DB_HOSTNAME)。 - 检查Kubernetes Deployment配置中,环境变量是否正确从Secrets挂载,例如:
env: - name: DB_HOST valueFrom: secretKeyRef: name: your-db-secret key: db-host - name: DB_PORT valueFrom: secretKeyRef: name: your-db-secret key: db-port # 其他变量...
5. 检查容器启动命令顺序
若容器启动命令中包含config:cache或optimize等优化命令,需确保这些命令在环境变量完全加载后执行。例如,在Dockerfile或Kubernetes启动命令中,不要将缓存命令作为镜像构建时的步骤,而是作为容器启动时的脚本步骤:
# 错误示例:构建镜像时执行缓存,此时环境变量未注入 RUN php artisan config:cache # 正确示例:容器启动时执行 CMD ["sh", "-c", "php artisan config:cache && php artisan serve --host=0.0.0.0 --port=8000"]
内容的提问来源于stack exchange,提问作者Muhammad AbuBaker
相关产品推荐
相关产品推荐

