From 14b40a9d40a71cfe0142ffb1af0cba22e594de01 Mon Sep 17 00:00:00 2001 From: Michele Cereda Date: Wed, 20 Mar 2024 23:29:44 +0100 Subject: [PATCH] chore(kb): include findings obtained while testing the creation of an eks cluster --- knowledge base/cloud computing/aws/cli.md | 51 +++- knowledge base/cloud computing/aws/eks.md | 288 +++++++++++++--------- knowledge base/pulumi.md | 63 ++++- knowledge base/template.md | 2 +- 4 files changed, 277 insertions(+), 127 deletions(-) diff --git a/knowledge base/cloud computing/aws/cli.md b/knowledge base/cloud computing/aws/cli.md index cebe75a..4ba3ffb 100644 --- a/knowledge base/cloud computing/aws/cli.md +++ b/knowledge base/cloud computing/aws/cli.md @@ -11,11 +11,13 @@ ## TL;DR +
+ Installation and configuration + ```sh # Install the CLI. brew install 'awscli' - # Configure profiles. aws configure aws configure --profile 'work' @@ -23,12 +25,17 @@ aws configure --profile 'work' # Use specific profiles for the rest of the shell session. export AWS_PROFILE='work' - # Enable auto-prompt mode (like `aws-shell` does). aws configure set 'cli_auto_prompt' 'on-partial' export AWS_CLI_AUTO_PROMPT='on' +``` +
+
+ Usage + +```sh # List applications in CodeDeploy. aws deploy list-applications @@ -40,7 +47,6 @@ aws deploy get-deployment-group --application-name 'batman' \ --deployment-group-name 'production' - # Show RDS instances. aws rds describe-db-instances aws rds describe-db-instances --output 'json' --query "DBInstances[?(DBInstanceIdentifier=='master-prod')]" @@ -70,14 +76,37 @@ aws secretsmanager get-secret-value --secret-id 'ecr-pullthroughcache/github' aws sns list-topics -# Start sessions via Session Manager. -aws ssm start-session --target 'i-0123456789abcdef0' +# Get information about the current user. +aws sts get-caller-identity ``` -Non listed subcommand: +Subcommands not listed here are in their own service-specific article: -- [`aws ecr`][ecr tldr] -- [`aws s3`][s3 tldr] +[`ebs`][ebs tldr] | +[`ec2`][ec2 tldr] | +[`ecr`][ecr tldr] | +[`eks`][eks tldr] | +[`s3`][s3 tldr] | +[`ssm`][ssm tldr] + +
+ +
+ Real world use cases + +```sh +# Get roles' ARN from their name. +aws iam list-roles --query "Roles[?RoleName == 'EKSRole'].[RoleName, Arn]" + +# Assume roles given their name. +aws iam list-roles --query "Roles[?RoleName == 'EKSRole'].Arn" --output 'text' \ +| xargs -I {} \ + aws sts assume-role \ + --role-arn "{}" \ + --role-session-name "AWSCLI-Session" +``` + +
## Profiles @@ -150,6 +179,7 @@ aws ssm start-session --target 'i-0123456789abcdef0' - [AWS] - CLI [quickstart] - [Configure profiles] in the CLI +- [How do I assume an IAM role using the AWS CLI?] ### Sources @@ -162,14 +192,19 @@ aws ssm start-session --target 'i-0123456789abcdef0' [aws]: README.md +[ebs tldr]: ebs.md#tldr +[ec2 tldr]: ec2.md#tldr [ecr tldr]: ecr.md#tldr +[eks tldr]: eks.md#tldr [s3 tldr]: s3.md#tldr +[ssm tldr]: ssm.md#tldr [cli config files]: ../../../examples/dotfiles/.aws [configure profiles]: https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-profiles.html +[how do i assume an iam role using the aws cli?]: https://repost.aws/knowledge-center/iam-assume-role-cli [improved cli auto-prompt mode]: https://github.com/aws/aws-cli/issues/5664 [install the session manager plugin for the aws cli]: https://docs.aws.amazon.com/systems-manager/latest/userguide/install-plugin-macos-overview.html#install-plugin-macos-signed [quickstart]: https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-quickstart.html diff --git a/knowledge base/cloud computing/aws/eks.md b/knowledge base/cloud computing/aws/eks.md index f3bb2c8..f761d4a 100644 --- a/knowledge base/cloud computing/aws/eks.md +++ b/knowledge base/cloud computing/aws/eks.md @@ -6,8 +6,11 @@ 1. [Create worker nodes](#create-worker-nodes) 1. [Create managed node groups](#create-managed-node-groups) 1. [Schedule pods on Fargate](#schedule-pods-on-fargate) +1. [Access management](#access-management) 1. [Secrets encryption through KMS](#secrets-encryption-through-kms) 1. [Troubleshooting](#troubleshooting) + 1. [Identify common issues](#identify-common-issues) + 1. [The worker nodes fail to join the cluster.](#the-worker-nodes-fail-to-join-the-cluster) 1. [Further readings](#further-readings) 1. [Sources](#sources) @@ -132,14 +135,14 @@ Some create Cloudformation stacks in the process. ```json { - "Version": "2012-10-17", - "Statement": [{ - "Effect": "Allow", - "Action": "sts:AssumeRole", - "Principal": { - "Service": "eks.amazonaws.com" - } - }] + "Version": "2012-10-17", + "Statement": [{ + "Effect": "Allow", + "Action": "sts:AssumeRole", + "Principal": { + "Service": "eks.amazonaws.com" + } + }] } ``` @@ -147,6 +150,9 @@ Some create Cloudformation stacks in the process. aws iam create-role \ --role-name 'DeepThinker' \ --assume-role-policy-document 'file://eks-cluster-role-trust-policy.json' + aws iam attach-role-policy \ + --role-name 'DeepThinker' \ + --policy-arn 'arn:aws:iam::aws:policy/AmazonEKSClusterPolicy' ``` @@ -156,20 +162,24 @@ Some create Cloudformation stacks in the process. ```ts const cluster_assumeRole_policy = JSON.stringify({ - Version: "2012-10-17", - Statement: [{ - Effect: "Allow", - Action: "sts:AssumeRole", - Principal: { - Service: "eks.amazonaws.com", - }, - }], + Version: "2012-10-17", + Statement: [{ + Effect: "Allow", + Action: "sts:AssumeRole", + Principal: { + Service: "eks.amazonaws.com", + }, + }], }); const cluster_service_role = new aws.iam.Role("cluster-service-role", { - assumeRolePolicy: cluster_assumeRole_policy, - name: "DeepThinker", - … + assumeRolePolicy: cluster_assumeRole_policy, + managedPolicyArns: [ + // alternatively, use RolePolicyAttachments + "arn:aws:iam::aws:policy/AmazonEKSClusterPolicy", + ], + name: "DeepThinker", + … }); ``` @@ -195,15 +205,15 @@ Some create Cloudformation stacks in the process. ```ts const cluster = new aws.eks.Cluster("cluster", { - name: "DeepThought", - roleArn: cluster_service_role.arn, - vpcConfig: { - subnetIds: [ - "subnet-11112222333344445", - "subnet-66667777888899990", - ], - }, - … + name: "DeepThought", + roleArn: cluster_service_role.arn, + vpcConfig: { + subnetIds: [ + "subnet-11112222333344445", + "subnet-66667777888899990", + ], + }, + … }); ``` @@ -261,16 +271,16 @@ Procedure: ```json { - "Version": "2012-10-17", - "Statement": [ - { - "Effect": "Allow", - "Action": "sts:AssumeRole", - "Principal": { - "Service": "ec2.amazonaws.com" - } - } - ] + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": "sts:AssumeRole", + "Principal": { + "Service": "ec2.amazonaws.com" + } + } + ] } ``` @@ -296,26 +306,26 @@ Procedure: ```ts const nodes_assumeRole_policy = JSON.stringify({ - Version: "2012-10-17", - Statement: [{ - Effect: "Allow", - Action: "sts:AssumeRole", - Principal: { - Service: "ec2.amazonaws.com", - }, - }], + Version: "2012-10-17", + Statement: [{ + Effect: "Allow", + Action: "sts:AssumeRole", + Principal: { + Service: "ec2.amazonaws.com", + }, + }], }); const node_service_role = new aws.iam.Role("node-service-role", { - assumeRolePolicy: nodes_assumeRole_policy, - managedPolicyArns: [ - // alternatively, use RolePolicyAttachments - "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly", - "arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy", - "arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy", - ], - name: "DeepThinkerNode", - … + assumeRolePolicy: nodes_assumeRole_policy, + managedPolicyArns: [ + // alternatively, use RolePolicyAttachments + "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly", + "arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy", + "arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy", + ], + name: "DeepThinkerNode", + … }); ``` @@ -343,16 +353,16 @@ Procedure: ```ts const nodeGroup_alpha = new aws.eks.NodeGroup("nodeGroup-alpha", { - nodeGroupName: "nodeGroup-alpha", - clusterName: cluster.name, - nodeRoleArn: node_service_role.arn, - scalingConfig: { - minSize: 1, - maxSize: 3, - desiredSize: 1, - }, - subnetIds: cluster.vpcConfig.subnetIds, - … + nodeGroupName: "nodeGroup-alpha", + clusterName: cluster.name, + nodeRoleArn: node_service_role.arn, + scalingConfig: { + minSize: 1, + maxSize: 3, + desiredSize: 1, + }, + subnetIds: cluster.vpcConfig.subnetIds, + … }); ``` @@ -384,21 +394,21 @@ Procedure: ```json { - "Version": "2012-10-17", - "Statement": [ - { - "Effect": "Allow", - "Action": "sts:AssumeRole", - "Principal": { - "Service": "eks-fargate-pods.amazonaws.com" - }, - "Condition": { - "ArnLike": { - "aws:SourceArn": "arn:aws:eks:region-code:111122223333:fargateprofile/my-cluster/*" - } - } - } - ] + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": "sts:AssumeRole", + "Principal": { + "Service": "eks-fargate-pods.amazonaws.com" + }, + "Condition": { + "ArnLike": { + "aws:SourceArn": "arn:aws:eks:region-code:111122223333:fargateprofile/my-cluster/*" + } + } + } + ] } ``` @@ -418,29 +428,29 @@ Procedure: ```ts const fargate_assumeRole_policy = JSON.stringify({ - Version: "2012-10-17", - Statement: [{ - Effect: "Allow", - Action: "sts:AssumeRole", - Principal: { - Service: "eks-fargate-pods.amazonaws.com", - }, - Condition: { - ArnLike: { - "aws:SourceArn": `arn:aws:eks:${region}:${account}:fargateprofile/${cluster.name}/*` - } - }, - }], + Version: "2012-10-17", + Statement: [{ + Effect: "Allow", + Action: "sts:AssumeRole", + Principal: { + Service: "eks-fargate-pods.amazonaws.com", + }, + Condition: { + ArnLike: { + "aws:SourceArn": `arn:aws:eks:${region}:${account}:fargateprofile/${cluster.name}/*` + } + }, + }], }); const fargate_service_role = new aws.iam.Role("fargate-service-role", { - assumeRolePolicy: fargate_assumeRole_policy, - managedPolicyArns: [ - // alternatively, use RolePolicyAttachments - "arn:aws:iam::aws:policy/AmazonEKSFargatePodExecutionRolePolicy", - ], - name: "DeepThinkerFargate", - … + assumeRolePolicy: fargate_assumeRole_policy, + managedPolicyArns: [ + // alternatively, use RolePolicyAttachments + "arn:aws:iam::aws:policy/AmazonEKSFargatePodExecutionRolePolicy", + ], + name: "DeepThinkerFargate", + … }); ``` @@ -468,20 +478,33 @@ Procedure: ```ts const fargateProfile_alpha = new aws.eks.FargateProfile("fargateProfile-alpha", { - fargateProfileName: "fargateProfile-alpha", - clusterName: cluster.name, - podExecutionRoleArn: fargate_service_role.arn, - selectors: [ - { namespace: "monitoring" }, - { namespace: "default" }, - ], - subnetIds: cluster.vpcConfig.subnetIds, - … + fargateProfileName: "fargateProfile-alpha", + clusterName: cluster.name, + podExecutionRoleArn: fargate_service_role.arn, + selectors: [ + { namespace: "monitoring" }, + { namespace: "default" }, + ], + subnetIds: cluster.vpcConfig.subnetIds, + … }); ``` +## Access management + +By default, the IAM principal creating the cluster is the only one able to make calls to the cluster's API server.
+To let other IAM principals have access to the cluster, one needs to add them to it. + +See the following to allow others: + +- [Required permissions to view EKS resources]. +- [Enabling IAM principal access to your cluster]. +- [Allowing IAM roles or users access to Kubernetes objects on your Amazon EKS cluster]. +- [How do I resolve the error "You must be logged in to the server (Unauthorized)" when I connect to the Amazon EKS API server?] +- https://docs.aws.amazon.com/eks/latest/userguide/access-entries.html + ## Secrets encryption through KMS See [Enabling secret encryption on an existing cluster]. @@ -510,11 +533,11 @@ TL;DR: ```ts const cluster = new aws.eks.Cluster("cluster", { - encryptionConfig: { - provider: { keyArn: `arn:aws:kms:${region}:${account}:key/${key_id}` }, - resources: [ "secrets" ], - }, - … + encryptionConfig: { + provider: { keyArn: `arn:aws:kms:${region}:${account}:key/${key_id}` }, + resources: [ "secrets" ], + }, + … }); ``` @@ -524,12 +547,41 @@ TL;DR: See [Amazon EKS troubleshooting]. +### Identify common issues + +Use the [AWSSupport-TroubleshootEKSWorkerNode](https://docs.aws.amazon.com/systems-manager-automation-runbooks/latest/userguide/automation-awssupport-troubleshooteksworkernode.html) runbook. + +> For the automation to work, worker nodes **must** have permission to access Systems Manager and have Systems Manager running.
+> Grant this permission by attaching the [`AmazonSSMManagedInstanceCore`](https://docs.aws.amazon.com/systems-manager/latest/userguide/setup-instance-profile.html#instance-profile-policies-overview) policy to the node role. + +Procedure: + +1. Open the [runbook](https://console.aws.amazon.com/systems-manager/automation/execute/AWSSupport-TroubleshootEKSWorkerNode). +1. Check that the AWS Region in the Management Console is set to the same Region as your cluster. +1. In the Input parameters section, specify the name of the cluster and the EC2 instance ID. +1. [optional] In the `AutomationAssumeRole` field, specify a role to allow Systems Manager to perform actions.
+ If left empty, the permissions of your current IAM entity are used to perform the actions in the runbook. +1. Choose `Execute`. +1. Check the `Outputs` section. + +### The worker nodes fail to join the cluster. + +Error message example: + +> NodeCreationFailure: Instances failed to join the kubernetes cluster. + +Debug: see [Identify common issues]. + ## Further readings - [Kubernetes] - [EKS Workshop] - [Pulumi] - [Terraform] +- [How can I get my worker nodes to join my Amazon EKS cluster?] +- [Enabling IAM principal access to your cluster] +- [Allowing IAM roles or users access to Kubernetes objects on your Amazon EKS cluster] +- [How do I resolve the error "You must be logged in to the server (Unauthorized)" when I connect to the Amazon EKS API server?] ### Sources @@ -547,6 +599,7 @@ See [Amazon EKS troubleshooting]. - [Enabling secret encryption on an existing cluster] - [Choosing an Amazon EC2 instance type] - [Private cluster requirements] +- [De-mystifying cluster networking for Amazon EKS worker nodes] [create worker nodes]: #create-worker-nodes +[identify common issues]: #identify-common-issues [requirements]: #requirements [secrets encryption through kms]: #secrets-encryption-through-kms @@ -564,6 +618,7 @@ See [Amazon EKS troubleshooting]. +[allowing iam roles or users access to kubernetes objects on your amazon eks cluster]: https://docs.aws.amazon.com/eks/latest/userguide/access-entries.html [amazon eks add-ons]: https://docs.aws.amazon.com/eks/latest/userguide/eks-add-ons.html [amazon eks cluster iam role]: https://docs.aws.amazon.com/eks/latest/userguide/service_IAM_role.html [amazon eks clusters]: https://docs.aws.amazon.com/eks/latest/userguide/clusters.html @@ -576,12 +631,17 @@ See [Amazon EKS troubleshooting]. [aws eks create-fargate-profile]: https://docs.aws.amazon.com/cli/latest/reference/eks/create-fargate-profile.html [aws eks create-nodegroup]: https://docs.aws.amazon.com/cli/latest/reference/eks/create-nodegroup.html [choosing an amazon ec2 instance type]: https://docs.aws.amazon.com/eks/latest/userguide/choosing-instance-type.html +[de-mystifying cluster networking for amazon eks worker nodes]: https://aws.amazon.com/blogs/containers/de-mystifying-cluster-networking-for-amazon-eks-worker-nodes/ [eks workshop]: https://www.eksworkshop.com/ +[enabling iam principal access to your cluster]: https://docs.aws.amazon.com/eks/latest/userguide/add-user-role.html [enabling secret encryption on an existing cluster]: https://docs.aws.amazon.com/eks/latest/userguide/enable-kms.html [fargate]: https://docs.aws.amazon.com/eks/latest/userguide/fargate.html [getting started with amazon eks - aws management console and aws cli]: https://docs.aws.amazon.com/eks/latest/userguide/getting-started-console.html +[how can i get my worker nodes to join my amazon eks cluster?]: https://repost.aws/knowledge-center/eks-worker-nodes-cluster +[how do i resolve the error "you must be logged in to the server (unauthorized)" when i connect to the amazon eks api server?]: https://repost.aws/knowledge-center/eks-api-server-unauthorized-error [managed node groups]: https://docs.aws.amazon.com/eks/latest/userguide/managed-node-groups.html [private cluster requirements]: https://docs.aws.amazon.com/eks/latest/userguide/private-clusters.html +[required permissions to view eks resources]: https://docs.aws.amazon.com/eks/latest/userguide/view-kubernetes-resources.html#view-kubernetes-resources-permissions [self-managed nodes]: https://docs.aws.amazon.com/eks/latest/userguide/worker.html [service-linked role permissions for amazon eks]: https://docs.aws.amazon.com/eks/latest/userguide/using-service-linked-roles-eks.html#service-linked-role-permissions-eks [using service-linked roles for amazon eks]: https://docs.aws.amazon.com/eks/latest/userguide/using-service-linked-roles.html diff --git a/knowledge base/pulumi.md b/knowledge base/pulumi.md index e7a8993..cf5b6c9 100644 --- a/knowledge base/pulumi.md +++ b/knowledge base/pulumi.md @@ -175,14 +175,31 @@ pulumi state unprotect 'resourceUrn' Data resources ```ts -const cluster_role = aws.iam.getRoleOutput({ - name: "AWSServiceRoleForAmazonEKS", -}); - +const cluster_role = aws.iam.getRoleOutput({ name: "AWSServiceRoleForAmazonEKS" }); const cluster = new aws.eks.Cluster("cluster", { roleArn: cluster_role.arn, … }); + +// If used in JSON documents, the function needs to cover the whole document. +const encryptionKey = aws.kms.getKeyOutput({ + keyId: "00001111-2222-3333-4444-555566667777", +}); +const clusterServiceRole = new aws.iam.Role("clusterServiceRole", { + inlinePolicies: [{ + policy: encryptionKey.arn.apply(arn => JSON.stringify({ + Version: "2012-10-17", + Statement: [{ + Effect: "Allow", + Action: [ + "kms:CreateGrant", + "kms:DescribeKey", + ], + Resource: arn, + }], + })), + }] +}); ``` @@ -259,6 +276,42 @@ yq -iy '. += {"backend": {"url": "s3://myBucket/prefix"}}' 'Pulumi.yaml' # TODO ``` +```ts +// Merge objects. +tags_base = { + ManagedBy: "Pulumi", + Prod: false, +}; +const fargateProfile = new aws.eks.FargateProfile("fargateProfile", { + tags: { + ...tags_base, + ...{ + Description: "Fargate profile for EKS cluster EksTest", + EksComponent: "Fargate profile", + Name: "eksTest-fargateProfile", + }, + }, + … +}); + +// Default tags with explicit provider. +const provider = new aws.Provider("provider", { + defaultTags: { + tags: { + ManagedBy: "Pulumi", + Owner: "user@company.com", + Team: "Infra", + }, + }, +}); +const fargateProfile = new aws.eks.FargateProfile("fargateProfile", { + … +}, { + provider: provider, + … +}); +``` +
@@ -368,6 +421,7 @@ const cluster = new aws.eks.Cluster("cluster", { - [Documentation] - [State] +- [Assigning tags by default on AWS with Pulumi] +[assigning tags by default on aws with pulumi]: https://blog.scottlowe.org/2023/09/11/assigning-tags-by-default-on-aws-with-pulumi/ diff --git a/knowledge base/template.md b/knowledge base/template.md index c6608eb..e2f5f6b 100644 --- a/knowledge base/template.md +++ b/knowledge base/template.md @@ -13,7 +13,7 @@ Intro