今回はArgoCDで管理しているアプリに対してkubernetes上でBule/Green Deploymentをできる様にしてくれる Argo Rolloutsを使用して Blue/Green Deploymentを行う方法を紹介していきます。
環境
Amazon EKS(Fargateを使用しています): 1.16 argocd : 1.6.1 argo-rollouts: 0.9.0 kustomize: 3.8.2
この様な環境で作業を行いました。
EKSの作成などは省略します。 eksctlで作成するのでも問題ありませんが毎回面倒なのでコードで管理したい場合はterraformなどを使用して環境を作成されるのをお勧めします。
前提としてArgoRollouts以外のツールを最低限使用できるという前提で考えています。
アプリケーションのデプロイ
最初にArgoCDにも接続していない簡単なアプリケーションのデプロイを行います。
僕は簡単なレスポンスを返すアプリでも構いませんし公式のレポジトリで配布されているnginxを使用しても構いません。
--- apiVersion: apps/v1 kind: Deployment metadata: name: sample-app-deployment spec: selector: matchLabels: app: sample-app template: metadata: labels: app: sample-app spec: containers: - name: app-container image: 好みのimageを使用してください。 ports: - containerPort: 8080 --- apiVersion: v1 kind: Service metadata: name: sample-app-service spec: type: NodePort ports: - port: 80 targetPort: 8080 protocol: TCP selector: app: sample-app
この様な簡単なアプリケーションをkustomizeを使用してデプロイします。
Ingressを使用して外部との通信をできるようにします。 ALB Ingress Controllerを使用しているのでAWSの公式の方法でalb-ingress-controllerをデプロイしてみてください。 Ingressリソースの部分は先ほど作成したServiceに対してトラフィックを流せるようにしたいので編集します
--- apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: name: app-a-ingress annotations: kubernetes.io/ingress.class: alb alb.ingress.kubernetes.io/scheme: internet-facing alb.ingress.kubernetes.io/target-type: ip alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80},{"HTTPS": 443}]' alb.ingress.kubernetes.io/certificate-arn: <ACMで作成した場合のarn> alb.ingress.kubernetes.io/actions.ssl-redirect: '{"Type": "redirect", "RedirectConfig": { "Protocol": "HTTPS", "Port": "443", "StatusCode": "HTTP_301"}}' spec: rules: - http: paths: - path: /* backend: serviceName: ssl-redirect servicePort: use-annotation - path: / backend: serviceName: sample-app-service servicePort: 80 - path: /app-a backend: serviceName: sample-app-service servicePort: 80
次にArgoCDのデプロイです。
ArgoCD
公式の導入方法で導入していただいても構いません
コードでArgoCDを管理してkustomizeでデプロイする際は以下の様にしてワンライナーでbaseを作成できお勧めの使用方法なのでこの方法で試してみてください。
bases: - github.com/argoproj/argo-cd/manifests/cluster-install?ref=v1.6.1
GUIの操作やコードで管理するなどのことは今回は割愛しますが実際にはGithubリポジトリとの接続などをmanifest上で管理することをお勧めします。 Githubと接続し参照するmanifestを指定することができたら次のステップ、Argo Rolloutsの導入に進みます。
Argo Rolloutsの導入
こちらも特に指定の方法はなく公式の方法で導入して頂いて構いません。
コードで管理したい場合、Argo RolloutsもArgoCD同様の方法でワンライナーでbaseを作成できるので kustomization.yamlに以下の様に記述してください。
bases: - github.com/argoproj/argo-rollouts/manifests/cluster-install?ref=v0.9.0
これで導入することはできます。 kusotmizeだとoverlaysなどで環境毎に設定を変更することができるのですが今回変更することはないのでそのまま進みます。 もしimageの更新などを開発環境だけ適用させたいなどあればそれぞれの環境配下でpatchを当ててkustomizeで更新していく方法をとって各環境問題なく動作していれば最終的にbase側を更新するなどの対応をとってもいいと思います。
今回はnamespaceの作成もkustomizeの一貫で作成したいので namespace.yamlを作成してそこで作っていきましょう。
apiVersion: v1 kind: Namespace metadata: name: argo-rollouts
kustomization.yamlで反映します。
--- namespace: argo-rollouts commonLabels: region: ap-northeast-1 bases: - ../../../bases/argo-rollouts resources: - namespace.yaml
こうすることでnamespace、argo-rollouts
が作成され各リソースも作成したnamespaceで作成されます。
DeploymentをRolloutに置き換える
ではここから実際にBule/Green Deploymentを行えるようにする Rollout リソースを作成していきます。
Rolloutリソースは Argo RolloutsでBule/Greenを行うために Deploymentのstrategyフィールドに Blue/Green DeploymentとCanary Releaseを実現するために拡張したCRDになります。
なので先ほど作成したDeploymentのリソースをRolloutに置き換えます
--- apiVersion: argoproj.io/v1alpha1 #apps/v1から置き換え kind: Rollout #Deploymentから置き換え metadata: name: sample-app-deployment spec: selector: matchLabels: app: sample-app template: metadata: labels: app: sample-app spec: containers: - name: app-container image: 好みのimageを使用してください。 ports: - containerPort: 8080 #ここから下がBule/Greenの設定 strategy: blueGreen: activeService: sample-app-service previewService: sample-app-preview-service autoPromotionEnabled: false
apiVersion
とkindの部分を置き換えましたが注目して欲しいのは strategy
のフィールドです。
ここでbuleGreenやcanaryを指定してデプロイメントの戦略を決めていきます。
今回はBule/Greenでやっていくので blueGreen
を選択してその下のフィールドを設定します。
activeService、previewServiceはそれぞれ本番で稼働しているserviceと検証のために立ち上げているserviceの2種類でactiveServiceに本番で使用するServiceリソースの metadata.name
を previewで使用したいServiceの metadata.name
を記入するようにしてください。
autoPromotionEnabledはpreviewのServiceが立ち上がったら自動的に昇格するか否かを決めるフィールドでdefaultではtureになっています。 今回のBule/Greenでは検証して問題なければ昇格をさせたいのでfalseに値を設定しています。
昇格させる際はargo rolloutのCLIを使用できるkubectlプラグインがありますので以下を参考にして使えるようにしてください。
ServiceとIngressもpreview用に作成します。
--- apiVersion: v1 kind: Service metadata: name: sample-app-preview-service labels: app: sample-app spec: type: NodePort ports: - port: 80 targetPort: 8080 protocol: TCP selector: app: sample-app --- apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: name: sample-app-preview-ingress annotations: kubernetes.io/ingress.class: alb alb.ingress.kubernetes.io/scheme: internet-facing alb.ingress.kubernetes.io/target-type: ip alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80},{"HTTPS": 443}]' alb.ingress.kubernetes.io/certificate-arn: <ACMのarn> alb.ingress.kubernetes.io/actions.ssl-redirect: '{"Type": "redirect", "RedirectConfig": { "Protocol": "HTTPS", "Port": "443", "StatusCode": "HTTP_301"}}' spec: rules: - http: paths: - path: /* backend: serviceName: ssl-redirect servicePort: use-annotation - path: / backend: serviceName: sample-app-preview-service servicePort: 80 - path: /app-a backend: serviceName: sample-app-preview-service servicePort: 80
この設定で先ほどのRollout含めリリースするとServiceとIngressがそれぞれ作成されます。
DeploymentからRolloutにリソースを変更した時の最初の状態はこのような状態になります
Podに関しては最初は一つしかできてないですがGitOpsのフローに乗ってimage tagが更新されマージされた際に通常であればpodが更新されると思うのですがRolloutリソースがpreview用のPodを作成してくれます。
これによって先ほど作成したIngressで作成したALBからアクセスして検証することができるようになります。
最後にこの変更が問題なくサービスに展開したいのであれば
kubectl argo rollouts promote <rollout-service>
これを実行することでpreviewで動いているPodを昇格させることができこれでBule/Greenデプロイの完了です。 また最初のような状態に戻り今まで本番で動いていたPodはしばらくすると自動的に削除されます。
簡単なステップでBule/Green デプロイメントを実行することができました。 Ingressのリソースがずっと残ってしまうので費用がかかったりArgoCD側の方でたまに変な挙動になったりと不具合もありそうですが動作としては問題なく使えていました。
今回はあくまで自分の環境下で行いましたがArgoCD上から rollouts promote
コマンドを使えないか、もし使えないのであればChatOpsなどを導入して実行するなどの必要があるかもしれないです。
Argo RolloutsのGUIの画面などもみれたような気がするので今後も調べてみたいと思います。
2020年9月1日追記
ArgoCDのGUI上から実行できることがわかったので方法を追記します。
Rolloutリソースを追加した状態でリリースを行いArgoCDのGUIからRolloutリソースをクリックすると以下のようにメニューが表示されます
その項目のResumeを押すことでBuleを昇格させることができる = kubectl argo rollouts promote <rollout-service>
と同等のことができるようになります。