From f09b25641fdc70b01e087c4b498edd55457f9797 Mon Sep 17 00:00:00 2001 From: fixpoint-hasan Date: Tue, 8 Apr 2025 22:04:51 +0900 Subject: [PATCH 1/3] Add Ecs fargate deployment template --- ke2/cloud/awsecs/.gitignore | 1 + ke2/cloud/awsecs/deployment.json | 748 +++++++++++++++++++++++++++++++ ke2/cloud/awsecs/parameters.json | 15 + 3 files changed, 764 insertions(+) create mode 100644 ke2/cloud/awsecs/.gitignore create mode 100644 ke2/cloud/awsecs/deployment.json create mode 100644 ke2/cloud/awsecs/parameters.json diff --git a/ke2/cloud/awsecs/.gitignore b/ke2/cloud/awsecs/.gitignore new file mode 100644 index 0000000..cfaad76 --- /dev/null +++ b/ke2/cloud/awsecs/.gitignore @@ -0,0 +1 @@ +*.pem diff --git a/ke2/cloud/awsecs/deployment.json b/ke2/cloud/awsecs/deployment.json new file mode 100644 index 0000000..cb0572c --- /dev/null +++ b/ke2/cloud/awsecs/deployment.json @@ -0,0 +1,748 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Description": "Template to deploy KE2 (External DB configuration) containers using ECS Fargate", + "Parameters": { + "UseCustomVpc": { + "Description": "Set to true to use an existing VPC.", + "Type": "String", + "AllowedValues": ["true", "false"], + "Default": "false" + }, + "CustomVpcId": { + "Description": "The ID of the existing VPC to deploy into. (Required if UseCustomVpc is true)", + "Type": "String", + "Default": "" + }, + "CustomPublicSubnetId": { + "Description": "The ID of the existing public subnet in the custom VPC. (Required if UseCustomVpc is true)", + "Type": "String", + "Default": "" + }, + "VpcCIDR": { + "Description": "CIDR block for the VPC (if not using custom VPC).", + "Type": "String", + "Default": "10.0.0.0/16" + }, + "PublicSubnetCIDR": { + "Description": "CIDR block for the public subnet (if not using custom VPC).", + "Type": "String", + "Default": "10.0.1.0/24" + }, + "UseECSService": { + "Description": "If true, the ECS Service will handle the deployment process. If false, you will handle containers deployment task manually.", + "Type": "String", + "AllowedValues": ["true", "false"], + "Default": "true" + }, + "ImageTag": { + "Description": "KE2 image tag", + "Type": "String", + "Default": "latest" + }, + "EFSFileSystemId": { + "Description": "EFS file system ID.", + "Type": "String" + }, + "DatabaseURL": { + "Description": "Database URL.", + "Type": "String" + }, + "TimeZone": { + "Description": "Application timezone", + "Type": "String", + "Default": "Asia/Tokyo" + }, + "MaxExecutors": { + "Description": "Maximum number of executors.", + "Type": "Number", + "Default": 2 + }, + "LogDriver": { + "Description": "Log driver to use (awslogs, or none)", + "Type": "String", + "Default": "awslogs", + "AllowedValues": [ + "awslogs", + "none" + ] + }, + "LogGroupName": { + "Description": "Name of the CloudWatch Log Group for awslogs or fluentd logging", + "Type": "String", + "Default": "ecs-fargate/ke2" + } + }, + "Conditions": { + "UseCustomVpcCond": { + "Fn::Equals": [ + { "Ref": "UseCustomVpc" }, + "true" + ] + }, + "CreateVpc": { + "Fn::Not": [ + { "Condition": "UseCustomVpcCond" } + ] + }, + "CreateECSService": { + "Fn::Equals": [ + { "Ref": "UseECSService" }, + "true" + ] + }, + "CreateLogGroup": { + "Fn::Not": [ + { + "Fn::Equals": [ + { "Ref": "LogDriver" }, + "none" + ] + } + ] + }, + "UseAWSLogs": { + "Fn::Equals": [ + { "Ref": "LogDriver" }, + "awslogs" + ] + } + }, + "Resources": { + "LogGroup": { + "Type": "AWS::Logs::LogGroup", + "Condition": "CreateLogGroup", + "Properties": { + "LogGroupName": { "Ref": "LogGroupName" } + } + }, + "VPC": { + "Type": "AWS::EC2::VPC", + "Condition": "CreateVpc", + "Properties": { + "CidrBlock": { "Ref": "VpcCIDR" }, + "EnableDnsSupport": true, + "EnableDnsHostnames": true, + "Tags": [ + { "Key": "Name", "Value": "KE2FargateVPC" } + ] + } + }, + "PublicSubnet": { + "Type": "AWS::EC2::Subnet", + "Condition": "CreateVpc", + "Properties": { + "VpcId": { "Ref": "VPC" }, + "CidrBlock": { "Ref": "PublicSubnetCIDR" }, + "MapPublicIpOnLaunch": true, + "AvailabilityZone": { "Fn::Select": [ 0, { "Fn::GetAZs": "" } ] }, + "Tags": [ + { "Key": "Name", "Value": "KE2FargatePublicSubnet" } + ] + } + }, + "InternetGateway": { + "Type": "AWS::EC2::InternetGateway", + "Condition": "CreateVpc", + "Properties": { + "Tags": [ + { "Key": "Name", "Value": "KE2FargateIgw" } + ] + } + }, + "VPCGatewayAttachment": { + "Type": "AWS::EC2::VPCGatewayAttachment", + "Condition": "CreateVpc", + "Properties": { + "VpcId": { "Ref": "VPC" }, + "InternetGatewayId": { "Ref": "InternetGateway" } + } + }, + "PublicRouteTable": { + "Type": "AWS::EC2::RouteTable", + "Condition": "CreateVpc", + "Properties": { + "VpcId": { "Ref": "VPC" }, + "Tags": [ + { "Key": "Name", "Value": "KE2FargatePublicRouteTable" } + ] + } + }, + "PublicRoute": { + "Type": "AWS::EC2::Route", + "Condition": "CreateVpc", + "Properties": { + "RouteTableId": { "Ref": "PublicRouteTable" }, + "DestinationCidrBlock": "0.0.0.0/0", + "GatewayId": { "Ref": "InternetGateway" } + } + }, + "SubnetRouteTableAssociation": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Condition": "CreateVpc", + "Properties": { + "SubnetId": { "Ref": "PublicSubnet" }, + "RouteTableId": { "Ref": "PublicRouteTable" } + } + }, + "ServiceSecurityGroup": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "Allow inbound HTTP traffic to the ECS tasks.", + "VpcId": { + "Fn::If": [ + "UseCustomVpcCond", + { "Ref": "CustomVpcId" }, + { "Ref": "VPC" } + ] + }, + "SecurityGroupIngress": [ + { + "IpProtocol": "tcp", + "FromPort": 80, + "ToPort": 80, + "CidrIp": "0.0.0.0/0" + }, + { + "IpProtocol": "tcp", + "FromPort": 443, + "ToPort": 443, + "CidrIp": "0.0.0.0/0" + } + ], + "Tags": [ + { "Key": "Name", "Value": "KE2FargateServiceSg" } + ] + } + }, + "EFSMountTargetSecurityGroup": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "Security group for EFS mount target", + "VpcId": { + "Fn::If": [ + "UseCustomVpcCond", + { "Ref": "CustomVpcId" }, + { "Ref": "VPC" } + ] + }, + "SecurityGroupIngress": [ + { + "IpProtocol": "tcp", + "FromPort": 2049, + "ToPort": 2049, + "CidrIp": "0.0.0.0/0" + } + ], + "Tags": [ + { "Key": "Name", "Value": "KE2FargateEFSMountTargetSecurityGroup" } + ] + } + }, + "EFSMountTarget": { + "Type": "AWS::EFS::MountTarget", + "Properties": { + "FileSystemId": { "Ref": "EFSFileSystemId" }, + "SubnetId": { + "Fn::If": [ + "UseCustomVpcCond", + { "Ref": "CustomPublicSubnetId" }, + { "Ref": "PublicSubnet" } + ] + }, + "SecurityGroups": [ + { "Ref": "EFSMountTargetSecurityGroup" } + ] + } + }, + "NginxEFSAccessPoint": { + "Type": "AWS::EFS::AccessPoint", + "Properties": { + "FileSystemId": { "Ref": "EFSFileSystemId" }, + "PosixUser": { + "Uid": "1000", + "Gid": "1000" + }, + "RootDirectory": { + "CreationInfo": { + "OwnerUid": "1000", + "OwnerGid": "1000", + "Permissions": "755" + }, + "Path": "/configs/nginx-conf" + } + } + }, + "SSLCertEFSAccessPoint": { + "Type": "AWS::EFS::AccessPoint", + "Properties": { + "FileSystemId": { "Ref": "EFSFileSystemId" }, + "PosixUser": { + "Uid": "1000", + "Gid": "1000" + }, + "RootDirectory": { + "CreationInfo": { + "OwnerUid": "1000", + "OwnerGid": "1000", + "Permissions": "755" + }, + "Path": "/ssl-cert" + } + } + }, + "KompiraVarEFSAccessPoint": { + "Type": "AWS::EFS::AccessPoint", + "Properties": { + "FileSystemId": { "Ref": "EFSFileSystemId" }, + "PosixUser": { + "Uid": "1000", + "Gid": "1000" + }, + "RootDirectory": { + "CreationInfo": { + "OwnerUid": "1000", + "OwnerGid": "1000", + "Permissions": "755" + }, + "Path": "/kompira-var" + } + } + }, + "RabbitEFSAccessPoint": { + "Type": "AWS::EFS::AccessPoint", + "Properties": { + "FileSystemId": { "Ref": "EFSFileSystemId" }, + "PosixUser": { + "Uid": "1000", + "Gid": "1000" + }, + "RootDirectory": { + "CreationInfo": { + "OwnerUid": "1000", + "OwnerGid": "1000", + "Permissions": "755" + }, + "Path": "/configs/rabbitmq-conf" + } + } + }, + "ECSCluster": { + "Type": "AWS::ECS::Cluster", + "Properties": { + "ClusterName": "KE2FargateCluster" + } + }, + "TaskExecutionRole": { + "Type": "AWS::IAM::Role", + "Properties": { + "RoleName": "ECSFargateTaskExecutionRole", + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": { + "Service": "ecs-tasks.amazonaws.com" + }, + "Action": "sts:AssumeRole" + } + ] + }, + "ManagedPolicyArns": [ + "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy" + ] + } + }, + "TaskRole": { + "Type": "AWS::IAM::Role", + "Properties": { + "RoleName": "ECSFargateTaskRole", + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": { + "Service": "ecs-tasks.amazonaws.com" + }, + "Action": "sts:AssumeRole" + } + ] + }, + "Policies": [ + { + "PolicyName": "AllowSSMMessages", + "PolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "ssmmessages:CreateControlChannel", + "ssmmessages:CreateDataChannel", + "ssmmessages:OpenControlChannel", + "ssmmessages:OpenDataChannel" + ], + "Resource": "*" + } + ] + } + } + ] + } + }, + "TaskDefinition": { + "Type": "AWS::ECS::TaskDefinition", + "Properties": { + "Family": "KE2Task", + "Cpu": "4096", + "Memory": "16384", + "RuntimePlatform": { + "OperatingSystemFamily": "LINUX", + "CpuArchitecture": "X86_64" + }, + "NetworkMode": "awsvpc", + "RequiresCompatibilities": [ + "FARGATE" + ], + "ExecutionRoleArn": { "Fn::GetAtt": [ "TaskExecutionRole", "Arn" ] }, + "TaskRoleArn": { "Ref": "TaskRole" }, + "ContainerDefinitions": [ + { + "Name": "kompira", + "Image": { "Fn::Sub": "kompira.azurecr.io/kompira-enterprise:${ImageTag}" }, + "PortMappings": [ + { "ContainerPort": 8000 } + ], + "Command": [ "uwsgi" ], + "Environment": [ + { + "Name": "DATABASE_URL", + "Value": { "Ref": "DatabaseURL" } + }, + { + "Name": "AMQP_URL", + "Value": "amqp://guest:guest@localhost:5672" + }, + { + "Name": "CACHE_URL", + "Value": "redis://localhost:6379" + }, + { + "Name": "TZ", + "Value": { "Ref": "TimeZone" } + } + ], + "MountPoints": [ + { + "SourceVolume": "kompiraVarVolume", + "ContainerPath": "/var/opt/kompira", + "ReadOnly": false + } + ], + "LogConfiguration": { + "Fn::If": [ + "UseAWSLogs", + { + "LogDriver": "awslogs", + "Options": { + "awslogs-region": { "Ref": "AWS::Region" }, + "awslogs-group": { "Ref": "LogGroupName" }, + "awslogs-stream-prefix": "kompira" + } + }, + { "Ref": "AWS::NoValue" } + ] + } + }, + { + "Name": "kengine", + "Image": { "Fn::Sub": "kompira.azurecr.io/kompira-enterprise:${ImageTag}" }, + "Command": [ "kompirad" ], + "Environment": [ + { + "Name": "DATABASE_URL", + "Value": { "Ref": "DatabaseURL" } + }, + { + "Name": "AMQP_URL", + "Value": "amqp://guest:guest@localhost:5672" + }, + { + "Name": "CACHE_URL", + "Value": "redis://localhost:6379" + }, + { + "Name": "TZ", + "Value": { "Ref": "TimeZone" } + }, + { + "Name": "MAX_EXECUTOR_NUM", + "Value": { "Ref": "MaxExecutors" } + } + ], + "MountPoints": [ + { + "SourceVolume": "kompiraVarVolume", + "ContainerPath": "/var/opt/kompira", + "ReadOnly": false + } + ], + "LogConfiguration": { + "Fn::If": [ + "UseAWSLogs", + { + "LogDriver": "awslogs", + "Options": { + "awslogs-region": { "Ref": "AWS::Region" }, + "awslogs-group": { "Ref": "LogGroupName" }, + "awslogs-stream-prefix": "kengine" + } + }, + { "Ref": "AWS::NoValue" } + ] + } + }, + { + "Name": "jobmngrd", + "Image": { "Fn::Sub": "kompira.azurecr.io/kompira-enterprise:${ImageTag}" }, + "Command": [ "jobmngrd" ], + "Environment": [ + { + "Name": "AMQP_URL", + "Value": "amqp://guest:guest@localhost:5672" + }, + { + "Name": "TZ", + "Value": { "Ref": "TimeZone" } + } + ], + "MountPoints": [ + { + "SourceVolume": "kompiraVarVolume", + "ContainerPath": "/var/opt/kompira", + "ReadOnly": false + } + ], + "LogConfiguration": { + "Fn::If": [ + "UseAWSLogs", + { + "LogDriver": "awslogs", + "Options": { + "awslogs-region": { "Ref": "AWS::Region" }, + "awslogs-group": { "Ref": "LogGroupName" }, + "awslogs-stream-prefix": "jobmngrd" + } + }, + { "Ref": "AWS::NoValue" } + ] + } + }, + { + "Name": "rabbitmq", + "Image": "registry.hub.docker.com/library/rabbitmq:3.12-alpine", + "PortMappings": [ + { "ContainerPort": 5671 }, + { "ContainerPort": 5672 } + ], + "MountPoints": [ + { + "SourceVolume": "sslCertVolume", + "ContainerPath": "/etc/rabbitmq/ssl" + }, + { + "SourceVolume": "rabbitConfVolume", + "ContainerPath": "/etc/rabbitmq/conf.d" + } + ], + "LogConfiguration": { + "Fn::If": [ + "UseAWSLogs", + { + "LogDriver": "awslogs", + "Options": { + "awslogs-region": { "Ref": "AWS::Region" }, + "awslogs-group": { "Ref": "LogGroupName" }, + "awslogs-stream-prefix": "rabbitmq" + } + }, + { "Ref": "AWS::NoValue" } + ] + } + }, + { + "Name": "redis", + "Image": "registry.hub.docker.com/library/redis:7.2-alpine", + "PortMappings": [ + { "ContainerPort": 6379 } + ], + "LogConfiguration": { + "Fn::If": [ + "UseAWSLogs", + { + "LogDriver": "awslogs", + "Options": { + "awslogs-region": { "Ref": "AWS::Region" }, + "awslogs-group": { "Ref": "LogGroupName" }, + "awslogs-stream-prefix": "redis" + } + }, + { "Ref": "AWS::NoValue" } + ] + } + }, + { + "Name": "nginx", + "Image": "registry.hub.docker.com/library/nginx:1.25-alpine", + "PortMappings": [ + { "ContainerPort": 80 }, + { "ContainerPort": 443 } + ], + "Environment": [ + { + "Name": "KOMPIRA_HOST", + "Value": "localhost" + }, + { + "Name": "KOMPIRA_PORT", + "Value": "8000" + } + ], + "MountPoints": [ + { + "SourceVolume": "nginxConfVolume", + "ContainerPath": "/etc/nginx/templates" + }, + { + "SourceVolume": "sslCertVolume", + "ContainerPath": "/etc/nginx/ssl" + }, + { + "SourceVolume": "kompiraVarVolume", + "ContainerPath": "/var/opt/kompira", + "ReadOnly": false + } + ], + "LogConfiguration": { + "Fn::If": [ + "UseAWSLogs", + { + "LogDriver": "awslogs", + "Options": { + "awslogs-region": { "Ref": "AWS::Region" }, + "awslogs-group": { "Ref": "LogGroupName" }, + "awslogs-stream-prefix": "nginx" + } + }, + { "Ref": "AWS::NoValue" } + ] + } + } + ], + "Volumes": [ + { + "Name": "nginxConfVolume", + "EFSVolumeConfiguration": { + "FileSystemId": { "Ref": "EFSFileSystemId" }, + "TransitEncryption": "ENABLED", + "AuthorizationConfig": { + "AccessPointId": { "Ref": "NginxEFSAccessPoint" }, + "IAM": "DISABLED" + } + } + }, + { + "Name": "sslCertVolume", + "EFSVolumeConfiguration": { + "FileSystemId": { "Ref": "EFSFileSystemId" }, + "TransitEncryption": "ENABLED", + "AuthorizationConfig": { + "AccessPointId": { "Ref": "SSLCertEFSAccessPoint" }, + "IAM": "DISABLED" + } + } + }, + { + "Name": "kompiraVarVolume", + "EFSVolumeConfiguration": { + "FileSystemId": { "Ref": "EFSFileSystemId" }, + "TransitEncryption": "ENABLED", + "AuthorizationConfig": { + "AccessPointId": { "Ref": "KompiraVarEFSAccessPoint" }, + "IAM": "DISABLED" + } + } + }, + { + "Name": "rabbitConfVolume", + "EFSVolumeConfiguration": { + "FileSystemId": { "Ref": "EFSFileSystemId" }, + "TransitEncryption": "ENABLED", + "AuthorizationConfig": { + "AccessPointId": { "Ref": "RabbitEFSAccessPoint" }, + "IAM": "DISABLED" + } + } + } + ] + } + }, + "ECSService": { + "Type": "AWS::ECS::Service", + "Condition": "CreateECSService", + "DependsOn": [ + "VPCGatewayAttachment" + ], + "Properties": { + "ServiceName": "KE2FargateService", + "Cluster": { "Ref": "ECSCluster" }, + "TaskDefinition": { "Ref": "TaskDefinition" }, + "LaunchType": "FARGATE", + "DesiredCount": 1, + "NetworkConfiguration": { + "AwsvpcConfiguration": { + "Subnets": [ + { + "Fn::If": [ + "UseCustomVpcCond", + { "Ref": "CustomPublicSubnetId" }, + { "Ref": "PublicSubnet" } + ] + } + ], + "SecurityGroups": [ + { "Ref": "ServiceSecurityGroup" } + ], + "AssignPublicIp": "ENABLED" + } + }, + "EnableExecuteCommand": true + } + } + }, + "Outputs": { + "ClusterName": { + "Description": "ECS Cluster Name", + "Value": { "Ref": "ECSCluster" } + }, + "TaskDefinitionFamily": { + "Description": "ECS Task Definition Family", + "Value": { "Ref": "TaskDefinition" } + }, + "PublicSubnetId": { + "Description": "Public Subnet ID", + "Value": { + "Fn::If": [ + "UseCustomVpcCond", + { "Ref": "CustomPublicSubnetId" }, + { "Ref": "PublicSubnet" } + ] + } + }, + "ServiceSecurityGroup": { + "Description": "Security Group for tasks", + "Value": { "Ref": "ServiceSecurityGroup" } + } +} +} diff --git a/ke2/cloud/awsecs/parameters.json b/ke2/cloud/awsecs/parameters.json new file mode 100644 index 0000000..307a431 --- /dev/null +++ b/ke2/cloud/awsecs/parameters.json @@ -0,0 +1,15 @@ +[ + { "ParameterKey": "UseCustomVpc", "ParameterValue": "false" }, + { "ParameterKey": "CustomVpcId", "ParameterValue": "" }, + { "ParameterKey": "CustomPublicSubnetId", "ParameterValue": "" }, + { "ParameterKey": "VpcCIDR", "ParameterValue": "10.0.0.0/16" }, + { "ParameterKey": "PublicSubnetCIDR", "ParameterValue": "10.0.1.0/24" }, + { "ParameterKey": "UseECSService", "ParameterValue": "true" }, + { "ParameterKey": "ImageTag", "ParameterValue": "latest" }, + { "ParameterKey": "EFSFileSystemId", "ParameterValue": "" }, + { "ParameterKey": "DatabaseURL", "ParameterValue": "" }, + { "ParameterKey": "TimeZone", "ParameterValue": "Asia/Tokyo" }, + { "ParameterKey": "MaxExecutors", "ParameterValue": "2" }, + { "ParameterKey": "LogDriver", "ParameterValue": "awslogs" }, + { "ParameterKey": "LogGroupName", "ParameterValue": "ecs-fargate/ke2" } +] From fa5f88298a775f9d9ba543ba76c2a53a951da3e9 Mon Sep 17 00:00:00 2001 From: fixpoint-hasan Date: Tue, 8 Apr 2025 22:05:29 +0900 Subject: [PATCH 2/3] Add EC2 deployment template for managing EFS mount operation --- ke2/cloud/awsecs/uploader.json | 227 +++++++++++++++++++++++++++++++++ 1 file changed, 227 insertions(+) create mode 100644 ke2/cloud/awsecs/uploader.json diff --git a/ke2/cloud/awsecs/uploader.json b/ke2/cloud/awsecs/uploader.json new file mode 100644 index 0000000..45c613b --- /dev/null +++ b/ke2/cloud/awsecs/uploader.json @@ -0,0 +1,227 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Description": "CloudFormation template with prefix KE2EFSFUP for all resources. It creates a VPC with a public subnet, Internet Gateway, Route Table, and Security Groups. It then creates a mount target for an existing EFS file system, and launches an EC2 instance that mounts the EFS file system.", + "Parameters": { + "KeyName": { + "Description": "Name of an existing EC2 KeyPair for SSH access.", + "Type": "AWS::EC2::KeyPair::KeyName" + }, + "InstanceType": { + "Description": "EC2 instance type.", + "Type": "String", + "Default": "t2.micro" + }, + "InstanceImageId": { + "Description": "EC2 instance image ID.", + "Type": "AWS::EC2::Image::Id" + }, + "EFSFileSystemId": { + "Description": "The ID of the existing EFS file system to mount.", + "Type": "String" + } + }, + "Resources": { + "KE2EFSFUPVPC": { + "Type": "AWS::EC2::VPC", + "Properties": { + "CidrBlock": "10.0.0.0/16", + "EnableDnsSupport": true, + "EnableDnsHostnames": true, + "Tags": [ + { + "Key": "Name", + "Value": "KE2EFSFUPVPC" + } + ] + } + }, + "KE2EFSFUPInternetGateway": { + "Type": "AWS::EC2::InternetGateway", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "KE2EFSFUPInternetGateway" + } + ] + } + }, + "KE2EFSFUPVPCGatewayAttachment": { + "Type": "AWS::EC2::VPCGatewayAttachment", + "Properties": { + "VpcId": { + "Ref": "KE2EFSFUPVPC" + }, + "InternetGatewayId": { + "Ref": "KE2EFSFUPInternetGateway" + } + } + }, + "KE2EFSFUPPublicSubnet": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "VpcId": { + "Ref": "KE2EFSFUPVPC" + }, + "CidrBlock": "10.0.1.0/24", + "MapPublicIpOnLaunch": true, + "AvailabilityZone": { + "Fn::Select": [ + "0", + { + "Fn::GetAZs": "" + } + ] + }, + "Tags": [ + { + "Key": "Name", + "Value": "KE2EFSFUPPublicSubnet" + } + ] + } + }, + "KE2EFSFUPPublicRouteTable": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Ref": "KE2EFSFUPVPC" + }, + "Tags": [ + { + "Key": "Name", + "Value": "KE2EFSFUPPublicRouteTable" + } + ] + } + }, + "KE2EFSFUPPublicRoute": { + "Type": "AWS::EC2::Route", + "DependsOn": "KE2EFSFUPVPCGatewayAttachment", + "Properties": { + "RouteTableId": { + "Ref": "KE2EFSFUPPublicRouteTable" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "GatewayId": { + "Ref": "KE2EFSFUPInternetGateway" + } + } + }, + "KE2EFSFUPSubnetRouteTableAssociation": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "SubnetId": { + "Ref": "KE2EFSFUPPublicSubnet" + }, + "RouteTableId": { + "Ref": "KE2EFSFUPPublicRouteTable" + } + } + }, + "KE2EFSFUPInstanceSecurityGroup": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "Security group for EC2 instance allowing SSH", + "VpcId": { + "Ref": "KE2EFSFUPVPC" + }, + "SecurityGroupIngress": [ + { + "IpProtocol": "tcp", + "FromPort": 22, + "ToPort": 22, + "CidrIp": "0.0.0.0/0" + } + ], + "Tags": [ + { + "Key": "Name", + "Value": "KE2EFSFUPInstanceSecurityGroup" + } + ] + } + }, + "KE2EFSFUPEFSSecurityGroup": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "Security group for EFS mount target allowing NFS (TCP 2049) access from EC2 instances", + "VpcId": { + "Ref": "KE2EFSFUPVPC" + }, + "SecurityGroupIngress": [ + { + "IpProtocol": "tcp", + "FromPort": 2049, + "ToPort": 2049, + "SourceSecurityGroupId": { + "Ref": "KE2EFSFUPInstanceSecurityGroup" + } + } + ], + "Tags": [ + { + "Key": "Name", + "Value": "KE2EFSFUPEFSSecurityGroup" + } + ] + } + }, + "KE2EFSFUPEFSMountTarget": { + "Type": "AWS::EFS::MountTarget", + "Properties": { + "FileSystemId": { + "Ref": "EFSFileSystemId" + }, + "SubnetId": { + "Ref": "KE2EFSFUPPublicSubnet" + }, + "SecurityGroups": [ + { + "Ref": "KE2EFSFUPEFSSecurityGroup" + } + ] + } + }, + "KE2EFSFUPEC2Instance": { + "Type": "AWS::EC2::Instance", + "Properties": { + "InstanceType": { + "Ref": "InstanceType" + }, + "KeyName": { + "Ref": "KeyName" + }, + "ImageId":{ + "Ref": "InstanceImageId" + }, + "NetworkInterfaces": [ + { + "AssociatePublicIpAddress": true, + "DeviceIndex": "0", + "SubnetId": { + "Ref": "KE2EFSFUPPublicSubnet" + }, + "GroupSet": [ + { + "Ref": "KE2EFSFUPInstanceSecurityGroup" + } + ] + } + ], + "UserData": { + "Fn::Base64": { + "Fn::Sub": "#!/bin/bash\nyum update -y\n# Install amazon-efs-utils for mounting EFS\nyum install -y amazon-efs-utils\nmkdir -p /mnt/efs" + } + }, + "Tags": [ + { + "Key": "Name", + "Value": "KE2EFSFUPEC2Instance" + } + ] + } + } + } + } + \ No newline at end of file From c181a806180bcc27f613f92a74b1c3454a324409 Mon Sep 17 00:00:00 2001 From: fixpoint-hasan Date: Mon, 14 Apr 2025 11:32:37 +0900 Subject: [PATCH 3/3] Add ECS fargate deployment doc --- ke2/cloud/awsecs/README.md | 498 +++++++++++++++++++++++++++++++++++++ 1 file changed, 498 insertions(+) create mode 100644 ke2/cloud/awsecs/README.md diff --git a/ke2/cloud/awsecs/README.md b/ke2/cloud/awsecs/README.md new file mode 100644 index 0000000..bec18de --- /dev/null +++ b/ke2/cloud/awsecs/README.md @@ -0,0 +1,498 @@ +# Kompira Enterprise: シンプルで軽量な次世代運用自動化プラットフォーム + +このディレクトリには、AWS Elastic Container Service (AWS ECS) の [Fargate](https://aws.amazon.com/fargate/) にデプロイするための CloudFormation テンプレートファイルおよび関連ファイルが含まれています。これらは、KE2 の外部 DB シングル構成向けに準備されたものです。なお、AWS Fargate はサーバーレスサービスですが、基盤 OS は Linux であり、KE2 の Docker イメージのプラットフォームは linux/amd64 です。 + +## 事前準備 + +デプロイ作業を行うために、以下の準備をしてください。 + +1. AWS CLI のインストール: + [AWS CLI インストールガイド](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) を参考に、お使いの OS に AWS CLI をインストールします。 + + ※ デプロイ後、コンテナにアクセスしたい場合は、[Session Manager plugin](https://docs.aws.amazon.com/systems-manager/latest/userguide/session-manager-working-with-install-plugin.html)必要です。 + + +2. ke2-docker リポジトリのファイル一式を取得: + https://github.com/fixpoint/ke2-docker から、Code -> Download ZIP を選択し、 + ke2-docker リポジトリのファイル一式を取得して、作業用 PC の適当なディレクトリに展開します。 + +3. Docker のインストール (オプショナル): + SSL (self-signed) 証明書の生成を行なうためには Docker が必要です。 + [Docker インストールガイド](https://docs.docker.com/engine/install/) を参考に、お使いの OS に Docker をインストールします。 + +## デプロイ手順 + +### AWS 上に各種リソース作成 + +AWS 上に以下に示すの各種リソースを作成していきます。 +(作成するリソースの名前は適宜変更してください) + +- PostgreSQL DB インスタンス (Aurora and RDS): pg-ke2 +- Elastic File System (Amazon EFS): ke2-efs + +### AWS 認証情報を使用してCLIを設定: + +あらかじめ、Identity and Access Management (IAM) から以下の情報を取得してください。 + +- AWS Access Key ID +- AWS Secret Access Key +- Default region name + +次に、以下の認証情報を使用して CLI を設定してください。 + +```bash +$ aws configure +AWS Access Key ID [None]: ********************** +AWS Secret Access Key [None]: ********************** +Default region name [None]: ap-northeast-1 # note: Asia pacific(tokyo) +Default output format [None]: json +``` + +以下のコマンドで設定状態を確認できます: +```bash +$ aws configure list +``` + +### PostgreSQL DB インスタンスの作成 + +AWS管理コンソールにログインして、同じリージョン (ap-northeast-1) に Aurora and RDS > Databases リソースを +以下のパラメータで作成します。 + +データベースの作成: +- データベース作成方法を選択: 標準作成 +- エンジンのオプション: PostgreSQL +- エンジンバージョン: PostgreSQL 16.8-R1 +- テンプレート: 必要に応じて適切なプランを選択してください +- 可用性と耐久性: + - デプロイオプション: シングル AZ DB インスタンスデプロイ (1 インスタンス) +- 設定 + - DB クラスター識別子: pg-ke2 +- 認証情報の設定 + - マスターユーザー名: kompira + - 認証情報管理: セルフマネージド + - マスターパスワード: 適切なパスワードを指定してください + - マスターパスワードを確認: 適切なパスワードを指定してください +- 接続 + - Virtual Private Cloud (VPC): 新しい VPC の作成 + - パブリックアクセス: あり 「AWS サービスにこのサーバーへのパブリック アクセスを許可する」 + - VPC セキュリティグループ (ファイアウォール): 新規作成 + - 新しい VPC セキュリティグループ名: pg-ke2-sg +- その他のモニタリング設定 + - ログのエクスポート: PostgreSQL ログ 「必要に応じて適切なオプションを選択してください」 + - DevOps Guru: チェックなし +- 追加設定 + - 追加設定 + - 最初のデータベース名: kompira + +> [!NOTE] +> その他のパラメータはデフォルトで構いません。ただし、必要に応じて要件に合わせて変更することもできます。VPC、サブネット、セキュリティグループ(ポート5432が開いている)の設定については、カスタム設定を使用しても構いませんが、必ずKE2アプリからアクセス可能であることを確認してください。 + +DB インスタンスの起動にはしばらく時間がかかる場合があります。 + +以下のコマンドを実行して、データベースにアクセスできるかどうかを確認してください。 +```bash +$ psql -h -p 5432 -U kompira -d kompira +``` + +> [!TIP] +> 上の通りに DB インスタンスを作成後、DB インスタンス詳細ページに行って、「接続とセキュリティ」タブ中からエンドポイントを習得してください。 + +■ PGCRYPTO の有効化 +```bash +# login +$ psql -h -p 5432 -U kompira -d kompira +# activate pgcrypto extension +kompira=> CREATE EXTENSION IF NOT EXISTS pgcrypto; +# check the status +kompira=> \dx +``` + +### 共有ファイルストレージの作成(EFS): + +Elastic Container Service(ECS) で必要となる共有ファイルストレージを以下の名称で作成しておきます。 + +```bash +$ aws efs create-file-system --creation-token ke2-efs --query 'FileSystemId' --tags Key=Name,Value=ke2-efs --output text +``` +> [!NOTE] +> ke2-efs ファイルストレージ ID を保存してください、ファイルのアップロードやデプロイなど時に必要となる。`efs-id: fs-*******` + +### 共有ファイルストレージにファイルのアップロードの準備 + +EFSにファイルをアップロードする方法はいくつかあり、たとえばAWS DataSync、AWS Transfer、またはEC2インスタンスにEFSをマウントする方法などがあります。異なる方法を使用しても構いませんが、ディレクトリおよびファイルの階層は以下の通りです。 + +```txt +/ (EFS root) +├── configs/ +│ ├── rabbitmq-conf/ +│ │ ├── 20-auth.conf (copy from ../../../../configs/rabbitmq-auth.conf) +│ │ └── 30-ssl.conf (copy from ../../../../configs/rabbitmq-ssl.conf) +│ └── nginx-conf/ +│ └── default.conf.template (copy from ../../../../configs/nginx.conf) +├── ssl-cert/ +│ ├── local-ca.crt (copy from ../../../../ssl/local-ca.crt) +│ ├── server.crt (copy from ../../../../ssl/server.crt) +│ └── server.key (copy from ../../../../ssl/server.key) +└── kompira-var/ +``` + +継続的な同期が不要な一度限りのアップロードの場合、最も簡単な方法は、EC2インスタンスにEFSをマウントし、標準のコマンドを使ってディレクトリを作成し、ファイルをコピーすることです。以下の手順を用いて、共有ファイルストレージ(EFS)をEC2にマウントしています。 + +#### EC2にアクセスするためのキーペアの作成 +```bash +$ cd ke2/cloud/awsecs/fargate +$ aws ec2 create-key-pair --key-name KE2ECSKeyPair --query 'KeyMaterial' --output text > KE2ECSKeyPair.pem +$ chmod 400 "KE2ECSKeyPair.pem" +``` + +#### Amazon Linux 2 ECS-最適化AMIの推奨イメージ ID の取得 +```bash +$ aws ssm get-parameters --names /aws/service/ecs/optimized-ami/amazon-linux-2/recommended/image_id --query "Parameters[0].Value" --output text +``` +> [!NOTE] +> イメージ ID を保存してください、EC2をデプロイ時に必要となる。`ec2-ami-id: ami-*******` + +#### EC2インスタンスの起動とパブリックIPアドレスの取得 + +上のステップで習得した `ec2-ami-id` と `efs-id` を用いて、下記のコマンドで EC2 インスタンスを立ち上がります。 + +```bash +$ cd ke2/cloud/awsecs/fargate +$ aws cloudformation create-stack \ + --stack-name KE2EFSFUPEC2Stack \ + --template-body file://uploader.json \ + --parameters ParameterKey=KeyName,ParameterValue=KE2ECSKeyPair \ + ParameterKey=InstanceImageId,ParameterValue= \ + ParameterKey=EFSFileSystemId,ParameterValue= +``` +> [!WARNING] +> インスタンスの起動にはしばらく時間がかかる場合があります。 + +EC2がEFSのマウントターゲットとして正しく登録されているかどうかを確認します。MountTargetsが空でなければ問題ありません。 +```bash +$ aws efs describe-mount-targets --file-system-id +``` + +立ち上げたインスタンスの ID を習得します。 +```bash +$ aws ec2 describe-instances \ + --filters "Name=tag:aws:cloudformation:stack-name,Values=KE2EFSFUPEC2Stack" "Name=instance-state-name,Values=running" \ + --query "Reservations[].Instances[].InstanceId" \ + --output text +``` +> [!NOTE] +> インスタンス ID を保存してください、次のステップに利用します。 `ec2-instance-id: i-******` + +パブリックIPアドレスを習得します。 +```bash +aws ec2 describe-instances \ + --instance-ids \ + --query "Reservations[].Instances[].{State:State.Name, PublicIP:PublicIpAddress}" \ + --output table +``` +> [!NOTE] +> パブリックIPアドレスを保存してください。ファイルのアップロード時に必要となる。`ec2-instance-ip: XX.XX.XX.XX` + +#### 共有ファイルストレージ(EFS)のEC2へのマウントと必要なディレクトリの作成 + +```bash +$ ssh -i "KE2ECSKeyPair.pem" ec2-user@13.231.238.175 "sudo mount -t efs -o tls fs-064594ea74b991a84:/ /mnt/efs" +# マウント状況を確認 +$ ssh -i "KE2ECSKeyPair.pem" ec2-user@13.231.238.175 "mount | grep /mnt/efs" +# 正しくマウントできれば以下の通りに結果もらいます。 +# 127.0.0.1:/ on /mnt/efs type nfs4 (rw,relatime,vers=4.1,rsize=1048576,wsize=1048576,namlen=255,hard,noresvport,proto=tcp,port=20636,timeo=600,retrans=2,sec=sys,clientaddr=127.0.0.1,local_lock=none,addr=127.0.0.1) +``` + +必要なディレクトリを作成します。`ec2-instance-ip`を用いて、以下のコマンドを実行します。 + +```bash +$ ssh -i "KE2ECSKeyPair.pem" ec2-user@ "sudo mkdir -p /mnt/efs/configs/rabbitmq-conf /mnt/efs/configs/nginx-conf /mnt/efs/ssl-cert /mnt/efs/kompira-var" +$ ssh -i "KE2ECSKeyPair.pem" ec2-user@ "sudo chown -R ec2-user:ec2-user /mnt/efs" +``` + +#### 証明書ファイルのアップロード手順 + +SSL (self-signed) 証明書の生成を行なうために、以下のコマンドを実行します。 + +``` +$ cd ke2/cloud/azureci +$ ../../../scripts/create-cert.sh +``` +作成された SSL 証明書は ssl ディレクトリに保存されます。 +> [!WARNING] +> 本番環境では、証明書認証局(CA)から証明書を取得してください。 + +作成した ssl-cert 共有ファイルストレージ(EFS)に以下のコマンドを使用して証明書ファイルをアップロードします。 + +```bash +# CA 証明書のローカルパス: ../../../../ssl/local-ca.crt +$ scp -i "KE2ECSKeyPair.pem" ../../../../ssl/local-ca.crt ec2-user@:/mnt/efs/ssl-cert +# サーバーキーのローカルパス: ../../../../ssl/server.key +$ scp -i "KE2ECSKeyPair.pem" ../../../../ssl/server.key ec2-user@:/mnt/efs/ssl-cert +# サーバー証明書のローカルパス: ../../../../ssl/server.crt +$ scp -i "KE2ECSKeyPair.pem" ../../../../ssl/server.crt ec2-user@:/mnt/efs/ssl-cert +``` +> [!CAUTION] +> `ec2-instance-ip`は実際のIPアドレスに置き換えてください。 + +#### NginxとRabbitMQ の conf ファイルのアップロード + +AWS CLI の以下のコマンドで ke2-docker に含まれる NginxとRabbitMQ の conf ファイルをアップロードします。 + +```bash +$ scp -i "KE2ECSKeyPair.pem" ../../../../configs/rabbitmq-auth.conf ec2-user@:/mnt/efs/configs/rabbitmq-conf/20-auth.conf +$ scp -i "KE2ECSKeyPair.pem" ../../../../configs/rabbitmq-ssl.conf ec2-user@:/mnt/efs/configs/rabbitmq-conf/30-ssl.conf +$ scp -i "KE2ECSKeyPair.pem" ../../../../configs/nginx.conf ec2-user@:/mnt/efs/configs/nginx-conf/default.conf.template +``` +> [!CAUTION] +> `ec2-instance-ip` は実際のIPアドレスに置き換えてください。 + +#### EC2から共有ファイルストレージ(EFS)のアンマウント + +```bash +$ ssh -i "KE2ECSKeyPair.pem" ec2-user@ "sudo umount -l /mnt/efs" +# アンマウント状況を確認します。正しくアンマウントされれば、何も表示されません。 +$ ssh -i "KE2ECSKeyPair.pem" ec2-user@ "mount | grep /mnt/efs" +``` +> [!CAUTION] +> `ec2-instance-ip` は実際のIPアドレスに置き換えてください。 + +#### EC2インスタンスと関連リソースの削除 + +```bash +aws cloudformation delete-stack --stack-name KE2EFSFUPEC2Stack +``` +> [!WARNING] +> インスタンスの終了にはしばらく時間がかかる場合があります。 + +EFSのマウントターゲットが空になるまで待機 +```bash +$ aws efs describe-mount-targets --file-system-id +``` +> [!CAUTION] +> `efs-id` は実際の ke2-efs ファイルストレージ IDに置き換えてください。 + +### アプリケーションを AWS ECS にデプロイ + +`ke2-docker/ke2/cloud/awsecs` ディレクトリ上で AWS CLI を使用して CloudFormation テンプレート `deployment.json` をデプロイします。 + +`parameters.json` ファイルを使用して必要な値を設定します。 + +■ デプロイパラメータの説明は、以下の通りです。 + +- `UseCustomVpc`: 既存のVPCを利用する場合は `true` と指定してください。既存VPCを使用しない場合(新規作成する場合)は `false`(デフォルト: `false`) + - 【`UseCustomVpc` が `true` の場合】 + - `CustomVpcId`: 既存の VPC ID を指定してください。 + - `CustomPublicSubnetId`: 既存の VPC 内のパブリックサブネットの ID を指定してください。 + - 【`UseCustomVpc` が `false` の場合】 + - `VpcCIDR`: VPC の CIDR ブロックを指定してください(デフォルト: `10.0.0.0/16`) + - `PublicSubnetCIDR`: パブリックサブネットの CIDR ブロックを指定してください(デフォルト: `10.0.1.0/24`) +- `UseECSService`: コンテナタスクのデプロイを自動的に管理するために、ECSService リソースを利用する場合は `true` と指定してください。手動でコンテナタスクのデプロイを管理したい場合は `false` と指定してください(デフォルト: `true`)。 + - 【`UseECSService` が `true` の場合】: ECSService リソースがデプロイされ、コンテナタスクの状態を監視し、問題が発生したタスクを停止して新しいタスクを起動するなど、タスクの自動管理を行います。 + - 【`UseECSService` が `false` の場合】: ECSService リソースはデプロイされず、コンテナタスクのデプロイを手動またはカスタムな方法で管理する機会が提供されます。 +- `ImageTag`: イメージのタグ(デフォルト: ke2-docker 更新時点で公開されていた最新の kompira コンテナイメージのタグ。例えば "2.0.2" など) +- `TimeZone`: タイムゾーン(デフォルト: `Asia/Tokyo`) +- `MaxExecutors`: 最大エグゼキュター数(デフォルト: `2`) +- `DatabaseURL`: データベースの接続 URL + 形式:pgsql://<ユーザ名>:<パスワード>@<アドレス・pg-ke2で始まる、PostgreSQL インスタンスのエンドポイント>:<ポート番号>/<データベース名> +> [!TIP] +> PostgreSQL インスタンスのエンドポイントとは、データベースに接続するためのDNS名またはIPアドレスのことです。AWS RDSなどのマネージドサービスを使用している場合、エンドポイントはAWS管理コンソールのDBインスタンス詳細ページで確認できます。 + +- `LogDriver`: Fargateのログサービス(オプション: `none`, `awslogs` デフォルト: `awslogs`) +- `LogGroupName`: ログが保存されるCloudWatch Logsグループの名前(デフォルト: `ecs-fargate/ke2`) +- `EFSFileSystemId`: 作成した `ke2-efs` ファイルストレージ ID (取得した `efs-id` を利用してください) + + +#### システムの起動 + +`ke2-docker/ke2/cloud/awsecs` ディレクトリ上で AWS CLI を使用して CloudFormation テンプレートのデプロイ。 + +■ 少なくとも、以下のデプロイパラメータを設定してデプロイ + +- `DatabaseURL`: `pgsql://:@:5432/kompira` +> [!CAUTION] +> ``、`` および `` は、実際の値に置き換えてください。 + +- `EFSFileSystemId`: 作成した `ke2-efs` ファイルストレージ ID (取得した `efs-id` を利用してください) +- `UseECSService`: `true`(コンテナタスクのデプロイを自動的に管理する)。`UseECSService` が `false` の場合は、以下のコマンドでコンテナタスクはデプロイされず、ECS Fargate 環境のみが準備されるため、後で手動でコンテナタスクをデプロイしてください。 + +```bash +$ aws cloudformation create-stack \ + --stack-name KE2ECSFargateStack \ + --template-body file://deployment.json \ + --parameters file://parameters.json \ + --capabilities CAPABILITY_NAMED_IAM +``` +> [!WARNING] +> AWS Fargate システムの起動にはしばらく時間がかかります。 + +既存のAWS CloudFormationスタックをパラメータの変更で更新することにより、CloudFormationで管理されているリソースを削除せずに変更できます。更新が失敗した場合、CloudFormationは自動的に以前の状態にロールバックします。たとえば、Kompiraのイメージタグ、最大エグゼキュータ数、ログドライバーなどを更新したい場合、リソースを削除して再作成するのではなく、スタックを更新する方が良いです。 + +```bash +$ aws cloudformation update-stack \ + --stack-name KE2ECSFargateStack \ + --template-body file://deployment.json \ + --parameters file://parameters.json \ + --capabilities CAPABILITY_NAMED_IAM +``` +> [!CAUTION] +> スタックを更新すると、以前のタスク(コンテナ)が停止し、新しいタスクが作成されます。その結果、パブリックIPが自動的に変更されます。 + +■ `UseECSService` が `false` の場合、以下の手順でコンテナタスクの手動デプロイ + +手動デプロイてめに、以下のコマンドで必要な情報習得します。AWS管理コンソールの CloudFormation > Stacks > KE2ECSFargateStack > Outputsでも習得できます。 +```bash +$ aws cloudformation describe-stacks --stack-name KE2ECSFargateStack --query "Stacks[0].Outputs" --output table +``` + +コンテナタスクの手動デプロイ +```bash +$ aws ecs run-task \ + --cluster KE2FargateCluster \ + --task-definition KE2Task \ + --launch-type FARGATE \ + --network-configuration "awsvpcConfiguration={subnets=[""],securityGroups=[""],assignPublicIp=ENABLED}" \ + --count 1 \ + --enable-execute-command +``` + +コンテナにアクセスしたい場合は、`--enable-execute-command` オプションを使用してください。 +> [!CAUTION] +> ``、`` は、実際の値に置き換えてください。 + + +デプロイ後、AWS管理コンソールの ECS > Clusters > KE2FargateCluster > Services リソースの配下に、KE2FargateService > Tasks が作成されるので、そこから、各コンテナの状態を確認することができます。 +KE2 コンテナインスタンスのタスクの Public IP アドレスにブラウザから HTTP・HTTPS アクセスすると、Kompira Enterprise のログイン画面が表示されるので、ログインすることができます。 + +> [!TIP] +> AWS管理コンソールの ECS > Clusters > KE2FargateCluster > Services(table) > Deployment and Tasks(column) > Tasks(table) > Task(Running) > Networking(tab) > Public IP の所から Public IP を習得できます。 + +#### コンテナログの確認 + +特定のコンテナのログを確認するには、以下のコマンドを実行します。 + +■ コンテナ名 +- kompira +- kengine +- jobmngrd +- redis +- rabbitmq +- nginx + +```bash +$ aws logs tail "<ロググループ名>" --log-stream-name-prefix "<コンテナ名>" +# ex: aws logs tail "ecs-fargate/ke2" --log-stream-name-prefix "kompira" +``` +> [!CAUTION] +> `<ロググループ名>`, および `<コンテナ名>` は、実際の値に置き換えてください。 + +> [!TIP] +> AWS管理コンソールの ECS > Clusters > KE2FargateCluster > Services リソースの配下に、KE2FargateService > Tasks、または CloudWatch からもログを確認できます。 + +#### コンテナへのシェルアクセス + +特定のコンテナにシェルアクセスするには、以下のコマンドを実行します。 + +```bash +$ aws ecs execute-command \ + --cluster KE2FargateCluster \ + --task <タスク ID/ARN> \ + --container <コンテナ名> \ + --interactive \ + --command "/bin/sh" +``` +> [!CAUTION] +> `<コンテナ名>`, および `<タスク ID/ARN>` は、実際の値に置き換えてください。 + +以下のコマンドでタスク ARNを習得できます。 +```bash +$ aws ecs list-tasks --cluster KE2FargateCluster --desired-status RUNNING --launch-type FARGATE --query "taskArns[]" --output text +``` +> [!TIP] +> AWS管理コンソールの ECS > Clusters > KE2FargateCluster > Services リソースの配下に、KE2FargateService > Tasks からも習得できます。 + +#### システムの削除・停止 + +■ 削除 +- `UseCustomVpc` が `false` の場合、以下のコマンドで、VPC から ECSクラスターおよび関連リソース、コンテナ、ログまで削除します。 +- `UseCustomVpc` が `true` の場合、以下のコマンドで、ECSクラスターおよび関連リソース、コンテナ、ログまで削除します。 + +```bash +$ aws cloudformation delete-stack --stack-name KE2ECSFargateStack +``` + +`UseECSService` が `false` の場合、コンテナタスクは ECS サービスによって自動的に管理されないため、実行中のタスクが存在する場合、KE2ECSFargateStack の ECS クラスターおよび関連リソースを削除することはできません。その場合は、まず以下のコマンドを使用してコンテナタスクを停止してください。 + +```bash +# <タスク ID/ARN>は、実際の値に置き換えてください。 +$ aws ecs stop-task --cluster KE2FargateCluster --task <タスク ID/ARN> +``` + + +KE2ECSFargateStackまたはKE2FargateClusterを削除ではなくコンテナタスクのみ停止・起動したい場合は、以下のコマンドも利用できます。 + +■ 停止 + +`UseECSService` が `true` の場合、コンテナタスクを直接に停止してもECSServiceで自動的に新タスクが起動されます。 +なので以下のコマンドでコンテナタスクを停止します。 +```bash +$ aws ecs update-service --cluster KE2FargateCluster --service KE2FargateService --desired-count 0 +``` + + +`UseECSService` が `false` の場合、以下のコマンドでコンテナタスクを停止できます。 +```bash +$ aws ecs stop-task --cluster KE2FargateCluster --task <タスク ID/ARN> +``` + +■ 起動・再起動 + +AWS Fargate はコンテナタスクの再起動機能をネイティブにサポートしていません。run-task および stop-task のみがサポートされており、run-task コマンドを実行すると新しいタスクが起動されます。 + +`UseECSService` が `true` の場合、以下のコマンドでコンテナタスクを起動できます。 +```bash +$ aws ecs update-service --cluster KE2FargateCluster --service KE2FargateService --desired-count 1 +``` + + +`UseECSService` が `false` の場合、以下のコマンドでコンテナタスクを起動できます。 +```bash +$ aws ecs run-task \ + --cluster KE2FargateCluster \ + --task-definition KE2Task \ + --launch-type FARGATE \ + --network-configuration "awsvpcConfiguration={subnets=[""],securityGroups=[""],assignPublicIp=ENABLED}" \ + --count 1 \ + --enable-execute-command +``` + +コンテナにアクセスしたい場合は、`--enable-execute-command` オプションを使用してください。 +> [!CAUTION] +> ``、`` は、実際の値に置き換えてください。 + +## 料金プラン +■ このデプロイメントでは、以下のスペックを使用します。 +- vCPU リソース:4 コア +- メモリ:16GB +- OS: Linux +- CPUアーキテクチャ: x86 +- タスクまたはポッドの数: 1 + +プランについては、[このリンクをご参照ください。](https://calculator.aws/#/createCalculator/Fargate) + +■ aws log を利用する場合、 AWS CloudWatch のコストも別途追加となります。プランについては、[このリンクをご参照ください。](https://aws.amazon.com/cloudwatch/pricing) + +■ AWS RDS インスタンス(PostgeSQL)を利用する場合、 RDS インスタンスのコストも別途追加となります。 + +PostgreSQL インスタンステンプレートがプロダクション(1 インスタンス)の場合、デフォルトのスペックは以下の通りです。 + +- DB インスタンスクラス: db.m7g.large +- デプロイオプション: Single-AZ +- ストレージボリューム: IOPS SSD IO2 +- ストレージ量: 400 GiB + +> [!NOTE] +> ストレージ容量は 400 GiBとなっていますが、用途に応じて変更いただいても問題ありません。 + +プランについては、[このリンクをご参照ください。](https://calculator.aws/#/createCalculator/RDSPostgreSQL) +