はじめに
前回の記事で作成したAzure Kubernetes Service(AKS)上のWordPressコンテナは、AKSの「LoadBalancer」を使ってhttpによる接続を検証しました。
前回の記事 : Azure KubernetesとAzure Database for MySQLを使ってWordPress Containerを動かす
今回はこのLoadBalancerを止めて、「nginx-ingress」を導入します。
誤解を恐れずにnginx-ingressの概要を書くと
- L7レベルのアプリケーションロードバランサ
- MS公式ドキュメントにも載っている他、Googleも推奨
- バックエンドの複数のサービスをURLでリダイレクト可能
- SSL証明書をnginx-ingressに投入することでバックエンドのサービスがhttpのみであっても、httpsによるサービス提供が可能
といったところでしょうか。
参考 : Azure Kubernetes Service (AKS) での HTTPS イングレス
必要なもの
前回作成したAKS、Azure Database for MySQLの環境の他、今回は更に以下のものが必要です。
- 独自ドメイン (この記事では私の個人ドメイン "nya-n.net" を使用します)
- 独自ドメインを管理しているDNSサーバ (この記事ではAzure DNSを使用します)
- SSL証明書 (この記事では digicert から取得したワイルドカード証明書を使用します)
手順
nginx-ingressのインストール
AzureポータルからCloudshellで利用している場合にはhelmは既にインストール済みですので、今回はこちらを使います。
Cloudshellから以下のコマンドを入力してhelmの初期化と、nginx-ingressのインストールをします。
namespaceの指定はご自由に。
$ helm init
$ helm install stable/nginx-ingress --namespace default --set rbac.create=false
しばらくすると、Azure上にも新しいPublic IP Addressリソースが作成されて、nginx-ingressに割り当てられます。
以下のコマンドを入力して「altered-octopus-nginx-ingress-controller」に割り当てられたEXTERNAL-IPを控えておきます。
こちらのIPアドレスはこの後、ご自身のDNSサーバのレコード登録時に使用します。
$ kubectl get service -l app=nginx-ingress --namespace wordpress01
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
altered-octopus-nginx-ingress-controller LoadBalancer 10.0.14.213 XX.XX.XX.XX 80:30686/TCP,443:32533/TCP 1h
altered-octopus-nginx-ingress-default-backend ClusterIP 10.0.216.180 <none> 80/TCP 7m
Azure DNSへのAレコード登録
先程作成されたEXTERNAL-IPをDNSサーバにAレコードとして登録します。
ちょっと画面が細かくて恐縮ですが、これで「wordpress.nya-n.net」で名前解決ができるようになりました。
お使いのNameserverがAzure DNSとは異なるものの場合にはそれぞれの設定方法でAレコードを登録します。
TTLは今回は検証用なので10分にしましたが、本番運用するのであればもっと長くていいと思います。
SSL証明書ファイルの準備
私はdigicertからワイルドカード証明書を取得しました。
SSL証明書の取得手順は各社異なりますので本記事では割愛します。
手元には以下のファイルがあります。
- private.key (パスワード暗号化された RSA PRIVATE KEY)
- server.csr (署名リクエスト CERTIFICATE REQUEST)
- star_nya-n_net.cer (digicertから送られてきたサーバー証明書 PKCS7)
private.keyは手元で作成時にパスワード設定を行いましたが、AKSのSecretに登録する際にはそのパスワードを外さないといけません。
不本意ですが、以下のコマンドでパスワードを外したprivate_unenc.keyを作成します。
$ openssl rsa -in server.key -out unencryred.key
Enter pass phrase for server.key:********
writing RSA key
また、digicertから送られてきたcerファイルはPKCS7形式で、申請したドメインの証明書の他、中間証明書などが含まれていて、このままではAKSのSecretに登録はできますが、nginx-ingressから認識してもらえません。
digicertのサイトではWindows PCを使った変換方法が書かれています。
もしopensslしか使えなければ、以下のコマンドでX.509に変換できます。
openssl pkcs7 -in star_nya-n_net.cer -print_certs > for-nginx-ingress.cer
出力されたファイルには中間証明書がまだ含まれていますので、「CN=」の内容を確認して自分のドメインの証明書(通常一番先頭のブロック)の「-----BEGIN CERTIFICATE-----」から「-----END CERTIFICATE-----」の部分を残して後の行は削除します。
最後にAKS上のSecretに登録して完了です。
$ kubectl apply secret tls tls-cert --key unencryred.key --cert for-nginx-ingress.cer
$ kubectl get secret
NAME TYPE DATA AGE
altered-octopus-nginx-ingress-token-vtj4j kubernetes.io/service-account-token 3 2h
default-token-75gbb kubernetes.io/service-account-token 3 2h
tls-cert kubernetes.io/tls 2 2h
wp-secrets Opaque 1 2h
WordPressサービス登録
前回の記事ではWordPressはLoadBalancer経由でしたが、今回はnginx-ingressの配下にぶら下げるため、Serviceとして登録しておきます。
yamlで書いてもいいのですが、以下のコマンドでサクッとサービスを作成します。
$ kubectl expose deployment wordpress --type NodePort
これでnginx-ingressからwordpressが参照できるようになりました。
nginx-ingressの登録
先程作成したのはnginx-ingressのコントローラー部分となるため、最後にwordpressをnginx-ingressの配下に設定します。
以下のyamlファイルを準備します。
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: wordpress-ingress
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
tls:
- hosts:
- wordpress.nya-n.net (ここは適宜変更)
secretName: tls-cert
rules:
- host: wordpress.nya-n.net (ここは適宜変更)
http:
paths:
- path: /
backend:
serviceName: wordpress
servicePort: 80
最後に以下のコマンドで適用します。
$ kubectl apply -f wp-ingress.yaml
$ kubectl get ingress
NAME HOSTS ADDRESS PORTS AGE
wordpress-ingress wordpress.nya-n.net 80, 443 1h
実際にnginx-ingressに新しい設定が追加されるまで、5分程度かかるみたいです。
WordPress側の変更
前回作成したLoadBalancer経由でhttpでアクセスして、「Really Simple SSL」プラグインをインストールします。
(WordPress側の操作方法は割愛)
[設定] → [一般] のWordPressアドレス(URL)とサイトアドレス(URL)を変更します。
無事httpsによる接続が行えて、証明書もdigicertのものが設定されていることが確認できました。
LoadBalancerの削除
別にこのまま残しておいても良いとは思いますが、前回の記事で作成したLoadBalancerはもう不要となりますので削除します。
$ kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
altered-octopus-nginx-ingress-controller LoadBalancer 10.0.14.213 XX.XX.XX.XX 80:30686/TCP,443:32533/TCP 2h
altered-octopus-nginx-ingress-default-backend ClusterIP 10.0.216.180 <none> 80/TCP 2h
azure-mysql ExternalName <none> ktkr-mysql.mysql.database.azure.com <none> 2h
wordpress NodePort 10.0.201.181 <none> 80:31464/TCP 2h
wp-external-lb LoadBalancer 10.0.9.190 XX.XX.XX.XX 80:30611/TCP 2h
$ kubectl delete service wp-external-lb
service "wp-external-lb" deleted
おわりに
前回の記事で作成したWordPressは、pod ⇔ MySQLの間はAzureのサービスエンドポイントを使って仮想ネットワーク内で安全に通信をする構成を取りました。
前回の記事 : Azure KubernetesとAzure Database for MySQLを使ってWordPress Containerを動かす
今回は更に外部との通信にhttpsを強制することで、よりセキュアなサービス構成が作れたと思います。(WordPress自身の脆弱性については別のオハナシ)