ConfigMap
主要有三种用法
1、向容器传递命令行参数
容器中运行完整指令由两部分组成:命令与参数
Dockerfile中两种指令分别定义命令与参数这两个部分
虽然可以直接使用CMD指令指定镜像运行时想要执行的命令,但正确的做法依旧是借助ENTRYPOINT指令,仅仅用CMD指定所需要的默认参数。这样镜像可以直接运行,无需再添加任何参数。
docker run
或添加一些参数,覆盖Dockerfile中任何CMD指定的默认参数
docker run
shell与exec的区别
上述两条指令都支持以下两种形式
可以从容器中运行额进程列表看出两者的区别
shell形式是先启动一个shell,然后node 再再shell进程中启动
exec形式是直接运行node进程,因此可以直接采用exec形式的ENTRYPOINT 指令
使用kubectl create ConfigMap -h 来查看关于创建ConfigMap的帮助信息
在使用命令创建configmap时,以上三种方式可以混合使用
可通过kubectl describe configmap cm-name
或 kubectl get configmap cm-name -o yaml 来获取configmap的内容
使用ConfigMap
向容器传递ConfigMap条目,作为环境变量
cm-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: cm-pod
spec:
containers:
- image: nginx
name: nginx
env:
- name: CMTEST # 环境变量的名称
valueFrom:
configMapKeyRef:
name: cm-1 # ConfigMap 的名称
key: key1 # ConfigMap中对应条目的key
可通过 kubectl exec -it cm-pod -c nginx -- /bin/bash 进入nginx容器,echo $CMTEST 查看变量的值
在pod中引用不存在的ConfigMap
如果创建pod时,引用的ConfigMap不存在,此时不存在ConfigMap的容器将会启动失败,其他容器可以正常运行,如果之后创建了这个ConfigMap,失败容器将会自动启动,无须再重新创建pod。
也可设置对ConfigMap的引用是可选,设置 configMapKeyRef.optional: true(默认是false)即可,这样就算ConfigMap不存在,容易也能正常启动
一次性传递ConfigMap的所有条目作为环境变量
如果ConfigMap的条目不少,一条一条的为其设置成环境变量台麻烦,kubernetes提供了一次性暴露所有ConfigMap的所有条目作为环境变量的的方法。
spec:
containers:
- image: nginx
envFrom: # 使用的envFrom 而非env
- perfix: CONFIG_ # 为所有环境变量添加前缀,如果不设置,将会与ConfigMap中的键名一致
configMapRef:
name: cm-name # 引用名为cm-name 的ConfigMap
注意:kubernetes不会主动转换键名,如果键名不是一个合法的环境变量名,创建环境变量时将会忽略对应的条目,且不会有发出事件通知。
作为命令行参数
在字段pod.spec.containers.args 中无法直接使用ConfigMap的条目,但是可以利用ConfigMap初始化某个环境变量,然后再再参数中引用该字段
apiVersion: v1
kind: Pod
metadata:
name: cm-pod
spec:
containers:
- image: nginx
name: nginx
env:
- name: CMTEST # 环境变量的名称
valueFrom:
configMapKeyRef:
name: cm-1 # ConfigMap 的名称
key: key1 # ConfigMap中对应条目的key
args: ["$(CMTEST)"] # 在参数中引用环境变量
使用configMap数据卷将条目暴露为文件
configMap数据卷可以将ConfigMap中的每个条目暴露为一个文件,运行在容器中的程序可以访问文件获取对应的条目值,比较适合内容多的配置文件,少量内容的配置文件当然也可以这样使用。
apiVersion: v1
kind: Pod
metadata:
name: cm-volume-item
spec:
containers:
- image: nginx
name: cm-volume-item
volumeMounts:
- name: tmp # 多个挂载,第一个挂载 tmp
mountPath: /tmp
readOnly: true
- name: etc-config # 多个挂载,第一个挂载 etc-config
mountPath: /etc/config
volumes:
- name: tmp
configMap:
name: cm-3
items: # 单独挂载ConfigMap中的某一个条目
- key: literal_key
path: ./literal_key
- name: etc-config
configMap:
name: cm-3
items: # items是一个数组,所以可多个挂载ConfigMap中的多个条目
- key: ss1
path: ss/ss/ss1 # 还可以再指定路径
- key: ss2
path: ss2/ss2
ConfigMap独立条目作为文件被挂载,且不隐藏原文件夹中的其他文件
通常挂载之后,源目录下的内容将访问不到,只能访问挂载的内容。如果刚好程序也要使用原目录下的文件,则这样会带来未知的后果。volumeMount额外的subPath 可以将文件挂载二不影响文件夹中其他的文件。
apiVersion: v1
kind: Pod
metadata:
name: cm-volume-subpath
spec:
containers:
- image: nginx
name: cm-volume-subpath
volumeMounts:
- name: etc-config
mountPath: /etc/hosts # 该文件必须在容器中存在
subPath: ss1 # 在ConfigMap cm-3中条目的键名
volumes:
- name: etc-config
configMap:
name: cm-3
设置权限
volumes:
- volumes:
configMap:
name: test
defaultMode: "6600" # 权限设置为 "-rw-rw----"
需要注意的,subPath 单独挂载一个文件,是不支持热更新的。但当挂载整个ConfigMap数据卷时,ConfigMap更新后,容器中的内容也会更新。进到容器中查看挂载文件夹下,各文件的属性,会发现它们是属于链接文件 ..data/xxx 。如果要更新指定的一个文件,可以先把数据卷挂载到另一个目录,然后创建符号链接指向目标文件,符号链接可以再容器中原生创建,也可以在容器启动的时候创建。
容器一个很重要的特性就是不变性,从同一个镜像创建的pod,他们之间没有任何差异,但是通过修改被运行容器使用的configMap数据,会打破这种不变性。但其中的关键是,应用是否支持重载配置,如果应用不支持重载配置,ConfigMap更新之前创建的pod会使用旧的配置文件,但是新创建的pod就会使用更新后的的配置,所以会导致运行中的容器的配置不同,并且不单是新建的pod,如果因为某些原因,pod中运行的容器发生重启,也将会使用新配置。因此,如果应用程序不支持热更新,那么修改某些运行pod的所使用的ConfigMap并不是一个好主意。
如果应用程序支持热更新,那修改ConfigMap就不算什么了,但需要注意的是,因为configMap数据卷中的文件更新行为对于运行中的pod而言,不是同步的,所以它们还是会保持一段时间配置不一致的情况,可能长达一分钟。
Secret 与ConfigMap类似,都是采用键值对的形式,Secret与ConfigMap使用方法与ConfigMap类似
kubernetes 通过仅仅将Secret分发到需要访问Secret的pod所在的机器节点来保障安全性。另外,Secret只会保存在节点的内存中,永远不写入物理存储,这样在节点上删除Secret时就不需要搽除磁盘了。
默认令牌Secret 介绍
对任意一个pod,使用命令kubectl describe pod 输出都会包含以下信息
Volumes:
default-token-8wzm5:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-8wzm5
Optional: false
并且还可看到secret数据卷被挂载的路径
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from default-token-8wzm5 (ro)
每个pod都会自动挂载一个secret数据卷,由于Secret也是一个资源对象,所以可以采用kubectl describe secret default-token-8wzm5 来获取一些详细信息。
Name: default-token-8wzm5
Namespace: default
Labels: >
Annotations: kubernetes.io/service-account.name: default
kubernetes.io/service-account.uid: 3b82d73e-92fe-419a-afb4-25767b7690e8
Type: kubernetes.io/service-account-token
Data
====
ca.crt: 1025 bytes
namespace: 7 bytes
token: eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJ ... #(太长了,就不展示了)
可以看到secret包含三个条目,ca.crt、namespace、token。包含了pod内部安全访问kubernetes API服务所需要的全部信息。
default-token Secret默认会被挂载至每一个容器,可以通过设置pod定义中的aotomountServiceAccountToken 字段为false。或者设置pod使用的服务账户中相同自动为false来关闭这种默认行为。
创建 Secret
需要创建私钥与证书,由于要确保私钥的安全性,可将其与证书同时存入Secret
在本地生产私钥
openssl genrsa -out test.key 2048
生产证书
openssl req -new -x509 -key test.key -out test.cert -days s650 -subj /CN=www.test.com
创建Secret
kubectl create secret generic test-secret --from-file=test.key --from-file=test.cert
查看Secret
kubectl get secret
查看test-secret 的描述信息
kubectl describe secret test-secret
使用Secret
spec:
containers:
- image: xxx
name: xxx
volumeMount:
- name: test-key
mountPath: xxx
volumes:
- name: test-key
secret:
secretName: test-secret
镜像拉取Secret
在docker hub上海支持创建私有镜像,从一个私有仓库中拉取一个私有镜像需要做两件事
创建一个docker镜像仓库的证书
kubectl create secret docker-registry mydockerhubsecret \
--docker-username=myusername --docker-password=mypassword \
--docker-[email protected]
这里创建了一个docker-registry 类型的secret ,通过kubectl describe 查看发现,其只有一个条目 .dockerconfigjson ,相当于用户主目录下的.dockerconfigjson文件,这文件通常在运行 docker login 命令时由Docker主动创建
在pod中使用docker-registry Secret
pull-private-image-secret.yaml
apiVersion: v1
kind: Pod
metadata:
name: test-docker-registry-secret
spec:
imagePullSecrets:
- name: mydockerhubsecret # 能够从私有仓库中拉取镜像
containers:
- image: bqwu/ubuntu:v1
name: ubuntu-test
command: ["/bin/bash", "-c", "while true; do sleep 3; done"]
(本文章是学习《kubernetes in action》 一书时做的笔记,由于本人是刚学习k8s,且自学方式就是把它敲一遍,然后加一些自己的理解。所以会发现很多内容是跟书中内容一模一样,如果本文是对本书的侵权,敬请谅解,告知后会删除。如果引用或转载,请注明出处——谢谢)