Jenkins

Jenkins

Jenkins is an open source continuous integration tool written in Java, that has packages for Linux, Mac OS X, Windows, FreeBSD and OpenBSD. The project was forked from Hudson.

Learn Jenkins by Building a CI/CD Pipeline for Web Application

Learn about Jenkins by building a CI/CD pipeline for a web application. Jenkins is an open source automation server which makes it easier to build, test, and deploy software. In this course, you will learn how to build a full dev-ops pipeline using Jenkins, Linode Servers, and other tools.

⭐️ Contents ⭐️
⌨️ (00:00:00) Video Intro
⌨️ (00:01:33) Course Overview
⌨️ (00:02:36) What is Jenkins?
⌨️ (00:08:47) Terms & Definitions
⌨️ (00:11:58) Project Architecture
⌨️ (00:13:28) Linode Intro
⌨️ (00:20:18) Setting Up Jenkins
⌨️ (00:24:11) Tour of Jenkins Interface
⌨️ (00:30:33) Installing Plugins
⌨️ (00:33:39) Blue Ocean
⌨️ (00:34:55) Creating a Pipeline
⌨️ (00:42:37) Installing Git
⌨️ (00:45:15) Jenkinsfile
⌨️ (00:46:27) Updating a Pipeline
⌨️ (00:52:05) Jenkins with nom
⌨️ (00:56:36) Docker & Dockerhub
⌨️ (01:02:14) Closing Remarks

#jenkins #devops #docker #linux #linode #webapp

 

Learn Jenkins by Building a CI/CD Pipeline for Web Application
Coding  Life

Coding Life

1659512271

How to Set Up AWS CodePipeline and CodeDeploy with Jenkins

This video demonstrate the setup of AWS CodePipeline and CodeDeploy with Jenkins.

AWS CodePipeline is a fully managed continuous delivery service that helps you automate your release pipelines for fast and reliable application and infrastructure updates. CodePipeline automates the build, test, and deploy phases of your release process every time there is a code change, based on the release model you define. This enables you to rapidly and reliably deliver features and updates. You can easily integrate AWS CodePipeline with third-party services such as GitHub or with your own custom plugin. With AWS CodePipeline, you only pay for what you use. There are no upfront fees or long-term commitments.

AWS CodeDeploy is a fully managed deployment service that automates software deployments to a variety of compute services such as Amazon EC2, AWS Fargate, AWS Lambda, and your on-premises servers. AWS CodeDeploy makes it easier for you to rapidly release new features, helps you avoid downtime during application deployment, and handles the complexity of updating your applications. You can use AWS CodeDeploy to automate software deployments, eliminating the need for error-prone manual operations. The service scales to match your deployment needs.

Jenkins is a free and open source automation server. It helps automate the parts of software development related to building, testing, and deploying, facilitating continuous integration and continuous delivery. It is a server-based system that runs in servlet containers such as Apache Tomcat.

Reference Link: https://docs.aws.amazon.com/codepipeline/latest/userguide/tutorials-four-stage-pipeline.html 

Subscribe: https://www.youtube.com/c/CloudGurus/featured 

#codepipeline #codedeploy #jenkins 

How to Set Up AWS CodePipeline and CodeDeploy with Jenkins
Coding  Life

Coding Life

1659079549

How to Create a Pipeline Job to Build Node.js and React Application using NPM

Learn how to create a pipeline job to build a node.js and react application using npm. Following will be covered in this video:

- Create Pipeline Job
- Use Pipeline Script from SCM
- Add Pipeline Script into Jenkins File
- Use Blue Ocean Interface
- Add different pipeline stages: Build, Test, Deliver
- Run pipeline job in Jenkins

Github Repository: https://github.com/patebija/simple-node-js-react-npm-app 

Subscribe: https://www.youtube.com/c/QASCRIPT/featured 

#jenkins #nodejs 

How to Create a Pipeline Job to Build Node.js and React Application using NPM
坂本  篤司

坂本 篤司

1658961000

AWSにJenkinsサーバーをデプロイしてTerraformを学ぶ

今日は、プロジェクトを構築してTerraformについて学びます。

Terraformは、運用チームの生産性を高めるための単なるツールではありません。Terraformを実装することで、開発者をオペレーターに変えるチャンスがあります。

これにより、エンジニアリングチーム全体の効率が向上し、開発者とオペレーター間のコミュニケーションが向上します。

この記事では、カスタムベイクドイメージでTerraformを使用して、AWSクラウドへのJenkinsサービスのデプロイを完全に自動化する方法を紹介します。

テラフォームとは?

HashiCorpによるTerraformは、コードソリューションとしてのインフラストラクチャです。これにより、再利用および共有できる人間が読み取れる構成ファイルでクラウドおよびオンプレミスのリソースを指定できます。これは強力なDevOpsプロビジョニングツールです。

なぜTerraformを使用する必要があるのですか?

Terraformには、次の機能を含む多くのユースケースがあります。

  • config / codeでインフラストラクチャを指定し、インフラストラクチャへの変更を簡単に再構築/変更および追跡します。
  • さまざまなクラウドプラットフォームをサポートする
  • リソースの増分変更を実行する
  • ソフトウェア定義ネットワークをサポートする

Terraformの仕組み

Terraformがどのように高レベルで機能するかを見てみましょう。

Terraformは、Goプログラミング言語で開発されています。Goコードは、単一のバイナリであるterraformにコンパイルされます。このバイナリを使用して、ラップトップ、ビルドサーバー、またはその他のほぼすべてのコンピューターからインフラストラクチャを展開できます。そのために追加のインフラストラクチャを実行する必要はありません。

これは、Terraformバイナリが、Azure、AWS、Google Cloud、DigitalOceanなどの1つ以上のプロバイダーに代わってAPI呼び出しを行うためです。これにより、Terraformは、これらのプロバイダーがAPIサーバー用にすでに配置しているインフラストラクチャと、必要な認証プロセスを利用できます。

しかし、Terraformは、どのAPIリクエストを作成するかを知りません。それでは、どのようにしてそれを知るのでしょうか。生成するインフラストラクチャを指定する宣言型言語のテキストファイルであるTerraform構成がその答えです。「コードとしてのインフラストラクチャ」の「コード」は、これらの設定です。

サーバー、データベース、ロードバランサー、ネットワークトポロジなど、インフラストラクチャを完全に制御できます。あなたに代わって、Terraformバイナリはコードを解析し、可能な限り迅速に一連のAPI呼び出しに変換します。

手続き型言語と宣言型言語とは何ですか?

手続き型言語を使用すると、プロセス全体を指定し、それを完了するために必要なステップをリストできます。指示を出し、プロセスの実行方法を指定するだけです。ChefとAnsibleはこの方法を推奨しています。

一方、宣言型言語では、コマンドまたは順序を設定し、システムに任せて実行することができます。プロセスに入る必要はありません。結果が必要です。例としては、Terraform、cloudFormation、Puppeteerなどがあります。

十分な理論...

今こそ、Terraformの高可用性、セキュリティ、パフォーマンス、および信頼性を実行に移す瞬間です。

ここでは、AmazonWebServices上のTerraformベースのJenkinsサーバーについて説明します。ネットワークをゼロからセットアップしているので、始めましょう。

前提条件とインストール

このチュートリアルに従うには、セットアップとインストールが必要なことがいくつかあります。

私たちのプロジェクトのファイル/フォルダ構造

モジュール式の開発戦略を使用して、Jenkinsクラスターのデプロイを(1つの大きなテンプレートファイルを開発するのではなく)多数のテンプレートファイルに分割します。

各ファイルは、ターゲットインフラストラクチャコンポーネントまたはAWSリソースの実行を担当します。

Terraformは、インフラストラクチャ設定を作成および適用するために、HCL(HashiCorp構成言語)と呼ばれるJSONのような構成言語の構文を利用します。

ファイル/フォルダの構造

ファイル/フォルダの構造

Terraform状態を最初に初期化する方法

ベストプラクティスに従うために、Terraform状態ファイルをクラウドストレージに保存します。これは、特にチームのコラボレーションに不可欠です。

Terraform状態ファイルは、プロジェクトのTerraformリソースを含むファイルです。

backend-stateフォルダーのmain.tfファイル内に、次のコードを追加します。

variable "aws_region" { 
	default = "us-east-1" 
 } 
variable "aws_secret_key" {} 
variable "aws_access_key" {} 

provider "aws" { 
	region = var.aws_region 
    access_key = var.aws_access_key 
    secret_key = var.aws_secret_key 
} 

resource "aws_s3_bucket" "terraform_state" { 
	bucket = "terraform-state-caesar-tutorial-jenkins" 
    
    lifecycle { 
    	prevent_destroy = true 
    } 
    
    versioning { 
    	enabled = true 
   } 
   
   server_side_encryption_configuration { 
   		rule { 
        	apply_server_side_encryption_by_default { 
            	sse_algorithm = "AES256" 
            } 
        } 
   } 
}

backend-state / main.tf

上記のコードで何が起こっているのかを確認しましょう。

データを格納するために変数を使用し、Terraformでは、variableキーワードの後に​​名前を付けて変数を宣言します。可変ブロックは、デフォルト、説明、タイプなどのいくつかのプロパティを取得することも、まったく取得しないこともできます。あなたはこれをたくさん見るでしょう。

現在、変数 をとして宣言variable "variable_name"{}し、それらを任意のリソース/データブロックでとして使用していvar.variable_nameます。後で、secrets.tfvarsファイルでこれらの変数に値を割り当てる方法を確認します。

Terraformを使用するには、通信するプロバイダーを通知し、認証に必要なプロパティを渡す必要があります。ここに、AWSリージョン、アクセス、および秘密鍵があります(前提条件からこれらをシステムにダウンロードする必要があります)。

テラフォームでは、必要な各リソースはリソースブロックで定義されます。リソースは、クラウドサービスを作成する下線付きのインフラストラクチャです。構文に従いますresource "terraform-resource-name" "custom-name" {}

Terraformには、terraformドキュメントの特定のプロバイダー向けのリソースがたくさんあります(質問がある場合は、常にドキュメントを参照してください)。

次に、aws_s3_bucketを作成しています。これにより、リモート状態が保存されます。次のプロパティが必要です。

  • バケット→これはグローバルに一意である必要があります
  • ライフサイクル→Terraformリソースを破棄する必要がある場合は、チーム間で共有されるため、状態の破棄を防止することをお勧めします。
  • バージョニング→状態のバージョン管理を提供するのに役立ちます
  • server_side_encryption_configuration →暗号化を提供します。

州のバックエンドの準備が整いました。ただし、初期化、計画、Terraformでの適用の前に、変数をその値に割り当てましょう。

secrets.tfvarsで、AWSアカウントから次の情報を追加します。

  aws_region = "us-east-1 
  aws_secret_key = "enter-your-secret" 
  aws_access_key = "enter-your-access    

backend-state / secrets.tfvars

同じbackend-stateフォルダー内のターミナルで、を実行しますterraform init

ターミナルのテラフォーム状態

ターミナルのテラフォーム状態

次にterraform apply -var-file=secrets.tfvars

ターミナルのテラフォーム状態

ターミナルのテラフォーム状態

AWSコンソールに表示される内容は次のとおりです。

AWSS3バケットのテラフォーム状態

AWSS3バケットのテラフォーム状態

‌‌状態の準備ができたので、次の部分に移りましょう。

AWS仮想プライベートクラウドをプロビジョニングする方法

Jenkinsクラスターを保護するために、仮想プライベートクラウド(VPC)とプライベートサブネット内にアーキテクチャをデプロイします。クラスターはAWSのデフォルトVPCにデプロイできます。

ネットワークトポロジを完全に制御するために、VPCを最初から作成します。

 variable "cidr_block" {} 
 variable "aws_access_key" {} 
 variable "aws_secret_key" {} 
 variable "aws_region" {} 
 
 provider "aws" { 
 	region = var.aws_region 
    access_key = var.aws_access_key 
    secret_key = var.aws_secret_key 
} 

terraform { 
	backend "s3" { 
    	bucket     = "terraform-state-caesar-tutorial-jenkins" 
        key        = "tutorial-jenkins/development/network/terraform.tfstate" 
        region     = "us-east-1" 
        encrypt    = true 
   }
} 

resource "aws_vpc" "main_vpc" { 
	cidr_block           = var.cidr_block 
    enable_dns_support   = true 
    enable_dns_hostnames = true 
    
    tags = { 
    	Name        = "jenkins-instance-main_vpc" 
    } 
}

development / main.tf

output "vpc_id" { 
	value = aws_vpc.main_vpc.id 
} 

output "vpc_cidr_block" { 
	value = aws_vpc.main_vpc.cidr_block 
}  

development / output.tf

cidr_block            = "172.0.0.0/16" 
aws_region = "us-east-1" 
aws_secret_key = "enter-your-secret" 
aws_access_key = "enter-your-access" 

development / secrets.tfvars

  • cidr_block→クラスレスドメイン間ルーティングはCIDRと呼ばれます。CIDRブロックは、簡単に言うとIPアドレス範囲です。これは、私たちが取り組んでいる範囲を定義します。
  • output→ Terraformのoutputブロックは、リソース値を他のモジュールにエクスポートするために使用されます。これは、あるモジュールのリソースデータを別のモジュールの別のリソースに転送する場合のもう1つの重要な用語です。(モジュールが間もなく登場することを学びます)その構文は次のとおりですoutput "custom_output_name" {  value = "resource-name"}。渡されたリソースを取得するキーを受け取ります。ここに、vpc_idとcidr_blockが出力されます。

次に、ターミナルで、を実行terraform initterraform apply てリソースを作成します。前に実行terraform planして、実際に作成しているリソースを確認できます。コマンドは次のとおりです。terraform apply -var-file=secrets.tfvars、および出力は次のとおりです。

s_0475B692F95FDEC0A6E8498B95C86079E0E8D8D5196F9F4DEAA5AA6D3B79CB44_1655907973370_vpc

AWSコンソールにvpc_idとvpc_cidr_blockが表示されます。

awsのvpcリソース

awsのvpc

Terraformモジュールの操作方法

特定のディレクトリにある一般的な構成ファイルのグループは、Terraformモジュールを構成します。Terraformモジュールは、単一の操作に使用されるリソースをまとめます。これにより、同一のインフラストラクチャコンポーネントを作成するために必要なコードの量が削減されます。

以下の構文を使用して、1つのTerraformモジュールリソースを別のリソースに転送して使用できます。

module "custom-module-name" { 
	source     = "path-to-modules-resources" 
}

terraform-modules構文

また、別のリソースモジュール内でモジュールリソース出力を使用するには、次のコマンドを使用しますmodule.custom-module-name.resource-output-value

VPCサブネットを作成する方法

VPCを作成するだけでは不十分です。この分離されたネットワークにJenkinsインスタンスをインストールできるようにするためのサブネットも必要です。このサブネットは以前に構築されたVPCに属しているため、前に出力したVPCIDを渡す必要があります。

復元力のために、異なるアベイラビリティーゾーンで2つのパブリックサブネットと2つのプライベートサブネットを使用します。各サブネットには独自のCIDRブロックがあります。これは、VPCリソースから取得したVPCCIDRブロックのサブセットです。

resource "aws_subnet" "public_subnets" { 
	vpc_id         = var.vpc_id 
    cidr_block     = cidrsubnet(var.vpc_cidr_block, 8, 2 + count.index)  
   	availability_zone   = element(var.availability_zones, count.index)  	
    map_public_ip_on_launch = true 
    count                   = var.public_subnets_count 
    
    tags = { 
    	Name        = "jenkins-instance-public-subnet" 
   } 
} 

resource "aws_subnet" "private_subnets" { 
	vpc_id     = var.vpc_id 
    cidr_block = cidrsubnet(var.vpc_cidr_block, 8, count.index)  			
    availability_zone    = element(var.availability_zones, count.index)  
    map_public_ip_on_launch = false 
    count                   = var.private_subnets_count 
    
    tags = { 
    	Name        = "jenkins-instance-private-subnet" 
    } 
 }

modules/サブネット.tf

さて、このコードで何が起こっているのですか?

  • count countメタ引数は整数を受け入れ、リソースまたはモジュールのその数のインスタンスを作成します。ここでは、変数private_subnets_countとpublic_subnets_countにそれぞれ2つを指定しています。
  • map_public_ip_on_launch→ trueを指定して、サブネットに起動されたインスタンスにパブリックIPアドレスを割り当てる必要があることを示します。
  • cidrsubnet() cidrsubnetは、指定されたIPネットワークアドレスプレフィックス内のサブネットアドレスを計算します。
  • element() elementは、リストから1つの要素を取得します。

それでは、モジュール変数を更新しましょう。

variable "vpc_id" {} 
variable "vpc_cidr_block" {} 
variable "private_subnets_count" {} 
variable "public_subnets_count" {} 
variable "availability_zones" {} 

development / modules / variables.tf

次のようにsecrets.tfvarsを更新します。

private_subnets_count = 2 
public_subnets_count  = 2

secrets.tfvars

VPCサブネットでトラフィックルーティング方法を指定するには、プライベートルートテーブルとパブリックルートテーブルを確立する必要があります。リソースにテラフォーム適用を実行する前に、それを実行しましょう。

VPCルートテーブルを設定する方法

きめ細かい交通管理のためのプライベートルートテーブルとパブリックルートテーブルを開発します。これにより、プライベートサブネットにデプロイされたインスタンスは、一般に公開されることなくインターネットにアクセスできるようになります。

パブリックルートテーブルを作成する方法

まず、インターネットゲートウェイリソースを確立し、それを以前に生成したVPCにリンクする必要があります。次に、パブリックルートテーブルと、すべてのトラフィック(0.0.0.0/0)をインターネットゲートウェイに向けるルートを定義する必要があります。最後に、VPC内のパブリックサブネットとリンクして、ルートテーブルの関連付けを作成することにより、これらのサブネットから流れるトラフィックがインターネットゲートウェイにルーティングされるようにする必要があります。

/*** Internet Gateway - Provides a connection between the VPC and the public internet, allowing traffic to flow in and out of the VPC and translating IP addresses to public* addresses.*/ 
resource "aws_internet_gateway" "igw" { 
	vpc_id = var.vpc_id 
    
    tags = { 
    	Name = "igw_jenkins" 
   } 
} 

/*** A route from the public route table out to the internet through the internet* gateway.*/ 
resource "aws_route_table" "public_rt" { 
	vpc_id = var.vpc_id 
    
    route { 
    	cidr_block = "0.0.0.0/0" 
        gateway_id = aws_internet_gateway.igw.id 
   } 
   
   tags = { 
   		Name = "public_rt_jenkins" 
   } 
} 
/*** Associate the public route table with the public subnets.*/ 
resource "aws_route_table_association" "public" { 
	count     = var.public_subnets_count 
    subnet_id = element(var.public_subnets.*.id, count.index) 
    route_table_id = aws_route_table.public_rt.id 
}

development / modules / public_rt.tf

‌プライベートルートテーブルを作成する方法

パブリックルートテーブルが完成したので、プライベートルートテーブルを作成しましょう。

Jenkinsインスタンスがプライベートサブネットにデプロイされたときにインターネットに接続できるようにするために、パブリックサブネット内にNATゲートウェイリソースを構築します。

その後、 Elastic IPアドレスをNATゲートウェイに追加し、すべてのトラフィックを確立したNATゲートウェイのIDに転送するルート(0.0.0.0/0)を持つプライベートルートテーブルを追加します。次に、ルートテーブルの関連付けを作成して、プライベートサブネットをプライベートルートテーブルにアタッチします。

 /*** An elastic IP address to be used by the NAT Gateway defined below.  The NAT* gateway acts as a gateway between our private subnets and the public* internet, providing access out to the internet from within those subnets,* while denying access to them from the public internet.  This IP address* acts as the IP address from which all the outbound traffic from the private* subnets will originate.*/ 
 
 resource "aws_eip" "eip_for_the_nat_gateway" { 
 	vpc = true 
    
    tags = { 
    	Name = "jenkins-tutoral-eip_for_the_nat_gateway" 
    } 
} 

/*** A NAT Gateway that lives in our public subnet and provides an interface* between our private subnets and the public internet.  It allows traffic to* exit our private subnets, but prevents traffic from entering them.*/ 

resource "aws_nat_gateway" "nat_gateway" { 
	allocation_id = aws_eip.eip_for_the_nat_gateway.id 
    subnet_id     = element(var.public_subnets.*.id, 0) 
    
    tags = { 
    	Name = "jenkins-tutorial-nat_gateway" 
	} 
} 
/*** A route from the private route table out to the internet through the NAT * Gateway.*/ 

resource "aws_route_table" "private_rt" { 
	vpc_id = var.vpc_id 
    
    route { 
    	cidr_block     = "0.0.0.0/0" 
        nat_gateway_id = aws_nat_gateway.nat_gateway.id } 
        
        tags = { 
        	Name   = "private_rt_${var.vpc_name}" 
            Author = var.author 
        } 
} 
/*** Associate the private route table with the private subnet.*/ 
resource "aws_route_table_association" "private" { 
	count = var.private_subnets_count 
    subnet_id = element(aws_subnet.private_subnets.*.id, count.index) 
    route_table_id = aws_route_table.private_rt.id 
}

development / modules / private_rt.tf

‌それでは実行しましょうterraform apply。ただし、main.tfファイル(これはエントリテラフォームファイルであるため)を更新して、サブネットとモジュール変数、およびsecrets.tfvars(変数用)を認識する必要があります。

variable "vpc_id" {} 
variable "vpc_cidr_block" {} 
variable "private_subnets_count" {} 
variable "public_subnets_count" {} 
variable "availability_zones" {} 
variable "public_subnets" {}

development / modules / variables.ftvars

variable "private_subnets_count" {} 
variable "public_subnets_count" {} 
variable "availability_zones" {} 

module "subnet_module" { 
	source     = "./modules" 
    vpc_id     = aws_vpc.main_vpc.id 
    vpc_cidr_block = aws_vpc.main_vpc.cidr_block 
    availability_zones = var.availability_zones 
    public_subnets_count = var.public_subnets_count 
    private_subnets_count = var.private_subnets_count 
 }

development / main.tf

 availability_zones    = ["us-east-1a", "us-east-1b", "us-east-1c", "us-east-1d", "us-east-1e"]

development / secrets.tf

私たちのサブネットとそれぞれの証券は準備ができています。これで、Terraformを初期化、計画、および適用できます。

terraformapplyを実行してリソースを作成します。前にテラフォームプランを実行して、実際に作成しているリソースを確認できます。

ターミナルで実行します。 terraform apply -var-file=secrets.tfvars

s_0475B692F95FDEC0A6E8498B95C86079E0E8D8D5196F9F4DEAA5AA6D3B79CB44_1656906570979_terminal-state-3

ここで追加されたリソースの数は、あなたのリソースとは異なる可能性があることに注意してください。

AWSコンソール(サブネット、エラスティックアドレス、route_tables)は次のとおりです。

サブネット

サブネットエラスティックIPエラスティックIPルートテーブルルートテーブル

VPC要塞ホストをセットアップする方法

Jenkinsクラスターをプライベートサブネット内にデプロイしました。クラスタにはパブリックIPがないため、インスタンスはインターネット経由でパブリックに利用できません。したがって、これを処理するために、Jenkinsインスタンスに安全にアクセスできるように要塞ホストを設定します。

bastion.tfファイルに次のリソースとセキュリティグループを追加します。

/*** A security group to allow SSH access into our bastion instance.*/ 
resource "aws_security_group" "bastion" { 
	name   = "bastion-security-group" 
    vpc_id = var.vpc_id 
    
    ingress { 
    	protocol    = "tcp" 
        from_port   = 22 
        to_port     = 22 
        cidr_blocks = ["0.0.0.0/0"] 
    } 
    egress { 
    	protocol    = -1 
        from_port   = 0 
        to_port     = 0 
        cidr_blocks = ["0.0.0.0/0"] 
   } 
   
   tags = { 
   		Name = "aws_security_group.bastion_jenkins" 
   } 
} 

/*** The public key for the key pair we'll use to ssh into our bastion instance.*/ 

resource "aws_key_pair" "bastion" { 
	key_name   = "bastion-key-jenkins" 
    public_key = var.public_key 
 } 
 
 /*** This parameter contains the AMI ID for the most recent Amazon Linux 2 ami,* managed by AWS.*/ 
 
 data "aws_ssm_parameter" "linux2_ami" { 
 	name = "/aws/service/ami-amazon-linux-latest/amzn-ami-hvm-x86_64-ebs" 
} 

/*** Launch a bastion instance we can use to gain access to the private subnets of* this availabilty zone.*/ 

resource "aws_instance" "bastion" { 
	ami           = data.aws_ssm_parameter.linux2_ami.value 
    key_name      = aws_key_pair.bastion.key_name 
    instance_type = "t2.large" 
    associate_public_ip_address = true 
    subnet_id                   = element(aws_subnet.public_subnets, 0).id 
    vpc_security_group_ids      = [aws_security_group.bastion.id] 
    
    tags = { 
    	Name        = "jenkins-bastion" 
    } 
} 

output "bastion" { value = aws_instance.bastion.public_ip }

bastion.tf

ここのコードで何が起こっているのか見てみましょう:

  • bastionセキュリティグループリソース–新しく生成されたEC2インスタンスはSSHアクセスを許可しません。
  • 要塞ホストへのSSHアクセスを有効にするために、セキュリティグループをアクティブインスタンスにリンクします。ポート22(SSH)での任意の場所(0.0.0.0/0)からのインバウンド(入力)トラフィックは、セキュリティグループによって許可されます。セキュリティを向上させ、セキュリティ違反を防ぐために、CIDRソースブロックの代わりに独自のパブリックIPアドレス/32またはネットワークアドレスを使用できます。
  • aws_key_pair – SSHと秘密鍵を使用して要塞ホストに接続できるようにするために、EC2の作成時にSSH鍵ペアを追加しました。キーペアでは、公開SSHキーが使用されます。sshkeygenコマンドを使用して、新しいコマンドを作成することもできます。
  • aws_ssm_parameter – Amazon2LinuxマシンイメージはEC2インスタンスによって使用されます。AMI IDは、AWSAMIデータソースを使用してAWSマーケットプレイスから取得されます
  • aws_instance –  最後に、定義された構成とアクセスを使用してEC2bastionインスタンスをデプロイします
  • 出力–出力を指定することにより、Terraform出力機能を使用してターミナルセッションのIPアドレスを表示します。

それでは、モジュール内の変数とmain.tfを、変数として渡す新しいpublic_keyで更新しましょう。

variable "public_key"{} 

開発/モジュール/変数/tfvars

varable "public_key" {} 
module "subnet_module" { 
	source     = "./modules" 
    ... 
    publc_key = var.public_key 
}

development / main.tf

public_key = "enter-your-public-key"

development / secrets.tf

terraformapplyを実行してリソースを作成します。前にテラフォームプランを実行して、実際に作成しているリソースを確認できます。

ターミナルで、実行してみましょうterraform apply -var-file=secrets.tfvars

ターミナルリソース

ターミナルリソース

AWSコンソールの出力は次のとおりです。

aws-consoleインスタンス

aws-consoleインスタンス

コンピューティングサービスをプロビジョニングする方法

Jenkinsマスターインスタンス

これまでのところ、VPCとネットワークトポロジを正常にセットアップすることができました。‌‌最後に、Packerによってベイク処理されたJenkinsマスターAMIを使用するJenkinsEC2インスタンスを作成します。

それがどのようにベイクされたかについての私の以前の記事をチェックすることができます:freecodecamp.orgでAWSでカスタムマシンイメージを構築することによってコードとしてのインフラストラクチャを学びます。 とにかく、カスタム画像があれば、それを使用できます。

 /*** This parameter contains our baked AMI ID fetch from the Amazon Console*/ data "aws_ami" "jenkins-master" { 
 	most_recent = true owners      = ["self"] 
} 

resource "aws_security_group" "jenkins_master_sg" { 
	name        = "jenkins_master_sg" 
    description = "Allow traffic on port 8080 and enable SSH" 
    vpc_id      = var.vpc_id 
    
    ingress { 
    	from_port       = "22" 
        to_port         = "22" 
        protocol        = "tcp" 
        security_groups = [aws_security_group.bastion.id] 
   } 
   ingress { 
   		from_port       = "8080" 
        to_port         = "8080" 
        protocol        = "tcp" 
        security_groups = [aws_security_group.lb.id] 
   } 
   ingress { 
   		from_port   = "8080" 
        to_port     = "8080" 
        protocol    = "tcp" 
        cidr_blocks = ["0.0.0.0/0"] 
  } 
  egress { 
  		from_port   = "0" 
        to_port     = "0" 
        protocol    = "-1" 
        cidr_blocks = ["0.0.0.0/0"] 
  } 
  
  tags = { 
  	Name = "jenkins_master_sg" 
  }
} 

development / modules / jenkins_master.tf

セキュリティグループをインスタンスにアタッチすると、ポート8080(Jenkins Webダッシュボード)でのインバウンドトラフィックと、要塞サーバーとVPCCIDRブロックからのSSHのみが有効になります。

resource "aws_key_pair" "jenkins" { 
	key_name   = "key-jenkins" 
    public_key = var.public_key 
} 

resource "aws_instance" "jenkins_master" { 
	ami       = data.aws_ami.jenkins-master.id 
    instance_type  = "t2.large" 
    key_name       = aws_key_pair.jenkins.key_name 
    vpc_security_group_ids = [aws_security_group.jenkins_master_sg.id]
    subnet_id              = element(aws_subnet.private_subnets, 0).id
    root_block_device { 
    	volume_type           = "gp3" 
        volume_size           = 30 
        delete_on_termination = false 
    } 
    
    tags = { 
    	Name = "jenkins_master" 
     } 
 }

development / modules / jenkins_master.tf

次に、変数を作成し、EC2インスタンスのデプロイに使用したインスタンスタイプを定義します。マスターにエグゼキュータまたはワーカーを割り当てることはないため、簡単にするためにt2.large(8 GBのメモリと2vCPU)で十分です。

したがって、ビルドジョブによってJenkinsマスターが過密になることはありません。ただし、Jenkinsのメモリ要件は、プロジェクトのビルド要件とそれらのビルドで使用されるツールによって異なります。各ビルドノードに接続するには、2〜3スレッド、または少なくとも2MBのメモリが必要です。

