无法通过单个 AWS CloudFormation 堆栈创建 AWS EKS 集群和工作线程节点组

时间:2021-01-27 22:45:40

标签: amazon-web-services amazon-cloudformation amazon-eks

我想在单个 CloudFormation 堆栈中设置 AWS EKS 集群 (AWS::EKS::Cluster) 和工作线程节点组 (AWS::AutoScaling::AutoScalingGroup)。这是我创建的 CF 定义:

AWSTemplateFormatVersion: "2010-09-09"

Description: Creates API gateway and services for my projects

Parameters:

  ClusterName:
    Type: String
    Description: Cluster name
    Default: eks-min-cluster

  NodeAutoScalingGroupDesiredCapacity:
    Type: Number
    Default: 2
    Description: Desired capacity of Node Group ASG.

  NodeAutoScalingGroupMinSize:
    Type: Number
    Default: 1
    Description: Minimum size of Node Group ASG.

  NodeAutoScalingGroupMaxSize:
    Type: Number
    Default: 3
    Description: Maximum size of Node Group ASG. Set to at least 1 greater than NodeAutoScalingGroupDesiredCapacity.

  BootstrapArguments:
    Type: String
    Default: ""
    Description: "Arguments to pass to the nodes' bootstrap script. See files/bootstrap.sh in https://github.com/awslabs/amazon-eks-ami"

  VpcCidr:
    Description: Please enter the IP range (CIDR notation) for this VPC
    Type: String
    Default: 10.192.0.0/16

  PublicSubnet1Cidr:
    Description: Please enter the IP range (CIDR notation) for the public subnet in the first Availability Zone
    Type: String
    Default: 10.192.20.0/24

  PublicSubnet2Cidr:
    Description: Please enter the IP range (CIDR notation) for the public subnet in the first Availability Zone
    Type: String
    Default: 10.192.21.0/24

  PrivateSubnet1Cidr:
    Description: Please enter the IP range (CIDR notation) for the private subnet in the first Availability Zone
    Type: String
    Default: 10.192.22.0/24

  PrivateSubnet2Cidr:
    Description: Please enter the IP range (CIDR notation) for the private subnet in the second Availability Zone
    Type: String
    Default: 10.192.23.0/24

  NodeImageIdSSMParam:
    Type: "AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>"
    Default: /aws/service/eks/optimized-ami/1.14/amazon-linux-2/recommended/image_id
    Description: AWS Systems Manager Parameter Store parameter of the AMI ID for the worker node instances.

