過去の記事でGKEを使ってnginxを動かしてみましたが、httpsの通信は出来ない状態でした。nginx自体にLet's Encryptの証明書を設定してhttps通信をさせる事も出来ますが、nginx自体を自前で管理するのはしたくないです。AmbassadorというAPI Gatewayとして動作させるものがあるので利用してみました。
Ambassadorの設定をする
基本的にDeploying Ambassador to Kubernetesと同じです。下記はGKEで利用した場合の流れになります。
clusterrolebindingを設定するkubectl create clusterrolebinding my-cluster-admin-binding --clusterrole=cluster-admin --user=$(gcloud info --format="value(config.account)")
ambassadorをローカルにダウンロードしてデプロイするcurl -O https://www.getambassador.io/yaml/ambassador/ambassador-rbac.yamlkubectl apply -f ambassador-rbac.yaml
ambassadorのServiceを作成するambassador-service.yamlを作成するkubectl apply -f ambassador-service.yamlでデプロイする
# ambassador-service.yaml
apiVersion: v1
kind: Service
metadata:
name: ambassador
spec:
type: LoadBalancer
externalTrafficPolicy: Local
ports:
- port: 80
targetPort: 8080
selector:
service: ambassador
- nginxのdeploymentを起動させる (過去の記事参考)
- nginxのserviceにAmbassadorのannotationsを追加する
apiVersion: v1
kind: Service
metadata:
name: nginx
annotations:
getambassador.io/config: |
---
apiVersion: ambassador/v1
kind: Mapping
name: nginx_mapping
prefix: /nginx/
service: nginx
spec:
selector:
name: nginx
ports:
- port: 80
name: http-nginx
targetPort: http-nginx-port
kubectl get svc ambassadorで EXTERNAL-IPを確認する
mayu-mbp-2:kubernetes mayu$ kubectl get svc ambassador NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE ambassador LoadBalancer ***** ***** 80:30294/TCP,443:32689/TCP 178m
<EXTERNAL-IP>/nginx/にブラウザで接続するとnginxの初期画面が表示される。
cert-managerを使って証明書を準備する
基本的にはcert-managerとAmbassadorのドキュメントを参考にしています。cert-managerは Let's EncryptのACMEプロトコルを利用して証明書を自動更新する事が出来ます。
事前準備
- namespace
cert-managerを作成するkubectl create namespace cert-manager
- resource validationの除外設定をしておきます。
kubectl label namespace cert-manager certmanager.k8s.io/disable-validation=truecert-managerの設定をダウンロードしてデプロイします。curl -O https://raw.githubusercontent.com/jetstack/cert-manager/release-0.7/deploy/manifests/cert-manager.yamlkubectl apply -f cert-manager.yaml
証明書の作成
issuer と Certificate リソースを作成する必要があります。Issuerはクライアント証明書でCertificateはサーバ証明書の発行を行います。ネームスペースに閉じた証明書を利用する場合は kind: Issuerでクラスタ全体で利用する場合は kind: ClusterIssuerで作成をしてください。この記事ではClusterIssuerで進めます。
ClusterIssuerリソースを作成するkubectl apply -f clusterIssuer.yaml
# clusterIssuer.yaml
apiVersion: certmanager.k8s.io/v1alpha1
kind: ClusterIssuer
metadata:
name: letsencrypt-staging
spec:
acme:
server: https://acme-staging-v02.api.letsencrypt.org/directory
email: <mail-address>
privateKeySecretRef:
name: letsencrypt-staging
http01: {}
Certificateリソースを作成するkubectl apply -f certificate.yaml
# certificate.yaml
apiVersion: certmanager.k8s.io/v1alpha1
kind: Certificate
metadata:
name: kubernetes-certificate
namespace: default
spec:
secretName: kubernetes-cert-secret
issuerRef:
name: letsencrypt-staging
kind: ClusterIssuer
dnsNames:
- <your_domain>
acme:
config:
- http01:
ingressClass: nginx
domains:
- <your_domain>
HTTP-01 Challengeの設定
ACME認証では HTTPかDNSを利用するかの二種類があります。
(Ambassadorのドキュメント)
- cert-managerのpodから
acme-http-domainとacme-http-tokenを取得するkubectl logs cert-manager-69568fb89d-76zm6 -n cert-manager | grep acme-http- 下記のようなログが出力されます
I0608 21:19:28.249101 1 ingress.go:49] Looking up Ingresses for selector certmanager.k8s.io/acme-http-domain=161156668,certmanager.k8s.io/acme-http-token=1100680922
acme-challenge-serviceリソースを作成します。- 先ほど取得した
acme-http-domainとacme-http-tokenを書き換えます。
- 先ほど取得した
apiVersion: v1
kind: Service
metadata:
name: acme-challenge-service
annotations:
getambassador.io/config: |
---
apiVersion: ambassador/v1
kind: Mapping
name: acme-challenge-mapping
prefix: /.well-known/acme-challenge
rewrite: ""
service: acme-challenge-service
spec:
ports:
- port: 80
targetPort: 8089
selector:
certmanager.k8s.io/acme-http-domain: "161156668" #rewrite
certmanager.k8s.io/acme-http-token: "1100680922" #rewrite
nginxにhttpsで通信出来てるかの確認
kubectl get svc ambassadorで EXTERNAL-IPを確認して設定したドメインに登録する<ドメイン名>/nginx/にブラウザで接続するとhttps通信がされるようになりました。- httpで接続した際はhttpsにリダイレクトされます。

一通りやってみましたが、実施すべき事が多いですね。 消したり作ったりする場合は、クラスタ構築のパイプラインを作った方が良さそう。