「継続的デリバリ」(CD)を実現できるコンテナクラスタ管理ツール「Spinnaker」

実運用されるソフトウェアのリリースは、かつては入念な準備のうえで行う一大イベントだった。しかし昨今ではソフトウェアの更新サイクルの高速化により、頻繁にソフトウェアのリリースを行うケースが増えている。特にソフトウェアの開発・デバッグサイクルにリリースも組み込んだ手法は「継続的デリバリ(CD)」と呼ばれており、Facebookなど大規模なシステムを運営する企業も採用している。今回はこのCDを支援するツール「Spinnaker」を紹介する。

継続的デリバリとは

最近、特にWebサービス関連業界においては、素早いソフトウェアの改善・改良や新機能追加が求められるようになっている。そのため、開発と並行して自動的にビルドやテストを実行するような「継続的インテグレーション」が普及しつつある。そして昨今ではこれをさらに拡張し、開発と並行してソフトウェアのリリースも自動的に行おうという考え方が出てきた。これが継続的デリバリである。

継続的デリバリでは、対象とするソフトウェアにおいて常時リリース可能なバージョンとそれをビルドしてインストール可能にしたもの、そしてそれを自動的に運用環境にデプロイする手段を用意しておく。この3つが常時存在することで、迅速に成果物を実運用環境に投入できるようになる。

常時リリース可能なバージョンを用意するというのは、バージョン管理システムの運用によって実現できる。たとえば新規機能開発や修正はすべて別のブランチで行い、作業が完了してテスト済みのものだけをメインブランチ(リリースブランチ)にマージするようにすれば良い。また、ビルドについてはTravis CIJenkinsなどの継続的インテグレーションツールを利用することで実現できる。

いっぽうで、自動的に運用環境にデプロイする手段については運用環境に依存することもあり、決定的な支援ツールはなかなか出てこなかった。

たとえば以前「カスタムRPMや独自yumリポジトリではじめるソフトウェア管理術」や「独自Debパッケージやaptリポジトリを使ったサーバー管理術」といった記事で紹介したように、ソフトウェアをRPMやDEB形式のパッケージにしてデプロイするという手法もあるが、これらは信頼性は高いものの「クリック1つでデプロイ」とはいかない。

しかし、最近では特に大規模なシステムを運用するような事業者ではクラウド環境を利用してサービスをデプロイするケースが増えてきた。このような環境ではクラウド環境のAPIを利用することで、スクリプトやツールを使ってデプロイを行える。これを発展させたデプロイ管理するツールも登場した。今回紹介する「Spinnaker」もその1つである。

大規模なインフラを活用するNetflixが開発した「Spinnaker」

Spinnakerは、動画配信サービスを手がける米Netflixが2015年に公開したツールだ。Webブラウザ経由で操作するフロントエンド(Web UI)と、さまざまなクラウドインフラに対応するバックエンドの組み合わせで構築されている。GUIでデプロイを実行できるだけでなく、特定の処理の完了をトリガーに処理を実行するパイプライン機能が提供されているのが特徴だ(図1)。

図1 SpinnakerのWeb UI
図1 SpinnakerのWeb UI

SpinnakerはAmazon Web Services(AWS)やGoogle Cloud Platform(GCP)といったパブリッククラウドで利用できるほか、KubernetesやOpenStackといったプライベートクラウド構築で使われている技術についてもサポートされている。今回は、このSpinnakerをKubernetesクラスタで利用するためのインストール・設定方法や、利用できる機能について紹介する。

なお、今回はさくらのクラウドを使用し、CentOS 7.4およびKubernetes 1.52を使用してマスターサーバー1台とクラスタノード4台からなるKubernetesクラスタを構築したものを検証環境として使用した。Spinnakerのインストールおよび動作にはクラスタ内でDNS(kube-dns)が動いている必要があるので、この設定も行っている。

Spinnakerのインストール

Spinnakerは表1のような複数のコンポーネントから構成されており、これらをすべて適切に設定・インストールする必要がある。

表1 Spinnakerのコンポーネント
名称 説明
Deck Web UIを提供する
Gate 各種操作を実行するAPIのエンドポイントを提供する
Orca オーケストレーションを行う
Clouddriver デプロイなどのクラウド環境の操作を行う
Front50 メタデータやパイプライン、プロジェクト、通知の管理などを行う
Rosco 仮想マシンイメージの管理を行う
Igor 継続的インテグレーション経由で処理を行うためのトリガーを管理する
Echo イベントや通知の管理を行う
Fiat 認証機能を提供する

