Blog
Verwenden Sie CloudWatch LogGroups für die EC2-Protokollierung

Sie können sich vor dem Verlust von Protokollen auf Amazon EC2 schützen, indem Sie CloudWatch Logs verwenden. Konfigurieren Sie den CloudWatch Agent so, dass er Ihre Protokolle in eine LogGroup streamt. Dies schützt Sie vor dem Verlust von Protokollen. Zum Beispiel, wenn die Instanz durch Autoscaling ersetzt wird. Sie sind auch vor Manipulationen der Protokolle geschützt. Ein Angreifer, der sich Zugang zu Ihrem System verschafft hat, kann die Protokolle entfernen. Aber die Protokolle in der LogGroup enthalten die ursprünglichen Protokollzeilen.
Vorbereitungen
Wir benötigen die folgenden Ressourcen:
InstanceSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Security group for the test instance
VpcId: "{{resolve:ssm:/landingzone/vpc/vpc-id}}"
SecurityGroupEgress:
- Description: Allow outbound connectivity to port 443.
IpProtocol: tcp
FromPort: 443
ToPort: 443
CidrIp: 0.0.0.0/0
Role:
Type: AWS::IAM::Role
Properties:
PermissionsBoundary: !Sub arn:aws:iam::${AWS::AccountId}:policy/landingzone-workload-permissions-boundary
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action: sts:AssumeRole
Principal:
Service: ec2.amazonaws.com
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
- arn:aws:iam::aws:policy/AmazonInspector2ManagedCispolicy
- arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy
InstanceProfile:
Type: AWS::IAM::InstanceProfile
Properties:
Roles:
- !Ref Role
LogGroup:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: !Sub ${AWS::StackName}-Instance
RetentionInDays: !!int 365
- InstanceSecurityGroup, erlaubt eine ausgehende Verbindung auf 443. Der CloudWatch Agent muss die Protokolle an den CloudWatch Endpunkt streamen.
- Rolle, enthält die Richtlinien, die es der Instanz erlauben, die Protokolle an die LogGroup zu senden.
- InstanceProfile, das Profil, das verwendet wird, um die Rolle mit den EC2-Instances zu verbinden.
- LogGroup, die LogGroup, in der die Protokolle gespeichert werden sollen.
Einrichten der EC2-Instanz
In meinem letzten Blog habe ich darüber geschrieben, wie Sie eine EC2-Instanz mit Infrastructure as Code erstellen können. Wir werden mit diesem Beispiel fortfahren. Anstelle einer einzelnen Instanz werden wir eine autoskalierende Gruppe erstellen.
Zunächst benötigen wir ein LaunchTemplate. Dieses LaunchTemplate enthält einige Metadaten namens AWS::CloudFormation::Init. Die Metadaten enthalten so genannte configSets und Konfigurationsblöcke. Hier ist ein Beispiel, das wir verwenden werden:
LaunchTemplate:
Type: AWS::EC2::LaunchTemplate
Metadata:
AWS::CloudFormation::Init:
configSets:
default:
- CloudFormationInit
- CloudWatchLogs
CloudFormationInit:
files:
/etc/cfn/cfn-hup.conf:
owner: root
group: root
mode: 000400
content: !Sub |-
[main]
stack=${AWS::StackId}
region=${AWS::Region}
/etc/cfn/hooks.d/cfn-auto-reloader.conf:
owner: root
group: root
mode: 000400
content: !Sub |-
[cfn-auto-reloader-hook]
triggers=post.update
path=Resources.LaunchTemplate.Metadata.AWS::CloudFormation::Init
action=/opt/aws/bin/cfn-init -v --stack ${AWS::StackName} --region ${AWS::Region} --resource LaunchTemplate
runas=root
services:
sysvinit:
cfn-hup:
enabled: true
ensureRunning: true
files:
- /etc/cfn/cfn-hup.conf
- /etc/cfn/hooks.d/cfn-auto-reloader.conf
CloudWatchLogs:
packages:
yum:
amazon-cloudwatch-agent: []
files:
/opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.d/file_amazon-cloudwatch-agent.json:
owner: root
group: root
mode: 000400
content: !Sub |-
{
"agent": {
"region": "${AWS::Region}",
"logfile": "/opt/aws/amazon-cloudwatch-agent/logs/amazon-cloudwatch-agent.log",
"debug": false
},
"logs": {
"logs_collected": {
"files": {
"collect_list": [
{
"file_path": "/var/log/user-data.log",
"log_group_name": "${LogGroup}",
"log_stream_name": "{instance_id}/user-data.log"
},
{
"file_path": "/var/log/cfn-hup.log",
"log_group_name": "${LogGroup}",
"log_stream_name": "{instance_id}/cfn-hup.log"
},
{
"file_path": "/opt/aws/amazon-cloudwatch-agent/logs/amazon-cloudwatch-agent.log",
"log_group_name": "${LogGroup}",
"log_stream_name": "{instance_id}/amazon-cloudwatch-agent.log"
}
]
}
},
"log_stream_name": "default_log_stream"
},
"metrics": {
"append_dimensions": {
"AutoScalingGroupName": "${!aws:AutoScalingGroupName}"
},
"metrics_collected": {
"disk": {
"measurement": [
"used_percent"
],
"metrics_collection_interval": 60,
"resources": [
"/"
]
}
}
}
}
services:
sysvinit:
amazon-cloudwatch-agent:
enabled: true
ensureRunning: true
files:
- /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.d/file_amazon-cloudwatch-agent.json
Properties:
LaunchTemplateData:
BlockDeviceMappings:
- DeviceName: /dev/xvda
Ebs:
DeleteOnTermination: !!bool true
Encrypted: !!bool true
KmsKeyId: !GetAtt EncryptionKey.Arn
VolumeSize: !!int 32
VolumeType: gp2
DisableApiTermination: !!bool true
IamInstanceProfile:
Arn: !GetAtt InstanceProfile.Arn
ImageId: "{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}"
InstanceType: t3.micro
SecurityGroupIds:
- !Ref InstanceSecurityGroup
MetadataOptions:
HttpTokens: required
InstanceMetadataTags: enabled
UserData:
Fn::Base64: !Sub |-
#!/bin/bash -x
/opt/aws/bin/cfn-init --stack ${AWS::StackName} --region ${AWS::Region} --resource LaunchTemplate
/opt/aws/bin/cfn-signal -e $? --stack ${AWS::StackName} --region ${AWS::Region} --resource AutoScalingGroup
CloudFormationInit
Der CloudFormationInit enthält eine Konfiguration. Diese Konfiguration wird vom cfn-init-Agenten verwendet. Sie wird mit den AMIs AmazonLinux2 und AmazonLinux2023 vorinstalliert. Unter dem Abschnitt Dateien können Sie sehen, dass wir 2 Dateien definieren:
/etc/cfn/cfn-hup.conf/etc/cfn/hooks.d/cfn-auto-reloader.conf
Die Syntax ist recht erklärend. Sie legen einen Eigentümer, eine Gruppe, einen Modus und den Inhalt der Datei fest. Der Inhalt der Datei teilt der EC2-Instanz mit, wo sie die Metadaten finden kann. Beim ersten Start sind diese in den Benutzerdaten enthalten. Aber Sie können die Metadaten im Laufe der Zeit ändern. Dadurch wird sichergestellt, dass die laufenden Instanzen prüfen, ob ein Update verfügbar ist.
Zusammenfassend lässt sich sagen, dass dadurch sichergestellt wird, dass die laufenden EC2-Instanzen mit den angegebenen Metadaten synchron bleiben.
CloudWatchLogs
Die Amazon Linux AMIs werden nicht mit dem CloudWatch Agent geliefert. Sie müssen den Agent zuerst installieren. Sie können dies tun, indem Sie das Paket amazon-cloudwatch-agent unter Pakete bereitstellen.
Jetzt ist es an der Zeit, den Agenten so zu konfigurieren, dass er die Protokolldateien an CloudWatch LogGroups streamt. Wir haben 3 Dateien definiert, die vom Agenten überwacht werden sollen:
/var/log/user-data.log/var/log/cfn-hup.log/opt/aws/amazon-cloudwatch-agent/logs/amazon-cloudwatch-agent.log
Sie können diese Liste nach Ihren eigenen Bedürfnissen erweitern. In diesem Beispiel wird jede EC2-Instanz 3 Streams haben. 1 pro Datei und die Instanz-ID wird als Präfix verwendet, Beispiel: i-0000000000/user-data.log.
Sie können auch Messungen an der Instanz selbst vornehmen und diese als CloudWatch Metrik darstellen. In diesem Beispiel erfassen wir einen Prozentsatz des belegten Speicherplatzes des Root-Volumes.
Wir haben jetzt den Agenten konfiguriert. Aber wir müssen auch sicherstellen, dass er läuft. Wenn wir Änderungen an der Konfigurationsdatei vornehmen, müssen wir ihn auch neu starten. Wir tun dies, indem wir auf die Konfigurationsdatei verweisen. Jetzt weiß cfn-init, wenn es die Konfiguration ändert, dass es auch den Agenten neu starten muss.
Benutzerdaten
Die Benutzerdaten stellen sicher, dass die Konfiguration übernommen wird. Da wir cfn-init so konfigurieren, dass die Konfiguration überprüft wird, bleibt sie von nun an synchron. Als Zweites sendet es ein Signal an die AutoScalingGroup-Ressource. Wenn das cfn-init erfolgreich ausgeführt wurde, wird ein Erfolg gemeldet, andernfalls ein Fehler.
Das heißt, wenn die Konfiguration fehlschlägt, erhält die Autoscaling-Gruppe einen Fehler. Infolgedessen wird der Stack zurückgesetzt.
AutoScalingGroup
Die Autoscaling-Gruppe sieht wie folgt aus:
AutoScalingGroup:
Type: AWS::AutoScaling::AutoScalingGroup
CreationPolicy:
ResourceSignal:
Timeout: PT5M
UpdatePolicy:
AutoScalingRollingUpdate:
MinInstancesInService: 1
MaxBatchSize: 1
PauseTime: PT5M
WaitOnResourceSignals: !!bool true
Properties:
LaunchTemplate:
LaunchTemplateId: !GetAtt LaunchTemplate.LaunchTemplateId
Version: !GetAtt LaunchTemplate.LatestVersionNumber
MinSize: !!int 1
MaxSize: !!int 2
DesiredCapacity: !!int 1
VPCZoneIdentifier:
- "{{resolve:ssm:/landingzone/vpc/private-subnet-1-id}}"
- "{{resolve:ssm:/landingzone/vpc/private-subnet-2-id}}"
Wir werden 2 Richtlinien definieren, eine für die Erstellung und eine für die Aktualisierung. Wenn das in den Benutzerdaten konfigurierte Signal fehlschlägt, schlägt die Ressource fehl und löst einen Rollback aus. Wenn die Instanz erfolgreich konfiguriert wurde, wird sie fortgesetzt. In der Gruppe für die automatische Skalierung können Sie die Anzahl der benötigten Instanzen festlegen. In diesem Beispiel ist das Maximum 2 und das Minimum 1. Dadurch wird sichergestellt, dass mindestens eine EC2-Instanz läuft. Wenn eine Ersatzinstanz benötigt wird, wird zunächst eine neue Instanz hinzugefügt, und wenn diese erfolgreich bereitgestellt wird, wird die alte Instanz entfernt. Aus diesem Grund ist der Höchstwert auf 2 gesetzt, damit wir die alte Instanz problemlos ersetzen können.
Fazit
Die Konfiguration einer LogGroup zum Streamen Ihrer Protokolldateien ist nicht schwer. Mit CloudFormation Init können Sie Anwendungen installieren und konfigurieren. In unserem Beispiel haben wir den CloudWatch-Agenten konfiguriert, der die Protokolle streamen wird.
Wenn Sie mit Autoscaling-Ereignissen und/oder bösartigen Angreifern zu tun haben. Sie können den Verlust von Protokollen verhindern, indem Sie Ihre Anwendungsprotokolldateien zentralisieren.
Foto von Pixabay
Verfasst von

Joris Conijn
Joris is the AWS Practise CTO of the Xebia Cloud service line and has been working with the AWS cloud since 2009 and focussing on building event-driven architectures. While working with the cloud from (almost) the start, he has seen most of the services being launched. Joris strongly believes in automation and infrastructure as code and is open to learning new things and experimenting with them because that is the way to learn and grow.
Unsere Ideen
Weitere Blogs
Contact



