Skip to main content
Version: main 🚧

cert-manager

Limited vCluster Tenancy Configuration Support

This feature is only available when using the following worker node types:

  • Host Nodes
  • Enterprise-Only Feature

    This feature is an Enterprise feature. See our pricing plans or contact our sales team for more information.

    You can integrate cert-manager with your virtual cluster to manage TLS certificates across host and virtual environments.

    Prerequisites​

    • Administrator access to a Kubernetes cluster: See Accessing Clusters with kubectl for more information. Your current kube-context must have administrative privileges, which you can verify with kubectl auth can-i create clusterrole -A

      info

      To obtain a kube-context with admin access, ensure you have the necessary credentials and permissions for your Kubernetes cluster. This typically involves using kubectl config commands or authenticating through your cloud provider's CLI tools.

    • helm installed: Helm v3.10 is required for deploying the platform. Refer to the Helm Installation Guide if you need to install it.

    • kubectl installed: Kubernetes command-line tool for interacting with the cluster. See Install and Set Up kubectl for installation instructions.

    Enable the integration​

    Enable cert-manager integration in your virtual cluster configuration:

    Enable cert-manager integration
    integrations:
    certManager:
    enabled: true

    This configuration enables the integration and configures automatic resource sync:

    • Imports: Cluster-scoped ClusterIssuers from your host cluster into the virtual cluster
    • Exports: Namespaced Issuers and Certificates from the virtual cluster to the host cluster
    • Syncs: Generated certificate secrets back to the virtual cluster automatically

    Set up cluster contexts​

    Create or update a virtual cluster following the vCluster quick start guide. Configure cluster contexts to simplify switching between host and virtual clusters:

    export HOST_CTX="your-host-context"
    export VCLUSTER_CTX="vcluster-ctx"
    Find your contexts

    Run kubectl config get-contexts to list available contexts.

    Certificate issuer configurations​

    Choose the appropriate certificate issuer based on your security and operational requirements.

    Self-signed certificates for development

    Self-signed certificates work well for development environments and internal services that don't require public trust.

    1. Virtual Cluster Create a self-signed issuer

      self-signed-issuer.yaml
      apiVersion: cert-manager.io/v1
      kind: Issuer
      metadata:
      name: selfsigned-issuer
      namespace: default
      spec:
      selfSigned: {}

      Apply the issuer:

      Apply self-signed issuer
      kubectl --context=$VCLUSTER_CTX apply -f self-signed-issuer.yaml
    2. Virtual Cluster Create a certificate

      self-signed-certificate.yaml
      apiVersion: cert-manager.io/v1
      kind: Certificate
      metadata:
      name: app-tls-cert
      namespace: default
      spec:
      secretName: app-tls-secret
      duration: 2160h # 90 days
      renewBefore: 360h # 15 days
      commonName: myapp.local
      dnsNames:
      - myapp.local
      - api.myapp.local
      privateKey:
      algorithm: RSA
      size: 2048
      issuerRef:
      name: selfsigned-issuer
      kind: Issuer

      Apply the certificate:

      Apply certificate
      kubectl --context=$VCLUSTER_CTX apply -f self-signed-certificate.yaml
    warning

    Self-signed certificates generate browser warnings and should not be used in production environments accessible to external users.

    Private PKI for enterprise environments

    Private PKI configurations provide enterprise-grade certificate management with custom certificate authorities.

    1. Host Cluster Create a root CA certificate

      Create a self-signed root CA in the host cluster (ClusterIssuers are imported from host to virtual cluster):

      root-ca.yaml
      apiVersion: cert-manager.io/v1
      kind: ClusterIssuer
      metadata:
      name: selfsigned-issuer
      spec:
      selfSigned: {}
      ---
      apiVersion: cert-manager.io/v1
      kind: Certificate
      metadata:
      name: root-ca-cert
      namespace: cert-manager
      spec:
      isCA: true
      commonName: "Enterprise Root CA"
      subject:
      organizations:
      - "Enterprise Corp"
      organizationalUnits:
      - "IT Security"
      countries:
      - "US"
      secretName: root-ca-secret
      duration: 87600h # 10 years
      renewBefore: 78840h # 9 years
      privateKey:
      algorithm: ECDSA
      size: 256
      issuerRef:
      name: selfsigned-issuer
      kind: ClusterIssuer

      Apply in the host cluster:

      Apply root CA in host cluster
      kubectl --context=$HOST_CTX apply -f root-ca.yaml
    2. Host Cluster Create a CA issuer

      ca-issuer.yaml
      apiVersion: cert-manager.io/v1
      kind: ClusterIssuer
      metadata:
      name: enterprise-ca-issuer
      spec:
      ca:
      secretName: root-ca-secret

      Apply in the host cluster:

      Apply CA issuer in host cluster
      kubectl --context=$HOST_CTX apply -f ca-issuer.yaml
    3. Virtual Cluster Issue certificates from your CA

      ca-signed-certificate.yaml
      apiVersion: cert-manager.io/v1
      kind: Certificate
      metadata:
      name: enterprise-app-cert
      namespace: default
      spec:
      secretName: enterprise-app-tls
      duration: 8760h # 1 year
      renewBefore: 720h # 30 days
      commonName: myapp.enterprise.local
      dnsNames:
      - myapp.enterprise.local
      - api.myapp.enterprise.local
      subject:
      organizations:
      - "Enterprise Corp"
      organizationalUnits:
      - "Application Services"
      usages:
      - digital signature
      - key encipherment
      - server auth
      issuerRef:
      name: enterprise-ca-issuer
      kind: ClusterIssuer

      Apply in the virtual cluster:

      Apply certificate in virtual cluster
      kubectl --context=$VCLUSTER_CTX apply -f ca-signed-certificate.yaml

    Security considerations:

    • Store root CA private keys securely and offline when possible
    • Implement proper certificate lifecycle management
    • Monitor certificate expiration dates
    • Establish clear revocation procedures
    ACME for public-facing services

    ACME (Automatic Certificate Management Environment) issuers like Let's Encrypt provide free, automatically-renewed certificates for public-facing services.

    1. Virtual Cluster Create an ACME issuer

      acme-issuer.yaml
      apiVersion: cert-manager.io/v1
      kind: Issuer
      metadata:
      name: letsencrypt-prod
      namespace: default
      spec:
      acme:
      email: admin@yourdomain.com
      server: https://acme-v02.api.letsencrypt.org/directory
      privateKeySecretRef:
      name: letsencrypt-prod-account-key
      solvers:
      - http01:
      ingress:
      ingressClassName: nginx
      - dns01:
      cloudflare:
      email: admin@yourdomain.com
      apiKeySecretRef:
      name: cloudflare-api-key-secret
      key: api-key
    2. Virtual Cluster Create an ACME certificate

      acme-certificate.yaml
      apiVersion: cert-manager.io/v1
      kind: Certificate
      metadata:
      name: public-app-cert
      namespace: default
      spec:
      secretName: public-app-secret
      duration: 2160h # 90 days
      renewBefore: 720h # 30 days
      dnsNames:
      - myapp.example.com
      - api.myapp.example.com
      issuerRef:
      name: letsencrypt-prod
      kind: Issuer

    Rate limits: Let's Encrypt enforces rate limits. Use staging environment (https://acme-staging-v02.api.letsencrypt.org/directory) for testing.

    PKI for compliance requirements

    PKI configurations require specific certificate formats and validation procedures for compliance with standards.

    gov-compliant-certificate.yaml
    apiVersion: cert-manager.io/v1
    kind: Certificate
    metadata:
    name: gov-service-cert
    namespace: default
    spec:
    secretName: gov-service-secret
    duration: 8760h # 1 year maximum
    renewBefore: 2160h # 90 days
    commonName: service.application.1234567890
    subject:
    organizations:
    - "Organization"
    organizationalUnits:
    - "PKI"
    - "CONTRACTOR"
    countries:
    - "US"
    usages:
    - digital signature
    - key encipherment
    - server auth
    privateKey:
    algorithm: RSA
    size: 2048 # Federal minimum requirement
    issuerRef:
    name: gov-pki-issuer
    kind: ClusterIssuer

    Compliance requirements:

    • Use hierarchical 3-tier CA structure
    • Include specific Distinguished Name fields
    • Maintain Certificate Revocation Lists (CRLs)
    • Follow Federal PKI Certificate Policy guidelines

    Verify certificate creation​

    Check that your certificates generate correctly:

    1. Virtual Cluster Check certificate status

      Verify certificate creation
      kubectl --context=$VCLUSTER_CTX describe certificate <certificate-name> -n <namespace>

      Look for Ready: True in the status conditions.

    2. Virtual Cluster Verify secret creation

      Check certificate secret
      kubectl --context=$VCLUSTER_CTX get secret <secret-name> -n <namespace> -o yaml

      Confirm the secret contains tls.crt and tls.key data.

    3. Host Cluster Confirm synchronization

      Check host cluster resources
      kubectl --context=$HOST_CTX get certificate,issuer -A

      Verify resources appear in the host cluster namespace.

    Use certificates in applications​

    Reference your certificate secrets in Ingress resources:

    secure-ingress.yaml
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    name: secure-app-ingress
    annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
    spec:
    tls:
    - hosts:
    - myapp.example.com
    secretName: your-tls-secret # Use the secretName from your Certificate
    rules:
    - host: myapp.example.com
    http:
    paths:
    - path: /
    pathType: Prefix
    backend:
    service:
    name: app-service
    port:
    number: 80
    tip

    Replace your-tls-secret with the actual secretName specified in your Certificate resource (e.g., app-tls-secret, enterprise-app-tls, or public-app-secret from the examples above).

    Troubleshooting​

    Certificate creation issues

    Check certificate status:

    kubectl --context=$VCLUSTER_CTX describe certificate <name>

    Common problems:

    • Pending status: Check CertificateRequest events
    • Failed validation: Verify DNS/HTTP challenge accessibility
    • Rate limiting: Switch to staging ACME server for testing

    Examine certificate requests:

    kubectl --context=$VCLUSTER_CTX get certificaterequests
    kubectl --context=$VCLUSTER_CTX describe certificaterequest <name>
    Integration synchronization problems

    Verify integration status:

    Host Cluster
    Check cert-manager installation
    kubectl --context=$HOST_CTX -n cert-manager get pods
    kubectl --context=$HOST_CTX -n cert-manager logs deployment/cert-manager
    Virtual Cluster
    Verify integration configuration
    # Check if integration is enabled
    kubectl --context=$VCLUSTER_CTX get configmap vcluster-config -o yaml

    # Check resource synchronization
    kubectl --context=$VCLUSTER_CTX get events --field-selector reason=Sync

    Common synchronization issues:

    • RBAC permissions missing on host cluster
    • Network policies blocking communication
    • Resource naming conflicts between clusters
    ACME challenge failures

    For detailed troubleshooting of ACME challenges:

    Check challenge status:

    kubectl --context=$VCLUSTER_CTX describe order <order-name>
    kubectl --context=$VCLUSTER_CTX describe challenge <challenge-name>

    For comprehensive ACME troubleshooting, including HTTP-01 and DNS-01 challenge issues, see the cert-manager ACME troubleshooting guide.

    For troubleshooting guidance, see the cert-manager troubleshooting documentation.

    Advanced configuration​

    Custom sync configurations

    Fine-tune resource synchronization behavior:

    Advanced cert-manager integration
    integrations:
    certManager:
    enabled: true
    sync:
    toHost:
    certificates:
    enabled: true
    issuers:
    enabled: true
    fromHost:
    clusterIssuers:
    enabled: true
    selector:
    labels:
    vcluster.loft.sh/managed: "true"
    resyncInterval: 30s

    Configuration options:

    • resyncInterval: How often to check for resource changes
    • selector: Filter which ClusterIssuers to import
    • Individual resource type controls for granular sync management

    Configuration reference​

    certManager required object ​

    CertManager reuses a host cert-manager and makes its CRDs from it available inside the vCluster.

    • Certificates and Issuers will be synced from the virtual cluster to the host cluster.
    • ClusterIssuers will be synced from the host cluster to the virtual cluster.

    enabled required boolean false ​

    Enabled defines if this option should be enabled.

    sync required object ​

    Sync contains advanced configuration for syncing cert-manager resources.

    toHost required object ​

    certificates required object ​

    Certificates defines if certificates should get synced from the virtual cluster to the host cluster.

    enabled required boolean true ​

    Enabled defines if this option should be enabled.

    issuers required object ​

    Issuers defines if issuers should get synced from the virtual cluster to the host cluster.

    enabled required boolean true ​

    Enabled defines if this option should be enabled.

    fromHost required object ​

    clusterIssuers required object ​

    ClusterIssuers defines if (and which) cluster issuers should get synced from the host cluster to the virtual cluster.

    enabled required boolean true ​

    Enabled defines if this option should be enabled.

    selector required object ​

    Selector defines what cluster issuers should be imported.

    labels required object {} ​

    Labels defines what labels should be looked for

    Config reference​