文字通りすべてが24時間年中無休で稼働する必要がある今日のインターネットの世界では、信頼性が鍵となります。これは、最新リリースのロールアウト中に、Webサイトのダウンタイムがほぼゼロになり、恐ろしい「見つかりません:404」エラーページやその他のサービスの中断を回避することを意味します。
クライアントまたはおそらく自分自身のために新しいアプリケーションを構築し、そのアプリケーションを気に入った優れたユーザーベースを獲得できたとします。ユーザーからフィードバックを収集し、開発者のところに行き、新しい機能を構築してアプリケーションをデプロイできるようにするように依頼します。これで、アプリケーション全体を停止して新しいバージョンをデプロイするか、ダウンタイムゼロのCI / CDデプロイパイプラインを構築して、手動で介入することなく新しいリリースをユーザーにプッシュするという面倒な作業をすべて行うことができます。
この記事では、後者について正確に説明します。Terraformをインフラストラクチャオーケストレーターとして使用して、AWSクラウド上のNode.jsに構築された3層Webアプリケーションの継続的デプロイパイプラインを作成する方法について説明します。使用します ジェンキンス 継続的デプロイ部分とBitbucketがコードベースをホストします。
コードを見つけることができるデモの3層Webアプリケーションを使用します ここに 。
リポジトリには、WebレイヤーとAPIレイヤーの両方のコードが含まれています。これは、ウェブモジュールがAPIレイヤーのエンドポイントの1つを呼び出し、データベースから現在の時刻に関する情報を内部的にフェッチしてウェブレイヤーに戻るシンプルなアプリケーションです。
レポの構造は次のとおりです。
デプロイする必要があるものがわかったので、このアプリケーションをAWSにデプロイするために必要なことについて説明し、次にCI / CDパイプラインのその部分を作成する方法について説明します。
インフラストラクチャオーケストレーターにTerraformを使用しているため、デプロイする層またはアプリケーションごとにプリベークされたイメージを用意するのが最も理にかなっています。そのためには、Hashicorpの別の製品であるPackerを使用します。
Packerは、AWSでのデプロイに使用されるAmazonマシンイメージまたはAMIの構築に役立つオープンソースツールです。 EC2、VirtualBox、VMwareなどのさまざまなプラットフォーム用のイメージを構築するために使用できます。
これは、Packer構成ファイル(terraform/packer-ami-api.json
)を使用してAPIレイヤーのAMIを作成する方法のスニペットです。
{ 'builders': [{ 'type': 'amazon-ebs', 'region': 'eu-west-1', 'source_ami': 'ami-844e0bf7', 'instance_type': 't2.micro', 'ssh_username': 'ubuntu', 'ami_name': 'api-instance {{timestamp}}' }], 'provisioners': [ { 'type': 'shell', 'inline': ['mkdir api', 'sudo apt-get update', 'sudo apt-get -y install npm nodejs-legacy'], 'pause_before': '10s' }, { 'type': 'file', 'source' : '../api/', 'destination' : 'api' }, { 'type': 'shell', 'inline': ['cd api', 'npm install'], 'pause_before': '10s' } ] }
また、AMIを作成するには、次のコマンドを実行する必要があります。
packer build -machine-readable packer-ami-api.json
このコマンドは、この記事の後半でJenkinsビルドから実行します。同様に、WebレイヤーにもPacker構成ファイル(terraform/packer-ami-web.json
)を使用します。
上記のPacker構成ファイルを調べて、何をしようとしているのかを理解しましょう。
inline
を使用してイメージにNode.jsをインストールしますプロパティ。実行するコマンドのセットです。したがって、本質的に、Packer構成には、必要なビルダーに関する情報と、イメージの構成方法に応じて任意の順序で定義できるプロビジョナーのセットが含まれています。
次に、CI / CDパイプラインに使用されるJenkinsサーバーのセットアップについて検討します。これもセットアップにTerraformとAWSを使用します。
Jenkinsを設定するためのTerraformコードは、フォルダーjenkins/setup
内にあります。この設定の興味深い点をいくつか見ていきましょう。
instance.tf
)に提供するか、認証情報ファイルの場所をプロパティshared_credentials_file
に提供することができます。 AWSプロバイダーで。iam.tf
)を作成して、それを使用してJenkinsインスタンスを作成します。backend.tf
)を使用すると、インフラストラクチャの状態をそこに維持できるため、他の同僚と共同作業を行うことができ、状態が離れた場所で管理されます。aws_key_pair
Terraform変数を使用して公開鍵の場所を指定するリソース(key.tf
)。Jenkinsを設定する手順:
ステップ1: Terraformのリモート状態を維持するには、Terraformで使用できるバケットをS3で手動で作成する必要があります。これは、Terraformの外部で実行される唯一のステップです。必ずAWS configure
を実行してください以下のコマンドを実行してAWS認証情報を指定する前に。
aws s3api create-bucket --bucket node-aws-jenkins-terraform --region eu-west-1 --create-bucket-configuration LocationConstraint=eu-west-1
ステップ2: terraform init
を実行します。これにより、状態が初期化され、S3に保存されるように設定され、AWSプロバイダープラグインがダウンロードされます。
プレゼンテーションのデザイン方法
ステップ3: terraform apply
を実行します。これにより、すべてのTerraformコードがチェックされ、プランが作成され、このステップの完了後に作成されるリソースの数が示されます。
ステップ4: yes
と入力すると、前の手順ですべてのリソースの作成が開始されます。コマンドが終了すると、JenkinsサーバーのパブリックIPアドレスを取得します。
ステップ5: 秘密鍵を使用して、JenkinsサーバーにSSH接続します。 ubuntu
AWSEBSでサポートされているインスタンスのデフォルトのユーザー名です。 terraform apply
によって返されたIPアドレスを使用しますコマンド。
ssh -i mykey [email protected]
ステップ6: http://34.245.4.73:8080
に移動して、Jenkins WebUIを開始します。パスワードは/var/lib/jenkins/secrets/initialAdminPassword
にあります。
ステップ7: 「推奨プラグインのインストール」を選択し、Jenkinsの管理者ユーザーを作成します。
echo 'variable 'WEB_INSTANCE_AMI' { default = ''${AMI_ID_WEB}'' }' > amivar_web.tf aws s3 cp amivar_web.tf s3://node-aws-jenkins-terraform/amivar_web.tf
APIとWebモジュールのAMIができたので、ビルドをトリガーして、アプリケーション全体をセットアップするためのTerraformコードを実行し、後でこのパイプラインにサービスのダウンタイムなしで変更をデプロイさせるTerraformコードのコンポーネントを調べます。
nodejs-terraform
を作成します。このプロジェクトは、Terraformコードを実行してアプリケーションをデプロイします。amivar_api.tf
およびamivar_web.tf
)をダウンロードし、Terraformコードを実行してアプリケーション全体をビルドします。 AWS。 すべてが適切に構成されている場合、コードをBitbucketリポジトリにプッシュすると、最初のJenkinsプロジェクトがトリガーされ、次に2番目のプロジェクトがトリガーされ、アプリケーションがAWSにデプロイされます。
httpライブストリーミング.tsファイルをダウンロードしてマージします
次に、このパイプラインがダウンタイムなしでコードをデプロイするのは、Terraformコードの内容について説明します。
まず、Terraformがこれらを提供することです ライフサイクル構成ブロック ために リソース その中であなたはオプションを持っています create_before_destroy
文字通り、Terraformが現在のリソースを破棄する前に同じタイプの新しいリソースを作成する必要があることを意味するフラグとして。
ここで、この機能をaws_autoscaling_group
で活用します。およびaws_launch_configuration
リソース。だからaws_launch_configuration
プロビジョニングするEC2インスタンスのタイプと、そのインスタンスにソフトウェアをインストールする方法、およびaws_autoscaling_group
を設定しますリソースはAWS自動スケーリンググループを提供します。
ここで興味深いのは、Terraformのすべてのリソースに一意の名前とタイプの組み合わせが必要なことです。したがって、新しいaws_autoscaling_group
に別の名前がない限りおよびaws_launch_configuration
、現在のものを破棄することはできません。
Terraformは、name_prefix
を提供することでこの制約を処理しますaws_launch_configuration
へのプロパティ資源。このプロパティが定義されると、Terraformはすべてのaws_launch_configuration
に一意のサフィックスを追加しますリソースを選択すると、その一意の名前を使用してaws_autoscaling_group
を作成できます。資源。
上記のすべてのコードはterraform/autoscaling-api.tf
で確認できます。
resource 'aws_launch_configuration' 'api-launchconfig' { name_prefix = 'api-launchconfig-' image_id = '${var.API_INSTANCE_AMI}' instance_type = 't2.micro' security_groups = ['${aws_security_group.api-instance.id}'] user_data = '${data.template_file.api-shell-script.rendered}' iam_instance_profile = '${aws_iam_instance_profile.CloudWatchAgentServerRole-instanceprofile.name}' connection { user = '${var.INSTANCE_USERNAME}' private_key = '${file('${var.PATH_TO_PRIVATE_KEY}')}' } lifecycle { create_before_destroy = true } } resource 'aws_autoscaling_group' 'api-autoscaling' { name = '${aws_launch_configuration.api-launchconfig.name}-asg' vpc_zone_identifier = ['${aws_subnet.main-public-1.id}'] launch_configuration = '${aws_launch_configuration.api-launchconfig.name}' min_size = 2 max_size = 2 health_check_grace_period = 300 health_check_type = 'ELB' load_balancers = ['${aws_elb.api-elb.name}'] force_delete = true lifecycle { create_before_destroy = true } tag { key = 'Name' value = 'api ec2 instance' propagate_at_launch = true } }
また、ダウンタイムがゼロのデプロイメントでの2番目の課題は、新しいデプロイメントが要求の受信を開始する準備ができていることを確認することです。状況によっては、新しいEC2インスタンスをデプロイして開始するだけでは不十分です。
その問題を解決するには、aws_launch_configuration
プロパティがありますuser_data
ネイティブAWS自動スケーリングをサポートしますuser_data
自動スケーリンググループの一部として、新しいインスタンスの起動時に実行するスクリプトを渡すことができるプロパティ。この例では、アプリサーバーのログを追跡し、起動メッセージが表示されるのを待ちます。 HTTPサーバーをチェックして、いつ起動するかを確認することもできます。
until tail /var/log/syslog | grep 'node ./bin/www' > /dev/null; do sleep 5; done
それに加えて、aws_autoscaling_group
でELBチェックを有効にすることもできます。リソースレベル。Terraformが古いインスタンスを破棄する前に、ELBチェックに合格するために新しいインスタンスが追加されたことを確認します。これは、APIレイヤーのELBチェックがどのように見えるかです。 /api/status
をチェックします成功を返すエンドポイント。
resource 'aws_elb' 'api-elb' { name = 'api-elb' subnets = ['${aws_subnet.main-public-1.id}'] security_groups = ['${aws_security_group.elb-securitygroup.id}'] listener { instance_port = '${var.API_PORT}' instance_protocol = 'http' lb_port = 80 lb_protocol = 'http' } health_check { healthy_threshold = 2 unhealthy_threshold = 2 timeout = 3 target = 'HTTP:${var.API_PORT}/api/status' interval = 30 } cross_zone_load_balancing = true connection_draining = true connection_draining_timeout = 400 tags { Name = 'my-elb' } }
これで、この記事の終わりになります。うまくいけば、これまでに、JenkinsデプロイメントとTerraformのベストプラクティスを使用してダウンタイムゼロのCI / CDパイプラインでアプリケーションをデプロイして実行しているか、この領域を探索してデプロイメントに手動の介入をほとんど必要としないようにすることに少し慣れています。可能。
この記事では、使用されている展開戦略をBlue-Green展開と呼びます。現在のインストール(Blue)は、新しいバージョン(Green)の展開とテスト中にライブトラフィックを受信し、新しいバージョンがすべての準備ができました。この戦略とは別に、アプリケーションをデプロイする方法は他にもあります。これについては、この記事で詳しく説明しています。 展開戦略の概要 。別の戦略の適応は、Jenkinsパイプラインを構成するのと同じくらい簡単になりました。
また、この記事では、API、ウェブ、データレイヤーのすべての新しい変更に互換性があることを前提としているため、新しいバージョンが古いバージョンと通信することを心配する必要はありません。しかし、実際には、常にそうであるとは限りません。この問題を解決するには、新しいリリース/機能を設計する際に、常に下位互換性レイヤーについて考えてください。そうしないと、その状況を処理するためにデプロイメントを微調整する必要があります。
統合テストは、このデプロイメントパイプラインにも欠けているものです。テストせずにエンドユーザーに何もリリースしたくないので、これらの戦略を自分のプロジェクトに適用するときは、間違いなく覚えておく必要があります。
Terraformの仕組みと、テクノロジーを使用してAWSにデプロイする方法について詳しく知りたい場合は、お勧めします Terraform AWSクラウド:健全なインフラストラクチャ管理 ここでは、仲間のApeeScapeerRadosławSzalskiがTerraformについて説明し、チーム用にマルチ環境で本番環境に対応したTerraformセットアップを構成するために必要な手順を示します。
関連: TerraformとCloudFormation:決定的なガイドTerraformは、バージョン管理されたインフラストラクチャコードを簡単に作成できるツールです。これを使用して、AWS、Alicoud、GCP、Azure、OpenStackなどの100を超えるさまざまなサービスプロバイダーのインフラストラクチャを調整できます。
継続的インテグレーションと継続的デプロイは、コードが変更されるたびにソフトウェアを統合してテストする方法です。その後、そのコードは本番環境にデプロイされます。主な利点は、展開中の手作業と人的エラーの可能性を減らすことです。
製品と技術的な実装方法に応じて、ローリング戦略、再作成戦略、青緑色、A / Bテスト、カナリア展開、またはシャドウ戦略を選択できます。
Packerは、AWS EC2、Virtual Box、VMWareなどのさまざまなプラットフォーム用のマシンイメージを簡単に構築できるようにするツールです。
Jenkinsは、ソフトウェアチームがプロジェクトの統合パイプラインを構築できるようにする継続的インテグレーションツールです。 Jenkinsを利用したパイプラインをカスタマイズして、ビルド、テスト、ステージングなどのさまざまなソフトウェア開発プロセスを含めたり、コードの静的分析を実行したりできます。
いいえ。Terraformはツールであり、Hashicorp構成言語(HCL)を使用してインフラストラクチャをコードとして記述します。 HCLは宣言型言語であり、必要なステップではなく、目的の状態を定義します。