Resources: 

  InternetGateway:
    Type: AWS::EC2::InternetGateway

  Vpc:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: !Ref VpcCidr
      EnableDnsSupport: true
      EnableDnsHostnames: true

  VpcGatewayAttachment:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties: 
      InternetGatewayId: !Ref InternetGateway
      VpcId: !Ref Vpc

  PublicSubnet1:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref Vpc
      AvailabilityZone: !Select [ 0, !GetAZs  '' ]
      CidrBlock: !Ref PublicSubnet1Cidr
      MapPublicIpOnLaunch: true

  PublicSubnet2:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref Vpc
      AvailabilityZone: !Select [ 1, !GetAZs  '' ]
      CidrBlock: !Ref PublicSubnet2Cidr
      MapPublicIpOnLaunch: true

  PrivateSubnet1:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref Vpc
      AvailabilityZone: !Select [ 0, !GetAZs  '' ]
      CidrBlock: !Ref PrivateSubnet1Cidr
      MapPublicIpOnLaunch: true

  PrivateSubnet2:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref Vpc
      AvailabilityZone: !Select [ 1, !GetAZs  '' ]
      CidrBlock: !Ref PrivateSubnet2Cidr
      MapPublicIpOnLaunch: true

  SshSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      VpcId: !Ref Vpc
      GroupDescription: Enable SSH access via port 22
      SecurityGroupIngress:
        - CidrIp: 0.0.0.0/0
          FromPort: 22
          IpProtocol: tcp
          ToPort: 22
        - CidrIp: 0.0.0.0/0
          FromPort: 8
          IpProtocol: icmp
          ToPort: -1

  GatewayHostSshPortAddress:
    Type: AWS::EC2::EIP
    DependsOn: VpcGatewayAttachment
    Properties:
      Domain: vpc

  AssociateGatewayHostSshPort:
    Type: AWS::EC2::EIPAssociation
    DependsOn: GatewayHostSshPortAddress
    Properties:
      AllocationId: !GetAtt GatewayHostSshPortAddress.AllocationId
      NetworkInterfaceId: !Ref GatewayHostSshNetworkInterface

  GatewayHostSshNetworkInterface:
    Type: AWS::EC2::NetworkInterface
    Properties:
      SubnetId: !Ref PublicSubnet1
      Description: Interface for controlling traffic such as SSH
      GroupSet: 
        - !Ref SshSecurityGroup
      SourceDestCheck: true

  PublicRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref Vpc

  PrivateSubnet1RouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref Vpc

  PrivateSubnet2RouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref Vpc

  DefaultPublicRoute:
    Type: AWS::EC2::Route
    DependsOn: VpcGatewayAttachment
    Properties:
      RouteTableId: !Ref PublicRouteTable
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref InternetGateway

  PrivateSubnet1Route:
    Type: AWS::EC2::Route
    DependsOn:
      - VpcGatewayAttachment
      - PrivateSubnet1NatGateway
    Properties:
      RouteTableId: !Ref PrivateSubnet1RouteTable
      DestinationCidrBlock: 0.0.0.0/0
      NatGatewayId: !Ref PrivateSubnet1NatGateway

  PrivateSubnet2Route:
    Type: AWS::EC2::Route
    DependsOn:
      - VpcGatewayAttachment
      - PrivateSubnet2NatGateway
    Properties:
      RouteTableId: !Ref PrivateSubnet2RouteTable
      DestinationCidrBlock: 0.0.0.0/0
      NatGatewayId: !Ref PrivateSubnet2NatGateway

  PrivateSubnet1NatGateway:
    Type: AWS::EC2::NatGateway
    DependsOn:
      - PrivateSubnet1NatGatewayEIP
      - PublicSubnet1
      - VpcGatewayAttachment
    Properties:
      AllocationId: !GetAtt PrivateSubnet1NatGatewayEIP.AllocationId
      SubnetId: !Ref PublicSubnet1

  PrivateSubnet2NatGateway:
    Type: AWS::EC2::NatGateway
    DependsOn:
      - PrivateSubnet2NatGatewayEIP
      - PublicSubnet2
      - VpcGatewayAttachment
    Properties:
      AllocationId: !GetAtt PrivateSubnet2NatGatewayEIP.AllocationId
      SubnetId: !Ref PublicSubnet2

  PrivateSubnet1NatGatewayEIP:
    DependsOn:
    - VpcGatewayAttachment
    Type: 'AWS::EC2::EIP'
    Properties:
      Domain: vpc

  PrivateSubnet2NatGatewayEIP:
    DependsOn:
    - VpcGatewayAttachment
    Type: 'AWS::EC2::EIP'
    Properties:
      Domain: vpc

  PublicRouteTableToPublicSubnet1Association:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref PublicRouteTable
      SubnetId: !Ref PublicSubnet1

  PublicRouteTableToPublicSubnet2Association:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref PublicRouteTable
      SubnetId: !Ref PublicSubnet2

  PrivateRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref Vpc


  GatewayHost:
    Type: AWS::EC2::Instance
    DependsOn: [AssociateGatewayHostSshPort]
    Properties:
      ImageId: ami-03c3a7e4263fd998c
      InstanceType: t2.nano
      AvailabilityZone: !Select [ 0, !GetAZs  '' ]
      KeyName: jd-system
      NetworkInterfaces:
        -
          NetworkInterfaceId: !Ref GatewayHostSshNetworkInterface
          DeviceIndex: 0
    Metadata: 
      AWS::CloudFormation::Init: 
        config: 
          files: 
            /etc/kong/kong.yml: 
              content: test-jd
              #source: 
              mode: "000644"
              owner: "root"
              group: "root"

  EksIamRole:
    Type: 'AWS::IAM::Role'
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - eks.amazonaws.com
            Action:
              - 'sts:AssumeRole'
      RoleName: EksIamRole
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AmazonEKSClusterPolicy
        - arn:aws:iam::aws:policy/AmazonEKSServicePolicy



