はじめに
カナリアリリース/カナリーリリース(Canary Release)とはサービスを一部ユーザーのみが利用できるようにリリースし、問題がないことを確認しながら段階的に全体に向けて展開していくデプロイ手法を指します。
本記事では2種類のnginxのバージョンをカナリーデプロイメントにて共存させる流れをハンズオン形式で実践します。
事前準備
以下デプロイメントとサービスのyamlファイルがあるとします。
$ cat nginx-deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment labels: app: nginx spec: replicas: 10 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.7.9 ports: - containerPort: 80
$ cat nginx-service.yaml apiVersion: v1 kind: Service metadata: name: nginx spec: type: LoadBalancer selector: app: nginx ports: - protocol: TCP port: 60000 targetPort: 80
レプリカ数は10になっているのでデプロイメントを起動すると以下のように10個のPodが立ち上がり
> kubectl apply -f .\nginx-deployment.yaml deployment.apps/nginx-deployment created > kubectl get pods NAME READY STATUS RESTARTS AGE nginx-deployment-5754944d6c-6425z 1/1 Running 0 12s nginx-deployment-5754944d6c-6sssz 1/1 Running 0 12s nginx-deployment-5754944d6c-872dh 1/1 Running 0 12s nginx-deployment-5754944d6c-8tm6d 1/1 Running 0 12s nginx-deployment-5754944d6c-8vwrm 1/1 Running 0 12s nginx-deployment-5754944d6c-b2z66 1/1 Running 0 12s nginx-deployment-5754944d6c-dmj4d 1/1 Running 0 12s nginx-deployment-5754944d6c-l4rt8 1/1 Running 0 12s nginx-deployment-5754944d6c-vd2w2 1/1 Running 0 12s nginx-deployment-5754944d6c-z6sdz 1/1 Running 0 12s
サービスを起動すれば
> kubectl apply -f .\nginx-service.yaml service/nginx created > kubectl get service NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE nginx LoadBalancer 10.X.X.X localhost 60000:32040/TCP 3s
localhostにてnginxの起動が確認できます。
カナリアリリース
サービスの確認のために存在しないURLに対してリクエストを行うと以下のようにバージョンと共にエラーが返ってきます。
$ curl localhost:60000/hoge <html> <head><title>404 Not Found</title></head> <body bgcolor="white"> <center><h1>404 Not Found</h1></center> <hr><center>nginx/1.7.9</center> </body> </html>
もちろん1000回リクエストを繰り返しても結果は1000回とも同じバージョンでエラーが返ってきます。
$ for i in `seq 1 1000`;do curl localhost:60000/hoge 2> /dev/null| grep hr;done | sort | uniq -c 1000 <hr><center>nginx/1.7.9</center>
ここでimageを以下とした別名のnginx-canary.yamlを
用意してレプリカ数を1で起動すれば
image: nginx:1.7.8
以下のように一つだけ異なるデプロイメントでPodが起動し
> kubectl apply -f .\nginx-canary.yaml deployment.apps/nginx-canary created > kubectl get pods NAME READY STATUS RESTARTS AGE nginx-canary-5c8784fd6d-ctqzk 1/1 Running 0 4s nginx-deployment-5754944d6c-6425z 1/1 Running 0 20m nginx-deployment-5754944d6c-6sssz 1/1 Running 0 20m nginx-deployment-5754944d6c-872dh 1/1 Running 0 20m nginx-deployment-5754944d6c-8tm6d 1/1 Running 0 20m nginx-deployment-5754944d6c-8vwrm 1/1 Running 0 20m nginx-deployment-5754944d6c-b2z66 1/1 Running 0 20m nginx-deployment-5754944d6c-dmj4d 1/1 Running 0 20m nginx-deployment-5754944d6c-l4rt8 1/1 Running 0 20m nginx-deployment-5754944d6c-vd2w2 1/1 Running 0 20m nginx-deployment-5754944d6c-z6sdz 1/1 Running 0 20m
同一のリクエストを飛ばしても
$ for i in `seq 1 1000`;do curl localhost:60000/hoge 2> /dev/null| grep hr;done | sort | uniq -c 93 <hr><center>nginx/1.7.8</center> 907 <hr><center>nginx/1.7.9</center>
約1:10の割合で別バージョンにリクエストがいっていることが分かります。カナリアリリースが成功です。
終わりに
カナリアリリースでは、以下のロールアウトではなく明示的に共存をさせます。そして問題が無ければ明示的に割合を変えていくことも可能です。
炭鉱で毒ガスを検知する「カナリア」から来ている本手法ですが、DevOpsにおけるリリースの形としてはよく見るので実際に動かしながらイメージを掴むと良いと思います。
以上、ご参考になれば幸いです。