注:マスターの過労を防ぐために、Jenkinsワーカーをインストールすることを検討してください。その結果、汎用インスタンスはJenkinsマスターをホストし、計算リソースとメモリリソースのバランスをとることができます。記事の簡潔さを維持するために、私たちはそれをしません。

ロードバランサーの作成方法

Jenkinsダッシュボードにアクセスするには、EC2インスタンスの前にパブリックロードバランサーを作成します。

このElasticロードバランサーは、ポート80でHTTPトラフィックを受け入れ、ポート8080でEC2インスタンスに転送します。また、ポート8080で登録されたEC2インスタンスの正常性を自動的にチェックします。ElasticLoadBalancing(ELB)がインスタンスに異常を検出した場合、Jenkinsインスタンスへのトラフィックの送信を停止します。

 /*** A security group to allow SSH access into our load balancer*/ resource "aws_security_group" "lb" { 
 	name   = "ecs-alb-security-group" 
    vpc_id = var.vpc_id 
    
    ingress { 
    	protocol    = "tcp" 
        from_port   = 80 
        to_port     = 80 
        cidr_blocks = ["0.0.0.0/0"] 
     } 
     egress { 
     	from_port   = 0 
        to_port     = 0 
        protocol    = "-1" 
        cidr_blocks = ["0.0.0.0/0"] 
     } 
     
     tags = { 
     	Name = "jenkins-lb-sg" 
      } 
 } 
 
 /***Load Balancer to be attached to the ECS cluster to distribute the load among instances*/ 
 
 resource "aws_elb" "jenkins_elb" { 
 	subnets    = [for subnet in aws_subnet.public_subnets : subnet.id]
    cross_zone_load_balancing = true 
    security_groups       = [aws_security_group.lb.id] 
    instances             = [aws_instance.jenkins_master.id] 
    
    listener { 
    	instance_port     = 8080 
        instance_protocol = "http" 
        lb_port           = 80 
        lb_protocol       = "http" 
     } 
     
     health_check { 
     	healthy_threshold   = 2 
        unhealthy_threshold = 2 
        timeout             = 3 
        target              = "TCP:8080"    
        interval            = 5 
    } 
    
    tags = { 
    	Name = "jenkins_elb" 
    } 
 } 
 
 output "load-balancer-ip" { 
 	value = aws_elb.jenkins_elb.dns_name 
 }

development / modules / loadbalancer.tf

テラフォームを適用する前に、development / output.tfフォルダーを更新して、ロードバランサーのDNSを出力しましょう。

 output "load-balancer-ip" { 
 	value = module.subnet_module.load-balancer-ip
 }

development / output.tf

ターミナルで、次のコマンドを実行しますterraform apply -var-file="secrets.tfvars"。これはあなたにこれを与えるでしょう:

ロードバランサー出力

ロードバランサー出力

Terraformで変更を適用すると、JenkinsマスターロードバランサーのURLがターミナルセッションに表示されます。

お気に入りのブラウザでURLを指定すると、JenkinsWebダッシュボードにアクセスできるはずです。

jenkins-インスタンス

jenkins-インスタンス

次に、画面の指示に従ってロックを解除します。

ジェンキンスのロックを解除する

ジェンキンスのロックを解除する

完全なコードは、このGitHubリポジトリにあります。

清掃

AWSサービスを実行するための不要なコストを回避するには、次のコマンドを実行して、作成および実行中のすべてのリソースterraform destroy -var-file="secrets.tfvars"をます。

リソースを破壊する

リソースを破壊する

どれだけ面白いでしょう?ほんの数行のコードで、リソースを破壊してスピンアップできます。

概要

このチュートリアルでは、Terraformを高レベルで使用する方法を学習しました。また、AWSクラウドプラットフォームでJenkinsサーバーをプロビジョニングすることで、そのアプリケーションの1つを学びました。

また、Terraformバックエンドの状態とモジュールのベストプラクティスについても学びました。

ハッピーラーニング! 

ソース:https ://www.freecodecamp.org/news/learn-terraform-b​​y-deploying-jenkins-server-on-aws/

 #jenkins #aws #terraform

AWSにJenkinsサーバーをデプロイしてTerraformを学ぶ
顾 静

顾 静

1658959380

通过在 AWS 上部署 Jenkins 服务器来学习 Terraform

今天我们将通过构建一个项目来了解 Terraform。

Terraform 不仅仅是提高运营团队生产力的工具。您有机会通过实施 Terraform 将您的开发人员转变为操作员。

这有助于提高整个工程团队的效率并改善开发人员和操作员之间的沟通。

在本文中,我将向您展示如何使用带有自定义烘焙映像的 Terraform 在 AWS 云上完全自动化部署 Jenkins 服务。

什么是 Terraform?

HashiCorp 的 Terraform 是一种基础架构即代码解决方案。它允许您在可以重用和共享的可读配置文件中指定云和本地资源。它是一个强大的 DevOps 配置工具。

为什么要使用 Terraform?

Terraform 有许多用例,包括:

  • 在配置/代码中指定基础设施,轻松重建/更改和跟踪基础设施的更改。
  • 支持不同的云平台
  • 执行增量资源修改
  • 支持软件定义网络

Terraform 的工作原理

让我们来看看 Terraform 在高层次上是如何工作的。

Terraform 是用 Go 编程语言开发的。Go 代码被编译成terraform,一个单一的二进制文件。您可以使用此二进制文件从您的笔记本电脑、构建服务器或几乎任何其他计算机上部署基础架构,并且您无需运行任何额外的基础架构来执行此操作。

这是因为 Terraform 二进制文件代表您向一个或多个提供商发出 API 调用,其中包括 Azure、AWS、Google Cloud、DigitalOcean 等。这使得 Terraform 可以利用这些提供商已经为他们的 API 服务器准备好的基础设施,以及他们需要的身份验证过程。

但是 Terraform 不知道要发出什么 API 请求——那么它是怎么知道的呢?Terraform 配置是声明性语言的文本文件,用于指定要生成的基础设施,就是答案。“基础设施即代码”中的“代码”就是这些设置。

您可以完全控制您的基础架构,包括服务器、数据库、负载平衡器、网络拓扑等。Terraform 二进制文件会代表您解析您的代码,并尽快将其转换为一系列 API 调用。

什么是过程语言与声明性语言?

过程语言允许您指定整个过程并列出完成它所需的步骤。您只需给出说明并指定如何执行该过程。Chef 和 A​​nsible 鼓励这种方法。

另一方面,声明性语言允许您简单地设置命令或命令并将其留给系统来执行。你不需要进入这个过程;你只需要结果。例如 Terraform、cloudFormation 和 Puppeteer。

理论够了...

现在是将 Terraform 的高可用性、安全性、性能和可靠性付诸实践的时候了。

在这里,我们谈论的是 Amazon Web Services 上基于 Terraform 的 Jenkins 服务器。我们正在从头开始建立网络,所以让我们开始吧。

先决条件和安装

您需要设置和安装一些东西才能跟随本教程:

我们项目的文件/文件夹结构

我们将使用模块化开发策略将我们的 Jenkins 集群部署分离为多个模板文件(而不是开发一个大型模板文件)。

每个文件负责执行目标基础设施组件或 AWS 资源。

为了创建和实施基础设施设置,Terraform 利用了一种类似于 JSON 的配置语言的语法,称为 HCL(HashiCorp 配置语言)。

文件/文件夹结构

文件/文件夹结构

如何首先初始化 Terraform 状态

为了遵循最佳实践,我们将把 Terraform 状态文件存储在我们的云存储中。这对于团队协作尤其重要。

Terraform 状态文件是包含项目中 Terraform 资源的文件。

在 backend-state 文件夹的 main.tf 文件中,添加以下代码:

variable "aws_region" { 
	default = "us-east-1" 
 } 
variable "aws_secret_key" {} 
variable "aws_access_key" {} 

provider "aws" { 
	region = var.aws_region 
    access_key = var.aws_access_key 
    secret_key = var.aws_secret_key 
} 

resource "aws_s3_bucket" "terraform_state" { 
	bucket = "terraform-state-caesar-tutorial-jenkins" 
    
    lifecycle { 
    	prevent_destroy = true 
    } 
    
    versioning { 
    	enabled = true 
   } 
   
   server_side_encryption_configuration { 
   		rule { 
        	apply_server_side_encryption_by_default { 
            	sse_algorithm = "AES256" 
            } 
        } 
   } 
}

后端状态/main.tf

让我们确保我们知道上面代码中发生了什么。

我们使用变量来存储数据,在 Terraform 中,您使用 variable 关键字后跟名称来声明一个变量。变量块可以采用一些属性,例如默认值、描述、类型等,也可以没有。你会经常看到这个。

现在我们将变量声明 variable "variable_name"{}在任何资源/数据块中使用它们作为var.variable_name. 稍后您将看到我们将如何在 secrets.tfvars 文件中为这些变量赋值。

要使用 Terraform,您需要告诉它将与之通信的提供者并传递其所需的属性以进行身份​​验证。在这里,我们有 AWS 区域、访问权限和密钥(您应该根据先决条件将这些下载到您的系统上)。

在 terraform 中,我们需要的每个资源都定义在资源块中。资源是创建我们的云服务的基础设施。它遵循语法resource "terraform-resource-name" "custom-name" {}

Terraform 在 terraform 文档中为特定提供者提供了大量资源(如果您有任何问题,请始终参考文档)。

接下来,我们正在创建 aws_s3_bucket。这将存储我们的远程状态。它具有以下属性:

  • bucket → 这必须是全局唯一的
  • 生命周期→ 如果您需要销毁 Terraform 资源,您可能希望防止破坏状态,因为它在团队之间共享
  • 版本控制→ 帮助提供对状态的一些版本控制
  • server_side_encryption_configuration → 提供加密。

我们的状态后端已准备就绪。但是在我们使用 Terraform 对其进行初始化、计划和应用之前,让我们将变量分配给它的值

在 secrets.tfvars 中,从您的 AWS 账户添加以下信息:

  aws_region = "us-east-1 
  aws_secret_key = "enter-your-secret" 
  aws_access_key = "enter-your-access    

后端状态/secrets.tfvars

在同一后端状态文件夹中的终端中,运行terraform init.

终端上的地形状态

终端上的地形状态

然后terraform apply -var-file=secrets.tfvars

终端上的地形状态

终端上的地形状态

在您的AWS 控制台中,您将看到以下内容:

aws s3 存储桶上的 terraform 状态

aws s3 存储桶上的 terraform 状态

‌‌现在我们的状态已经准备好了,让我们进入下一部分。

如何预置 AWS 虚拟私有云

为了保护我们的 Jenkins 集群,我们将在虚拟私有云 (VPC) 和私有子网中部署该架构。您可以在 AWS 默认 VPC 中部署集群。

为了完全控制网络拓扑,我们将从头开始创建一个 VPC。

 variable "cidr_block" {} 
 variable "aws_access_key" {} 
 variable "aws_secret_key" {} 
 variable "aws_region" {} 
 
 provider "aws" { 
 	region = var.aws_region 
    access_key = var.aws_access_key 
    secret_key = var.aws_secret_key 
} 

terraform { 
	backend "s3" { 
    	bucket     = "terraform-state-caesar-tutorial-jenkins" 
        key        = "tutorial-jenkins/development/network/terraform.tfstate" 
        region     = "us-east-1" 
        encrypt    = true 
   }
} 

resource "aws_vpc" "main_vpc" { 
	cidr_block           = var.cidr_block 
    enable_dns_support   = true 
    enable_dns_hostnames = true 
    
    tags = { 
    	Name        = "jenkins-instance-main_vpc" 
    } 
}

开发/main.tf

output "vpc_id" { 
	value = aws_vpc.main_vpc.id 
} 

output "vpc_cidr_block" { 
	value = aws_vpc.main_vpc.cidr_block 
}  

开发/输出.tf

cidr_block            = "172.0.0.0/16" 
aws_region = "us-east-1" 
aws_secret_key = "enter-your-secret" 
aws_access_key = "enter-your-access" 

开发/secrets.tfvars

  • cidr_block →无类域间路由称为 CIDR。CIDR 块是一个 IP 地址范围,简单地说。这定义了我们正在工作的范围。
  • 输出 → Terraform 中的输出块用于将资源值导出到其他模块。这是将一个模块中的资源数据传输到单独模块中的另一个资源时的另一个重要术语。(您将很快了解什么是模块)它的语法如下:output "custom_output_name" {  value = "resource-name"}. 它接受一个键,该键接受传递的资源。这里我们输出 vpc_id 和 cidr_block。

现在,在终端中运行terraform initterraform apply 创建资源。您可以在terraform plan之前运行以查看您实际创建的资源。这是命令:terraform apply -var-file=secrets.tfvars和输出:

s_0475B692F95FDEC0A6E8498B95C86079E0E8D8D5196F9F4DEAA5AA6D3B79CB44_1655907973370_vpc

您应该在AWS 控制台中看到您的vpc_id 和 vpc_cidr_block

aws 上的 vpc 资源

aws 上的 vpc

如何使用 Terraform 模块

特定目录中的一组典型配置文件组成了一个 Terraform 模块。Terraform 模块将用于单个操作的资源放在一起。这减少了创建相同基础架构组件所需的代码量。

使用以下语法,您可以将一个 Terraform 模块资源转移到另一个以供使用。

module "custom-module-name" { 
	source     = "path-to-modules-resources" 
}

terraform-modules 语法

并且要在另一个资源模块中使用模块资源输出,这是命令:module.custom-module-name.resource-output-value

如何创建 VPC 子网

创建一个 VPC 是不够的——我们还需要一个子网才能在这个隔离的网络上安装 Jenkins 实例。我们必须传递我们之前输出的 VPC ID,因为这个子网属于之前构建的 VPC。

为了弹性,我们将在不同的可用区中使用两个公共子网和两个私有子网。每个子网都有自己的 CIDR 块,它是我们从 VPC 资源中获得的 VPC CIDR 块的子集。

resource "aws_subnet" "public_subnets" { 
	vpc_id         = var.vpc_id 
    cidr_block     = cidrsubnet(var.vpc_cidr_block, 8, 2 + count.index)  
   	availability_zone   = element(var.availability_zones, count.index)  	
    map_public_ip_on_launch = true 
    count                   = var.public_subnets_count 
    
    tags = { 
    	Name        = "jenkins-instance-public-subnet" 
   } 
} 

resource "aws_subnet" "private_subnets" { 
	vpc_id     = var.vpc_id 
    cidr_block = cidrsubnet(var.vpc_cidr_block, 8, count.index)  			
    availability_zone    = element(var.availability_zones, count.index)  
    map_public_ip_on_launch = false 
    count                   = var.private_subnets_count 
    
    tags = { 
    	Name        = "jenkins-instance-private-subnet" 
    } 
 }

模块/子网.tf

好的,这段代码发生了什么?

  • count count 元参数接受一个整数,并创建资源或模块的多个实例。这里我们为变量 private_subnets_count 和 public_subnets_count 分别指定 2 个。
  • map_public_ip_on_launch →指定 true 表示应为启动到子网的实例分配公共 IP 地址。
  • cidrsubnet() cidrsubnet 计算给定 IP 网络地址前缀内的子网地址。
  • element() element 从列表中检索单个元素。

现在让我们更新我们的模块变量:

variable "vpc_id" {} 
variable "vpc_cidr_block" {} 
variable "private_subnets_count" {} 
variable "public_subnets_count" {} 
variable "availability_zones" {} 

开发/模块/变量.tf

像这样更新 secrets.tfvars:

private_subnets_count = 2 
public_subnets_count  = 2

秘密.tfvars

您必须建立私有和公共路由表来指定 VPC 子网中的流量路由方法。在我们对我们的资源执行terraform apply之前,让我们这样做。

如何设置 VPC 路由表

我们将开发用于细粒度交通管理的私有和公共路由表。这将使部署在私有子网中的实例能够访问互联网,而不会暴露给公众。

如何创建公共路由表

首先,我们需要建立一个Internet 网关资源并将其链接到我们之前生成的 VPC。然后我们需要定义一个公共路由表和一个将所有流量(0.0.0.0/0)指向互联网网关的路由。最后,我们需要将其与 VPC 中的公共子网链接,以便通过创建路由表关联将来自这些子网的流量路由到 Internet 网关。

/*** Internet Gateway - Provides a connection between the VPC and the public internet, allowing traffic to flow in and out of the VPC and translating IP addresses to public* addresses.*/ 
resource "aws_internet_gateway" "igw" { 
	vpc_id = var.vpc_id 
    
    tags = { 
    	Name = "igw_jenkins" 
   } 
} 

/*** A route from the public route table out to the internet through the internet* gateway.*/ 
resource "aws_route_table" "public_rt" { 
	vpc_id = var.vpc_id 
    
    route { 
    	cidr_block = "0.0.0.0/0" 
        gateway_id = aws_internet_gateway.igw.id 
   } 
   
   tags = { 
   		Name = "public_rt_jenkins" 
   } 
} 
/*** Associate the public route table with the public subnets.*/ 
resource "aws_route_table_association" "public" { 
	count     = var.public_subnets_count 
    subnet_id = element(var.public_subnets.*.id, count.index) 
    route_table_id = aws_route_table.public_rt.id 
}

开发/模块/public_rt.tf

‌如何创建私有路由表

现在我们的公共路由表已经完成,让我们创建私有路由表。

为了让我们的 Jenkins 实例在部署在私有子网上时能够连接到互联网,我们将在公共子网中构建一个NAT 网关资源。

之后将弹性 IP地址添加到 NAT 网关,并添加一个带有路由 (0.0.0.0/0) 的私有路由表,该路由将所有流量定向到您建立的 NAT 网关的 ID。然后我们通过创建路由表关联将私有子网附加到私有路由表。

 /*** An elastic IP address to be used by the NAT Gateway defined below.  The NAT* gateway acts as a gateway between our private subnets and the public* internet, providing access out to the internet from within those subnets,* while denying access to them from the public internet.  This IP address* acts as the IP address from which all the outbound traffic from the private* subnets will originate.*/ 
 
 resource "aws_eip" "eip_for_the_nat_gateway" { 
 	vpc = true 
    
    tags = { 
    	Name = "jenkins-tutoral-eip_for_the_nat_gateway" 
    } 
} 

/*** A NAT Gateway that lives in our public subnet and provides an interface* between our private subnets and the public internet.  It allows traffic to* exit our private subnets, but prevents traffic from entering them.*/ 

resource "aws_nat_gateway" "nat_gateway" { 
	allocation_id = aws_eip.eip_for_the_nat_gateway.id 
    subnet_id     = element(var.public_subnets.*.id, 0) 
    
    tags = { 
    	Name = "jenkins-tutorial-nat_gateway" 
	} 
} 
/*** A route from the private route table out to the internet through the NAT * Gateway.*/ 

resource "aws_route_table" "private_rt" { 
	vpc_id = var.vpc_id 
    
    route { 
    	cidr_block     = "0.0.0.0/0" 
        nat_gateway_id = aws_nat_gateway.nat_gateway.id } 
        
        tags = { 
        	Name   = "private_rt_${var.vpc_name}" 
            Author = var.author 
        } 
} 
/*** Associate the private route table with the private subnet.*/ 
resource "aws_route_table_association" "private" { 
	count = var.private_subnets_count 
    subnet_id = element(aws_subnet.private_subnets.*.id, count.index) 
    route_table_id = aws_route_table.private_rt.id 
}

开发/模块/private_rt.tf

‌现在让我们运行terraform apply。但是我们需要更新我们的 main.tf文件(因为这是我们的入口 terraform 文件)以了解我们的子网和模块变量以及secrets.tfvars(用于我们的变量)。

variable "vpc_id" {} 
variable "vpc_cidr_block" {} 
variable "private_subnets_count" {} 
variable "public_subnets_count" {} 
variable "availability_zones" {} 
variable "public_subnets" {}

开发/模块/变量.ftvars

variable "private_subnets_count" {} 
variable "public_subnets_count" {} 
variable "availability_zones" {} 

module "subnet_module" { 
	source     = "./modules" 
    vpc_id     = aws_vpc.main_vpc.id 
    vpc_cidr_block = aws_vpc.main_vpc.cidr_block 
    availability_zones = var.availability_zones 
    public_subnets_count = var.public_subnets_count 
    private_subnets_count = var.private_subnets_count 
 }

开发/main.tf

 availability_zones    = ["us-east-1a", "us-east-1b", "us-east-1c", "us-east-1d", "us-east-1e"]

开发/secrets.tf

我们的子网和相应的证券已准备就绪。现在我们可以使用 Terraform 对其进行初始化、计划和应用。

我们将运行terraform apply来创建资源。您可以先运行 terraform plan 以查看您实际创建的资源。

在终端运行。 terraform apply -var-file=secrets.tfvars

s_0475B692F95FDEC0A6E8498B95C86079E0E8D8D5196F9F4DEAA5AA6D3B79CB44_1656906570979_terminal-state-3

请记住,此处添加的资源数量可能与您的有所不同。

这是 AWS 控制台(子网、弹性地址、路由表):

子网

子网弹性ip弹性 ip路由表路由表

如何设置 VPC 堡垒主机

我们在私有子网中部署了 Jenkins 集群。由于集群缺少公共 IP,实例将无法通过 Internet 公开可用。因此,为了解决这个问题,我们将设置一个堡垒主机,以便我们可以安全地访问 Jenkins 实例。

在 bastion.tf 文件中添加以下资源和安全组:

/*** A security group to allow SSH access into our bastion instance.*/ 
resource "aws_security_group" "bastion" { 
	name   = "bastion-security-group" 
    vpc_id = var.vpc_id 
    
    ingress { 
    	protocol    = "tcp" 
        from_port   = 22 
        to_port     = 22 
        cidr_blocks = ["0.0.0.0/0"] 
    } 
    egress { 
    	protocol    = -1 
        from_port   = 0 
        to_port     = 0 
        cidr_blocks = ["0.0.0.0/0"] 
   } 
   
   tags = { 
   		Name = "aws_security_group.bastion_jenkins" 
   } 
} 

/*** The public key for the key pair we'll use to ssh into our bastion instance.*/ 

resource "aws_key_pair" "bastion" { 
	key_name   = "bastion-key-jenkins" 
    public_key = var.public_key 
 } 
 
 /*** This parameter contains the AMI ID for the most recent Amazon Linux 2 ami,* managed by AWS.*/ 
 
 data "aws_ssm_parameter" "linux2_ami" { 
 	name = "/aws/service/ami-amazon-linux-latest/amzn-ami-hvm-x86_64-ebs" 
} 

/*** Launch a bastion instance we can use to gain access to the private subnets of* this availabilty zone.*/ 

resource "aws_instance" "bastion" { 
	ami           = data.aws_ssm_parameter.linux2_ami.value 
    key_name      = aws_key_pair.bastion.key_name 
    instance_type = "t2.large" 
    associate_public_ip_address = true 
    subnet_id                   = element(aws_subnet.public_subnets, 0).id 
    vpc_security_group_ids      = [aws_security_group.bastion.id] 
    
    tags = { 
    	Name        = "jenkins-bastion" 
    } 
} 

output "bastion" { value = aws_instance.bastion.public_ip }

堡垒.tf

让我们看看这里的代码发生了什么:

  • 堡垒安全组资源 –新生成的 EC2 实例不允许 SSH 访问。
  • 我们将一个安全组链接到活动实例,以启用对堡垒主机的 SSH 访问。安全组将允许来自任何地方 (0.0.0.0/0) 的端口 22 (SSH) 上的任何入站(入口)流量。为了提高安全性并防止安全漏洞,您可以用自己的公共 IP 地址/32 或网络地址替换 CIDR 源块。
  • aws_key_pair –为了能够使用 SSH 和私钥连接到堡垒主机,我们在创建 EC2 时添加了一个 SSH 密钥对。我们的公共 SSH 密钥用于密钥对。使用sshkeygen命令,您还可以创建一个新的。
  • aws_ssm_parameter – EC2 实例使用 Amazon 2 Linux 机器映像。AMI ID 是使用 AWS AMI 数据源从 AWS 市场获取的
  • aws_instance –  最后,我们使用其定义的配置和访问权限部署我们的 EC2 堡垒实例
  • 输出——通过指定输出,我们使用 Terraform 输出功能在终端会话中显示 IP 地址。

现在,让我们使用作为变量传递的新public_key更新模块和 main.tf中的变量:

variable "public_key"{} 

开发/模块/变量/tfvars

varable "public_key" {} 
module "subnet_module" { 
	source     = "./modules" 
    ... 
    publc_key = var.public_key 
}

开发/main.tf

public_key = "enter-your-public-key"

开发/secrets.tf

我们将运行terraform apply来创建资源。您可以先运行 terraform plan 以查看您实际创建的资源。

在终端上,让我们运行terraform apply -var-file=secrets.tfvars

终端资源

终端资源

这是 AWS 控制台中的输出:

aws 控制台实例

aws 控制台实例

如何配置我们的计算服务

詹金斯主实例

到目前为止,我们已经成功地设置了我们的 VPC 和网络拓扑。‌‌最后,我们将创建我们的 Jenkins EC2 实例,该实例将使用 Packer 烘焙的 Jenkins 主 AMI。

您可以在 freecodecamp.org 上查看我之前的文章:通过在 AWS 中构建自定义机器映像来学习基础设施即代码 无论如何,如果您有自定义图像,您可以使用任何自定义图像。

 /*** This parameter contains our baked AMI ID fetch from the Amazon Console*/ data "aws_ami" "jenkins-master" { 
 	most_recent = true owners      = ["self"] 
} 

resource "aws_security_group" "jenkins_master_sg" { 
	name        = "jenkins_master_sg" 
    description = "Allow traffic on port 8080 and enable SSH" 
    vpc_id      = var.vpc_id 
    
    ingress { 
    	from_port       = "22" 
        to_port         = "22" 
        protocol        = "tcp" 
        security_groups = [aws_security_group.bastion.id] 
   } 
   ingress { 
   		from_port       = "8080" 
        to_port         = "8080" 
        protocol        = "tcp" 
        security_groups = [aws_security_group.lb.id] 
   } 
   ingress { 
   		from_port   = "8080" 
        to_port     = "8080" 
        protocol    = "tcp" 
        cidr_blocks = ["0.0.0.0/0"] 
  } 
  egress { 
  		from_port   = "0" 
        to_port     = "0" 
        protocol    = "-1" 
        cidr_blocks = ["0.0.0.0/0"] 
  } 
  
  tags = { 
  	Name = "jenkins_master_sg" 
  }
} 

开发/模块/jenkins_master.tf

将安全组附加到实例将启用端口 8080(Jenkins Web 仪表板)和仅来自堡垒服务器和 VPC CIDR 块的 SSH 上的入站流量。

resource "aws_key_pair" "jenkins" { 
	key_name   = "key-jenkins" 
    public_key = var.public_key 
} 

resource "aws_instance" "jenkins_master" { 
	ami       = data.aws_ami.jenkins-master.id 
    instance_type  = "t2.large" 
    key_name       = aws_key_pair.jenkins.key_name 
    vpc_security_group_ids = [aws_security_group.jenkins_master_sg.id]
    subnet_id              = element(aws_subnet.private_subnets, 0).id
    root_block_device { 
    	volume_type           = "gp3" 
        volume_size           = 30 
        delete_on_termination = false 
    } 
    
    tags = { 
    	Name = "jenkins_master" 
     } 
 }

开发/模块/jenkins_master.tf

接下来,我们创建一个变量并定义我们用于部署 EC2 实例的实例类型。我们不会在 master 上分配 executor 或 worker,因此 t2.large(8 GB 内存和 2vCPU)对于简单来说应该足够了。

因此,构建作业不会导致 Jenkins master 过度拥挤。但是 Jenkins 的内存要求会因项目的构建要求和这些构建中使用的工具而异。它需要两到三个线程,或至少 2 MB 内存,才能连接到每个构建节点。

请注意:考虑安装 Jenkins 工人以防止主人过度工作。因此,通用实例可以托管 Jenkins 主服务器并在计算和内存资源之间提供平衡。为了保持文章的简单性,我们不会这样做。

如何创建负载均衡器

要访问 Jenkins 仪表板,我们将在 EC2 实例前创建一个公共负载均衡器。

此 Elastic Load Balancer 将接受端口 80 上的 HTTP 流量并将其转发到端口 8080 上的 EC2 实例。此外,它会自动检查端口 8080 上已注册 EC2 实例的运行状况。如果 Elastic Load Balancing (ELB) 发现实例运行状况不佳,它停止向 Jenkins 实例发送流量。

 /*** A security group to allow SSH access into our load balancer*/ resource "aws_security_group" "lb" { 
 	name   = "ecs-alb-security-group" 
    vpc_id = var.vpc_id 
    
    ingress { 
    	protocol    = "tcp" 
        from_port   = 80 
        to_port     = 80 
        cidr_blocks = ["0.0.0.0/0"] 
     } 
     egress { 
     	from_port   = 0 
        to_port     = 0 
        protocol    = "-1" 
        cidr_blocks = ["0.0.0.0/0"] 
     } 
     
     tags = { 
     	Name = "jenkins-lb-sg" 
      } 
 } 
 
 /***Load Balancer to be attached to the ECS cluster to distribute the load among instances*/ 
 
 resource "aws_elb" "jenkins_elb" { 
 	subnets    = [for subnet in aws_subnet.public_subnets : subnet.id]
    cross_zone_load_balancing = true 
    security_groups       = [aws_security_group.lb.id] 
    instances             = [aws_instance.jenkins_master.id] 
    
    listener { 
    	instance_port     = 8080 
        instance_protocol = "http" 
        lb_port           = 80 
        lb_protocol       = "http" 
     } 
     
     health_check { 
     	healthy_threshold   = 2 
        unhealthy_threshold = 2 
        timeout             = 3 
        target              = "TCP:8080"    
        interval            = 5 
    } 
    
    tags = { 
    	Name = "jenkins_elb" 
    } 
 } 
 
 output "load-balancer-ip" { 
 	value = aws_elb.jenkins_elb.dns_name 
 }

开发/模块/负载均衡器.tf

之前,我们进行 terraform 应用,让我们更新 development/output.tf 文件夹以输出负载均衡器 DNS:

 output "load-balancer-ip" { 
 	value = module.subnet_module.load-balancer-ip
 }

开发/输出.tf

在终端上,运行以下命令:terraform apply -var-file="secrets.tfvars". 这会给你这个:

负载均衡器输出

负载均衡器输出

使用 Terraform 应用更改后,Jenkins 主负载均衡器 URL 应显示在终端会话中。

