Launch and SSH to EC2

本文主要介绍了如何使用 SSH 连接到 AWS EC2.

Step1. Launch EC2

本质上 EC2 就是使用 虚拟机软件, 例如 VMWare, 在亚马逊的数据中心上运行的虚拟机. 虚拟机主要作为服务器使用, 这里面 90% 以上的服务器是 Linux.

Step2. Connect via SSH

Grant access to your pem key:

chmod 400 ~/ec2-pem/<key-pair-name>.pem

SSH connect:

$ ssh -i {path-to-your-pem-file} {username}@{ip-address}
  • path-to-your-pem-file: it is where you store your EC2 SSH Key Pair .pem file, usually, you should put it at ${HOME}/ec2-pem/<key-pair-name>.pem

  • username: the operation system username account. By default, if it is Amazon Linux, it is ec2-user. If it is ubuntu, it is ubuntu. It is not your IAM username!

  • ip-address: For EC2 on public subnet, public IPV4 address, can be found at your EC2 instances dashboard. For EC2 on private subnet, it is private IPV4 address.

Reference:

Step3. Connect via SSH the Better Way

由于在我们启动一个 EC2 的时候, 是并不知道他的 public ip 地址的. 而每次 EC2 关闭再启动后, 这个 IP 地址都会改变. 我们希望提供一小段代码, 使得每次想要 SSH 到 EC2 上的时候, 只要快速的复制粘贴即可.

# specify your ec2 name
EC2_NAME="your-ec2-name"

# specify your cli profile
AWS_PROFILE="your-aws-cli-profile"

# retrieve public ip
EC2_IP="$(aws ec2 describe-instances --filters "Name=tag:Name,Values=${EC2_NAME}" --query 'Reservations[0].Instances[0].PublicIpAddress' --output text --profile ${AWS_PROFILE})"

# retrieve private ip
EC2_IP="$(aws ec2 describe-instances --filters "Name=tag:Name,Values=${EC2_NAME}" --query 'Reservations[0].Instances[0].PrivateIpAddress' --output text --profile ${AWS_PROFILE})"

# specify the default user, for redhat, centos, amazon linux, it is ec2-user. for ubuntu it is ubuntu
EC2_USER="ec2-user"

# specify the location of your pem file
EC2_PEM="path-to-your-pem-file"

# run ssh connect
echo EC2_PEM="${EC2_PEM}", EC2_USER="${EC2_USER}", EC2_IP="${EC2_IP}" && ssh -i ${EC2_PEM} ${EC2_USER}@${EC2_IP}

Step4. Copy file or dir between EC2 and local machine via SSH Copy

Reference:

# Copy file from a EC2 to local host:
$ scp -i {path-to-your-pem-file} <username>@<ec2-ip>:<path-to-ec2-file> <path-to-file>

# Copy file from local host to a EC2:
$ scp -i {path-to-your-pem-file} <path-to-file> <username>@<ec2-ip>:<path-to-ec2-file>


# Copy directory from a EC2 to local host:
$ scp -i {path-to-your-pem-file} -r <username>@<ec2-ip>:<path-to-ec2-dir> <path-to-dir>

# Copy directory from local host to a EC2:
$ scp -i {path-to-your-pem-file} -r <path-to-dir> <username>@<ec2-ip>:<path-to-ec2-dir>

Tool

# -*- coding: utf-8 -*-

"""
Generate the ssh command to connect to ec2 for you.

You have to put your ec2 key pair (.pem) file at ${HOME}/${AWS_ACCOUNT_ALIAS}/${AWS_REGION}/${KEY_NAME}

Ref:

- Default user name for AMI: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/connection-prereqs.html#connection-prereqs-get-info-about-instance

- For Amazon Linux 2 or the Amazon Linux AMI, the user name is ec2-user.
- For a CentOS AMI, the user name is centos.
- For a Debian AMI, the user name is admin.
- For a Fedora AMI, the user name is ec2-user or fedora.
- For a RHEL AMI, the user name is ec2-user or root.
- For a SUSE AMI, the user name is ec2-user or root.
- For an Ubuntu AMI, the user name is ubuntu.
"""

import boto3
from pathlib import Path

# ------------------------- File in value here -------------------------
aws_profile = "your_aws_profile"
aws_region = "us-east-1"
ec2_name = ""
# ----------------------------------------------------------------------
print(f"try to create the ssh connect command for the ec2 {ec2_name!r} ...")

boto_ses = boto3.session.Session(profile_name=aws_profile, region_name=aws_region)
ec2_client = boto_ses.client("ec2")
iam_client = boto_ses.client("iam")


def get_aws_account_alias() -> str:
    return iam_client.list_account_aliases()["AccountAliases"][0]


def get_instance_dict(ec2_name: str) -> dict:
    res = ec2_client.describe_instances(
        Filters=[
            dict(
                Name="tag:Name",
                Values=[
                    ec2_name,
                ]
            )
        ]
    )
    inst_dict = res["Reservations"][0]["Instances"][0]
    return inst_dict


def get_image_name(image_id: str) -> str:
    image_dct = ec2_client.describe_images(
        ImageIds=[image_id, ]
    )["Images"][0]
    image_name = image_dct["Name"]
    return image_name


aws_account_alias = get_aws_account_alias()
instance_dict = get_instance_dict(ec2_name)
public_ip = instance_dict["PublicIpAddress"]
image_id = instance_dict["ImageId"]
key_name = instance_dict["KeyName"]
image_name = get_image_name(image_id)

pem_file_path = (
    Path.home().absolute()
    / "ec2-pem"
    / aws_account_alias
    / aws_region
    / f"{key_name}.pem"
)

if image_name.startswith("amzn"):
    username = "ec2-user"
elif image_name.startswith("RHEL"):
    username = "ec2-user"
elif image_name.startswith("suse"):
    username = "ec2-user"
elif image_name.startswith("fedora"):
    username = "ec2-user"
elif image_name.startswith("ubuntu"):
    username = "ubuntu"
elif image_name.startswith("debian"):
    username = "admin"
else:
    username = "ec2-user"

cmd = "ssh -i {ec2_pem} {username}@{public_ip}".format(
    ec2_pem=pem_file_path, username=username, public_ip=public_ip,
)
if pem_file_path.exists():
    print("enter the following command to terminal:")
    print()
    print(cmd)
else:
    raise FileNotFoundError(f"{pem_file_path} not found!")