From 4b85efed41320ee8d5d2eedbf8e9e3e2ffd72e32 Mon Sep 17 00:00:00 2001 From: Vedant Koditkar Date: Tue, 15 Feb 2022 12:22:46 +0530 Subject: [PATCH 01/73] Update hyperlinks to point to main branch --- content/ja/docs/contribute/participate/_index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/content/ja/docs/contribute/participate/_index.md b/content/ja/docs/contribute/participate/_index.md index bf21148c40757..740c44d6e83e1 100644 --- a/content/ja/docs/contribute/participate/_index.md +++ b/content/ja/docs/contribute/participate/_index.md @@ -68,8 +68,8 @@ Kubernetesプロジェクトは、GitHubのissueとPull Requestに関連する - approve これらの2つのプラグインは`kubernetes.website`のGithubリポジトリのトップレベルにある -[OWNERS](https://github.com/kubernetes/website/blob/master/OWNERS)ファイルと、 -[OWNERS_ALIASES](https://github.com/kubernetes/website/blob/master/OWNERS_ALIASES)ファイルを使用して、 +[OWNERS](https://github.com/kubernetes/website/blob/main/OWNERS)ファイルと、 +[OWNERS_ALIASES](https://github.com/kubernetes/website/blob/main/OWNERS_ALIASES)ファイルを使用して、 リポジトリ内でのprowの動作を制御します。 OWNERSファイルには、SIG Docsのレビュー担当者および承認者であるユーザーのリストが含まれています。 From aa8b37770ea3a851c732874e2938b020742094b4 Mon Sep 17 00:00:00 2001 From: Shubham Kuchhal Date: Tue, 8 Mar 2022 13:10:22 +0530 Subject: [PATCH 02/73] Improvement: Updated FEATURE STATE of NamespaceDefaultLabelName. --- .../en/docs/concepts/services-networking/network-policies.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/en/docs/concepts/services-networking/network-policies.md b/content/en/docs/concepts/services-networking/network-policies.md index 7c01017f05070..884cfc960d39a 100644 --- a/content/en/docs/concepts/services-networking/network-policies.md +++ b/content/en/docs/concepts/services-networking/network-policies.md @@ -281,7 +281,7 @@ the policy will be applied only for the single `port` field. ## Targeting a Namespace by its name -{{< feature-state state="beta" for_k8s_version="1.21" >}} +{{< feature-state for_k8s_version="1.22" state="stable" >}} The Kubernetes control plane sets an immutable label `kubernetes.io/metadata.name` on all namespaces, provided that the `NamespaceDefaultLabelName` From 461a09332b34e25501303ec7f28fcb14b366cb47 Mon Sep 17 00:00:00 2001 From: Qiming Teng Date: Wed, 9 Mar 2022 21:28:09 +0800 Subject: [PATCH 03/73] [zh] Tune the feature gates page Reformat some line wraps, reorder some items in the description and fix a version missing in table 1. --- .../feature-gates.md | 171 +++++++++++------- 1 file changed, 101 insertions(+), 70 deletions(-) diff --git a/content/en/docs/reference/command-line-tools-reference/feature-gates.md b/content/en/docs/reference/command-line-tools-reference/feature-gates.md index 4e1b4c6184258..f33d2d747f9d7 100644 --- a/content/en/docs/reference/command-line-tools-reference/feature-gates.md +++ b/content/en/docs/reference/command-line-tools-reference/feature-gates.md @@ -74,7 +74,7 @@ different Kubernetes components. | `CSIInlineVolume` | `true` | Beta | 1.16 | - | | `CSIMigration` | `false` | Alpha | 1.14 | 1.16 | | `CSIMigration` | `true` | Beta | 1.17 | | -| `CSIMigrationAWS` | `false` | Alpha | 1.14 | | +| `CSIMigrationAWS` | `false` | Alpha | 1.14 | 1.16 | | `CSIMigrationAWS` | `false` | Beta | 1.17 | 1.22 | | `CSIMigrationAWS` | `true` | Beta | 1.23 | | | `CSIMigrationAzureDisk` | `false` | Alpha | 1.15 | 1.18 | @@ -579,39 +579,47 @@ Each feature gate is designed for enabling/disabling a specific feature: See [AppArmor Tutorial](/docs/tutorials/security/apparmor/) for more details. - `AttachVolumeLimit`: Enable volume plugins to report limits on number of volumes that can be attached to a node. - See [dynamic volume limits](/docs/concepts/storage/storage-limits/#dynamic-volume-limits) for more details. -- `BalanceAttachedNodeVolumes`: Include volume count on node to be considered for balanced resource allocation - while scheduling. A node which has closer CPU, memory utilization, and volume count is favored by the scheduler - while making decisions. + See [dynamic volume limits](/docs/concepts/storage/storage-limits/#dynamic-volume-limits) + for more details. +- `BalanceAttachedNodeVolumes`: Include volume count on node to be considered for + balanced resource allocation while scheduling. A node which has closer CPU, + memory utilization, and volume count is favored by the scheduler while making decisions. - `BlockVolume`: Enable the definition and consumption of raw block devices in Pods. See [Raw Block Volume Support](/docs/concepts/storage/persistent-volumes/#raw-block-volume-support) for more details. -- `BoundServiceAccountTokenVolume`: Migrate ServiceAccount volumes to use a projected volume consisting of a - ServiceAccountTokenVolumeProjection. Cluster admins can use metric `serviceaccount_stale_tokens_total` to - monitor workloads that are depending on the extended tokens. If there are no such workloads, turn off - extended tokens by starting `kube-apiserver` with flag `--service-account-extend-token-expiration=false`. +- `BoundServiceAccountTokenVolume`: Migrate ServiceAccount volumes to use a projected volume + consisting of a ServiceAccountTokenVolumeProjection. Cluster admins can use metric + `serviceaccount_stale_tokens_total` to monitor workloads that are depending on the extended + tokens. If there are no such workloads, turn off extended tokens by starting `kube-apiserver` with + flag `--service-account-extend-token-expiration=false`. Check [Bound Service Account Tokens](https://github.com/kubernetes/enhancements/blob/master/keps/sig-auth/1205-bound-service-account-tokens/README.md) - for more details. + for more details. - `ControllerManagerLeaderMigration`: Enables Leader Migration for [kube-controller-manager](/docs/tasks/administer-cluster/controller-manager-leader-migration/#initial-leader-migration-configuration) and - [cloud-controller-manager](/docs/tasks/administer-cluster/controller-manager-leader-migration/#deploy-cloud-controller-manager) which allows a cluster operator to live migrate + [cloud-controller-manager](/docs/tasks/administer-cluster/controller-manager-leader-migration/#deploy-cloud-controller-manager) + which allows a cluster operator to live migrate controllers from the kube-controller-manager into an external controller-manager (e.g. the cloud-controller-manager) in an HA cluster without downtime. - `CPUManager`: Enable container level CPU affinity support, see [CPU Management Policies](/docs/tasks/administer-cluster/cpu-management-policies/). -- `CPUManagerPolicyAlphaOptions`: This allows fine-tuning of CPUManager policies, experimental, Alpha-quality options +- `CPUManagerPolicyAlphaOptions`: This allows fine-tuning of CPUManager policies, + experimental, Alpha-quality options This feature gate guards *a group* of CPUManager options whose quality level is alpha. This feature gate will never graduate to beta or stable. -- `CPUManagerPolicyBetaOptions`: This allows fine-tuning of CPUManager policies, experimental, Beta-quality options +- `CPUManagerPolicyBetaOptions`: This allows fine-tuning of CPUManager policies, + experimental, Beta-quality options This feature gate guards *a group* of CPUManager options whose quality level is beta. This feature gate will never graduate to stable. - `CPUManagerPolicyOptions`: Allow fine-tuning of CPUManager policies. -- `CRIContainerLogRotation`: Enable container log rotation for CRI container runtime. The default max size of a log file is 10MB and the - default max number of log files allowed for a container is 5. These values can be configured in the kubelet config. - See the [logging at node level](/docs/concepts/cluster-administration/logging/#logging-at-the-node-level) documentation for more details. +- `CRIContainerLogRotation`: Enable container log rotation for CRI container runtime. + The default max size of a log file is 10MB and the default max number of + log files allowed for a container is 5. + These values can be configured in the kubelet config. + See [logging at node level](/docs/concepts/cluster-administration/logging/#logging-at-the-node-level) + for more details. - `CSIBlockVolume`: Enable external CSI volume drivers to support block storage. - See the [`csi` raw block volume support](/docs/concepts/storage/volumes/#csi-raw-block-volume-support) - documentation for more details. + See [`csi` raw block volume support](/docs/concepts/storage/volumes/#csi-raw-block-volume-support) + for more details. - `CSIDriverRegistry`: Enable all logic related to the CSIDriver API object in csi.storage.k8s.io. - `CSIInlineVolume`: Enable CSI Inline volumes support for pods. @@ -643,7 +651,8 @@ Each feature gate is designed for enabling/disabling a specific feature: AzureDisk CSI plugin. Requires CSIMigration and CSIMigrationAzureDisk feature flags enabled and AzureDisk CSI plugin installed and configured on all nodes in the cluster. This flag has been deprecated in favor of the - `InTreePluginAzureDiskUnregister` feature flag which prevents the registration of in-tree AzureDisk plugin. + `InTreePluginAzureDiskUnregister` feature flag which prevents the registration + of in-tree AzureDisk plugin. - `CSIMigrationAzureFile`: Enables shims and translation logic to route volume operations from the Azure-File in-tree plugin to AzureFile CSI plugin. Supports falling back to in-tree AzureFile plugin for mount operations to @@ -666,19 +675,13 @@ Each feature gate is designed for enabling/disabling a specific feature: Does not support falling back for provision operations, for those the CSI plugin must be installed and configured. Requires CSIMigration feature flag enabled. -- `csiMigrationRBD`: Enables shims and translation logic to route volume - operations from the RBD in-tree plugin to Ceph RBD CSI plugin. Requires - CSIMigration and csiMigrationRBD feature flags enabled and Ceph CSI plugin - installed and configured in the cluster. This flag has been deprecated in - favor of the - `InTreePluginRBDUnregister` feature flag which prevents the registration of - in-tree RBD plugin. - `CSIMigrationGCEComplete`: Stops registering the GCE-PD in-tree plugin in kubelet and volume controllers and enables shims and translation logic to route volume operations from the GCE-PD in-tree plugin to PD CSI plugin. Requires CSIMigration and CSIMigrationGCE feature flags enabled and PD CSI plugin installed and configured on all nodes in the cluster. This flag has - been deprecated in favor of the `InTreePluginGCEUnregister` feature flag which prevents the registration of in-tree GCE PD plugin. + been deprecated in favor of the `InTreePluginGCEUnregister` feature flag which + prevents the registration of in-tree GCE PD plugin. - `CSIMigrationOpenStack`: Enables shims and translation logic to route volume operations from the Cinder in-tree plugin to Cinder CSI plugin. Supports falling back to in-tree Cinder plugin for mount operations to nodes that have @@ -691,7 +694,14 @@ Each feature gate is designed for enabling/disabling a specific feature: volume operations from the Cinder in-tree plugin to Cinder CSI plugin. Requires CSIMigration and CSIMigrationOpenStack feature flags enabled and Cinder CSI plugin installed and configured on all nodes in the cluster. This flag has - been deprecated in favor of the `InTreePluginOpenStackUnregister` feature flag which prevents the registration of in-tree openstack cinder plugin. + been deprecated in favor of the `InTreePluginOpenStackUnregister` feature flag + which prevents the registration of in-tree openstack cinder plugin. +- `csiMigrationRBD`: Enables shims and translation logic to route volume + operations from the RBD in-tree plugin to Ceph RBD CSI plugin. Requires + CSIMigration and csiMigrationRBD feature flags enabled and Ceph CSI plugin + installed and configured in the cluster. This flag has been deprecated in + favor of the `InTreePluginRBDUnregister` feature flag which prevents the registration of + in-tree RBD plugin. - `CSIMigrationvSphere`: Enables shims and translation logic to route volume operations from the vSphere in-tree plugin to vSphere CSI plugin. Supports falling back to in-tree vSphere plugin for mount operations to nodes that have the feature @@ -704,11 +714,12 @@ Each feature gate is designed for enabling/disabling a specific feature: from the vSphere in-tree plugin to vSphere CSI plugin. Requires CSIMigration and CSIMigrationvSphere feature flags enabled and vSphere CSI plugin installed and configured on all nodes in the cluster. This flag has been deprecated in favor - of the `InTreePluginvSphereUnregister` feature flag which prevents the registration of in-tree vsphere plugin. + of the `InTreePluginvSphereUnregister` feature flag which prevents the + registration of in-tree vsphere plugin. - `CSIMigrationPortworx`: Enables shims and translation logic to route volume operations from the Portworx in-tree plugin to Portworx CSI plugin. - Requires Portworx CSI driver to be installed and configured in the cluster, and feature gate set `CSIMigrationPortworx=true` in kube-controller-manager and kubelet configs. -- `CSINodeInfo`: Enable all logic related to the CSINodeInfo API object in csi.storage.k8s.io. + Requires Portworx CSI driver to be installed and configured in the cluster. +- `CSINodeInfo`: Enable all logic related to the CSINodeInfo API object in `csi.storage.k8s.io`. - `CSIPersistentVolume`: Enable discovering and mounting volumes provisioned through a [CSI (Container Storage Interface)](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/storage/container-storage-interface.md) compatible volume plugin. @@ -736,7 +747,9 @@ Each feature gate is designed for enabling/disabling a specific feature: version 1 of the same controller is selected. - `CustomCPUCFSQuotaPeriod`: Enable nodes to change `cpuCFSQuotaPeriod` in [kubelet config](/docs/tasks/administer-cluster/kubelet-config-file/). -- `CustomResourceValidationExpressions`: Enable expression language validation in CRD which will validate customer resource based on validation rules written in `x-kubernetes-validations` extension. +- `CustomResourceValidationExpressions`: Enable expression language validation in CRD + which will validate customer resource based on validation rules written in + the `x-kubernetes-validations` extension. - `CustomPodDNS`: Enable customizing the DNS settings for a Pod using its `dnsConfig` property. Check [Pod's DNS Config](/docs/concepts/services-networking/dns-pod-service/#pods-dns-config) for more details. @@ -819,7 +832,8 @@ Each feature gate is designed for enabling/disabling a specific feature: host mounts, or containers that are privileged or using specific non-namespaced capabilities (e.g. `MKNODE`, `SYS_MODULE` etc.). This should only be enabled if user namespace remapping is enabled in the Docker daemon. -- `ExternalPolicyForExternalIP`: Fix a bug where ExternalTrafficPolicy is not applied to Service ExternalIPs. +- `ExternalPolicyForExternalIP`: Fix a bug where ExternalTrafficPolicy is not + applied to Service ExternalIPs. - `GCERegionalPersistentDisk`: Enable the regional PD feature on GCE. - `GenericEphemeralVolume`: Enables ephemeral, inline volumes that support all features of normal volumes (can be provided by third-party storage vendors, storage capacity tracking, @@ -832,8 +846,10 @@ Each feature gate is designed for enabling/disabling a specific feature: for more details. - `GracefulNodeShutdownBasedOnPodPriority`: Enables the kubelet to check Pod priorities when shutting down a node gracefully. -- `GRPCContainerProbe`: Enables the gRPC probe method for {Liveness,Readiness,Startup}Probe. See [Configure Liveness, Readiness and Startup Probes](/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/#define-a-grpc-liveness-probe). -- `HonorPVReclaimPolicy`: Honor persistent volume reclaim policy when it is `Delete` irrespective of PV-PVC deletion ordering. +- `GRPCContainerProbe`: Enables the gRPC probe method for {Liveness,Readiness,Startup}Probe. + See [Configure Liveness, Readiness and Startup Probes](/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/#define-a-grpc-liveness-probe). +- `HonorPVReclaimPolicy`: Honor persistent volume reclaim policy when it is `Delete` + irrespective of PV-PVC deletion ordering. - `HPAContainerMetrics`: Enable the `HorizontalPodAutoscaler` to scale based on metrics from individual containers in target pods. - `HPAScaleToZero`: Enables setting `minReplicas` to 0 for `HorizontalPodAutoscaler` @@ -845,10 +861,19 @@ Each feature gate is designed for enabling/disabling a specific feature: - `HyperVContainer`: Enable [Hyper-V isolation](https://docs.microsoft.com/en-us/virtualization/windowscontainers/manage-containers/hyperv-container) for Windows containers. -- `IdentifyPodOS`: Allows the Pod OS field to be specified. This helps in identifying the OS of the pod - authoritatively during the API server admission time. In Kubernetes {{< skew currentVersion >}}, the allowed values for the `pod.spec.os.name` are `windows` and `linux`. +- `IdentifyPodOS`: Allows the Pod OS field to be specified. This helps in identifying + the OS of the pod authoritatively during the API server admission time. + In Kubernetes {{< skew currentVersion >}}, the allowed values for the `pod.spec.os.name` + are `windows` and `linux`. - `ImmutableEphemeralVolumes`: Allows for marking individual Secrets and ConfigMaps as immutable for better safety and performance. +- `IndexedJob`: Allows the [Job](/docs/concepts/workloads/controllers/job/) + controller to manage Pod completions per completion index. +- `IngressClassNamespacedParams`: Allow namespace-scoped parameters reference in + `IngressClass` resource. This feature adds two fields - `Scope` and `Namespace` + to `IngressClass.spec.parameters`. +- `Initializers`: Allow asynchronous coordination of object creation using the + Initializers admission plugin. - `InTreePluginAWSUnregister`: Stops registering the aws-ebs in-tree plugin in kubelet and volume controllers. - `InTreePluginAzureDiskUnregister`: Stops registering the azuredisk in-tree plugin in kubelet @@ -865,13 +890,6 @@ Each feature gate is designed for enabling/disabling a specific feature: and volume controllers. - `InTreePluginvSphereUnregister`: Stops registering the vSphere in-tree plugin in kubelet and volume controllers. -- `IndexedJob`: Allows the [Job](/docs/concepts/workloads/controllers/job/) - controller to manage Pod completions per completion index. -- `IngressClassNamespacedParams`: Allow namespace-scoped parameters reference in - `IngressClass` resource. This feature adds two fields - `Scope` and `Namespace` - to `IngressClass.spec.parameters`. -- `Initializers`: Allow asynchronous coordination of object creation using the - Initializers admission plugin. - `IPv6DualStack`: Enable [dual stack](/docs/concepts/services-networking/dual-stack/) support for IPv6. - `JobMutableNodeSchedulingDirectives`: Allows updating node scheduling directives in @@ -889,17 +907,21 @@ Each feature gate is designed for enabling/disabling a specific feature: a file specified using a config file. See [setting kubelet parameters via a config file](/docs/tasks/administer-cluster/kubelet-config-file/) for more details. -- `KubeletCredentialProviders`: Enable kubelet exec credential providers for image pull credentials. -- `KubeletInUserNamespace`: Enables support for running kubelet in a {{}}. +- `KubeletCredentialProviders`: Enable kubelet exec credential providers for + image pull credentials. +- `KubeletInUserNamespace`: Enables support for running kubelet in a + {{}}. See [Running Kubernetes Node Components as a Non-root User](/docs/tasks/administer-cluster/kubelet-in-userns/). - `KubeletPluginsWatcher`: Enable probe-based plugin watcher utility to enable kubelet to discover plugins such as [CSI volume drivers](/docs/concepts/storage/volumes/#csi). - `KubeletPodResources`: Enable the kubelet's pod resources gRPC endpoint. See [Support Device Monitoring](https://github.com/kubernetes/enhancements/blob/master/keps/sig-node/606-compute-device-assignment/README.md) for more details. -- `KubeletPodResourcesGetAllocatable`: Enable the kubelet's pod resources `GetAllocatableResources` functionality. - This API augments the [resource allocation reporting](/docs/concepts/extend-kubernetes/compute-storage-net/device-plugins/#monitoring-device-plugin-resources) - with informations about the allocatable resources, enabling clients to properly track the free compute resources on a node. +- `KubeletPodResourcesGetAllocatable`: Enable the kubelet's pod resources + `GetAllocatableResources` functionality. This API augments the + [resource allocation reporting](/docs/concepts/extend-kubernetes/compute-storage-net/device-plugins/#monitoring-device-plugin-resources) + with informations about the allocatable resources, enabling clients to properly + track the free compute resources on a node. - `LegacyNodeRoleBehavior`: When disabled, legacy behavior in service load balancers and node disruption will ignore the `node-role.kubernetes.io/master` label in favor of the feature-specific labels provided by `NodeDisruptionExclusion` and `ServiceNodeExclusion`. @@ -918,18 +940,22 @@ Each feature gate is designed for enabling/disabling a specific feature: based on logarithmic bucketing of pod timestamps. - `MemoryManager`: Allows setting memory affinity for a container based on NUMA topology. -- `MemoryQoS`: Enable memory protection and usage throttle on pod / container using cgroup v2 memory controller. +- `MemoryQoS`: Enable memory protection and usage throttle on pod / container using + cgroup v2 memory controller. - `MixedProtocolLBService`: Enable using different protocols in the same `LoadBalancer` type Service instance. - `MountContainers`: Enable using utility containers on host as the volume mounter. - `MountPropagation`: Enable sharing volume mounted by one container to other containers or pods. For more details, please see [mount propagation](/docs/concepts/storage/volumes/#mount-propagation). -- `NamespaceDefaultLabelName`: Configure the API Server to set an immutable {{< glossary_tooltip text="label" term_id="label" >}} - `kubernetes.io/metadata.name` on all namespaces, containing the namespace name. -- `NetworkPolicyEndPort`: Enable use of the field `endPort` in NetworkPolicy objects, allowing the selection of a port range instead of a single port. +- `NamespaceDefaultLabelName`: Configure the API Server to set an immutable + {{< glossary_tooltip text="label" term_id="label" >}} `kubernetes.io/metadata.name` + on all namespaces, containing the namespace name. +- `NetworkPolicyEndPort`: Enable use of the field `endPort` in NetworkPolicy objects, + allowing the selection of a port range instead of a single port. - `NodeDisruptionExclusion`: Enable use of the Node label `node.kubernetes.io/exclude-disruption` which prevents nodes from being evacuated during zone failures. -- `NodeLease`: Enable the new Lease API to report node heartbeats, which could be used as a node health signal. +- `NodeLease`: Enable the new Lease API to report node heartbeats, which could be used + as a node health signal. - `NodeSwap`: Enable the kubelet to allocate swap memory for Kubernetes workloads on a node. Must be used with `KubeletConfiguration.failSwapOn` set to false. For more details, please see [swap memory](/docs/concepts/architecture/nodes/#swap-memory) @@ -937,23 +963,23 @@ Each feature gate is designed for enabling/disabling a specific feature: - `OpenAPIEnums`: Enables populating "enum" fields of OpenAPI schemas in the spec returned from the API server. - `OpenAPIV3`: Enables the API server to publish OpenAPI v3. -- `PVCProtection`: Enable the prevention of a PersistentVolumeClaim (PVC) from - being deleted when it is still used by any Pod. - `PodDeletionCost`: Enable the [Pod Deletion Cost](/docs/concepts/workloads/controllers/replicaset/#pod-deletion-cost) feature which allows users to influence ReplicaSet downscaling order. - `PersistentLocalVolumes`: Enable the usage of `local` volume type in Pods. Pod affinity has to be specified if requesting a `local` volume. -- `PodAndContainerStatsFromCRI`: Configure the kubelet to gather container and pod stats from the CRI container runtime - rather than gathering them from cAdvisor. +- `PodAndContainerStatsFromCRI`: Configure the kubelet to gather container and + pod stats from the CRI container runtime rather than gathering them from cAdvisor. - `PodDisruptionBudget`: Enable the [PodDisruptionBudget](/docs/tasks/run-application/configure-pdb/) feature. -- `PodAffinityNamespaceSelector`: Enable the [Pod Affinity Namespace Selector](/docs/concepts/scheduling-eviction/assign-pod-node/#namespace-selector) - and [CrossNamespacePodAffinity](/docs/concepts/policy/resource-quotas/#cross-namespace-pod-affinity-quota) quota scope features. +- `PodAffinityNamespaceSelector`: Enable the + [Pod Affinity Namespace Selector](/docs/concepts/scheduling-eviction/assign-pod-node/#namespace-selector) + and [CrossNamespacePodAffinity](/docs/concepts/policy/resource-quotas/#cross-namespace-pod-affinity-quota) + quota scope features. - `PodOverhead`: Enable the [PodOverhead](/docs/concepts/scheduling-eviction/pod-overhead/) feature to account for pod overheads. - `PodPriority`: Enable the descheduling and preemption of Pods based on their [priorities](/docs/concepts/scheduling-eviction/pod-priority-preemption/). - `PodReadinessGates`: Enable the setting of `PodReadinessGate` field for extending - Pod readiness evaluation. See [Pod readiness gate](/docs/concepts/workloads/pods/pod-lifecycle/#pod-readiness-gate) + Pod readiness evaluation. See [Pod readiness gate](/docs/concepts/workloads/pods/pod-lifecycle/#pod-readiness-gate) for more details. - `PodSecurity`: Enables the `PodSecurity` admission plugin. - `PodShareProcessNamespace`: Enable the setting of `shareProcessNamespace` in a Pod for sharing @@ -964,25 +990,27 @@ Each feature gate is designed for enabling/disabling a specific feature: the cluster. - `ProbeTerminationGracePeriod`: Enable [setting probe-level `terminationGracePeriodSeconds`](/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/#probe-level-terminationgraceperiodseconds) - on pods. See the [enhancement proposal](https://github.com/kubernetes/enhancements/tree/master/keps/sig-node/2238-liveness-probe-grace-period) for more details. + on pods. See the [enhancement proposal](https://github.com/kubernetes/enhancements/tree/master/keps/sig-node/2238-liveness-probe-grace-period) + for more details. - `ProcMountType`: Enables control over the type proc mounts for containers by setting the `procMount` field of a SecurityContext. - `ProxyTerminatingEndpoints`: Enable the kube-proxy to handle terminating endpoints when `ExternalTrafficPolicy=Local`. +- `PVCProtection`: Enable the prevention of a PersistentVolumeClaim (PVC) from + being deleted when it is still used by any Pod. - `QOSReserved`: Allows resource reservations at the QoS level preventing pods at lower QoS levels from bursting into resources requested at higher QoS levels (memory only for now). - `ReadWriteOncePod`: Enables the usage of `ReadWriteOncePod` PersistentVolume access mode. -- `RecoverVolumeExpansionFailure`: Enables users to edit their PVCs to smaller sizes so as they can recover from previously issued - volume expansion failures. See - [Recovering from Failure when Expanding Volumes](/docs/concepts/storage/persistent-volumes/#recovering-from-failure-when-expanding-volumes) +- `RecoverVolumeExpansionFailure`: Enables users to edit their PVCs to smaller + sizes so as they can recover from previously issued volume expansion failures. + See [Recovering from Failure when Expanding Volumes](/docs/concepts/storage/persistent-volumes/#recovering-from-failure-when-expanding-volumes) for more details. - `RemainingItemCount`: Allow the API servers to show a count of remaining items in the response to a [chunking list request](/docs/reference/using-api/api-concepts/#retrieving-large-results-sets-in-chunks). -- `RemoveSelfLink`: Deprecates and removes `selfLink` from ObjectMeta and - ListMeta. +- `RemoveSelfLink`: Deprecates and removes `selfLink` from ObjectMeta and ListMeta. - `RequestManagement`: Enables managing request concurrency with prioritization and fairness at each API server. Deprecated by `APIPriorityAndFairness` since 1.17. - `ResourceLimitsPriorityFunction`: Enable a scheduler priority function that @@ -997,7 +1025,8 @@ Each feature gate is designed for enabling/disabling a specific feature: [Bound Service Account Tokens](https://github.com/kubernetes/enhancements/blob/master/keps/sig-auth/1205-bound-service-account-tokens/README.md) for more details. - `RotateKubeletClientCertificate`: Enable the rotation of the client TLS certificate on the kubelet. - See [kubelet configuration](/docs/reference/command-line-tools-reference/kubelet-tls-bootstrapping/#kubelet-configuration) for more details. + See [kubelet configuration](/docs/reference/command-line-tools-reference/kubelet-tls-bootstrapping/#kubelet-configuration) + for more details. - `RotateKubeletServerCertificate`: Enable the rotation of the server TLS certificate on the kubelet. See [kubelet configuration](/docs/reference/command-line-tools-reference/kubelet-tls-bootstrapping/#kubelet-configuration) for more details. @@ -1009,7 +1038,8 @@ Each feature gate is designed for enabling/disabling a specific feature: instead of the DaemonSet controller. - `SCTPSupport`: Enables the _SCTP_ `protocol` value in Pod, Service, Endpoints, EndpointSlice, and NetworkPolicy definitions. -- `SeccompDefault`: Enables the use of `RuntimeDefault` as the default seccomp profile for all workloads. +- `SeccompDefault`: Enables the use of `RuntimeDefault` as the default seccomp profile + for all workloads. The seccomp profile is specified in the `securityContext` of a Pod and/or a Container. - `SelectorIndex`: Allows label and field based indexes in API server watch cache to accelerate list operations. @@ -1023,7 +1053,8 @@ Each feature gate is designed for enabling/disabling a specific feature: - `ServiceInternalTrafficPolicy`: Enables the `internalTrafficPolicy` field on Services - `ServiceLBNodePortControl`: Enables the `allocateLoadBalancerNodePorts` field on Services. - `ServiceLoadBalancerClass`: Enables the `loadBalancerClass` field on Services. See - [Specifying class of load balancer implementation](/docs/concepts/services-networking/service/#load-balancer-class) for more details. + [Specifying class of load balancer implementation](/docs/concepts/services-networking/service/#load-balancer-class) + for more details. - `ServiceLoadBalancerFinalizer`: Enable finalizer protection for Service load balancers. - `ServiceNodeExclusion`: Enable the exclusion of nodes from load balancers created by a cloud provider. A node is eligible for exclusion if labelled with From 7e54b18dd4abf3226baf8c09d1fbce8ef22becce Mon Sep 17 00:00:00 2001 From: PriyanshuAhlawat Date: Wed, 16 Mar 2022 01:31:54 +0530 Subject: [PATCH 04/73] Update controlling-access.md --- .../en/docs/concepts/security/controlling-access.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/content/en/docs/concepts/security/controlling-access.md b/content/en/docs/concepts/security/controlling-access.md index 1a0c93d8cfeaa..7db564b3dc88b 100644 --- a/content/en/docs/concepts/security/controlling-access.md +++ b/content/en/docs/concepts/security/controlling-access.md @@ -130,6 +130,16 @@ Once a request passes all admission controllers, it is validated using the valid for the corresponding API object, and then written to the object store (shown as step **4**). +## Auditing + +Kubernetes auditing provides a security-relevant, chronological set of records documenting the sequence of actions in a cluster. +The cluster audits the activities generated by users, by applications that use the Kubernetes API, and by the control plane itself. +Each request on each stage of its execution generates an audit event, which is then pre-processed according to a certain policy and written to a backend. +The policy determines what's recorded when an event is processed and it's compared against the list of rules in order. The first matching rule sets the audit level of the event. +The defined audit levels are: None, Metadata, Request and RequestResponse. +The Audit backends persist audit events to an external storage. By default kube-apiserver provides two backends: log and webhook backend. + + ## API server ports and IPs The previous discussion applies to requests sent to the secure port of the API server From c7952b2c3ee47534f37c197189680fbf00eab1b3 Mon Sep 17 00:00:00 2001 From: PriyanshuAhlawat Date: Wed, 16 Mar 2022 19:16:46 +0530 Subject: [PATCH 05/73] Update controlling-access.md --- content/en/docs/concepts/security/controlling-access.md | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/content/en/docs/concepts/security/controlling-access.md b/content/en/docs/concepts/security/controlling-access.md index 7db564b3dc88b..97cf71f829f6f 100644 --- a/content/en/docs/concepts/security/controlling-access.md +++ b/content/en/docs/concepts/security/controlling-access.md @@ -129,16 +129,12 @@ The available Admission Control modules are described in [Admission Controllers] Once a request passes all admission controllers, it is validated using the validation routines for the corresponding API object, and then written to the object store (shown as step **4**). - ## Auditing Kubernetes auditing provides a security-relevant, chronological set of records documenting the sequence of actions in a cluster. The cluster audits the activities generated by users, by applications that use the Kubernetes API, and by the control plane itself. -Each request on each stage of its execution generates an audit event, which is then pre-processed according to a certain policy and written to a backend. -The policy determines what's recorded when an event is processed and it's compared against the list of rules in order. The first matching rule sets the audit level of the event. -The defined audit levels are: None, Metadata, Request and RequestResponse. -The Audit backends persist audit events to an external storage. By default kube-apiserver provides two backends: log and webhook backend. +For more information, see "[Auditing](https://kubernetes.io/docs/tasks/debug-application-cluster/audit/)". ## API server ports and IPs From 3d78bd31df665899ab5eda0a865e4a5335246442 Mon Sep 17 00:00:00 2001 From: PriyanshuAhlawat Date: Thu, 17 Mar 2022 02:21:16 +0530 Subject: [PATCH 06/73] Update create-cluster-kubeadm.md --- .../tools/kubeadm/create-cluster-kubeadm.md | 53 ++++++++++++++++--- 1 file changed, 47 insertions(+), 6 deletions(-) diff --git a/content/en/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm.md b/content/en/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm.md index e9b423e279559..343aa4a60c4c8 100644 --- a/content/en/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm.md +++ b/content/en/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm.md @@ -524,15 +524,56 @@ options. ## Version skew policy {#version-skew-policy} -The `kubeadm` tool of version v{{< skew latestVersion >}} may deploy clusters with a control plane of version v{{< skew latestVersion >}} or v{{< skew prevMinorVersion >}}. -`kubeadm` v{{< skew latestVersion >}} can also upgrade an existing kubeadm-created cluster of version v{{< skew prevMinorVersion >}}. +While kubeadm allows version skew against some components that it manages, it is recommended that you +match the kubeadm version with the versions of the control plane components, kube-proxy and kubelet. -Due to that we can't see into the future, kubeadm CLI v{{< skew latestVersion >}} may or may not be able to deploy v{{< skew nextMinorVersion >}} clusters. +### kubeadm's skew against the Kubernetes version -These resources provide more information on supported version skew between kubelets and the control plane, and other Kubernetes components: +kubeadm can be used with Kubernetes components that are the same version as kubeadm +or one version older. The Kubernetes version can be specified to kubeadm by using the +`--kubernetes-version` flag of `kubeadm init` or the +[`ClusterConfiguration.kubernetesVersion`](/docs/reference/config-api/kubeadm-config.v1beta3/) +field when using `--config`. This option will control the versions +of kube-apiserver, kube-controller-manager, kube-scheduler and kube-proxy. -* Kubernetes [version and version-skew policy](/docs/setup/release/version-skew-policy/) -* Kubeadm-specific [installation guide](/docs/setup/production-environment/tools/kubeadm/install-kubeadm/#installing-kubeadm-kubelet-and-kubectl) +Example: +* kubeadm is at {{< skew latestVersion >}} +* `kubernetesVersion` must be at {{< skew latestVersion >}} or {{< skew prevMinorVersion >}} + +### kubeadm's skew against the kubelet + +Similarly to the Kubernetes version, kubeadm can be used with a kubelet version that is the same +version as kubeadm or one version older. + +Example: +* kubeadm is at {{< skew latestVersion >}} +* kubelet on the host must be at {{< skew latestVersion >}} or {{< skew prevMinorVersion >}} + +### kubeadm's skew against kubeadm + +There are certain limitations on how kubeadm commands can operate on existing nodes or whole cluster +managed by kubeadm. + +If new nodes are joined to the cluster, the kubeadm binary used for `kubeadm join` must match +the last version of kubeadm used to either create the cluster with `kubeadm init` or to upgrade +the same node with `kubeadm upgrade`. Similar rules apply to the rest of the kubeadm commands +with the exception of `kubeadm upgrade`. + +Example for `kubeadm join`: +* kubeadm version {{< skew latestVersion >}} was used to create a cluster with `kubeadm init` +* Joining nodes must use a kubeadm binary that is at version {{< skew latestVersion >}} + +Nodes that are being upgraded must use a version of kubeadm that is the same MINOR +version or one MINOR version newer than the version of kubeadm used for managing the +node. + +Example for `kubeadm upgrade`: +* kubeadm version {{< skew prevMinorVersion >}} was used to create or upgrade the node +* The version of kubeadm used for upgrading the node must be at {{< skew prevMinorVersion >}} +or {{< skew latestVersion >}} + +To learn more about the version skew between the different Kubernetes component see +the [Version Skew Policy](https://kubernetes.io/releases/version-skew-policy/). ## Limitations {#limitations} From 0ffcc6612040c3b4f55efe32de8e2c5759e6be4c Mon Sep 17 00:00:00 2001 From: edithturn Date: Sun, 20 Mar 2022 20:33:55 -0500 Subject: [PATCH 07/73] add storage limits documentation --- .../docs/concepts/storage/storage-limits.md | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 content/es/docs/concepts/storage/storage-limits.md diff --git a/content/es/docs/concepts/storage/storage-limits.md b/content/es/docs/concepts/storage/storage-limits.md new file mode 100644 index 0000000000000..8654748da0455 --- /dev/null +++ b/content/es/docs/concepts/storage/storage-limits.md @@ -0,0 +1,67 @@ +--- +reviewers: +- edithturn +- raelga +- electrocucaracha +title: Límites de volumen específicos del nodo +content_type: concept +--- + + + +Esta página describe la cantidad máxima de Volúmenes que se pueden adjuntar a un nodo para varios proveedores de nube. + +Los proveedores de la nube como Google, Amazon y Microsoft suelen tener un límite en la cantidad de Volúmenes que se pueden adjuntar a un Nodo. Es importante que Kubernetes respete esos límites. De lo contrario, los pods planificados en un Nodo podrían quedarse atascados esperando que se conecten los volúmenes. + + + + + +## Límites predeterminados de Kubernetes + +El Planificador de Kubernetes tiene límites predeterminados en la cantidad de volúmenes que se pueden adjuntar a un Nodo: + + + + + + +
Servicio de almacenamiento en la nubeVolúmenes máximos por Nodo
Amazon Elastic Block Store (EBS)39
Google Persistent Disk16
Microsoft Azure Disk Storage16
+ +## Límites personalizados + +Puede cambiar estos límites configurando el valor de la variable de entorno KUBE_MAX_PD_VOLS y luego iniciando el Planificador. Los controladores CSI pueden tener un procedimiento diferente, consulte su documentación sobre cómo personalizar sus límites. + +Tenga cuidado si establece un límite superior al límite predeterminado. Consulte la documentación del proveedor de la nube para asegurarse de que los Nodos realmente puedan admitir el límite que establezca. + +El límite se aplica a todo el clúster, por lo que afecta a todos los Nodos. + +## Límites de Volumen dinámico + +{{< feature-state state="stable" for_k8s_version="v1.17" >}} + +Los límites de Volumen dinámico son compatibles con los siguientes tipos de Volumen. + +- Amazon EBS +- Google Persistent Disk +- Azure Disk +- CSI + +Para los Volúmenes administrados por complementos de Volumen en árbol, Kubernetes determina automáticamente el tipo de Nodo y aplica la cantidad máxima adecuada de volúmenes para el Nodo. Por ejemplo: + +* En +Google Compute Engine, +se pueden adjuntar hasta 127 Volúmenes a un Nodo, [según el tipo de Nodo](https://cloud.google.com/compute/docs/disks/#pdnumberlimits). + +* Para los discos de Amazon EBS en los tipos de instancias M5,C5,R5,T3 y Z1D, Kubernetes permite que solo se adjunten 25 Volúmenes a un Nodo. Para otros tipos de instancias en +Amazon Elastic Compute Cloud (EC2), +Kubernetes permite adjuntar 39 Volúmenes a un Nodo. + +* En Azure, se pueden conectar hasta 64 discos a un Nodo, según el tipo de Nodo. Para obtener más detalles, consulte [Sizes for virtual machines in Azure](https://docs.microsoft.com/en-us/azure/virtual-machines/windows/sizes). + +* Si un controlador de almacenamiento CSI anuncia una cantidad máxima de Volúmenes para un Nodo (usando `NodeGetInfo`), the {{< glossary_tooltip text="kube-scheduler" term_id="kube-scheduler" >}} respeta ese límite. +Consulte las especificaciones de [CSI specifications](https://github.com/container-storage-interface/spec/blob/master/spec.md#nodegetinfo) para obtener más información. + +* Para los Volúmenes administrados por complementos en árbol que se han migrado a un controlador CSI, la cantidad máxima de Volúmenes será la que informe el controlador CSI. + + From 131f3b2b46698d81503c1cafbbf46310cfd17af2 Mon Sep 17 00:00:00 2001 From: edithturn Date: Sun, 20 Mar 2022 21:01:32 -0500 Subject: [PATCH 08/73] fix minor typo errors --- content/es/docs/concepts/storage/storage-limits.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/content/es/docs/concepts/storage/storage-limits.md b/content/es/docs/concepts/storage/storage-limits.md index 8654748da0455..5bcbfc6b208ca 100644 --- a/content/es/docs/concepts/storage/storage-limits.md +++ b/content/es/docs/concepts/storage/storage-limits.md @@ -3,15 +3,15 @@ reviewers: - edithturn - raelga - electrocucaracha -title: Límites de volumen específicos del nodo +title: Límites de Volumen específicos del Nodo content_type: concept --- -Esta página describe la cantidad máxima de Volúmenes que se pueden adjuntar a un nodo para varios proveedores de nube. +Esta página describe la cantidad máxima de Volúmenes que se pueden adjuntar a un Nodo para varios proveedores de nube. -Los proveedores de la nube como Google, Amazon y Microsoft suelen tener un límite en la cantidad de Volúmenes que se pueden adjuntar a un Nodo. Es importante que Kubernetes respete esos límites. De lo contrario, los pods planificados en un Nodo podrían quedarse atascados esperando que se conecten los volúmenes. +Los proveedores de la nube como Google, Amazon y Microsoft suelen tener un límite en la cantidad de Volúmenes que se pueden adjuntar a un Nodo. Es importante que Kubernetes respete esos límites. De lo contrario, los pods planificados en un Nodo podrían quedarse atascados esperando que se conecten los Volúmenes. @@ -19,7 +19,7 @@ Los proveedores de la nube como Google, Amazon y Microsoft suelen tener un lími ## Límites predeterminados de Kubernetes -El Planificador de Kubernetes tiene límites predeterminados en la cantidad de volúmenes que se pueden adjuntar a un Nodo: +El Planificador de Kubernetes tiene límites predeterminados en la cantidad de Volúmenes que se pueden adjuntar a un Nodo: @@ -47,7 +47,7 @@ Los límites de Volumen dinámico son compatibles con los siguientes tipos de Vo - Azure Disk - CSI -Para los Volúmenes administrados por complementos de Volumen en árbol, Kubernetes determina automáticamente el tipo de Nodo y aplica la cantidad máxima adecuada de volúmenes para el Nodo. Por ejemplo: +Para los Volúmenes administrados por complementos de Volumen en árbol, Kubernetes determina automáticamente el tipo de Nodo y aplica la cantidad máxima adecuada de Volúmenes para el Nodo. Por ejemplo: * En Google Compute Engine, @@ -59,7 +59,7 @@ Kubernetes permite adjuntar 39 Volúmenes a un Nodo. * En Azure, se pueden conectar hasta 64 discos a un Nodo, según el tipo de Nodo. Para obtener más detalles, consulte [Sizes for virtual machines in Azure](https://docs.microsoft.com/en-us/azure/virtual-machines/windows/sizes). -* Si un controlador de almacenamiento CSI anuncia una cantidad máxima de Volúmenes para un Nodo (usando `NodeGetInfo`), the {{< glossary_tooltip text="kube-scheduler" term_id="kube-scheduler" >}} respeta ese límite. +* Si un controlador de almacenamiento CSI anuncia una cantidad máxima de Volúmenes para un Nodo (usando `NodeGetInfo`), el {{< glossary_tooltip text="kube-scheduler" term_id="kube-scheduler" >}} respeta ese límite. Consulte las especificaciones de [CSI specifications](https://github.com/container-storage-interface/spec/blob/master/spec.md#nodegetinfo) para obtener más información. * Para los Volúmenes administrados por complementos en árbol que se han migrado a un controlador CSI, la cantidad máxima de Volúmenes será la que informe el controlador CSI. From 28ae4d78090acec2fff40e934e58121da7ea8584 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gwena=C3=ABl=20Gallon?= Date: Fri, 25 Mar 2022 10:31:42 +0100 Subject: [PATCH 09/73] [fr] fix spaces --- .../kubernetes-basics/deploy-app/deploy-intro.html | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/content/fr/docs/tutorials/kubernetes-basics/deploy-app/deploy-intro.html b/content/fr/docs/tutorials/kubernetes-basics/deploy-app/deploy-intro.html index 0dd896232b329..ff41cae0dd0a8 100644 --- a/content/fr/docs/tutorials/kubernetes-basics/deploy-app/deploy-intro.html +++ b/content/fr/docs/tutorials/kubernetes-basics/deploy-app/deploy-intro.html @@ -27,12 +27,7 @@

Objectifs

Déploiements Kubernetes

-

- Une fois que vous avez un cluster Kubernetes en cours d'exécution, vous pouvez déployer vos applications conteneurisées par dessus. - Pour ce faire, vous créez une configuration de Déploiement (Deployments) Kubernetes. Le déploiement instruit Kubernetes -                de comment créer et mettre à jour des instances de votre application. Une fois que vous avez créé un déploiement, le plannificateur de Kubernetes (kube-scheduler) -                planifient les instanciations d'application sur des nœuds du cluster. -

+

Une fois que vous avez un cluster Kubernetes en cours d'exécution, vous pouvez déployer vos applications conteneurisées par dessus. Pour ce faire, vous créez une configuration de Déploiement (Deployments) Kubernetes. Le déploiement instruit Kubernetes de comment créer et mettre à jour des instances de votre application. Une fois que vous avez créé un déploiement, le plannificateur de Kubernetes (kube-scheduler) planifient les instanciations d'application sur des nœuds du cluster.

Une fois les instances d’application créées, un contrôleur de déploiement Kubernetes surveille en permanence ces instances. Si le nœud hébergeant une instance tombe en panne ou est supprimé, le contrôleur de déploiement remplace l'instance par une instance située sur un autre nœud du cluster. Ceci fournit un mécanisme d'auto-réparation pour faire face aux pannes ou à la maintenance de la machine.

From 180fa82d9c3f23a0c351abb4ce485a779069da7a Mon Sep 17 00:00:00 2001 From: Shannon Kularathna Date: Tue, 8 Mar 2022 23:09:36 +0000 Subject: [PATCH 10/73] Add draft content for migrating to dockerd --- .../migrate-dockershim-dockerd.md | 116 ++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 content/en/docs/tasks/administer-cluster/migrating-from-dockershim/migrate-dockershim-dockerd.md diff --git a/content/en/docs/tasks/administer-cluster/migrating-from-dockershim/migrate-dockershim-dockerd.md b/content/en/docs/tasks/administer-cluster/migrating-from-dockershim/migrate-dockershim-dockerd.md new file mode 100644 index 0000000000000..2660644a6d968 --- /dev/null +++ b/content/en/docs/tasks/administer-cluster/migrating-from-dockershim/migrate-dockershim-dockerd.md @@ -0,0 +1,116 @@ +--- +title: "Migrate Docker Engine nodes from dockershim to cri-dockerd" +weight: 9 +content_type: task +--- + +{{% thirdparty-content %}} + +This page shows you how to migrate your Docker Engine nodes to use `cri-dockerd` +instead of dockershim. Follow these steps if your clusters run Kubernetes 1.23 +or earlier and you want to continue using Docker Engine after +you upgrade to Kubernetes 1.24 and later, or if you just want to move off the +dockershim component. + +## What is cri-dockerd? {#what-is-cri-dockerd} + +In Kubernetes 1.23 and earlier, Docker Engine used a component called the +dockershim to interact with Kubernetes system components such as the kubelet. +The dockershim component is deprecated and will be removed in Kubernetes 1.24. A +third-party replacement, `cri-dockerd`, is available. The `cri-dockerd` adapter +lets you use Docker Engine through the {{}}. + +{{}} +If you already use `cri-dockerd`, you aren't affected by the dockershim removal. +Before you begin, [Check whether your nodes use the dockershim](/docs/tasks/administer-cluster/migrating-from-dockershim/find-out-runtime-you-use/). +{{}} + +If you want to migrate to `cri-dockerd` so that you can continue using Docker +Engine as your container runtime, you should do the following for each affected +node: + +1. Install `cri-dockerd`. +1. Cordon and drain the node. +1. Configure the kubelet to use `cri-dockerd`. +1. Restart the kubelet. +1. Verify that the node is healthy. + +Test the migration on non-critical nodes first. + +You should perform the following steps for each node that you want to migrate +to `cri-dockerd`. + +## {{% heading "prerequisites" %}} + +* [`cri-dockerd`](https://github.com/mirantis/cri-dockerd#build-and-install) + installed and started on each node. +* A [network plugin](/docs/concepts/extend-kubernetes/compute-storage-net/network-plugins/). + +## Cordon and drain the node + +1. Cordon the node to stop new Pods scheduling on it: + + ```shell + kubectl cordon + ``` + Replace `` with the name of the node. + +1. Drain the node to safely evict running Pods: + + ```shell + kubectl drain \ + --ignore-daemonsets + ``` + +## Configure the kubelet to use cri-dockerd + +The following steps apply to clusters set up using the kubeadm tool. If you use +a different tool, you should modify the kubelet using the configuration +instructions for that tool. + +1. Open `/var/lib/kubelet/kubeadm-flags.env` on each affected node. +1. Modify the `--container-runtime-endpoint` flag to + `unix:///var/run/cri-dockerd.sock`. + +The kubeadm tool stores the node's socket as an annotation on the `Node` object +in the control plane. To modify this socket for each affected node: + +1. Edit the YAML representation of the `Node` object: + + ```shell + KUBECONFIG=/path/to/admin.conf kubectl edit no + ``` + Replace the following: + + * `/path/to/admin.conf`: the path to the kubectl configuration file, + `admin.conf`. + * ``: the name of the node you want to modify. + +1. Change `kubeadm.alpha.kubernetes.io/cri-socket` from + `/var/run/dockershim.sock` to `unix:///var/run/cri-dockerd.sock`. +1. Save the changes. The `Node` object is updated on save. + +## Restart the kubelet + +```shell +systemctl start kubelet +``` + +## Verify that the node is healthy + +To check whether the node uses the `cri-dockerd` endpoint, follow the +instructions in [Find out which runtime you use](/docs/tasks/administer-cluster/migrating-from-dockershim/find-out-runtime-you-use/). +The `--container-runtime-endpoint` flag for the kubelet should be `unix:///var/run/cri-dockerd.sock`. + +## Uncordon the node + +Uncordon the node to let Pods schedule on it: + +```shell +kubectl uncordon +``` + +## {{% heading "whatsnext" %}} + +* Read the [dockershim removal FAQ](/dockershim/). +* [Learn how to migrate from Docker Engine with dockershim to containerd](/docs/tasks/administer-cluster/migrating-from-dockershim/change-runtime-containerd/). \ No newline at end of file From 5bb9befe1cc6825417feee42e441cf506f29e427 Mon Sep 17 00:00:00 2001 From: Edith Puclla <58795858+edithturn@users.noreply.github.com> Date: Sat, 26 Mar 2022 17:37:45 -0500 Subject: [PATCH 11/73] Update content/es/docs/concepts/storage/storage-limits.md Co-authored-by: Victor Morales --- content/es/docs/concepts/storage/storage-limits.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/es/docs/concepts/storage/storage-limits.md b/content/es/docs/concepts/storage/storage-limits.md index 5bcbfc6b208ca..552d38d0f09d0 100644 --- a/content/es/docs/concepts/storage/storage-limits.md +++ b/content/es/docs/concepts/storage/storage-limits.md @@ -11,7 +11,7 @@ content_type: concept Esta página describe la cantidad máxima de Volúmenes que se pueden adjuntar a un Nodo para varios proveedores de nube. -Los proveedores de la nube como Google, Amazon y Microsoft suelen tener un límite en la cantidad de Volúmenes que se pueden adjuntar a un Nodo. Es importante que Kubernetes respete esos límites. De lo contrario, los pods planificados en un Nodo podrían quedarse atascados esperando que se conecten los Volúmenes. +Los proveedores de la nube como Google, Amazon y Microsoft suelen tener un límite en la cantidad de Volúmenes que se pueden adjuntar a un Nodo. Es importante que Kubernetes respete esos límites. De lo contrario, los Pods planificados en un Nodo podrían quedarse atascados esperando que los Volúmenes se conecten. From ecaffa667b1742c464a66aad48d09c7b6804cb16 Mon Sep 17 00:00:00 2001 From: Edith Puclla <58795858+edithturn@users.noreply.github.com> Date: Sat, 26 Mar 2022 17:38:28 -0500 Subject: [PATCH 12/73] Update content/es/docs/concepts/storage/storage-limits.md Co-authored-by: Victor Morales --- content/es/docs/concepts/storage/storage-limits.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/es/docs/concepts/storage/storage-limits.md b/content/es/docs/concepts/storage/storage-limits.md index 552d38d0f09d0..ce1b0f0f18799 100644 --- a/content/es/docs/concepts/storage/storage-limits.md +++ b/content/es/docs/concepts/storage/storage-limits.md @@ -47,7 +47,7 @@ Los límites de Volumen dinámico son compatibles con los siguientes tipos de Vo - Azure Disk - CSI -Para los Volúmenes administrados por complementos de Volumen en árbol, Kubernetes determina automáticamente el tipo de Nodo y aplica la cantidad máxima adecuada de Volúmenes para el Nodo. Por ejemplo: +Para los Volúmenes administrados por in-tree plugins de Volumen, Kubernetes determina automáticamente el tipo de Nodo y aplica la cantidad máxima adecuada de Volúmenes para el Nodo. Por ejemplo: * En Google Compute Engine, From 6c24e33f922826d85a593a49a5e88cc47d051939 Mon Sep 17 00:00:00 2001 From: Edith Puclla <58795858+edithturn@users.noreply.github.com> Date: Sat, 26 Mar 2022 17:38:43 -0500 Subject: [PATCH 13/73] Update content/es/docs/concepts/storage/storage-limits.md Co-authored-by: Victor Morales --- content/es/docs/concepts/storage/storage-limits.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/es/docs/concepts/storage/storage-limits.md b/content/es/docs/concepts/storage/storage-limits.md index ce1b0f0f18799..418b145c563f3 100644 --- a/content/es/docs/concepts/storage/storage-limits.md +++ b/content/es/docs/concepts/storage/storage-limits.md @@ -53,7 +53,7 @@ Para los Volúmenes administrados por in-tree plugins de Volumen, Kubernetes det Google Compute Engine, se pueden adjuntar hasta 127 Volúmenes a un Nodo, [según el tipo de Nodo](https://cloud.google.com/compute/docs/disks/#pdnumberlimits). -* Para los discos de Amazon EBS en los tipos de instancias M5,C5,R5,T3 y Z1D, Kubernetes permite que solo se adjunten 25 Volúmenes a un Nodo. Para otros tipos de instancias en +* Para los discos de Amazon EBS en los tipos de instancias M5,C5,R5,T3 y Z1D, Kubernetes permite que solo se adjunten 25 Volúmenes a un Nodo. Para otros tipos de instancias en Amazon Elastic Compute Cloud (EC2), Kubernetes permite adjuntar 39 Volúmenes a un Nodo. From b12f7e1ad3a924be537d63c3e1b37e79e5352172 Mon Sep 17 00:00:00 2001 From: Edith Puclla <58795858+edithturn@users.noreply.github.com> Date: Sat, 26 Mar 2022 17:39:03 -0500 Subject: [PATCH 14/73] Update content/es/docs/concepts/storage/storage-limits.md Co-authored-by: Victor Morales --- content/es/docs/concepts/storage/storage-limits.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/es/docs/concepts/storage/storage-limits.md b/content/es/docs/concepts/storage/storage-limits.md index 418b145c563f3..28cc16937f4e7 100644 --- a/content/es/docs/concepts/storage/storage-limits.md +++ b/content/es/docs/concepts/storage/storage-limits.md @@ -60,7 +60,7 @@ Kubernetes permite adjuntar 39 Volúmenes a un Nodo. * En Azure, se pueden conectar hasta 64 discos a un Nodo, según el tipo de Nodo. Para obtener más detalles, consulte [Sizes for virtual machines in Azure](https://docs.microsoft.com/en-us/azure/virtual-machines/windows/sizes). * Si un controlador de almacenamiento CSI anuncia una cantidad máxima de Volúmenes para un Nodo (usando `NodeGetInfo`), el {{< glossary_tooltip text="kube-scheduler" term_id="kube-scheduler" >}} respeta ese límite. -Consulte las especificaciones de [CSI specifications](https://github.com/container-storage-interface/spec/blob/master/spec.md#nodegetinfo) para obtener más información. +Consulte las [especificaciones de CSI](https://github.com/container-storage-interface/spec/blob/master/spec.md#nodegetinfo) para obtener más información. * Para los Volúmenes administrados por complementos en árbol que se han migrado a un controlador CSI, la cantidad máxima de Volúmenes será la que informe el controlador CSI. From 01a210abdf283add0983c2069fd8491fad758a7e Mon Sep 17 00:00:00 2001 From: Edith Puclla <58795858+edithturn@users.noreply.github.com> Date: Sat, 26 Mar 2022 17:41:19 -0500 Subject: [PATCH 15/73] Update content/es/docs/concepts/storage/storage-limits.md Co-authored-by: Victor Morales --- content/es/docs/concepts/storage/storage-limits.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/content/es/docs/concepts/storage/storage-limits.md b/content/es/docs/concepts/storage/storage-limits.md index 28cc16937f4e7..0cb4a376e8125 100644 --- a/content/es/docs/concepts/storage/storage-limits.md +++ b/content/es/docs/concepts/storage/storage-limits.md @@ -1,8 +1,4 @@ --- -reviewers: -- edithturn -- raelga -- electrocucaracha title: Límites de Volumen específicos del Nodo content_type: concept --- From 280104545a42e6d222ba699db84615c4c44631f3 Mon Sep 17 00:00:00 2001 From: Edith Puclla <58795858+edithturn@users.noreply.github.com> Date: Sat, 26 Mar 2022 17:41:43 -0500 Subject: [PATCH 16/73] Update content/es/docs/concepts/storage/storage-limits.md Co-authored-by: Victor Morales --- content/es/docs/concepts/storage/storage-limits.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/es/docs/concepts/storage/storage-limits.md b/content/es/docs/concepts/storage/storage-limits.md index 0cb4a376e8125..4a62a27c94dfe 100644 --- a/content/es/docs/concepts/storage/storage-limits.md +++ b/content/es/docs/concepts/storage/storage-limits.md @@ -58,6 +58,6 @@ Kubernetes permite adjuntar 39 Volúmenes a un Nodo. * Si un controlador de almacenamiento CSI anuncia una cantidad máxima de Volúmenes para un Nodo (usando `NodeGetInfo`), el {{< glossary_tooltip text="kube-scheduler" term_id="kube-scheduler" >}} respeta ese límite. Consulte las [especificaciones de CSI](https://github.com/container-storage-interface/spec/blob/master/spec.md#nodegetinfo) para obtener más información. -* Para los Volúmenes administrados por complementos en árbol que se han migrado a un controlador CSI, la cantidad máxima de Volúmenes será la que informe el controlador CSI. +* Para los Volúmenes administrados por in-tree plugins que han sido migrados a un controlador CSI, la cantidad máxima de Volúmenes será la que informe el controlador CSI. From 81881f8d8452ac2ab30f3f708e6149c1fc8630e7 Mon Sep 17 00:00:00 2001 From: Sudheer Satyanarayana Date: Sun, 27 Mar 2022 16:01:25 +0530 Subject: [PATCH 17/73] minor text edit `Pay attention to the case of suffixes` seems better than `Take care about case for suffixes` --- .../docs/concepts/configuration/manage-resources-containers.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/en/docs/concepts/configuration/manage-resources-containers.md b/content/en/docs/concepts/configuration/manage-resources-containers.md index 18f2fc5cb589a..575f96f04dd26 100644 --- a/content/en/docs/concepts/configuration/manage-resources-containers.md +++ b/content/en/docs/concepts/configuration/manage-resources-containers.md @@ -134,7 +134,7 @@ Mi, Ki. For example, the following represent roughly the same value: 128974848, 129e6, 129M, 128974848000m, 123Mi ``` -Take care about case for suffixes. If you request `400m` of memory, this is a request +Pay attention to the case of the suffixes. If you request `400m` of memory, this is a request for 0.4 bytes. Someone who types that probably meant to ask for 400 mebibytes (`400Mi`) or 400 megabytes (`400M`). From fa8872f70fff35783e17fac38f5835226c300838 Mon Sep 17 00:00:00 2001 From: Vaibhav Date: Mon, 28 Mar 2022 01:07:38 +0530 Subject: [PATCH 18/73] Update the doc regarding out of date link --- .../docs/tasks/configure-pod-container/security-context.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/content/en/docs/tasks/configure-pod-container/security-context.md b/content/en/docs/tasks/configure-pod-container/security-context.md index 30dfeb0e5d042..5a3e6a243850e 100644 --- a/content/en/docs/tasks/configure-pod-container/security-context.md +++ b/content/en/docs/tasks/configure-pod-container/security-context.md @@ -44,9 +44,6 @@ The above bullets are not a complete set of security context settings -- please [SecurityContext](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#securitycontext-v1-core) for a comprehensive list. -For more information about security mechanisms in Linux, see -[Overview of Linux Kernel Security Features](https://www.linux.com/learn/overview-linux-kernel-security-features) - ## {{% heading "prerequisites" %}} {{< include "task-tutorial-prereqs.md" >}} {{< version-check >}} @@ -490,3 +487,5 @@ kubectl delete pod security-context-demo-4 * [Pod Security Policies](/docs/concepts/policy/pod-security-policy/) * [AllowPrivilegeEscalation design document](https://git.k8s.io/community/contributors/design-proposals/auth/no-new-privs.md) +* For more information about security mechanisms in Linux, see +[Overview of Linux Kernel Security Features](https://www.linux.com/learn/overview-linux-kernel-security-features) (Note: Some information is out of date) From a4196f77f587f210ba57dba256b591072c5d0c0b Mon Sep 17 00:00:00 2001 From: Lan Luo Date: Mon, 28 Mar 2022 21:07:51 +0800 Subject: [PATCH 19/73] Fix extra double quotation mark Signed-off-by: Lan Luo --- .../update-api-object-kubectl-patch.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/content/zh/docs/tasks/manage-kubernetes-objects/update-api-object-kubectl-patch.md b/content/zh/docs/tasks/manage-kubernetes-objects/update-api-object-kubectl-patch.md index a5c7cd9452357..dd47ec39cf1e5 100644 --- a/content/zh/docs/tasks/manage-kubernetes-objects/update-api-object-kubectl-patch.md +++ b/content/zh/docs/tasks/manage-kubernetes-objects/update-api-object-kubectl-patch.md @@ -613,10 +613,10 @@ The following commands are equivalent: 以下命令是等价的: ```shell -kubectl patch deployment patch-demo --patch-file patch-file.yaml" +kubectl patch deployment patch-demo --patch-file patch-file.yaml kubectl patch deployment patch-demo --patch 'spec:\n template:\n spec:\n containers:\n - name: patch-demo-ctr-2\n image: redis' -kubectl patch deployment patch-demo --patch-file patch-file.json" +kubectl patch deployment patch-demo --patch-file patch-file.json kubectl patch deployment patch-demo --patch '{"spec": {"template": {"spec": {"containers": [{"name": "patch-demo-ctr-2","image": "redis"}]}}}}' ``` From d21c4302bc793971697f6ce6ddd1fa05ceac00c1 Mon Sep 17 00:00:00 2001 From: Mitesh Jain <47820816+miteshskj@users.noreply.github.com> Date: Mon, 28 Mar 2022 19:17:39 +0530 Subject: [PATCH 20/73] Remove bootstrap token being in beta state in kubelet-tls-bootstrapping.md --- .../command-line-tools-reference/kubelet-tls-bootstrapping.md | 1 - 1 file changed, 1 deletion(-) diff --git a/content/en/docs/reference/command-line-tools-reference/kubelet-tls-bootstrapping.md b/content/en/docs/reference/command-line-tools-reference/kubelet-tls-bootstrapping.md index 5d2458079e317..78aee8cf062f4 100644 --- a/content/en/docs/reference/command-line-tools-reference/kubelet-tls-bootstrapping.md +++ b/content/en/docs/reference/command-line-tools-reference/kubelet-tls-bootstrapping.md @@ -126,7 +126,6 @@ of provisioning. 2. [Token authentication file](#token-authentication-file) Bootstrap tokens are a simpler and more easily managed method to authenticate kubelets, and do not require any additional flags when starting kube-apiserver. -Using bootstrap tokens is currently __beta__ as of Kubernetes version 1.12. Whichever method you choose, the requirement is that the kubelet be able to authenticate as a user with the rights to: From 5183202a3bf782ed4cbecf0b3999ee454c3ad1a4 Mon Sep 17 00:00:00 2001 From: Bob <39816893+bobcode99@users.noreply.github.com> Date: Mon, 28 Mar 2022 22:36:36 +0800 Subject: [PATCH 21/73] Update horizontal-pod-autoscale.md Update HPA V2, custom.metrics.k8s.io, external.metrics.k8s.io design proposals to archive github link. --- .../docs/tasks/run-application/horizontal-pod-autoscale.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/content/en/docs/tasks/run-application/horizontal-pod-autoscale.md b/content/en/docs/tasks/run-application/horizontal-pod-autoscale.md index e5c05ea90cf2d..0039254f7ed37 100644 --- a/content/en/docs/tasks/run-application/horizontal-pod-autoscale.md +++ b/content/en/docs/tasks/run-application/horizontal-pod-autoscale.md @@ -337,9 +337,9 @@ APIs, cluster administrators must ensure that: * For external metrics, this is the `external.metrics.k8s.io` API. It may be provided by the custom metrics adapters provided above. For more information on these different metrics paths and how they differ please see the relevant design proposals for -[the HPA V2](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/autoscaling/hpa-v2.md), -[custom.metrics.k8s.io](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/instrumentation/custom-metrics-api.md) -and [external.metrics.k8s.io](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/instrumentation/external-metrics-api.md). +[the HPA V2](https://github.com/kubernetes/design-proposals-archive/blob/main/autoscaling/hpa-v2.md), +[custom.metrics.k8s.io](https://github.com/kubernetes/design-proposals-archive/blob/main/instrumentation/custom-metrics-api.md) +and [external.metrics.k8s.io](https://github.com/kubernetes/design-proposals-archive/blob/main/instrumentation/external-metrics-api.md). For examples of how to use them see [the walkthrough for using custom metrics](/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/#autoscaling-on-multiple-metrics-and-custom-metrics) and [the walkthrough for using external metrics](/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/#autoscaling-on-metrics-not-related-to-kubernetes-objects). From a76cc64203cecbdb804944664311fa6d86537be6 Mon Sep 17 00:00:00 2001 From: Mitesh Jain <47820816+miteshskj@users.noreply.github.com> Date: Mon, 28 Mar 2022 20:53:39 +0530 Subject: [PATCH 22/73] Fix broken link for stale CSR clean up in garbage-collection.md --- content/en/docs/concepts/architecture/garbage-collection.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/en/docs/concepts/architecture/garbage-collection.md b/content/en/docs/concepts/architecture/garbage-collection.md index 38aa99d654ed4..a6fa885bfc843 100644 --- a/content/en/docs/concepts/architecture/garbage-collection.md +++ b/content/en/docs/concepts/architecture/garbage-collection.md @@ -13,7 +13,7 @@ allows the clean up of resources like the following: * [Objects without owner references](#owners-dependents) * [Unused containers and container images](#containers-images) * [Dynamically provisioned PersistentVolumes with a StorageClass reclaim policy of Delete](/docs/concepts/storage/persistent-volumes/#delete) - * [Stale or expired CertificateSigningRequests (CSRs)](/reference/access-authn-authz/certificate-signing-requests/#request-signing-process) + * [Stale or expired CertificateSigningRequests (CSRs)](/docs/reference/access-authn-authz/certificate-signing-requests/#request-signing-process) * {{}} deleted in the following scenarios: * On a cloud when the cluster uses a [cloud controller manager](/docs/concepts/architecture/cloud-controller/) * On-premises when the cluster uses an addon similar to a cloud controller From 273271bbefad2264fe6b19670307c29c0d84e606 Mon Sep 17 00:00:00 2001 From: 196Ikuchil <196thinline@gmail.com> Date: Tue, 29 Mar 2022 01:02:17 +0900 Subject: [PATCH 23/73] add:translate concepts/security/pod-security-admission.md --- .../security/pod-security-admission.md | 134 ++++++++++++++++++ 1 file changed, 134 insertions(+) create mode 100644 content/ja/docs/concepts/security/pod-security-admission.md diff --git a/content/ja/docs/concepts/security/pod-security-admission.md b/content/ja/docs/concepts/security/pod-security-admission.md new file mode 100644 index 0000000000000..a7d7c02c89d3a --- /dev/null +++ b/content/ja/docs/concepts/security/pod-security-admission.md @@ -0,0 +1,134 @@ +--- +title: Podセキュリティのアドミッション +content_type: concept +weight: 20 +min-kubernetes-server-version: v1.22 +--- + + + + +{{< feature-state for_k8s_version="v1.23" state="beta" >}} + +Kubernetesの[Podセキュリティの標準](/ja/docs/concepts/security/pod-security-standards/)はPodに対して異なる分離レベルを定義します。 +これらの標準によって、Podの動作をどのように制限したいかを、明確かつ一貫した方法で定義することができます。 + +ベータ版機能として、Kubernetesは[PodSecurityPolicies](/docs/concepts/policy/pod-security-policy/)の後継である組み込みの _Pod Security_ {{< glossary_tooltip text="アドミッションコントローラー" term_id="admission-controller" >}}を提供しています。 +Podセキュリティの制限は、Pod作成時に{{< glossary_tooltip text="名前空間" term_id="namespace" >}}レベルで適用されます。 + +{{< note >}} +PodSecurityPolicy APIは非推奨であり、v1.25でKubernetesから[削除](/docs/reference/using-api/deprecation-guide/#v1-25)される予定です。 +{{< /note >}} + + + + +## `PodSecurity`アドミッションプラグインの有効化 +v1.23において、`PodSecurity`の[フィーチャーゲート](/ja/docs/reference/command-line-tools-reference/feature-gates/)はベータ版の機能で、デフォルトで有効化されています。 +v1.22において、`PodSecurity`の[フィーチャーゲート](/ja/docs/reference/command-line-tools-reference/feature-gates/)はアルファ版の機能で、組み込みのアドミッションプラグインを使用するには、`kube-apiserver`で有効にする必要があります。 + +```shell +--feature-gates="...,PodSecurity=true" +``` + +## 代替案:`PodSecurity`アドミッションwebhookのインストール {#webhook} + +クラスターがv1.22より古い、あるいは`PodSecurity`機能を有効にできないなどの理由で、ビルトインの`PodSecurity`アドミッションプラグインが使えない環境では、`PodSecurity`はアドミッションロジックはベータ版の[validating admission webhook](https://git.k8s.io/pod-security-admission/webhook)としても提供されています。 + +ビルド前のコンテナイメージ、証明書生成スクリプト、マニフェストの例は、[https://git.k8s.io/pod-security-admission/webhook](https://git.k8s.io/pod-security-admission/webhook)で入手可能です。 + + +インストール方法: +```shell +git clone git@github.com:kubernetes/pod-security-admission.git +cd pod-security-admission/webhook +make certs +kubectl apply -k . +``` + +{{< note >}} +生成された証明書の有効期限は2年間です。有効期限が切れる前に、証明書を再生成するか、内蔵のアドミッションプラグインを使用してWebhookを削除してください。 +{{< /note >}} + +## Podのセキュリティレベル + +Pod Securityアドミッションは、Podの[Security Context](/docs/tasks/configure-pod-container/security-context/)とその他の関連フィールドに、[Podセキュリティの標準](/ja/docs/concepts/security/pod-security-standards)で定義された3つのレベル、`privileged`、`baseline`、`restricted`に従って要件を設定するものです。 +これらの要件の詳細については、[Podセキュリティの標準](/ja/docs/concepts/security/pod-security-standards)のページを参照してください。 + +## Podの名前空間に対するセキュリティアドミッションラベル + +この機能を有効にするか、Webhookをインストールすると、名前空間を設定して、各名前空間でPodセキュリティに使用したいadmission controlモードを定義できます。 +Kubernetesは、名前空間に使用したい定義済みのPodセキュリティの標準レベルのいずれかを適用するために設定できる{{< glossary_tooltip term_id="label" text="ラベル" >}}のセットを用意しています。 +選択したラベルは、以下のように違反の可能性が検出された場合に{{< glossary_tooltip text="コントロールプレーン" term_id="control-plane" >}}が取るアクションを定義します。 + +{{< table caption="Podのセキュリティアドミッションのモード" >}} +モード | 説明 +:---------|:------------ +**enforce** | ポリシーに違反した場合、Podは拒否されます。 +**audit** | ポリシー違反は、[監査ログ](/ja/docs/tasks/debug-application-cluster/audit/)に記録されるイベントに監査アノテーションを追加するトリガーとなりますが、それ以外は許可されます。 +**warn** | ポリシーに違反した場合は、ユーザーへの警告がトリガーされますが、それ以外は許可されます。 +{{< /table >}} + +名前空間は、任意のまたはすべてのモードを設定することができ、異なるモードに対して異なるレベルを設定することもできます。 + +各モードには、使用するポリシーを決定する2つのラベルがあります。 +```yaml +# モードごとのレベルラベルは、そのモードに適用するポリシーレベルを示す。 +# +# MODEは`enforce`、`audit`、`warn`のいずれかでなければならない。 +# LEVELは`privileged`、`baseline`、`restricted`のいずれかでなければならない。 +pod-security.kubernetes.io/: + +# オプション: モードごとのバージョンラベルは、Kubernetesのマイナーバージョンに同梱される +# バージョンにポリシーを固定するために使用できる(例えばv{{< skew latestVersion >}}など)。 +# +# MODEは`enforce`、`audit`、`warn`のいずれかでなければならない。 +# VERSIONは有効なKubernetesのマイナーバージョンか`latest`でなければならない。 +pod-security.kubernetes.io/-version: +``` + +[名前空間ラベルでのPodセキュリティの標準の適用](/docs/tasks/configure-pod-container/enforce-standards-namespace-labels)で使用例を確認できます。 + + +## WorkloadのリソースとPodテンプレート + +Podは、{{< glossary_tooltip term_id="deployment" >}}や{{< glossary_tooltip term_id="job">}}のような[ワークロードオブジェクト](/ja/docs/concepts/workloads/controllers/)を作成することによって、しばしば間接的に生成されます。 +ワークロードオブジェクトは_Pod template_を定義し、ワークロードリソースの{{< glossary_tooltip term_id="controller" text="コントローラー" >}}はそのテンプレートに基づきPodを作成します。 +違反の早期発見を支援するために、auditモードとwarningモードは、ワークロードリソースに適用されます。 +ただし、enforceモードはワークロードリソースには**適用されず**、結果としてのPodオブジェクトにのみ適用されます。 + +## 適用除外(Exemptions) + +Podセキュリティの施行から _exemptions_ を定義することで、特定の名前空間に関連するポリシーのために禁止されていたPodの作成を許可することができます。 +Exemptionsは[アドミッションコントローラーの設定](/docs/tasks/configure-pod-container/enforce-standards-admission-controller/#configure-the-admission-controller)で静的に設定することができます。 + +Exemptionsは明示的に列挙する必要があります。 +Exemptionsを満たしたリクエストは、アドミッションコントローラーによって _ignored_ されます(`enforce`、`audit`、`warn`のすべての動作がスキップされます)。Exemptionの次元は以下の通りです。 + +- **Usernames:** 認証されていない(あるいは偽装された)ユーザー名を持つユーザーからの要求は無視されます。 +- **RuntimeClassNames:** Podと[ワークロードリソース](#workload-resources-and-pod-templates)で指定された除外ランタイムクラス名は、無視されます。 +- **Namespaces:** 除外された名前空間のPodと[ワークロードリソース](#workload-resources-and-pod-templates)は、無視されます。 + +{{< caution >}} + +ほとんどのPodは、[ワークロードリソース](#workload-resources-and-pod-templates)に対応してコントローラーが作成します。つまり、エンドユーザーを適用除外にするのはPodを直接作成する場合のみで、ワークロードリソースを作成する場合は適用除外になりません。 +コントローラサービスアカウント(`system:serviceaccount:kube-system:replicaset-controller`など)は通常、除外してはいけません。そうした場合、対応するワークロードリソースを作成できるすべてのユーザーを暗黙的に除外してしまうためです。 + +{{< /caution >}} + +以下のPodフィールドに対する更新は、ポリシーチェックの対象外となります。つまり、Podの更新要求がこれらのフィールドを変更するだけであれば、Podが現在のポリシーレベルに違反していても拒否されることはありません。 + +- すべてのメタデータの更新(seccompまたはAppArmorアノテーションへの変更を**除く**) + - `seccomp.security.alpha.kubernetes.io/pod`(非推奨) + - `container.seccomp.security.alpha.kubernetes.io/*`(非推奨) + - `container.apparmor.security.beta.kubernetes.io/*` +- `.spec.activeDeadlineSeconds`に対する有効な更新 +- `.spec.tolerations`に対する有効な更新 + +## {{% heading "whatsnext" %}} + +- [Podセキュリティの標準](/ja/docs/concepts/security/pod-security-standards) +- [Podセキュリティの標準の適用](/docs/setup/best-practices/enforcing-pod-security-standards) +- [ビルトインのアドミッションコントローラーの設定によるPodセキュリティの標準の適用](/docs/tasks/configure-pod-container/enforce-standards-admission-controller) +- [名前空間ラベルでのPodセキュリティの標準の適用](/docs/tasks/configure-pod-container/enforce-standards-namespace-labels) +- [PodSecurityPolicyからビルトインのPodSecurityアドミッションコントローラーへの移行](/docs/tasks/configure-pod-container/migrate-from-psp) From abab541c57768f977535c6979d7ca82d56076c6e Mon Sep 17 00:00:00 2001 From: Ilya Z Date: Mon, 28 Mar 2022 23:40:05 +0400 Subject: [PATCH 24/73] small_fix --- content/ru/docs/reference/kubectl/overview.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/content/ru/docs/reference/kubectl/overview.md b/content/ru/docs/reference/kubectl/overview.md index 58305f2d95877..15a0a3e611671 100644 --- a/content/ru/docs/reference/kubectl/overview.md +++ b/content/ru/docs/reference/kubectl/overview.md @@ -52,7 +52,7 @@ kubectl [command] [TYPE] [NAME] [flags] * Выбор ресурсов по одному или нескольким файлов: `-f file1 -f file2 -f file<#>` - * [Используйте YAML вместо JSON](/docs/concepts/configuration/overview/#general-configuration-tips), так так YAML удобнее для пользователей, особенно в конфигурационных файлов.
+ * [Используйте YAML вместо JSON](/docs/concepts/configuration/overview/#general-configuration-tips), так как YAML удобнее для пользователей, особенно в конфигурационных файлах.
Пример: `kubectl get pod -f ./pod.yaml` * `flags`: определяет дополнительные флаги. Например, вы можете использовать флаги `-s` или `--server`, чтобы указать адрес и порт API-сервера Kubernetes.
@@ -162,7 +162,7 @@ kubectl [command] [TYPE] [NAME] [flags] ### Форматирование вывода -Стандартный формат вывода всех команд `kubectl` представлен в человекочитаемом текстовом формате. Чтобы вывести подробности в определенном формате можно добавить флаги `-o` или `--output` к команде `kubectl`. +Стандартный формат вывода всех команд `kubectl` представлен в понятном для человека текстовом формате. Чтобы вывести подробности в определенном формате можно добавить флаги `-o` или `--output` к команде `kubectl`. #### Синтаксис @@ -229,7 +229,7 @@ submit-queue 610995 `kubectl` может получать информацию об объектах с сервера. Это означает, что для любого указанного ресурса сервер вернет столбцы и строки по этому ресурсу, которые отобразит клиент. -Благодаря тому, что сервер инкапсулирует реализацию вывода, гарантируется единообразный и человекочитаемый вывод на всех клиентах, использующих один и тот же кластер. +Благодаря тому, что сервер инкапсулирует реализацию вывода, гарантируется единообразный и понятный для человека вывод на всех клиентах, использующих один и тот же кластер. Эта функциональность включена по умолчанию, начиная с `kubectl` 1.11 и выше. Чтобы отключить ее, добавьте флаг `--server-print=false` в команду `kubectl get`. @@ -340,7 +340,7 @@ kubectl delete pods,services -l name= kubectl delete pods --all ``` -`kubectl exec` - Выполнить команду в контейнера пода. +`kubectl exec` - Выполнить команду в контейнере пода. ```shell # Получить вывод от запущенной команды 'date' в поде . По умолчанию отображается вывод из первого контейнера. From 5ff402c477f792e4bd14658dfee4a5e78647dd6b Mon Sep 17 00:00:00 2001 From: Tim Bannister Date: Mon, 28 Mar 2022 23:08:25 +0100 Subject: [PATCH 25/73] Remove incorrect /dockershim alias This fixes up a previous, inadvertent mistake where the alias was retained during localization. --- content/pt-br/blog/_posts/2022-02-17-updated-dockershim-faq.md | 1 - 1 file changed, 1 deletion(-) diff --git a/content/pt-br/blog/_posts/2022-02-17-updated-dockershim-faq.md b/content/pt-br/blog/_posts/2022-02-17-updated-dockershim-faq.md index 526ec6e344173..bf92c1fedce11 100644 --- a/content/pt-br/blog/_posts/2022-02-17-updated-dockershim-faq.md +++ b/content/pt-br/blog/_posts/2022-02-17-updated-dockershim-faq.md @@ -3,7 +3,6 @@ layout: blog title: "Atualizado: Perguntas frequentes (FAQ) sobre a remoção do Dockershim" date: 2022-02-17 slug: dockershim-faq -aliases: [ '/dockershim' ] --- **Esta é uma atualização do artigo original [FAQ sobre a depreciação do Dockershim](/blog/2020/12/02/dockershim-faq/), From fb3db4db2b84f9df11a9a87c551ba9e6a5370d05 Mon Sep 17 00:00:00 2001 From: Tim Bannister Date: Mon, 28 Mar 2022 23:46:34 +0100 Subject: [PATCH 26/73] Remove incorrect /dockershim alias This fixes up a previous, inadvertent mistake where the alias was retained during localization. --- content/zh/blog/_posts/2022-02-17-updated-dockershim-faq.md | 1 - 1 file changed, 1 deletion(-) diff --git a/content/zh/blog/_posts/2022-02-17-updated-dockershim-faq.md b/content/zh/blog/_posts/2022-02-17-updated-dockershim-faq.md index 9a1cac8cc255d..8400012b61c7f 100644 --- a/content/zh/blog/_posts/2022-02-17-updated-dockershim-faq.md +++ b/content/zh/blog/_posts/2022-02-17-updated-dockershim-faq.md @@ -3,7 +3,6 @@ layout: blog title: "更新:弃用 Dockershim 的常见问题" date: 2022-02-17 slug: dockershim-faq -aliases: [ '/dockershim' ] --- @@ -38,8 +39,8 @@ Secret 是一种包含少量敏感信息例如密码、令牌或密钥的对象 Because Secrets can be created independently of the Pods that use them, there is less risk of the Secret (and its data) being exposed during the workflow of creating, viewing, and editing Pods. Kubernetes, and applications that run in -your cluster, can also take additional precautions with Secrets, such as -avoiding writing confidential data to nonvolatile storage. +your cluster, can also take additional precautions with Secrets, such as avoiding +writing confidential data to nonvolatile storage. Secrets are similar to {{< glossary_tooltip text="ConfigMaps" term_id="configmap" >}} but are specifically intended to hold confidential data. @@ -60,9 +61,11 @@ Additionally, anyone who is authorized to create a Pod in a namespace can use th In order to safely use Secrets, take at least the following steps: 1. [Enable Encryption at Rest](/docs/tasks/administer-cluster/encrypt-data/) for Secrets. -2. Enable or configure [RBAC rules](/docs/reference/access-authn-authz/authorization/) that - restrict reading data in Secrets (including via indirect means). -3. Where appropriate, also use mechanisms such as RBAC to limit which principals are allowed to create new Secrets or replace existing ones. +1. Enable or configure [RBAC rules](/docs/reference/access-authn-authz/authorization/) that + restrict reading and writing data in Secrets. Be aware that secrets can be obtained + implicitly by anyone with the permission to create a Pod. +1. Where appropriate, also use mechanisms such as RBAC to limit which principals are allowed + to create new Secrets or replace existing ones. --> 默认情况下,Kubernetes Secret 未加密地存储在 API 服务器的底层数据存储(etcd)中。 任何拥有 API 访问权限的人都可以检索或修改 Secret,任何有权访问 etcd 的人也可以。 @@ -72,1781 +75,1965 @@ In order to safely use Secrets, take at least the following steps: 为了安全地使用 Secret,请至少执行以下步骤: 1. 为 Secret [启用静态加密](/zh/docs/tasks/administer-cluster/encrypt-data/); -2. 启用或配置 [RBAC 规则](/zh/docs/reference/access-authn-authz/authorization/)来限制读取 Secret 的数据(包括通过间接方式)。 -3. 在适当的情况下,还可以使用 RBAC 等机制来限制允许哪些主体创建新 Secret 或替换现有 Secret。 +1. 启用或配置 [RBAC 规则](/zh/docs/reference/access-authn-authz/authorization/)来限制读取和写入 + Secret 的数据(包括通过间接方式)。需要注意的是,被准许创建 Pod 的人也隐式地被授权获取 + Secret 内容。 +1. 在适当的情况下,还可以使用 RBAC 等机制来限制允许哪些主体创建新 Secret 或替换现有 Secret。 {{< /caution >}} + +参见 [Secret 的信息安全](#information-security-for-secrets)了解详情。 + -## Secret 概览 {#overview-of-secrets} +## Secret 的使用 {#uses-for-secrets} -要使用 Secret,Pod 需要引用 Secret。 Pod 可以用三种方式之一来使用 Secret: -- 作为挂载到一个或多个容器上的 {{< glossary_tooltip text="卷" term_id="volume" >}} +- 作为挂载到一个或多个容器上的{{< glossary_tooltip text="卷" term_id="volume" >}} 中的[文件](#using-secrets-as-files-from-a-pod)。 -- 作为[容器的环境变量](#using-secrets-as-environment-variables) -- 由 [kubelet 在为 Pod 拉取镜像时使用](#using-imagepullsecrets) +- 作为[容器的环境变量](#using-secrets-as-environment-variables)。 +- 由 [kubelet 在为 Pod 拉取镜像时使用](#using-imagepullsecrets)。 - -Kubernetes 控制平面也使用 Secret; +Kubernetes 控制面也使用 Secret; 例如,[引导令牌 Secret](#bootstrap-token-secrets) 是一种帮助自动化节点注册的机制。 -Secret 对象的名称必须是合法的 [DNS 子域名](/zh/docs/concepts/overview/working-with-objects/names#dns-subdomain-names)。 -在为创建 Secret 编写配置文件时,你可以设置 `data` 与/或 `stringData` 字段。 -`data` 和 `stringData` 字段都是可选的。`data` 字段中所有键值都必须是 base64 -编码的字符串。如果不希望执行这种 base64 字符串的转换操作,你可以选择设置 -`stringData` 字段,其中可以使用任何字符串作为其取值。 - - -## Secret 的类型 {#secret-types} +### Secret 的替代方案 {#alternatives-to-secrets} -创建 Secret 时,你可以使用 Secret 资源的 `type` 字段, -或者与其等价的 `kubectl` 命令行参数(如果有的话)为其设置类型。 -Secret 的 `type` 有助于对不同类型机密数据的编程处理。 +除了使用 Secret 来保护机密数据,你也可以选择一些替代方案。 -Kubernetes 提供若干种内置的类型,用于一些常见的使用场景。 -针对这些类型,Kubernetes 所执行的合法性检查操作以及对其所实施的限制各不相同。 +下面是一些选项: -| 内置类型 | 用法 | -|--------------|-------| -| `Opaque` | 用户定义的任意数据 | -| `kubernetes.io/service-account-token` | 服务账号令牌 | -| `kubernetes.io/dockercfg` | `~/.dockercfg` 文件的序列化形式 | -| `kubernetes.io/dockerconfigjson` | `~/.docker/config.json` 文件的序列化形式 | -| `kubernetes.io/basic-auth` | 用于基本身份认证的凭据 | -| `kubernetes.io/ssh-auth` | 用于 SSH 身份认证的凭据 | -| `kubernetes.io/tls` | 用于 TLS 客户端或者服务器端的数据 | -| `bootstrap.kubernetes.io/token` | 启动引导令牌数据 | +- 如果你的云原生组件需要执行身份认证来访问你所知道的、在同一 Kubernetes 集群中运行的另一个应用, + 你可以使用 [ServiceAccount](/zh/docs/reference/access-authn-authz/authentication/#service-account-tokens) + 及其令牌来标识你的客户端身份。 +- 你可以运行的第三方工具也有很多,这些工具可以运行在集群内或集群外,提供机密数据管理。 + 例如,这一工具可能是 Pod 通过 HTTPS 访问的一个服务,该服务在客户端能够正确地通过身份认证 + (例如,通过 ServiceAccount 令牌)时,提供机密数据内容。 + +- 就身份认证而言,你可以为 X.509 证书实现一个定制的签名者,并使用 + [CertificateSigningRequest](/zh/docs/reference/access-authn-authz/certificate-signing-requests/) + 来让该签名者为需要证书的 Pod 发放证书。 +- 你可以使用一个[设备插件](/zh/docs/concepts/extend-kubernetes/compute-storage-net/device-plugins/) + 来将节点本地的加密硬件暴露给特定的 Pod。例如,你可以将可信任的 Pod + 调度到提供可信平台模块(Trusted Platform Module,TPM)的节点上。 + 这类节点是另行配置的。 -通过为 Secret 对象的 `type` 字段设置一个非空的字符串值,你也可以定义并使用自己 -Secret 类型。如果 `type` 值为空字符串,则被视为 `Opaque` 类型。 -Kubernetes 并不对类型的名称作任何限制。不过,如果你要使用内置类型之一, -则你必须满足为该类型所定义的所有要求。 +你还可以将如上选项的两种或多种进行组合,包括直接使用 Secret 对象本身也是一种选项。 + +例如:实现(或部署)一个 {{< glossary_tooltip text="operator" term_id="operator-pattern" >}}, +从外部服务取回生命期很短的会话令牌,之后基于这些生命期很短的会话令牌来创建 Secret。 +运行在集群中的 Pod 可以使用这些会话令牌,而 Operator 则确保这些令牌是合法的。 +这种责权分离意味着你可以运行那些不了解会话令牌如何发放与刷新的确切机制的 Pod。 -### Opaque Secret +## 使用 Secret {#working-with-secrets} -当 Secret 配置文件中未作显式设定时,默认的 Secret 类型是 `Opaque`。 -当你使用 `kubectl` 来创建一个 Secret 时,你会使用 `generic` 子命令来标明 -要创建的是一个 `Opaque` 类型 Secret。 -例如,下面的命令会创建一个空的 `Opaque` 类型 Secret 对象: +### 创建 Secret {#creating-a-secret} -```shell -kubectl create secret generic empty-secret -kubectl get secret empty-secret -``` +- [使用 `kubectl` 命令来创建 Secret](/zh/docs/tasks/configmap-secret/managing-secret-using-kubectl/) +- [基于配置文件来创建 Secret](/zh/docs/tasks/configmap-secret/managing-secret-using-config-file/) +- [使用 kustomize 来创建 Secret](/zh/docs/tasks/configmap-secret/managing-secret-using-kustomize/) -输出类似于 +#### 对 Secret 名称与数据的约束 {#restriction-names-data} -``` -NAME TYPE DATA AGE -empty-secret Opaque 0 2m6s -``` +Secret 对象的名称必须是合法的 +[DNS 子域名](/zh/docs/concepts/overview/working-with-objects/names#dns-subdomain-names)。 -`DATA` 列显示 Secret 中保存的数据条目个数。 -在这个例子种,`0` 意味着我们刚刚创建了一个空的 Secret。 +在为创建 Secret 编写配置文件时,你可以设置 `data` 与/或 `stringData` 字段。 +`data` 和 `stringData` 字段都是可选的。`data` 字段中所有键值都必须是 base64 +编码的字符串。如果不希望执行这种 base64 字符串的转换操作,你可以选择设置 +`stringData` 字段,其中可以使用任何字符串作为其取值。 + +`data` 和 `stringData` 中的键名只能包含字母、数字、`-`、`_` 或 `.` 字符。 +`stringData` 字段中的所有键值对都会在内部被合并到 `data` 字段中。 +如果某个主键同时出现在 `data` 和 `stringData` 字段中,`stringData` +所指定的键值具有高优先级。 +#### 尺寸限制 {#restriction-data-size} -The following example configuration declares a service account token Secret: +每个 Secret 的尺寸最多为 1MiB。施加这一限制是为了避免用户创建非常大的 Secret, +进而导致 API 服务器和 kubelet 内存耗尽。不过创建很多小的 Secret 也可能耗尽内存。 +你可以使用[资源配额](/zh/docs/concepts/policy/resource-quotas/)来约束每个名字空间中 +Secret(或其他资源)的个数。 + + -### 服务账号令牌 Secret {#service-account-token-secrets} +### 编辑 Secret {#editing-a-secret} -类型为 `kubernetes.io/service-account-token` 的 Secret 用来存放标识某 -服务账号的令牌。使用这种 Secret 类型时,你需要确保对象的注解 -`kubernetes.io/service-account-name` 被设置为某个已有的服务账号名称。 -某个 Kubernetes 控制器会填写 Secret 的其它字段,例如 -`kubernetes.io/service-account.uid` 注解以及 `data` 字段中的 `token` -键值,使之包含实际的令牌内容。 +你可以使用 kubectl 来编辑一个已有的 Secret: -下面的配置实例声明了一个服务账号令牌 Secret: +```shell +kubectl edit secrets mysecret +``` + +这一命令会启动你的默认编辑器,允许你更新 `data` 字段中存放的 base64 编码的 Secret 值; +例如: - -```yaml -apiVersion: v1 + username: YWRtaW4= + password: MWYyZDFlMmU2N2Rm kind: Secret metadata: - name: secret-sa-sample annotations: - kubernetes.io/service-account.name: "sa-name" -type: kubernetes.io/service-account-token -data: - # 你可以像 Opaque Secret 一样在这里添加额外的键/值偶对 - extra: YmFyCg== + kubectl.kubernetes.io/last-applied-configuration: { ... } + creationTimestamp: 2020-01-22T18:41:56Z + name: mysecret + namespace: default + resourceVersion: "164619" + uid: cfee02d6-c137-11e5-8d73-42010af00002 +type: Opaque ``` -Kubernetes 在创建 Pod 时会自动创建一个服务账号 Secret 并自动修改你的 Pod -以使用该 Secret。该服务账号令牌 Secret 中包含了访问 Kubernetes API -所需要的凭据。 +这一示例清单定义了一个 Secret,其 `data` 字段中包含两个主键:`username` 和 `password`。 +清单中的字段值是 Base64 字符串,不过,当你在 Pod 中使用 Secret 时,kubelet 为 Pod +及其中的容器提供的是解码后的数据。 -如果需要,可以禁止或者重载这种自动创建并使用 API 凭据的操作。 -不过,如果你仅仅是希望能够安全地访问 API 服务器,这是建议的工作方式。 +你可以在一个 Secret 中打包多个主键和数值,也可以选择使用多个 Secret, +完全取决于哪种方式最方便。 -参考 [ServiceAccount](/zh/docs/tasks/configure-pod-container/configure-service-account/) -文档了解服务账号的工作原理。你也可以查看 -[`Pod`](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#pod-v1-core) -资源中的 `automountServiceAccountToken` 和 `serviceAccountName` 字段文档,了解 -从 Pod 中引用服务账号。 +### 使用 Secret {#using-a-secret} + +Secret 可以以数据卷的形式挂载,也可以作为{{< glossary_tooltip text="环境变量" term_id="container-env-variables" >}} +暴露给 Pod 中的容器使用。Secret 也可用于系统中的其他部分,而不是一定要直接暴露给 Pod。 +例如,Secret 也可以包含系统中其他部分在替你与外部系统交互时要使用的凭证数据。 -### Docker 配置 Secret {#docker-config-secrets} +Kubernetes 会检查 Secret 的卷数据源,确保所指定的对象引用确实指向类型为 Secret +的对象。因此,如果 Pod 依赖于某 Secret,该 Secret 必须先于 Pod 被创建。 -你可以使用下面两种 `type` 值之一来创建 Secret,用以存放访问 Docker 仓库 -来下载镜像的凭据。 +如果 Secret 内容无法取回(可能因为 Secret 尚不存在或者临时性地出现 API +服务器网络连接问题),kubelet 会周期性地重试 Pod 运行操作。kubelet 也会为该 Pod +报告 Event 事件,给出读取 Secret 时遇到的问题细节。 -- `kubernetes.io/dockercfg` -- `kubernetes.io/dockerconfigjson` + +#### 可选的 Secret {#restriction-secret-must-exist} + +当你定义一个基于 Secret 的环境变量时,你可以将其标记为可选。 +默认情况下,所引用的 Secret 都是必需的。 + +只有所有非可选的 Secret 都可用时,Pod 中的容器才能启动运行。 + +如果 Pod 引用了 Secret 中的特定主键,而虽然 Secret 本身存在,对应的主键不存在, +Pod 启动也会失败。 -`kubernetes.io/dockercfg` 是一种保留类型,用来存放 `~/.dockercfg` 文件的 -序列化形式。该文件是配置 Docker 命令行的一种老旧形式。 -使用此 Secret 类型时,你需要确保 Secret 的 `data` 字段中包含名为 -`.dockercfg` 的主键,其对应键值是用 base64 编码的某 `~/.dockercfg` -文件的内容。 +### 在 Pod 中以文件形式使用 Secret {#using-secrets-as-files-from-a-pod} + +如果你希望在 Pod 中访问 Secret 内的数据,一种方式是让 Kubernetes 将 Secret +以 Pod 中一个或多个容器的文件系统中的文件的形式呈现出来。 + +要配置这种行为,你需要: -类型 `kubernetes.io/dockerconfigjson` 被设计用来保存 JSON 数据的序列化形式, -该 JSON 也遵从 `~/.docker/config.json` 文件的格式规则,而后者是 -`~/.dockercfg` 的新版本格式。 -使用此 Secret 类型时,Secret 对象的 `data` 字段必须包含 `.dockerconfigjson` -键,其键值为 base64 编码的字符串包含 `~/.docker/config.json` 文件的内容。 +1. 创建一个 Secret 或者使用已有的 Secret。多个 Pod 可以引用同一个 Secret。 +1. 更改 Pod 定义,在 `.spec.volumes[]` 下添加一个卷。根据需要为卷设置其名称, + 并将 `.spec.volumes[].secret.secretName` 字段设置为 Secret 对象的名称。 +1. 为每个需要该 Secret 的容器添加 `.spec.containers[].volumeMounts[]`。 + 并将 `.spec.containers[].volumeMounts[].readyOnly` 设置为 `true`, + 将 `.spec.containers[].volumeMounts[].mountPath` 设置为希望 Secret + 被放置的、目前尚未被使用的路径名。 +1. 更改你的镜像或命令行,以便程序读取所设置的目录下的文件。Secret 的 `data` + 映射中的每个主键都成为 `mountPath` 下面的文件名。 -下面是一个 `kubernetes.io/dockercfg` 类型 Secret 的示例: +下面是一个通过卷来挂载名为 `mysecret` 的 Secret 的 Pod 示例: ```yaml apiVersion: v1 -kind: Secret +kind: Pod metadata: - name: secret-dockercfg -type: kubernetes.io/dockercfg -data: - .dockercfg: | - "" + name: mypod +spec: + containers: + - name: mypod + image: redis + volumeMounts: + - name: foo + mountPath: "/etc/foo" + readOnly: true + volumes: + - name: foo + secret: + secretName: mysecret + optional: false # 默认设置,意味着 "mysecret" 必须已经存在 ``` -{{< note >}} -如果你不希望执行 base64 编码转换,可以使用 `stringData` 字段代替。 +你要访问的每个 Secret 都需要通过 `.spec.volumes` 来引用。 + +如果 Pod 中包含多个容器,则每个容器需要自己的 `volumeMounts` 块, +不过针对每个 Secret 而言,只需要一份 `.spec.volumes` 设置。 + +{{< note >}} + +Kubernetes v1.22 版本之前都会自动创建用来访问 Kubernetes API 的凭证。 +这一老的机制是基于创建可被挂载到 Pod 中的令牌 Secret 来实现的。 +在最近的版本中,包括 Kubernetes v{{< skew currentVersion >}} 中,API 凭据是直接通过 +[TokenRequest](/docs/reference/kubernetes-api/authentication-resources/token-request-v1/) +API 来获得的,这一凭据会使用[投射卷](/zh/docs/reference/access-authn-authz/service-accounts-admin/#bound-service-account-token-volume) +挂载到 Pod 中。使用这种方式获得的令牌有确定的生命期,并且在挂载它们的 Pod +被删除时自动作废。 + + +你仍然可以[手动创建](/zh/docs/tasks/configure-pod-container/configure-service-account/#manually-create-a-service-account-api-token) +服务账号令牌。例如,当你需要一个永远都不过期的令牌时。 +不过,仍然建议使用 [TokenRequest](/docs/reference/kubernetes-api/authentication-resources/token-request-v1/) +子资源来获得访问 API 服务器的令牌。 {{< /note >}} -当你使用清单文件来创建这两类 Secret 时,API 服务器会检查 `data` 字段中是否 -存在所期望的主键,并且验证其中所提供的键值是否是合法的 JSON 数据。 -不过,API 服务器不会检查 JSON 数据本身是否是一个合法的 Docker 配置文件内容。 +#### 将 Secret 键投射到特定目录 -```shell -kubectl create secret docker-registry secret-tiger-docker \ - --docker-username=tiger \ - --docker-password=pass113 \ - --docker-email=tiger@acme.com -``` - - -上面的命令创建一个类型为 `kubernetes.io/dockerconfigjson` 的 Secret。 -如果你对 `data` 字段中的 `.dockerconfigjson` 内容进行转储,你会得到下面的 -JSON 内容,而这一内容是一个合法的 Docker 配置文件。 +你也可以控制 Secret 键所投射到的卷中的路径。 +你可以使用 `.spec.volumes[].secret.items` 字段来更改每个主键的目标路径: -```json -{ - "auths": { - "https://index.docker.io/v1/": { - "username": "tiger", - "password": "pass113", - "email": "tiger@acme.com", - "auth": "dGlnZXI6cGFzczExMw==" - } - } -} +```yaml +apiVersion: v1 +kind: Pod +metadata: + name: mypod +spec: + containers: + - name: mypod + image: redis + volumeMounts: + - name: foo + mountPath: "/etc/foo" + readOnly: true + volumes: + - name: foo + secret: + secretName: mysecret + items: + - key: username + path: my-group/my-username ``` -### 基本身份认证 Secret {#basic-authentication-secret} +将发生的事情如下: -`kubernetes.io/basic-auth` 类型用来存放用于基本身份认证所需的凭据信息。 -使用这种 Secret 类型时,Secret 的 `data` 字段必须包含以下两个键: +- `mysecret` 中的键 `username` 会出现在容器中的路径为 `/etc/foo/my-group/my-username`, + 而不是 `/etc/foo/username`。 +- Secret 对象的 `password` 键不会被投射。 -- `username`: 用于身份认证的用户名; -- `password`: 用于身份认证的密码或令牌。 +如果使用了 `.spec.volumes[].secret.items`,则只有 `items` 中指定了的主键会被投射。 +如果要使用 Secret 中的所有主键,则需要将它们全部枚举到 `items` 字段中。 + +如果你显式地列举了主键,则所列举的主键都必须在对应的 Secret 中存在。 +否则所在的卷不会被创建。 -以上两个键的键值都是 base64 编码的字符串。 -当然你也可以在创建 Secret 时使用 `stringData` 字段来提供明文形式的内容。 -下面的 YAML 是基本身份认证 Secret 的一个示例清单: +#### Secret 文件的访问权限 + +你可以为某个 Secret 主键设置 POSIX 文件访问权限位。 +如果你不指定访问权限,默认会使用 `0644`。 +你也可以为整个 Secret 卷设置默认的访问模式,然后再根据需要在主键层面重载。 + +例如,你可以像下面这样设置默认的模式: ```yaml apiVersion: v1 -kind: Secret +kind: Pod metadata: - name: secret-basic-auth -type: kubernetes.io/basic-auth -stringData: - username: admin - password: t0p-Secret + name: mypod +spec: + containers: + - name: mypod + image: redis + volumeMounts: + - name: foo + mountPath: "/etc/foo" + volumes: + - name: foo + secret: + secretName: mysecret + defaultMode: 0400 ``` -提供基本身份认证类型的 Secret 仅仅是出于用户方便性考虑。 -你也可以使用 `Opaque` 类型来保存用于基本身份认证的凭据。 -不过,使用内置的 Secret 类型的有助于对凭据格式进行归一化处理,并且 -API 服务器确实会检查 Secret 配置中是否提供了所需要的主键。 +该 Secret 被挂载在 `/etc/foo` 下,Secret 卷挂载所创建的所有文件的访问模式都是 `0400`。 +{{< note >}} +如果你是使用 JSON 来定义 Pod 或 Pod 模板,需要注意 JSON 规范不支持八进制的记数方式。 +你可以在 `defaultMode` 中设置十进制的值(例如,八进制中的 0400 在十进制中为 256)。 +如果你使用 YAML 来编写定义,你可以用八进制值来设置 `defaultMode`。 +{{< /note >}} -The builtin type `kubernetes.io/ssh-auth` is provided for storing data used in -SSH authentication. When using this Secret type, you will have to specify a -`ssh-privatekey` key-value pair in the `data` (or `stringData`) field. -as the SSH credential to use. + -### SSH 身份认证 Secret {#ssh-authentication-secrets} +#### 使用来自卷中的 Secret 值 {#consuming-secret-values-from-volumes} -Kubernetes 所提供的内置类型 `kubernetes.io/ssh-auth` 用来存放 SSH 身份认证中 -所需要的凭据。使用这种 Secret 类型时,你就必须在其 `data` (或 `stringData`) -字段中提供一个 `ssh-privatekey` 键值对,作为要使用的 SSH 凭据。 +在挂载了 Secret 卷的容器内,Secret 的主键都呈现为文件。 +Secret 的取值都是 Base64 编码的,保存在这些文件中。 -下面的 YAML 是一个 SSH 身份认证 Secret 的配置示例: +下面是在上例中的容器内执行命令的结果: -```yaml -apiVersion: v1 -kind: Secret -metadata: - name: secret-ssh-auth -type: kubernetes.io/ssh-auth -data: - # 此例中的实际数据被截断 - ssh-privatekey: | - MIIEpQIBAAKCAQEAulqb/Y ... +```shell +ls /etc/foo/ ``` -提供 SSH 身份认证类型的 Secret 仅仅是出于用户方便性考虑。 -你也可以使用 `Opaque` 类型来保存用于 SSH 身份认证的凭据。 -不过,使用内置的 Secret 类型的有助于对凭据格式进行归一化处理,并且 -API 服务器确实会检查 Secret 配置中是否提供了所需要的主键。 +输出类似于: + +``` +username +password +``` + +```shell +cat /etc/foo/username +``` -{{< caution >}} -SSH 私钥自身无法建立 SSH 客户端与服务器端之间的可信连接。 -需要其它方式来建立这种信任关系,以缓解“中间人(Man In The Middle)” -攻击,例如向 ConfigMap 中添加一个 `known_hosts` 文件。 -{{< /caution >}} +输出类似于: + +``` +admin +``` + +```shell +cat /etc/foo/password +``` +输出类似于: -Kubernetes provides a builtin Secret type `kubernetes.io/tls` for storing -a certificate and its associated key that are typically used for TLS . This -data is primarily used with TLS termination of the Ingress resource, but may -be used with other resources or directly by a workload. -When using this type of Secret, the `tls.key` and the `tls.crt` key must be provided -in the `data` (or `stringData`) field of the Secret configuration, although the API -server doesn't actually validate the values for each key. +``` +1f2d1e2e67df +``` -The following YAML contains an example config for a TLS Secret: + -### TLS Secret +容器中的程序要负责根据需要读取 Secret 数据。 -Kubernetes 提供一种内置的 `kubernetes.io/tls` Secret 类型,用来存放证书 -及其相关密钥(通常用在 TLS 场合)。 -此类数据主要提供给 Ingress 资源,用以终结 TLS 链接,不过也可以用于其他 -资源或者负载。当使用此类型的 Secret 时,Secret 配置中的 `data` (或 -`stringData`)字段必须包含 `tls.key` 和 `tls.crt` 主键,尽管 API 服务器 -实际上并不会对每个键的取值作进一步的合法性检查。 + +#### 挂载的 Secret 是被自动更新的 {#mounted-secrets-are-updated-automatically} -```yaml -apiVersion: v1 -kind: Secret -metadata: - name: secret-tls -type: kubernetes.io/tls -data: - # 此例中的数据被截断 - tls.crt: | - MIIC2DCCAcCgAwIBAgIBATANBgkqh ... - tls.key: | - MIIEpgIBAAKCAQEA7yn3bRHQ5FHMQ ... -``` +当卷中包含来自 Secret 的数据,而对应的 Secret 被更新,Kubernetes +会跟踪到这一操作并更新卷中的数据。更新的方式是保证最终一致性。 +{{< note >}} -提供 TLS 类型的 Secret 仅仅是出于用户方便性考虑。 -你也可以使用 `Opaque` 类型来保存用于 TLS 服务器与/或客户端的凭据。 -不过,使用内置的 Secret 类型的有助于对凭据格式进行归一化处理,并且 -API 服务器确实会检查 Secret 配置中是否提供了所需要的主键。 +对于以 [subPath](/zh/docs/concepts/storage/volumes#using-subpath) 形式挂载 Secret 卷的容器而言, +它们无法收到自动的 Secret 更新。 +{{< /note >}} -当使用 `kubectl` 来创建 TLS Secret 时,你可以像下面的例子一样使用 `tls` -子命令: + +Kubelet 组件会维护一个缓存,在其中保存节点上 Pod 卷中使用的 Secret 的当前主键和取值。 +你可以配置 kubelet 如何检测所缓存数值的变化。 +[kubelet 配置](/zh/docs/reference/config-api/kubelet-config.v1beta1/)中的 +`configMapAndSecretChangeDetectionStrategy` 字段控制 kubelet 所采用的策略。 +默认的策略是 `Watch`。 -```shell -kubectl create secret tls my-tls-secret \ - --cert=path/to/cert/file \ - --key=path/to/key/file -``` + +对 Secret 的更新操作既可以通过 API 的 watch 机制(默认)来传播, +基于设置了生命期的缓存获取,也可以通过 kubelet 的同步回路来从集群的 API +服务器上轮询获取。 -这里的公钥/私钥对都必须事先已存在。用于 `--cert` 的公钥证书必须是 .PEM 编码的 -(Base64 编码的 DER 格式),且与 `--key` 所给定的私钥匹配。 -私钥必须是通常所说的 PEM 私钥格式,且未加密。对这两个文件而言,PEM 格式数据 -的第一行和最后一行(例如,证书所对应的 `--------BEGIN CERTIFICATE-----` 和 -`-------END CERTIFICATE----`)都不会包含在其中。 +As a result, the total delay from the moment when the Secret is updated to the moment +when new keys are projected to the Pod can be as long as the kubelet sync period + cache +propagation delay, where the cache propagation delay depends on the chosen cache type +(following the same order listed in the previous paragraph, these are: +watch propagation delay, the configured cache TTL, or zero for direct polling). +--> +因此,从 Secret 被更新到新的主键被投射到 Pod 中,中间存在一个延迟。 +这一延迟的上限是 kubelet 的同步周期加上缓存的传播延迟, +其中缓存的传播延迟取决于所选择的缓存类型。 +对应上一段中提到的几种传播机制,延迟时长为 watch 的传播延迟、所配置的缓存 TTL +或者对于直接轮询而言是零。 + -### 启动引导令牌 Secret {#bootstrap-token-secrets} +### 以环境变量的方式使用 Secret {#using-secrets-as-environment-variables} -通过将 Secret 的 `type` 设置为 `bootstrap.kubernetes.io/token` 可以创建 -启动引导令牌类型的 Secret。这种类型的 Secret 被设计用来支持节点的启动引导过程。 -其中包含用来为周知的 ConfigMap 签名的令牌。 +如果需要在 Pod 中以{{< glossary_tooltip text="环境变量" term_id="container-env-variables" >}} +的形式使用 Secret: -启动引导令牌 Secret 通常创建于 `kube-system` 名字空间内,并以 -`bootstrap-token-<令牌 ID>` 的形式命名;其中 `<令牌 ID>` 是一个由 6 个字符组成 -的字符串,用作令牌的标识。 +1. 创建 Secret(或者使用现有 Secret)。多个 Pod 可以引用同一个 Secret。 +1. 更改 Pod 定义,在要使用 Secret 键值的每个容器中添加与所使用的主键对应的环境变量。 + 读取 Secret 主键的环境变量应该在 `env[].valueFrom.secretKeyRef` 中填写 Secret + 的名称和主键名称。 +1. 更改你的镜像或命令行,以便程序读取环境变量中保存的值。 -以 Kubernetes 清单文件的形式,某启动引导令牌 Secret 可能看起来像下面这样: + +下面是一个通过环境变量来使用 Secret 的示例 Pod: ```yaml apiVersion: v1 -kind: Secret +kind: Pod metadata: - name: bootstrap-token-5emitj - namespace: kube-system -type: bootstrap.kubernetes.io/token -data: - auth-extra-groups: c3lzdGVtOmJvb3RzdHJhcHBlcnM6a3ViZWFkbTpkZWZhdWx0LW5vZGUtdG9rZW4= - expiration: MjAyMC0wOS0xM1QwNDozOToxMFo= - token-id: NWVtaXRq - token-secret: a3E0Z2lodnN6emduMXAwcg== - usage-bootstrap-authentication: dHJ1ZQ== - usage-bootstrap-signing: dHJ1ZQ== -``` - - -启动引导令牌类型的 Secret 会在 `data` 字段中包含如下主键: +#### 非法环境变量 {#restriction-env-from-invalid} -- `token-id`:由 6 个随机字符组成的字符串,作为令牌的标识符。必需。 -- `token-secret`:由 16 个随机字符组成的字符串,包含实际的令牌机密。必需。 -- `description`:供用户阅读的字符串,描述令牌的用途。可选。 -- `expiration`:一个使用 RFC3339 来编码的 UTC 绝对时间,给出令牌要过期的时间。可选。 -- `usage-bootstrap-`:布尔类型的标志,用来标明启动引导令牌的其他用途。 -- `auth-extra-groups`:用逗号分隔的组名列表,身份认证时除被认证为 - `system:bootstrappers` 组之外,还会被添加到所列的用户组中。 +对于通过 `envFrom` 字段来填充环境变量的 Secret 而言, +如果其中包含的主键不能被当做合法的环境变量名,这些主键会被忽略掉。 +Pod 仍然可以启动。 +如果你定义的 Pod 中包含非法的变量名称,则 Pod 可能启动失败, +会形成 reason 为 `InvalidVariableNames` 的事件,以及列举被略过的非法主键的消息。 +下面的例子中展示了一个 Pod,引用的是名为 `mysecret` 的 Secret, +其中包含两个非法的主键:`1badkey` 和 `2alsobad`。 -```yaml -apiVersion: v1 -kind: Secret -metadata: - # Note how the Secret is named - name: bootstrap-token-5emitj - # A bootstrap token Secret usually resides in the kube-system namespace - namespace: kube-system -type: bootstrap.kubernetes.io/token -stringData: - auth-extra-groups: "system:bootstrappers:kubeadm:default-node-token" - expiration: "2020-09-13T04:39:10Z" - # This token ID is used in the name - token-id: "5emitj" - token-secret: "kq4gihvszzgn1p0r" - # This token can be used for authentication - usage-bootstrap-authentication: "true" - # and it can be used for signing - usage-bootstrap-signing: "true" +```shell +kubectl get events ``` + + -上面的 YAML 文件可能看起来令人费解,因为其中的数值均为 base64 编码的字符串。 -实际上,你完全可以使用下面的 YAML 来创建一个一模一样的 Secret: +输出类似于: -```yaml -apiVersion: v1 -kind: Secret -metadata: - # 注意 Secret 的命名方式 - name: bootstrap-token-5emitj - # 启动引导令牌 Secret 通常位于 kube-system 名字空间 - namespace: kube-system -type: bootstrap.kubernetes.io/token -stringData: - auth-extra-groups: "system:bootstrappers:kubeadm:default-node-token" - expiration: "2020-09-13T04:39:10Z" - # 此令牌 ID 被用于生成 Secret 名称 - token-id: "5emitj" - token-secret: "kq4gihvszzgn1p0r" - # 此令牌还可用于 authentication (身份认证) - usage-bootstrap-authentication: "true" - # 且可用于 signing (证书签名) - usage-bootstrap-signing: "true" +``` +LASTSEEN FIRSTSEEN COUNT NAME KIND SUBOBJECT TYPE REASON +0s 0s 1 dapi-test-pod Pod Warning InvalidEnvironmentVariableNames kubelet, 127.0.0.1 Keys [1badkey, 2alsobad] from the EnvFrom secret default/mysecret were skipped since they are considered invalid environment variable names. ``` -## 创建 Secret {#creating-a-secret} +#### 通过环境变量使用 Secret 值 -有几种不同的方式来创建 Secret: +在通过环境变量来使用 Secret 的容器中,Secret 主键展现为普通的环境变量。 +这些变量的取值是 Secret 数据的 Base64 解码值。 -- [使用 `kubectl` 命令创建 Secret](/zh/docs/tasks/configmap-secret/managing-secret-using-kubectl/) -- [使用配置文件来创建 Secret](/zh/docs/tasks/configmap-secret/managing-secret-using-config-file/) -- [使用 kustomize 来创建 Secret](/zh/docs/tasks/configmap-secret/managing-secret-using-kustomize/) +下面是在前文示例中的容器内执行命令的结果: - -## 编辑 Secret {#editing-a-secret} +输出类似于: -你可以通过下面的命令编辑现有的 Secret: +``` +admin +``` ```shell -kubectl edit secrets mysecret +echo "$SECRET_PASSWORD" ``` -这一命令会打开默认的编辑器,允许你更新 `data` 字段中包含的 -base64 编码的 Secret 值: +输出类似于: -```yaml -# Please edit the object below. Lines beginning with a '#' will be ignored, -# and an empty file will abort the edit. If an error occurs while saving this file will be -# reopened with the relevant failures. -# -apiVersion: v1 -data: - username: YWRtaW4= - password: MWYyZDFlMmU2N2Rm -kind: Secret -metadata: - annotations: - kubectl.kubernetes.io/last-applied-configuration: { ... } - creationTimestamp: 2016-01-22T18:41:56Z - name: mysecret - namespace: default - resourceVersion: "164619" - uid: cfee02d6-c137-11e5-8d73-42010af00002 -type: Opaque +``` +1f2d1e2e67df ``` +{{< note >}} -## 使用 Secret {#using-secrets} - -Secret 可以作为数据卷被挂载,或作为{{< glossary_tooltip text="环境变量" term_id="container-env-variables" >}} -暴露出来以供 Pod 中的容器使用。它们也可以被系统的其他部分使用,而不直接暴露在 Pod 内。 -例如,它们可以保存凭据,系统的其他部分将用它来代表你与外部系统进行交互。 +如果容器已经在通过环境变量来使用 Secret,Secret 更新在容器内是看不到的, +除非容器被重启。有一些第三方的解决方案,能够在 Secret 发生变化时触发容器重启。 +{{< /note >}} +### 容器镜像拉取 Secret {#using-imagepullsecrets} -1. Create a secret or use an existing one. Multiple pods can reference the same secret. -1. Modify your Pod definition to add a volume under `.spec.volumes[]`. Name the volume anything, and have a `.spec.volumes[].secret.secretName` field equal to the name of the secret object. -1. Add a `.spec.containers[].volumeMounts[]` to each container that needs the secret. Specify `.spec.containers[].volumeMounts[].readOnly = true` and `.spec.containers[].volumeMounts[].mountPath` to an unused directory name where you would like the secrets to appear. -1. Modify your image and/or command line so that the program looks for files in that directory. Each key in the secret `data` map becomes the filename under `mountPath`. +如果你尝试从私有仓库拉取容器镜像,你需要一种方式让每个节点上的 kubelet +能够完成与镜像库的身份认证。你可以配置 *镜像拉取 Secret* 来实现这点。 +Secret 是在 Pod 层面来配置的。 -This is an example of a pod that mounts a secret in a volume: + +Pod 的 `imagePullSecrets` 字段是一个对 Pod 所在的名字空间中的 Secret +的引用列表。你可以使用 `imagePullSecrets` 来将镜像仓库访问凭据传递给 kubelet。 +kubelet 使用这个信息来替你的 Pod 拉取私有镜像。 +参阅 [Pod API 参考](/docs/reference/kubernetes-api/workload-resources/pod-v1/#PodSpec) +中的 `PodSpec` 进一步了解 `imagePullSecrets` 字段。 -### 在 Pod 中使用 Secret 文件 {#using-secrets-as-files-from-a-pod} + +#### 使用 imagePullSecrets -1. 创建一个 Secret 或者使用已有的 Secret。多个 Pod 可以引用同一个 Secret。 -1. 修改你的 Pod 定义,在 `spec.volumes[]` 下增加一个卷。可以给这个卷随意命名, - 它的 `spec.volumes[].secret.secretName` 必须是 Secret 对象的名字。 -1. 将 `spec.containers[].volumeMounts[]` 加到需要用到该 Secret 的容器中。 - 指定 `spec.containers[].volumeMounts[].readOnly = true` 和 - `spec.containers[].volumeMounts[].mountPath` 为你想要该 Secret 出现的尚未使用的目录。 -1. 修改你的镜像并且/或者命令行,让程序从该目录下寻找文件。 - Secret 的 `data` 映射中的每一个键都对应 `mountPath` 下的一个文件名。 +`imagePullSecrets` 字段是一个列表,包含对同一名字空间中 Secret 的引用。 +你可以使用 `imagePullSecrets` 将包含 Docker(或其他)镜像仓库密码的 Secret +传递给 kubelet。kubelet 使用此信息来替 Pod 拉取私有镜像。 +参阅 [PodSpec API ](/docs/reference/kubernetes-api/workload-resources/pod-v1/#PodSpec) +进一步了解 `imagePullSecrets` 字段。 -这是一个在 Pod 中使用存放在挂载卷中 Secret 的例子: + +##### 手动设定 imagePullSecret + +你可以通过阅读[容器镜像](/zh/docs/concepts/containers/images/#specifying-imagepullsecrets-on-a-pod) +文档了解如何设置 `imagePullSecrets`。 +##### 设置 imagePullSecrets 为自动挂载 -You can package many files into one secret, or use many secrets, whichever is convenient. +你可以手动创建 `imagePullSecret`,并在一个 ServiceAccount 中引用它。 +对使用该 ServiceAccount 创建的所有 Pod,或者默认使用该 ServiceAccount 创建的 Pod +而言,其 `imagePullSecrets` 字段都会设置为该服务账号。 +请阅读[向服务账号添加 ImagePullSecrets](/zh/docs/tasks/configure-pod-container/configure-service-account/#add-imagepullsecrets-to-a-service-account) +来详细了解这一过程。 -#### Projection of Secret keys to specific paths + -您想要用的每个 Secret 都需要在 `spec.volumes` 中引用。 +### 在静态 Pod 中使用 Secret {#restriction-static-pod} + +你不可以在{{< glossary_tooltip text="静态 Pod" term_id="static-pod" >}}. +中使用 ConfigMap 或 Secret。 -如果 Pod 中有多个容器,每个容器都需要自己的 `volumeMounts` 配置块, -但是每个 Secret 只需要一个 `spec.volumes`。 + +## 使用场景 {#use-case} -#### 将 Secret 键名映射到特定路径 +### 使用场景:作为容器环境变量 -我们还可以控制 Secret 键名在存储卷中映射的的路径。 -你可以使用 `spec.volumes[].secret.items` 字段修改每个键对应的目标路径: +创建 Secret: ```yaml apiVersion: v1 -kind: Pod +kind: Secret metadata: - name: mypod -spec: - containers: - - name: mypod - image: redis - volumeMounts: - - name: foo - mountPath: "/etc/foo" - readOnly: true - volumes: - - name: foo - secret: - secretName: mysecret - items: - - key: username - path: my-group/my-username + name: mysecret +type: Opaque +data: + USER_NAME: YWRtaW4= + PASSWORD: MWYyZDFlMmU2N2Rm ``` -将会发生什么呢: +创建 Secret: -- `username` Secret 存储在 `/etc/foo/my-group/my-username` 文件中而不是 `/etc/foo/username` 中。 -- `password` Secret 没有被映射 - -如果使用了 `spec.volumes[].secret.items`,只有在 `items` 中指定的键会被映射。 -要使用 Secret 中所有键,就必须将它们都列在 `items` 字段中。 -所有列出的键名必须存在于相应的 Secret 中。否则,不会创建卷。 - -#### Secret 文件权限 - -你还可以指定 Secret 将拥有的权限模式位。如果不指定,默认使用 `0644`。 -你可以为整个 Secret 卷指定默认模式;如果需要,可以为每个密钥设定重载值。 +```shell +kubectl apply -f mysecret.yaml +``` -例如,您可以指定如下默认模式: + +使用 `envFrom` 来将 Secret 的所有数据定义为容器的环境变量。 +来自 Secret 的主键成为 Pod 中的环境变量名称: ```yaml apiVersion: v1 kind: Pod metadata: - name: mypod + name: secret-test-pod spec: containers: - - name: mypod - image: redis - volumeMounts: - - name: foo - mountPath: "/etc/foo" - volumes: - - name: foo - secret: - secretName: mysecret - defaultMode: 256 + - name: test-container + image: k8s.gcr.io/busybox + command: [ "/bin/sh", "-c", "env" ] + envFrom: + - secretRef: + name: mysecret + restartPolicy: Never ``` -之后,Secret 将被挂载到 `/etc/foo` 目录,而所有通过该 Secret 卷挂载 -所创建的文件的权限都是 `0400`。 - -请注意,JSON 规范不支持八进制符号,因此使用 256 值作为 0400 权限。 -如果你使用 YAML 而不是 JSON,则可以使用八进制符号以更自然的方式指定权限。 - - -注意,如果你通过 `kubectl exec` 进入到 Pod 中,你需要沿着符号链接来找到 -所期望的文件模式。例如,下面命令检查 Secret 文件的访问模式: +创建包含一些 SSH 密钥的 Secret: ```shell -kubectl exec mypod -it sh - -cd /etc/foo -ls -l +kubectl create secret generic ssh-key-secret --from-file=ssh-privatekey=/path/to/.ssh/id_rsa --from-file=ssh-publickey=/path/to/.ssh/id_rsa.pub ``` 输出类似于: ``` -total 0 -lrwxrwxrwx 1 root root 15 May 18 00:18 password -> ..data/password -lrwxrwxrwx 1 root root 15 May 18 00:18 username -> ..data/username +secret "ssh-key-secret" created ``` -沿着符号链接,可以查看文件的访问模式: - -```shell -cd /etc/foo/..data -ls -l -``` +你也可以创建一个 `kustomization.yaml` 文件,在其 `secretGenerator` +字段中包含 SSH 密钥。 +{{< caution >}} -输出类似于: - -``` -total 8 --r-------- 1 root root 12 May 18 00:18 password --r-------- 1 root root 5 May 18 00:18 username -``` +在提供你自己的 SSH 密钥之前要仔细思考:集群的其他用户可能有权访问该 Secret。 +你也可以创建一个 SSH 私钥,代表一个你希望与你共享 Kubernetes 集群的其他用户分享的服务标识。 +当凭据信息被泄露时,你可以收回该访问权限。 +{{< /caution >}} -你还可以使用映射,如上一个示例,并为不同的文件指定不同的权限,如下所示: + +现在你可以创建一个 Pod,在其中访问包含 SSH 密钥的 Secret,并通过卷的方式来使用它: ```yaml apiVersion: v1 kind: Pod metadata: - name: mypod -spec: - containers: - - name: mypod - image: redis - volumeMounts: - - name: foo - mountPath: "/etc/foo" + name: secret-test-pod + labels: + name: secret-test +spec: volumes: - - name: foo + - name: secret-volume secret: - secretName: mysecret - items: - - key: username - path: my-group/my-username - mode: 511 + secretName: ssh-key-secret + containers: + - name: ssh-test-container + image: mySshImage + volumeMounts: + - name: secret-volume + readOnly: true + mountPath: "/etc/secret-volume" ``` +容器命令执行时,秘钥的数据可以在下面的位置访问到: -#### Consuming Secret Values from Volumes +``` +/etc/secret-volume/ssh-publickey +/etc/secret-volume/ssh-privatekey +``` -Inside the container that mounts a secret volume, the secret keys appear as -files and the secret values are base-64 decoded and stored inside these files. -This is the result of commands -executed inside the container from the example above: + -在这里,位于 `/etc/foo/my-group/my-username` 的文件的权限值为 `0777`。 -由于 JSON 限制,必须以十进制格式指定模式,即 `511`。 - -请注意,如果稍后读取此权限值,可能会以十进制格式显示。 +容器就可以随便使用 Secret 数据来建立 SSH 连接。 -#### 使用来自卷中的 Secret 值 {#consuming-secret-values-from-volumes} + +### 使用场景:带有生产、测试环境凭据的 Pod - -输出类似于: +这一示例所展示的一个 Pod 会使用包含生产环境凭据的 Secret,另一个 Pod +使用包含测试环境凭据的 Secret。 -``` -username -password -``` +你可以创建一个带有 `secretGenerator` 字段的 `kustomization.yaml` 文件或者运行 +`kubectl create secret` 来创建 Secret。 ```shell -cat /etc/foo/username +kubectl create secret generic prod-db-secret --from-literal=username=produser --from-literal=password=Y4nys7f11 ``` - + 输出类似于: ``` -admin +secret "prod-db-secret" created ``` + +你也可以创建一个包含测试环境凭据的 Secret: + ```shell -cat /etc/foo/password +kubectl create secret generic test-db-secret --from-literal=username=testuser --from-literal=password=iluvtests ``` - + 输出类似于: ``` -1f2d1e2e67df +secret "test-db-secret" created ``` +{{< note >}} -容器中的程序负责从文件中读取 secret。 +特殊字符(例如 `$`、`\`、`*`、`=` 和 `!`)会被你的 +[Shell](https://en.wikipedia.org/wiki/Shell_(computing))解释,因此需要转义。 -#### 挂载的 Secret 会被自动更新 - -当已经存储于卷中被使用的 Secret 被更新时,被映射的键也将终将被更新。 -组件 kubelet 在周期性同步时检查被挂载的 Secret 是不是最新的。 -但是,它会使用其本地缓存的数值作为 Secret 的当前值。 - -缓存的类型可以使用 [KubeletConfiguration 结构](/zh/docs/reference/config-api/kubelet-config.v1beta1/) -中的 `ConfigMapAndSecretChangeDetectionStrategy` 字段来配置。 -它可以通过 watch 操作来传播(默认),基于 TTL 来刷新,也可以 -将所有请求直接重定向到 API 服务器。 -因此,从 Secret 被更新到将新 Secret 被投射到 Pod 的那一刻的总延迟可能与 -kubelet 同步周期 + 缓存传播延迟一样长,其中缓存传播延迟取决于所选的缓存类型。 -对应于不同的缓存类型,该延迟或者等于 watch 传播延迟,或者等于缓存的 TTL, -或者为 0。 +在大多数 Shell 中,对密码进行转义的最简单方式是用单引号(`'`)将其括起来。 +例如,如果你的实际密码是 `S!B\*d$zDsb`,则应通过以下方式执行命令: +```shell +kubectl create secret generic dev-db-secret --from-literal=username=devuser --from-literal=password='S!B\*d$zDsb=' +``` -{{< note >}} -使用 Secret 作为[子路径](/zh/docs/concepts/storage/volumes#using-subpath)卷挂载的容器 -不会收到 Secret 更新。 +你无需对文件中的密码(`--from-file`)中的特殊字符进行转义。 {{< /note >}} -#### 以环境变量的形式使用 Secrets {#using-secrets-as-environment-variables} - -将 Secret 作为 Pod 中的{{< glossary_tooltip text="环境变量" term_id="container-env-variables" >}}使用: - -1. 创建一个 Secret 或者使用一个已存在的 Secret。多个 Pod 可以引用同一个 Secret。 -1. 修改 Pod 定义,为每个要使用 Secret 的容器添加对应 Secret 键的环境变量。 - 使用 Secret 键的环境变量应在 `env[x].valueFrom.secretKeyRef` 中指定 - 要包含的 Secret 名称和键名。 -1. 更改镜像并/或者命令行,以便程序在指定的环境变量中查找值。 +现在生成 Pod: -这是一个使用来自环境变量中的 Secret 值的 Pod 示例: - -```yaml +```shell +cat < pod.yaml apiVersion: v1 -kind: Pod -metadata: - name: secret-env-pod -spec: - containers: - - name: mycontainer - image: redis - env: - - name: SECRET_USERNAME - valueFrom: - secretKeyRef: - name: mysecret - key: username - - name: SECRET_PASSWORD - valueFrom: - secretKeyRef: - name: mysecret - key: password - restartPolicy: Never +kind: List +items: +- kind: Pod + apiVersion: v1 + metadata: + name: prod-db-client-pod + labels: + name: prod-db-client + spec: + volumes: + - name: secret-volume + secret: + secretName: prod-db-secret + containers: + - name: db-client-container + image: myClientImage + volumeMounts: + - name: secret-volume + readOnly: true + mountPath: "/etc/secret-volume" +- kind: Pod + apiVersion: v1 + metadata: + name: test-db-client-pod + labels: + name: test-db-client + spec: + volumes: + - name: secret-volume + secret: + secretName: test-db-secret + containers: + - name: db-client-container + image: myClientImage + volumeMounts: + - name: secret-volume + readOnly: true + mountPath: "/etc/secret-volume" +EOF ``` -#### 使用来自环境变量的 Secret 值 {#consuming-secret-values-from-environment-variables} - -在一个以环境变量形式使用 Secret 的容器中,Secret 键表现为常规的环境变量,其中 -包含 Secret 数据的 base-64 解码值。这是从上面的示例在容器内执行的命令的结果: +将 Pod 添加到同一 `kustomization.yaml` 文件中: ```shell -echo $SECRET_USERNAME +cat <> kustomization.yaml +resources: +- pod.yaml +EOF ``` -输出类似于: - -``` -admin -``` +通过下面的命令在 API 服务器上应用所有这些对象: ```shell -echo $SECRET_PASSWORD +kubectl apply -k . ``` -输出类似于: +两个文件都会在其文件系统中出现下面面的文件,文件中内容是各个容器的环境值: ``` -1f2d1e2e67df +/etc/secret-volume/username +/etc/secret-volume/password ``` -#### Secret 更新之后对应的环境变量不会被更新 - -如果某个容器已经在通过环境变量使用某 Secret,对该 Secret 的更新不会被 -容器马上看见,除非容器被重启。有一些第三方的解决方案能够在 Secret 发生 -变化时触发容器重启。 +注意这两个 Pod 的规约中只有一个字段不同。 +这便于基于相同的 Pod 模板生成具有不同能力的 Pod。 -## 不可更改的 Secret {#secret-immutable} +You could further simplify the base Pod specification by using two service accounts: -{{< feature-state for_k8s_version="v1.21" state="stable" >}} - - -Kubernetes 的特性 _不可变的 Secret 和 ConfigMap_ 提供了一种可选配置, -可以设置各个 Secret 和 ConfigMap 为不可变的。 -对于大量使用 Secret 的集群(至少有成千上万各不相同的 Secret 供 Pod 挂载), -禁止变更它们的数据有下列好处: +你可以通过使用两个服务账号来进一步简化这一基本的 Pod 规约: -- 防止意外(或非预期的)更新导致应用程序中断 -- 通过将 Secret 标记为不可变来关闭 kube-apiserver 对其的监视,从而显著降低 - kube-apiserver 的负载,提升集群性能。 +1. `prod-user` 服务账号使用 `prod-db-secret` +1. `test-user` 服务账号使用 `test-db-secret` + +Pod 规约简化为: + +```yaml +apiVersion: v1 +kind: Pod +metadata: + name: prod-db-client-pod + labels: + name: prod-db-client +spec: + serviceAccount: prod-db-client + containers: + - name: db-client-container + image: myClientImage +``` -这个特性通过 `ImmutableEmphemeralVolumes` -[特性门控](/zh/docs/reference/command-line-tools-reference/feature-gates/) -来控制,从 v1.19 开始默认启用。 -你可以通过将 Secret 的 `immutable` 字段设置为 `true` 创建不可更改的 Secret。 -例如: +### 使用场景:在 Secret 卷中带句点的文件 + +通过定义以句点(`.`)开头的主键,你可以“隐藏”你的数据。 +这些主键代表的是以句点开头的文件或“隐藏”文件。 +例如,当下面的 Secret 被挂载到 `secret-volume` 卷中时: ```yaml apiVersion: v1 kind: Secret metadata: - ... + name: dotfile-secret data: - ... -immutable: true + .secret-file: dmFsdWUtMg0KDQo= +--- +apiVersion: v1 +kind: Pod +metadata: + name: secret-dotfiles-pod +spec: + volumes: + - name: secret-volume + secret: + secretName: dotfile-secret + containers: + - name: dotfile-test-container + image: k8s.gcr.io/busybox + command: + - ls + - "-l" + - "/etc/secret-volume" + volumeMounts: + - name: secret-volume + readOnly: true + mountPath: "/etc/secret-volume" ``` + +卷中会包含一个名为 `.secret-file` 的文件,并且容器 `dotfile-test-container` +中此文件位于路径 `/etc/secret-volume/.secret-file` 处。 + {{< note >}} -一旦一个 Secret 或 ConfigMap 被标记为不可更改,撤销此操作或者更改 `data` 字段的内容都是 _不_ 可能的。 -只能删除并重新创建这个 Secret。现有的 Pod 将维持对已删除 Secret 的挂载点 - 建议重新创建这些 Pod。 +以句点开头的文件会在 `ls -l` 的输出中被隐藏起来; +列举目录内容时你必须使用 `ls -la` 才能看到它们。 {{< /note >}} -#### 使用 imagePullSecret {#using-imagepullsecrets} - -`imagePullSecrets` 字段中包含一个列表,列举对同一名字空间中的 Secret 的引用。 -你可以使用 `imagePullSecrets` 将包含 Docker(或其他)镜像仓库密码的 Secret 传递给 -kubelet。kubelet 使用此信息来替你的 Pod 拉取私有镜像。 -关于 `imagePullSecrets` 字段的更多信息,请参考 -[PodSpec API](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#podspec-v1-core) 文档。 +### 使用场景:仅对 Pod 中一个容器可见的 Secret -#### 手动指定 imagePullSecret - -你可以阅读[容器镜像文档](/zh/docs/concepts/containers/images/#specifying-imagepullsecrets-on-a-pod) -以了解如何设置 `imagePullSecrets`。 +考虑一个需要处理 HTTP 请求,执行某些复杂的业务逻辑,之后使用 HMAC +来对某些消息进行签名的程序。因为这一程序的应用逻辑很复杂, +其中可能包含未被注意到的远程服务器文件读取漏洞, +这种漏洞可能会把私钥暴露给攻击者。 -#### 设置自动附加 imagePullSecrets - -您可以手动创建 `imagePullSecret`,并在 ServiceAccount 中引用它。 -使用该 ServiceAccount 创建的任何 Pod 和默认使用该 ServiceAccount 的 -Pod 将会将其的 imagePullSecret 字段设置为服务帐户的 imagePullSecret 值。 -有关该过程的详细说明,请参阅 -[将 ImagePullSecrets 添加到服务帐户](/zh/docs/tasks/configure-pod-container/configure-service-account/#adding-imagepullsecrets-to-a-service-account)。 - +This could be divided into two processes in two containers: a frontend container +which handles user interaction and business logic, but which cannot see the +private key; and a signer container that can see the private key, and responds +to simple signing requests from the frontend (for example, over localhost networking). +--> +这一程序可以分隔成两个容器中的两个进程:前端容器要处理用户交互和业务逻辑, +但无法看到私钥;签名容器可以看到私钥,并对来自前端的简单签名请求作出响应 +(例如,通过本地主机网络)。 +采用这种划分的方法,攻击者现在必须欺骗应用服务器来做一些其他操作, +而这些操作可能要比读取一个文件要复杂很多。 -### Restrictions + -## 详细说明 {#details} - -### 限制 {#restrictions} +## Secret 的类型 {#secret-types} -Kubernetes 会验证 Secret 作为卷来源时所给的对象引用确实指向一个类型为 -Secret 的对象。因此,Secret 需要先于任何依赖于它的 Pod 创建。 +创建 Secret 时,你可以使用 [Secret](/docs/reference/kubernetes-api/config-and-storage-resources/secret-v1/) +资源的 `type` 字段,或者与其等价的 `kubectl` 命令行参数(如果有的话)为其设置类型。 +Secret 类型有助于对 Secret 数据进行编程处理。 -Secret API 对象处于某{{< glossary_tooltip text="名字空间" term_id="namespace" >}} -中。它们只能由同一命名空间中的 Pod 引用。 +Kubernetes 提供若干种内置的类型,用于一些常见的使用场景。 +针对这些类型,Kubernetes 所执行的合法性检查操作以及对其所实施的限制各不相同。 +| 内置类型 | 用法 | +|--------------|-------| +| `Opaque` | 用户定义的任意数据 | +| `kubernetes.io/service-account-token` | 服务账号令牌 | +| `kubernetes.io/dockercfg` | `~/.dockercfg` 文件的序列化形式 | +| `kubernetes.io/dockerconfigjson` | `~/.docker/config.json` 文件的序列化形式 | +| `kubernetes.io/basic-auth` | 用于基本身份认证的凭据 | +| `kubernetes.io/ssh-auth` | 用于 SSH 身份认证的凭据 | +| `kubernetes.io/tls` | 用于 TLS 客户端或者服务器端的数据 | +| `bootstrap.kubernetes.io/token` | 启动引导令牌数据 | -Kubelet only supports use of secrets for Pods it gets from the API server. -This includes any pods created using kubectl, or indirectly via a replication -controller. It does not include pods created via the kubelets -`--manifest-url` flag, its `--config` flag, or its REST API (these are -not common ways to create pods.) -The `spec` of a {{< glossary_tooltip text="static Pod" term_id="static-pod" >}} cannot refer to a Secret -or any other API objects. + -每个 Secret 的大小限制为 1MB。这是为了防止创建非常大的 Secret 导致 API 服务器 -和 kubelet 的内存耗尽。然而,创建过多较小的 Secret 也可能耗尽内存。 -更全面得限制 Secret 内存用量的功能还在计划中。 +通过为 Secret 对象的 `type` 字段设置一个非空的字符串值,你也可以定义并使用自己 +Secret 类型。如果 `type` 值为空字符串,则被视为 `Opaque` 类型。 -kubelet 仅支持从 API 服务器获得的 Pod 使用 Secret。 -这包括使用 `kubectl` 创建的所有 Pod,以及间接通过副本控制器创建的 Pod。 -它不包括通过 kubelet `--manifest-url` 标志,`--config` 标志或其 REST API -创建的 Pod(这些不是创建 Pod 的常用方法)。 -{{}} -的 `spec` 不能引用 Secret 或任何其他 API 对象。 + +Kubernetes 并不对类型的名称作任何限制。不过,如果你要使用内置类型之一, +则你必须满足为该类型所定义的所有要求。 +如果你要定义一种公开使用的 Secret 类型,请遵守 Secret 类型的约定和结构, +在类型名签名添加域名,并用 `/` 隔开。 +例如:`cloud-hosting.example.net/cloud-api-credentials`。 -References via `secretKeyRef` to keys that do not exist in a named Secret -will prevent the pod from starting. + -以环境变量形式在 Pod 中使用 Secret 之前必须先创建 -Secret,除非该环境变量被标记为可选的。 -Pod 中引用不存在的 Secret 时将无法启动。 - -使用 `secretKeyRef` 时,如果引用了指定 Secret 不存在的键,对应的 Pod 也无法启动。 +### Opaque Secret -对于通过 `envFrom` 填充环境变量的 Secret,如果 Secret 中包含的键名无法作为 -合法的环境变量名称,对应的键会被跳过,该 Pod 将被允许启动。 -不过这时会产生一个事件,其原因为 `InvalidVariableNames`,其消息中包含被跳过的无效键的列表。 -下面的示例显示一个 Pod,它引用了包含 2 个无效键 1badkey 和 2alsobad。 +当 Secret 配置文件中未作显式设定时,默认的 Secret 类型是 `Opaque`。 +当你使用 `kubectl` 来创建一个 Secret 时,你会使用 `generic` 子命令来标明 +要创建的是一个 `Opaque` 类型 Secret。 +例如,下面的命令会创建一个空的 `Opaque` 类型 Secret 对象: ```shell -kubectl get events +kubectl create secret generic empty-secret +kubectl get secret empty-secret ``` - -输出类似于: + +输出类似于 ``` -LASTSEEN FIRSTSEEN COUNT NAME KIND SUBOBJECT TYPE REASON -0s 0s 1 dapi-test-pod Pod Warning InvalidEnvironmentVariableNames kubelet, 127.0.0.1 Keys [1badkey, 2alsobad] from the EnvFrom secret default/mysecret were skipped since they are considered invalid environment variable names. +NAME TYPE DATA AGE +empty-secret Opaque 0 2m6s ``` -### Secret 与 Pod 生命周期的关系 - -通过 API 创建 Pod 时,不会检查引用的 Secret 是否存在。一旦 Pod 被调度,kubelet -就会尝试获取该 Secret 的值。如果获取不到该 Secret,或者暂时无法与 API 服务器建立连接, -kubelet 将会定期重试。kubelet 将会报告关于 Pod 的事件,并解释它无法启动的原因。 -一旦获取到 Secret,kubelet 将创建并挂载一个包含它的卷。在 Pod 的所有卷被挂载之前, -Pod 中的容器不会启动。 +`DATA` 列显示 Secret 中保存的数据条目个数。 +在这个例子种,`0` 意味着我们刚刚创建了一个空的 Secret。 -## 使用案例 - +### 服务账号令牌 Secret {#service-account-token-secrets} -### 案例:以环境变量的形式使用 Secret +类型为 `kubernetes.io/service-account-token` 的 Secret 用来存放标识某 +{{< glossary_tooltip text="服务账号" term_id="service-account" >}}的令牌。 +使用这种 Secret 类型时,你需要确保对象的注解 `kubernetes.io/service-account-name` +被设置为某个已有的服务账号名称。某个 Kubernetes +{{< glossary_tooltip text="控制器" term_id="controller" >}}会填写 Secret +的其它字段,例如 `kubernetes.io/service-account.uid` 注解以及 `data` 字段中的 +`token` 键值,使之包含实际的令牌内容。 - -创建一个 Secret 定义: +下面的配置实例声明了一个服务账号令牌 Secret: + -生成 Secret 对象: - -```shell -kubectl apply -f mysecret.yaml + # You can include additional key value pairs as you do with Opaque Secrets + extra: YmFyCg== ``` - - -使用 `envFrom` 将 Secret 的所有数据定义为容器的环境变量。 -Secret 中的键名称为 Pod 中的环境变量名称: - ```yaml apiVersion: v1 -kind: Pod +kind: Secret metadata: - name: secret-test-pod -spec: - containers: - - name: test-container - image: k8s.gcr.io/busybox - command: [ "/bin/sh", "-c", "env" ] - envFrom: - - secretRef: - name: mysecret - restartPolicy: Never + name: secret-sa-sample + annotations: + kubernetes.io/service-account.name: "sa-name" +type: kubernetes.io/service-account-token +data: + # 你可以像 Opaque Secret 一样在这里添加额外的键/值偶对 + extra: YmFyCg== ``` -### 案例:包含 SSH 密钥的 Pod - -创建一个包含 SSH 密钥的 Secret: - -```shell -kubectl create secret generic ssh-key-secret \ - --from-file=ssh-privatekey=/path/to/.ssh/id_rsa \ - --from-file=ssh-publickey=/path/to/.ssh/id_rsa.pub -``` +Kubernetes 在创建 Pod 时会自动创建一个服务账号 Secret 并自动修改你的 Pod +以使用该 Secret。该服务账号令牌 Secret 中包含了访问 Kubernetes API +所需要的凭据。 - -输出类似于: +如果需要,可以禁止或者重载这种自动创建并使用 API 凭据的操作。 +不过,如果你仅仅是希望能够安全地访问 API 服务器,这是建议的工作方式。 -``` -secret "ssh-key-secret" created -``` + +参考 [ServiceAccount](/zh/docs/tasks/configure-pod-container/configure-service-account/) +文档了解服务账号的工作原理。你也可以查看 +[`Pod`](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#pod-v1-core) +资源中的 `automountServiceAccountToken` 和 `serviceAccountName` 字段文档, +进一步了解从 Pod 中引用服务账号。 -你也可以创建一个带有包含 SSH 密钥的 `secretGenerator` 字段的 -`kustomization.yaml` 文件。 +### Docker 配置 Secret {#docker-config-secrets} + +你可以使用下面两种 `type` 值之一来创建 Secret,用以存放访问 Docker 仓库 +来下载镜像的凭据。 + +- `kubernetes.io/dockercfg` +- `kubernetes.io/dockerconfigjson` -{{< caution >}} -发送自己的 SSH 密钥之前要仔细思考:集群的其他用户可能有权访问该密钥。 -你可以使用一个服务帐户,分享给 Kubernetes 集群中合适的用户,这些用户是你要分享的。 -如果服务账号遭到侵犯,可以将其收回。 -{{< /caution >}} +`kubernetes.io/dockercfg` 是一种保留类型,用来存放 `~/.dockercfg` 文件的序列化形式。 +该文件是配置 Docker 命令行的一种老旧形式。使用此 Secret 类型时,你需要确保 +Secret 的 `data` 字段中包含名为 `.dockercfg` 的主键,其对应键值是用 base64 +编码的某 `~/.dockercfg` 文件的内容。 -现在我们可以创建一个 Pod,令其引用包含 SSH 密钥的 Secret,并通过存储卷来使用它: +类型 `kubernetes.io/dockerconfigjson` 被设计用来保存 JSON 数据的序列化形式, +该 JSON 也遵从 `~/.docker/config.json` 文件的格式规则,而后者是 `~/.dockercfg` +的新版本格式。使用此 Secret 类型时,Secret 对象的 `data` 字段必须包含 +`.dockerconfigjson` 键,其键值为 base64 编码的字符串包含 `~/.docker/config.json` +文件的内容。 + +下面是一个 `kubernetes.io/dockercfg` 类型 Secret 的示例: ```yaml apiVersion: v1 -kind: Pod +kind: Secret metadata: - name: secret-test-pod - labels: - name: secret-test -spec: - volumes: - - name: secret-volume - secret: - secretName: ssh-key-secret - containers: - - name: ssh-test-container - image: mySshImage - volumeMounts: - - name: secret-volume - readOnly: true - mountPath: "/etc/secret-volume" + name: secret-dockercfg +type: kubernetes.io/dockercfg +data: + .dockercfg: | + "" ``` +{{< note >}} -容器中的命令运行时,密钥的片段可以在以下目录找到: +如果你不希望执行 base64 编码转换,可以使用 `stringData` 字段代替。 +{{< /note >}} -``` -/etc/secret-volume/ssh-publickey -/etc/secret-volume/ssh-privatekey + +当你使用清单文件来创建这两类 Secret 时,API 服务器会检查 `data` 字段中是否 +存在所期望的主键,并且验证其中所提供的键值是否是合法的 JSON 数据。 +不过,API 服务器不会检查 JSON 数据本身是否是一个合法的 Docker 配置文件内容。 + +```shell +kubectl create secret docker-registry secret-tiger-docker \ + --docker-email=tiger@acme.example \ + --docker-username=tiger \ + --docker-password=pass113 \ + --docker-server=my-registry.example:5000 ``` -然后容器可以自由使用 Secret 数据建立一个 SSH 连接。 +上面的命令创建一个类型为 `kubernetes.io/dockerconfigjson` 的 Secret。 +如果你对 `.data.dockerconfigjson` 内容进行转储并执行 base64 解码: + +```json +{ + "auths": { + "my-registry.example:5000": { + "username": "tiger", + "password": "pass113", + "email": "tiger@acme.com", + "auth": "dGlnZXI6cGFzczExMw==" + } + } +} +``` +{{< note >}} +`auths` 值是 base64 编码的,其内容被屏蔽但未被加密。 +任何能够读取该 Secret 的人都可以了解镜像库的访问令牌。 +{{< /note >}} -This example illustrates a pod which consumes a secret containing prod -credentials and another pod which consumes a secret with test environment -credentials. + -### 案例:包含生产/测试凭据的 Pod +### 基本身份认证 Secret {#basic-authentication-secret} -下面的例子展示的是两个 Pod。 -一个 Pod 使用包含生产环境凭据的 Secret,另一个 Pod 使用包含测试环境凭据的 Secret。 +`kubernetes.io/basic-auth` 类型用来存放用于基本身份认证所需的凭据信息。 +使用这种 Secret 类型时,Secret 的 `data` 字段必须包含以下两个键: -你可以创建一个带有 `secretGenerator` 字段的 `kustomization.yaml` -文件,或者执行 `kubectl create secret`: +- `username`: 用于身份认证的用户名; +- `password`: 用于身份认证的密码或令牌。 -```shell -kubectl create secret generic prod-db-secret \ - --from-literal=username=produser \ - --from-literal=password=Y4nys7f11 -``` + -输出类似于: +The following YAML is an example config for a basic authentication Secret: +--> +以上两个键的键值都是 base64 编码的字符串。 +当然你也可以在创建 Secret 时使用 `stringData` 字段来提供明文形式的内容。 +下面的 YAML 是基本身份认证 Secret 的一个示例清单: -``` -secret "prod-db-secret" created +```yaml +apiVersion: v1 +kind: Secret +metadata: + name: secret-basic-auth +type: kubernetes.io/basic-auth +stringData: + username: admin # kubernetes.io/basic-auth 类型的必需字段 + password: t0p-Secret # kubernetes.io/basic-auth 类型的必需字段 ``` -```shell -kubectl create secret generic test-db-secret \ - --from-literal=username=testuser \ - --from-literal=password=iluvtests -``` + +提供基本身份认证类型的 Secret 仅仅是出于方便性考虑。 +你也可以使用 `Opaque` 类型来保存用于基本身份认证的凭据。 +不过,使用预定义的、公开的 Secret 类型(`kubernetes.io/basic-auth`) +有助于帮助其他用户理解 Secret 的目的,并且对其中存在的主键形成一种约定。 +API 服务器会检查 Secret 配置中是否提供了所需要的主键。 - -输出类似于: + -{{< note >}} -特殊字符(例如 `$`、`\`、`*`、`=` 和 `!`)会被你的 -[Shell](https://en.wikipedia.org/wiki/Shell_(computing))解释,因此需要转义。 -在大多数 Shell 中,对密码进行转义的最简单方式是用单引号(`'`)将其括起来。 -例如,如果您的实际密码是 `S!B\*d$zDsb`,则应通过以下方式执行命令: +### SSH 身份认证 Secret {#ssh-authentication-secrets} -```shell -kubectl create secret generic dev-db-secret --from-literal=username=devuser --from-literal=password='S!B\*d$zDsb=' +Kubernetes 所提供的内置类型 `kubernetes.io/ssh-auth` 用来存放 SSH 身份认证中 +所需要的凭据。使用这种 Secret 类型时,你就必须在其 `data` (或 `stringData`) +字段中提供一个 `ssh-privatekey` 键值对,作为要使用的 SSH 凭据。 + +下面的清单是一个 SSH 公钥/私钥身份认证的 Secret 示例: + +```yaml +apiVersion: v1 +kind: Secret +metadata: + name: secret-ssh-auth +type: kubernetes.io/ssh-auth +data: + # 此例中的实际数据被截断 + ssh-privatekey: | + MIIEpQIBAAKCAQEAulqb/Y ... ``` -您无需对文件中的密码(`--from-file`)中的特殊字符进行转义。 -{{< /note >}} + +提供 SSH 身份认证类型的 Secret 仅仅是出于用户方便性考虑。 +你也可以使用 `Opaque` 类型来保存用于 SSH 身份认证的凭据。 +不过,使用预定义的、公开的 Secret 类型(`kubernetes.io/ssh-auth`) +有助于其他人理解你的 Secret 的用途,也可以就其中包含的主键名形成约定。 +API 服务器确实会检查 Secret 配置中是否提供了所需要的主键。 +{{< caution >}} -创建 pod : +SSH 私钥自身无法建立 SSH 客户端与服务器端之间的可信连接。 +需要其它方式来建立这种信任关系,以缓解“中间人(Man In The Middle)” +攻击,例如向 ConfigMap 中添加一个 `known_hosts` 文件。 +{{< /caution >}} -```shell -$ cat < pod.yaml -apiVersion: v1 -kind: List -items: -- kind: Pod - apiVersion: v1 - metadata: - name: prod-db-client-pod - labels: - name: prod-db-client - spec: - volumes: - - name: secret-volume - secret: - secretName: prod-db-secret - containers: - - name: db-client-container - image: myClientImage - volumeMounts: - - name: secret-volume - readOnly: true - mountPath: "/etc/secret-volume" -- kind: Pod - apiVersion: v1 - metadata: - name: test-db-client-pod - labels: - name: test-db-client - spec: - volumes: - - name: secret-volume - secret: - secretName: test-db-secret - containers: - - name: db-client-container - image: myClientImage - volumeMounts: - - name: secret-volume - readOnly: true - mountPath: "/etc/secret-volume" -EOF -``` + -将 Pod 添加到同一个 kustomization.yaml 文件 +### TLS Secret -```shell -$ cat <> kustomization.yaml -resources: -- pod.yaml -EOF +Kubernetes 提供一种内置的 `kubernetes.io/tls` Secret 类型,用来存放 TLS +场合通常要使用的证书及其相关密钥。 +TLS Secret 的一种典型用法是为 [Ingress](/zh/docs/concepts/services-networking/ingress/) +资源配置传输过程中的数据加密,不过也可以用于其他资源或者直接在负载中使用。 +当使用此类型的 Secret 时,Secret 配置中的 `data` (或 `stringData`)字段必须包含 +`tls.key` 和 `tls.crt` 主键,尽管 API 服务器实际上并不会对每个键的取值作进一步的合法性检查。 + +下面的 YAML 包含一个 TLS Secret 的配置示例: + +```yaml +apiVersion: v1 +kind: Secret +metadata: + name: secret-tls +type: kubernetes.io/tls +data: + # 此例中的数据被截断 + tls.crt: | + MIIC2DCCAcCgAwIBAgIBATANBgkqh ... + tls.key: | + MIIEpgIBAAKCAQEA7yn3bRHQ5FHMQ ... ``` -通过下面的命令应用所有对象 +提供 TLS 类型的 Secret 仅仅是出于用户方便性考虑。 +你也可以使用 `Opaque` 类型来保存用于 TLS 服务器与/或客户端的凭据。 +不过,使用内置的 Secret 类型的有助于对凭据格式进行归一化处理,并且 +API 服务器确实会检查 Secret 配置中是否提供了所需要的主键。 + +当使用 `kubectl` 来创建 TLS Secret 时,你可以像下面的例子一样使用 `tls` +子命令: ```shell -kubectl apply -k . +kubectl create secret tls my-tls-secret \ + --cert=path/to/cert/file \ + --key=path/to/key/file ``` -两个容器都会在其文件系统上存在以下文件,其中包含容器对应的环境的值: - -``` -/etc/secret-volume/username -/etc/secret-volume/password -``` +这里的公钥/私钥对都必须事先已存在。用于 `--cert` 的公钥证书必须是 +[RFC 7468 中 5.1 节](https://datatracker.ietf.org/doc/html/rfc7468#section-5.1) +中所规定的 DER 格式,且与 `--key` 所给定的私钥匹配。 +私钥必须是 DER 格式的 PKCS #8 +(参见 [RFC 7468 第 11节](https://datatracker.ietf.org/doc/html/rfc7468#section-11))。 +{{< note >}} +类型为 `kubernetes.io/tls` 的 Secret 中包含密钥和证书的 DER 数据,以 Base64 格式编码。 +如果你熟悉私钥和证书的 PEM 格式,base64 与该格式相同,只是你需要略过 PEM +数据中所包含的第一行和最后一行。 -You could further simplify the base pod specification by using two Service Accounts: + +例如,对于证书而言,你 **不要** 包含 `--------BEGIN CERTIFICATE-----` +和 `-------END CERTIFICATE----` 这两行。 +{{< /note >}} -1. `prod-user` with the `prod-db-secret` -1. `test-user` with the `test-db-secret` + -请注意,两个 Pod 的规约配置中仅有一个字段不同;这有助于使用共同的 Pod 配置模板创建 -具有不同能力的 Pod。 +### 启动引导令牌 Secret {#bootstrap-token-secrets} -您可以使用两个服务账号进一步简化基本的 Pod 规约: +通过将 Secret 的 `type` 设置为 `bootstrap.kubernetes.io/token` 可以创建 +启动引导令牌类型的 Secret。这种类型的 Secret 被设计用来支持节点的启动引导过程。 +其中包含用来为周知的 ConfigMap 签名的令牌。 + + +启动引导令牌 Secret 通常创建于 `kube-system` 名字空间内,并以 +`bootstrap-token-<令牌 ID>` 的形式命名;其中 `<令牌 ID>` 是一个由 6 个字符组成 +的字符串,用作令牌的标识。 -然后,Pod 规约可以缩短为: +以 Kubernetes 清单文件的形式,某启动引导令牌 Secret 可能看起来像下面这样: ```yaml apiVersion: v1 -kind: Pod +kind: Secret metadata: - name: prod-db-client-pod - labels: - name: prod-db-client -spec: - serviceAccount: prod-db-client - containers: - - name: db-client-container - image: myClientImage + name: bootstrap-token-5emitj + namespace: kube-system +type: bootstrap.kubernetes.io/token +data: + auth-extra-groups: c3lzdGVtOmJvb3RzdHJhcHBlcnM6a3ViZWFkbTpkZWZhdWx0LW5vZGUtdG9rZW4= + expiration: MjAyMC0wOS0xM1QwNDozOToxMFo= + token-id: NWVtaXRq + token-secret: a3E0Z2lodnN6emduMXAwcg== + usage-bootstrap-authentication: dHJ1ZQ== + usage-bootstrap-signing: dHJ1ZQ== ``` -### 案例:Secret 卷中以句点号开头的文件 +启动引导令牌类型的 Secret 会在 `data` 字段中包含如下主键: + +- `token-id`:由 6 个随机字符组成的字符串,作为令牌的标识符。必需。 +- `token-secret`:由 16 个随机字符组成的字符串,包含实际的令牌机密。必需。 +- `description`:供用户阅读的字符串,描述令牌的用途。可选。 +- `expiration`:一个使用 RFC3339 来编码的 UTC 绝对时间,给出令牌要过期的时间。可选。 +- `usage-bootstrap-`:布尔类型的标志,用来标明启动引导令牌的其他用途。 +- `auth-extra-groups`:用逗号分隔的组名列表,身份认证时除被认证为 + `system:bootstrappers` 组之外,还会被添加到所列的用户组中。 -你可以通过定义以句点开头的键名,将数据“隐藏”起来。 -例如,当如下 Secret 被挂载到 `secret-volume` 卷中: + +上面的 YAML 文件可能看起来令人费解,因为其中的数值均为 base64 编码的字符串。 +实际上,你完全可以使用下面的 YAML 来创建一个一模一样的 Secret: + +```yaml apiVersion: v1 -kind: Pod +kind: Secret metadata: - name: secret-dotfiles-pod -spec: - volumes: - - name: secret-volume - secret: - secretName: dotfile-secret - containers: - - name: dotfile-test-container - image: k8s.gcr.io/busybox - command: - - ls - - "-l" - - "/etc/secret-volume" - volumeMounts: - - name: secret-volume - readOnly: true - mountPath: "/etc/secret-volume" + # 注意 Secret 的命名方式 + name: bootstrap-token-5emitj + # 启动引导令牌 Secret 通常位于 kube-system 名字空间 + namespace: kube-system +type: bootstrap.kubernetes.io/token +stringData: + auth-extra-groups: "system:bootstrappers:kubeadm:default-node-token" + expiration: "2020-09-13T04:39:10Z" + # 此令牌 ID 被用于生成 Secret 名称 + token-id: "5emitj" + token-secret: "kq4gihvszzgn1p0r" + # 此令牌还可用于 authentication (身份认证) + usage-bootstrap-authentication: "true" + # 且可用于 signing (证书签名) + usage-bootstrap-signing: "true" ``` - -卷中将包含唯一的叫做 `.secret-file` 的文件。 -容器 `dotfile-test-container` 中,该文件处于 `/etc/secret-volume/.secret-file` 路径下。 +## 不可更改的 Secret {#secret-immutable} - -{{< note >}} -以点号开头的文件在 `ls -l` 的输出中会被隐藏起来; -列出目录内容时,必须使用 `ls -la` 才能看到它们。 -{{< /note >}} +{{< feature-state for_k8s_version="v1.21" state="stable" >}} -### 案例:Secret 仅对 Pod 中的一个容器可见 {#secret-visible-to-only-one-container} -考虑一个需要处理 HTTP 请求、执行一些复杂的业务逻辑,然后使用 HMAC 签署一些消息的应用。 -因为应用程序逻辑复杂,服务器中可能会存在一个未被注意的远程文件读取漏洞, -可能会将私钥暴露给攻击者。 +Kubernetes 允许你将特定的 Secret(和 ConfigMap)标记为 **不可更改(Immutable)**。 +禁止更改现有 Secret 的数据有下列好处: + +- 防止意外(或非预期的)更新导致应用程序中断 +- (对于大量使用 Secret 的集群而言,至少数万个不同的 Secret 供 Pod 挂载), + 通过将 Secret 标记为不可变,可以极大降低 kube-apiserver 的负载,提升集群性能。 + kubelet 不需要监视那些被标记为不可更改的 Secret。 -解决的办法可以是将应用分为两个进程,分别运行在两个容器中: -前端容器,用于处理用户交互和业务逻辑,但无法看到私钥; -签名容器,可以看到私钥,响应来自前端(例如通过本地主机网络)的简单签名请求。 +### 将 Secret 标记为不可更改 {#secret-immutable-create} -使用这种分割方法,攻击者现在必须欺骗应用程序服务器才能进行任意的操作, -这可能比使其读取文件更难。 +你可以通过将 Secret 的 `immutable` 字段设置为 `true` 创建不可更改的 Secret。 +例如: - +```yaml +apiVersion: v1 +kind: Secret +metadata: + ... +data: + ... +immutable: true +``` +你也可以更改现有的 Secret,令其不可更改。 -When deploying applications that interact with the secrets API, access should be -limited using [authorization policies]( -/docs/reference/access-authn-authz/authorization/) such as [RBAC]( -/docs/reference/access-authn-authz/rbac/). +{{< note >}} + -## 最佳实践 {#best-practices} +一旦一个 Secret 或 ConfigMap 被标记为不可更改,撤销此操作或者更改 `data` +字段的内容都是 **不** 可能的。 +只能删除并重新创建这个 Secret。现有的 Pod 将维持对已删除 Secret 的挂载点 -- +建议重新创建这些 Pod。 +{{< /note >}} + + +## Secret 的信息安全问题 -当部署与 Secret API 交互的应用程序时,应使用 -[鉴权策略](/zh/docs/reference/access-authn-authz/authorization/), -例如 [RBAC](/zh/docs/reference/access-authn-authz/rbac/),来限制访问。 +尽管 ConfigMap 和 Secret 的工作方式类似,但 Kubernetes 对 Secret 有一些额外的保护。 - -Secret 中的值对于不同的环境来说重要性可能不同。 -很多 Secret 都可能导致 Kubernetes 集群内部的权限越界(例如服务账号令牌) -甚至逃逸到集群外部。 -即使某一个应用程序可以就所交互的 Secret 的能力作出正确抉择,但是同一命名空间中 -的其他应用程序却可能不这样做。 - -由于这些原因,在命名空间中 `watch` 和 `list` Secret 的请求是非常强大的能力, -是应该避免的行为。列出 Secret 的操作可以让客户端检查该命名空间中存在的所有 Secret。 -在群集中 `watch` 和 `list` 所有 Secret 的能力应该只保留给特权最高的系统级组件。 +Secret 通常保存重要性各异的数值,其中很多都可能会导致 Kubernetes 中 +(例如,服务账号令牌)或对外部系统的特权提升。 +即使某些个别应用能够推导它期望使用的 Secret 的能力, +同一名字空间中的其他应用可能会让这种假定不成立。 -需要访问 Secret API 的应用程序应该针对所需要的 Secret 执行 `get` 请求。 -这样,管理员就能限制对所有 Secret 的访问,同时为应用所需要的 -[实例设置访问允许清单](/zh/docs/reference/access-authn-authz/rbac/#referring-to-resources) 。 - -为了获得高于轮询操作的性能,客户端设计资源时,可以引用 Secret,然后对资源执行 `watch` -操作,在引用更改时重新检索 Secret。 -此外,社区还存在一种 [“批量监控” API](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/bulk_watch.md) -的提案,允许客户端 `watch` 独立的资源,该功能可能会在将来的 Kubernetes 版本中提供。 +只有当某个节点上的 Pod 需要某 Secret 时,对应的 Secret 才会被发送到该节点上。 +如果将 Secret 挂载到 Pod 中,kubelet 会将数据的副本保存在在 `tmpfs` 中, +这样机密的数据不会被写入到持久性存储中。 +一旦依赖于该 Secret 的 Pod 被删除,kubelet 会删除来自于该 Secret 的机密数据的本地副本。 -## 安全属性 {#security-properties} - -### 保护 {#protections} - -因为 Secret 对象可以独立于使用它们的 Pod 而创建,所以在创建、查看和编辑 Pod 的流程中 -Secret 被暴露的风险较小。系统还可以对 Secret 对象采取额外的预防性保护措施, -例如,在可能的情况下避免将其写到磁盘。 +同一个 Pod 中可能包含多个容器。默认情况下,你所定义的容器只能访问默认 ServiceAccount +及其相关 Secret。你必须显式地定义环境变量或者将卷映射到容器中,才能为容器提供对其他 +Secret 的访问。 -只有当某节点上的 Pod 需要用到某 Secret 时,该 Secret 才会被发送到该节点上。 -Secret 不会被写入磁盘,而是被 kubelet 存储在 tmpfs 中。 -一旦依赖于它的 Pod 被删除,Secret 数据的本地副本就被删除。 - -同一节点上的很多个 Pod 可能拥有多个 Secret。 -但是,只有 Pod 所请求的 Secret 在其容器中才是可见的。 -因此,一个 Pod 不能访问另一个 Pod 的 Secret。 +针对同一节点上的多个 Pod 可能有多个 Secret。不过,只有某个 Pod 所请求的 Secret +才有可能对 Pod 中的容器可见。因此,一个 Pod 不会获得访问其他 Pod 的 Secret 的权限。 +{{< warning >}} -同一个 Pod 中可能有多个容器。但是,Pod 中的每个容器必须通过 `volumeeMounts` -请求挂载 Secret 卷才能使卷中的 Secret 对容器可见。 -这一实现可以用于在 Pod 级别[构建安全分区](#secret-visible-to-only-one-container)。 +节点上的所有特权容器都可能访问到该节点上使用的所有 Secret。 +{{< /warning >}} -在大多数 Kubernetes 发行版中,用户与 API 服务器之间的通信以及 -从 API 服务器到 kubelet 的通信都受到 SSL/TLS 的保护。 -通过这些通道传输时,Secret 受到保护。 + +### 针对开发人员的安全性建议 +- 应用在从环境变量或卷中读取了机密信息内容之后仍要对其进行保护。例如, + 你的应用应该避免用明文的方式将 Secret 数据写入日志,或者将其传递给不可信的第三方。 +- 如果你在一个 Pod 中定义了多个容器,而只有一个容器需要访问某 Secret, + 定义卷挂载或环境变量配置时,应确保其他容器无法访问该 Secret。 + +- 如果你通过{{< glossary_tooltip text="清单" term_id="manifest" >}}来配置某 Secret, + Secret 数据以 Base64 的形式编码,将此文件共享,或者将其检入到某源码仓库, + 都意味着 Secret 对于任何可以读取清单的人都是可见的。 + Base64 编码 **不是** 一种加密方法,与明文相比没有任何安全性提升。 + +- 部署与 Secret API 交互的应用时,你应该使用 [RBAC](/zh/docs/reference/access-authn-authz/rbac/) + 这类[鉴权策略](/zh/docs/reference/access-authn-authz/authorization/)来限制访问。 -你可以为 Secret 数据开启[静态加密](/zh/docs/tasks/administer-cluster/encrypt-data/), -这样 Secret 数据就不会以明文形式存储到{{< glossary_tooltip term_id="etcd" >}} 中。 +- 在 Kubernetes API 中,名字空间内对 Secret 对象的 `watch` 和 `list` 请求是非常强大的能力。 + 在可能的时候应该避免授予这类访问权限,因为通过列举 Secret, + 客户端能够查看对应名字空间内所有 Secret 的取值。 +### 针对集群管理员的安全性建议 - - In the API server secret data is stored in {{< glossary_tooltip term_id="etcd" >}}; - therefore: - - Administrators should enable encryption at rest for cluster data (requires v1.13 or later) - - Administrators should limit access to etcd to admin users - - Administrators may want to wipe/shred disks used by etcd when no longer in use - - If running etcd in a cluster, administrators should make sure to use SSL/TLS - for etcd peer-to-peer communication. - - If you configure the secret through a manifest (JSON or YAML) file which has - the secret data encoded as base64, sharing this file or checking it in to a - source repository means the secret is compromised. Base64 encoding is _not_ an - encryption method and is considered the same as plain text. - - Applications still need to protect the value of secret after reading it from the volume, - such as not accidentally logging it or transmitting it to an untrusted party. - - A user who can create a pod that uses a secret can also see the value of that secret. Even - if apiserver policy does not allow that user to read the secret object, the user could - run a pod which exposes the secret. +{{< caution >}} + -### 风险 +能够创建使用 Secret 的 Pod 的用户也可以查看该 Secret 的取值。 +即使集群策略不允许某用户直接读取 Secret 对象,这一用户仍然可以通过运行一个 +Pod 来访问 Secret 的内容。 +{{< /caution >}} -- API 服务器上的 Secret 数据以纯文本的方式存储在 etcd 中,因此: - - 管理员应该为集群数据开启静态加密(要求 v1.13 或者更高版本)。 - - 管理员应该限制只有 admin 用户能访问 etcd; - - API 服务器中的 Secret 数据位于 etcd 使用的磁盘上;管理员可能希望在不再使用时擦除/粉碎 etcd 使用的磁盘 - - 如果 etcd 运行在集群内,管理员应该确保 etcd 之间的通信使用 SSL/TLS 进行加密。 -- 如果您将 Secret 数据编码为 base64 的清单(JSON 或 YAML)文件,共享该文件或将其检入代码库,该密码将会被泄露。 Base64 编码不是一种加密方式,应该视同纯文本。 -- 应用程序在从卷中读取 Secret 后仍然需要保护 Secret 的值,例如不会意外将其写入日志或发送给不信任方。 -- 可以创建使用 Secret 的 Pod 的用户也可以看到该 Secret 的值。即使 API 服务器策略不允许用户读取 Secret 对象,用户也可以运行 Pod 导致 Secret 暴露。 + +- 保留(使用 Kubernetes API)对集群中所有 Secret 对象执行 `watch` 或 `list` 操作的能力, + 这样只有特权级最高、系统级别的组件能够执行这类操作。 +- 在部署需要通过 Secret API 交互的应用时,你应该通过使用 + [RBAC](/zh/docs/reference/access-authn-authz/rbac/) + 这类[鉴权策略](/zh/docs/reference/access-authn-authz/authorization/)来限制访问。 + +- 在 API 服务器上,对象(包括 Secret)会被持久化到 {{< glossary_tooltip term_id="etcd" >}} 中; + 因此: + + - 只应准许集群管理员访问 etcd(包括只读访问); + - 为 Secret 对象启用[静态加密](/zh/docs/tasks/administer-cluster/encrypt-data/), + 这样这些 Secret 的数据就不会以明文的形式保存到 + {{< glossary_tooltip term_id="etcd" >}} 中; + - 当 etcd 的持久化存储不再被使用时,请考虑彻底擦除存储介质; + - 如果存在多个 etcd 实例,请确保 etcd 使用 SSL/TLS 来完成其对等通信。 ## {{% heading "whatsnext" %}} From 849eed7d0ad030f6e1958d43d0a09e27178ca951 Mon Sep 17 00:00:00 2001 From: "xin.li" Date: Tue, 29 Mar 2022 11:21:58 +0800 Subject: [PATCH 28/73] [zh] Update optional-kubectl-configs-zsh.md Signed-off-by: xin.li --- .../tools/included/optional-kubectl-configs-zsh.md | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/content/zh/docs/tasks/tools/included/optional-kubectl-configs-zsh.md b/content/zh/docs/tasks/tools/included/optional-kubectl-configs-zsh.md index b439db63bc1ab..9a40a829aa30d 100644 --- a/content/zh/docs/tasks/tools/included/optional-kubectl-configs-zsh.md +++ b/content/zh/docs/tasks/tools/included/optional-kubectl-configs-zsh.md @@ -26,24 +26,19 @@ source <(kubectl completion zsh) ``` -如果你为 kubectl 定义了别名,可以扩展脚本补全,以兼容该别名。 - -```zsh -echo 'alias k=kubectl' >>~/.zshrc -echo 'compdef __start_kubectl k' >>~/.zshrc -``` +如果你为 kubectl 定义了别名,kubectl 自动补全将自动使用它。 重新加载 shell 后,kubectl 自动补全功能将立即生效。 -如果你收到 `complete:13: command not found: compdef` 这样的错误提示,那请将下面内容添加到 `~/.zshrc` 文件的开头: - +如果你收到 `2: command not found: compdef` 这样的错误提示,那请将下面内容添加到 `~/.zshrc` 文件的开头: ```zsh autoload -Uz compinit compinit From 047966418e7928b23b8ee36f13e87e08ae41c8f2 Mon Sep 17 00:00:00 2001 From: "xin.li" Date: Tue, 29 Mar 2022 11:51:15 +0800 Subject: [PATCH 29/73] [zh] update create-cluster_index.md Signed-off-by: xin.li --- .../tutorials/kubernetes-basics/create-cluster/_index.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/content/zh/docs/tutorials/kubernetes-basics/create-cluster/_index.md b/content/zh/docs/tutorials/kubernetes-basics/create-cluster/_index.md index a3e250856e9dd..59dc1385c7925 100644 --- a/content/zh/docs/tutorials/kubernetes-basics/create-cluster/_index.md +++ b/content/zh/docs/tutorials/kubernetes-basics/create-cluster/_index.md @@ -2,3 +2,9 @@ title: 创建集群 weight: 10 --- + + +了解 Kubernetes {{}}并使用 Minikube +创建一个简单的集群。 From 62c4ddc8f68ea22816f07c7505d6f30017d793cb Mon Sep 17 00:00:00 2001 From: "xin.li" Date: Tue, 29 Mar 2022 15:35:59 +0800 Subject: [PATCH 30/73] [zh]Update cluster-intro.md Signed-off-by: xin.li --- .../kubernetes-basics/create-cluster/cluster-intro.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/zh/docs/tutorials/kubernetes-basics/create-cluster/cluster-intro.html b/content/zh/docs/tutorials/kubernetes-basics/create-cluster/cluster-intro.html index d6a0d4a9ec180..eb1d9eb7ca25f 100644 --- a/content/zh/docs/tutorials/kubernetes-basics/create-cluster/cluster-intro.html +++ b/content/zh/docs/tutorials/kubernetes-basics/create-cluster/cluster-intro.html @@ -72,7 +72,7 @@

集群图

Master 负责管理整个集群。 Master 协调集群中的所有活动,例如调度应用、维护应用的所需状态、应用扩容以及推出新的更新。

-

Node 是一个虚拟机或者物理机,它在 Kubernetes 集群中充当工作机器的角色 每个Node都有 Kubelet , 它管理 Node 而且是 Node 与 Master 通信的代理。 Node 还应该具有用于​​处理容器操作的工具,例如 Docker 或 rkt 。处理生产级流量的 Kubernetes 集群至少应具有三个 Node 。

+

Node 是一个虚拟机或者物理机,它在 Kubernetes 集群中充当工作机器的角色 每个Node都有 Kubelet , 它管理 Node 而且是 Node 与 Master 通信的代理。 Node 还应该具有用于​​处理容器操作的工具,例如 Docker 或 rkt 。处理生产级流量的 Kubernetes 集群至少应具有三个 Node,因为如果一个 Node 出现故障其对应的 etcd 成员和控制平面实例都会丢失,并且冗余会受到影响。 你可以通过添加更多控制平面节点来降低这种风险 。

From 138c15205d7fd89104a8515c25bed60df5e1833b Mon Sep 17 00:00:00 2001 From: 196Ikuchil <196thinline@gmail.com> Date: Tue, 29 Mar 2022 18:51:24 +0900 Subject: [PATCH 31/73] =?UTF-8?q?fix:change=20Pod=E3=82=BB=E3=82=AD?= =?UTF-8?q?=E3=83=A5=E3=83=AA=E3=83=86=E3=82=A3=E3=81=AE=E3=82=A2=E3=83=89?= =?UTF-8?q?=E3=83=9F=E3=83=83=E3=82=B7=E3=83=A7=E3=83=B3=20to=20Pod?= =?UTF-8?q?=E3=81=AE=E3=82=BB=E3=82=AD=E3=83=A5=E3=83=AA=E3=83=86=E3=82=A3?= =?UTF-8?q?=E3=82=A2=E3=83=89=E3=83=9F=E3=83=83=E3=82=B7=E3=83=A7=E3=83=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- content/ja/docs/concepts/security/pod-security-admission.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/content/ja/docs/concepts/security/pod-security-admission.md b/content/ja/docs/concepts/security/pod-security-admission.md index a7d7c02c89d3a..843ce371bfeef 100644 --- a/content/ja/docs/concepts/security/pod-security-admission.md +++ b/content/ja/docs/concepts/security/pod-security-admission.md @@ -1,5 +1,5 @@ --- -title: Podセキュリティのアドミッション +title: Podのセキュリティアドミッション content_type: concept weight: 20 min-kubernetes-server-version: v1.22 @@ -52,7 +52,7 @@ kubectl apply -k . ## Podのセキュリティレベル -Pod Securityアドミッションは、Podの[Security Context](/docs/tasks/configure-pod-container/security-context/)とその他の関連フィールドに、[Podセキュリティの標準](/ja/docs/concepts/security/pod-security-standards)で定義された3つのレベル、`privileged`、`baseline`、`restricted`に従って要件を設定するものです。 +Podのセキュリティアドミッションは、Podの[Security Context](/docs/tasks/configure-pod-container/security-context/)とその他の関連フィールドに、[Podセキュリティの標準](/ja/docs/concepts/security/pod-security-standards)で定義された3つのレベル、`privileged`、`baseline`、`restricted`に従って要件を設定するものです。 これらの要件の詳細については、[Podセキュリティの標準](/ja/docs/concepts/security/pod-security-standards)のページを参照してください。 ## Podの名前空間に対するセキュリティアドミッションラベル From 200f5f5e4c8e8c78371777fefcbe4a38228b3b2d Mon Sep 17 00:00:00 2001 From: "xin.li" Date: Tue, 29 Mar 2022 17:52:33 +0800 Subject: [PATCH 32/73] [zh] Update cluster-level-pass.md Signed-off-by: xin.li --- .../zh/docs/tutorials/security/cluster-level-pss.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/content/zh/docs/tutorials/security/cluster-level-pss.md b/content/zh/docs/tutorials/security/cluster-level-pss.md index 0b4721c43bae9..714bbca1f79bf 100644 --- a/content/zh/docs/tutorials/security/cluster-level-pss.md +++ b/content/zh/docs/tutorials/security/cluster-level-pss.md @@ -19,7 +19,7 @@ Pod Security admission (PSA) is enabled by default in v1.23 and later, as it has [graduated to beta](/blog/2021/12/09/pod-security-admission-beta/). Pod Security is an admission controller that carries out checks against the Kubernetes -[Pod Security Standards](docs/concepts/security/pod-security-standards/) when new pods are +[Pod Security Standards](/docs/concepts/security/pod-security-standards/) when new pods are created. This tutorial shows you how to enforce the `baseline` Pod Security Standard at the cluster level which applies a standard configuration to all namespaces in a cluster. @@ -406,14 +406,14 @@ following: ## 清理 {#clean-up} -运行 `kind delete cluster -name psa-with-cluster-pss` 和 -`kind delete cluster -name psa-wo-cluster-pss` 来删除你创建的集群。 +运行 `kind delete cluster --name psa-with-cluster-pss` 和 +`kind delete cluster --name psa-wo-cluster-pss` 来删除你创建的集群。 ## {{% heading "whatsnext" %}} From df4728f9cd3f36858ae06050248dce269dca6a46 Mon Sep 17 00:00:00 2001 From: "xin.li" Date: Tue, 29 Mar 2022 18:30:34 +0800 Subject: [PATCH 33/73] [zh] Update pod-configmap-env-var-valueFrom.md Signed-off-by: xin.li --- content/zh/examples/pods/pod-with-node-affinity.yaml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/content/zh/examples/pods/pod-with-node-affinity.yaml b/content/zh/examples/pods/pod-with-node-affinity.yaml index 253d2b21ea917..e077f79883eff 100644 --- a/content/zh/examples/pods/pod-with-node-affinity.yaml +++ b/content/zh/examples/pods/pod-with-node-affinity.yaml @@ -8,11 +8,10 @@ spec: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - - key: kubernetes.io/e2e-az-name + - key: kubernetes.io/os operator: In values: - - e2e-az1 - - e2e-az2 + - linux preferredDuringSchedulingIgnoredDuringExecution: - weight: 1 preference: From 41336b8c0693f36288f41cd0398dd72a7df75305 Mon Sep 17 00:00:00 2001 From: "xin.li" Date: Tue, 29 Mar 2022 19:01:46 +0800 Subject: [PATCH 34/73] [zh] Update pod-configmap-env-var-valueFrom.md Signed-off-by: xin.li --- content/zh/examples/pods/pod-configmap-env-var-valueFrom.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/zh/examples/pods/pod-configmap-env-var-valueFrom.yaml b/content/zh/examples/pods/pod-configmap-env-var-valueFrom.yaml index a72b4335ce3b0..00827ec98aaa3 100644 --- a/content/zh/examples/pods/pod-configmap-env-var-valueFrom.yaml +++ b/content/zh/examples/pods/pod-configmap-env-var-valueFrom.yaml @@ -6,7 +6,7 @@ spec: containers: - name: test-container image: k8s.gcr.io/busybox - command: [ "/bin/sh", "-c", "echo $(SPECIAL_LEVEL_KEY) $(SPECIAL_TYPE_KEY)" ] + command: [ "/bin/echo", "$(SPECIAL_LEVEL_KEY) $(SPECIAL_TYPE_KEY)" ] env: - name: SPECIAL_LEVEL_KEY valueFrom: From ee0d8a0b27e38b486d7036dec4069c8bd94cc64c Mon Sep 17 00:00:00 2001 From: "xin.li" Date: Tue, 29 Mar 2022 19:29:43 +0800 Subject: [PATCH 35/73] [zh] Update zookeeper-pod-disruption-budget-maxunavailable.yaml Signed-off-by: xin.li --- .../policy/zookeeper-pod-disruption-budget-maxunavailable.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/zh/examples/policy/zookeeper-pod-disruption-budget-maxunavailable.yaml b/content/zh/examples/policy/zookeeper-pod-disruption-budget-maxunavailable.yaml index a62bef140f2b1..ef0b8645bacdf 100644 --- a/content/zh/examples/policy/zookeeper-pod-disruption-budget-maxunavailable.yaml +++ b/content/zh/examples/policy/zookeeper-pod-disruption-budget-maxunavailable.yaml @@ -1,4 +1,4 @@ -apiVersion: policy/v1beta1 +apiVersion: policy/v1 kind: PodDisruptionBudget metadata: name: zk-pdb From 6ef4d4614380fbf6721b4f554731091ad40c8c19 Mon Sep 17 00:00:00 2001 From: "xin.li" Date: Tue, 29 Mar 2022 19:54:49 +0800 Subject: [PATCH 36/73] [zh] Update baseline-psp.yaml Signed-off-by: xin.li --- content/zh/examples/policy/baseline-psp.yaml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/content/zh/examples/policy/baseline-psp.yaml b/content/zh/examples/policy/baseline-psp.yaml index 36e440588b1db..57258bf313255 100644 --- a/content/zh/examples/policy/baseline-psp.yaml +++ b/content/zh/examples/policy/baseline-psp.yaml @@ -6,20 +6,16 @@ metadata: # Optional: Allow the default AppArmor profile, requires setting the default. apparmor.security.beta.kubernetes.io/allowedProfileNames: 'runtime/default' apparmor.security.beta.kubernetes.io/defaultProfileName: 'runtime/default' - # Optional: Allow the default seccomp profile, requires setting the default. - seccomp.security.alpha.kubernetes.io/allowedProfileNames: 'docker/default,runtime/default,unconfined' - seccomp.security.alpha.kubernetes.io/defaultProfileName: 'unconfined' + seccomp.security.alpha.kubernetes.io/allowedProfileNames: '*' spec: privileged: false - # The moby default capability set, defined here: - # https://github.com/moby/moby/blob/0a5cec2833f82a6ad797d70acbf9cbbaf8956017/oci/caps/defaults.go#L6-L19 + # The moby default capability set, minus NET_RAW allowedCapabilities: - 'CHOWN' - 'DAC_OVERRIDE' - 'FSETID' - 'FOWNER' - 'MKNOD' - - 'NET_RAW' - 'SETGID' - 'SETUID' - 'SETFCAP' @@ -36,15 +32,16 @@ spec: - 'projected' - 'secret' - 'downwardAPI' - # Assume that persistentVolumes set up by the cluster admin are safe to use. + # Assume that ephemeral CSI drivers & persistentVolumes set up by the cluster admin are safe to use. + - 'csi' - 'persistentVolumeClaim' + - 'ephemeral' # Allow all other non-hostpath volume types. - 'awsElasticBlockStore' - 'azureDisk' - 'azureFile' - 'cephFS' - 'cinder' - - 'csi' - 'fc' - 'flexVolume' - 'flocker' @@ -67,6 +64,9 @@ spec: runAsUser: rule: 'RunAsAny' seLinux: + # This policy assumes the nodes are using AppArmor rather than SELinux. + # The PSP SELinux API cannot express the SELinux Pod Security Standards, + # so if using SELinux, you must choose a more restrictive default. rule: 'RunAsAny' supplementalGroups: rule: 'RunAsAny' From cde6f321b2d7605b45a1544bf83a906759b3f531 Mon Sep 17 00:00:00 2001 From: "xin.li" Date: Tue, 29 Mar 2022 19:56:50 +0800 Subject: [PATCH 37/73] [zh] Update zookeeper-pod-disruption-budget-minavailable.yaml Signed-off-by: xin.li --- .../policy/zookeeper-pod-disruption-budget-minavailable.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/zh/examples/policy/zookeeper-pod-disruption-budget-minavailable.yaml b/content/zh/examples/policy/zookeeper-pod-disruption-budget-minavailable.yaml index c4776ad4c0b04..49a66ee66908a 100644 --- a/content/zh/examples/policy/zookeeper-pod-disruption-budget-minavailable.yaml +++ b/content/zh/examples/policy/zookeeper-pod-disruption-budget-minavailable.yaml @@ -1,4 +1,4 @@ -apiVersion: policy/v1beta1 +apiVersion: policy/v1 kind: PodDisruptionBudget metadata: name: zk-pdb From 7580383a7d7f32b010ee9deb860d1061c9b66e99 Mon Sep 17 00:00:00 2001 From: Mitesh Jain <47820816+miteshskj@users.noreply.github.com> Date: Tue, 29 Mar 2022 19:18:46 +0530 Subject: [PATCH 38/73] Reflect the changed behaviour for multiple use of --from-env-file in ConfigMap creation (#32603) * Fix 32392 - Reflect the changed behaviour for multiple from-env-file in configmap creation. * Update content/en/docs/tasks/configure-pod-container/configure-pod-configmap.md updated suggestions. Co-authored-by: Qiming Teng Co-authored-by: Qiming Teng --- .../configure-pod-configmap.md | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/content/en/docs/tasks/configure-pod-container/configure-pod-configmap.md b/content/en/docs/tasks/configure-pod-container/configure-pod-configmap.md index 8adc4071f460f..62b334e06824b 100644 --- a/content/en/docs/tasks/configure-pod-container/configure-pod-configmap.md +++ b/content/en/docs/tasks/configure-pod-container/configure-pod-configmap.md @@ -218,6 +218,7 @@ Use the option `--from-env-file` to create a ConfigMap from an env-file, for exa # Download the sample files into `configure-pod-container/configmap/` directory wget https://kubernetes.io/examples/configmap/game-env-file.properties -O configure-pod-container/configmap/game-env-file.properties +wget https://kubernetes.io/examples/configmap/ui-env-file.properties -O configure-pod-container/configmap/ui-env-file.properties # The env-file `game-env-file.properties` looks like below cat configure-pod-container/configmap/game-env-file.properties @@ -255,17 +256,10 @@ data: lives: "3" ``` -{{< caution >}} -When passing `--from-env-file` multiple times to create a ConfigMap from multiple data sources, only the last env-file is used. -{{< /caution >}} - -The behavior of passing `--from-env-file` multiple times is demonstrated by: +Starting with Kubernetes v1.23, `kubectl` supports the `--from-env-file` argument to be +specified multiple times to create a ConfigMap from multiple data sources. ```shell -# Download the sample files into `configure-pod-container/configmap/` directory -wget https://kubernetes.io/examples/configmap/ui-env-file.properties -O configure-pod-container/configmap/ui-env-file.properties - -# Create the configmap kubectl create configmap config-multi-env-files \ --from-env-file=configure-pod-container/configmap/game-env-file.properties \ --from-env-file=configure-pod-container/configmap/ui-env-file.properties @@ -288,8 +282,11 @@ metadata: resourceVersion: "810136" uid: 252c4572-eb35-11e7-887b-42010a8002b8 data: + allowed: '"true"' color: purple + enemies: aliens how: fairlyNice + lives: "3" textmode: "true" ``` From 5650e76c450095859725a3231a376693e3ee8edb Mon Sep 17 00:00:00 2001 From: Cezary Czekalski Date: Tue, 29 Mar 2022 19:27:32 +0200 Subject: [PATCH 39/73] Fix typo --- content/en/docs/reference/access-authn-authz/authentication.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/en/docs/reference/access-authn-authz/authentication.md b/content/en/docs/reference/access-authn-authz/authentication.md index 68e8b89869d4a..bcec107182793 100644 --- a/content/en/docs/reference/access-authn-authz/authentication.md +++ b/content/en/docs/reference/access-authn-authz/authentication.md @@ -121,7 +121,7 @@ token,user,uid,"group1,group2,group3" When using bearer token authentication from an http client, the API server expects an `Authorization` header with a value of `Bearer -THETOKEN`. The bearer token must be a character sequence that can be +`. The bearer token must be a character sequence that can be put in an HTTP header value using no more than the encoding and quoting facilities of HTTP. For example: if the bearer token is `31ada4fd-adec-460c-809a-9e56ceb75269` then it would appear in an HTTP From e611a04e6dae76bc8911131f454afe9c39cdcfdc Mon Sep 17 00:00:00 2001 From: Chuck Ha Date: Tue, 29 Mar 2022 12:56:15 -0700 Subject: [PATCH 40/73] Removes a space that breaks a markdown link Signed-off-by: Chuck Ha --- content/en/docs/concepts/storage/projected-volumes.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/content/en/docs/concepts/storage/projected-volumes.md b/content/en/docs/concepts/storage/projected-volumes.md index a498e3b237b54..ed7c31db1475d 100644 --- a/content/en/docs/concepts/storage/projected-volumes.md +++ b/content/en/docs/concepts/storage/projected-volumes.md @@ -54,8 +54,7 @@ into a Pod at a specified path. For example: The example Pod has a projected volume containing the injected service account token. Containers in this Pod can use that token to access the Kubernetes API -server, authenticating with the identity of [the pod's ServiceAccount] -(/docs/tasks/configure-pod-container/configure-service-account/). +server, authenticating with the identity of [the pod's ServiceAccount](/docs/tasks/configure-pod-container/configure-service-account/). The `audience` field contains the intended audience of the token. A recipient of the token must identify itself with an identifier specified in the audience of the token, and otherwise should reject the token. This field From 7b7b8d2d5ca901a81e2ce4fb496745651ebf81be Mon Sep 17 00:00:00 2001 From: "xin.li" Date: Tue, 29 Mar 2022 19:51:51 +0800 Subject: [PATCH 41/73] [zh] Update restricted-psp.yaml Signed-off-by: xin.li --- .../zh/examples/policy/restricted-psp.yaml | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/content/zh/examples/policy/restricted-psp.yaml b/content/zh/examples/policy/restricted-psp.yaml index 4db57688b190d..99c836b9ffc0b 100644 --- a/content/zh/examples/policy/restricted-psp.yaml +++ b/content/zh/examples/policy/restricted-psp.yaml @@ -5,44 +5,43 @@ metadata: annotations: seccomp.security.alpha.kubernetes.io/allowedProfileNames: 'docker/default,runtime/default' apparmor.security.beta.kubernetes.io/allowedProfileNames: 'runtime/default' - seccomp.security.alpha.kubernetes.io/defaultProfileName: 'runtime/default' apparmor.security.beta.kubernetes.io/defaultProfileName: 'runtime/default' spec: privileged: false - # Required to prevent escalations to root. + # 防止权限升级到 root allowPrivilegeEscalation: false - # This is redundant with non-root + disallow privilege escalation, - # but we can provide it for defense in depth. requiredDropCapabilities: - ALL - # Allow core volume types. + # 允许的核心卷类型. volumes: - 'configMap' - 'emptyDir' - 'projected' - 'secret' - 'downwardAPI' - # Assume that persistentVolumes set up by the cluster admin are safe to use. + # 假设集群管理员设置的临时 CSI 驱动程序和持久卷可以安全使用 + - 'csi' - 'persistentVolumeClaim' + - 'ephemeral' hostNetwork: false hostIPC: false hostPID: false runAsUser: - # Require the container to run without root privileges. + # 要求容器在没有 root 权限的情况下运行 rule: 'MustRunAsNonRoot' seLinux: - # This policy assumes the nodes are using AppArmor rather than SELinux. + # 此策略假定节点使用 AppArmor 而不是 SELinux rule: 'RunAsAny' supplementalGroups: rule: 'MustRunAs' ranges: - # Forbid adding the root group. + # 禁止添加 root 组 - min: 1 max: 65535 fsGroup: rule: 'MustRunAs' ranges: - # Forbid adding the root group. + # 禁止添加 root 组 - min: 1 max: 65535 readOnlyRootFilesystem: false From adde98e681b2087003f5001534295a9bb881ace9 Mon Sep 17 00:00:00 2001 From: Waynerv Date: Wed, 30 Mar 2022 10:13:53 +0800 Subject: [PATCH 42/73] Update pod-security-admission.md No need to use the ssh protocol to access a public repository --- content/en/docs/concepts/security/pod-security-admission.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/en/docs/concepts/security/pod-security-admission.md b/content/en/docs/concepts/security/pod-security-admission.md index 67b8770a84371..54e8235d90287 100644 --- a/content/en/docs/concepts/security/pod-security-admission.md +++ b/content/en/docs/concepts/security/pod-security-admission.md @@ -55,7 +55,7 @@ are available at [https://git.k8s.io/pod-security-admission/webhook](https://git To install: ```shell -git clone git@github.com:kubernetes/pod-security-admission.git +git clone https://github.com/kubernetes/pod-security-admission.git cd pod-security-admission/webhook make certs kubectl apply -k . From 7f782da3b7a50d2197b7ff1df6557446bd732a5d Mon Sep 17 00:00:00 2001 From: "xin.li" Date: Wed, 30 Mar 2022 10:20:55 +0800 Subject: [PATCH 43/73] [zh] Update garbage-collection Signed-off-by: xin.li --- content/zh/docs/concepts/architecture/garbage-collection.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/zh/docs/concepts/architecture/garbage-collection.md b/content/zh/docs/concepts/architecture/garbage-collection.md index a9b6942f524cd..7fb0eb0d3e21c 100644 --- a/content/zh/docs/concepts/architecture/garbage-collection.md +++ b/content/zh/docs/concepts/architecture/garbage-collection.md @@ -25,7 +25,7 @@ allows the clean up of resources like the following: * [Objects without owner references](#owners-dependents) * [Unused containers and container images](#containers-images) * [Dynamically provisioned PersistentVolumes with a StorageClass reclaim policy of Delete](/docs/concepts/storage/persistent-volumes/#delete) -* [Stale or expired CertificateSigningRequests (CSRs)](/reference/access-authn-authz/certificate-signing-requests/#request-signing-process) +* [Stale or expired CertificateSigningRequests (CSRs)](/docs/reference/access-authn-authz/certificate-signing-requests/#request-signing-process) * {{}} deleted in the following scenarios: * On a cloud when the cluster uses a [cloud controller manager](/docs/concepts/architecture/cloud-controller/) * On-premises when the cluster uses an addon similar to a cloud controller From 8966e293a0d690163a7bc797d7651d30d9f1c1f8 Mon Sep 17 00:00:00 2001 From: "xin.li" Date: Wed, 30 Mar 2022 11:29:57 +0800 Subject: [PATCH 44/73] [zh]Update manage-resources-containers.md Signed-off-by: xin.li --- .../docs/concepts/configuration/manage-resources-containers.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/zh/docs/concepts/configuration/manage-resources-containers.md b/content/zh/docs/concepts/configuration/manage-resources-containers.md index bb15c005435cd..00c5eba26107c 100644 --- a/content/zh/docs/concepts/configuration/manage-resources-containers.md +++ b/content/zh/docs/concepts/configuration/manage-resources-containers.md @@ -254,7 +254,7 @@ Mi, Ki. For example, the following represent roughly the same value: ``` From 74449d14596f79da52204683981c16d07b4996ab Mon Sep 17 00:00:00 2001 From: "xin.li" Date: Wed, 30 Mar 2022 12:14:28 +0800 Subject: [PATCH 45/73] [zh] Update projected-volumes.md Signed-off-by: xin.li --- .../docs/concepts/storage/projected-volumes.md | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/content/zh/docs/concepts/storage/projected-volumes.md b/content/zh/docs/concepts/storage/projected-volumes.md index 15c01c2719683..a1cc2a3a724af 100644 --- a/content/zh/docs/concepts/storage/projected-volumes.md +++ b/content/zh/docs/concepts/storage/projected-volumes.md @@ -34,7 +34,7 @@ Currently, the following types of volume sources can be projected: * [`secret`](/docs/concepts/storage/volumes/#secret) * [`downwardAPI`](/docs/concepts/storage/volumes/#downwardapi) * [`configMap`](/docs/concepts/storage/volumes/#configmap) -* `serviceAccountToken` +* [`serviceAccountToken`](#serviceaccounttoken) --> ## 介绍 {#introduction} @@ -45,7 +45,7 @@ Currently, the following types of volume sources can be projected: * [`secret`](/zh/docs/concepts/storage/volumes/#secret) * [`downwardAPI`](/zh/docs/concepts/storage/volumes/#downwardapi) * [`configMap`](/zh/docs/concepts/storage/volumes/#configmap) -* `serviceAccountToken` +* [`serviceAccountToken`](#serviceaccounttoken) +## serviceAccountToken 投射卷 {#serviceaccounttoken} 当 `TokenRequestProjection` 特性被启用时,你可以将当前 [服务账号](/zh/docs/reference/access-authn-authz/authentication/#service-account-tokens) 的令牌注入到 Pod 中特定路径下。例如: @@ -97,14 +99,17 @@ into a Pod at a specified path. For example: -示例 Pod 中包含一个投射卷,其中包含注入的服务账号令牌。该令牌可以被 Pod -中的容器用来访问 Kubernetes API 服务器。`audience` 字段包含令牌所针对的受众。 +示例 Pod 中包含一个投射卷,其中包含注入的服务账号令牌。 +此 Pod 中的容器可以使用该令牌访问 Kubernetes API 服务器, 使用 +[pod 的 ServiceAccount](/zh/docs/tasks/configure-pod-container/configure-service-account/) +进行身份验证。`audience` 字段包含令牌所针对的受众。 收到令牌的主体必须使用令牌受众中所指定的某个标识符来标识自身,否则应该拒绝该令牌。 此字段是可选的,默认值为 API 服务器的标识。 From 1905b25b89e132472e4a4ee1ca9ccfd92dd845e9 Mon Sep 17 00:00:00 2001 From: "xin.li" Date: Wed, 30 Mar 2022 12:24:19 +0800 Subject: [PATCH 46/73] [zh] Update authentication.md Signed-off-by: xin.li --- .../zh/docs/reference/access-authn-authz/authentication.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/content/zh/docs/reference/access-authn-authz/authentication.md b/content/zh/docs/reference/access-authn-authz/authentication.md index eb3b544ca084f..2961b2f0bab48 100644 --- a/content/zh/docs/reference/access-authn-authz/authentication.md +++ b/content/zh/docs/reference/access-authn-authz/authentication.md @@ -233,7 +233,7 @@ token,user,uid,"group1,group2,group3" When using bearer token authentication from an http client, the API server expects an `Authorization` header with a value of `Bearer -THETOKEN`. The bearer token must be a character sequence that can be +`. The bearer token must be a character sequence that can be put in an HTTP header value using no more than the encoding and quoting facilities of HTTP. For example: if the bearer token is `31ada4fd-adec-460c-809a-9e56ceb75269` then it would appear in an HTTP @@ -242,7 +242,7 @@ header as shown below. #### 在请求中放入持有者令牌 {#putting-a-bearer-token-in-a-request} 当使用持有者令牌来对某 HTTP 客户端执行身份认证时,API 服务器希望看到 -一个名为 `Authorization` 的 HTTP 头,其值格式为 `Bearer THETOKEN`。 +一个名为 `Authorization` 的 HTTP 头,其值格式为 `Bearer `。 持有者令牌必须是一个可以放入 HTTP 头部值字段的字符序列,至多可使用 HTTP 的编码和引用机制。 例如:如果持有者令牌为 `31ada4fd-adec-460c-809a-9e56ceb75269`,则其 From b25f4761a8346617055a9e3dc4ba2b98e5861d80 Mon Sep 17 00:00:00 2001 From: "xin.li" Date: Wed, 30 Mar 2022 12:26:31 +0800 Subject: [PATCH 47/73] [zh] Update kubelet-tls-bootstrapping.md Signed-off-by: xin.li --- .../command-line-tools-reference/kubelet-tls-bootstrapping.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/content/zh/docs/reference/command-line-tools-reference/kubelet-tls-bootstrapping.md b/content/zh/docs/reference/command-line-tools-reference/kubelet-tls-bootstrapping.md index 132accf337815..62aff4d4c20db 100644 --- a/content/zh/docs/reference/command-line-tools-reference/kubelet-tls-bootstrapping.md +++ b/content/zh/docs/reference/command-line-tools-reference/kubelet-tls-bootstrapping.md @@ -273,11 +273,9 @@ of provisioning. 启动引导令牌是一种对 kubelet 进行身份认证的方法,相对简单且容易管理, 且不需要在启动 kube-apiserver 时设置额外的标志。 -启动引导令牌从 Kubernetes 1.12 开始是一种 __Beta__ 功能特性。 + +**作者:** Sergey Kanzhelev (Google), Elana Hashman (Red Hat) + + + +保证 SIG 节点上游代码的可靠性是一项持续的工作,需要许多贡献者在幕后付出大量努力。 +Kubernetes、基础操作系统、容器运行时和测试基础架构的频繁发布,导致了一个复杂的矩阵, +需要关注和稳定的投资来“保持灯火通明”。2020 年 5 月,Kubernetes Node 特殊兴趣小组 +(“SIG Node”)为节点相关代码和测试组织了一个新的持续集成(CI)子项目。自成立以来,SIG Node CI +子项目每周举行一次会议,即使一整个小时通常也不足以完成对所有缺陷、测试相关的 PR 和问题的分类, +并讨论组内所有相关的正在进行的工作。 + + +在过去两年中,我们修复了阻塞合并和阻塞发布的测试,由于减少了测试缺陷,缩短了合并 Kubernetes +贡献者的拉取请求的时间。通过我们的努力,任务通过率由开始时 42% 提高至稳定大于 90% 。我们已经解决了 144 个测试失败问题, +并在 kubernetes/kubernetes 中合并了 176 个拉取请求。 +我们还帮助子项目参与者提升了 Kubernetes 贡献者的等级,新增了 3 名组织成员、6 名评审员和 2 名审批员。 + + + +Node CI 子项目是一个可入门的第一站,帮助新参与者开始使用 SIG Node。对于新贡献者来说, +解决影响较大的缺陷和测试修复的门槛很低,尽管贡献者要攀登整个贡献者阶梯还有很长的路要走: +为该团队培养了两个新的审批人花了一年多的时间。为 Kubernetes 节点及其测试基础设施提供动力的所有 +不同组件的复杂性要求开发人员在很长一段时间内进行持续投资, +以深入了解整个系统,从宏观到微观。 + + +虽然在我们的会议上有几个比较固定的贡献者;但是我们的评审员和审批员仍然很少。 +我们的目标是继续增加贡献者,以确保工作的可持续分配,而不仅仅是少数关键批准者。 + + +SIG 中的子项目如何形成、运行和工作并不总是显而易见的。每一个都是其背后的 SIG 所独有的, +并根据该小组打算支持的项目量身定制。作为一个欢迎了许多第一次 SIG Node 贡献者的团队, +我们想分享过去两年的一些细节和成就,帮助揭开我们内部工作的神秘面纱,并庆祝我们所有专注贡献者的辛勤工作! + + +## 时间线 + + +***2020 年 5 月*** SIG Node CI 组于 2020 年 5 月 11 日成立,超过 +[30 名志愿者](https://docs.google.com/document/d/1fb-ugvgdSVIkkuJ388_nhp2pBTy_4HEVg5848Xy7n5U/edit#bookmark=id.vsb8pqnf4gib) +注册,以改进 SIG Node CI 信号和整体可观测性。 +Victor Pickard 专注于让 [testgrid 可以运行](https://testgrid.k8s.io/sig-node) , +当时 Ning Liao 建议围绕这项工作组建一个小组,并提出 +[最初的小组章程文件](https://docs.google.com/document/d/1yS-XoUl6GjZdjrwxInEZVHhxxLXlTIX2CeWOARmD8tY/edit#heading=h.te6sgum6s8uf) 。 +SIG Node 赞助成立以 Victor 作为子项目负责人的小组。Sergey Kanzhelev 不久后就加入 Victor,担任联合领导人。 + + +在启动会议上,我们讨论了应该首先集中精力修复哪些测试,并讨论了阻塞合并和阻塞发布的测试, +其中许多测试由于基础设施问题或错误的测试代码而失败。 + + +该子项目每周召开一小时的会议,讨论正在进行的工作会谈和分类。 + + +***2020 年 6 月*** Morgan Bauer 、 Karan Goel 和 Jorge Alarcon Ochoa +因其贡献而被公认为 SIG Node CI 小组的评审员,为该子项目的早期阶段提供了重要帮助。 +David Porter 和 Roy Yang 也加入了 SIG 检测失败的 GitHub 测试团队。 + + +***2020 年 8 月*** 所有的阻塞合并和阻塞发布的测试都通过了,伴有一些逻辑问题。 +然而,只有 42% 的 SIG Node 测试作业是绿色的, +因为有许多逻辑错误和失败的测试。 + + +***2020 年 10 月*** Amim Knabben 因对子项目的贡献成为 Kubernetes 组织成员。 + + +***2021 年 1 月*** 随着健全的预提交和关键定期工作的通过,子项目讨论了清理其余定期测试并确保其顺利通过的目标。 + + +Elana Hashman 加入了这个子项目,在 Victor 离开后帮助领导该项目。 + + +***2021 年 2 月*** Artyom Lukianov 因其对子项目的贡献成为 Kubernetes 组织成员。 + + +***2021 年 8 月*** 在 SIG Node 成功运行 [bug scrub](https://groups.google.com/g/kubernetes-dev/c/w2ghO4ihje0/m/VeEql1LJBAAJ) +以清理其累积的缺陷之后,会议的范围扩大到包括缺陷分类以提高整体可靠性, +在问题影响 CI 信号之前预测问题。 + + +子项目负责人 Elana Hashman 和 Sergey Kanzhelev 都被认为是所有节点测试代码的审批人,由 SIG node 和 SIG Testing 支持。 + + +***2021 年 9 月*** 在 Francesco Romani 牵头的 1.22 版本系列测试取得重大进展后, +该子项目设定了一个目标,即在 1.23 发布日期之前让串行任务完全通过。 + + +Mike Miranda 因其对子项目的贡献成为 Kubernetes 组织成员。 + + +***2021 年 11 月*** 在整个 2021 年, SIG Node 没有合并或发布的测试失败。 +过去版本中的许多古怪测试都已从阻止发布的仪表板中删除,因为它们已被完全清理。 + + +Danielle Lancashire 被公认为 SIG Node 子组测试代码的评审员。 + + +最终节点系列测试已完全修复。系列测试由许多中断性和缓慢的测试组成,这些测试往往是碎片化的,很难排除故障。 +到 1.23 版本冻结时,最后一次系列测试已修复,作业顺利通过。 + + +[![宣布系列测试为绿色](serial-tests-green.png)](https://kubernetes.slack.com/archives/C0BP8PW9G/p1638211041322900) + + +1.23 版本在测试质量和 CI 信号方面得到了特别的关注。SIG Node CI 子项目很自豪能够为这样一个高质量的发布做出贡献, +部分原因是我们在识别和修复节点内外的碎片方面所做的努力。 + + +[![Slack 大声宣布发布的版本大多是绿色的](release-mostly-green.png)](https://kubernetes.slack.com/archives/C92G08FGD/p1637175755023200) + + +***2021 年 12 月*** 在 1.23 版本发布时,估计有 90% 的测试工作通过了测试(2020 年 8 月为 42%)。 + + +Dockershim 代码已从 Kubernetes 中删除。这影响了 SIG Node 近一半的测试作业, +SIG Node CI 子项目反应迅速,并重新确定了所有测试的目标。 +SIG Node 是第一个完成 dockershim 外测试迁移的 SIG ,为其他受影响的 SIG 提供了示例。 +绝大多数新工作在引入时都已通过,无需进一步修复。 +从 Kubernetes 中[将 dockershim 除名的工作](https://k8s.io/dockershim) 正在进行中。 +随着我们发现 dockershim 对 dockershim 的依赖性越来越大,dockershim 的删除仍然存在一些问题, +但我们计划在 1.24 版本之前确保所有测试任务稳定。 + + +## 统计数据 + + +我们过去几个月的定期会议与会者和子项目参与者: + +- Aditi Sharma +- Artyom Lukianov +- Arnaud Meukam +- Danielle Lancashire +- David Porter +- Davanum Srinivas +- Elana Hashman +- Francesco Romani +- Matthias Bertschy +- Mike Miranda +- Paco Xu +- Peter Hunt +- Ruiwen Zhao +- Ryan Phillips +- Sergey Kanzhelev +- Skyler Clark +- Swati Sehgal +- Wenjun Wu + + +[kubernetes/test-infra](https://github.com/kubernetes/test-infra/) 源代码存储库包含测试定义。该存储库中的节点 PR 数: +- 2020 年 PR(自 5 月起):[183](https://github.com/kubernetes/test-infra/pulls?q=is%3Apr+is%3Aclosed+label%3Asig%2Fnode+created%3A2020-05-01..2020-12-31+-author%3Ak8s-infra-ci-robot+) +- 2021 年 PR:[264](https://github.com/kubernetes/test-infra/pulls?q=is%3Apr+is%3Aclosed+label%3Asig%2Fnode+created%3A2021-01-01..2021-12-31+-author%3Ak8s-infra-ci-robot+) + + + +CI 委员会上的问题和 PRs 分类(包括子组范围之外的分类): + +- 2020 年(自 5 月起):[132](https://github.com/issues?q=project%3Akubernetes%2F43+created%3A2020-05-01..2020-12-31) +- 2021 年:[532](https://github.com/issues?q=project%3Akubernetes%2F43+created%3A2021-01-01..2021-12-31+) + + +## 未来 + + + +只是“保持灯亮”是一项大胆的任务,我们致力于改善这种体验。 +我们正在努力简化 SIG Node 的分类和审查流程。 + +具体来说,我们正在致力于更好的测试组织、命名和跟踪: + + + +- https://github.com/kubernetes/enhancements/pull/3042 +- https://github.com/kubernetes/test-infra/issues/24641 +- [Kubernetes SIG Node CI 测试网格跟踪器](https://docs.google.com/spreadsheets/d/1IwONkeXSc2SG_EQMYGRSkfiSWNk8yWLpVhPm-LOTbGM/edit#gid=0) + + +我们还在改进测试的可调试性和去剥落方面不断取得进展。 + +如果你对此感兴趣,我们很乐意您能加入我们! +在调试测试失败中有很多东西需要学习,它将帮助你熟悉 SIG Node 维护的代码。 + + + +你可以在 [SIG Node](https://github.com/kubernetes/community/tree/master/sig-node) 页面上找到有关该组的信息。 +我们在我们的维护者轨道会议上提供组更新,例如: +[KubeCon + CloudNativeCon Europe 2021](https://kccnceu2021.sched.com/event/iE8E/kubernetes-sig-node-intro-and-deep-dive-elana-hashman-red-hat-sergey-kanzhelev-google) 和 +[KubeCon + CloudNative North America 2021](https://kccncna2021.sched.com/event/lV9D/kubenetes-sig-node-intro-and-deep-dive-elana-hashman-derek-carr-red-hat-sergey-kanzhelev-dawn-chen-google?iframe=no&w=100%&sidebar=yes&bg=no)。 +加入我们的使命,保持 kubelet 和其他 SIG Node 组件的可靠性,确保顺顺利利发布! diff --git a/content/zh/blog/_posts/2022-02-16-sig-node-ci-subproject-celebrates/release-mostly-green.png b/content/zh/blog/_posts/2022-02-16-sig-node-ci-subproject-celebrates/release-mostly-green.png new file mode 100644 index 0000000000000000000000000000000000000000..c88eb3b37ef7c44cfd7451265799e7186f40e8a1 GIT binary patch literal 101346 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

?d;dkwb|xhe)j7$ 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 literal 0 HcmV?d00001 From c33389c97422189f6b77d0b9c069d4200e8d4063 Mon Sep 17 00:00:00 2001 From: twilight0620 Date: Wed, 30 Mar 2022 16:26:59 +0800 Subject: [PATCH 49/73] [zh] Translate blog Securing-Admission-Controllers-2022.1.19 --- ...22-01-19-Securing-Admission-Controllers.md | 137 ++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 content/zh/blog/_posts/2022-01-19-Securing-Admission-Controllers.md diff --git a/content/zh/blog/_posts/2022-01-19-Securing-Admission-Controllers.md b/content/zh/blog/_posts/2022-01-19-Securing-Admission-Controllers.md new file mode 100644 index 0000000000000..cf710ca3dbb21 --- /dev/null +++ b/content/zh/blog/_posts/2022-01-19-Securing-Admission-Controllers.md @@ -0,0 +1,137 @@ +--- +layout: blog +title: "确保准入控制器的安全" +date: 2022-01-19 +slug: secure-your-admission-controllers-and-webhooks +--- + + + + + +**作者:** Rory McCune (Aqua Security) + + + +[准入控制](/zh/docs/reference/access-authn-authz/admission-controllers/)和认证、授权都是 Kubernetes 安全性的关键部分。 +Webhook 准入控制器被广泛用于以多种方式帮助提高 Kubernetes 集群的安全性, +包括限制工作负载权限和确保部署到集群的镜像满足组织安全要求。 + +然而,与添加到集群中的任何其他组件一样,安全风险也会随之出现。 +一个安全风险示例是没有正确处理准入控制器的部署和管理。 +为了帮助准入控制器用户和设计人员适当地管理这些风险, +SIG 安全小组[安全文档](https://github.com/kubernetes/community/tree/master/sig-security#security-docs) +花费了一些时间来开发一个[准入控制器威胁模型](https://github.com/kubernetes/sig-security/tree/main/sig-security-docs/papers/admission-control)。 +这种威胁模型着眼于由于不正确使用准入控制器而产生的可能的风险,可能允许绕过安全策略,甚至允许攻击者未经授权访问集群。 + +从威胁模型中,我们开发了一套安全最佳实践,应该采用这些实践来确保集群操作员可以获得准入控制器带来的安全优势,同时避免使用它们带来的任何风险。 + + + +## 准入控制器和安全的良好做法 + +从威胁模型中,围绕如何确保准入控制器的安全性出现了几个主题。 + + + +### 安全的 webhook 配置 + +确保集群中的任何安全组件都配置良好并且准入控制器在这里没有什么不同是很重要的。 +使用准入控制器时需要考虑几个安全最佳实践 + +* **为所有 webhook 流量正确配置了 TLS**。 + API 服务器和准入控制器 webhook 之间的通信应该经过身份验证和加密,以确保处于网络中查看或修改此流量的攻击者无法查看或修改。 + 要实现此访问,API 服务器和 webhook 必须使用来自受信任的证书颁发机构的证书,以便它们可以验证相互的身份。 +* **只允许经过身份验证的访问**。 +如果攻击者可以向准入控制器发送大量请求,他们可能会压倒服务导致其失败。 +确保所有访问都需要强身份验证可以降低这种风险。 +* **准入控制器关闭失败**。 + 这是一种需要权衡的安全实践,集群操作员是否要对其进行配置取决于集群的威胁模型。 + 如果一个准入控制器关闭失败,当 API 服务器无法从它得到响应时,所有的部署都会失败。 + 这可以阻止攻击者通过禁用准入控制器绕过准入控制器,但可能会破坏集群的运行。 + 由于集群可以有多个 webhook,因此达到中间立场的一种方法是对故障关闭设置进行关键控制,并允许不太关键的控制进行故障打开。 +* **定期审查 webhook 配置**。 +配置错误可能导致安全问题,因此检查准入控制器 webhook 配置以确保设置正确非常重要。 +这种审查可以由基础设施即代码扫描程序自动完成,也可以由管理员手动完成。 + + + +### 准入控制的安全集群配置 + +在大多数情况下,集群使用的准入控制器 webhook 将作为工作负载安装在集群中。 +因此,确保正确配置了可能影响其操作的 Kubernetes 安全特性非常重要。 + +* **限制 [RBAC](/zh/docs/reference/access-authn-authz/rbac/) 权限**。 +任何有权修改 webhook 对象的配置或准入控制器使用的工作负载的用户都可能会中断其操作。 +因此,确保只有集群管理员拥有这些权限非常重要。 +* **防止特权工作负载**。 +容器系统的一个现实是,如果工作负载被赋予某些特权, +则有可能突破到底层集群节点并影响该节点上的其他容器。 +如果准入控制器服务在它们所保护的集群上运行, +一定要确保对特权工作负载的任何要求都要经过仔细审查并尽可能地加以限制。 +* **严格控制外部系统访问**。 +作为集群准入控制器系统中的安全服务,将有权访问敏感信息,如凭证。 +为了降低此信息被发送到集群外的风险, +应使用[网络策略](/zh/docs/concepts/services-networking/network-policies/) +来限制准入控制器服务对外部网络的访问。 +* **每个集群都有一个专用的 webhook**。 +虽然可能有服务于多个集群的准入控制器 webhook, +但在使用该模型时存在对 webhook 服务的攻击会对共享它的地方产生更大影响的风险。 +此外,在多个集群使用准入控制器的情况下,复杂性和访问要求也会增加,从而更难保护其安全。 + + + +### 准入控制器规则 + +任何用于 Kubernetes 安全的准入控制器的一个关键元素是它使用的规则库。 +规则需要能够准确地满足其目标,避免误报和误报结果。 + +* **定期测试和审查规则**。 +需要测试准入控制器规则以确保其准确性。 +还需要定期审查,因为 Kubernetes API 会随着每个新版本而改变, +并且需要在每个 Kubernetes 版本中评估规则,以了解使他们保持最新版本所需要做的任何改变。 \ No newline at end of file From f90ea705c94f942608c88809f5b759e7bc841239 Mon Sep 17 00:00:00 2001 From: liutao <473139299@qq.com> Date: Wed, 30 Mar 2022 10:00:25 +0800 Subject: [PATCH 50/73] Update custom-resources.md --- .../extend-kubernetes/api-extension/custom-resources.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/content/zh/docs/concepts/extend-kubernetes/api-extension/custom-resources.md b/content/zh/docs/concepts/extend-kubernetes/api-extension/custom-resources.md index 307a31d304928..e2021c404341b 100644 --- a/content/zh/docs/concepts/extend-kubernetes/api-extension/custom-resources.md +++ b/content/zh/docs/concepts/extend-kubernetes/api-extension/custom-resources.md @@ -51,7 +51,7 @@ many core Kubernetes functions are now built using custom resources, making Kube Custom resources can appear and disappear in a running cluster through dynamic registration, and cluster admins can update custom resources independently of the cluster itself. Once a custom resource is installed, users can create and access its objects using -[kubectl](/docs/reference/kubectl/overview/), just as they do for built-in resources like +[kubectl](/docs/reference/kubectl/), just as they do for built-in resources like *Pods*. --> *定制资源(Custom Resource)* 是对 Kubernetes API 的扩展,不一定在默认的 @@ -61,7 +61,7 @@ Kubernetes 安装中就可用。定制资源所代表的是对特定 Kubernetes 定制资源可以通过动态注册的方式在运行中的集群内或出现或消失,集群管理员可以独立于集群 更新定制资源。一旦某定制资源被安装,用户可以使用 -[kubectl](/zh/docs/reference/kubectl/overview/) +[kubectl](/docs/reference/kubectl/) 来创建和访问其中的对象,就像他们为 *pods* 这种内置资源所做的一样。 ## API 服务器聚合 {#api-server-aggregation} -通常,Kubernetes API 中的每个都需要处理 REST 请求和管理对象持久性存储的代码。 +通常,Kubernetes API 中的每个资源都需要处理 REST 请求和管理对象持久性存储的代码。 Kubernetes API 主服务器能够处理诸如 *pods* 和 *services* 这些内置资源,也可以 按通用的方式通过 [CRD](#customresourcedefinitions) 来处理定制资源。 From 0561eaa17a7ccaf7003f5d9ef9153ad657c74371 Mon Sep 17 00:00:00 2001 From: "Yu.Bozhong" Date: Wed, 30 Mar 2022 17:18:25 +0800 Subject: [PATCH 51/73] [zh] Resync kubectl-convert-overview (#32642) * docs: update translation * Update content/zh/docs/tasks/tools/included/kubectl-convert-overview.md Co-authored-by: Qiming Teng Co-authored-by: Qiming Teng --- .../zh/docs/tasks/tools/included/kubectl-convert-overview.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/content/zh/docs/tasks/tools/included/kubectl-convert-overview.md b/content/zh/docs/tasks/tools/included/kubectl-convert-overview.md index f26827f2c2ff5..9e277732d529a 100644 --- a/content/zh/docs/tasks/tools/included/kubectl-convert-overview.md +++ b/content/zh/docs/tasks/tools/included/kubectl-convert-overview.md @@ -15,10 +15,10 @@ headless: true --> 一个 Kubernetes 命令行工具 `kubectl` 的插件,允许你将清单在不同 API 版本间转换。 -在将清单迁移到具有较新 Kubernetes 版本的未弃用 API 版本时,这个插件特别有用。 +这对于将清单迁移到新的 Kubernetes 发行版上未被废弃的 API 版本时尤其有帮助。 更多信息请访问 [迁移到非弃用 API](/zh/docs/reference/using-api/deprecation-guide/#migrate-to-non-deprecated-apis) From c112afaba29d3005298644517044123b7c99e921 Mon Sep 17 00:00:00 2001 From: 196Ikuchil <196thinline@gmail.com> Date: Wed, 30 Mar 2022 18:39:34 +0900 Subject: [PATCH 52/73] fix:heading --- .../docs/concepts/security/pod-security-admission.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/content/ja/docs/concepts/security/pod-security-admission.md b/content/ja/docs/concepts/security/pod-security-admission.md index 843ce371bfeef..6949577947008 100644 --- a/content/ja/docs/concepts/security/pod-security-admission.md +++ b/content/ja/docs/concepts/security/pod-security-admission.md @@ -23,7 +23,7 @@ PodSecurityPolicy APIは非推奨であり、v1.25でKubernetesから[削除](/d -## `PodSecurity`アドミッションプラグインの有効化 +## `PodSecurity`アドミッションプラグインの有効化 {#enabling-the-podsecurity-admission-plugin} v1.23において、`PodSecurity`の[フィーチャーゲート](/ja/docs/reference/command-line-tools-reference/feature-gates/)はベータ版の機能で、デフォルトで有効化されています。 v1.22において、`PodSecurity`の[フィーチャーゲート](/ja/docs/reference/command-line-tools-reference/feature-gates/)はアルファ版の機能で、組み込みのアドミッションプラグインを使用するには、`kube-apiserver`で有効にする必要があります。 @@ -50,12 +50,12 @@ kubectl apply -k . 生成された証明書の有効期限は2年間です。有効期限が切れる前に、証明書を再生成するか、内蔵のアドミッションプラグインを使用してWebhookを削除してください。 {{< /note >}} -## Podのセキュリティレベル +## Podのセキュリティレベル {#pod-security-levels} Podのセキュリティアドミッションは、Podの[Security Context](/docs/tasks/configure-pod-container/security-context/)とその他の関連フィールドに、[Podセキュリティの標準](/ja/docs/concepts/security/pod-security-standards)で定義された3つのレベル、`privileged`、`baseline`、`restricted`に従って要件を設定するものです。 これらの要件の詳細については、[Podセキュリティの標準](/ja/docs/concepts/security/pod-security-standards)のページを参照してください。 -## Podの名前空間に対するセキュリティアドミッションラベル +## Podの名前空間に対するセキュリティアドミッションラベル {#pod-security-admission-labels-for-namespaces} この機能を有効にするか、Webhookをインストールすると、名前空間を設定して、各名前空間でPodセキュリティに使用したいadmission controlモードを定義できます。 Kubernetesは、名前空間に使用したい定義済みのPodセキュリティの標準レベルのいずれかを適用するために設定できる{{< glossary_tooltip term_id="label" text="ラベル" >}}のセットを用意しています。 @@ -90,14 +90,14 @@ pod-security.kubernetes.io/-version: [名前空間ラベルでのPodセキュリティの標準の適用](/docs/tasks/configure-pod-container/enforce-standards-namespace-labels)で使用例を確認できます。 -## WorkloadのリソースとPodテンプレート +## WorkloadのリソースとPodテンプレート {#workload-resources-and-pod-templates} Podは、{{< glossary_tooltip term_id="deployment" >}}や{{< glossary_tooltip term_id="job">}}のような[ワークロードオブジェクト](/ja/docs/concepts/workloads/controllers/)を作成することによって、しばしば間接的に生成されます。 ワークロードオブジェクトは_Pod template_を定義し、ワークロードリソースの{{< glossary_tooltip term_id="controller" text="コントローラー" >}}はそのテンプレートに基づきPodを作成します。 違反の早期発見を支援するために、auditモードとwarningモードは、ワークロードリソースに適用されます。 ただし、enforceモードはワークロードリソースには**適用されず**、結果としてのPodオブジェクトにのみ適用されます。 -## 適用除外(Exemptions) +## 適用除外(Exemptions) {#exemptions} Podセキュリティの施行から _exemptions_ を定義することで、特定の名前空間に関連するポリシーのために禁止されていたPodの作成を許可することができます。 Exemptionsは[アドミッションコントローラーの設定](/docs/tasks/configure-pod-container/enforce-standards-admission-controller/#configure-the-admission-controller)で静的に設定することができます。 From fce303bf3bb02df3f36234f5f2bdc8aa87887748 Mon Sep 17 00:00:00 2001 From: 196Ikuchil <196thinline@gmail.com> Date: Wed, 30 Mar 2022 18:46:15 +0900 Subject: [PATCH 53/73] fix:pluralization --- .../docs/concepts/security/pod-security-admission.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/content/ja/docs/concepts/security/pod-security-admission.md b/content/ja/docs/concepts/security/pod-security-admission.md index 6949577947008..42015f468fff4 100644 --- a/content/ja/docs/concepts/security/pod-security-admission.md +++ b/content/ja/docs/concepts/security/pod-security-admission.md @@ -13,7 +13,7 @@ min-kubernetes-server-version: v1.22 Kubernetesの[Podセキュリティの標準](/ja/docs/concepts/security/pod-security-standards/)はPodに対して異なる分離レベルを定義します。 これらの標準によって、Podの動作をどのように制限したいかを、明確かつ一貫した方法で定義することができます。 -ベータ版機能として、Kubernetesは[PodSecurityPolicies](/docs/concepts/policy/pod-security-policy/)の後継である組み込みの _Pod Security_ {{< glossary_tooltip text="アドミッションコントローラー" term_id="admission-controller" >}}を提供しています。 +ベータ版機能として、Kubernetesは[PodSecurityPolicy](/docs/concepts/policy/pod-security-policy/)の後継である組み込みの _Pod Security_ {{< glossary_tooltip text="アドミッションコントローラー" term_id="admission-controller" >}}を提供しています。 Podセキュリティの制限は、Pod作成時に{{< glossary_tooltip text="名前空間" term_id="namespace" >}}レベルで適用されます。 {{< note >}} @@ -97,13 +97,13 @@ Podは、{{< glossary_tooltip term_id="deployment" >}}や{{< glossary_tooltip te 違反の早期発見を支援するために、auditモードとwarningモードは、ワークロードリソースに適用されます。 ただし、enforceモードはワークロードリソースには**適用されず**、結果としてのPodオブジェクトにのみ適用されます。 -## 適用除外(Exemptions) {#exemptions} +## 適用除外(Exemption) {#exemptions} -Podセキュリティの施行から _exemptions_ を定義することで、特定の名前空間に関連するポリシーのために禁止されていたPodの作成を許可することができます。 -Exemptionsは[アドミッションコントローラーの設定](/docs/tasks/configure-pod-container/enforce-standards-admission-controller/#configure-the-admission-controller)で静的に設定することができます。 +Podセキュリティの施行から _exemption_ を定義することで、特定の名前空間に関連するポリシーのために禁止されていたPodの作成を許可することができます。 +Exemptionは[アドミッションコントローラーの設定](/docs/tasks/configure-pod-container/enforce-standards-admission-controller/#configure-the-admission-controller)で静的に設定することができます。 -Exemptionsは明示的に列挙する必要があります。 -Exemptionsを満たしたリクエストは、アドミッションコントローラーによって _ignored_ されます(`enforce`、`audit`、`warn`のすべての動作がスキップされます)。Exemptionの次元は以下の通りです。 +Exemptionは明示的に列挙する必要があります。 +Exemptionを満たしたリクエストは、アドミッションコントローラーによって _ignored_ されます(`enforce`、`audit`、`warn`のすべての動作がスキップされます)。Exemptionの次元は以下の通りです。 - **Usernames:** 認証されていない(あるいは偽装された)ユーザー名を持つユーザーからの要求は無視されます。 - **RuntimeClassNames:** Podと[ワークロードリソース](#workload-resources-and-pod-templates)で指定された除外ランタイムクラス名は、無視されます。 From 1df046ce084f9a95928b1c6ff91df14e4841487f Mon Sep 17 00:00:00 2001 From: 196Ikuchil <196thinline@gmail.com> Date: Wed, 30 Mar 2022 18:46:32 +0900 Subject: [PATCH 54/73] fix:typo --- content/ja/docs/concepts/security/pod-security-admission.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/content/ja/docs/concepts/security/pod-security-admission.md b/content/ja/docs/concepts/security/pod-security-admission.md index 42015f468fff4..591c13bd1d066 100644 --- a/content/ja/docs/concepts/security/pod-security-admission.md +++ b/content/ja/docs/concepts/security/pod-security-admission.md @@ -103,7 +103,7 @@ Podセキュリティの施行から _exemption_ を定義することで、特 Exemptionは[アドミッションコントローラーの設定](/docs/tasks/configure-pod-container/enforce-standards-admission-controller/#configure-the-admission-controller)で静的に設定することができます。 Exemptionは明示的に列挙する必要があります。 -Exemptionを満たしたリクエストは、アドミッションコントローラーによって _ignored_ されます(`enforce`、`audit`、`warn`のすべての動作がスキップされます)。Exemptionの次元は以下の通りです。 +Exemptionを満たしたリクエストは、アドミッションコントローラーによって _無視_ されます(`enforce`、`audit`、`warn`のすべての動作がスキップされます)。Exemptionの次元は以下の通りです。 - **Usernames:** 認証されていない(あるいは偽装された)ユーザー名を持つユーザーからの要求は無視されます。 - **RuntimeClassNames:** Podと[ワークロードリソース](#workload-resources-and-pod-templates)で指定された除外ランタイムクラス名は、無視されます。 @@ -112,7 +112,7 @@ Exemptionを満たしたリクエストは、アドミッションコントロ {{< caution >}} ほとんどのPodは、[ワークロードリソース](#workload-resources-and-pod-templates)に対応してコントローラーが作成します。つまり、エンドユーザーを適用除外にするのはPodを直接作成する場合のみで、ワークロードリソースを作成する場合は適用除外になりません。 -コントローラサービスアカウント(`system:serviceaccount:kube-system:replicaset-controller`など)は通常、除外してはいけません。そうした場合、対応するワークロードリソースを作成できるすべてのユーザーを暗黙的に除外してしまうためです。 +コントローラーサービスアカウント(`system:serviceaccount:kube-system:replicaset-controller`など)は通常、除外してはいけません。そうした場合、対応するワークロードリソースを作成できるすべてのユーザーを暗黙的に除外してしまうためです。 {{< /caution >}} From f8c9721c52019ce72533e876f68b7ac81e78c3b8 Mon Sep 17 00:00:00 2001 From: twilight0620 Date: Wed, 30 Mar 2022 17:51:19 +0800 Subject: [PATCH 55/73] [zh] comments modify --- ...22-01-19-Securing-Admission-Controllers.md | 139 ++++++++++-------- 1 file changed, 79 insertions(+), 60 deletions(-) diff --git a/content/zh/blog/_posts/2022-01-19-Securing-Admission-Controllers.md b/content/zh/blog/_posts/2022-01-19-Securing-Admission-Controllers.md index cf710ca3dbb21..960624276817e 100644 --- a/content/zh/blog/_posts/2022-01-19-Securing-Admission-Controllers.md +++ b/content/zh/blog/_posts/2022-01-19-Securing-Admission-Controllers.md @@ -22,116 +22,135 @@ slug: secure-your-admission-controllers-and-webhooks +[准入控制](/zh/docs/reference/access-authn-authz/admission-controllers/)和认证、授权都是 Kubernetes 安全性的关键部分。 +Webhook 准入控制器被广泛用于以多种方式帮助提高 Kubernetes 集群的安全性, +包括限制工作负载权限和确保部署到集群的镜像满足组织安全要求。 + -[准入控制](/zh/docs/reference/access-authn-authz/admission-controllers/)和认证、授权都是 Kubernetes 安全性的关键部分。 -Webhook 准入控制器被广泛用于以多种方式帮助提高 Kubernetes 集群的安全性, -包括限制工作负载权限和确保部署到集群的镜像满足组织安全要求。 - 然而,与添加到集群中的任何其他组件一样,安全风险也会随之出现。 一个安全风险示例是没有正确处理准入控制器的部署和管理。 为了帮助准入控制器用户和设计人员适当地管理这些风险, -SIG 安全小组[安全文档](https://github.com/kubernetes/community/tree/master/sig-security#security-docs) +SIG Security 的[安全文档](https://github.com/kubernetes/community/tree/master/sig-security#security-docs)小组 花费了一些时间来开发一个[准入控制器威胁模型](https://github.com/kubernetes/sig-security/tree/main/sig-security-docs/papers/admission-control)。 这种威胁模型着眼于由于不正确使用准入控制器而产生的可能的风险,可能允许绕过安全策略,甚至允许攻击者未经授权访问集群。 -从威胁模型中,我们开发了一套安全最佳实践,应该采用这些实践来确保集群操作员可以获得准入控制器带来的安全优势,同时避免使用它们带来的任何风险。 + +基于这个威胁模型,我们开发了一套安全最佳实践。 +你应该采用这些实践来确保集群操作员可以获得准入控制器带来的安全优势,同时避免使用它们带来的任何风险。 - ## 准入控制器和安全的良好做法 -从威胁模型中,围绕如何确保准入控制器的安全性出现了几个主题。 + +基于这个威胁模型,围绕着如何确保准入控制器的安全性出现了几个主题。 +### 安全的 webhook 配置 + +确保集群中的任何安全组件都配置良好是很重要的,在这里准入控制器也并不例外。 +使用准入控制器时需要考虑几个安全最佳实践: + - -### 安全的 webhook 配置 - -确保集群中的任何安全组件都配置良好并且准入控制器在这里没有什么不同是很重要的。 -使用准入控制器时需要考虑几个安全最佳实践 - * **为所有 webhook 流量正确配置了 TLS**。 - API 服务器和准入控制器 webhook 之间的通信应该经过身份验证和加密,以确保处于网络中查看或修改此流量的攻击者无法查看或修改。 - 要实现此访问,API 服务器和 webhook 必须使用来自受信任的证书颁发机构的证书,以便它们可以验证相互的身份。 + API 服务器和准入控制器 webhook 之间的通信应该经过身份验证和加密,以确保处于网络中查看或修改此流量的攻击者无法查看或修改。 + 要实现此访问,API 服务器和 webhook 必须使用来自受信任的证书颁发机构的证书,以便它们可以验证相互的身份。 + * **只允许经过身份验证的访问**。 -如果攻击者可以向准入控制器发送大量请求,他们可能会压倒服务导致其失败。 -确保所有访问都需要强身份验证可以降低这种风险。 + 如果攻击者可以向准入控制器发送大量请求,他们可能会压垮服务导致其失败。 + 确保所有访问都需要强身份验证可以降低这种风险。 + * **准入控制器关闭失败**。 - 这是一种需要权衡的安全实践,集群操作员是否要对其进行配置取决于集群的威胁模型。 - 如果一个准入控制器关闭失败,当 API 服务器无法从它得到响应时,所有的部署都会失败。 - 这可以阻止攻击者通过禁用准入控制器绕过准入控制器,但可能会破坏集群的运行。 - 由于集群可以有多个 webhook,因此达到中间立场的一种方法是对故障关闭设置进行关键控制,并允许不太关键的控制进行故障打开。 + 这是一种需要权衡的安全实践,集群操作员是否要对其进行配置取决于集群的威胁模型。 + 如果一个准入控制器关闭失败,当 API 服务器无法从它得到响应时,所有的部署都会失败。 + 这可以阻止攻击者通过禁用准入控制器绕过准入控制器,但可能会破坏集群的运行。 + 由于集群可以有多个 webhook,因此一种折中的方法是对关键控制允许故障关闭, + 并允许不太关键的控制进行故障打开。 + * **定期审查 webhook 配置**。 -配置错误可能导致安全问题,因此检查准入控制器 webhook 配置以确保设置正确非常重要。 -这种审查可以由基础设施即代码扫描程序自动完成,也可以由管理员手动完成。 + 配置错误可能导致安全问题,因此检查准入控制器 webhook 配置以确保设置正确非常重要。 + 这种审查可以由基础设施即代码扫描程序自动完成,也可以由管理员手动完成。 - ### 准入控制的安全集群配置 + 在大多数情况下,集群使用的准入控制器 webhook 将作为工作负载安装在集群中。 因此,确保正确配置了可能影响其操作的 Kubernetes 安全特性非常重要。 + * **限制 [RBAC](/zh/docs/reference/access-authn-authz/rbac/) 权限**。 -任何有权修改 webhook 对象的配置或准入控制器使用的工作负载的用户都可能会中断其操作。 -因此,确保只有集群管理员拥有这些权限非常重要。 + 任何有权修改 webhook 对象的配置或准入控制器使用的工作负载的用户都可能会中断其操作。 + 因此,确保只有集群管理员拥有这些权限非常重要。 + * **防止特权工作负载**。 -容器系统的一个现实是,如果工作负载被赋予某些特权, -则有可能突破到底层集群节点并影响该节点上的其他容器。 -如果准入控制器服务在它们所保护的集群上运行, -一定要确保对特权工作负载的任何要求都要经过仔细审查并尽可能地加以限制。 + 容器系统的一个现实是,如果工作负载被赋予某些特权, + 则有可能突破到底层集群节点并影响该节点上的其他容器。 + 如果准入控制器服务在它们所保护的集群上运行, + 一定要确保对特权工作负载的任何要求都要经过仔细审查并尽可能地加以限制。 + * **严格控制外部系统访问**。 -作为集群准入控制器系统中的安全服务,将有权访问敏感信息,如凭证。 -为了降低此信息被发送到集群外的风险, -应使用[网络策略](/zh/docs/concepts/services-networking/network-policies/) -来限制准入控制器服务对外部网络的访问。 + 作为集群准入控制器系统中的安全服务,将有权访问敏感信息,如凭证。 + 为了降低此信息被发送到集群外的风险, + 应使用[网络策略](/zh/docs/concepts/services-networking/network-policies/) + 来限制准入控制器服务对外部网络的访问。 + * **每个集群都有一个专用的 webhook**。 -虽然可能有服务于多个集群的准入控制器 webhook, -但在使用该模型时存在对 webhook 服务的攻击会对共享它的地方产生更大影响的风险。 -此外,在多个集群使用准入控制器的情况下,复杂性和访问要求也会增加,从而更难保护其安全。 + 虽然可能有服务于多个集群的准入控制器 webhook, + 但在使用该模型时存在对 webhook 服务的攻击会对共享它的地方产生更大影响的风险。 + 此外,在多个集群使用准入控制器的情况下,复杂性和访问要求也会增加,从而更难保护其安全。 - ### 准入控制器规则 + 任何用于 Kubernetes 安全的准入控制器的一个关键元素是它使用的规则库。 规则需要能够准确地满足其目标,避免误报和误报结果。 + * **定期测试和审查规则**。 -需要测试准入控制器规则以确保其准确性。 -还需要定期审查,因为 Kubernetes API 会随着每个新版本而改变, -并且需要在每个 Kubernetes 版本中评估规则,以了解使他们保持最新版本所需要做的任何改变。 \ No newline at end of file + 需要测试准入控制器规则以确保其准确性。 + 还需要定期审查,因为 Kubernetes API 会随着每个新版本而改变, + 并且需要在每个 Kubernetes 版本中评估规则,以了解使他们保持最新版本所需要做的任何改变。 \ No newline at end of file From 3bc2141575897a3743cb00fd21c39d5cca47e909 Mon Sep 17 00:00:00 2001 From: 196Ikuchil <196thinline@gmail.com> Date: Wed, 30 Mar 2022 18:52:22 +0900 Subject: [PATCH 56/73] fix:_exemptions_ --- content/ja/docs/concepts/security/pod-security-admission.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/ja/docs/concepts/security/pod-security-admission.md b/content/ja/docs/concepts/security/pod-security-admission.md index 591c13bd1d066..807ac69f88069 100644 --- a/content/ja/docs/concepts/security/pod-security-admission.md +++ b/content/ja/docs/concepts/security/pod-security-admission.md @@ -99,7 +99,7 @@ Podは、{{< glossary_tooltip term_id="deployment" >}}や{{< glossary_tooltip te ## 適用除外(Exemption) {#exemptions} -Podセキュリティの施行から _exemption_ を定義することで、特定の名前空間に関連するポリシーのために禁止されていたPodの作成を許可することができます。 +Podセキュリティの施行から _exemptions_ を定義することで、特定の名前空間に関連するポリシーのために禁止されていたPodの作成を許可することができます。 Exemptionは[アドミッションコントローラーの設定](/docs/tasks/configure-pod-container/enforce-standards-admission-controller/#configure-the-admission-controller)で静的に設定することができます。 Exemptionは明示的に列挙する必要があります。 From 26716d7326fea4f1527c882dcbaca4fdd5e58b43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Piotr=20C=C5=82apa?= Date: Wed, 30 Mar 2022 13:18:11 +0200 Subject: [PATCH 57/73] Added a link to the SocketCAN device plugin --- .../extend-kubernetes/compute-storage-net/device-plugins.md | 1 + 1 file changed, 1 insertion(+) diff --git a/content/en/docs/concepts/extend-kubernetes/compute-storage-net/device-plugins.md b/content/en/docs/concepts/extend-kubernetes/compute-storage-net/device-plugins.md index 97dfa3860e4c3..f57be2d76ae3b 100644 --- a/content/en/docs/concepts/extend-kubernetes/compute-storage-net/device-plugins.md +++ b/content/en/docs/concepts/extend-kubernetes/compute-storage-net/device-plugins.md @@ -350,6 +350,7 @@ Here are some examples of device plugin implementations: * Requires [nvidia-docker](https://github.com/NVIDIA/nvidia-docker) 2.0, which allows you to run GPU-enabled Docker containers. * The [NVIDIA GPU device plugin for Container-Optimized OS](https://github.com/GoogleCloudPlatform/container-engine-accelerators/tree/master/cmd/nvidia_gpu) * The [RDMA device plugin](https://github.com/hustcat/k8s-rdma-device-plugin) +* The [SocketCAN device plugin](https://github.com/collabora/k8s-socketcan) * The [Solarflare device plugin](https://github.com/vikaschoudhary16/sfc-device-plugin) * The [SR-IOV Network device plugin](https://github.com/intel/sriov-network-device-plugin) * The [Xilinx FPGA device plugins](https://github.com/Xilinx/FPGA_as_a_Service/tree/master/k8s-fpga-device-plugin) for Xilinx FPGA devices From ea3bdee54fcd8913ddc10c45569d65ebb5bf66fa Mon Sep 17 00:00:00 2001 From: Wang Date: Wed, 30 Mar 2022 23:48:25 +0900 Subject: [PATCH 58/73] add index.md (#31362) --- .../docs/tasks/administer-cluster/manage-resources/_index.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 content/ja/docs/tasks/administer-cluster/manage-resources/_index.md diff --git a/content/ja/docs/tasks/administer-cluster/manage-resources/_index.md b/content/ja/docs/tasks/administer-cluster/manage-resources/_index.md new file mode 100644 index 0000000000000..a10d5bf6abc2f --- /dev/null +++ b/content/ja/docs/tasks/administer-cluster/manage-resources/_index.md @@ -0,0 +1,4 @@ +--- +title: メモリー、CPU、APIリソースの管理 +weight: 20 +--- From f0e4a10636176626141f2011a209893d47032b00 Mon Sep 17 00:00:00 2001 From: Mitesh Jain <47820816+miteshskj@users.noreply.github.com> Date: Wed, 30 Mar 2022 21:24:51 +0530 Subject: [PATCH 59/73] Remove note for unsupported version. --- .../workloads/pods/pod-topology-spread-constraints.md | 8 -------- 1 file changed, 8 deletions(-) diff --git a/content/en/docs/concepts/workloads/pods/pod-topology-spread-constraints.md b/content/en/docs/concepts/workloads/pods/pod-topology-spread-constraints.md index 4823cd26f56c4..369c81eb8de8c 100644 --- a/content/en/docs/concepts/workloads/pods/pod-topology-spread-constraints.md +++ b/content/en/docs/concepts/workloads/pods/pod-topology-spread-constraints.md @@ -12,14 +12,6 @@ obsolete --> You can use _topology spread constraints_ to control how {{< glossary_tooltip text="Pods" term_id="Pod" >}} are spread across your cluster among failure-domains such as regions, zones, nodes, and other user-defined topology domains. This can help to achieve high availability as well as efficient resource utilization. -{{< note >}} -In versions of Kubernetes before v1.18, you must enable the `EvenPodsSpread` -[feature gate](/docs/reference/command-line-tools-reference/feature-gates/) on -the [API server](/docs/concepts/overview/components/#kube-apiserver) and the -[scheduler](/docs/reference/command-line-tools-reference/kube-scheduler/) in order to use Pod -topology spread constraints. -{{< /note >}} - ## Prerequisites From 672813f3e782295f96b14e7e518ba28511c4543d Mon Sep 17 00:00:00 2001 From: Tim Bannister Date: Mon, 10 Jan 2022 23:25:34 +0000 Subject: [PATCH 60/73] Move PSP into Security concepts section The logical navigation definitely works better if Pod Security admission and PodSecurityPolicy are pages in the same section. Make It So. Co-authored-by: Rey Lejano --- .../index.md | 2 +- ...dSecurityPolicy-Past-Present-and-Future.md | 2 +- .../_posts/2021-10-05-nsa-cisa-hardening.md | 2 +- ...1-11-09-non-root-containers-and-devices.md | 2 +- .../2021-12-09-pod-security-admission-beta.md | 2 +- .../docs/concepts/extend-kubernetes/_index.md | 2 +- .../security/pod-security-admission.md | 2 +- .../pod-security-policy.md | 0 .../security/pod-security-standards.md | 2 +- .../concepts/storage/ephemeral-volumes.md | 13 +++++------ .../en/docs/concepts/workloads/pods/_index.md | 3 +-- .../admission-controllers.md | 13 +++++++---- .../access-authn-authz/authorization.md | 2 +- .../reference/glossary/pod-security-policy.md | 2 +- .../windows/intro-windows-in-kubernetes.md | 2 +- .../administer-cluster/securing-a-cluster.md | 23 ++++++++++++++----- .../security-context.md | 2 +- .../configure-pod-container/static-pod.md | 3 +-- .../en/docs/tutorials/security/apparmor.md | 2 +- static/_redirects | 5 ++-- 20 files changed, 49 insertions(+), 37 deletions(-) rename content/en/docs/concepts/{policy => security}/pod-security-policy.md (100%) diff --git a/content/en/blog/_posts/2020-11-18-cloud-native-security-for-your-cluster/index.md b/content/en/blog/_posts/2020-11-18-cloud-native-security-for-your-cluster/index.md index 900f8b07eee1e..7851a04380edd 100644 --- a/content/en/blog/_posts/2020-11-18-cloud-native-security-for-your-cluster/index.md +++ b/content/en/blog/_posts/2020-11-18-cloud-native-security-for-your-cluster/index.md @@ -18,7 +18,7 @@ The paper attempts to _not_ focus on any specific [cloud native project](https:/ ## Kubernetes native security controls When using Kubernetes as a workload orchestrator, some of the security controls this version of the whitepaper recommends are: -* [Pod Security Policies](/docs/concepts/policy/pod-security-policy/): Implement a single source of truth for “least privilege” workloads across the entire cluster +* [Pod Security Policies](/docs/concepts/security/pod-security-policy/): Implement a single source of truth for “least privilege” workloads across the entire cluster * [Resource requests and limits](/docs/concepts/configuration/manage-resources-containers/#requests-and-limits): Apply requests (soft constraint) and limits (hard constraint) for shared resources such as memory and CPU * [Audit log analysis](/docs/tasks/debug-application-cluster/audit/): Enable Kubernetes API auditing and filtering for security relevant events * [Control plane authentication and certificate root of trust](/docs/concepts/architecture/control-plane-node-communication/): Enable mutual TLS authentication with a trusted CA for communication within the cluster diff --git a/content/en/blog/_posts/2021-04-06-PodSecurityPolicy-Past-Present-and-Future.md b/content/en/blog/_posts/2021-04-06-PodSecurityPolicy-Past-Present-and-Future.md index c65069460a38f..73043a67e006b 100644 --- a/content/en/blog/_posts/2021-04-06-PodSecurityPolicy-Past-Present-and-Future.md +++ b/content/en/blog/_posts/2021-04-06-PodSecurityPolicy-Past-Present-and-Future.md @@ -21,7 +21,7 @@ Until then, PSP is still PSP. There will be at least a year during which the new ## What is PodSecurityPolicy? -[PodSecurityPolicy](/docs/concepts/policy/pod-security-policy/) is a built-in [admission controller](/blog/2019/03/21/a-guide-to-kubernetes-admission-controllers/) that allows a cluster administrator to control security-sensitive aspects of the Pod specification. +[PodSecurityPolicy](/docs/concepts/security/pod-security-policy/) is a built-in [admission controller](/blog/2019/03/21/a-guide-to-kubernetes-admission-controllers/) that allows a cluster administrator to control security-sensitive aspects of the Pod specification. First, one or more PodSecurityPolicy resources are created in a cluster to define the requirements Pods must meet. Then, RBAC rules are created to control which PodSecurityPolicy applies to a given pod. If a pod meets the requirements of its PSP, it will be admitted to the cluster as usual. In some cases, PSP can also modify Pod fields, effectively creating new defaults for those fields. If a Pod does not meet the PSP requirements, it is rejected, and cannot run. diff --git a/content/en/blog/_posts/2021-10-05-nsa-cisa-hardening.md b/content/en/blog/_posts/2021-10-05-nsa-cisa-hardening.md index 1af75e9ceb597..c953a02677f53 100644 --- a/content/en/blog/_posts/2021-10-05-nsa-cisa-hardening.md +++ b/content/en/blog/_posts/2021-10-05-nsa-cisa-hardening.md @@ -175,7 +175,7 @@ require internet access to update the vulnerability database. ### Pod Security Policies -Since Kubernetes v1.21, the [PodSecurityPolicy](/docs/concepts/policy/pod-security-policy/) +Since Kubernetes v1.21, the [PodSecurityPolicy](/docs/concepts/security/pod-security-policy/) API and related features are [deprecated](/blog/2021/04/06/podsecuritypolicy-deprecation-past-present-and-future/), but some of the guidance in this section will still apply for the next few years, until cluster operators upgrade their clusters to newer Kubernetes versions. diff --git a/content/en/blog/_posts/2021-11-09-non-root-containers-and-devices.md b/content/en/blog/_posts/2021-11-09-non-root-containers-and-devices.md index 8fd5cc6ba1e0a..2dcaf952dd65b 100644 --- a/content/en/blog/_posts/2021-11-09-non-root-containers-and-devices.md +++ b/content/en/blog/_posts/2021-11-09-non-root-containers-and-devices.md @@ -18,7 +18,7 @@ One of the key security principles for running containers in Kubernetes is the principle of least privilege. The Pod/container `securityContext` specifies the config options to set, e.g., Linux capabilities, MAC policies, and user/group ID values to achieve this. -Furthermore, the cluster admins are supported with tools like [PodSecurityPolicy](/docs/concepts/policy/pod-security-policy/) (deprecated) or +Furthermore, the cluster admins are supported with tools like [PodSecurityPolicy](/docs/concepts/security/pod-security-policy/) (deprecated) or [Pod Security Admission](/docs/concepts/security/pod-security-admission/) (alpha) to enforce the desired security settings for pods that are being deployed in the cluster. These settings could, for instance, require that containers must be `runAsNonRoot` or that they are forbidden from running with root's group ID in `runAsGroup` or `supplementalGroups`. diff --git a/content/en/blog/_posts/2021-12-09-pod-security-admission-beta.md b/content/en/blog/_posts/2021-12-09-pod-security-admission-beta.md index 5b1fe2fe0038f..f1eec3ef766c8 100644 --- a/content/en/blog/_posts/2021-12-09-pod-security-admission-beta.md +++ b/content/en/blog/_posts/2021-12-09-pod-security-admission-beta.md @@ -9,7 +9,7 @@ slug: pod-security-admission-beta With the release of Kubernetes v1.23, [Pod Security admission](/docs/concepts/security/pod-security-admission/) has now entered beta. Pod Security is a [built-in](/docs/reference/access-authn-authz/admission-controllers/) admission controller that evaluates pod specifications against a predefined set of [Pod Security Standards](/docs/concepts/security/pod-security-standards/) and determines whether to `admit` or `deny` the pod from running. -Pod Security is the successor to [PodSecurityPolicy](/docs/concepts/policy/pod-security-policy/) which was deprecated in the v1.21 release, and will be removed in Kubernetes v1.25. In this article, we cover the key concepts of Pod Security along with how to use it. We hope that cluster administrators and developers alike will use this new mechanism to enforce secure defaults for their workloads. +Pod Security is the successor to [PodSecurityPolicy](/docs/concepts/security/pod-security-policy/) which was deprecated in the v1.21 release, and will be removed in Kubernetes v1.25. In this article, we cover the key concepts of Pod Security along with how to use it. We hope that cluster administrators and developers alike will use this new mechanism to enforce secure defaults for their workloads. ## Why Pod Security diff --git a/content/en/docs/concepts/extend-kubernetes/_index.md b/content/en/docs/concepts/extend-kubernetes/_index.md index 7686666b58bf8..3cf3eb1f7a676 100644 --- a/content/en/docs/concepts/extend-kubernetes/_index.md +++ b/content/en/docs/concepts/extend-kubernetes/_index.md @@ -46,7 +46,7 @@ Customization approaches can be broadly divided into *configuration*, which only Flags and configuration files may not always be changeable in a hosted Kubernetes service or a distribution with managed installation. When they are changeable, they are usually only changeable by the cluster administrator. Also, they are subject to change in future Kubernetes versions, and setting them may require restarting processes. For those reasons, they should be used only when there are no other options. -*Built-in Policy APIs*, such as [ResourceQuota](/docs/concepts/policy/resource-quotas/), [PodSecurityPolicies](/docs/concepts/policy/pod-security-policy/), [NetworkPolicy](/docs/concepts/services-networking/network-policies/) and Role-based Access Control ([RBAC](/docs/reference/access-authn-authz/rbac/)), are built-in Kubernetes APIs. APIs are typically used with hosted Kubernetes services and with managed Kubernetes installations. They are declarative and use the same conventions as other Kubernetes resources like pods, so new cluster configuration can be repeatable and be managed the same way as applications. And, where they are stable, they enjoy a [defined support policy](/docs/reference/using-api/deprecation-policy/) like other Kubernetes APIs. For these reasons, they are preferred over *configuration files* and *flags* where suitable. +*Built-in Policy APIs*, such as [ResourceQuota](/docs/concepts/policy/resource-quotas/), [PodSecurityPolicies](/docs/concepts/security/pod-security-policy/), [NetworkPolicy](/docs/concepts/services-networking/network-policies/) and Role-based Access Control ([RBAC](/docs/reference/access-authn-authz/rbac/)), are built-in Kubernetes APIs. APIs are typically used with hosted Kubernetes services and with managed Kubernetes installations. They are declarative and use the same conventions as other Kubernetes resources like pods, so new cluster configuration can be repeatable and be managed the same way as applications. And, where they are stable, they enjoy a [defined support policy](/docs/reference/using-api/deprecation-policy/) like other Kubernetes APIs. For these reasons, they are preferred over *configuration files* and *flags* where suitable. ## Extensions diff --git a/content/en/docs/concepts/security/pod-security-admission.md b/content/en/docs/concepts/security/pod-security-admission.md index 67b8770a84371..7511f881441d6 100644 --- a/content/en/docs/concepts/security/pod-security-admission.md +++ b/content/en/docs/concepts/security/pod-security-admission.md @@ -21,7 +21,7 @@ behavior of pods in a clear, consistent fashion. As a Beta feature, Kubernetes offers a built-in _Pod Security_ {{< glossary_tooltip text="admission controller" term_id="admission-controller" >}}, the successor -to [PodSecurityPolicies](/docs/concepts/policy/pod-security-policy/). Pod security restrictions +to [PodSecurityPolicies](/docs/concepts/security/pod-security-policy/). Pod security restrictions are applied at the {{< glossary_tooltip text="namespace" term_id="namespace" >}} level when pods are created. diff --git a/content/en/docs/concepts/policy/pod-security-policy.md b/content/en/docs/concepts/security/pod-security-policy.md similarity index 100% rename from content/en/docs/concepts/policy/pod-security-policy.md rename to content/en/docs/concepts/security/pod-security-policy.md diff --git a/content/en/docs/concepts/security/pod-security-standards.md b/content/en/docs/concepts/security/pod-security-standards.md index c4333c1542e0a..b8c2c2771f191 100644 --- a/content/en/docs/concepts/security/pod-security-standards.md +++ b/content/en/docs/concepts/security/pod-security-standards.md @@ -452,7 +452,7 @@ of individual policies are not defined here. - {{< example file="security/podsecurity-baseline.yaml" >}}Baseline namespace{{< /example >}} - {{< example file="security/podsecurity-restricted.yaml" >}}Restricted namespace{{< /example >}} -[**PodSecurityPolicy**](/docs/concepts/policy/pod-security-policy/) (Deprecated) +[**PodSecurityPolicy**](/docs/concepts/security/pod-security-policy/) (Deprecated) - {{< example file="policy/privileged-psp.yaml" >}}Privileged{{< /example >}} - {{< example file="policy/baseline-psp.yaml" >}}Baseline{{< /example >}} diff --git a/content/en/docs/concepts/storage/ephemeral-volumes.md b/content/en/docs/concepts/storage/ephemeral-volumes.md index fb86967114afb..282cc21f8dd35 100644 --- a/content/en/docs/concepts/storage/ephemeral-volumes.md +++ b/content/en/docs/concepts/storage/ephemeral-volumes.md @@ -126,10 +126,10 @@ standardized. See the documentation of each CSI driver for further instructions. ### CSI driver restrictions - + {{< feature-state for_k8s_version="v1.21" state="deprecated" >}} -As a cluster administrator, you can use a [PodSecurityPolicy](/docs/concepts/policy/pod-security-policy/) to control which CSI drivers can be used in a Pod, specified with the +As a cluster administrator, you can use a [PodSecurityPolicy](/docs/concepts/security/pod-security-policy/) to control which CSI drivers can be used in a Pod, specified with the [`allowedCSIDrivers` field](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#podsecuritypolicyspec-v1beta1-policy). {{< note >}} @@ -250,13 +250,12 @@ PVCs indirectly if they can create Pods, even if they do not have permission to create PVCs directly. Cluster administrators must be aware of this. If this does not fit their security model, they have two choices: -- Use a [Pod Security - Policy](/docs/concepts/policy/pod-security-policy/) where the - `volumes` list does not contain the `ephemeral` volume type - (deprecated in Kubernetes 1.21). - Use an [admission webhook](/docs/reference/access-authn-authz/extensible-admission-controllers/) - which rejects objects like Pods that have a generic ephemeral + that rejects objects like Pods that have a generic ephemeral volume. +- Use a [Pod Security Policy](/docs/concepts/security/pod-security-policy/) + where the `volumes` list does not contain the `ephemeral` volume type + (deprecated since Kubernetes 1.21). The normal [namespace quota for PVCs](/docs/concepts/policy/resource-quotas/#storage-resource-quota) still applies, so even if users are allowed to use this new mechanism, they cannot use diff --git a/content/en/docs/concepts/workloads/pods/_index.md b/content/en/docs/concepts/workloads/pods/_index.md index 3aca6e094b7be..e7b5b4dc86e02 100644 --- a/content/en/docs/concepts/workloads/pods/_index.md +++ b/content/en/docs/concepts/workloads/pods/_index.md @@ -261,8 +261,7 @@ Within a Pod, containers share an IP address and port space, and can find each other via `localhost`. The containers in a Pod can also communicate with each other using standard inter-process communications like SystemV semaphores or POSIX shared memory. Containers in different Pods have distinct IP addresses -and can not communicate by IPC without -[special configuration](/docs/concepts/policy/pod-security-policy/). +and can not communicate by OS-level IPC without special configuration. Containers that want to interact with a container running in a different Pod can use IP networking to communicate. diff --git a/content/en/docs/reference/access-authn-authz/admission-controllers.md b/content/en/docs/reference/access-authn-authz/admission-controllers.md index 6f8bf5b8b3fc8..869f183a33f70 100644 --- a/content/en/docs/reference/access-authn-authz/admission-controllers.md +++ b/content/en/docs/reference/access-authn-authz/admission-controllers.md @@ -716,7 +716,7 @@ for more information. This admission controller acts on creation and modification of the pod and determines if it should be admitted based on the requested security context and the available Pod Security Policies. -See also [Pod Security Policy documentation](/docs/concepts/policy/pod-security-policy/) +See also the [PodSecurityPolicy](/docs/concepts/security/pod-security-policy/) documentation for more information. ### PodTolerationRestriction {#podtolerationrestriction} @@ -777,14 +777,17 @@ for more information. ### SecurityContextDeny {#securitycontextdeny} -This admission controller will deny any pod that attempts to set certain escalating +This admission controller will deny any Pod that attempts to set certain escalating [SecurityContext](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#securitycontext-v1-core) fields, as shown in the [Configure a Security Context for a Pod or Container](/docs/tasks/configure-pod-container/security-context/) task. -This should be enabled if a cluster doesn't utilize -[pod security policies](/docs/concepts/policy/pod-security-policy/) -to restrict the set of values a security context can take. +If you don't use [Pod Security admission]((/docs/concepts/security/pod-security-admission/), +[PodSecurityPolicies](/docs/concepts/security/pod-security-policy/), nor any external enforcement mechanism, +then you could use this admission controller to restrict the set of values a security context can take. + +See [Pod Security Standards](/docs/concepts/security/pod-security-standards/) for more context on restricting +pod privileges. ### ServiceAccount {#serviceaccount} diff --git a/content/en/docs/reference/access-authn-authz/authorization.md b/content/en/docs/reference/access-authn-authz/authorization.md index 21b6089e86fdc..3e7d71977c369 100644 --- a/content/en/docs/reference/access-authn-authz/authorization.md +++ b/content/en/docs/reference/access-authn-authz/authorization.md @@ -76,7 +76,7 @@ DELETE | delete (for individual resources), deletecollection (for collections Kubernetes sometimes checks authorization for additional permissions using specialized verbs. For example: -* [PodSecurityPolicy](/docs/concepts/policy/pod-security-policy/) +* [PodSecurityPolicy](/docs/concepts/security/pod-security-policy/) * `use` verb on `podsecuritypolicies` resources in the `policy` API group. * [RBAC](/docs/reference/access-authn-authz/rbac/#privilege-escalation-prevention-and-bootstrapping) * `bind` and `escalate` verbs on `roles` and `clusterroles` resources in the `rbac.authorization.k8s.io` API group. diff --git a/content/en/docs/reference/glossary/pod-security-policy.md b/content/en/docs/reference/glossary/pod-security-policy.md index 52c4433b481eb..ec6796205938a 100644 --- a/content/en/docs/reference/glossary/pod-security-policy.md +++ b/content/en/docs/reference/glossary/pod-security-policy.md @@ -2,7 +2,7 @@ title: Pod Security Policy id: pod-security-policy date: 2018-04-12 -full_link: /docs/concepts/policy/pod-security-policy/ +full_link: /docs/concepts/security/pod-security-policy/ short_description: > Enables fine-grained authorization of pod creation and updates. diff --git a/content/en/docs/setup/production-environment/windows/intro-windows-in-kubernetes.md b/content/en/docs/setup/production-environment/windows/intro-windows-in-kubernetes.md index 91118c4d6c812..add81bd71e6fa 100644 --- a/content/en/docs/setup/production-environment/windows/intro-windows-in-kubernetes.md +++ b/content/en/docs/setup/production-environment/windows/intro-windows-in-kubernetes.md @@ -696,7 +696,7 @@ operator, you should take both of the following additional measures: [RunAsUsername](/docs/tasks/configure-pod-container/configure-runasusername) can be specified for Windows Pods or containers to execute the container processes as a node-default user. This is roughly equivalent to -[RunAsUser](/docs/concepts/policy/pod-security-policy/#users-and-groups). +[RunAsUser](/docs/concepts/security/pod-security-policy/#users-and-groups). Linux-specific pod security context privileges such as SELinux, AppArmor, Seccomp, or capabilities (POSIX capabilities), and others are not supported. diff --git a/content/en/docs/tasks/administer-cluster/securing-a-cluster.md b/content/en/docs/tasks/administer-cluster/securing-a-cluster.md index ba820cbe0a765..b68a48487001c 100644 --- a/content/en/docs/tasks/administer-cluster/securing-a-cluster.md +++ b/content/en/docs/tasks/administer-cluster/securing-a-cluster.md @@ -63,7 +63,7 @@ actions a client might want to perform. It is recommended that you use the As with authentication, simple and broad roles may be appropriate for smaller clusters, but as more users interact with the cluster, it may become necessary to separate teams into separate -namespaces with more limited roles. +{{< glossary_tooltip text="namespaces" term_id="namespace" >}} with more limited roles. With authorization, it is important to understand how updates on one object may cause actions in other places. For instance, a user may not be able to create pods directly, but allowing them to @@ -106,15 +106,18 @@ reserved resources like memory, or to provide default limits when none are speci A pod definition contains a [security context](/docs/tasks/configure-pod-container/security-context/) that allows it to request access to run as a specific Linux user on a node (like root), access to run privileged or access the host network, and other controls that would otherwise -allow it to run unfettered on a hosting node. [Pod security policies](/docs/concepts/policy/pod-security-policy/) -can limit which users or service accounts can provide dangerous security context settings. For example, pod security policies can limit volume mounts, especially `hostPath`, which are aspects of a pod that should be controlled. +allow it to run unfettered on a hosting node. + +You can configure [Pod security admission](/docs/concepts/security/pod-security-admission/) +to enforce use of a particular [Pod Security Standard](/docs/concepts/security/pod-security-standards/) +in a {{< glossary_tooltip text="namespace" term_id="namespace" >}}, or to detect breaches. Generally, most application workloads need limited access to host resources so they can successfully run as a root process (uid 0) without access to host information. However, considering the privileges associated with the root user, you should write application containers to run as a non-root user. Similarly, administrators who wish to prevent -client applications from escaping their containers should use a restrictive pod security -policy. +client applications from escaping their containers should apply the **Baseline** +or **Restricted** Pod Security Standard. ### Preventing containers from loading unwanted kernel modules @@ -238,7 +241,15 @@ restrict the integration to functioning in a single namespace if possible. Components that create pods may also be unexpectedly powerful if they can do so inside namespaces like the `kube-system` namespace, because those pods can gain access to service account secrets or run with elevated permissions if those service accounts are granted access to permissive -[pod security policies](/docs/concepts/policy/pod-security-policy/). +[PodSecurityPolicies](/docs/concepts/security/pod-security-policy/). + +If you use [Pod Security admission]((/docs/concepts/security/pod-security-admission/) and allow +any component to create Pods within a namespace that permits privileged Pods, those Pods may +be able to escape their containers and use this widened access to elevate their privileges. + +You should not allow untrusted components to create Pods in any system namespace (those with +names that start with `kube-`) nor in any namespace where that access grant allows the possibility +of privilege escalation. ### Encrypt secrets at rest diff --git a/content/en/docs/tasks/configure-pod-container/security-context.md b/content/en/docs/tasks/configure-pod-container/security-context.md index 30dfeb0e5d042..2520285caf5bf 100644 --- a/content/en/docs/tasks/configure-pod-container/security-context.md +++ b/content/en/docs/tasks/configure-pod-container/security-context.md @@ -487,6 +487,6 @@ kubectl delete pod security-context-demo-4 * [Tuning Docker with the newest security enhancements](https://github.com/containerd/containerd/blob/main/docs/cri/config.md) * [Security Contexts design document](https://git.k8s.io/community/contributors/design-proposals/auth/security_context.md) * [Ownership Management design document](https://git.k8s.io/community/contributors/design-proposals/storage/volume-ownership-management.md) -* [Pod Security Policies](/docs/concepts/policy/pod-security-policy/) +* [PodSecurityPolicy](/docs/concepts/security/pod-security-policy/) * [AllowPrivilegeEscalation design document](https://git.k8s.io/community/contributors/design-proposals/auth/no-new-privs.md) diff --git a/content/en/docs/tasks/configure-pod-container/static-pod.md b/content/en/docs/tasks/configure-pod-container/static-pod.md index fcaa0d9db438c..11df9fde0491a 100644 --- a/content/en/docs/tasks/configure-pod-container/static-pod.md +++ b/content/en/docs/tasks/configure-pod-container/static-pod.md @@ -182,8 +182,7 @@ static-web 1/1 Running 0 2m ``` {{< note >}} -Make sure the kubelet has permission to create the mirror Pod in the API server. If not, the creation request is rejected by the API server. See -[PodSecurityPolicy](/docs/concepts/policy/pod-security-policy/). +Make sure the kubelet has permission to create the mirror Pod in the API server. If not, the creation request is rejected by the API server. See [Pod Security admission](/docs/concepts/security/pod-security-admission) and [PodSecurityPolicy](/docs/concepts/security/pod-security-policy/). {{< /note >}} {{< glossary_tooltip term_id="label" text="Labels" >}} from the static Pod are diff --git a/content/en/docs/tutorials/security/apparmor.md b/content/en/docs/tutorials/security/apparmor.md index 1e8ead93101ff..5af4d86668cec 100644 --- a/content/en/docs/tutorials/security/apparmor.md +++ b/content/en/docs/tutorials/security/apparmor.md @@ -350,7 +350,7 @@ node with the required profile. {{< note >}} PodSecurityPolicy is deprecated in Kubernetes v1.21, and will be removed in v1.25. -See [PodSecurityPolicy documentation](/docs/concepts/policy/pod-security-policy/) for more information. +See [PodSecurityPolicy](/docs/concepts/security/pod-security-policy/) documentation for more information. {{< /note >}} If the PodSecurityPolicy extension is enabled, cluster-wide AppArmor restrictions can be applied. To diff --git a/static/_redirects b/static/_redirects index b8b28e1948f0b..2f5ce4234a5ab 100644 --- a/static/_redirects +++ b/static/_redirects @@ -159,7 +159,8 @@ /docs/concepts/workloads/pods/pod-overview/ /docs/concepts/workloads/pods/ 301 /docs/concepts/workloads/pods/init-containers/Kubernetes/ /docs/concepts/workloads/pods/init-containers/ 301 -/docs/consumer-guideline/pod-security-coverage/ /docs/concepts/policy/pod-security-policy/ 301 +/docs/concepts/policy/pod-security-policy/ /docs/concepts/security/pod-security-policy/ 301 +/docs/consumer-guideline/pod-security-coverage/ /docs/concepts/security/pod-security-policy/ 301 /docs/contribute/create-pull-request/ /docs/home/contribute/create-pull-request/ 301 /docs/contribute/page-templates/ /docs/home/contribute/page-templates/ 301 @@ -424,7 +425,7 @@ /docs/user-guide/persistent-volumes/index /docs/concepts/storage/persistent-volumes/ 301 /docs/user-guide/persistent-volumes/index.md /docs/concepts/storage/persistent-volumes/ 301 /docs/user-guide/persistent-volumes/walkthrough/ /docs/tasks/configure-pod-container/configure-persistent-volume-storage/ 301 -/docs/user-guide/pod-security-policy/ /docs/concepts/policy/pod-security-policy/ 301 +/docs/user-guide/pod-security-policy/ /docs/concepts/security/pod-security-policy/ 301 /docs/user-guide/pod-states/ /docs/concepts/workloads/pods/pod-lifecycle/ 301 /docs/user-guide/pod-templates/ /docs/concepts/workloads/pods/#pod-templates 301 /docs/user-guide/pods/ /docs/concepts/workloads/pods/pod/ 301 From 1f25824e050382e00287769094437bfdccbada56 Mon Sep 17 00:00:00 2001 From: Priyanshu Ahlawat <84102724+PriyanshuAhlawat@users.noreply.github.com> Date: Wed, 30 Mar 2022 22:01:29 +0530 Subject: [PATCH 61/73] Update content/en/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Stefan Büringer <4662360+sbueringer@users.noreply.github.com> --- .../tools/kubeadm/create-cluster-kubeadm.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/en/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm.md b/content/en/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm.md index 343aa4a60c4c8..8349b4a817034 100644 --- a/content/en/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm.md +++ b/content/en/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm.md @@ -551,7 +551,7 @@ Example: ### kubeadm's skew against kubeadm -There are certain limitations on how kubeadm commands can operate on existing nodes or whole cluster +There are certain limitations on how kubeadm commands can operate on existing nodes or whole clusters managed by kubeadm. If new nodes are joined to the cluster, the kubeadm binary used for `kubeadm join` must match From 16ae848701d4b8f401dd726805f33eeee7a5b6c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20G=C3=BCttler?= Date: Wed, 30 Mar 2022 08:32:23 +0200 Subject: [PATCH 62/73] Link to 'Guaranteed' pods. related to #32619 --- .../tasks/administer-cluster/reserve-compute-resources.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/content/en/docs/tasks/administer-cluster/reserve-compute-resources.md b/content/en/docs/tasks/administer-cluster/reserve-compute-resources.md index 0dd24d3f6ea45..f3c73ee01a0ec 100644 --- a/content/en/docs/tasks/administer-cluster/reserve-compute-resources.md +++ b/content/en/docs/tasks/administer-cluster/reserve-compute-resources.md @@ -182,8 +182,9 @@ respectively. ## General Guidelines -System daemons are expected to be treated similar to 'Guaranteed' pods. System -daemons can burst within their bounding control groups and this behavior needs +System daemons are expected to be treated similar to +['Guaranteed' pods](/docs/tasks/configure-pod-container/quality-service-pod/#create-a-pod-that-gets-assigned-a-qos-class-of-guaranteed). +System daemons can burst within their bounding control groups and this behavior needs to be managed as part of kubernetes deployments. For example, `kubelet` should have its own control group and share `kube-reserved` resources with the container runtime. However, Kubelet cannot burst and use up all available Node From 998d762331887c76682997662b3d8c432389c5e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20G=C3=BCttler?= Date: Wed, 30 Mar 2022 20:29:26 +0200 Subject: [PATCH 63/73] S/'Guaranteed'/Guaranteed --- .../docs/tasks/administer-cluster/reserve-compute-resources.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/en/docs/tasks/administer-cluster/reserve-compute-resources.md b/content/en/docs/tasks/administer-cluster/reserve-compute-resources.md index f3c73ee01a0ec..8922a2fe003ba 100644 --- a/content/en/docs/tasks/administer-cluster/reserve-compute-resources.md +++ b/content/en/docs/tasks/administer-cluster/reserve-compute-resources.md @@ -183,7 +183,7 @@ respectively. ## General Guidelines System daemons are expected to be treated similar to -['Guaranteed' pods](/docs/tasks/configure-pod-container/quality-service-pod/#create-a-pod-that-gets-assigned-a-qos-class-of-guaranteed). +[Guaranteed pods](/docs/tasks/configure-pod-container/quality-service-pod/#create-a-pod-that-gets-assigned-a-qos-class-of-guaranteed). System daemons can burst within their bounding control groups and this behavior needs to be managed as part of kubernetes deployments. For example, `kubelet` should have its own control group and share `kube-reserved` resources with the From 8df0736acb9e13760d628b19433d7b0910dfdc69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20G=C3=BCttler?= Date: Wed, 30 Mar 2022 21:03:48 +0200 Subject: [PATCH 64/73] typo: "the" --> "then" fixed typo --- content/en/docs/tasks/administer-cluster/safely-drain-node.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/en/docs/tasks/administer-cluster/safely-drain-node.md b/content/en/docs/tasks/administer-cluster/safely-drain-node.md index 74d1694b08573..6dc5cf93c0f60 100644 --- a/content/en/docs/tasks/administer-cluster/safely-drain-node.md +++ b/content/en/docs/tasks/administer-cluster/safely-drain-node.md @@ -32,7 +32,7 @@ configure a [PodDisruptionBudget](/docs/concepts/workloads/pods/disruptions/). If availability is important for any applications that run or could run on the node(s) that you are draining, [configure a PodDisruptionBudgets](/docs/tasks/run-application/configure-pdb/) -first and the continue following this guide. +first and then continue following this guide. ## Use `kubectl drain` to remove a node from service From 3cb2b0cb141242c604a93004ad00caa1f17dbc02 Mon Sep 17 00:00:00 2001 From: Tim Bannister Date: Wed, 30 Mar 2022 22:26:12 +0100 Subject: [PATCH 65/73] Fixup incorrect systemctl command The subcommand for restart is "restart" --- .../migrating-from-dockershim/migrate-dockershim-dockerd.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/en/docs/tasks/administer-cluster/migrating-from-dockershim/migrate-dockershim-dockerd.md b/content/en/docs/tasks/administer-cluster/migrating-from-dockershim/migrate-dockershim-dockerd.md index 2660644a6d968..9593a1134a5b4 100644 --- a/content/en/docs/tasks/administer-cluster/migrating-from-dockershim/migrate-dockershim-dockerd.md +++ b/content/en/docs/tasks/administer-cluster/migrating-from-dockershim/migrate-dockershim-dockerd.md @@ -93,7 +93,7 @@ in the control plane. To modify this socket for each affected node: ## Restart the kubelet ```shell -systemctl start kubelet +systemctl restart kubelet ``` ## Verify that the node is healthy From 25c9403bf3f84adb59330ce79ec95a6529739291 Mon Sep 17 00:00:00 2001 From: twilight0620 Date: Thu, 31 Mar 2022 09:59:04 +0800 Subject: [PATCH 66/73] [zh] comments modify --- .../2022-01-19-Securing-Admission-Controllers.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/content/zh/blog/_posts/2022-01-19-Securing-Admission-Controllers.md b/content/zh/blog/_posts/2022-01-19-Securing-Admission-Controllers.md index 960624276817e..99dad347e56a2 100644 --- a/content/zh/blog/_posts/2022-01-19-Securing-Admission-Controllers.md +++ b/content/zh/blog/_posts/2022-01-19-Securing-Admission-Controllers.md @@ -98,7 +98,7 @@ It’s important to ensure that any security component in a cluster is well conf -### 准入控制的安全集群配置 +### 为准入控制保护集群配置 * **限制 [RBAC](/zh/docs/reference/access-authn-authz/rbac/) 权限**。 - 任何有权修改 webhook 对象的配置或准入控制器使用的工作负载的用户都可能会中断其操作。 + 任何有权修改 webhook 对象的配置或准入控制器使用的工作负载的用户都可以破坏其运行。 因此,确保只有集群管理员拥有这些权限非常重要。 * **防止特权工作负载**。 容器系统的一个现实是,如果工作负载被赋予某些特权, - 则有可能突破到底层集群节点并影响该节点上的其他容器。 + 则有可能逃逸到下层的集群节点并影响该节点上的其他容器。 如果准入控制器服务在它们所保护的集群上运行, - 一定要确保对特权工作负载的任何要求都要经过仔细审查并尽可能地加以限制。 + 一定要确保对特权工作负载的所有请求都要经过仔细审查并尽可能地加以限制。 * **严格控制外部系统访问**。 - 作为集群准入控制器系统中的安全服务,将有权访问敏感信息,如凭证。 + 作为集群中的安全服务,准入控制器系统将有权访问敏感信息,如凭证。 为了降低此信息被发送到集群外的风险, 应使用[网络策略](/zh/docs/concepts/services-networking/network-policies/) 来限制准入控制器服务对外部网络的访问。 @@ -132,7 +132,7 @@ In most cases, the admission controller webhook used by a cluster will be instal * **Each cluster has a dedicated webhook**. Whilst it may be possible to have admission controller webhooks that serve multiple clusters, there is a risk when using that model that an attack on the webhook service would have a larger impact where it’s shared. Also where multiple clusters use an admission controller there will be increased complexity and access requirements, making it harder to secure. --> * **每个集群都有一个专用的 webhook**。 - 虽然可能有服务于多个集群的准入控制器 webhook, + 虽然可能让准入控制器 webhook 服务于多个集群的, 但在使用该模型时存在对 webhook 服务的攻击会对共享它的地方产生更大影响的风险。 此外,在多个集群使用准入控制器的情况下,复杂性和访问要求也会增加,从而更难保护其安全。 @@ -144,8 +144,8 @@ In most cases, the admission controller webhook used by a cluster will be instal -任何用于 Kubernetes 安全的准入控制器的一个关键元素是它使用的规则库。 -规则需要能够准确地满足其目标,避免误报和误报结果。 +对于用于 Kubernetes 安全的所有准入控制器而言,一个关键元素是它使用的规则库。 +规则需要能够准确地满足其目标,避免假阳性和假阴性结果。 你可以使用命令 `kubectl logs --previous` 检索之前容器实例的日志。 如果 Pod 中有多个容器,你应该为该命令附加容器名以访问对应容器的日志。 详见 [`kubectl logs` 文档](/docs/reference/generated/kubectl/kubectl-commands#logs)。 如果 Pod 有多个容器,你应该为该命令附加容器名以访问对应容器的日志, 使用 `-c` 标志来指定要访问的容器的日志,如下所示: -```console +```console kubectl logs counter -c count - ``` -详见 [kubectl logs 文档](/zh/docs/reference/generated/kubectl/kubectl-commands#logs)。 + + +详见 [`kubectl logs` 文档](/docs/reference/generated/kubectl/kubectl-commands#logs)。 + 默认调度约束所生成的评分可能与 -[`SelectorSpread` 插件](/zh/docs/reference/scheduling/config/#scheduling-plugins). +[`SelectorSpread` 插件](/zh/docs/reference/scheduling/config/#scheduling-plugins) 所生成的评分有冲突。 建议你在为 `PodTopologySpread` 设置默认约束是禁用调度方案中的该插件。 {{< /note >}} From 421eb9a5cb8550f820bf3575cbfc516212cd5758 Mon Sep 17 00:00:00 2001 From: my-git9 <76980726+my-git9@users.noreply.github.com> Date: Thu, 31 Mar 2022 19:37:15 +0800 Subject: [PATCH 70/73] Update pod-topology-spread-constraints.md --- .../pods/pod-topology-spread-constraints.md | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/content/zh/docs/concepts/workloads/pods/pod-topology-spread-constraints.md b/content/zh/docs/concepts/workloads/pods/pod-topology-spread-constraints.md index 950e68aa0bf23..42f6677e25b1c 100644 --- a/content/zh/docs/concepts/workloads/pods/pod-topology-spread-constraints.md +++ b/content/zh/docs/concepts/workloads/pods/pod-topology-spread-constraints.md @@ -25,23 +25,6 @@ You can use _topology spread constraints_ to control how {{< glossary_tooltip te 之间的分布,例如区域(Region)、可用区(Zone)、节点和其他用户自定义拓扑域。 这样做有助于实现高可用并提升资源利用率。 - - -{{< note >}} -在 v1.18 之前的 Kubernetes 版本中,如果要使用 Pod 拓扑扩展约束,你必须在 -[API 服务器](/zh/docs/concepts/overview/components/#kube-apiserver) -和[调度器](/zh/docs/reference/command-line-tools-reference/kube-scheduler/) -中启用 `EvenPodsSpread` [特性门控](/zh/docs/reference/command-line-tools-reference/feature-gates/)。 -{{< /note >}} - *内置的策略 API*,例如[ResourceQuota](/zh/docs/concepts/policy/resource-quotas/)、 [PodSecurityPolicies](/zh/docs/concepts/policy/pod-security-policy/)、 From 99bf6b71cde355d57385cf109d26ac73d1b16a8a Mon Sep 17 00:00:00 2001 From: "xin.li" Date: Thu, 31 Mar 2022 19:48:02 +0800 Subject: [PATCH 72/73] --amend Signed-off-by: xin.li --- Dockerfile | 4 ++-- content/zh/docs/concepts/extend-kubernetes/_index.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index f8985faa72b98..9e9a6d65b0bf0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,7 +7,7 @@ FROM golang:1.16-alpine LABEL maintainer="Luc Perkins " -RUN sed -i 's!http://dl-cdn.alpinelinux.org/!https://mirrors.ustc.edu.cn/!g' /etc/apk/repositories + RUN apk add --no-cache \ curl \ gcc \ @@ -25,7 +25,7 @@ RUN mkdir $HOME/src && \ go install --tags extended FROM golang:1.16-alpine -RUN sed -i 's!http://dl-cdn.alpinelinux.org/!https://mirrors.ustc.edu.cn/!g' /etc/apk/repositories + RUN apk add --no-cache \ git \ openssh-client \ diff --git a/content/zh/docs/concepts/extend-kubernetes/_index.md b/content/zh/docs/concepts/extend-kubernetes/_index.md index 3be90a977eb24..e6f8d4bf86026 100644 --- a/content/zh/docs/concepts/extend-kubernetes/_index.md +++ b/content/zh/docs/concepts/extend-kubernetes/_index.md @@ -98,7 +98,7 @@ Flags and configuration files may not always be changeable in a hosted Kubernete *Built-in Policy APIs*, such as [ResourceQuota](/docs/concepts/policy/resource-quotas/), [PodSecurityPolicies](/docs/concepts/security/pod-security-policy/), [NetworkPolicy](/docs/concepts/services-networking/network-policies/) and Role-based Access Control ([RBAC](/docs/reference/access-authn-authz/rbac/)), are built-in Kubernetes APIs. APIs are typically used with hosted Kubernetes services and with managed Kubernetes installations. They are declarative and use the same conventions as other Kubernetes resources like pods, so new cluster configuration can be repeatable and be managed the same way as applications. And, where they are stable, they enjoy a [defined support policy](/docs/reference/using-api/deprecation-policy/) like other Kubernetes APIs. For these reasons, they are preferred over *configuration files* and *flags* where suitable. --> *内置的策略 API*,例如[ResourceQuota](/zh/docs/concepts/policy/resource-quotas/)、 -[PodSecurityPolicies](/zh/docs/concepts/policy/pod-security-policy/)、 +[PodSecurityPolicies](/zh/docs/concepts/security/pod-security-policy/)、 [NetworkPolicy](/zh/docs/concepts/services-networking/network-policies/) 和基于角色的访问控制([RBAC](/zh/docs/reference/access-authn-authz/rbac/)) 等等都是内置的 Kubernetes API。 From dc3425b79c0a875d99737ce3add4cc634204df56 Mon Sep 17 00:00:00 2001 From: Rey Lejano Date: Thu, 31 Mar 2022 08:55:14 -0700 Subject: [PATCH 73/73] fix link on blog --- .../en/blog/_posts/2022-03-31-ready-for-dockershim-removal.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/en/blog/_posts/2022-03-31-ready-for-dockershim-removal.md b/content/en/blog/_posts/2022-03-31-ready-for-dockershim-removal.md index 63d0cc5be5f3d..b615a4183e585 100644 --- a/content/en/blog/_posts/2022-03-31-ready-for-dockershim-removal.md +++ b/content/en/blog/_posts/2022-03-31-ready-for-dockershim-removal.md @@ -14,7 +14,7 @@ Way back in December of 2020, Kubernetes announced the [deprecation of Dockershi If you are rolling your own cluster or are otherwise unsure whether or not this removal affects you, stay on the safe side and [check to see if you have any dependencies on Docker Engine](/docs/tasks/administer-cluster/migrating-from-dockershim/check-if-dockershim-deprecation-affects-you/). Please note that using Docker Desktop to build your application containers is not a Docker dependency for your cluster. Container images created by Docker are compliant with the [Open Container Initiative (OCI)](https://opencontainers.org/), a Linux Foundation governance structure that defines industry standards around container formats and runtimes. They will work just fine on any container runtime supported by Kubernetes. -If you are using a managed Kubernetes service from a cloud provider, and you haven’t explicitly changed the container runtime, there may be nothing else for you to do. Amazon EKS, Azure AKS, and Google GKE all default to containerd now, though you should make sure they do not need updating if you have any node customizations. To check the runtime of your nodes, follow [Find Out What Container Runtime is Used on a Node](​​/docs/tasks/administer-cluster/migrating-from-dockershim/find-out-runtime-you-use/). +If you are using a managed Kubernetes service from a cloud provider, and you haven’t explicitly changed the container runtime, there may be nothing else for you to do. Amazon EKS, Azure AKS, and Google GKE all default to containerd now, though you should make sure they do not need updating if you have any node customizations. To check the runtime of your nodes, follow [Find Out What Container Runtime is Used on a Node](/docs/tasks/administer-cluster/migrating-from-dockershim/find-out-runtime-you-use/). Regardless of whether you are rolling your own cluster or using a managed Kubernetes service from a cloud provider, you may need to [migrate telemetry or security agents that rely on Docker Engine](/docs/tasks/administer-cluster/migrating-from-dockershim/migrating-telemetry-and-security-agents/).

Servicio de almacenamiento en la nubeVolúmenes máximos por Nodo