################### CONTROL PLANE ###################

  ClusterControlPlaneSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Cluster communication with worker nodes
      VpcId: !Ref Vpc

  EksCluster:
    Type: AWS::EKS::Cluster
    Properties:
      Name: !Ref ClusterName
      RoleArn: !GetAtt EksIamRole.Arn
      ResourcesVpcConfig:
        SecurityGroupIds:
          - !Ref SshSecurityGroup
          - !Ref ClusterControlPlaneSecurityGroup
        SubnetIds:
          - !Ref PublicSubnet1
          - !Ref PublicSubnet2
          - !Ref PrivateSubnet1
          - !Ref PrivateSubnet2
    DependsOn: [EksIamRole, PublicSubnet1, PublicSubnet2, PrivateSubnet1, PrivateSubnet2, SshSecurityGroup]

################### WORKER NODES ###################


  NodeSecurityGroup:
    Type: "AWS::EC2::SecurityGroup"
    Properties:
      GroupDescription: Security group for all nodes in the cluster
      Tags:
        - Key: !Sub kubernetes.io/cluster/${ClusterName}
          Value: owned
      VpcId: !Ref Vpc

  NodeSecurityGroupIngress:
    Type: "AWS::EC2::SecurityGroupIngress"
    DependsOn: NodeSecurityGroup
    Properties:
      Description: Allow node to communicate with each other
      FromPort: 0
      GroupId: !Ref NodeSecurityGroup
      IpProtocol: "-1"
      SourceSecurityGroupId: !Ref NodeSecurityGroup
      ToPort: 65535

  ClusterControlPlaneSecurityGroupIngress:
    Type: "AWS::EC2::SecurityGroupIngress"
    DependsOn: NodeSecurityGroup
    Properties:
      Description: Allow pods to communicate with the cluster API Server
      FromPort: 443
      GroupId: !Ref ClusterControlPlaneSecurityGroup
      IpProtocol: tcp
      SourceSecurityGroupId: !Ref NodeSecurityGroup
      ToPort: 443

  ControlPlaneEgressToNodeSecurityGroup:
    Type: "AWS::EC2::SecurityGroupEgress"
    DependsOn: NodeSecurityGroup
    Properties:
      Description: Allow the cluster control plane to communicate with worker Kubelet and pods
      DestinationSecurityGroupId: !Ref NodeSecurityGroup
      FromPort: 1025
      GroupId: !Ref ClusterControlPlaneSecurityGroup
      IpProtocol: tcp
      ToPort: 65535

  ControlPlaneEgressToNodeSecurityGroupOn443:
    Type: "AWS::EC2::SecurityGroupEgress"
    DependsOn: NodeSecurityGroup
    Properties:
      Description: Allow the cluster control plane to communicate with pods running extension API servers on port 443
      DestinationSecurityGroupId: !Ref NodeSecurityGroup
      FromPort: 443
      GroupId: !Ref ClusterControlPlaneSecurityGroup
      IpProtocol: tcp
      ToPort: 443

  NodeSecurityGroupFromControlPlaneIngress:
    Type: "AWS::EC2::SecurityGroupIngress"
    DependsOn: NodeSecurityGroup
    Properties:
      Description: Allow worker Kubelets and pods to receive communication from the cluster control plane
      FromPort: 1025
      GroupId: !Ref NodeSecurityGroup
      IpProtocol: tcp
      SourceSecurityGroupId: !Ref ClusterControlPlaneSecurityGroup
      ToPort: 65535

  NodeSecurityGroupFromControlPlaneOn443Ingress:
    Type: "AWS::EC2::SecurityGroupIngress"
    DependsOn: NodeSecurityGroup
    Properties:
      Description: Allow pods running extension API servers on port 443 to receive communication from cluster control plane
      FromPort: 443
      GroupId: !Ref NodeSecurityGroup
      IpProtocol: tcp
      SourceSecurityGroupId: !Ref ClusterControlPlaneSecurityGroup
      ToPort: 443

  NodeInstanceRole:
    Type: "AWS::IAM::Role"
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - ec2.amazonaws.com
            Action:
              - "sts:AssumeRole"
      ManagedPolicyArns:
        - "arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy"
        - "arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy"
        - "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly"
      Path: /

  NodeInstanceProfile:
    Type: "AWS::IAM::InstanceProfile"
    Properties:
      Path: /
      Roles:
        - Ref: NodeInstanceRole

  NodeLaunchConfig:
    Type: "AWS::AutoScaling::LaunchConfiguration"
    Properties:
      AssociatePublicIpAddress: "true"
      BlockDeviceMappings:
        - DeviceName: /dev/xvda
          Ebs:
            DeleteOnTermination: true
            VolumeSize: 10
            VolumeType: gp2
      IamInstanceProfile: !Ref NodeInstanceProfile
      #ImageId: ami-03c3a7e4263fd998c
      ImageId: !Ref NodeImageIdSSMParam
      InstanceType: t2.nano
      KeyName: jd-system
      SecurityGroups:
        - Ref: NodeSecurityGroup
      UserData: !Base64
        "Fn::Sub": |
          #!/bin/bash
          set -o xtrace
          /etc/eks/bootstrap.sh ${ClusterName} ${BootstrapArguments}
          /opt/aws/bin/cfn-signal --exit-code $? \
                   --stack  ${AWS::StackName} \
                   --resource NodeGroup  \
                   --region ${AWS::Region}

  NodeGroup:
    Type: "AWS::AutoScaling::AutoScalingGroup"
    DependsOn: 
      - EksCluster
      - Vpc
    Properties:
      DesiredCapacity: !Ref NodeAutoScalingGroupDesiredCapacity
      LaunchConfigurationName: !Ref NodeLaunchConfig
      MaxSize: !Ref NodeAutoScalingGroupMaxSize
      MinSize: !Ref NodeAutoScalingGroupMinSize
      Tags:
        - Key: Name
          PropagateAtLaunch: "true"
          Value: !Sub ${ClusterName}-NodeGroup-Node
        - Key: !Sub kubernetes.io/cluster/${ClusterName}
          PropagateAtLaunch: "true"
          Value: owned
      VPCZoneIdentifier: 
        - !Ref PublicSubnet1
        - !Ref PublicSubnet2
        - !Ref PrivateSubnet1
        - !Ref PrivateSubnet2
    UpdatePolicy:
      AutoScalingRollingUpdate:
        MaxBatchSize: "1"
        MinInstancesInService: !Ref NodeAutoScalingGroupDesiredCapacity
        PauseTime: PT5M

