cert-managerはTLSの証明書を自動で生成し管理するK8sのアドオン。 Istioにも含まれていて、これを使ってLet’s Encryptで証明書を生成しGatewayに設定することでHTTPS対応することができる。
デフォルトではcert-managerは入らないのでenabled=trueにしてインストールする。 最初に入るLet’s EncryptのClusterIssuerはエラーになったので消す。
IstioをHelmでインストールしてRoutingとTelemetryを行いJaeger/Kialiで確認する - sambaiz-net
$ helm install install/kubernetes/helm/istio --name istio --namespace istio-system --set certmanager.enabled=true
$ kubectl delete ClusterIssuer --all
確認用にBookInfoを動かす。
$ kubectl label namespace default istio-injection=enabled
$ kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml
$ kubectl apply -f samples/bookinfo/networking/bookinfo-gateway.yaml
Let’s Encryptで使われているACMEプロトコルのドメイン認証(Challenge)には
/.well-known/acme-challenge/{token}
でHTTPレスポンスを返すHTTP Challenge(http-01)と
DNSのTXTレコードに書き込むDNS Challenge(dns-01)がある。
HTTP Challengeは手軽に達成できる一方、CAからアクセスできるようにする必要がある。今回はDNS Challengeでやる。
cert-managerはCloud DNSやRoute53などに対応していて、今回はCloudflareを使う。
DNSに書き込めるようにするためCloudflareのMy ProfileからGlobal API Keyを持ってきてBase64デコードしSecretに入れる。
改行コードが含まれないように-n
を付ける。
$ echo -n ***** | base64
apiVersion: v1
kind: Secret
metadata:
name: cloudflare-api-key
namespace: istio-system
type: Opaque
data:
api-key: *****
Let’s EncryptのClusterIssuerと証明書を生成するドメインのCertificateを作成する。 serverのURLはStatusのページから確認できる。 本番のURLはレート制限があるので、まずはFakeの証明書が生成されるstgで試すとよい。
証明書を書くsecretNameはistio-system
ネームスペースのistio-ingressgateway-certs
にする必要がある。
apiVersion: certmanager.k8s.io/v1alpha1
kind: ClusterIssuer
metadata:
name: letsencrypt-dns01
namespace: istio-system
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: [email protected]
privateKeySecretRef:
name: letsencrypt-dns01
dns01:
providers:
- name: cloudflare
cloudflare:
email: [email protected]
apiKeySecretRef:
name: cloudflare-api-key
key: api-key
---
apiVersion: certmanager.k8s.io/v1alpha1
kind: Certificate
metadata:
name: xxx-example-com
namespace: istio-system
spec:
secretName: istio-ingressgateway-certs
issuerRef:
name: letsencrypt-dns01
kind: ClusterIssuer
commonName: xxx.example.com
dnsNames:
- xxx.example.com
acme:
config:
- dns01:
provider: cloudflare
domains:
- xxx.example.com
これをapplyするとcertmanagerのログが流れ始める。何か間違いがあるとエラーになるのでなんとかする。
$ kubectl -n istio-system logs -f $(kubectl -n istio-system get pods -l app=certmanager -o jsonpath='{.items[0].metadata.name}')
証明書と秘密鍵のSecretはこんな感じ。
$ kubectl describe secret istio-ingressgateway-certs -n istio-system
Name: istio-ingressgateway-certs
Namespace: istio-system
Labels: <none>
Annotations: certmanager.k8s.io/alt-names=xxx.example.com
certmanager.k8s.io/common-name=xxx.example.com
certmanager.k8s.io/issuer-kind=ClusterIssuer
certmanager.k8s.io/issuer-name=letsencrypt-dns01
Type: kubernetes.io/tls
Data
====
tls.key: 1675 bytes
tls.crt: 3805 bytes
ingressgateway-certs
は自動で/etc/istio/ingressgateway-certs
にマウントされる。
このGatewayをapplyするとHTTPでアクセスした場合はリダイレクトし、HTTPSで正常にアクセスできるようになる。
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: bookinfo-gateway
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- xxx.example.com
tls:
httpsRedirect: true
- port:
number: 443
name: https
protocol: HTTPS
hosts:
- xxx.example.com
tls:
mode: SIMPLE
serverCertificate: /etc/istio/ingressgateway-certs/tls.crt
privateKey: /etc/istio/ingressgateway-certs/tls.key