Certificate Distribution in Kubernetes with AWS Private CA - Issue, Request, Store, Consume, and the Layer Where Renewal Stops

First Published:
Last Updated:

When an expired certificate takes internal traffic down, the cause is almost never that the certificate could not be issued. It was issued. The new certificate reached the cluster. And a running process went on holding the old one.

Introducing AWS Private CA addresses the first part of this problem. AWS takes responsibility for securing the CA key with a hardware security module, issuing certificates in an auditable manner, and distributing revocation information. However, the second part remains unresolved. Getting an issued certificate all the way to the workload process, and getting that process to drop the old one, happens only if somebody designed it to happen.

This article takes up exactly the ground that the published AWS Private CA Hierarchy Design declared out of scope in its own text.

Certificate distribution inside container orchestrators is out of scope for this article.

What this article covers is the inside of a cluster, on Amazon EKS or on self-managed Kubernetes, and nothing outside it. The intended audience is infrastructure and platform engineers who are currently managing internal TLS or mTLS, often relying on manual scripts or extended certificate validity periods to handle certificate renewals. Specifically, this applies to situations where the private key for a self-signed CA is stored in a Secret in plain text, where operational processes struggle to keep pace with shortened validity periods, or where engineers believe that deploying cert-manager has solved the certificate renewal issue.

The technical information presented in this article has been verified against primary sources as of September 9, 2026. References include the Secure Kubernetes with AWS Private Certificate Authority chapter of the AWS Private CA User Guide, the add-on and envelope encryption chapters of the Amazon EKS User Guide, the AWS Managed Policy Reference, the cert-manager documentation, the Secrets Store CSI Driver documentation, the Kubernetes documentation, and AWS What's New. Availability status and Regional coverage move. Look them up again when you read this. This article does not discuss pricing and does not include any performance metrics obtained through personal testing. It also does not include any attack procedures.

This article delegates the adjacent topics to published articles rather than repeating them.

  • Designing the CA Hierarchy — including how to divide root CAs and subordinate CAs, path lengths, revocation design, and short-lived certificate mode, as well as mTLS for Application Load Balancers — belongs to AWS Private CA Hierarchy Design. This article assumes you already have a CA in place.
  • How to grant AWS permissions to Pods — including whether to choose EKS Pod Identity or IRSA — belongs to Amazon EKS Pod Identity and IRSA Decision Guide. This article only describes the fact that the connector creates a Pod Identity association and does not discuss the decision-making process.
  • Designing trust anchors for IAM Roles Anywhere, and the convergence of OIDC and SPIFFE, belong to AWS IAM Inbound Workload Federation. This article only touches on the use of Roles Anywhere by the connector in clusters other than Amazon EKS.
  • The history of public Web PKI and the story of shrinking validity periods belong to TLS Certificate Ecosystem History and Timeline. This article focuses solely on what factors become bottlenecks on the private side; the rules for the public side do not apply to private CAs.
  • Deciding when to migrate from Ingress to Gateway API, and the path for using certificates from AWS Certificate Manager on the Application Load Balancer, belong to Life After Ingress NGINX on Amazon EKS. This article only covers private certificates that terminate inside the cluster.
  • Definitions of terms around X.509 and mTLS belong to Cryptography Glossary for Engineers.

Table of Contents

  1. 1. Issuing Is the Easier Half
  2. 2. Four Layers - Who Issues, Who Requests, Who Stores, and Who Reads
  3. 3. The Issuing Layer - What AWS Private CA Guards, and What It Does Not
  4. 4. The Requesting Layer - cert-manager, aws-privateca-issuer, and Two Kinds of Add-on
  5. 5. The Requesting Layer Has Its Own Credential, and It Expires Too
  6. 6. The Storing Layer - The Certificate Lands in a Kubernetes Secret
  7. 7. The Other Storing Path - What the Secrets Store CSI Driver Does Not Replace
  8. 8. The Consuming Layer - Where the Renewal Stops
  9. 9. When Lifetimes Get Shorter, Which Layer Becomes the Bottleneck First
  10. 10. Where the Primary Sources Disagree
  11. 11. Failure Modes and Anti-Patterns
  12. 12. Frequently Asked Questions
  13. 13. Summary
  14. 14. References

1. Issuing Is the Easier Half

The motivation for introducing a private CA usually comes from the issuing side. Teams want to stop handing out self-signed certificates, and they want a way to show an auditor who issued what. Or somebody handed down a requirement for mutual authentication between services. Every one of those is a question about issuance.

And issuance does get solved. Create a CA in AWS Private CA, install cert-manager and aws-privateca-issuer, and you can raise certificate requests from inside Kubernetes. The AWS Private CA User Guide writes out every one of those steps.

The problems arise later in the process. Certificates expire. A loop has to keep turning: issue a new certificate before the old one runs out, deliver it to whatever uses it, and get that thing to drop the old one. No single component runs that loop. It is spread across four separate owners. When one of them stops, the other three keep working correctly, which is why a broken loop stays invisible.

When the expiry arrives with nothing having been done, the symptom looks like this. kubectl get certificate returns READY True. However, when you extract the contents of the Secret and run it through openssl x509, the expiration date shows a future date. Despite this, the Pod still refuses to establish a handshake. The certificate has been renewed, but there's no process reading the updated certificate.

This article breaks that loop into four layers and pins down whose job each layer is. The point of the split is to let you put a finger on where your own loop is breaking, before it actually breaks.

The point that matters most is this. cert-manager updates the Kubernetes Secret. It does not update the memory of the process that reads that Secret. The cert-manager documentation does not hide this boundary.

If your application only loads the private key and signed certificate once at start up, the new certificate
won't immediately be served by your application, and you will want to either manually restart your pod with
kubectl rollout restart, or automate the action by running Reloader.

Section 8 is built around that one sentence. Sections 2 through 7 detail who is responsible for what, leading up to this point.