Outputs:
  GatewayHostPublicIp:
    Description: Gateway host public ip
    Value: !GetAtt GatewayHost.PublicIp
  EksClusterEndpoint:
    Description: EksCluster endpoint
    Value: !GetAtt EksCluster.Endpoint

堆栈创建后,我看不到任何工作节点:

$ kubectl get nodes
No resources found

也没有创建 Pod:

$ kubectl get pods --all-namespaces
NAMESPACE     NAME                              READY   STATUS    RESTARTS   AGE
kube-system   coredns-59b69b4849-l97bq          0/1     Pending   0          7m15s
kube-system   coredns-59b69b4849-zwtql          0/1     Pending   0          7m15s
kube-system   metrics-server-7949d47784-2xjck   0/1     Pending   0          8s

我阅读的教程通过一个 CF 堆栈和工作节点组通过另一个创建 EKS 集群。我想通过单个脚本设置所有内容。我怀疑工作节点组创建得太快了,但是,我是 CF 和 EKS 的新手,无法确认这一点。请指教。

1 个答案:

答案 0 :(得分:0)

我尝试重现该错误并修改了您的测试模板。修改的模板在下面,所以你必须检查它是否需要。如果您想使用它,您还必须将其调整为您的设置。为简单起见,我将所有内容都放在公共子网中,但我认为这不是这里的关键问题。

我认为核心问题是您没有设置 aws-auth-cm.yaml 禁止节点实例向集群注册。

设置 aws-auth-cm.yaml,请查看 To enable nodes to join your cluster 部分。完成后,我可以在使用下面的模板时在 kubectl get nodes 中看到我的节点。

