KubernetesやOpenShift向けのTLS認証を自動化するポッド。Ingress-nginxポッドとセットで利用します(minikube)。
$ kubectl apply -f https://github.com/cert-manager/cert-manager/releases/latest/download/cert-manager.yaml
minikubeでIngressをインストール(アドオンを有効化)
$ minikube addons enable ingress
各ポッドの確認
$ kubectl get pod -A
NAMESPACE NAME READY STATUS RESTARTS AGE
cert-manager cert-manager-6468fc8f56-r49lz 0/1 ContainerCreating 0 18s
cert-manager cert-manager-cainjector-7fd85dcc7-w8wv2 1/1 Running 0 18s
cert-manager cert-manager-webhook-57df45f686-xq5xx 0/1 Running 0 18s
ingress-nginx ingress-nginx-admission-create-vbdbs 0/1 Completed 0 22m
ingress-nginx ingress-nginx-admission-patch-jrvlt 0/1 Completed 0 22m
ingress-nginx ingress-nginx-controller-67c5cb88f-p4c87 1/1 Running 0 22m
kube-system coredns-674b8bbfcf-pjstq 1/1 Running 0 27m
kube-system etcd-minikube 1/1 Running 0 27m
kube-system kindnet-mb8jv 1/1 Running 0 27m
kube-system kube-apiserver-minikube 1/1 Running 0 27m
kube-system kube-controller-manager-minikube 1/1 Running 0 27m
kube-system kube-proxy-wxjc7 1/1 Running 0 27m
kube-system kube-scheduler-minikube 1/1 Running 0 27m
kube-system storage-provisioner 1/1 Running 1 (27m ago) 27m
Cloudflare + Let’s Encrypt : DNS-01チャレンジ
KubernetesにAPIトークンをシークレットとして保存
cert-managerはsecretを探す際、以下のルールで動作
-
ClusterIssuer
を使っている場合:secret は
cert-manager
のNamespace(通常はcert-manager
)に作成する必要があります。これはClusterIssuer
が「クラスタ全体で共有」されるため、Namespace に依存しないリソースだからです。 -
Issuer
を使っている場合:secret は、その
Issuer
が存在するNamespace
に作成する必要があります。
$ kubectl create secret generic cloudflare-api-token-secret \
--from-literal=api-token='YOUR_CLOUDFLARE_API_TOKEN' -n cert-manager
ClusterIssuerの作成
cluster-issuer.yaml
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-dns
spec:
acme:
email: [email protected]
server: https://acme-v02.api.letsencrypt.org/directory
privateKeySecretRef:
name: letsencrypt-dns-private-key
solvers:
- dns01:
cloudflare:
email: [email protected]
apiTokenSecretRef:
name: cloudflare-api-token-secret
key: api-token
適用
$ kubectl apply -f cluster-issuer.yaml
Apacheポット(Deployment+Service)を用意
apache-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: apache
spec:
replicas: 1
selector:
matchLabels:
app: apache
template:
metadata:
labels:
app: apache
spec:
containers:
- name: apache
image: httpd:alpine
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: apache-service
spec:
selector:
app: apache
ports:
- protocol: TCP
port: 80
targetPort: 80
適用
$ kubectl apply -f apache-deployment.yaml
Certificateリソースの作成(TLS証明書)
注01) このファイルは手動で認証取得する場合の設定で、以下のIngressで自動取得する設定をした場合には必要ありません。
annotations:
cert-manager.io/cluster-issuer: letsencrypt-dns
certificate.yaml
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: wildcard-cert
namespace: default
spec:
secretName: wildcard-cert-tls
issuerRef:
name: letsencrypt-dns
kind: ClusterIssuer
commonName: example.com
dnsNames:
- example.com
- '*.example.com'
適用
$ kubectl apply -f certificate.yaml
Ingressの作成(TLSと統合)
ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress
annotations:
kubernetes.io/ingress.class: nginx
cert-manager.io/cluster-issuer: letsencrypt-dns
spec:
tls:
- hosts:
- example.com
- www.example.com
secretName: wildcard-cert-tls
rules:
- host: example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: my-service
port:
number: 80
適用
$ kubectl apply -f ingress.yaml
実行順序
$ kubectl create secret generic cloudflare-api-token-secret \
--from-literal=api-token='YOUR_CLOUDFLARE_API_TOKEN' -n cert-manager
$ kubectl apply -f cluster-issuer.yaml
clusterissuer.cert-manager.io/letsencrypt-dns created
$ kubectl apply -f certificate.yaml ### 注01)参照
certificate.cert-manager.io/wildcard-cert created ### 注01)参照
$ kubectl apply -f ingress.yaml
Warning: annotation "kubernetes.io/ingress.class" is deprecated, please use 'spec.ingressClassName' instead
ingress.networking.k8s.io/my-ingress created
TLS認証リソースの確認
$ kubectl get certificate
NAME READY SECRET AGE
wildcard-cert-tls True wildcard-cert-tls 177m
TLS認証リソース詳細
$ kubectl get certificate wildcard-cert-tls -n default -o yaml
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
creationTimestamp: "2025-06-07T05:36:44Z"
generation: 1
name: wildcard-cert-tls
namespace: default
ownerReferences:
- apiVersion: networking.k8s.io/v1
blockOwnerDeletion: true
controller: true
kind: Ingress
name: my-ingress
....
....
....
Secretから証明書と秘密鍵を抽出
$ kubectl get secret wildcard-cert-tls -n default -o jsonpath="{.data['tls\.crt']}" | base64 -d > tls.crt
$ kubectl get secret wildcard-cert-tls -n default -o jsonpath="{.data['tls\.key']}" | base64 -d > tls.key
証明書の中身を確認(対象ドメインは Subject Alternative Name
として示されます)
$ openssl x509 -in tls.crt -text -noout
.....
.....
X509v3 Subject Alternative Name:
DNS:sub1.example.com, DNS:sub2.example.com, DNS:sub3.example.com
.....
.....