[GKE] ingress-nginx配下のwebサーバ用のSSL証明書をcert-managerで付与してSSL化→Redirect込み
GKE(Google Kubernetes Engine)で動作しているingress-nginx配下のwebサーバ用にSSL証明書を付与し、サイトをSSL化する方法を記述する
Kubernetes上のコンテナWEBサイトのSSL化はいろいろある(Cloud CDN, LoadbalancerでSSL証明書を発行してもらう方法)が、GKEの都合上15のサブドメイン分しか証明書を発行できないので、let’s encryptのcert-managerコンテナを建て、SSL発行→ingress-nginxで使用できるようにした。
Let’s Encryptの証明書発行にも制限があるが、GKEよりも緩く、毎週50個のドメイン用の証明書が発行できる(https://letsencrypt.org/ja/docs/rate-limits/)
httpでアクセスしてもhttpsにRedirectするannotationを付与すればRedirectも可能となっている。
目次
HelmとTillerを使用してcert-managerをインストール
KubernetesにHelmをインストール
kubectl apply --validate=false -f https://raw.githubusercontent.com/jetstack/cert-manager/v0.13.1/deploy/manifests/00-crds.yaml
名前空間も作成しておく
kubectl create namespace cert-manager
Tillerをインストール
kubectl create serviceaccount tiller --namespace=kube-system
helm init --service-account=tiller
Repositoryを追加
helm repo add jetstack https://charts.jetstack.io
RepositotyをUpdate
helm repo update
Helmを使用してcert-managerをインストールする。
helm install \ --name cert-manager \ --namespace cert-manager \ --version v0.13.1 \ jetstack/cert-manager
インストール後に3つのpodが作成→稼働していれば問題なくインストールされている
$ kubectl get pods --namespace cert-manager NAME READY STATUS RESTARTS AGE cert-manager-5c6866597-zw7kh 1/1 Running 0 2m cert-manager-cainjector-577f6d9fd7-tr77l 1/1 Running 0 2m cert-manager-webhook-787858fcdb-nlzsq 1/1 Running 0 2m
もし、cert-manager-cainjectorが再起動を繰り返している場合は、
[GKE] Cert-Managerをdeployするとcert-manager-cainjector上でcrashloopbackoffエラーが発生した件
を参照のこと。
Cert-Managerの動作テスト
テストのIssuerを作成して証明書が作成されることを確認
$ cat <<EOF > test-resources.yaml
apiVersion: v1
kind: Namespace
metadata:
name: cert-manager-test
---
apiVersion: cert-manager.io/v1alpha2
kind: Issuer
metadata:
name: test-selfsigned
namespace: cert-manager-test
spec:
selfSigned: {}
---
apiVersion: cert-manager.io/v1alpha2
kind: Certificate
metadata:
name: selfsigned-cert
namespace: cert-manager-test
spec:
dnsNames:
- example.com
secretName: selfsigned-cert-tls
issuerRef:
name: test-selfsigned
EOF
test-resources.yamlというファイルが作成されるのでapplyする
kubectl apply -f test-resources.yaml
証明書が作成されていることを確認
$ kubectl describe certificate -n cert-manager-test ... Spec: Common Name: example.com Issuer Ref: Name: test-selfsigned Secret Name: selfsigned-cert-tls Status: Conditions: Last Transition Time: 2019-01-29T17:34:30Z Message: Certificate is up to date and has not expired Reason: Ready Status: True Type: Ready Not After: 2019-04-29T17:34:29Z Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal CertIssued 4s cert-manager Certificate issued successfully
Last Transitionがapplyした日時と同じであれば成功している
動作確認できたらテスト環境は削除
kubectl delete -f test-resources.yaml
NGINX Ingress ControllerをDeploy
リバースProxyであるNginxを稼働させてIngressをサブドメインに従って適切なWEBコンテナに通信を振り分けさせる。
既にNGINX Ingress Controllerが稼働している場合は、この章はスキップしてよい。
NginxをDeploy
helm install stable/nginx-ingress --name quickstart
結果確認
$ kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.63.240.1 <none> 443/TCP 23m quickstart-nginx-ingress-controller LoadBalancer 10.63.248.177 35.233.154.161 80:31345/TCP,443:31376/TCP 16m quickstart-nginx-ingress-default-backend ClusterIP 10.63.250.234 <none> 80/TCP 16m
nginx-ingress-controllerのpodにLoadBalancerが付与され、Global IPが付与されていることを確認
WEBサービスコンテナ(仮)をDeploy
既にnginxに振り分けさせたいWEBサービスコンテナが稼働している場合は読み飛ばしてよい
こちらはテスト用にWEBサービスコンテナ(仮)をDeployする
kubectl apply -f https://netlify.cert-manager.io/docs/tutorials/acme/example/deployment.yaml
kubectl apply -f https://netlify.cert-manager.io/docs/tutorials/acme/example/service.yaml
kuardというServiceとDeploymentが作成される
IngressルールをDeploy
Nginxに振り分けさせたいIngressルールをDeployする
ingress-nginx.yamlを作成し
apiVersion: extensions/v1beta1 kind: Ingress metadata: name: kuard annotations: kubernetes.io/ingress.class: "nginx" #cert-manager.io/issuer: "letsencrypt-staging" spec: tls: - hosts: - [nginxに振り分けさせたいサブドメイン:例:example.example.com] secretName: quickstart-example-tls rules: - host: [nginxに振り分けさせたいサブドメイン:例:example.example.com] http: paths: - path: / backend: serviceName: kuard servicePort: 80
Applyする
kubectl apply -f ingress-nginx.yaml
サブドメイン経由でWEBサーバにアクセスできることをブラウザなどで確認
現時点ではまだSSL化が終了していない
Let’s Encrypt Issuerを設定
Staging用Issuer設定
本番稼働前に動作確認したい場合はStaging設定で動作確認するとよい。特に発行制限がある程度設けられているため、いろいろ実験したい場合はStaging Issuerでテストするとよい。
もしいきなり本番稼働させたい場合は、StagingのところはSkipしてよい
letsencrypt-staging.yamlを作成
*自分のメールアドレスに変更しておくこと
apiVersion: cert-manager.io/v1alpha2 kind: Issuer metadata: name: letsencrypt-staging spec: acme: # The ACME server URL server: https://acme-staging-v02.api.letsencrypt.org/directory # Email address used for ACME registration email: [自分のメールアドレスに変更:例:user@example.com] # Name of a secret used to store the ACME account private key privateKeySecretRef: name: letsencrypt-staging # Enable the HTTP-01 challenge provider solvers: - http01: ingress: class: nginx
apply
kubectl apply -f letsencrypt-staging.yaml
証明書確認
kubectl describe issuer letsencrypt-staging
applyコマンドを発行した日時で証明書が発行されていればOK(Creation Timestamp)
本番用Issuer設定
本番稼働用のIssuerも作成しておく。letsencrypt-prod.yamlを作成
*自分のメールアドレスに変更しておくこと
apiVersion: cert-manager.io/v1alpha2 kind: Issuer metadata: name: letsencrypt-prod spec: acme: # The ACME server URL server: https://acme-v02.api.letsencrypt.org/directory # Email address used for ACME registration email: [自分のメールアドレスに変更:例:user@example.com] # Name of a secret used to store the ACME account private key privateKeySecretRef: name: letsencrypt-prod # Enable the HTTP-01 challenge provider solvers: - http01: ingress: class: nginx
apply
kubectl apply -f letsencrypt-prod.yaml
証明書確認
kubectl describe issuer letsencrypt-prod
applyコマンドを発行した日時で証明書が発行されていればOK(Creation Timestamp)
TLSをIngressに設定してSSL化
ようやくIngress-NginxにTLS設定を行ってWEB通信をSSL化できる。
ingress-nginx.yamlに追記する
↓はStaging Issuerの証明書を使用するルール設定
apiVersion: extensions/v1beta1 kind: Ingress metadata: name: kuard annotations: kubernetes.io/ingress.class: "nginx" cert-manager.io/issuer: "letsencrypt-staging" spec: tls: - hosts: - [nginxに振り分けさせたいサブドメイン:例:example.example.com] secretName: quickstart-example-tls rules: - host: [nginxに振り分けさせたいサブドメイン:例:example.example.com] http: paths: - path: / backend: serviceName: kuard servicePort: 80
Apply
kubectl appply -f ingress-nginx.yaml
証明書発行状態確認
kubectl describe certificate quickstart-example-tls
Certificate issued Successfullyと出ていればOK
本番用Issuerを使用するIngressルールは以下の通り
apiVersion: extensions/v1beta1 kind: Ingress metadata: name: kuard annotations: kubernetes.io/ingress.class: "nginx" cert-manager.io/issuer: "letsencrypt-prod" spec: tls: - hosts: - [nginxに振り分けさせたいサブドメイン:例:example.example.com] secretName: quickstart-example-tls rules: - host: [nginxに振り分けさせたいサブドメイン:例:example.example.com] http: paths: - path: / backend: serviceName: kuard servicePort: 80
Apply
kubectl appply -f ingress-nginx.yaml
証明書発行状態確認
kubectl describe certificate quickstart-example-tls
Certificate issued Successfullyと出ていればOK
後は、SSL化設定を行ったURLにブラウザからアクセスしてみてSSL化が成功しているか、証明書がLets Encryptになっているか確認できればOK
ちなみに、上記設定ではhttpsへの自動フォワーディングはされないので、ブラウザからたたく場合はhttps://とする必要があるので注意。
SSL Redirect
いろいろネットで調べてGKEにはHTTPSへのRedirectは実装されていないという記事しか載っていないが、IngressのAnnotationを付与すればRedirectも可能
apiVersion: extensions/v1beta1 kind: Ingress metadata: name: ingress-resource annotations: kubernetes.io/ingress.class: nginx nginx.ingress.kubernetes.io/ssl-redirect: "true" //trueにするとRedirectされる cert-manager.io/issuer: "letsencrypt-prod" ~以下略
参考:
https://cert-manager.io/docs/tutorials/acme/ingress/
https://cert-manager.io/docs/installation/kubernetes/