そのため、Spinnaker 1.0からはインストールや設定を行うための専用ツール「halyard」が導入された。Spinnakerをインストールするにはまずこのhalyardをインストールし、続いてhalyardが提供する「hal」コマンドを使ってコンポーネントの設定やインストールを行うことになる。

halyardのインストール方法については公式ドキュメントでも解説されているが、直接作業用のマシンにインストールする方法と、halyardがインストールされたコンテナを利用する方法がある。Spinnakerが提供しているインストールスクリプトはUbuntu 14.04/16.04向けとなっていることもあり、今回はコンテナをDocker経由で実行する方法を選択した。

また、Spinnakerの各コンポーネントのインストールについても、これらを直接ホストにインストールする方法(Local Debian)と、クラウド上に分散インストールする方法(Distributed)が用意されている。対応するクラウドは次のとおりだ。

  • App Engine
  • Amazon Web Services
  • Azure
  • DC/OS
  • Google Compute Engine
  • Kubernetes (legacy)
  • Kubernetes V2 (manifest based)
  • Openstack
  • Oracle

今回はKubernetesを利用するので後者(Distributed)を選択し、Kubernetes上にSpinnakerの各コンポーネントをインストールする。

そのほか、Spinnakerの各種設定を保存する永続的ストレージサービスや、使用するイメージを格納するリポジトリ(Docker Registry)も必要になる。今回はこれらについてもコンテナを利用して稼動させることとした。

ストレージサービスの準備

Spinnakerでは各種設定を保存するストレージとして、次のものが利用できる。

  • Azure Storage
  • Google Cloud Storage
  • Minio
  • S3

なお、ドキュメントではRedisも利用できるとされているが、プロダクション環境での利用は推奨されていない。そのため今回はS3互換のストレージサービスであるMinioを利用する。

Minioはコンテナイメージの形でも提供されており、Kubernetesの管理下で実行させることで冗長化や管理が容易になるが、今回はDockerを利用してKubernetesのマスターノード上で稼動させることとした。作業手順としては次のようになる。

まず、Minioコンテナ内にマウントさせるデータや設定保存用のディレクトリを作成する。今回は/var/minio以下に「data」および「config」の2つのディレクトリを用意した。

# mkdir -p /var/minio/{data,config}

続いてこのディレクトリをマウントするように設定して「minio/minio」イメージからコンテナを作成する。

# docker run -d -p 9001:9000 --name minio -v /var/minio/data:/data -v /var/minio/config:/root/.minio minio/minio server /data

これで、「minio」という名称でコンテナが作成される。なお、デフォルトでminioは9000番ポートで待ち受けを行うが、このポートはSpinnakerも使用するため、念のため異なるポート(9001番ポート)で待ち受けするよう設定している。

コンテナの作成後、「docker logs」でこのコンテナの出力を確認すると、MinioのストレージにアクセスするためのAccessKeyおよびSecretKeyが表示される。これはあとでSpinnakerの設定で利用するので、適宜コピーしておこう。

$ docker logs minio
Created minio configuration file successfully at /root/.minio
Drive Capacity: 12 GiB Free, 15 GiB Total
Endpoint:  http://172.17.69.2:9000  http://127.0.0.1:9000
AccessKey: YYNO7REGTXUGDW8L5KZW
SecretKey: mvuhy4qtdqt6lgnTTpXSsGDM3m86yQWnrvu8HjOh
Browser Access:
   http://172.17.69.2:9000  http://127.0.0.1:9000
Command-line Access: https://docs.minio.io/docs/minio-client-quickstart-guide
   $ mc config host add myminio http://172.17.69.2:9000 YYNO7REGTXUGDW8L5KZW mvuhy4qtdqt6lgnTTpXSsGDM3m86yQWnrvu8HjOh
Object API (Amazon S3 compatible):
   Go:         https://docs.minio.io/docs/golang-client-quickstart-guide
   Java:       https://docs.minio.io/docs/java-client-quickstart-guide
   Python:     https://docs.minio.io/docs/python-client-quickstart-guide
   JavaScript: https://docs.minio.io/docs/javascript-client-quickstart-guide
   .NET:       https://docs.minio.io/docs/dotnet-client-quickstart-guide

