使用 PodPreset 将信息注入 Pods

在 pod 创建时,用户可以使用 podpreset 对象将 secrets、卷挂载和环境变量等信息注入其中。 本文展示了一些 PodPreset 资源使用的示例。 用户可以从理解 Pod Presets 中了解 PodPresets 的整体情况。

创建 Pod Preset

简单的 Pod Spec 示例

这里是一个简单的示例,展示了如何通过 Pod Preset 修改 Pod spec 。

podpreset/preset.yaml 使用 PodPreset 将信息注入 Pods - 图1
  1. apiVersion: settings.k8s.io/v1alpha1
  2. kind: PodPreset
  3. metadata:
  4. name: allow-database
  5. spec:
  6. selector:
  7. matchLabels:
  8. role: frontend
  9. env:
  10. - name: DB_PORT
  11. value: 6379
  12. volumeMounts:
  13. - mountPath: /cache
  14. name: cache-volume
  15. volumes:
  16. - name: cache-volume
  17. emptyDir: {}

创建 PodPreset:

  1. kubectl apply -f https://k8s.io/examples/podpreset/preset.yaml

检查所创建的 PodPreset:

  1. kubectl get podpreset
  1. NAME AGE
  2. allow-database 1m

新的 PodPreset 会对所有具有标签 role: frontend 的 Pods 采取行动。

用户提交的 pod spec:

podpreset/pod.yaml 使用 PodPreset 将信息注入 Pods - 图2
  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. name: website
  5. labels:
  6. app: website
  7. role: frontend
  8. spec:
  9. containers:
  10. - name: website
  11. image: nginx
  12. ports:
  13. - containerPort: 80

创建 Pod:

  1. kubectl create -f https://k8s.io/examples/podpreset/pod.yaml

列举运行中的 Pods:

  1. kubectl get pods
  1. NAME READY STATUS RESTARTS AGE
  2. website 1/1 Running 0 4m

通过准入控制器后的 Pod 规约:

podpreset/merged.yaml 使用 PodPreset 将信息注入 Pods - 图3
  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. name: website
  5. labels:
  6. app: website
  7. role: frontend
  8. annotations:
  9. podpreset.admission.kubernetes.io/podpreset-allow-database: resource version
  10. spec:
  11. containers:
  12. - name: website
  13. image: nginx
  14. volumeMounts:
  15. - mountPath: /cache
  16. name: cache-volume
  17. ports:
  18. - containerPort: 80
  19. env:
  20. - name: DB_PORT
  21. value: 6379
  22. volumes:
  23. - name: cache-volume
  24. emptyDir: {}

要查看如上输出,运行下面的命令:

  1. kubectl get pod website -o yaml

带有 ConfigMap 的 Pod Spec 示例

这里的示例展示了如何通过 PodPreset 修改 Pod 规约,PodPreset 中定义了 ConfigMap 作为环境变量取值来源。

用户提交的 pod spec:

podpreset/pod.yaml 使用 PodPreset 将信息注入 Pods - 图4
  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. name: website
  5. labels:
  6. app: website
  7. role: frontend
  8. spec:
  9. containers:
  10. - name: website
  11. image: nginx
  12. ports:
  13. - containerPort: 80

用户提交的 ConfigMap

podpreset/configmap.yaml 使用 PodPreset 将信息注入 Pods - 图5
  1. apiVersion: v1
  2. kind: ConfigMap
  3. metadata:
  4. name: etcd-env-config
  5. data:
  6. number_of_members: 1
  7. initial_cluster_state: new
  8. initial_cluster_token: DUMMY_ETCD_INITIAL_CLUSTER_TOKEN
  9. discovery_token: DUMMY_ETCD_DISCOVERY_TOKEN
  10. discovery_url: http://etcd_discovery:2379
  11. etcdctl_peers: http://etcd:2379
  12. duplicate_key: FROM_CONFIG_MAP
  13. REPLACE_ME: a value

PodPreset 示例:

podpreset/allow-db.yaml 使用 PodPreset 将信息注入 Pods - 图6
  1. apiVersion: settings.k8s.io/v1alpha1
  2. kind: PodPreset
  3. metadata:
  4. name: allow-database
  5. spec:
  6. selector:
  7. matchLabels:
  8. role: frontend
  9. env:
  10. - name: DB_PORT
  11. value: 6379
  12. - name: duplicate_key
  13. value: FROM_ENV
  14. - name: expansion
  15. value: $(REPLACE_ME)
  16. envFrom:
  17. - configMapRef:
  18. name: etcd-env-config
  19. volumeMounts:
  20. - mountPath: /cache
  21. name: cache-volume
  22. volumes:
  23. - name: cache-volume
  24. emptyDir: {}