将您喜欢的浏览器指向该 URL,您应该可以访问 Jenkins Web 仪表板。

詹金斯实例

詹金斯实例

然后只需按照屏幕说明解锁。

解锁詹金斯

解锁詹金斯

您可以在此 GitHub 存储库中找到完整代码。

打扫干净

为了避免运行 AWS 服务的不必要成本,您需要运行以下命令来销毁所有已创建和正在运行的资源terraform destroy -var-file="secrets.tfvars": ‌‌ 应该会给出以下输出:

破坏资源

破坏资源

多么有趣,对吧?只需几行代码,我们就可以破坏和启动我们的资源。

概括

在本教程中,您学习了如何在较高级别使用 Terraform。您还通过在 AWS 云平台上配置 Jenkins 服务器了解了它的一个应用程序。

您还了解了 Terraform 后端状态和模块的最佳实践。

快乐学习! 

来源:https ://www.freecodecamp.org/news/learn-terraform-b​​y-deploying-jenkins-server-on-aws/

 #jenkins #aws #terraform

通过在 AWS 上部署 Jenkins 服务器来学习 Terraform
Mélanie  Faria

Mélanie Faria

1658959200

Aprenda O Terraform Implantando Um Jenkins Server Na AWS

Hoje vamos aprender sobre o Terraform construindo um projeto.

O Terraform é mais do que apenas uma ferramenta para aumentar a produtividade das equipes de operações. Você tem a chance de transformar seus desenvolvedores em operadores implementando o Terraform.

Isso pode ajudar a aumentar a eficiência de toda a sua equipe de engenharia e melhorar a comunicação entre desenvolvedores e operadores.

Neste artigo, mostrarei como automatizar totalmente a implantação de seus serviços Jenkins na nuvem AWS usando o Terraform com uma imagem personalizada.

O que é Terraform?

O Terraform da HashiCorp é uma solução de infraestrutura como código. Ele permite especificar recursos na nuvem e no local em arquivos de configuração legíveis por humanos que você pode reutilizar e compartilhar. É uma poderosa ferramenta de provisionamento de DevOps.

Por que você deve usar o Terraform?

O Terraform tem vários casos de uso, incluindo a capacidade de:

  • Especifique a infraestrutura na configuração/código e reconstrua/altere e rastreie facilmente as alterações na infraestrutura.
  • Suporte a diferentes plataformas de nuvem
  • Realize modificações incrementais de recursos
  • Suporta rede definida por software

Como o Terraform funciona

Vamos dar uma olhada em como o Terraform funciona em alto nível.

O Terraform é desenvolvido na linguagem de programação Go. O código Go é compilado em terraform, um único binário. Você pode usar esse binário para implantar a infraestrutura de seu laptop, um servidor de compilação ou praticamente qualquer outro computador e não precisará executar nenhuma infraestrutura adicional para fazer isso.

Isso ocorre porque o binário do Terraform faz chamadas de API em seu nome para um ou mais provedores, que incluem Azure, AWS, Google Cloud, DigitalOcean e outros. Isso permite que o Terraform aproveite a infraestrutura que esses provedores já possuem para seus servidores de API, bem como os processos de autenticação que eles exigem.

Mas o Terraform não sabe quais solicitações de API devem ser feitas – então, como ele sabe? As configurações do Terraform, que são arquivos de texto em linguagem declarativa que especificam qual infraestrutura você deseja gerar, são a resposta. O "código" em "infraestrutura como código" são essas configurações.

Você tem controle total sobre sua infraestrutura, incluindo servidores, bancos de dados, balanceadores de carga, topologia de rede e muito mais. Em seu nome, o binário do Terraform analisa seu código e o converte em uma série de chamadas de API o mais rápido possível.

O que é uma Linguagem Processual versus uma Linguagem Declarativa?

Uma linguagem procedural permite especificar todo o processo e listar as etapas necessárias para concluí-lo. Você apenas dá instruções e especifica como o processo será realizado. Chef e Ansible incentivam esse método.

As linguagens declarativas, por outro lado, permitem que você simplesmente defina o comando ou a ordem e deixe que o sistema o execute. Você não precisa entrar no processo; você só precisa do resultado. Exemplos são Terraform, cloudFormation e Puppeteer.

Chega de teoria...

Agora é o momento de colocar em ação a alta disponibilidade, segurança, desempenho e confiabilidade do Terraform.

Aqui, estamos falando de um servidor Jenkins baseado em Terraform na Amazon Web Services. Estamos configurando a rede do zero, então vamos começar.

Estrutura de arquivos/pastas do nosso projeto

Usaremos uma estratégia de desenvolvimento modular para separar nossa implantação de cluster Jenkins em vários arquivos de modelo (em vez de desenvolver um arquivo de modelo grande).

Cada arquivo é responsável pela execução de um componente de infraestrutura de destino ou recurso da AWS.

Para criar e aplicar configurações de infraestrutura, o Terraform aproveita a sintaxe de uma linguagem de configuração semelhante a JSON chamada HCL (HashiCorp Configuration Language).

estruturas de arquivos/pastas

estruturas de arquivos/pastas

Como inicializar o estado do Terraform pela primeira vez

Para seguir as melhores práticas, armazenaremos nossos arquivos de estado do Terraform em nosso armazenamento em nuvem. Isso é essencial especialmente para a colaboração em equipe.

Os arquivos de estado do Terraform são arquivos que contêm recursos do Terraform nos projetos.

Dentro do arquivo main.tf na pasta backend-state, adicione o seguinte código:

variable "aws_region" { 
	default = "us-east-1" 
 } 
variable "aws_secret_key" {} 
variable "aws_access_key" {} 

provider "aws" { 
	region = var.aws_region 
    access_key = var.aws_access_key 
    secret_key = var.aws_secret_key 
} 

resource "aws_s3_bucket" "terraform_state" { 
	bucket = "terraform-state-caesar-tutorial-jenkins" 
    
    lifecycle { 
    	prevent_destroy = true 
    } 
    
    versioning { 
    	enabled = true 
   } 
   
   server_side_encryption_configuration { 
   		rule { 
        	apply_server_side_encryption_by_default { 
            	sse_algorithm = "AES256" 
            } 
        } 
   } 
}

backend-state/main.tf

Vamos nos certificar de que sabemos o que está acontecendo no código acima.

Usamos variáveis ​​para armazenar dados e no Terraform você declara uma variável com a palavra-chave variável seguida do nome. O bloco variável pode ter algumas propriedades como padrão, descrição, tipo e assim por diante ou nenhuma. Você vai ver muito isso.

Agora estamos declarando as variáveis ​​como variable "variable_name"{}e usando-as em qualquer bloco de recursos/dados comovar.variable_name . Mais tarde, você verá como atribuiremos valores a essas variáveis ​​em nosso arquivo secrets.tfvars.

Para usar o Terraform, você precisa informar o provedor com o qual ele se comunicará e passar suas propriedades necessárias para autenticação. Aqui temos a região da AWS, acesso e chave secreta (você deve baixá-los em seu sistema a partir dos pré-requisitos).

No terraform, cada recurso que precisamos é definido no bloco de recursos. Recursos é a infraestrutura sublinhada que cria nosso serviço de nuvem. Segue a sintaxe resource "terraform-resource-name" "custom-name" {}.

O Terraform tem muitos recursos para provedores específicos nos documentos do terraform (sempre consulte os documentos se tiver dúvidas).

Em seguida, estamos criando o arquivo aws_s3_bucket. Isso armazenará nosso estado remoto. Ele assume as seguintes propriedades:

  • bucket → Isso tem que ser globalmente único
  • ciclo de vida → Se você precisar destruir seus recursos do Terraform, convém evitar a destruição do estado, pois ele é compartilhado entre as equipes
  • versionamento → Ajuda a fornecer algum controle de versão sobre os estados
  • server_side_encryption_configuration → Fornece criptografia.

Nosso back-end de estado está pronto. Mas antes de inicializá-lo, planejá-lo e aplicá-lo com o Terraform, vamos atribuir nossa variável aos seus valores .

Em secrets.tfvars, adicione as seguintes informações da sua conta da AWS:

  aws_region = "us-east-1 
  aws_secret_key = "enter-your-secret" 
  aws_access_key = "enter-your-access    

backend-state/secrets.tfvars

Em seu terminal na mesma pasta de estado de back-end, execute terraform init.

estado terraform no terminal

estado terraform no terminal

Então terraform apply -var-file=secrets.tfvars:

estado terraform no terminal

estado terraform no terminal

Em seu console da AWS , veja o que você verá:

estado terraform no bucket aws s3

estado terraform no bucket aws s3

‌‌Agora que nosso estado está pronto, vamos para a próxima parte.

Como provisionar uma nuvem privada virtual da AWS

Para proteger nosso cluster Jenkins, implantaremos a arquitetura em uma nuvem privada virtual (VPC) e uma sub-rede privada. Você pode implantar o cluster na VPC padrão da AWS.

Para ter controle total sobre a topologia da rede, criaremos uma VPC do zero.

 variable "cidr_block" {} 
 variable "aws_access_key" {} 
 variable "aws_secret_key" {} 
 variable "aws_region" {} 
 
 provider "aws" { 
 	region = var.aws_region 
    access_key = var.aws_access_key 
    secret_key = var.aws_secret_key 
} 

terraform { 
	backend "s3" { 
    	bucket     = "terraform-state-caesar-tutorial-jenkins" 
        key        = "tutorial-jenkins/development/network/terraform.tfstate" 
        region     = "us-east-1" 
        encrypt    = true 
   }
} 

resource "aws_vpc" "main_vpc" { 
	cidr_block           = var.cidr_block 
    enable_dns_support   = true 
    enable_dns_hostnames = true 
    
    tags = { 
    	Name        = "jenkins-instance-main_vpc" 
    } 
}

desenvolvimento/main.tf

output "vpc_id" { 
	value = aws_vpc.main_vpc.id 
} 

output "vpc_cidr_block" { 
	value = aws_vpc.main_vpc.cidr_block 
}  

desenvolvimento/saída.tf

cidr_block            = "172.0.0.0/16" 
aws_region = "us-east-1" 
aws_secret_key = "enter-your-secret" 
aws_access_key = "enter-your-access" 

desenvolvimento/secrets.tfvars

  • cidr_block → Roteamento entre domínios sem classe é referido como CIDR. Um bloco CIDR é um intervalo de endereços IP, para simplificar. Isso define em que faixa estamos trabalhando.
  • output → O bloco output no Terraform é usado para exportar valores de recursos para outros módulos. Este é outro termo importante ao transferir dados de um recurso em um módulo para outro recurso em um módulo separado. (Você aprenderá quais módulos são em breve) Aqui está sua sintaxe: output "custom_output_name" {  value = "resource-name"}. Ele recebe uma chave de valor que recebe o recurso passado. Aqui temos a saída vpc_id e cidr_block.

Agora, no terminal, execute terraform inite terraform apply crie os recursos. Você pode executar terraform planantes para ver quais recursos você está realmente criando. Aqui está o comando: terraform apply -var-file=secrets.tfvars, e a saída:

s_0475B692F95FDEC0A6E8498B95C86079E0E8D8D5196F9F4DEAA5AA6D3B79CB44_1655907973370_vpc

Você deve ver seu vpc_id e vpc_cidr_block em seu Console AWS :

recurso vpc no aws

vpc no aws

Como trabalhar com módulos do Terraform

Um grupo de arquivos de configuração típicos em um diretório específico formam um módulo Terraform. Os módulos do Terraform reúnem recursos que são usados ​​para uma única operação. Isso reduz a quantidade de código necessária para criar componentes de infraestrutura idênticos.

Usando a sintaxe abaixo, você pode transferir um recurso do módulo Terraform para outro a ser usado.

module "custom-module-name" { 
	source     = "path-to-modules-resources" 
}

sintaxe dos módulos terraform

E para usar a saída de recurso do módulo dentro de outro módulo de recurso, este é o comando: module.custom-module-name.resource-output-value.

Como criar uma sub-rede VPC

Criar uma VPC não é suficiente – também precisamos de uma sub-rede para poder instalar instâncias do Jenkins nessa rede isolada. Devemos passar o ID da VPC que produzimos antes, pois essa sub-rede pertence a uma VPC construída anteriormente.

Para resiliência, usaremos duas sub-redes públicas e duas sub-redes privadas em zonas de disponibilidade distintas. Cada sub-rede tem seu próprio bloco CIDR, que é um subconjunto do bloco VPC CIDR, obtido do recurso VPC.

resource "aws_subnet" "public_subnets" { 
	vpc_id         = var.vpc_id 
    cidr_block     = cidrsubnet(var.vpc_cidr_block, 8, 2 + count.index)  
   	availability_zone   = element(var.availability_zones, count.index)  	
    map_public_ip_on_launch = true 
    count                   = var.public_subnets_count 
    
    tags = { 
    	Name        = "jenkins-instance-public-subnet" 
   } 
} 

resource "aws_subnet" "private_subnets" { 
	vpc_id     = var.vpc_id 
    cidr_block = cidrsubnet(var.vpc_cidr_block, 8, count.index)  			
    availability_zone    = element(var.availability_zones, count.index)  
    map_public_ip_on_launch = false 
    count                   = var.private_subnets_count 
    
    tags = { 
    	Name        = "jenkins-instance-private-subnet" 
    } 
 }

módulos/sub-redes.tf

Certo, o que está acontecendo neste código?

  • count O meta-argumento count aceita um número inteiro e cria esse número de instâncias do recurso ou módulo. Aqui estamos especificando 2 cada para as variáveis ​​private_subnets_count e public_subnets_count.
  • map_public_ip_on_launch → Especifique true para indicar que as instâncias iniciadas na sub-rede devem receber um endereço IP público.
  • cidrsubnet() cidrsubnet calcula um endereço de sub-rede dentro de um determinado prefixo de endereço de rede IP.
  • element() element recupera um único elemento de uma lista.

Agora vamos atualizar nossas variáveis ​​de módulos:

variable "vpc_id" {} 
variable "vpc_cidr_block" {} 
variable "private_subnets_count" {} 
variable "public_subnets_count" {} 
variable "availability_zones" {} 

development/modules/variables.tf

Atualize o secrets.tfvars assim:

private_subnets_count = 2 
public_subnets_count  = 2

secrets.tfvars

Você deve estabelecer tabelas de rotas públicas e privadas para especificar o método de roteamento de tráfego nas sub-redes VPC. Vamos fazer isso antes de executar o terraform apply em nossos recursos.

Como configurar tabelas de rotas VPC

Desenvolveremos tabelas de rotas privadas e públicas para gerenciamento de tráfego refinado. Isso permitirá que instâncias implantadas em sub-redes privadas acessem a Internet sem serem expostas ao público em geral.

Como criar uma tabela de rotas públicas

Primeiro, precisamos estabelecer um recurso de gateway da Internet e vinculá-lo à VPC que geramos anteriormente. Em seguida, precisamos definir uma tabela de rotas públicas e uma rota que aponte todo o tráfego (0.0.0.0/0) para o gateway de internet. E, por último, precisamos vinculá-lo a sub-redes públicas em nossa VPC para que o tráfego que flui dessas sub-redes seja roteado para o gateway da Internet criando uma associação de tabela de rotas.

/*** Internet Gateway - Provides a connection between the VPC and the public internet, allowing traffic to flow in and out of the VPC and translating IP addresses to public* addresses.*/ 
resource "aws_internet_gateway" "igw" { 
	vpc_id = var.vpc_id 
    
    tags = { 
    	Name = "igw_jenkins" 
   } 
} 

/*** A route from the public route table out to the internet through the internet* gateway.*/ 
resource "aws_route_table" "public_rt" { 
	vpc_id = var.vpc_id 
    
    route { 
    	cidr_block = "0.0.0.0/0" 
        gateway_id = aws_internet_gateway.igw.id 
   } 
   
   tags = { 
   		Name = "public_rt_jenkins" 
   } 
} 
/*** Associate the public route table with the public subnets.*/ 
resource "aws_route_table_association" "public" { 
	count     = var.public_subnets_count 
    subnet_id = element(var.public_subnets.*.id, count.index) 
    route_table_id = aws_route_table.public_rt.id 
}

development/modules/public_rt.tf

‌Como criar uma tabela de rotas privada

Agora que nossa tabela de rotas pública está concluída, vamos criar a tabela de rotas privada.

Para permitir que nossas instâncias do Jenkins se conectem à Internet conforme ela é implantada na sub-rede privada, construiremos um recurso de gateway NAT dentro de uma sub-rede pública.

Adicione um endereço IP elástico ao gateway NAT depois disso e uma tabela de rotas privada com uma rota (0.0.0.0/0) que direcione todo o tráfego para o ID do gateway NAT que você estabeleceu. Em seguida, anexamos sub-redes privadas à tabela de rotas privada criando a associação da tabela de rotas .

 /*** An elastic IP address to be used by the NAT Gateway defined below.  The NAT* gateway acts as a gateway between our private subnets and the public* internet, providing access out to the internet from within those subnets,* while denying access to them from the public internet.  This IP address* acts as the IP address from which all the outbound traffic from the private* subnets will originate.*/ 
 
 resource "aws_eip" "eip_for_the_nat_gateway" { 
 	vpc = true 
    
    tags = { 
    	Name = "jenkins-tutoral-eip_for_the_nat_gateway" 
    } 
} 

/*** A NAT Gateway that lives in our public subnet and provides an interface* between our private subnets and the public internet.  It allows traffic to* exit our private subnets, but prevents traffic from entering them.*/ 

resource "aws_nat_gateway" "nat_gateway" { 
	allocation_id = aws_eip.eip_for_the_nat_gateway.id 
    subnet_id     = element(var.public_subnets.*.id, 0) 
    
    tags = { 
    	Name = "jenkins-tutorial-nat_gateway" 
	} 
} 
/*** A route from the private route table out to the internet through the NAT * Gateway.*/ 

resource "aws_route_table" "private_rt" { 
	vpc_id = var.vpc_id 
    
    route { 
    	cidr_block     = "0.0.0.0/0" 
        nat_gateway_id = aws_nat_gateway.nat_gateway.id } 
        
        tags = { 
        	Name   = "private_rt_${var.vpc_name}" 
            Author = var.author 
        } 
} 
/*** Associate the private route table with the private subnet.*/ 
resource "aws_route_table_association" "private" { 
	count = var.private_subnets_count 
    subnet_id = element(aws_subnet.private_subnets.*.id, count.index) 
    route_table_id = aws_route_table.private_rt.id 
}

development/modules/private_rt.tf

‌Agora vamos correr terraform apply. Mas precisamos atualizar nossos arquivos main.tf (pois este é nosso arquivo terraform de entrada) para estarmos cientes de nossas sub-redes e variáveis ​​de módulo e secrets.tfvars (para nossas variáveis).

variable "vpc_id" {} 
variable "vpc_cidr_block" {} 
variable "private_subnets_count" {} 
variable "public_subnets_count" {} 
variable "availability_zones" {} 
variable "public_subnets" {}

development/modules/variables.ftvars

variable "private_subnets_count" {} 
variable "public_subnets_count" {} 
variable "availability_zones" {} 

module "subnet_module" { 
	source     = "./modules" 
    vpc_id     = aws_vpc.main_vpc.id 
    vpc_cidr_block = aws_vpc.main_vpc.cidr_block 
    availability_zones = var.availability_zones 
    public_subnets_count = var.public_subnets_count 
    private_subnets_count = var.private_subnets_count 
 }

desenvolvimento/main.tf

 availability_zones    = ["us-east-1a", "us-east-1b", "us-east-1c", "us-east-1d", "us-east-1e"]

desenvolvimento/segredos.tf

Nossas sub-redes e respectivos títulos estão prontos. Agora podemos inicializá-lo, planejar e aplicar com o Terraform.

Executaremos o terraform apply para criar os recursos. Você pode executar o terraform plan antes para ver quais recursos você está realmente criando.

No terminal execute . terraform apply -var-file=secrets.tfvars

s_0475B692F95FDEC0A6E8498B95C86079E0E8D8D5196F9F4DEAA5AA6D3B79CB44_1656906570979_terminal-state-3

Lembre-se de que o número de recursos adicionados aqui pode ser diferente do seu.

Aqui está o Console AWS (sub-redes, endereço elástico, route_tables):

sub-redes

tabelas de roteamento deip elásticoip elástico de sub -redestabelas de rotas

Como configurar um host Bastion VPC

Implantamos nosso cluster Jenkins dentro das sub-redes privadas. Como o cluster não possui um IP público, as instâncias não estarão disponíveis publicamente pela Internet. Então, para cuidar disso, vamos configurar um Bastion Host para que possamos acessar as instâncias do Jenkins com segurança.

Adicione os seguintes recursos e grupo de segurança no arquivo bastion.tf:

/*** A security group to allow SSH access into our bastion instance.*/ 
resource "aws_security_group" "bastion" { 
	name   = "bastion-security-group" 
    vpc_id = var.vpc_id 
    
    ingress { 
    	protocol    = "tcp" 
        from_port   = 22 
        to_port     = 22 
        cidr_blocks = ["0.0.0.0/0"] 
    } 
    egress { 
    	protocol    = -1 
        from_port   = 0 
        to_port     = 0 
        cidr_blocks = ["0.0.0.0/0"] 
   } 
   
   tags = { 
   		Name = "aws_security_group.bastion_jenkins" 
   } 
} 

/*** The public key for the key pair we'll use to ssh into our bastion instance.*/ 

resource "aws_key_pair" "bastion" { 
	key_name   = "bastion-key-jenkins" 
    public_key = var.public_key 
 } 
 
 /*** This parameter contains the AMI ID for the most recent Amazon Linux 2 ami,* managed by AWS.*/ 
 
 data "aws_ssm_parameter" "linux2_ami" { 
 	name = "/aws/service/ami-amazon-linux-latest/amzn-ami-hvm-x86_64-ebs" 
} 

/*** Launch a bastion instance we can use to gain access to the private subnets of* this availabilty zone.*/ 

resource "aws_instance" "bastion" { 
	ami           = data.aws_ssm_parameter.linux2_ami.value 
    key_name      = aws_key_pair.bastion.key_name 
    instance_type = "t2.large" 
    associate_public_ip_address = true 
    subnet_id                   = element(aws_subnet.public_subnets, 0).id 
    vpc_security_group_ids      = [aws_security_group.bastion.id] 
    
    tags = { 
    	Name        = "jenkins-bastion" 
    } 
} 

output "bastion" { value = aws_instance.bastion.public_ip }

bastião.tf

Vamos ver o que está acontecendo no código aqui:

  • recurso bastion security group – instâncias EC2 recém-geradas não permitem acesso SSH.
  • Vamos vincular um grupo de segurança à instância ativa para habilitar o acesso SSH aos hosts bastiões. Qualquer tráfego de entrada (entrada) na porta 22 (SSH) de qualquer lugar (0.0.0.0/0) será permitido pelo grupo de segurança. Para melhorar a segurança e evitar violações de segurança, você pode substituir seu próprio endereço IP público/32 ou endereço de rede pelo bloco de origem CIDR.
  • aws_key_pair – Para poder se conectar ao Bastion Host usando SSH e a chave privada, adicionamos um par de chaves SSH quando criamos o EC2. Nossa chave SSH pública é usada no par de chaves. Usando o comando sshkeygen , você também pode criar um novo.
  • aws_ssm_parameter – A imagem de máquina Linux do Amazon 2 é usada pela instância do EC2. O ID da AMI é obtido no mercado da AWS usando a fonte de dados da AWS AMI
  • aws_instance –  Por fim, implantamos nossa instância bastion do EC2 com suas configurações e acessos definidos
  • output – Ao especificar uma saída, usamos a funcionalidade de saídas do Terraform para mostrar o endereço IP na sessão do terminal.

Agora, vamos atualizar nossa variável dentro dos módulos e o main.tf com a nova public_key que estamos passando como variável:

variable "public_key"{} 

desenvolvimento/módulos/variáveis/tfvars

varable "public_key" {} 
module "subnet_module" { 
	source     = "./modules" 
    ... 
    publc_key = var.public_key 
}

desenvolvimento/main.tf

public_key = "enter-your-public-key"

desenvolvimento/segredos.tf

Executaremos o terraform apply para criar os recursos. Você pode executar o terraform plan antes para ver quais recursos você está realmente criando.

No terminal, vamos executar terraform apply -var-file=secrets.tfvars:

recursos do terminal

recursos do terminal

Aqui está a saída no console da AWS:

instâncias do console aws

instâncias do console aws

Como provisionar nosso serviço de computação

instância mestre do Jenkins

Até agora, conseguimos configurar nossa VPC e topologia de rede com sucesso. ‌‌Por fim, criaremos nossa instância do Jenkins EC2 que usará uma AMI principal do Jenkins criada pelo Packer.

Você pode conferir meu artigo anterior sobre como ele foi desenvolvido: Aprenda infraestrutura como código criando uma imagem de máquina personalizada na AWS em freecodecamp.org . Independentemente disso, você pode usar qualquer uma de suas imagens personalizadas, se tiver uma.

 /*** This parameter contains our baked AMI ID fetch from the Amazon Console*/ data "aws_ami" "jenkins-master" { 
 	most_recent = true owners      = ["self"] 
} 

resource "aws_security_group" "jenkins_master_sg" { 
	name        = "jenkins_master_sg" 
    description = "Allow traffic on port 8080 and enable SSH" 
    vpc_id      = var.vpc_id 
    
    ingress { 
    	from_port       = "22" 
        to_port         = "22" 
        protocol        = "tcp" 
        security_groups = [aws_security_group.bastion.id] 
   } 
   ingress { 
   		from_port       = "8080" 
        to_port         = "8080" 
        protocol        = "tcp" 
        security_groups = [aws_security_group.lb.id] 
   } 
   ingress { 
   		from_port   = "8080" 
        to_port     = "8080" 
        protocol    = "tcp" 
        cidr_blocks = ["0.0.0.0/0"] 
  } 
  egress { 
  		from_port   = "0" 
        to_port     = "0" 
        protocol    = "-1" 
        cidr_blocks = ["0.0.0.0/0"] 
  } 
  
  tags = { 
  	Name = "jenkins_master_sg" 
  }
} 

development/modules/jenkins_master.tf

Anexar um grupo de segurança à instância permitirá o tráfego de entrada na porta 8080 (o painel da Web do Jenkins) e SSH somente do servidor bastion e do bloco VPC CIDR.

resource "aws_key_pair" "jenkins" { 
	key_name   = "key-jenkins" 
    public_key = var.public_key 
} 

resource "aws_instance" "jenkins_master" { 
	ami       = data.aws_ami.jenkins-master.id 
    instance_type  = "t2.large" 
    key_name       = aws_key_pair.jenkins.key_name 
    vpc_security_group_ids = [aws_security_group.jenkins_master_sg.id]
    subnet_id              = element(aws_subnet.private_subnets, 0).id
    root_block_device { 
    	volume_type           = "gp3" 
        volume_size           = 30 
        delete_on_termination = false 
    } 
    
    tags = { 
    	Name = "jenkins_master" 
     } 
 }

development/modules/jenkins_master.tf

Em seguida, criamos uma variável e definimos o tipo de instância que usamos para implantar a instância do EC2. Não alocaremos executores ou trabalhadores no mestre, portanto t2.large (8 GB de memória e 2vCPU) deve ser adequado para fins de simplicidade.

Assim, os trabalhos de construção não farão com que o mestre do Jenkins fique superlotado. Mas os requisitos de memória do Jenkins variam dependendo dos requisitos de compilação do seu projeto e das ferramentas usadas nessas compilações. Serão necessários dois a três threads, ou pelo menos 2 MB de memória, para conectar-se a cada nó de compilação.

Apenas uma observação: considere instalar os trabalhadores do Jenkins para evitar sobrecarregar o mestre. Como resultado, uma instância de uso geral pode hospedar um mestre Jenkins e oferecer um equilíbrio entre recursos de computação e memória. Para manter a simplicidade do artigo, não faremos isso.

Como criar o balanceador de carga

Para acessar o painel do Jenkins, criaremos um balanceador de carga público na frente da instância do EC2.

Este Elastic load balancer aceitará tráfego HTTP na porta 80 e o encaminhará para a instância EC2 na porta 8080. Além disso, ele verificará automaticamente a integridade da instância EC2 registrada na porta 8080. Se o Elastic Load Balancing (ELB) encontrar a instância não íntegra , ele para de enviar tráfego para a instância do Jenkins.

 /*** A security group to allow SSH access into our load balancer*/ resource "aws_security_group" "lb" { 
 	name   = "ecs-alb-security-group" 
    vpc_id = var.vpc_id 
    
    ingress { 
    	protocol    = "tcp" 
        from_port   = 80 
        to_port     = 80 
        cidr_blocks = ["0.0.0.0/0"] 
     } 
     egress { 
     	from_port   = 0 
        to_port     = 0 
        protocol    = "-1" 
        cidr_blocks = ["0.0.0.0/0"] 
     } 
     
     tags = { 
     	Name = "jenkins-lb-sg" 
      } 
 } 
 
 /***Load Balancer to be attached to the ECS cluster to distribute the load among instances*/ 
 
 resource "aws_elb" "jenkins_elb" { 
 	subnets    = [for subnet in aws_subnet.public_subnets : subnet.id]
    cross_zone_load_balancing = true 
    security_groups       = [aws_security_group.lb.id] 
    instances             = [aws_instance.jenkins_master.id] 
    
    listener { 
    	instance_port     = 8080 
        instance_protocol = "http" 
        lb_port           = 80 
        lb_protocol       = "http" 
     } 
     
     health_check { 
     	healthy_threshold   = 2 
        unhealthy_threshold = 2 
        timeout             = 3 
        target              = "TCP:8080"    
        interval            = 5 
    } 
    
    tags = { 
    	Name = "jenkins_elb" 
    } 
 } 
 
 output "load-balancer-ip" { 
 	value = aws_elb.jenkins_elb.dns_name 
 }

development/modules/loadbalancer.tf

Antes de aplicarmos o terraform, vamos atualizar nossa pasta development/output.tf para gerar o DNS do balanceador de carga:

 output "load-balancer-ip" { 
 	value = module.subnet_module.load-balancer-ip
 }

desenvolvimento/saída.tf

No terminal, execute o seguinte comando: terraform apply -var-file="secrets.tfvars". Que vai te dar isso:

saída do balanceador de carga

saída do balanceador de carga

Depois de aplicar as alterações com o Terraform, a URL do balanceador de carga mestre do Jenkins deve ser exibida em sua sessão de terminal.

