本章主要讲如何向容器传递环境变量或配置信息等
一、docker如何写启动命令
1、ENTRYPOINT和CMD
Dockerfile中的ENTRYPOINT一定会执行,所以一般把命令放在ENTRYPOINT,把参数放在CMD,这样运行docker run 时,加的命令行参数只会覆盖CMD,而ENTRYPOINT依然会执行
2、两种写法
(1)shell形式-----如 ENTRYPOINT node app.js
(2)exec形式----如 ENTRYPOINT ["node", "app.js"]
区别在于第一个的主进程是shell,然后在shell里运行了node app.js这个命令,第二个主进程直接是node进程
假设原来的Dockerfile长这样:
直接运行docker run,容器就会执行脚本,参数为10
而运行docker run 镜像名 15,那么容器就会执行脚本,但参数是15
3、使用k8s覆盖容器的启动命令
用command参数直接连ENTRYPOINT都可以覆盖,不想覆盖ENTRYPOINT可以只写args:
kind: Pod
spec:
containers:
- image: some/image
command: ["/bin/command"]
args: ["arg1", "arg2", "arg3"]
二、为容器设置环境变量
复用其他环境变量:
env:
- name: FIRST_VAR
value: "foo"
- name: SECOND_VAR
value: "$(FIRST_VAR)bar" // SECOND_VAR=foobar
三、利用ConfigMap解耦配置
试想,如果开发环境、测试环境、生产环境对某个环境变量的配置都不一样,那是不是这些变化都要侵入代码呢?因为pod的定义yaml肯定是放到代码仓库里的,所以找一种方法不改yaml还能让环境变量在不同环境上不一样,就需要ConfigMap
ConfigMap是一些键值对,每个环境上不一样,当同一份pod的yaml部署在不同环境上时,需要的环境变量会去ConfigMap中查找,这样就只需要针对不同环境,制作不同ConfigMap即可
1、创建ConfigMap
ConfigMap是k8s的一种资源,但与之前的资源不同,它不需要通过yaml创建(kubectl create -f),而是直接用命令创建
kubectl create configmap config名称 --选项
选项有两种:
(1)from-literal 字面量
kubectl create configmap fortune-config --from-literal=sleep-interval=25
会创建一个名为fortune-config的ConfigMap,其中只包含一个键值对,key是sleep-interval,value是25
(2)from-file 文件
kubectl create configmap my-config --from-file=config-file.conf
会创建一个名为my-config的ConfigMap,其中只包含一个键值对,key是config-file.conf(字符串),value是config-file.conf的文件内容
kubectl create configmap my-config --from-file=customkey=config-file.conf
key是customkey(字符串),value是config-file.conf的文件内容
kubectl create configmap my-config --from-file=/path/dir
key是路径下所有的文件名,value是文件名对应的文件内容
上面几种方式可以混合使用
kubectl create configmap my-config \
--from-file=foo.json
--from-file=bar=foobar.conf
--from-file=config-opts/
--from-literal=some=thing
2、给容器传递ConfigMap条目作为环境变量
如果pod引用了不存在的ConfigMap,则容器启动失败,之后创建了这个缺失的ConfigMap后,失败的容器会自动重启,无需自己重建pod
可以设置configMapKeyRef . option: true,这样即便引用的ConfigMap不存在,容器也能正常启动
3、一次性传递ConfigMap的所有条目作为环境变量
假设一个ConfigMap又三个键:FOO, BAR, FOO-BAR
现在这个容器有两个环境变量:CONFIG_FOO和CONFIG_BAR
为什么是两个?因为FOO-BAR的破折号不符合环境变量的命名规范
4、传递ConfigMap条目作为命令行参数
将容器启动时的命令行参数做成可配置,通过ConfigMap来配置参数
5、使用ConfigMap挂载配置文件(configmap卷类型)
(1)创建一个ConfigMap:
kubectl create configmap fortune-config --from-file=configmap-files
configmap-files文件夹下有两个文件:一个nginx的配置文件my-nginx-config.conf,一个变量型的文件sleep-interval
查看一下configmap:
(2)使用:
这样容器内/etc/nginx/conf.d文件夹下就有两个文件,跟configmap里一样
如果只想挂载configmap里的一个文件my-nginx-config.conf,那就在卷声明时加上一个参数items:
(3)注意:挂载卷到一个文件夹,会隐藏该文件夹下原有的文件
上述的例子中,如果容器里/etc/nginx/conf.d文件下之前有文件,那么现在会被隐藏
解决方法:指定subpath
(4)修改卷中文件权限
卷中文件的权限默认都是644
改:
5、不重启pod修改配置
修改configmap,pod不用重启也会自动更新、重载
原理:
可以查看之前容器/etc/nginx/conf.d下的内容,发现它们其实是个软链接,每当配置更新后,k8s会在容器某个位置新创建一个文件夹,然后将这些文件链接到新文件夹下。
但如果使用items只挂载部分条目,那修改configmap,这些文件不会更新。解决:挂载完整卷到另一目录,在/etc/nginx/conf.d下手动设置软链接到挂载的目录
四、Secret卷类型
Secret和ConfigMap基本一致,只是查看卷中的变量时,是base64编码过的,所以起到加密敏感数据的作用,一般用于存放证书、私钥等。
kubectl get secret fortune-https -o yaml
apiVersion: v1
data:
foo: YmFyCg==
https.cert: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tL...
https.key: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVk...
kind: Secret
创建一个fortune-secret卷并挂载到pod
secret挂载文件的使用的是tmpfs,存储在secret中的数据不会写入磁盘,这样也就无法被盗取
通过环境变量暴露secret里的内容是不明智的,因为都是敏感数据,非敏感数据应该用configmap存储
镜像拉取Secret:
一种特殊的Secret,假设dockhub上有私仓,需要配置证书私钥,那么可以这样做:
首先创建一个docker-registry Secret
kubectl create secret docker-registry mydockerhubsecret \
--docker-username=myusername --docker-password=mypassword \
--docker-email=my.email@provider.com
pod定义中使用: