GitLab CI/CD中如何在for循环内正确使用KUBE变量?
问题:GitLab CI/CD中无法正确使用变量替代kubectl查询语句
我有如下GitLab CI/CD配置文件gitlab-ci.yml:
stages: - lang - db variables: repo: "cidcd-runner" dir: "/var/www/html/moodle/report/" KUBE: $(kubectl get ns | awk -F ' ' '{print $1}' | grep -vE 'NAME|default|kube-node-lease|kube-public|kube-system') job-lang: stage: lang script: - for i in $(kubectl get ns | awk -F ' ' '{print $1}' | grep -vE 'NAME|default|kube-node-lease|kube-public|kube-system'); do if [ -z $(kubectl exec cron-$i-0 -n $i -- ls -l $dir | grep $repo | awk -F " " '{print ($NF)}') ]; then echo NO esta en $i; else echo esta en $i; fi; done tags: - onlytest
我希望在for循环中使用KUBE变量替代重复的kubectl查询语句,但执行流水线时出现如下错误:
$ for i in $kube; do if [ -z $(kubectl exec cron-$i-0 -n $i -- ls -l $dir | grep $repo | awk -F " " '{print ($NF)}') ]; then echo NO esta en $i; else echo esta en $i; fi; done Error from server (NotFound): namespaces "`kubectl" not found NO esta en `kubectl Error from server (NotFound): namespaces "get" not found NO esta en get Error from server (NotFound): namespaces "ns" not found NO esta en ns Error from server (NotFound): namespaces "|" not found
请问如何在for循环中正确使用该变量?
解决方法
错误原因
GitLab CI的variables块中定义的变量默认会被当作纯字符串处理,不会执行$(...)格式的命令。你定义的KUBE变量实际值是字符串$(kubectl get ns | awk -F ' ' '{print $1}' | grep -vE 'NAME|default|kube-node-lease|kube-public|kube-system'),而非命令执行后的命名空间列表。当你在循环中使用$KUBE时,Shell会按空格拆分这个字符串,把kubectl、get、ns、|等当作独立的命名空间名称传入,导致报错。
另外注意:Shell变量大小写敏感,你错误使用了小写$kube,但定义的是大写KUBE,这也会导致变量未正确解析。
正确实现方式
方式一:在script中直接定义变量(推荐)
将变量赋值逻辑移到script块内,让Shell直接执行命令并赋值:
stages: - lang - db variables: repo: "cidcd-runner" dir: "/var/www/html/moodle/report/" job-lang: stage: lang script: # 在Shell中执行命令并赋值给KUBE变量 - KUBE=$(kubectl get ns | awk -F ' ' '{print $1}' | grep -vE 'NAME|default|kube-node-lease|kube-public|kube-system') # 使用大写$KUBE遍历命名空间 - for i in $KUBE; do if [ -z $(kubectl exec cron-$i-0 -n $i -- ls -l $dir | grep $repo | awk -F " " '{print ($NF)}') ]; then echo NO esta en $i; else echo esta en $i; fi; done tags: - onlytest
方式二:使用GitLab CI的before_script定义变量
如果需要在多个job中复用该变量,可以在before_script中赋值:
stages: - lang - db variables: repo: "cidcd-runner" dir: "/var/www/html/moodle/report/" before_script: - KUBE=$(kubectl get ns | awk -F ' ' '{print $1}' | grep -vE 'NAME|default|kube-node-lease|kube-public|kube-system') job-lang: stage: lang script: - for i in $KUBE; do if [ -z $(kubectl exec cron-$i-0 -n $i -- ls -l $dir | grep $repo | awk -F " " '{print ($NF)}') ]; then echo NO esta en $i; else echo esta en $i; fi; done tags: - onlytest
额外优化建议
为避免命名空间名称包含空格(虽然K8s不允许,但可以增强鲁棒性),建议改用while read循环遍历:
- kubectl get ns | awk -F ' ' '{print $1}' | grep -vE 'NAME|default|kube-node-lease|kube-public|kube-system' | while read i; do if [ -z $(kubectl exec cron-$i-0 -n $i -- ls -l $dir | grep $repo | awk -F " " '{print ($NF)}') ]; then echo NO esta en $i; else echo esta en $i; fi; done
内容的提问来源于stack exchange,提问作者Vincent Romero
相关产品推荐
相关产品推荐

