一 背景
自动化代码部署以确保应用程序正常运行时间
Amazon CodeDeploy 是一项完全托管的部署服务,可自动将软件部署到计算服务,例如 Amazon EC2、Amazon Lambda 以及您的本地服务器。借助 Amazon CodeDeploy,您可以更轻松地快速发布新功能、避免在应用程序部署过程中出现停机,并简化应用程序的更新工作。
二 概述
AWS CodeDeploy旨在帮助用户完成应用的快速部署,按照用户指定的策略将代码部署在一组EC2服务器上。用户策略可以包括集群部署速度、部署事件通知、警报处理策略等。此外,CodeDeploy还可以和弹性负载均衡(Elastic Load Balancer)、自动扩展组(Auto Scaling Group)等服务结合,完成无缝升级和动态部署。
三 相关概念
为方便有效地组织部署任务,CodeDeploy设立了三个概念:应用(Application)、部署(Deployment),以及部署配置(Deployment Configuration)。
3.1 应用程序(Application)
应用程序是部署的核心,由部署组(Deployment Group)和代码修订(Revisions)组成。一个应用可以包含多个部署组,一个部署组又可以包含多台EC2服务器。同时,一个服务器也可以属于多个部署组,因为一个服务器可能同时运行多个应用。
3.1.1 部署组
创建或修改部署组时,如果添加EC2服务器,可以通过标签(Tag)对已有的EC2服务器进行筛选。所以,在创建EC2时一定要打上标签(Tag),便于在创建应用的部署组时找到对应业务的服务器。
此外,部署组还可以添加自动扩展组(Auto Scaling Group),以及用户自己机房的主机(On-Premise Instance)。
3.1.2 代码修订
代码修订保存了当前应用涉及到得所有代码,代码的存放位置可以在S3或Github。
如果用户自建代码托管,当需要部署时,可以在工作机上同步代码到本地,然后使用AWS命令行进行打包上传。
上面的命令可以将运行目录下得代码打包上传到S3,同时显示在关联应用的代码修订一栏中。
3.2 部署(Deployment)
每一次部署都有唯一的ID标记,并保存所有信息,如代码来源、部署时间、目标服务器、部署结果等。并且针对每一台服务器,都可以详细查看部署过程中的事件(如下载程序、安装前检查、 程序启动、安装后检查等7个事件),以便追踪部署的各个步骤。当部署出错时,可以快速定位和排查。
3.3 部署配置
部署配置存放了一次部署的服务器台数或百分比,在发起部署时需要指定所需配置。CodeDeploy默认提供了三种配置:一次部署一台、一次部署一半数量的服务器,以及一次完成全部部署。部署发起后,CodeDeploy会按照上述策略进行工作,指导完成部署组内全部服务器的更新。
四 实现流程
4.1 架构图
4.2 实现流程
- 创建应用程序,标识部署应用程序版本及计算平台。
- 指定部署类型配置部署组,可以指定应用于实例的标签、Amazon EC2 Auto Scaling组名,需在实例中安装并正常运行CodeDeploy。
- 指定部署配置,指定您的应用程序需同时部署多少实例,及部署成功和失败条件。
- 应用程序需通过CodeBuild或其他方式提前上传至Amazon S3或Github,应用程序需保护部署期间用到的脚本,还需要包含应用程序AppSpec文件。
- 将应用程序修订部署到部署组。
- 检查部署结果。
五 实战
5.1 手动创建AWS资源组
资源组 LB,EC2资源组
- 创建VPC
利用terraform对VPC进行编排
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.62"
}
}
}
provider "aws" {
region = "cn-north-1"
}
locals {
xuel_tag = {
application = "xuel_app_test"
environment = "dev"
purpose = "person test"
contact = "xuel@anchnet.com"
creator = "xuelei"
role = "cloud manager"
owner = "xuel"
project = "aws_partner_project"
team = "smartops"
organization = "mse"
company = "anchnet"
}
}
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
instance_tenancy = "default"
tags = local.xuel_tag
}
variable "public_subnet_cidrs" {
type = list(string)
description = "Public Subnet CIDR values"
default = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"]
}
variable "private_subnet_cidrs" {
type = list(string)
description = "Private Subnet CIDR values"
default = ["10.0.4.0/24", "10.0.5.0/24", "10.0.6.0/24"]
}
variable "azs" {
type = list(string)
description = "Availability Zones"
default = ["cn-north-1a", "cn-north-1b", "cn-north-1d"]
}
resource "aws_subnet" "public_subnets" {
count = length(var.public_subnet_cidrs)
vpc_id = aws_vpc.main.id
cidr_block = element(var.public_subnet_cidrs, count.index)
availability_zone = element(var.azs, count.index)
tags = local.xuel_tag
}
resource "aws_subnet" "private_subnets" {
count = length(var.private_subnet_cidrs)
vpc_id = aws_vpc.main.id
cidr_block = element(var.private_subnet_cidrs, count.index)
availability_zone = element(var.azs, count.index)
tags = local.xuel_tag
}
resource "aws_internet_gateway" "gw" {
vpc_id = aws_vpc.main.id
tags = local.xuel_tag
}
resource "aws_route_table" "second_rt" {
vpc_id = aws_vpc.main.id
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.gw.id
}
tags = local.xuel_tag
}
resource "aws_route_table_association" "public_subnet_asso" {
count = length(var.public_subnet_cidrs)
subnet_id = element(aws_subnet.public_subnets[*].id, count.index)
route_table_id = aws_route_table.second_rt.id
}
- 创建EC2并配置
- 创建EC2实例,由于需要安装codedeployAgent,选择EC2实例为公有子网,为其分配公网IP
由于后期EC2实例需要从S3中获取build好的部署文件,需要附加一个具备S3读权限的IAM用户。
创建或修改部署组时,如果添加EC2服务器,可以通过标签(Tag)对已有的EC2服务器进行筛选。所以,在创建EC2时一定要打上标签(Tag),便于在创建应用的部署组时找到对应业务的服务器。
- 为EC2实例安装codedeployAgent
仅当您部署到 EC2/本地计算平台时,才需要CodeDeploy代理。使用亚马逊 ECS 或 AWS Lambda 计算平台的部署不需要代理。CodeDeploy代理通过端口443使用HTTPS进行出站通信,因此需要安全组放开对应端口。其次需要选择CodeDeploy支持的EC2镜像。
CodeDeploy详细介绍:docs.aws.amazon.com/zh_cn/coded…
安装CodeDeploy:docs.aws.amazon.com/zh_cn/coded…
sudo yum update
sudo yum install ruby -y
sudo yum install wget -y
#!/bin/bash
CODEDEPLOY_BIN="/opt/codedeploy-agent/bin/codedeploy-agent"
$CODEDEPLOY_BIN stop
yum erase codedeploy-agent -y
cd /home/ec2-user
wget https://aws-codedeploy-us-east-2.s3.us-east-2.amazonaws.com/latest/install
chmod +x ./install
sudo ./install auto
由于后期部署应用的端口为API服务8000,所以EC2安全组需要放开8000端口
5.2 创建目标群组
目标群组为负载均衡组,主要为CodeDeploy部署的后端组,
创建目标组,检查为8000端口,确保主机存活
注册主机
如果目标组未关联LB则为unused
创建LB并关联
创建NLB
关联LB后,查看目标组为正常
至此,后端组创建完成。
5.3 创建CodeDeploy
5.3.1 创建应用程序
5.3.2 配置源信息
源程序需要除了包含构建好的可执行文件外,还需要应用程序的生命周期脚本函数,其次需要AppSpec文件描述应用程序信息,最终将源应用程序上传至对象存储S3中,以供后续CodeDeploy使用。
main文件为构建好的Golang 二进制可执行程序,以.sh结尾的为应用程序的生命周期函数,用于在EC2实例上进行部署。
appspec.yml为描述应用程序的配置文件,在此将源文件移动到/opt/golang-api/目录下,之后执行一系列hooks脚本,实现应用程序生命周期管理。
version: 0.0
os: linux
files:
- source: /
destination: /opt/golang-api/
hooks:
ApplicationStart:
- location: deploy.sh
timeout: 10
ValidateService:
- location: validate.sh
timeout: 10
ApplicationStop:
- location: stop.sh
timeout: 10
将文件打包后上传至对象存储。
tar -zcvf mainv4.tar.gz build/
复制应用程序的S3 URL供后期使用。
5.3.3 创建部署组
在应用程序内创建部署组
需要创建输入具有授权 Amazon CodeDeploy 访问您的目标实例的 CodeDeploy 权限的服务角色。
需要后期访问ec2资源,授权ec2访问权限
创建部署组
在此指定了目标主机需要添加tag,app=xuel-codedeploy
为EC2主机打上标签
创建部署,选取刚才创建的部署组,选取修订位置,改文件为之前build好的golang api,内部包含服务安装appsec.yaml
查看部署日志
登录EC2主机查看进程,查看进程已经正常运行
六 测试
通过postman进行测试,获取LB地址,在代码中发送GET请求,返回API 版本,发送POST请求并传递json请求题,返回json请求体
发送GET请求
发送POST请求
至此就已成功利用CodeDeploy部署实现golang API部署。
七 注意事项
- 本实践中,在之前codebuild进行了构建,将公上传至S3中,仅在codedeploy中进行部署,也可以在codedeploy中进行构建然后再继续执行部署。
八 反思
- 目前使用就地部署,未使用蓝绿部署;
- 为使用CodeBuild构建出制品;
- 容器部署;
- 利用CodePipeline将CodeBuild和CodeDeploy联和起来。