Docker Registryの設定

続いて、使用するイメージを保存するプライベートリポジトリの準備を行う。

プライベートリポジトリを利用するための設定についてはKubernetesによるDockerコンテナ管理入門記事で以前紹介しているので基本的にはこれに従えば良いのだが、注意点としてDockerではリポジトリへの接続にSSL/TLSを利用するのがデフォルトとなっており、SSL/TLSに非対応、もしくはSSL/TLSに対応していてもいわゆる自己署名証明書を利用するリポジトリの場合、設定が煩雑になってしまう。そのため、今回は適切なSSL/TLS証明書を用意したうえで、SSL/TLS対応のプライベートリポジトリを実行させることとした。

この場合、Kubernetesクラスタ内から証明書に対応したホスト名でプライベートリポジトリにアクセスできなければならない。そのため適切なDNS設定などを事前に行っておく必要がある。

さて、CentOSの「docker-distribution」パッケージを使ってプライベートリポジトリを運用する場合、次のように設定ファイル(/etc/docker-distribution/registry/config.yml)に記述を追加することで、SSL/TLS接続を利用できるようになる。

version: 0.1
log:
  fields:
    service: registry
storage:
    cache:
        layerinfo: inmemory
    filesystem:
        rootdirectory: /var/lib/registry
http:
    addr: <待ち受けに使用するIPアドレスもしくはホスト名>:5000
    tls:
        certificate: <証明書ファイルのパス名>
        key: <秘密鍵ファイルのパス名>
auth:
    htpasswd:
        realm: "docker registry"
        path: *[<htpasswdファイルのパス名>]

また、ここではhtpasswdファイルを利用してユーザー管理を行うよう設定している。これにより、リポジトリへのアクセスにあらかじめ用意しておいたユーザー名およびパスワードでの認証を必要とするよう設定できる。たとえば「admin」というユーザーを作成したい場合、次のようにしてこのユーザーを含むhtpasswdファイルを作成できる。

$ htpasswd -cB htpasswd admin
New password:  ←パスワードを入力
Re-type new password:  ←同じパスワードを再度入力
Adding password for user admin

これらに加えて、docker-distributionサービスはデフォルトでは5000番ポートで待ち受けを行うので、このポートにクラスタ内からアクセスできるようファイアウォールの設定を行っておこう。

正しく設定が行えているかどうかは、次のように「docker login」コマンドでログインを試みることで確認できる。

$ docker login <設定したドメイン名>:5000
Username: admin
Password:  ←設定したパスワードを入力
Login Succeeded

このように「Login Succeeded」と表示されれば成功だ。

halyardコンテナの実行

永続的ストレージおよびプライベートリポジトリを用意したら、続いてhalyard環境を含むコンテナを実行し、そこでSpinnakerの設定およびデプロイ作業を行っていく。halyard環境を含むコンテナは、次のようにして実行できる。

# mkdir ~/hal
# docker run -d --name halyard -v ~/hal:/root/.hal -v <使用するKubernetesの設定ファイル>:/root/.kube/config gcr.io/spinnaker-marketplace/halyard:stable

なお、ここでは~/halというディレクトリを作成し、これをコンテナ内の/root/.halにマウントしている。このディレクトリにはhalyardの設定ファイルなどが保存される。また、Kubernetesの設定が保存された設定ファイルも同様にコンテナ内にマウントしている。この設定ファイルは通常はユーザーのホームディレクトリ以下の.kubeディレクトリ内に「config」というファイル名で保存されている。このファイルの作成方法については「KubernetesによるDockerコンテナ管理入門」記事の『「kubectl」コマンドを利用するための設定』項目で解説しているので、こちらを参照して欲しい。このファイル内にはKubernetesへのアクセスに使用する情報などが含まれており、これがないと適切にKubernetesへのデプロイが行えないので注意したい。

コンテナが起動したら、次のようにしてコンテナ内のシェルにアクセスする。

$ docker exec -ti halyard bash

使用するSpinnakerバージョンとプライベートリポジトリ設定

続いて、コンテナ内のシェルから「hal」コマンドを実行してデプロイのための各種設定を行っていく。

まず、デプロイするSpinnakerのバージョンを指定する。今回は記事作成時点の最新版であるバージョン1.6.0を使用することとした。