我有 kubectl 在我的本地工作站上运行,而不是在您创建的堡垒主机上。我只测试了加入集群的节点,没有测试任何 Pod 的功能。此外,EKS AWS 控制台不显示节点,但 kubectl get nodes 显示它们。

AWSTemplateFormatVersion: "2010-09-09"

Description: Creates API gateway and services for my projects

Parameters:

  ClusterName:
    Type: String
    Description: Cluster name
    Default: eks-min-cluster

  NodeAutoScalingGroupDesiredCapacity:
    Type: Number
    Default: 1
    Description: Desired capacity of Node Group ASG.

  NodeAutoScalingGroupMinSize:
    Type: Number
    Default: 1
    Description: Minimum size of Node Group ASG.

  KeyPair:
    Type: AWS::EC2::KeyPair::KeyName
    Default: jd-system

  NodeAutoScalingGroupMaxSize:
    Type: Number
    Default: 3
    Description: Maximum size of Node Group ASG. Set to at least 1 greater than NodeAutoScalingGroupDesiredCapacity.

  BootstrapArguments:
    Type: String
    Default: ""
    Description: "Arguments to pass to the nodes' bootstrap script. See files/bootstrap.sh in https://github.com/awslabs/amazon-eks-ami"

  VpcCidr:
    Description: Please enter the IP range (CIDR notation) for this VPC
    Type: String
    Default: 10.192.0.0/16

  PublicSubnet1Cidr:
    Description: Please enter the IP range (CIDR notation) for the public subnet in the first Availability Zone
    Type: String
    Default: 10.192.20.0/24

  PublicSubnet2Cidr:
    Description: Please enter the IP range (CIDR notation) for the public subnet in the first Availability Zone
    Type: String
    Default: 10.192.21.0/24

  PrivateSubnet1Cidr:
    Description: Please enter the IP range (CIDR notation) for the private subnet in the first Availability Zone
    Type: String
    Default: 10.192.22.0/24

  PrivateSubnet2Cidr:
    Description: Please enter the IP range (CIDR notation) for the private subnet in the second Availability Zone
    Type: String
    Default: 10.192.23.0/24

  NodeImageIdSSMParam:
    Type: "AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>"
    Default: /aws/service/eks/optimized-ami/1.18/amazon-linux-2/recommended/image_id
    Description: AWS Systems Manager Parameter Store parameter of the AMI ID for the worker node instances.

  LatestAmiId:
    Type: 'AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>'
    Default: '/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2'


