新訊:在TwitterMastodon取得專案更新

已註解的 Gateway 資源

apiVersion: gateway.networking.k8s.io/v1
kind: Gateway

功能狀態:cert-manager 1.15 [beta]

📌 此頁面重點在透過註解 Kubernetes Gateway 資源自動建立 Certificate 資源。如果您正在尋找搭配 Kubernetes Gateway API 使用 ACME Issuer 以及 HTTP-01 挑戰,請參閱ACME HTTP-01

🚧 cert-manager 1.14+ 已使用 v1 Kubernetes Gateway API 進行測試。它也應該能與 v1beta1 和 v1alpha2 搭配運作,因為有資源轉換,但尚未進行測試。

cert-manager 可以為 Gateway 資源產生 TLS 憑證。這是透過將註解新增至 Gateway 來設定,類似於保護 Ingress 資源的程序。

Gateway 資源是 Gateway API 的一部分,它是一組您安裝在 Kubernetes 叢集上的 CRD,並且提供比 Ingress API 更豐富的各種改進。

Gateway 資源會保留 TLS 設定,如下圖所示(來源:https://gateway-api.sigs.k8s.io

Gateway vs. HTTPRoute

📌 此功能需要安裝 Gateway API 套件,並將額外的旗標傳遞至 cert-manager 控制器。

若要安裝 v1.5.1 Gateway API 套件(Gateway CRD 和 webhook),請執行以下命令

kubectl apply -f "https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.0.0/standard-install.yaml"

從 cert-manager 1.15 開始,Gateway API 支援不再受功能旗標限制,但您仍然需要啟用 Gateway API 支援。

若要啟用 Gateway API 支援,請使用 基於檔案的組態,並使用下列 config Helm 值

config:
apiVersion: controller.config.cert-manager.io/v1alpha1
kind: ControllerConfiguration
enableGatewayAPI: true

對應的 Helm 命令為

helm upgrade --install cert-manager jetstack/cert-manager --namespace cert-manager \
--set config.apiVersion="controller.config.cert-manager.io/v1alpha1" \
--set config.kind="ControllerConfiguration" \
--set config.enableGatewayAPI=true

Gateway API CRD 應該在 cert-manager 啟動之前安裝,或者應該在安裝 Gateway API CRD 之後重新啟動 cert-manager Deployment。這很重要,因為某些 cert-manager 元件只會在啟動時執行 Gateway API 檢查。您可以使用以下命令重新啟動 cert-manager

kubectl rollout restart deployment cert-manager -n cert-manager

註解 cert-manager.io/issuercert-manager.io/cluster-issuer 會告知 cert-manager 為 Gateway 建立 Certificate。例如,下列 Gateway 將觸發建立名為 example-com-tls 的 Certificate

apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: example
annotations:
cert-manager.io/issuer: foo
spec:
gatewayClassName: foo
listeners:
- name: http
hostname: example.com
port: 443
protocol: HTTPS
allowedRoutes:
namespaces:
from: All
tls:
mode: Terminate
certificateRefs:
- name: example-com-tls

稍後,cert-manager 將建立 Certificate。Certificate 會以 Secret 名稱 example-com-tls 命名。dnsNames 欄位會設定為 Gateway spec 中的 hostname 欄位。

apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: example-com-tls
spec:
issuerRef:
name: my-issuer
kind: Issuer
group: cert-manager.io
dnsNames:
- example.com # ✅ Copied from the `hostname` field.
secretName: example-com-tls

🚧 此機制只能用來在與 Gateway 相同的命名空間中建立 Secret,請參閱 cert-manager#5610

使用案例

為選定的 TLS 區塊產生 TLS 憑證

cert-manager 會跳過任何無法用於產生 Certificate 的監聽器區塊。若要使用監聽器區塊來建立 Certificate,它必須符合下列需求

欄位需求
tls.hostname不得為空。
tls.mode必須設定為 TerminatePassthrough 不受支援。
tls.certificateRef.name不得留空。
tls.certificateRef.kind如果指定,必須設定為 Secret
tls.certificateRef.group如果指定,必須設定為 core
tls.certificateRef.namespace如果指定,必須與 Gateway 相同。

在以下範例中,前四個監聽器區塊將不會用於產生 Certificate 資源

apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: my-gateway
namespace: default
annotations:
cert-manager.io/issuer: my-issuer
spec:
gatewayClassName: foo
listeners:
# ❌ Missing "tls" block, the following listener is skipped.
- name: example-1
port: 80
protocol: HTTP
hostname: example.com
# ❌ Missing "hostname", the following listener is skipped.
- name: example-2
port: 443
protocol: HTTPS
tls:
certificateRefs:
- name: example-com-tls
kind: Secret
group: ""
# ❌ "mode: Passthrough" is not supported, the following listener is skipped.
- name: example-3
hostname: example.com
port: 8443
protocol: HTTPS
tls:
mode: Passthrough
certificateRefs:
- name: example-com-tls
kind: Secret
group: ""
# ❌ Cross-namespace secret references are not supported, the following listener is skipped.
- name: example-4
hostname: foo.example.com
port: 8443
protocol: HTTPS
allowedRoutes:
namespaces:
from: All
tls:
mode: Terminate
certificateRefs:
- name: example-com-tls
kind: Secret
group: ""
namespace: other-namespace
# ✅ The following listener is valid.
- name: example-5
hostname: bar.example.com # ✅ Required.
port: 8443
protocol: HTTPS
allowedRoutes:
namespaces:
from: All
tls:
mode: Terminate # ✅ Required. "Terminate" is the only supported mode.
certificateRefs:
- name: example-com-tls # ✅ Required.
kind: Secret # ✅ Optional. "Secret" is the only valid value.
group: "" # ✅ Optional. "" is the only valid value.

cert-manager 已跳過前四個監聽器區塊,並為最後一個監聽器區塊建立一個名為 example-com-tls 的 Certificate

apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: example-com-tls
spec:
issuerRef:
name: my-issuer
kind: Issuer
group: cert-manager.io
dnsNames:
- foo.example.com
secretName: example-com-tls

兩個具有相同 Secret 名稱的監聽器

相同的 Secret 名稱可以在多個 TLS 區塊中重複使用,而不論主機名稱為何。讓我們想像一下,您有這兩個監聽器

apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: example
annotations:
cert-manager.io/issuer: my-issuer
spec:
gatewayClassName: foo
listeners:
# Listener 1.
- name: example-1
hostname: example.com
port: 443
protocol: HTTPS
tls:
mode: Terminate
certificateRefs:
- name: example-com-tls
# Listener 2: Same Secret name as Listener 1, with a different hostname.
- name: example-2
hostname: "*.example.com"
port: 443
protocol: HTTPS
tls:
mode: Terminate
certificateRefs:
- name: example-com-tls
# Listener 3: also same Secret name, except the hostname is also the same.
- name: example-3
hostname: "*.example.com"
port: 8443
protocol: HTTPS
tls:
mode: Terminate
certificateRefs:
- name: example-com-tls
# Listener 4: different Secret name.
- name: example-4
hostname: site.org
port: 443
protocol: HTTPS
tls:
mode: Terminate
certificateRefs:
- name: site-org-tls

cert-manager 將建立兩個 Certificate,因為使用了兩個 Secret 名稱:example-com-tlssite-org-tls。請注意,Certificate 的 dnsNames 對於監聽器 2 和 3 包含一個 *.example.com hostname 值會被刪除重複項)。

