diff --git a/samples/eks-cluster-prework/scripts/pw-script.sh b/samples/eks-cluster-prework/scripts/pw-script.sh index f75a0af..b264164 100644 --- a/samples/eks-cluster-prework/scripts/pw-script.sh +++ b/samples/eks-cluster-prework/scripts/pw-script.sh @@ -1,17 +1,18 @@ #!/bin/bash # Install kubectl -yum install -y unzip -# TODO: Make this generic based on the EKS Version -curl -o kubectl https://amazon-eks.s3.us-west-2.amazonaws.com/1.16.8/2020-04-16/bin/linux/amd64/kubectl -chmod +x ./kubectl +# we are installing the current version if you are on an older cluster you might need to change this. +curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" +# Install kubectl +install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl #============= INSERT YOUR PREWORK STEPS HERE ====================# -# Confirm VNI version (Current is 1.9.0) - we could just assume this since it is a new cluster -kubectl describe daemonset aws-node --namespace kube-system | grep Image | cut -d "/" -f 2 > /tmp/foo.txt -# TODO: add to a kubernetes secret we output into the CloudFormation template - -# Set AWS_VPC_K8S_CNI_CUSTOM_NETWORK_CFG to True -kubectl set env daemonset aws-node -n kube-system AWS_VPC_K8S_CNI_CUSTOM_NETWORK_CFG=true +# We will create a simple script the point of the blog is to show that you CAN run pre-work on the cluster via CloudFormation +# so we are less concerned with the content of this script. -# Add additional steps below +# there are much better ways to manage secrets ;) +kubectl create secret generic db-user-pass \ + --from-literal=username=devuser \ + --from-literal=password='S!B\*d$zDsb=' \ + -- namespace $KUBE_NAMESPACE +kubectl describe secrets/db-user-pass \ No newline at end of file diff --git a/samples/eks-cluster-prework/templates/eks-cluster-prework.template.yaml b/samples/eks-cluster-prework/templates/eks-cluster-prework.template.yaml index b53c118..c1ca84f 100644 --- a/samples/eks-cluster-prework/templates/eks-cluster-prework.template.yaml +++ b/samples/eks-cluster-prework/templates/eks-cluster-prework.template.yaml @@ -4,6 +4,9 @@ Parameters: AccessCIDR: Default: 0.0.0.0/0 Type: String + JobName: + Type: String + Default: 'job-example' PreworkScriptBucket: Type: String Default: 'aws-quickstart' @@ -16,23 +19,38 @@ Resources: Properties: TemplateURL: 'https://aws-quickstart.s3.amazonaws.com/quickstart-amazon-eks/templates/amazon-eks-entrypoint-new-vpc.template.yaml' Parameters: - # Quickstart properties + # QuickStart properties QSS3BucketName: aws-quickstart QSS3KeyPrefix: quickstart-amazon-eks/ - QSS3BucketRegion: us-east-1 # Cluster properties - ProvisionBastionHost: Enabled - AccessCIDR: !Ref AccessCIDR + ProvisionBastionHost: Enabled + AccessCIDR: !Ref AccessCIDR NodeInstanceType: t3.large NumberOfNodes: 1 MaxNumberOfNodes: 1 + GetOIDCProvider: + Type: Custom::GetOIDCProvider + Properties: + ServiceToken: !Sub "arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:eks-quickstart-ResourceReader" + AwsCliCommand: !Sub "eks describe-cluster --name ${ClusterName} --query 'cluster.identity.oidc.{issuer:issuer}'" + IdField: 'issuer' PreworkStack: Type: AWS::CloudFormation::Stack Properties: TemplateURL: 'https://aws-quickstart.s3.amazonaws.com/quickstart-examples/samples/eks-cluster-prework/templates/prework.template.yaml' Parameters: - ClusterName: !Sub "EKSStack.Outputs.EKSClusterName" - PreworkScriptBucket: "aws-quickstart" - PreworkScriptObject: "quickstart-examples/samples/eks-cluster-prework/scripts/pw-script.sh" - JobName: "ExampleJob" + ClusterName: !Sub "EKSStack.Outputs.EKSClusterName" + PreworkScriptBucket: !Ref PreworkScriptBucket + PreworkScriptObject: !Ref PreworkScriptObject + JobName: !Ref JobName KubernetesNameSpace: "prework-example" + OIDCProvider: !Sub + - "${OIDCProvider1}/${OIDCProvider2}/${OIDCProvider3}" + - OIDCProvider1: !Select [ 2, !Split [ "/", !Ref GetOIDCProvider ] ] + OIDCProvider2: !Select [ 3, !Split [ "/", !Ref GetOIDCProvider ] ] + OIDCProvider3: !Select [ 4, !Split [ "/", !Ref GetOIDCProvider ] ] +Outputs: + EKSClusterName: + Value: !GetAtt EKSStack.Outputs.EKSClusterName + BastionIP: + Value: !GetAtt EKSStack.Outputs.BastionIP diff --git a/samples/eks-cluster-prework/templates/prework.template.yaml b/samples/eks-cluster-prework/templates/prework.template.yaml index cfd4e66..aae7057 100644 --- a/samples/eks-cluster-prework/templates/prework.template.yaml +++ b/samples/eks-cluster-prework/templates/prework.template.yaml @@ -1,5 +1,5 @@ AWSTemplateFormatVersion: "2010-09-09" -Description: +Description: "Amazon EKS cluster pre/post-work blog sample" Parameters: ClusterName: Type: String @@ -11,15 +11,23 @@ Parameters: Default: "quickstart-examples/samples/eks-cluster-prework/scripts/pw-script.sh" JobName: Type: String - Default: ExampleJob + Default: job-example + AllowedPattern: '[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*' + ConstraintDescription: "a lowercase RFC 1123 subdomain must consist of lower case + alphanumeric characters, '-' or '.', and must start and end with an alphanumeric + character" + OIDCProvider: + Type: String + Description: Amazon EKS cluster OIDC provider, without the protocol (e.g., oidc.eks.us-east-1.amazonaws.com/id/SADFASFFASFXCCVXCVSDFSDF). + Default: "" KubernetesNameSpace: Type: String Default: "prework-example" Resources: - KubernetesPreWorkIAMRole: + PreWorkIAMRole: Type: AWS::IAM::Role Properties: - RoleName: !Sub "pw-role-${JobName}" + RoleName: !Sub "pw-role-${JobName}" AssumeRolePolicyDocument: !Sub - | { @@ -33,14 +41,14 @@ Resources: "Action": "sts:AssumeRoleWithWebIdentity", "Condition": { "StringEquals": { - "${OIDCProvider}:sub": "system:serviceaccount:${NameSpace}:${ResourceName}-${JobName}" + "${OIDCProvider}:sub": "system:serviceaccount:${NameSpace}:${ResourceName}" } } } ] } - NameSpace: !Ref KubernetesNameSpace - ResourceName: "pw-service-account" + ResourceName: !Sub "pw-service-account-${JobName}" Path: "/" Policies: - PolicyName: root @@ -50,10 +58,22 @@ Resources: - Effect: Allow Action: - s3:GetObject + - s3:HeadObject Resource: - !Sub "arn:aws:s3:::${PreworkScriptBucket}/${PreworkScriptObject}" - KubernetesRole: + KubePreWorkNamespace: + Type: "AWSQS::Kubernetes::Resource" + Properties: + ClusterName: !Ref ClusterName + Namespace: default + Manifest: !Sub | + kind: Namespace + apiVersion: v1 + metadata: + name: ${KubernetesNameSpace} + KubePreWorkRole: Type: AWSQS::Kubernetes::Resource + DependsOn: [ KubePreWorkNamespace ] Properties: ClusterName: !Ref ClusterName Namespace: !Ref KubernetesNameSpace @@ -63,8 +83,8 @@ Resources: kind: Role metadata: labels: - app.kubernetes.io/name: "${ResourceName}-${JobName}" - name: "${ResourceName}-${JobName}" + app.kubernetes.io/name: "${ResourceName}" + name: "${ResourceName}" # Modify for your scripts here rules: - apiGroups: @@ -74,11 +94,12 @@ Resources: verbs: - create - delete - - ResourceName: "pw-role" + - get + - ResourceName: !Sub "pw-role-${JobName}" NameSpace: !Ref "KubernetesNameSpace" - - PreWorkServiceAccount: + KubePreWorkServiceAccount: Type: AWSQS::Kubernetes::Resource + DependsOn: [ KubePreWorkNamespace ] Properties: ClusterName: !Ref ClusterName Namespace: !Ref KubernetesNameSpace @@ -88,17 +109,17 @@ Resources: kind: ServiceAccount metadata: labels: - app.kubernetes.io/name: "${ResourceName}-${JobName}" + app.kubernetes.io/name: "${ResourceName}" annotations: - eks.amazonaws.com/role-arn: arn:aws:iam::${AWS::AccountId}:role/${RoleName}-${JobName} - name: "${ResourceName}-${JobName}" + eks.amazonaws.com/role-arn: arn:aws:iam::${AWS::AccountId}:role/${RoleName} + name: "${ResourceName}" namespace: ${NameSpace} - - ResourceName: "pw-service-account" + - ResourceName: !Sub "pw-service-account-${JobName}" NameSpace: !Ref KubernetesNameSpace - RoleName: !Ref "PreWorkIAMRole" - - PreWorkClusterRoleBinding: + RoleName: !Ref PreWorkIAMRole + KubePreWorkRoleBinding: Type: AWSQS::Kubernetes::Resource + DependsOn: [ KubePreWorkNamespace, KubePreWorkRole, KubePreWorkServiceAccount ] Properties: ClusterName: !Ref ClusterName Namespace: !Ref KubernetesNameSpace @@ -108,8 +129,8 @@ Resources: kind: RoleBinding metadata: labels: - app.kubernetes.io/name: "${ResourceName}-${JobName}" - name: "${ResourceName}-${JobName}" + app.kubernetes.io/name: "${ResourceName}" + name: "${ResourceName}" roleRef: apiGroup: rbac.authorization.k8s.io kind: Role @@ -118,11 +139,10 @@ Resources: - kind: ServiceAccount name: "pw-service-account-${JobName}" namespace: ${NameSpace} - - ResourceName: "pw-role-binding-${JobName}" + - ResourceName: !Sub "pw-role-binding-${JobName}" NameSpace: !Ref KubernetesNameSpace - - PreWorkJob: - DependsOn: [ PreWorkIAMRole, PreWorkRole, PreWorkServiceAccount, PreWorkRoleBinding ] + KubePreWorkJob: + DependsOn: [ PreWorkIAMRole, KubePreWorkRole, KubePreWorkServiceAccount, KubePreWorkRoleBinding ] Type: AWSQS::Kubernetes::Resource Properties: ClusterName: !Ref ClusterName @@ -132,7 +152,7 @@ Resources: apiVersion: batch/v1 kind: Job metadata: - name: "${ResourceName}-${JobName}" + name: "${ResourceName}" namespace: ${NameSpace} spec: template: @@ -157,9 +177,11 @@ Resources: value: ${S3ScriptURL} - name: AWS_REGION value: ${AWS::Region} + - name: KUBE_NAMESPACE + value: ${KubernetesNameSpace} serviceAccountName: "pw-service-account-${JobName}" restartPolicy: Never backoffLimit: 4 - - ResourceName: "pw-job" + - ResourceName: !Sub "pw-job-${JobName}" NameSpace: !Ref "KubernetesNameSpace" - S3ScriptURL: !Sub "s3://${PreworkScriptBucket}/${PreworkScriptObject}" + S3ScriptURL: !Sub "s3://${PreworkScriptBucket}/${PreworkScriptObject}" \ No newline at end of file