Amazon Web Services (AWS)
Seccions d'aquesta pàgina 25
- 01General
- 02Casos d'ús / Use cases
- 03LightSail
- 04WAF - Web Application Firewall
- 05Cloudformation
- 06SAM - Serverless Application Model
- 07IAM
- 08ACM (AWS Certificate Manager)
- 09EC2
- 10S3
- 11S3 Glacier
- 12Database
- 13Amazon MQ
- 14ECR (Elastic Container Registry)
- 15EKS
- 16CloudFront
- 17Route53
- 18VPC
- 19Big data and analytics
- 20CLI
- 21Boto ( Python )
- 22Mobile
- 23Kinesis Data Streams
- 24CloudWatch
- 25Lambda
01General#
- Amazon Web Services AWS (wp)
- Documentació / Documentation
- AWSome Day Barcelona (keynote) (26th Feb 2015)
- AWSome Day Barcelona (26th Feb 2015)
- Accés programàtic / Programmatic access
- Cost
- Simple month calculator
- Tracking the Cost of Your AWS CloudFormation Stack
- Amazon
EC2 Reserved Instances (RI)
- Reserved Instance Recommendations
- RI Utilization (Cost Explorer)
- Reports
- QuickSight
- Discount programmes
- Free Tier
- AWS Activate (for startups)
- AWS Architecture
Center
- AWS Reference Architecture
- Architecture Whitepapers from AWS
- Desatres / Disaster
- VPC (Virtual Private Cloud)
- Tags
- MFA tokens
- AWS Console
- Connecting to Your Linux/Unix Instances Using SSH
- Free tier
- How to find your AWS Access Key ID and Secret Access Key
- IAM (Identity and Access Management) users
- What is Auto Scaling?
- AWS from Django
- Tips
- Network
- Components
- Development
- API
- Error messages
- DecodeAuthorizationMessage
- Maybe from a rollback message in CloudFormation:
- API: ec2:RunInstances You are not authorized to perform this operation. Encoded authorization failure message: xxxxxx
- To decode message:
decoded_message=$(aws --profile my_profile sts decode-authorization-message --encoded-message xxxxxx)
echo $decoded_message | jq -r '.DecodedMessage' | jq ''
- Problems
- An error occurred (AccessDenied) when calling the DecodeAuthorizationMessage operation: User: arn:aws:iam::... is not authorized to perform: sts:DecodeAuthorizationMessage
- Solutions
- use a profile with more permissions (
--profile my_profile_with_permissions) - give ... permissions to used profile
- use a profile with more permissions (
- Alarmes / Alarms
- Rangs de xarxa / Network ranges
- AWS IP Address Ranges
- Exemples / Examples
wget https://ip-ranges.amazonaws.com/ip-ranges.json- CloudFront
jq -r '.prefixes[] | select(.region=="GLOBAL") | select(.service=="CLOUDFRONT") | .ip_prefix' < ip-ranges.json
- EC2, ELB for region eu-west-1
jq -r '.prefixes[] | select(.region=="eu-west-1") | select(.service=="EC2") | .ip_prefix' < ip-ranges.json
- Limits
- Documentation
- Real usage
- Service Quotas
- Trusted Advisor (monitor limits status)
- AWS CLI
- service-quotas
- list-services
aws --profile ... service-quotas list-services
- list-aws-default-service-quotas
aws --profile ... service-quotas list-aws-default-service-quotas --service-code cloudformation
- list-service-quotas
aws --profile ... service-quotas list-service-quotas --service-code cloudformation
- list-services
- service-quotas
- AWS CLI
- AWS CLI : discover your service limits from the command line
-
aws ...
autoscaling
describe-account-limits
{
"NumberOfLaunchConfigurations": 82,
"MaxNumberOfLaunchConfigurations": 200,
"NumberOfAutoScalingGroups": 6,
"MaxNumberOfAutoScalingGroups": 200
}
elb
describe-account-limits
{
"Limits": [
{
"Max": "20",
"Name": "classic-load-balancers"
},
{
"Max": "100",
"Name": "classic-listeners"
}
]
}
elbv2
describe-account-limits
Aquesta taula continua cap a la dreta — desplaça-la o gira el mòbil.
02Casos d'ús / Use cases#
- Use cases
- Digital Media
- Digital
Media
in the Cloud: Best Practices for Processing Media on AWS
(YouTube)
- Media processing in AWS (AWS)
- Cloud transcoding architecture
- Phase 1:
- Add transcoder instances to EC2
- Use S3 to store file-based sources
- Use S3 to store file-based outputs
- Use CloudFront to distribute output streams
- Phase 2:
- Use acceleration and/or Direct Connect for ingest
- Use Amazon Virtual Private Cloud to ringfence
- Use EC2 Reserved Instances
- Use EC2 Spot Instances
- Phase 3:
- Create a fleet of transcode workers
- Use your on-premise workflow controller to orchestrate using SWF
- Use SQS to create a cloud transcode queue
- Use SNS for notifications
- Phase 1:
- Securing content (14:00)
- Local encryption: encrypt and mantain your own keys
- Network encryption: use secured network transfer (SSL, VPC)
- At REST encryption: S3 encrypts at REST using AES-256
- DRM: integrate certificated-based DRM through third parties
- Watermarking: Integrate digital watermarking through third parties
- Cloud transcoding architecture
- Best practices for hybrid transcoding workflows (Elemental Technologies)
- Cloud-based content management (Ericsson)
- High performance media processing (Intel)
- Media processing in AWS (AWS)
- Digital
Media
in the Cloud: Best Practices for Processing Media on AWS
(YouTube)
03LightSail#
04WAF - Web Application Firewall#
- Info
- Structure
- web ACL
- rules
- own
rule groups
- rules
- managed
rule groups
- from
AWS (list)
- Baseline rule groups
- Core rule set (CRS): "Consider using this rule group for any AWS WAF use case."
- Admin protection
- Known bad inputs
- Use-case specific rule groups
- SQL database
- Linux operating system
- POSIX operating system
- Windows operating system
- PHP application
- WordPress application
- IP reputation rule groups
- Amazon IP reputation list
- Anonymous IP list
- AWS WAF Bot Control rule group
- AWS WAF Bot Control
- Baseline rule groups
- from marketplace
- from
AWS (list)
- web ACL
- Rate-based
- when a single IP address exceeds the configured maximum number of request during 5-minute period
- The
three most important AWS WAF rate-based rules
- Blanket rate-based rule: any IP address to any destination
- URI-specific rate-based rule: any IP address to some
destinations
- consider target_processing_time in ALB logs
- IP reputation rate-based rule: from specific IP addresses
- Apply rate-limiting to your resources using AWS Cloud-front and WAF
- Set up global rate limiting with AWS WAF in 5 minutes
- Custom response
- ...
05Cloudformation#
- AWS CloudFormation Product Details
- User
guide
- Getting started
- Working with templates
- Template anatomy
- Parameters
- AWS-specific parameter types
- List
- CommaDelimitedList
- Example
- single value:
Parameters:
MyAllowedInstanceTypes:
Description: Server allowed instances
Type: String
Default: "g5.*"
Resources:
MyGroup:
Type: AWS::AutoScaling::AutoScalingGroup
Properties:
MixedInstancesPolicy:
LaunchTemplate:
Overrides:
- InstanceRequirements:
AllowedInstanceTypes:
- Ref:MyAllowedInstanceTypes
- comma-separated values:
Parameters:
MyAllowedInstanceTypes:
Description: Server allowed instances
Type: CommaDelimitedList
Default: "g4dn.*,g5.*"
Resources:
MyGroup:
Type: AWS::AutoScaling::AutoScalingGroup
Properties:
MixedInstancesPolicy:
LaunchTemplate:
Overrides:
- InstanceRequirements:
AllowedInstanceTypes: !RefMyAllowedInstanceTypes
- single value:
- Example
- CommaDelimitedList
- Conditionally
assign a resource property
AWSTemplateFormatVersion: "2010-09-09"
Parameters:
...
DBSnapshotName:
Description: The name of a DB snapshot (optional)
Default: ""
Type: String...
Conditions:
UseDBSnapshot: !Not [!Equals [!Ref DBSnapshotName, ""]]
Resources:
MyDB:
Type: "AWS::RDS::DBInstance"
Properties:
DBSnapshotIdentifier: !If [UseDBSnapshot, !Ref DBSnapshotName, !Ref "AWS::NoValue"]
- Parameters
- Template anatomy
- Template reference
- Creation Policy
- Deploying Applications on Amazon EC2 with AWS CloudFormation
- Sample templates
- 19 Best Practices for Creating Amazon CloudFormation Templates
- Designer
- Preserve resources after stack destruction
- Delete Your Stacks But Keep Your Data
- template.json
"DeletionPolicy" : "Retain"
- Info
- Estructura / Structure (Learn
template basics)
- JSON
{
"AWSTemplateFormatVersion" : "2010-09-09",
"Description": "...",
"Parameters": {},
"Conditions": {},
"Resources": {},
"Outputs": {}
}
- YAML
- AWSTemplateFormatVersion:
"2020-09-09"
Description:
Parameters:
Resources:
Outputs:
- AWSTemplateFormatVersion:
"2020-09-09"
- lint
- cfn-lint
- command-line
- install
pip install cfn-lint- usage
cfn-lint my-template.yaml- emacs
- lsp-cfn.el
- dependencies:
- install
- ...
- usage
- Describe
- install
M-x package-installflycheck- setup
(use-package cfn-lint
:ensure t
:after (flycheck)
:hook (yaml-mode . cfn-lint-mode))- usage
- ...
- Equivalència:
JSON YAML {"Ref": a}# when used in the same line (*):
!Ref a
# otherwise:
Ref: a{"Fn::GetAttr": [a,b]}!GetAtt
- a
- b{"Fn::Join": [ "", [a,b,c] ]}!Join
- ''
- - a
- b
- c
MyKey:!Sub "${MyFirstParameter}${MySecondParameter}"MyKey:
Fn::Join:
- MyFirstParameter
- MySecondParameter
MyKey: !Ref MyParameter- MyKey: !Ref MyResource
- MyKey:
Ref: MyParameter
- MyKey:
Ref: MyResource
MyKey: !GetAtt 'MyResource.PropertyName'- MyKey:
Fn::GetAtt:
- MyResource
- PropertyName
Aquesta taula continua cap a la dreta — desplaça-la o gira el mòbil.
- JSON
- Comentaris / Comments
- Etiquetes / Tags
- How can I tag a root volume from an instance created by AWS CloudFormation?
- role permissions:
ec2:CreateTags
- from UserData in cloudformation template, call:
AWS_AVAIL_ZONE=$(curl http://169.254.169.254/latest/meta-data/placement/availability-zone)
AWS_REGION=${AWS_AVAIL_ZONE::-1}
AWS_INSTANCE_ID=$(curl http://169.254.169.254/latest/meta-data/instance-id)
ROOT_VOLUME_IDS=$(aws ec2 describe-instances --region $AWS_REGION --instance-id $AWS_INSTANCE_ID --output text --query Reservations[0].Instances[0].BlockDeviceMappings[0].Ebs.VolumeId)
aws ec2 create-tags --resources $ROOT_VOLUME_IDS --region $AWS_REGION --tags Key=MyRootTag,Value=MyRootVolumesValue
- CLI Cloudformation
- EC2
- Instance
- Volume
- VPC
AWS::EC2::VPC-
graph LR S(AWS::EC2::Subnet) --- SRTA[AWS::EC2::SubnetRouteTableAssociation] --> RT(AWS::EC2::RouteTable) RT --- R[AWS::EC2::Route] --> I(AWS::EC2::InternetGateway) V(AWS::EC2::VPC) --- VGA[AWS::EC2::VPCGatewayAttachment] --> I click S "https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-subnet.html" click RT "https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-routetable.html" click I "https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-internetgateway.html" click V "https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-vpc.html" click SRTA "https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-subnetroutetableassociation.html" click R "https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-route.html" click VGA "https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-vpcgatewayattachment.html" %% relacions sense estil classDef relacio fill:none,stroke:none,color:none class SRTA,R,VGA relacio
- ...
VPC (in a region) AZ zone (subregion) subnet (in a AZ zone) AWS::EC2::SecurityGroup "VpcId": String
AWS::EC2::Instance
"AvailabilityZone": String "SubnetId": String AWS::ElasticLoadBalancing::LoadBalancer (classic)
"AvailabilityZones": [String, ...] "Subnets": [String, ...] AWS::ElasticLoadBalancingV2::LoadBalancer (new: ALB, ...)
"Subnets": [String, ...] AWS::AutoScaling::AutoScalingGroup
"AvailabilityZones": [String, ...] "VPCZoneIdentifier": [String, ...] Aquesta taula continua cap a la dreta — desplaça-la o gira el mòbil.
- single EC2
instance
- single_ec2.json
{
"Description": "Single EC2 instance",
"AWSTemplateFormatVersion": "2010-09-09",
"Metadata": {},
"Resources": {
"singleEC2": {
"Type": "AWS::EC2::Instance",
"Properties": {
"ImageId":"ami-xxxxxxxx",
"KeyName":"my_key_pair",
"InstanceType":"t2.micro"
}
}
}
}
- single_ec2.json
- single ec2
instance with an extra volume
- single_ec2_volume.json
"Resources": {
...
"EC2Instance": {
"Type": "AWS::EC2::Instance",
"Properties": {
"ImageId":{"Ref" : "ImageId"},
"SecurityGroups" : [ { "Ref" : "InstanceSecurityGroup" } ],
"KeyName":"my_server_key",
"InstanceType":{"Ref" : "InstanceType"},
"UserData": {
"Fn::Base64": {
"Fn::Join" : [ "", [
"#!/bin/bash -xe\n",
"sudo mkfs -t xfs /dev/xvdh\n",
"sudo mkdir /mnt/vol\n",
"sudo chmod 777 /mnt/vol\n",
"sudo mount /dev/xvdh /mnt/vol\n",
] ]
}
},
"Tags":[{"Key":"Name","Value":{"Ref":"BaseName"}}]
}
},
...
"NewVolume" : {
"Type" : "AWS::EC2::Volume",
"Properties" : {
"Size" : "100",
"AvailabilityZone" : { "Fn::GetAtt" : [ "EC2Instance", "AvailabilityZone" ]}
}
},
"MountPoint" : {
"Type" : "AWS::EC2::VolumeAttachment",
"Properties" : {
"InstanceId" : { "Ref" : "EC2Instance" },
"VolumeId" : { "Ref" : "NewVolume" },
"Device" : "/dev/xvdh"
}
},
- single_ec2_volume.json
- single EC2 with
UserData
and extra volume
- Notes:
- When using direct bash commands:
- add "\n" at the end of each command
- no need to call sudo
- When using direct bash commands:
- single_ec2_userdata_volume.json
{
"Description": "Single EC2 instance with extra volume",
"AWSTemplateFormatVersion": "2010-09-09",
"Metadata": {},
"Parameters" : {
"InstanceType" : {
"Description" : "EC2 instance type",
"Type" : "String",
"Default" : "t2.micro",
"AllowedValues" : [ "t1.micro", "t2.micro", "t2.small", "t2.medium", "m1.small", "m1.medium", "m1.large", "m1.xlarge", "m2.xlarge", "m2.2xlarge", "m2.4xlarge", "m3.medium", "m3.large", "m3.xlarge", "m3.2xlarge", "c1.medium", "c1.xlarge", "c3.large", "c3.xlarge", "c3.2xlarge", "c3.4xlarge", "c3.8xlarge", "c4.large", "c4.xlarge", "c4.2xlarge", "c4.4xlarge", "c4.8xlarge", "g2.2xlarge", "r3.large", "r3.xlarge", "r3.2xlarge", "r3.4xlarge", "r3.8xlarge", "i2.xlarge", "i2.2xlarge", "i2.4xlarge", "i2.8xlarge", "d2.xlarge", "d2.2xlarge", "d2.4xlarge", "d2.8xlarge", "hi1.4xlarge", "hs1.8xlarge", "cr1.8xlarge", "cc2.8xlarge", "cg1.4xlarge"]
,
"ConstraintDescription" : "must be a valid EC2 instance type."
},
"HostedZone" : {
"Type" : "String",
"Description" : "The DNS name of an existing Amazon Route 53 hosted zone",
"AllowedPattern" : "(?!-)[a-zA-Z0-9-.]{1,63}(?<!-)",
"ConstraintDescription" : "must be a valid DNS zone name.",
"Default" : "example.net"
},
"ImageId" : {
"Type" : "String",
"Description" : "The image_id for the ec2 instance"
},
"NewVolumeSize" : {
"Type" : "String",
"Description" : "The size of the new volume (GB)",
"Default": "5"
}
},
"Resources": {
"EC2Instance": {
"Type": "AWS::EC2::Instance",
"Properties": {
"ImageId":{"Ref" : "ImageId"},
"SecurityGroups" : [ { "Ref" : "InstanceSecurityGroup" } ],
"KeyName":"wct_streaming_server",
"InstanceType":{"Ref" : "InstanceType"},
"UserData": {
"Fn::Base64": {
"Fn::Join" : [ "", [
"#!/bin/bash -xe \n",
"while [ ! -e /dev/xvdh ]; do echo waiting for /dev/xvdh to attach; sleep 10; done \n",
"mkfs -t xfs /dev/xvdh \n",
"mkdir -p /mnt/vol1 \n",
"mount /dev/xvdh /mnt/vol1 \n",
"chmod 777 /mnt/vol1 \n"
] ]
}
},
"Tags":[{"Key":"Name","Value":{"Ref":"BaseName"}}]
}
},
"NewVolume" : {
"Type" : "AWS::EC2::Volume",
"Properties" : {
"Size" : {"Ref" : "NewVolumeSize"},
"AvailabilityZone" : { "Fn::GetAtt" : [ "EC2Instance", "AvailabilityZone" ]}
}
},
"MountPoint" : {
"Type" : "AWS::EC2::VolumeAttachment",
"Properties" : {
"InstanceId" : { "Ref" : "EC2Instance" },
"VolumeId" : { "Ref" : "NewVolume" },
"Device" : "/dev/xvdh"
}
},
}
- Notes:
- single EC2 entry with
Route53
- single_ec2_r53.json
{
"Description": "Single EC2 instance",
"AWSTemplateFormatVersion": "2010-09-09",
"Metadata": {},
"Parameters" : {
"InstanceType" : {
"Description" : "EC2 instance type",
"Type" : "String",
"Default" : "m1.small",
"AllowedValues" : [ "t1.micro", "t2.micro", "t2.small", "t2.medium", "m1.small", "m1.medium", "m1.large", "m1.xlarge", "m2.xlarge", "m2.2xlarge", "m2.4xlarge", "m3.medium", "m3.large", "m3.xlarge", "m3.2xlarge", "c1.medium", "c1.xlarge", "c3.large", "c3.xlarge", "c3.2xlarge", "c3.4xlarge", "c3.8xlarge", "c4.large", "c4.xlarge", "c4.2xlarge", "c4.4xlarge", "c4.8xlarge", "g2.2xlarge", "r3.large", "r3.xlarge", "r3.2xlarge", "r3.4xlarge", "r3.8xlarge", "i2.xlarge", "i2.2xlarge", "i2.4xlarge", "i2.8xlarge", "d2.xlarge", "d2.2xlarge", "d2.4xlarge", "d2.8xlarge", "hi1.4xlarge", "hs1.8xlarge", "cr1.8xlarge", "cc2.8xlarge", "cg1.4xlarge"]
,
"ConstraintDescription" : "must be a valid EC2 instance type."
},
"HostedZone" : {
"Type" : "String",
"Description" : "The DNS name of an existing Amazon Route 53 hosted zone",
"AllowedPattern" : "(?!-)[a-zA-Z0-9-.]{1,63}(?<!-)",
"ConstraintDescription" : "must be a valid DNS zone name."
}
},
"Resources": {
"EC2Instance": {
"Type": "AWS::EC2::Instance",
"Properties": {
"ImageId":"ami-437da730",
"SecurityGroups" : [ { "Ref" : "InstanceSecurityGroup" } ],
"KeyName":"my_key_pair",
"InstanceType":"t2.micro"
}
},
"InstanceSecurityGroup" : {
"Type" : "AWS::EC2::SecurityGroup",
"Properties" : {
"GroupDescription" : "Enable SSH, HTTP, RTMP",
"SecurityGroupIngress" : [
{
"IpProtocol" : "tcp",
"FromPort" : "22",
"ToPort" : "22",
"CidrIp" : "0.0.0.0/0"
},
{
"IpProtocol" : "tcp",
"FromPort" : "80",
"ToPort" : "80",
"CidrIp" : "0.0.0.0/0"
},
{
"IpProtocol" : "tcp",
"FromPort" : "1935",
"ToPort" : "1935",
"CidrIp" : "0.0.0.0/0"
}
]
}
},
"MyDNSRecord" : {
"Type" : "AWS::Route53::RecordSet",
"Properties" : {
"HostedZoneName" : { "Fn::Join" : [ "", [{"Ref" : "HostedZone"}, "." ]]},
"Comment" : "DNS name for my instance.",
"Name" : { "Fn::Join" : [ "", [{"Ref" : "EC2Instance"}, ".", {"Ref" : "AWS::Region"}, ".", {"Ref" : "HostedZone"} ,"."]]},
"Type" : "A",
"TTL" : "900",
"ResourceRecords" : [ { "Fn::GetAtt" : [ "EC2Instance", "PublicIp" ] } ]
}
}
},
"Outputs" : {
"InstanceId" : {
"Description" : "InstanceId of the newly created EC2 instance",
"Value" : { "Ref" : "EC2Instance" }
},
"AZ" : {
"Description" : "Availability Zone of the newly created EC2 instance",
"Value" : { "Fn::GetAtt" : [ "EC2Instance", "AvailabilityZone" ] }
},
"PublicDNS" : {
"Description" : "Public DNSName of the newly created EC2 instance",
"Value" : { "Fn::GetAtt" : [ "EC2Instance", "PublicDnsName" ] }
},
"PublicIP" : {
"Description" : "Public IP address of the newly created EC2 instance",
"Value" : { "Fn::GetAtt" : [ "EC2Instance", "PublicIp" ] }
},
"DomainName" : {
"Description" : "Fully qualified domain name",
"Value" : { "Ref" : "MyDNSRecord" }
}
}
}
- single_ec2_r53.json
- EFS
- AWS::EFS::FileSystem
- AWS::EFS::MountTarget
- exemple
...
"Resources": {
"MyFileSystem" : {
"Type": "AWS::EFS::FileSystem",
"Properties": {
"PerformanceMode": "generalPurpose",
"FileSystemTags": [
{
"Key": "Name",
"Value": "my-fs"
}
]
}
},
"MyMountTargetSecurityGroup" : {
"Type" : "AWS::EC2::SecurityGroup",
"Properties" : {
"GroupDescription" : "Enable ports 2049 (nfs)",
"VpcId" : {"Ref" : "VPCId"},
"SecurityGroupIngress" : [
{
"IpProtocol" : "tcp",
"FromPort" : "2049",
"ToPort" : "2049",
"CidrIp" : {"Ref": "CidrSubnet"}
}
]
}
},
"MyMountTarget" : {
"Type": "AWS::EFS::MountTarget",
"Properties": {
"FileSystemId": { "Ref": "MyFileSystem" },
"SubnetId": { "Ref": "MySubnet" },
"SecurityGroups": [ { "Ref": "MyMountTargetSecurityGroup" } ]
}
},
...
"# mount efs from instance \n",
"# mount -t nfs4 -o nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2,noresvport ", {"Ref": "ProcessFileSystem"},".efs.",{"Ref" : "AWS::Region"},".amazonaws.com:/ /mnt/efs \n",
"mkdir -p /mnt/efs \n",
"echo ", {"Ref": "ProcessFileSystem"},".efs.",{"Ref" : "AWS::Region"},".amazonaws.com:/ /mnt/efs nfs4nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2,noresvport 0 0>>/etc/fstab \n",
"mount /mnt/efs \n",
...
}
- Route53
- Alarm
- Autoscaling group
- Recover
- S3
- AWS::S3
- AWS::S3::Bucket
"MyBucket": {
"Type": "AWS::S3::Bucket",
"Properties": {
"BucketName": "my-bucket-name",
"AccessControl": "PublicRead",
"CorsConfiguration": {
"CorsRules": [
{
"AllowedHeaders": [
"*"
],
"AllowedMethods": [
"GET",
"HEAD"
],
"AllowedOrigins": [
"*"
],
"ExposedHeaders": [],
"MaxAge": 3000
}
]
}
}
}
- AWS::S3::BucketPolicy
- ...
- ...
- AWS::S3::Bucket
- AWS::S3
- CloudFront
- AWS::CloudFront::Distribution
"PriceClass":"PriceClass_100"-> Use Only U.S., Canada and Europe"PriceClass_200"-> Use U.S., Canada, Europe, Asia and Africa"PriceClass_All"-> Use All Edge Locations (Best Performance)
- No cache for 404
"MyCloudFront" : {}
"Type" : "AWS::CloudFront::Distribution",
"Properties" : {
"DistributionConfig" : {
"CustomErrorResponses" : [ {
"ErrorCode" : "404",
"ErrorCachingMinTTL" : "2"
} ]
...
}
}
- Cache
behaviour
/ Forward headers: Whitelist
- Configuring CloudFront to Cache Objects Based on Request Headers
- To avoid problems with CORS and 403 response from CloudFront
"DefaultCacheBehavior" : {
"TargetOriginId" : { "Fn::Join" : [ "", ["S3-", {"Ref":"BucketName"}, "-my_dir" ] ]},
"CachePolicyId": "658327ea-f89d-4fab-a63d-7e88639e58f6",
"OriginRequestPolicyId": "88a5eaf4-2fd4-4709-b370-b4c650ea3fcf",
"ResponseHeaderPolicyId": "60669652-455b-4ae9-85a4-c4c02393f86c",
"AllowedMethods" : ["GET", "HEAD", "OPTIONS"],
"CachedMethods" : ["GET", "HEAD", "OPTIONS"],
"ViewerProtocolPolicy" : "allow-all"
},
- (ForwardedValues is deprecated; use CachePolicyId) To avoid problems with CORS and 403 response from CloudFront
"DefaultCacheBehavior" : {
"TargetOriginId" : { "Fn::Join" : [ "", ["S3-", {"Ref":"BucketName"}, "-my_dir" ] ]},
"ForwardedValues" : {
"Headers" : ["Origin","Access-Control-Request-Headers","Access-Control-Request-Method"],
"QueryString" : "false",
"Cookies" : { "Forward" : "none" }
},
"AllowedMethods" : ["GET", "HEAD", "OPTIONS"],
"CachedMethods" : ["GET", "HEAD", "OPTIONS"],
"ViewerProtocolPolicy" : "allow-all"
},
- Group of origins, to establish a fallback
"Origins": [
{"Id": "My-primary-origin",
...
},
{"Id": "My-secondary-origin",
...
}
],
"OriginGroups": {
"Items": [
{
"Id": "My-first-origin-group",
"FailoverCriteria": {"StatusCodes": {"Items": [403, 404], "Quantity": 2} },
"Members": {
"Items": [
{"OriginId": "My-primary-origin",
{"OriginId": "My-secondary-origin"}
],
"Quantity": 2
}
}
],
"Quantity": 1
},
"DeafultCacheBehavior": ...
- Full examples:
- Origin is S3, with whitelist for forwarded headers
("Origin"):
"Resources": {
"MyCloudFront" : {
"Type" : "AWS::CloudFront::Distribution",
"Properties" : {
"DistributionConfig" : {
"Origins" : [ {
"DomainName": { "Fn::Join" : [ "", [{"Ref":"BucketName"}, ".s3.amazonaws.com"]]},
"OriginPath": "my_dir",
"Id" : { "Fn::Join" : [ "", ["S3-", {"Ref":"BucketName"}, "-my_dir" ] ]},
"S3OriginConfig": {}
}],
"Enabled" : "true",
"Comment" : "My comments",
"DefaultCacheBehavior" : {
"TargetOriginId" : { "Fn::Join" : [ "", ["S3-", {"Ref":"BucketName"}, "-my_dir" ] ]},
"ForwardedValues" : {
"Headers" : ["Origin"],
"QueryString" : "false",
"Cookies" : { "Forward" : "none" }
},
"ViewerProtocolPolicy" : "allow-all"
},
"PriceClass" : "PriceClass_100"
}
}
}
},
- Origin is own http server, with no cache for 404
responses:
"Resources": {
"MyCloudFront" : {
"Type" : "AWS::CloudFront::Distribution",
"Properties" : {
"DistributionConfig" : {
"Origins" : [ {
"DomainName": "myserver.toto.org",
"OriginPath": "/root_dir",
"Id" : "oid-root_dir",
"CustomOriginConfig": {
"HTTPPort": "80",
"HTTPSPort": "443",
"OriginProtocolPolicy": "http-only"
}
}],
"Enabled" : "true",
"Comment" : "My comments",
"DefaultCacheBehavior" : {
"TargetOriginId" :"oid-root_dir",
"ForwardedValues" : {
"QueryString" : "false",
"Cookies" : { "Forward" : "none" }
},
"ViewerProtocolPolicy" : "allow-all"
},
"CustomErrorResponses" : [ {
"ErrorCode" : "404",
"ErrorCachingMinTTL" : "2"
} ],
"PriceClass" : "PriceClass_100"
}
}
}
},
- ...
- Origin is S3, with whitelist for forwarded headers
("Origin"):
- Amazon CloudFront Template Snippets
- Amazon CloudFront - Introduction
- AWS::CloudFront::Distribution
- LoadBalancer
-
Application Load Balancer Network Load Balancer
Classic Load Balancer protocols
HTTP, HTTPS, HTTP/2, WebSockets
TCP, UDP
HTTP, HTTPS, TCP, SSL
AWS::ElasticLoadBalancingV2::LoadBalancer
- Type: application
- Subnets
- ?
- ?
AWS::ElasticLoadBalancingV2::LoadBalancer
- Type: network
- Subnets
- ?
- ?
AWS::ElasticLoadBalancing::LoadBalancer
- AvailabilityZones
- HealthCheck
- LBCookieStickinessPolicy
- CookieExpirationPeriod
- AppCookieStickinessPolicy
- CookieName
TargetGroup
- "HealthCheckPath": "/mypath/",
"HealthCheckPort": "443",
"HealthCheckProtocol": "HTTPS",
"HealthCheckTimeoutSeconds": 5,
"UnhealthyThresholdCount": 5,
"HealthCheckIntervalSeconds": 30
LoadBalancer.HealthCheck Fn::GetAtt
CanonicalHostedZoneID
CanonicalHostedZoneNameID
DNSName
CanonicalHostedZoneName
LoadBalancerName
-
AWS::ElasticLoadBalancingV2::Listener
AWS::ElasticLoadBalancingV2::TargetGroup (TargetGroups)
Listeners
TargetGroup.TargetGroupAttributes (Sticky sessions for your Application Load Balancer)
- Key: ..., Value: ...
- (Atributes -> Target selection configuration -> Stickiness -> Stickiness type)
TargetGroup.TargetGroupAttributes - (Atributes -> Target selection configuration -> Stickiness -> Stickiness type)
Listener.PolicyNames (cookie stickiness, linked to LBCookieStickinessPolicy, AppCookieStickinessPolicy)
Listener.Certificates.CertificateArn
Listener.SSLCertificateId linked from ASG TargetGroupARNs
LoadBalancerNames Aquesta taula continua cap a la dreta — desplaça-la o gira el mòbil.
- Application Load Balancer
- Create and Configure AWS Application Load Balancer with CloudFormation
- a minimum of 2 subnets (in 2 different availability
zones) are needed
{
"Description": "Application load balancer",
"AWSTemplateFormatVersion": "2010-09-09",
"Metadata": {},
"Parameters" : {
"BaseName" : {
"Type" : "String",
"Description" : "The basename of the stack",
"Default": "basename"
},
"VPCId" : {
"Type" : "String",
"Description" : "Id of the used VPC",
"Default" : "vpc-de64aab8"
},
"AvailabilityZone" : {
"Description" : "Availability zone to try to deploy the resources to. Passing empty string will let AWS select the AZ. E.g.: eu-west-1a",
"Type" : "String",
"Default": "eu-west-1a"
},
"CidrSubnet" : {
"Type" : "String",
"Description" : "CIDR for the created subnet (must be a subset of VPC CIDR)",
"Default" : "10.1.1.0/27"
},
"SecondaryAvailabilityZone" : {
"Description" : "Secondary vailability zone to try to deploy the resources to. Passing empty string will let AWS select the AZ. E.g.: eu-west-1a",
"Type" : "String",
"Default": "eu-west-1b"
},
"CidrSecondarySubnet" : {
"Type" : "String",
"Description" : "Secondary CIDR for the created subnet (must be a subset of VPC CIDR)",
"Default" : "10.1.1.32/27"
},
"CertificateId" : {
"Type" : "String",
"Description" : "Certificate id"
}
},
"Resources": {
"PrimarySubnet" : {
"Type" : "AWS::EC2::Subnet",
"Properties" : {
"VpcId" : {"Ref" : "VPCId"},
"AvailabilityZone" : {"Ref" : "AvailabilityZone"},
"CidrBlock" : {"Ref":"CidrSubnet"},
"MapPublicIpOnLaunch" : "true",
"Tags" : [
{
"Key" : "Name",
"Value" : { "Fn::Join" : [ "", ["snet-", {"Ref" : "BaseName"}]]}
}
]
}
},
"SecondarySubnet" : {
"Type" : "AWS::EC2::Subnet",
"Properties" : {
"VpcId" : {"Ref" : "VPCId"},
"AvailabilityZone" : {"Ref" : "SecondaryAvailabilityZone"},
"CidrBlock" : {"Ref":"CidrSecondarySubnet"},
"MapPublicIpOnLaunch" : "true",
"Tags" : [
{
"Key" : "Name",
"Value" : { "Fn::Join" : [ "", ["snet-", {"Ref" : "BaseName"}, "-sec"]]}
}
]
}
},
"MyApplicationLoadBalancer": {
"Type" : "AWS::ElasticLoadBalancingV2::LoadBalancer",
"Properties" : {
"Name": "my-alb",
"Type": "application",
"IpAddressType": "ipv4",
"Subnets": [{"Ref" : "PrimarySubnet"}, {"Ref" : "SecondarySubnet"}],
"LoadBalancerAttributes": [
{"Key": "idle_timeout.timeout_seconds", "Value": 60}
]
}
},
"MyHTTPSListener": {
"Type": "AWS::ElasticLoadBalancingV2::Listener",
"Properties": {
"LoadBalancerArn": {"Ref" : "MyApplicationLoadBalancer"},
"Port": 443,
"Protocol": "HTTPS",
"Certificates": [{"Ref" : "CertificateId"}],
"DefaultActions": [
{
"Order": 1,
"Type": "forward",
"TargetGroupArn": {"Ref": "MyTargetGroup"}
}
]
}
},
"MyTargetGroup": {
"Type": "AWS::ElasticLoadBalancingV2::TargetGroup",
"Properties": {
"VpcId": {"Ref" : "VPCId"},
"TargetType": "instance",
"Name": "my-targetgroup",
"Port": 443,
"Protocol": "HTTPS"
}
}
}
}
- Network load balancer
- only one subnet is needed:
{
"Description": "Network load balancer",
"AWSTemplateFormatVersion": "2010-09-09",
"Metadata": {},
"Parameters" : {
"BaseName" : {
"Type" : "String",
"Description" : "The basename of the stack",
"Default": "nbasename"
},
"VPCId" : {
"Type" : "String",
"Description" : "Id of the used VPC",
"Default" : "vpc-de64aab8"
},
"AvailabilityZone" : {
"Description" : "Availability zone to try to deploy the resources to. Passing empty string will let AWS select the AZ. E.g.: eu-west-1a",
"Type" : "String",
"Default": "eu-west-1a"
},
"CidrSubnet" : {
"Type" : "String",
"Description" : "CIDR for the created subnet (must be a subset of VPC CIDR)",
"Default" : "10.1.3.0/27"
},
"CertificateId" : {
"Type" : "String",
"Description" : "Certificate id",
"Default" : "arn:aws:acm:eu-west-1:458626664701:certificate/c82f280a-8f5f-4d34-bbec-45e521724b60"
}
},
"Resources": {
"PrimarySubnet" : {
"Type" : "AWS::EC2::Subnet",
"Properties" : {
"VpcId" : {"Ref" : "VPCId"},
"AvailabilityZone" : {"Ref" : "AvailabilityZone"},
"CidrBlock" : {"Ref":"CidrSubnet"},
"MapPublicIpOnLaunch" : "true",
"Tags" : [
{
"Key" : "Name",
"Value" : { "Fn::Join" : [ "", ["snet-", {"Ref" : "BaseName"}]]}
}
]
}
},
"MyNetworkLoadBalancer": {
"Type" : "AWS::ElasticLoadBalancingV2::LoadBalancer",
"Properties" : {
"Name": "dev-my-nlb",
"Type": "network",
"IpAddressType": "ipv4",
"Subnets": [{"Ref" : "PrimarySubnet"}],
"LoadBalancerAttributes": [
]
}
},
"MyRTMPListener": {
"Type": "AWS::ElasticLoadBalancingV2::Listener",
"Properties": {
"LoadBalancerArn": {"Ref" : "MyNetworkLoadBalancer"},
"Port": 1935,
"Protocol": "TCP",
"DefaultActions": [
{
"Order": 1,
"Type": "forward",
"TargetGroupArn": {"Ref": "MyTargetGroup"}
}
]
}
},
"MyTargetGroup": {
"Type": "AWS::ElasticLoadBalancingV2::TargetGroup",
"Properties": {
"VpcId": {"Ref" : "VPCId"},
"TargetType": "instance",
"Name": "my-ntargetgroup",
"Port": 1935,
"Protocol": "TCP"
}
}
}
}
- only one subnet is needed:
- Classic Load Balancer
- listener with redirect ports http/80, http/8088,
https/8089, tcp/1935 and LBCookieStickinessPolicy:
"MyLoadBalancer": {
"Type": "AWS::ElasticLoadBalancing::LoadBalancer",
"Properties": {
"LoadBalancerName": "MyLoadbalancerName",
"SecurityGroups" : [ ... ],
"AvailabilityZones": {
"Fn::GetAZs": ""
},
"CrossZone": "true",
"ConnectionSettings": {
"IdleTimeout" : 60
}
"Listeners": [
{
"LoadBalancerPort": "80",
"InstancePort": "80",
"Protocol": "HTTP",
"PolicyNames": ["MyFirstLBCookieStickinessPolicy"]
},
{
"LoadBalancerPort": "8088",
"InstancePort": "8088",
"Protocol": "HTTP",
"PolicyNames": ["MySecondLBCookieStickinessPolicy"]
},
{
"LoadBalancerPort": "8089",
"Protocol": "HTTPS",
"InstancePort": "8089",
"InstanceProtocol": "HTTPS",
"SSLCertificateId": "arn:aws:acm:eu-west-1:...",
"PolicyNames": ["MySecondLBCookieStickinessPolicy"]
},
{
"LoadBalancerPort": "1935",
"InstancePort": "1935",
"Protocol": "TCP"
}
],
"LBCookieStickinessPolicy" : [
{
"CookieExpirationPeriod" : "500",
"PolicyName" : "MyFirstLBCookieStickinessPolicy"
},
{
"CookieExpirationPeriod" : "1000",
"PolicyName" : "MySecondLBCookieStickinessPolicy"
}
],
"HealthCheck": {
"Target": "HTTP:80/",
"HealthyThreshold": "3",
"UnhealthyThreshold": "5",
"Interval": "30",
"Timeout": "5"
}
}
}
- listener with a certificate from ACM
- ...
- listener with redirect ports http/80, http/8088,
https/8089, tcp/1935 and LBCookieStickinessPolicy:
- SecurityGroup
- UDP
-
- AutoScalingGroup
- Prerequisites (for LaunchConfig and LaunchTemplate):
- cfn-signal
- Download from:
- kixorz/ubuntu-cloudformation.json
- Install (Debian, Ubuntu)
- debian.template
apt-get install -y python3 pipx && pipx ensurepathpipx install https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-py3-latest.tar.gz
- debian.template
- Install (Python 3)
- ...
# install to /usr (e.g. /usr/bin/cfn-signal)
easy_install-3.6 --prefix /usr aws-cfn-bootstrap-py3-latest
- Install (Python 2)
mkdir aws-cfn-bootstrap-latestcurl https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-latest.tar.gz | tar xz -C aws-cfn-bootstrap-latest --strip-components 1easy_install aws-cfn-bootstrap-latest
- Problemes / Problems
Traceback (most recent call last):
File "/bin/easy_install", line 9, in <module>
load_entry_point('setuptools==0.9.8', 'console_scripts', 'easy_install')()
[...]
File "/usr/lib/python2.7/site-packages/setuptools/command/easy_install.py", line 701, in process_distribution
distreq.project_name, distreq.specs, requirement.extras
TypeError: __init__() takes exactly 2 arguments (4 given)- Diagnose
- python
>>> from pkg_resources import load_entry_point
>>> load_entry_point('setuptools==0.9.8', 'console_scripts', 'easy_install')()
...
pkg_resources.VersionConflict: (setuptools 25.1.4 (/usr/lib/python2.7/site-packages/setuptools-25.1.4-py2.7.egg), Requirement.parse('setuptools==0.9.8'))
- python
- Solució / Solution
sudo rm -rf /usr/lib/python2.7/site-packages/setuptools-25.1.4-py2.7.egg
- Diagnose
- You must install a UserData
on your instance (AMI) that generates a cfn-signal received by CreationPolicy
"LaunchConfig" : {
"Type" : "AWS::AutoScaling::LaunchConfiguration",
"Properties" : {
"ImageId":{"Ref" : "MyImageId"},
"SecurityGroups" : [ { "Ref" : "MySecurityGroup" } ],
"KeyName":"my_key",
"InstanceType":{"Ref" : "MyInstanceType"},
"IamInstanceProfile": "role_my_server",
"UserData": {
"Fn::Base64": {
"Fn::Join" : [ "", [
"#!/bin/bash -xe\n",
"/usr/bin/cfn-signal -e 0 --stack ", { "Ref": "AWS::StackName" },
" --resource MyAutoscalingGroup ",
" --region ", { "Ref" : "AWS::Region" }, "\n"
] ]
}
}
}
},
- cfn-signal
- Auto Scaling Template Snippets
- AutoScalingGroup
- AWS::AutoScaling::AutoScalingGroup
- CreationPolicy Attribute
- UpdatePolicy Attribute
- attach to a loadbalancer:
-
type
property
Classic Load Balancer
"LoadBalancerNames"Application Load Balancer
"TargetGroupARNs"
Aquesta taula continua cap a la dreta — desplaça-la o gira el mòbil.
-
- fallback instance types:
without fallback with fallback MyLaunchTemplate:
...
MyAutoScalingGroup:
Properties:
LaunchTemplate:
LaunchTemplateId: MyLaunchTemplate
Version:
Fn::GetAtt:
- MyLaunchTemplate
- DefaultVersionNumberMyLaunchTemplate:MyAutoscalingGroup:
...
Properties:
MixedInstancesPolicy:
InstancesDistribution:
OnDemandAllocationStrategy: prioritized
LaunchTemplate:
LaunchTemplateSpecification:
LaunchTemplateId: MyLaunchTemplate
Version:
Fn::GetAtt:
- MyLaunchTemplate
- DefaultVersionNumber
Overrides:
- InstanceType: g4dn.xlarge
- InstanceType: g3.4xlarge
- InstanceType: g3.8xlarge-
MyLaunchTemplate:
...
MyAutoscalingGroup:
Properties:
MixedInstancesPolicy:
InstancesDistribution:
OnDemandAllocationStrategy: lowest-price
LaunchTemplate:
LaunchTemplateSpecification:
LaunchTemplateId: MyLaunchTemplate
Version:
Fn::GetAtt:
- MyLaunchTemplate
- DefaultVersionNumber
Overrides:- InstanceRequirements:
AllowedInstanceTypes:
- g5.*
MemoryMiB:
Min: 32768
VCpuCount:
Min: 8
Aquesta taula continua cap a la dreta — desplaça-la o gira el mòbil.
- example.json
"MyAutoScalingGroup" : {
"Type" : "AWS::AutoScaling::AutoScalingGroup",
"Properties" : {
"LaunchConfigurationName" : { "Ref" : "MyLaunchConfig" },
"MinSize" : "1",
"MaxSize" : "3",
"LoadBalancerNames" : [ { "Ref" : "MyLoadBalancer" } ],
"Tags":[
{
"Key":"Name",
"Value":{ "Fn::Join" : [ "", ["myinstance-", {"Ref" : "MyName"}]]},
"PropagateAtLaunch" : "true"
}
]
},
"CreationPolicy" : {
"ResourceSignal" : {
"Timeout" : "PT15M",
"Count" : "1"
}
},
"UpdatePolicy": {
"AutoScalingRollingUpdate": {
"MinInstancesInService": "1",
"MaxBatchSize": "1",
"PauseTime" : "PT15M",
"WaitOnResourceSignals": "true"
}
}
},
- example_with_launch_template.json (create a single
instance of type, in order of preference: t3.micro or
t3.small or t3.medium; t3.nano is not used)
{
"AWSTemplateFormatVersion" : "2010-09-09",
"Description": "Tetst asg",
"Parameters": {},
"Resources": {
"MyLaunchTemplate": {
"Type": "AWS::EC2::LaunchTemplate",
"Properties": {
"LaunchTemplateData": {
"ImageId" : "ami-xxx",
"InstanceType" : "t3.nano",
"IamInstanceProfile": {"Name": "role_my_server"},
"UserData": {
"Fn::Base64": {
"Fn::Join" : [
"",
[
"#!/bin/bash -xe\n",
"sudo mkdir /mnt/toto \n",
"sudo chmod 777 /mnt/toto \n"
]
]
}
}
}
}
},
"MyGroup": {
"Type" : "AWS::AutoScaling::AutoScalingGroup",
"Properties": {
"MinSize": "1",
"MaxSize": "1",
"DesiredCapacity" : "1",
"AvailabilityZones" : ["eu-west-1a","eu-west-1b","eu-west-1c"],
"MixedInstancesPolicy": {
"InstancesDistribution": {
"OnDemandAllocationStrategy": "prioritized"
},
"LaunchTemplate": {
"LaunchTemplateSpecification": {
"LaunchTemplateId": {
"Ref": "MyLaunchTemplate"
},
"Version" : {
"Fn::GetAtt": ["MyLaunchTemplate", "DefaultVersionNumber"]
}
},
"Overrides": [
{"InstanceType": "t3.micro"},
{"InstanceType": "t3.small"},
{"InstanceType": "t3.medium"}
]
}
}
}
}
}
}
- AWS::AutoScaling::AutoScalingGroup
- ScalingPolicy
- Alarm
- AWS::...
- example.json
"MyUpScalingPolicy" : {
"Type" : "AWS::AutoScaling::ScalingPolicy",
"Properties" : {
"AdjustmentType" : "ChangeInCapacity",
"AutoScalingGroupName" : { "Ref" : "MyAutoScalingGroup" },
"Cooldown" : "60",
"ScalingAdjustment" : "1"
}
},
"MyCPUHighAlarm": {
"Type": "AWS::CloudWatch::Alarm",
"Properties": {
"EvaluationPeriods": "1",
"Statistic": "Average",
"Threshold": "80",
"AlarmDescription": "Alarm if CPU too high or metric disappears indicating instance is down",
"Period": "60",
"AlarmActions": [ { "Ref": "MyUpScalingPolicy" } ],
"Namespace": "AWS/EC2",
"Dimensions": [ {
"Name": "AutoScalingGroupName",
"Value": { "Ref": "MyAutoScalingGroup" }
} ],
"ComparisonOperator": "GreaterThanThreshold",
"MetricName": "CPUUtilization"
}
},
- Launch
-
response from:
autoscaling describe-auto-scaling-groups --auto-scaling-group-names ...UserData cfn-signal LaunchTemplate (new) "LaunchTemplate": {
"LaunchTemplateId": "...",
"LaunchTemplateName": "...",
"Version": "$Default"
}
needed in UserData LaunchConfiguration (old) "LaunchConfigurationName": "..."
needed in UserData Aquesta taula continua cap a la dreta — desplaça-la o gira el mòbil.
- LaunchTemplate (deprecates LaunchConfiguration)
- LaunchConfiguration
(use LaunchTemplate
instead) (deprecated by end 2022)
- Amazon EC2 Auto Scaling will no longer add support for new EC2 features to Launch Configurations
- AWS::AutoScaling::LaunchConfiguration
- InstanceMonitoring (detailed monitoring)
- auto_scaling_with_instance_profile.template
- AWS::IAM::InstanceProfile
- Associating an existing IAM role with AWS::EC2::Instance in CloudFormation
- Tags
- Tags should be defined at AutoscalingGroup:
- PassRole permission
- Granting Permission to Launch EC2 Instances with IAM Roles (PassRole Permission)
- needed when using
IamInstanceProfile - passos / steps
- create a role that will be used by
Cloudformation:
- IAM -> Roles
- create a new role
- copy the Role ARN (it will be used
at Resource in PassRoleMyServer):
arn:aws:iam::xxxxxxxxxx:role/role-my_server
- IAM -> Roles
- create a policy
- IAM -> Policies
- Filter: Customer Managed Policies
- Create Policy
- PassRoleMyServer
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1454093987000",
"Effect": "Allow",
"Action": [
"iam:PassRole"
],
"Resource": [
"arn:aws:iam::xxxxxxxxxx:role/role-my_server"
]
}
]
}
- PassRoleMyServer
- IAM -> Policies
- associate this policy to your group or
role:
- IAM -> Groups/Roles ->
Permissions -> Attach policy
- PassRoleMyServer
- IAM -> Groups/Roles ->
Permissions -> Attach policy
- create a role that will be used by
Cloudformation:
-
- Example:
- my_scaling.json
- ...
- my_scaling.json
- Prerequisites (for LaunchConfig and LaunchTemplate):
- ElastiCache
- EKS
- ...
- ...
06SAM - Serverless Application Model#
- What
is the AWS Serverless Application Model (AWS SAM)?
- desplegament de serverless applications
- cal docker local per a fer el build que finalment es desplegarà
- Templates amb un llenguatge semblant al de CloudFormation, però de nivell més alt; acaba generant un template de CloudFormation
- ...
07IAM#
- IAM
Roles
- Using an IAM Role to Grant Permissions to Applications Running on Amazon EC2 Instances
- IAM
Roles
for Amazon EC2
curl http://169.254.169.254/latest/meta-data/iam/security-credentials/curl http://169.254.169.254/latest/meta-data/iam/security-credentials/my_role_name
- Certificats de servidor / Server
certificates
- Consider new alternative: AWS Certificate Manager (ACM)
- Working with Server Certificates
- Limitations on IAM Entities and Objects
- CLI IAM: server
certificates (
aws iam) - Get Alerts for Expiring SSL Certificates
- Usuaris / Users
- Permisos a S3 / S3 permissions
08ACM (AWS Certificate Manager)#
- What Is AWS Certificate Manager?
- CLI:
aws acm - Can be used in:
- LoadBalancer
- Example with Cloudformation
- CloudFront
- must be requested from region N.Virginia
- LoadBalancer
09EC2#
- Amazon EC2 instances
- ec2instances.info
-
general purpose (>=large: 4GB/vcpu) compute optimized (2GB/vcpu) memory optimized
t3 (5Gb/s) t4g (Graviton ARM) (CentOS 7) (5Gb/s) m5 m6i (CentOS 7) m6g (10,12,20,25Gb/s) c5 c6g (CentOS 7) r6g x nano t3.nano: 2/0.5 (0.0057) t4g.nano: 2/0.5 (0.0046) - - - - -
micro t3.micro: 2/1 (0.0114) t4g.micro: 2/1 (0.0092) - - - - -
small t3.small: 2/2 (0.0228) t4g.small: 2/2 (0.0184) - - - - -
medium t3.medium: 2/4 (0.0456) t4g.medium: 2/4 (0.0368) - - m6g.medium: 1/4 (0.043) - c6g.medium: 1/2 (0.0384)
large t3.large: 2/8 (0.0912) t4g.large: 2/8 (0.0736) m5.large: 2/8 (0.107) m6i.large: 2/8 (0.107) m6g.large: 2/8 (0.086) c5.large: 2/4 (0.096) c6g.large: 2/4 (0.0768)
xlarge t3.xlarge: 4/16 (0.1824) t4g.xlarge: 4/16 (0.1472) m5.xlarge: 4/16 (0.214) m6i.xlarge: 4/16 (0.214) m6g.xlarge: 4/16 (0.172) c5.xlarge: 4/8 (0.192) c6g.xlarge: 4/8 (0.1536)
2xlarge t3.2xlarge: 8/32 (0.3648) t4g.2xlarge: 8/32 (0.2944) m5.2xlarge: 8/32 (0.428) m6i.2xlarge: 8/32 (0.428) m6g.2xlarge: 8/32 (0.344) c5.2xlarge: 8/16 (0.384) c6g.2xlarge: 8/16 (0.3072)
4xlarge - - m5.4xlarge: 16/64 (0.856) m6i.4xlarge: 16/64 (0.856) m6g.4xlarge: 16/64 (0.688) c5.4xlarge: 16/32 (0.768) c6g.4xlarge: 16/32 (0.6144)
8xlarge - - m5.8xlarge: 32/128 (1.712) m6i.8xlarge: 32/128 (1.712) m6g.8xlarge: 32/128 (1.376) c5.9xlarge: 36/72 (1.728) c6g.8xlarge: 32/64 (1.2288)
12xlarge - - m5.12xlarge: 48/192 (2.568) m6i.12xlarge: 48/192 (2.568) m6g.12xlarge: 48/192 (2.064) c5.12xlarge: 48/96 (2.304) c6g.12xlarge: 48/96 (1.8432)
16xlarge - - m5.16xlarge: 64/256 (3.424) m6i.16xlarge: 64/256 (3.424) m6g.16xlarge: 64/256 (2.752) c5.18x: 72/144 (3.456) c6g.16xlarge: 64/128 (2.4576)
24xlarge - - m5.24xlarge: 96/384 (5.136) m6i.24xlarge: 96/384 (5.136) - c5.24xlarge: 96/192 (4.608) -
32xlarge - - - m6i.32xlarge: 128/512 (6.848) - - -
Aquesta taula continua cap a la dreta — desplaça-la o gira el mòbil.
- Service Health Dashboard
- Free tier eligible
- Amazon Linux AMI 2014.03 (yum)
- Red Hat Enterprise Linux 6.4
- SuSE Linux Enterprise Server 11 sp3
- Ubuntu Server 12.04 LTS
- Ubuntu Server 13.10
- Nitro-based instances
- lslblk
nvme0n1
- lslblk
- Elastic Network Adapter (ENA)
- used by e.g. c5, t3 instance types
- Enabling
Enhanced Networking with the Elastic Network Adapter (ENA)
on Linux Instances
- check instance ENA installation
ssh ...sudo modinfo ena- ethtool -i
eth0
- driver: ena
- check instance ENA support
instance_id=...
aws ec2 describe-instances --instance-ids ${instance_id} --query "Reservations[].Instances[].EnaSupport"
- check AMI ENA support
ami_id=...
aws ec2 describe-images --image-id ${ami_id} --query "Images[].EnaSupport"
- steps
- check ENA kernel module
sudo modinfo ena- CentOS: if not available, update the kernel
sudo yum install kernel
- check systemd version
rpm -qa | grep -e '^systemd-[0-9]\+\|^udev-[0-9]\+'
- if it is greater or equal than 197, disable
predictable network interface names:
sudo sed -i '/^GRUB\_CMDLINE\_LINUX/s/\"$/\ net\.ifnames\=0\"/' /etc/default/grubsudo grub2-mkconfig -o /boot/grub2/grub.cfg
- stop instance
- from local computer:
- set ENA support:
instance_id=...
aws ec2 modify-instance-attribute --instance-id ${instance_id} --ena-support
- check ENA support:
aws ec2 describe-instances --instance-ids ${instance_id} --query "Reservations[].Instances[].EnaSupport"- should return True
- set ENA support:
- change instance type to c5 or t3
- start instance
- you may need to update Route53 with the new public ip address
- to create an AMI from this one:
- connect to your new instance:
ssh ...
sudo rm /etc/udev/rules.d/70-persistent-net.rules- stop instance
- create AMI: Actions -> Image -> Create image
- check that AMI has ENA enabled:
ami_id=...
aws ec2 describe-images --image-id ${ami_id} --query "Images[].EnaSupport"- should return True
- connect to your new instance:
- check ENA kernel module
- check instance ENA installation
- cloud-init
- How do I set up cloud-init on custom AMIs in AWS? (CentOS)
- Installation
sudo dnf install cloud-init
- Docs
- Boot
stages
-
systemd service journalctl -f/var/log/cloud-init-output.log 1. Detect
2. Local cloud-init-local.service Starting Initial cloud-init job (pre-networking)...
Finished Initial cloud-init job (pre-networking).running 'init-local'3. Network cloud-init.service Starting Initial cloud-init job (metadata service crawler)...
Finished Initial cloud-init job (metadata service crawler).running 'init'4. Config cloud-config.service Starting Apply the settings specified in cloud-config...
Finished Apply the settings specified in cloud-config.running 'modules:config'
Reached target Multi-User System.
5. Final cloud-final.service Starting Execute cloud user/final scripts...
Finished Execute cloud user/final scripts.running 'modules:final'Aquesta taula continua cap a la dreta — desplaça-la o gira el mòbil.
-
- Boot
stages
- Usage
- CLI Interface
- when an error appears at
/var/log/cloud-init-output.log, e.g.:
util.py[WARNING]: Running module scripts-user (<module 'cloudinit.config.cc_scripts_user' from '/usr/lib/python3.6/site-packages/cloudinit/config/cc_scripts_user.py'>) failed
- and you want to rerun scripts_user
(/var/lib/cloud/instance/scripts/*), you must first
delete the semaphore before running the final module
(which contains scripts_user, as stated by
/etc/cloud/cloud.cfg):
rm -f /var/lib/cloud/instance/sem/config_scripts_usercloud-init --debug modules --mode final
- hint: check that all commands executed in your scripts
(/var/lib/cloud/instance/scripts/*) return a 0 and not a
1 (
echo $?). If one of them returns 1, the script will immediately fail
- Network bandwidth
- Testing Amazon EC2 network speed
- Boosting
Amazon
EC2 Network for High Throughput
- Low – Up to 100 Mbps
- Moderate – 100 Mbps to 300 Mbps
- High – 100 Mbps to 1.86 Gbps
- 10Gb – upto 8.86Gbps
- Reboot
- Alarms
- Volumes: EBS
- Xifratge / Encryption
- Making
an
Amazon EBS Volume Available for Use
- get list of available drives
lsblkNAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
xvda 202:0 0 10G 0 disk
??xvda1 202:1 0 10G 0 part /
xvdg 202:96 0 20G 0 disk
- get mountability of drives
sudo file -s /dev/xvdg- "
/dev/xvdg: SGI XFS filesystem data (blksz 4096, inosz 256, v2 dirs)"- ready to mount
- "
/dev/xvdg: data"- you need to create filesystem (e.g. XFS):
sudo mkfs -t xfs /dev/xvdg
- you need to create filesystem (e.g. XFS):
- "
- mount the drive
- temporarily
mkdir /mnt/my_pointmount/dev/xvdg/mnt/my_point
- permanently
- /etc/fstab
/dev/xvdg/mnt/my_point xfs defaults 0 0
- /etc/fstab
- temporarily
- get list of available drives
- Redimensionament / Resize
- Amazon
EBS Elastic Volumes
- Amazon EBS Update – New Elastic Volumes Change Everything
- Automating Amazon EBS Volume-resizing with AWS Step Functions and AWS Systems Manager
- Ebs Auto Resize
- IMPORTANT:
An error occurred (VolumeModificationRateExceeded) when calling the ModifyVolume operation: You've reached the maximum modification rate per volume limit. Wait at least 6 hours between modifications per EBS volume.
- Passos / Steps
- Comproveu la mida inicial / Check original
size:
lsblk- voleu modificar la partició dins d'un disc
/ you want to modify a partition in a disk:
- NAME
MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
nvme0n1 259:1 0 20G 0 disk
??nvme0n1p1 259:2 0 20G 0 part /
- NAME
MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
- voleu modificar un disc sense particions /
you want to modify a disk without
partitions:
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
nvme1n1 259:0 0 20G 0 disk /mnt/vol1
- Modifiqueu la mida del volum AWS / Modify AWS
volume size (e.g. from 20GB to 25GB):
- AWS console:
- Volumes -> Modify
- CLI
- ...
- boto3
- ...
- AWS console:
- Espereu que el disc estigui a punt: passarà de l'estat «modifying» a «optimizing». Encara que el percentatge a «optimizing» sigui 0%, ja podeu passar al següent pas / Wait for disk to be ready: it will go from "modifying" to "optimizing". Even if percentage of optimizing is 0%, you can now proceed with the next step
- Comproveu els canvis al disc / Check changes
on disk:
lsblk- NAME
MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
nvme0n1 259:1 0 25G 0 disk
??nvme0n1p1 259:2 0 20G 0 part / NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
nvme1n1 259:0 0 25G 0 disk /mnt/vol1
- Feu créixer la partició (si n'hi ha) / Grow
partition (if any):
- si el disc té una partició, feu créixer la
que volgueu. Per exemple, per a fer créixer
la primera (1) partició del disc
/dev/nvme0n1 (és a dir nvme0n1p1)
/ if disk has any partition on it, grow the
desired partition. E.g. to grow first (1)
partition of disk /dev/nvme0n1 (i.e. nvme0n1p1)
- CentOS
sudo yum install ...
growpart /dev/nvme0n1 1- check changes with lsblk:
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
nvme0n1 259:1 0 25G 0 disk
??nvme0n1p1 259:2 0 25G 0 part /
- CentOS
- si el disc no té cap particio, aneu al pas següent / if disk has no partition, you can proceed with the next step
- si el disc té una partició, feu créixer la
que volgueu. Per exemple, per a fer créixer
la primera (1) partició del disc
/dev/nvme0n1 (és a dir nvme0n1p1)
/ if disk has any partition on it, grow the
desired partition. E.g. to grow first (1)
partition of disk /dev/nvme0n1 (i.e. nvme0n1p1)
- Amplieu el sistema de fitxers / Extend file
system (parameter for xfs_growfs is the mount
point: /, /mnt/vol1 ...):
- comproveu el tipus de sistema de fitxers
utilitzat / check the used filesystem (e.g.
ext4, xfs...):
df -hT
- ext2, ext3, ext4
resize2fs /dev/sda1
- xfs
sudo yum install xfsprogs
sudo xfs_growfs -d /sudo xfs_growfs -d /mnt/vol1
- comproveu el tipus de sistema de fitxers
utilitzat / check the used filesystem (e.g.
ext4, xfs...):
- Comproveu el resultat final / Check the final
result:
df -h- Filesystem
Size Used Avail Use% Mounted on
/dev/nvme0n1p1 25G 18G 7.7G 70% /
/dev/nvme1n1 25G 12G 13G 49% /mnt/vol1
- Filesystem
Size Used Avail Use% Mounted on
- Comproveu la mida inicial / Check original
size:
- check_disk.sh
#!/bin/bash
# usage threshold: 80%
usage_threshold=80
# instance_id
instance_id="id-1234"
#instance_id=$(curl -m 2 -s http://169.254.169.254/latest/meta-data/instance-id/)
# resize factor
resize_factor=1.5
# check local (not efs-mounted) disk usage
full_disks=$(df --local --output=source,fstype,pcent,target | tail -n +2 | awk -v usage_threshold=${usage_threshold} '{gsub(/%/,"",$3)} $3+0 >= usage_threshold {print $1 " " $2 " " $3 " " $4}')
# if needed, resize on AWS and resize partition/disk
while IFS= read -r linia
do
if (( ${#linia} > 0 ))
then
echo "-- ${linia}"
# split line using bash array
array_df_line=(${linia// / })
device_name=${array_df_line[0]}
fs_type=${array_df_line[1]}
usage=${array_df_line[2]}
mount_point=${array_df_line[3]}
# 1. change aws ebs volume size
echo " 1. change volume size: /usr/local/bin/aws_resize_volume.py --instance-id ${instance_id} --device-name ${device_name} ${resize_factor}"
# grow partition (if any) (e.g. nvme0n1p1)
# get partition from device name
# - /dev/nvme0n1p1 is a partition and needs to be grown
# - /dev/nvme1n1 is not a partition and does not need to be grown
# lsblk --inverse --nodeps
# NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
# nvme0n1p1 259:2 0 25G 0 part /
# nvme1n1 259:0 0 25G 0 disk /disc1
# 2. grow partition (if any)
short_device_name=${device_name##*/}
# get only entry if TYPE is part (not when TYPE is disk)
partition=$(lsblk --inverse --nodeps | awk -v pattern=${short_device_name} '$1 ~ pattern && $6 ~ /part/ {print $1}')
if [ -v partition ]
then
# /dev/nvme0n1p1: growpart /dev/nvme0n1 1
# /dev/sda1: growpart /dev/sda 1
device_name_partition_index=${device_name: -1}
device_name_without_partition_index=${device_name: : -1}
device_name_root=${device_name_without_partition_index%p*}
echo " 2. grow partition: sudo growpart ${device_name_root} ${device_name_partition_index}"
else
echo " 2. no partition"
fi
# 3. grow filesystem
case ${fs_type} in
"xfs" )
echo " 3. grow filesystem: sudo xfs_growfs -d ${mount_point}"
;;
"ext4" )
echo " 3. grow filesystem: sudo resize2fs ${mount_point}"
;;
* ) echo " 3. unknown filesystem ${fs_type}"
;;
esac
fi
done < <(echo "${full_disks}")
exit 0
- How to Resize AWS EC2 EBS Volumes
- Amazon
EBS Elastic Volumes
- LVM
- Swap
- Instance Store Swap Volumes
- How do you add swap to an EC2 instance?
- Check
- cat /proc/meminfo
SwapTotalSwapFree
- cat /proc/meminfo
- Methods
- File
sudo dd if=/dev/zero of=/swapfile bs=1M count=1024sudo mkswap /swapfilesudo chmod 0600 /swapfilesudo swapon /swapfilesudo echo "/swapfile swap swap defaults 0 0" >>/etc/fstab
- Instance Storage (certain instance types)
- File
- Management
- list of devices acting as swap
swapon -s
- list of devices acting as swap
- EFS
(Elastic File System)
- NFS
- Managing file system network accessibility
- Walkthrough 1: Create Amazon EFS File System and Mount It on an EC2 Instance Using the AWS CLI
- Creació / Creation
- Console
- ...
- Network:
- add a security group with port 2049 open for your Cidr
- CloudFormation EFS
- CLI EFS
- Console
- mount efs from an instance
- Mounting
on Amazon EC2 with a DNS Name
- detailed instructions can be obtained from console:
"Attach" button on top right
file_system_id=""
aws_region="eu-west-1"
sudo mkdir -p /mnt/efs
# in order to fs_dns_name to work, the VPC must have both DNS hostnames and DNS resolution enabled
fs_dns_name=${file_system_id}.efs.${aws_region}.amazonaws.com# mount once:
mount -t nfs4 -o nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2,noresvport ${fs_dns_name}:/ /mnt/efs
# permanent mount
echo ${fs_dns_name}:/ /mnt/efs nfs4nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2,noresvport 0 0>>/etc/fstabmount /mnt/efs- Problemes / Problems
- not mounted
- check that port 2049 is accessible:
nmap -p 2049 ${fs_dns_name}- if response is "filtered", then you need to open the port in the security group associated to the mount target
- check that port 2049 is accessible:
- not mounted
- Mounting
on Amazon EC2 with a DNS Name
- AMI (images)
- Removal
- When deleting (deregister) an AMI, the corresponding snapshot is not deleted
- When trying to delete a snapshot attached to an AMI, an error is shown. Therefore, you can safely (try to) remove all snapshots; those which are attached to an AMI will not be removed.
- IMPORTANT: when deleting an AMI, if its is attached to a Launch Configuration, this will not be checked by AWS, and LaunchConfiguration will point to a non-existing AMI!
- Removal
- Auto
Scaling
- CLI:
aws autoscaling - Termination
- Proteccció / Protection
- Removal:
- When deleting an autoscaling group, the corresponding launch configuration is not deleted
- When trying to delete a launch configuration attached to an autoscaling group, an error is shown. Therefore, you can safely (try to) remove all launch configurations; those which are attached to an autoscaling group will not be removed.
- Amazon
EC2 Auto Scaling lifecycle hooks
- amazon-ec2-auto-scaling-group-examples/features/lifecycle-hooks/
- CLI:
- userdata:
pas de paràmetres en
crear una instància / pass parameters when creating an instance
- Instance metadata and user data
- How to pass environment variables when programmatically starting a new Amazon EC2 from image?
- Automate EC2 Instance Setup with user-data Scripts
- Setting environment variables with user-data
- Logs
/var/log/cloud-init.log/var/log/cloud-init-output.log
- metadades / metadata
- Instance Metadata and User Data
- des de la instància / from ec2 instance:
curl http://169.254.169.254/latest/curl http://169.254.169.254/latest/user-data/curl http://169.254.169.254/latest/meta-data/public-keys/curl http://169.254.169.254/latest/meta-data/public-ipv4local_ipv4=$(curl http://169.254.169.254/latest/meta-data/local-ipv4/)instance_id=$(curl http://169.254.169.254/latest/meta-data/instance-id/)ami_id=$(curl -s http://169.254.169.254/latest/meta-data/ami-id)-
dynamic/ instance-identity/ document {
"accountId" : "...",
"architecture" : "x86_64",
"availabilityZone" : "eu-west-1b",
"billingProducts" : null,
"devpayProductCodes" : null,
"marketplaceProductCodes" : [ "..." ],
"imageId" : "ami-...",
"instanceId" : "i-...",
"instanceType" : "g4dn.2xlarge",
"kernelId" : null,
"pendingTime" : "2022-04-14T10:23:04Z",
"privateIp" : "...",
"ramdiskId" : null,
"region" : "eu-west-1",
"version" : "2017-09-30"
}
pkcs7
rsa2048
signature
meta-data/ ami-id
ami-launch-index
ami-manifest-path
autoscaling/ target-lifecycle-state
block-device-mapping/ ami
ebs1
events/ maintenance/ history
hostname
iam/ info {
"Code" : "Success",
"LastUpdated" : "2022-04-14T11:06:11Z",
"InstanceProfileArn" : "arn:aws:iam::...",
"InstanceProfileId" : "..."
}
identity-credentials/ ec2/ info ...
instance-action
instance-id
instance-life-cycle
instance-type
local-hostname
local-ipv4
mac
metrics/ vhostmd
network/ interfaces/ macs/ xx:xx:xx:xx:xx:xx/ device-number
interface-id
ipv4-associations/
local-hostname
local-ipv4s
mac
owner-id
public-hostname
public-ipv4s
security-group-ids
security-groups
subnet-id
subnet-ipv4-cidr-block
vpc-id
vpc-ipv4-cidr-block
vpc-ipv4-cidr-blocks
placement/ availability-zone
availability-zone-id
region
product-codes
profile
public-hostname
public-ipv4
reservation-id
security-groups
services/ domain
partitition
user-data/
Aquesta taula continua cap a la dreta — desplaça-la o gira el mòbil.
http://169.254.169.254/latest/- user-data/
- ...
- meta-data/
- ...
- user-data/
- EC2 Instance Metadata Query Tool
- region
- Find region from within an EC2 instance
# eu-west-1a
availability_zone=$(curl -s http://169.254.169.254/latest/meta-data/placement/availability-zone)
# eu-west-1
#region=$(echo $availability_zone | sed 's/.$//')
region=${availability_zone: : -1}
- Exemples / Examples
- CLI userdata
- Cloudformation
userdata
- UserData in EC2
- UserData in LaunchTemplate
- UserData in LaunchConfiguration
- Balancejador de càrrega / Load
balancer
- Types
(comparison: Classic
Load
Balancer FAQs)
- Application Load Balancer
- Network Load Balancer
- Classic Load Balancer
- Migració / Migration ELB (classic) -> ALB
- Migrate your Classic Load Balancer
- Passos / Steps
- des de l'ELB actual, aneu a la pestanya
«Migration» i feu clic al botó «Launch ALB Migration
Wizard»
- se us posarà automàticament al pas 6
- si voleu, aneu al pas 1 i al 4 per a canviar els noms del nou balancejador i del nou target group (si no, us posarà el mateix nom que teníeu a l'ELB)
- Create
- After migration is complete, you can do
the following as needed:
Redirect traffic to your new load balancer (see Migrate Traffic).
Change the deregistration delay (see Deregistration Delay). The default is 300 seconds.
Change the idle connection timeout if needed (see Connection Idle Timeout). The default is 60 seconds.
Enable access logs (see Access Logs).
Suggested next steps
Discover other services that you can integrate with your load balancer. Visit the Integrated services tab within pro-alb-wbe
Consider using AWS Global Accelerator to further improve the availability and performance of your applications. AWS Global Accelerator console
- After migration is complete, you can do
the following as needed:
- a l'ALB, aneu a Attributes: Idle timeout i poseu-hi el valor que teníeu a l'antic ELB (aquest valor no s'ha copiat amb la migració)
- si teniu un ASG, aneu-hi, i des de la primera pestanya («Details»), aneu a «Load balancing» i associeu-hi el nou target, des de la secció «Application, Network or Gateway Load Balancer target groups»
- comproveu que quan augmenta l'ASG, també hi ha més instàncies dins del nou target group
- a Route53:
- creeu un nou record, que apunti (alias) cap al
nou ALB
- Routing policy: Weighted
- Weight: 9
- Record ID: my_new_alb
- modifiqueu l'entrada antiga (que té el mateix
nom):
- Routing policy: Weighted
- Weight: 1
- Record ID: my_old_elb
- creeu un nou record, que apunti (alias) cap al
nou ALB
- ...
- des de l'ELB actual, aneu a la pestanya
«Migration» i feu clic al botó «Launch ALB Migration
Wizard»
- Cloudformation: load balancers
- CLI: load balancers
- Sticky sessions
- ALB logs
- Access logs for your Application Load Balancer
- configure ALB so as logs are written to an S3 bucket and download the gz file from there
- type time elb client:port target:port request_processing_time target_processing_time response_processing_time elb_status_code target_status_code received_bytes sent_bytes "request" "user_agent" ssl_cipher ssl_protocol target_group_arn "trace_id" "domain_name" "chosen_cert_arn" matched_rule_priority request_creation_time "actions_executed" "redirect_url" "error_reason" "target:port_list" "target_status_code_list" "classification" "classification_reason"
- columns
- type
- time
- elb
- client:port
- target:port
- request_processing_time
- target_processing_time
- response_processing_time
- elb_status_code
- target_status_code
- received_bytes
- sent_bytes
- "request"
- "user_agent"
- ssl_cipher
- ssl_protocol
- target_group_arn
- "trace_id"
- "domain_name"
- "chosen_cert_arn"
- matched_rule_priority
- request_creation_time
- "actions_executed"
- "redirect_url"
- "error_reason"
- "target:port_list"
- "target_status_code_list"
- "classification"
- "classification_reason"
- Parse with awk
- get request which returned 4xx from ALB and print
response codes and request (if $10 is '-', this is a
pure load balancer response):
awk 'BEGIN {FPAT="([^ ]+)|(\"[^\"]+\")"}; $9 ~ /^4/ {print $9, $10, $13}' alb.log
- get request which returned 460 from ALB:
awk 'BEGIN {FPAT="([^ ]+)|(\"[^\"]+\")"}; $9 ~ /^460/ {print $6, $7, $8, $9, $10, $13}' alb.log
- ...
- get request which returned 4xx from ALB and print
response codes and request (if $10 is '-', this is a
pure load balancer response):
- ...
- ELB Logs
- Access logs for your Classic Load Balancer
- columns
- time
- elb
- client:port
- backend:port
- request_processing_time
- backend_processing_time
- response_processing_time
- elb_status_code
- backend_status_code
- received_bytes
- sent_bytes
- request
- user_agent
- ssl_cipher
- ssl_protocol
- parse
- get backend_status_code
awk ...
- ...
- get backend_status_code
- Types
(comparison: Classic
Load
Balancer FAQs)
10S3#
- What is Amazon S3?
- Alternatives
- Usage
- Format and Parse Amazon S3 URLs
- Amazon Simple Storage Service endpoints and quotas
-
regional
(RECOMMENDED)legacy
(for us-east-1; HTTP 307 for non-supported regions)global url s3://<bucket>/<key>virtual-hosted-style https://<bucket>.s3.<region>.amazonaws.com/<key>
https://<bucket>.s3.amazonaws.com/<key>
path-style (DEPRECATED) https://s3.<region>.amazonaws.com/<bucket>/<key>
https://s3.amazonaws.com/<bucket>/<key>
Aquesta taula continua cap a la dreta — desplaça-la o gira el mòbil.
- Amazon
S3 Path Deprecation Plan – The Rest of the Story
- Security and access management
- Public access
- Amazon S3 Security and Access Management
- Identity
and access management in Amazon S3
- Access policies
- Resource-based policies
- S3 object: object ACL (xml)
- Bucket: bucket ACL (xml), bucket policy (json)
- User policies
- Resource-based policies
- ...
- Access policies
- restricted access from CloudFront
- Mètriques / Metrics
- Metrics and dimensions (Amazon Simple Storage Service)
- S3
Storage Lens
- settings: advanced -> export to CloudWatch
- Monitor
S3 Storage Lens metrics in CloudWatch
- " Prefix-level metrics are not available in CloudWatch."
- boto3
- ...
- Access using:
- Redundància / Redundancy
- Bucket policy
- AWS Policy Generator
- Granting Read-Only Permission to an Anonymous User
- How
do I grant cross-account access to objects that are in
Amazon S3 buckets?
- allow accountA-userA
to have access to accountA-bucketA:
-
account A access as accountA/userA to accountA/bucketA if missing some config, you will get this message: read, write accountA-userA
accountA-bucketA- Bucket policy
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::accountA_id:user/accountA-userA"
},
"Action": [
"s3:PutObject",
"s3:GetObject",
],
"Resource": [
"arn:aws:s3:::accountA-bucketA/*"
]
}
]
}
- write:
aws --profileaccountA-userAs3 cp toto.txt s3://accountA-bucketA/- read:
aws --profileaccountA-userAs3 cp s3://accountA-bucketA/toto.txt .
- when writing, and missing
s3:PutObject in bucket policy:
upload failed: ./toto.txt to s3://accountA-bucketA/toto.txt An error occurred (AccessDenied) when calling the PutObject operation: User: arn:aws:iam::xxxx:user/accountA-userA is not authorized to perform: s3:PutObject on resource: "arn:aws:s3:::accountA-bucketA/toto.txt" because no identity-based policy allows the s3:PutObject action
- when reading, and missing s3:GetObject
in bucket policy:
fatal error: An error occurred (403) when calling the HeadObject operation: Forbidden
read, write, list accountA-userA
accountA-bucketA- Bucket policy
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::accountA_id:user/accountA-userA"
},
"Action": [
"s3:ListBucket",
"s3:PutObject",
"s3:GetObject",
],
"Resource": [
"arn:aws:s3:::accountA-bucketA",
"arn:aws:s3:::accountA-bucketA/*"
]
}
]
}
- write:
aws --profileaccountA-userAs3 cp toto.txt s3://accountA-bucketA/
- read:
aws --profileaccountA-userAs3 cp s3://accountA-bucketA/toto.txt .- list:
aws --profileaccountA-userAs3 ls s3://accountA-bucketA/
- ...
- when listing, and missing s3:ListObject and Resource without asterisk, in bucket poicy:
An error occurred (AccessDenied) when calling the ListObjectsV2 operation: User: arn:aws:iam::xxxx:user/accountA-userA is not authorized to perform: s3:ListBucket on resource: "arn:aws:s3:::accountA-bucketA" because no identity-based policy allows the s3:ListBucket action
Aquesta taula continua cap a la dreta — desplaça-la o gira el mòbil.
- Bucket policy
-
- allow
accountB-userBto have access toaccountA-bucketA:-
account A account B access as accountB-userB to accountA-bucketA if some of the two policies are not set, you will get this message: read, write accountA-bucketA - Bucket policy
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::accountB_id:user/accountB-userB"
},
"Action": [
"s3:PutObject",
"s3:PutObjectAcl",
"s3:GetObject"
],
"Resource": [
"arn:aws:s3:::accountA-bucketA/*"
]
}
]
}
accountB-userB - Permissions policies
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:PutObjectAcl",
"s3:GetObject"
],
"Resource": [
"arn:aws:s3:::accountA-bucketA/*"
]
}
]
}
- write:
aws --profile accountB-userB s3 cp toto.txt s3://accountA-bucketA/
- read:
aws --profile accountB-userB s3 cp s3://accountA-bucketA/toto.txt .
- when writing, and missing s3:PutObject
in at least one of the policies:
upload failed: ./toto.txt to s3://accountA-bucketA/toto.txt An error occurred (AccessDenied) when calling the PutObject operation: Access Denied
- when reading, and missing s3:GetObect
in at least one of the policies:
fatal error: An error occurred (403) when calling the HeadObject operation: Forbidden
read, write, list accountA-bucketA - Bucket policy
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::accountB_id:user/accountB-userB"
},
"Action": [
"s3:ListBucket",
"s3:PutObject",
"s3:PutObjectAcl",
"s3:GetObject"
],
"Resource": [
"arn:aws:s3:::accountA-bucketA",
"arn:aws:s3:::accountA-bucketA/*"
]
}
]
}
accountB-userB - Permissions policies
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:ListBucket",
"s3:PutObject",
"s3:PutObjectAcl",
"s3:GetObject"
],
"Resource": [
"arn:aws:s3:::accountA-bucketA",
"arn:aws:s3:::accountA-bucketA/*"
]
}
]
}
- write:
aws --profile accountB-userB s3 cp toto.txt s3://accountA-bucketA/
- read:
aws --profile accountB-userB s3 cp s3://accountA-bucketA/toto.txt .
- list:
aws --profile accountB-userB s3 ls s3://accountA-bucketA/
- ...
- ...
- missing s3:ListBucket and Resource
without asterisk in at least one of the
policies:
An error occurred (AccessDenied) when calling the ListObjectsV2 operation: Access Denied
Aquesta taula continua cap a la dreta — desplaça-la o gira el mòbil.
- Bucket policy
-
- ...
- allow accountA-userA
to have access to accountA-bucketA:
- Public
Readable
Amazon S3 Bucket Policy
{
"Version": "2008-10-17",
"Statement": [
{
"Sid": "AllowPublicRead",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": [
"s3:GetObject"
],
"Resource": [
"arn:aws:s3:::bucket_name/*"
]
}
]
}- Boto
(Python):
# modify policy to make it publicly available
policy_json = '{"Version":"2008-10-17","Statement":[{"Sid":"AllowPublicRead","Effect":"Allow","Principal":{"AWS":"*"},"Action":["s3:GetObject"],"Resource":["arn:aws:s3:::%s/*"]}]}' % (bucket_name)
print policy_json
bucket.set_policy(policy_json)
- Cache
- Adding
Headers
to Your Objects Using the Amazon S3 Console
- Properties
- Metadata
- Key:
Cache-Control, Expires
- Key:
- Metadata
- Properties
- Adding
Headers
to Your Objects Using the Amazon S3 Console
- CORS
- CORS in CloudFront
- Cross-Origin Resource Sharing (CORS)
- Enabling
Cross-Origin
Resource Sharing (CORS)
- Enable CORS using the AWS management console
- go to bucket
- Permissions tab
- Cross-origin ressource sharing (CORS)
[
{
"AllowedHeaders": [
"*"
],
"AllowedMethods": [
"GET",
"HEAD"
],
"AllowedOrigins": [
"*"
],
"ExposeHeaders": [],
"MaxAgeSeconds": 3000
}
]
- Enable bucket CORS from S3 CloudFormation
- [old] Enabling
Cross-Origin
Resource Sharing (CORS) Using the AWS Management
Console
- Select bucket
- Add CORS Configuration
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<AllowedMethod>HEAD</AllowedMethod>
<MaxAgeSeconds>3000</MaxAgeSeconds>
<AllowedHeader>Authorization</AllowedHeader>
</CORSRule>
</CORSConfiguration>
- CloudFront: invalidate
- In your browser, delete disk cache for images:
- Chrome
- Més eines / Esborra les dades de navegació
- Imatges i fitxers desats a la memòria cau
- Més eines / Esborra les dades de navegació
- Firefox
- Preferències -> Privadesa i seguretat -> Galetes i dades dels llocs -> Gestiona les dades
- Chrome
- Enable CORS using the AWS management console
- Static website
- See also: CloudFront with S3 as origin
- Virtual Hosting of Buckets
- Hosting a Static Website on Amazon S3
- Example: Setting Up a Static Website Using a Custom Domain
- Authentication
- Redireccionament /
Redirect
- (Optional) Configuring a Webpage Redirect
- Vegeu també / See also: Route53 redirect
- Angular
- S3 Static Website Hosting Route All Paths to Index.html
- CloudFront
- Error Pages: Create Custom Error Response
- HTTP Error Code: 403 Forbidden
- Error Caching Minimum TTL (seconds): 300
- Customize Error Response: Yes
- Response Page Path: /index.html
- HTTP Response Code: 200 OK
- Error Pages: Create Custom Error Response
- React
- Directory list
- Directory Listing in S3 Static Website
- s3-bucket-listing
- 4.
Use Amazon S3 in non-website mode
var S3BL_IGNORE_PATH = true;
var BUCKET_NAME = 'mybucket';- index.html must be public
- https://mybucket.s3.amazonaws.com/index.html
- 4.
Use Amazon S3 in non-website mode
- HTTPS
- Add CloudFront
and configure your own certificate there
- SSL support for S3 website endpoints? (AWS Discussion forums)
- Implementing SSL on Amazon S3 Static Websites (2015)
- Setting Up SSL on AWS CloudFront and S3 (2014)
- With Let's Encrypt certificates:
- Add CloudFront
and configure your own certificate there
-
s3 bucket
cloudfront
route53
http
https
name
Static website hosting
www.toto.org
-
-
-
http://s3-eu-west-1.amazonaws.com/www.toto.org/index.html
https://s3-eu-west-1.amazonaws.com/www.toto.org/index.html -
-
-
http://www.toto.org.s3.amazonaws.com/ (Access denied)
http://www.toto.org.s3.amazonaws.com/index.html
http://www.toto.org.s3.eu-west-1.amazonaws.com/ (Access denied)
http://www.toto.org.s3.eu-west-1.amazonaws.com/index.html
https://www.toto.org.s3.amazonaws.com/ x
-
-
http://www.toto.org.s3-website-eu-west-1.amazonaws.com/ https://www.toto.org.s3-website-eu-west-1.amazonaws.com/ (timeout: because of dots?) x
-
www.toto.org A ALIAS s3-website-eu-west-1.amazonaws.com.
http://www.toto.org/ https://www.toto.org/ x
- Origin Domain Name: www.toto.org.s3.amazonaws.com
- Default root object: index.html
- Alternate Domain Names (CNAMEs): www.toto.org
- Custom SSL Certificate: (choose one of the certificates previously uploaded to path /cloudfront/)
www.toto.org A ALIAS www.toto.org (xxxxxx.cloudfront.net) http://www.toto.org/ https://www.toto.org/ www-toto-org
-
-
-
http://s3-eu-west-1.amazonaws.com/www-toto-org/ (Access denied)
http://s3-eu-west-1.amazonaws.com/www-toto-org/index.html
https://s3-eu-west-1.amazonaws.com/www-toto-org/
https://s3-eu-west-1.amazonaws.com/www-toto-org/index.html
-
-
-
http://www-toto-org.s3.amazonaws.com/ (Access denied)
http://www-toto-org.s3.amazonaws.com/index.html
http://www-toto-org.s3-eu-west-1.amazonaws.com/ (Access denied)
http://www-toto-org.s3.eu-west-1.amazonaws.com/index.html
https://www-toto-org.s3.amazonaws.com/ (Access denied)
https://www-toto-org.s3.amazonaws.com/index.html
https://www-toto-org.s3-eu-west-1.amazonaws.com/ (Access denied)
https://www-toto-org.s3.eu-west-1amazonaws.com/index.htmlx
-
-
http://www-toto-org.s3-website-eu-west-1.amazonaws.com/ https://www-toto-org.s3-website-eu-west-1.amazonaws.com/ (timeout)
x
- Origin Domain Name: www-toto-org.s3.amazonaws.com
- Default root object: index.html
- Alternate Domain Names (CNAMEs): www.toto.org
- Custom SSL Certificate: (choose one of the certificates previously uploaded to path /cloudfront/)
www.toto.org A ALIAS www.toto.org (xxxxxx.cloudfront.net) http://www.toto.org/ https://www.toto.org/ Aquesta taula continua cap a la dreta — desplaça-la o gira el mòbil.
- s3tools
- s3cmd
- Instal·lació / Installation
- Mageia
urpmi python-s3cmd
- Mageia
- make bucket
s3cmd mb s3://...
- list
s3cmd ls s3://bucket_name
- upload
s3cmd put ...
- Instal·lació / Installation
- s3cmd
- yas3fs
- Instal·lació / Installation
- CentOS
sudo yum -y install fuse fuse-libs
sudo easy_install pip
sudo pip install yas3fs
sudo sed -i'' 's/^# *user_allow_other/user_allow_other/' /etc/fuse.conf
yas3fs s3://mybucket/path /mnt/local_path
fusermount -u mnt/local_path
- CentOS
- Instal·lació / Installation
- s3fs-fuse
- Wiki
- See also (alternatives)
- maximum file size: 64GB
- Instal·lació / Installation
- from package
- Alma 8
sudo dnf install epel-releasesudo dnf install s3fs-fuse
- Alma 8
- from source
- dependències / dependencies
- Mageia
urpmi lib64fuse-devel
- CentOS
yum install automake gcc-c++ fuse fuse-devel libcurl-devel libxml2-devel
- Mageia
- compilació / compilation
git clone https://github.com/s3fs-fuse/s3fs-fuse.gitcd s3fs-fuse./autogen.sh./configure --exec-prefix=/usrmakesu; make install- Problemes / Problems
./configure: line 4964: syntax error near unexpected token `common_lib_checking,'
./configure: line 4964: `PKG_CHECK_MODULES(common_lib_checking, fuse >= ${min_fuse_version} libcurl >= 7.0 libxml-2.0 >= 2.6 )'- ...
- dependències / dependencies
- from package
- ?
echo "user_allow_other" >> /etc/fuse.conf
- utilització / usage
- Wowza
- when not using roles
- ~/.passwd-s3fs (/etc/passwd-s3fs)
bucketName:accessKeyId:secretAccessKey
- chmod 600 ~/.passwd-s3fs
- ~/.passwd-s3fs (/etc/passwd-s3fs)
- mkdir
/mnt/bucketName; chmod 755/mnt/bucketName
s3fsbucketName/mnt/bucketName -ouse_cache=/tmp-o allow_other,ahbe_conf=/etc/ahbe.conf- with role:
s3fsbucketName/mnt/bucketName-o allow_other,ahbe_conf=/etc/ahbe.conf,iam_role=my_rolename
- mount on boot (FAQ)
- How to force s3fs mount
on boot
- option 1:
- /etc/init.d/local
- option 2:
- /etc/fstab
s3fs#my_bucket /mnt/my_bucket fuse _netdev,nonempty,allow_other,ahbe_conf=/etc/ahbe.conf 0 0s3fs#my_bucket /mnt/my_bucket fuse _netdev,nonempty,allow_other,ahbe_conf=/etc/ahbe.conf,iam_role=my_rolename0 0
- Problems:
d????????? ? ? ? ? ? my_bucket- Solution
- check that
_netdevoption is present in /etc/fstab
- check that
- Solution
- /etc/fstab
- option 1:
- How to force s3fs mount
on boot
- public permission for new files:
s3fs#my_bucket /mnt/my_bucket fuse _netdev,nonempty,allow_other,ahbe_conf=/etc/ahbe.conf,iam_role=my_rolename,default_acl=public-read 0 0
- Problemes / Problems
- debug
- s3fs -d -f
- Desconnexió / Disconnection
- debug
- Cloudfront
Cache-control
- ahbe.conf
- sample_ahbe.conf
# mpd and m3u8 files are cached for 2 seconds
.mpd Cache-Control max-age=2
.m3u8 Cache-Control max-age=1
s3fsbucketName/mnt/bucketName-oallow_other,ahbe_conf="/etc/ahbe.conf"
- ahbe.conf
- Wiki
- Logs
- Amazon
S3 Server Access Log Format
- columns
- Bucket owner
- bucket
- datetime
- remote ip
- requester
- request id
- operation
- key
- request-uri
- http status
- error code
- bytes sent
- object size
- total time
- turn-around time
- referer
- user-agent
- version id
- host id
- signature version
- cipher suite
- authentication type
- host header
- tls version
- parse
# show: datetime operation key remote_ip http_status bytes_sent
gawk 'BEGIN {FPAT="([^ ]+)|(\"[^\"]+\")|(\\[[^\\[\\]]+\\])"}; $8 ~ /myfile.mp4/ && $7 ~ /REST.GET.OBJECT/ {print $3, $7, $8, $4, $10, $12}' *
- columns
- Amazon
S3 Server Access Log Format
11S3 Glacier#
- Info
- Usage
- AWS S3 Glacier (aws console)
- CLI
- ...
12Database#
- RDS
- Using RDS with Django
- Is Amazon RDS for PostgreSQL or Amazon Aurora PostgreSQL a better choice for me?
- Scaling
- Security group
- Default rule make database available from outside
- To be reachable from ec2 instances, add a rule for your VPC (e.g. 172.32.0.0/16)
- Replication
- Best practices for Amazon RDS PostgreSQL replication
- How
can I distribute read requests across multiple Amazon
RDS read replicas?
- Route53 weighted records
- Comparison
- Types
- Multi-AZ deployments
- Multi-Region deployments
- Read replicas
- RDS Proxy
- Amazon RDS Proxy FAQs
- Using
Amazon RDS Proxy
- Set up shared database connections with Amazon RDS Proxy (tutorial)
- Getting
started with RDS Proxy
- create a Secret in Secrets Manager (for one regular user in database, not the master user) and note its arn
- setup a policy in IAM
Policies that can access the secret
- Roles -> Create role
- RDS -> RDS - Add role to database
- Create policy
- JSON: with arn from previous step (sample json)
- Create
- Roles (refresh)
- Roles -> Create role
- RDS upgrade
- Best option: blue/green deployment
- PostgreSQL
- Upgrades of the RDS for PostgreSQL DB engine
- How to perform a major version upgrade for RDS for PostgreSQL
- Upgrading PostgreSQL extensions in RDS for PostgreSQL databases
- Parameter groups
- Problemes
The current parameter group associated with the blue instance (wct-postgres12) is not the default. You need to explicitly specify a new parameter group (default or custom) for the green instance when creating a blue/green deployment with the --target-engine-version option set to an engine version that's different from the blue instance.- Solució:
- feu servir aws cli en lloc de la
consola web:
aws rds create-blue-green-deployment --blue-green-deployment-name bg-my-database --source arn:aws:rds:eu-west-1:xxxx:db:my-database --target-engine-version 13.18 --target-db-parameter-group-name my-postgres13
- feu servir aws cli en lloc de la
consola web:
- Solució:
- Question about blue/green RDS postgreSQL deployment.
-
30.8 Configuration Settings (12, 13) PostgreSQL 12 PostgreSQL 13 b/g
default modified (*) default modified
from b/g docs:
Preparing an RDS for PostgreSQL DB instance for a blue/green deployment with logical replicationrds.logical_replication
0 1 0 1 Blue/Green Deployments require a DB instance with logical replication enabled. Before you create a Blue/Green Deployment for a DB instance, associate the DB instance with a custom DB instance parameter group that enables logical replication.
max_replication_slots- publisher: must be set to at least the number of subscriptions expected to connect, plus some reserve for table synchronization
- subscriber: be set to configure how many replication origins can be tracked. In this case it should be set to at least the number of subscriptions that will be added to the subscriber.
10 - count(databases) + 3
- 20
20
max_wal_senders- publisher: should
be set to at least the same as
max_replication_slotsplus the number of physical replicas that are connected at the same time
10 - max_replication_slots + 3
- 20 -> 35
(blue logs:
The parameter max_wal_senders was set to a value incompatible with replication. It has been adjusted from 20 to 35.) (added 15)
20 - 35
max_logical_replication_workers- subscriber: must be set to at least the number of subscriptions, again plus some reserve for the table synchronization
- - max_replication_slots
- 20
- - 20
max_worker_processes- subscriber: may
need to be adjusted to accommodate
for replication workers, at least (
max_logical_replication_workers+ 1). Note that some extensions and parallel queries also take worker slots from max_worker_processes
8 - max_logical_replication_worker + 3
- 35
GREATEST(${DBInstanceVCPU*2},8)
other parameters from PostgreSQL docs (30.8 Configuration Settings) wal_level- publisher: must
be set to
logical
(not present)
(not present)
diff default.postgres12,
default.postgres13
(done by copying default to custom and action compare)ignore_invalid_pages
-
0
max_parallel_workers
-
GREATEST(${DBInstanceVCPU/2},8)
max_replication_slots
10
20
max_wal_senders
10
20
max_worker_processes
8
GREATEST(${DBInstanceVCPU*2},8)
rds.accepted_password_auth_method
-
md5+scram
rds.extensions
...
...
rds.force_autovacuum_logging_level
INFO
WARNING
rds.replica_identity_full
-
0
wal_compression
-
1
wal_keep_segments
32
-
wal_keep_size
-
2048
wal_receiver_create_temp_slot
-
0
Aquesta taula continua cap a la dreta — desplaça-la o gira el mòbil.
- Problemes
- Aurora
- RDS console
- Instances
- Creation of a database server with replica
- Engine options
- Engine type: Amazon Aurora
- Edition: Amazon Aurora with PostgreSQL compatibility
- Capacity type: Provisioned
- Version: Aurora PostgreSQL (Compatible with PostgreSQL 12.7)
- Templates
- Settings
- DB cluster identifier: my-first-cluster
- Master username: postgres
- Master password: xxxx
- DB Instance class
- Burstable classes: db.t4g.medium
- Availability & durability
- Create an Aurora Replica or Reader node in a different AZ (recommended for scaled availability)
- Connectivity
- Virtual private cloud (VPC): Default VPC
- Subnet group: default
- Public access: Yes
- VPC security group
- Create new: sg_aurora
- Database authentication
- Additional configuration
- Backup
- Backup retention period: 35 days
- ...
- Log exports
- Backup
- Engine options
- ...
- Migració des de PostgreSQL / Migration from PostgreSQL
- Migrate
to an Amazon Aurora PostgreSQL instance from another
PostgreSQL source
- Migrating from a self-managed PostgreSQL instance
to an Aurora PostgreSQL instance
- pg_dump and pg_restore
- Logical replication
- AWS DMS
- Migrating from a self-managed PostgreSQL instance
to an Aurora PostgreSQL instance
- Best practices for migrating PostgreSQL databases to Amazon RDS and Amazon Aurora
- Importing data into PostgreSQL on Amazon RDS
- ...
- Migrate
to an Amazon Aurora PostgreSQL instance from another
PostgreSQL source
- Accés / Access
- Can't
connect to Amazon RDS DB instance
psql --host my-first-cluster.cluster-xxx.rds.amazonaws.com --username postgres --password xxxx
- Can't
connect to Amazon RDS DB instance
13Amazon MQ#
- Broker for messaging:
- Amazon MQ Features
14ECR (Elastic Container Registry)#
- CLI: aws ecr
15EKS#
- Amazon EKS user guide
- eksctl
- Instal·lació / Installation
- Config file schema
- create a cluster:
eksctl create cluster -name <cluster_name> --version 1.22 --region eu-west-1 --nodegroup-name <cluster_name>-nodes --node-type t3.small --nodes 1
- delete a cluster:
eksctl delete cluster <cluster_name>
- AWS Load Balancer Controller
- Best practices
- EKS
Best Practices Guides
- Identity
and Access Management
- Create
the cluster with a dedicated IAM role
- create a role
role-eks-create- Trusted entity type: Custom trust policy
- Add a principal
- Principal type: IAM users
- ARN: arn:aws:iam::{Account}:user/myuser
- Permission policies:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"ec2:DescribeInstanceTypeOfferings",
"ec2:DescribeAvailabilityZones",
"ec2:AllocateAddress",
"ec2:CreateVpc",
"ec2:DeleteVpc",
"ec2:DescribeVpcs",
"ec2:DescribeAddresses",
"ec2:ReleaseAddress",
"ec2:CreateInternetGateway",
"ec2:AttachInternetGateway",
"ec2:CreateTags",
"ec2:DescribeInternetGateways",
"ec2:DeleteInternetGateway",
"ec2:DetachInternetGateway",
"ec2:ModifyVpcAttribute",
"ec2:CreateSubnet",
"ec2:DeleteSubnet",
"ec2:DescribeSubnets",
"ec2:ModifySubnetAttribute",
"ec2:CreateRouteTable",
"ec2:CreateRoute",
"ec2:DeleteRoute",
"ec2:CreateSecurityGroup",
"ec2:DescribeSecurityGroups",
"ec2:AuthorizeSecurityGroupIngress",
"ec2:RevokeSecurityGroupIngress",
"ec2:DeleteSecurityGroup",
"ec2:DescribeRouteTables",
"ec2:DeleteRouteTable",
"ec2:AssociateRouteTable",
"ec2:DisassociateRouteTable",
"ec2:CreateNatGateway",
"ec2:DescribeNatGateways",
"ec2:DescribeNatGateways",
"ec2:DeleteNatGateway",
"ec2:CreateLaunchTemplate",
"ec2:DeleteLaunchTemplate",
"ec2:DescribeLaunchTemplateVersions",
"ec2:RunInstances",
"cloudformation:CreateStack",
"cloudformation:DescribeStacks",
"cloudformation:DescribeStackEvents",
"cloudformation:ListStacks",
"cloudformation:DeleteStack",
"iam:DetachRolePolicy",
"iam:DeleteRole",
"iam:GetRole",
"iam:CreateRole",
"iam:AttachRolePolicy",
"iam:PutRolePolicy",
"iam:DeleteRolePolicy",
"iam:PassRole",
"iam:ListAttachedRolePolicies",
"eks:DescribeCluster",
"eks:ListClusters","eks:DescribeNodegroup",
"eks:CreateCluster",
"eks:TagResource",
"eks:DeleteCluster",
"eks:CreateNodegroup",
"eks:DescribeNodegroup",
"eks:DeleteNodegroup"
],
"Resource": "*"
}
]
}
- ~/.aws/config
[profile eks-create]
role_arn = arn:aws:iam::xxxxx:role/role-eks-create
source_profile = myuser
export AWS_PROFILE=eks-create- verify that eks-create role will be used by
eksctl:
aws sts get-caller-identity
eksctl create cluster --name my-cluster --region eu-west-1 --nodegroup-name my-cluster-nodes --node-type t3.micro --nodes 2- this will create 2 CloudFormation stacks:
eksctl-<my-cluster>-clustereksctl-<my-cluster>-nodegroup-<my-cluster-nodes>
- this will create 2 CloudFormation stacks:
- verify:
- CloudTrail / Event history / Event Name = CreateCluster
- cluster will be available in about 15-20 minutes
- create a role
- Create
the cluster with a dedicated IAM role
- Identity
and Access Management
- EKS
Best Practices Guides
16CloudFront#
- General:
- Supercharge Your Website with Amazon CloudFront
- Amazon Cloudfront as Reverse Proxy for WordPress
- Slow responses
- Amazon
Cloudfront settings to reduce waiting time
- use "Custom" instead of "Use Origin Cache Headers"
- Amazon
Cloudfront settings to reduce waiting time
-
delivery method
origin
usage
Amazon S3 bucket Web server Web x
x
- static files
- media files with HTTP, HTTPS
- add, update, delete objects
- live streaming
RTMP x -
- RTMP
Aquesta taula continua cap a la dreta — desplaça-la o gira el mòbil.
-
CloudFront
origin
console option
console value
CloudFormation web server nginx web server
AWS S3
Cache
2xx
Behaviour -> Object Caching
Use Origin Cache Headers
Cache-ControlExpires
Customize
-
-
(default: 24h)
4xx
Error Pages -> Custom Error Response
HTTP Error Code: 404
Error Caching Minimum TTL: 1
"MyCloudFront" : {
"Type" : "AWS::CloudFront::Distribution",
"Properties" : {
"DistributionConfig" : {
"CustomErrorResponses" : [ {
"ErrorCode" : "404",
"ErrorCachingMinTTL" : "1"
} ]
...
}
}
}
Nginx: no-cache for 404 responses
server {
...
error_page 404 /404.html;
location = /404.html {
root html;
add_header Cache-Control "no-cache" always;
add_header Cache-Control "max-age=0" always;
}
}
-
-
-
CORS
Behaviour -> Forward Headers
Whitelist (of forwarded request headers, from client to origin):
- Origin
- Access-Control-Request-Headers
- Access-Control-Request-Method
Nginx: CORS
(consider also adding cors headers for error responses:always)S3 CORS None
-
-
Aquesta taula continua cap a la dreta — desplaça-la o gira el mòbil.
- HTTPS
- Cache-control (see
table
above)
- Control of cache in CloudFront
- cache key
- la cache key determina la unicitat d'un objecte i si cal servir-lo directament o bé demanar-lo a l'origin
- un cop demanat a l'origin, es queda a l'edge, identificat amb aquella key, per si hi torna a haver una petició idèntica
- com més camps conformin la key més variants hi haurà a l'edge d'un mateix objecte i més peticions es passaran a l'origin i menys eficient serà la cache (hit/miss)
- els camps que conformen la key s'especifiquen dins de la Cache Policy, secció Cache key settings:
- headers
- cookies
- query strings
- els camps que es defineixen a la Cache Policy, secció Cache key settings també es passen amb l'origin request
- totes les seccions d'una Cache Policy:
- Policy information
- Time
to live (TTL) settings (Manage
how long content stays in the cache (expiration))
- Minimum TTL
- Maximum TTL
- Default TTL
- Cache key settings
- Headers
- Cookies
- Query strings
- hi ha algunes Cache Policy ja definides: Use managed cache policies
- origin request
- quan la cdn no troba un objecte amb exactament la mateixa key (Miss from Cloudfront), passa la petició cap a l'origin: és l'origin request
- a l'origin request s'hi posa la següent informació:
- url path
- request body (si n'hi ha)
- HTTP headers:
HostUser-AgentX-Amz-Cf-Id- el camps definits per la Cache Policy, secció Cache key settings (que també contribueixen a conformar la key)
- altres camps que no es volen fer servir per a conformar la cache key, però es volen passar igualment cap a l'origin, es defineixen a l'Origin Request Policy
- s3fs cache control
- Specifying How Long Objects Stay in a CloudFront Edge Cache (Expiration)
- Request and Response Behavior for Custom Origins
- Issue 336: s3fs - Automatically setting the cache-control header (s3fs)
- Reduce your Cloudfront costs with cache control
- How to Set Cache Control Header for Amazon S3 Object?
- Cache for
error (404) responses
- How CloudFront Processes and Caches HTTP 4xx and 5xx Status Codes from Your Origin
- Problems
- User player requests a resource, but it is still
no available. It gets a 404 from CloudFront. If
response 404 is cached (default configuration for
CloudFront), even if the player (e.g. HLS player)
requests again the resource, CloudFront will not
request the origin again, and player will always get
the 404. Usually seen in live
distributions.
- Solution
- mark 404 responses as no cached
- in origin
- in CloudFront
- aws console
- Distribution -> Error Pages
-> Custom Error Response
- HTTP Error Code: 404 Not Found
- Error Caching Minimum TTL (seconds): 2
- Distribution -> Error Pages
-> Custom Error Response
- Cloudformation: CloudFront no cache for 404
- aws console
- mark 404 responses as no cached
- Solution
- User player requests a resource, but it is still
no available. It gets a 404 from CloudFront. If
response 404 is cached (default configuration for
CloudFront), even if the player (e.g. HLS player)
requests again the resource, CloudFront will not
request the origin again, and player will always get
the 404. Usually seen in live
distributions.
- CORS (see table
above)
- Examples in CloudFormation
- Headers
- Problems
- User player requests a resource via Ajax, gets a
response with no CORS headers and refuses to play it.
Usually seen in vod
distributions.
- Solution
- allow passing the needed request
headers (
Origin) from final user to origin, to force the generation of CORS response header (Access-Control-Allow-Origin)- in origin
- AWS S3 CORS
- Nginx: CORS
- in CloudFront (see CloudFormation)
- console
- Distribution -> Behaviour
- Forward Headers ->
Whitelist
- Origin
- Access-Control-Request-Headers
- Access-Control-Request-Method
- Allowed HTTP Methods (to avoid
a 403 response from CloudFront
when requested a CORS preflight)
- GET, HEAD, OPTIONS
- Cached HTTP Methods
- OPTIONS
- Forward Headers ->
Whitelist
- Distribution -> Behaviour
- Cloudfromation: CloudFront Forward headers
- console
- in origin
- allow passing the needed request
headers (
- Solution
- Chrome S3 Cloudfront: No 'Access-Control-Allow-Origin' header on initial XHR request
- User player requests a resource via Ajax, gets a
response with no CORS headers and refuses to play it.
Usually seen in vod
distributions.
- WordPress
- Cloudfront logs
- Activation
- ...
- from CloudFormation
- ...
- Problemes / Problems
-
The S3 bucket that you specified for CloudFront logs does not enable ACL access- from April 2023
- NOTICE: new S3 Buckets trying to use ACLs fail to create if not explicitly opted in #25358
- Solution:
- on your bucket, activate Object writer as
Object ownership:
- from console (Permissions -> Object
Ownership):
- ACLs enabled
- Object Ownership: Object writer
- ACLs enabled
- from CloudFormation:
"MyBucket": {[...]
"Type" : "AWS::S3::Bucket",
"Properties": {
"OwnershipControls": {
"Rules" : [
{"ObjectOwnership": "ObjectWriter"}
]
},
- from console (Permissions -> Object
Ownership):
- on your bucket, activate Object writer as
Object ownership:
-
- Format
- Real-time logs
- Architectures
- CloudFront
Real-Time Monitoring Solution
- using AWS SAM CLI
- components
- Amazon Kinesis Data Streams
- AWS Lambda
- Amazon Timestream
- Creating
realtime dashboards using Amazon CloudFront logs
- components
- Amazon Kinesis Data Streams
- Amazon Kinesis Firehose with AWS Lambda,
to:
- S3 Bucket
- Amazon OpenSearch Service (previoulsy
known as: Amazon Elasticsearch Service)
- includes OpenSearch Dashboards (previously: Kibana)
- Tutorial: Creating a search application with Amazon OpenSearch Service
- REST
API reference
- Search
- examples (see also Firehose
stream console "Test with demo
data")
curl -v -XGET -u 'master-user:master-user-password' 'https://search-....aos.eu-west-1.on.aws/realtime/_search'
- components
- ...
- CloudFront
Real-Time Monitoring Solution
- Fields
- 46-63: Common Media Client Data (CMCD)
- ...
- Architectures
- Activation
- Problemes / Problems
- ERROR The request could not be satisfied. (400)
- CloudFront has a limit of 20GB per file (L)
- ERROR The request could not be satisfied. (400)
- S3 as origin
- do not allow direct access to S3 and force access using
associated CloudFront
- Restricting access to Amazon S3 content by using an origin access identity (OAI)
- Problems
- when creation of bucket is recent, access through
cloufront returns 307 responses
- AWS CloudFront returns http 307 when origin is S3 bucket
- Solution:
- specify region in origin:
<bucket>.s3.amazonaws.com<bucket>.s3-eu-west-1.amazonaws.com
- specify region in origin:
- when creation of bucket is recent, access through
cloufront returns 307 responses
- index.html in subdirectories (GET /toto/tata/ ->
/toto/tata/index.html)
- using CloudFront
Functions:
function handler(event) {
var request = event.request;
var olduri = request.uri;
var newuri = olduri.replace(/\/$/, '\/index.html');
request.uri = newuri;
return request;
}
- Implementing Default Directory Indexes in Amazon S3-backed Amazon CloudFront Origins Using Lambda@Edge
- Serve index file instead of download prompt
- Lambda@Edge Example Functions
- Redirect to index.html for S3 subfolder
- using CloudFront
Functions:
- Content-Disposition (HTTP header in response)
- Recipe for CloudFront distribution forwarding response-content-disposition to S3
- if request to cloudfront contains the queryparam
?response-content-disposition=..., response will contain http headerContent-Disposition, and content will be downloaded by browser instead of displayed
- in order to queryparam be propagated from cloudfront to s3, cache policy for CloudFront distribution must allow:
- Cache key settings > Query strings: All (default is None)
- do not allow direct access to S3 and force access using
associated CloudFront
- Use functions to customize at the edge
- Two options
- Differences between CloudFront Functions and Lambda@Edge
- Customize
with CloudFront functions (new)
- JavaScript (ECMAScript 5.1 compliant)
- Write
function code
- Function purpose
event type
Modify the HTTP request in a viewer request event type viewer request function handler(event) {
var request = event.request;
// Modify the request object here.
return request;
}
Generate an HTTP response in a viewer request event type viewer request function handler(event) {
var request = event.request;
var response = ...; // Create the response object here,
// using the request properties if needed.
return response;
}
Modify the HTTP response in a viewer response event type viewer response function handler(event) {
var request = event.request;
var response = event.response;
// Modify the response object here,
// using the request properties if needed.
return response;
}
Aquesta taula continua cap a la dreta — desplaça-la o gira el mòbil.
- event structure:
context distributionDomainNamedistributionIdeventType: viewer-request, viewer-responserequestId
viewer ip
request response statusCode(int)statusDescriptionheaderscookiesbodyencodingdata
Aquesta taula continua cap a la dreta — desplaça-la o gira el mòbil.
- ...
- Function purpose
- Exemples / Examples:
- Tutorials
- Tutorial: Create a simple function with CloudFront Functions
- Tutorial:
Create a CloudFront function that includes key
values
- access to KeyValueStore from function:
import cf from 'cloudfront';
// This fails if there is no key value store associated with the function
const kvsHandle = cf.kvs();
async function handler(event) {
const key = ...
let value = "Not found" // Default value
try {
value = await kvsHandle.get(key);
} catch (err) {
console.log(`Kvs key lookup failed for ${key}: ${err}`);
}
...
}
- access to KeyValueStore from function:
- Test functions
- Debug
- activació
- ...
- generació
var request = event.request;
var headers = request.headers;
if (headers.origin && headers.origin.value) {
var receivedOrigin = headers.origin.value;
console.log(`Origin is: ${receivedOrigin}`);
} else {
console.log("No Origin");
}
if (headers.referer && headers.referer.value) {var receivedReferer = headers.referer.value;
console.log(`Referer is: ${receivedReferer}`);
}else {
console.log("No Referer");
}- visualització
- CloudWatch
(N. Virginia) / Logs / Log groups
- /aws/cloudfront/function/myFunction
- ...
- Customize
with Lambda@Edge (old)
- Node.js, Python
- Lambda@Edge
- Adding HTTP Security Headers Using Lambda@Edge and Amazon CloudFront
- Tutorial: Create a basic Lambda@Edge function
- Delete replicated Lambda@Edge functions
- Delete
Lambda@Edge functions and replicas
- go to your CloudFront distribution
- edit your Behaviour:
- (bottom) Function associations: Lambda@Edge -> No association
- ...
- Delete
Lambda@Edge functions and replicas
- ...
- Access restriction
- Info
- Configure secure access and restrict access to content
- Referer restriction
- Geo restriction
- Distribution
- Security > CloudFront geographic restrictions
- No restrictions
- Allow list
- Block list
- using jwt
token
- amazon-cloudfront-functions/redirect-based-on-country
- when creating jwt token, include e.g.:
- "aud": ["FR","AD"]
- in distribution behaviour, include cache header:
CloudFront-Viewer-Country
- when validating jwt token, compare both:
try{
var payload = jwt_decode(jwtToken, secret_key);
log(`payload.aud: ${payload.aud}`)
}
catch(e) {
log(e);
return response401;
}
var headers = request.headers;
if (headers['cloudfront-viewer-country']) {
var countryCode = headers['cloudfront-viewer-country'].value;
log(`countryCode=${countryCode}`)
} else {
log("no cloudfront-viewer-country")
}
if (payload.aud.includes(countryCode)) {
log(`${countryCode} in ${payload.aud}`);
} else {
log(`${countryCode} not in ${payload.aud}`);
}
- Methods
- signed cookies
- signed urls
- jwt token
- ip-whitelisting
- static api-key
- using signed urls
- Use signed URLs
- ...
- using
JWT
tokens
- Using CloudFront functions (new)
- Validate
a simple token in the request
- Verify a JSON Web Token (JWT) using SHA256
HMAC signature:
- amazon-cloudfront-functions/kvs-jwt-verify
- Verify a JSON Web Token (JWT) using SHA256
HMAC signature:
- steps (see: Tutorial:
Create a CloudFront function that includes key
values):
- go to CloudFront Functions console
- Create the key value store (tab:
KeyValueStores)
- Create KeyValueStore
- Name: myJWTVerifyValueStore
- Description: ...
- S3 bucket: (empty)
- go to your recently created KeyValueStore
- Key value pairs
- Add key value pairs
- Add pair
jwt.secret = xxxx
- Add pair
- Associated functions
- (here the associations done from next section will appear)
- ...
- Create KeyValueStore
- Create the function (tab: Functions)
- Create function
- Name: myJWTVerifyFunction
- Description: ...
- Runtime: cloudfront-js-2.0
- go to detail of your recently created function
- Function code:
- paste from aws-samples/amazon-cloudfront-functions/kvs-jwt-verify/verify-jwt.js
- Publish
- Publish function
- Associated distributions
- Add association
- Distribution:
- Event type: Viewer request
- Cache behavior: ...
- Add association
- Create function
- associate
KVS
- go to detail of your function
- Associated KeyValueStore
- Associate existing KeyValueStore
- modify generate-jwt.sh
# same value as in your KeyValueStore
secret='xxxx'
- test
curl -I https://.../myobject?jwt=<token_generated_with_generate-jwt.sh>
- ...
- Validate
a simple token in the request
- Using Lambda@Edge functions (old)
- Secure your Media Workloads with JWT Token with Lambda@Edge
- Protecting your media assets with token authentication
- Protecting an AWS Lambda function URL with Amazon CloudFront and Lambda@Edge
- (valid?) steps
- go to lambda (IMPORTANT: us-east-1 N. Virginal Region, where all CloudFront distributions reside)
- Create Function
- Author from scratch
- Basic information
- Function name: myVerifyJWT
- Runtime: Node.js 20.x
- Additional Configurations
- ...
- open created function details
- Add trigger
- Trigger configuration
- Select a source: CloudFront
- Deploy to Lambda@Edge
- Distribution: ...
- Cache behavior: ...
- CloudFront event: Viewer request
- Include body: disable
- Confirm deploy to Lambda@Edge: enable
- Trigger configuration
- ...
- Using CloudFront functions (new)
- ...
17Route53#
- Routing Queries to an Amazon CloudFront Distribution
- Redireccionament /
Redirect
- Vegeu també / See also: S3 redirect
- Set up DNS based URL forwarding in Amazon Route53
18VPC#
- VPCs and Subnets
- Delete VPC
- Dependency error
- I
tried to delete my Amazon VPC, but I received a
dependency error. How can I delete my Amazon VPC?
AWS_DEFAULT_OUTPUT=json ./vpc_script.sh
- I
tried to delete my Amazon VPC, but I received a
dependency error. How can I delete my Amazon VPC?
- Dependency error
- Differences in CloudFormation
when having a particular VPC
-
default VPC
own VPC
default subnet
own subnet own subnet
AWS::EC2::Subnet
AWS::EC2::RouteTable
AWS::EC2::Route
AWS::EC2::SubnetRouteTableAssociationAWS::EC2::VPC
AWS::EC2::InternetGateway
AWS::EC2::VPCGatewayAttachment
AWS::EC2::Subnet
AWS::EC2::RouteTable
AWS::EC2::Route
AWS::EC2::SubnetRouteTableAssociation
AWS::EC2::SecurityGroup
"VpcId" : {"Ref" : "MyVPC"} AWS::EC2::Instance
"SecurityGroups" : [{ "Ref" : "MySecurityGroup" }] "SecurityGroupIds" : [{ "Ref" : "MySecurityGroup" }]
"SubnetId" : {"Ref" : "MyFirstSubnet"}"SecurityGroupIds" : [{ "Ref" : "MySecurityGroup" }]
"SubnetId" : {"Ref" : "MyFirstSubnet"}AWS::ElasticLoadBalancing::LoadBalancer
"AvailabilityZones" : {"Fn::GetAZs": ""}
"Subnets" : [{"Ref" : "MyFirstSubnet"}] "Subnets" : [{"Ref" : "MyFirstSubnet"}] AWS::AutoScaling::AutoScalingGroup
"AvailabilityZones" : {"Fn::GetAZs": ""} "VPCZoneIdentifier" : [{"Ref" : "MyFirstSubnet"}] "VPCZoneIdentifier" : [{"Ref" : "MyFirstSubnet"}]
Aquesta taula continua cap a la dreta — desplaça-la o gira el mòbil.
-
- Multicast
- Overlay
Multicast
in Amazon Virtual Private Cloud
- Summary
- tag every instance on the same multicast group with tag: multicast=MYCOMMUNITY
- every instance must have a bridge:
bridge_name=mcbr-MYCOMMUNITY
#determine a second local ip address, different from the real one, in a completely different subnet, to give it to the bridge. E.g.:
local_ip_address_and_subnet_used_for_multicast="172.16.0.3/24"
# create the bridge
#deprecated: brctl addbr ${bridge_name}
ip link add name ${bridge_name} type bridge
# set tables
ebtables -P FORWARD DROP
# add address/subnet_mask that will be used for multicast, to bridge
ip addr add ${local_ip_address_and_subnet_used_for_multicast} dev ${bridge_name}
# set bridge up
ip link set ${bridge_name} up
- and a route for multicast:
multicast_cidr="224.0.0.0/4"
#deprecated: route add -net ${multicast_cidr} ${bridge_name}
ip route add${multicast_cidr} dev ${bridge_name}
- every instance must establish a grep tunnel to
each other member of the community (and periodically
check for changes):
local_ip_address="10.0.1.5"
remote_ip_address=...
# got from another script that searches for instances with tag multicast=MYCOMMUNITY
gretap_name=gre-...
# create GRE tunnel interface
ip link add ${gretap_name} type gretap local ${local_ip_address} remote ${remote_ip_address}
# set tunnel up
ip link set dev ${gretap_name} up
# add tunnel interface to bridge
#deprecated: brctl addif ${bridge_name} ${gretap_name}
ip link set ${gretap_name} master ${bridge_name}
- Known limitations
- MTU is reduced by 38 bytes because of GRE
- Info
- Get all instances with a multicast tag, and filter
those within a specific community (e.g.: foo)
aws --output json ec2 describe-instances --filters "Name=tag-key,Values=multicast" >instances_multicast.jsonjq '.Reservations[].Instances[] | select( .Tags[] | . and .Key=="multicast" and (.Value | startswith("foo")) )' instances_multicast.json
- from the selected instances, get only some
information:
jq '.Reservations[].Instances[] | select( .Tags[] | . and .Key=="multicast" and (.Value | startswith("foo")) ) | [.InstanceId, .PrivateIpAddress, .PublicIpAddress, .Tags]' instances_multicast.json
- Get all instances with a multicast tag, and filter
those within a specific community (e.g.: foo)
- Setup
- Setup step 1: prepare network
- Option 1: just create one or more subnets in a existing VPC
- Option 2: Create new AWS VPC (vpc-xxxxxx) with
a subnet and a route table to Internet:
- Subnet
- Name: Public subnet
- IPv4 CIDR: 10.0.0.0/24
- Cloudformation
{
"Resources": {
"MyVPC": {
"Type" : "AWS::EC2::VPC",
"Properties" : {
"CidrBlock": "10.0.0.0/16",
"EnableDnsSupport" : "true",
"EnableDnsHostnames" : "true",
"Tags" :[ { "Key" : "Name", "Value" : "my-vpc"} } ]
}
},
"MyInternetGateway" : {
"Type" : "AWS::EC2::InternetGateway"
},
"MyVPCGatewayAttachment" : {
"Type" : "AWS::EC2::VPCGatewayAttachment",
"Properties" : {
"InternetGatewayId" : {"Ref" : "MyInternetGateway"},
"VpcId" : {"Ref" : "MyVPC"}
}
},
"MyPublicSubnet" : {
"Type" : "AWS::EC2::Subnet",
"Properties" : {
"VpcId" : { "Ref" : "MyVPC" },
"CidrBlock" : "10.0.0.0/24",
"MapPublicIpOnLaunch" : "true",
"Tags" : [ { "Key" : "Name", "Value" : "my-subnet"} ]
}
},
"PublicRouteTable" : {
"Type" : "AWS::EC2::RouteTable",
"Properties" : {
"VpcId" : {"Ref" : "MyVPC"}
}
},
"PublicRoute" : {
"Type" : "AWS::EC2::Route",
"DependsOn" : "MyVPCGatewayAttachment",
"Properties" : {
"RouteTableId" : {"Ref" : "PublicRouteTable"},
"DestinationCidrBlock" : "0.0.0.0/0",
"GatewayId" : {"Ref" : "MyInternetGateway"}
}
},
"PublicSubnetRouteTableAssociation" : {
"Type" : "AWS::EC2::SubnetRouteTableAssociation",
"Properties" : {
"SubnetId" : {"Ref" : "MyPublicSubnet"},
"RouteTableId" : {"Ref" : "PublicRouteTable"}
}
},
}
}
- Subnet
- Setup step 2: Create AWS role with policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1414071732000",
"Effect": "Allow",
"Action": [
"ec2:DescribeInstances",
"ec2:DescribeTags",
"ec2:DescribeRegions"
],
"Resource": [
"*"
]
}
]
}- Cloudformation:
- ...
- Setup step 3: Create AWS security group
(sg-yyyyyy) in your VPC (vpc-xxxxxx)
- Inbound Rules:
- Type: Custom Protocol Rule
- Protocol: GRE (47)
- Port Range: All
- Source: sg-yyyyyy
- Cloudformation (to avoid circular
dependency, because SourceSecurityGroupId
is the same as GroupId, a
AWS::EC2::SecurityGroupIngressmust be created)"MyInboundRule" : {
"Type": "AWS::EC2::SecurityGroupIngress",
"Properties":{
"IpProtocol" : "47",
"SourceSecurityGroupId" : {"Fn::GetAtt" : ["MySecurityGroup","GroupId"]},
"GroupId" : {"Fn::GetAtt" : ["MySecurityGroup","GroupId"]}
}
},
"MySecurityGroup" : {
"Type" : "AWS::EC2::SecurityGroup",
"Properties" : {
"GroupDescription" : "Enable ports 22 (ssh), GRE (47) (multicast)",
"SecurityGroupIngress" : [
{
"IpProtocol" : "tcp",
"FromPort" : "22",
"ToPort" : "22",
"CidrIp" : "0.0.0.0/0"
}
]
}
},"MyInboundRule" : {
"Type": "AWS::EC2::SecurityGroupIngress",
"Properties":{
"IpProtocol" : "47",
"SourceSecurityGroupId" : {"Ref" : "MySecurityGroup"},
"GroupId" : {"Ref" : "MySecurityGroup"}
}
},
"MySecurityGroup" : {
"Type" : "AWS::EC2::SecurityGroup",
"Properties" : {
"GroupDescription" : "Enable ports 22 (ssh), GRE (47) (multicast)",
"VpcId" : {"Ref" : "MyVPC"},
"SecurityGroupIngress" : [
{
"IpProtocol" : "tcp",
"FromPort" : "22",
"ToPort" : "22",
"CidrIp" : "0.0.0.0/0"
}
]
}
},
- Inbound Rules:
- Setup step 4: Creation of several instances with
this role and security group, with tag:
- Name:
multicast; Value:foo,172.16.0.7/24 - Name:
multicast; Value:foo,172.16.0.8/24 - ...
- Name:
- Setup step 1: prepare network
- Installation
- Option 1:
- Installation of Ruby script
- CentOS
sudo yum install unzip bridge-utils ebtables curl ruby ruby-devel rubygem-nokogiri rubygem-daemons libxml2-develsudo gem install aws-sdk-v1 integration libxml-ruby
cdwget https://s3.amazonaws.com/mcd-code/mcd-code-2014-07-11.zipcd mcd-code-2014-07-11sudo chmod 755 *sudo mkdir -p /opt/mcastsudo cp -pr * /opt/mcast'sudo chown -R root:root /opt/mcast
- CentOS
- Start Ruby script
- temporarily
sudo ruby -d /opt/mcast/mcd
- daemon
- CentOS
- mcd.service
[Unit]
Description=Multicast daemon for AWS EC2 instances
After=syslog.target network.target cloud-init.service
[Service]
Type=simple
#PIDFile=/run/mcd.pid
ExecStartPre=/usr/local/bin/mcd_setup.sh foo 172.16.0.0/24
ExecStart=/opt/mcast/mcd
ExecStartPost=/usr/local/bin/mcd_setup_route.sh foo
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s QUIT $MAINPID
[Install]
WantedBy=multi-user.target
- mcd_setup_route.sh
#!/bin/bash
function print_help_and_exit {
cat <<EOF
Usage: `basename $0` multicast_name
Add route for multicast: mcbr-<multicast_name>
Examples:
- `basename $0` foo
EOF
exit 1
}
MIN_ARGS=1
MAX_ARGS=1
if (( $# < $MIN_ARGS )) || (( $# > $MAX_ARGS ))
then
print_help_and_exit
fi
# options
if ! params=$(getopt -o h --long help -n $0 -- "$@")
then
# invalid option
print_help_and_exit
fi
eval set -- ${params}
while true
do
case "$1" in
-h | --help ) print_help_and_exit;;
-- ) shift; break ;;
* ) break ;;
esac
done
# parameters
multicast_name=$1
# wait for bridge to exist
bridge_name="mcbr-${multicast_name}"
timeout=60
increment=5
t=0
while (( t < timeout )) && (brctl show ${bridge_name} 2>&1 1>/dev/null | grep -q "No such device")
do
echo "[`basename $0`] bridge ${bridge_name} is not available yet (${t}s/${timeout}s)"
(( t+=increment ))
sleep ${increment}
done
# add route for multicast
echo "[`basename $0`] adding route for multicast: mcbr-${multicast_name}"
route add -net 224.0.0.0/4 mcbr-${multicast_name}
exit 0
- mcd_setup.sh
#!/bin/bash
function print_help_and_exit {
cat <<EOF
Usage: `basename $0` multicast_name multicast_cidr
Set the AWS EC2 tag: "multicast", "<multicast_name>,<multicast_cidr>"
Address multicast_cidr has the same number as local ip address, but converted to specified subnet
E.g.: if local address is 10.1.2.3/24 and you specify 172.16.0.0/24, the multicast_cidr=172.16.0.3/24
IMPORTANT: role for this ec2 instance must include a policy with: "ec2:CreateTags"
Examples:
- `basename $0` foo 172.16.0.0/24
EOF
exit 1
}
MIN_ARGS=2
MAX_ARGS=2
if (( $# < $MIN_ARGS )) || (( $# > $MAX_ARGS ))
then
print_help_and_exit
fi
# options
if ! params=$(getopt -o h --long help -n $0 -- "$@")
then
# invalid option
print_help_and_exit
fi
eval set -- ${params}
while true
do
case "$1" in
-h | --help ) print_help_and_exit;;
-- ) shift; break ;;
* ) break ;;
esac
done
# parameters
multicast_name=$1
multicast_cidr=$2
function translate_ip {
input_cidr=$1
output_cidr=$2
# remove subnet
input_address=${input_cidr%/*}
# get network and prefix
eval $(ipcalc -np $output_cidr)
output_prefix=$PREFIX
output_network=$NETWORK
# calculate number of bytes (n)
let output_positions=${output_prefix}/8
# remove first n bytes
input_array=(${input_address//./ })
input_significative=${input_array[@]:${output_positions}}
# get first n bytes
output_array=(${output_network//./ })
output_significative=${output_array[@]:0:${output_positions}}
# join all bytes
total_address_array=(${output_significative[@]} ${input_significative[@]})
total_address=$(IFS='.';echo "${total_address_array[*]}";IFS=$'')
total_cidr="${total_address}/${output_prefix}"
echo $total_cidr
}
# check whether ip command is available
if ! (which ip >/dev/null 2>&1)
then
echo "ERROR: command ip not found. Consider running this script as root or sudo."
exit 1
fi
# get own information
local_cidr=$(ip -o address | awk '$2 !~ /lo/ && $3 ~ /^inet$/ {print $4; exit;}')
#local_ipv4=$(curl http://169.254.169.254/latest/meta-data/local-ipv4/)
multicast_cidr=$(translate_ip $local_cidr $multicast_cidr)
echo multicast_cidr: $multicast_cidr
# eu-west-1c
if ! aws_subregion=$(curl -s -m 4 http://169.254.169.254/latest/meta-data/placement/availability-zone)
then
echo "no aws_subregion found. Are you sure that you are running this script on an AWS instance?"
exit 1
fi
# eu-west-1
aws_region=${aws_subregion: : -1}
instance_id=$(curl -s -m 4 http://169.254.169.254/latest/meta-data/instance-id)
# create a tag
aws ec2 create-tags --region ${aws_region} --resources $instance_id --tags Key="multicast",Value="${multicast_name}\,${multicast_cidr}"
exit 0
- mcd.service
- CentOS
- temporarily
- Installation of Ruby script
- Option 2: Install bash script
- Installation of mcd.sh
- Start bash script
- temporarily
- daemon
- CentOS
- Option 1:
- Check
- Process
sudo ps -edalf | grep mcd
- Logs
tail -f /var/log/messages | grep mcd
- Created bridges
brctl show
- Created GRE tunnels
ip link show
- Routes
route -n- ip route
- Members
netstat -g- ip maddr
- Omping:
to test multicast
- from each instance, simultaneously, specify
all the addresses in
, including the own one:local_ip_address_and_subnet_used_for_multicastomping 172.16.0.7 172.16.0.8 ...- output will show the remote address
- if it does not work:
- check if some gretap points to a non
existing address
- to get the remote address, check the logs in /var/log/messages when the gretap was created
- check if some gretap points to a non
existing address
- from each instance, simultaneously, specify
all the addresses in
- Process
- Ús / Usage
- routes
- in each instance, specify that multicast
traffic should go through the bridge:
route add -net 224.0.0.0/4 mcbr-fooip route add 224.0.0.0/4 dev mcbr-foo
- in each instance, specify that multicast
traffic should go through the bridge:
- application:
- from one instance:
ffmpeg ...
- from the other one:
- ...
- from one instance:
- routes
- Summary
- Overlay
Multicast
in Amazon Virtual Private Cloud
19Big data and analytics#
- cs
- Kinesis
- Elastic Map Reduce (EMR)
- Redshift
- Getting Started with Amazon Redshift
- Tutorial: Tuning Table Design
- Masterclass
Webinar
- Amazon Redshift (YouTube)
- Masterclass - Redshift (Slideshare)
20CLI#
- AWS Command Line Interface
- Instal·lació / Installation (python)
- Install or update the latest version of the AWS CLI (v2)
- What Is the AWS Command Line Interface?
- Pip
pip install awscli
- apt-get (Ubuntu)
sudo apt-get install awscli
- Ús / Usage
aws --version ...
- Problemes / Problems
ImportError: No module named history- the problem is that a pair of awscli (1.14.28) and
botocore (1.6.0), installed from yum (
awscli.noarch), does not work - Solucions / Solutions
- Swap s3transfer packages (awscli-1.14.28-5):
yum swap python2-s3transfer python-s3transfer
- Use pip
sudo pip install awscli- a pair of working packages is, e.g.:
awscli==1.14.28, botocore==1.8.32
- a pair of working packages is, e.g.:
- Swap s3transfer packages (awscli-1.14.28-5):
- the problem is that a pair of awscli (1.14.28) and
botocore (1.6.0), installed from yum (
- queries
- templates
--generate-cli-skeleton > skeleton.json--cli-input-json file://skeleton.json
- stdin/stdout
aws s3 cp s3://bucket/key - | bzip2 -best | aws s3 cp - s3://bucket/key.bz2
- CLI
reference
- Environment
variables to configure the AWS CLI
AWS_PROFILEAWS_DEFAULT_OUTPUTAWS_DEFAULT_REGION...
- general
options
--debug
--region eu-west-1--profile myprofile--output json...
aws autoscaling- launch configuration
aws autoscaling create-launch-configuration --launch-configuration-name lc_stateless_yyyymmdd_hhmm --image-id ami-2dd81a5a --security-groups launch-wizard-2 --instance-type t1.microaws autoscaling describe-launch-configurations --launch-configuration-names lc_stateless_yyyymmdd_hhmm- pas de paràmetres en
crear una instància / pass parameters when
creating an instance:
aws autoscaling create-launch-configuration --user-data ...
- autoscaling
group
aws autoscaling create-auto-scaling-group --auto-scaling-group-name grup_stateless --launch-configuration-name lc_stateless_yyyymmdd_hhmm--min-size 1 --max-size 2 --load-balancer-names lb-statelessaws autoscaling update-auto-scaling-group --auto-scaling-group-name grup_stateless --launch-configuration-name lc_stateless_yyyymmdd_hhmm- number of instances inside an autoscaling group,
given its name
result=$(aws --output json autoscaling describe-auto-scaling-groups --auto-scaling-group-names $asg_name)
number_instances=$(echo $result | jq '.AutoScalingGroups[0].Instances | length')
- get autoscaling group, given its tag Name=myname:
asg_info=$(aws --output json autoscaling describe-auto-scaling-groups)
asg_name_tag_value="myname"
asg=$(echo "$asg_info" | jq ".AutoScalingGroups[] | select( .Tags[] | . and .Key==\"Name\" and .Value==\"${asg_name_tag_value}\")")
aws autoscaling set-desired-capacity --auto-scaling-group-name $asg_name --desired-capacity 2- Instance protection
aws autoscaling set-instance-protection --instance-ids i-93633f9b --auto-scaling-group-name my-auto-scaling-group --protected-from-scale-in
- given an instance id, get the autoscaling
group name it belongs to:
aws ec2 describe-tags --filters "Name=resource-id,Values=$instance_id" "Name=key,Values=aws:autoscaling:groupName" | jq '.Tags[] | .Value'- ...
- retrieve own instance id and region and get the autoscaling group name it belongs to:
REGION=$(curl -s http://169.254.169.254/latest/meta-data/placement/region)
INSTANCE_ID=$(curl -s http://169.254.169.254/latest/meta-data/instance-id)
aws ec2 describe-instances --instance-id $INSTANCE_ID --query "Reservations[*].Instances[*].Tags[?Key=='aws:autoscaling:groupName'].Value" --region $REGION --output text
- get all autoscaling groups (with pagination)
aws_options="--profile my_profile --output json --region eu-west-1"
next_token=""
max_items=50
page_size=100
total_number=0
total_elements=$(jq -n '[]')
while [[ $next_token != "null" ]]
do
if [[ "$next_token" ]]
then
lc_info=$(aws ${aws_options} autoscaling describe-launch-configurations --max-items $max_items --page-size $page_size --starting-token $next_token)
else
lc_info=$(aws ${aws_options} autoscaling describe-launch-configurations --max-items $max_items --page-size $page_size)
fi
#echo $lc_info | jq '.'
returned_number=$(echo $lc_info | jq '.LaunchConfigurations | length' )
returned_elements=$(echo $lc_info | jq '.LaunchConfigurations')
echo $returned_elements | jq '.'
total_elements=$( echo $total_elements | jq ". += $returned_elements")
echo "returned_number: $returned_number"
total_number=$(( total + returned_number ))
echo "total_number: $total_number"
echo $lc_info | jq '.LaunchConfigurations[] | ([.LaunchConfigurationName] | join (" "))'
next_token=$(echo $lc_info | jq '.NextToken')
echo "next_token: $next_token"
done
echo "---------------------------"
echo $total_elements | jq '.[].LaunchConfigurationName'
- launch configuration
aws cloudformationaws cloudfrontaws configure set preview.cloudfront true- list all distributions
aws cloudfront list-distributions--output json
- get a specific distribution:
- aws cloudfront get-distribution --id E1KBXTVP599T0A
- get the config for a specific distribution
- aws cloudfront get-distribution-config --id E1KBXTVP599T0A
- update distribution
aws cloudfront get-distribution-config --id ${cloudfront_id} --output json > /tmp/${cloudfront_id}.json
# get etag
etag=$(jq -r '.ETag' /tmp/${cloudfront_id}.json)
# modify/tmp/${cloudfront_id}.json
...
aws cloudfront update-distribution --id ${cloudfront_id} --if-match $etag --distribution-config $(jq -c '.DistributionConfig' /tmp/${cloudfront_id}.json)
aws configure- boto3 credentials
- generated files
~/.aws/credentials(for all SDKs)~/.aws/config(only for CLI)
- crearà / will create: ~/.aws/config
[default]
output = json
region = eu-west-1aws_access_key_id = xxx
aws_secret_access_key = yyy
[preview]
cloudfront = true
- i/and
~/.aws/credentials (? now included in
~/.aws/config)
[default]
aws_access_key_id = xxx
aws_secret_access_key = yyy
- per a fer servir un altre perfil / to use another
profile
aws --profile myprofile configure- will create ~/.aws/config
[profile myprofile]
output = json
region = eu-west-1
- and ~/.aws/credentials
[myprofile]aws_access_key_id = xxx
aws_secret_access_key = yyy
- una de les següents opcions / one of the
following:
aws --profile myprofile ...- #
necessari quan es fa servir kubectl i eksctl
export AWS_PROFILE=myprofile
aws ...
- per saber quina arn es fa servir en la crida:
aws sts get-caller-identityaws sts get-caller-identity --profile ...- Problemes
An error occurred (InvalidClientTokenId) when calling the GetCallerIdentity operation: The security token included in the request is invalid
- per a configurar un role com a perfil (myuser ha de
poder assumir el role myrole)
- .config
[profile my-role]
role_arn = arn:aws:iam::xxxx:role/myrole
source_profile = myuser
- .config
- per a fer servir un altre fitxer de configuració / to
use an alternate config file (e.g.
/etc/aws/config):export AWS_CONFIG_FILE=/etc/aws/config- AWS_CONFIG_FILE vs. AWS_CREDENTIAL_FILE #1037
- to use it from a user without home:
sudo -isu nginx -s /bin/bash -c "export AWS_ACCESS_KEY_ID=...; export AWS_SECRET_ACCESS_KEY=...; export AWS_CONFIG_FILE=/etc/aws/config; aws..."- variables can be extracted from /etc/aws/credentials using awk
- or use a role if the code is executed from an EC2 instance
- aws efs
- file system
- mount targets
- create a security group for NFS (port 2049)
group_name="sgroup-nfs-toto"
vpc_id="vpc-..."
description="Enable port 2049 (nfs)"
response=$(aws ec2 create-security-group --group-name ${group_name} --vpc-id ${vpc_id} --description "${description}")
group_id=$(echo ${response} | jq -r '.GroupId')
echo ${group_id}protocol=tcp
port=2049
cidr="" # cidr of the subnet inside the vpc
aws ec2 authorize-security-group-ingress --group-id ${group_id} --protocol ${protocol} --port ${port} --cidr "${cidr}"- create a mount target
subnet_id="subnet-..."echo ${mount_target_id}
response=$(aws efs create-mount-target --file-system-id ${file_system_id} --subnet-id ${subnet_id} --security-groups ${group_id})
mount_target_id=$(echo ${response} | jq -r '.MountTargetId')
- get info about a mount target
response=$(aws efs describe-mount-targets --mount-target-id ${mount_target_id})
- mount efs from an instance
awsec2- instances
aws ec2 run-instances
aws ec2 start-instances --instance-ids i-9b789ed8- filter by name:
aws --output=json ec2 describe-instances --filters 'Name=tag:Name,Values=myprefix*' --query 'Reservations[*].Instances[*].InstanceId'aws --output=json ec2 describe-instances --filters 'Name=tag:Name,Values=myprefix*' | jq '.Reservations[].Instances[].InstanceId'aws ec2 describe-instances --filters Name=tag:Name,Values=ubuntu_1310- ...
TAGS Name ubuntu_1310 - get PublicIpAddress
aws --output json ec2describe-instances--instance-ids i-9b789ed8 | jq -r '.Reservations[0].Instances[0].PublicIpAddress'
- ...
- get a list and process it:
instance_name="myprefix-*"
instances=$(aws --output=json ec2 describe-instances --filters "Name=tag:Name,Values=${instance_name}" | jq -r '.Reservations[].Instances[]')
while IFS= read -r instance
do
echo "-- "
echo ${instance} | jq ''
instance_id=$(echo ${instance} | jq -r '.InstanceId')
echo "instance_id: ${instance_id}"
instance_name=$(echo ${instance} | jq -c -r '(.Tags | values | .[] | select(.Key == "Name") ) | .Value')
echo "instance_name: ${instance_name}"
public_dns_name=$(echo ${instance} | jq -r '.PublicDnsName')
echo "public_dns_name: ${public_dns_name}"
security_groups=$(echo ${instance} | jq -c -r '[.SecurityGroups[].GroupId] | join(" ")')
echo "security_groups: ${security_groups}"
done < <(echo "$instances" | jq -c '.')
- ...
aws ec2 describe-instance-attribute --instance-id i-896b92c9 --attribute instanceType
aws ec2 stop-instances --instance-ids i-9b789ed8aws ec2 terminate-instances--instance-ids i-9b789ed8- waiters
- add a security group
securitygroups=$(aws ec2 describe-instances --instance-ids ... --query "Reservations[].Instances[].SecurityGroups[].GroupId[]" --output text)securitygroups+=" sg-12345678"
aws ec2 modify-instance-attribute --instance-id ... --groups $securitygroups
- images
- create an image:
instance_id=i-xxxxxxx
image_prefix=image_u1404
data=$(date '+%Y%m%d_%H%M')
imatge_id=$(aws ec2 create-image --instance-id ${instance_id} --name "${image_prefix}_${data}" --description "My description")
echo "${imatge_id} ${image_prefix}_${data} (from ${instance_id})"
- create an image but root volume (
/dev/sda1) will be destroyed on termination (useful when this image will be used in a launch configuration of an autoscaling group)instance_id=i-xxxxxxx
image_prefix=image_u1404
data=$(date '+%Y%m%d_%H%M')
imatge_id=$(aws ec2 create-image --instance-id ${instance_id} --name "${image_prefix}_${data}" --description "My description" --block-device-mappings "[{\"DeviceName\": \"/dev/sda1\",\"Ebs\":{\"VolumeType\":\"gp2\",\"DeleteOnTermination\":true}}]")
echo "${imatge_id} ${image_prefix}_${data} (from ${instance_id})"
- describe images:
- get all own images
aws ec2describe-images--owners selfaws_options="--profile my_profile --output json --region eu-west-1"
ami_info=$(aws ${aws_options} ec2 describe-images --owners self)
echo $ami_info | jq '.Images | sort_by(.Name) | .[] | [.ImageId, .OwnerId, .Name] | join(" ")'
- describe an image given its id
aws ec2 describe-images --image-id ami-xxxx --output json
- get an image by name:
aws ec2 describe-images--owners self --filters "Name=name,Values=my_image_name"--output json
- using wildcards:
aws ec2 describe-images--owners self --filters "Name=name,Values=my_image_basename*"--output json
- get image_id of an image with given its name:
aws ec2 describe-images--owners self --filters "Name=name,Values=my_image_name" --output json | awk '/ImageId/ {print $2}' | tr -d '",'aws ec2 describe-images--owners self --filters "Name=name,Values=my_image_name" --output json | jq -r '.Images[].ImageId'
- get a list of amis, sorted by creation date
aws ec2 describe-images--owners self --filters "Name=name,Values=my_image_basename*" --output json | jq -r '(.Images | sort_by(.CreationDate) | .[] | [.CreationDate, .ImageId] | join(" ") )'
- get image_id of the most recent image:
aws ec2 describe-images--owners self --filters "Name=name,Values=my_image_basename*" --output json |jq -r '(.Images | sort_by(.CreationDate) | .[-1] | .ImageId )'
aws ec2 describe-image-attribute --image-id ami-6be62b1c --attribute description
- get all own images
- waiters
aws ec2 wait image-available--image-idami-6be62b1c- Problemes / Problems
- Waiter ImageAvailable failed: Max attempts
exceeded
- Solució / Solution
aws -debug ...- AWS
CLI retries
- env
export AWS_RETRY_MODE=standard
export AWS_MAX_ATTEMPTS=2 # default for standard
- config
[default]
retry_mode = standard
max_attempts = 2
- env
- Waiter ImageAvailable failed: Max attempts
exceeded
- create an image:
- snapshots
- get all own snapshots
aws ec2 describe-snapshots --owner self
- get all own snapshots
- add tags to an:
- instance:
aws ec2 create-tags --resourcesi-9b789ed8--tags Key=Name,Value=ubuntu_1404
- image:
aws ec2create-tags--resourcesami-6be62b1c --tags Key=Name,Value=image_ubuntu_1404value="..."
# escape commas and remove single quotes
escaped_value=$(echo ${value//,/\\,} | tr -d "'")
aws ec2create-tags--resourcesami-6be62b1c --tags Key=Name,Value="${escaped_value}"
- instance:
- get tags from an:
- instance
aws ec2 describe-tags --filters "Name=resource-id,Values=i-1234567890abcdef8"
- instance
- create an instance from an image:
aws ec2 run-instances --image-idami-6be62b1c --security-groups launch-wizard-2--count 1 --key-name my_keyname--placement AvailabilityZone='eu-west-1a',Tenancy='default' --instance-typet2.micro- get the instance_id:
- reponse in json (parse with jq)
instance_description=$(aws --output json ec2 run-instances --image-id $image_id --security-groups $security_group_name --iam-instance-profile Name="role-nfs_server" --count 1 --key-name $key_name --placement AvailabilityZone=${availability_zone},Tenancy='default' --instance-type $instance_type --block-device-mappings 'DeviceName=/dev/sda1,Ebs={DeleteOnTermination=true,VolumeType=gp2}' )instance_id=$(echo $instance_description | jq -r '.Instances[0].InstanceId')
- response in text (parse with awk)
instance_id=$(aws --output text ec2 run-instances --image-idami-6be62b1c --security-groups launch-wizard-2--count 1 --key-name my_keyname--placement AvailabilityZone='eu-west-1a',Tenancy='default' --instance-typet2.micro | awk '/INSTANCES/ {print $8}')aws ec2 describe-instances--instance-ids$instance_id
- reponse in json (parse with jq)
- overwrite the delete on termination behaviour:
aws ec2 run-instances --image-idami-6be62b1c ... --block-device-mappings 'DeviceName=/dev/sda1,Ebs={DeleteOnTermination=true,VolumeType=gp2}'
- ...
- dades d'usuari
/user data:
- when creating instance:
aws ec2 run-instances ...--user-data "..."...aws ec2 run-instances ...--user-data "#!/bin/bash\n..."
- des de la instància / from ec2 instance:
curl http://169.254.169.254/latest/user-data/
- ec2-run-user-data (ec2ubuntu) (already installed in EC2 Ubuntu ami)
- when creating instance:
- dades d'usuari
/user data:
- assign a role to the instance
- Launching an Instance with an IAM Role Using the AWS CLI
- Assign IAM role to EC2 instance with AWS CLI
- Passos / Steps
- If role has not been created using the
console:
- create a role
- ...
- create an instance
profile
aws iam create-instance-profile --instance-profile-name s3access-profile
- add the existing role (
s3access) to the instance profileaws iam add-role-to-instance-profile --instance-profile-name s3access-profile --role-name s3access
- create a role
- launch an instance with the instance
profile (if role was created using console,
an instance profile with the same name of
the role was automatically created)
aws ec2 run-instances ... --iam-instance-profile Name="s3access-profile" ...
- If role has not been created using the
console:
- Problems:
- Client.InvalidParameterCombination: Could not
create volume with size 10GiB and iops 30 from
snapshot 'snap-xxxxx'
- AutoScaling - Client.InvalidParameterCombination
- Re: Stabilization Error (Again)
- "Iops" should not be there (?)
- Workaround: create image from web interface instead
- Solution: add
--block-device-mappingsoption (following example is for 10GiB volume)aws ec2 create-image --instance-id i-xxxxxxxx --name AMIName --block-device-mappings '[{"DeviceName":"/dev/sda1","Ebs":{"VolumeType":"gp2","DeleteOnTermination":"true","VolumeSize":10}}]'
- Client.InvalidParameterCombination: Could not
create volume with size 10GiB and iops 30 from
snapshot 'snap-xxxxx'
- volumes
- create a volume
volume_description=$(aws ec2 create-volume --availability-zone $availability_zone --volume-type $volume_type --size $small_volume_size_gibytes)volume_id=$(echo $volume_description | jq '.VolumeId')
- wait for volume to be created
- aws ec2 wait volume-available
- tag a volume with a name
aws ec2create-tags--resources $volume_id --tags Key=Name,Value=$volume_name
- describe a volume with specified name:
aws ec2 describe-volumes --filters Name=tag:Name,Values=my-volume-name
- get availability zone of a volume
aws_cli_options="--profile my_profile --output json"
volume_name=my-volume-name
volume_description=$(aws $aws_cli_options ec2 describe-volumes --filters "Name=tag:Name,Values=$volume_name")
availability_zone=$(echo $volume_description | jq -r '.Volumes[0].AvailabilityZone')
- attach a volume to an instance
aws ec2 attach-volume --volume-id $volume_id --instance-id $instance_id --device /dev/sd${volume_letter}
- detach volume
aws ec2 detach-volume--volume-id $volume_id
- list all volumes
response=$(aws --output json ec2 describe-volumes)
while IFS= read -r; do
volume=$REPLY
volume_id=$(echo $volume | jq -r '.VolumeId')
echo "--- VolumeId: $volume_id"
#tags=$(echo $volume | jq -c -r '(.Tags | values | .[] | select(.Key == "Name") )')
tags=$(echo $volume | jq -c -r '(.Tags | values | .[] )')
for tag in $tags
do
tag_key=$(echo $tag | jq '.Key')
tag_value=$(echo $tag | jq '.Value')
echo " $tag_key: $tag_value"
done
done < <(echo "$response" | jq -c -r '.[] | .[]')
- create a volume
- network interfaces
- list network interfaces associated to a given
security group:
aws ec2 describe-network-interfaces --filters "Name=group-id,Values=sg-002009be0b4657d87" --query "NetworkInterfaces[*].NetworkInterfaceId" --output text
- delete network interfaces associated to a given
security group:
aws ec2 describe-network-interfaces --filters "Name=group-id,Values=sg-002009be0b4657d87" --output json | jq -r ".NetworkInterfaces[].NetworkInterfaceId" | xargs -I{} aws ec2 delete-network-interface --network-interface-id {}
- list network interfaces associated to a given
security group:
- instances
aws elb- create a load balancer and associate to an instance:
aws elb create-load-balancer --load-balancer-name lb-stateful --listeners Protocol=HTTP,LoadBalancerPort=80,InstanceProtocol=HTTP,InstancePort=80 --availability-zones eu-west-1a eu-west-1b eu-west-1c --security-groups sg-ba33c2dfaws elb configure-health-check --load-balancer-name lb-stateful --health-check Target=TCP:80,Interval=30,Timeout=10,UnhealthyThreshold=2,HealthyThreshold=2aws elb register-instances-with-load-balancer --load-balancer-namelb-stateful--instancesi-9b789ed8
create a load balancer to be associated to an autoscaling group:aws elbcreate-load-balancer--load-balancer-name lb-stateless --listeners Protocol=TCP,LoadBalancerPort=1935,InstanceProtocol=TCP,InstancePort=1935 Protocol=HTTP,LoadBalancerPort=8080,InstanceProtocol=HTTP,InstancePort=8080 --availability-zones eu-west-1a eu-west-1b eu-west-1c --security-groups sg-ba33c2dfaws elb configure-health-check --load-balancer-name lb-stateless --health-check Target=TCP:8080,Interval=30,Timeout=10,UnhealthyThreshold=2,HealthyThreshold=2
- add an HTTPS listener
with ARN
of an uploaded IAM certificate
aws --region eu-west-1 elb create-load-balancer-listeners --load-balancer-name $load_balancer_name --listeners Protocol=HTTPS,LoadBalancerPort=443,InstanceProtocol=HTTPS,InstancePort=443,SSLCertificateId=$ARN
- modify the certificate of an existing listener for a
given port:
aws --region $aws_region elb set-load-balancer-listener-ssl-certificate --load-balancer-name $load_balancer_name --load-balancer-port $load_balancer_port --ssl-certificate-id $ARN
- create a load balancer and associate to an instance:
- aws iam
- certificats
de servidor / server certificates
- upload a certificate
- obtained e.g. from Letsencrypt
letsencrypt_dirname=/etc/letsencrypt
aws iam upload-server-certificate --server-certificate-name cert-${domain} \
--certificate-body file://${letsencrypt_dirname}/live/${domain}/cert.pem \
--private-key file://${letsencrypt_dirname}/live/${domain}/privkey.pem \
--certificate-chain file://${letsencrypt_dirname}/live/${domain}/chain.pem
- self-signed, to be used in cloudfront:
openssl req -new -nodes -keyout www.toto.org.key -sha256 -x509 -days 365 -out www.toto.org.crt- Common Name:
www.toto.org
- Common Name:
aws iamupload-server-certificate \
--server-certificate-name cert-www.toto.org \
--certificate-body file://.../www.toto.org.crt \
--private-key file://.../www.toto.org.key \
--certificate-chainfile://.../www.toto.org.crt \
--path /cloudfront/
- obtained e.g. from Letsencrypt
- get a list of server certificates
aws --output json iam list-server-certificates
- get ARN of a
certificate (will be specified when adding a listener to a
ELB)
ARN=$(aws --output json iam get-server-certificate --server-certificate-name ${domain}.cert | jq '.ServerCertificate.ServerCertificateMetadata.Arn')
- check if a certificate is available
- ...
- upload a certificate
- certificats
de servidor / server certificates
aws rds- Cancel a pending modification (e.g. change instance
type)
- How do you remove/undo/delete a pending modification on Amazon Aurora RDS?
- passos / steps (e.g. to cancel an upgrade from
db.m6g.xlarge to db.m6g.2xlarge)
- verify that there is a pending modification
aws --output=json rds describe-db-instances --db-instance-identifier my-db-identifier | jq '.DBInstances[].PendingModifiedValues'- {
"DBInstanceClass": "db.m6g.2xlarge"
}
- {
- undo changing instance type by setting the old
value
- aws
--output=jsonrds modify-db-instance --db-instance-identifier my-db-identifier --db-instance-class db.m6g.xlarge | jq '.DBInstance.PendingModifiedValues'- ...
- aws
- verify that there is no pending modification
aws --output=json rds describe-db-instances --db-instance-identifier my-db-identifier | jq '.DBInstances[].PendingModifiedValues'- {}
- verify that there is a pending modification
- Cancel a pending modification (e.g. change instance
type)
aws route53- Adding EC2 instances to Route53 (bash+boto)
- Creating Route53 Record Sets via Shell Script
aws route53 list-resource-record-sets --hosted-zone-idxxxxxx
aws route53 change-resource-record-sets --hosted-zone-id xxxxxx --change-batch file:///absolute_path_to/change_entry.jsonchange_entry.json(to modify record www.toto.org; e.g. TTL value){
"Comment": "Modifying TTL to 55",
"Changes": [
{
"Action": "UPSERT",
"ResourceRecordSet": {
"Name": "www.toto.org.",
"Type": "A",
"TTL": 55,
"ResourceRecords": [
{
"Value": "xx.xx.xx.xx"
}
]
}
}
]
}
- Auto configuration of Route53 from EC2 at boot (Ubuntu
Upstart)
- previously, from any computer:
- option 1 (preferred): create a role and assign
it to the instance when launching it. This role
should have the following policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"route53:ChangeResourceRecordSets",
"route53:ListHostedZonesByName"
],
"Resource": [
"*"
]
}
]
}
- option 2: create a user
- create a user and group that can only
modify Route53 entries:
- from web interface:
- Grup
- Group name
- grup_nomes_route53
- Policy
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"route53:*"
],
"Resource": [
"*"
]
}
]
}
- Group name
- Grup
- alternatively, from aws cli:
- ...
- from web interface:
- create a user and group that can only
modify Route53 entries:
- option 1 (preferred): create a role and assign
it to the instance when launching it. This role
should have the following policy:
- once logged into EC2 instance:
- only if used option 2 (not using a role):
- as user (e.g. ubuntu):
- as user (e.g. ubuntu):
- set_route53_with_my_ip.sh
#!/bin/bash
EXPECTED_ARGS=1
if (( $# != $EXPECTED_ARGS ))
then
cat <<EOF
Usage: $(basename $0) name
Examples:
- $(basename $0) myserver.toto.org
EOF
exit 1
fi
full_name=$1
name=${full_name%%.*}
domain=${full_name#*.}
echo "name: ${name}"
echo "domain: ${domain}"
function on_exit {
rm -f $tmp_file
}
# when EXIT signal is sent to this script (either from an exit command or from a CTRL-C), go to finish function
trap on_exit EXIT
full_zone_id=$(aws route53 list-hosted-zones-by-name --dns-name ${domain} | jq -r '.HostedZones[0].Id')
zone_id=${full_zone_id##*/}
echo "zone_id: ${zone_id}"
# zone_id for mydomain.org
ip_address=$(curl http://169.254.169.254/latest/meta-data/public-ipv4)
tmp_file=$(mktemp)
cat > ${tmp_file} <<EOF
{
"Comment": "Modifying ip address",
"Changes": [
{
"Action": "UPSERT",
"ResourceRecordSet": {
"Name": "${full_name}.",
"Type": "A",
"TTL": 60,
"ResourceRecords": [
{
"Value": "${ip_address}"
}
]
}
}
]
}
EOF
cat ${tmp_file}
aws route53 change-resource-record-sets --hosted-zone-id ${zone_id} --change-batch file://${tmp_file}
exit 0
- /usr/local/bin/route53.sh
#!/bin/bash
# zone_id formydomain.org
ZONE_ID=$(cat zone_id.txt)
ip_address=$(curl http://169.254.169.254/latest/meta-data/public-ipv4)
name=www.mydomain.org
tmp_file=/tmp/modify_record_set.json
rm -f $tmp_file
#aws route53 list-resource-record-sets --hosted-zone-id $ZONE_ID
cat > $tmp_file <<EOF
{
"Comment": "Modifying ip address",
"Changes": [
{
"Action": "UPSERT",
"ResourceRecordSet": {
"Name": "${name}.",
"Type": "A",
"TTL": 60,
"ResourceRecords": [
{
"Value": "$ip_address"
}
]
}
}
]
}
EOF
#source /opt/p27/bin/activate
aws route53 change-resource-record-sets --hosted-zone-id $ZONE_ID --change-batch file://$tmp_file
#deactivate
exit 0
- init script
- CentOS
- /etc/systemd/system/route53.service
[Unit]
Description=Description of my script
After=syslog.target network.target
[Service]
Type=oneshot
ExecStart=/usr/local/bin/route53.sh
[Install]
WantedBy=multi-user.target
sudo systemctl enable route53.servicesudo systemctl start route53.service
- /etc/systemd/system/route53.service
- Ubuntu
- /etc/init/route53.conf
description "route53 daemon"
start on (filesystem and net-device-up IFACE=lo)
stop on runlevel [!2345]
env DAEMON=/usr/local/bin/route53.sh
env PID=/var/run/route53.pid
env AWS_CONFIG_FILE=/home/ubuntu/.aws/credentials
exec $DAEMON
- /etc/init/route53.conf
- CentOS
- only if used option 2 (not using a role):
- previously, from any computer:
aws s3- Note: no need to create dirs: they do not exist
- get total usage of a bucket, using cloudwatch
- Velocitat / Speed
- aws s3 slow upload/download speed for bigfiles #6736
- with awscli v2:
- ~/.aws/config
[default]
s3 =
preferred_transfer_client = crt
- ~/.aws/config
- list all buckets
aws s3 ls
- list all files in a "directory":
aws s3 ls --recursive s3://my_bucket/my_dir1/
- dry-run copy a single file to S3:
aws s3 cp --dryrun toto.txt s3://my_bucket/
- copy a single file to S3:
aws s3 cp toto.txt s3://my_bucket/
- recursively copy to S3:
aws s3cp--recursive . s3://my_bucket/
- recursively copy from S3:
aws s3--recursive s3://my_bucket/ .cp
- remove
- Use of Exclude and Include Filters
- remove toto1.txt, toto2.txt ... from /path/to/
aws s3 rm [--dryrun] --recursive --exclude "*" --include "toto[0-9].txt" "s3:/my_bucket/path/to"
- sync
aws s3 sync ... --exclude '*.png' --exclude 'log' ...- Problemes / Problems
- content-type for webp images on S3 is
binary/octet-stream instead of image/webp
- because aws s3 command relies on mimetypes Python library
- Solució / Solution
- on CentOS 8 you need to install
package mailcap (
sudo dnf install mailcap), which will install file /etc/mime.types
- on CentOS 8 you need to install
package mailcap (
- sincronització lenta quan hi ha molts fitxers
/ slow sync when a lot of files exist
- AWS S3 Sync very slow when copying to large directories
- Solució / Solution
- feu servir / use: "
aws s3 cp --recursive ..."
- feu servir / use: "
- content-type for webp images on S3 is
binary/octet-stream instead of image/webp
- Problemes / Problems
aws s3 ls s3://mybucket/mydir
An error occurred (AccessDenied) when calling the ListObjectsV2 operation: Access Denied- Solució / Solution
- policy:
{
"Sid": "0",
"Effect": "Allow",
"Action": [
"s3:ListBucket"
],
"Resource": "arn:aws:s3:::mybucket"
}
- policy:
- Solució / Solution
aws cloudwatch- CloudWatch
- get metrics from an s3
bucket (e.g. usage):
- using boto3
aws cloudwatch get-metric-statistics --namespace AWS/S3 --start-time 2021-12-20T10:00:00 --end-time 2021-12-20T12:00:00 --period 86400 --statistics Average --region eu-west-1 --metric-name BucketSizeBytes --dimensions "Name=BucketName,Value=my_bucket_name Name=StorageType,Value=StandardStorage"- ...
- get downloaded bytes metrics from a cloudfront
distribution (limited to 1440 datapoints: equivalent to
e.g. 60 days at one hour resolution):
- retention policy:
- ...
- 1-day (86400 seconds) resolution:
aws cloudwatch get-metric-statistics --start-time 2024-01-01T00:00:00Z --end-time 2024-12-31T23:59:59Z --namespace "AWS/CloudFront" --statistics Sum --period 86400 --metric-name BytesDownloaded --dimensions Name=DistributionId,Value=Exxxx Name=Region,Value=Global --region us-east-1
- retention policy:
awsecr- get images in a registry (aws account id) and
repository (created by you)
aws ecr describe-images --repository-name=<my_account_id> --repository-name=<my_repository_name>
- ...
- get images in a registry (aws account id) and
repository (created by you)
aws eks- get arn for a cluster
cluster_arn=$(aws eks describe-cluster --name ${cluster_name} | jq -r '.cluster.arn')
- tag cluster
aws ekstag-resource--resource-arn ${cluster_arn} --tags my_tag_key=my_tag_value
- get cluster information
- aws eks describe-cluster --name ${CLUSTER_NAME} --query "cluster.endpoint" --output text
- get arn for a cluster
- Environment
variables to configure the AWS CLI
21Boto ( Python )#
- Instal·lació / Installation
- v3
pip install boto3
- v2
pip install boto- Alternative: get it from git and install it:
- cd ~/src
- git clone https://github.com/boto/boto.git
- cd boto
- [source /opt/PYTHON27/bin/activate]
- python setup.py install
- v3
- Credencials / Credentials
- aws configure
- ~/.boto
[Credentials]
aws_access_key_id = xxxx
aws_secret_access_key = yyyy
- Django
- if instance running Django has no IAM role, and Django uses boto3 (e.g. django-storages), the credentials must be set at settings.py
- settings.py
AWS_ACCESS_KEY_ID = '...'
AWS_SECRET_ACCESS_KEY = '...'
- Celery
- in an instance running Celery / Django without IAM
role, if a process called by celery uses boto3 (e.g. django-storages),
variables defined in Django settings.py are not set.
They must explicitly be set at celery.conf (called as
EnvironmentFileby celery.service) - celery.conf
AWS_ACCESS_KEY_ID = '...'
AWS_SECRET_ACCESS_KEY = '...'
- in an instance running Celery / Django without IAM
role, if a process called by celery uses boto3 (e.g. django-storages),
variables defined in Django settings.py are not set.
They must explicitly be set at celery.conf (called as
- Docs
- Problemes / Problems
An error occurred (Throttling) when calling the DescribeStacks operation (reached max retries: 4): Rate exceeded
- Usage
- Amazon EC2 Basics For Python Programmers
- Difference in boto3 between resource, client, and session?
-
examples
default session
specific session
Amazon S3 Examples
Session
- stores configuration information (primarily credentials and selected region)
- allows you to create service clients and resources
- boto3 creates a default session for you when needed
-
session = boto3.Session(profile_name='dev')
Resource - higher-level, object-oriented API
- generated from resource description
- uses identifiers and attributes
- has actions (operations on resources)
- exposes subresources and collections of AWS resources
- does not provide 100% API coverage of AWS services
creation
s3_resource = boto3.resource('s3')...
methods
s3_resource.create_bucket(Bucket='mybucket')
bucket = s3_resource.Bucket("mybucket")
bucket.objects.filter(Prefix="myprefix/").delete()Client
- low-level AWS service access
- generated from AWS service description
- exposes botocore client to the developer
- typically maps 1:1 with the AWS service API
- all AWS service operations are supported by clients
- snake-cased method names (e.g. ListBuckets API => list_buckets method)
creation
from resource
s3_client = s3_resource.meta.client
from session
s3_client = boto3.client('s3')
s3_client = session.client('s3')
methods
Amazon S3 examples
s3_client.list_buckets()s3_client.create_bucket(Bucket='mybucket')
s3_client.upload_file()...
Paginators
import boto3
client = boto3.client('s3', region_name='us-west-2')
paginator = client.get_paginator('list_objects')
operation_parameters = {'Bucket': 'my-bucket',
'Prefix': 'foo/baz'}
page_iterator = paginator.paginate(**operation_parameters)
for page in page_iterator:
print(page['Contents'])
import boto3
client = boto3.client('s3', region_name='us-west-2')
paginator = client.get_paginator('list_objects')
page_iterator = paginator.paginate(Bucket='my-bucket')
filtered_iterator = page_iterator.search("Contents[?Size > `100`][]")
for key_data in filtered_iterator:
print(key_data)
Using an Amazon S3 Bucket as a Static Web Host s3_client.get_bucket_website()s3_client.put_bucket_website()s3_client.delete_bucket_website()
Aquesta taula continua cap a la dreta — desplaça-la o gira el mòbil.
- autoscaling
- s3
- Amazon S3
examples
s3put -a <access_key> -s <secret_key> -b <bucket_name> path- user with provided acces_key/secret_key must have
permission to upload to S3:
- Users / Permissions: AmazonS3FullAccess
- user with provided acces_key/secret_key must have
permission to upload to S3:
- check availability
- single key
try:
s3_client = boto3.client("s3")
response = s3_client.head_object(Bucket=bucket_name, Key=key)
- prefix
s3_resource = boto3.resource("s3", region_name="eu-west-1")
bucket = s3_resource.Bucket(bucket_name)
object_summary_iterator = bucket.objects.filter(Prefix=prefix)
# verify that we got at least one object:
if list(object_summary_iterator.limit(1)):
prefix_exists = True
- single key
- remove keys (files)
- Amazon
S3 boto - how to delete folder?
list_objects, delete_objectshave a limit of 1000 object and should be paginated
- How to delete files recursively from an S3 bucket
s3 = boto3.resource('s3')
bucket = s3.Bucket('mybucket')
bucket.objects.filter(Prefix="myprefix/").delete()
- Amazon
S3 boto - how to delete folder?
- delete recursively (WARNING: not working with boto3)
path = '/path/to'
bucketListResultSet = bucket.list(prefix=path[1:])
multiresult = bucket.delete_keys([key.name for key in bucketListResultSet])
if multiresult.errors:
logger.error("errors when recursively deleting {}: {}".format(path, multiresult.errors))
- Retrieving
subfolders names in S3 bucket from boto3
def s3list(...)
...
if not recursive:
kwargs.update(Delimiter='/')
if path and not path.endswith('/'):
path += '/'- Examples:
- # list
all first-level dirs in a bucket
for p in s3list(bucket, '', recursive=False, list_objs=False):
print(p)
- # list
all first-level dirs in a bucket
- Amazon S3 boto - how to delete folder?
- Mida / Size (mètriques
/ metrics)
- Can't get total size of a bucket with Boto3
- Getting
the Size of an S3 Bucket using Boto3 for AWS
- getting metrics from AWS Cloudwatch
- using boto cloudwatch
- Move
- Move
files between two AWS S3 buckets using boto3
- using awscli.clidriver
- Move
files between two AWS S3 buckets using boto3
- Change several objects from public to private
- Presigned urls
- Docs
- Presigned URLs (boto latest)
- Presigned URLs (boto 1.10.35)
- AWS
- Browser-Based Uploads Using POST (AWS Signature Version 4)
- Example: Browser-Based Upload using HTTP POST (Using AWS Signature Version 4)
- Límits
- AWS
S3 FAQs
- The largest object that can be uploaded in a single PUT is 5 GB. For objects larger than 100 MB, customers should consider using the multipart upload capability.
- Uploading
and copying objects using multipart
upload
-
API CLI SDK
Python 1. Create Multipart Upload CreateMultipartUpload create-multipart-upload S3.Client.create_multipart_upload 2. Upload Part UploadPart
S3.Client.upload_part 3. Complete Multipart Upload CompleteMultipartUpload
S3.Client.complete_multipart_upload ...
... Aquesta taula continua cap a la dreta — desplaça-la o gira el mòbil.
- Unable to use presigned upload URLs to upload from JS frontend #3708
- ...
-
- AWS
S3 FAQs
- Info
- Problemes
- SignatureDoesNotMatch The request signature we
calculated does not match the signature you
provided. Check your key and signing method.
- Solució / Solution
- do not specify Content-Type (curl, by
default, sends
Content-Type: application/x-www-form-urlencoded):curl -X PUT -H "Content-Type:" ...
- do not specify Content-Type (curl, by
default, sends
- Solució / Solution
- SignatureDoesNotMatch The request signature we
calculated does not match the signature you
provided. Check your key and signing method.
-
action s3_client.get presigned url and perform action (from Presigned URLs) large files
s3_client.upload_file(local_file, bucket_name, object_name)
# upload_file internally (s3transfer/__init__.py) calls: create_multipart_upload, (several) upload_part, complete_multipart_uploadupload a file generate_presigned_post(
bucket_name,
object_name,
Fields=fields,
Conditions=conditions,
ExpiresIn=expiration)import requests # To install: pip install requests
# Generate a presigned S3 POST URL
object_name = 'OBJECT_NAME'
response = create_presigned_post('BUCKET_NAME', object_name)
if response is None:
exit(1)
# Demonstrate how another Python program can use the presigned URL to upload a file
with open(object_name, 'rb') as f:
files = {'file': (object_name, f)}
http_response = requests.post(response['url'], data=response['fields'], files=files)
# If successful, returns HTTP status code 204
logging.info(f'File upload HTTP status code: {http_response.status_code}')import requests # To install: pip install requests
from requests_toolbelt.multipart.encoder import MultipartEncoder # pip install requests-toolbelt
# Generate a presigned S3 POST URL
object_name = 'OBJECT_NAME'
response = create_presigned_post('BUCKET_NAME', object_name)
if response is None:
exit(1)
# Demonstrate how another Python program can use the presigned URL to upload a file
with open(object_name, 'rb') as f:fields =fields['file'] = (object_name, f)response['fields']
m = MultipartEncoder(fields=fields)http_response = requests.post(response['url'], data=m)
# If successful, returns HTTP status code 204
logging.info(f'File upload HTTP status code: {http_response.status_code}')download an object generate_presigned_url(
"get_object",
Params={"Bucket": bucket_name, "Key": object_name},
ExpiresIn=expiration)import requests # To install: pip install requests
url = create_presigned_url('BUCKET_NAME', 'OBJECT_NAME')
if url is not None:
response = requests.get(url)
other s3 operations generate_presigned_url(
ClientMethod=client_method_name,
Params=method_parameters,
ExpiresIn=expiration,
HttpMethod=http_method)import sys
import boto3
import requests
def create_presigned_url_expanded(
client_method_name, method_parameters=None, expiration=3600, http_method=None
):
"""Generate a presigned URL to invoke an S3.Client method
Not all the client methods provided in the AWS Python SDK are supported.
:param client_method_name: Name of the S3.Client method, e.g., 'list_buckets'
:param method_parameters: Dictionary of parameters to send to the method
:param expiration: Time in seconds for the presigned URL to remain valid
:param http_method: HTTP method to use (GET, etc.)
:return: Presigned URL as string. If error, returns None.
"""
# Generate a presigned URL for the S3 client method
s3_client = boto3.client("s3")
try:
response = s3_client.generate_presigned_url(
ClientMethod=client_method_name,
Params=method_parameters,
ExpiresIn=expiration,
HttpMethod=http_method,
)
except ClientError as e:
logging.error(e)
return None
# The response contains the presigned URL
return response
def main(args):
# https://github.com/boto/boto3/issues/3708
# Generate a presigned URL for the S3 client method
s3_client = boto3.client("s3")
local_file = "/tmp/fitxer.mp4"
bucket_name = "mybucketname"
object_name = "myobject.mp4"
# 0. using upload
# response = s3_client.upload_file(local_file, bucket_name, object_name)
# return
# 1. create_multipart_upload
response = s3_client.create_multipart_upload(Bucket=bucket_name, Key=object_name)
upload_id = response["UploadId"]
# 2a. generate_presigned_url
chunk_number = 1
client_method_name = "upload_part"
method_parameters = {
"Bucket": bucket_name,
"Key": object_name,
"PartNumber": chunk_number,
"UploadId": upload_id,
}
expiration = 3600
presigned_url = create_presigned_url_expanded(
client_method_name, method_parameters, expiration
)
# 2b. upload part
with open(local_file, "rb") as f:
with requests.Session() as session:
data = {}
headers = {}
response = requests.put(
presigned_url,
data=f.read(),
headers=headers,
)
print(response)
print(response.text)
etag = response.headers["ETag"]
parts = [{"ETag": etag, "PartNumber": 1}]
# 3. complete_multipart_upload
s3_client.complete_multipart_upload(
Bucket=bucket_name,
Key=object_name,
UploadId=upload_id,
MultipartUpload={"Parts": parts},
)
if __name__ == "__main__":
main(sys.argv[1:])
Aquesta taula continua cap a la dreta — desplaça-la o gira el mòbil.
- Docs
- Amazon S3
examples
- cloudwatch
- Cloudwatch
- ...
- get_metric_statistics()
- get usage metrics from an s3 bucket:
import boto3'])
cloudwatch_client = boto3.client('cloudwatch', region_name='eu-west-1')
response = cloudwatch_client.get_metric_statistics(
Namespace='AWS/S3',
MetricName='BucketSizeBytes',
Dimensions=[
{'Name': 'BucketName', 'Value': 'my_bucket_name',
{'Name': 'StorageType', 'Value': 'StandardStorage'}
],
Statistics=['Average'],
Period=3600,
StartTime=(now-datetime.timedelta(days=2)).isoformat(),
EndTime=now.isoformat()
)
# get last datapoint to get date and bytes
if response['Datapoints']:
latest_datapoint = response['Datapoints'][-1]
storage_date = latest_datapoint['Timestamp']
storage_bytes = int(latest_datapoint['Average
- get usage metrics from an s3 bucket:
- cloudformation
- boto.cloudformation
- Examples with boto3:
- List of all stacks using a paginator:
- Listing more than 100 stacks using boto3
import boto3
cloudformation_resource = boto3.resource('cloudformation', region_name='eu-west-1')
client = cloudformation_resource.meta.client
number_stacks = 0
paginator = client.get_paginator('list_stacks')
#response_iterator = paginator.paginate(StackStatusFilter=['CREATE_COMPLETE'])
response_iterator = paginator.paginate()
for page in response_iterator:
stacks = page['StackSummaries']
for stack in stacks:
stack_name = (stack['StackName'])
stack_status = (stack['StackStatus'])
print('{} {} {}'.format(number_stacks, stack_name, stack_status))
number_stacks += 1
- List of all stacks using a paginator:
- Examples with boto v2:
- single EC2 instance
- single_ec2.json
- single_ec2.py
import boto.cloudformation
from django.conf import settings
...
try:
conn = boto.cloudformation.connect_to_region( settings.AWS_DEFAULT_REGION )
stack = conn.create_stack(self.name,
template_body=template_body,
template_url=None,
parameters=[],
notification_arns=[],
disable_rollback=False,
timeout_in_minutes=None,
capabilities=None)
- single EC2 entry with Route53
- single_ec2_r53.json
- single_ec2_r53.py
try:
# connect to the cloud and create the stack
# connect to AWS
conn = boto.cloudformation.connect_to_region( settings.AWS_DEFAULT_REGION )
# check if the stack already exists
existing_stacks = [s.stack_name for s in conn.describe_stacks()]
logger.debug(" Existing stacks: %s" % existing_stacks)
if self.name in existing_stacks:
logger.error(" Stack %s is already created" % self.name)
raise Exception("Stack %s is already created" % self.name)
# create the stack
conn.create_stack(self.name,
template_body=template_body,
template_url=None,
parameters=[
('HostedZone','toto.org'),
],
notification_arns=[],
disable_rollback=False,
timeout_in_minutes=None,
capabilities=None)
# wait for COMPLETE
ready = False
while not ready:
stacks = conn.describe_stacks(self.name)
if len(stacks) == 1:
stack = stacks[0]
else:
raise Exception("Stack %s has not been created" % self.name)
logger.debug(" stack status: %s" % stack.stack_status)
# CREATE_COMPLETE, ROLLBACK_COMPLETE
ready = (string.find(stack.stack_status, 'COMPLETE')) != -1
time.sleep(5)
# get output information
outputs = dict()
for output in stack.outputs:
outputs[output.key] = output.value
logger.debug(" DomainName: %s" % outputs['DomainName'])
- ...
- my_file.py
# connect to AWS
conn = boto.cloudformation.connect_to_region( settings.AWS_DEFAULT_REGION )
stacks = conn.describe_stacks(stack_name)
if len(stacks) == 1:
stack = stacks[0]
else:
raise Exception("Stack %s does not exist" % stack_name)
# CREATE_COMPLETE, ROLLBACK_COMPLETE
ready = (string.find(stack.stack_status, 'CREATE_COMPLETE')) != -1
if ready:
# get parameters (conversion from ResultSet to dictionary)
parameters = {item.key:item.value for item in stack.parameters}
# get output information (conversion from ResultSet to dictionary)
outputs = {item.key:item.value for item in stack.outputs}
- my_file.py
- single EC2 instance
- cloudfront
- Create an invalidation:
try:
import boto3
except Exception as e:
print 'ERROR: %s' % e
profile_name = 'my_profile'
session = boto3.Session(profile_name=profile_name)
cloudfront_client = session.client('cloudfront')
distribution_id = 'xxxxxx'
# create invalidation
import time
response = cloudfront_client.create_invalidation(
DistributionId=distribution_id,
InvalidationBatch={
'Paths': {
'Quantity': 1,
'Items': ['/*']
},
'CallerReference': str(time.time())
}
)
print response
- Create an invalidation:
- autoscaling
- Examples with boto3
- Get ids of instances inside an autoscaling group
with specified name (using JMESPath):
# get the list of instances in the autoscaling group
client_autoscaling = boto3.client('autoscaling', region_name='eu-west-1')
paginator = client_autoscaling.get_paginator('describe_auto_scaling_instances')
page_iterator = paginator.paginate(
PaginationConfig={'PageSize': 50}
)
# ids for instances whose 'AutoScalingGroupName' == asg_name
# http://boto3.readthedocs.io/en/latest/guide/paginators.html#filtering-results-with-jmespath
filtered_instances = page_iterator.search(
'AutoScalingInstances[?AutoScalingGroupName == `{}`]'.format(asg_name)
)
instance_ids = [ i['InstanceId'] for i in filtered_instances ]
- Get all volumes in zones starting with 'eu-'
import boto3
ec2_client = boto3.client('ec2', region_name='eu-west-1')
paginator = ec2_client.get_paginator('describe_volumes')
page_iterator = paginator.paginate(
PaginationConfig={'PageSize': 50}
)
zone_prefix = 'eu-'
filtered_volumes = page_iterator.search(
'Volumes[?starts_with(AvailabilityZone,`{}`)]'.format(zone_prefix)
)
- ... and size is greater than 80 (GiB):
zone_prefix = 'eu-'
filtered_volumes = page_iterator.search(
'Volumes[?(starts_with(AvailabilityZone,`{}`) && Size>`80`)]'.format(zone_prefix)
)
- Have a tag "Name" whose value starts with "my-":
prefix = 'my-'
filtered_volumes = page_iterator.search(
'Volumes[?(Tags[?Key==`Name`] | [?starts_with(Value,`{}`)])]'.format(prefix)
)
- Get ids of instances inside an autoscaling group
with specified name (using JMESPath):
- Examples with boto3
- ec2
- An Introduction to boto’s EC2 interface
- EC2 (API reference)
- Amazon EC2 Deployment with Boto
- volumes (boto3)
- get volume with a given name (in tag "Name")
filtered_volumes = page_iterator.search(
'Volumes[?(Tags[?Key==`Name`] | [?Value==`{}`])]'.format(volume_name)
)
- resize volume
- get volume with a given name (in tag "Name")
- yourfile.py
conn = boto.ec2.connect_to_region("eu-west-1", aws_access_key_id=settings.AWS_ACCESS_KEY_ID, aws_secret_access_key=settings.AWS_SECRET_ACCESS_KEY)
reservation = conn.run_instances( 'ami-...', security_groups=['launch-wizard'], min_count=1, max_count=1, key_name='parell_key', placement='eu-west-1a', tenancy='default', instance_type='t1.micro')
instance = reservation.instances[0]
while instance.state != 'running':
time.sleep(5)
instance.update() # Updates Instance metadata
print "Instance state: %s" % (instance.state)
# add Name tag
instance.add_tag("Name","your_instance_name")
print "Instance ID: %s" % instance.id
print "Instance IP address: %s" % instance.ip_address# get all the reservations with a given Name tag:
reservations = conn.get_all_instances(filters={'tag:Name': 'your_instance_name'})
# get the first reservation
reservation = reservations[0]# get all the reservations with a given instance_id
reservations = conn.get_all_instances(instance_ids=["i-27823367"])# get the first reservation
reservation = reservations[0]
instance = reservation.instances[0]
# get the value of tag "Name"
name = instance.tags["Name"]# connection
conn = boto.ec2.autoscale.connect_to_region(settings.AWS_REGION,
aws_access_key_id=settings.AWS_ACCESS_KEY_ID_EC2,
aws_secret_access_key=settings.AWS_SECRET_ACCESS_KEY_EC2)
# get autoscaling group
asg = conn.get_all_groups(names='my_name')[0]
# get instances
instance_ids = [i.instance_id for i in asg.instances]
print " Instances ID: %s" % (instance_ids)
# shutdown instances
asg.shutdown_instances()
# wait for all instances to be shutdown
instances = True
while instances:
time.sleep(5)
asg = conn.get_all_groups('my_name')[0]
if not asg.instances:
instances = False
else:
logger.debug(" still some instances in group %s"%self.name)
# remove group
asg.delete()
- zip
22Mobile#
23Kinesis Data Streams#
- Amazon Kinesis Data Streams (Developer
Guide)
- entrada generada per / Writing Data to Amazon Kinesis Data Streams (producers):
- sortida consumida per / Reading
Data from Amazon Kinesis Data Streams (consumers):
- KCL: Using the Kinesis Client Library
- Developing Consumers Using AWS Lambda
- Developing
Consumers Using Amazon Data Firehose
- pont entre una font i una destinació, amb possibilitat de transformació mitjançant una funció Lambda
- destinations:
- Amazon S3 (tots o només els errors), Amazon Redshift, Amazon OpenSearch Service
- Datadog, Datazoom, New Relic, Splunk
- Writing to Amazon Data Firehose Using Kinesis Data Streams
- Developing Consumers Using Amazon Managed Service for Apache Flink
- ...
- ...
24CloudWatch#
- Observabilitat / Observability
- Access
- Collect
metrics, logs, and traces with the CloudWatch agent
- Metrics collected by the
CloudWatch agent
- GPU metrics (e.g.
to be used in Autoscaling Groups)
- example:
amazon-cloudwatch-agent.d/nvidia.aws_cloudwatch.json
{
"metrics": {
"metrics_collected": {
"nvidia_gpu": {
"measurement": [
"nvidia_smi_utilization_gpu",
"nvidia_smi_utilization_memory"
],
"metrics_collection_interval": 60
}
}
}
}
- Collect NVIDIA GPU metrics
- Amazon CloudWatch Agent adds Support for NVIDIA GPU Metrics
- What is the best metric for auto-scaling GPU instances for machine learning inference in the cloud?
- example:
amazon-cloudwatch-agent.d/nvidia.aws_cloudwatch.json
- GPU metrics (e.g.
to be used in Autoscaling Groups)
- Install
the CloudWatch agent
- aws/amazon-cloudwatch-agent
CloudWatchAgentServerPolicypolicy must be present into role (when using them)
- Create the CloudWatch agent
configuration file
- Create
the CloudWatch agent configuration file with the
wizard
- /opt/aws/amazon-cloudwatch-agent/bin/config.json
- schema: installation-directory/doc/amazon-cloudwatch-agent-schema.json
- /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json
-
observability
example agent
- metrics_collection_interval
- run_as_user
- cwagent
- root
- ...
- region
- credentials
- role_arn
- debug
- logfile
metrics
- namespace
- append_dimensions
- aggregation_dimensions
- endpoint_override
- metrics_collected
- collectd
- cpu
- resources
- totalcpu
- measurement[]
- rename
- unit
- metrics_collection_interval
- append_dimensions
- disk
- resources
- measurement[]
- rename
- unit
- ignore_file_system_types
- metrics_collection_interval
- append_dimensions
- diskio
- resources
- measurement[]
- rename
- unit
- metrics_collection_interval
- append_dimensions
- swap
- measurement[]
- rename
- unit
- metrics_collection_interval
- append_dimensions
- measurement[]
- mem
- measurement[]
- rename
- unit
- metrics_collection_interval
- append_dimensions
- measurement[]
- net
- ...
- netstat
- ...
- processes
- ...
- procstat
- statsd
- force_flush_interval
- credentials
- role_arn
logs - logs_collected
- files
- collect_list[]
- file_path
- log_group_name
- log_stream_name
- timezone
- multi_line_start_pattern
- encoding
- collect_list[]
- windows_events
- collect_list[]
- event_name
- event_levels
- log_group_name
- log_stream_name
- event_format
- collect_list[]
- log_stream_name
- endpoint_override
- force_flush_interval
- credentials
- role_arn
- files
traces (AWS X-Ray)
Aquesta taula continua cap a la dreta — desplaça-la o gira el mòbil.
-
- Create
the CloudWatch agent configuration file with the
wizard
- start service
systemctl start amazon-cloudwatch-agent.service- calls:
/opt/aws/amazon-cloudwatch-agent/bin/start-amazon-cloudwatch-agent- when called it directly it can give some clues
about issues
Error running agent: Error loading config file /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.toml: error parsing socket_listener, open /usr/share/collectd/types.db: no such file or directory
- when called it directly it can give some clues
about issues
- loaded config:
/opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json/opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.d/*
- calls:
- logs:
- /opt/aws/amazon-cloudwatch-agent/logs
- Troubleshooting
amazon-cloudwatch-agent-ctl -help
amazon-cloudwatch-agent-ctl -a status- ...
- access metrics
- from CloudWatch
- Custom namespaces: CWAgent
- Graphed metrics
- Period: 1 minute
- from cli
- ...
- from CloudWatch
- Metrics collected by the
CloudWatch agent
- Alarmes / Alarms
- Action (Step 2: Configure actions)
- Notification
- message to Slack (using: alarm
-> AWS SNS topic -> (subscriber) AWS
Chatbot -> (channel configuration in client
Slack) -> channel in Slack)
- Send a notification to the following SNS topic
> Select an existing SNS topic > Send a
notification to...:
my_topic_for_slack_in_some_channel - Info
- needed previous steps:
- AWS SNS
- Create topic:
- Details
- Type:
Standard - Name:
my_topic_for_slack_in_some_channel - Display name - optional:
my_topic_for_slack_in_some_channel
- Type:
- Details
- Create topic:
- AWS Chatbot
- Configure new client:
- Slack
- Configured clients
- Slack
- Configure new channel
- Configuration details
- Configuration name:
my-awesome-configuration
- Configuration name:
- Slack channel
- Public channel name: (choose from list)
- Permissions:
- Role settings: Channel role
- Notifications - optional
- SNS topics
- Region 1: (select your region)
- Topics 1: (select
from list)
my_topic_for_slack_in_some_channel
- SNS topics
- Tags
- Configuration details
- Configure new channel
- Slack
- verify that a new subscription has automatically been created and it now appears in your AWS SNS topic
- Configure new client:
- Slack
- add application "AWS Chatbot"
- send messages not in the same thread:
- ...?
- AWS SNS
- Send a notification to the following SNS topic
> Select an existing SNS topic > Send a
notification to...:
- Lambda
- Notification
- Action (Step 2: Configure actions)
- Log
- Python
- WatchTower
- system logs
- awslogs
- Instal·lació / Installation
- Configuració / Setup
- Upload the CloudWatch Agent Configuration File to Systems Manager Parameter Store
- /opt/aws/amazon-cloudwatch-agent/etc/common-config.toml
[credentials]
[proxy]
[region]
- Manually Create or Edit the CloudWatch Agent Configuration File
- Multiple
CloudWatch agent configuration files Merge
several json files:
- awslogs_merge_conf.sh
#!/bin/bash
EXPECTED_ARGS=2
if (( $# != $EXPECTED_ARGS ))
then
cat <<EOF
Usage: `basename $0` config_dir config_file
Examples:
- `basename $0` /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.d /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json
EOF
exit 1
fi
# parameters
config_dir=$1
config_file=$2
jq -s '.[0].logs.logs_collected.files.collect_list = [.[].logs.logs_collected.files.collect_list | add] | .[0]' ${config_dir}/*.json >${config_file}
exit 0
- awslogs_merge_conf.sh
- Python
25Lambda#
- Lambda functions
- Python
- use urllib3
instead of requests
- ...
- use urllib3
instead of requests
- Python
- Lambda from a CloudWatch
Alarm
- Alarm actions
- Trigger AWS Lambda directly from Cloudwatch Alarm
- add permissions so as the alarm can run the lambda as an
action:
- <my lambda function> > Configuration (tab)
> Resource-based policy statement > Add
permissions
- AWS service
- Service:
Other - Statement ID:
my-custom-id-0001 - Principal:
lambda.alarms.cloudwatch.amazonaws.com - Source ARN:
arn:aws:cloudwatch:eu-west-1:xxxxxx:alarm:My Alarm - Action:
lambda:InvokeFunction
- <my lambda function> > Configuration (tab)
> Resource-based policy statement > Add
permissions
http://www.francescpinyol.cat/aws.html
Primera versió: / First version: 2.X.2015
Darrera modificació: 19 de maig de 2026 / Last update: 19th May
2026