ci 진행하기 위한 github와 연동이 필요
circle ci 환경변수
docker pw는 Access Token으로 대체
docker access token
repo .circleci 의 config.yml
version: 2
jobs:
build:
# Variable expansion in working_directory not supported at this time
# You will need to modify the code below to reflect your github account/repo setup
working_directory: /go/src/github.com/dotlike13/invoicer-chapter2
docker:
- image: circleci/golang:1.10
steps:
- checkout
- setup_remote_docker
- run:
name: Setup environment
command: |
gb="/src/github.com/${CIRCLE_PROJECT_USERNAME}";
if [ ${CIRCLE_PROJECT_USERNAME} == 'Securing-DevOps' ]; then
dr="securingdevops"
else
dr=$DOCKER_USER
fi
cat >> $BASH_ENV << EOF
export GOPATH_HEAD="$(echo ${GOPATH}|cut -d ':' -f 1)"
export GOPATH_BASE="$(echo ${GOPATH}|cut -d ':' -f 1)${gb}"
export DOCKER_REPO="$dr"
EOF
- run: mkdir -p "${GOPATH_BASE}"
- run: mkdir -p "${GOPATH_HEAD}/bin"
- run:
name: Testing application
command: |
go test \
github.com/${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}
- deploy:
command: |
if [ "${CIRCLE_BRANCH}" == "master" ]; then
docker login -u ${DOCKER_USER} -p ${DOCKER_PASS};
go install --ldflags '-extldflags "-static"' \
github.com/${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME};
mkdir bin;
cp "$GOPATH_HEAD/bin/${CIRCLE_PROJECT_REPONAME}" bin/invoicer;
docker build -t ${DOCKER_REPO}/${CIRCLE_PROJECT_REPONAME} .;
docker images --no-trunc | awk '/^app/ {print $3}' | \
sudo tee $CIRCLE_ARTIFACTS/docker-image-shasum256.txt;
docker push ${DOCKER_REPO}/${CIRCLE_PROJECT_REPONAME};
fi
책에서는 aws-cli로 생성하지만 테라폼 연습겸할겸 작성해봄
vpc, ec2, db등 구성은 3tier 실습 참고
module "db" {
source = "terraform-aws-modules/rds/aws"
identifier = "invoicer-db"
engine = "postgres"
engine_version = "14.3"
family = "postgres14" # DB parameter group
major_engine_version = "14" # DB option group
instance_class = "db.t4g.large"
allocated_storage = 5
db_name = "invoicer"
username = "invoicer"
password = "invoicerpassword"
port = "13306"
multi_az = false
db_subnet_group_name = module.vpc.database_subnet_group
vpc_security_group_ids = [module.rds_security_group.security_group_id]
maintenance_window = "Mon:00:00-Mon:03:00"
backup_window = "03:00-06:00"
enabled_cloudwatch_logs_exports = ["postgresql", "upgrade"]
create_cloudwatch_log_group = true
backup_retention_period = 1
skip_final_snapshot = true
deletion_protection = false
performance_insights_enabled = true
performance_insights_retention_period = 7
create_monitoring_role = true
monitoring_interval = 60
monitoring_role_name = "example-monitoring-role-name"
monitoring_role_use_name_prefix = true
monitoring_role_description = "Description for monitoring role"
parameters = [
{
name = "autovacuum"
value = 1
},
{
name = "client_encoding"
value = "utf8"
}
]
db_option_group_tags = {
"Sensitive" = "low"
}
db_parameter_group_tags = {
"Sensitive" = "low"
}
}
module "rds_security_group" {
source = "terraform-aws-modules/security-group/aws"
version = "4.13.0"
name = "invoicer_db"
description = "invoicer db security group"
vpc_id = module.vpc.vpc_id
ingress_with_cidr_blocks = [
{
from_port = 13306
to_port = 13306
protocol = "tcp"
description = "invoicer db inbound"
cidr_blocks = "0.0.0.0/0"
},
{
cidr_blocks = "0.0.0.0/0"
description = "ICMP"
from_port = -1
protocol = "icmp"
to_port = -1
}
]
}
resource "aws_elastic_beanstalk_application" "invoicer" {
name = "invoicer"
description = "Securing DevOps Inovicer application"
appversion_lifecycle {
service_role = aws_iam_role.beanstalk_role.arn
max_count = 128
delete_source_from_s3 = true
}
}
data "aws_elastic_beanstalk_solution_stack" "docker" {
most_recent = true
name_regex = "^64bit Amazon Linux .* running Docker$"
}
resource "aws_elastic_beanstalk_application_version" "invoicer" {
name = "invoicer-version"
application = "invoicer"
bucket = aws_s3_bucket.this.id
key = aws_s3_object.this.id
depends_on = [aws_elastic_beanstalk_application.invoicer]
}
resource "aws_elastic_beanstalk_environment" "eb" {
name = "invoicer-api"
description = "invoicer APP"
application = aws_elastic_beanstalk_application.invoicer.name
solution_stack_name = data.aws_elastic_beanstalk_solution_stack.docker.name
tier = "WebServer"
version_label = "invoicer-version"
setting {
namespace = "aws:elasticbeanstalk:application:environment"
name = "INVOICER_POSTGRES_USER"
value = "invoicer"
}
setting {
namespace = "aws:elasticbeanstalk:application:environment"
name = "INVOICER_POSTGRES_PASSWORD"
value = "invoicerpassword"
}
setting {
namespace = "aws:elasticbeanstalk:application:environment"
name = "INVOICER_POSTGRES_DB"
value = "invoicer"
}
setting {
namespace = "aws:elasticbeanstalk:application:environment"
name = "INVOICER_POSTGRES_HOST"
value = "invoicer-db.cqumm9p8ksgp.ap-northeast-2.rds.amazonaws.com"
}
setting {
namespace = "aws:autoscaling:launchconfiguration"
name = "IamInstanceProfile"
value = "invoicer-eb-glen-profile"
}
}
resource "aws_iam_instance_profile" "this" {
name = "invoicer-eb-glen-profile"
role = aws_iam_role.beanstalk_role.name
}
resource "aws_iam_role" "beanstalk_role" {
name = "beanstalk_role"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = "sts:AssumeRole"
Effect = "Allow"
Principal = {
Service = "ec2.amazonaws.com"
}
},
]
})
}
resource "aws_iam_role_policy_attachment" "beansservice" {
role = aws_iam_role.beanstalk_role.name
policy_arn = "arn:aws:iam::aws:policy/service-role/AWSElasticBeanstalkService"
}
resource "aws_s3_bucket" "this" {
bucket = "glen-invoicer"
}
resource "aws_s3_object" "this" {
depends_on = [aws_s3_bucket.this]
bucket = "glen-invoicer"
key = "glen-invoicer/app-version.json"
source = "app-version.json"
}
resource "aws_s3_bucket_policy" "this" {
bucket = aws_s3_bucket.this.id
policy = data.aws_iam_policy_document.this.json
}
resource "aws_iam_policy" "full" {
name = format("%s-s3-full-access-policy", aws_s3_bucket.this.id)
path = "/"
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = [
"s3:*",
]
Effect = "Allow"
Resource = [
format("arn:aws:s3:::%s", aws_s3_bucket.this.id),
format("arn:aws:s3:::%s/*", aws_s3_bucket.this.id),
]
},
]
})
}