apeescape2.com
  • メイン
  • 製品の担当者とチーム
  • 収益と成長
  • 投資家と資金調達
  • Uxデザイン
技術

GoogleCloud継続的デプロイへのより良いアプローチ

継続的デプロイ(CD)は、新しいコードを本番環境に自動的にデプロイする方法です。ほとんどの継続的デプロイシステムは、ユニットテストと機能テストを実行することにより、デプロイされるコードが実行可能であることを検証し、すべてが正常に見える場合は、デプロイメントがロールアウトされます。通常、ロールアウト自体は、コードが期待どおりに動作しない場合にロールバックできるようにするために段階的に行われます。

AWSスタック、Google Cloudスタック、Bitbucketパイプラインなどのさまざまなツールを使用して独自のCDパイプラインを実装する方法についてのブログ投稿は少なくありません。しかし、それらのほとんどは、優れたCDパイプラインについての私の考えに合わないことがわかりました。次のようになります。最初にビルドし、ビルドされた単一のファイルのみをテストしてデプロイします。

この記事では、イベント駆動型の継続的デプロイパイプラインを構築します。このパイプラインは、最初にビルドしてから、デプロイの最終アーティファクトでテストを実行します。これにより、テスト結果の信頼性が高まるだけでなく、CDパイプラインを簡単に拡張できるようになります。次のようになります。



  1. ソースリポジトリに対してコミットが行われます。
  2. これにより、関連するイメージのビルドがトリガーされます。
  3. テストは、ビルドされたアーティファクトで実行されます。
  4. すべてが良好に見える場合、イメージは本番環境にデプロイされます。

この記事は、Kubernetesとコンテナテクノロジーに少なくともある程度精通していることを前提としていますが、慣れていない場合や復習を使用できる場合は、を参照してください。 Kubernetesとは何ですか?コンテナ化と展開のガイド 。

ほとんどのCDセットアップの問題

ほとんどのCDパイプラインに関する私の問題は次のとおりです。通常、ビルドファイル内のすべてを実行します。これについて私が読んだほとんどのブログ投稿には、ビルドファイルに次のシーケンスのバリエーションがあります(Google CloudBuildの場合はcloudbuild.yaml、Bitbucketの場合はbitbucket-pipeline.yaml)。

  1. テストを実行する
  2. イメージを構築する
  3. 画像をコンテナリポジトリにプッシュ
  4. 新しいイメージで環境を更新します

最終的な成果物に対してテストを実行していません。

この順序で実行することにより、テストを実行します。それらが成功した場合は、イメージを構築し、パイプラインの残りの部分に進みます。ビルドプロセスによってイメージが変更され、テストに合格しなくなった場合はどうなりますか?私の意見では、アーティファクト(最終的なコンテナイメージ)を作成することから始めるべきであり、このアーティファクトはビルドと本番環境にデプロイされる時間の間で変更されるべきではありません。これにより、アーティファクトに関するデータ(テスト結果、サイズなど)が常に有効になります。

ビルド環境には「王国への鍵」があります。

ビルド環境を使用してイメージを本番スタックにデプロイすることにより、本番環境を効果的に変更できるようになります。ソースリポジトリへの書き込みアクセス権を持っている人なら誰でも、本番環境に対してやりたいことができるようになったので、これは非常に悪いことだと思います。

最後のステップが失敗した場合は、パイプライン全体を再実行する必要があります。

最後のステップが失敗した場合(たとえば、資格情報の問題のため)、パイプライン全体を再実行する必要があり、他のことを行うために費やすことができる時間やその他のリソースを消費します。

これは私の最後のポイントに私を導きます:

あなたのステップは独立していません。

より一般的な意味では、独立したステップを持つことで、パイプラインの柔軟性を高めることができます。パイプラインに機能テストを追加したいとします。 1つのビルドファイルにステップを含めることにより、ビルド環境で機能テスト環境を起動し、その中でテストを実行する必要があります(ほとんどの場合は順次)。ステップが独立している場合は、「イメージ構築」イベントによって単体テストと機能テストの両方を開始できます。その後、それらは独自の環境で並行して実行されます。

私の理想的なCDセットアップ

私の意見では、この問題に取り組むためのより良い方法は、一連の独立したステップをすべてイベントメカニズムによってリンクさせることです。

これには、以前の方法と比較していくつかの利点があります。

さまざまなイベントに対して、いくつかの独立したアクションを実行できます。

