#!/bin/bash # // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. # // SPDX-License-Identifier: MIT-0 # Define params # export EKSCLUSTER_NAME=eks-rss # export AWS_REGION=us-east-1 export EMR_NAMESPACE=emr export OSS_NAMESPACE=oss export EKS_VERSION=1.22 export EMRCLUSTER_NAME=emr-on-$EKSCLUSTER_NAME export ROLE_NAME=${EMRCLUSTER_NAME}-execution-role export ACCOUNTID=$(aws sts get-caller-identity --query Account --output text) export S3TEST_BUCKET=${EMRCLUSTER_NAME}-${ACCOUNTID}-${AWS_REGION} echo "===============================================" echo " setup IAM roles ......" echo "===============================================" # create S3 bucket for application if [ $AWS_REGION == "us-east-1" ]; then aws s3api create-bucket --bucket $S3TEST_BUCKET --region $AWS_REGION else aws s3api create-bucket --bucket $S3TEST_BUCKET --region $AWS_REGION --create-bucket-configuration LocationConstraint=$AWS_REGION fi # update artifact aws s3 sync example/ s3://$S3TEST_BUCKET/app_code/ # Create a job execution role (https://docs.aws.amazon.com/emr/latest/EMR-on-EKS-DevelopmentGuide/creating-job-execution-role.html) cat >/tmp/job-execution-policy.json </tmp/trust-policy.json </tmp/ekscluster.yaml --- apiVersion: eksctl.io/v1alpha5 kind: ClusterConfig metadata: name: $EKSCLUSTER_NAME region: $AWS_REGION version: "$EKS_VERSION" vpc: clusterEndpoints: publicAccess: true privateAccess: true availabilityZones: ["${AWS_REGION}a","${AWS_REGION}b"] iam: withOIDC: true serviceAccounts: - metadata: name: cluster-autoscaler namespace: kube-system labels: {aws-usage: "cluster-ops"} wellKnownPolicies: autoScaler: true roleName: eksctl-cluster-autoscaler-role - metadata: name: oss namespace: $OSS_NAMESPACE labels: {aws-usage: "application"} attachPolicyARNs: - arn:aws:iam::$ACCOUNTID:policy/$ROLE_NAME-policy - metadata: name: amp-iamproxy-ingest-service-account namespace: prometheus labels: {aws-usage: "monitoring"} attachPolicyARNs: - "arn:aws:iam::aws:policy/AmazonPrometheusRemoteWriteAccess" roleName: $EKSCLUSTER_NAME-prometheus-ingest roleOnly: true managedNodeGroups: - name: rss availabilityZones: ["${AWS_REGION}a"] preBootstrapCommands: # - "sudo yum -y install mdadm" # - "IDX=0;for DEV in /dev/nvme[1-9]n1; do IDX=\$((\${IDX} + 1)); done; sudo mdadm --create --verbose /dev/md0 --level=0 --name=MY_RAID --chunk=64 --raid-devices=\${IDX} /dev/nvme[1-9]n1" # - "sudo mkfs.xfs -L MY_RAID /dev/md0;sudo mkdir -p /local1; sudo echo /dev/md0 /local1 xfs defaults,noatime 1 2 >> /etc/fstab;sudo mount -a" # - "sudo chown ec2-user:ec2-user /local1" - "IDX=1;for DEV in /dev/nvme[1-9]n1;do sudo mkfs.xfs \${DEV}; sudo mkdir -p /local\${IDX}; sudo echo \${DEV} /local\${IDX} xfs defaults,noatime 1 2 >> /etc/fstab; IDX=\$((\${IDX} + 1)); done" - "sudo mount -a" - "sudo chown ec2-user:ec2-user /local*" instanceType: i3en.6xlarge volumeSize: 20 volumeType: gp3 minSize: 1 desiredCapacity: 1 maxSize: 20 placement: groupName: $EKSCLUSTER_NAME-agroup labels: app: rss tags: # required for cluster-autoscaler auto-discovery k8s.io/cluster-autoscaler/enabled: "true" k8s.io/cluster-autoscaler/$EKSCLUSTER_NAME: "owned" - name: css availabilityZones: ["${AWS_REGION}b"] preBootstrapCommands: - "IDX=1;for DEV in /dev/nvme[1-9]n1;do sudo mkfs.xfs \${DEV}; sudo mkdir -p /local\${IDX}; sudo echo \${DEV} /local\${IDX} xfs defaults,noatime 1 2 >> /etc/fstab; IDX=\$((\${IDX} + 1)); done" - "sudo mount -a" - "sudo chown ec2-user:ec2-user /local*" instanceType: i3en.6xlarge volumeSize: 20 volumeType: gp3 minSize: 1 desiredCapacity: 1 maxSize: 20 placement: groupName: $EKSCLUSTER_NAME-bgroup labels: app: css tags: # required for cluster-autoscaler auto-discovery k8s.io/cluster-autoscaler/enabled: "true" k8s.io/cluster-autoscaler/$EKSCLUSTER_NAME: "owned" - name: c59a availabilityZones: ["${AWS_REGION}a"] instanceType: c5.9xlarge preBootstrapCommands: - "sudo systemctl restart docker --no-block" volumeSize: 50 volumeType: gp3 minSize: 1 desiredCapacity: 1 maxSize: 50 placement: groupName: $EKSCLUSTER_NAME-agroup labels: app: sparktest tags: k8s.io/cluster-autoscaler/enabled: "true" k8s.io/cluster-autoscaler/$EKSCLUSTER_NAME: "owned" - name: c59b availabilityZones: ["${AWS_REGION}b"] instanceType: c5.9xlarge preBootstrapCommands: - "sudo systemctl restart docker --no-block" volumeSize: 50 volumeType: gp3 minSize: 1 desiredCapacity: 1 maxSize: 50 placement: groupName: $EKSCLUSTER_NAME-bgroup labels: app: sparktest tags: k8s.io/cluster-autoscaler/enabled: "true" k8s.io/cluster-autoscaler/$EKSCLUSTER_NAME: "owned" - name: c5d9a availabilityZones: ["${AWS_REGION}a"] instanceType: c5d.9xlarge preBootstrapCommands: - "sudo systemctl restart docker --no-block" volumeSize: 20 volumeType: gp3 minSize: 1 desiredCapacity: 1 maxSize: 6 placement: groupName: $EKSCLUSTER_NAME-agroup labels: app: sparktest tags: k8s.io/cluster-autoscaler/enabled: "true" k8s.io/cluster-autoscaler/$EKSCLUSTER_NAME: "owned" # enable all of the control plane logs cloudWatch: clusterLogging: enableTypes: ["*"] EOF # create eks cluster in two AZs eksctl create cluster -f /tmp/ekscluster.yaml # if EKS cluster exists, comment out the line above, uncomment this line # eksctl create nodegroup -f /tmp/ekscluster.yaml aws eks update-kubeconfig --name $EKSCLUSTER_NAME --region $AWS_REGION echo "===============================================" echo " Enable EMR on EKS ......" echo "===============================================" # Create kubernetes namespace for EMR on EKS kubectl create namespace $EMR_NAMESPACE # Enable cluster access for Amazon EMR on EKS in the 'emr' namespace eksctl create iamidentitymapping --cluster $EKSCLUSTER_NAME --namespace $EMR_NAMESPACE --service-name "emr-containers" aws emr-containers update-role-trust-policy --cluster-name $EKSCLUSTER_NAME --namespace $EMR_NAMESPACE --role-name $ROLE_NAME # Create emr virtual cluster aws emr-containers create-virtual-cluster --name $EMRCLUSTER_NAME \ --container-provider '{ "id": "'$EKSCLUSTER_NAME'", "type": "EKS", "info": { "eksInfo": { "namespace": "'$EMR_NAMESPACE'" } } }' echo "===============================================" echo " Configure EKS Cluster ......" echo "===============================================" # Map the s3 bucket environment variable to EKS cluster kubectl create -n $OSS_NAMESPACE configmap special-config --from-literal=codeBucket=$S3TEST_BUCKET # Install k8s metrics server kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml # Install Spark-Operator for the OSS Spark test helm repo add spark-operator https://googlecloudplatform.github.io/spark-on-k8s-operator helm install -n $OSS_NAMESPACE spark-operator spark-operator/spark-operator --version 1.1.26 \ --set serviceAccounts.spark.create=false --set metrics.enable=false --set webhook.enable=true --set webhook.port=443 --debug # Install Cluster Autoscaler that automatically adjusts the number of nodes in EKS cat </tmp/autoscaler-config.yaml --- autoDiscovery: clusterName: $EKSCLUSTER_NAME awsRegion: $AWS_REGION image: tag: v1.22.2 podAnnotations: cluster-autoscaler.kubernetes.io/safe-to-evict: 'false' extraArgs: skip-nodes-with-system-pods: false scale-down-unneeded-time: 1m scale-down-unready-time: 2m rbac: serviceAccount: create: false name: cluster-autoscaler EOF helm repo add autoscaler https://kubernetes.github.io/autoscaler helm install nodescaler autoscaler/cluster-autoscaler --namespace kube-system --values /tmp/autoscaler-config.yaml --debug # config k8s rbac access to service account 'oss' cat <