這兩個 Certificate 看起來像這樣

apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: example-com-tls
spec:
issuerRef:
name: my-issuer
kind: Issuer
group: cert-manager.io
dnsNames:
- example.com # From listener 1.
- *.example.com # From listener 2 and 3.
secretName: example-com-tls
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: site-org-tls
spec:
issuerRef:
name: my-issuer
kind: Issuer
group: cert-manager.io
dnsNames:
- site.org # From listener 4.
secretName: site-org-tls

支援的註解

如果您要從 Ingress 資源移轉到 Gateway 資源,請注意Ingress 資源的註解與 Gateway 資源的註解之間存在一些差異。

Gateway 資源支援下列用於產生 Certificate 資源的註解

  • cert-manager.io/issuer:要取得此 Gateway 所需憑證的 Issuer 名稱。Issuer必須與 Gateway 資源位於相同的命名空間中。

  • cert-manager.io/cluster-issuer:要取得此 Gateway 所需 Certificate 的 ClusterIssuer 名稱。您的 Gateway 所在的命名空間並不重要,因為 ClusterIssuers 是非命名空間資源。

  • cert-manager.io/issuer-kind:外部簽發者資源的種類,例如 AWSPCACIssuer。這僅適用於樹外簽發者。

  • cert-manager.io/issuer-group:外部簽發者控制器的 API 群組,例如 awspca.cert-manager.io。這僅適用於樹外簽發者。

  • cert-manager.io/common-name:(選用)此註解可讓您設定要產生之 Certificate 的 spec.commonName

  • cert-manager.io/email-sans:(選用)此註解可讓您設定要產生之 Certificate 的 spec.emailAddresses 欄位。支援逗號分隔值,例如「me@example.com,you@example.com

  • cert-manager.io/subject-organizations:(選用)此註解可讓您設定要產生之 Certificate 的 spec.subject.organizations 欄位。支援逗號分隔值,例如「公司 1、公司 2」

  • cert-manager.io/subject-organizationalunits:(選用)此註解可讓您設定要產生之 Certificate 的 spec.subject.organizationalUnits 欄位。支援逗號分隔值,例如「IT 服務、雲端服務」

  • cert-manager.io/subject-countries:(選用)此註解可讓您設定要產生之 Certificate 的 spec.subject.countries 欄位。支援逗號分隔值,例如「國家 1、國家 2」

  • cert-manager.io/subject-provinces:(選用)此註解可讓您設定要產生之 Certificate 的 spec.subject.provinces 欄位。支援逗號分隔值,例如「省份 1、省份 2」

  • cert-manager.io/subject-localities: (選用) 此註釋允許您設定要產生的憑證的 spec.subject.localities 欄位。支援以逗號分隔的值,例如 "City 1,City 2"

  • cert-manager.io/subject-postalcodes: (選用) 此註釋允許您設定要產生的憑證的 spec.subject.postalCodes 欄位。支援以逗號分隔的值,例如 "123ABC,456DEF"

  • cert-manager.io/subject-streetaddresses: (選用) 此註釋允許您設定要產生的憑證的 spec.subject.streetAddresses 欄位。支援以逗號分隔的值,例如 "123 Example St,456 Other Blvd"

  • cert-manager.io/subject-serialnumber: (選用) 此註釋允許您設定要產生的憑證的 spec.subject.serialNumber 欄位。支援以逗號分隔的值,例如 "10978342379280287615,1111144445555522228888"

  • cert-manager.io/duration: (選用) 此註釋允許您設定要產生的憑證的 spec.duration 欄位。

  • cert-manager.io/renew-before: (選用) 此註釋允許您設定要產生的憑證的 spec.renewBefore 欄位。

  • cert-manager.io/usages: (選用) 此註釋允許您設定要產生的憑證的 spec.usages 欄位。傳遞一個以逗號分隔的值的字串,例如 "金鑰協商,數位簽章,伺服器驗證"

  • cert-manager.io/revision-history-limit: (選用) 此註釋允許您設定 spec.revisionHistoryLimit 欄位,以限制要為憑證保留的 CertificateRequests 數量。最小值為 1。如果未設定,則將保留所有 CertificateRequests。

  • cert-manager.io/private-key-algorithm: (選用) 此註釋允許您設定 spec.privateKey.algorithm 欄位,以設定憑證的私鑰產生演算法。有效值為 RSAECDSAEd25519。如果未設定,則將使用 RSA 演算法。

  • cert-manager.io/private-key-encoding: (選用) 此註釋允許您設定 spec.privateKey.encoding 欄位,以設定憑證的私鑰產生編碼。有效值為 PKCS1PKCS8。如果未設定,則將使用 PKCS1 演算法。

  • cert-manager.io/private-key-size: (選用) 此註釋允許您設定 spec.privateKey.size 欄位,以設定憑證的私鑰大小。如果演算法設定為 RSA,則有效值為 204840968192,如果未指定,則預設為 2048。如果演算法設定為 ECDSA,則有效值為 256384521,如果未指定,則預設為 256。如果演算法設定為 Ed25519,則會忽略大小。

  • cert-manager.io/private-key-rotation-policy: (選用) 此註釋允許您設定 spec.privateKey.rotationPolicy 欄位,以設定憑證私鑰的輪換策略。有效值為 NeverAlways。如果未設定,則將使用 Never 的輪換策略。

開發人員的內部運作圖

[1] https://cert-manager.dev.org.tw/docs/usage/certificate