2. Four Layers - Who Issues, Who Requests, Who Stores, and Who Reads

This article divides the certificate's journey inside the cluster into four layers. The layer names are this article's own scaffolding, not official AWS or Kubernetes terminology. Each layer, though, consists of officially defined components, and the documentation draws the boundaries between them.

  • Issuing Layer: This layer creates a certificate by signing it with a private key. The owner is AWS Private CA.
  • Requesting Layer: This layer decides when a certificate is needed and what it should say, then asks the issuing layer for it. The owners are cert-manager and aws-privateca-issuer.
  • Storing Layer: This layer puts the issued certificate and its private key somewhere inside the cluster. The owner is a Kubernetes Secret, or, for material that arrives from somewhere else, a CSI volume.
  • Consuming Layer: This layer reads what was stored and uses it in a TLS handshake. The owner is the workload process itself.

Four Layers of Certificate Delivery in a Kubernetes Cluster
Four Layers of Certificate Delivery in a Kubernetes Cluster
AWS is only responsible for the Issuing Layer. The Requesting Layer consists of controllers that run inside the cluster, and is not an AWS managed service. You can install it as an Amazon EKS add-on, which puts part of it inside the managed boundary, but what the add-on manages is installation and updates. AWS does not guarantee that the loop keeps turning. The Storing Layer and Consuming Layer sit entirely on the cluster side.

2.1 Two Families of Identifiers in One Article

Two families of identifiers with different origins run through this article. They are declared here so that later sections can lean on them.

Kubernetes-side custom resources: Issuer, ClusterIssuer, Certificate, AWSPCAIssuer, AWSPCAClusterIssuer, SecretProviderClass. These are the kinds of objects that live inside the cluster.

AWS-side API actions and policy names: acm-pca:IssueCertificate, acm-pca:GetCertificate, acm-pca:DescribeCertificateAuthority, eks:CreatePodIdentityAssociation, AWSPrivateCAConnectorForKubernetesPolicy. These are strings that IAM evaluates.

There's one point that may initially cause confusion. While the service is named AWS Private CA, the API namespace remains acm-pca:. This is a legacy from its previous name, AWS Certificate Manager Private Certificate Authority. Although it may appear inconsistent, these are official identifiers and should not be altered. Writing privateca:IssueCertificate in an IAM policy will not produce any effect.

2.2 The Word Issuer Carries Two Meanings

There's one linguistic point to be aware of. The word issuer carries two meanings: a certificate authority in the PKI sense, and the Issuer custom resource in cert-manager.

For the CA in the PKI sense, this article writes issuer in plain text.

In cert-manager, Issuer is an object that defines which CA to use and how to request certificates. This article always writes that one as Issuer, in monospace, and never translates it. ClusterIssuer is a version of this concept that spans namespaces; the cert-manager documentation states outright that an Issuer is confined to a single namespace. AWSPCAIssuer and AWSPCAClusterIssuer are external issuer types added by aws-privateca-issuer and belong to the API group awspca.cert-manager.io/v1beta1.

2.3 Separating Renewal, Rotation, and Reload

This article keeps three terms apart. Sections 8 and 9 are built upon this differentiation:

  • Renewal — Issuing a new certificate for the same purpose before the existing one expires. This is the responsibility of cert-manager.
  • Rotation — Replacing the contents of a Secret with the new material. Whether the private key is swapped along with it is a matter of configuration.
  • Reload — The process by which an active process reads in and begins using the replaced file. Nothing does this on its own.

3. The Issuing Layer - What AWS Private CA Guards, and What It Does Not

At the issuing layer, AWS Private CA takes on two things: protecting the CA's private key, and signing on request. The AWS Private CA User Guide describes the first of those as follows:

AWS Private CA has HSM backed keys that can't be exported.

The substance is in the phrase that the key cannot be exported. The CA's private key never leaves the hardware security module. Neither the operators, those who can log in to the console, nor AWS support can extract it. Compared to operating a self-signed CA, where the CA's private key might be stored in plain text within a Kubernetes Secret or on someone's laptop, this is a significant improvement.

It's crucial to understand this: AWS Private CA protects the CA's private key. It does not protect the private keys of the issued leaf certificates.

The leaf private key is generated inside the cluster by cert-manager. What cert-manager sends to AWS Private CA is a certificate signing request, and that request carries only the public key. The private key never travels along the signing path. cert-manager then puts that private key straight into a Kubernetes Secret. Therefore, the asset protected by the hardware security module and the asset actually used in TLS handshakes are two separate things. The former resides within AWS, while the latter is located within your cluster's etcd. Section 6 addresses the latter.

Bringing in AWS Private CA improves on self-signed certificates in three ways.

  • The CA's private key is out of reach. Compromising one CA no longer lets anyone forge every certificate under it.
  • AWS Private CA keeps the issuance records. You can show an auditor who issued what, and when.
  • AWS Private CA serves the revocation information. You no longer keep your own CRL and OCSP endpoints highly available.

However, it's important to note that the location and accessibility of the leaf private keys have not changed. A design document that says the keys became safe because the CA is now a private CA has to be stopped in review.

3.1 Where It Runs

The AWS Private CA User Guide states where aws-privateca-issuer can run. It can be used with Amazon EKS, self-managed Kubernetes clusters on AWS, and on-premises Kubernetes clusters. It supports both x86 and ARM architectures. Support for ARM was announced in a What's New post on July 18, 2024.

The fact that it runs outside Amazon EKS is what Section 5 turns on. When the cluster sits outside Amazon EKS, the way the connector obtains AWS credentials changes.

4. The Requesting Layer - cert-manager, aws-privateca-issuer, and Two Kinds of Add-on

The requesting layer consists of two components: cert-manager, which manages the certificate lifecycle, and aws-privateca-issuer, which bridges those requests to AWS Private CA.

The AWS Private CA User Guide says what the two of them do together in one sentence. It is the single most important primary source for the design in this article, and the destination it names is the part to read closely.

AWS Private CA provides an open source plugin, AWS Private CA Connector for Kubernetes,
(aws-privateca-issuer) for the widely adopted cert-manager add-on to Kubernetes that requests
certificates, distributes them to Kubernetes secrets, and automates certificate renewal.

Three verbs sit side by side: requesting, distributing to a Kubernetes secret, and automating renewal. It explicitly states that the destination is a Kubernetes secret. It does not mention distributing to Pods, nor does it mention distributing to applications. This single sentence covers the process from issuance to storage within this article's four layers, but it does not address the consuming layer.

4.1 Two Add-ons of Different Kinds

When deploying on Amazon EKS, there are two add-ons that are required. And these two add-ons are of different types.

cert-manager is a community add-on. It is listed on the Community add-ons page in the Amazon EKS User Guide. The add-on name is cert-manager, and the namespace is also cert-manager. The Managed IAM policy and Service account name are both listed as None. The AWS Containers Blog says that Amazon EKS packages, scans, and validates these add-ons for version compatibility and supports their lifecycle, while for core functionality support you keep engaging with the open source community.

aws-privateca-connector-for-kubernetes is an AWS add-on. While the add-on name is aws-privateca-connector-for-kubernetes, the namespace it is deployed in is aws-privateca-issuer. This discrepancy in names can cause issues when searching with kubectl. This add-on is designed to tolerate the CriticalAddonsOnly taint used by the system NodePool in EKS Auto Mode.

This add-on was added to the Amazon EKS add-on catalog on June 4, 2025. The What's New announcement describes the scope of its availability as follows:

This new Amazon EKS add-on is available in all commercial AWS Regions.

Commercial Regions was the qualifier at that point, so AWS GovCloud (US) and the China Regions sat outside it. On September 9, 2026, AWS announced the add-on for the AWS GovCloud (US-East) and AWS GovCloud (US-West) Regions. This line moves. Look it up again when you read this.

Outside of Amazon EKS, both add-ons can be installed using Helm. cert-manager uses the jetstack/cert-manager chart, and aws-privateca-issuer uses the awspca/aws-privateca-issuer chart.

4.2 What You Declare to Get a Certificate

You write two kinds of object in the requesting layer.

First, you create an issuer declaration, either AWSPCAClusterIssuer or AWSPCAIssuer. That declaration holds nothing but the Amazon Resource Name of the CA and its Region.

apiVersion: awspca.cert-manager.io/v1beta1
kind: AWSPCAClusterIssuer
metadata:
  name: aws-privateca-cluster-issuer
spec:
  arn: "arn:aws:acm-pca:region:account:certificate-authority/CA_ID"
  region: "aws-region"

Second, you create a declaration for the certificate itself, using cert-manager's Certificate resource. This declaration references the issuer (created above) using the issuerRef field and specifies the destination Secret using the secretName field.

apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: example-certificate
  namespace: default
spec:
  secretName: example-certificate-tls
  issuerRef:
    name: aws-privateca-cluster-issuer
    kind: AWSPCAClusterIssuer
    group: awspca.cert-manager.io
  commonName: example.internal
  dnsNames:
    - example.internal
    - api.example.internal
  duration: 2160h # 90 days
  renewBefore: 360h # 15 days
  usages:
    - digital signature
    - key encipherment
    - server auth

The key difference between this and built-in issuers is the group field required inside issuerRef. Because this is an external issuer, you need to tell cert-manager which API group to look in.

Notably, this declaration does not specify anything about the application that will use the certificate. The declaration reaches as far as secretName, which fixes the destination. Everything past that is a different conversation.

4.3 The Connector Needs Only Three AWS Permissions

The AWS managed policy you attach to aws-privateca-connector-for-kubernetes is AWSPrivateCAConnectorForKubernetesPolicy. It contains only three actions.

{
  "Version" : "2012-10-17",
  "Statement" : [
    {
      "Effect" : "Allow",
      "Action" : [
        "acm-pca:DescribeCertificateAuthority",
        "acm-pca:GetCertificate",
        "acm-pca:IssueCertificate"
      ],
      "Resource" : "arn:aws:acm-pca:*:*:certificate-authority/*"
    }
  ]
}

It carries nothing but permission to ask for issuance. It does not include permissions to revoke certificates, create the CA, or read Secrets. Kubernetes RBAC governs reading and writing Secrets, outside IAM. Section 6 picks that asymmetry up.

The Resource element wildcards both the account and the Region, which is the obvious place to narrow the scope when you copy this into a policy of your own. This managed policy was created on May 19, 2025, and updated on February 12, 2026. The default version is v3.

5. The Requesting Layer Has Its Own Credential, and It Expires Too

Everything so far has assumed that the requesting layer can reach AWS. That assumption is worth opening up. How it holds depends on whether the cluster is Amazon EKS.

5.1 On Amazon EKS - The Pod Identity Association

On Amazon EKS you use EKS Pod Identity. The principal in the role's trust policy is pods.eks.amazonaws.com, and the permitted actions are sts:AssumeRole and sts:TagSession.

{
  "Version":"2012-10-17",
  "Statement": [
    {
      "Sid": "TrustPolicyForEKSClusters",
      "Effect": "Allow",
      "Principal": {
        "Service": "pods.eks.amazonaws.com"
      },
      "Action": [
        "sts:AssumeRole",
        "sts:TagSession"
      ]
    }
  ]
}

You create the association together with the add-on. Use the aws eks create-addon command, passing the --pod-identity-associations parameter to bind the service account aws-privateca-issuer to the role's Amazon Resource Name. That is why the operator running the command needs eks:CreatePodIdentityAssociation.

This article does not discuss the decision between using Pod Identity and IRSA. That decision belongs to the published Amazon EKS Pod Identity and IRSA Decision Guide. What is stated here is only the fact that the connector add-on creates the Pod Identity association.

5.2 Off Amazon EKS - IAM Roles Anywhere and a One-Day Bootstrap Certificate

Outside of Amazon EKS, Pod Identity does not exist. The Get started page in the AWS Private CA User Guide gives a procedure that uses IAM Roles Anywhere instead. The trust policy for the role will have rolesanywhere.amazonaws.com as the principal, using aws:SourceArn to define the trust anchor and aws:PrincipalTag/x509Subject/CN to specify the certificate's common name.

And this is the core subject of this article: IAM Roles Anywhere uses certificates for authentication. The process involves issuing a single client certificate from the same private CA, storing it in a Kubernetes Secret, and making it readable by the rolesanywhere-credential-helper sidecar.

The Get started page pins the validity period of that one certificate like this.

--validity Value=1,Type=DAYS

It expires after one day. To stand up the machinery that distributes certificates, you create a certificate that lasts one day and place it by hand. The only logical conclusion is this: Follow the procedure and stop there, and the connector cannot call AWS the next day. And when the connector fails, any further certificate renewals will also stop. The symptoms of the expiration originate from the renewal mechanism itself.

The Get started page spells out the next step that prevents this:

If you are not using an Amazon EKS cluster, after you manually bootstrap a trusted certificate in
aws-privateca-issuer you can transition to a client authentication certificate managed by cert-manager.

Replace the manually created certificate with a Certificate managed by cert-manager, and subsequently allow cert-manager to handle renewals. The replacement configuration specifies a 168-hour validity period, initiates renewal 48 hours before expiration, and uses a rotationPolicy: Always for the private key. Since the output Secret name remains the same (aws-privateca-credentials), you do not need to modify the sidecar configuration.

The distribution mechanism itself is also the target of distribution. The four layers also apply to the connector's own credentials, mirroring the same process. And on this path the same question that Section 8 takes up, whether the sidecar rereads the updated Secret, shows up in the same shape.

This article does not discuss how to design the trust anchor for IAM Roles Anywhere. That topic belongs to the published AWS IAM Inbound Workload Federation.

6. The Storing Layer - The Certificate Lands in a Kubernetes Secret

The issued certificates and private keys are stored within a Kubernetes Secret, specified by the secretName field in the Certificate resource. The Secret type is kubernetes.io/tls, and according to the Kubernetes documentation, it requires two keys: tls.crt and tls.key. cert-manager may also include a ca.crt key.

According to cert-manager's documentation, if an intermediate CA issued the certificate and the issuer provides a certificate chain, the contents of tls.crt will include the certificate chain following the requested certificate. If the certificate authority is known, cert-manager stores the corresponding CA certificate in the Secret under the key ca.crt.

6.1 Who Can Read the Secret Is Decided Outside IAM

As Section 4.3 showed, the connector's IAM permissions say nothing about Secrets. Who can read a Secret is decided by Kubernetes RBAC.

This is where a note from the Kubernetes documentation becomes relevant.

Additionally, anyone who is authorized to create a Pod in a namespace can use that access to read any
Secret in that namespace; this includes indirect access such as the ability to create a Deployment.

Even if someone doesn't have direct permission to get a Secret, if they can create Pods within a particular namespace, they can read what is in the Secret by mounting it into a Pod. The same principle applies to those who can create Deployments. Which means the namespace holding the leaf private key for internal TLS is also a key store that everyone who can deploy into it can read.

The asymmetry named in Section 3 becomes concrete here. The CA's private key cannot be accessed, but anyone who can deploy into the namespace can read the leaf private key.

6.2 What Happens Inside etcd - Amazon EKS Has a Different Default

The Kubernetes documentation notes that, by default, Secrets are stored in the API server's datastore without encryption. However, this default does not apply to Amazon EKS.

The Amazon EKS User Guide states:

Amazon Elastic Kubernetes Service (Amazon EKS) provides default envelope encryption for all Kubernetes
API data in EKS clusters running Kubernetes version 1.28 or higher.

Amazon EKS encrypts that data with an AWS owned key by default, using AWS Key Management Service and the Kubernetes KMS provider v2. You can also configure it to use customer-managed keys. Previously, this only applied to Kubernetes Secrets, but now it extends to all Kubernetes API data.

The scope needs care here. The same page states what this encryption does not cover.

Envelope encryption does not apply to data on nodes or EBS volumes.

Even with encryption enabled, nothing in Section 6.1 changes. Encryption is not involved in the standard, authorized pathways for accessing data through the API server. Envelope encryption protects only the data that is stored. The existing permission model remains in place.

7. The Other Storing Path - What the Secrets Store CSI Driver Does Not Replace

Beyond Kubernetes Secrets, there are other options for storage. The Secrets Store CSI Driver mounts the contents of external secret stores as CSI inline volumes into Pods. The Secrets Store CSI Driver documentation describes it as a mechanism that allows Kubernetes to mount multiple secrets, keys, and certificates from external stores as volumes within Pods.

To be clear, this approach does not replace the path that cert-manager and aws-privateca-issuer take. The destination for data written by aws-privateca-issuer is always a Kubernetes Secret. The AWS provider for the Secrets Store CSI Driver fetches secrets from AWS Secrets Manager and parameters from AWS Systems Manager Parameter Store; it does not retrieve certificates from AWS Private CA. This approach is applicable only when the primary location for certificates is Secrets Manager. It cannot be used as an alternative to a configuration that relies on certificates issued by AWS Private CA.

Furthermore, if you are considering adding certificates to a cluster that already distributes secrets via CSI, you should be aware of the following three points.

7.1 Only the Mount Is Stable

The documentation splits the features into stable and alpha. The mount itself sits in the stable list. Portability via SecretProviderClass, mounting via CSI inline volumes, and mounting multiple secret store objects as a single volume are all listed as stable features.

Only two features are listed as alpha, and both are directly relevant to the topic of this article. These are automatic Kubernetes Secret rotation synchronized with the mount content, and synchronization with Kubernetes Secrets.

7.2 Auto Rotation Is Off by Default

The status of the automatic rotation feature is indicated as Secrets Store CSI Driver v0.0.15 [alpha]. The documentation clearly describes how to enable it.

NOTE: This alpha feature is not enabled by default. To enable auto rotation, set the
--enable-secret-rotation flag to true for the secrets-store container in the Secrets Store
CSI Driver pods.

The default value for --rotation-poll-interval is 2 minutes, which determines the minimum interval for reacquisition. From version 1.6.0 onwards the driver uses the CSI RequiresRepublish mechanism, and the documentation says outright that setting requiresRepublish: true on its own does not enable rotation.

7.3 The Reload Problem Survives This Path Too

The consuming layer's problem survives on this path in exactly the same shape. The documentation says the action you need depends on how the application consumes the secret, listing three scenarios. When using a mounted Kubernetes Secret as a volume, the application needs to monitor changes to the mounted volume. Similarly, when reading from the container's file system, the application must monitor file changes. And when the secret is consumed as an environment variable, the documentation is blunt.

Using Kubernetes secret for environment variable: The pod needs to be restarted to get the latest
secret as environment variable.

Other systems, different projects, and separate documentation have reached the same conclusion as cert-manager. Ultimately, the final step requires you to take action yourself.

8. The Consuming Layer - Where the Renewal Stops

This is the core of this article. cert-manager updates Secrets. No one updates the contents of the memory used by the processes that read those Secrets.

8.1 The Trigger for Renewal Is Time

First, pin down when the renewal runs. cert-manager computes the renewal time from the duration of the issued certificate and the value of renewBefore. The default duration is stated plainly.

Default value for spec.duration is 90 days.

By default the renewal time falls two-thirds of the way through the certificate's duration.

By default this will be 2/3 through the X.509 certificate's duration.

If you specify spec.renewBefore or spec.renewBeforePercentage, the renewal happens that far ahead of expiry. cert-manager writes the calculated time to the status.RenewalTime field of the Certificate resource. To find out when a renewal will run in your own configuration, read that field.

The minimum value for spec.duration is 1 hour, while the effective minimum value for spec.renewBefore is 5 minutes. spec.duration must be greater than spec.renewBefore. Furthermore, cert-manager recommends using a percentage-based value for renewBefore rather than an absolute time.

Using spec.renewBeforePercentage is recommended to prevent renewal loops in case the actual duration
is less than expected.

The reason is that an issuer may hand back a certificate with a shorter validity period than the one you asked for. cert-manager notes that some issuers are configured to issue only certificates with a set duration, so the actual duration may differ from the requested one. For example, if you specify an absolute time of 15 days before expiration, but the issued certificate has a validity period of only 10 days, the renewal condition is met the moment the certificate is issued, and the controller enters a renewal loop.

This condition specifically exists with AWS Private CA. A CA created in short-lived certificate mode only issues certificates with a maximum validity period of 7 days. Applying a Certificate resource with duration: 2160h and renewBefore: 360h to such a CA will result in the issuance of 7-day certificates, meaning the calculated renewal point of 15 days before expiration occurs before the certificate is even issued. The shortening of validity periods discussed in Section 9 is a change that moves in exactly the direction that creates this condition.

8.2 There Is a Gap Between the Secret and the File

When a Secret is updated, the files in every Pod mounting that Secret as a volume follow. However, this doesn't happen immediately. This is how the Kubernetes documentation puts it.

When a volume contains data from a Secret, and that Secret is updated, Kubernetes tracks this and
updates the data in the volume, using an eventually-consistent approach.

The maximum delay is the sum of the kubelet's synchronization period and the cache propagation delay. The default detection method is Watch, which can be modified using configMapAndSecretChangeDetectionStrategy.

However, there's one exception. This exception shows up as an ordinary way of writing a manifest. It does not look like a misconfiguration.

A container using a Secret as a subPath volume mount does not receive automated Secret updates.

Using subPath is appropriate when you want to insert only one file into an existing directory. The need to place a single certificate in a specific path is a very natural requirement. However, once you write it that way, that file will never be updated again. cert-manager keeps renewing, the Secret is replaced correctly, and only the file inside the Pod stays on the first certificate.

8.3 The File Changes, and the Process Does Not Reread It

Even if a file is updated, a potential issue remains. If a process only reads the file once at startup, it won't react even if the file changes.

Where a Renewal Stops Short of the Running Process
Where a Renewal Stops Short of the Running Process
The cert-manager documentation puts a condition on this. When using rotationPolicy: Always, cert-manager waits for the Certificate to be properly signed before overwriting the Secret's tls.key. It then explicitly states the conditions under which zero downtime can be expected.

With this setting, you can expect no downtime if your application can detect changes to the mounted
tls.crt and tls.key and reload them gracefully or automatically restart.

There is a conditional clause attached. It holds if the application can detect changes to the mounted tls.crt and tls.key and reload them. When it cannot, this is what the page says instead.

If your application only loads the private key and signed certificate once at start up, the new
certificate won't immediately be served by your application, and you will want to either manually
restart your pod with kubectl rollout restart, or automate the action by running Reloader.

You can manually trigger a kubectl rollout restart or automate this process using a tool like Reloader. The documentation describes Reloader as a Secret controller that restarts Deployments when a mounted Secret changes.

The last part needed to close the loop is the part you supply yourself. Neither cert-manager nor AWS Private CA handles this aspect. You must either ensure that the workload itself detects changes and reloads, or deploy a separate controller that monitors Secret changes and restarts Pods. A configuration that has neither is a loop that never closes.

8.4 Checking Whether Your Own Loop Is Closed

You can find out whether the loop is closed by working down this list, from the outermost layer to the innermost.

What to checkWhere to lookSign that the loop is open
Is a renewal scheduled at all?status.RenewalTime on the CertificateThe field is absent, or the renewal time falls after the expiry
Did the renewal actually run?Pull tls.crt out of the Secret and read its notAfterThe expiry has not moved even though the renewal time has passed
Did the file inside the Pod change?Read notAfter from the mounted file, inside the PodIt disagrees with the Secret, or the mount uses subPath
Did the process reread it?Look at the certificate presented in an actual handshakeIt disagrees with the file
Who makes the reread happen?A reload path in the application, or a controller watching the SecretNeither one exists

Only the last two rows escape every other check. Neither kubectl get certificate nor kubectl get secret looks there.

9. When Lifetimes Get Shorter, Which Layer Becomes the Bottleneck First

The pressure to shorten the validity period comes from the public Web PKI side. However, these regulations do not directly apply to private CAs. The history and timeline of the public side belong to TLS Certificate Ecosystem History and Timeline. This article covers only one question: when you decide to shorten the lifetime yourself, which of the four layers gives out first.

To state the conclusion upfront: the consuming layer will be the first to be constrained. The issuing, requesting, and storing layers scale roughly linearly as the frequency goes up. Only the consuming layer changes in kind.

9.1 The Issuing Layer - Only the Count Goes Up

Reducing the validity period from 90 days to 7 days would increase the number of calls to acm-pca:IssueCertificate by approximately 13 times. According to the AWS General Reference quota table, a single CA can issue 100,000,000 certificates per Region by default, and this value cannot be adjusted. However, this quota applies only when revocation is disabled, or when revocation is enabled through a partitioned CRL or OCSP. A CA with complete CRLs enabled draws on a separate quota of 1,000,000 certificates, one-hundredth of the first. API rate limits are also configured for each operation, and exceeding these limits will result in a ThrottlingException. The AWS Private CA User Guide states outright that AWS Private CA does not guarantee a minimum API request rate.

The choice of revocation method cuts the ceiling on issuance to one-hundredth, and that ceiling is what a shorter validity period pushes against. The design of the revocation method itself belongs to the published AWS Private CA Hierarchy Design. When you decide to shorten the lifetime, though, you have to look at both at once.

When primarily issuing certificates with a validity period of 7 days or less, AWS Private CA offers a CA mode called short-lived certificate mode. How to choose that mode and what it constrains belong to the published AWS Private CA Hierarchy Design. It's important to note that the CA mode is determined at the time of creation and cannot be changed later. If you plan to shorten the validity period, that decision must be made before creating the CA.

9.2 The Requesting Layer - Renewal Loops Become Easier to Enter

What is new in the requesting layer is the renewal loop from Section 8.1. As the validity period becomes shorter, the difference between the requested duration and the actual validity period issued becomes proportionally larger, making it more likely that the absolute time renewBefore will exceed the validity period. cert-manager recommends using spec.renewBeforePercentage, as this becomes increasingly effective with shorter validity periods.

Another mechanism is available for controlling renewal timing. cert-manager allows you to configure renewal windows using spec.renewal, which offers two policies: RenewBefore and Disabled. Disabled prevents automatic renewal of the Certificate. Renewal windows further restrict the timeframes in which renewals are permitted; they do not replace renewBefore or renewBeforePercentage. By limiting renewals to maintenance windows when the validity period is short, you can create configurations where the certificate expires before the renewal window becomes active.

9.3 The Storing Layer - The Delay Grows in Relative Terms

The delay between a Secret update and its arrival in the Pod's files is bounded by the kubelet sync period plus the cache propagation delay. This delay does not decrease even if the validity period is shortened. Tens of seconds against a 90-day validity period is nothing. Against a one-hour validity period it is not. Considering that the effective minimum value of renewBefore, as described in Section 8.1, is 5 minutes, it's important to assess the remaining margin.

9.4 The Consuming Layer - Frequency Changes the Kind of Problem

And now the consuming layer. A configuration that runs a 90-day validity period without implementing reload needs a Pod restart once every 90 days. If deployments land more often than every 90 days, an ordinary deployment doubles as that restart and the problem never surfaces. The reason it looks healthy is that deployments happen to arrive in time. It is not that the loop is closed.

Reducing the validity period to 7 days will eliminate this coincidence. Reducing it to 1 day will certainly eliminate it. What a shorter validity period breaks is the coincidence that had been hiding the missing piece. The piece was never there to begin with.

So the order in which you check things, before shortening the lifetime, runs against intuition. First, you should verify whether the workload can reread the certificate. AWS Private CA mode and issuance limits can be considered next. If the workload cannot reread the certificate, put in something like Reloader, or build certificate rereading into the application itself, before you shorten the validity period.

9.5 Revocation Does Not Help Here

Choosing a shorter validity period has one advantage: it eliminates the need to rely on certificate revocation. The AWS Private CA FAQ addresses the question of whether short-lived certificates should be revoked, answering no, and explains that the model rests on frequent reissuance to reaffirm health.

Conversely, configurations with longer validity periods necessitate reliance on certificate revocation. And revocation settles nothing across the four layers of this article. Even if a certificate is revoked, the certificates held by the consuming layer won't disappear from memory. Revocation is effective for the validating side; it doesn't work for the presenting side. The design of revocation itself belongs to the published AWS Private CA Hierarchy Design.

10. Where the Primary Sources Disagree

Cross-checking the primary sources for this article turned up two pairs of pages that say different things about the same fact. Both are official, and reading only one of them puts a wrong statement in your article.

10.1 The Default rotationPolicy in cert-manager