Aponte seu navegador favorito para a URL e você deverá ter acesso ao painel da web do Jenkins.

jenkins-instâncias

jenkins-instâncias

Depois é só seguir as instruções da tela para DESBLOQUEAR.

desbloquear jenkins

desbloquear jenkins

Você pode encontrar o código completo neste repositório do GitHub.

Limpando

Para evitar o custo desnecessário de executar os serviços da AWS, você precisará executar o seguinte comando para destruir todos os recursos criados e em execução: terraform destroy -var-file="secrets.tfvars"‌‌ que deve fornecer esta saída:

destruir recursos

destruir recursos

Que interessante, certo? Com apenas algumas linhas de código, podemos destruir e aumentar nossos recursos.

Resumo

Neste tutorial, você aprendeu a usar o Terraform em alto nível. Você também aprendeu um de seus aplicativos provisionando um servidor Jenkins na plataforma de nuvem AWS.

Você também aprendeu sobre as melhores práticas de estados e módulos de back-end do Terraform.

Feliz Aprendizagem! 

Fonte: https://www.freecodecamp.org/news/learn-terraform-by-deploying-jenkins-server-on-aws/

 #jenkins #aws #terraform

Aprenda O Terraform Implantando Um Jenkins Server Na AWS

Aprenda Terraform Implementando Un Servidor Jenkins En AWS

Hoy vamos a aprender sobre Terraform construyendo un proyecto.

Terraform es más que una herramienta para aumentar la productividad de los equipos de operaciones. Tiene la oportunidad de transformar a sus desarrolladores en operadores implementando Terraform.

Esto puede ayudar a aumentar la eficiencia de todo su equipo de ingeniería y mejorar la comunicación entre desarrolladores y operadores.

En este artículo, le mostraré cómo automatizar por completo la implementación de sus servicios de Jenkins en la nube de AWS mediante Terraform con una imagen personalizada.

¿Qué es Terraform?

Terraform de HashiCorp es una solución de infraestructura como código. Le permite especificar recursos locales y en la nube en archivos de configuración legibles por humanos que puede reutilizar y compartir. Es una poderosa herramienta de aprovisionamiento de DevOps.

¿Por qué debería usar Terraform?

Terraform tiene una serie de casos de uso, incluida la capacidad de:

  • Especifique la infraestructura en configuración/código y reconstruya/cambie fácilmente y realice un seguimiento de los cambios en la infraestructura.
  • Admite diferentes plataformas en la nube
  • Realizar modificaciones de recursos incrementales
  • Admite redes definidas por software

Cómo funciona Terraform

Echemos un vistazo a cómo funciona Terraform a un alto nivel.

Terraform está desarrollado en el lenguaje de programación Go. El código Go se compila en terraform, un solo binario. Puede usar este binario para implementar infraestructura desde su computadora portátil, un servidor de compilación o casi cualquier otra computadora, y no necesitará ejecutar ninguna infraestructura adicional para hacerlo.

Esto se debe a que el binario de Terraform realiza llamadas API en su nombre a uno o más proveedores, que incluyen Azure, AWS, Google Cloud, DigitalOcean y otros. Esto permite que Terraform aproveche la infraestructura que esos proveedores ya tienen para sus servidores API, así como los procesos de autenticación que requieren.

Pero Terraform no sabe qué solicitudes de API hacer, entonces, ¿cómo lo sabe? Las configuraciones de Terraform, que son archivos de texto en lenguaje declarativo que especifican qué infraestructura quieres generar, son la respuesta. El "código" en "infraestructura como código" son estas configuraciones.

Tiene control total sobre su infraestructura, incluidos servidores, bases de datos, balanceadores de carga, topología de red y más. En su nombre, el binario de Terraform analiza su código y lo convierte en una serie de llamadas API lo más rápido posible.

¿Qué es un lenguaje procedimental frente a un lenguaje declarativo?

Un lenguaje procedimental le permite especificar todo el proceso y enumerar los pasos necesarios para completarlo. Usted simplemente da instrucciones y especifica cómo se llevará a cabo el proceso. Chef y Ansible fomentan este método.

Los lenguajes declarativos, por otro lado, le permiten simplemente configurar el comando u orden y dejar que el sistema lo lleve a cabo. No necesita entrar en el proceso; solo necesitas el resultado. Algunos ejemplos son Terraform, cloudFormation y Puppeteer.

Basta de teoría...

Ahora es el momento de poner en acción la alta disponibilidad, seguridad, rendimiento y confiabilidad de Terraform.

Aquí, estamos hablando de un servidor Jenkins basado en Terraform en Amazon Web Services. Estamos configurando la red desde cero, así que comencemos.

Estructura de archivos/carpetas de nuestro proyecto

Usaremos una estrategia de desarrollo modular para separar la implementación de nuestro clúster de Jenkins en numerosos archivos de plantilla (en lugar de desarrollar un archivo de plantilla grande).

Cada archivo se encarga de ejecutar un componente de infraestructura de destino o un recurso de AWS.

Para crear y hacer cumplir la configuración de la infraestructura, Terraform aprovecha la sintaxis de un lenguaje de configuración similar a JSON llamado HCL (lenguaje de configuración de HashiCorp).

estructuras de archivos/carpetas

estructuras de archivos/carpetas

Cómo inicializar primero el estado de Terraform

Para seguir las mejores prácticas, almacenaremos nuestros archivos de estado de Terraform en nuestro almacenamiento en la nube. Esto es esencial especialmente para la colaboración en equipo.

Los archivos de estado de Terraform son archivos que contienen recursos de Terraform en los proyectos.

Dentro del archivo main.tf en la carpeta backend-state, agregue el siguiente código:

variable "aws_region" { 
	default = "us-east-1" 
 } 
variable "aws_secret_key" {} 
variable "aws_access_key" {} 

provider "aws" { 
	region = var.aws_region 
    access_key = var.aws_access_key 
    secret_key = var.aws_secret_key 
} 

resource "aws_s3_bucket" "terraform_state" { 
	bucket = "terraform-state-caesar-tutorial-jenkins" 
    
    lifecycle { 
    	prevent_destroy = true 
    } 
    
    versioning { 
    	enabled = true 
   } 
   
   server_side_encryption_configuration { 
   		rule { 
        	apply_server_side_encryption_by_default { 
            	sse_algorithm = "AES256" 
            } 
        } 
   } 
}

backend-estado/main.tf

Asegurémonos de saber qué está pasando en el código anterior.

Usamos variables para almacenar datos, y en Terraform usted declara una variable con la palabra clave variable seguida del nombre. El bloque de variables puede tomar algunas propiedades, como por defecto, descripción, tipo, etc., o ninguna. Verás esto mucho.

Ahora estamos declarando las variables como variable "variable_name"{}y usándolas en cualquier recurso/bloque de datos comovar.variable_name . Más adelante verá cómo asignaremos valores a esas variables en nuestro archivo secrets.tfvars.

Para usar Terraform, debe indicarle el proveedor con el que se comunicará y pasar sus propiedades requeridas para la autenticación. Aquí tenemos la región, el acceso y la clave secreta de AWS (debe tenerlos descargados en su sistema desde los requisitos previos).

En terraform, cada recurso que necesitamos está definido en el bloque de recursos. Recursos es la infraestructura subrayada que crea nuestro servicio en la nube. Sigue la sintaxis resource "terraform-resource-name" "custom-name" {}.

Terraform tiene muchos recursos para proveedores particulares en los documentos de terraform (consulte siempre los documentos si tiene preguntas).

A continuación, estamos creando aws_s3_bucket. Esto almacenará nuestro estado remoto. Toma las siguientes propiedades:

  • cubo → Esto tiene que ser globalmente único
  • ciclo de vida → Si necesita destruir sus recursos de Terraform, es posible que desee evitar la destrucción del estado, ya que se comparte entre equipos
  • control de versiones → Ayuda a proporcionar cierto control de versión sobre los estados
  • server_side_encryption_configuration → Proporciona cifrado.

Nuestro backend estatal está listo. Pero antes de inicializarlo, planificarlo y aplicarlo con Terraform, asignemos nuestra variable a sus valores .

En secrets.tfvars, agregue la siguiente información de su cuenta de AWS:

  aws_region = "us-east-1 
  aws_secret_key = "enter-your-secret" 
  aws_access_key = "enter-your-access    

backend-estado/secretos.tfvars

En su terminal en la misma carpeta de estado de fondo, ejecute terraform init.

estado de terraformación en la terminal

estado de terraformación en la terminal

Entonces terraform apply -var-file=secrets.tfvars:

estado de terraformación en la terminal

estado de terraformación en la terminal

En su consola de AWS , esto es lo que verá:

estado de terraformación en el cubo aws s3

estado de terraformación en el cubo aws s3

‌‌Ahora que nuestro estado está listo, pasemos a la siguiente parte.

Cómo aprovisionar una nube privada virtual de AWS

Para asegurar nuestro clúster de Jenkins, implementaremos la arquitectura dentro de una nube privada virtual (VPC) y una subred privada. Puede implementar el clúster en la VPC predeterminada de AWS.

Para tener un control completo sobre la topología de la red, crearemos una VPC desde cero.

 variable "cidr_block" {} 
 variable "aws_access_key" {} 
 variable "aws_secret_key" {} 
 variable "aws_region" {} 
 
 provider "aws" { 
 	region = var.aws_region 
    access_key = var.aws_access_key 
    secret_key = var.aws_secret_key 
} 

terraform { 
	backend "s3" { 
    	bucket     = "terraform-state-caesar-tutorial-jenkins" 
        key        = "tutorial-jenkins/development/network/terraform.tfstate" 
        region     = "us-east-1" 
        encrypt    = true 
   }
} 

resource "aws_vpc" "main_vpc" { 
	cidr_block           = var.cidr_block 
    enable_dns_support   = true 
    enable_dns_hostnames = true 
    
    tags = { 
    	Name        = "jenkins-instance-main_vpc" 
    } 
}

desarrollo/main.tf

output "vpc_id" { 
	value = aws_vpc.main_vpc.id 
} 

output "vpc_cidr_block" { 
	value = aws_vpc.main_vpc.cidr_block 
}  

desarrollo/salida.tf

cidr_block            = "172.0.0.0/16" 
aws_region = "us-east-1" 
aws_secret_key = "enter-your-secret" 
aws_access_key = "enter-your-access" 

desarrollo/secretos.tfvars

  • cidr_block → El enrutamiento entre dominios sin clase se conoce como CIDR. Un bloque CIDR es un rango de direcciones IP, en pocas palabras. Esto define en qué rango estamos trabajando.
  • salida → El bloque de salida en Terraform se usa para exportar valores de recursos a otros módulos. Este es otro término importante cuando se transfieren datos de un recurso en un módulo a otro recurso en un módulo separado. (Aprenderá qué módulos son pronto) Aquí está su sintaxis: output "custom_output_name" {  value = "resource-name"}. Toma una clave de valor que toma el recurso pasado. Aquí tenemos la salida vpc_id y cidr_block.

Ahora, en la terminal, ejecuta terraform inity terraform apply crea los recursos. Puede ejecutar terraform planantes para ver qué recursos está creando realmente. Aquí está el comando: terraform apply -var-file=secrets.tfvarsy la salida:

s_0475B692F95FDEC0A6E8498B95C86079E0E8D8D5196F9F4DEAA5AA6D3B79CB44_1655907973370_vpc

Debería ver su vpc_id y vpc_cidr_block en su consola de AWS :

recurso vpc en aws

vpc en aws

Cómo trabajar con módulos de Terraform

Un grupo de archivos de configuración típicos en un directorio específico conforman un módulo de Terraform. Los módulos de Terraform reúnen recursos que se utilizan para una sola operación. Esto reduce la cantidad de código que necesita para crear componentes de infraestructura idénticos.

Con la siguiente sintaxis, puede transferir un recurso del módulo Terraform a otro para que lo use.

module "custom-module-name" { 
	source     = "path-to-modules-resources" 
}

sintaxis de terraform-modules

Y para usar la salida de recursos del módulo dentro de otro módulo de recursos, este es el comando: module.custom-module-name.resource-output-value.

Cómo crear una subred de VPC

Crear una VPC no es suficiente: también necesitamos una subred para poder instalar instancias de Jenkins en esta red aislada. Debemos pasar el ID de VPC que mostramos antes, ya que esta subred pertenece a una VPC construida previamente.

Para la resiliencia, usaremos dos subredes públicas y dos subredes privadas en distintas zonas de disponibilidad. Cada subred tiene su propio bloque CIDR, que es un subconjunto del bloque VPC CIDR, que obtuvimos del recurso VPC.

resource "aws_subnet" "public_subnets" { 
	vpc_id         = var.vpc_id 
    cidr_block     = cidrsubnet(var.vpc_cidr_block, 8, 2 + count.index)  
   	availability_zone   = element(var.availability_zones, count.index)  	
    map_public_ip_on_launch = true 
    count                   = var.public_subnets_count 
    
    tags = { 
    	Name        = "jenkins-instance-public-subnet" 
   } 
} 

resource "aws_subnet" "private_subnets" { 
	vpc_id     = var.vpc_id 
    cidr_block = cidrsubnet(var.vpc_cidr_block, 8, count.index)  			
    availability_zone    = element(var.availability_zones, count.index)  
    map_public_ip_on_launch = false 
    count                   = var.private_subnets_count 
    
    tags = { 
    	Name        = "jenkins-instance-private-subnet" 
    } 
 }

módulos/subredes.tf

Muy bien, ¿qué está pasando en este código?

  • count El metaargumento count acepta un número entero y crea esa cantidad de instancias del recurso o módulo. Aquí estamos especificando 2 para cada una de las variables private_subnets_count y public_subnets_count.
  • map_public_ip_on_launch → Especifique true para indicar que a las instancias lanzadas en la subred se les debe asignar una dirección IP pública.
  • cidrsubnet() cidrsubnet calcula una dirección de subred dentro de un prefijo de dirección de red IP dado.
  • elemento() elemento recupera un solo elemento de una lista.

Ahora actualicemos las variables de nuestros módulos:

variable "vpc_id" {} 
variable "vpc_cidr_block" {} 
variable "private_subnets_count" {} 
variable "public_subnets_count" {} 
variable "availability_zones" {} 

desarrollo/modulos/variables.tf

Actualice secrets.tfvars así:

private_subnets_count = 2 
public_subnets_count  = 2

secretos.tfvars

Debe establecer tablas de rutas públicas y privadas para especificar el método de enrutamiento del tráfico en las subredes de VPC. Hagámoslo antes de ejecutar terraform apply en nuestros recursos.

Cómo configurar tablas de ruteo de VPC

Desarrollaremos tablas de rutas privadas y públicas para una gestión de tráfico detallada. Esto permitirá que las instancias implementadas en subredes privadas accedan a Internet sin estar expuestas al público en general.

Cómo crear una tabla de rutas pública

Primero, debemos establecer un recurso de puerta de enlace de Internet y vincularlo a la VPC que generamos anteriormente. Luego, debemos definir una tabla de rutas públicas y una ruta que apunte todo el tráfico (0.0.0.0/0) a la puerta de enlace de Internet. Y, por último, debemos vincularlo con subredes públicas en nuestra VPC para que el tráfico que fluye desde esas subredes se enrute a la puerta de enlace de Internet mediante la creación de una asociación de tabla de rutas.

/*** Internet Gateway - Provides a connection between the VPC and the public internet, allowing traffic to flow in and out of the VPC and translating IP addresses to public* addresses.*/ 
resource "aws_internet_gateway" "igw" { 
	vpc_id = var.vpc_id 
    
    tags = { 
    	Name = "igw_jenkins" 
   } 
} 

/*** A route from the public route table out to the internet through the internet* gateway.*/ 
resource "aws_route_table" "public_rt" { 
	vpc_id = var.vpc_id 
    
    route { 
    	cidr_block = "0.0.0.0/0" 
        gateway_id = aws_internet_gateway.igw.id 
   } 
   
   tags = { 
   		Name = "public_rt_jenkins" 
   } 
} 
/*** Associate the public route table with the public subnets.*/ 
resource "aws_route_table_association" "public" { 
	count     = var.public_subnets_count 
    subnet_id = element(var.public_subnets.*.id, count.index) 
    route_table_id = aws_route_table.public_rt.id 
}

desarrollo/módulos/public_rt.tf

‌Cómo crear una tabla de rutas privada

Ahora que nuestra tabla de rutas pública está terminada, creemos la tabla de rutas privada.

Para permitir que nuestras instancias de Jenkins se conecten a Internet mientras se implementa en la subred privada, construiremos un recurso de puerta de enlace NAT dentro de una subred pública.

Agregue una dirección IP elástica a la puerta de enlace NAT después de eso y una tabla de rutas privadas con una ruta (0.0.0.0/0) que dirija todo el tráfico a la ID de la puerta de enlace NAT que estableció. Luego adjuntamos subredes privadas a la tabla de rutas privadas creando la asociación de la tabla de rutas .

 /*** An elastic IP address to be used by the NAT Gateway defined below.  The NAT* gateway acts as a gateway between our private subnets and the public* internet, providing access out to the internet from within those subnets,* while denying access to them from the public internet.  This IP address* acts as the IP address from which all the outbound traffic from the private* subnets will originate.*/ 
 
 resource "aws_eip" "eip_for_the_nat_gateway" { 
 	vpc = true 
    
    tags = { 
    	Name = "jenkins-tutoral-eip_for_the_nat_gateway" 
    } 
} 

/*** A NAT Gateway that lives in our public subnet and provides an interface* between our private subnets and the public internet.  It allows traffic to* exit our private subnets, but prevents traffic from entering them.*/ 

resource "aws_nat_gateway" "nat_gateway" { 
	allocation_id = aws_eip.eip_for_the_nat_gateway.id 
    subnet_id     = element(var.public_subnets.*.id, 0) 
    
    tags = { 
    	Name = "jenkins-tutorial-nat_gateway" 
	} 
} 
/*** A route from the private route table out to the internet through the NAT * Gateway.*/ 

resource "aws_route_table" "private_rt" { 
	vpc_id = var.vpc_id 
    
    route { 
    	cidr_block     = "0.0.0.0/0" 
        nat_gateway_id = aws_nat_gateway.nat_gateway.id } 
        
        tags = { 
        	Name   = "private_rt_${var.vpc_name}" 
            Author = var.author 
        } 
} 
/*** Associate the private route table with the private subnet.*/ 
resource "aws_route_table_association" "private" { 
	count = var.private_subnets_count 
    subnet_id = element(aws_subnet.private_subnets.*.id, count.index) 
    route_table_id = aws_route_table.private_rt.id 
}

desarrollo/módulos/private_rt.tf

‌Ahora vamos a correr terraform apply. Pero necesitamos actualizar nuestros archivos main.tf (ya que este es nuestro archivo terraform de entrada) para estar al tanto de nuestras subredes y variables de módulo y secrets.tfvars (para nuestras variables).

variable "vpc_id" {} 
variable "vpc_cidr_block" {} 
variable "private_subnets_count" {} 
variable "public_subnets_count" {} 
variable "availability_zones" {} 
variable "public_subnets" {}

desarrollo/módulos/variables.ftvars

variable "private_subnets_count" {} 
variable "public_subnets_count" {} 
variable "availability_zones" {} 

module "subnet_module" { 
	source     = "./modules" 
    vpc_id     = aws_vpc.main_vpc.id 
    vpc_cidr_block = aws_vpc.main_vpc.cidr_block 
    availability_zones = var.availability_zones 
    public_subnets_count = var.public_subnets_count 
    private_subnets_count = var.private_subnets_count 
 }

desarrollo/main.tf

 availability_zones    = ["us-east-1a", "us-east-1b", "us-east-1c", "us-east-1d", "us-east-1e"]

desarrollo/secretos.tf

Nuestras subredes y respectivos valores están listos. Ahora podemos inicializarlo, planificarlo y aplicarlo con Terraform.

Ejecutaremos terraform apply para crear los recursos. Puede ejecutar el plan de terraformación antes para ver qué recursos está creando realmente.

En la ejecución de la terminal . terraform apply -var-file=secrets.tfvars

s_0475B692F95FDEC0A6E8498B95C86079E0E8D8D5196F9F4DEAA5AA6D3B79CB44_1656906570979_estado-terminal-3

Solo tenga en cuenta que la cantidad de recursos agregados aquí puede diferir de la suya.

Aquí está la consola de AWS (subredes, dirección elástica, tablas de rutas):

subredes

subredes tablas de rutaselástico ipIP elásticastablas de rutas

Cómo configurar un host bastión de VPC

Implementamos nuestro clúster de Jenkins dentro de las subredes privadas. Debido a que el clúster carece de una IP pública, las instancias no estarán disponibles públicamente a través de Internet. Entonces, para encargarnos de esto, configuraremos un host bastión para que podamos acceder a las instancias de Jenkins de manera segura.

Agregue los siguientes recursos y grupo de seguridad en el archivo bastion.tf:

/*** A security group to allow SSH access into our bastion instance.*/ 
resource "aws_security_group" "bastion" { 
	name   = "bastion-security-group" 
    vpc_id = var.vpc_id 
    
    ingress { 
    	protocol    = "tcp" 
        from_port   = 22 
        to_port     = 22 
        cidr_blocks = ["0.0.0.0/0"] 
    } 
    egress { 
    	protocol    = -1 
        from_port   = 0 
        to_port     = 0 
        cidr_blocks = ["0.0.0.0/0"] 
   } 
   
   tags = { 
   		Name = "aws_security_group.bastion_jenkins" 
   } 
} 

/*** The public key for the key pair we'll use to ssh into our bastion instance.*/ 

resource "aws_key_pair" "bastion" { 
	key_name   = "bastion-key-jenkins" 
    public_key = var.public_key 
 } 
 
 /*** This parameter contains the AMI ID for the most recent Amazon Linux 2 ami,* managed by AWS.*/ 
 
 data "aws_ssm_parameter" "linux2_ami" { 
 	name = "/aws/service/ami-amazon-linux-latest/amzn-ami-hvm-x86_64-ebs" 
} 

/*** Launch a bastion instance we can use to gain access to the private subnets of* this availabilty zone.*/ 

resource "aws_instance" "bastion" { 
	ami           = data.aws_ssm_parameter.linux2_ami.value 
    key_name      = aws_key_pair.bastion.key_name 
    instance_type = "t2.large" 
    associate_public_ip_address = true 
    subnet_id                   = element(aws_subnet.public_subnets, 0).id 
    vpc_security_group_ids      = [aws_security_group.bastion.id] 
    
    tags = { 
    	Name        = "jenkins-bastion" 
    } 
} 

output "bastion" { value = aws_instance.bastion.public_ip }

bastión.tf

Veamos qué está pasando en el código aquí:

  • Recurso de grupo de seguridad de bastión: las instancias EC2 recién generadas no permiten el acceso SSH.
  • Vincularemos un grupo de seguridad a la instancia activa para habilitar el acceso SSH a los hosts bastión. El grupo de seguridad permitirá cualquier tráfico entrante (ingreso) en el puerto 22 (SSH) desde cualquier lugar (0.0.0.0/0). Para mejorar la seguridad y evitar violaciones de seguridad, puede sustituir su propia dirección IP pública/32 o dirección de red por el bloque fuente CIDR.
  • aws_key_pair: para poder conectarse al host bastión mediante SSH y la clave privada, agregamos un par de claves SSH cuando creamos el EC2. Nuestra clave SSH pública se utiliza en el par de claves. Usando el comando sshkeygen , también puede crear uno nuevo.
  • aws_ssm_parameter : la instancia EC2 utiliza la imagen de máquina Linux de Amazon 2. El ID de AMI se obtiene del mercado de AWS utilizando la fuente de datos de AMI de AWS
  • aws_instance:  finalmente, implementamos nuestra instancia de bastión EC2 con sus configuraciones definidas y acceso
  • salida : al especificar una salida, usamos la funcionalidad de salidas de Terraform para mostrar la dirección IP en la sesión de la terminal.

Ahora, actualicemos nuestra variable dentro de los módulos y main.tf con la nueva public_key que estamos pasando como variable:

variable "public_key"{} 

desarrollo/módulos/variables/tfvars

varable "public_key" {} 
module "subnet_module" { 
	source     = "./modules" 
    ... 
    publc_key = var.public_key 
}

desarrollo/main.tf

public_key = "enter-your-public-key"

desarrollo/secretos.tf

Ejecutaremos terraform apply para crear los recursos. Puede ejecutar el plan de terraformación antes para ver qué recursos está creando realmente.

En la terminal, vamos a ejecutar terraform apply -var-file=secrets.tfvars:

recursos terminales

recursos terminales

Aquí está el resultado en la consola de AWS:

instancias de la consola de aws

instancias de la consola de aws

Cómo aprovisionar nuestro servicio informático

Instancia maestra de Jenkins

Hasta ahora, hemos podido configurar con éxito nuestra VPC y la topología de red. ‌‌Finalmente, crearemos nuestra instancia EC2 de Jenkins que usará una AMI maestra de Jenkins creada por Packer.

Puede consultar mi artículo anterior sobre cómo se creó: Aprenda la infraestructura como código mediante la creación de una imagen de máquina personalizada en AWS en freecodecamp.org . Independientemente, puede usar cualquiera de sus imágenes personalizadas si tiene una.

 /*** This parameter contains our baked AMI ID fetch from the Amazon Console*/ data "aws_ami" "jenkins-master" { 
 	most_recent = true owners      = ["self"] 
} 

resource "aws_security_group" "jenkins_master_sg" { 
	name        = "jenkins_master_sg" 
    description = "Allow traffic on port 8080 and enable SSH" 
    vpc_id      = var.vpc_id 
    
    ingress { 
    	from_port       = "22" 
        to_port         = "22" 
        protocol        = "tcp" 
        security_groups = [aws_security_group.bastion.id] 
   } 
   ingress { 
   		from_port       = "8080" 
        to_port         = "8080" 
        protocol        = "tcp" 
        security_groups = [aws_security_group.lb.id] 
   } 
   ingress { 
   		from_port   = "8080" 
        to_port     = "8080" 
        protocol    = "tcp" 
        cidr_blocks = ["0.0.0.0/0"] 
  } 
  egress { 
  		from_port   = "0" 
        to_port     = "0" 
        protocol    = "-1" 
        cidr_blocks = ["0.0.0.0/0"] 
  } 
  
  tags = { 
  	Name = "jenkins_master_sg" 
  }
} 

desarrollo/módulos/jenkins_master.tf

Asociar un grupo de seguridad a la instancia habilitará el tráfico entrante en el puerto 8080 (el panel web de Jenkins) y SSH solo desde el servidor bastión y el bloque CIDR de la VPC.

resource "aws_key_pair" "jenkins" { 
	key_name   = "key-jenkins" 
    public_key = var.public_key 
} 

resource "aws_instance" "jenkins_master" { 
	ami       = data.aws_ami.jenkins-master.id 
    instance_type  = "t2.large" 
    key_name       = aws_key_pair.jenkins.key_name 
    vpc_security_group_ids = [aws_security_group.jenkins_master_sg.id]
    subnet_id              = element(aws_subnet.private_subnets, 0).id
    root_block_device { 
    	volume_type           = "gp3" 
        volume_size           = 30 
        delete_on_termination = false 
    } 
    
    tags = { 
    	Name = "jenkins_master" 
     } 
 }

desarrollo/módulos/jenkins_master.tf

A continuación, creamos una variable y definimos el tipo de instancia que usamos para implementar la instancia EC2. No asignaremos ejecutores ni trabajadores en el maestro, por lo que t2.large (8 GB de memoria y 2 vCPU) debería ser adecuado para fines de simplicidad.

Por lo tanto, los trabajos de compilación no harán que el maestro de Jenkins se sobrecargue. Pero los requisitos de memoria de Jenkins varían según los requisitos de compilación de su proyecto y las herramientas utilizadas en esas compilaciones. Se requerirán de dos a tres subprocesos, o al menos 2 MB de memoria, para conectarse a cada nodo de compilación.

Solo una nota: considere instalar trabajadores de Jenkins para evitar trabajar en exceso el maestro. Como resultado, una instancia de uso general puede albergar un maestro de Jenkins y ofrecer un equilibrio entre los recursos informáticos y de memoria. Para mantener la simplicidad del artículo, no lo haremos.

Cómo crear el balanceador de carga

Para acceder al tablero de Jenkins, crearemos un balanceador de carga público frente a la instancia EC2.

Este balanceador de carga elástico aceptará tráfico HTTP en el puerto 80 y lo reenviará a la instancia EC2 en el puerto 8080. Además, verifica automáticamente el estado de la instancia EC2 registrada en el puerto 8080. Si Elastic Load Balancing (ELB) encuentra que la instancia no está en buen estado , deja de enviar tráfico a la instancia de Jenkins.

 /*** A security group to allow SSH access into our load balancer*/ resource "aws_security_group" "lb" { 
 	name   = "ecs-alb-security-group" 
    vpc_id = var.vpc_id 
    
    ingress { 
    	protocol    = "tcp" 
        from_port   = 80 
        to_port     = 80 
        cidr_blocks = ["0.0.0.0/0"] 
     } 
     egress { 
     	from_port   = 0 
        to_port     = 0 
        protocol    = "-1" 
        cidr_blocks = ["0.0.0.0/0"] 
     } 
     
     tags = { 
     	Name = "jenkins-lb-sg" 
      } 
 } 
 
 /***Load Balancer to be attached to the ECS cluster to distribute the load among instances*/ 
 
 resource "aws_elb" "jenkins_elb" { 
 	subnets    = [for subnet in aws_subnet.public_subnets : subnet.id]
    cross_zone_load_balancing = true 
    security_groups       = [aws_security_group.lb.id] 
    instances             = [aws_instance.jenkins_master.id] 
    
    listener { 
    	instance_port     = 8080 
        instance_protocol = "http" 
        lb_port           = 80 
        lb_protocol       = "http" 
     } 
     
     health_check { 
     	healthy_threshold   = 2 
        unhealthy_threshold = 2 
        timeout             = 3 
        target              = "TCP:8080"    
        interval            = 5 
    } 
    
    tags = { 
    	Name = "jenkins_elb" 
    } 
 } 
 
 output "load-balancer-ip" { 
 	value = aws_elb.jenkins_elb.dns_name 
 }

desarrollo/módulos/loadbalancer.tf

Antes, aplicamos nuestra terraformación, actualicemos nuestra carpeta development/output.tf para generar el DNS del equilibrador de carga:

 output "load-balancer-ip" { 
 	value = module.subnet_module.load-balancer-ip
 }

desarrollo/salida.tf

En la terminal, ejecute el siguiente comando: terraform apply -var-file="secrets.tfvars". Que te dará esto:

salida del balanceador de carga

salida del balanceador de carga

Después de aplicar los cambios con Terraform, la URL del balanceador de carga maestro de Jenkins debería mostrarse en su sesión de terminal.

Dirija su navegador favorito a la URL y debería tener acceso al panel web de Jenkins.

instancias de jenkins

instancias de jenkins

Luego simplemente siga las instrucciones de la pantalla para DESBLOQUEAR.

desbloquear jenkins

desbloquear jenkins

Puede encontrar el código completo en este repositorio de GitHub.

Limpiar

Para evitar el costo innecesario de ejecutar los servicios de AWS, deberá ejecutar el siguiente comando para destruir todos los recursos creados y en ejecución: terraform destroy -var-file="secrets.tfvars"‌‌ que debería generar este resultado:

destruir recursos

destruir recursos

Qué interesante, ¿verdad? Con solo unas pocas líneas de código, podemos destruir y acelerar nuestros recursos.

Resumen

En este tutorial, ha aprendido a usar Terraform a un alto nivel. También aprendió una de sus aplicaciones al aprovisionar un servidor Jenkins en la plataforma en la nube de AWS.

También aprendió sobre las mejores prácticas de los módulos y estados de back-end de Terraform.

¡Feliz aprendizaje! 

Fuente: https://www.freecodecamp.org/news/learn-terraform-by-deploying-jenkins-server-on-aws/

 #jenkins #aws #terraform

Aprenda Terraform Implementando Un Servidor Jenkins En AWS
Thierry  Perret

Thierry Perret

1658955600

Découvrez Terraform En Déployant Un Serveur Jenkins Sur AWS

Aujourd'hui, nous allons découvrir Terraform en construisant un projet.

Terraform est plus qu'un simple outil pour booster la productivité des équipes opérationnelles. Vous avez la possibilité de transformer vos développeurs en opérateurs en implémentant Terraform.

Cela peut aider à augmenter l'efficacité de toute votre équipe d'ingénierie et à améliorer la communication entre les développeurs et les opérateurs.

Dans cet article, je vais vous montrer comment automatiser entièrement le déploiement de vos services Jenkins sur le cloud AWS à l'aide de Terraform avec une image personnalisée.

Qu'est-ce que Terraform ?

Terraform by HashiCorp est une infrastructure en tant que solution de code. Il vous permet de spécifier des ressources cloud et sur site dans des fichiers de configuration lisibles par l'homme que vous pouvez réutiliser et partager. Il s'agit d'un puissant outil de provisionnement DevOps.

Pourquoi devriez-vous utiliser Terraform ?

Terraform a un certain nombre de cas d'utilisation, y compris la capacité de :

  • Spécifiez l'infrastructure dans la configuration/le code et reconstruisez/modifiez et suivez facilement les modifications apportées à l'infrastructure.
  • Prise en charge de différentes plates-formes cloud
  • Effectuer des modifications de ressources incrémentielles
  • Prise en charge de la mise en réseau définie par logiciel

Comment fonctionne Terraform

Voyons comment fonctionne Terraform à un niveau élevé.

Terraform est développé dans le langage de programmation Go. Le code Go est compilé dans terraform, un binaire unique. Vous pouvez utiliser ce binaire pour déployer une infrastructure à partir de votre ordinateur portable, d'un serveur de build ou de n'importe quel autre ordinateur, et vous n'aurez pas besoin d'exécuter d'infrastructure supplémentaire pour le faire.

En effet, le binaire Terraform effectue des appels d'API en votre nom à un ou plusieurs fournisseurs, notamment Azure, AWS, Google Cloud, DigitalOcean et autres. Cela permet à Terraform de tirer parti de l'infrastructure que ces fournisseurs ont déjà en place pour leurs serveurs d'API, ainsi que des processus d'authentification dont ils ont besoin.

Mais Terraform ne sait pas quelles requêtes API faire - alors comment le sait-il ? Les configurations Terraform, qui sont des fichiers texte en langage déclaratif qui spécifient l'infrastructure que vous souhaitez générer, sont la réponse. Le "code" dans "l'infrastructure en tant que code" correspond à ces configurations.

Vous avez un contrôle total sur votre infrastructure, y compris les serveurs, les bases de données, les équilibreurs de charge, la topologie du réseau, etc. En votre nom, le binaire Terraform analyse votre code et le convertit en une série d'appels d'API aussi rapidement que possible.

Qu'est-ce qu'un langage procédural vs un langage déclaratif ?

Un langage procédural vous permet de spécifier l'ensemble du processus et de lister les étapes nécessaires pour le mener à bien. Vous donnez simplement des instructions et précisez comment le processus sera effectué. Chef et Ansible encouragent cette méthode.

Les langages déclaratifs, en revanche, vous permettent de définir simplement la commande ou l'ordre et de laisser le système s'en charger. Vous n'avez pas besoin d'entrer dans le processus; vous avez juste besoin du résultat. Les exemples sont Terraform, cloudFormation et Puppeteer.

Assez de théorie...

Le moment est venu de mettre en action la haute disponibilité, la sécurité, les performances et la fiabilité de Terraform.

Ici, nous parlons d'un serveur Jenkins basé sur Terraform sur Amazon Web Services. Nous mettons en place le réseau à partir de zéro, alors commençons.

Prérequis et installation

Il y a quelques éléments que vous devrez avoir configurés et installés pour suivre ce didacticiel :

Structure des fichiers/dossiers de notre projet

Nous utiliserons une stratégie de développement modulaire pour séparer notre déploiement de cluster Jenkins en plusieurs fichiers modèles (plutôt que de développer un seul fichier modèle volumineux).

Chaque fichier est chargé d'exécuter un composant d'infrastructure cible ou une ressource AWS.

Pour créer et appliquer les paramètres d'infrastructure, Terraform exploite la syntaxe d'un langage de configuration de type JSON appelé HCL (HashiCorp Configuration Language).

structure des fichiers/dossiers

structure des fichiers/dossiers

Comment initialiser d'abord l'état de Terraform

Pour suivre les meilleures pratiques, nous stockerons nos fichiers d'état Terraform dans notre stockage cloud. Ceci est essentiel, en particulier pour la collaboration en équipe.

Les fichiers d'état Terraform sont des fichiers qui contiennent des ressources Terraform sur les projets.

Dans le fichier main.tf du dossier backend-state, ajoutez le code suivant :

variable "aws_region" { 
	default = "us-east-1" 
 } 
variable "aws_secret_key" {} 
variable "aws_access_key" {} 

provider "aws" { 
	region = var.aws_region 
    access_key = var.aws_access_key 
    secret_key = var.aws_secret_key 
} 

resource "aws_s3_bucket" "terraform_state" { 
	bucket = "terraform-state-caesar-tutorial-jenkins" 
    
    lifecycle { 
    	prevent_destroy = true 
    } 
    
    versioning { 
    	enabled = true 
   } 
   
   server_side_encryption_configuration { 
   		rule { 
        	apply_server_side_encryption_by_default { 
            	sse_algorithm = "AES256" 
            } 
        } 
   } 
}

backend-state/main.tf

Assurons-nous de savoir ce qui se passe dans le code ci-dessus.

Nous utilisons des variables pour stocker des données, et dans Terraform, vous déclarez une variable avec le mot-clé variable suivi du nom. Le bloc de variables peut prendre certaines propriétés telles que la valeur par défaut, la description, le type, etc., ou aucune. Vous verrez cela beaucoup.

Maintenant, nous déclarons les variables en tant que variable "variable_name"{}et les utilisons dans n'importe quel bloc de ressources/données en tant quevar.variable_name . Plus tard, vous verrez comment nous attribuerons des valeurs à ces variables dans notre fichier secrets.tfvars.

Pour utiliser Terraform, vous devez lui indiquer le fournisseur avec lequel il communiquera et transmettre ses propriétés requises pour l'authentification. Ici, nous avons la région AWS, l'accès et la clé secrète (vous devriez les avoir téléchargés sur votre système à partir des prérequis).

Dans terraform, chaque ressource dont nous avons besoin est définie dans le bloc de ressources. Les ressources sont l'infrastructure sous-jacente qui crée notre service cloud. Il suit la syntaxe resource "terraform-resource-name" "custom-name" {}.

Terraform a beaucoup de ressources pour des fournisseurs particuliers dans les docs terraform (référez-vous toujours aux docs si vous avez des questions).

Ensuite, nous créons le aws_s3_bucket. Cela stockera notre état distant. Il prend les propriétés suivantes :

  • bucket → Cela doit être unique au monde
  • cycle de vie → Si vous devez détruire vos ressources Terraform, vous voudrez peut-être empêcher la destruction de l'état car il est partagé entre les équipes
  • versioning → Aide à fournir un certain contrôle de version sur les états
  • server_side_encryption_configuration → Fournit le chiffrement.

Notre backend d'état est prêt. Mais avant de l'initialiser, de le planifier et de l'appliquer avec Terraform, attribuons notre variable à ses valeurs .

Dans secrets.tfvars, ajoutez les informations suivantes à partir de votre compte AWS :

  aws_region = "us-east-1 
  aws_secret_key = "enter-your-secret" 
  aws_access_key = "enter-your-access    

backend-state/secrets.tfvars

Dans votre terminal dans le même dossier backend-state, exécutez terraform init.

état de terraform sur le terminal

état de terraform sur le terminal

Ensuite terraform apply -var-file=secrets.tfvars:

état de terraform sur le terminal

état de terraform sur le terminal

Dans votre console AWS , voici ce que vous verrez :

état terraform sur le compartiment aws s3

état terraform sur le compartiment aws s3

‌‌Maintenant que notre état est prêt, passons à la partie suivante.

Comment provisionner un cloud privé virtuel AWS

Pour sécuriser notre cluster Jenkins, nous déploierons l'architecture au sein d'un cloud privé virtuel (VPC) et d'un sous-réseau privé. Vous pouvez déployer le cluster dans le VPC par défaut AWS.

Pour avoir un contrôle total sur la topologie du réseau, nous allons créer un VPC à partir de rien.

 variable "cidr_block" {} 
 variable "aws_access_key" {} 
 variable "aws_secret_key" {} 
 variable "aws_region" {} 
 
 provider "aws" { 
 	region = var.aws_region 
    access_key = var.aws_access_key 
    secret_key = var.aws_secret_key 
} 

terraform { 
	backend "s3" { 
    	bucket     = "terraform-state-caesar-tutorial-jenkins" 
        key        = "tutorial-jenkins/development/network/terraform.tfstate" 
        region     = "us-east-1" 
        encrypt    = true 
   }
} 

resource "aws_vpc" "main_vpc" { 
	cidr_block           = var.cidr_block 
    enable_dns_support   = true 
    enable_dns_hostnames = true 
    
    tags = { 
    	Name        = "jenkins-instance-main_vpc" 
    } 
}

développement/main.tf

output "vpc_id" { 
	value = aws_vpc.main_vpc.id 
} 

output "vpc_cidr_block" { 
	value = aws_vpc.main_vpc.cidr_block 
}  

développement/sortie.tf

cidr_block            = "172.0.0.0/16" 
aws_region = "us-east-1" 
aws_secret_key = "enter-your-secret" 
aws_access_key = "enter-your-access" 

développement/secrets.tfvars

  • cidr_block → Le routage inter-domaine sans classe est appelé CIDR. Un bloc CIDR est une plage d'adresses IP, pour faire simple. Cela définit dans quelle gamme nous travaillons.
  • sortie → Le bloc de sortie dans Terraform est utilisé pour exporter les valeurs des ressources vers d'autres modules. Il s'agit d'un autre terme important lors du transfert des données d'une ressource dans un module vers une autre ressource dans un module séparé. (Vous apprendrez bientôt ce que sont les modules) Voici sa syntaxe : output "custom_output_name" {  value = "resource-name"}. Il prend une clé de valeur qui prend la ressource transmise. Ici, nous sortons vpc_id et cidr_block.

Maintenant, dans le terminal, exécutez terraform initet terraform apply créez les ressources. Vous pouvez exécuter terraform planavant pour voir quelles ressources vous créez réellement. Voici la commande : terraform apply -var-file=secrets.tfvars, et le résultat :

s_0475B692F95FDEC0A6E8498B95C86079E0E8D8D5196F9F4DEAA5AA6D3B79CB44_1655907973370_vpc

Vous devriez voir vos vpc_id et vpc_cidr_block dans votre AWS Console :

ressource vpc sur aws

vpc sur aws

Comment travailler avec les modules Terraform

Un groupe de fichiers de configuration typiques dans un répertoire spécifique constitue un module Terraform. Les modules Terraform rassemblent des ressources qui sont utilisées pour une seule opération. Cela réduit la quantité de code dont vous avez besoin pour créer des composants d'infrastructure identiques.

En utilisant la syntaxe ci-dessous, vous pouvez transférer une ressource de module Terraform vers une autre à utiliser.

module "custom-module-name" { 
	source     = "path-to-modules-resources" 
}

syntaxe des modules terraform

Et pour utiliser la sortie de la ressource du module dans un autre module de ressources, voici la commande : module.custom-module-name.resource-output-value.

Comment créer un sous-réseau VPC

Créer un VPC ne suffit pas, il nous faut aussi un sous-réseau pour pouvoir installer des instances Jenkins sur ce réseau isolé. Nous devons transmettre l'ID de VPC que nous avons généré auparavant, car ce sous-réseau appartient à un VPC précédemment construit.

Pour la résilience, nous utiliserons deux sous-réseaux publics et deux sous-réseaux privés dans des zones de disponibilité distinctes. Chaque sous-réseau a son propre bloc CIDR, qui est un sous-ensemble du bloc CIDR VPC, que nous avons obtenu de la ressource VPC.

resource "aws_subnet" "public_subnets" { 
	vpc_id         = var.vpc_id 
    cidr_block     = cidrsubnet(var.vpc_cidr_block, 8, 2 + count.index)  
   	availability_zone   = element(var.availability_zones, count.index)  	
    map_public_ip_on_launch = true 
    count                   = var.public_subnets_count 
    
    tags = { 
    	Name        = "jenkins-instance-public-subnet" 
   } 
} 

resource "aws_subnet" "private_subnets" { 
	vpc_id     = var.vpc_id 
    cidr_block = cidrsubnet(var.vpc_cidr_block, 8, count.index)  			
    availability_zone    = element(var.availability_zones, count.index)  
    map_public_ip_on_launch = false 
    count                   = var.private_subnets_count 
    
    tags = { 
    	Name        = "jenkins-instance-private-subnet" 
    } 
 }

modules/sous-réseaux.tf

D'accord, que se passe-t-il dans ce code ?

  • count Le méta-argument count accepte un nombre entier et crée autant d'instances de la ressource ou du module. Ici, nous spécifions 2 chacun aux variables private_subnets_count et public_subnets_count.
  • map_public_ip_on_launch → Spécifiez true pour indiquer que les instances lancées dans le sous-réseau doivent se voir attribuer une adresse IP publique.
  • cidrsubnet() cidrsubnet calcule une adresse de sous-réseau dans un préfixe d'adresse réseau IP donné.
  • element() element récupère un seul élément d'une liste.

Maintenant, mettons à jour nos variables de modules :

variable "vpc_id" {} 
variable "vpc_cidr_block" {} 
variable "private_subnets_count" {} 
variable "public_subnets_count" {} 
variable "availability_zones" {} 

développement/modules/variables.tf

Mettez à jour les secrets.tfvars comme ceci :

private_subnets_count = 2 
public_subnets_count  = 2

secrets.tfvars

Vous devez établir des tables de routage privées et publiques pour spécifier la méthode de routage du trafic dans les sous-réseaux VPC. Faisons cela avant d'exécuter terraform apply sur nos ressources.

Comment configurer les tables de routage VPC

Nous développerons des tables de routage privées et publiques pour une gestion fine du trafic. Cela permettra aux instances déployées dans des sous-réseaux privés d'accéder à Internet sans être exposées au grand public.

Comment créer une table de routage publique

Nous devons d'abord établir une ressource de passerelle Internet et la lier au VPC que nous avons généré précédemment. Ensuite, nous devons définir une table de routage publique et une route qui dirige tout le trafic (0.0.0.0/0) vers la passerelle Internet. Et enfin, nous devons le lier aux sous-réseaux publics de notre VPC afin que le trafic provenant de ces sous-réseaux soit acheminé vers la passerelle Internet en créant une association de table de routage.

/*** Internet Gateway - Provides a connection between the VPC and the public internet, allowing traffic to flow in and out of the VPC and translating IP addresses to public* addresses.*/ 
resource "aws_internet_gateway" "igw" { 
	vpc_id = var.vpc_id 
    
    tags = { 
    	Name = "igw_jenkins" 
   } 
} 

/*** A route from the public route table out to the internet through the internet* gateway.*/ 
resource "aws_route_table" "public_rt" { 
	vpc_id = var.vpc_id 
    
    route { 
    	cidr_block = "0.0.0.0/0" 
        gateway_id = aws_internet_gateway.igw.id 
   } 
   
   tags = { 
   		Name = "public_rt_jenkins" 
   } 
} 
/*** Associate the public route table with the public subnets.*/ 
resource "aws_route_table_association" "public" { 
	count     = var.public_subnets_count 
    subnet_id = element(var.public_subnets.*.id, count.index) 
    route_table_id = aws_route_table.public_rt.id 
}

développement/modules/public_rt.tf

‌Comment créer une table de routage privée

Maintenant que notre table de routage publique est terminée, créons la table de routage privée.

Pour permettre à nos instances Jenkins de se connecter à Internet lors de son déploiement sur le sous-réseau privé, nous allons construire une ressource de passerelle NAT à l' intérieur d'un sous-réseau public.

Ajoutez ensuite une adresse IP Elastic à la passerelle NAT et une table de routage privée avec une route (0.0.0.0/0) qui dirige tout le trafic vers l'ID de la passerelle NAT que vous avez établie. Ensuite, nous attachons des sous-réseaux privés à la table de routage privée en créant l' association de table de routage .

 /*** An elastic IP address to be used by the NAT Gateway defined below.  The NAT* gateway acts as a gateway between our private subnets and the public* internet, providing access out to the internet from within those subnets,* while denying access to them from the public internet.  This IP address* acts as the IP address from which all the outbound traffic from the private* subnets will originate.*/ 
 
 resource "aws_eip" "eip_for_the_nat_gateway" { 
 	vpc = true 
    
    tags = { 
    	Name = "jenkins-tutoral-eip_for_the_nat_gateway" 
    } 
} 

/*** A NAT Gateway that lives in our public subnet and provides an interface* between our private subnets and the public internet.  It allows traffic to* exit our private subnets, but prevents traffic from entering them.*/ 

resource "aws_nat_gateway" "nat_gateway" { 
	allocation_id = aws_eip.eip_for_the_nat_gateway.id 
    subnet_id     = element(var.public_subnets.*.id, 0) 
    
    tags = { 
    	Name = "jenkins-tutorial-nat_gateway" 
	} 
} 
/*** A route from the private route table out to the internet through the NAT * Gateway.*/ 

resource "aws_route_table" "private_rt" { 
	vpc_id = var.vpc_id 
    
    route { 
    	cidr_block     = "0.0.0.0/0" 
        nat_gateway_id = aws_nat_gateway.nat_gateway.id } 
        
        tags = { 
        	Name   = "private_rt_${var.vpc_name}" 
            Author = var.author 
        } 
} 
/*** Associate the private route table with the private subnet.*/ 
resource "aws_route_table_association" "private" { 
	count = var.private_subnets_count 
    subnet_id = element(aws_subnet.private_subnets.*.id, count.index) 
    route_table_id = aws_route_table.private_rt.id 
}

développement/modules/private_rt.tf

‌Maintenant, allons courir terraform apply. Mais nous devons mettre à jour nos fichiers main.tf (car il s'agit de notre fichier terraform d'entrée) pour connaître nos variables de sous-réseaux et de module et secrets.tfvars (pour nos variables).

variable "vpc_id" {} 
variable "vpc_cidr_block" {} 
variable "private_subnets_count" {} 
variable "public_subnets_count" {} 
variable "availability_zones" {} 
variable "public_subnets" {}

développement/modules/variables.ftvars

variable "private_subnets_count" {} 
variable "public_subnets_count" {} 
variable "availability_zones" {} 

module "subnet_module" { 
	source     = "./modules" 
    vpc_id     = aws_vpc.main_vpc.id 
    vpc_cidr_block = aws_vpc.main_vpc.cidr_block 
    availability_zones = var.availability_zones 
    public_subnets_count = var.public_subnets_count 
    private_subnets_count = var.private_subnets_count 
 }

développement/main.tf

 availability_zones    = ["us-east-1a", "us-east-1b", "us-east-1c", "us-east-1d", "us-east-1e"]

développement/secrets.tf

Nos sous-réseaux et les titres respectifs sont prêts. Nous pouvons maintenant l'initialiser, le planifier et l'appliquer avec Terraform.

Nous exécuterons terraform apply pour créer les ressources. Vous pouvez exécuter terraform plan avant pour voir quelles ressources vous créez réellement.

Dans le terminal, exécutez . terraform apply -var-file=secrets.tfvars

s_0475B692F95FDEC0A6E8498B95C86079E0E8D8D5196F9F4DEAA5AA6D3B79CB44_1656906570979_état-terminal-3

N'oubliez pas que le nombre de ressources ajoutées ici peut différer du vôtre.

Voici la console AWS (sous-réseaux, adresse élastique, route_tables) :

sous-réseaux

sous-réseaux tables de routageIP élastiqueIP élastiquestables de routage

Comment configurer un hôte bastion VPC

Nous avons déployé notre cluster Jenkins à l'intérieur des sous-réseaux privés. Étant donné que le cluster n'a pas d'adresse IP publique, les instances ne seront pas accessibles au public via Internet. Donc, pour nous en occuper, nous allons mettre en place un hôte bastion afin que nous puissions accéder aux instances Jenkins en toute sécurité.

Ajoutez les ressources et le groupe de sécurité suivants dans le fichier bastion.tf :

/*** A security group to allow SSH access into our bastion instance.*/ 
resource "aws_security_group" "bastion" { 
	name   = "bastion-security-group" 
    vpc_id = var.vpc_id 
    
    ingress { 
    	protocol    = "tcp" 
        from_port   = 22 
        to_port     = 22 
        cidr_blocks = ["0.0.0.0/0"] 
    } 
    egress { 
    	protocol    = -1 
        from_port   = 0 
        to_port     = 0 
        cidr_blocks = ["0.0.0.0/0"] 
   } 
   
   tags = { 
   		Name = "aws_security_group.bastion_jenkins" 
   } 
} 

/*** The public key for the key pair we'll use to ssh into our bastion instance.*/ 

resource "aws_key_pair" "bastion" { 
	key_name   = "bastion-key-jenkins" 
    public_key = var.public_key 
 } 
 
 /*** This parameter contains the AMI ID for the most recent Amazon Linux 2 ami,* managed by AWS.*/ 
 
 data "aws_ssm_parameter" "linux2_ami" { 
 	name = "/aws/service/ami-amazon-linux-latest/amzn-ami-hvm-x86_64-ebs" 
} 

/*** Launch a bastion instance we can use to gain access to the private subnets of* this availabilty zone.*/ 

resource "aws_instance" "bastion" { 
	ami           = data.aws_ssm_parameter.linux2_ami.value 
    key_name      = aws_key_pair.bastion.key_name 
    instance_type = "t2.large" 
    associate_public_ip_address = true 
    subnet_id                   = element(aws_subnet.public_subnets, 0).id 
    vpc_security_group_ids      = [aws_security_group.bastion.id] 
    
    tags = { 
    	Name        = "jenkins-bastion" 
    } 
} 

output "bastion" { value = aws_instance.bastion.public_ip }

bastion.tf

Voyons ce qui se passe dans le code ici :

  • Ressource de groupe de sécurité bastion – Les instances EC2 nouvellement générées n'autorisent pas l'accès SSH.
  • Nous allons lier un groupe de sécurité à l'instance active afin de permettre l'accès SSH aux hôtes bastion. Tout trafic entrant (entrée) sur le port 22 (SSH) depuis n'importe quel endroit (0.0.0.0/0) sera autorisé par le groupe de sécurité. Pour améliorer la sécurité et prévenir les failles de sécurité, vous pouvez substituer votre propre adresse IP publique/32 ou adresse réseau au bloc source CIDR.
  • aws_key_pair – Pour pouvoir se connecter à l'hôte bastion à l'aide de SSH et de la clé privée, nous avons ajouté une paire de clés SSH lors de la création de l'EC2. Notre clé SSH publique est utilisée dans la paire de clés. À l'aide de la commande sshkeygen , vous pouvez également en créer un nouveau.
  • aws_ssm_parameter – L'image machine Amazon 2 Linux est utilisée par l'instance EC2. L'ID AMI est obtenu à partir de la place de marché AWS à l'aide de la source de données AWS AMI
  • aws_instance –  Enfin, nous déployons notre instance bastion EC2 avec ses configurations et accès définis
  • sortie – En spécifiant une sortie, nous utilisons la fonctionnalité de sorties Terraform pour afficher l'adresse IP dans la session du terminal.

Maintenant, mettons à jour notre variable dans les modules et le main.tf avec la nouvelle public_key que nous transmettons en tant que variable :

variable "public_key"{} 

développement/modules/variables/tfvars

varable "public_key" {} 
module "subnet_module" { 
	source     = "./modules" 
    ... 
    publc_key = var.public_key 
}

développement/main.tf

public_key = "enter-your-public-key"

développement/secrets.tf

Nous exécuterons terraform apply pour créer les ressources. Vous pouvez exécuter terraform plan avant pour voir quelles ressources vous créez réellement.

Sur le terminal, lançons terraform apply -var-file=secrets.tfvars:

ressources terminales

ressources terminales

Voici le résultat dans la console AWS :

instances aws-console

instances aws-console

Comment provisionner notre service de calcul

Instance maître Jenkins

Jusqu'à présent, nous avons réussi à mettre en place notre VPC et notre topologie de mise en réseau. ‌‌Enfin, nous allons créer notre instance Jenkins EC2 qui utilisera une AMI maître Jenkins préparée par Packer.

Vous pouvez consulter mon article précédent sur la façon dont il a été cuit : Apprenez l'infrastructure en tant que code en créant une image de machine personnalisée dans AWS sur freecodecamp.org . Quoi qu'il en soit, vous pouvez utiliser n'importe laquelle de vos images personnalisées si vous en avez une.

 /*** This parameter contains our baked AMI ID fetch from the Amazon Console*/ data "aws_ami" "jenkins-master" { 
 	most_recent = true owners      = ["self"] 
} 

resource "aws_security_group" "jenkins_master_sg" { 
	name        = "jenkins_master_sg" 
    description = "Allow traffic on port 8080 and enable SSH" 
    vpc_id      = var.vpc_id 
    
    ingress { 
    	from_port       = "22" 
        to_port         = "22" 
        protocol        = "tcp" 
        security_groups = [aws_security_group.bastion.id] 
   } 
   ingress { 
   		from_port       = "8080" 
        to_port         = "8080" 
        protocol        = "tcp" 
        security_groups = [aws_security_group.lb.id] 
   } 
   ingress { 
   		from_port   = "8080" 
        to_port     = "8080" 
        protocol    = "tcp" 
        cidr_blocks = ["0.0.0.0/0"] 
  } 
  egress { 
  		from_port   = "0" 
        to_port     = "0" 
        protocol    = "-1" 
        cidr_blocks = ["0.0.0.0/0"] 
  } 
  
  tags = { 
  	Name = "jenkins_master_sg" 
  }
} 

développement/modules/jenkins_master.tf

L'association d'un groupe de sécurité à l'instance activera le trafic entrant sur le port 8080 (le tableau de bord Web Jenkins) et SSH uniquement à partir du serveur bastion et du bloc CIDR VPC.

resource "aws_key_pair" "jenkins" { 
	key_name   = "key-jenkins" 
    public_key = var.public_key 
} 

resource "aws_instance" "jenkins_master" { 
	ami       = data.aws_ami.jenkins-master.id 
    instance_type  = "t2.large" 
    key_name       = aws_key_pair.jenkins.key_name 
    vpc_security_group_ids = [aws_security_group.jenkins_master_sg.id]
    subnet_id              = element(aws_subnet.private_subnets, 0).id
    root_block_device { 
    	volume_type           = "gp3" 
        volume_size           = 30 
        delete_on_termination = false 
    } 
    
    tags = { 
    	Name = "jenkins_master" 
     } 
 }

développement/modules/jenkins_master.tf

Ensuite, nous créons une variable et définissons le type d'instance que nous avons utilisé pour déployer l'instance EC2. Nous n'allouerons pas d'exécuteurs ou de travailleurs sur le maître, donc t2.large (8 Go de mémoire et 2 vCPU) devrait être suffisant pour des raisons de simplicité.

Ainsi, les tâches de build ne surchargeront pas le maître Jenkins. Mais les besoins en mémoire de Jenkins varient en fonction des exigences de build de votre projet et des outils utilisés dans ces builds. Il faudra deux à trois threads, ou au moins 2 Mo de mémoire, pour se connecter à chaque nœud de build.

Juste une note : pensez à installer les travailleurs Jenkins pour éviter de surmener le maître. Par conséquent, une instance à usage général peut héberger un maître Jenkins et offrir un équilibre entre les ressources de calcul et de mémoire. Afin de maintenir la simplicité de l'article, nous ne le ferons pas.

Comment créer l'équilibreur de charge

Pour accéder au tableau de bord Jenkins, nous allons créer un équilibreur de charge public devant l'instance EC2.

