テクノロジー開発部の村上です。
弊社で現在開発中のシステムはKubernetesを用いてマイクロサービスで構築しており、そのデプロイの一部にSpinnakerを使用しています。
Spinnakerを使用するにあたって認証を追加するので当然TLS(SSL)対応が必要となるのですが、公式サイトにはServer-terminated SSLの方法しか掲載されていなく、その方法がやや面倒です。
ですので今回は、Load Balancer-terminated SSLの方法を紹介したいと思います。
Spinnakerとは
本記事に興味を持つ方にはそもそも説明不要だとは思いますが、簡単に説明させていただければと思います。
SpinnakerはNetflixによって開発された、デプロイ(ビルドも)をパイプラインで管理する、Continuous Deploymentのためのシステムとなります。
GCPやAWSなどに対応していて、Slackへの通知も設定できて、とても便利です。
公式ではbakeと呼ばれるビルド部分もSpinnakerで行うことも可能ですが、弊社では以下の流れでデプロイしています。
- GitHubでmasterブランチにマージ
- Cloud Buildでビルド
- Container Registryにpush
- pushされたことを検知してSpinnakerによってGKEクラスタにデプロイ
上記の手順でデプロイしているのは、KubernetesのDeploymentとJobです。
TSL(SSL)対応手順
Load Balancer-terminated SSLということで、Ingressを作成することになります。
また、今回はGKEでSpinnakerを構築していることを想定しています。(基本的な手順はAWSなどでも同様だと思います)
- Try out public Spinnaker on GKE の手順を一部変更して実施
- Ingressを作成
ちなみに、1のページをそのまま実行すると、LoadBalancerとしてKubernetesのServiceを作成することになります。
DeckとGateという、UI用とAPI用の2つのマイクロサービスのコンポーネント用のServiceが必要となるので、
それぞれにTSL対応をすれば、Server-terminated SSLが実現出来ます。
事前準備
まず、手順1と2のために以下の2つを事前準備として実行しておきます
- Load Balancer用のstatic ipを作成する
- ドメインを取得しDNSサーバーを設定する
- Deck用とGate用に、1で作成したIPアドレスを指す用にDNSサーバーのAレコードをそれぞれ作成する
Aレコードは、"Try out public Spinnaker on GKE"では、それぞれspinnaker.$DOMAIN
とspinnaker.$DOMAIN
となっています。
($DOMAINは取得したドメインかそのサブドメイン)
1. Try out public Spinnaker on GKEの手順を一部変更して実施
公式ページからの変更点は以下の2点です。
- ServiceのtypeをNodePortにする
- httpでURLを設定している部分をhttpsに変更する
- Serviceのポート番号を変更しない
2と3は文字通りなので、1について説明させて頂きます。
NodePortにするとだけ聞くと単純なのですが、少し工夫が必要となります。
その工夫とは、
- 手動でServiceのマニフェストを変更しないで済むように、設定ファイルをローカルに配置する
~/.hal/default/service-settings/deck.yml
と~/.hal/default/service-settings/gate.yml
- Load Balancer作成時のhealth checkに通るように、1の設定ファイルでhealth checkの種類を変更する
となります。
1については、指定のYAMLファイルにkubernetes.serviceType: NodePort
と書けばSpinnakerへの設定反映時にServiceがNodePortになります。(デフォルトはCluterIP)
2については、私もLoadBalancer作成後にhealth checkが通らずにエラーが出ていることで気がついたのですが、デフォルトではhttpによるhealth checkになっていません。
公式ページのuseExecHealthCheckの項に書かれているのですが、
Istioとの互換性向上のために、デフォルトではexec
ベースのhealth checkを行うようになっているようです。
よって、kubernetes.useExecHealthCheck: false
をYAMLファイルに記述すれば大丈夫です。
まとめると以下のようなYAMLファイルをdeck.ymlとgate.ymlとして作成することになります。
kubernetes: serviceType: NodePort useExecHealthCheck: false
2. Ingressを作成
以下のYAMLを使用して、Ingressを作成します。
このYAMLでは、spinnaker-ingress-cert
というKubernetesのsecretに証明書と秘密鍵を保管しています。
今回私はCloudflareで証明書と秘密鍵を作成し(それぞれcert.pemとkey.pemとする)、以下のコマンドでsecretを作成しました。
kubectl create -n spinnaker secret tls spinnaker-ingress-cert --key key.pem --cert cert.pem
それとは別にGoogleのmanaged certを使用する方法もあり、その場合はtls
部分を消して
、annotationsにingress.gcp.kubernetes.io/pre-shared-cert: "GOOGLE_MANAGED_CERT"
を足すこととなります。
apiVersion: extensions/v1beta1 kind: Ingress metadata: name: spinnaker-ingress namespace: spinnaker annotations: kubernetes.io/ingress.global-static-ip-name: <事前に作成したStatic IPの名前> kubernetes.io/ingress.allow-http: "false" spec: tls: - secretName: spinnaker-ingress-cert rules: - host: <UI用のドメイン名> http: paths: - backend: serviceName: spin-deck servicePort: 9000 - host: <API用のドメイン名> http: paths: - backend: serviceName: spin-gate servicePort: 8084
まとめ
いかがでしたでしょうか。自分自身で設定する際に、あまりウェブ上にも参考資料がなかったので今回紹介させて頂きました。
弊社では上記に加えてIP制限も足すことで、セキュアにSpinnakerを運用しています。
まだ開発中のシステムで使用しているだけなので自動デプロイの恩恵しか受けていませんが、今後はManual Judgeパイプライン等も活用していけたらと思っているので、その際はまた何か紹介出来ればと思います。
参考資料
- Setup https access on GKE
- Spinnakerの公式フォーラムで、Ingress作成の参考にさせて頂きました