Resources: 

  InternetGateway:
    Type: AWS::EC2::InternetGateway

  Vpc:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: !Ref VpcCidr
      EnableDnsSupport: true
      EnableDnsHostnames: true
      Tags:
       - Key: !Sub "kubernetes.io/cluster/${ClusterName}"
         Value: shared           
       - Key: Name
         Value: MyEksVpc      

  VpcGatewayAttachment:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties: 
      InternetGatewayId: !Ref InternetGateway
      VpcId: !Ref Vpc

  PublicSubnet1:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref Vpc
      AvailabilityZone: !Select [ 0, !GetAZs  '' ]
      CidrBlock: !Ref PublicSubnet1Cidr
      MapPublicIpOnLaunch: true
      Tags:
       - Key: kubernetes.io/role/elb
         Value: 1    
      Tags:
       - Key: !Sub "kubernetes.io/cluster/${ClusterName}"
         Value: shared

  PublicSubnet2:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref Vpc
      AvailabilityZone: !Select [ 1, !GetAZs  '' ]
      CidrBlock: !Ref PublicSubnet2Cidr
      MapPublicIpOnLaunch: true
      Tags:
       - Key: kubernetes.io/role/elb
         Value: 1            
       - Key: !Sub "kubernetes.io/cluster/${ClusterName}"
         Value: shared      

  PrivateSubnet1:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref Vpc
      AvailabilityZone: !Select [ 0, !GetAZs  '' ]
      CidrBlock: !Ref PrivateSubnet1Cidr
      MapPublicIpOnLaunch: true
      Tags:
       - Key: kubernetes.io/role/internal-elb
         Value: 1    

  PrivateSubnet2:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref Vpc
      AvailabilityZone: !Select [ 1, !GetAZs  '' ]
      CidrBlock: !Ref PrivateSubnet2Cidr
      MapPublicIpOnLaunch: true
      Tags:
       - Key: kubernetes.io/role/internal-elb
         Value: 1         

  SshSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      VpcId: !Ref Vpc
      GroupDescription: Enable SSH access via port 22
      SecurityGroupIngress:
        - CidrIp: 0.0.0.0/0
          FromPort: 22
          IpProtocol: tcp
          ToPort: 22
        - CidrIp: 0.0.0.0/0
          FromPort: 8
          IpProtocol: icmp
          ToPort: -1

  GatewayHostSshPortAddress:
    Type: AWS::EC2::EIP
    DependsOn: VpcGatewayAttachment
    Properties:
      Domain: vpc

  AssociateGatewayHostSshPort:
    Type: AWS::EC2::EIPAssociation
    DependsOn: GatewayHostSshPortAddress
    Properties:
      AllocationId: !GetAtt GatewayHostSshPortAddress.AllocationId
      NetworkInterfaceId: !Ref GatewayHostSshNetworkInterface

  GatewayHostSshNetworkInterface:
    Type: AWS::EC2::NetworkInterface
    Properties:
      SubnetId: !Ref PublicSubnet1
      Description: Interface for controlling traffic such as SSH
      GroupSet: 
        - !Ref SshSecurityGroup
      SourceDestCheck: true

  PublicRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref Vpc

  PrivateSubnet1RouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref Vpc

  PrivateSubnet2RouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref Vpc

  DefaultPublicRoute:
    Type: AWS::EC2::Route
    #DependsOn: VpcGatewayAttachment
    Properties:
      RouteTableId: !Ref PublicRouteTable
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref InternetGateway

  PrivateSubnet1Route:
    Type: AWS::EC2::Route
    #DependsOn:
    #  - VpcGatewayAttachment
    #  - PrivateSubnet1NatGateway
    Properties:
      RouteTableId: !Ref PrivateSubnet1RouteTable
      DestinationCidrBlock: 0.0.0.0/0
      NatGatewayId: !Ref PrivateSubnet1NatGateway

  PrivateSubnet2Route:
    Type: AWS::EC2::Route
    #DependsOn:
    #  - VpcGatewayAttachment
    #  - PrivateSubnet2NatGateway
    Properties:
      RouteTableId: !Ref PrivateSubnet2RouteTable
      DestinationCidrBlock: 0.0.0.0/0
      NatGatewayId: !Ref PrivateSubnet2NatGateway

  PrivateSubnet1NatGateway:
    Type: AWS::EC2::NatGateway
    #DependsOn:
    #  - PrivateSubnet1NatGatewayEIP
      #- PublicSubnet1
      #- VpcGatewayAttachment
    Properties:
      AllocationId: !GetAtt PrivateSubnet1NatGatewayEIP.AllocationId
      SubnetId: !Ref PublicSubnet1

  PrivateSubnet2NatGateway:
    Type: AWS::EC2::NatGateway
    # DependsOn:
    #   - PrivateSubnet2NatGatewayEIP
    #   - PublicSubnet2
    #   - VpcGatewayAttachment
    Properties:
      AllocationId: !GetAtt PrivateSubnet2NatGatewayEIP.AllocationId
      SubnetId: !Ref PublicSubnet2

  PrivateSubnet1NatGatewayEIP:
    DependsOn:
    - VpcGatewayAttachment
    Type: 'AWS::EC2::EIP'
    Properties:
      Domain: vpc

  PrivateSubnet2NatGatewayEIP:
    DependsOn:
    - VpcGatewayAttachment
    Type: 'AWS::EC2::EIP'
    Properties:
      Domain: vpc

  PublicRouteTableToPublicSubnet1Association:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref PublicRouteTable
      SubnetId: !Ref PublicSubnet1

  PublicRouteTableToPublicSubnet2Association:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref PublicRouteTable
      SubnetId: !Ref PublicSubnet2

  PrivateRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref Vpc