# hal config version edit --version 1.6.0
+ Get current deployment
  Success
+ Edit Spinnaker version
  Success
+ Spinnaker has been configured to update/install version "1.6.0".
  Deploy this version of Spinnaker with `hal deploy apply`.

次に、Dockerプライベートリポジトリにアクセスするための情報(docker-registry account)を登録する。ここでは「test-repo」という名称を指定し、さらにアクセスに使用するユーザー名として「admin」を指定しているが、これらは適宜適切な名前に変更してほしい。

# hal config provider docker-registry account add test-repo --address <リポジトリのホスト名>:5000 --username admin --password
Your docker registry password:  ←パスワードを入力
+ Get current deployment
  Success
+ Add the test-repo account
  Success
Problems in default.provider.dockerRegistry.test-repo:
- WARNING Your docker registry has no repositories specified, and
  the registry's catalog is empty. Spinnaker will not be able to deploy any images
  until some are pushed to this registry.
? Manually specify some repositories for this docker registry to
  index.

+ Successfully added account test-repo for provider
  dockerRegistry.

続いてDocker Registry機能のサポートを有効にする。

# hal config provider docker-registry enable
+ Get current deployment
  Success
+ Edit the dockerRegistry provider
  Success
Problems in default.provider.dockerRegistry.test-hylom-net:
- WARNING Your docker registry has no repositories specified, and
  the registry's catalog is empty. Spinnaker will not be able to deploy any images
  until some are pushed to this registry.
? Manually specify some repositories for this docker registry to
  index.

+ Successfully enabled dockerRegistry

Kubernetesプロバイダの設定

Spinnakerの機能は「プロバイダ」という形で提供されており、利用するクラウドインフラストラクチャに対応するプロバイダを有効にする必要がある。今回はKubernetesを利用するので、「kubernetes」プロバイダを有効にすれば良い。

まず、kuberneteで使用するアカウントを追加する。ここでは「admin」という名前とした。また、先に登録したdocker-registry accountを「--docker-registries」オプションで指定しておく。

# hal config provider kubernetes account add admin --docker-registries test-repo
+ Get current deployment
  Success
+ Add the admin account
  Success
+ Successfully added account admin for provider kubernetes.

続いてkubernetesプロバイダを有効にするよう設定する。

# hal config provider kubernetes enable
+ Get current deployment
  Success
+ Edit the kubernetes provider
  Success
Problems in default.provider.kubernetes.admin:
- WARNING You have not specified a Kubernetes context in your
  halconfig, Spinnaker will use "default-context" instead.
? We recommend explicitly setting a context in your halconfig, to
  ensure changes to your kubeconfig won't break your deployment.
? Options include:
  - default-context

+ Successfully enabled kubernetes

永続的ストレージ設定

今回は永続的ストレージとしてS3互換のminioを使用するので、その情報を登録する。このとき、minioが待ち受けを行っているホストおよびポート番号と、前述したAccessKey、SecretKeyの情報が必要となる。

# hal config storage s3 edit --endpoint http://<minioの待ち受けホスト>:<ポート> --access-key-id <AccessKey> --secret-access-key
Your AWS Secret Key.:  ←minioのSecretKeyを入力
+ Get current deployment
  Success
+ Get persistent store
  Success
Generated bucket name: spin-89567809-7f6b-418f-bef8-a9ece00fd822
+ Edit persistent store
  Success
Problems in default.persistentStorage:
- WARNING Your deployment will most likely fail until you configure
  and enable a persistent store.

+ Successfully edited persistent store "s3".

続いてストレージとしてS3を使用するよう指定する。

# hal config storage edit --type s3
+ Get current deployment
  Success
+ Get persistent storage settings
  Success
+ Edit persistent storage settings
  Success
+ Successfully edited persistent storage.

デプロイ設定

今回はKubernetes上に分散デプロイを行うので、次のようにしてその設定を行う。

# hal config deploy edit --type distributed --account-name admin
+ Get current deployment
  Success
+ Get the deployment environment
  Success
+ Edit the deployment environment
  Success
+ Successfully updated your deployment environment.

Web UIのURL設定

Spinnakerでは各種操作をWebブラウザ経由で行うが、デフォルト設定ではこのWeb UIのURLのホスト名が「localhost」になっている。そのため、これを適切なホスト名に変更しておこう。詳しくは後述するが、今回はKubernetesのNodePort機能を使ってマスターノードへのアクセスをDeckおよびGateコンテナに転送する構成を取るので、次のように設定を行った。

# hal config security ui edit --override-base-url http://<マスターノードのIPアドレス>:30009
+ Get current deployment
  Success
+ Get UI security settings
  Success
+ Edit UI security settings
  Success
Problems in default.security:
- WARNING Your UI or API domain does not have override base URLs
  set even though your Spinnaker deployment is a Distributed deployment on a
  remote cloud provider. As a result, you will need to open SSH tunnels against
  that deployment to access Spinnaker.
? We recommend that you instead configure an authentication
  mechanism (OAuth2, SAML2, or x509) to make it easier to access Spinnaker
  securely, and then register the intended Domain and IP addresses that your
  publicly facing services will be using.

# hal config security api edit --override-base-url http://<マスターノードのIPアドレス>:30008
+ Get current deployment
  Success
+ Get API security settings
  Success
+ Edit API security settings
  Success

なお、この設定によってKubernetesクラスタを構成する各ノードからSpinnakerにアクセスできるようになるため、ファイアウォールなどを適切に設定してアクセスを制限しておく必要がある。

デプロイの実行

以上で設定は完了だ。この状態で「hal deploy apply」コマンドを実行するとSpinnakerの構成コンポーネントがKubernetesにデプロイされる。

# hal deploy apply

なお、デプロイに失敗した場合はその旨が表示され、作業が中断される。Spinnakerの各コンポーネントは「spinnaker」というネームスペース上に展開されるので、次のように稼動しているPodを確認し、トラブルシューティングを行うとよいだろう。

$ kubectl -n spinnaker get pod
NAME                                    READY     STATUS    RESTARTS   AGE
spin-clouddriver-bootstrap-v000-qjn05   0/1       Running   0          1d
spin-clouddriver-v000-jbndd             0/1       Running   0          1d
spin-deck-v000-7960f                    1/1       Running   0          1d
spin-echo-v000-v3h9s                    1/1       Running   0          1d
spin-gate-v000-9dx0j                    1/1       Running   0          1d
spin-igor-v000-m4zw2                    1/1       Running   0          1d
spin-orca-bootstrap-v000-rf3rl          1/1       Running   0          1d
spin-orca-v000-62j22                    1/1       Running   0          1d
spin-redis-bootstrap-v000-cpbjh         1/1       Running   0          1d
spin-redis-v000-b7cjw                   1/1       Running   0          1d
spin-rosco-v000-bp4hz                   1/1       Running   0          1d

また、「hal deploy clean」コマンドを実行すればデプロイされたコンポーネントがすべて削除される。

ポートの転送設定

Spinnakerをデプロイすると、次のように多数のサービスが作成される。このうち、「spin-deck」サービスがWeb UIを、「spin-gate」サービスがSpinnakerをコントロールするためのAPIを提供するものだ。

$ kubectl -n spinnaker get svc
NAME                         CLUSTER-IP       EXTERNAL-IP   PORT(S)             AGE
spin-clouddriver             10.254.102.221   <none>        7002/TCP,8008/TCP   1d
spin-clouddriver-bootstrap   10.254.162.60    <none>        7002/TCP,8008/TCP   1d
spin-deck                    10.254.132.106   <none>        9000/TCP,8008/TCP   1d
spin-echo                    10.254.28.49     <none>        8089/TCP,8008/TCP   1d
spin-front50                 10.254.121.107   <none>        8080/TCP,8008/TCP   1d
spin-gate                    10.254.98.155    <none>        8084/TCP,8008/TCP   1d
spin-igor                    10.254.82.125    <none>        8088/TCP,8008/TCP   1d
spin-orca                    10.254.116.148   <none>        8083/TCP,8008/TCP   1d
spin-orca-bootstrap          10.254.89.221    <none>        8083/TCP,8008/TCP   1d
spin-redis                   10.254.178.149   <none>        6379/TCP,8008/TCP   1d
spin-redis-bootstrap         10.254.27.173    <none>        6379/TCP,8008/TCP   1d
spin-rosco                   10.254.54.33     <none>        8087/TCP,8008/TCP   1d