上記のように、新しいイメージのビルドが成功すると、「ビルドの成功」イベントが公開されます。次に、このイベントがトリガーされたときに、いくつかのことを実行できます。この場合、ユニットテストと機能テストを開始します。ビルド失敗イベントがトリガーされたときや、テストに合格しなかった場合に開発者に警告するなどのことも考えられます。

各環境には、独自の一連の権限があります。

各ステップを独自の環境で実行することにより、単一の環境ですべての権限を取得する必要がなくなります。これで、ビルド環境はビルドのみ、テスト環境はテストのみ、デプロイメント環境はデプロイのみが可能になります。これにより、イメージが作成された後は変更されないことを確信できます。生成されたアーティファクトは、最終的にプロダクションスタックに含まれるアーティファクトです。また、1セットの資格情報を1つのステップにリンクできるため、パイプラインのどのステップが何を行っているかを簡単に監査できます。

より柔軟性があります。

ビルドが成功するたびに誰かにメールを送信したいですか?そのイベントに反応してメールを送信するものを追加するだけです。簡単です。ビルドコードを変更したり、ソースリポジトリに誰かのメールをハードコーディングしたりする必要はありません。

再試行は簡単です。

独立したステップがあるということは、1つのステップが失敗した場合にパイプライン全体を再起動する必要がないことも意味します。失敗状態が一時的なものであるか、手動で修正されている場合は、失敗したステップを再試行できます。これにより、より効率的なパイプラインが可能になります。ビルドステップに数分かかる場合は、デプロイ環境にクラスターへの書き込みアクセス権を付与し忘れたという理由だけで、イメージを再構築する必要がないのは良いことです。

GoogleCloud継続的デプロイの実装

Google Cloud Platformには、このようなシステムを短時間で、非常に少ないコードで構築するために必要なすべてのツールがあります。

私たちのテストアプリケーションは、静的テキストの一部を提供するだけの単純なFlaskアプリケーションです。このアプリケーションは、より広範なインターネットにサービスを提供するKubernetesクラスターにデプロイされます。

以前に紹介したパイプラインの簡略化されたバージョンを実装します。基本的にテスト手順を削除したので、次のようになります。

  • ソースリポジトリに対して新しいコミットが行われます
  • これにより、イメージのビルドがトリガーされます。成功すると、コンテナリポジトリにプッシュされ、イベントがPub / Subトピックに公開されます。
  • 小さなスクリプトがそのサブジェクトにサブスクライブされ、イメージのパラメーターがチェックされます。要求されたものと一致する場合は、Kubernetesクラスターにデプロイされます。

これがパイプラインのグラフィック表現です。

パイプラインのグラフィック表現

フローは次のとおりです。

  1. 誰かが私たちのリポジトリにコミットします。
  2. これにより、ソースリポジトリに基づいてDockerイメージをビルドするクラウドビルドがトリガーされます。
  3. クラウドビルドはイメージをコンテナリポジトリにプッシュし、メッセージをクラウドpub / subにパブリッシュします。
  4. これにより、公開されたメッセージのパラメーター(ビルドのステータス、ビルドされたイメージの名前など)をチェックするクラウド機能がトリガーされます。
  5. パラメータが適切な場合、クラウド関数はKubernetesデプロイメントを新しいイメージで更新します。
  6. Kubernetesは、新しいイメージで新しいコンテナをデプロイします。

ソースコード

私たちのソースコード は非常にシンプルなFlaskアプリで、静的なテキストを提供するだけです。プロジェクトの構造は次のとおりです。

├── docker │ ├── Dockerfile │ └── uwsgi.ini ├── k8s │ ├── deployment.yaml │ └── service.yaml ├── LICENSE ├── Pipfile ├── Pipfile.lock └── src └── main.py

Dockerディレクトリには、Dockerイメージの構築に必要なすべてのものが含まれています。画像はに基づいています uWSGIとNginxの画像 依存関係をインストールして、アプリを正しいパスにコピーするだけです。

k8sディレクトリにはKubernetes設定が含まれています。これは、1つのサービスと1つのデプロイメントで構成されます。デプロイメントは、から構築されたイメージに基づいて1つのコンテナーを開始します Dockerfile 。次に、サービスはパブリックIPアドレスを持つロードバランサーを開始し、アプリコンテナーにリダイレクトします。

クラウドビルド

クラウドビルドの構成自体は、クラウドコンソールまたはGoogleCloudコマンドラインから実行できます。クラウドコンソールを使用することにしました。

