Cloud

CloudFormation

burrri 2025. 4. 10. 19:21

Cloudformation이란?

  • IaC (infrastructure as code) 도구
  • json, yaml 형식의 template을 사용하여 AWS 리소스를 자동으로 생성/관리/배포
    (유사 서비스 terraform은 다양한 클라우드 서비스에서 활용 가능)

 

특징은 다음과 같다. 

  •  stack단위로 리소스 관리 → stack 삭제 시, 해당 template으로 생성된 모든 리소스들이 삭제됨
  • 모범 사례를 자동화 가능
  • AWS 서비스 간 긴밀한 통합
  • 다른 IaC 도구인 Terraform은 다양한 클라우드 지원, 반면 CloudFormation은 AWS 전용

 

 

활용 예시

1. ec2/security group

더보기
Parameters:
  KeyName:
    Description: Name of an existing EC2 KeyPair to enable SSH access to the instances. Linked to AWS Parameter
    Type: AWS::EC2::KeyPair::KeyName
    ConstraintDescription: must be the name of an existing EC2 KeyPair.
  LatestAmiId:
    Description: (DO NOT CHANGE)
    Type: 'AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>'
    Default: '/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2'
    AllowedValues:
      - /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2

# 리소스: ec2, sg 등에 대한 정의
Resources:
  MyInstance: # 자원 name
    Type: AWS::EC2::Instance
    Properties: # 파라미터
      ImageId: !Ref LatestAmiId
      InstanceType: t2.micro
      KeyName: !Ref KeyName
      Tags:
        - Key: Name
          Value: WebServer
      SecurityGroups:
        - !Ref MySG
      UserData:
        Fn::Base64:
          !Sub |
            #!/bin/bash
            yum install httpd -y
            systemctl start httpd && systemctl enable httpd
            echo "<h1>Test Web Server</h1>" > /var/www/html/index.html

  MySG:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Enable HTTP access via port 80 and SSH access via port 22
      SecurityGroupIngress:
      - IpProtocol: tcp
        FromPort: 80
        ToPort: 80
        CidrIp: 0.0.0.0/0
      - IpProtocol: tcp
        FromPort: 22
        ToPort: 22
        CidrIp: 0.0.0.0/0

 

 

2. vpc 구축

더보기
AWSTemplateFormatVersion: "2010-09-09"
Description: VPC Configuration

Resources:
  VPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.0.0.0/16
      EnableDnsHostnames: true
      Tags:
        - Key: Name
          Value: myVPC
 
  # AZ-2a, 2c에 각각 퍼블릭, 프라이빗 서브넷을 생성
  PublicSubnet:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      CidrBlock: 10.0.0.0/24
      AvailabilityZone: "ap-northeast-2a"
      MapPublicIpOnLaunch: true # 퍼블릭 서브넷에 퍼블릭 IP를 자동으로 할당
      Tags:
        - Key: Name
          Value: public subnet
  PrivateSubnet:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      CidrBlock: 10.0.10.0/24
      AvailabilityZone: "ap-northeast-2c"
      Tags:
        - Key: Name
          Value: private subnet
 
  # IGW 생성, vpc에 연결
  IGW:
    Type: AWS::EC2::InternetGateway
    Properties:
      Tags:
        - Key: Name
          Value: myigw
  Attachigw:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      InternetGatewayId: !Ref IGW
      VpcId: !Ref VPC
 
  # EIP 생성, NAT Gateway에 연결
  EIP:
    Type: AWS::EC2::EIP
  NAT:
    Type: AWS::EC2::NatGateway
    DependsOn: Attachigw
    Properties:
      AllocationId: !GetAtt EIP.AllocationId
      SubnetId: !Ref PublicSubnet
 
  # Route Table 생성, 퍼블릭 서브넷과 프라이빗 서브넷에 각각 연결
  # 퍼블릭 서브넷은 IGW를 통해 인터넷과 연결, 프라이빗 서브넷은 NAT Gateway를 통해 인터넷과 연결
  PublicRT:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: Public RT
  PublicRoute:
    Type: AWS::EC2::Route
    DependsOn: Attachigw
    Properties:
      RouteTableId: !Ref PublicRT
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref IGW
  PublicSubnetRTAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref PublicRT
      SubnetId: !Ref PublicSubnet
 
  PrivateRT:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: Private RT
  PrivateRoute:
    Type: AWS::EC2::Route
    DependsOn: Attachigw
    Properties:
      RouteTableId: !Ref PrivateRT
      DestinationCidrBlock: 0.0.0.0/0
      NatGatewayId: !Ref NAT
  PrivateSubnetRTAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref PrivateRT
      SubnetId: !Ref PrivateSubnet

 

 

3. 내부 서버 사용자 데이터를 이용하여 SSH 접속

 

내부 private sub에 접속하려면?

  1. Bastion 서버에서 ssh key를 통해 접속
    그러나, Bastion server 속의 key값이 만약 침투당한다면, 보안상으로 개큰 위협.
     
  2. 내부 서버 프록시를 통한 접속
    → port forwarding으로 내부 IP에 접속

  3. 내부에 서버 인스턴스를 생성할 때, ssh root계정을 생성
    → Bastion server에서 root 권한으로 접속

<3번 방안>

1. 이전 2번의 vpc formation을 통해서 환경 생성

2. public subnet/private subnet에 ec2생성 

3. private subnet에 ec2생성 

 

'고급 세부 정보 - 사용자 데이터'를 통하여

해당 ssh root계정 생성하는 자동화 코드 설정

#!/bin/bash

echo "root:pw_is_buriburi" | chpasswd

sed -i 's/^.*PasswordAuthentication.*/PasswordAuthentication yes/' /etc/ssh/sshd_config
sed -i 's/^.*PermitRootLogin.*/PermitRootLogin yes/' /etc/ssh/sshd_config

systemctl restart sshd

 

 

4. 테스트

public ec2에 접속 후, 해당 ec2내부에서 private ec2에 접속 가능하다.

 

 

<2번 방안 >

private ec2를 생성 후, 접속하려는 사용자의 환경에서 .ssh에서 config파일 생성하여

 

SSH가 직접 접근할 수 없는 대상에 접속할 때, 중간 서버를 통해 터널링을 구현한다.

Host web01
	Hostname {public_ip}
    User {사용자명}
    IdentityFile {public_ip의 key 경로}

Host priv01
	Hostname {private_내부ip}
    User {사용자명}
    IdentityFile {private_ip의 key 경로}
    Proxycommand ssh web01 -W %h%p

 

이를 통해, teminal에서

$ssh web01을 통해 public ec2에, 

$ssh priv01을 통해 private ec2에 접속이 가능하다!