IA e Automação na AWS: Implementando Soluções Inteligentes

Introdução A AWS oferece um ecossistema completo de serviços de IA que permite implementar soluções inteligentes sem a necessidade de expertise profunda em machine learning. Este guia explora como usar esses serviços para automatizar processos e criar aplicações mais inteligentes. Serviços de IA da AWS 1. Amazon Comprehend - Análise de Texto Análise de Sentimento import boto3 import json def analyze_sentiment(text): """Analisar sentimento de texto usando Comprehend""" comprehend = boto3.client('comprehend') response = comprehend.detect_sentiment( Text=text, LanguageCode='pt' ) return { 'sentiment': response['Sentiment'], 'confidence': response['SentimentScore'] } # Exemplo de uso text = "Estou muito satisfeito com o atendimento da empresa!" result = analyze_sentiment(text) print(f"Sentimento: {result['sentiment']}") print(f"Confiança: {result['confidence']}") Extração de Entidades def extract_entities(text): """Extrair entidades nomeadas do texto""" comprehend = boto3.client('comprehend') response = comprehend.detect_entities( Text=text, LanguageCode='pt' ) entities = [] for entity in response['Entities']: entities.append({ 'text': entity['Text'], 'type': entity['Type'], 'confidence': entity['Score'] }) return entities # Exemplo text = "João Silva trabalha na Amazon em São Paulo desde 2020" entities = extract_entities(text) for entity in entities: print(f"{entity['text']} - {entity['type']} ({entity['confidence']:.2f})") 2. Amazon Rekognition - Análise de Imagens Detecção de Objetos def detect_objects_in_image(bucket_name, image_key): """Detectar objetos em imagem do S3""" rekognition = boto3.client('rekognition') response = rekognition.detect_labels( Image={ 'S3Object': { 'Bucket': bucket_name, 'Name': image_key } }, MaxLabels=10, MinConfidence=80 ) objects = [] for label in response['Labels']: objects.append({ 'name': label['Name'], 'confidence': label['Confidence'], 'instances': len(label.get('Instances', [])) }) return objects Reconhecimento Facial def detect_faces(bucket_name, image_key): """Detectar faces em imagem""" rekognition = boto3.client('rekognition') response = rekognition.detect_faces( Image={ 'S3Object': { 'Bucket': bucket_name, 'Name': image_key } }, Attributes=['ALL'] ) faces = [] for face in response['FaceDetails']: faces.append({ 'age_range': face['AgeRange'], 'gender': face['Gender']['Value'], 'emotions': [ { 'type': emotion['Type'], 'confidence': emotion['Confidence'] } for emotion in face['Emotions'] if emotion['Confidence'] > 50 ] }) return faces 3. Amazon Polly - Text-to-Speech def text_to_speech(text, output_bucket, output_key): """Converter texto em áudio usando Polly""" polly = boto3.client('polly') s3 = boto3.client('s3') # Sintetizar fala response = polly.synthesize_speech( Text=text, OutputFormat='mp3', VoiceId='Camila', # Voz em português brasileiro LanguageCode='pt-BR' ) # Salvar no S3 s3.put_object( Bucket=output_bucket, Key=output_key, Body=response['AudioStream'].read(), ContentType='audio/mpeg' ) return f"s3://{output_bucket}/{output_key}" # Exemplo audio_url = text_to_speech( "Olá! Este é um exemplo de síntese de voz usando Amazon Polly.", "my-audio-bucket", "speech/example.mp3" ) Casos de Uso Práticos 1. Análise Automática de Feedback de Clientes import boto3 from datetime import datetime import json class FeedbackAnalyzer: def __init__(self): self.comprehend = boto3.client('comprehend') self.dynamodb = boto3.resource('dynamodb') self.sns = boto3.client('sns') self.table = self.dynamodb.Table('customer-feedback') def process_feedback(self, feedback_text, customer_id): """Processar feedback do cliente""" # Análise de sentimento sentiment_response = self.comprehend.detect_sentiment( Text=feedback_text, LanguageCode='pt' ) # Extração de tópicos-chave key_phrases_response = self.comprehend.detect_key_phrases( Text=feedback_text, LanguageCode='pt' ) # Preparar dados para armazenamento feedback_data = { 'feedback_id': f"{customer_id}_{int(datetime.now().timestamp())}", 'customer_id': customer_id, 'text': feedback_text, 'sentiment': sentiment_response['Sentiment'], 'sentiment_scores': sentiment_response['SentimentScore'], 'key_phrases': [ phrase['Text'] for phrase in key_phrases_response['KeyPhrases'] if phrase['Score'] > 0.8 ], 'timestamp': datetime.now().isoformat(), 'processed': True } # Salvar no DynamoDB self.table.put_item(Item=feedback_data) # Alertar se feedback negativo if sentiment_response['Sentiment'] == 'NEGATIVE': self.send_alert(feedback_data) return feedback_data def send_alert(self, feedback_data): """Enviar alerta para feedback negativo""" message = { 'alert_type': 'negative_feedback', 'customer_id': feedback_data['customer_id'], 'sentiment_score': feedback_data['sentiment_scores']['Negative'], 'key_issues': feedback_data['key_phrases'][:3], 'timestamp': feedback_data['timestamp'] } self.sns.publish( TopicArn='arn:aws:sns:region:account:customer-alerts', Message=json.dumps(message), Subject='Feedback Negativo Detectado' ) # Uso da classe analyzer = FeedbackAnalyzer() result = analyzer.process_feedback( "O produto chegou com defeito e o atendimento foi péssimo!", "customer_123" ) 2. Moderação Automática de Conteúdo class ContentModerator: def __init__(self): self.rekognition = boto3.client('rekognition') self.comprehend = boto3.client('comprehend') self.s3 = boto3.client('s3') def moderate_image(self, bucket_name, image_key): """Moderar conteúdo de imagem""" # Detectar conteúdo inadequado moderation_response = self.rekognition.detect_moderation_labels( Image={ 'S3Object': { 'Bucket': bucket_name, 'Name': image_key } }, MinConfidence=60 ) inappropriate_content = [] for label in moderation_response['ModerationLabels']: inappropriate_content.append({ 'category': label['Name'], 'confidence': label['Confidence'], 'parent_category': label.get('ParentName', '') }) # Detectar texto na imagem text_response = self.rekognition.detect_text( Image={ 'S3Object': { 'Bucket': bucket_name, 'Name': image_key } } ) detected_text = ' '.join([ text['DetectedText'] for text in text_response['TextDetections'] if text['Type'] == 'LINE' ]) # Analisar sentimento do texto detectado text_sentiment = None if detected_text: sentiment_response = self.comprehend.detect_sentiment( Text=detected_text, LanguageCode='pt' ) text_sentiment = sentiment_response['Sentiment'] return { 'image_key': image_key, 'inappropriate_content': inappropriate_content, 'detected_text': detected_text, 'text_sentiment': text_sentiment, 'approved': len(inappropriate_content) == 0, 'confidence_score': min([label['confidence'] for label in inappropriate_content]) if inappropriate_content else 100 } def moderate_text(self, text_content): """Moderar conteúdo de texto""" # Detectar linguagem tóxica usando Comprehend sentiment_response = self.comprehend.detect_sentiment( Text=text_content, LanguageCode='pt' ) # Lista de palavras proibidas (exemplo simplificado) prohibited_words = ['spam', 'golpe', 'fraude'] contains_prohibited = any( word.lower() in text_content.lower() for word in prohibited_words ) return { 'text': text_content, 'sentiment': sentiment_response['Sentiment'], 'sentiment_scores': sentiment_response['SentimentScore'], 'contains_prohibited_words': contains_prohibited, 'approved': not contains_prohibited and sentiment_response['Sentiment'] != 'NEGATIVE' } # Exemplo de uso moderator = ContentModerator() # Moderar imagem image_result = moderator.moderate_image('content-bucket', 'user-uploads/image.jpg') print(f"Imagem aprovada: {image_result['approved']}") # Moderar texto text_result = moderator.moderate_text("Este é um comentário normal sobre o produto.") print(f"Texto aprovado: {text_result['approved']}") 3. Chatbot Inteligente com Lex class IntelligentChatbot: def __init__(self): self.lex = boto3.client('lexv2-runtime') self.comprehend = boto3.client('comprehend') self.dynamodb = boto3.resource('dynamodb') self.conversation_table = self.dynamodb.Table('chatbot-conversations') def process_message(self, user_id, message, session_id=None): """Processar mensagem do usuário""" if not session_id: session_id = f"{user_id}_{int(datetime.now().timestamp())}" # Analisar intenção com Lex lex_response = self.lex.recognize_text( botId='your-bot-id', botAliasId='your-bot-alias-id', localeId='pt_BR', sessionId=session_id, text=message ) # Analisar sentimento da mensagem sentiment_response = self.comprehend.detect_sentiment( Text=message, LanguageCode='pt' ) # Preparar resposta baseada na intenção intent_name = lex_response.get('sessionState', {}).get('intent', {}).get('name', 'Unknown') bot_response = lex_response.get('messages', [{}])[0].get('content', 'Desculpe, não entendi.') # Personalizar resposta baseada no sentimento if sentiment_response['Sentiment'] == 'NEGATIVE': bot_response = f"Percebo que você está frustrado. {bot_response} Posso transferir você para um atendente humano?" # Salvar conversa conversation_data = { 'conversation_id': f"{session_id}_{int(datetime.now().timestamp())}", 'user_id': user_id, 'session_id': session_id, 'user_message': message, 'bot_response': bot_response, 'intent': intent_name, 'sentiment': sentiment_response['Sentiment'], 'confidence': lex_response.get('sessionState', {}).get('intent', {}).get('confirmationState', 'None'), 'timestamp': datetime.now().isoformat() } self.conversation_table.put_item(Item=conversation_data) return { 'response': bot_response, 'intent': intent_name, 'sentiment': sentiment_response['Sentiment'], 'session_id': session_id } def get_conversation_analytics(self, user_id): """Obter analytics da conversa""" response = self.conversation_table.query( IndexName='user-id-index', KeyConditionExpression='user_id = :user_id', ExpressionAttributeValues={':user_id': user_id} ) conversations = response['Items'] # Calcular métricas total_messages = len(conversations) sentiments = [conv['sentiment'] for conv in conversations] intents = [conv['intent'] for conv in conversations] return { 'total_messages': total_messages, 'sentiment_distribution': { 'positive': sentiments.count('POSITIVE'), 'negative': sentiments.count('NEGATIVE'), 'neutral': sentiments.count('NEUTRAL') }, 'top_intents': list(set(intents)), 'last_interaction': max([conv['timestamp'] for conv in conversations]) if conversations else None } # Exemplo de uso chatbot = IntelligentChatbot() # Processar mensagem response = chatbot.process_message( user_id="user_123", message="Preciso cancelar meu pedido", session_id="session_456" ) print(f"Resposta do bot: {response['response']}") print(f"Intenção detectada: {response['intent']}") Automação com Step Functions Workflow de Processamento de Documentos { "Comment": "Workflow de processamento automático de documentos", "StartAt": "ExtractText", "States": { "ExtractText": { "Type": "Task", "Resource": "arn:aws:states:::aws-sdk:textract:startDocumentTextDetection", "Parameters": { "DocumentLocation": { "S3Object": { "Bucket.$": "$.bucket", "Name.$": "$.key" } } }, "Next": "WaitForExtraction" }, "WaitForExtraction": { "Type": "Wait", "Seconds": 10, "Next": "GetExtractionResults" }, "GetExtractionResults": { "Type": "Task", "Resource": "arn:aws:states:::aws-sdk:textract:getDocumentTextDetection", "Parameters": { "JobId.$": "$.JobId" }, "Next": "AnalyzeText" }, "AnalyzeText": { "Type": "Task", "Resource": "arn:aws:states:::lambda:invoke", "Parameters": { "FunctionName": "analyze-extracted-text", "Payload.$": "$" }, "Next": "ClassifyDocument" }, "ClassifyDocument": { "Type": "Task", "Resource": "arn:aws:states:::aws-sdk:comprehend:detectSentiment", "Parameters": { "Text.$": "$.extractedText", "LanguageCode": "pt" }, "Next": "StoreResults" }, "StoreResults": { "Type": "Task", "Resource": "arn:aws:states:::dynamodb:putItem", "Parameters": { "TableName": "processed-documents", "Item": { "documentId": {"S.$": "$.documentId"}, "extractedText": {"S.$": "$.extractedText"}, "sentiment": {"S.$": "$.Sentiment"}, "processedAt": {"S.$": "$$.State.EnteredTime"} } }, "End": true } } } Monitoramento e Otimização CloudWatch Metrics para IA Services def monitor_ai_services(): """Monitorar uso e performance dos serviços de IA""" cloudwatch = boto3.client('cloudwatch') # Métricas customizadas metrics = [ { 'MetricName': 'ComprehendRequests', 'Value': 1, 'Unit': 'Count', 'Dimensions': [ { 'Name': 'Service', 'Value': 'Comprehend' } ] }, { 'MetricName': 'RekognitionRequests', 'Value': 1, 'Unit': 'Count', 'Dimensions': [ { 'Name': 'Service', 'Value': 'Rekognition' } ] } ] cloudwatch.put_metric_data( Namespace='AI/Services', MetricData=metrics ) # Dashboard para monitoramento dashboard_config = { "widgets": [ { "type": "metric", "properties": { "metrics": [ ["AI/Services", "ComprehendRequests"], ["AI/Services", "RekognitionRequests"] ], "period": 300, "stat": "Sum", "region": "us-east-1", "title": "AI Services Usage" } } ] } Conclusão Os serviços de IA da AWS democratizam o acesso à inteligência artificial, permitindo que desenvolvedores implementem soluções sofisticadas sem expertise profunda em ML. As principais vantagens incluem: ...

July 16, 2025 · 7 min · 1312 words · Matheus Costa

Infrastructure as Code com Terraform na AWS: Melhores Práticas e Automação

Introdução Infrastructure as Code (IaC) revolucionou a forma como gerenciamos infraestrutura na nuvem. O Terraform, combinado com a AWS, oferece uma solução poderosa para criar, modificar e versionar infraestrutura de forma declarativa e reproduzível. Por que Terraform + AWS? Vantagens do Terraform ✅ Multi-cloud - Suporte a múltiplos provedores ✅ Declarativo - Descreve o estado desejado ✅ Planejamento - Preview das mudanças antes da aplicação ✅ State Management - Controle de estado centralizado ✅ Modularidade - Reutilização de código Benefícios na AWS 🚀 Escalabilidade - Infraestrutura que cresce com demanda 🔒 Segurança - Controles integrados de segurança 💰 Custo-efetivo - Otimização automática de recursos 🔄 Automação - Deploy e gestão automatizados Estrutura de Projeto Terraform Organização de Diretórios terraform-aws-infrastructure/ ├── environments/ │ ├── dev/ │ │ ├── main.tf │ │ ├── variables.tf │ │ ├── outputs.tf │ │ └── terraform.tfvars │ ├── staging/ │ └── production/ ├── modules/ │ ├── vpc/ │ ├── ec2/ │ ├── rds/ │ ├── s3/ │ └── security-groups/ ├── shared/ │ ├── backend.tf │ └── providers.tf └── scripts/ ├── deploy.sh └── destroy.sh Configuração Base Provider Configuration # providers.tf terraform { required_version = ">= 1.0" required_providers { aws = { source = "hashicorp/aws" version = "~> 5.0" } random = { source = "hashicorp/random" version = "~> 3.1" } } backend "s3" { bucket = "terraform-state-bucket" key = "infrastructure/terraform.tfstate" region = "us-east-1" encrypt = true dynamodb_table = "terraform-locks" } } provider "aws" { region = var.aws_region default_tags { tags = { Environment = var.environment Project = var.project_name ManagedBy = "Terraform" Owner = var.owner CostCenter = var.cost_center } } } Variables Configuration # variables.tf variable "aws_region" { description = "AWS region for resources" type = string default = "us-east-1" } variable "environment" { description = "Environment name" type = string validation { condition = contains(["dev", "staging", "production"], var.environment) error_message = "Environment must be dev, staging, or production." } } variable "project_name" { description = "Name of the project" type = string } variable "vpc_cidr" { description = "CIDR block for VPC" type = string default = "10.0.0.0/16" } variable "availability_zones" { description = "List of availability zones" type = list(string) default = ["us-east-1a", "us-east-1b", "us-east-1c"] } Módulos Terraform Reutilizáveis Módulo VPC # modules/vpc/main.tf resource "aws_vpc" "main" { cidr_block = var.cidr_block enable_dns_hostnames = true enable_dns_support = true tags = { Name = "${var.name}-vpc" } } resource "aws_internet_gateway" "main" { vpc_id = aws_vpc.main.id tags = { Name = "${var.name}-igw" } } resource "aws_subnet" "public" { count = length(var.public_subnets) vpc_id = aws_vpc.main.id cidr_block = var.public_subnets[count.index] availability_zone = var.availability_zones[count.index] map_public_ip_on_launch = true tags = { Name = "${var.name}-public-${count.index + 1}" Type = "Public" } } resource "aws_subnet" "private" { count = length(var.private_subnets) vpc_id = aws_vpc.main.id cidr_block = var.private_subnets[count.index] availability_zone = var.availability_zones[count.index] tags = { Name = "${var.name}-private-${count.index + 1}" Type = "Private" } } resource "aws_route_table" "public" { vpc_id = aws_vpc.main.id route { cidr_block = "0.0.0.0/0" gateway_id = aws_internet_gateway.main.id } tags = { Name = "${var.name}-public-rt" } } resource "aws_route_table_association" "public" { count = length(aws_subnet.public) subnet_id = aws_subnet.public[count.index].id route_table_id = aws_route_table.public.id } # NAT Gateway para subnets privadas resource "aws_eip" "nat" { count = var.enable_nat_gateway ? length(var.public_subnets) : 0 domain = "vpc" tags = { Name = "${var.name}-nat-eip-${count.index + 1}" } depends_on = [aws_internet_gateway.main] } resource "aws_nat_gateway" "main" { count = var.enable_nat_gateway ? length(var.public_subnets) : 0 allocation_id = aws_eip.nat[count.index].id subnet_id = aws_subnet.public[count.index].id tags = { Name = "${var.name}-nat-${count.index + 1}" } } resource "aws_route_table" "private" { count = var.enable_nat_gateway ? length(var.private_subnets) : 0 vpc_id = aws_vpc.main.id route { cidr_block = "0.0.0.0/0" nat_gateway_id = aws_nat_gateway.main[count.index].id } tags = { Name = "${var.name}-private-rt-${count.index + 1}" } } resource "aws_route_table_association" "private" { count = var.enable_nat_gateway ? length(aws_subnet.private) : 0 subnet_id = aws_subnet.private[count.index].id route_table_id = aws_route_table.private[count.index].id } Módulo Security Groups # modules/security-groups/main.tf resource "aws_security_group" "web" { name_prefix = "${var.name}-web-" vpc_id = var.vpc_id description = "Security group for web servers" ingress { description = "HTTP" from_port = 80 to_port = 80 protocol = "tcp" cidr_blocks = ["0.0.0.0/0"] } ingress { description = "HTTPS" from_port = 443 to_port = 443 protocol = "tcp" cidr_blocks = ["0.0.0.0/0"] } egress { from_port = 0 to_port = 0 protocol = "-1" cidr_blocks = ["0.0.0.0/0"] } tags = { Name = "${var.name}-web-sg" } lifecycle { create_before_destroy = true } } resource "aws_security_group" "database" { name_prefix = "${var.name}-db-" vpc_id = var.vpc_id description = "Security group for database servers" ingress { description = "MySQL/Aurora" from_port = 3306 to_port = 3306 protocol = "tcp" security_groups = [aws_security_group.web.id] } ingress { description = "PostgreSQL" from_port = 5432 to_port = 5432 protocol = "tcp" security_groups = [aws_security_group.web.id] } tags = { Name = "${var.name}-db-sg" } lifecycle { create_before_destroy = true } } Módulo EC2 com Auto Scaling # modules/ec2/main.tf data "aws_ami" "amazon_linux" { most_recent = true owners = ["amazon"] filter { name = "name" values = ["amzn2-ami-hvm-*-x86_64-gp2"] } } resource "aws_launch_template" "web" { name_prefix = "${var.name}-web-" image_id = data.aws_ami.amazon_linux.id instance_type = var.instance_type vpc_security_group_ids = var.security_group_ids user_data = base64encode(templatefile("${path.module}/user_data.sh", { environment = var.environment })) iam_instance_profile { name = aws_iam_instance_profile.web.name } block_device_mappings { device_name = "/dev/xvda" ebs { volume_size = var.root_volume_size volume_type = "gp3" encrypted = true } } tag_specifications { resource_type = "instance" tags = { Name = "${var.name}-web-instance" } } lifecycle { create_before_destroy = true } } resource "aws_autoscaling_group" "web" { name = "${var.name}-web-asg" vpc_zone_identifier = var.subnet_ids target_group_arns = var.target_group_arns health_check_type = "ELB" health_check_grace_period = 300 min_size = var.min_size max_size = var.max_size desired_capacity = var.desired_capacity launch_template { id = aws_launch_template.web.id version = "$Latest" } tag { key = "Name" value = "${var.name}-web-asg" propagate_at_launch = false } instance_refresh { strategy = "Rolling" preferences { min_healthy_percentage = 50 } } } # IAM Role para instâncias EC2 resource "aws_iam_role" "web" { name = "${var.name}-web-role" assume_role_policy = jsonencode({ Version = "2012-10-17" Statement = [ { Action = "sts:AssumeRole" Effect = "Allow" Principal = { Service = "ec2.amazonaws.com" } } ] }) } resource "aws_iam_instance_profile" "web" { name = "${var.name}-web-profile" role = aws_iam_role.web.name } resource "aws_iam_role_policy_attachment" "web_ssm" { role = aws_iam_role.web.name policy_arn = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore" } Implementação de Ambientes Ambiente de Desenvolvimento # environments/dev/main.tf module "vpc" { source = "../../modules/vpc" name = "${var.project_name}-${var.environment}" cidr_block = var.vpc_cidr availability_zones = var.availability_zones public_subnets = ["10.0.1.0/24", "10.0.2.0/24"] private_subnets = ["10.0.10.0/24", "10.0.20.0/24"] enable_nat_gateway = false # Economia de custos em dev } module "security_groups" { source = "../../modules/security-groups" name = "${var.project_name}-${var.environment}" vpc_id = module.vpc.vpc_id } module "web_servers" { source = "../../modules/ec2" name = "${var.project_name}-${var.environment}" environment = var.environment instance_type = "t3.micro" min_size = 1 max_size = 2 desired_capacity = 1 subnet_ids = module.vpc.public_subnet_ids security_group_ids = [module.security_groups.web_sg_id] } Ambiente de Produção # environments/production/main.tf module "vpc" { source = "../../modules/vpc" name = "${var.project_name}-${var.environment}" cidr_block = var.vpc_cidr availability_zones = var.availability_zones public_subnets = ["10.1.1.0/24", "10.1.2.0/24", "10.1.3.0/24"] private_subnets = ["10.1.10.0/24", "10.1.20.0/24", "10.1.30.0/24"] enable_nat_gateway = true } module "security_groups" { source = "../../modules/security-groups" name = "${var.project_name}-${var.environment}" vpc_id = module.vpc.vpc_id } module "web_servers" { source = "../../modules/ec2" name = "${var.project_name}-${var.environment}" environment = var.environment instance_type = "t3.medium" min_size = 2 max_size = 10 desired_capacity = 3 subnet_ids = module.vpc.private_subnet_ids security_group_ids = [module.security_groups.web_sg_id] } module "database" { source = "../../modules/rds" name = "${var.project_name}-${var.environment}" engine = "mysql" engine_version = "8.0" instance_class = "db.t3.medium" allocated_storage = 100 subnet_ids = module.vpc.private_subnet_ids security_group_ids = [module.security_groups.database_sg_id] backup_retention = 7 multi_az = true } Automação e CI/CD Pipeline GitLab CI # .gitlab-ci.yml stages: - validate - plan - apply - destroy variables: TF_ROOT: ${CI_PROJECT_DIR} TF_ADDRESS: ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/terraform/state/${CI_ENVIRONMENT_NAME} cache: key: "${TF_ROOT}" paths: - ${TF_ROOT}/.terraform before_script: - cd ${TF_ROOT}/environments/${CI_ENVIRONMENT_NAME} - terraform --version - terraform init -backend-config="address=${TF_ADDRESS}" -backend-config="lock_address=${TF_ADDRESS}/lock" -backend-config="unlock_address=${TF_ADDRESS}/lock" -backend-config="username=${CI_USERNAME}" -backend-config="password=${CI_JOB_TOKEN}" -backend-config="lock_method=POST" -backend-config="unlock_method=DELETE" -backend-config="retry_wait_min=5" validate: stage: validate script: - terraform validate - terraform fmt -check only: - merge_requests - main plan: stage: plan script: - terraform plan -out="planfile" artifacts: name: plan paths: - ${TF_ROOT}/environments/${CI_ENVIRONMENT_NAME}/planfile only: - merge_requests - main apply: stage: apply script: - terraform apply -input=false "planfile" dependencies: - plan when: manual only: - main environment: name: ${CI_ENVIRONMENT_NAME} destroy: stage: destroy script: - terraform destroy -auto-approve when: manual only: - main environment: name: ${CI_ENVIRONMENT_NAME} action: stop Scripts de Automação #!/bin/bash # scripts/deploy.sh set -e ENVIRONMENT=${1:-dev} ACTION=${2:-plan} echo "🚀 Deploying to $ENVIRONMENT environment" cd "environments/$ENVIRONMENT" # Inicializar Terraform terraform init # Validar configuração terraform validate # Formatar código terraform fmt -recursive case $ACTION in "plan") echo "📋 Planning infrastructure changes..." terraform plan -var-file="terraform.tfvars" ;; "apply") echo "🔨 Applying infrastructure changes..." terraform plan -var-file="terraform.tfvars" -out=tfplan terraform apply tfplan rm tfplan ;; "destroy") echo "💥 Destroying infrastructure..." terraform plan -destroy -var-file="terraform.tfvars" -out=tfplan terraform apply tfplan rm tfplan ;; *) echo "❌ Invalid action. Use: plan, apply, or destroy" exit 1 ;; esac echo "✅ Operation completed successfully!" Monitoramento e Observabilidade CloudWatch Integration # modules/monitoring/main.tf resource "aws_cloudwatch_dashboard" "main" { dashboard_name = "${var.name}-infrastructure" dashboard_body = jsonencode({ widgets = [ { type = "metric" x = 0 y = 0 width = 12 height = 6 properties = { metrics = [ ["AWS/EC2", "CPUUtilization", "AutoScalingGroupName", var.asg_name], ["AWS/ApplicationELB", "TargetResponseTime", "LoadBalancer", var.alb_name] ] period = 300 stat = "Average" region = var.aws_region title = "Infrastructure Metrics" } } ] }) } resource "aws_cloudwatch_metric_alarm" "high_cpu" { alarm_name = "${var.name}-high-cpu" comparison_operator = "GreaterThanThreshold" evaluation_periods = "2" metric_name = "CPUUtilization" namespace = "AWS/EC2" period = "300" statistic = "Average" threshold = "80" alarm_description = "This metric monitors ec2 cpu utilization" dimensions = { AutoScalingGroupName = var.asg_name } alarm_actions = [aws_sns_topic.alerts.arn] } resource "aws_sns_topic" "alerts" { name = "${var.name}-infrastructure-alerts" } Segurança e Compliance Terraform Security Scanning # .github/workflows/security-scan.yml name: Security Scan on: pull_request: branches: [main] jobs: security-scan: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Run Checkov uses: bridgecrewio/checkov-action@master with: directory: . framework: terraform output_format: sarif output_file_path: reports/results.sarif - name: Run TFSec uses: aquasecurity/[email protected] with: soft_fail: true - name: Run Terrascan uses: accurics/terrascan-action@main with: iac_type: terraform iac_version: v14 policy_type: aws State File Security # Backend configuration with encryption terraform { backend "s3" { bucket = "terraform-state-secure-bucket" key = "infrastructure/terraform.tfstate" region = "us-east-1" encrypt = true kms_key_id = "arn:aws:kms:us-east-1:account:key/key-id" dynamodb_table = "terraform-locks" # Versioning enabled on S3 bucket versioning = true # Server-side encryption server_side_encryption_configuration { rule { apply_server_side_encryption_by_default { sse_algorithm = "aws:kms" kms_master_key_id = "arn:aws:kms:us-east-1:account:key/key-id" } } } } } Melhores Práticas 1. Organização de Código ✅ Use módulos reutilizáveis ✅ Separe ambientes em diretórios ✅ Mantenha arquivos pequenos e focados ✅ Use naming conventions consistentes ✅ Documente módulos e variáveis 2. Gestão de Estado ✅ Use backend remoto (S3 + DynamoDB) ✅ Habilite versionamento do state ✅ Configure locks para evitar conflitos ✅ Criptografe state files ✅ Faça backup regular do estado 3. Segurança ✅ Use least privilege principle ✅ Criptografe dados em trânsito e repouso ✅ Implemente resource tagging ✅ Use secrets management ✅ Faça security scanning regular 4. Performance e Custos ✅ Use data sources para recursos existentes ✅ Implemente lifecycle rules ✅ Monitore custos com tags ✅ Use spot instances quando apropriado ✅ Otimize storage classes Troubleshooting Comum 1. State Lock Issues # Forçar unlock (use com cuidado) terraform force-unlock LOCK_ID # Verificar estado atual terraform show # Importar recursos existentes terraform import aws_instance.example i-1234567890abcdef0 2. Dependency Issues # Explicit dependencies resource "aws_instance" "web" { # ... configuration ... depends_on = [ aws_security_group.web, aws_subnet.public ] } 3. Provider Version Conflicts # Lock provider versions terraform { required_providers { aws = { source = "hashicorp/aws" version = "= 5.0.1" # Exact version } } } Conclusão O Terraform oferece uma plataforma robusta para implementar Infrastructure as Code na AWS. Seguindo as melhores práticas apresentadas, você pode: ...

July 16, 2025 · 9 min · 1908 words · Matheus Costa

CI/CD com GitHub Actions: Automatizando Deploy para Cloudflare Pages

Introdução ao CI/CD Continuous Integration/Continuous Deployment (CI/CD) é uma prática essencial no desenvolvimento moderno que automatiza o processo de integração, teste e deploy de código. Por que GitHub Actions? Vantagens ✅ Integração nativa com GitHub ✅ Gratuito para repositórios públicos ✅ Marketplace com milhares de actions ✅ Suporte a múltiplas linguagens e plataformas ✅ Execução em containers Docker Conceitos Básicos Workflow: Processo automatizado Job: Conjunto de steps executados em um runner Step: Tarefa individual Action: Bloco reutilizável de código Configurando o Pipeline 1. Estrutura do Workflow Crie o arquivo .github/workflows/deploy.yml: ...

July 16, 2025 · 3 min · 519 words · Matheus Costa