在第十天的時候,
我們使用 AWS CodeDeploy 部署到 EC2,
當時只有陽春版的部署,
我們做了大費周章的設定,
但是卻無法知道是否部署成功,
即便官方有提供一些方式,
讓我們可透過 aws cli 去取得部署狀態,
不免俗的還是會覺得有點小麻煩,
後來我們將系統容器化,
容器化以後是起一個容器去執行部署,
非但沒有解決之前是否有正常部署的問題,
可能還會因為要部署到不同環境,
而要藏 Token 在 Jenkins Server,
當 Jenkins 只執行一個專案的部署或許沒問題,
但是當公司內有多個專案(十個以上),
甚至有多個環境需(五個或以上)要部署的時候,
全部仰賴 Jenkins 就不會是個好的做法,
這時候我們就需要更強而有力的工具來協助我們。
那就是 Octopus Deploy,
Octopus Deploy 不但可以整合各種不同的 CI,
在部署上也支援各種不同的環境,
接下來我們會分兩集介紹,
今天會先調整我們目前的環境,
把不重要的環境先砍掉,
再配置 Octopus Deploy 的基礎設施,
接下來才要串接 Jenkins 做自動部署。
將下列程式碼註解掉或是直接刪除
除了 EC2 以外,還需要刪除 EC2 的 Security Group、EIP、Load Balance
因為程式碼有進版控
剛剛又有 Take Sanpshot
建議是可以直接刪除就好了
stage/main.tf
# resource "aws_security_group" "ithome_ironman_portal" {
# name = "ithome-ironman-portal"
# description = "It is used for ithome ironman 2021 portal."
# vpc_id = aws_vpc.stage.id
# tags = { Name = "ithome ironman 2021" }
# revoke_rules_on_delete = null
# }
# resource "aws_security_group_rule" "ithome_ironman_igress_22" {
# type = "ingress"
# from_port = 22
# to_port = 22
# cidr_blocks = [var.personal_cidr, aws_vpc.stage.cidr_block]
# protocol = "tcp"
# security_group_id = aws_security_group.ithome_ironman_portal.id
# }
# resource "aws_security_group_rule" "ithome_ironman_egress_22" {
# type = "egress"
# from_port = 22
# to_port = 22
# cidr_blocks = [var.personal_cidr, aws_vpc.stage.cidr_block]
# protocol = "tcp"
# security_group_id = aws_security_group.ithome_ironman_portal.id
# }
# resource "aws_security_group_rule" "ithome_ironman_igress_80" {
# type = "ingress"
# from_port = 80
# to_port = 80
# cidr_blocks = ["0.0.0.0/0",]
# protocol = "tcp"
# security_group_id = aws_security_group.ithome_ironman_portal.id
# }
# resource "aws_security_group_rule" "ithome_ironman_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.ithome_ironman_portal.id
# }
# resource "aws_security_group_rule" "ithome_ironman_igress_443" {
# type = "ingress"
# from_port = 443
# to_port = 443
# cidr_blocks = ["0.0.0.0/0",]
# protocol = "tcp"
# security_group_id = aws_security_group.ithome_ironman_portal.id
# }
# resource "aws_security_group_rule" "ithome_ironman_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.ithome_ironman_portal.id
# }
# resource "aws_security_group_rule" "ithome_ironman_ingress_3128" {
# type = "ingress"
# from_port = 3128
# to_port = 3128
# cidr_blocks = ["0.0.0.0/0",]
# protocol = "tcp"
# security_group_id = aws_security_group.ithome_ironman_portal.id
# }
# resource "aws_security_group_rule" "ithome_ironman_egress_3128" {
# type = "egress"
# from_port = 3128
# to_port = 3128
# cidr_blocks = ["0.0.0.0/0",]
# protocol = "tcp"
# security_group_id = aws_security_group.ithome_ironman_portal.id
# }
# module "key_pair_ithome_ironman_portal" {
# source = "../modules/key"
# key_name = "portal"
# }
# resource "local_file" "ithome_ironman_portal" {
# content = module.key_pair_ithome_ironman_portal.private_key
# filename = format("%s.pem", module.key_pair_ithome_ironman_portal.key_name)
# }
# resource "aws_eip" "portal" {
# network_border_group = "ap-northeast-1"
# public_ipv4_pool = "amazon"
# }
# resource "aws_eip_association" "portal" {
# depends_on = [aws_eip.portal, module.ec2_ithome_ironman_portal]
# instance_id = module.ec2_ithome_ironman_portal.id
# allocation_id = aws_eip.portal.id
# }
# module "ec2_ithome_ironman_portal" {
# source = "../modules/ec2"
# name = "ithome ironman 2021 portal"
# ami = "ami-09ac3ab1b7a1e9444"
# subnet_id = sort(data.aws_subnet_ids.public_subnet_ids.ids)[0]
# key_name = module.key_pair_ithome_ironman_portal.key_name
# security_groups_id = [ aws_security_group.ithome_ironman_portal.id ]
# iam_instance_profile = aws_iam_instance_profile.ec2_profile.name
# tags = {
# Name = "ithome ironman 2021 portal"
# Usage = "portal"
# Creator = "Terraform"
# }
# }
# resource "aws_lb" "portal" {
# name = "ithome-ironman-portal"
# internal = false
# load_balancer_type = "application"
# security_groups = [ aws_security_group.ithome_ironman_portal.id ]
# subnets = data.aws_subnet_ids.public_subnet_ids.ids
# enable_deletion_protection = false
# tags = {
# Creator = "Terraform"
# }
# }
# resource "aws_lb_target_group" "portal" {
# name = "ithome-ironman-portal"
# port = 80
# protocol = "HTTP"
# target_type = "ip"
# vpc_id = aws_vpc.stage.id
# stickiness {
# type = "lb_cookie"
# }
# }
# resource "aws_lb_target_group_attachment" "portal01" {
# target_group_arn = aws_lb_target_group.portal.arn
# target_id = module.ec2_ithome_ironman_portal.private_ip
# }
# resource "aws_lb_listener" "portal_port443" {
# load_balancer_arn = aws_lb.portal.arn
# port = "443"
# protocol = "HTTPS"
# ssl_policy = "ELBSecurityPolicy-2016-08"
# certificate_arn = aws_acm_certificate.cert.arn
# default_action {
# type = "forward"
# target_group_arn = aws_lb_target_group.portal.arn
# }
# }
# resource "aws_lb_listener" "portal_port80" {
# load_balancer_arn = aws_lb.portal.arn
# port = "80"
# protocol = "HTTP"
# default_action {
# type = "redirect"
# target_group_arn = aws_lb_target_group.portal.arn
# redirect {
# port = "443"
# protocol = "HTTPS"
# status_code = "HTTP_301"
# }
# }
# }
# resource "aws_wafv2_web_acl_association" "portal" {
# resource_arn = aws_lb.portal.arn
# web_acl_arn = aws_wafv2_web_acl.fundamental_acl.arn
# }
註解或移除後
記得要執行配置
terraform apply
自己的 DNS
修改 CName Record根據官網的介紹
Octopus Deploy 是個獨立空間
讓你的團隊可以管理釋出版本、自動化部屬及自動化腳本
來維持軟體的運作
老實說也沒有一定要使用什麼軟體
你高興使用 Gitlab 就用 Gitlab
公司原本就有使用 Jenkins 就使用 Jenkins
公司有整合 AAD 和微軟的服務因此想使用 Azure DevOps 就使用 Azure DevOps
我沒有收業配的費用
我也不太想說服別人一定要用什麼
早期十個部署以下免費用
現在三十天免費用
也的確沒有特別的優勢
真的就是個人高興就好
不過這邊示範 Octopus Deploy
除了表示他是一種可能以外
我覺得最大的好處就是可以將環境分開
今天 CI 環境大部分還是 Dev 在使用
那有沒有一個環境專門給 Operating 或是 QA 使用呢?
我覺得 Octopus Deploy 就是很適合的環境
明明 Ops 和 QA 大部分的工作都與 CI 無關
那它只要知道有這環境就可以了
大部分他們需要知道的是版本釋出以及部署的部分
以這次的挑戰來說
就是除了常見的 Linux 環境以外
還可以秀出 Windows 環境
你沒聽錯,因為 Octopus 只支援 Windows
所以必須要開一個 Windows Server 的環境
而且也需要配置 SQL Server
價格上又比一般的機械花更多錢
stage/main.tf
data "aws_ami" "windows" {
most_recent = true
filter {
name = "name"
values = ["Windows_Server-2019-English-Full-Base-*"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
owners = ["801119661308"] # Canonical
}
stage/main.tf
這裡需要注意的是 windows server 的 硬碟不能配置太小
resource "aws_security_group" "octopus_deploy" {
name = "octopus-deploy"
description = "It is used for octopus_deploy."
vpc_id = aws_vpc.stage.id
tags = { Name = "octopus deploy" }
revoke_rules_on_delete = null
}
resource "aws_security_group_rule" "ithome_ironman_igress_80" {
type = "ingress"
from_port = 80
to_port = 80
cidr_blocks = [var.personal_cidr, aws_vpc.stage.cidr_block]
protocol = "tcp"
security_group_id = aws_security_group.octopus_deploy.id
}
resource "aws_security_group_rule" "ithome_ironman_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.octopus_deploy.id
}
resource "aws_security_group_rule" "ithome_ironman_igress_443" {
type = "ingress"
from_port = 443
to_port = 443
cidr_blocks = [var.personal_cidr, aws_vpc.stage.cidr_block]
protocol = "tcp"
security_group_id = aws_security_group.octopus_deploy.id
}
resource "aws_security_group_rule" "ithome_ironman_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.octopus_deploy.id
}
resource "aws_security_group_rule" "ithome_ironman_igress_1433" {
type = "ingress"
from_port = 1433
to_port = 1433
cidr_blocks = [aws_vpc.stage.cidr_block]
protocol = "tcp"
security_group_id = aws_security_group.octopus_deploy.id
}
resource "aws_security_group_rule" "ithome_ironman_egress_1433" {
type = "egress"
from_port = 1433
to_port = 1433
cidr_blocks = [aws_vpc.stage.cidr_block]
protocol = "tcp"
security_group_id = aws_security_group.octopus_deploy.id
}
resource "aws_security_group_rule" "ithome_ironman_igress_3389" {
type = "ingress"
from_port = 3389
to_port = 3389
cidr_blocks = [var.personal_cidr, aws_vpc.stage.cidr_block]
protocol = "tcp"
security_group_id = aws_security_group.octopus_deploy.id
}
resource "aws_security_group_rule" "ithome_ironman_egress_3389" {
type = "egress"
from_port = 3389
to_port = 3389
cidr_blocks = [var.personal_cidr, aws_vpc.stage.cidr_block]
protocol = "tcp"
security_group_id = aws_security_group.octopus_deploy.id
}
module "key_pair_octopus_deploy" {
source = "../modules/key"
key_name = "octopus-deploy"
}
resource "local_file" "octopus_deploy" {
content = module.key_pair_octopus_deploy.private_key
filename = format("%s.pem", module.key_pair_octopus_deploy.key_name)
}
resource "aws_eip" "octopus_deploy" {
network_border_group = "ap-northeast-1"
public_ipv4_pool = "amazon"
}
resource "aws_eip_association" "octopus_deploy" {
depends_on = [aws_eip.octopus_deploy, module.ec2_octopus_deploy]
instance_id = module.ec2_octopus_deploy.id
allocation_id = aws_eip.octopus_deploy.id
}
module "ec2_octopus_deploy" {
source = "../modules/ec2"
name = "octopus deploy"
ami = data.aws_ami.windows.id
subnet_id = sort(data.aws_subnet_ids.public_subnet_ids.ids)[0]
key_name = module.key_pair_octopus_deploy.key_name
security_groups_id = [ aws_security_group.octopus_deploy.id ]
iam_instance_profile = aws_iam_instance_profile.ec2_profile.name
tags = {
Name = "octopus deploy"
Usage = "continue deploy"
Creator = "Terraform"
}
}
stage/main.tf
resource "aws_lb" "octopus_deploy" {
name = "octopus-deploy"
internal = false
load_balancer_type = "application"
security_groups = [aws_security_group.octopus_deploy.id]
subnets = data.aws_subnet_ids.public_subnet_ids.ids
enable_deletion_protection = false
tags = {
Environment = "staging"
}
}
resource "aws_lb_target_group" "octopus_deploy" {
name = "octopus-deploy"
port = 80
protocol = "HTTP"
target_type = "ip"
vpc_id = aws_vpc.stage.id
stickiness {
type = "lb_cookie"
}
}
resource "aws_lb_target_group_attachment" "octopus_deploy" {
target_group_arn = aws_lb_target_group.octopus_deploy.arn
target_id = module.ec2_octopus_deploy.private_ip
}
resource "aws_lb_listener" "octopus_deploy_port443" {
load_balancer_arn = aws_lb.octopus_deploy.arn
port = "443"
protocol = "HTTPS"
ssl_policy = "ELBSecurityPolicy-2016-08"
certificate_arn = aws_acm_certificate.cert.arn
default_action {
type = "forward"
target_group_arn = aws_lb_target_group.octopus_deploy.arn
}
}
resource "aws_lb_listener" "octopus_deploy_port80" {
load_balancer_arn = aws_lb.octopus_deploy.arn
port = "80"
protocol = "HTTP"
default_action {
type = "redirect"
target_group_arn = aws_lb_target_group.octopus_deploy.arn
redirect {
port = "443"
protocol = "HTTPS"
status_code = "HTTP_301"
}
}
}
今天我們用一點不同的方式
用 aws 的 secret manager 來存放帳號和密碼
resource "aws_security_group" "rds_octopus_deploy" {
name = "rds-octopus-deploy"
description = "It used for RDS."
vpc_id = aws_vpc.stage.id
tags = { Name = "RDS SQL Server" }
revoke_rules_on_delete = null
}
resource "aws_security_group_rule" "rds_octopus_deploy_igress_1433" {
type = "ingress"
from_port = 1433
to_port = 1433
cidr_blocks = ["0.0.0.0/0",]
protocol = "tcp"
security_group_id = aws_security_group.rds_octopus_deploy.id
}
resource "aws_security_group_rule" "rds_octopus_deploy_egress_1433" {
type = "egress"
from_port = 1433
to_port = 1433
cidr_blocks = ["0.0.0.0/0",]
protocol = "tcp"
security_group_id = aws_security_group.rds_octopus_deploy.id
}
resource "aws_db_parameter_group" "mssql_ex_15_parameter_group" {
name = "sqlserver-ex-15-parameter-group"
family = "sqlserver-ex-15.0"
description = "sqlserver-ex-15-parameter-group"
}
resource "aws_db_instance" "octopus_deploy" {
depends_on = [aws_db_parameter_group.mssql_ex_15_parameter_group]
identifier = "mssql-octopus-deploy-instance"
max_allocated_storage = 100
allocated_storage = 30
engine = "sqlserver-ex"
engine_version = "15.00.4073.23.v1"
instance_class = "db.t3.small"
username = "admin"
password = random_password.octopus_deploy_password.result
parameter_group_name = aws_db_parameter_group.mssql_ex_15_parameter_group.name
timezone = "Taipei Standard Time"
skip_final_snapshot = true
db_subnet_group_name = aws_db_subnet_group.rds_subnet_group.name
vpc_security_group_ids = [aws_security_group.rds_octopus_deploy.id]
}
resource "random_password" "octopus_deploy_password" {
length = 16
special = false
}
resource "aws_secretsmanager_secret" "octopus_deploy_credentials" {
name = "octopus-deploy-credentials"
}
resource "aws_secretsmanager_secret_version" "octopus_deploy_credentials" {
secret_id = aws_secretsmanager_secret.octopus_deploy_credentials.id
secret_string = <<EOF
{
"username": "${aws_db_instance.octopus_deploy.username}",
"password": "${random_password.octopus_deploy_password.result}",
"engine": "${aws_db_instance.octopus_deploy.engine}",
"host": "${aws_db_instance.octopus_deploy.endpoint}",
"port": ${aws_db_instance.octopus_deploy.port},
}
EOF
}
因為我們有使用到 random_password
這不是原本存在的模組
而且也有另外撰寫的 EC2 模組
因此需要先安裝模組
terraform init
EC2 建置需要一點時間
資料庫建置需要大概十多分鐘
大家可能要有點耐心
或是去上完廁所再回來
terraform apply
首先我們先進官網,點按右上角的 Start a Trial
然後選擇 Server
接著填寫資料
然後就準備去信箱收確認信啦
選擇 New Trail License
輸入公司名稱
複製 License Code
待續...
參考資料: