前幾天我們使用 terraform 配置好 gitlab 環境,
會單純使用 gitlab 來管理程式碼,
而另外建 Jenkins 來處理 CI,
是因為大家使用的 Source Code Management (SCM) 可能不同,
早期可能使用 SVN,
後來可能是自建 Git Server、Github 或是 Gitlab,
會各別拆開,
只是表示 CI/CD 有各種可能,
如果 SCM 不是大家目前使用的,
只需單純將 gitlab 替換成自己使用的即可,
再加上 gitlab 免費版跑 CI/CD 有限制(以月計算),
因此如果不願意付錢購買 License,
但是又無法預估 CI/CD 執行時間,
建立 Jenkins 仍是個理想的選擇。
昨天我們配置 inbound/outbound 的時候
是使用白名單的方式
配置完我們發現自己的 IP 已經在多處重複使用到
此時會建議重構建立 gitlab 配置的這段程式碼
variables.tf
variable "personal_cidr" {
description = "the default vpc id when inital the aws"
default = "你的IP/32"
}
main.tf
將 inbound/outbound 的 CIDR blocks 替換成 var.personal_cidr
resource "aws_security_group_rule" "gitlab_igress_22" {
type = "ingress"
from_port = 22
to_port = 22
cidr_blocks = [var.personal_cidr,]
protocol = "tcp"
security_group_id = aws_security_group.gitlab.id
}
resource "aws_security_group_rule" "gitlab_egress_22" {
type = "egress"
from_port = 22
to_port = 22
cidr_blocks = [var.personal_cidr,]
protocol = "tcp"
security_group_id = aws_security_group.gitlab.id
}
resource "aws_security_group_rule" "gitlab_igress_80" {
type = "ingress"
from_port = 80
to_port = 80
cidr_blocks = [var.personal_cidr,]
protocol = "tcp"
security_group_id = aws_security_group.gitlab.id
}
resource "aws_security_group_rule" "gitlab_egress_80" {
type = "egress"
from_port = 80
to_port = 80
cidr_blocks = ["0.0.0.0/0",]
protocol = "tcp"
security_group_id = aws_security_group.gitlab.id
}
resource "aws_security_group_rule" "gitlab_igress_443" {
type = "ingress"
from_port = 443
to_port = 443
cidr_blocks = [var.personal_cidr,]
protocol = "tcp"
security_group_id = aws_security_group.gitlab.id
}
resource "aws_security_group_rule" "gitlab_egress_443" {
type = "egress"
from_port = 443
to_port = 443
cidr_blocks = ["0.0.0.0/0",]
protocol = "tcp"
security_group_id = aws_security_group.gitlab.id
}
回到 console 中輸入
terraform apply
理論上不會有什麼變動
或是 pem key 重新產生而已
有了昨天 gitlab 配置的訓練
我們知道我們會建立一台 EC2
會有個 Security Group 以及 Security Group Rule
以及綁定 SSH Key 到 EC2 上
這邊我們就一次全部撰寫
不再分段介紹
與 gitlab 不同的是
Jenkins 因為是 Java 的服務
所以有多設置 8080 port
沒用到的 80 port 目前暫不移除
使用的經驗上 EC2 的規格可先配置 t3.medium
如果未來不敷使用
再往上升即可
resource "aws_security_group" "jenkins" {
name = "jenkins-server"
description = "It used for Jenkins server."
vpc_id = data.aws_vpc.default.id
tags = { Name = "Jenkins-Server" }
revoke_rules_on_delete = null
}
resource "aws_security_group_rule" "jenkins_igress_22" {
type = "ingress"
from_port = 22
to_port = 22
cidr_blocks = [var.personal_cidr,]
protocol = "tcp"
security_group_id = aws_security_group.jenkins.id
}
resource "aws_security_group_rule" "jenkins_egress_22" {
type = "egress"
from_port = 22
to_port = 22
cidr_blocks = [var.personal_cidr,]
protocol = "tcp"
security_group_id = aws_security_group.jenkins.id
}
resource "aws_security_group_rule" "jenkins_igress_80" {
type = "ingress"
from_port = 80
to_port = 80
cidr_blocks = [var.personal_cidr,]
protocol = "tcp"
security_group_id = aws_security_group.jenkins.id
}
resource "aws_security_group_rule" "jenkins_egress_80" {
type = "egress"
from_port = 80
to_port = 80
cidr_blocks = ["0.0.0.0/0",]
protocol = "tcp"
security_group_id = aws_security_group.jenkins.id
}
resource "aws_security_group_rule" "jenkins_igress_443" {
type = "ingress"
from_port = 443
to_port = 443
cidr_blocks = [var.personal_cidr,]
protocol = "tcp"
security_group_id = aws_security_group.jenkins.id
}
resource "aws_security_group_rule" "jenkins_egress_443" {
type = "egress"
from_port = 443
to_port = 443
cidr_blocks = ["0.0.0.0/0",]
protocol = "tcp"
security_group_id = aws_security_group.jenkins.id
}
resource "aws_security_group_rule" "jenkins_igress_8080" {
type = "ingress"
from_port = 8080
to_port = 8080
cidr_blocks = [var.personal_cidr,]
protocol = "tcp"
security_group_id = aws_security_group.jenkins.id
}
resource "aws_security_group_rule" "jenkins_egress_8080" {
type = "egress"
from_port = 8080
to_port = 8080
cidr_blocks = [var.personal_cidr,]
protocol = "tcp"
security_group_id = aws_security_group.jenkins.id
}
resource "tls_private_key" "jenkins" {
algorithm = "RSA"
rsa_bits = 4096
}
resource "aws_key_pair" "jenkins" {
key_name = "jenkins"
public_key = tls_private_key.jenkins.public_key_openssh
}
resource "local_file" "jenkins" {
content = tls_private_key.jenkins.private_key_pem
filename = format("%s.pem", aws_key_pair.jenkins.key_name)
}
resource "aws_instance" "jenkins" {
ami = data.aws_ami.ubuntu.id
instance_type = "t3.medium"
subnet_id = sort(data.aws_subnet_ids.subnet_ids.ids)[0]
key_name = aws_key_pair.jenkins.key_name
vpc_security_group_ids = [ aws_security_group.jenkins.id ]
disable_api_termination = false
ebs_optimized = true
hibernation = false
tags = {
Name = "Jenkins Server"
Usage = "CI Tools"
Creator = "Terraform"
}
root_block_device {
delete_on_termination = true
encrypted = false
throughput = 0
volume_size = 30
volume_type = "gp2"
tags = {
Name = "Jenkins Server"
Attached = "Jenkins Server"
}
}
}
建立完成後
我們可以透過 aws 的 console 看到之前建立 gitlab server
以及剛剛建立好的 jenkins server
同昨天的教學
要變更讀寫權限
sudo chmod 400 jenkins.pem
ssh -i "jenkins.pem" ubuntu@你的主機
sudo apt-get update
sudo apt-get upgrade -y
因為 Jenkins 是由 Java 編寫的開源持續整合工具
因此在安裝 Jenkins 之前需要安裝 Java
Java 版本的選擇選擇 Java 11
會選擇 Java 11 的原因是因為 LTS
而 Java 17 又太新
不過如果沒有要在 Jenkins Server 做其他的操作
其實版本應該是不需要太在意(?)
sudo apt-get install openjdk-11-jdk
在安裝時我喜歡安裝最新版本
尤其許多套件可能也會跟著 Jenkins 版本再走
因此下方是安裝最新版本的 Jenkins 而不是穩定版本
如果想要安裝穩定版本的
可以參考 Digital Ocean 的這篇文章
sudo wget -q -O - https://pkg.jenkins.io/debian/jenkins.io.key | sudo apt-key add -
sudo sh -c 'echo deb http://pkg.jenkins.io/debian binary/ > /etc/apt/sources.list.d/jenkins.list'
添加完後
記得要先 update 更新清單
sudo apt update
更新完後
可以看到列表中出現 jenkins
sudo apt install jenkins
sudo systemctl start jenkins
啟動後可以輸入以下指令
確定 jenkins 啟動狀況
sudo systemctl status jenkins
目前已經有使用 security group 去管 inbound/outbound
因此就不會開啟 ubunut 內建的 firewall
在瀏覽器中輸入下列網址
http:// your_server_ip_or_domain :8080
就可以開始設定 jenkins 了
有看到畫面
表示 Jenkins 服務有正常啟動
輸入指令取得密碼後貼上以繼續設定
sudo cat /var/lib/jenkins/secrets/initialAdminPassword
選擇建議的擴充套件後
接下來就是等待安裝的過程
此步驟可於日後更改
如果網址設定不正確
則會一直跳出警示
儲存後就結束整個安裝的過程
也會自動跳轉到主頁面
這兩天我們用 terraform 建立好兩台 EC2
此時也許會開始有兩個人進行協作
但也如同前幾天說的 tfstate 是重要的檔案
它記錄全部配置的狀態
但是同時可能也包含機密資訊
因此不適合放在 git 做管理
常見的作法則是將這檔案放到 S3 做管理
創建 S3 bucket 時要注意
bucket 的名稱必須是全世界獨一無二的
因此儘量避免菜市場命名
resource "aws_s3_bucket" "tfstate" {
bucket = "ithome-ironman-markmew-tfstate"
acl = "private"
tags = {
Name = "My bucket"
Creator = "Terraform"
}
versioning {
enabled = true
}
}
最初我們做了一個設置
表示我們 terraform 撰寫時
使用的套件來源和版本
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~>3.0"
}
}
}
程式碼需添加 backend
來告知我們 tfstate 要放在哪個位置
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~>3.0"
}
}
backend "s3" {
bucket = "ithome-ironman-markmew-tfstate"
key = "ithome-ironman.tfstate"
region = "ap-northeast-1"
}
}
配置完後
需要初始化配置
terraform init
配置完後
在 aws 的 s3 就可以看到我們的tfstate檔案已經建立好了
但是還沒結束
我們的 tfstate 移動到 s3
同樣的我們也必須設定 tfstate 要從 s3 抓取
在 main.tf 中增加
data "terraform_remote_state" "tfstate" {
backend = "s3"
config = {
bucket = "ithome-ironman-markmew-tfstate"
key = "ithome-ironman.tfstate"
region = "ap-northeast-1"
}
}
新增完後再 apply 一次
terraform apply
正常狀況應該會是沒有任何變更
git add stage/main.tf
git add stage/variables.tf
git commit -m "1. add jenkins server\n 2. refactor white list settings\n 3. migrate tfstate to s3"
git push
回顧一下我們今天做的
我們使用 terraform 建立第二個 EC2
白名單的設定上
用簡單的方式重構程式碼
讓我們不需要重複輸入自己 IP
並且為了能夠多人協作
也將 tfstate 檔案放到 s3 上
最後也別忘了程式碼要記得 push
參考資料: