PodPreset 介绍
PodPreset 是一种 K8s API 资源,用于在创建 Pod 时注入其他运行时需要的信息,这些信息包括 secrets、volume mounts、environment variables 等,我们可以使用标签选择器来指定某个或某些 Pod,来将 PodPreset 预设信息应用上去。使用 PodPreset 的好处就是我们可以将一些常用 Pod 预设信息配置为模板,这样就不需要显式为每个 Pod 提供所有信息,简化 Pod 初始化配置,还能起到配置统一的效果。
K8s 启用 PodPreset 配置 K8s 默认不开启 PodPreset 支持的,其 API 类型为 settings.k8s.io/v1alpha1
,如果不确认集群是否已开启 PodPreset 支持,可以通过 kubectl api-versions 命令查看是否存在该类型,或者 kubectl get podpreset
命令查看,如果没开启会提示 error: the server doesn't have a resource type "podpreset"
错误。
启用 PodPreset,可以通过 K8s ApiServer 增加 --runtime-config=settings.k8s.io/v1alpha1=true
配置即可。Kubeadm 方式安装集群,可以在/etc/kubernetes/manifests
路径下的kube-apiserver.yaml
中追加如下命令:
1 --runtime -config=api/all,settings.k8s.io/ v1alpha1=true
admission中添加:
1 --enable-admission-plugins =NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeClaimResize,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota,Priority,PodPreset
待组件自动重启完毕后,可以再次检查是否已支持 PodPreset。
1 2 $ kubectl api-versions | grep settings.k8s.io settings.k8s.io /v1alpha1
PodPreset 注入信息示例 现在我们演示一下,如何使用 PodPreset 注入信息到 Pod 中,这里举两个示例,一个是匹配指定 Pod 加载配置,另一个是匹配某个 Namespace 下所有 Pod 加载配置。
匹配指定 Pod 加载配置 上边提到过 使用标签选择器来指定某个或某些 Pod,来将 PodPreset 预设信息应用上去
,这里我们来演示下如何匹配指定 Pod 加载配置。首先新建 PodPreset Yaml 资源文件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 $ vim podpreset-busybox-hwy.yaml apiVersion : settings.k8s.io/v1alpha1 kind : PodPreset metadata : name : busybox-hwy namespace : wanyang3 spec : selector : matchLabels : role : busybox-hwy env : - name: PODPRESET_MESSAGE value : "This is podpreset message." volumeMounts : - mountPath: /opt/logs name : logs-volume volumes : - name: logs-volume emptyDir : {}
可以看到如下几个关键信息:
PodPreset 资源 ApiVersion 为 settings.k8s.io/v1alpha1
这里 selector.matchLabels
通过 Labels 匹配标签包含 role: busybox-hwy
的 Pod
注入了 env
环境变量 PODPRESET_MESSAGE=This is podpreset message.
到匹配的 Pod 中
注入了 volumes
卷挂载目录到匹配的 Pod 中的 /opt/logs
目录
创建一下该 PodPreset 资源。
1 2 3 4 5 6 7 8 9 10 11 $ kubectl create ns wanyang3 namespace/wanyang3 created$ kubectl apply -f podpreset-busybox -hwy .yaml podpreset.settings.k8s.io/busybox-hwy created$ kubectl get podpreset -n wanyang3 NAME CREATED AT busybox-hwy 2019 -07-07T02 :10 :31 Z
接下来,我们来创建 Pod Yaml 资源文件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 $ vim pod-busybox-hwy.yaml apiVersion: v1kind: Podmetadata: name: busybox-hwy namespace: wanyang3 labels: app: busybox-hwy role: busybox-hwyspec: containers: - name: busybox-hwy image: busybox:latest command: ["sleep" , "60000" ]
注意:这里我以 busybox
容器来测试,这里 labels role: busybox-hwy
要跟上边 PodPreset selector.matchLabels
匹配上,否则将没法注入信息。那么创建一下该 Pod 资源。
1 2 3 4 5 6 7 $ kubectl apply -f pod-busybox-hwy .yaml pod/busybox-hwy created$ kubectl get pod -n wanyang3 NAME READY STATUS RESTARTS AGE busybox-hwy 1 /1 Running 0 15 s
成功创建,进入到容器内验证一下 PodPreset 信息是否正确注入吧!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 $ kubectl exec -it busybox-hwy -n wanyang3 /bin/ sh / # printenv |grep PODPRESET PODPRESET_MESSAGE=This is podpreset message. / # df -h Filesystem Size Used Available Use% Mounted on overlay 36.0 G 9.3 G 26.7 G 26 % / tmpfs 64.0 M 0 64.0 M 0 % /dev tmpfs 1.8 G 0 1.8 G 0 % /sys/ fs/cgroup/dev/m apper/centos-root 36.0 G 9.3 G 26.7 G 26 % /opt/ logs/dev/m apper/centos-root 36.0 G 9.3 G 26.7 G 26 % /dev/ termination-log/dev/m apper/centos-root 36.0 G 9.3 G 26.7 G 26 % /etc/ resolv.conf/dev/m apper/centos-root 36.0 G 9.3 G 26.7 G 26 % /etc/ hostname/dev/m apper/centos-root 36.0 G 9.3 G 26.7 G 26 % /etc/ hosts ......
验证没有问题,PodPreset 信息注入到 Pod 里面了,而我们的 Pod yaml 文件就非常简洁了,从而避免了某一个配置更改,所有相关的 Pod 都需要更新 Yaml 配置的麻烦,是不是很方便!咱们在更深入了解一下 PodPreset 实现的方式,此时获取 Pod 的 Yaml 文件看下。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 # kubectl get pod busybox-hwy -n wanyang3 -o yaml apiVersion: v1kind: Podmetadata: annotations: podpreset.admission.kubernetes.io/podpreset-busybox-hwy: "24187" creationTimestamp: 2019 -07 -07 T02:22 :27 Z labels: app: busybox-hwy role: busybox-hwy name: busybox-hwy namespace: wanyang3 resourceVersion: "24302" selfLink: /api/ v1/namespaces/ wanyang3/pods/ busybox-hwy uid: 1066 b217-a05e-11e9 -aab0-080027 a076a9spec: containers: - command: - sleep - "60000" env: - name: PODPRESET_MESSAGE value: This is podpreset message. image: busybox:latest imagePullPolicy: Always name: busybox-hwy resources: { } terminationMessagePath: /dev/ termination-log terminationMessagePolicy: File volumeMounts: - mountPath: /opt/ logs name: logs-volume - mountPath: /var/ run/secrets/ kubernetes.io/serviceaccount name: default-token-nnbrm readOnly: true dnsPolicy: ClusterFirst nodeName: minikube ......
可以看到,经过 k8s admission controller 之后此时的 Yaml 文件是将 PodPreset 和 Pod 资源 Merge 合并了,同时增加了 podpreset.admission.kubernetes.io/podpreset-busybox-hwy: "24187"
这样的注解,类似模板的 Include 功能,而这个 24187
资源号就是上边 podpreset-busybox-hwy
创建完成之后的 resourceVersion: "24187"
资源版本号。
匹配某个 Namespace 下所有 Pod 加载配置 上边演示了匹配一个或多个指定 Pod 注入信息,如果我们想针对某个 Namespace 下的所有的 Pod 注入信息该如何配置呢?方法就是配置 selector.matchLabels
时匹配所有即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 $ vim podpreset-ns-test.yaml apiVersion: settings.k8s.io/v1alpha1 kind: PodPreset metadata: name: podpreset-ns-test namespace: podpreset-test spec: selector: matchLabels: env: - name: DB_PORT value: "6379" - name: TZ value: Asia/Shanghai
说明一下:这里 matchLabels:
设置为空,表示匹配该 Namespaces 下所有,这里匹配 podpreset-test
命名空间下所有 Pod,并注入了 DB_PORT= 6379
和 TZ=Asia/Shanghai
两个公用环境变量配置。注意:这里的 TZ=Asia/Shanghai
环境变量配置可以用于修改 Pod 所属时区,从而实现该命名空间所有的 Pod 统一更改时区(毕竟 Centos 默认时间为 UTC
)。接下来,创建一下该 PodPreset 资源。
1 2 3 4 5 6 7 8 9 10 11 $ kubectl create ns podpreset-test namespace/podpreset-test created$ kubectl apply -f podpreset-ns -test .yaml podpreset.settings.k8s.io/podpreset-ns -test created$ kubectl get podpreset -n podpreset-test NAME CREATED AT podpreset-ns -test 2019 -07-07T03 :52 :42 Z
然后,分别创建多个 Pod 来注入该 PodPreset 信息。
1 2 3 4 5 6 7 8 9 10 11 12 $ vim pod-nginx-test-1.yaml apiVersion : v1 kind : Pod metadata : name : nginx-test-1 namespace : podpreset-test labels : app : nginx-test-1 spec : containers : - name: nginx-test-1 image : nginx:latest
1 2 3 4 5 6 7 8 9 10 11 12 $ vim pod-nginx-test-2.yaml apiVersion : v1 kind : Pod metadata : name : nginx-test-2 namespace : podpreset-test labels : app : nginx-test-2 spec : containers : - name: nginx-test-2 image : nginx:latest
创建以上 Pod 资源,并分别验证是否注入信息成功。
1 2 3 4 5 6 7 8 9 10 11 12 $ kubectl apply -f pod-nginx-test -1 .yaml pod/nginx-test -1 created $ kubectl apply -f pod-nginx-test -2 .yaml pod/nginx-test -2 created $ kubectl get pod -n podpreset-test NAME READY STATUS RESTARTS AGE nginx-test -1 1 /1 Running 0 26 s nginx-test -2 1 /1 Running 0 20 s
分别进入容器内验证是否注入成功
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 $ kubectl exec -it nginx-test-1 -n podpreset-test /bin/shKUBERNETES_PORT =tcp://10.96.0.1:443KUBERNETES_SERVICE_PORT =443HOSTNAME =nginx-test-1DB_PORT =6379HOME =/rootPKG_RELEASE =1~stretchTERM =xtermKUBERNETES_PORT_443_TCP_ADDR =10.96.0.1NGINX_VERSION =1.17.1.. .. .. PWD =/TZ =Asia/Shanghai Sun Jul 7 12:16:53 CST 2019
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 $ kubectl exec -it nginx-test-2 -n podpreset-test /bin/shKUBERNETES_SERVICE_PORT =443KUBERNETES_PORT =tcp://10.96.0.1:443HOSTNAME =nginx-test-2DB_PORT =6379HOME =/rootPKG_RELEASE =1~stretchTERM =xtermKUBERNETES_PORT_443_TCP_ADDR =10.96.0.1NGINX_VERSION =1.17.1.. .. .. PWD =/TZ =Asia/Shanghai Sun Jul 7 12:17:26 CST 2019
可以看到,该 Namespace 下的两个 Pod 都成功注入了配置信息,时区也改过来了,是不是很方便了。不过,如果想指定该 Namespace 下某个 Pod 不使用该 PodPreset 该如何配置呢?毕竟有些个性化的 Pod 不使用通用配置。我们可以配置 podpreset.admission.kubernetes.io/exclude: "true"
注解来注明该 Pod 不注入 PodPreset,接下来演示一下。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 $ vim pod-nginx-test-3.yaml apiVersion : v1 kind : Pod metadata : name : nginx-test-3 namespace : podpreset-test annotations : podpreset.admission.kubernetes.io/exclude : "true" labels : app : nginx-test-3 spec : containers : - name: nginx-test-3 image : nginx:latest
创建该 Pod 资源,验证信息是否注入容器进去。
1 2 3 4 5 6 $ kubectl apply -f pod-nginx-test-3.yaml $ kubectl exec -it nginx-test-3 -n podpreset-test /bin/sh $ printenv | grep TZ$ printenv | grep DB_PORT$ date Sun Jul 7 04:18:54 UTC 2019
可以看到,添加了忽略 PodPreset 注入 annotations 后,没有将信息注入进去,时间还是默认的 UTC 时间。
PodPreset 除了上边演示的两种用法外,还支持多 PodPreset 应用到同一 Pod,支持多种资源类型(ReplicaSet 等),支持从 ConfigMap 中取值。同时要说明一下,当 PodPreset 跟 Pod 配置有冲突时,例如 Pod Yaml 容器挂载配置跟 PodPreset 容器挂载配置为同一路径时,会报错提示冲突。
最后要提一下注意的问题:
目前 PodPreset 的预设功能这块还在演进中,不过已经能大大简化了相关的管理工作,将这些公用配置从开发者手中分离出来,变成系统管理配置。
PodPreset 是 Namespace 级别的对象,其作用范围只能是同一个命名空间下容器。
目前为 v1alpha1
版本,还不成熟,例如当我们对已创建的 PodPreset 执行非常少量的修改时,重新 apply 或者 replace 时,服务端并没有更新过来(亲测会有问题,只能删除重建),大家可以自己尝试下。
参考资料