[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/

https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#server-side-https-enforcement-through-redirect

 

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です