@@ -96,6 +96,131 @@ By default, the kubelet will prevent the pod from starting if the named ClusterT
9696
9797{{% code_sample file="pods/storage/projected-clustertrustbundle.yaml" %}}
9898
99+ ## podCertificate projected volumes {#podcertificate}
100+
101+ {{< feature-state feature_gate_name="PodCertificateRequest" >}}
102+
103+ {{< note >}}
104+ In Kubernetes {{< skew currentVersion >}}, you must enable the
105+ ` PodCertificateRequest ` [ feature
106+ gate] ( /docs/reference/command-line-tools-reference/feature-gates/ ) _ and_ the
107+ ` certificates.k8s.io/v1alpha1 ` {{< glossary_tooltip text="API group"
108+ term_id="api-group" >}} in order to use this API.
109+ {{< /note >}}
110+
111+ The ` podCertificate ` projected volumes source securely provisions a private key
112+ and X.509 certificate chain for pod to use as client or server credentials.
113+ Kubelet will then handle refreshing the private key and certificate chain when
114+ they get close to expiration. The application just has to make sure that it
115+ reloads the file promptly when it changes, with a mechanism like ` inotify ` or
116+ polling.
117+
118+ Each ` podCertificate ` projection supports the following configuration fields:
119+ * ` signerName ` : Which
120+ [ signer] ( /docs/reference/access-authn-authz/certificate-signing-requests#ctb-signer-unlinked#signers )
121+ you want to issue the certificate. Note that signers may have their own
122+ access requirements, and may refuse to issue certificates to your pod.
123+ * ` keyType ` : The type of private key that should be generated. Valid values are
124+ ` ED25519 ` , ` ECDSAP256 ` , ` ECDSAP384 ` , ` ECDSAP521 ` , ` RSA3072 ` , and ` RSA4096 ` .
125+ * ` maxExpirationSeconds ` : What's the maximum lifetime you want for the
126+ certificate issued to the pod? If not set, will be defaulted to ` 86400 ` (24
127+ hours). Must be at least ` 3600 ` (1 hour), and at most ` 7862400 ` (91 days).
128+ * ` credentialBundlePath ` : Relative path within the projection where the
129+ credential bundle should be written. The credential bundle is a PEM-formatted
130+ file, where the first block is a "PRIVATE KEY" block that contains a
131+ PKCS #8 -serialized private key, and the remaining blocks are "CERTIFICATE"
132+ blocks that comprise the certificate chain (leaf certificate and any
133+ intermediates).
134+ * ` keyPath ` and ` certificateChainPath ` : Separate paths where Kubelet should
135+ write * just* the private key or certificate chain.
136+
137+ {{< note >}}
138+
139+ Most applications should prefer using ` credentialBundlePath ` unless they need
140+ the key and certificates in separate files for compatibility reasons. Kubelet
141+ uses an atomic writing strategy based on symlinks to make sure that when you
142+ open the files it projects, you read either the old content or the new content.
143+ However, if you read the key and certificate chain from separate files, Kubelet
144+ may rotate the credentials after your first read and before your second read,
145+ resulting in your application loading a mismatched key and certificate.
146+
147+ {{< /note >}}
148+
149+ Under the hood, Kubelet will run the following state machine for each
150+ ` podCertificate ` projection:
151+ 1 . The projection starts out in ` Initial ` state.
152+ 2 . Kubelet generates a private key and holds it in memory.
153+ 3 . Kubelet creates a
154+ [ PodCertificateRequest] ( /docs/reference/access-authn-authz/certificate-signing-requests#ctb-signer-unlinked#pod-certificate-requests )
155+ addressed to the requested signer. Kubelet then moves the projection into
156+ the ` Wait ` state.
157+ 4 . If the PodCertificateRequest is marked "Denied", move to the ` Denied ` state. This is
158+ a permanent error state, and the container(s) that mount this projection will
159+ fail to start.
160+ 5 . If the PodCertificateRequest is marked "Failed", move to the ` Failed ` state.
161+ This is a permanent error state, and the container(s) that mount this
162+ projection will fail to start.
163+ 6 . If the PodCertificate is marked "Issued", move to the ` Fresh ` state. Kubelet
164+ holds the private key and certificate chain in memory, and will periodically
165+ write them to the filesystem at the requested location. The container that
166+ mounts this projection will start up and run (assuming nothing else blocks
167+ its execution).
168+ 7 . The signer indicated an appropriate time to begin refreshing the certificate
169+ when it issued the PodCertificateRequest. Once that time has passed Kubelet
170+ will generate a new private key, create a new PodCertificateRequest, and move
171+ the projection into ` WaitRefresh ` state.
172+ 8 . If the PodCertificateRequest is marked "Denied", move to the ` Denied ` state.
173+ This is a permanent error state, and the container(s) will begin to get
174+ Kubelet volume remount errors.
175+ 9 . If the PodCertificateRequest is marked "Failed", move to the ` Failed ` state.
176+ This is a permanent error state, and the container(s) will begin to get
177+ Kubelet volume remount errors.
178+ 10 . If the PodCertificate is marked "Issued", move back to the ` Fresh ` state. The
179+ container(s) will continue to run, with the new private key and certificate
180+ chain written to the filesystem.
181+
182+ {{< mermaid >}}
183+ graph TB
184+ Initial --> Wait
185+ Wait --> Fresh
186+ Wait --> Failed
187+ Wait --> Denied
188+ Fresh --> WaitRefresh
189+ WaitRefresh --> Failed
190+ WaitRefresh --> Denied
191+ {{< /mermaid >}}
192+ Figure 1: Kubelet podCertificate lifecycle
193+
194+ Example Pod spec that generates an ED25519 private key, requests a certificate
195+ from the ` coolcert.example.com/foo ` signer, and writes the results to
196+ ` /var/run/my-x509-credentials/coolcert.example.com/foo ` :
197+ ``` yaml
198+ apiVersion : v1
199+ kind : Pod
200+ metadata :
201+ namespace : default
202+ name : podcertificate-pod
203+ spec :
204+ serviceAccountName : default
205+ containers :
206+ - image : debian
207+ name : main
208+ command : ["sleep", "infinity"]
209+ volumeMounts :
210+ - name : my-x509-credentials
211+ mountPath : /var/run/my-x509-credentials
212+ volumes :
213+ - name : my-x509-credentials
214+ projected :
215+ defaultMode : 420
216+ sources :
217+ - podCertificate :
218+ keyType : ED25519
219+ signerName : coolcert.example.com/foo
220+ credentialBundlePath : credentialbundle.pem
221+ ` ` `
222+
223+
99224## SecurityContext interactions
100225
101226The [proposal](https://git.k8s.io/enhancements/keps/sig-storage/2451-service-account-token-volumes#proposal) for file permission handling in projected service account volume enhancement introduced the projected files having the correct owner permissions set.
0 commit comments