Kubernetes 使用 PodPreset 注入信息到 Pods
PodPreset 是一种 K8s API 资源,用于在创建 Pod 时注入其他运行时需要的信息,这些信息包括 secrets、volume mounts、environment variables 等,我们可以使用标签选择器来指定某个或某些 Pod,来将 PodPreset 预设信息应用上去。使用 PodPreset 的好处就是我们可以将一些常用 Pod 预设信息配置为模板,这样就不需要显式为每
文章目录
1、PodPreset 介绍
PodPreset 是一种 K8s API 资源,用于在创建 Pod 时注入其他运行时需要的信息,这些信息包括 secrets、volume mounts、environment variables 等,我们可以使用标签选择器来指定某个或某些 Pod,来将 PodPreset 预设信息应用上去。使用 PodPreset 的好处就是我们可以将一些常用 Pod 预设信息配置为模板,这样就不需要显式为每个 Pod 提供所有信息,简化 Pod 初始化配置,还能起到配置统一的效果。
2、环境、软件准备
本次演示环境,我是在本机 MAC OS 上操作,以下是安装的软件及版本:
- Docker: 18.06.3-ce
- Oracle VirtualBox: 6.0.8 r130520 (Qt5.6.3)
- Linux: 7.6.1810
- Minikube: v0.30.0
- Kubernetes: 1.12.1
注意:这里 Kubernetes 集群搭建使用 Minikube 来完成,Minikube 启动的单节点 k8s Node 实例是需要运行在本机的 VM 虚拟机里面,所以需要提前安装好 VM,这里我选择 Oracle VirtualBox。k8s 运行底层使用 Docker 容器,所以本机需要安装好 Docker 环境,这里忽略 Docker、VirtualBox、Minikube、Kubectl 的安装过程,着重介绍一下如何配置 PodPreset 以及使用。
3、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
配置即可。Minikube 方式启动集群,可以在启动时追加如下命令:
minikube start --extra-config=apiserver.runtime-config=settings.k8s.io/v1alpha1=true --extra-config=apiserver.enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota,PodPreset`
如果觉得以上命令太复杂,还可以通过修改 Yaml 方式配置,因为 Minikube 通过 Static Pod 的方式用 Kubelet 启动各组件服务,所以可以更改对应组件的 Yaml 来激活 PodPreset,通过修改 /etc/kubernetes/manifests/kube-apiserver.yaml
文件增加如下配置,修改完成后 Kubelet 会自动重启 kube-apiserver 各组件。
$ vim /etc/kubernetes/manifests/kube-apiserver.yaml
- --runtime-config=settings.k8s.io/v1alpha1=true #新增该配置
- --enable-admission-plugins=NamespaceLifecycle...,PodPreset #最后边增加 ,PodPreset 支持
截取修改后部分 kube-apiserver.yaml
文件如下:
spec:
containers:
- command:
- kube-apiserver
- --authorization-mode=Node,RBAC
- --enable-admission-plugins=Initializers,NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota,PodPreset
- --runtime-config=settings.k8s.io/v1alpha1=true
- --advertise-address=172.30.12.98
- --allow-privileged=true
- --client-ca-file=/var/lib/minikube/certs/ca.crt
- --enable-bootstrap-token-auth=true
待组件重启完毕后,可以再次检查是否已支持 PodPreset。
$ kubectl api-versions | grep settings.k8s.io
settings.k8s.io/v1alpha1
4、PodPreset 注入信息示例
现在我们演示一下,如何使用 PodPreset 注入信息到 Pod 中,这里举两个示例,一个是匹配指定 Pod 加载配置,另一个是匹配某个 Namespace 下所有 Pod 加载配置。
4.1、匹配指定 Pod 加载配置
上边提到过 使用标签选择器来指定某个或某些 Pod,来将 PodPreset 预设信息应用上去
,这里我们来演示下如何匹配指定 Pod 加载配置。首先新建 PodPreset Yaml 资源文件。
$ 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-why
的 Pod - 注入了
env
环境变量PODPRESET_MESSAGE=This is podpreset message.
到匹配的 Pod 中 - 注入了
volumes
卷挂载目录到匹配的 Pod 中的/opt/logs
目录
创建一下该 PodPreset 资源。
$ 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:31Z
接下来,我们来创建 Pod Yaml 资源文件。
$ vim pod-busybox-hwy.yaml
apiVersion: v1
kind: Pod
metadata:
name: busybox-hwy
namespace: wanyang3
labels:
app: busybox-hwy
role: busybox-hwy
spec:
containers:
- name: busybox-hwy
image: busybox:latest
command: ["sleep", "60000"]
注意:这里我以 busybox
容器来测试,这里 labels role: busybox-hwy
要跟上边 PodPreset selector. matchLabels
匹配上,否则将没法注入信息。那么创建一下该 Pod 资源。
$ 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 15s
成功创建,进入到容器内验证一下 PodPreset 信息是否正确注入吧!
$ 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.0G 9.3G 26.7G 26% /
tmpfs 64.0M 0 64.0M 0% /dev
tmpfs 1.8G 0 1.8G 0% /sys/fs/cgroup
/dev/mapper/centos-root
36.0G 9.3G 26.7G 26% /opt/logs
/dev/mapper/centos-root
36.0G 9.3G 26.7G 26% /dev/termination-log
/dev/mapper/centos-root
36.0G 9.3G 26.7G 26% /etc/resolv.conf
/dev/mapper/centos-root
36.0G 9.3G 26.7G 26% /etc/hostname
/dev/mapper/centos-root
36.0G 9.3G 26.7G 26% /etc/hosts
......
验证没有问题,PodPreset 信息注入到 Pod 里面了,而我们的 Pod yaml 文件就非常简洁了,从而避免了某一个配置更改,所有相关的 Pod 都需要更新 Yaml 配置的麻烦,是不是很方便!咱们在更深入了解一下 PodPreset 实现的方式,此时获取 Pod 的 Yaml 文件看下。
# kubectl get pod busybox-hwy -n wanyang3 -o yaml
apiVersion: v1
kind: Pod
metadata:
annotations:
podpreset.admission.kubernetes.io/podpreset-busybox-hwy: "24187"
creationTimestamp: 2019-07-07T02:22:27Z
labels:
app: busybox-hwy
role: busybox-hwy
name: busybox-hwy
namespace: wanyang3
resourceVersion: "24302"
selfLink: /api/v1/namespaces/wanyang3/pods/busybox-hwy
uid: 1066b217-a05e-11e9-aab0-080027a076a9
spec:
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"
资源版本号。
4.2、匹配某个 Namespace 下所有 Pod 加载配置
上边演示了匹配一个或多个指定 Pod 注入信息,如果我们想针对某个 Namespace 下的所有的 Pod 注入信息该如何配置呢?方法就是配置 selector.matchLabels
时匹配所有即可。
$ 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 所属时区,之前我们修改 Centos 容器内部时间方式,可以参照 Docker/K8s 解决容器内时区不一致方案 文章,这里提供一个新的简便的方式配置时区,从而实现该命名空间所有的 Pod 统一更改时区(毕竟 Centos 默认时间为 UTC
)。接下来,创建一下该 PodPreset 资源。
$ 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:42Z
然后,分别创建多个 Pod 来注入该 PodPreset 信息。
$ 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
$ 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 资源,并分别验证是否注入信息成功。
$ 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 26s
nginx-test-2 1/1 Running 0 20s
# 分别进入容器内验证是否注入成功
$ kubectl exec -it nginx-test-1 -n podpreset-test /bin/sh
# printenv
KUBERNETES_PORT=tcp://10.96.0.1:443
KUBERNETES_SERVICE_PORT=443
HOSTNAME=nginx-test-1
DB_PORT=6379
HOME=/root
PKG_RELEASE=1~stretch
TERM=xterm
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
NGINX_VERSION=1.17.1
......
PWD=/
TZ=Asia/Shanghai
# date
Sun Jul 7 12:16:53 CST 2019
$ kubectl exec -it nginx-test-2 -n podpreset-test /bin/sh
# printenv
KUBERNETES_SERVICE_PORT=443
KUBERNETES_PORT=tcp://10.96.0.1:443
HOSTNAME=nginx-test-2
DB_PORT=6379
HOME=/root
PKG_RELEASE=1~stretch
TERM=xterm
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
NGINX_VERSION=1.17.1
......
PWD=/
TZ=Asia/Shanghai
# date
Sun Jul 7 12:17:26 CST 2019
可以看到,该 Namespace 下的两个 Pod 都成功注入了配置信息,时区也改过来了,是不是很方便了。不过,如果想指定该 Namespace 下某个 Pod 不使用该 PodPreset 该如何配置呢?毕竟有些个性化的 Pod 不使用通用配置。我们可以配置 podpreset.admission.kubernetes.io/exclude: "true"
注解来注明该 Pod 不注入 PodPreset,接下来演示一下。
$ 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 资源,验证信息是否注入容器进去。
$ 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 时,服务端并没有更新过来(亲测会有问题,只能删除重建),大家可以自己尝试下。
参考资料
更多推荐
所有评论(0)