Cloud Endpoints + GKEで構築したAPIをマネージド証明書を用いてhttps通信に対応させる
概要
APIを作成する際に、GCPのサービスであるCloud Endpointsを使うとAPIのドキュメント管理や認証機能を簡単に実装できるなどいろいろと便利です。アプリケーションの部分はGKEで作ってそれらを連携させていたりします。
それらの詳しい方法は以下のリンクでチュートリアルを実際にやっていただくのがわかりやすいです。
Kubernetes での Endpoints のスタートガイド | OpenAPI を使用した Cloud Endpoints | Google Cloud
ですが、このチュートリアルではhttpでの通信を行うところまでしかできません。この記事では、マネージド証明書を用いてCloud Endpointsにて作成したAPIをhttps通信に対応させる方法を記載します。
手順
GKEクラスタの作成
ここは普通にクラスタを作ります。 kubectl
を使えるようにするために認証情報も取得しておきます。
gcloud container clusters create sample-cluster gcloud container clusters get-credentials sample-cluster
静的IPの取得
Endpointsで使う静的IPアドレスを事前に用意しておきます。2行目のコマンドで作成されたIPアドレスを確認できます。
gcloud compute addresses create smaple-api-ip --global gcloud compute addresses list
Endpoints DNSでAレコードの作成
Cloud Endpointsにデプロイする openapi.yaml
ファイルを編集します。該当する箇所だけ抜粋すると以下のようになります。
swagger: "2.0" host: "[API_NAME].endpoints.[PROJECT_ID].cloud.goog" x-google-endpoints: - name: "[API_NAME].endpoints.[PROJECT_ID].cloud.goog" target: "xx.xxx.xx.xx" #ここに先程の静的IPアドレスを記入 schemes: - "https"
これを gcloud endpoints services deploy openapi.yaml
コマンドでデプロイします。このyamlファイルをデプロイすると自動的にDNS Aレコードが作成されます。
ドメインとIPアドレスが紐付いているかは dig [API_NAME].endpoints.[PROJECT_ID].cloud.goog
のようにして確認することができます。
マネージド証明書の発行
以下のコマンドで証明書を発行します。
gcloud compute ssl-certificates create sample-api-cert \ --domains [API_NAME].endpoints.[PROJECT_ID].cloud.goog
発行された証明書は gcloud compute ssl-certificates list
で確認できます。
GKEのDeploymentの作成
Deploymentもチュートリアル通りに作ります。
apiVersion: apps/v1beta1 kind: Deployment metadata: name: sample-api spec: replicas: 1 template: metadata: labels: app: sample-api spec: containers: - name: sample-api image: gcr.io/[YOUR_PROJECT]/[YOUR_APP]:[TAG] imagePullPolicy: Always ports: - containerPort: 8080 protocol: TCP - name: esp image: gcr.io/endpoints-release/endpoints-runtime:1 imagePullPolicy: IfNotPresent args: [ "--http_port=8081", "--backend=127.0.0.1:8080", "--service=[API_NAME].endpoints.[PROJECT_ID].cloud.goog", "--rollout_strategy=managed", "-z", "healthz" ] ports: - containerPort: 8081 readinessProbe: httpGet: path: /healthz port: 8081
1点注意しなくてはいけないことがあります。後にIngressを作成するのですが、GCEのHTTP(S) Load Balancingのヘルスチェックを受ける対象が esp
コンテナになっており、チュートリアルの実装のままだとヘルスチェックに引っかかってエラーになります。これを避けるために readinessProbe
を esp
コンテナの部分に追記します。
GKEのServiceの作成
Serviceもほぼチュートリアル通りですが、1点変更点があります。 type: LoadBalancer
を type: NodePort
に変えておいてください。インターネットへの公開はIngressを用います。
apiVersion: v1 kind: Service metadata: name: sample-api spec: ports: - port: 80 targetPort: 8081 protocol: TCP name: http selector: app: sample-api type: NodePort
GKEのIngressの作成
ServiceではなくIngressでロードバランサーを作成します。 annotaions
で先程作成した静的IPアドレス名、証明書名を記述します。
apiVersion: extensions/v1beta1 kind: Ingress metadata: name: sample-api-ingress annotations: kubernetes.io/ingress.global-static-ip-name: smaple-api-ip ingress.gcp.kubernetes.io/pre-shared-cert: sample-api-cert spec: rules: - host: [API_NAME].endpoints.[PROJECT_ID].cloud.goog http: paths: - path: /* backend: serviceName: sample-api servicePort: 80
Ingressの設定をGKEクラスタに反映させると証明書のステータスがACTIVEになるまで数分かかります。 kubectl apply -f
で更新しても反映されないことがあるので、そのときは一旦削除して作り直してください。
問題なく証明書がACTIVEになればHTTPSで通信ができるようになっているはずです。