背景: GKEのProduction環境でのIngressはTLSの認証書を発行し、自動更新したい
必要な環境変数:
export GCLOUD_PROJECT="$(gcloud config get-value project)"
export MY_DOMAIN=example.com
export CERT_MANAGER_GCP_SA=cert-manager
export CERT_MANAGER_GKE_SA=clouddns-service-account
export CERT_MANAGER_NS=cert-manager
export ACME_EMAIL=admin@example.com
export CERTIFICATE_NAME=example-com
export CLUSTER_ISSUER_NAME=letsencrypt-prod
手順:
#####I. Google Account と GKE Secretの設定
- CloudDNS にて
${MY_DOMAIN}
のA recordを設定する - GCPのIAMにて
${CERT_MANAGER_GCP_SA}
と呼ばれるService Accountを作る - kubectlで
${CERT_MANAGER_GKE_SA}
と呼ばれるsecretを作る.このsecretのNamespace必ずcert-manager自体のNamespace${CERT_MANAGER_NS}
一致することが重要!
#####II.Cert-Manager 自体をinstallする
#####III.Certificateを生成する為にClusterIssuer を作る
#####IV. Certificateを発行する.
(spec.issuerRef.kind
を指定しないと ${CLUSTER_ISSUER_NAME}
のcluster issuerが見つからない。)
===================================================================
I. Google Account と GKE Secretの設定
gcloud iam service-accounts create ${CERT_MANAGER_GCP_SA} --display-name "cert-manager"
gcloud projects add-iam-policy-binding ${GCLOUD_PROJECT} --member serviceAccount:${CERT_MANAGER_GCP_SA}@${GCLOUD_PROJECT}.iam.gserviceaccount.com --role roles/dns.admin
gcloud iam service-accounts keys create ${CERT_MANAGER_GCP_SA}-key.json --iam-account ${CERT_MANAGER_GCP_SA}@${GCLOUD_PROJECT}.iam.gserviceaccount.com
####The secret namespace must be the same as cert-manager#####
kubectl create secret generic ${CERT_MANAGER_GKE_SA} --from-file=${CERT_MANAGER_GCP_SA}-key.json=${CERT_MANAGER_GCP_SA}-key.json -n ${CERT_MANAGER_NS}
II. Cert-Manager 自体をinstallする
export VER_CERT_MANAGER=v0.7.0
# Install the CustomResourceDefinition resources separately
kubectl apply -f https://raw.githubusercontent.com/jetstack/cert-manager/release-0.7/deploy/manifests/00-crds.yaml
# Create the namespace for cert-manager
kubectl create namespace ${CERT_MANAGER_NS}
# Label the cert-manager namespace to disable resource validation
kubectl label namespace ${CERT_MANAGER_NS} certmanager.k8s.io/disable-validation=true
# Add the Jetstack Helm repository
helm repo add jetstack https://charts.jetstack.io
# Update your local Helm chart repository cache
helm repo update
# Install the cert-manager Helm chart
helm install \
--name cert-manager \
--namespace ${CERT_MANAGER_NS} \
--version ${VER_CERT_MANAGER} \
jetstack/cert-manager
######## Verify the installation(Optional)########
# Create a ClusterIssuer to test the webhook works okay
cat <<EOF > test-resources.yaml
apiVersion: v1
kind: Namespace
metadata:
name: cert-manager-test
---
apiVersion: certmanager.k8s.io/v1alpha1
kind: Issuer
metadata:
name: test-selfsigned
namespace: cert-manager-test
spec:
selfSigned: {}
---
apiVersion: certmanager.k8s.io/v1alpha1
kind: Certificate
metadata:
name: selfsigned-cert
namespace: cert-manager-test
spec:
commonName: example.com
secretName: selfsigned-cert-tls
issuerRef:
name: test-selfsigned
EOF
# Create the test resources
kubectl apply -f test-resources.yaml
kubectl describe certificate -n cert-manager-test
kubectl delete -f test-resources.yaml
################################################
III. Certificateを生成する為にCluster Issuerの作成
######Create ClusterIssuer######
kubectl apply -f - << EOF
apiVersion: certmanager.k8s.io/v1alpha1
kind: ClusterIssuer
metadata:
name: ${CLUSTER_ISSUER_NAME}
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
# Email address used for ACME registration
email: ${ACME_EMAIL}
# Name of a secret used to store the ACME account private key
privateKeySecretRef:
name: letsencrypt-prod-pk
# Enable the HTTP-01 challenge provider
http01: {}
# ACME dns-01 provider configurations
dns01:
# Here we define a list of DNS-01 providers that can solve DNS challenges
providers:
- name: prod-clouddns
clouddns:
# A secretKeyRef to a the google cloud json service account
serviceAccountSecretRef:
name: ${CERT_MANAGER_GKE_SA}
key: ${CERT_MANAGER_GCP_SA}-key.json
# The project in which to update the DNS zone
project: ${GCLOUD_PROJECT}
EOF
kubectl describe ClusterIssuer
IV. Certificateを発行する(Let’s EncryptのACME v2)
######Create Certificate Using ClusterIssuer######
kubectl apply -f - <<EOF
apiVersion: certmanager.k8s.io/v1alpha1
kind: Certificate
metadata:
name: ${CERTIFICATE_NAME}
namespace: default
spec:
secretName: cert-manager-tls
issuerRef:
name: ${CLUSTER_ISSUER_NAME}
#The kind should be refered explicitly
kind: ClusterIssuer
commonName: ${MY_DOMAIN}
dnsNames:
- ${MY_DOMAIN}
acme:
config:
- dns01:
provider: prod-clouddns
domains:
- ${MY_DOMAIN}
EOF
kubectl describe certificate
kubectl get clusterissuer,certificate,order,challenge --all-namespaces=true
非常にいい参考になるページ
1.Cert-Manager
2.Cluster Issuer
3.GKE で TLS 証明書を自動管理(cert-manager DNS-01 編)
4.Let’s EncryptのACME v2