通过准入控制器后的 Pod spec:

podpreset/allow-db-merged.yaml 使用 PodPreset 将信息注入 Pods - 图7
  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. name: website
  5. labels:
  6. app: website
  7. role: frontend
  8. annotations:
  9. podpreset.admission.kubernetes.io/podpreset-allow-database: resource version
  10. spec:
  11. containers:
  12. - name: website
  13. image: nginx
  14. volumeMounts:
  15. - mountPath: /cache
  16. name: cache-volume
  17. ports:
  18. - containerPort: 80
  19. env:
  20. - name: DB_PORT
  21. value: 6379
  22. - name: duplicate_key
  23. value: FROM_ENV
  24. - name: expansion
  25. value: $(REPLACE_ME)
  26. envFrom:
  27. - configMapRef:
  28. name: etcd-env-config
  29. volumes:
  30. - name: cache-volume
  31. emptyDir: {}

带有 Pod Spec 的 ReplicaSet 示例

以下示例展示了(通过 ReplicaSet 创建 pod 后)只有 pod spec 会被 Pod Preset 所修改。

用户提交的 ReplicaSet:

podpreset/replicaset.yaml 使用 PodPreset 将信息注入 Pods - 图8
  1. apiVersion: apps/v1
  2. kind: ReplicaSet
  3. metadata:
  4. name: frontend
  5. spec:
  6. replicas: 3
  7. selector:
  8. matchLabels:
  9. role: frontend
  10. matchExpressions:
  11. - {key: role, operator: In, values: [frontend]}
  12. template:
  13. metadata:
  14. labels:
  15. app: guestbook
  16. role: frontend
  17. spec:
  18. containers:
  19. - name: php-redis
  20. image: gcr.io/google_samples/gb-frontend:v3
  21. resources:
  22. requests:
  23. cpu: 100m
  24. memory: 100Mi
  25. env:
  26. - name: GET_HOSTS_FROM
  27. value: dns
  28. ports:
  29. - containerPort: 80

PodPreset 示例:

podpreset/preset.yaml 使用 PodPreset 将信息注入 Pods - 图9
  1. apiVersion: settings.k8s.io/v1alpha1
  2. kind: PodPreset
  3. metadata:
  4. name: allow-database
  5. spec:
  6. selector:
  7. matchLabels:
  8. role: frontend
  9. env:
  10. - name: DB_PORT
  11. value: 6379
  12. volumeMounts:
  13. - mountPath: /cache
  14. name: cache-volume
  15. volumes:
  16. - name: cache-volume
  17. emptyDir: {}

通过准入控制器后的 Pod spec:

注意 ReplicaSet spec 没有改变,用户必须检查单独的 pod 来验证 PodPreset 已被应用。

podpreset/replicaset-merged.yaml 使用 PodPreset 将信息注入 Pods - 图10
  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. name: frontend
  5. labels:
  6. app: guestbook
  7. role: frontend
  8. annotations:
  9. podpreset.admission.kubernetes.io/podpreset-allow-database: resource version
  10. spec:
  11. containers:
  12. - name: php-redis
  13. image: gcr.io/google_samples/gb-frontend:v3
  14. resources:
  15. requests:
  16. cpu: 100m
  17. memory: 100Mi
  18. volumeMounts:
  19. - mountPath: /cache
  20. name: cache-volume
  21. env:
  22. - name: GET_HOSTS_FROM
  23. value: dns
  24. - name: DB_PORT
  25. value: 6379
  26. ports:
  27. - containerPort: 80
  28. volumes:
  29. - name: cache-volume
  30. emptyDir: {}

多 PodPreset 示例

这里的示例展示了如何通过多个 Pod 注入策略修改 Pod spec。

用户提交的 Pod 规约:

podpreset/pod.yaml 使用 PodPreset 将信息注入 Pods - 图11
  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. name: website
  5. labels:
  6. app: website
  7. role: frontend
  8. spec:
  9. containers:
  10. - name: website
  11. image: nginx
  12. ports:
  13. - containerPort: 80

PodPreset 示例:

podpreset/preset.yaml 使用 PodPreset 将信息注入 Pods - 图12
  1. apiVersion: settings.k8s.io/v1alpha1
  2. kind: PodPreset
  3. metadata:
  4. name: allow-database
  5. spec:
  6. selector:
  7. matchLabels:
  8. role: frontend
  9. env:
  10. - name: DB_PORT
  11. value: 6379
  12. volumeMounts:
  13. - mountPath: /cache
  14. name: cache-volume
  15. volumes:
  16. - name: cache-volume
  17. emptyDir: {}

另一个 Pod Preset 示例:

podpreset/proxy.yaml 使用 PodPreset 将信息注入 Pods - 图13
  1. apiVersion: settings.k8s.io/v1alpha1
  2. kind: PodPreset
  3. metadata:
  4. name: proxy
  5. spec:
  6. selector:
  7. matchLabels:
  8. role: frontend
  9. volumeMounts:
  10. - mountPath: /etc/proxy/configs
  11. name: proxy-volume
  12. volumes:
  13. - name: proxy-volume
  14. emptyDir: {}

通过准入控制器后的 Pod 规约:

podpreset/multi-merged.yaml 使用 PodPreset 将信息注入 Pods - 图14
  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. name: website
  5. labels:
  6. app: website
  7. role: frontend
  8. annotations:
  9. podpreset.admission.kubernetes.io/podpreset-allow-database: resource version
  10. podpreset.admission.kubernetes.io/podpreset-proxy: resource version
  11. spec:
  12. containers:
  13. - name: website
  14. image: nginx
  15. volumeMounts:
  16. - mountPath: /cache
  17. name: cache-volume
  18. - mountPath: /etc/proxy/configs
  19. name: proxy-volume
  20. ports:
  21. - containerPort: 80
  22. env:
  23. - name: DB_PORT
  24. value: 6379
  25. volumes:
  26. - name: cache-volume
  27. emptyDir: {}
  28. - name: proxy-volume
  29. emptyDir: {}

冲突示例

这里的示例展示了 PodPreset 与原 Pod 存在冲突时,Pod spec 不会被修改。

用户提交的 Pod 规约:

podpreset/conflict-pod.yaml 使用 PodPreset 将信息注入 Pods - 图15
  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. name: website
  5. labels:
  6. app: website
  7. role: frontend
  8. spec:
  9. containers:
  10. - name: website
  11. image: nginx
  12. volumeMounts:
  13. - mountPath: /cache
  14. name: cache-volume
  15. ports:
  16. - containerPort: 80
  17. volumes:
  18. - name: cache-volume
  19. emptyDir: {}

PodPreset 示例:

podpreset/conflict-preset.yaml 使用 PodPreset 将信息注入 Pods - 图16
  1. apiVersion: settings.k8s.io/v1alpha1
  2. kind: PodPreset
  3. metadata:
  4. name: allow-database
  5. spec:
  6. selector:
  7. matchLabels:
  8. role: frontend
  9. env:
  10. - name: DB_PORT
  11. value: 6379
  12. volumeMounts:
  13. - mountPath: /cache
  14. name: other-volume
  15. volumes:
  16. - name: other-volume
  17. emptyDir: {}

因存在冲突,通过准入控制器后的 Pod spec 不会改变:

podpreset/conflict-pod.yaml 使用 PodPreset 将信息注入 Pods - 图17
  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. name: website
  5. labels:
  6. app: website
  7. role: frontend
  8. spec:
  9. containers:
  10. - name: website
  11. image: nginx
  12. volumeMounts:
  13. - mountPath: /cache
  14. name: cache-volume
  15. ports:
  16. - containerPort: 80
  17. volumes:
  18. - name: cache-volume
  19. emptyDir: {}

如果运行 kubectl describe... 用户会看到以下事件:

  1. $ kubectl describe ...
  2. ....
  3. Events:
  4. FirstSeen LastSeen Count From SubobjectPath Reason Message
  5. Tue, 07 Feb 2017 16:56:12 -0700 Tue, 07 Feb 2017 16:56:12 -0700 1 {podpreset.admission.kubernetes.io/podpreset-allow-database } conflict Conflict on pod preset. Duplicate mountPath /cache.

删除 Pod Preset

一旦用户不再需要 pod preset,可以使用 kubectl 进行删除:

  1. kubectl delete podpreset allow-database
  1. podpreset "allow-database" deleted