The cert-manager Certificate page carries a note about private key rotation that names the version. The note states that the default rotationPolicy changed in v1.18.0, and that from v1.18.0 onwards, Always is the default, resulting in automatic private key rotation. Prior to v1.18.0, Never was the default, and automatic rotation did not occur.

However, the table listing values later on the same page still shows Never with (default) and Always with (recommended) attached. The note is the newer of the two, and it is the one that names the version boundary.

This article avoids stating default values without specifying a version. If you want to verify this in your own cluster, it is best to explicitly set spec.privateKey.rotationPolicy. The Get started page quoted in Section 5.2 writes rotationPolicy: Always explicitly, which is one way of stepping around this ambiguity.

10.2 The Availability Status of Connector for SCEP

AWS Private CA offers three types of connectors: for Active Directory, for Kubernetes, and for SCEP. While this article focuses on the Kubernetes connector, the information regarding the SCEP connector's availability varies across different documentation.

The AWS Private CA documentation overview page and the console help panel both list the SCEP connector as being in Preview. The Connector for SCEP page in the AWS Private CA User Guide carries no such label.

Reading the announcements in order settles it. The Connector for SCEP was announced as a preview on June 11, 2024, and its general availability announcement went out on September 16, 2024. The announcement states that the connector is available in the AWS Regions where AWS Private CA is available, excluding AWS GovCloud (US) and China Regions.

So the Preview label is the older of the two. As of September 9, 2026 there is no reason to separate the three connectors by availability status. Labels like this drift because documentation updates lag, so check What's New when you read this.

11. Failure Modes and Anti-Patterns

11.1 Assuming That Installing cert-manager Finished the Job

This is the most common mistake. cert-manager automates only the request for issuance and the update of Secrets. It is not cert-manager's responsibility to ensure that the process reading the Secret rereads it. The primary source quoted in Section 8.3 says so. You need one of two things: a reread path in the application, or a controller that watches the Secret and restarts the Pod.

The easiest way to determine this is to examine your application's code and see where it reads the TLS certificate. If it reads the certificate once at startup and never again, the loop is not closed.

11.2 Reading a High Deployment Frequency as Proof That Nothing Is Wrong

This is the pattern from Section 9.4. In clusters where Pods are constantly being replaced with each deployment, the problem stays hidden even when reload is not implemented. The absence of symptoms is not evidence that the loop is closed. Problems typically emerge after deployment pauses, such as during holiday periods, or during change freeze periods.

11.3 Confusing the CA Private Key with the Leaf Private Key

The sentence that the private key is protected by a hardware security module because AWS Private CA is in the picture is true of the CA's private key, and of nothing else. The leaf private keys are stored within Kubernetes Secrets and are accessible to anyone who can create Pods within that namespace. The primary source quoted in Section 6.1 says so. The design document has to say that the protected asset and the asset in use are two different things.

11.4 Mounting with subPath and Cutting Off Updates

This is the pattern from Section 8.2. A volume mount that uses subPath does not receive automatic Secret updates. This is not a bug but the documented behavior, stated outright in the Kubernetes documentation. The mistake gets in through a natural requirement: put one certificate file, and only that file, into an existing directory.

You can identify this configuration by looking for subPath under volumeMounts in your Pod manifest.

11.5 Shortening the Lifetime and Falling into a Renewal Loop

This is the pattern from Sections 8.1 and 9.2. If you shorten the validity period while leaving renewBefore as an absolute duration, then whenever the issued certificate is shorter than requested, the renewal condition is met the moment the certificate is issued. cert-manager recommends using spec.renewBeforePercentage. The transition to a shorter validity period and the change to specifying renewBefore as a percentage should be treated as a single, unified change.

11.6 Going Live Off Amazon EKS on the One-Day Bootstrap Certificate

This is the pattern from Section 5.2. The first certificate the Get started page has you create carries a one-day validity period. Depending on where the process is stopped, the connector may fail to connect to AWS the following day. Make the move to a cert-manager-managed Certificate part of the definition of done for the build.

The symptoms are difficult to detect. When the connector stops functioning, all other certificate renewals will silently cease. Furthermore, the fact that it has stopped may not become apparent until the expiration date is reached.

11.7 Building on an Alpha Feature as Though It Were Generally Available

This is the pattern from Section 7. The Secrets Store CSI Driver documentation marks both Kubernetes Secret synchronization and automatic rotation as alpha, and automatic rotation is off unless you turn it on. If you design certificate renewal pathways based on these two features, nothing will function in clusters left with their default settings.

11.8 Making the Renewal Window Too Narrow

This is the pattern from Section 9.2. A renewal window restricts the hours in which a renewal is allowed to happen. If you point a short-lived certificate at a monthly maintenance period and nothing else, the certificate expires before the window opens. A renewal window is a constraint layered on top of renewBefore. It does not stand in for renewBefore.

11.9 Mixing Up the Add-on Name and the Namespace

This is the pattern from Section 4.1. The add-on's name is aws-privateca-connector-for-kubernetes, while its namespace is aws-privateca-issuer. Because these do not match, kubectl get pods -n aws-privateca-connector-for-kubernetes will return an empty result. Furthermore, cert-manager is a community add-on, whereas the connector is an AWS add-on, resulting in different support channels.

11.10 Writing privateca as the Namespace in an IAM Policy

This is the pattern from Section 2.1. While the service name is AWS Private CA, the API action remains acm-pca:. Policies written with privateca:IssueCertificate will pass syntax checks, but will not grant any permissions.

12. Frequently Asked Questions

Will cert-manager renew certificates automatically?

It renews the certificate and writes the new one into the Secret. Whether a running process picks that up is a separate question. The cert-manager documentation states that if an application loads the private key and the signed certificate only once at start up, the new certificate is not served immediately. You either run kubectl rollout restart by hand, or put in a controller that watches the Secret and restarts the Deployment.

If I use AWS Private CA, are my private keys secure?