#   GatewayHost:
#     Type: AWS::EC2::Instance
#     DependsOn: [AssociateGatewayHostSshPort]
#     Properties:
#       ImageId:  !Ref LatestAmiId
#       InstanceType: t2.nano
#       AvailabilityZone: !Select [ 0, !GetAZs  '' ]
#       KeyName: !Ref KeyPair
#       NetworkInterfaces:
#         -
#           NetworkInterfaceId: !Ref GatewayHostSshNetworkInterface
#           DeviceIndex: 0
#     # Metadata: 
#     #   AWS::CloudFormation::Init: 
#     #     config: 
#     #       files: 
#     #         /etc/kong/kong.yml: 
#     #           content: test-jd
#     #           #source: 
#     #           mode: "000644"
#     #           owner: "root"
#     #           group: "root"

  EksIamRole:
    Type: 'AWS::IAM::Role'
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - eks.amazonaws.com
            Action:
              - 'sts:AssumeRole'
      #RoleName: EksIamRole
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AmazonEKSClusterPolicy
        - arn:aws:iam::aws:policy/AmazonEKSServicePolicy



################### CONTROL PLANE ###################

  ClusterControlPlaneSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Cluster communication with worker nodes
      VpcId: !Ref Vpc

  EksCluster:
    Type: AWS::EKS::Cluster
    Properties:
      Name: !Ref ClusterName
      RoleArn: !GetAtt EksIamRole.Arn
      ResourcesVpcConfig:
        SecurityGroupIds:
          #- !Ref SshSecurityGroup
          - !Ref ClusterControlPlaneSecurityGroup
        SubnetIds:
          - !Ref PublicSubnet1
          - !Ref PublicSubnet2
          #- !Ref PrivateSubnet1
          #- !Ref PrivateSubnet2
    #DependsOn: [EksIamRole, PublicSubnet1, PublicSubnet2, PrivateSubnet1, PrivateSubnet2, SshSecurityGroup]

