我在Jenkins上尝试使用Terraform来部署基础架构

首先

    • 今回はAmazon EC2でJenkinsサーバを構築し、Jenkins上でTerraformによるインフラのデプロイをやってみたいと思います。

 

    • 以下のバージョンで動作確認をしています。

Jenkins: 2.361.1
Terraform: 1.3.4

请注意。

    • 本記事で構築するアーキテクチャはdemo用のため、本番環境などで利用する際に非機能要件等を考慮した適切な設計が必要です。

 

    • ソースのバージョン管理としてGithubを使用していますが、Githubアカウントをお持ちでない方は別途用意する必要があります。

 

    本記事はJenkinsパイプラインの構築およびJenkinsパイプラインを使ったTerraformデプロイのやり方にフォーカスしていますので、それを実現するための関連AWSリソースの詳細構築手順を割愛させていただきます。

建构图

tf-jenkins-demo.drawio.png

構成圖的解釋

    1. 将Terraform代码推送到远程仓库

 

    1. 通过Jenkins控制台连接并执行作业

 

    1. 从远程仓库克隆Terraform代码到Jenkins服务器

 

    1. 执行terraform plan和terraform apply,将tfstate文件保存到已创建的S3存储桶中

 

    使用Terraform创建AWS验证资源

建立环境

我们将在ap-northeast-1地区创建AWS资源,以实现上述架构。对于未提及的设置项目,将使用默认值。(详细构建步骤已省略)
此外,请使用现有的网络类资源(VPC、子网等),如果可以的话。
※我们准备了以下CloudFormation模板,如果您希望节省构建的工作量,可以使用它。

AWSTemplateFormatVersion: “2010-09-09″Parameters:
MyPublicIP:
Type: “String”
Description: “以/32结尾”
Default: “”
KeyName:
Type: “AWS::EC2::KeyPair::KeyName”
InstanceType:
Type: “String”
Default: “t2.micro”
AMI:
Type: AWS::SSM::Parameter::Value
Default: “/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2”
TfstateS3BucketName:
Type: “String”
Default: “”

Resources:
# 创建VPC
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: “10.0.0.0/16”
EnableDnsHostnames: true
EnableDnsSupport: true
InstanceTenancy: default
Tags:
– Key: “Name”
Value: “tf-jenkins-demo-vpc”

# 创建互联网网关
InternetGateway:
Type: AWS::EC2::InternetGateway
Properties:
Tags:
– Key: “Name”
Value: “tf-jenkins-demo-igw”
VPCGatewayAttachment:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
InternetGatewayId: !Ref InternetGateway
VpcId: !Ref VPC

# 创建路由表
PublicRouteTable:
Type: AWS::EC2::RouteTable
Properties:
Tags:
– Key: Name
Value: “tf-jenkins-demo-public-rtb”
VpcId: !Ref VPC
PublicRoute:
Type: AWS::EC2::Route
Properties:
DestinationCidrBlock: “0.0.0.0/0”
GatewayId: !Ref InternetGateway
RouteTableId: !Ref PublicRouteTable

# 创建公有子网
PublicSubnetA:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
CidrBlock: “10.0.1.0/24”
AvailabilityZone: !Sub ${AWS::Region}a
Tags:
– Key: “Name”
Value: “tf-jenkins-demo-public-subnet-1a”
PublicSubnetARouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
RouteTableId: !Ref PublicRouteTable
SubnetId: !Ref PublicSubnetA

# 创建EC2的安全组
LinuxEC2SG:
Type: AWS::EC2::SecurityGroup
Properties:
GroupName: “tf-jenkins-demo-linux-sg”
GroupDescription: “tf-jenkins-demo-linux-sg”
VpcId: !Ref VPC
Tags:
– Key: Name
Value: “tf-jenkins-demo-linux-sg”
SecurityGroupIngress:
– IpProtocol: tcp
FromPort: 8080
ToPort: 8080
CidrIp: !Ref MyPublicIP
Description: “用于Jenkins控制台”
– IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: !Ref MyPublicIP
Description: “用于SSH”
SecurityGroupEgress:
– IpProtocol: -1
CidrIp: “0.0.0.0/0”
Description: “用于互联网访问”

# 创建EC2的IAM角色
IAMRoleForLinuxEC2:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: “2012-10-17”
Statement:
– Effect: Allow
Principal:
Service:
– ec2.amazonaws.com
Action:
– ‘sts:AssumeRole’
Path: /
Policies:
– PolicyName: “ec2-s3-full-access-policy”
PolicyDocument:
Version: “2012-10-17”
Statement:
– Effect: Allow
Action:
– ‘ec2:*’
– ‘s3:*’
Resource: ‘*’
RoleName: “ec2-s3-full-access-role”
LinuxInstanceProfile:
Type: ‘AWS::IAM::InstanceProfile’
Properties:
Path: /
Roles:
– !Ref IAMRoleForLinuxEC2

# 创建EC2实例
LinuxEC2:
Type: AWS::EC2::Instance
Properties:
ImageId: !Ref AMI
KeyName: !Ref KeyName
InstanceType: !Ref InstanceType
IamInstanceProfile: !Ref LinuxInstanceProfile
NetworkInterfaces:
– AssociatePublicIpAddress: “true”
DeviceIndex: “0”
SubnetId: !Ref PublicSubnetA
GroupSet:
– !Ref LinuxEC2SG
Tags:
– Key: Name
Value: “jenkins-server”

# 创建用于保存tfstate文件的S3存储桶
S3Bucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Ref TfstateS3BucketName

# Jenkins服务器的公有IP地址
Outputs:
JenkinsServerPublicIp:
Description: Jenkins服务器的公有IP地址
Value: !GetAtt LinuxEC2.PublicIp
Export:
Name: !Sub “${AWS::StackName}-PublicIp”

网络

    VPC
設定項目設定値名前タグtf-jenkins-demo-vpcIPv4 CIDRブロック10.0.0.0/16DNSホスト名有効化DNS解決有効化
    インターネットゲートウェイ
設定項目設定値名前タグtf-jenkins-demo-igwアタッチするVPCtf-jenkins-demo-vpc
    ルートテーブル
設定項目設定値名前タグtf-jenkins-demo-public-rtbVPCtf-jenkins-demo-vpcルート送信先: 0.0.0.0/0
ターゲット: tf-jenkins-demo-igw
    サブネット
設定項目設定値VPCtf-jenkins-demo-vpcサブネット名tf-jenkins-demo-public-subnet-1aアベイラビリティーゾーンap-northeast-1aIPv4 CIDRブロック10.0.1.0/24関連付けるルートテーブルtf-jenkins-demo-public-rtb

安全组

設定項目設定値セキュリティグループ名tf-jenkins-demo-linux-sg説明tf-jenkins-demo-linux-sgVPCtf-jenkins-demo-vpcインバウンドルール(カスタムTCP)タイプ: タスタムTCP
プロトコル: TCP
ポート範囲: 8080
ソース: 自分自身のパブリックIPアドレス(末尾に/32が必要)インバウンドルール(SSH)タイプ: SSH
プロトコル: TCP
ポート範囲: 22
ソース: 自分自身のパブリックIPアドレス(末尾に/32が必要)アウトバウンドルール(インターネット接続)タイプ: すべてのトラフィック
プロトコル: すべて
ポート範囲: すべて
送信先: 0.0.0.0/0

我是IAM策略和角色。

    IAMポリシー
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "ec2:*",
                "s3:*"
            ],
            "Resource": "*",
            "Effect": "Allow"
        }
    ]
}
    IAMロール
設定項目設定値ロール名ec2-s3-full-access-role信頼されたエンティティタイプEC2許可ポリシーec2-s3-full-access-policy

EC2实例

設定項目設定値名前タグjenkins-serverAMIAmazon Linux 2(amzn2-ami-hvm-x86_64-gp2)インスタンスタイプt2.microキーペア既存のものを選択、または新規作成VPCtf-jenkins-demo-vpcサブネットtf-jenkins-demo-public-subnet-1aパブリック IP の自動割り当て有効化セキュリティグループtf-jenkins-demo-linux-sgIAMインスタンスプロフィールec2-s3-full-access-role

S3桶(用于Terraform的后端)

設定項目設定値バケット名任意(グローバルで一意でなければならないリージョンap-northeast-1

建立 Jenkins

Jenkins安装

我们将在上述创建的EC2实例上安装Jenkins。虽然也可以使用Docker容器等方法进行构建,但本次我们决定直接在EC2上安装。
通过SSH连接到EC2,根据Jenkins官方网站的安装步骤,执行以下命令。

sudo wget -O /etc/yum.repos.d/jenkins.repo \
    https://pkg.jenkins.io/redhat-stable/jenkins.repo
sudo rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io.key
sudo yum upgrade -y
sudo amazon-linux-extras install java-openjdk11 -y
sudo yum install git -y
# Jenkinsのバージョンを指定してインストールする
sudo yum install jenkins-2.361.1 -y
sudo systemctl daemon-reload
sudo systemctl enable jenkins
sudo systemctl start jenkins

Jenkins的初始配置

image.png
sudo cat /var/lib/jenkins/secrets/initialAdminPassword
Screenshot 2022-11-10 at 11.21.14.png

一旦显示初始管理员用户创建页面,请输入所需信息并点击“保存并继续”。

Screenshot 2022-11-10 at 11.30.49.png
Screenshot 2022-11-10 at 11.32.23.png

安装Terraform插件

Screenshot 2022-11-10 at 12.12.35.png

创建Github仓库

由于这次只是演示,我决定创建一个公共存储库。如果要创建私有存储库,需要在Jenkins中注册存储库Clone的访问令牌或SSH密钥,请注意。

创建Jenkinsfile和Terraform代码

Jenkins文件

在Pipeline的tools区块中,写入Jenkins已安装的Terraform插件的“Name”。此外,本次将使用input,在执行terraform plan后,手动批准执行terraform apply。
※此脚本仅用于演示,仅包含基本处理。

pipeline {
  agent any
  options {
    skipDefaultCheckout(true)
  }
  tools {
    terraform "terraform-1.3.4"
  }
  stages{
    stage("clean workspace") {
      steps {
        cleanWs()
      }
    }
    stage("checkout") {
      steps {
        checkout scm
      }
    }
    stage("terraform init") {
      steps {
        sh "terraform init -no-color"   
      }
    }
    stage("terraform plan") {
      steps {
        sh "terraform plan -no-color -out=plan.out"
        input message: "Apply Plan?", ok: "Apply"
      }
    }
    stage("terraform apply") {
      steps {
        sh "terraform apply plan.out -no-color"    
      }
    }
  }
}

土壤形态法的代码

这次为了演示的目的,我们将在main.tf文件中将provider、backend、以及目标资源等全部写在一起,不将tf文件分开。这次我们将使用Terraform创建VPC,并给它添加一个名为”created-by-terraform”的标签。
请指定在环境建设中创建的S3桶的名称作为backend使用的S3桶。

provider "aws" {
  region = "ap-northeast-1"
}

terraform {
  required_version = "~> 1.3.4"
  backend "s3" {
    # your own s3 bucket
    bucket = ""
    region = "ap-northeast-1"
    key    = "terraform.tfstate"
  }
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 4.0"
    }
  }
}

resource "aws_vpc" "main" {
  cidr_block           = "10.0.0.0/16"
  instance_tenancy     = "default"
  enable_dns_support   = true
  enable_dns_hostnames = true
  tags = {
    Name = "created-by-terraform"
  }
}

目录结构

将已经生成的Jenkinsfile和Terraform代码预先准备好,并将它们推送到事先准备好的Github存储库中。目录结构如下所示。

.
├── .gitignore
├── Jenkinsfile
└── main.tf

创建Jenkins任务

Screenshot 2022-11-10 at 18.46.44.png

将管道设置如下。

Screenshot 2022-11-10 at 15.02.08.png
Screenshot 2022-11-10 at 18.47.56.png

执行Jenkins任务

Screenshot 2022-11-10 at 18.48.43.png
Screenshot 2022-11-10 at 18.49.52.png

本次将在Jenkinsfile中添加input,并加入手动批准的阶段,但如果不需要手动批准,则可以删除相关部分的input。

Screenshot 2022-11-10 at 18.53.48.png

最后

这次我在Amazon EC2上搭建了一个Jenkins服务器,并尝试使用Jenkins和Terraform进行基础设施的部署。虽然只是一个简单的演示,但我希望您可以在使用Jenkins运行Terraform时参考一下。最后,别忘了删除这次构建的AWS资源!

请提供更多的上下文,这样我才能为您提供一个准确的中文翻译。

    • Installing Jenkins | jenkins.io

 

    • Pipeline | jenkins.io

 

    Providers – aws | registry.terraform.io
广告
将在 10 秒后关闭
bannerAds