From 7c689f2c668de732917871ff655addfeb5ecdf6e Mon Sep 17 00:00:00 2001 From: Andre Wlodkovski Date: Sun, 7 Apr 2024 11:40:48 -0300 Subject: [PATCH 1/2] Implement Application Load Balancer AWS EKS Ingress through Terraform --- ...troller-yml => alb-ingress-controller.yml} | 2 +- kubernetes/aws/eks-service-account.yml | 6 +- kubernetes/aws/ingress.yml | 15 +- kubernetes/aws/service.yml | 2 +- terraform/.terraform.lock.hcl | 38 +++++ terraform/README.md | 14 ++ .../alb_ingress_controller_policy.json} | 1 + terraform/main.tf | 134 ++++++++++++++++-- 8 files changed, 192 insertions(+), 20 deletions(-) rename kubernetes/aws/{alb-ingress-controller-yml => alb-ingress-controller.yml} (89%) create mode 100644 terraform/README.md rename terraform/{iam_roles/alb_ingress_controller_role.json => iam_policies/alb_ingress_controller_policy.json} (99%) diff --git a/kubernetes/aws/alb-ingress-controller-yml b/kubernetes/aws/alb-ingress-controller.yml similarity index 89% rename from kubernetes/aws/alb-ingress-controller-yml rename to kubernetes/aws/alb-ingress-controller.yml index a9ee902..7523ed0 100644 --- a/kubernetes/aws/alb-ingress-controller-yml +++ b/kubernetes/aws/alb-ingress-controller.yml @@ -21,5 +21,5 @@ spec: - --cluster-name=$CLUSTER_NAME - --aws-vpc-id=$VPC_ID - --aws-region=$AWS_REGION - image: docker.io/amazon/aws-alb-ingress-controller:v1.1.6 + image: public.ecr.aws/eks/aws-alb-ingress-controller:v2.4.7 serviceAccountName: alb-ingress-controller \ No newline at end of file diff --git a/kubernetes/aws/eks-service-account.yml b/kubernetes/aws/eks-service-account.yml index 6c12a62..248601b 100644 --- a/kubernetes/aws/eks-service-account.yml +++ b/kubernetes/aws/eks-service-account.yml @@ -1,5 +1,7 @@ apiVersion: v1 kind: ServiceAccount metadata: - name: my-service-account - namespace: default \ No newline at end of file + name: alb-ingress-controller + namespace: kube-system + annotations: + eks.amazonaws.com/role-arn: $ALB_ROLE_ARN \ No newline at end of file diff --git a/kubernetes/aws/ingress.yml b/kubernetes/aws/ingress.yml index b0acdf3..47f718e 100644 --- a/kubernetes/aws/ingress.yml +++ b/kubernetes/aws/ingress.yml @@ -1,17 +1,22 @@ -apiVersion: extensions/v1beta1 +apiVersion: networking.k8s.io/v1 kind: Ingress metadata: annotations: alb.ingress.kubernetes.io/scheme: internet-facing + alb.ingress.kubernetes.io/target-type: ip kubernetes.io/ingress.class: alb name: authentication-api-ingress labels: app: authentication-api-ingress spec: + ingressClassName: alb rules: - http: paths: - - backend: - serviceName: authentication-api-service - servicePort: 80 - path: /* \ No newline at end of file + - path: / + pathType: Prefix + backend: + service: + name: authentication-api-service + port: + number: 80 \ No newline at end of file diff --git a/kubernetes/aws/service.yml b/kubernetes/aws/service.yml index 6393769..66253ac 100644 --- a/kubernetes/aws/service.yml +++ b/kubernetes/aws/service.yml @@ -4,7 +4,7 @@ metadata: name: authentication-api-service namespace: default spec: - type: LoadBalancer + type: ClusterIP selector: app: authentication-api ports: diff --git a/terraform/.terraform.lock.hcl b/terraform/.terraform.lock.hcl index a2363b7..cb9437d 100644 --- a/terraform/.terraform.lock.hcl +++ b/terraform/.terraform.lock.hcl @@ -23,3 +23,41 @@ provider "registry.terraform.io/hashicorp/aws" { "zh:fecbcbd63111c9518de261bcb37482cb06ee149e7298f567d45b2a55674faa75", ] } + +provider "registry.terraform.io/hashicorp/helm" { + version = "2.13.0" + hashes = [ + "h1:hQIozFWLJk67bKslnNIZPHYb037+6uO86sHVkntPjXY=", + "zh:016e42bea1c9145b0856bfcf1e5faf657e40e9a94e4d80bee9e0b8742eb9f5fd", + "zh:0a325cfcb62d4c611a9a7854d2ca26ee8cbd27a1cae40f607c0966e36a858358", + "zh:2e22929aa1cc59c02e1cb8af8cee25063a706cdfc15d3aff242c8bf76cd12ea3", + "zh:35d989aa6f43d6401077c190c3262c6df434290c5bec978079ae69eb33f3929e", + "zh:4cc42ee66af3fa965424c19904e5ac52326d4a31df066d565d591d0e46e64c2d", + "zh:69a429be3f7183f53ec1928a44ed7ad0606a0247a7ce34e2c5a8e9d8906dbcbd", + "zh:88155234e7a4d45cc91ebcb2d633fdfc2daad4e85e5b1990c864dab0432afa0e", + "zh:b13055e38617be147e82eec8b20c579e9c202da9ead8c976a54ed08bde6b06f7", + "zh:bc6f8f1f84afcc66c5b248ffa34580d8f7e7552628eb6ad044765513159db8e4", + "zh:d91899fe77e7223d91d2cfed2cacde1afe8b528771402ec4d494b81457421bb1", + "zh:ef5ca86c48a786a0cc481f4cfb1c9f2e3b8eccb640c106c6a1f253f97f5e9c55", + "zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c", + ] +} + +provider "registry.terraform.io/hashicorp/tls" { + version = "4.0.5" + hashes = [ + "h1:e4LBdJoZJNOQXPWgOAG0UuPBVhCStu98PieNlqJTmeU=", + "zh:01cfb11cb74654c003f6d4e32bbef8f5969ee2856394a96d127da4949c65153e", + "zh:0472ea1574026aa1e8ca82bb6df2c40cd0478e9336b7a8a64e652119a2fa4f32", + "zh:1a8ddba2b1550c5d02003ea5d6cdda2eef6870ece86c5619f33edd699c9dc14b", + "zh:1e3bb505c000adb12cdf60af5b08f0ed68bc3955b0d4d4a126db5ca4d429eb4a", + "zh:6636401b2463c25e03e68a6b786acf91a311c78444b1dc4f97c539f9f78de22a", + "zh:76858f9d8b460e7b2a338c477671d07286b0d287fd2d2e3214030ae8f61dd56e", + "zh:a13b69fb43cb8746793b3069c4d897bb18f454290b496f19d03c3387d1c9a2dc", + "zh:a90ca81bb9bb509063b736842250ecff0f886a91baae8de65c8430168001dad9", + "zh:c4de401395936e41234f1956ebadbd2ed9f414e6908f27d578614aaa529870d4", + "zh:c657e121af8fde19964482997f0de2d5173217274f6997e16389e7707ed8ece8", + "zh:d68b07a67fbd604c38ec9733069fbf23441436fecf554de6c75c032f82e1ef19", + "zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c", + ] +} diff --git a/terraform/README.md b/terraform/README.md new file mode 100644 index 0000000..b4e3e01 --- /dev/null +++ b/terraform/README.md @@ -0,0 +1,14 @@ +# Terraform deployment for Authentication API + +Script order: + +```sh +export AWS_REGION= +aws eks update-kubeconfig --region $AWS_REGION --name authentication-cluster-test + +# After fargate profile has been created +kubectl rollout restart deployment coredns -n kube-system + +kubectl apply -f kubernetes/aws/ingress.yml +``` + diff --git a/terraform/iam_roles/alb_ingress_controller_role.json b/terraform/iam_policies/alb_ingress_controller_policy.json similarity index 99% rename from terraform/iam_roles/alb_ingress_controller_role.json rename to terraform/iam_policies/alb_ingress_controller_policy.json index b1d2d2b..8c5230a 100644 --- a/terraform/iam_roles/alb_ingress_controller_role.json +++ b/terraform/iam_policies/alb_ingress_controller_policy.json @@ -17,6 +17,7 @@ "ec2:CreateSecurityGroup", "ec2:CreateTags", "ec2:DeleteTags", + "ec2:DescribeAvailabilityZones", "ec2:DeleteSecurityGroup", "ec2:DescribeAccountAttributes", "ec2:DescribeAddresses", diff --git a/terraform/main.tf b/terraform/main.tf index 77ae024..04a42cd 100644 --- a/terraform/main.tf +++ b/terraform/main.tf @@ -45,6 +45,8 @@ resource "aws_subnet" "public_subnets" { "Project" = "authentication-app" "ManagedBy" = "terraform" "Organization" = "andrewlod" + "kubernetes.io/role/elb": 1 + "kubernetes.io/cluster/authentication-cluster-${var.infra_env}" = "shared" } } @@ -171,7 +173,7 @@ resource "aws_subnet" "private_subnets" { "ManagedBy" = "terraform" "Organization" = "andrewlod" "kubernetes.io/role/internal-elb" = "1" - "kubernetes.io/cluster/authentication-cluster-${var.infra_env}" = "owned" + "kubernetes.io/cluster/authentication-cluster-${var.infra_env}" = "shared" } } @@ -315,16 +317,6 @@ resource "aws_iam_role_policy_attachment" "eks_fargate_execution_attachment" { role = aws_iam_role.eks_fargate_execution_role.name } -resource "aws_iam_policy" "eks_alb_ingress_controller_policy" { - name = "eks-alb-ingress-controller-policy" - policy = file("iam_roles/alb_ingress_controller_role.json") -} - -resource "aws_iam_role_policy_attachment" "eks_alb_ingress_controller_policy_attachment" { - policy_arn = aws_iam_policy.eks_alb_ingress_controller_policy.arn - role = aws_iam_role.eks_fargate_execution_role.name -} - resource "aws_iam_role" "eks_cluster_role" { name = "eks-cluster-role" assume_role_policy = jsonencode({ @@ -401,4 +393,124 @@ resource "aws_eks_fargate_profile" "auth_cluster_fargate_profile" { selector { namespace = "kube-node-lease" } +} + +## Helm +provider "helm" { + kubernetes { + host = aws_eks_cluster.authentication_cluster.endpoint + cluster_ca_certificate = base64decode(aws_eks_cluster.authentication_cluster.certificate_authority[0].data) + exec { + api_version = "client.authentication.k8s.io/v1beta1" + args = ["eks", "get-token", "--cluster-name", aws_eks_cluster.authentication_cluster.id] + command = "aws" + } + } +} + +resource "helm_release" "metrics-server" { + name = "metrics-server" + + repository = "https://kubernetes-sigs.github.io/metrics-server/" + chart = "metrics-server" + namespace = "kube-system" + version = "3.8.2" + + set { + name = "metrics.enabled" + value = false + } + + depends_on = [aws_eks_fargate_profile.auth_cluster_fargate_profile] +} + +## EKS IAM +data "tls_certificate" "eks_certificate" { + url = aws_eks_cluster.authentication_cluster.identity[0].oidc[0].issuer +} + +resource "aws_iam_openid_connect_provider" "eks_oidc_connector" { + client_id_list = ["sts.amazonaws.com"] + thumbprint_list = [data.tls_certificate.eks_certificate.certificates[0].sha1_fingerprint] + url = aws_eks_cluster.authentication_cluster.identity[0].oidc[0].issuer +} + +data "aws_iam_policy_document" "aws_load_balancer_controller_assume_role_policy" { + statement { + actions = ["sts:AssumeRoleWithWebIdentity"] + effect = "Allow" + + condition { + test = "StringEquals" + variable = "${replace(aws_iam_openid_connect_provider.eks_oidc_connector.url, "https://", "")}:sub" + values = ["system:serviceaccount:kube-system:alb-ingress-controller"] + } + + principals { + identifiers = [aws_iam_openid_connect_provider.eks_oidc_connector.arn] + type = "Federated" + } + } +} + +resource "aws_iam_role" "eks_alb_ingress_controller_role" { + name = "eks-alb-ingress-controller-role" + assume_role_policy = data.aws_iam_policy_document.aws_load_balancer_controller_assume_role_policy.json +} + +resource "aws_iam_policy" "eks_alb_ingress_controller_policy" { + name = "eks-alb-ingress-controller-policy" + policy = file("iam_policies/alb_ingress_controller_policy.json") +} + +resource "aws_iam_role_policy_attachment" "eks_alb_ingress_controller_policy_attachment" { + policy_arn = aws_iam_policy.eks_alb_ingress_controller_policy.arn + role = aws_iam_role.eks_alb_ingress_controller_role.name +} + +resource "helm_release" "aws_load_balancer_ingress_controller" { + name = "aws-load-balancer-ingress-controller" + + repository = "https://aws.github.io/eks-charts" + chart = "aws-load-balancer-controller" + namespace = "kube-system" + version = "1.4.1" + + set { + name = "clusterName" + value = aws_eks_cluster.authentication_cluster.id + } + + set { + name = "image.tag" + value = "v2.4.2" + } + + set { + name = "replicaCount" + value = 1 + } + + set { + name = "serviceAccount.name" + value = "alb-ingress-controller" + } + + set { + name = "serviceAccount.annotations.eks\\.amazonaws\\.com/role-arn" + value = aws_iam_role.eks_alb_ingress_controller_role.arn + } + + # EKS Fargate specific + set { + name = "region" + value = var.aws_region + } + + set { + name = "vpcId" + value = aws_vpc.main_vpc.id + } + + depends_on = [aws_eks_fargate_profile.auth_cluster_fargate_profile] } \ No newline at end of file From 601bb35c7cd7fe4685c311f828424ad2662f925f Mon Sep 17 00:00:00 2001 From: Andre Wlodkovski Date: Sun, 7 Apr 2024 11:41:44 -0300 Subject: [PATCH 2/2] Update version to 1.2.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c3c120f..d41a2a1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "authentication-api", - "version": "1.1.1", + "version": "1.2.0", "description": "Authentication REST API created with TypeScript", "main": "src/server.ts", "scripts": {