AWSTemplateFormatVersion: '2010-09-09' Metadata: AWS::CloudFormation::Interface: ParameterGroups: - Label: default: "<<<<< EKSCTL MY EC2 >>>>>" Parameters: - ClusterBaseName - KeyName - SgIngressSshCidr - MyInstanceType - LatestAmiId - Label: default: "<<<<< Region AZ >>>>>" Parameters: - TargetRegion - AvailabilityZone1 - AvailabilityZone2 - Label: default: "<<<<< VPC Subnet >>>>>" Parameters: - VpcBlock - PublicSubnet1Block - PublicSubnet2Block - PrivateSubnet1Block - PrivateSubnet2Block Parameters: ClusterBaseName: Type: String Default: myeks AllowedPattern: "[a-zA-Z][-a-zA-Z0-9]*" Description: must be a valid Allowed Pattern '[a-zA-Z][-a-zA-Z0-9]*' ConstraintDescription: ClusterBaseName - must be a valid Allowed Pattern 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. SgIngressSshCidr: Description: The IP address range that can be used to communicate to the EC2 instances Type: String MinLength: '9' MaxLength: '18' Default: 0.0.0.0/0 AllowedPattern: (\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/(\d{1,2}) ConstraintDescription: must be a valid IP CIDR range of the form x.x.x.x/x. MyInstanceType: Description: Enter t2.micro, t2.small, t2.medium, t3.micro, t3.small, t3.medium. Default is t2.micro. Type: String Default: t3.medium AllowedValues: - t2.micro - t2.small - t2.medium - t3.micro - t3.small - t3.medium LatestAmiId: Description: (DO NOT CHANGE) Type: 'AWS::SSM::Parameter::Value' 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 TargetRegion: Type: String Default: ap-northeast-2 AvailabilityZone1: Type: String Default: ap-northeast-2a AvailabilityZone2: Type: String Default: ap-northeast-2c VpcBlock: Type: String Default: 192.168.0.0/16 PublicSubnet1Block: Type: String Default: 192.168.1.0/24 PublicSubnet2Block: Type: String Default: 192.168.2.0/24 PrivateSubnet1Block: Type: String Default: 192.168.3.0/24 PrivateSubnet2Block: Type: String Default: 192.168.4.0/24 Resources: # VPC EksVPC: Type: AWS::EC2::VPC Properties: CidrBlock: !Ref VpcBlock EnableDnsSupport: true EnableDnsHostnames: true Tags: - Key: Name Value: !Sub ${ClusterBaseName}-VPC # PublicSubnets PublicSubnet1: Type: AWS::EC2::Subnet Properties: AvailabilityZone: !Ref AvailabilityZone1 CidrBlock: !Ref PublicSubnet1Block VpcId: !Ref EksVPC MapPublicIpOnLaunch: true Tags: - Key: Name Value: !Sub ${ClusterBaseName}-PublicSubnet1 - Key: kubernetes.io/role/elb Value: 1 PublicSubnet2: Type: AWS::EC2::Subnet Properties: AvailabilityZone: !Ref AvailabilityZone2 CidrBlock: !Ref PublicSubnet2Block VpcId: !Ref EksVPC MapPublicIpOnLaunch: true Tags: - Key: Name Value: !Sub ${ClusterBaseName}-PublicSubnet2 - Key: kubernetes.io/role/elb Value: 1 InternetGateway: Type: AWS::EC2::InternetGateway VPCGatewayAttachment: Type: AWS::EC2::VPCGatewayAttachment Properties: InternetGatewayId: !Ref InternetGateway VpcId: !Ref EksVPC PublicSubnetRouteTable: Type: AWS::EC2::RouteTable Properties: VpcId: !Ref EksVPC Tags: - Key: Name Value: !Sub ${ClusterBaseName}-PublicSubnetRouteTable PublicSubnetRoute: Type: AWS::EC2::Route Properties: RouteTableId: !Ref PublicSubnetRouteTable DestinationCidrBlock: 0.0.0.0/0 GatewayId: !Ref InternetGateway PublicSubnet1RouteTableAssociation: Type: AWS::EC2::SubnetRouteTableAssociation Properties: SubnetId: !Ref PublicSubnet1 RouteTableId: !Ref PublicSubnetRouteTable PublicSubnet2RouteTableAssociation: Type: AWS::EC2::SubnetRouteTableAssociation Properties: SubnetId: !Ref PublicSubnet2 RouteTableId: !Ref PublicSubnetRouteTable # PrivateSubnets PrivateSubnet1: Type: AWS::EC2::Subnet Properties: AvailabilityZone: !Ref AvailabilityZone1 CidrBlock: !Ref PrivateSubnet1Block VpcId: !Ref EksVPC Tags: - Key: Name Value: !Sub ${ClusterBaseName}-PrivateSubnet1 - Key: kubernetes.io/role/internal-elb Value: 1 PrivateSubnet2: Type: AWS::EC2::Subnet Properties: AvailabilityZone: !Ref AvailabilityZone2 CidrBlock: !Ref PrivateSubnet2Block VpcId: !Ref EksVPC Tags: - Key: Name Value: !Sub ${ClusterBaseName}-PrivateSubnet2 - Key: kubernetes.io/role/internal-elb Value: 1 PrivateSubnetRouteTable: Type: AWS::EC2::RouteTable Properties: VpcId: !Ref EksVPC Tags: - Key: Name Value: !Sub ${ClusterBaseName}-PrivateSubnetRouteTable PrivateSubnet1RouteTableAssociation: Type: AWS::EC2::SubnetRouteTableAssociation Properties: SubnetId: !Ref PrivateSubnet1 RouteTableId: !Ref PrivateSubnetRouteTable PrivateSubnet2RouteTableAssociation: Type: AWS::EC2::SubnetRouteTableAssociation Properties: SubnetId: !Ref PrivateSubnet2 RouteTableId: !Ref PrivateSubnetRouteTable # EKSCTL-Host EKSEC2SG: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: eksctl-host Security Group VpcId: !Ref EksVPC Tags: - Key: Name Value: !Sub ${ClusterBaseName}-HOST-SG SecurityGroupIngress: - IpProtocol: '-1' #FromPort: '22' #ToPort: '22' CidrIp: !Ref SgIngressSshCidr EKSEC2: Type: AWS::EC2::Instance Properties: InstanceType: !Ref MyInstanceType ImageId: !Ref LatestAmiId KeyName: !Ref KeyName Tags: - Key: Name Value: !Sub ${ClusterBaseName}-host NetworkInterfaces: - DeviceIndex: 0 SubnetId: !Ref PublicSubnet1 GroupSet: - !Ref EKSEC2SG AssociatePublicIpAddress: true PrivateIpAddress: 192.168.1.100 BlockDeviceMappings: - DeviceName: /dev/xvda Ebs: VolumeType: gp3 VolumeSize: 20 DeleteOnTermination: true UserData: Fn::Base64: !Sub | #!/bin/bash hostnamectl --static set-hostname "${ClusterBaseName}-host" # Config convenience echo 'alias vi=vim' >> /etc/profile echo "sudo su -" >> /home/ec2-user/.bashrc # Change Timezone sed -i "s/UTC/Asia\/Seoul/g" /etc/sysconfig/clock ln -sf /usr/share/zoneinfo/Asia/Seoul /etc/localtime # Install Packages cd /root yum -y install tree jq git htop lynx # Install kubectl & helm #curl -O https://s3.us-west-2.amazonaws.com/amazon-eks/1.26.2/2023-03-17/bin/linux/amd64/kubectl curl -O https://s3.us-west-2.amazonaws.com/amazon-eks/1.25.7/2023-03-17/bin/linux/amd64/kubectl install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl curl -s https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 | bash # Install eksctl curl --silent --location "https://github.com/weaveworks/eksctl/releases/latest/download/eksctl_$(uname -s)_amd64.tar.gz" | tar xz -C /tmp mv /tmp/eksctl /usr/local/bin # Install aws cli v2 curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" unzip awscliv2.zip >/dev/null 2>&1 sudo ./aws/install complete -C '/usr/local/bin/aws_completer' aws echo 'export AWS_PAGER=""' >>/etc/profile export AWS_DEFAULT_REGION=${AWS::Region} echo "export AWS_DEFAULT_REGION=$AWS_DEFAULT_REGION" >> /etc/profile # Install YAML Highlighter wget https://github.com/andreazorzetto/yh/releases/download/v0.4.0/yh-linux-amd64.zip unzip yh-linux-amd64.zip mv yh /usr/local/bin/ # Install krew curl -LO https://github.com/kubernetes-sigs/krew/releases/download/v0.4.3/krew-linux_amd64.tar.gz tar zxvf krew-linux_amd64.tar.gz ./krew-linux_amd64 install krew export PATH="$PATH:/root/.krew/bin" echo 'export PATH="$PATH:/root/.krew/bin"' >> /etc/profile # Install kube-ps1 echo 'source <(kubectl completion bash)' >> /etc/profile echo 'alias k=kubectl' >> /etc/profile echo 'complete -F __start_kubectl k' >> /etc/profile git clone https://github.com/jonmosco/kube-ps1.git /root/kube-ps1 cat <<"EOT" >> /root/.bash_profile source /root/kube-ps1/kube-ps1.sh KUBE_PS1_SYMBOL_ENABLE=false function get_cluster_short() { echo "$1" | cut -d . -f1 } KUBE_PS1_CLUSTER_FUNCTION=get_cluster_short KUBE_PS1_SUFFIX=') ' PS1='$(kube_ps1)'$PS1 EOT # Install krew plugin kubectl krew install ctx ns get-all # ktop df-pv mtail tree # Install Docker amazon-linux-extras install docker -y systemctl start docker && systemctl enable docker # CLUSTER_NAME export CLUSTER_NAME=${ClusterBaseName} echo "export CLUSTER_NAME=$CLUSTER_NAME" >> /etc/profile # Create SSH Keypair ssh-keygen -t rsa -N "" -f /root/.ssh/id_rsa Outputs: eksctlhost: Value: !GetAtt EKSEC2.PublicIp