# DevOps Training (Create VPC and subnet, NAT Gateway, Internet Gateway, EKS Cluster A-Z using Terraform) ###### tags: `Devops` `AWS` `Terraform` I am using VSCode to writing the Code you can use as your choice. Create a Folder with name of Terraform where you can write your code. Open that folder in VS Code and Create a file **provide.tf** ```java= ![](https://i.imgur.com/fmPFALb.png) ``` ## Amazon EKS polices Githubs https://github.com/SummitRoute/aws_managed_policies/tree/master/policies ## Github link I am follwoing: https://github.com/antonputra/tutorials/tree/main/lessons/038/terraform ### Reference to understand Virtual route inside VPC between subnets in different availability zone in same region: (Khassi Router). ![](https://i.imgur.com/QNYVtbP.png) **The Architecture we are implementing:** ![](https://i.imgur.com/wrduNbu.png) ### Open the provider.tf and Write the code. 1: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc 2: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/subnet ```javascript= provider "aws" { profile = "Terraform" region = "ap-northeast-2" } # VPC Code resource "aws_vpc" "main" { cidr_block = "192.168.0.0/16" instance_tenancy = "default" tags = { Name = "main" Location = "Seoul" } } # Subnet under the existing VPC resource "aws_subnet" "subnet1" { vpc_id = aws_vpc.main.id cidr_block = "192.168.1.0/24" tags = { Name = "subnet1" } } ``` ![](https://i.imgur.com/Xy0sNpq.png) ### Next Step to Go to Terminal and Folder location and see the files and run: ```javascript= # terraform fmt ``` This above command can help to check the format of the file or code: ![](https://i.imgur.com/Z5E4gR6.png) ### Initializing the Terraform ```javascript= # terraform init ``` ![](https://i.imgur.com/vPH168V.png) ### Check the plan of your VPC This will give you the detail about your VPC. If the details is ok then we can create VPC on AWS. ```javascript= # terraform plan ``` ![](https://i.imgur.com/dHxLQqF.png) ### Apply the Terraform Script to create resources on AWS ```javascript= # terraform apply ``` ![](https://i.imgur.com/XOVhxSK.png) ### Now you can check on AWS you vpc and subnet is created or not: #### VPC ![](https://i.imgur.com/eBdCkD6.png) #### Subnet ![](https://i.imgur.com/C53yPkK.png) ## Adding the Internet Gateway resource: add another resource in the provider.tf file: ```javascript= # resource "aws_internet_gateway" "gw" { vpc_id = aws_vpc.main.id tags = { Name = "main" } } ``` ![](https://i.imgur.com/othA834.png) ### Again apply Terraform and see the output of cmdline. ![](https://i.imgur.com/5jmIToV.png) ### Check on the AWS console your Internet-Gateway is created. make sure everything under same vpc: ![](https://i.imgur.com/Xqqtjra.png) ### Creating Subnet 1st Availbility-Zone 1 Public and 1 Private subnet, 2nd availbility zone 1 Public and 1 Private subnet ```javascript= # Subnet under the existing VPC public 1 resource "aws_subnet" "public_1" { vpc_id = aws_vpc.main.id cidr_block = "192.168.0.0/18" availability_zone = "ap-northeast-2a" map_public_ip_on_launch = true tags = { Name = "public_1" "kubernetes.io/cluster/eks" = "shared" "kubenretes.io/role/elb" = 1 } } # Subnet under the existing VPC private 1 resource "aws_subnet" "private_1" { vpc_id = aws_vpc.main.id cidr_block = "192.168.128.0/18" availability_zone = "ap-northeast-2a" tags = { Name = "private_1" "kubernetes.io/cluster/eks" = "shared" "kubenretes.io/role/internal-elb" = 1 } } # Subnet under the existing VPC public 2 resource "aws_subnet" "public_2" { vpc_id = aws_vpc.main.id cidr_block = "192.168.64.0/18" availability_zone = "ap-northeast-2b" map_public_ip_on_launch = true tags = { Name = "public_2" "kubernetes.io/cluster/eks" = "shared" "kubenretes.io/role/elb" = 1 } } # Subnet under the existing VPC private 2 resource "aws_subnet" "private_2" { vpc_id = aws_vpc.main.id cidr_block = "192.168.192.0/18" availability_zone = "ap-northeast-2b" tags = { Name = "private_2" "kubernetes.io/cluster/eks" = "shared" "kubenretes.io/role/internal-elb" = 1 } } ``` ![](https://i.imgur.com/NOycOHr.png) ### Terraform output ```javascript= # terraform fmt # terraform init # terraform plan # terraform apply ``` ![](https://i.imgur.com/VzBUTjH.png) ![](https://i.imgur.com/7ACK5eS.png) ### AWS Console output ![](https://i.imgur.com/ZrMuHXo.png) ### Create eip ```javascript= #Create Elastic IP Addresses NAT1 resource "aws_eip" "nat1" { depends_on = [aws_internet_gateway.igw] } #Create Elastic IP Addresses NAT2 resource "aws_eip" "nat2" { depends_on = [aws_internet_gateway.igw] } ``` ![](https://i.imgur.com/HboygXz.png) ### Create NAT Gateway ```javascript= #Create NAT Gateway 1 resource "aws_nat_gateway" "gw1" { allocation_id = aws_eip.nat1.id subnet_id = aws_subnet.public_1.id tags = { Name = "NAT 1" } } #Create NAT Gateway 2 resource "aws_nat_gateway" "gw2" { allocation_id = aws_eip.nat2.id subnet_id = aws_subnet.public_2.id tags = { Name = "NAT 2" } } ``` ![](https://i.imgur.com/xiYPaA0.png) ### Destory and Run all again: The output is: **Destroy:** ![](https://i.imgur.com/a7RkwPG.png) **Apply Again:** ![](https://i.imgur.com/m2PbleD.png) **The complete output is:** ```javascript= PS C:\Users\sohail.anjum.AEWIN\Desktop\Terraform> terraform apply An execution plan has been generated and is shown below. Resource actions are indicated with the following symbols: + create Terraform will perform the following actions: # aws_eip.nat1 will be created + resource "aws_eip" "nat1" { + allocation_id = (known after apply) + association_id = (known after apply) + carrier_ip = (known after apply) + customer_owned_ip = (known after apply) + domain = (known after apply) + id = (known after apply) + instance = (known after apply) + network_border_group = (known after apply) + network_interface = (known after apply) + private_dns = (known after apply) + private_ip = (known after apply) + public_dns = (known after apply) + public_ip = (known after apply) + public_ipv4_pool = (known after apply) + tags_all = (known after apply) + vpc = (known after apply) } # aws_eip.nat2 will be created + resource "aws_eip" "nat2" { + allocation_id = (known after apply) + association_id = (known after apply) + carrier_ip = (known after apply) + customer_owned_ip = (known after apply) + domain = (known after apply) + id = (known after apply) + instance = (known after apply) + network_border_group = (known after apply) + network_interface = (known after apply) + private_dns = (known after apply) + private_ip = (known after apply) + public_dns = (known after apply) + public_ip = (known after apply) + public_ipv4_pool = (known after apply) + tags_all = (known after apply) + vpc = (known after apply) } # aws_internet_gateway.main will be created + resource "aws_internet_gateway" "main" { + arn = (known after apply) + id = (known after apply) + owner_id = (known after apply) + tags = { + "Name" = "main" } + tags_all = { + "Name" = "main" } + vpc_id = (known after apply) } # aws_nat_gateway.gw1 will be created + resource "aws_nat_gateway" "gw1" { + allocation_id = (known after apply) + connectivity_type = "public" + id = (known after apply) + network_interface_id = (known after apply) + private_ip = (known after apply) + public_ip = (known after apply) + subnet_id = (known after apply) + tags = { + "Name" = "NAT 1" } + tags_all = { + "Name" = "NAT 1" } } # aws_nat_gateway.gw2 will be created + resource "aws_nat_gateway" "gw2" { + allocation_id = (known after apply) + connectivity_type = "public" + id = (known after apply) + network_interface_id = (known after apply) + private_ip = (known after apply) + public_ip = (known after apply) + subnet_id = (known after apply) + tags = { + "Name" = "NAT 2" } + tags_all = { + "Name" = "NAT 2" } } # aws_subnet.private_1 will be created + resource "aws_subnet" "private_1" { + arn = (known after apply) + assign_ipv6_address_on_creation = false + availability_zone = "ap-northeast-2a" + availability_zone_id = (known after apply) + cidr_block = "192.168.128.0/18" + id = (known after apply) + ipv6_cidr_block_association_id = (known after apply) + map_public_ip_on_launch = false + owner_id = (known after apply) + tags = { + "Name" = "private_1" + "kubenretes.io/role/internal-elb" = "1" + "kubernetes.io/cluster/eks" = "shared" } + tags_all = { + "Name" = "private_1" + "kubenretes.io/role/internal-elb" = "1" + "kubernetes.io/cluster/eks" = "shared" } + vpc_id = (known after apply) } # aws_subnet.private_2 will be created + resource "aws_subnet" "private_2" { + arn = (known after apply) + assign_ipv6_address_on_creation = false + availability_zone = "ap-northeast-2b" + availability_zone_id = (known after apply) + cidr_block = "192.168.192.0/18" + id = (known after apply) + ipv6_cidr_block_association_id = (known after apply) + map_public_ip_on_launch = false + owner_id = (known after apply) + tags = { + "Name" = "private_2" + "kubenretes.io/role/internal-elb" = "1" + "kubernetes.io/cluster/eks" = "shared" } + tags_all = { + "Name" = "private_2" + "kubenretes.io/role/internal-elb" = "1" + "kubernetes.io/cluster/eks" = "shared" } + vpc_id = (known after apply) } # aws_subnet.public_1 will be created + resource "aws_subnet" "public_1" { + arn = (known after apply) + assign_ipv6_address_on_creation = false + availability_zone = "ap-northeast-2a" + availability_zone_id = (known after apply) + cidr_block = "192.168.0.0/18" + id = (known after apply) + ipv6_cidr_block_association_id = (known after apply) + map_public_ip_on_launch = true + owner_id = (known after apply) + tags = { + "Name" = "public_1" + "kubenretes.io/role/elb" = "1" + "kubernetes.io/cluster/eks" = "shared" } + tags_all = { + "Name" = "public_1" + "kubenretes.io/role/elb" = "1" + "kubernetes.io/cluster/eks" = "shared" } + vpc_id = (known after apply) } # aws_subnet.public_2 will be created + resource "aws_subnet" "public_2" { + arn = (known after apply) + assign_ipv6_address_on_creation = false + availability_zone = "ap-northeast-2b" + availability_zone_id = (known after apply) + cidr_block = "192.168.64.0/18" + id = (known after apply) + ipv6_cidr_block_association_id = (known after apply) + map_public_ip_on_launch = true + owner_id = (known after apply) + tags = { + "Name" = "public_2" + "kubenretes.io/role/elb" = "1" + "kubernetes.io/cluster/eks" = "shared" } + tags_all = { + "Name" = "public_2" + "kubenretes.io/role/elb" = "1" + "kubernetes.io/cluster/eks" = "shared" } + vpc_id = (known after apply) } # aws_vpc.main will be created + resource "aws_vpc" "main" { + arn = (known after apply) + cidr_block = "192.168.0.0/16" + default_network_acl_id = (known after apply) + default_route_table_id = (known after apply) + default_security_group_id = (known after apply) + dhcp_options_id = (known after apply) + enable_classiclink = (known after apply) + enable_classiclink_dns_support = (known after apply) + enable_dns_hostnames = true + enable_dns_support = true + id = (known after apply) + instance_tenancy = "default" + ipv6_association_id = (known after apply) + ipv6_cidr_block = (known after apply) + main_route_table_id = (known after apply) + owner_id = (known after apply) + tags = { + "Location" = "Seoul" + "Name" = "main" } + tags_all = { + "Location" = "Seoul" + "Name" = "main" } } Plan: 10 to add, 0 to change, 0 to destroy. Do you want to perform these actions? Terraform will perform the actions described above. Only 'yes' will be accepted to approve. Enter a value: yes aws_vpc.main: Creating... aws_vpc.main: Still creating... [10s elapsed] aws_vpc.main: Creation complete after 15s [id=vpc-051baee0f6da3a812] aws_internet_gateway.main: Creating... aws_subnet.public_2: Creating... aws_subnet.public_1: Creating... aws_subnet.private_2: Creating... aws_subnet.private_1: Creating... aws_subnet.private_2: Creation complete after 2s [id=subnet-04441ddd00cb87d5c] aws_subnet.private_1: Creation complete after 2s [id=subnet-09e437eac9f5f3196] aws_internet_gateway.main: Creation complete after 2s [id=igw-05394420f5f890d61] aws_eip.nat1: Creating... aws_eip.nat2: Creating... aws_eip.nat2: Creation complete after 1s [id=eipalloc-0333e309649e492e8] aws_eip.nat1: Creation complete after 1s [id=eipalloc-0b33187c89bfcac96] aws_subnet.public_2: Still creating... [10s elapsed] aws_subnet.public_1: Still creating... [10s elapsed] aws_subnet.public_2: Creation complete after 12s [id=subnet-039bd052a1fb6786a] aws_nat_gateway.gw2: Creating... aws_subnet.public_1: Creation complete after 12s [id=subnet-0ed6c1efa6a8d14b1] aws_nat_gateway.gw1: Creating... aws_nat_gateway.gw2: Still creating... [10s elapsed] aws_nat_gateway.gw1: Still creating... [10s elapsed] aws_nat_gateway.gw2: Still creating... [20s elapsed] aws_nat_gateway.gw1: Still creating... [20s elapsed] aws_nat_gateway.gw2: Still creating... [30s elapsed] aws_nat_gateway.gw1: Still creating... [30s elapsed] aws_nat_gateway.gw2: Still creating... [40s elapsed] aws_nat_gateway.gw1: Still creating... [40s elapsed] aws_nat_gateway.gw2: Still creating... [50s elapsed] aws_nat_gateway.gw1: Still creating... [50s elapsed] aws_nat_gateway.gw2: Still creating... [1m0s elapsed] aws_nat_gateway.gw1: Still creating... [1m0s elapsed] aws_nat_gateway.gw2: Still creating... [1m10s elapsed] aws_nat_gateway.gw1: Still creating... [1m10s elapsed] aws_nat_gateway.gw2: Still creating... [1m20s elapsed] aws_nat_gateway.gw1: Still creating... [1m20s elapsed] aws_nat_gateway.gw2: Still creating... [1m30s elapsed] aws_nat_gateway.gw1: Still creating... [1m30s elapsed] aws_nat_gateway.gw1: Creation complete after 1m40s [id=nat-076654fc2af36e8a9] aws_nat_gateway.gw2: Still creating... [1m40s elapsed] aws_nat_gateway.gw2: Creation complete after 1m50s [id=nat-0903b427e7c022b8c] Apply complete! Resources: 10 added, 0 changed, 0 destroyed. ``` ### Create the Routing Table resouce: ```javascript= resource "aws_route_table" "public" { vpc_id = aws_vpc.main.id route { cidr_block = "0.0.0.0/0" gateway_id = aws_internet_gateway.main.id } tags = { Name = "public" } } resource "aws_route_table" "private1" { vpc_id = aws_vpc.main.id route { cidr_block = "0.0.0.0/0" gateway_id = aws_nat_gateway.gw1.id } tags = { Name = "private1" } } resource "aws_route_table" "private2" { vpc_id = aws_vpc.main.id route { cidr_block = "0.0.0.0/0" gateway_id = aws_nat_gateway.gw2.id } tags = { Name = "private2" } } ``` ![](https://i.imgur.com/g9c4wSl.png) ### Create the Routing table association: ```javascript= resource "aws_route_table_association" "public1" { subnet_id = aws_subnet.public_1.id route_table_id = aws_route_table.public.id } resource "aws_route_table_association" "public2" { subnet_id = aws_subnet.public_2.id route_table_id = aws_route_table.public.id } resource "aws_route_table_association" "private1" { subnet_id = aws_subnet.private_1.id route_table_id = aws_route_table.private1.id } resource "aws_route_table_association" "private2" { subnet_id = aws_subnet.private_2.id route_table_id = aws_route_table.private1.id } ``` ![](https://i.imgur.com/PVEL2Ki.png) ### Routing table creation using Terraform ![](https://i.imgur.com/58E4Cq3.png) ### Routing Table on AWS ![](https://i.imgur.com/K81D9aM.png) ## EKS Cluster Creation ```javascript= resource "aws_iam_role" "eks_cluster" { name = "eks-cluster" assume_role_policy = <<POLICY { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "eks.amazonaws.com" }, "Action": "sts:AssumeRole" } ] } POLICY } resource "aws_iam_role_policy_attachment" "amazon_eks_cluster_policy" { policy_arn = "arn:aws:iam::aws:policy/AmazonEKSClusterPolicy" role = aws_iam_role.eks_cluster.name } # Resource: aws_eks_cluster # https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_cluster resource "aws_eks_cluster" "eks" { # Name of the cluster. name = "eks" # The Amazon Resource Name (ARN) of the IAM role that provides permissions for # the Kubernetes control plane to make calls to AWS API operations on your behalf role_arn = aws_iam_role.eks_cluster.arn # Desired Kubernetes master version version = "1.18" vpc_config { # Indicates whether or not the Amazon EKS private API server endpoint is enabled endpoint_private_access = false # Indicates whether or not the Amazon EKS public API server endpoint is enabled endpoint_public_access = true # Must be in at least two different availability zones subnet_ids = [ aws_subnet.public_1.id, aws_subnet.public_2.id, aws_subnet.private_1.id, aws_subnet.private_2.id ] } # Ensure that IAM Role permissions are created before and deleted after EKS Cluster handling. # Otherwise, EKS will not be able to properly delete EKS managed EC2 infrastructure such as Security Groups. depends_on = [ aws_iam_role_policy_attachment.amazon_eks_cluster_policy ] } ``` ![](https://i.imgur.com/uUyS8HT.png) ## EKS Cluster Node Creation: ```javascript= # Resource: aws_iam_role # https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role # Create IAM role for EKS Node Group resource "aws_iam_role" "nodes_general" { # The name of the role name = "eks-node-group-general" # The policy that grants an entity permission to assume the role. assume_role_policy = <<POLICY { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "ec2.amazonaws.com" }, "Action": "sts:AssumeRole" } ] } POLICY } # Resource: aws_iam_role_policy_attachment # https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment resource "aws_iam_role_policy_attachment" "amazon_eks_worker_node_policy_general" { # The ARN of the policy you want to apply. # https://github.com/SummitRoute/aws_managed_policies/blob/master/policies/AmazonEKSWorkerNodePolicy policy_arn = "arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy" # The role the policy should be applied to role = aws_iam_role.nodes_general.name } resource "aws_iam_role_policy_attachment" "amazon_eks_cni_policy_general" { # The ARN of the policy you want to apply. # https://github.com/SummitRoute/aws_managed_policies/blob/master/policies/AmazonEKS_CNI_Policy policy_arn = "arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy" # The role the policy should be applied to role = aws_iam_role.nodes_general.name } resource "aws_iam_role_policy_attachment" "amazon_ec2_container_registry_read_only" { # The ARN of the policy you want to apply. # https://github.com/SummitRoute/aws_managed_policies/blob/master/policies/AmazonEC2ContainerRegistryReadOnly policy_arn = "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly" # The role the policy should be applied to role = aws_iam_role.nodes_general.name } # Resource: aws_eks_node_group # https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_node_group resource "aws_eks_node_group" "nodes_general" { # Name of the EKS Cluster. cluster_name = aws_eks_cluster.eks.name # Name of the EKS Node Group. node_group_name = "nodes-general" # Amazon Resource Name (ARN) of the IAM Role that provides permissions for the EKS Node Group. node_role_arn = aws_iam_role.nodes_general.arn # Identifiers of EC2 Subnets to associate with the EKS Node Group. # These subnets must have the following resource tag: kubernetes.io/cluster/CLUSTER_NAME # (where CLUSTER_NAME is replaced with the name of the EKS Cluster). subnet_ids = [ aws_subnet.private_1.id, aws_subnet.private_2.id ] # Configuration block with scaling settings scaling_config { # Desired number of worker nodes. desired_size = 1 # Maximum number of worker nodes. max_size = 1 # Minimum number of worker nodes. min_size = 1 } # Type of Amazon Machine Image (AMI) associated with the EKS Node Group. # Valid values: AL2_x86_64, AL2_x86_64_GPU, AL2_ARM_64 ami_type = "AL2_x86_64" # Type of capacity associated with the EKS Node Group. # Valid values: ON_DEMAND, SPOT capacity_type = "ON_DEMAND" # Disk size in GiB for worker nodes disk_size = 20 # Force version update if existing pods are unable to be drained due to a pod disruption budget issue. force_update_version = false # List of instance types associated with the EKS Node Group instance_types = ["t3.small"] labels = { role = "nodes-general" } # Kubernetes version version = "1.18" # Ensure that IAM Role permissions are created before and deleted after EKS Node Group handling. # Otherwise, EKS will not be able to properly delete EC2 Instances and Elastic Network Interfaces. depends_on = [ aws_iam_role_policy_attachment.amazon_eks_worker_node_policy_general, aws_iam_role_policy_attachment.amazon_eks_cni_policy_general, aws_iam_role_policy_attachment.amazon_ec2_container_registry_read_only, ] } ``` ![](https://i.imgur.com/2C7EOnF.png) ![](https://i.imgur.com/801Y666.png) ## Creation EKS Clsuter and Nodes using Terraform ![](https://i.imgur.com/hPFVIDc.png) ![](https://i.imgur.com/AzdRrg1.png) ## AWS Console output creating K8s Cluster ![](https://i.imgur.com/RpDBqRp.png) ## Connect kubernetes cluster: ### Check the users we have ![](https://i.imgur.com/0ssH2r7.png) ### Allow Terraform user to access k8s cluster ![](https://i.imgur.com/2bWrpVz.png) ### Install the Kubectl #### please follow the version: https://docs.aws.amazon.com/eks/latest/userguide/install-kubectl.html #### Open the PowerShell ```javascript= # curl -o kubectl.exe.sha256 https://amazon-eks.s3.us-west-2.amazonaws.com/1.18.9/2020-11-02/bin/windows/amd64/kubectl.exe.sha256 ``` #### Create folder: ![](https://i.imgur.com/picGSoW.png) #### Copy the downloaded file in created foler bin: ![](https://i.imgur.com/bfxqc5w.png) #### Add the Environment variables: ![](https://i.imgur.com/tLpZfOI.png) ## Quit the Powershell and open again and check kubectl version and get svc: ![](https://i.imgur.com/p9ECHES.png) ## Create the Nginx Service: ```javascript= --- apiVersion: apps/v1 kind: Deployment metadata: name: nginx labels: app: nginx spec: replicas: 1 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.14.2 ports: - containerPort: 80 --- apiVersion: v1 kind: Service metadata: name: internal-nginx-service annotations: service.beta.kubernetes.io/aws-load-balancer-type: nlb service.beta.kubernetes.io/aws-load-balancer-cross-zone-load-balancing-enabled: 'true' service.beta.kubernetes.io/aws-load-balancer-internal: 0.0.0.0/0 spec: selector: app: nginx type: LoadBalancer ports: - protocol: TCP port: 80 --- apiVersion: v1 kind: Service metadata: name: external-nginx-service annotations: service.beta.kubernetes.io/aws-load-balancer-type: nlb service.beta.kubernetes.io/aws-load-balancer-cross-zone-load-balancing-enabled: 'true' spec: selector: app: nginx type: LoadBalancer ports: - protocol: TCP port: 80 ``` ![](https://i.imgur.com/UVahVzR.png) ### Apply the nginx app.yaml ![](https://i.imgur.com/Tzzyt7v.png) ### Console output for Nginx ![](https://i.imgur.com/cMHpQRB.png) ### Open the Nginx on Browser: ![](https://i.imgur.com/oQmUJHl.png) # Next: Note ( EKS Doesn't support IAM Role Users so we have to create a user.) ## update the kube-config ```javascript= # aws eks --region ap-northeast-2 update-kubeconfig --name eks --profile Terraform ``` ![](https://i.imgur.com/vFNzxsx.png) ## Create Cluster role and Role Binding: ```javascript= # This role will allow users to get list and watch --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: reader rules: - apiGroups: ["*"] resources: ["deployments", "configmaps", "pods", "secrets", "services"] verbs: ["get", "list", "watch"] --- # Bind the above cluster role apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: reader subjects: - kind: Group name: reader apiGroup: rbac.authorization.k8s.io roleRef: kind: ClusterRole name: reader apiGroup: rbac.authorization.k8s.io ``` ![](https://i.imgur.com/QImXUzd.png) ## Apply the yamal file for Role Binding. ![](https://i.imgur.com/Xtl1607.png) ## Create AWS Policy to allow users to access eks cluster -> IAM -> Polices -> Create Polices: ![](https://i.imgur.com/r9UuAJW.png) ## Create the Policy and Select Json ![](https://i.imgur.com/IIcMri0.png) ## Update the Json Code with: ```javascript= { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "eks:DescribeNodegroup", "eks:ListNodegroups", "eks:DescribeCluster", "eks:ListClusters", "eks:AccessKubernetesApi", "ssm:GetParameter", "eks:ListUpdates", "eks:ListFargateProfiles" ], "Resource": "*" } ] } ``` ### Aws Console: If you have any error in the code you can see in the highlighed part: Errors:0 ![](https://i.imgur.com/9qvMXdc.png) ### Click the Next AddTag: Skip and Go to Review Policy and add the AmazonEKSDeveloperPolicy and Create policy: ![](https://i.imgur.com/7UDca7o.png) ### The Policy is Created: ![](https://i.imgur.com/wJs1aTW.png) ### Now Create a group to attach the policy: -> User Group -> Create New Group -> -> attach the Policy -> Add the Group name -> Click Create: ![](https://i.imgur.com/Q1oZtfx.png) ### Group is Created: ![](https://i.imgur.com/SIBiXy5.png) ### Now Create the user to grant those permission to access the cluster: -> Users -> Create User -> Add username -> Select the programmtic and console permission -> Next:Permissions ![](https://i.imgur.com/pWC77bG.png) ### Select eks-developer and Next ![](https://i.imgur.com/V7m62Xt.png) ### Review and Create user ![](https://i.imgur.com/AvR8FiU.png) ### User is created: downliad credentials .csv file: ![](https://i.imgur.com/8R6EdE1.png) ### New profile configuration using Terminal ![](https://i.imgur.com/nBJuYsb.png) ### Copy the userarn: ![](https://i.imgur.com/XPf0yFq.png) ### Edit the Config Map using kubectl for new user: https://docs.aws.amazon.com/eks/latest/userguide/add-user-role.html ```javascript= # curl -o aws-auth-cm.yaml https://amazon-eks.s3.us-west-2.amazonaws.com/cloudformation/2020-10-29/aws-auth-cm.yaml ``` ### Open the Downloaded file and Edit via VSCode ![](https://i.imgur.com/YZcSYJp.png) ![](https://i.imgur.com/K0DLavC.png) ### Apply the Kubectl ![](https://i.imgur.com/leL46iz.png) ### Update the kubeconfig with developer profile: ![](https://i.imgur.com/KAH9MDW.png) ### Verify that we can use developer profile run: ```javascript= # kubectl config view --minify ``` ![](https://i.imgur.com/A67iJt5.png) ### Verify the permissions