Regarding the CA's private key, yes. The AWS Private CA User Guide states that the keys used by AWS Private CA are backed by a hardware security module and cannot be exported. However, the leaf private keys actually used during TLS handshakes are stored in a Kubernetes Secret within your cluster, and anyone who can create Pods in that namespace can read them. The assets being protected and the assets being used are distinct.

Where are the certificates stored?

In a Kubernetes Secret. The AWS Private CA User Guide states that the plugin requests the certificate, distributes it to a Kubernetes secret, and automates certificate renewal. The type is kubernetes.io/tls, and it contains tls.crt and tls.key. If the issuer can provide a chain, tls.crt will contain the certificate with the chain appended. If the Certificate Authority is identifiable, ca.crt may also be included.

If I use the Secrets Store CSI Driver, does this path become unnecessary?

No. aws-privateca-issuer always writes to a Kubernetes Secret. The AWS provider for the Secrets Store CSI Driver fetches data from AWS Secrets Manager and AWS Systems Manager Parameter Store, but not from AWS Private CA. While it can be an option if your configuration stores certificates in AWS Secrets Manager, it cannot replace a configuration that issues certificates from AWS Private CA.

When does a renewal run?

By default, this occurs after two-thirds of the certificate's validity period has passed. If you specify spec.renewBefore or spec.renewBeforePercentage, the renewal time is adjusted accordingly. cert-manager writes the calculated renewal time to the Certificate's status.RenewalTime, allowing you to verify the actual renewal time within your configuration.

Can it be used with clusters other than Amazon EKS?

Yes. The AWS Private CA User Guide states that it can be used with Amazon EKS, self-managed Kubernetes clusters on AWS, and on-premises Kubernetes clusters. However, the method for obtaining AWS credentials changes; it uses EKS Pod Identity with Amazon EKS, and IAM Roles Anywhere for other clusters. With the latter, you will need to manage the client certificate for the connector itself.

What can be saved by installing it as an add-on on Amazon EKS?

The add-on takes over installation and version management, and it creates the Pod Identity association for you. When you pass --pod-identity-associations to aws eks create-addon, Amazon EKS creates the binding between the service account and the role for you. This eliminates the need for manual Helm installation and IAM configuration. However, because cert-manager is a community add-on, the level of support provided by AWS is not the same.

How can you tell if certificate renewal has stopped?

Work through the five rows of Section 8.4 in order. Compare the renewal time written to the Certificate's status.RenewalTime, the expiration date of the Secret's contents, the expiry on the file inside the Pod, and the certificate presented during an actual handshake. Finally, check whether anything at all triggers the reload. Many configurations only monitor the first two points, so even if renewal has stopped, the monitoring system may remain green, and the certificate will expire.

Is it okay to shorten the validity period?

Yes, as long as your workload can reread the certificate. If it cannot, shortening the validity period only shortens a tightrope walk that depends on how often you deploy. The correct order is to implement certificate rereading first, and then shorten the validity period.

If you revoke the certificate, will the old certificate stop working?

For the side doing the validation, yes. For the side presenting it, no: the certificate a running process is already holding does not disappear when you revoke it. The AWS Private CA FAQ states that due to the model of frequent reissuance used for short-lived certificates, they should not be revoked. The design of revocation itself belongs to the published AWS Private CA Hierarchy Design.

What happens when you mount using subPath?

The file will stop being updated. The Kubernetes documentation states that containers using Secrets with a subPath volume mount will not receive automatic Secret updates. cert-manager keeps renewing, the Secret gets replaced, and only the file inside the Pod stays on the first certificate.

Is the Connector for SCEP in preview?

No. AWS announced general availability on September 16, 2024. The AWS Private CA documentation overview page and the console help panel still carry the Preview label, but What's New and the User Guide show the newer state. This was confirmed as of September 9, 2026.

13. Summary

The route a certificate takes into a cluster splits into four layers. AWS Private CA handles the issuing layer, cert-manager and aws-privateca-issuer handle the requesting layer, and a Kubernetes Secret is the storing layer. The consuming layer has an owner too, the workload process. What it does not have is anything that makes that process read the new certificate.

AWS Private CA protects the CA's private key. The leaf private keys used in TLS handshakes are stored within Kubernetes Secrets, and are readable by anyone who can create Pods within that namespace. On Amazon EKS running Kubernetes 1.28 or higher, envelope encryption is on by default, but that changes the state of the data at rest and nothing about who is allowed to read it.

By default, cert-manager runs the renewal two-thirds of the way through the validity period and replaces the Secret. The file inside the Pod follows, but with a delay bounded by the kubelet sync period plus the cache propagation delay. If you are using subPath, this synchronization will not occur. Even when the files do synchronize, processes that read the certificate only once at startup will continue to use the old certificate.

This final layer requires you to design your own solution. You must either ensure that your application detects changes and reloads, or implement a controller that monitors the Secret and restarts the Pod. A configuration with neither of them leaves the loop open.

An open loop stays out of sight for as long as deployments keep landing often. Shortening the certificate validity period will expose this issue. Therefore, you should only shorten the validity period after you have implemented a mechanism for detecting and responding to changes. Reverse that order and things break right after you shorten it.

Outside of Amazon EKS, there is one additional layer. The connector itself authenticates using IAM Roles Anywhere, and those credentials are also provided as certificates. The initial certificate that AWS instructs you to create has a validity period of only one day, and moving it under cert-manager management is where the documented procedure ends. The mechanism for distribution is itself a subject of distribution.

A certificate is not the only thing inside a cluster that carries an expiry date. The operating system the nodes run carries one as well, and the dates that govern it are collected in Amazon Linux History and Timeline. What separates the two is who is left holding the replacement. Here a controller performs it on a schedule. There, nothing moves until someone rebuilds the instance.

14. References

Related Articles



References:
Tech Blog with curated related content

Written by Hidekazu Konishi