SpinnakerのWeb UIにアクセスするにはこのspin-deckサービスにWebブラウザでアクセスすれば良いのだが、今回のように独自に構築したKubernetesクラスタではデフォルトでは外部からクラスタ内のサービスに直接アクセスできない。そのため、KubernetesのNodePort機能を利用してこれらのサービスに個別のポートを割り当て、さらにプロクシを用意することで外部からアクセスできるように設定する。

まず、「kubectl edit」コマンドでspin-deckおよびspin-gateサービスの設定を編集し、NodePort機能を利用してポートを割り当てる。

$ kubectl -n spinnaker edit svc spin-deck
  
  
spec:
  clusterIP: 10.254.132.106
  ports:
  - name: http
    port: 9000
    protocol: TCP
    targetPort: 9000
    nodePort: 30009  ←nodePort設定を追加
  - name: monitoring
    port: 8008
    protocol: TCP
    targetPort: 8008
  selector:
    load-balancer-spin-deck: "true"
  sessionAffinity: None
  type: NodePort  ←type:をNodePortに変更
status:
  loadBalancer: {}
$ kubectl -n spinnaker edit svc spin-gate
  
  
spec:
  clusterIP: 10.254.98.155
  ports:
  - name: http
    port: 8084
    protocol: TCP
    targetPort: 8084
    nodePort: 30008  ←nodePort設定を追加
  - name: monitoring
    port: 8008
    protocol: TCP
    targetPort: 8008
  selector:
    load-balancer-spin-gate: "true"
  sessionAffinity: None
  type: NodePort  ←type:をNodePortに変更
status:
  loadBalancer: {}

これで、spin-deckの9000番ポートに30009番ポートから、spin-gateの8084番ポートに30008番ポートからアクセスできるようになる。

$ kubectl -n spinnaker get svc
NAME                         CLUSTER-IP       EXTERNAL-IP   PORT(S)                         AGE
spin-clouddriver             10.254.102.221   <none>        7002/TCP,8008/TCP               1d
spin-clouddriver-bootstrap   10.254.162.60    <none>        7002/TCP,8008/TCP               1d
spin-deck                    10.254.132.106   <nodes>       9000:30009/TCP,8008:32545/TCP   1d
spin-echo                    10.254.28.49     <none>        8089/TCP,8008/TCP               1d
spin-front50                 10.254.121.107   <none>        8080/TCP,8008/TCP               1d
spin-gate                    10.254.98.155    <nodes>       8084:30008/TCP,8008:32468/TCP   1d
spin-igor                    10.254.82.125    <none>        8088/TCP,8008/TCP               1d
spin-orca                    10.254.116.148   <none>        8083/TCP,8008/TCP               1d
spin-orca-bootstrap          10.254.89.221    <none>        8083/TCP,8008/TCP               1d
spin-redis                   10.254.178.149   <none>        6379/TCP,8008/TCP               1d
spin-redis-bootstrap         10.254.27.173    <none>        6379/TCP,8008/TCP               1d
spin-rosco                   10.254.54.33     <none>        8087/TCP,8008/TCP               1d

以上で設定は完了だ。Kubernetesクラスタを構成するノードの30009番ポートにブラウザでアクセスすれば、Spinnakerの管理画面が表示される。

Spinnakerでのデプロイ管理

続いては、Spinnakerを使ってクラスタ上にアプリケーションをデプロイする流れについて紹介していこう。

「application」を作成する

Spinnakerでは「application(アプリケーション)」という単位でアプリケーションを管理する。applicationに関する操作は、はWeb UIの「Application」タブで行える(図2)。

図2 Web UIの「Application」タブ
図2 Web UIの「Application」タブ