クラウドコンソールのスクリーンショット

ここでは、任意のブランチで任意のコミット用のイメージを作成しますが、たとえば、開発用と本番用で異なるイメージを使用できます。

ビルドが成功すると、クラウドビルドは独自にイメージをコンテナレジストリに公開します。次に、cloud-builds pub / subトピックにメッセージを公開します。

クラウドビルドは、ビルドの進行中と失敗したときにもメッセージを公開するため、これらのメッセージに反応させることもできます。

クラウドビルドのpub / sub通知のドキュメントは ここに そしてメッセージのフォーマットは見つけることができます ここに

企業の社会的責任は利益を増やしますか

クラウドパブ/サブ

クラウドコンソールの[cloudpub / sub]タブを見ると、クラウドビルドによってクラウドビルドと呼ばれるトピックが作成されていることがわかります。これは、クラウドビルドがステータスの更新を公開する場所です。

Pub / Subプロジェクトのスクリーンショット

クラウド機能

ここで行うことは、cloud-buildsトピックに公開されたメッセージでトリガーされるクラウド関数を作成することです。ここでも、クラウドコンソールまたはGoogleCloudコマンドラインユーティリティのいずれかを使用できます。私の場合は、クラウドビルドを使用して、変更があるたびにクラウド機能をデプロイします。

クラウド機能のソースコードは ここに 。

まず、このクラウド関数をデプロイするコードを見てみましょう。

steps: - name: 'gcr.io/cloud-builders/gcloud' id: 'test' args: ['functions', 'deploy', 'new-image-trigger', '--runtime=python37', '--trigger-topic=cloud-builds', '--entry-point=onNewImage', '--region=us-east1', '--source=https://source.developers.google.com/projects/$PROJECT_ID/repos/$REPO_NAME']

ここでは、Google CloudDockerイメージを使用します。これにより、GCcloudコマンドを簡単に実行できます。実行しているのは、ターミナルから直接次のコマンドを実行するのと同じです。

gcloud functions deploy new-image-trigger --runtime=python37 --trigger-topic=cloud-builds --entry-point=onNewImage --region=us-east1 --source=https://source.developers.google.com/projects/$PROJECT_ID/repos/$REPO_NAME

Google Cloudに、Python 3.7ランタイムを使用し、cloud-buildsトピックの新しいメッセージによってトリガーされる新しいクラウド関数をデプロイするように依頼しています(または、そのリージョンにその名前の関数が既に存在する場合は置き換えます)。また、その関数のソースコードの場所をGoogleに通知します(ここで、PROJECT_IDとREPO_NAMEは、ビルドプロセスによって設定される環境変数です)。また、エントリポイントとして呼び出す関数も指定します。

ちなみに、これを機能させるには、クラウドビルドサービスアカウントに「クラウド機能開発者」と「サービスアカウントユーザー」の両方を与えて、クラウド機能をデプロイできるようにする必要があります。

クラウド関数コードのコメント付きスニペットを次に示します。

エントリポイントデータには、pub / subトピックで受信したメッセージが含まれます。

def onNewImage(data, context):