Cet équilibreur de charge élastique acceptera le trafic HTTP sur le port 80 et le transmettra à l'instance EC2 sur le port 8080. En outre, il vérifie automatiquement l'intégrité de l'instance EC2 enregistrée sur le port 8080. Si Elastic Load Balancing (ELB) trouve l'instance malsaine , il arrête d'envoyer du trafic vers l'instance Jenkins.

 /*** A security group to allow SSH access into our load balancer*/ resource "aws_security_group" "lb" { 
 	name   = "ecs-alb-security-group" 
    vpc_id = var.vpc_id 
    
    ingress { 
    	protocol    = "tcp" 
        from_port   = 80 
        to_port     = 80 
        cidr_blocks = ["0.0.0.0/0"] 
     } 
     egress { 
     	from_port   = 0 
        to_port     = 0 
        protocol    = "-1" 
        cidr_blocks = ["0.0.0.0/0"] 
     } 
     
     tags = { 
     	Name = "jenkins-lb-sg" 
      } 
 } 
 
 /***Load Balancer to be attached to the ECS cluster to distribute the load among instances*/ 
 
 resource "aws_elb" "jenkins_elb" { 
 	subnets    = [for subnet in aws_subnet.public_subnets : subnet.id]
    cross_zone_load_balancing = true 
    security_groups       = [aws_security_group.lb.id] 
    instances             = [aws_instance.jenkins_master.id] 
    
    listener { 
    	instance_port     = 8080 
        instance_protocol = "http" 
        lb_port           = 80 
        lb_protocol       = "http" 
     } 
     
     health_check { 
     	healthy_threshold   = 2 
        unhealthy_threshold = 2 
        timeout             = 3 
        target              = "TCP:8080"    
        interval            = 5 
    } 
    
    tags = { 
    	Name = "jenkins_elb" 
    } 
 } 
 
 output "load-balancer-ip" { 
 	value = aws_elb.jenkins_elb.dns_name 
 }

développement/modules/loadbalancer.tf

Avant de faire notre application terraform, mettons à jour notre dossier development/output.tf pour sortir le DNS de l'équilibreur de charge :

 output "load-balancer-ip" { 
 	value = module.subnet_module.load-balancer-ip
 }

développement/sortie.tf

Sur le terminal, lancez la commande suivante : terraform apply -var-file="secrets.tfvars". Ce qui vous donnera ceci :

sortie de l'équilibreur de charge

sortie de l'équilibreur de charge

Après avoir appliqué les modifications avec Terraform, l'URL de l'équilibreur de charge principal Jenkins doit s'afficher dans votre session de terminal.

Pointez votre navigateur préféré vers l'URL et vous devriez avoir accès au tableau de bord Web Jenkins.

instances-jenkins

instances-jenkins

Ensuite, suivez simplement les instructions à l'écran pour DÉVERROUILLER.

déverrouiller jenkins

déverrouiller jenkins

Vous pouvez trouver le code complet sur ce dépôt GitHub.

Nettoyer

Pour éviter les coûts inutiles d'exécution des services AWS, vous devrez exécuter la commande suivante pour détruire toutes les ressources créées et en cours d'exécution : terraform destroy -var-file="secrets.tfvars"‌‌ qui devrait donner ce résultat :

détruire les ressources

détruire les ressources

Comment intéressant, non? Avec seulement quelques lignes de code, nous pouvons détruire et faire tourner nos ressources.

Sommaire

Dans ce didacticiel, vous avez appris à utiliser Terraform à un niveau élevé. Vous avez également appris l'une de ses applications en provisionnant un serveur Jenkins sur la plateforme cloud AWS.

Vous avez également découvert les meilleures pratiques des états et des modules du backend Terraform.

Bon apprentissage! 

Source : https://www.freecodecamp.org/news/learn-terraform-by-deploying-jenkins-server-on-aws/

 #jenkins #aws #terraform

Découvrez Terraform En Déployant Un Serveur Jenkins Sur AWS
Hong  Nhung

Hong Nhung

1658953800

Tìm Hiểu Terraform Bằng Cách Triển Khai Máy Chủ Jenkins Trên AWS

Hôm nay chúng ta sẽ tìm hiểu về Terraform bằng cách xây dựng một dự án.

Terraform không chỉ là một công cụ để thúc đẩy năng suất của các nhóm vận hành. Bạn có cơ hội chuyển đổi các nhà phát triển của mình thành các nhà khai thác bằng cách triển khai Terraform.

Điều này có thể giúp tăng hiệu quả của toàn bộ nhóm kỹ thuật của bạn và cải thiện giao tiếp giữa các nhà phát triển và nhà điều hành.

Trong bài viết này, tôi sẽ chỉ cho bạn cách tự động hóa hoàn toàn việc triển khai các dịch vụ Jenkins của bạn trên đám mây AWS bằng cách sử dụng Terraform với một hình ảnh nướng tùy chỉnh.

Terraform là gì?

Terraform của HashiCorp là một giải pháp mã cơ sở hạ tầng. Nó cho phép bạn chỉ định tài nguyên đám mây và tài nguyên tại chỗ trong các tệp cấu hình mà con người có thể đọc được mà bạn có thể sử dụng lại và chia sẻ. Nó là một công cụ cung cấp DevOps mạnh mẽ.

Tại sao bạn nên sử dụng Terraform?

Terraform có một số trường hợp sử dụng, bao gồm khả năng:

  • Chỉ định cơ sở hạ tầng trong cấu hình / mã và dễ dàng xây dựng lại / thay đổi và theo dõi các thay đổi đối với cơ sở hạ tầng.
  • Hỗ trợ các nền tảng đám mây khác nhau
  • Thực hiện các sửa đổi tài nguyên gia tăng
  • Hỗ trợ mạng do phần mềm xác định

Cách Terraform hoạt động

Chúng ta hãy xem cách Terraform hoạt động ở cấp độ cao.

Terraform được phát triển bằng ngôn ngữ lập trình cờ vây. Mã cờ vây được biên dịch thành dạng địa hình, một dạng nhị phân duy nhất. Bạn có thể sử dụng tệp nhị phân này để triển khai cơ sở hạ tầng từ máy tính xách tay, máy chủ bản dựng hoặc bất kỳ máy tính nào khác và bạn sẽ không cần chạy bất kỳ cơ sở hạ tầng bổ sung nào để làm như vậy.

Điều này là do nhị phân Terraform thay mặt bạn thực hiện các cuộc gọi API tới một hoặc nhiều nhà cung cấp, bao gồm Azure, AWS, Google Cloud, DigitalOcean và các nhà cung cấp khác. Điều này cho phép Terraform tận dụng cơ sở hạ tầng mà các nhà cung cấp đó đã có sẵn cho các máy chủ API của họ, cũng như các quy trình xác thực mà họ yêu cầu.

Nhưng Terraform không biết những yêu cầu API phải thực hiện - vậy làm thế nào nó biết được? Cấu hình Terraform, là các tệp văn bản bằng ngôn ngữ khai báo chỉ định cơ sở hạ tầng nào bạn muốn tạo, là câu trả lời. "Mã" trong "cơ sở hạ tầng dưới dạng mã" là những thiết lập này.

Bạn có toàn quyền kiểm soát cơ sở hạ tầng của mình, bao gồm máy chủ, cơ sở dữ liệu, bộ cân bằng tải, cấu trúc liên kết mạng, v.v. Thay mặt bạn, hệ nhị phân Terraform phân tích mã của bạn và chuyển nó thành một chuỗi lệnh gọi API nhanh nhất có thể.

Ngôn ngữ Thủ tục so với Ngôn ngữ Khai báo là gì?

Ngôn ngữ thủ tục cho phép bạn chỉ định toàn bộ quy trình và liệt kê các bước cần thiết để hoàn thành nó. Bạn chỉ đưa ra hướng dẫn và chỉ định cách thức quá trình sẽ được thực hiện. Chef và Ansible khuyến khích phương pháp này.

Mặt khác, các ngôn ngữ khai báo cho phép bạn chỉ cần đặt lệnh hoặc lệnh và để hệ thống thực hiện. Bạn không cần phải đi vào quy trình; bạn chỉ cần kết quả. Ví dụ như Terraform, cloudFormation và Puppeteer.

Đủ lý thuyết ...

Bây giờ là thời điểm để đưa tính khả dụng, bảo mật, hiệu suất và độ tin cậy cao của Terraform vào hoạt động.

Ở đây, chúng ta đang nói về máy chủ Jenkins dựa trên Terraform trên Amazon Web Services. Chúng tôi đang thiết lập mạng từ đầu, vì vậy hãy bắt đầu.

Điều kiện tiên quyết và cài đặt

Có một số thứ bạn cần phải thiết lập và cài đặt để làm theo hướng dẫn này:

Cấu trúc tệp / thư mục của dự án của chúng tôi

Chúng tôi sẽ sử dụng chiến lược phát triển mô-đun để tách việc triển khai cụm Jenkins của chúng tôi thành nhiều tệp mẫu (thay vì phát triển một tệp mẫu lớn).

Mỗi tệp chịu trách nhiệm thực thi một thành phần cơ sở hạ tầng đích hoặc tài nguyên AWS.

Để tạo và thực thi cài đặt cơ sở hạ tầng, Terraform tận dụng cú pháp của ngôn ngữ cấu hình giống JSON được gọi là HCL (Ngôn ngữ cấu hình HashiCorp).

cấu trúc tệp / thư mục

cấu trúc tệp / thư mục

Cách khởi tạo trạng thái Terraform đầu tiên

Để làm theo các phương pháp hay nhất, chúng tôi sẽ lưu trữ các tệp trạng thái Terraform của mình trong bộ nhớ đám mây của chúng tôi. Điều này là cần thiết, đặc biệt cho sự hợp tác nhóm.

Tệp trạng thái Terraform là tệp chứa tài nguyên Terraform trên các dự án.

Bên trong tệp main.tf trong thư mục trạng thái phụ trợ, hãy thêm mã sau:

variable "aws_region" { 
	default = "us-east-1" 
 } 
variable "aws_secret_key" {} 
variable "aws_access_key" {} 

provider "aws" { 
	region = var.aws_region 
    access_key = var.aws_access_key 
    secret_key = var.aws_secret_key 
} 

resource "aws_s3_bucket" "terraform_state" { 
	bucket = "terraform-state-caesar-tutorial-jenkins" 
    
    lifecycle { 
    	prevent_destroy = true 
    } 
    
    versioning { 
    	enabled = true 
   } 
   
   server_side_encryption_configuration { 
   		rule { 
        	apply_server_side_encryption_by_default { 
            	sse_algorithm = "AES256" 
            } 
        } 
   } 
}

backend-state / main.tf

Hãy đảm bảo rằng chúng ta biết những gì đang xảy ra trong đoạn mã trên.

Chúng tôi sử dụng các biến để lưu trữ dữ liệu và trong Terraform, bạn khai báo một biến với từ khóa biến theo sau là tên. Khối biến có thể nhận một số thuộc tính như mặc định, mô tả, kiểu, v.v. hoặc không có. Bạn sẽ thấy điều này rất nhiều.

Bây giờ chúng ta đang khai báo các biến dưới dạng variable "variable_name"{}sử dụng chúng trong bất kỳ khối tài nguyên / dữ liệu nào dưới dạngvar.variable_name . Sau đó, bạn sẽ thấy cách chúng tôi sẽ gán giá trị cho các biến đó trong tệp secret.tfvars của chúng tôi.

Để sử dụng Terraform, bạn cần cho nhà cung cấp biết nó sẽ giao tiếp và chuyển các thuộc tính cần thiết của nó để xác thực. Ở đây chúng tôi có khu vực AWS, quyền truy cập và khóa bí mật (bạn nên tải những thứ này xuống hệ thống của mình từ các điều kiện tiên quyết).

Trong terraform, mỗi tài nguyên chúng ta cần được xác định trong khối tài nguyên. Tài nguyên là cơ sở hạ tầng được nhấn mạnh để tạo ra dịch vụ đám mây của chúng tôi. Nó tuân theo cú pháp resource "terraform-resource-name" "custom-name" {}.

Terraform có rất nhiều tài nguyên dành cho các nhà cung cấp cụ thể trong tài liệu về địa hình (luôn tham khảo tài liệu nếu bạn có thắc mắc).

Tiếp theo, chúng tôi đang tạo aws_s3_bucket. Điều này sẽ lưu trữ trạng thái từ xa của chúng tôi. Nó có các thuộc tính sau:

  • → Điều này phải là duy nhất trên toàn cầu
  • vòng đời → Nếu ​​bạn cần phá hủy tài nguyên Terraform của mình, bạn có thể muốn ngăn chặn việc phá hủy trạng thái vì nó được chia sẻ giữa các nhóm
  • lập phiên bản → Giúp cung cấp một số kiểm soát phiên bản đối với các trạng thái
  • server_side_encryption_configuration → Cung cấp mã hóa.

Chương trình phụ trợ trạng thái của chúng tôi đã sẵn sàng. Nhưng trước khi khởi tạo, lập kế hoạch và áp dụng nó với Terraform, chúng ta hãy gán biến của chúng ta cho các giá trị của nó .

Trong secret.tfvars, hãy thêm thông tin sau từ tài khoản AWS của bạn:

  aws_region = "us-east-1 
  aws_secret_key = "enter-your-secret" 
  aws_access_key = "enter-your-access    

backend-state / secret.tfvars

Trong thiết bị đầu cuối của bạn trong cùng một thư mục trạng thái phụ trợ, hãy chạy terraform init.

trạng thái địa hình trên thiết bị đầu cuối

trạng thái địa hình trên thiết bị đầu cuối

Sau đó terraform apply -var-file=secrets.tfvars:

trạng thái địa hình trên thiết bị đầu cuối

trạng thái địa hình trên thiết bị đầu cuối

Trong bảng điều khiển AWS của bạn , đây là những gì bạn sẽ thấy:

trạng thái địa hình trên thùng aws s3

trạng thái địa hình trên thùng aws s3

‌‌Bây giờ trạng thái của chúng ta đã sẵn sàng, hãy chuyển sang phần tiếp theo.

Cách cung cấp Đám mây riêng ảo AWS

Để bảo mật cụm Jenkins của chúng tôi, chúng tôi sẽ triển khai kiến ​​trúc trong một đám mây riêng ảo (VPC) và mạng con riêng tư. Bạn có thể triển khai cụm trong VPC mặc định của AWS.

Để có toàn quyền kiểm soát cấu trúc liên kết mạng, chúng tôi sẽ tạo một VPC từ đầu.

 variable "cidr_block" {} 
 variable "aws_access_key" {} 
 variable "aws_secret_key" {} 
 variable "aws_region" {} 
 
 provider "aws" { 
 	region = var.aws_region 
    access_key = var.aws_access_key 
    secret_key = var.aws_secret_key 
} 

terraform { 
	backend "s3" { 
    	bucket     = "terraform-state-caesar-tutorial-jenkins" 
        key        = "tutorial-jenkins/development/network/terraform.tfstate" 
        region     = "us-east-1" 
        encrypt    = true 
   }
} 

resource "aws_vpc" "main_vpc" { 
	cidr_block           = var.cidr_block 
    enable_dns_support   = true 
    enable_dns_hostnames = true 
    
    tags = { 
    	Name        = "jenkins-instance-main_vpc" 
    } 
}

development / main.tf

output "vpc_id" { 
	value = aws_vpc.main_vpc.id 
} 

output "vpc_cidr_block" { 
	value = aws_vpc.main_vpc.cidr_block 
}  

phát triển / đầu ra.tf

cidr_block            = "172.0.0.0/16" 
aws_region = "us-east-1" 
aws_secret_key = "enter-your-secret" 
aws_access_key = "enter-your-access" 

phát triển / secret.tfvars

  • cidr_block → Định tuyến liên miền không phân lớp được gọi là CIDR. Nói một cách đơn giản, khối CIDR là một dải địa chỉ IP. Điều này xác định phạm vi chúng tôi đang làm việc.
  • đầu ra → Khối đầu ra trong Terraform được sử dụng để xuất các giá trị tài nguyên sang các mô-đun khác. Đây là một thuật ngữ quan trọng khác khi chuyển dữ liệu tài nguyên trong một mô-đun này sang tài nguyên khác trong một mô-đun riêng biệt. (Bạn sẽ sớm tìm hiểu các mô-đun là gì) Đây là cú pháp của nó output "custom_output_name" {  value = "resource-name"}:. Nó có một khóa giá trị nhận tài nguyên được truyền vào. Ở đây chúng tôi là đầu ra vpc_id và cidr_block.

Bây giờ, trong thiết bị đầu cuối, hãy chạy terraform initterraform apply để tạo tài nguyên. Bạn có thể chạy terraform plantrước để xem bạn thực sự đang tạo ra những tài nguyên nào. Đây là lệnh: terraform apply -var-file=secrets.tfvarsvà đầu ra:

s_0475B692F95FDEC0A6E8498B95C86079E0E8D8D5196F9F4DEAA5AA6D3B79CB44_1655907973370_vpc

Bạn sẽ thấy vpc_id và vpc_cidr_block trong Bảng điều khiển AWS của mình :

tài nguyên vpc trên aws

vpc trên aws

Cách làm việc với Mô-đun Terraform

Một nhóm các tệp cấu hình điển hình trong một thư mục cụ thể tạo nên một mô-đun Terraform. Các mô-đun Terraform tập hợp các tài nguyên được sử dụng cho một hoạt động duy nhất. Điều này cắt giảm số lượng mã bạn cần để tạo các thành phần cơ sở hạ tầng giống hệt nhau.

Sử dụng cú pháp bên dưới, bạn có thể chuyển một tài nguyên mô-đun Terraform sang một tài nguyên khác để sử dụng.

module "custom-module-name" { 
	source     = "path-to-modules-resources" 
}

cú pháp địa hình-mô-đun

Và để sử dụng đầu ra tài nguyên mô-đun bên trong mô-đun tài nguyên khác, đây là lệnh module.custom-module-name.resource-output-value:.

Cách tạo mạng con VPC

Tạo VPC là không đủ - chúng tôi cũng cần một mạng con để có thể cài đặt các phiên bản Jenkins trên mạng bị cô lập này. Chúng ta phải chuyển ID VPC mà chúng ta xuất ra trước đó, vì mạng con này thuộc về một VPC đã được xây dựng trước đó.

Để có khả năng phục hồi, chúng tôi sẽ sử dụng hai mạng con công cộng và hai mạng con riêng trong các khu vực khả dụng riêng biệt. Mỗi mạng con có khối CIDR riêng, là một tập hợp con của khối VPC CIDR, mà chúng tôi nhận được từ tài nguyên VPC.

resource "aws_subnet" "public_subnets" { 
	vpc_id         = var.vpc_id 
    cidr_block     = cidrsubnet(var.vpc_cidr_block, 8, 2 + count.index)  
   	availability_zone   = element(var.availability_zones, count.index)  	
    map_public_ip_on_launch = true 
    count                   = var.public_subnets_count 
    
    tags = { 
    	Name        = "jenkins-instance-public-subnet" 
   } 
} 

resource "aws_subnet" "private_subnets" { 
	vpc_id     = var.vpc_id 
    cidr_block = cidrsubnet(var.vpc_cidr_block, 8, count.index)  			
    availability_zone    = element(var.availability_zones, count.index)  
    map_public_ip_on_launch = false 
    count                   = var.private_subnets_count 
    
    tags = { 
    	Name        = "jenkins-instance-private-subnet" 
    } 
 }

module / subnets.tf

Được rồi, điều gì đang xảy ra trong mã này?

  • count Đối số meta đếm chấp nhận một số nguyên và tạo ra nhiều bản sao của tài nguyên hoặc mô-đun. Ở đây chúng tôi chỉ định 2 mỗi biến private_subnets_count và public_subnets_count.
  • map_public_ip_on_launch → Chỉ định true để chỉ ra rằng các phiên bản được đưa vào mạng con phải được gán một địa chỉ IP công cộng.
  • cidrsubnet () cidrsubnet tính toán một địa chỉ mạng con trong một tiền tố địa chỉ mạng IP nhất định.
  • element () phần tử truy xuất một phần tử từ danh sách.

Bây giờ, hãy cập nhật các biến mô-đun của chúng tôi:

variable "vpc_id" {} 
variable "vpc_cidr_block" {} 
variable "private_subnets_count" {} 
variable "public_subnets_count" {} 
variable "availability_zones" {} 

phát triển / mô-đun / biến.tf

Cập nhật các secret.tfvars như thế này:

private_subnets_count = 2 
public_subnets_count  = 2

secret.tfvars

Bạn phải thiết lập các bảng tuyến đường riêng và công khai để chỉ định phương pháp định tuyến lưu lượng trong mạng con VPC. Hãy làm điều đó trước khi chúng tôi thực hiện áp dụng terraform trên tài nguyên của chúng tôi.

Cách thiết lập bảng định tuyến VPC

Chúng tôi sẽ phát triển các bảng tuyến đường riêng và công cộng để quản lý giao thông chi tiết. Điều này sẽ cho phép các phiên bản được triển khai trong các mạng con riêng tư có thể truy cập internet mà không bị công khai.

Cách tạo bảng tuyến đường công cộng

Trước tiên, chúng ta cần thiết lập một tài nguyên cổng Internet và liên kết nó với VPC mà chúng ta đã tạo trước đó. Sau đó, chúng ta cần xác định một bảng lộ trình công cộng và một lộ trình hướng tất cả lưu lượng truy cập (0.0.0.0/0) đến cổng internet. Và cuối cùng, chúng ta cần liên kết nó với các mạng con công cộng trong VPC của chúng ta để lưu lượng truy cập từ các mạng con đó được chuyển đến cổng internet bằng cách tạo liên kết bảng định tuyến.

/*** Internet Gateway - Provides a connection between the VPC and the public internet, allowing traffic to flow in and out of the VPC and translating IP addresses to public* addresses.*/ 
resource "aws_internet_gateway" "igw" { 
	vpc_id = var.vpc_id 
    
    tags = { 
    	Name = "igw_jenkins" 
   } 
} 

/*** A route from the public route table out to the internet through the internet* gateway.*/ 
resource "aws_route_table" "public_rt" { 
	vpc_id = var.vpc_id 
    
    route { 
    	cidr_block = "0.0.0.0/0" 
        gateway_id = aws_internet_gateway.igw.id 
   } 
   
   tags = { 
   		Name = "public_rt_jenkins" 
   } 
} 
/*** Associate the public route table with the public subnets.*/ 
resource "aws_route_table_association" "public" { 
	count     = var.public_subnets_count 
    subnet_id = element(var.public_subnets.*.id, count.index) 
    route_table_id = aws_route_table.public_rt.id 
}

phát triển / mô-đun / public_rt.tf

‌Cách tạo bảng tuyến đường riêng

Bây giờ bảng tuyến đường công cộng của chúng ta đã hoàn thành, hãy tạo bảng tuyến đường riêng.

Để cho phép các phiên bản Jenkins của chúng tôi kết nối với internet khi nó được triển khai trên mạng con riêng, chúng tôi sẽ xây dựng một tài nguyên cổng NAT bên trong một mạng con công cộng.

Sau đó, thêm địa chỉ IP đàn hồi vào cổng NAT và bảng tuyến đường riêng có tuyến đường (0.0.0.0/0) hướng tất cả lưu lượng truy cập đến ID của cổng NAT mà bạn đã thiết lập. Sau đó, chúng tôi đính kèm các mạng con riêng vào bảng tuyến riêng bằng cách tạo liên kết bảng tuyến .

 /*** An elastic IP address to be used by the NAT Gateway defined below.  The NAT* gateway acts as a gateway between our private subnets and the public* internet, providing access out to the internet from within those subnets,* while denying access to them from the public internet.  This IP address* acts as the IP address from which all the outbound traffic from the private* subnets will originate.*/ 
 
 resource "aws_eip" "eip_for_the_nat_gateway" { 
 	vpc = true 
    
    tags = { 
    	Name = "jenkins-tutoral-eip_for_the_nat_gateway" 
    } 
} 

/*** A NAT Gateway that lives in our public subnet and provides an interface* between our private subnets and the public internet.  It allows traffic to* exit our private subnets, but prevents traffic from entering them.*/ 

resource "aws_nat_gateway" "nat_gateway" { 
	allocation_id = aws_eip.eip_for_the_nat_gateway.id 
    subnet_id     = element(var.public_subnets.*.id, 0) 
    
    tags = { 
    	Name = "jenkins-tutorial-nat_gateway" 
	} 
} 
/*** A route from the private route table out to the internet through the NAT * Gateway.*/ 

resource "aws_route_table" "private_rt" { 
	vpc_id = var.vpc_id 
    
    route { 
    	cidr_block     = "0.0.0.0/0" 
        nat_gateway_id = aws_nat_gateway.nat_gateway.id } 
        
        tags = { 
        	Name   = "private_rt_${var.vpc_name}" 
            Author = var.author 
        } 
} 
/*** Associate the private route table with the private subnet.*/ 
resource "aws_route_table_association" "private" { 
	count = var.private_subnets_count 
    subnet_id = element(aws_subnet.private_subnets.*.id, count.index) 
    route_table_id = aws_route_table.private_rt.id 
}

development / modules / private_rt.tf

‌Bây giờ chúng ta hãy chạy terraform apply. Nhưng chúng tôi cần cập nhật tệp main.tf (vì đây là tệp địa hình mục nhập của chúng tôi) để biết về các mạng con và biến mô-đun cũng như secret.tfvars (đối với các biến của chúng tôi).

variable "vpc_id" {} 
variable "vpc_cidr_block" {} 
variable "private_subnets_count" {} 
variable "public_subnets_count" {} 
variable "availability_zones" {} 
variable "public_subnets" {}

phát triển / mô-đun / biến.ftvars

variable "private_subnets_count" {} 
variable "public_subnets_count" {} 
variable "availability_zones" {} 

module "subnet_module" { 
	source     = "./modules" 
    vpc_id     = aws_vpc.main_vpc.id 
    vpc_cidr_block = aws_vpc.main_vpc.cidr_block 
    availability_zones = var.availability_zones 
    public_subnets_count = var.public_subnets_count 
    private_subnets_count = var.private_subnets_count 
 }

development / main.tf

 availability_zones    = ["us-east-1a", "us-east-1b", "us-east-1c", "us-east-1d", "us-east-1e"]

phát triển / secret.tf

Mạng con và chứng khoán tương ứng của chúng tôi đã sẵn sàng. Bây giờ chúng ta có thể khởi tạo nó, lập kế hoạch và áp dụng với Terraform.

Chúng tôi sẽ chạy áp dụng địa hình để tạo tài nguyên. Bạn có thể chạy kế hoạch địa hình trước đó để xem bạn thực sự đang tạo ra những tài nguyên nào.

Trong phần chạy của thiết bị đầu cuối . terraform apply -var-file=secrets.tfvars

s_0475B692F95FDEC0A6E8498B95C86079E0E8D8D5196F9F4DEAA5AA6D3B79CB44_1656906570979_terminal-state-3

Chỉ cần lưu ý rằng số lượng tài nguyên được thêm vào đây có thể trì hoãn từ nguồn của bạn.

Đây là Bảng điều khiển AWS (mạng con, địa chỉ đàn hồi, route_tables):

mạng con

mạng con bảng tuyến đườngip đàn hồiip đàn hồibảng lộ trình

Cách thiết lập Máy chủ lưu trữ VPC Bastion

Chúng tôi đã triển khai cụm Jenkins của mình bên trong các mạng con riêng tư. Bởi vì cụm thiếu IP công cộng, các phiên bản sẽ không được cung cấp công khai qua internet. Vì vậy, để giải quyết vấn đề này, chúng tôi sẽ thiết lập một máy chủ pháo đài để chúng tôi có thể truy cập các phiên bản Jenkins một cách an toàn.

Thêm các tài nguyên và nhóm bảo mật sau vào tệp bastion.tf:

/*** A security group to allow SSH access into our bastion instance.*/ 
resource "aws_security_group" "bastion" { 
	name   = "bastion-security-group" 
    vpc_id = var.vpc_id 
    
    ingress { 
    	protocol    = "tcp" 
        from_port   = 22 
        to_port     = 22 
        cidr_blocks = ["0.0.0.0/0"] 
    } 
    egress { 
    	protocol    = -1 
        from_port   = 0 
        to_port     = 0 
        cidr_blocks = ["0.0.0.0/0"] 
   } 
   
   tags = { 
   		Name = "aws_security_group.bastion_jenkins" 
   } 
} 

/*** The public key for the key pair we'll use to ssh into our bastion instance.*/ 

resource "aws_key_pair" "bastion" { 
	key_name   = "bastion-key-jenkins" 
    public_key = var.public_key 
 } 
 
 /*** This parameter contains the AMI ID for the most recent Amazon Linux 2 ami,* managed by AWS.*/ 
 
 data "aws_ssm_parameter" "linux2_ami" { 
 	name = "/aws/service/ami-amazon-linux-latest/amzn-ami-hvm-x86_64-ebs" 
} 

/*** Launch a bastion instance we can use to gain access to the private subnets of* this availabilty zone.*/ 

resource "aws_instance" "bastion" { 
	ami           = data.aws_ssm_parameter.linux2_ami.value 
    key_name      = aws_key_pair.bastion.key_name 
    instance_type = "t2.large" 
    associate_public_ip_address = true 
    subnet_id                   = element(aws_subnet.public_subnets, 0).id 
    vpc_security_group_ids      = [aws_security_group.bastion.id] 
    
    tags = { 
    	Name        = "jenkins-bastion" 
    } 
} 

output "bastion" { value = aws_instance.bastion.public_ip }

bastion.tf

Hãy xem điều gì đang xảy ra trong đoạn mã ở đây:

  • tài nguyên nhóm bảo mật pháo đài - Các phiên bản EC2 mới được tạo không cho phép truy cập SSH.
  • Chúng tôi sẽ liên kết một nhóm bảo mật với phiên bản đang hoạt động để cho phép truy cập SSH vào các máy chủ pháo đài. Mọi lưu lượng truy cập vào (nhập) trên cổng 22 (SSH) từ bất kỳ đâu (0.0.0.0/0) sẽ được nhóm bảo mật cho phép. Để cải thiện bảo mật và ngăn chặn vi phạm bảo mật, bạn có thể thay thế địa chỉ IP / 32 hoặc địa chỉ mạng công cộng của riêng mình cho khối nguồn CIDR.
  • aws_key_pair - Để có thể kết nối với máy chủ pháo đài bằng SSH và khóa cá nhân, chúng tôi đã thêm một cặp khóa SSH khi chúng tôi tạo EC2. Khóa SSH công khai của chúng tôi được sử dụng trong cặp khóa. Sử dụng lệnh sshkeygen , bạn cũng có thể tạo một lệnh mới.
  • aws_ssm_parameter - Hình ảnh máy Amazon 2 Linux được sử dụng bởi phiên bản EC2. ID AMI được lấy từ thị trường AWS bằng cách sử dụng nguồn dữ liệu AWS AMI
  • aws_instance -  Cuối cùng, chúng tôi triển khai phiên bản pháo đài EC2 của mình với các cấu hình và quyền truy cập đã xác định của nó
  • đầu ra - Bằng cách chỉ định đầu ra, chúng tôi sử dụng chức năng đầu ra Terraform để hiển thị địa chỉ IP trong phiên đầu cuối.

