在 pod 创建时,用户可以使用 podpreset 对象将特定信息注入 pod 中,这些信息可以包括 secret、 卷、 卷挂载和环境变量。

查看 PodPreset 提案 了解更多信息。

什么是 Pod Preset?

Pod Preset 是一种 API 资源,在 pod 创建时,用户可以用它将额外的运行时需求信息注入 pod。 使用标签选择器(label selector)来指定 Pod Preset 所适用的 pod。 查看更多关于 标签选择器 的信息。

使用 Pod Preset 使得 pod 模板编写者不必显式地为每个 pod 设置信息。 这样,使用特定服务的 pod 模板编写者不需要了解该服务的所有细节。

准入控制

准入控制 是指 Kubernetes 如何将 Pod Preset 应用于接收到的创建请求中。 当出现创建请求时,系统会执行以下操作:

  • 检索全部可用 PodPresets 。
  • 对 PodPreset 的标签选择器和要创建的 pod 进行匹配。
  • 尝试合并 PodPreset 中定义的各种资源,并注入要创建的 pod。
  • 发生错误时抛出事件,该事件记录了 pod 信息合并错误,同时不注入 PodPreset 信息创建 pod。

行为

当 PodPreset 应用于一个或多个 Pod 时, Kubernetes 修改 pod spec。 对于 Env、 EnvFrom 和 VolumeMounts 的改动, Kubernetes 修改 pod 中所有容器的规格, 对于卷的改动,Kubernetes 修改 Pod spec。

Kubernetes 为改动的 pod spec 添加注解,来表明它被 PodPreset 所修改。 注解形如: podpreset.admission.kubernetes.io/podpreset-<pod-preset name>": "<resource version>"。

启用 Pod Preset

为了在集群中使用 Pod Preset,必须确保以下内容

  • 已启用 api 类型 settings.k8s.io/v1alpha1/podpreset
  • 已启用准入控制器 PodPreset
  • 已定义 pod preset

为 Pod 禁用 Pod Preset

在一些情况下,用户不希望 pod 被 pod preset 所改动,这时,用户可以在 pod spec 中添加形如 podpreset.admission.kubernetes.io/exclude: "true" 的注解。

创建 Pod Preset

简单的 Pod Spec 示例

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

用户提交的 pod spec:

  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: ecorp/website
  12. ports:
  13. - containerPort: 80

Pod Preset 示例:

  1. kind: PodPreset
  2. apiVersion: settings.k8s.io/v1alpha1
  3. metadata:
  4. name: allow-database
  5. namespace: myns
  6. spec:
  7. selector:
  8. matchLabels:
  9. role: frontend
  10. env:
  11. - name: DB_PORT
  12. value: "6379"
  13. volumeMounts:
  14. - mountPath: /cache
  15. name: cache-volume
  16. volumes:
  17. - name: cache-volume
  18. emptyDir: {}

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

  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: ecorp/website
  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: {}

带有 ConfigMap 的 Pod Spec 示例

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

用户提交的 pod spec:

  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: ecorp/website
  12. ports:
  13. - containerPort: 80

用户提交的 ConfigMap:

  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"

Pod Preset 示例:

  1. kind: PodPreset
  2. apiVersion: settings.k8s.io/v1alpha1
  3. metadata:
  4. name: allow-database
  5. namespace: myns
  6. spec:
  7. selector:
  8. matchLabels:
  9. role: frontend
  10. env:
  11. - name: DB_PORT
  12. value: 6379
  13. - name: duplicate_key
  14. value: FROM_ENV
  15. - name: expansion
  16. value: $(REPLACE_ME)
  17. envFrom:
  18. - configMapRef:
  19. name: etcd-env-config
  20. volumeMounts:
  21. - mountPath: /cache
  22. name: cache-volume
  23. - mountPath: /etc/app/config.json
  24. readOnly: true
  25. name: secret-volume
  26. volumes:
  27. - name: cache-volume
  28. emptyDir: {}
  29. - name: secret-volume
  30. secret:
  31. secretName: config-details

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

  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: ecorp/website
  14. volumeMounts:
  15. - mountPath: /cache
  16. name: cache-volume
  17. - mountPath: /etc/app/config.json
  18. readOnly: true
  19. name: secret-volume
  20. ports:
  21. - containerPort: 80
  22. env:
  23. - name: DB_PORT
  24. value: "6379"
  25. - name: duplicate_key
  26. value: FROM_ENV
  27. - name: expansion
  28. value: $(REPLACE_ME)
  29. envFrom:
  30. - configMapRef:
  31. name: etcd-env-config
  32. volumes:
  33. - name: cache-volume
  34. emptyDir: {}
  35. - name: secret-volume
  36. secret:
  37. secretName: config-details

带有 Pod Spec 的 ReplicaSet 示例

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

用户提交的 ReplicaSet:

  1. apiVersion: settings.k8s.io/v1alpha1
  2. kind: ReplicaSet
  3. metadata:
  4. name: frontend
  5. spec:
  6. replicas: 3
  7. selector:
  8. matchLabels:
  9. tier: frontend
  10. matchExpressions:
  11. - {key: tier, operator: In, values: [frontend]}
  12. template:
  13. metadata:
  14. labels:
  15. app: guestbook
  16. tier: 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

Pod Preset 示例:

  1. kind: PodPreset
  2. apiVersion: settings.k8s.io/v1alpha1
  3. metadata:
  4. name: allow-database
  5. namespace: myns
  6. spec:
  7. selector:
  8. matchLabels:
  9. tier: frontend
  10. env:
  11. - name: DB_PORT
  12. value: "6379"
  13. volumeMounts:
  14. - mountPath: /cache
  15. name: cache-volume
  16. volumes:
  17. - name: cache-volume
  18. emptyDir: {}

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

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

多 PodPreset 示例

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

用户提交的 pod spec:

  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: ecorp/website
  12. ports:
  13. - containerPort: 80

Pod Preset 示例:

  1. kind: PodPreset
  2. apiVersion: settings.k8s.io/v1alpha1
  3. metadata:
  4. name: allow-database
  5. namespace: myns
  6. spec:
  7. selector:
  8. matchLabels:
  9. role: frontend
  10. env:
  11. - name: DB_PORT
  12. value: "6379"
  13. volumeMounts:
  14. - mountPath: /cache
  15. name: cache-volume
  16. volumes:
  17. - name: cache-volume
  18. emptyDir: {}

另一个 Pod Preset:

  1. kind: PodPreset
  2. apiVersion: settings.k8s.io/v1alpha1
  3. metadata:
  4. name: proxy
  5. namespace: myns
  6. spec:
  7. selector:
  8. matchLabels:
  9. role: frontend
  10. volumeMounts:
  11. - mountPath: /etc/proxy/configs
  12. name: proxy-volume
  13. volumes:
  14. - name: proxy-volume
  15. emptyDir: {}

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

  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: ecorp/website
  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: {}

冲突示例

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

用户提交的 pod spec:

  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: ecorp/website
  12. volumeMounts:
  13. - mountPath: /cache
  14. name: cache-volume
  15. ports:
  16. volumes:
  17. - name: cache-volume
  18. emptyDir: {}
  19. - containerPort: 80

Pod Preset 示例:

  1. kind: PodPreset
  2. apiVersion: settings.k8s.io/v1alpha1
  3. metadata:
  4. name: allow-database
  5. namespace: myns
  6. spec:
  7. selector:
  8. matchLabels:
  9. role: frontend
  10. env:
  11. - name: DB_PORT
  12. value: "6379"
  13. volumeMounts:
  14. - mountPath: /cache
  15. name: other-volume
  16. volumes:
  17. - name: other-volume
  18. emptyDir: {}

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

  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: ecorp/website
  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
  2. podpreset "allow-database" deleted

译者:lichuqiang / 原文链接

K8S中文社区微信公众号

原文: http://docs.kubernetes.org.cn/789.html