################### WORKER NODES ###################


  NodeSecurityGroup:
    Type: "AWS::EC2::SecurityGroup"
    Properties:
      GroupDescription: Security group for all nodes in the cluster
      Tags:
        - Key: !Sub kubernetes.io/cluster/${ClusterName}
          Value: owned
      VpcId: !Ref Vpc

  NodeSecurityGroupIngress:
    Type: "AWS::EC2::SecurityGroupIngress"
    DependsOn: NodeSecurityGroup
    Properties:
      Description: Allow node to communicate with each other
      FromPort: 0
      GroupId: !Ref NodeSecurityGroup
      IpProtocol: "-1"
      SourceSecurityGroupId: !Ref NodeSecurityGroup
      ToPort: 65535

  ClusterControlPlaneSecurityGroupIngress:
    Type: "AWS::EC2::SecurityGroupIngress"
    #DependsOn: NodeSecurityGroup
    Properties:
      Description: Allow pods to communicate with the cluster API Server
      FromPort: 443
      GroupId: !Ref ClusterControlPlaneSecurityGroup
      IpProtocol: tcp
      SourceSecurityGroupId: !Ref NodeSecurityGroup
      ToPort: 443

  ControlPlaneEgressToNodeSecurityGroup:
    Type: "AWS::EC2::SecurityGroupEgress"
    #DependsOn: NodeSecurityGroup
    Properties:
      Description: Allow the cluster control plane to communicate with worker Kubelet and pods
      DestinationSecurityGroupId: !Ref NodeSecurityGroup
      FromPort: 1025
      GroupId: !Ref ClusterControlPlaneSecurityGroup
      IpProtocol: tcp
      ToPort: 65535

  ControlPlaneEgressToNodeSecurityGroupOn443:
    Type: "AWS::EC2::SecurityGroupEgress"
    #DependsOn: NodeSecurityGroup
    Properties:
      Description: Allow the cluster control plane to communicate with pods running extension API servers on port 443
      DestinationSecurityGroupId: !Ref NodeSecurityGroup
      FromPort: 443
      GroupId: !Ref ClusterControlPlaneSecurityGroup
      IpProtocol: tcp
      ToPort: 443

  NodeSecurityGroupFromControlPlaneIngress:
    Type: "AWS::EC2::SecurityGroupIngress"
    #DependsOn: NodeSecurityGroup
    Properties:
      Description: Allow worker Kubelets and pods to receive communication from the cluster control plane
      FromPort: 1025
      GroupId: !Ref NodeSecurityGroup
      IpProtocol: tcp
      SourceSecurityGroupId: !Ref ClusterControlPlaneSecurityGroup
      ToPort: 65535

  NodeSecurityGroupFromControlPlaneOn443Ingress:
    Type: "AWS::EC2::SecurityGroupIngress"
    #DependsOn: NodeSecurityGroup
    Properties:
      Description: Allow pods running extension API servers on port 443 to receive communication from cluster control plane
      FromPort: 443
      GroupId: !Ref NodeSecurityGroup
      IpProtocol: tcp
      SourceSecurityGroupId: !Ref ClusterControlPlaneSecurityGroup
      ToPort: 443

  NodeInstanceRole:
    Type: "AWS::IAM::Role"
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - ec2.amazonaws.com
            Action:
              - "sts:AssumeRole"
      ManagedPolicyArns:
        - "arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy"
        - "arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy"
        - "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly"
      Path: /

  NodeInstanceProfile:
    Type: "AWS::IAM::InstanceProfile"
    Properties:
      Path: /
      Roles:
        - Ref: NodeInstanceRole

  NodeLaunchConfig:
    Type: "AWS::AutoScaling::LaunchConfiguration"
    Properties:
      AssociatePublicIpAddress: "true"
      BlockDeviceMappings:
        - DeviceName: /dev/xvda
          Ebs:
            DeleteOnTermination: true
            VolumeSize: 20
            VolumeType: gp2
      IamInstanceProfile: !Ref NodeInstanceProfile
      #ImageId: ami-03c3a7e4263fd998c
      ImageId: !Ref NodeImageIdSSMParam
      InstanceType: t2.micro
      KeyName: !Ref KeyPair
      SecurityGroups:
        - Ref: NodeSecurityGroup
      UserData: !Base64
        "Fn::Sub": |
          #!/bin/bash
          set -o xtrace
          /etc/eks/bootstrap.sh ${ClusterName} ${BootstrapArguments}
          /opt/aws/bin/cfn-signal --exit-code $? \
                   --stack  ${AWS::StackName} \
                   --resource NodeGroup  \
                   --region ${AWS::Region}

  NodeGroup:
    Type: "AWS::AutoScaling::AutoScalingGroup"
    DependsOn: 
      - EksCluster
    #  - Vpc
    Properties:
      DesiredCapacity: !Ref NodeAutoScalingGroupDesiredCapacity
      LaunchConfigurationName: !Ref NodeLaunchConfig
      MaxSize: !Ref NodeAutoScalingGroupMaxSize
      MinSize: !Ref NodeAutoScalingGroupMinSize
      Tags:
        - Key: Name
          PropagateAtLaunch: "true"
          Value: !Sub ${ClusterName}-MyNodeGroup-Node
        - Key: !Sub kubernetes.io/cluster/${ClusterName}
          PropagateAtLaunch: "true"
          Value: owned
      VPCZoneIdentifier: 
        - !Ref PublicSubnet1
        - !Ref PublicSubnet2
        #- !Ref PrivateSubnet1
        #- !Ref PrivateSubnet2        

    # CreationPolicy:
    #   AutoScalingCreationPolicy:
    #     MinSuccessfulInstancesPercent: !Ref NodeAutoScalingGroupDesiredCapacity
    #   ResourceSignal:    
    #     Count: !Ref NodeAutoScalingGroupDesiredCapacity
    #     Timeout: PT5M

    # UpdatePolicy:
    #   AutoScalingRollingUpdate:
    #     MaxBatchSize: "1"
    #     MinInstancesInService: !Ref NodeAutoScalingGroupDesiredCapacity
    #     PauseTime: PT5M

Outputs:
#   GatewayHostPublicIp:
#     Description: Gateway host public ip
#     Value: !GetAtt GatewayHost.PublicIp

  NodeInstanceRoleArn:
    Value: !GetAtt NodeInstanceRole.Arn

  EksClusterEndpoint:
    Description: EksCluster endpoint
    Value: !GetAtt EksCluster.Endpoint