Managing TLS Termination via Ingress Spec
One of the most valuable features of Ingress is its ability to handle TLS (Transport Layer Security) termination. This means the Ingress Controller can terminate the encrypted HTTPS connection from the external client, process the routing rules based on the decrypted HTTP request (host, path), and then forward the traffic to your backend Services/Pods, typically over unencrypted HTTP within the cluster network.
This significantly simplifies application development:
Your application containers don't need to handle TLS certificates or encryption/decryption.
TLS certificate management (renewal, deployment) is centralized at the Ingress layer.
Configuration for TLS termination is done directly within the Ingress resource's spec.tls section.
The spec.tls Section Revisited
As briefly introduced earlier, spec.tls is a slice of networkingv1.IngressTLS objects. Each entry in this slice associates one or more hostnames with a Kubernetes Secret containing the necessary TLS certificate and private key.
// Go struct definition snippet
type IngressSpec struct {
// ... other fields like IngressClassName, Rules ...
TLS []IngressTLS `json:"tls,omitempty" protobuf:"bytes,3,rep,name=tls"`
}
type IngressTLS struct {
// Hosts are a list of hosts included in the TLS certificate. The values in
// this list must match the name/s used in the tlsSecret. Defaults to the
// wildcard host setting for the loadbalancer controller fulfilling this
// Ingress, if left unspecified.
Hosts []string `json:"hosts,omitempty" protobuf:"bytes,1,rep,name=hosts"`
// SecretName is the name of the secret used to terminate TLS traffic on
// port 443. Field is left optional to allow TLS routing based on SNI
// headers, if the ingress controller supports SNI.
SecretName string `json:"secretName,omitempty" protobuf:"bytes,2,opt,name=secretName"`
}Hosts([]string): Specifies which hostnames listed in the Ingress rules this particular TLS configuration applies to. The TLS handshake will only succeed if the hostname requested by the client is listed here (and matches the certificate's Common Name (CN) or Subject Alternative Names (SANs)). IfHostsis omitted, the certificate inSecretNamemight be used as a default/fallback certificate by some Ingress controllers.SecretName(string): The name of the Kubernetes Secret that holds the certificate (tls.crt) and private key (tls.key). Crucially, this Secret MUST exist in the same namespace as the Ingress resource.
The TLS Secret (kubernetes.io/tls)
The Secret referenced by SecretName is not just any Secret; it must adhere to specific requirements:
Type: The Secret's
typemust bekubernetes.io/tls.Data Keys: It must contain two specific keys in its
datafield:tls.crt: The value must be the base64-encoded server certificate (and potentially intermediate certificates concatenated).tls.key: The value must be the base64-encoded private key corresponding to the certificate.
You typically create such Secrets using kubectl create secret tls <secret-name> --cert=/path/to/cert.pem --key=/path/to/key.pem -n <namespace> or by defining them in YAML.
Adding TLS Configuration Programmatically
Adding or modifying the spec.tls section in your Go code follows the same principles as managing rules. You construct or modify the []networkingv1.IngressTLS slice within your Ingress struct before calling Create or Update.
Let's adapt the update example from the previous section. Suppose we want to ensure the app.example.com host in our example-ingress uses the TLS secret app-tls-secret.
Explanation:
Find/Add Logic: We iterate through the existing
spec.TLSslice.Check Secret: We look for an entry matching the desired
SecretName.Check Host: If the secret entry exists, we check if our target
Hostis already listed. If not, we append it to theHostsslice of that entry.Add New Entry: If no entry for the
SecretNameexists, we create a newnetworkingv1.IngressTLSstruct and append it to thespec.TLSslice.Conditional Update: We introduce flags (
ruleUpdated,tlsNeedsUpdate) to track if we actually made any changes. We only callingressClient.Updateif a modification occurred, preventing unnecessary API calls and potential conflicts.
Prerequisites and Considerations:
Secret Existence: The referenced Secret (
app-tls-secret) must exist in the same namespace before the Ingress Controller tries to use it. Creating the Ingress resource itself doesn't create the Secret.Secret Permissions: The Ingress Controller's Service Account needs RBAC permissions (usually
get,list,watch) for Secrets in the namespaces it manages Ingress resources for.Certificate Management: Directly managing TLS Secrets via
kubectlorclient-gois feasible for a few certificates, but it quickly becomes complex to handle renewals. Tools like cert-manager are commonly used in Kubernetes to automate the issuance and renewal of TLS certificates (e.g., from Let's Encrypt) and automatically create/update the necessarykubernetes.io/tlsSecrets. Your Go code would then just reference theSecretNamemanaged by cert-manager.
Programmatically managing the spec.tls section allows you to automate the configuration of secure external access for your applications, ensuring that the correct certificates are associated with the right hostnames as defined in your Ingress rules.
Last updated
Was this helpful?