最初のステップは、その特定のデプロイメントの変数を環境から取得することです(クラウドコンソールでクラウド機能を変更することによって変数を定義しました。

project = os.environ.get('PROJECT') zone = os.environ.get('ZONE') cluster = os.environ.get('CLUSTER') deployment = os.environ.get('DEPLOYMENT') deploy_image = os.environ.get('IMAGE') target_container = os.environ.get('CONTAINER')

メッセージの構造が期待どおりであることを確認する部分はスキップし、ビルドが成功して1つのイメージアーティファクトが生成されたことを検証します。

次のステップは、ビルドされたイメージがデプロイするイメージであることを確認することです。

image = decoded_data['results']['images'][0]['name'] image_basename = image.split('/')[-1].split(':')[0] if image_basename != deploy_image: logging.error(f'{image_basename} is different from {deploy_image}') return

ここで、Kubernetesクライアントを取得し、変更するデプロイを取得します

v1 = get_kube_client(project, zone, cluster) dep = v1.read_namespaced_deployment(deployment, 'default') if dep is None: logging.error(f'There was no deployment named {deployment}') return

最後に、デプロイメントに新しいイメージをパッチします。 Kubernetesがロールアウトを担当します。

for i, container in enumerate(dep.spec.template.spec.containers): if container.name == target_container: dep.spec.template.spec.containers[i].image = image logging.info(f'Updating to {image}') v1.patch_namespaced_deployment(deployment, 'default', dep)

結論

これは、CDパイプラインで物事を設計する方法の非常に基本的な例です。どのpub / subイベントが何をトリガーするかを変更するだけで、より多くのステップを実行できます。

たとえば、イメージ内でテストを実行し、成功時にイベントを公開し、失敗時に別のイベントを公開するコンテナーを実行し、結果に応じてデプロイメントを更新するかアラートを出すことでそれらに対応できます。

私たちが構築したパイプラインは非常に単純ですが、他の部分のために他のクラウド関数を書くことができます(たとえば、単体テストを壊したコードをコミットした開発者に電子メールを送信するクラウド関数)。

ご覧のとおり、ビルド環境ではKubernetesクラスター内の何も変更できず、デプロイコード(クラウド関数)ではビルドされたイメージを変更できません。特権の分離は見栄えがよく、不正な開発者が本番クラスターをダウンさせないことを知って、しっかりと眠ることができます。また、私たちは私たちのより多くを与えることができます ops指向の開発者 クラウド機能コードにアクセスして、修正または改善できるようにします。

ご質問、ご意見、改善点がございましたら、以下のコメントでお気軽にお問い合わせください。

基本を理解する

継続的デリバリーと継続的デプロイの違いは何ですか?

継続的デリバリーは、いつでも安定したソフトウェアをデリバリーできるようにすることを目的とした手法です。継続的デプロイはこれをさらに一歩進め、前述のソフトウェアを自動的にデプロイします(通常はサービスとしてのソフトウェア環境で)。

デプロイメントパイプラインとは何ですか?

デプロイメントパイプラインは、開発者がアプリケーションのソースコードから本番環境で実行されているアプリケーションに移動できるようにするソフトウェアのコレクションです。これには通常、アプリケーションをビルド、テスト、およびデプロイするためのソフトウェアが含まれます。

従来の継続的デプロイパイプラインの問題は何ですか?

ほとんどの従来の継続的デプロイパイプラインは、新しいアーティファクトを本番環境にプッシュするための資格情報を含むすべての情報を同じ場所に置くことに依存しています。

より良い継続的デプロイパイプラインを作成するにはどうすればよいですか?

理想的には、パイプラインのすべての異なる部分が独立している必要があり、前のステップが成功したときにステップを開始するために何らかのタイプのイベントメカニズムを使用する必要があります。

モバイルユーザビリティの基本ガイド

モバイルデザイン

モバイルユーザビリティの基本ガイド
国際送金市場はどのように進化していますか?

国際送金市場はどのように進化していますか?

財務プロセス

人気の投稿
ApeeScapeは、自動車業界が新興のモビリティ業界に移行する際のソフトウェア開発者のニーズを満たします
ApeeScapeは、自動車業界が新興のモビリティ業界に移行する際のソフトウェア開発者のニーズを満たします
フラックスとバックボーンを使用したReactアプリの単純なデータフロー:例を含むチュートリアル
フラックスとバックボーンを使用したReactアプリの単純なデータフロー:例を含むチュートリアル
Adobe XD vs Sketch – Showdown 2020
Adobe XD vs Sketch – Showdown 2020
欧州連合でビジネスを行う
欧州連合でビジネスを行う
閉じられないAndroidPOSアプリの構築
閉じられないAndroidPOSアプリの構築
 
混合整数計画法:計算による意思決定のガイド
混合整数計画法:計算による意思決定のガイド
開発者向けの設計ワークフロー:より優れたUX / UIを時間と形式で提供
開発者向けの設計ワークフロー:より優れたUX / UIを時間と形式で提供
進化する絵文字:メッセージングの新しい顔のためのデザイン
進化する絵文字:メッセージングの新しい顔のためのデザイン
50の最高のスケッチプラグインの究極のリスト
50の最高のスケッチプラグインの究極のリスト
ブランドイラスト101:ナラティブの視覚化
ブランドイラスト101:ナラティブの視覚化
人気の投稿
  • グラフィックデザインの原則は何ですか
  • 知覚組織のゲシュタルト法
  • 第11章の提出とは
  • 最も人気のあるデータ視覚化ツール
  • ノードjsは新しいエラーをスローします
カテゴリー
製品の担当者とチーム ヒントとツール 人とチーム 財務プロセス アジャイルタレント 製品ライフサイクル 投資家と資金調達 仕事の未来 デザイナーライフ その他

© 2021 | 全著作権所有

apeescape2.com