v0.32 vs v0.37

Created Diff never expires
7 removals
330 lines
23 additions
347 lines
AWSTemplateFormatVersion: "2010-09-09"
AWSTemplateFormatVersion: "2010-09-09"
Description: Resources used by https://github.com/aws/karpenter
Description: Resources used by https://github.com/aws/karpenter
Parameters:
Parameters:
ClusterName:
ClusterName:
Type: String
Type: String
Description: "EKS cluster name"
Description: "EKS cluster name"
Resources:
Resources:
KarpenterNodeRole:
KarpenterNodeRole:
Type: "AWS::IAM::Role"
Type: "AWS::IAM::Role"
Properties:
Properties:
RoleName: !Sub "KarpenterNodeRole-${ClusterName}"
RoleName: !Sub "KarpenterNodeRole-${ClusterName}"
Path: /
Path: /
AssumeRolePolicyDocument:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Version: "2012-10-17"
Statement:
Statement:
- Effect: Allow
- Effect: Allow
Principal:
Principal:
Service:
Service:
!Sub "ec2.${AWS::URLSuffix}"
!Sub "ec2.${AWS::URLSuffix}"
Action:
Action:
- "sts:AssumeRole"
- "sts:AssumeRole"
ManagedPolicyArns:
ManagedPolicyArns:
- !Sub "arn:${AWS::Partition}:iam::aws:policy/AmazonEKS_CNI_Policy"
- !Sub "arn:${AWS::Partition}:iam::aws:policy/AmazonEKS_CNI_Policy"
- !Sub "arn:${AWS::Partition}:iam::aws:policy/AmazonEKSWorkerNodePolicy"
- !Sub "arn:${AWS::Partition}:iam::aws:policy/AmazonEKSWorkerNodePolicy"
- !Sub "arn:${AWS::Partition}:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly"
- !Sub "arn:${AWS::Partition}:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly"
- !Sub "arn:${AWS::Partition}:iam::aws:policy/AmazonSSMManagedInstanceCore"
- !Sub "arn:${AWS::Partition}:iam::aws:policy/AmazonSSMManagedInstanceCore"
KarpenterControllerPolicy:
KarpenterControllerPolicy:
Type: AWS::IAM::ManagedPolicy
Type: AWS::IAM::ManagedPolicy
Properties:
Properties:
ManagedPolicyName: !Sub "KarpenterControllerPolicy-${ClusterName}"
ManagedPolicyName: !Sub "KarpenterControllerPolicy-${ClusterName}"
# The PolicyDocument must be in JSON string format because we use a StringEquals condition that uses an interpolated
# The PolicyDocument must be in JSON string format because we use a StringEquals condition that uses an interpolated
# value in one of its key parameters which isn't natively supported by CloudFormation
# value in one of its key parameters which isn't natively supported by CloudFormation
PolicyDocument: !Sub |
PolicyDocument: !Sub |
{
{
"Version": "2012-10-17",
"Version": "2012-10-17",
"Statement": [
"Statement": [
{
{
"Sid": "AllowScopedEC2InstanceActions",
"Sid": "AllowScopedEC2InstanceAccessActions",
"Effect": "Allow",
"Effect": "Allow",
"Resource": [
"Resource": [
"arn:${AWS::Partition}:ec2:${AWS::Region}::image/*",
"arn:${AWS::Partition}:ec2:${AWS::Region}::image/*",
"arn:${AWS::Partition}:ec2:${AWS::Region}::snapshot/*",
"arn:${AWS::Partition}:ec2:${AWS::Region}::snapshot/*",
"arn:${AWS::Partition}:ec2:${AWS::Region}:*:spot-instances-request/*",
"arn:${AWS::Partition}:ec2:${AWS::Region}:*:security-group/*",
"arn:${AWS::Partition}:ec2:${AWS::Region}:*:security-group/*",
"arn:${AWS::Partition}:ec2:${AWS::Region}:*:subnet/*",
"arn:${AWS::Partition}:ec2:${AWS::Region}:*:subnet/*"
"arn:${AWS::Partition}:ec2:${AWS::Region}:*:launch-template/*"
],
],
"Action": [
"Action": [
"ec2:RunInstances",
"ec2:RunInstances",
"ec2:CreateFleet"
"ec2:CreateFleet"
]
]
},
},
{
{
"Sid": "AllowScopedEC2LaunchTemplateAccessActions",
"Effect": "Allow",
"Resource": "arn:${AWS::Partition}:ec2:${AWS::Region}:*:launch-template/*",
"Action": [
"ec2:RunInstances",
"ec2:CreateFleet"
],
"Condition": {
"StringEquals": {
"aws:ResourceTag/kubernetes.io/cluster/${ClusterName}": "owned"
},
"StringLike": {
"aws:ResourceTag/karpenter.sh/nodepool": "*"
}
}
},
{
"Sid": "AllowScopedEC2InstanceActionsWithTags",
"Sid": "AllowScopedEC2InstanceActionsWithTags",
"Effect": "Allow",
"Effect": "Allow",
"Resource": [
"Resource": [
"arn:${AWS::Partition}:ec2:${AWS::Region}:*:fleet/*",
"arn:${AWS::Partition}:ec2:${AWS::Region}:*:fleet/*",
"arn:${AWS::Partition}:ec2:${AWS::Region}:*:instance/*",
"arn:${AWS::Partition}:ec2:${AWS::Region}:*:instance/*",
"arn:${AWS::Partition}:ec2:${AWS::Region}:*:volume/*",
"arn:${AWS::Partition}:ec2:${AWS::Region}:*:volume/*",
"arn:${AWS::Partition}:ec2:${AWS::Region}:*:network-interface/*",
"arn:${AWS::Partition}:ec2:${AWS::Region}:*:network-interface/*",
"arn:${AWS::Partition}:ec2:${AWS::Region}:*:launch-template/*"
"arn:${AWS::Partition}:ec2:${AWS::Region}:*:launch-template/*",
"arn:${AWS::Partition}:ec2:${AWS::Region}:*:spot-instances-request/*"
],
],
"Action": [
"Action": [
"ec2:RunInstances",
"ec2:RunInstances",
"ec2:CreateFleet",
"ec2:CreateFleet",
"ec2:CreateLaunchTemplate"
"ec2:CreateLaunchTemplate"
],
],
"Condition": {
"Condition": {
"StringEquals": {
"StringEquals": {
"aws:RequestTag/kubernetes.io/cluster/${ClusterName}": "owned"
"aws:RequestTag/kubernetes.io/cluster/${ClusterName}": "owned"
},
},
"StringLike": {
"StringLike": {
"aws:RequestTag/karpenter.sh/nodepool": "*"
"aws:RequestTag/karpenter.sh/nodepool": "*"
}
}
}
}
},
},
{
{
"Sid": "AllowScopedResourceCreationTagging",
"Sid": "AllowScopedResourceCreationTagging",
"Effect": "Allow",
"Effect": "Allow",
"Resource": [
"Resource": [
"arn:${AWS::Partition}:ec2:${AWS::Region}:*:fleet/*",
"arn:${AWS::Partition}:ec2:${AWS::Region}:*:fleet/*",
"arn:${AWS::Partition}:ec2:${AWS::Region}:*:instance/*",
"arn:${AWS::Partition}:ec2:${AWS::Region}:*:instance/*",
"arn:${AWS::Partition}:ec2:${AWS::Region}:*:volume/*",
"arn:${AWS::Partition}:ec2:${AWS::Region}:*:volume/*",
"arn:${AWS::Partition}:ec2:${AWS::Region}:*:network-interface/*",
"arn:${AWS::Partition}:ec2:${AWS::Region}:*:network-interface/*",
"arn:${AWS::Partition}:ec2:${AWS::Region}:*:launch-template/*"
"arn:${AWS::Partition}:ec2:${AWS::Region}:*:launch-template/*",
"arn:${AWS::Partition}:ec2:${AWS::Region}:*:spot-instances-request/*"
],
],
"Action": "ec2:CreateTags",
"Action": "ec2:CreateTags",
"Condition": {
"Condition": {
"StringEquals": {
"StringEquals": {
"aws:RequestTag/kubernetes.io/cluster/${ClusterName}": "owned",
"aws:RequestTag/kubernetes.io/cluster/${ClusterName}": "owned",
"ec2:CreateAction": [
"ec2:CreateAction": [
"RunInstances",
"RunInstances",
"CreateFleet",
"CreateFleet",
"CreateLaunchTemplate"
"CreateLaunchTemplate"
]
]
},
},
"StringLike": {
"StringLike": {
"aws:RequestTag/karpenter.sh/nodepool": "*"
"aws:RequestTag/karpenter.sh/nodepool": "*"
}
}
}
}
},
},
{
{
"Sid": "AllowScopedResourceTagging",
"Sid": "AllowScopedResourceTagging",
"Effect": "Allow",
"Effect": "Allow",
"Resource": "arn:${AWS::Partition}:ec2:${AWS::Region}:*:instance/*",
"Resource": "arn:${AWS::Partition}:ec2:${AWS::Region}:*:instance/*",
"Action": "ec2:CreateTags",
"Action": "ec2:CreateTags",
"Condition": {
"Condition": {
"StringEquals": {
"StringEquals": {
"aws:ResourceTag/kubernetes.io/cluster/${ClusterName}": "owned"
"aws:ResourceTag/kubernetes.io/cluster/${ClusterName}": "owned"
},
},
"StringLike": {
"StringLike": {
"aws:ResourceTag/karpenter.sh/nodepool": "*"
"aws:ResourceTag/karpenter.sh/nodepool": "*"
},
},
"ForAllValues:StringEquals": {
"ForAllValues:StringEquals": {
"aws:TagKeys": [
"aws:TagKeys": [
"karpenter.sh/nodeclaim",
"karpenter.sh/nodeclaim",
"Name"
"Name"
]
]
}
}
}
}
},
},
{
{
"Sid": "AllowScopedDeletion",
"Sid": "AllowScopedDeletion",
"Effect": "Allow",
"Effect": "Allow",
"Resource": [
"Resource": [
"arn:${AWS::Partition}:ec2:${AWS::Region}:*:instance/*",
"arn:${AWS::Partition}:ec2:${AWS::Region}:*:instance/*",
"arn:${AWS::Partition}:ec2:${AWS::Region}:*:launch-template/*"
"arn:${AWS::Partition}:ec2:${AWS::Region}:*:launch-template/*"
],
],
"Action": [
"Action": [
"ec2:TerminateInstances",
"ec2:TerminateInstances",
"ec2:DeleteLaunchTemplate"
"ec2:DeleteLaunchTemplate"
],
],
"Condition": {
"Condition": {
"StringEquals": {
"StringEquals": {
"aws:ResourceTag/kubernetes.io/cluster/${ClusterName}": "owned"
"aws:ResourceTag/kubernetes.io/cluster/${ClusterName}": "owned"
},
},
"StringLike": {
"StringLike": {
"aws:ResourceTag/karpenter.sh/nodepool": "*"
"aws:ResourceTag/karpenter.sh/nodepool": "*"
}
}
}
}
},
},
{
{
"Sid": "AllowRegionalReadActions",
"Sid": "AllowRegionalReadActions",
"Effect": "Allow",
"Effect": "Allow",
"Resource": "*",
"Resource": "*",
"Action": [
"Action": [
"ec2:DescribeAvailabilityZones",
"ec2:DescribeAvailabilityZones",
"ec2:DescribeImages",
"ec2:DescribeImages",
"ec2:DescribeInstances",
"ec2:DescribeInstances",
"ec2:DescribeInstanceTypeOfferings",
"ec2:DescribeInstanceTypeOfferings",
"ec2:DescribeInstanceTypes",
"ec2:DescribeInstanceTypes",
"ec2:DescribeLaunchTemplates",
"ec2:DescribeLaunchTemplates",
"ec2:DescribeSecurityGroups",
"ec2:DescribeSecurityGroups",
"ec2:DescribeSpotPriceHistory",
"ec2:DescribeSpotPriceHistory",
"ec2:DescribeSubnets"
"ec2:DescribeSubnets"
],
],
"Condition": {
"Condition": {
"StringEquals": {
"StringEquals": {
"aws:RequestedRegion": "${AWS::Region}"
"aws:RequestedRegion": "${AWS::Region}"
}
}
}
}
},
},
{
{
"Sid": "AllowSSMReadActions",
"Sid": "AllowSSMReadActions",
"Effect": "Allow",
"Effect": "Allow",
"Resource": "arn:${AWS::Partition}:ssm:${AWS::Region}::parameter/aws/service/*",
"Resource": "arn:${AWS::Partition}:ssm:${AWS::Region}::parameter/aws/service/*",
"Action": "ssm:GetParameter"
"Action": "ssm:GetParameter"
},
},
{
{
"Sid": "AllowPricingReadActions",
"Sid": "AllowPricingReadActions",
"Effect": "Allow",
"Effect": "Allow",
"Resource": "*",
"Resource": "*",
"Action": "pricing:GetProducts"
"Action": "pricing:GetProducts"
},
},
{
{
"Sid": "AllowInterruptionQueueActions",
"Sid": "AllowInterruptionQueueActions",
"Effect": "Allow",
"Effect": "Allow",
"Resource": "${KarpenterInterruptionQueue.Arn}",
"Resource": "${KarpenterInterruptionQueue.Arn}",
"Action": [
"Action": [
"sqs:DeleteMessage",
"sqs:DeleteMessage",
"sqs:GetQueueUrl",
"sqs:GetQueueUrl",
"sqs:ReceiveMessage"
"sqs:ReceiveMessage"
]
]
},
},
{
{
"Sid": "AllowPassingInstanceRole",
"Sid": "AllowPassingInstanceRole",
"Effect": "Allow",
"Effect": "Allow",
"Resource": "${KarpenterNodeRole.Arn}",
"Resource": "${KarpenterNodeRole.Arn}",
"Action": "iam:PassRole",
"Action": "iam:PassRole",
"Condition": {
"Condition": {
"StringEquals": {
"StringEquals": {
"iam:PassedToService": "ec2.amazonaws.com"
"iam:PassedToService": "ec2.amazonaws.com"
}
}
}
}
},
},
{
{
"Sid": "AllowScopedInstanceProfileCreationActions",
"Sid": "AllowScopedInstanceProfileCreationActions",
"Effect": "Allow",
"Effect": "Allow",
"Resource": "*",
"Resource": "*",
"Action": [
"Action": [
"iam:CreateInstanceProfile"
"iam:CreateInstanceProfile"
],
],
"Condition": {
"Condition": {
"StringEquals": {
"StringEquals": {
"aws:RequestTag/kubernetes.io/cluster/${ClusterName}": "owned",
"aws:RequestTag/kubernetes.io/cluster/${ClusterName}": "owned",
"aws:RequestTag/topology.kubernetes.io/region": "${AWS::Region}"
"aws:RequestTag/topology.kubernetes.io/region": "${AWS::Region}"
},
},
"StringLike": {
"StringLike": {
"aws:RequestTag/karpenter.k8s.aws/ec2nodeclass": "*"
"aws:RequestTag/karpenter.k8s.aws/ec2nodeclass": "*"
}
}
}
}
},
},
{
{
"Sid": "AllowScopedInstanceProfileTagActions",
"Sid": "AllowScopedInstanceProfileTagActions",
"Effect": "Allow",
"Effect": "Allow",
"Resource": "*",
"Resource": "*",
"Action": [
"Action": [
"iam:TagInstanceProfile"
"iam:TagInstanceProfile"
],
],
"Condition": {
"Condition": {
"StringEquals": {
"StringEquals": {
"aws:ResourceTag/kubernetes.io/cluster/${ClusterName}": "owned",
"aws:ResourceTag/kubernetes.io/cluster/${ClusterName}": "owned",
"aws:ResourceTag/topology.kubernetes.io/region": "${AWS::Region}",
"aws:ResourceTag/topology.kubernetes.io/region": "${AWS::Region}",
"aws:RequestTag/kubernetes.io/cluster/${ClusterName}": "owned",
"aws:RequestTag/kubernetes.io/cluster/${ClusterName}": "owned",
"aws:RequestTag/topology.kubernetes.io/region": "${AWS::Region}"
"aws:RequestTag/topology.kubernetes.io/region": "${AWS::Region}"
},
},
"StringLike": {
"StringLike": {
"aws:ResourceTag/karpenter.k8s.aws/ec2nodeclass": "*",
"aws:ResourceTag/karpenter.k8s.aws/ec2nodeclass": "*",
"aws:RequestTag/karpenter.k8s.aws/ec2nodeclass": "*"
"aws:RequestTag/karpenter.k8s.aws/ec2nodeclass": "*"
}
}
}
}
},
},
{
{
"Sid": "AllowScopedInstanceProfileActions",
"Sid": "AllowScopedInstanceProfileActions",
"Effect": "Allow",
"Effect": "Allow",
"Resource": "*",
"Resource": "*",
"Action": [
"Action": [
"iam:AddRoleToInstanceProfile",
"iam:AddRoleToInstanceProfile",
"iam:RemoveRoleFromInstanceProfile",
"iam:RemoveRoleFromInstanceProfile",
"iam:DeleteInstanceProfile"
"iam:DeleteInstanceProfile"
],
],
"Condition": {
"Condition": {
"StringEquals": {
"StringEquals": {
"aws:ResourceTag/kubernetes.io/cluster/${ClusterName}": "owned",
"aws:ResourceTag/kubernetes.io/cluster/${ClusterName}": "owned",
"aws:ResourceTag/topology.kubernetes.io/region": "${AWS::Region}"
"aws:ResourceTag/topology.kubernetes.io/region": "${AWS::Region}"
},
},
"StringLike": {
"StringLike": {
"aws:ResourceTag/karpenter.k8s.aws/ec2nodeclass": "*"
"aws:ResourceTag/karpenter.k8s.aws/ec2nodeclass": "*"
}
}
}
}
},
},
{
{
"Sid": "AllowInstanceProfileReadActions",
"Sid": "AllowInstanceProfileReadActions",
"Effect": "Allow",
"Effect": "Allow",
"Resource": "*",
"Resource": "*",
"Action": "iam:GetInstanceProfile"
"Action": "iam:GetInstanceProfile"
},
},
{
{
"Sid": "AllowAPIServerEndpointDiscovery",
"Sid": "AllowAPIServerEndpointDiscovery",
"Effect": "Allow",
"Effect": "Allow",
"Resource": "arn:${AWS::Partition}:eks:${AWS::Region}:${AWS::AccountId}:cluster/${ClusterName}",
"Resource": "arn:${AWS::Partition}:eks:${AWS::Region}:${AWS::AccountId}:cluster/${ClusterName}",
"Action": "eks:DescribeCluster"
"Action": "eks:DescribeCluster"
}
}
]
]
}
}
KarpenterInterruptionQueue:
KarpenterInterruptionQueue:
Type: AWS::SQS::Queue
Type: AWS::SQS::Queue
Properties:
Properties:
QueueName: !Sub "${ClusterName}"
QueueName: !Sub "${ClusterName}"
MessageRetentionPeriod: 300
MessageRetentionPeriod: 300
SqsManagedSseEnabled: true
SqsManagedSseEnabled: true
KarpenterInterruptionQueuePolicy:
KarpenterInterruptionQueuePolicy:
Type: AWS::SQS::QueuePolicy
Type: AWS::SQS::QueuePolicy
Properties:
Properties:
Queues:
Queues:
- !Ref KarpenterInterruptionQueue
- !Ref KarpenterInterruptionQueue
PolicyDocument:
PolicyDocument:
Id: EC2InterruptionPolicy
Id: EC2InterruptionPolicy
Statement:
Statement:
- Effect: Allow
- Effect: Allow
Principal:
Principal:
Service:
Service:
- events.amazonaws.com
- events.amazonaws.com
- sqs.amazonaws.com
- sqs.amazonaws.com
Action: sqs:SendMessage
Action: sqs:SendMessage
Resource: !GetAtt KarpenterInterruptionQueue.Arn
Resource: !GetAtt KarpenterInterruptionQueue.Arn
ScheduledChangeRule:
ScheduledChangeRule:
Type: 'AWS::Events::Rule'
Type: 'AWS::Events::Rule'
Properties:
Properties:
EventPattern:
EventPattern:
source:
source:
- aws.health
- aws.health
detail-type:
detail-type:
- AWS Health Event
- AWS Health Event
Targets:
Targets:
- Id: KarpenterInterruptionQueueTarget
- Id: KarpenterInterruptionQueueTarget
Arn: !GetAtt KarpenterInterruptionQueue.Arn
Arn: !GetAtt KarpenterInterruptionQueue.Arn
SpotInterruptionRule:
SpotInterruptionRule:
Type: 'AWS::Events::Rule'
Type: 'AWS::Events::Rule'
Properties:
Properties:
EventPattern:
EventPattern:
source:
source:
- aws.ec2
- aws.ec2
detail-type:
detail-type:
- EC2 Spot Instance Interruption Warning
- EC2 Spot Instance Interruption Warning
Targets:
Targets:
- Id: KarpenterInterruptionQueueTarget
- Id: KarpenterInterruptionQueueTarget
Arn: !GetAtt KarpenterInterruptionQueue.Arn
Arn: !GetAtt KarpenterInterruptionQueue.Arn
RebalanceRule:
RebalanceRule:
Type: 'AWS::Events::Rule'
Type: 'AWS::Events::Rule'
Properties:
Properties:
EventPattern:
EventPattern:
source:
source:
- aws.ec2
- aws.ec2
detail-type:
detail-type:
- EC2 Instance Rebalance Recommendation
- EC2 Instance Rebalance Recommendation
Targets:
Targets:
- Id: KarpenterInterruptionQueueTarget
- Id: KarpenterInterruptionQueueTarget
Arn: !GetAtt KarpenterInterruptionQueue.Arn
Arn: !GetAtt KarpenterInterruptionQueue.Arn
InstanceStateChangeRule:
InstanceStateChangeRule:
Type: 'AWS::Events::Rule'
Type: 'AWS::Events::Rule'
Properties:
Properties:
EventPattern:
EventPattern:
source:
source:
- aws.ec2
- aws.ec2
detail-type:
detail-type:
- EC2 Instance State-change Notification
- EC2 Instance State-change Notification
Targets:
Targets:
- Id: KarpenterInterruptionQueueTarget
- Id: KarpenterInterruptionQueueTarget
Arn: !GetAtt KarpenterInterruptionQueue.Arn
Arn: !GetAtt KarpenterInterruptionQueue.Arn