Bây giờ, hãy cập nhật biến của chúng ta trong các mô-đun và main.tf với public_key mới mà chúng ta đang chuyển dưới dạng một biến:

variable "public_key"{} 

phát triển / mô-đun / biến / tfvars

varable "public_key" {} 
module "subnet_module" { 
	source     = "./modules" 
    ... 
    publc_key = var.public_key 
}

development / main.tf

public_key = "enter-your-public-key"

phát triển / secret.tf

Chúng tôi sẽ chạy áp dụng địa hình để tạo tài nguyên. Bạn có thể chạy kế hoạch địa hình trước đó để xem bạn thực sự đang tạo ra những tài nguyên nào.

Trên thiết bị đầu cuối, hãy chạy terraform apply -var-file=secrets.tfvars:

tài nguyên đầu cuối

tài nguyên đầu cuối

Đây là kết quả trong bảng điều khiển AWS:

phiên bản aws-console

phiên bản aws-console

Cách cung cấp dịch vụ máy tính của chúng tôi

Phiên bản chính của Jenkins

Cho đến nay, chúng tôi đã có thể thiết lập VPC và cấu trúc liên kết mạng thành công. ‌‌Cuối cùng, chúng tôi sẽ tạo phiên bản Jenkins EC2 của chúng tôi sẽ sử dụng một AMI chính của Jenkins được tạo bởi Packer.

Bạn có thể xem bài viết trước của tôi về cách nó được ra đời: Tìm hiểu Cơ sở hạ tầng dưới dạng mã bằng cách Xây dựng Hình ảnh Máy tùy chỉnh trong AWS trên freecodecamp.org . Bất kể, bạn có thể sử dụng bất kỳ hình ảnh tùy chỉnh nào của mình nếu bạn có.

 /*** This parameter contains our baked AMI ID fetch from the Amazon Console*/ data "aws_ami" "jenkins-master" { 
 	most_recent = true owners      = ["self"] 
} 

resource "aws_security_group" "jenkins_master_sg" { 
	name        = "jenkins_master_sg" 
    description = "Allow traffic on port 8080 and enable SSH" 
    vpc_id      = var.vpc_id 
    
    ingress { 
    	from_port       = "22" 
        to_port         = "22" 
        protocol        = "tcp" 
        security_groups = [aws_security_group.bastion.id] 
   } 
   ingress { 
   		from_port       = "8080" 
        to_port         = "8080" 
        protocol        = "tcp" 
        security_groups = [aws_security_group.lb.id] 
   } 
   ingress { 
   		from_port   = "8080" 
        to_port     = "8080" 
        protocol    = "tcp" 
        cidr_blocks = ["0.0.0.0/0"] 
  } 
  egress { 
  		from_port   = "0" 
        to_port     = "0" 
        protocol    = "-1" 
        cidr_blocks = ["0.0.0.0/0"] 
  } 
  
  tags = { 
  	Name = "jenkins_master_sg" 
  }
} 

development / modules / jenkins_master.tf

Việc đính kèm nhóm bảo mật vào phiên bản sẽ cho phép lưu lượng truy cập vào trên cổng 8080 (bảng điều khiển web Jenkins) và chỉ SSH từ máy chủ pháo đài và khối VPC CIDR.

resource "aws_key_pair" "jenkins" { 
	key_name   = "key-jenkins" 
    public_key = var.public_key 
} 

resource "aws_instance" "jenkins_master" { 
	ami       = data.aws_ami.jenkins-master.id 
    instance_type  = "t2.large" 
    key_name       = aws_key_pair.jenkins.key_name 
    vpc_security_group_ids = [aws_security_group.jenkins_master_sg.id]
    subnet_id              = element(aws_subnet.private_subnets, 0).id
    root_block_device { 
    	volume_type           = "gp3" 
        volume_size           = 30 
        delete_on_termination = false 
    } 
    
    tags = { 
    	Name = "jenkins_master" 
     } 
 }

development / modules / jenkins_master.tf

Tiếp theo, chúng tôi tạo một biến và xác định loại cá thể mà chúng tôi đã sử dụng để triển khai cá thể EC2. Chúng tôi sẽ không phân bổ người thực thi hoặc công nhân trên máy chủ, vì vậy t2.large (8 GB bộ nhớ và 2vCPU) phải đủ cho mục đích đơn giản.

Do đó, các công việc xây dựng sẽ không khiến Jenkins master bị quá tải. Nhưng yêu cầu bộ nhớ của Jenkins thay đổi tùy thuộc vào yêu cầu xây dựng dự án của bạn và các công cụ được sử dụng trong các bản dựng đó. Nó sẽ yêu cầu hai đến ba luồng, hoặc ít nhất 2 MB bộ nhớ, để kết nối với mỗi nút xây dựng.

Chỉ cần một lưu ý: hãy xem xét cài đặt Jenkins worker để tránh làm việc quá mức cho master. Do đó, một cá thể có mục đích chung có thể lưu trữ một tổng thể Jenkins và cung cấp sự cân bằng giữa tài nguyên tính toán và bộ nhớ. Để duy trì sự đơn giản của bài viết, chúng tôi sẽ không làm điều đó.

Cách tạo bộ cân bằng tải

Để truy cập bảng điều khiển Jenkins, chúng tôi sẽ tạo một bộ cân bằng tải công khai trước phiên bản EC2.

Bộ cân bằng tải đàn hồi này sẽ chấp nhận lưu lượng HTTP trên cổng 80 và chuyển tiếp nó đến cá thể EC2 trên cổng 8080. Ngoài ra, nó tự động kiểm tra tình trạng của cá thể EC2 đã đăng ký trên cổng 8080. Nếu Cân bằng tải đàn hồi (ELB) thấy phiên bản đó không lành mạnh , nó ngừng gửi lưu lượng đến phiên bản Jenkins.

 /*** A security group to allow SSH access into our load balancer*/ resource "aws_security_group" "lb" { 
 	name   = "ecs-alb-security-group" 
    vpc_id = var.vpc_id 
    
    ingress { 
    	protocol    = "tcp" 
        from_port   = 80 
        to_port     = 80 
        cidr_blocks = ["0.0.0.0/0"] 
     } 
     egress { 
     	from_port   = 0 
        to_port     = 0 
        protocol    = "-1" 
        cidr_blocks = ["0.0.0.0/0"] 
     } 
     
     tags = { 
     	Name = "jenkins-lb-sg" 
      } 
 } 
 
 /***Load Balancer to be attached to the ECS cluster to distribute the load among instances*/ 
 
 resource "aws_elb" "jenkins_elb" { 
 	subnets    = [for subnet in aws_subnet.public_subnets : subnet.id]
    cross_zone_load_balancing = true 
    security_groups       = [aws_security_group.lb.id] 
    instances             = [aws_instance.jenkins_master.id] 
    
    listener { 
    	instance_port     = 8080 
        instance_protocol = "http" 
        lb_port           = 80 
        lb_protocol       = "http" 
     } 
     
     health_check { 
     	healthy_threshold   = 2 
        unhealthy_threshold = 2 
        timeout             = 3 
        target              = "TCP:8080"    
        interval            = 5 
    } 
    
    tags = { 
    	Name = "jenkins_elb" 
    } 
 } 
 
 output "load-balancer-ip" { 
 	value = aws_elb.jenkins_elb.dns_name 
 }

phát triển / mô-đun / loadbalancer.tf

Trước khi áp dụng terraform, hãy cập nhật thư mục development / output.tf để xuất DNS cân bằng tải:

 output "load-balancer-ip" { 
 	value = module.subnet_module.load-balancer-ip
 }

phát triển / đầu ra.tf

Trên thiết bị đầu cuối, hãy chạy lệnh sau terraform apply -var-file="secrets.tfvars":. Cái nào sẽ cung cấp cho bạn điều này:

đầu ra cân bằng tải

đầu ra cân bằng tải

Sau khi bạn áp dụng các thay đổi với Terraform, URL của bộ cân bằng tải Jenkins chính sẽ được hiển thị trong phiên đầu cuối của bạn.

Trỏ trình duyệt yêu thích của bạn tới URL và bạn sẽ có quyền truy cập vào trang tổng quan web Jenkins.

jenkins-instance

jenkins-instance

Sau đó, chỉ cần làm theo hướng dẫn trên màn hình để MỞ KHÓA.

mở khóa jenkins

mở khóa jenkins

Bạn có thể tìm thấy mã đầy đủ tại repo GitHub này.

Dọn dẹp

Để tránh chi phí không cần thiết khi chạy các dịch vụ AWS, bạn sẽ cần chạy lệnh sau để hủy tất cả các tài nguyên đã tạo và đang chạy terraform destroy -var-file="secrets.tfvars": ‌‌ sẽ cung cấp đầu ra này:

phá hủy tài nguyên

phá hủy tài nguyên

Thật thú vị, phải không? Chỉ với vài dòng mã, chúng ta có thể phá hủy và khai thác tài nguyên của mình.

Bản tóm tắt

Trong hướng dẫn này, bạn đã học cách sử dụng Terraform ở cấp độ cao. Bạn cũng đã tìm hiểu một trong các ứng dụng của nó bằng cách cung cấp máy chủ Jenkins trên nền tảng đám mây AWS.

Bạn cũng đã tìm hiểu về các phương pháp hay nhất của các trạng thái và mô-đun phụ trợ Terraform.

Chúc bạn học vui vẻ! 

Nguồn: https://www.freecodecamp.org/news/learn-terraform-by-deploy-jenkins-server-on-aws/

 #jenkins #aws #terraform

Tìm Hiểu Terraform Bằng Cách Triển Khai Máy Chủ Jenkins Trên AWS

Learn Terraform by Deploying a Jenkins Server on AWS

Today we're going to learn about Terraform by building a project.

Terraform is more than just a tool to boost the productivity of operations teams. You have the chance to transform your developers into operators by implementing Terraform.

This can help increase the efficiency of your entire engineering team and improve communication between developers and operators.

In this article, I'll show you how to fully automate the deployment of your Jenkins services on the AWS cloud using Terraform with a custom baked image.

Source: https://www.freecodecamp.org/news/learn-terraform-by-deploying-jenkins-server-on-aws/

#jenkins #aws #terraform 

Learn Terraform by Deploying a Jenkins Server on AWS

Почему вам следует перейти с Jenkins на Drone CI

Мы продолжаем видеть новые и улучшенные программные решения для автоматизации развертывания кода/программного обеспечения в мире DevOps. Являетесь ли вы разработчиком или инженером по эксплуатации, в этом облачном мире нет места для использования посредственных инструментов. Каждый день появляются инновации, обновленные версии старых инструментов и более доступные сервисы, которые облегчают жизнь кодерам и операционным специалистам. Сегодня DevOps стал центром внимания, и каждая компания называется компанией-разработчиком программного обеспечения. Непрерывная интеграция становится первым шагом к использованию DevOps как методологии.

Однако из-за того, что на рынке представлено так много инструментов непрерывной интеграции, определить, какой из них лучше всего подходит для вашей организации, может быть непросто. Существует также множество вариантов с различными функциями, моделями ценообразования и планами поддержки. Эта статья поможет вам понять, почему Jenkins не подходит для CI на современных предприятиях и как можно перейти с Jenkins на Drone CI.

Необходимость в настоящем инструменте непрерывной интеграции

Мы все знаем, что облачные инструменты развиваются каждый день, и мы видим множество инструментов-заменителей для одной и той же работы. Для непрерывной интеграции на рынке существует множество инструментов, но трудно найти тот, который действительно понимает разработчиков и создан для них. Хотя Jenkins может быть хорошей отправной точкой для новичков и организаций, с увеличением количества развертываний становится все труднее. Хотя скорость может быть еще одним фактором для оценки инструмента непрерывной интеграции, его также должно быть легко настроить на вашем компьютере с минимальным количеством команд. У Drone CI есть все, что нужно, чтобы стать единственным в своем роде инструментом CI, помогающим разработчикам создавать и тестировать свои приложения посредством непрерывной интеграции. Вы можете настроить его на своем локальном компьютере за считанные минуты и начать непрерывную интеграцию. Drone CI построен на Docker и использует возможности контейнеров на каждом этапе.

Далее, давайте посмотрим, чем Drone может быть лучшим инструментом для непрерывной интеграции, чем Jenkins.

Дженкинс

Jenkins — это инструмент непрерывной интеграции с открытым исходным кодом. Он используется для создания и тестирования программного обеспечения либо на локальном компьютере разработчика, либо в среде непрерывной интеграции, такой как любое общедоступное облако. С помощью Jenkins вы можете автоматизировать конвейер доставки программного обеспечения от фиксации кода до производства. Jenkins в основном используется для автоматизации сборки и развертывания. Обычно его комбинируют с другими инструментами в цепочке инструментов DevOps, такими как управление исходным кодом, отслеживание проблем и управление проектами. В дополнение к этим инструментам Jenkins используется для автоматизированного тестирования и развертывания приложений. Функции Дженкинса включают управление различными заданиями, просмотр сводных графиков и получение уведомлений по электронной почте.

КИ дрон

Drone CI — это сервер непрерывной интеграции с открытым исходным кодом, приобретенный Harness. Он используется для создания и тестирования программного обеспечения либо на локальном компьютере разработчика, либо в среде непрерывной интеграции, такой как любое общедоступное облако. С помощью Drone вы можете автоматизировать конвейер доставки программного обеспечения от фиксации кода до производства. Помимо создания программного обеспечения, Drone позволяет создавать, тестировать и развертывать приложения. Drone CI считается современным инструментом непрерывной интеграции, поскольку он использует декларативный подход в виде файлов yaml для автоматизации тестов и широко использует контейнеры Docker на каждом этапе. Конвейеры сборки занимают меньше времени, их легко настроить и запустить.

Drone CI — это инструмент декларативной непрерывной интеграции на основе контейнеров, который широко использует контейнеры Docker на каждом этапе и может легко работать на ваших ноутбуках, в частном центре обработки данных или в общедоступном облаке. Этот декларативный характер непрерывной интеграции помогает организациям внедрять Gitops.

Вот простой файл конфигурации yaml

kind: pipeline
type: kubernetes
name: default
steps:
- name: test
  image: node
  commands:
  - npm install
  - npm test

Просто расширите конфигурацию YAML другим сценарием, в котором вы хотели бы объединить изменения с основной веткой. В этом случае этапы:

  • Строить
  • Модульный тест
  • Развернуть для разработчиков
  • Интеграционный тест

Конфигурацию yaml можно легко указать, как показано ниже:

kind: pipeline
name: default
steps:
- name: build
  image: node:8.6.0
  commands:
  - npm install
  - npm run build
  when:
   event:
     - push
- name: unit_test
  image: node:8.6.0
  commands:
  - npm run unit_test
  when:
   event:
     - push
- name: intergration_test
  image: node:8.6.0
  commands:
  - npm run integration_test
- name: deploy_dev
  image: node:8.6.0
  commands:
  - npm run deploy -- --env=dev
  when:
   event:
     - push
  branch:
    - master

Причины, по которым Jenkins не подходит для современного мира Cloud Native,

  • Jenkins используется не только для выполнения CI, и именно здесь начинается проблема, поскольку экземпляры Jenkins становятся более сложными и создают узкое место. Выполнение CI и CD по отдельности дает больше преимуществ. Пользователи Jenkins используют его для создания компакт-дисков с пользовательскими сценариями, что не является правильным способом выполнения DevOps.
  • Вам нужен эксперт Jenkins, чтобы поддерживать его и отлаживать, когда что-то пойдет не так. Администраторы Drone сообщают, что тратят гораздо меньше времени на обслуживание своих экземпляров Drone, чем администраторы Jenkins. Drone легко масштабируется, чтобы обрабатывать тысячи запусков конвейера в день, и требует всего несколько часов обслуживания в месяц.
  • С таким количеством плагинов уязвимости легко внедряются и хаотичны. Плагины имеют сложные взаимозависимости, поэтому обновление одного плагина может привести к поломке другого.
  • Эффективное масштабирование Jenkins может быть затруднено, поскольку у вас может быть только один контроллер, который нельзя запустить в режиме высокой доступности. Причина этого в том, что несколько экземпляров Jenkins не могут работать вместе в конфигурации высокой доступности, только один экземпляр Jenkins может одновременно записывать в базу данных.
  • Я имею в виду, серьезно, Дженкинс не был разработан с учетом будущих инноваций. Jenkins был запущен за много лет до того, как был создан Docker, поэтому Jenkins никогда не был инструментом CI для контейнеров.
  • Jenkins потребляет много вычислительных ресурсов, потребляет много ресурсов и по-прежнему отстает, когда вы загружаете некоторые базовые плагины.

Размер докер-образа Jenkins составляет ~270 МБ, а размер докер-образа Drone — ~22 МБ.

Кроме того, проверьте твит Джима на том же,

  • Дженкинсу требуется крутая кривая обучения, и ему необходимо изучить Groovy для сложной настройки CI/CD. Groovy — это всего лишь один, Jenkins DSL — другой, и поэтому он становится сложным и хаотичным для тех, кто пытается настроить его в первый раз.
  • Некоторые пользователи сообщали, что запуск сборок с использованием Jenkins CLI зависает, и это плохой знак для инструмента DevOps. Принимая во внимание, что Drone CLI работает быстро, и вы можете запускать сборки локально с помощью простой команды Drone exec. У Drone также есть « режим отладки », который можно включить, что позволяет пользователям интерактивно отлаживать неисправные конвейеры, но есть ли у Jenkins эта функция? Я сомневаюсь в этом.

Почему вы должны перейти с Jenkins на Drone?

Несомненно, у Jenkins есть преимущество первопроходца в области непрерывной интеграции, и он стал популярным благодаря широкому распространению подключаемых модулей. Для небольшой команды с базовым использованием Jenkins подходит, но по мере роста вашей команды становится все труднее. Ему не хватает современных облачных возможностей. Конфигурация плагина кажется кошмаром, и в какой-то момент ее становится трудно поддерживать и масштабировать, а также может быть трудно поддерживать время безотказной работы. Кроме того, Jenkins широко известен своими высокими эксплуатационными расходами. Видимость конвейеров при использовании Jenkins очень плохая, и отладка становится настоящей проблемой. Изначально, когда настраиваешь, работает как шарм, меняешь простую вещь, начинает ломаться.

Отсутствие инноваций и старые методологии заставляют предприятия переходить с Jenkins на гораздо более сложные платформы. Управление Jenkins может быть работой на полный рабочий день, она выжимает энергию и время ваших разработчиков.

Есть много причин, по которым стоит подумать о переходе с Jenkins на Drone. Вот лучшие из них, которые мы рассматриваем:

  • Простота : Drone намного проще, чем Jenkins. Если вам нужно что-то более продвинутое, то у Jenkins больше возможностей. Однако, если вы просто хотите быстро приступить к работе без необходимости что-либо настраивать, то Drone — гораздо лучший выбор.
  • Скорость : Jenkins по умолчанию использует механизм опроса для поиска изменений в вашем коде. Это то, чего Drone избегает, поскольку использует веб-перехватчики. Это означает, что Drone намного быстрее обнаруживает изменения в вашем коде. Jenkins может работать с веб-перехватчиками, но это не стандартное поведение и не так просто, как Drone.
  • Простота использования : есть два способа, которыми Drone проще, чем Jenkins. Во-первых, пользовательский интерфейс намного проще. Во-вторых, процесс установки намного проще.
  • Современный подход : Дженкинс по-прежнему использует старые методологии и выполняет команды непосредственно при выполнении заданий, а не использует современные подходы, такие как контейнеры.
  • Написано на Go : Go становится подходящим языком из-за его возможностей соответствовать облачному пространству, и Drone написан на Go, тогда как Jenkins написан на Java.
  • Простые тесты : вам больше не нужно использовать Groovy для создания тестов, как в Jenkins. Все в декларативной форме, а тесты указаны в файле .drone.yaml.
  • Просто декларативный: в Drone все настраивается с помощью простых файлов YAML, и его очень легко настроить, и даже новичок может понять и настроить. Как мы обсуждали ранее, декларативный характер Drone помогает организациям легко внедрять Gitops.
  • Полностью на основе контейнеров и в облаке: каждый шаг представляет собой полностью изолированный контейнер Docker, поэтому разработчики могут быстро узнать, какой образ использовался на каждом этапе. Это помогает отладить, если что-то пойдет не так на любом этапе конвейера. Легко воспроизвести каждый шаг на вашем локальном компьютере.

Кроме того, поскольку GitOps — это более современный подход к развертыванию развертываний, связанных с Kubernetes, сочетание Drone и Argo CD работает на удивление хорошо. Например, вы можете использовать Drone для создания образов, а затем зафиксировать изменение конфигурации вашего приложения в git, которое Argo распознает и развернет изменение. Если вам нравится более индивидуальный подход, вы можете использовать Harness GitOps, который хорошо интегрирован с Drone.

Вывод

Когда речь идет об инструментах CI/CD, универсального решения не существует. У разных организаций будут разные потребности. Точно так же разные организации будут отдавать приоритет разным функциям. Поэтому при выборе правильного инструмента CI/CD для вашей организации очень важно оценить ваши потребности и найти продукт, который лучше всего им соответствует. Также важно учитывать, какие функции необходимы вашей организации, а какие желательно иметь. Сегодня каждая организация желает внедрить DevOps и использовать современные облачные технологии для быстрого развертывания программного обеспечения. Следовательно, становится жизненно важным помнить о выборе платформы/инструмента, который является облачным и имеет современные возможности. Имея это в виду, если вы в настоящее время используете Jenkins и ищете альтернативу, подумайте о переходе на Drone;

Ссылка: https://medium.com/faun/why-you-should-migrate-from-jenkins-to-drone-ci-today-90c96cc9a090

#java  #jenkins #docker 

Почему вам следует перейти с Jenkins на Drone CI
山田  千代

山田 千代

1658481600

為什麼你應該從 Jenkins 遷移到 Drone CI

我們繼續看到用於在 DevOps 世界中自動化代碼/軟件部署的新的和改進的軟件解決方案。無論您是開發人員還是運維工程師,在這個雲原生世界中都沒有使用平庸工具的餘地。每天都有創新、舊工具的更新版本和更易於訪問的服務,使我們作為編碼人員和運維專業人員的生活更加輕鬆。如今,DevOps 已成為焦點,每家公司都被稱為軟件公司。持續集成成為將 DevOps 作為一種方法論的第一步。

然而,市場上有如此多的持續集成工具,要知道哪一個最適合您的組織可能會很棘手。還有許多具有不同功能、定價模型和支持計劃的選項。本文將幫助您了解為什麼 Jenkins 不是為現代企業執行 CI 的合適工具,以及如何從 Jenkins 遷移到 Drone CI。

需要真正的持續集成工具

我們都知道云工具每天都在發展,我們看到很多替代工具可以完成同樣的工作。對於持續集成,市場上有很多工具,但真正了解開發人員並為他們構建的工具卻很難找到。雖然 Jenkins 對於初學者和組織來說可能是一個很好的起點,但一旦部署增加,它就會變得困難。雖然速度可能是判斷持續集成工具的另一個因素,但它也應該很容易在您的計算機上使用最少的命令進行設置。Drone CI 具備成為獨一無二的 CI 工具所需的一切,幫助開發人員通過持續集成構建和測試他們的應用程序。您可以在幾分鐘內將其設置在本地機器上並開始進行持續集成。Drone CI 建立在 Docker 之上,並在每個階段都使用容器的力量。

此外,讓我們看看 Drone 如何成為比 Jenkins 更好的持續集成工具。

詹金斯

Jenkins 是一個開源的持續集成工具。它用於在開發人員的本地機器上或在任何公共雲等持續集成環境中構建和測試軟件。使用 Jenkins,您可以自動化從代碼提交到生產的軟件交付管道。Jenkins 主要用於構建和部署自動化。它通常與 DevOps 工具鏈中的其他工具結合使用,例如源代碼管理、問題跟踪和項目管理。除了這些工具之外,Jenkins 還用於自動化測試和部署應用程序。Jenkins 的功能包括管理不同的工作、查看摘要圖表和接收電子郵件通知。

CI無人機

Drone CI 是 Harness 收購的開源持續集成服務器。它用於在開發人員的本地機器上或在任何公共雲等持續集成環境中構建和測試軟件。使用 Drone,您可以自動化從代碼提交到生產的軟件交付管道。除了構建軟件,Drone 還允許您構建、測試和部署您的應用程序。Drone CI 被認為是一種現代持續集成工具,因為它使用 yaml 文件形式的聲明性方法來自動化測試,並在每一步都廣泛使用 Docker 容器。構建管道花費的時間更少,並且易於設置和運行。

Drone CI 是一個基於容器的聲明式持續集成工具,它在每一步都廣泛使用 Docker 容器,並且可以輕鬆地在您的筆記本電腦、私有數據中心或公共雲上運行。持續集成的這種聲明性特性有助於組織採用 Gitops。

這是一個簡單的配置yaml文件

kind: pipeline
type: kubernetes
name: default
steps:
- name: test
  image: node
  commands:
  - npm install
  - npm test

只需將 YAML 配置擴展為您希望將更改合併到主分支的另一個場景。在這種情況下,階段是,

  • 建造
  • 單元測試
  • 部署到開發
  • 集成測試

yaml 配置可以很容易地指定如下,

kind: pipeline
name: default
steps:
- name: build
  image: node:8.6.0
  commands:
  - npm install
  - npm run build
  when:
   event:
     - push
- name: unit_test
  image: node:8.6.0
  commands:
  - npm run unit_test
  when:
   event:
     - push
- name: intergration_test
  image: node:8.6.0
  commands:
  - npm run integration_test
- name: deploy_dev
  image: node:8.6.0
  commands:
  - npm run deploy -- --env=dev
  when:
   event:
     - push
  branch:
    - master

Jenkins 不適合當今的 Cloud Native 世界的原因,

  • Jenkins 不僅僅用於執行 CI,這就是問題開始的地方,因為 Jenkins 實例變得更加複雜並產生了瓶頸。分開做 CI 和 CD 有更多的好處。Jenkins 用戶正在使用它來使用自定義腳本進行 CD,這不是進行 DevOps 的正確方法。
  • 您需要 Jenkins 專家來維護它並在出現問題時對其進行調試。Drone 管理員報告說,維護 Drone 實例的時間比 Jenkins 管理員少得多。Drone 可以輕鬆擴展以每天處理數千個管道執行,並且每月只需要幾個小時的維護。
  • 有這麼多的插件,漏洞很容易引入和混亂。插件具有復雜的相互依賴性,因此更新一個插件可能會破壞另一個插件。
  • Jenkins 很難有效擴展,因為您只能擁有一個無法在高可用模式下運行的控制器。這背後的原因是多個 Jenkins 實例不能在高可用性配置中一起工作,一次只能有一個 Jenkins 實例寫入數據庫。
  • 我的意思是,說真的,Jenkins 在設計時並沒有考慮到未來的創新。Jenkins 在創建 Docker 之前幾年就開始了,所以 Jenkins 從來都不是一個容器原生的 CI 工具。
  • Jenkins 的計算資源很重,它消耗大量資源,當你下載一些基本插件時它仍然滯後。

Jenkins docker 鏡像約為 270MB,而 Drone docker 鏡像約為 22MB。

另外,請查看Jim 的同一推文,

  • Jenkins 需要陡峭的學習曲線,並且需要學習 Groovy 以進行複雜的 CI/CD 設置。Groovy 只是一個,Jenkins DSL是另一個,因此對於第一次嘗試設置它的人來說變得困難和混亂。
  • 一些用戶報告說使用 Jenkins CLI 運行構建會掛起,這對於 DevOps 工具來說不是一個好兆頭。而 Drone CLI 速度很快,您可以使用簡單的無人機 exec 命令在本地運行構建。Drone 還有一個可以啟用的“調試模式”,允許用戶交互調試失敗的管道,但是 Jenkins 有這個功能嗎?我對此表示懷疑。

為什麼要從 Jenkins 遷移到 Drone?

毫無疑問,Jenkins在持續集成領域具有先發優勢,並因其插件的廣泛傳播而廣受歡迎。對於一個有基本用法的小團隊來說,Jenkins 是可以的,但隨著團隊的成長,它變得具有挑戰性。它缺乏現代云原生功能。插件配置似乎是一場噩夢,在某些時候,它變得難以維護和擴展,並且難以維持正常運行時間。此外,Jenkins 以其高維護性而聞名。使用 Jenkins 對管道的可見性非常差,這使得調試非常痛苦。最初,當你設置它時,它就像一個魅力,你改變一個簡單的東西,它開始崩潰。

缺乏創新和舊方法使企業從 Jenkins 轉向更複雜的平台。管理 Jenkins 可以是一個全職角色,它會擠出開發人員的精力和時間。

考慮從 Jenkins 遷移到 Drone 的原因有很多。這些是我們認為最重要的:

  • 簡單:Drone 比 Jenkins 簡單得多。如果你需要更高級的東西,那麼 Jenkins 有更多的功能。但是,如果您只想快速啟動並運行而無需配置任何東西,那麼 Drone 是一個更好的選擇。
  • 速度:Jenkins 默認使用輪詢機制來查找對代碼的更改。這是 Drone 在使用 webhook 時避免的。這意味著 Drone 在檢測代碼更改方面要快得多。Jenkins 可以使用 webhook,但這不是默認行為,也沒有 Drone 簡單。
  • 易用性:Drone 有兩種方式比 Jenkins 更簡單。首先,用戶界面要簡單得多。其次,安裝過程要簡單得多。
  • 現代方法:Jenkins 仍然使用舊方法並在運行作業時直接執行命令,而不是使用容器等現代方法。
  • 用 Go 編寫:Go 正在成為一種合適的語言,因為它能夠適應云原生空間,Drone 是用 Go 編寫的,而 Jenkins 是用 Java 編寫的。
  • 簡單測試:您不再需要像在 Jenkins 中那樣使用 Groovy 來構建您的測試。一切都是聲明式的,測試是用 .drone.yaml 文件指定的。
  • 簡單聲明:在 Drone 中,一切都通過簡單的 YAML 文件進行配置,配置非常簡單,即使是新手也能理解和設置。正如我們之前所討論的,Drone 的聲明性有助於組織輕鬆地採用 Gitops。
  • 完全基於容器和雲原生:每一步都是一個完全隔離的 Docker 容器,以便開發人員可以快速了解每個階段使用了哪個鏡像。如果管道的任何階段出現問題,它有助於調試。在本地機器上重現每個步驟很容易。

此外,由於 GitOps 是一種更現代的部署 Kubernetes 相關部署的方法,Drone 和 Argo CD 的結合非常好。例如,您可以使用 Drone 構建圖像,然後在 git 中提交對應用程序配置的更改,Argo 可以識別並部署更改。如果您喜歡更加定制化的方法,您可以使用與 Drone 很好集成的 Harness GitOps。

結論

對於 CI/CD 工具,沒有一種萬能的解決方案。不同的組織會有不同的需求。同樣,不同的組織將優先考慮不同的功能。因此,在為您的組織選擇正確的 CI/CD 工具時,評估您的需求並找到最能滿足這些需求的產品至關重要。此外,重要的是要考慮您的組織需要哪些功能以及哪些功能適合。如今,每個組織都希望採用 DevOps 並使用現代云原生技術快速部署軟件。因此,務必牢記選擇雲原生且具有現代功能的平台/工具。考慮到這一點,如果您目前正在使用 Jenkins 並正在尋找替代方案,請考慮遷移到 Drone;

鏈接:https ://medium.com/faun/why-you-should-migrate-from-jenkins-to-drone-ci-today-90c96cc9a090

#java  #jenkins #docker 

為什麼你應該從 Jenkins 遷移到 Drone CI
Thierry  Perret

Thierry Perret

1658470747

Pourquoi Vous Devriez Migrer De Jenkins Vers Drone CI

Nous continuons à voir des solutions logicielles nouvelles et améliorées pour automatiser le déploiement de code/logiciel dans le monde DevOps. Que vous soyez développeur ou ingénieur d'exploitation, il n'y a pas de place pour l'utilisation d'outils médiocres dans ce monde natif du cloud. Chaque jour, des innovations, des versions mises à jour d'anciens outils et des services plus accessibles facilitent la vie des codeurs et des professionnels des opérations. Aujourd'hui, DevOps est devenu le point central, chaque entreprise étant appelée une société de logiciels. L'intégration continue devient la première étape vers l'adoption de DevOps en tant que méthodologie.

Cependant, avec autant d'outils d'intégration continue sur le marché, il peut être difficile de savoir lequel convient le mieux à votre organisation. Il existe également de nombreuses options avec différentes fonctionnalités, modèles de tarification et plans de support. Cet article vous aidera à comprendre pourquoi Jenkins n'est pas un outil approprié pour faire du CI pour les entreprises modernes et comment vous pouvez migrer de Jenkins vers Drone CI.

Le besoin d'un véritable outil d'intégration continue

Nous savons tous que les outils cloud évoluent chaque jour et nous voyons de nombreux outils de substitution pour le même travail. Pour faire de l'intégration continue, il existe de nombreux outils sur le marché, mais celui qui comprend vraiment les développeurs et construit pour eux est difficile à trouver. Bien que Jenkins puisse être un bon point de départ pour les débutants et les organisations, cela devient difficile une fois que les déploiements augmentent. Bien que la vitesse puisse être un autre facteur pour juger un outil d'intégration continue, il doit également être facile à configurer sur votre ordinateur avec un minimum de commandes. Drone CI a tout ce qu'il faut pour être l'outil CI unique en son genre aidant les développeurs à créer et tester leurs applications grâce à l'intégration continue. Vous pouvez le configurer sur votre machine locale en quelques minutes et commencer à faire une intégration continue. Drone CI est construit sur Docker et utilise la puissance des conteneurs à chaque étape.

De plus, voyons comment Drone peut être un meilleur outil d'intégration continue que Jenkins.

Jenkins

Jenkins est un outil d'intégration continue open-source. Il est utilisé pour créer et tester des logiciels, soit sur la machine locale d'un développeur, soit dans un environnement d'intégration continue comme n'importe quel cloud public. Avec Jenkins, vous pouvez automatiser votre pipeline de livraison de logiciels, de la validation du code à la production. Jenkins est principalement utilisé pour l'automatisation de la construction et du déploiement. Il est généralement associé à d'autres outils de la chaîne d'outils DevOps, tels que la gestion du code source, le suivi des problèmes et la gestion de projet. En plus de ces outils, Jenkins est utilisé pour les tests automatisés et le déploiement d'applications. Les fonctionnalités de Jenkins incluent la gestion de différents travaux, l'affichage de graphiques récapitulatifs et la réception de notifications par e-mail.

Drone CI

Drone CI est un serveur d'intégration continue open-source acquis par Harness. Il est utilisé pour créer et tester des logiciels, soit sur la machine locale d'un développeur, soit dans un environnement d'intégration continue comme n'importe quel cloud public. Avec Drone, vous pouvez automatiser votre pipeline de livraison de logiciels, de la validation du code à la production. En plus de créer des logiciels, Drone vous permet de créer, tester et déployer vos applications. Drone CI est considéré comme un outil d'intégration continue moderne car il utilise l'approche déclarative sous la forme de fichiers yaml pour automatiser les tests et utilise largement les conteneurs Docker à chaque étape. Les pipelines de build prennent moins de temps et sont faciles à configurer et à exécuter.

Drone CI est un outil d'intégration continue déclaratif basé sur des conteneurs qui utilise largement des conteneurs Docker à chaque étape et peut facilement s'exécuter sur vos ordinateurs portables, votre centre de données privé ou sur un cloud public. Cette nature déclarative de l'intégration continue aide les organisations à adopter Gitops.

Voici un fichier yaml de configuration simple

kind: pipeline
type: kubernetes
name: default
steps:
- name: test
  image: node
  commands:
  - npm install
  - npm test

Il suffit d'étendre la configuration YAML avec un autre scénario dans lequel vous souhaitez fusionner les modifications apportées à la branche principale. Dans ce cas, les étapes sont,

  • Construire
  • Test de l'unité
  • Déployer vers le développeur
  • Test d'intégration

La configuration yaml peut être facilement spécifiée comme ci-dessous,

kind: pipeline
name: default
steps:
- name: build
  image: node:8.6.0
  commands:
  - npm install
  - npm run build
  when:
   event:
     - push
- name: unit_test
  image: node:8.6.0
  commands:
  - npm run unit_test
  when:
   event:
     - push
- name: intergration_test
  image: node:8.6.0
  commands:
  - npm run integration_test
- name: deploy_dev
  image: node:8.6.0
  commands:
  - npm run deploy -- --env=dev
  when:
   event:
     - push
  branch:
    - master

Raisons pour lesquelles Jenkins n'est pas adapté au monde Cloud Native d'aujourd'hui,

  • Jenkins est utilisé plus que pour faire de la CI, et c'est là que le problème commence car les instances de Jenkins deviennent plus complexes et créent un goulot d'étranglement. Il y a plus d'avantages à faire CI et CD séparément. Les utilisateurs de Jenkins l'utilisent pour créer des CD avec des scripts personnalisés, ce qui n'est pas la bonne façon de faire DevOps.
  • Vous avez besoin d'un expert Jenkins pour le maintenir et le déboguer en cas de problème. Les administrateurs de drones déclarent passer beaucoup moins de temps à maintenir leurs instances de drones que les administrateurs Jenkins. Le drone peut facilement évoluer pour gérer des milliers d'exécutions de pipelines par jour et ne nécessite que quelques heures de maintenance par mois.
  • Avec autant de plugins, les vulnérabilités sont facilement introduites et chaotiques. Les plugins ont des interdépendances complexes, donc la mise à jour d'un plugin pourrait potentiellement en casser un autre.
  • Jenkins peut être difficile à mettre à l'échelle efficacement car vous ne pouvez avoir qu'un seul contrôleur qui ne peut pas être exécuté dans un mode hautement disponible. La raison derrière cela est que plusieurs instances Jenkins ne peuvent pas fonctionner ensemble dans une configuration à haute disponibilité, une seule instance Jenkins peut écrire dans la base de données à la fois.
  • Je veux dire, sérieusement, Jenkins n'a pas été conçu en gardant à l'esprit les innovations futures. Jenkins a été lancé des années avant la création de Docker, donc Jenkins n'a jamais été un outil CI natif pour les conteneurs.
  • Jenkins est lourd en ressources de calcul, il consomme beaucoup de ressources et il est toujours en retard lorsque vous téléchargez des plugins de base.

L'image du menu fixe Jenkins est d'environ 270 Mo, tandis que l'image du menu fixe Drone est d'environ 22 Mo.

Consultez également le tweet de Jim sur le même sujet,

  • Jenkins nécessite une courbe d'apprentissage abrupte et doit apprendre Groovy pour une configuration CI/CD complexe. Groovy n'en est qu'un, Jenkins DSL en est un autre et devient donc difficile et chaotique pour quelqu'un qui essaie de le configurer pour la première fois.
  • Certains utilisateurs ont signalé que l'exécution de builds à l'aide de la CLI Jenkins se bloque, ce qui n'est pas bon signe pour un outil DevOps. Alors que Drone CLI est rapide et que vous pouvez exécuter des builds localement avec une simple commande drone exec. Drone dispose également d'un « mode de débogage » qui peut être activé, permettant aux utilisateurs de déboguer de manière interactive les pipelines défaillants, mais Jenkins a-t-il cette fonctionnalité ? J'en doute.

Pourquoi devriez-vous migrer de Jenkins vers Drone ?

Sans aucun doute, Jenkins a un avantage de premier arrivé dans le domaine de l'intégration continue, et il est devenu populaire en raison de sa vaste diffusion de plugins. Pour une petite équipe avec une utilisation de base, Jenkins est OK, mais cela devient difficile à mesure que votre équipe grandit. Il manque de capacités natives cloud modernes. La configuration des plugins semble être un cauchemar, et à un moment donné, elle devient difficile à maintenir et à faire évoluer et peut être difficile à maintenir la disponibilité. De plus, Jenkins est populairement connu pour son entretien élevé. La visibilité sur les pipelines est très mauvaise avec Jenkins et cela rend le débogage très pénible. Au départ, lorsque vous l'installez, cela fonctionne comme un charme, vous changez une chose simple, ça commence à casser.

Le manque d'innovation et les anciennes méthodologies font que les entreprises s'éloignent de Jenkins vers des plateformes beaucoup plus sophistiquées. La gestion de Jenkins peut être un rôle à temps plein, cela épuise l'énergie et le temps de vos développeurs.

Il existe de nombreuses raisons d'envisager de migrer de Jenkins vers Drone. Voici les principaux que nous considérons :

  • Simplicité : Drone est beaucoup plus simple que Jenkins. Si vous avez besoin de quelque chose de plus avancé, alors Jenkins a plus de fonctionnalités. Cependant, si vous voulez simplement être opérationnel rapidement sans avoir à configurer quoi que ce soit, alors Drone est un bien meilleur choix.
  • Rapidité : Jenkins utilise un mécanisme de polling par défaut pour rechercher les modifications apportées à votre code. C'est quelque chose que Drone évite car il utilise des webhooks. Cela signifie que Drone est beaucoup plus rapide pour détecter les modifications apportées à votre code. Jenkins peut fonctionner avec des webhooks, mais ce n'est pas le comportement par défaut et ce n'est pas aussi simple que Drone.
  • Facilité d'utilisation : Drone est plus simple que Jenkins de deux manières. Tout d'abord, l'interface utilisateur est beaucoup plus simple. Deuxièmement, le processus d'installation est beaucoup plus simple.
  • Approche moderne : Jenkins utilise toujours les anciennes méthodologies et exécute les commandes directement lors de l'exécution des tâches plutôt que d'utiliser des approches modernes telles que les conteneurs.
  • Écrit en Go : Go devient un langage approprié en raison de ses capacités à s'adapter à l'espace natif du cloud, et Drone est écrit en Go, tandis que Jenkins est écrit en Java.
  • Tests simples : Vous n'êtes plus obligé d'utiliser Groovy pour construire vos tests comme dans Jenkins. Tout est de façon déclarative, et les tests sont spécifiés avec le fichier .drone.yaml.
  • Simplement déclaratif : Dans Drone, tout est configuré via de simples fichiers YAML et il est très facile à configurer et même un débutant peut comprendre et configurer. Comme nous en avons discuté précédemment, la nature déclarative de Drone aide les organisations à adopter facilement Gitops.
  • Totalement basé sur des conteneurs et natif du cloud : chaque étape est un conteneur Docker entièrement isolé afin que les développeurs puissent rapidement savoir quelle image a été utilisée à chaque étape. Cela aide à déboguer si quelque chose ne va pas à n'importe quelle étape du pipeline. Il est facile de reproduire chaque étape sur votre machine locale.

De plus, étant donné que GitOps est une approche plus moderne pour déployer des déploiements liés à Kubernetes, la combinaison de Drone et Argo CD se passe incroyablement bien. Par exemple, vous pouvez utiliser Drone pour créer vos images, puis valider une modification de la configuration de votre application dans git, qu'Argo reconnaît et déploie la modification. Si vous aimez une approche plus personnalisée, vous pouvez utiliser Harness GitOps, qui est bien intégré à Drone.

Conclusion

Il n'existe pas de solution unique en matière d'outils CI/CD. Différentes organisations auront des besoins différents. De même, différentes organisations donneront la priorité à différentes fonctionnalités. Par conséquent, lors de la sélection du bon outil CI/CD pour votre organisation, il est essentiel d'évaluer vos besoins et de trouver le produit qui y répond le mieux. De plus, il est important de considérer quelles fonctions sont nécessaires pour votre organisation et lesquelles sont agréables à avoir. Aujourd'hui, chaque organisation souhaite adopter DevOps et utiliser des technologies cloud natives modernes pour déployer rapidement des logiciels. Par conséquent, il devient essentiel de garder à l'esprit de sélectionner une plate-forme/un outil cloud natif et doté de capacités modernes. Dans cet esprit, si vous utilisez actuellement Jenkins et recherchez une alternative, envisagez de migrer vers Drone ;

Lien : https://medium.com/faun/why-you-should-migrate-from-jenkins-to-drone-ci-today-90c96cc9a090

#java  #jenkins #docker 

Pourquoi Vous Devriez Migrer De Jenkins Vers Drone CI
Hoang  Kim

Hoang Kim

1658463473

Tại Sao Bạn Nên Chuyển Từ Jenkins Sang Drone CI

Chúng tôi tiếp tục thấy các giải pháp phần mềm mới và cải tiến để tự động hóa việc triển khai mã / phần mềm trong thế giới DevOps. Cho dù bạn là nhà phát triển hay kỹ sư vận hành, không có chỗ cho việc sử dụng các công cụ tầm thường trong thế giới gốc đám mây này. Mỗi ngày đều có những đổi mới, phiên bản cập nhật của các công cụ cũ và các dịch vụ dễ tiếp cận hơn giúp cuộc sống của chúng ta với tư cách là lập trình viên và chuyên gia hoạt động trở nên dễ dàng hơn. Ngày nay, DevOps đã trở thành tâm điểm, với mọi công ty được gọi là công ty phần mềm. Tích hợp liên tục trở thành bước đầu tiên hướng tới việc sử dụng DevOps như một phương pháp luận.

Tuy nhiên, với rất nhiều công cụ tích hợp liên tục trên thị trường, việc biết cái nào là tốt nhất cho tổ chức của bạn có thể rất khó khăn. Ngoài ra còn có nhiều tùy chọn với các tính năng, mô hình giá cả và gói hỗ trợ khác nhau. Bài viết này sẽ giúp bạn hiểu tại sao Jenkins không phải là công cụ phù hợp để làm CI cho các doanh nghiệp hiện đại và cách bạn có thể chuyển từ Jenkins sang Drone CI.

Sự cần thiết của một công cụ tích hợp liên tục thực sự

Tất cả chúng ta đều biết rằng các công cụ đám mây đang phát triển mỗi ngày và chúng ta thấy có rất nhiều công cụ thay thế cho cùng một công việc. Để thực hiện tích hợp liên tục, có rất nhiều công cụ trên thị trường, nhưng khó tìm được công cụ thực sự hiểu các nhà phát triển và xây dựng cho họ. Mặc dù Jenkins có thể là một điểm khởi đầu tốt cho người mới bắt đầu và các tổ chức, nhưng nó sẽ trở nên khó khăn khi việc triển khai tăng lên. Mặc dù tốc độ có thể là một yếu tố khác để đánh giá một công cụ tích hợp liên tục, nhưng nó cũng phải dễ dàng thiết lập trên máy tính của bạn với các lệnh tối thiểu. Drone CI có tất cả những gì cần thiết để trở thành công cụ CI độc nhất vô nhị giúp các nhà phát triển xây dựng và kiểm tra các ứng dụng của họ thông qua tích hợp liên tục. Bạn có thể thiết lập nó trên máy cục bộ của mình trong vài phút và bắt đầu tích hợp liên tục. Drone CI được xây dựng trên Docker & sử dụng sức mạnh của các thùng chứa ở mỗi giai đoạn.

Hơn nữa, hãy xem Drone có thể là một công cụ tích hợp liên tục tốt hơn Jenkins như thế nào.

Jenkins

Jenkins là một công cụ tích hợp liên tục mã nguồn mở. Nó được sử dụng để xây dựng và kiểm tra phần mềm, trên máy cục bộ của nhà phát triển hoặc trong môi trường tích hợp liên tục như bất kỳ đám mây công cộng nào. Với Jenkins, bạn có thể tự động hóa quy trình phân phối phần mềm của mình từ cam kết mã đến sản xuất. Jenkins chủ yếu được sử dụng để xây dựng và tự động hóa triển khai. Nó thường được kết hợp với các công cụ khác trong chuỗi công cụ DevOps, như quản lý mã nguồn, theo dõi vấn đề và quản lý dự án. Ngoài các công cụ này, Jenkins được sử dụng để thử nghiệm tự động và triển khai các ứng dụng. Các tính năng của Jenkins bao gồm quản lý các công việc khác nhau, xem đồ thị tóm tắt và nhận thông báo qua email.

Máy bay không người lái CI

Drone CI là một máy chủ tích hợp liên tục mã nguồn mở được mua lại bởi Harness. Nó được sử dụng để xây dựng và kiểm tra phần mềm, trên máy cục bộ của nhà phát triển hoặc trong môi trường tích hợp liên tục như bất kỳ đám mây công cộng nào. Với Drone, bạn có thể tự động hóa quy trình phân phối phần mềm của mình từ cam kết mã đến sản xuất. Ngoài việc xây dựng phần mềm, Drone cho phép bạn xây dựng, kiểm tra và triển khai các ứng dụng của mình. Drone CI được coi là một công cụ tích hợp liên tục hiện đại vì nó sử dụng phương pháp khai báo dưới dạng tệp yaml để tự động hóa các bài kiểm tra và sử dụng rộng rãi các vùng chứa Docker ở mọi bước. Các đường ống xây dựng tốn ít thời gian hơn và dễ dàng thiết lập và chạy.

Drone CI là một công cụ tích hợp liên tục dựa trên khai báo dựa trên vùng chứa, sử dụng rộng rãi các vùng chứa Docker ở mọi bước và có thể dễ dàng chạy trên máy tính xách tay, trung tâm dữ liệu cá nhân hoặc trên đám mây công cộng của bạn. Bản chất khai báo của tích hợp liên tục này giúp các tổ chức áp dụng Gitops.

Đây là một tệp yaml cấu hình đơn giản

kind: pipeline
type: kubernetes
name: default
steps:
- name: test
  image: node
  commands:
  - npm install
  - npm test

Chỉ cần mở rộng cấu hình YAML với một kịch bản khác mà bạn muốn hợp nhất các thay đổi vào nhánh chính. Trong trường hợp này, các giai đoạn là,

  • Xây dựng
  • Bài kiểm tra đơn vị
  • Triển khai cho nhà phát triển
  • Bài kiểm tra tích hợp

Cấu hình yaml có thể được chỉ định dễ dàng như dưới đây,

kind: pipeline
name: default
steps:
- name: build
  image: node:8.6.0
  commands:
  - npm install
  - npm run build
  when:
   event:
     - push
- name: unit_test
  image: node:8.6.0
  commands:
  - npm run unit_test
  when:
   event:
     - push
- name: intergration_test
  image: node:8.6.0
  commands:
  - npm run integration_test
- name: deploy_dev
  image: node:8.6.0
  commands:
  - npm run deploy -- --env=dev
  when:
   event:
     - push
  branch:
    - master

Lý do tại sao Jenkins không phù hợp trong thế giới Cloud Native ngày nay,

  • Jenkins được sử dụng nhiều hơn là chỉ để làm CI, và đó là nơi vấn đề bắt đầu khi các cá thể Jenkins trở nên phức tạp hơn và tạo ra một nút thắt cổ chai. Có nhiều lợi ích hơn khi thực hiện riêng rẽ CI và CD. Người dùng Jenkins đang sử dụng nó để tạo đĩa CD với các tập lệnh tùy chỉnh, đây không phải là cách phù hợp để thực hiện DevOps.
  • Bạn cần một chuyên gia Jenkins để bảo trì nó và gỡ lỗi khi có sự cố. Các quản trị viên Drone báo cáo dành ít thời gian hơn để duy trì các phiên bản Drone của họ so với các quản trị viên Jenkins. Drone có thể dễ dàng mở rộng quy mô để xử lý hàng nghìn lần thực thi đường ống mỗi ngày và chỉ yêu cầu vài giờ bảo trì mỗi tháng.
  • Với rất nhiều plugin, các lỗ hổng bảo mật dễ dàng được đưa vào và hỗn loạn. Các plugin có sự phụ thuộc lẫn nhau phức tạp, vì vậy việc cập nhật một plugin có thể phá vỡ một plugin khác.
  • Jenkins có thể khó mở rộng quy mô hiệu quả bởi vì bạn chỉ có thể có một bộ điều khiển không thể chạy ở chế độ khả dụng cao. Lý do đằng sau điều này là nhiều cá thể Jenkins không thể hoạt động cùng nhau trong một cấu hình có tính khả dụng cao, chỉ một cá thể Jenkins có thể ghi vào cơ sở dữ liệu tại một thời điểm.
  • Ý tôi là, nghiêm túc mà nói, Jenkins không được thiết kế để lưu ý đến những đổi mới trong tương lai. Jenkins đã được bắt đầu nhiều năm trước khi Docker được tạo ra, vì vậy Jenkins chưa bao giờ là một công cụ CI gốc vùng chứa.
  • Jenkins nặng về tài nguyên máy tính, nó tiêu tốn rất nhiều tài nguyên và nó vẫn bị trễ khi bạn tải xuống một số plugin cơ bản.

Hình ảnh docker Jenkins là ~ 270MB trong khi hình ảnh docker Drone là ~ 22MB.

Ngoài ra, hãy kiểm tra tweet của Jim trên cùng một,

  • Jenkins yêu cầu một đường cong học tập dốc và cần học Groovy để thiết lập CI / CD phức tạp. Groovy chỉ là một, Jenkins DSL là một người khác và do đó trở nên khó khăn và hỗn loạn đối với những người đang cố gắng thiết lập nó lần đầu tiên.
  • Một số người dùng báo cáo rằng việc chạy các bản dựng sử dụng Jenkins CLI bị treo và đó không phải là một dấu hiệu tốt cho một công cụ DevOps. Trong khi Drone CLI nhanh và bạn có thể chạy các bản dựng cục bộ bằng một lệnh thực thi máy bay không người lái đơn giản. Drone cũng có “ chế độ gỡ lỗi ” có thể được bật, cho phép người dùng tương tác gỡ lỗi các đường ống bị lỗi nhưng Jenkins có tính năng này không? Tôi nghi ngờ điều đó.

Tại sao bạn nên di chuyển từ Jenkins sang Drone?

Không nghi ngờ gì nữa, Jenkins có lợi thế đi đầu trong lĩnh vực tích hợp liên tục, và nó trở nên phổ biến vì sự phổ biến rộng lớn của các plugin. Đối với một nhóm nhỏ với cách sử dụng cơ bản, Jenkins không sao, nhưng nó sẽ trở nên khó khăn khi nhóm của bạn phát triển. Nó thiếu các khả năng tự nhiên của đám mây hiện đại. Cấu hình plugin dường như là một cơn ác mộng và tại một số thời điểm, nó trở nên khó bảo trì và mở rộng và có thể khó duy trì thời gian hoạt động. Ngoài ra, Jenkins nổi tiếng với khả năng bảo trì cao. Khả năng hiển thị trên các đường ống là rất kém khi sử dụng Jenkins và nó khiến việc gỡ lỗi trở nên thực sự khó khăn. Ban đầu, khi bạn thiết lập nó, nó hoạt động như một cái bùa, bạn thay đổi một thứ đơn giản, nó bắt đầu vỡ.

Thiếu sự đổi mới và phương pháp luận cũ khiến các doanh nghiệp rời xa Jenkins sang các nền tảng phức tạp hơn nhiều. Quản lý Jenkins có thể là một vai trò toàn thời gian, nó vắt kiệt năng lượng và thời gian của các nhà phát triển của bạn.

Có nhiều lý do để cân nhắc việc chuyển từ Jenkins sang Drone. Đây là những thứ hàng đầu mà chúng tôi xem xét:

  • Tính đơn giản : Drone đơn giản hơn nhiều so với Jenkins. Nếu bạn cần một cái gì đó cao cấp hơn, thì Jenkins có nhiều tính năng hơn. Tuy nhiên, nếu bạn chỉ muốn khởi động và chạy nhanh chóng mà không cần phải cấu hình bất cứ thứ gì, thì Drone là lựa chọn tốt hơn nhiều.
  • Tốc độ : Jenkins sử dụng cơ chế thăm dò theo mặc định để tìm kiếm các thay đổi đối với mã của bạn. Đây là điều mà Drone tránh vì nó sử dụng webhook. Điều này có nghĩa là Drone nhanh hơn nhiều trong việc phát hiện các thay đổi đối với mã của bạn. Jenkins có thể làm việc với webhook, nhưng nó không phải là hành vi mặc định và không dễ dàng như Drone.
  • Dễ sử dụng : Có hai cách mà Drone đơn giản hơn Jenkins. Đầu tiên, giao diện người dùng đơn giản hơn nhiều. Thứ hai, quá trình cài đặt đơn giản hơn nhiều.
  • Phương pháp tiếp cận hiện đại : Jenkins vẫn sử dụng các phương pháp luận cũ và thực hiện các lệnh trực tiếp khi chạy công việc thay vì sử dụng các phương pháp tiếp cận hiện đại như vùng chứa.
  • Viết bằng Go : Go đang trở thành một ngôn ngữ phù hợp vì khả năng của nó để phù hợp với không gian gốc đám mây và Drone được viết bằng Go, trong khi Jenkins được viết bằng Java.
  • Kiểm tra đơn giản : Bạn không còn phải sử dụng Groovy để xây dựng các bài kiểm tra của mình như trong Jenkins. Mọi thứ đều theo kiểu khai báo và các bài kiểm tra được chỉ định bằng tệp .drone.yaml.
  • Đơn giản chỉ cần khai báo: Trong Drone, mọi thứ được cấu hình thông qua các tệp YAML đơn giản và nó rất dễ cấu hình và ngay cả một người mới cũng có thể hiểu và thiết lập. Như chúng ta đã thảo luận trước đây, bản chất khai báo của Drone giúp các tổ chức áp dụng Gitops một cách dễ dàng.
  • Hoàn toàn dựa trên vùng chứa và dựa trên nền tảng đám mây: Mỗi bước là một vùng chứa Docker hoàn toàn biệt lập để các nhà phát triển có thể nhanh chóng biết hình ảnh nào đã được sử dụng ở mọi giai đoạn. Nó giúp gỡ lỗi nếu có sự cố xảy ra ở bất kỳ giai đoạn nào của đường ống. Thật dễ dàng để tái tạo từng bước trên máy cục bộ của bạn.

Ngoài ra, vì GitOps là một cách tiếp cận hiện đại hơn để triển khai các triển khai liên quan đến Kubernetes, sự kết hợp giữa Drone và Argo CD diễn ra tốt một cách đáng kinh ngạc. Ví dụ: bạn có thể sử dụng Drone để xây dựng hình ảnh của mình và sau đó cam kết thay đổi cấu hình ứng dụng của bạn trong git, Argo nhận ra và triển khai thay đổi. Nếu bạn thích cách tiếp cận tùy chỉnh hơn, bạn có thể sử dụng Harness GitOps, được tích hợp tốt với Drone.

Sự kết luận

Không có một giải pháp phù hợp với tất cả khi nói đến các công cụ CI / CD. Các tổ chức khác nhau sẽ có những nhu cầu khác nhau. Tương tự, các tổ chức khác nhau sẽ ưu tiên các tính năng khác nhau. Do đó, khi lựa chọn công cụ CI / CD phù hợp cho tổ chức của bạn, điều quan trọng là phải đánh giá nhu cầu của bạn và tìm ra sản phẩm đáp ứng tốt nhất. Ngoài ra, điều quan trọng là phải xem xét những chức năng nào cần thiết cho tổ chức của bạn và những chức năng nào tốt để có. Ngày nay, mọi tổ chức đều mong muốn nắm lấy DevOps và sử dụng các công nghệ gốc đám mây hiện đại để triển khai phần mềm một cách nhanh chóng. Do đó, điều quan trọng cần ghi nhớ là chọn một nền tảng / công cụ có nguồn gốc từ đám mây và có các khả năng hiện đại. Với suy nghĩ đó, nếu bạn hiện đang sử dụng Jenkins và đang tìm kiếm một giải pháp thay thế, hãy cân nhắc chuyển sang Drone;

Liên kết: https://medium.com/faun/why-you-should-migrate-from-jenkins-to-drone-ci-today-90c96cc9a090

#java  #jenkins #docker 

Tại Sao Bạn Nên Chuyển Từ Jenkins Sang Drone CI
Coding  Life

Coding Life

1656475393

Deploy Docker Image to Kubernetes using Jenkins | CI CD Pipeline Using Jenkins

This tutorial will help you to understand complete devops end to end integration where We are going to cover Build Docker Image using Jenkins Pipeline and Push Docker Image to Docker Hub and next deploy it to kubernetes cluster step by step using Jenkins Pipeline

GitHub: https://github.com/Java-Techie-jt/devops-automation 

Subscribe: https://www.youtube.com/c/JavaTechie/featured 

#docker #jenkins #kubernetes 

Deploy Docker Image to Kubernetes using Jenkins | CI CD Pipeline Using Jenkins