mirror of https://github.com/knative/docs.git
234 lines
7.0 KiB
Markdown
234 lines
7.0 KiB
Markdown
# Configuring Knative and CertManager for Google Cloud DNS
|
|
|
|
These instructions assume you have already setup a Knative cluster and
|
|
installed cert-manager into your cluster. For more information, see [using an
|
|
SSL certificate](using-an-ssl-cert.md#install-cert-manager). They also assume
|
|
you have already set up your managed zone with Cloud DNS as part of
|
|
configuring the domain to map to your IP address.
|
|
|
|
To automate the generation of a certificate with cert-manager and LetsEncrypt,
|
|
we will use a `DNS01` challenge type, which requires the domain owner to add a TXT record
|
|
to their zone to prove ownership. Other challenge types are not currently supported by
|
|
Knative.
|
|
|
|
## Creating a Cloud DNS service account
|
|
To add the TXT record, configure Knative with a service account
|
|
that can be used by cert-manager to create and update the DNS record.
|
|
|
|
To begin, create a new service account with the project role `dns.admin`:
|
|
|
|
```shell
|
|
# Set this to your GCP project ID
|
|
export PROJECT_ID=<your-project-id>
|
|
|
|
# Name of the service account you want to create.
|
|
export CLOUD_DNS_SA=cert-manager-cloud-dns-admin
|
|
gcloud --project $PROJECT_ID iam service-accounts \
|
|
create $CLOUD_DNS_SA \
|
|
--display-name "Service Account to support ACME DNS-01 challenge."
|
|
|
|
# Fully-qualified service account name also has project-id information.
|
|
export CLOUD_DNS_SA=$CLOUD_DNS_SA@$PROJECT_ID.iam.gserviceaccount.com
|
|
|
|
# Bind the role dns.admin to this service account, so it can be used to support
|
|
# the ACME DNS01 challenge.
|
|
gcloud projects add-iam-policy-binding $PROJECT_ID \
|
|
--member serviceAccount:$CLOUD_DNS_SA \
|
|
--role roles/dns.admin
|
|
|
|
# Download the secret key file for your service account.
|
|
gcloud iam service-accounts keys create ~/key.json \
|
|
--iam-account=$CLOUD_DNS_SA
|
|
```
|
|
|
|
After obtaining the service account secret, publish it to your cluster.
|
|
This command uses the secret name `cloud-dns-key`, but you can
|
|
choose a different name.
|
|
|
|
```shell
|
|
# Upload that as a secret in your Kubernetes cluster.
|
|
kubectl create secret --namespace cert-manager generic cloud-dns-key \
|
|
--from-file=key.json=$HOME/key.json
|
|
|
|
# Delete the local secret
|
|
rm ~/key.json
|
|
|
|
```
|
|
|
|
## Configuring CertManager to use your DNS admin service account
|
|
|
|
Next, configure cert-manager to request new certificates and
|
|
verify the challenges using DNS.
|
|
|
|
### Specifying a certificate issuer
|
|
|
|
This example configures cert-manager to use LetsEncrypt, but you can
|
|
use any certificate provider that supports the ACME protocol.
|
|
|
|
This example uses the `dns01` challenge type, which will
|
|
enable certificate generation and wildcard certificates.
|
|
|
|
```shell
|
|
kubectl apply --filename - <<EOF
|
|
apiVersion: certmanager.k8s.io/v1alpha1
|
|
kind: ClusterIssuer
|
|
metadata:
|
|
name: letsencrypt-issuer
|
|
namespace: cert-manager
|
|
spec:
|
|
acme:
|
|
server: https://acme-v02.api.letsencrypt.org/directory
|
|
# This will register an issuer with LetsEncrypt. Replace
|
|
# with your admin email address.
|
|
email: myemail@gmail.com
|
|
privateKeySecretRef:
|
|
# Set privateKeySecretRef to any unused secret name.
|
|
name: letsencrypt-issuer
|
|
dns01:
|
|
providers:
|
|
- name: cloud-dns-provider
|
|
clouddns:
|
|
# Set this to your GCP project-id
|
|
project: $PROJECT_ID
|
|
# Set this to the secret that we publish our service account key
|
|
# in the previous step.
|
|
serviceAccountSecretRef:
|
|
name: cloud-dns-key
|
|
key: key.json
|
|
EOF
|
|
|
|
```
|
|
|
|
To check if your ClusterIssuer is valid, enter:
|
|
|
|
```shell
|
|
kubectl get clusterissuer --namespace cert-manager letsencrypt-issuer --output yaml
|
|
```
|
|
|
|
Then confirm that its conditions have `Ready=True`. For example:
|
|
|
|
```yaml
|
|
status:
|
|
acme:
|
|
uri: https://acme-v02.api.letsencrypt.org/acme/acct/40759665
|
|
conditions:
|
|
- lastTransitionTime: 2018-08-23T01:44:54Z
|
|
message: The ACME account was registered with the ACME server
|
|
reason: ACMEAccountRegistered
|
|
status: "True"
|
|
type: Ready
|
|
```
|
|
|
|
### Specifying the certificate
|
|
|
|
Next, configure which certificate issuer to use
|
|
and which secret you will publish the certificate into. Use the Secret `istio-ingressgateway-certs`.
|
|
The following steps will overwrite this Secret if it already exists.
|
|
|
|
```shell
|
|
# Change this value to the domain you want to use.
|
|
export DOMAIN=your-domain.com
|
|
|
|
kubectl apply --filename - <<EOF
|
|
apiVersion: certmanager.k8s.io/v1alpha1
|
|
kind: Certificate
|
|
metadata:
|
|
name: my-certificate
|
|
# Istio certs secret lives in the istio-system namespace, and
|
|
# a cert-manager Certificate is namespace-scoped.
|
|
namespace: istio-system
|
|
spec:
|
|
# Reference to the Istio default cert secret.
|
|
secretName: istio-ingressgateway-certs
|
|
acme:
|
|
config:
|
|
# Each certificate could rely on different ACME challenge
|
|
# solver. In this example we are using one provider for all
|
|
# the domains.
|
|
- dns01:
|
|
provider: cloud-dns-provider
|
|
domains:
|
|
# Since certificate wildcards only allow one level, we will
|
|
# need to one for every namespace that Knative is used in.
|
|
# We don't need to use wildcard here, fully-qualified domains
|
|
# will work fine too.
|
|
- "*.default.$DOMAIN"
|
|
- "*.other-namespace.$DOMAIN"
|
|
# The certificate common name, use one from your domains.
|
|
commonName: "*.default.$DOMAIN"
|
|
dnsNames:
|
|
# Provide same list as `domains` section.
|
|
- "*.default.$DOMAIN"
|
|
- "*.other-namespace.$DOMAIN"
|
|
# Reference to the ClusterIssuer we created in the previous step.
|
|
issuerRef:
|
|
kind: ClusterIssuer
|
|
name: letsencrypt-issuer
|
|
EOF
|
|
```
|
|
|
|
To check that your certificate setting is valid, enter:
|
|
|
|
```shell
|
|
kubectl get certificate --namespace istio-system my-certificate --output yaml
|
|
```
|
|
|
|
Verify that its `Status.Conditions` have `Ready=True`. For example:
|
|
```yaml
|
|
status:
|
|
acme:
|
|
order:
|
|
url: https://acme-v02.api.letsencrypt.org/acme/order/40759665/45358362
|
|
conditions:
|
|
- lastTransitionTime: 2018-08-23T02:28:44Z
|
|
message: Certificate issued successfully
|
|
reason: CertIssued
|
|
status: "True"
|
|
type: Ready
|
|
```
|
|
A condition with `Ready=False` is a failure to obtain certificate, and such
|
|
condition usually has an error message to indicate the reason of failure.
|
|
|
|
### Configuring the gateway
|
|
|
|
In the last step, configure the knative-shared-gateway to use the certificate
|
|
that is generated and stored automatically by cert-manager.
|
|
|
|
The key edit here is adding the `tls:` section to the end of the HTTPS port
|
|
configuration.
|
|
|
|
```shell
|
|
kubectl apply --filename - <<EOF
|
|
apiVersion: networking.istio.io/v1alpha3
|
|
kind: Gateway
|
|
metadata:
|
|
name: knative-shared-gateway
|
|
namespace: knative-serving
|
|
spec:
|
|
selector:
|
|
knative: ingressgateway
|
|
servers:
|
|
- port:
|
|
number: 80
|
|
name: http
|
|
protocol: HTTP
|
|
hosts:
|
|
- "*"
|
|
- port:
|
|
number: 443
|
|
name: https
|
|
protocol: HTTPS
|
|
hosts:
|
|
- "*"
|
|
tls:
|
|
httpsRedirect: true # sends 301 redirect for http requests.
|
|
mode: SIMPLE
|
|
privateKey: /etc/istio/ingressgateway-certs/tls.key
|
|
serverCertificate: /etc/istio/ingressgateway-certs/tls.crt
|
|
EOF
|
|
```
|
|
|
|
Now you can access your services via HTTPS; cert-manager will keep your certificates
|
|
up-to-date, replacing them before the certificate expires.
|
|
|