それでは、まずは実際にapplicationを作成してみよう。画面右上の「Actions」をクリックし、続いて表示される「create Application」メニュー項目をクリックする。すると「New Application」というダイアログが表示されるので、必要事項を入力して「Create」をクリックする(図3

図3 「New Application」ダイアログ
図3 「New Application」ダイアログ

ここで必須なのは「Name」(名前)と「Owner Email」(所有者のメールアドレス)だけで、残りは後からでも設定可能だ。これらを入力して「Create」をクリックするとapplicationが作成され、詳細画面が表示される。この画面では表2のようなタブが用意されており、たとえば「Clusters」ではapplicationに関連したコンテナの情報を確認できる(図4)。

図4 applcationの「Clusters」タブ
図4 applcationの「Clusters」タブ
表2 application画面で用意されているタブ
タブ名 行える設定や表示される情報
Pipeline パイプラインを利用したデプロイ管理
Clusters applicationに関連するコンテナ
Tasks 実行した/実行するタスク
Load Balancers ロードバランサ管理
Security Groups ネットワークトラフィックに関するアクセス管理
Config applicationに対する各種設定

サーバーの作成

「Clusters」タブからは、手動でKubernetesクラスタ上にPodを作成する操作を行える。なお、SpinnakerはKubernetes以外のクラスタ環境にも対応しているため、KubernetesにおけるPodを「Server」と呼んでいる。以下でもこれに準じてPodを「サーバー」と呼ぶことにする。

画面上に表示されている「+」ボタンをクリックすると作成するサーバーに関する情報を入力するダイアログが表示されるので、ここに必要事項を入力して「Create」をクリックする(図5)。

図5 「Create New Server Group」ダイアログ
図5 「Create New Server Group」ダイアログ

すると作業の進捗を表示する画面が表示され、作業が完了するとその旨が表示される(図6)。

図6 作業の進捗を示すダイアログが表示される
図6 作業の進捗を示すダイアログが表示される

その後「Clusters」画面に戻ると、作成されたサーバーが表示される(図7)。

図7 作成したサーバーが画面に追加される
図7 作成したサーバーが画面に追加される

なお、ここで作成されたサーバーはKubernetesのReplicaSet機能を使って作成される。そのため、レプリカ数の指定なども可能だ。さらにコマンドや環境変数、使用するポートやリソースなどのオプションを指定することもできる(図8)。

図8 サーバーの作成時には細かくオプションを指定できる
図8 サーバーの作成時には細かくオプションを指定できる

作成したサーバーに対する各種操作は「Server Group Actions」ドロップダウンメニューから行える(図9)。

図9 「Server Group Actions」からロールバックやリサイズ、無効化、削除、クローンといった操作を行える
図9 「Server Group Actions」からロールバックやリサイズ、無効化、削除、クローンといった操作を行える

ちなみにここから実行できる「Destroy(削除)」と「Disable(無効化)」の違いだが、Destroyではサーバーが削除されるのに対し、Disableでは削除は行われず、ロードバランサに対しそのサーバーへのルーティングを行わないよう設定するという違いがある。

パイプラインの作成

継続的インテグレーションや継続的デリバリでは、なんらかの通知をトリガーとして処理を実行し、その処理が完了した際にそれを受けて続く処理を実行する、という流れを「パイプライン」と呼ぶ。Spinnakerではあらかじめパイプラインを設定しておくことで、自動的にクラスタ内にコンテナをデプロイできる仕組みとなっている。

パイプラインを作成するには、application画面の「PIPELINE」タブを開き、「Configure a new pipeline」をクリックする(図10)。

図10 application画面の「PIPELINE」タブ
図10 application画面の「PIPELINE」タブ

「Create New Pipeline」ダイアログが表示されるので、ここでパイプライン名(「Pipeline Name」)を入力して「Create」をクリックする(図11)。

図11 「Create New Pipeline」ダイアログ
図11 「Create New Pipeline」ダイアログ

すると新たなパイプラインが作成され、パイプラインの内容を設定する画面が表示される(図12)。

図12 パイプラインの設定画面
図12 パイプラインの設定画面

ここで、まずはパイプラインを起動するトリガーの設定などの設定(Configuration)を行うこととなる。たとえば「Add Trigger」をクリックすると、パイプラインを起動するトリガーを指定できる。トリガーには定期的に実行する「CRON」やGitリポジトリへのプッシュを検知して実行する「Git」、Jenkinsと連携する「Jenkins」などさまざまなものが利用できるが、今回はDocker Registryを監視し、指定されたイメージの新たなバージョンがプッシュされたら実行を開始する「Docker Registry」を利用する(図13)。なお、ここで選択できるのはSpinnakerのデプロイ時に登録しておいたDocker Registryのみなので注意したい。

図13 「Docker Registry」ではDocker Registryへのプッシュをトリガーにパイプラインを実行できる
図13 「Docker Registry」ではDocker Registryへのプッシュをトリガーにパイプラインを実行できる

続いて「Add Stage」をクリックし、パイプラインで実行する処理を追加していく(図14)。

図14 パイプラインに実行する処理を追加する
図14 パイプラインに実行する処理を追加する

ここではまず「Type」で実行する処理の内容を指定する。ここでは表3のような処理を選択可能だ。

表3 Spinnakerで指定できる処理内容
名称 説明
Check Preconditions 事前に実行された処理の進行状況を確認する
Delete (Manifest) Kubernetesオブジェクトを削除する
Deploy イメージをデプロイする
Deploy (Manifest) YAML/JSON形式のKubernetes設定ファイルからデプロイを行う
Destroy Server Group サーバーを削除する
Disable Server Group サーバーを無効にする
Enable Server Group サーバーを有効にする
Find Image from Cluster クラスタ内に存在するイメージを検索する
Jenkins Jenkinsのジョブを実行する
Manual Judgment 手動で管理者の判断を待つ
Pipeline パイプラインを実行する
Resize Server Group サーバーのレプリカ数を変更する
Run Job コンテナを実行する
Scale (Manifest) Kubernetesオブジェクトをスケールさせる
Scale Down Cluster クラスタをスケールダウンさせる
Script スクリプトを実行する
Shrink Cluster クラスタを縮小する
Undo Rollout (Manifest) ロールバックを実行する
Wait 指定した時間待機する
Webhook Webhookを使ってジョブを実行する

今回はイメージをデプロイする「Deploy」を指定した。この場合、「Deploy Configuration」という項目が表示され、ここでデプロイするサーバーの設定を行える。デプロイ設定ではサーバーの作成時と同様にコンテナイメージや各種オプションの設定などが行えるのだが、それに加えてデプロイ完了後に既存のサーバーを無効化/削除するための「Strategy」指定も可能だ(表4)。

表4 デプロイ時に選択できる「Strategy」
名称 説明
Red/Black デプロイ完了後に既存のサーバーを無効にする
Highlander デプロイ完了後に既存のサーバーを削除する
Custom あらかじめ用意しておいた任意の処理を実行する
None デプロイのみを実行し既存のサーバーはそのまま放置する

ここで「Red/Black」や「Highlander」を指定すれば、デプロイの完了後に古いイメージで動いているコンテナを無効化/削除する処理を自動で実行できる。今回は「Highlander」を指定し、デプロイ完了後に古いコンテナを削除するよう設定した。

設定が完了したら、画面右下の「Save Changes」をクリックすることで設定を保存できる。続いてPiplelines画面に戻り、作成したパイプラインの「Start Manual Execution」をクリックすることで手動でパイプラインを起動してテストできる(図15)。

図15 「Start Manual Execution」から作成したパイプラインを手動で起動できる
図15 「Start Manual Execution」から作成したパイプラインを手動で起動できる

これで、「コンテナイメージがプッシュされたらそのイメージから新たなコンテナを作成し、古いコンテナを削除する」という操作を自動化できるようになった。ただ、筆者の環境では既存のタグと同名のタグでイメージをプッシュした場合はパイプラインが起動せず、新しいタグ名を指定しないと正常に動作しなかった。

また、パイプラインの実行結果はPipelines画面で確認できる(図16)。

図16 パイプラインの実行結果はPipelines画面に表示される
図16 パイプラインの実行結果はPipelines画面に表示される

さまざまな処理を自動化可能、ただし独自に構築したクラウドで利用するには注意が必要か

今回はコンテナイメージのプッシュをトリガーにしてそこから自動的にコンテナを作成する、というシンプルなデプロイ方法を紹介したが、Spinnakerではこれ以外にもJenkinsと連動させたり、独自にビルド処理を実行するといったさまざまな処理を実現できる。ユーザーインターフェイスの完成度も高く、うまく活用することでデプロイ作業を効率化できる。

ただ、注意したいのが作成したコンテナを外部に公開する(外部からコンテナに通信をルーティングする)処理についてはロードバランサの実装に依存する点だ。Google Cloud PlatformやMicrosoft Azureといったクラウド環境ではKubernetesと統合されたロードバランサが提供されているが、独自に構築したKubernetesクラスタの場合、Kubernetesと連携して動作するロードバランサを用意するのは簡単ではない。そのため、KubernetesのNodePort機能を使うような設定と組み合わせるといった工夫が必要だろう。