概要
ゼットラボではいくつかの CI/CD ツールを利用していますが、その中の一つが Concourse です。Concourse はパイプラインベースの CI/CD ツールで Pivotal により開発されています。Concourse から Kubernetes にアプリケーションをデプロイするための Concourse リソースに我々の要件を満たすものが存在しなかったため、新たに開発し OSS (MIT License) として公開しています。
Kubernetes にどのようにアプリケーションをデプロイするか
Kubernetes にアプリケーションをデプロイするには Kubernetes を操作するための CLI である kubectl を利用します。
- kubectl run: 特定のコンテナイメージをクラスタで実行する
- kubectl create: リソースを作成する(既に作成済の場合は実行に失敗する)
- kubectl delete: リソースを削除する
- kubectl apply: リソースに設定を適応する
- kubectl get: 一つまたは複数のリソースの情報を表示する
この他にも多くのサブコマンドが用意されており、これらを組み合わせてアプリケーションをデプロイします。Kubernetes はアプリケーションの構成を Pod, Service, Volume など複数の「リソース」を組み合わせて表現します。そのため、デプロイというのはリソースを操作することと同義です。
これらのサブコマンドを駆使してリソースを管理する手法を3つ紹介します。
Imperative command
Imperative command はおもに kubectl run などの一度限りのコマンドを利用してアプリケーションをデプロイする方法です。以下の例は、nginx:latest イメージをレプリカ数5で myapp という名前で作成します。この手法はアプリケーションの設定を詳細に設定できないため、開発用途など一時的に実行したい場合に利用します。
# Start a replicated contianer of nginx
$ kubectl run myapp --image=nginx:latest --replicas=5
Imperative object configuration
Imperative object configuration はリソースの設定をマニフェストファイルとして YAML または JSON としてファイルに記載し、kubectl create や kubectl delete などを利用してリソースを作成、削除します。この方法は Imperative command と比較してアプリケーションの設定をファイルとして記載するため、バージョン管理することができます。ただしこれらのコマンドはリソースが既に作成されていたり、削除されていて存在しない場合に実行に失敗します。
# Create a resource by a manifest file
$ kubectl create -f nginx-deployment.yaml
Declarative object configuration
Declarative object configuration をマニフェストファイルを kubectl apply のみを利用してリソースを作成、削除します。kubectl apply は kubectl create と比較して既にリソースが存在していればそれを更新し、存在していなければ作成します。また更新方法も他のコマンドによるリソースの操作に干渉しないものとなっており、CD としてアプリケーションを継続的にデプロイするにはもっとも適しています。
# Create/Update a resource by a manifest file
$ kubectl apply -f nginx-deployment.yaml
kubectl apply の挙動についてより詳しく知りたいなら kubectl apply の仕組み / How kubectl apply works を参照してください。
Concourse で Kubernetes にアプリケーションを継続的にデプロイする
Concourse から Kubernetes を操作するには zlabjp/kubernetes-resource を利用できます。これは Concourse リソースとして動作し、クラスタに対して kubectl を使った任意のコマンドを実行できます。またアプリケーションをデプロイする上で便利な機能を備えています。
Versions
このリソースは下記のような複数のバージョンを提供しています。バージョンは kubectl のバージョンと紐付いているため、Kubernetes クラスタのバージョンと同一のバージョンを利用することを推奨します。
-
zlabjp/kubernetes-resource:1.8(stable-1.8) -
zlabjp/kubernetes-resource:1.7(stable-1.7) -
zlabjp/kubernetes-resource:1.6(stable-1.6) -
zlabjp/kubernetes-resource:latest(latest)
ソース設定
kubeconfig ファイルを直接渡す方法とクラスタコンフィグを個々に設定する方法の二つを提供します。
kubeconfig
-
kubeconfig: 任意. kubeconfig ファイルkubeconfig: | apiVersion: v1 clusters: - cluster: ...
kubeconfig ファイルの生成には zlabjp/kubernetes-scripts に含まれる create-kubeconfig スクリプトを利用すると便利です。
# Create a kubeconfig to access the apiserver with the specified serviceaccount and outputs it to stdout.
$ ./create-kubeconfig <serviceaccount-name> <kubectl-options>
クラスタ設定
-
server: 任意. API サーバとアドレスとポート。tokenが必須です。 (e.g.https://192.168.99.100:8443 -
token: 任意. API サーバの認証に利用するトークン。serverが必須です。 (e.g.eyj.... -
namespace: 任意. ネームスペース。デフォルトはdefaultです。 -
certificate_authority: 任意. 認証局の証明書です。 -
insecure_skip_tls_verify: 任意. もしtrueなら、API サーバの証明書の有効性を確認しません。HTTPS が安全ではなくなります。デフォルトはfalseです。
動作
out のみの実装です。
check: 何もしない
in: 何もしない
out: Kubernetes クラスタを操作する
kubectl apply や kubectl delete, kubectl label などのような Kubernetes クラスタの操作を行う。
パラメータ
-
kubectl: 必須.kubectlに続く任意のコマンドを指定します。(e.g.apply -f ... -
wait_until_ready: 任意. 全ての Pods が Ready になるまで待機する秒数です。0 なら待機しません。デフォルトは30です。 -
wait_until_ready_interval: 任意. 全ての Pods が Ready かどうか確認する間隔(秒)です。デフォルトは3です。 -
wait_until_ready_selector: 任意. Ready かどうか確認する Pods を絞り込むラベルセレクタです。デフォルトはネームスペース内の全ての Pods です。
Kubernetes は非同期の分散システムのため、リソースの操作はスペックさえ満たしていればコマンドとしては成功しますが、実際には例えばコンテナイメージのバージョンが存在しないものが指定されている場合などデプロイに失敗している場合があります。そのような場合にジョブを失敗させるために wait_until_ready を用意しています。これはそのネームスペースの Pod が Running になるまで待機します。もし指定された時間内に Pod が全て Running にならなければジョブが失敗します。対象の Pod を絞り込むには wait_until_ready_selector を利用してください。またこの機能によってデプロイ後に e2e テストを実施する場合にコンテナが起動する前にテストを実行してしまうことを防ぐことができます。
パイプライン例
repo リポジトリに含まれるマニフェストファイルの更新をトリガに prod クラスタに対して kubectl apply を実行しています。
resource_types:
- name: kubernetes
type: docker-image
source:
repository: zlabjp/kubernetes-resource
tag: "1.8"
resources:
- name: prod
type: kubernetes
source:
kubeconfig: ((prod-kubeconfig))
- name: repo
type: git
source:
...
jobs:
- name: prod-deploy
plan:
- get: repo
trigger: true
- put: prod
params:
kubectl: apply -f repo/deploy -f repo/deploy/prod
wait_until_ready_selector: app=myapp
kubectl パラメータはコマンド置換に対応しているため、下記のような使い方もできます。
jobs:
- name: force-update-deployment
serial: true
plan:
- put: mycluster
params:
kubectl: |
patch deploy nginx -p '{"spec":{"template":{"metadata":{"labels":{"updated_at":"'$(date +%s)'"}}}}}'
wait_until_ready_selector: run=nginx
まとめ
zlabjp/kubernetes-resource は Kubernetes クラスタを操作する Concourse リソースです。kubectl のさまざまなサブコマンドを駆使してクラスタを操作することができます。下記リポジトリにこのリソースを利用したデモのパイプラインを用意しています。こちらも参考にしてください。
おわりに
このエントリは、弊社 Z Lab のメンバーによる Z Lab Advent Calendar 2017 の一日目として業務時間中に書きました。二日目は @Ladicle による Istio 入門です。
