[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"content-/blog/2023/09/08/infrastructure-azure-terraform":3,"related-/blog/2023/09/08/infrastructure-azure-terraform":728},{"id":4,"title":5,"author":6,"body":7,"cover":710,"date":711,"description":13,"draft":712,"excerpt":713,"extension":714,"github":715,"keywords":716,"meta":717,"navigation":214,"path":718,"seo":719,"shortDesc":713,"slug":720,"stem":721,"tags":722,"video":713,"__hash__":727},"blog/blog/2023/09/08/Infrastructure-azure-terraform.md","Infrastructure As Code","Oz Shemesh",{"type":8,"value":9,"toc":703},"minimark",[10,14,19,22,43,47,50,79,87,90,100,187,191,194,300,441,445,453,496,499,563,566,664,668,696,699],[11,12,13],"p",{},"In the upcoming blog post, we will establish the foundational infrastructure that will be pivotal throughout the remaining CI & CD tutorials.",[15,16,18],"h2",{"id":17},"guidelines","Guidelines",[11,20,21],{},"For this purpose, I've opted to utilize Azure Kubernetes Service (AKS) and Terraform. However, it's worth noting that you have the flexibility to choose from a variety of providers, including GCP, EKS, or any other Kubernetes service that suits your needs.",[23,24,26,29],"info-box",{"type":25},"warning",[11,27,28],{},"Persisting Terraform State!",[30,31,33],"template",{"v-slot:details":32},"",[11,34,35,36],{},"I'm utilizing Azure Blob Storage as the backend for storing the Terraform state, but it's important to mention that you have the option to select an alternative backend or even forgo state persistence altogether.",[37,38,42],"a",{"href":39,"rel":40},"https://developer.hashicorp.com/terraform/language/settings/backends/configuration",[41],"nofollow","More information can be found here",[15,44,46],{"id":45},"terraform","Terraform",[11,48,49],{},"We are about to buildthe following:",[51,52,53,57,68],"ul",{},[54,55,56],"li",{},"Simple AKS",[54,58,59,60],{},"Terrafor will create for us two resource groups:\n",[51,61,62,65],{},[54,63,64],{},"one to hold AKS itself (and other resources like key vault for example if being used)",[54,66,67],{},"the second for node pools, load balancer, volumes etc.",[54,69,70,71],{},"We have devided it into two node pools:\n",[51,72,73,76],{},[54,74,75],{},"System PODs (only_critical_addons_enabled)",[54,77,78],{},"Management PODs (our application).",[11,80,81,82],{},"More information about Terraform and AKS can be found ",[37,83,86],{"href":84,"rel":85},"https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/kubernetes_cluster",[41],"Here",[11,88,89],{},"Update azure/aks/variables.tf and azure/environment/dev/backend.conf files.",[23,91,92,95],{"type":25},[11,93,94],{},"Cloud provide CLI init",[30,96,97],{"v-slot:details":32},[11,98,99],{},"Before executing Terraform CLI make sure to login to init the relevant provider (i.e. az login, gcloud init etc.) depends on the backend you are using.",[101,102,106],"pre",{"className":103,"code":104,"language":105,"meta":32,"style":32},"language-bash shiki shiki-themes nord github-dark monokai","cd infra/terraform/azure\nterraform -chdir='aks' init -backend-config=../environment/dev/backend.conf -reconfigure\nterraform -chdir='aks' plan -var-file=../environment/dev/.tfvars\nterraform -chdir='aks' apply -var-file=../environment/dev/.tfvars\n","bash",[107,108,109,122,150,169],"code",{"__ignoreMap":32},[110,111,114,118],"span",{"class":112,"line":113},"line",1,[110,115,117],{"class":116},"sCWj5","cd",[110,119,121],{"class":120},"siq7d"," infra/terraform/azure\n",[110,123,125,128,132,136,139,141,144,147],{"class":112,"line":124},2,[110,126,45],{"class":127},"sNHwn",[110,129,131],{"class":130},"sqTyp"," -chdir=",[110,133,135],{"class":134},"sQE_P","'",[110,137,138],{"class":120},"aks",[110,140,135],{"class":134},[110,142,143],{"class":120}," init",[110,145,146],{"class":130}," -backend-config=../environment/dev/backend.conf",[110,148,149],{"class":130}," -reconfigure\n",[110,151,153,155,157,159,161,163,166],{"class":112,"line":152},3,[110,154,45],{"class":127},[110,156,131],{"class":130},[110,158,135],{"class":134},[110,160,138],{"class":120},[110,162,135],{"class":134},[110,164,165],{"class":120}," plan",[110,167,168],{"class":130}," -var-file=../environment/dev/.tfvars\n",[110,170,172,174,176,178,180,182,185],{"class":112,"line":171},4,[110,173,45],{"class":127},[110,175,131],{"class":130},[110,177,135],{"class":134},[110,179,138],{"class":120},[110,181,135],{"class":134},[110,183,184],{"class":120}," apply",[110,186,168],{"class":130},[15,188,190],{"id":189},"azure-kubernetes-service","Azure Kubernetes Service",[11,192,193],{},"If everything went well at the prevois step you should have a working AKS.\nGo to Azure portal and search for AKS instances or use the Azure CLI and kubectl.",[101,195,197],{"className":103,"code":196,"language":105,"meta":32,"style":32},"az aks list\n\n[\n  {\n    \"aadProfile\": null,\n    \"addonProfiles\": null,\n    \"agentPoolProfiles\": [\n      {}\n    ]\n  }\n  ...\n]\n",[107,198,199,210,216,222,228,243,255,270,276,282,288,294],{"__ignoreMap":32},[110,200,201,204,207],{"class":112,"line":113},[110,202,203],{"class":127},"az",[110,205,206],{"class":120}," aks",[110,208,209],{"class":120}," list\n",[110,211,212],{"class":112,"line":124},[110,213,215],{"emptyLinePlaceholder":214},true,"\n",[110,217,218],{"class":112,"line":152},[110,219,221],{"class":220},"sUaCP","[\n",[110,223,224],{"class":112,"line":171},[110,225,227],{"class":226},"sw3Zv","  {\n",[110,229,231,234,237,240],{"class":112,"line":230},5,[110,232,233],{"class":134},"    \"",[110,235,236],{"class":120},"aadProfile",[110,238,239],{"class":134},"\"",[110,241,242],{"class":226},": null,\n",[110,244,246,248,251,253],{"class":112,"line":245},6,[110,247,233],{"class":134},[110,249,250],{"class":120},"addonProfiles",[110,252,239],{"class":134},[110,254,242],{"class":226},[110,256,258,260,263,265,268],{"class":112,"line":257},7,[110,259,233],{"class":134},[110,261,262],{"class":120},"agentPoolProfiles",[110,264,239],{"class":134},[110,266,267],{"class":226},": ",[110,269,221],{"class":220},[110,271,273],{"class":112,"line":272},8,[110,274,275],{"class":226},"      {}\n",[110,277,279],{"class":112,"line":278},9,[110,280,281],{"class":220},"    ]\n",[110,283,285],{"class":112,"line":284},10,[110,286,287],{"class":226},"  }\n",[110,289,291],{"class":112,"line":290},11,[110,292,293],{"class":226},"  ...\n",[110,295,297],{"class":112,"line":296},12,[110,298,299],{"class":220},"]\n",[101,301,303],{"className":103,"code":302,"language":105,"meta":32,"style":32},"kubectl get nodes -owide\n\nNAME                                 STATUS   ROLES   AGE   VERSION   INTERNAL-IP    EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION      CONTAINER-RUNTIME\naks-management-41779884-vmss000001   Ready    agent   15s   v1.26.6   10.224.0.100   \u003Cnone>        Ubuntu 22.04.3 LTS   5.15.0-1042-azure   containerd://1.7.1+azure-1\naks-system-18952855-vmss000000       Ready    agent   29h   v1.26.6   10.224.0.4     \u003Cnone>        Ubuntu 22.04.3 LTS   5.15.0-1042-azure   containerd://1.7.1+azure-1\n\n",[107,304,305,319,323,355,404],{"__ignoreMap":32},[110,306,307,310,313,316],{"class":112,"line":113},[110,308,309],{"class":127},"kubectl",[110,311,312],{"class":120}," get",[110,314,315],{"class":120}," nodes",[110,317,318],{"class":130}," -owide\n",[110,320,321],{"class":112,"line":124},[110,322,215],{"emptyLinePlaceholder":214},[110,324,325,328,331,334,337,340,343,346,349,352],{"class":112,"line":152},[110,326,327],{"class":127},"NAME",[110,329,330],{"class":120},"                                 STATUS",[110,332,333],{"class":120},"   ROLES",[110,335,336],{"class":120},"   AGE",[110,338,339],{"class":120},"   VERSION",[110,341,342],{"class":120},"   INTERNAL-IP",[110,344,345],{"class":120},"    EXTERNAL-IP",[110,347,348],{"class":120},"   OS-IMAGE",[110,350,351],{"class":120},"             KERNEL-VERSION",[110,353,354],{"class":120},"      CONTAINER-RUNTIME\n",[110,356,357,360,363,366,369,372,376,380,383,386,389,392,395,398,401],{"class":112,"line":171},[110,358,359],{"class":127},"aks-management-41779884-vmss000001",[110,361,362],{"class":120},"   Ready",[110,364,365],{"class":120},"    agent",[110,367,368],{"class":120},"   15s",[110,370,371],{"class":120},"   v1.26.6",[110,373,375],{"class":374},"sX_qU","   10.224.0.100",[110,377,379],{"class":378},"s4BcI","   \u003C",[110,381,382],{"class":120},"non",[110,384,385],{"class":226},"e",[110,387,388],{"class":378},">",[110,390,391],{"class":120},"        Ubuntu",[110,393,394],{"class":374}," 22.04.3",[110,396,397],{"class":120}," LTS",[110,399,400],{"class":120},"   5.15.0-1042-azure",[110,402,403],{"class":120},"   containerd://1.7.1+azure-1\n",[110,405,406,409,412,414,417,419,422,425,427,429,431,433,435,437,439],{"class":112,"line":230},[110,407,408],{"class":127},"aks-system-18952855-vmss000000",[110,410,411],{"class":120},"       Ready",[110,413,365],{"class":120},[110,415,416],{"class":120},"   29h",[110,418,371],{"class":120},[110,420,421],{"class":374},"   10.224.0.4",[110,423,424],{"class":378},"     \u003C",[110,426,382],{"class":120},[110,428,385],{"class":226},[110,430,388],{"class":378},[110,432,391],{"class":120},[110,434,394],{"class":374},[110,436,397],{"class":120},[110,438,400],{"class":120},[110,440,403],{"class":120},[15,442,444],{"id":443},"validation","Validation",[11,446,447,448],{},"We`ll be a simple web application just to test a POD deployment.\n",[37,449,452],{"href":450,"rel":451},"https://github.com/stefanprodan/podinfo",[41],"Here is a useful implementation",[101,454,456],{"className":103,"code":455,"language":105,"meta":32,"style":32},"kubectl apply -k github.com/stefanprodan/podinfo/kustomize\n\nservice/podinfo created\ndeployment.apps/podinfo created\nhorizontalpodautoscaler.autoscaling/podinfo created\n\n",[107,457,458,470,474,482,489],{"__ignoreMap":32},[110,459,460,462,464,467],{"class":112,"line":113},[110,461,309],{"class":127},[110,463,184],{"class":120},[110,465,466],{"class":130}," -k",[110,468,469],{"class":120}," github.com/stefanprodan/podinfo/kustomize\n",[110,471,472],{"class":112,"line":124},[110,473,215],{"emptyLinePlaceholder":214},[110,475,476,479],{"class":112,"line":152},[110,477,478],{"class":127},"service/podinfo",[110,480,481],{"class":120}," created\n",[110,483,484,487],{"class":112,"line":171},[110,485,486],{"class":127},"deployment.apps/podinfo",[110,488,481],{"class":120},[110,490,491,494],{"class":112,"line":230},[110,492,493],{"class":127},"horizontalpodautoscaler.autoscaling/podinfo",[110,495,481],{"class":120},[11,497,498],{},"Check the PODs are running",[101,500,502],{"className":103,"code":501,"language":105,"meta":32,"style":32},"kubectl get pod\n\nNAME                       READY   STATUS    RESTARTS   AGE\npodinfo-6c77b54bb8-9vgd2   1/1     Running   0          25m\npodinfo-6c77b54bb8-cnnc8   1/1     Running   0          25m\n\n",[107,503,504,513,517,533,550],{"__ignoreMap":32},[110,505,506,508,510],{"class":112,"line":113},[110,507,309],{"class":127},[110,509,312],{"class":120},[110,511,512],{"class":120}," pod\n",[110,514,515],{"class":112,"line":124},[110,516,215],{"emptyLinePlaceholder":214},[110,518,519,521,524,527,530],{"class":112,"line":152},[110,520,327],{"class":127},[110,522,523],{"class":120},"                       READY",[110,525,526],{"class":120},"   STATUS",[110,528,529],{"class":120},"    RESTARTS",[110,531,532],{"class":120},"   AGE\n",[110,534,535,538,541,544,547],{"class":112,"line":171},[110,536,537],{"class":127},"podinfo-6c77b54bb8-9vgd2",[110,539,540],{"class":120},"   1/1",[110,542,543],{"class":120},"     Running",[110,545,546],{"class":374},"   0",[110,548,549],{"class":120},"          25m\n",[110,551,552,555,557,559,561],{"class":112,"line":230},[110,553,554],{"class":127},"podinfo-6c77b54bb8-cnnc8",[110,556,540],{"class":120},[110,558,543],{"class":120},[110,560,546],{"class":374},[110,562,549],{"class":120},[11,564,565],{},"Remove the podinfo resources",[101,567,569],{"className":103,"code":568,"language":105,"meta":32,"style":32},"kubectl delete -k github.com/stefanprodan/podinfo/kustomize\n\nservice \"podinfo\" deleted\ndeployment.apps \"podinfo\" deleted\nhorizontalpodautoscaler.autoscaling \"podinfo\" deleted\n\nkubectl get pod                                            \nNo resources found in default namespace.\n",[107,570,571,582,586,602,615,628,632,644],{"__ignoreMap":32},[110,572,573,575,578,580],{"class":112,"line":113},[110,574,309],{"class":127},[110,576,577],{"class":120}," delete",[110,579,466],{"class":130},[110,581,469],{"class":120},[110,583,584],{"class":112,"line":124},[110,585,215],{"emptyLinePlaceholder":214},[110,587,588,591,594,597,599],{"class":112,"line":152},[110,589,590],{"class":127},"service",[110,592,593],{"class":134}," \"",[110,595,596],{"class":120},"podinfo",[110,598,239],{"class":134},[110,600,601],{"class":120}," deleted\n",[110,603,604,607,609,611,613],{"class":112,"line":171},[110,605,606],{"class":127},"deployment.apps",[110,608,593],{"class":134},[110,610,596],{"class":120},[110,612,239],{"class":134},[110,614,601],{"class":120},[110,616,617,620,622,624,626],{"class":112,"line":230},[110,618,619],{"class":127},"horizontalpodautoscaler.autoscaling",[110,621,593],{"class":134},[110,623,596],{"class":120},[110,625,239],{"class":134},[110,627,601],{"class":120},[110,629,630],{"class":112,"line":245},[110,631,215],{"emptyLinePlaceholder":214},[110,633,634,636,638,641],{"class":112,"line":257},[110,635,309],{"class":127},[110,637,312],{"class":120},[110,639,640],{"class":120}," pod",[110,642,643],{"class":226},"                                            \n",[110,645,646,649,652,655,658,661],{"class":112,"line":272},[110,647,648],{"class":127},"No",[110,650,651],{"class":120}," resources",[110,653,654],{"class":120}," found",[110,656,657],{"class":120}," in",[110,659,660],{"class":120}," default",[110,662,663],{"class":120}," namespace.\n",[15,665,667],{"id":666},"cleanup-resource","Cleanup Resource",[101,669,671],{"className":103,"code":670,"language":105,"meta":32,"style":32},"cd infra/terraform/azure\nterraform -chdir='aks' destroy -var-file=../environment/dev/.tfvars\n",[107,672,673,679],{"__ignoreMap":32},[110,674,675,677],{"class":112,"line":113},[110,676,117],{"class":116},[110,678,121],{"class":120},[110,680,681,683,685,687,689,691,694],{"class":112,"line":124},[110,682,45],{"class":127},[110,684,131],{"class":130},[110,686,135],{"class":134},[110,688,138],{"class":120},[110,690,135],{"class":134},[110,692,693],{"class":120}," destroy",[110,695,168],{"class":130},[11,697,698],{},"Also remember to delete BlobStorage or any other backend that you have used for the Terraform state and any other resource that you have created manualy.",[700,701,702],"style",{},"html pre.shiki code .sCWj5, html code.shiki .sCWj5{--shiki-default:#88C0D0;--shiki-dark:#79B8FF;--shiki-sepia:#66D9EF}html pre.shiki code .siq7d, html code.shiki .siq7d{--shiki-default:#A3BE8C;--shiki-dark:#9ECBFF;--shiki-sepia:#E6DB74}html pre.shiki code .sNHwn, html code.shiki .sNHwn{--shiki-default:#88C0D0;--shiki-dark:#B392F0;--shiki-sepia:#A6E22E}html pre.shiki code .sqTyp, html code.shiki .sqTyp{--shiki-default:#A3BE8C;--shiki-dark:#79B8FF;--shiki-sepia:#AE81FF}html pre.shiki code .sQE_P, html code.shiki .sQE_P{--shiki-default:#ECEFF4;--shiki-dark:#9ECBFF;--shiki-sepia:#E6DB74}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html .sepia .shiki span {color: var(--shiki-sepia);background: var(--shiki-sepia-bg);font-style: var(--shiki-sepia-font-style);font-weight: var(--shiki-sepia-font-weight);text-decoration: var(--shiki-sepia-text-decoration);}html.sepia .shiki span {color: var(--shiki-sepia);background: var(--shiki-sepia-bg);font-style: var(--shiki-sepia-font-style);font-weight: var(--shiki-sepia-font-weight);text-decoration: var(--shiki-sepia-text-decoration);}html pre.shiki code .sUaCP, html code.shiki .sUaCP{--shiki-default:#ECEFF4;--shiki-dark:#E1E4E8;--shiki-sepia:#F8F8F2}html pre.shiki code .sw3Zv, html code.shiki .sw3Zv{--shiki-default:#D8DEE9FF;--shiki-dark:#E1E4E8;--shiki-sepia:#F8F8F2}html pre.shiki code .sX_qU, html code.shiki .sX_qU{--shiki-default:#B48EAD;--shiki-dark:#79B8FF;--shiki-sepia:#AE81FF}html pre.shiki code .s4BcI, html code.shiki .s4BcI{--shiki-default:#81A1C1;--shiki-dark:#F97583;--shiki-sepia:#F92672}",{"title":32,"searchDepth":124,"depth":124,"links":704},[705,706,707,708,709],{"id":17,"depth":124,"text":18},{"id":45,"depth":124,"text":46},{"id":189,"depth":124,"text":190},{"id":443,"depth":124,"text":444},{"id":666,"depth":124,"text":667},"./infra.png","2023-09-08T08:00:00.000Z",false,null,"md","https://github.com/devozs/blog-deployment/tree/main/infra/terraform/azure","IaC, Infra, Azure, AKS, Terraform",{"published":214},"/blog/2023/09/08/infrastructure-azure-terraform",{"title":5,"description":13},"infrastructure-azure-terraform","blog/2023/09/08/Infrastructure-azure-terraform",[723,724,725,726,46],"IaC","Infra","Azure","AKS","vJX4TS3MBcjWpEvB4Y0RozC5VYfxqzZXGDBQ_R4BVIY",[729],{"id":730,"title":731,"author":6,"body":732,"cover":1182,"date":1183,"description":32,"draft":712,"excerpt":713,"extension":714,"github":740,"keywords":1184,"meta":1185,"navigation":214,"path":1186,"seo":1187,"shortDesc":713,"slug":1188,"stem":1189,"tags":1190,"video":713,"__hash__":1196},"blog/blog/2024/08/06/tf-tg-flux-eks.md","Terraform, Terragrunt for IaC and FluxCD for GitOps",{"type":8,"value":733,"toc":1149},[734,743,746,750,753,777,782,790,794,797,801,804,819,822,826,840,844,847,879,883,886,890,901,904,915,919,922,926,929,933,954,957,968,971,978,982,985,996,999,1003,1006,1012,1015,1018,1022,1025,1029,1040,1044,1047,1051,1060,1064,1079,1083,1109,1113,1116,1120,1134,1138,1146],[23,735,736],{"type":32},[11,737,738],{},[37,739,742],{"href":740,"rel":741},"https://gitlab.com/devozs/devops-infra",[41],"Show me the Code!",[11,744,745],{},"This repository contains the Infrastructure as Code (IaC) using Terraform and Terragrunt, and implements GitOps practices using FluxCD for a simple counter application.",[15,747,749],{"id":748},"iac-terraform-and-terragrunt","IaC - Terraform and Terragrunt",[11,751,752],{},"We use Terraform with Terragrunt to manage our AWS infrastructure. The main components include:",[51,754,755,758],{},[54,756,757],{},"EKS Cluster",[54,759,760,761,765,766],{},"Modules (",[37,762,763],{"href":763,"rel":764},"https://gitlab.com/devozs/infrastructure-modules",[41],")\n",[51,767,768,771,774],{},[54,769,770],{},"VPC and Networking",[54,772,773],{},"IAM Roles and Policies",[54,775,776],{},"ECR Repository",[778,779,781],"h3",{"id":780},"directory-structure","Directory Structure",[101,783,788],{"className":784,"code":786,"language":787},[785],"language-text","infrastructure/\n├── dev/\n│   ├── eks/\n│   ├── vpc/\n│   └── ecr/\n├── modules/ (in a seperate repo)\n│   ├── eks/\n│   ├── vpc/\n│   └── ecr/\n└── terragrunt.hcl\n","text",[107,789,786],{"__ignoreMap":32},[15,791,793],{"id":792},"references-and-credits","References and Credits",[11,795,796],{},"In the development of this project, several external resources were invaluable:",[778,798,800],{"id":799},"terraform-and-terragrunt","Terraform and Terragrunt",[11,802,803],{},"For learning and implementing Terraform with Terragrunt, the following tutorial was extensively used:",[51,805,806,809,812],{},[54,807,808],{},"Title: \"Terraform & Terragrunt for AWS Beginner Project Tutorial\"",[54,810,811],{},"Author: Anton Putra",[54,813,814,815],{},"URL: ",[37,816,817],{"href":817,"rel":818},"https://www.youtube.com/watch?v=yduHaOj3XMg",[41],[11,820,821],{},"This tutorial provided crucial insights into setting up and managing AWS infrastructure using Terraform and Terragrunt, which greatly influenced the structure and approach of this project.",[778,823,825],{"id":824},"key-features","Key Features",[51,827,828,831,834,837],{},[54,829,830],{},"Modular design for reusability",[54,832,833],{},"Environment separation (dev, staging, prod)",[54,835,836],{},"Remote state management using S3 backend",[54,838,839],{},"IAM roles for EKS and ECR access",[778,841,843],{"id":842},"usage","Usage",[11,845,846],{},"To apply changes:",[101,848,850],{"className":103,"code":849,"language":105,"meta":32,"style":32},"cd infrastructure/dev\nterragrunt run-all plan\nterragrunt run-all apply\n",[107,851,852,859,870],{"__ignoreMap":32},[110,853,854,856],{"class":112,"line":113},[110,855,117],{"class":116},[110,857,858],{"class":120}," infrastructure/dev\n",[110,860,861,864,867],{"class":112,"line":124},[110,862,863],{"class":127},"terragrunt",[110,865,866],{"class":120}," run-all",[110,868,869],{"class":120}," plan\n",[110,871,872,874,876],{"class":112,"line":152},[110,873,863],{"class":127},[110,875,866],{"class":120},[110,877,878],{"class":120}," apply\n",[15,880,882],{"id":881},"gitops-fluxcd","GitOps - FluxCD",[11,884,885],{},"We use FluxCD for continuous deployment and GitOps practices.",[778,887,889],{"id":888},"components","Components",[51,891,892,895,898],{},[54,893,894],{},"Flux Bootstrap",[54,896,897],{},"Image Update Automation",[54,899,900],{},"Kustomize for Kubernetes manifests",[778,902,825],{"id":903},"key-features-1",[51,905,906,909,912],{},[54,907,908],{},"Automatic deployment of new container images",[54,910,911],{},"Git repository as the single source of truth",[54,913,914],{},"Kubernetes manifest management",[778,916,918],{"id":917},"configuration","Configuration",[11,920,921],{},"Flux is configured to watch the ECR repository for new images and automatically update the Kubernetes deployments.",[15,923,925],{"id":924},"cicd-pipeline","CI/CD Pipeline",[11,927,928],{},"We use GitLab CI for continuous integration and deployment.",[778,930,932],{"id":931},"pipeline-stages","Pipeline Stages",[934,935,936,939,942,945,948,951],"ol",{},[54,937,938],{},"Validate",[54,940,941],{},"Init",[54,943,944],{},"Plan",[54,946,947],{},"Apply",[54,949,950],{},"Destroy",[54,952,953],{},"Post-apply (Flux bootstrap)",[778,955,825],{"id":956},"key-features-2",[51,958,959,962,965],{},[54,960,961],{},"Automatic Terraform plan and apply on changes to infrastructure code",[54,963,964],{},"Manual approval step for apply stage",[54,966,967],{},"Flux bootstrap after successful infrastructure updates",[778,969,918],{"id":970},"configuration-1",[11,972,973,974,977],{},"The CI/CD pipeline is defined in ",[107,975,976],{},".gitlab-ci.yml"," at the root of this repository.",[15,979,981],{"id":980},"application-details","Application Details",[11,983,984],{},"The counter application (in a separate repository) is a simple Python Flask app that:",[51,986,987,990,993],{},[54,988,989],{},"Counts POST and GET requests",[54,991,992],{},"Displays the current count",[54,994,995],{},"Shows the application version (to demonstrate live update)",[11,997,998],{},"The application is containerized and pushed to ECR, from where Flux picks up new versions for deployment.",[15,1000,1002],{"id":1001},"accessing-the-application","Accessing the Application",[11,1004,1005],{},"After deployment, the application is accessible via the Contour ingress controller. The URL for accessing the application is:",[101,1007,1010],{"className":1008,"code":1009,"language":787},[785],"http://a6c503949052c42ad8bcd686137bc100-40713477.eu-west-1.elb.amazonaws.com/counter\n",[107,1011,1009],{"__ignoreMap":32},[11,1013,1014],{},"This URL is composed of the DNS name of the AWS Elastic Load Balancer created by the Contour ingress controller, followed by the '/counter' path.",[11,1016,1017],{},"Note: This URL may change if the Load Balancer is recreated. Always refer to the most recent ELB DNS name in your AWS console or infrastructure outputs.",[15,1019,1021],{"id":1020},"versioning","Versioning",[11,1023,1024],{},"The application version is injected at build time and displayed on the web interface. This helps in identifying which version of the application is currently deployed.",[15,1026,1028],{"id":1027},"security-considerations","Security Considerations",[51,1030,1031,1034,1037],{},[54,1032,1033],{},"EKS cluster uses IAM roles for service accounts (IRSA)",[54,1035,1036],{},"Least privilege principle applied to IAM roles",[54,1038,1039],{},"Network policies and security groups restrict access",[15,1041,1043],{"id":1042},"monitoring-and-logging","Monitoring and Logging",[11,1045,1046],{},"Our application and infrastructure can be monitored through various methods:",[778,1048,1050],{"id":1049},"application-monitoring","Application Monitoring",[51,1052,1053],{},[54,1054,1055,1059],{},[1056,1057,1058],"strong",{},"UI Counter Tracking",": Monitor the increase in counters directly through the application's user interface. This provides a real-time view of application usage.",[778,1061,1063],{"id":1062},"image-updates","Image Updates",[51,1065,1066],{},[54,1067,1068,1071,1072,1078],{},[1056,1069,1070],{},"Flux Image Policy",": Use the following command to check the latest image update detected by Flux:\n",[101,1073,1076],{"className":1074,"code":1075,"language":787},[785],"flux get image policy\n",[107,1077,1075],{"__ignoreMap":32},"\nThis command shows which image versions Flux is aware of and which one it considers the latest.",[778,1080,1082],{"id":1081},"pod-information","Pod Information",[51,1084,1085],{},[54,1086,1087,1090,1091,1097,1098,1101,1102,1108],{},[1056,1088,1089],{},"Kubernetes Pod Details",": To get information about the currently running pod, including the image version in use, use the following kubectl command:\n",[101,1092,1095],{"className":1093,"code":1094,"language":787},[785],"kubectl describe pod -n counter-service \u003Cpod-name>\n",[107,1096,1094],{"__ignoreMap":32},"\nReplace ",[107,1099,1100],{},"\u003Cpod-name>"," with the actual name of your pod. For example:\n",[101,1103,1106],{"className":1104,"code":1105,"language":787},[785],"kubectl describe pod -n counter-service counter-service-f5f75fc69-5wd2k\n",[107,1107,1105],{"__ignoreMap":32},"\nThis command provides detailed information about the pod, including which image version is currently deployed.",[15,1110,1112],{"id":1111},"future-enhancements-and-notes","Future Enhancements and Notes",[11,1114,1115],{},"As we continue to develop and improve this project, we've identified several areas for future enhancements and some important notes:",[778,1117,1119],{"id":1118},"infrastructure-and-gitops","Infrastructure and GitOps",[51,1121,1122,1128],{},[54,1123,1124,1127],{},[1056,1125,1126],{},"FluxCD as a Module",": Implement FluxCD as an additional Terraform module instead of installing it within the CI pipeline. This would provide better management and versioning of the GitOps tooling.",[54,1129,1130,1133],{},[1056,1131,1132],{},"CI Pipeline Structure",": Further refine the CI stages to create a more logical separation between the Terraform steps and Flux operations. This could improve pipeline clarity and maintainability.",[778,1135,1137],{"id":1136},"cicd-improvements","CI/CD Improvements",[51,1139,1140],{},[54,1141,1142,1145],{},[1056,1143,1144],{},"Merge Request Approvals",": Implement additional merge request approvals and other GitLab approval processes to enhance code quality and security.",[700,1147,1148],{},"html pre.shiki code .sCWj5, html code.shiki .sCWj5{--shiki-default:#88C0D0;--shiki-dark:#79B8FF;--shiki-sepia:#66D9EF}html pre.shiki code .siq7d, html code.shiki .siq7d{--shiki-default:#A3BE8C;--shiki-dark:#9ECBFF;--shiki-sepia:#E6DB74}html pre.shiki code .sNHwn, html code.shiki .sNHwn{--shiki-default:#88C0D0;--shiki-dark:#B392F0;--shiki-sepia:#A6E22E}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html .sepia .shiki span {color: var(--shiki-sepia);background: var(--shiki-sepia-bg);font-style: var(--shiki-sepia-font-style);font-weight: var(--shiki-sepia-font-weight);text-decoration: var(--shiki-sepia-text-decoration);}html.sepia .shiki span {color: var(--shiki-sepia);background: var(--shiki-sepia-bg);font-style: var(--shiki-sepia-font-style);font-weight: var(--shiki-sepia-font-weight);text-decoration: var(--shiki-sepia-text-decoration);}",{"title":32,"searchDepth":124,"depth":124,"links":1150},[1151,1154,1159,1164,1169,1170,1171,1172,1173,1178],{"id":748,"depth":124,"text":749,"children":1152},[1153],{"id":780,"depth":152,"text":781},{"id":792,"depth":124,"text":793,"children":1155},[1156,1157,1158],{"id":799,"depth":152,"text":800},{"id":824,"depth":152,"text":825},{"id":842,"depth":152,"text":843},{"id":881,"depth":124,"text":882,"children":1160},[1161,1162,1163],{"id":888,"depth":152,"text":889},{"id":903,"depth":152,"text":825},{"id":917,"depth":152,"text":918},{"id":924,"depth":124,"text":925,"children":1165},[1166,1167,1168],{"id":931,"depth":152,"text":932},{"id":956,"depth":152,"text":825},{"id":970,"depth":152,"text":918},{"id":980,"depth":124,"text":981},{"id":1001,"depth":124,"text":1002},{"id":1020,"depth":124,"text":1021},{"id":1027,"depth":124,"text":1028},{"id":1042,"depth":124,"text":1043,"children":1174},[1175,1176,1177],{"id":1049,"depth":152,"text":1050},{"id":1062,"depth":152,"text":1063},{"id":1081,"depth":152,"text":1082},{"id":1111,"depth":124,"text":1112,"children":1179},[1180,1181],{"id":1118,"depth":152,"text":1119},{"id":1136,"depth":152,"text":1137},"./cd.png","2024-08-06T08:00:00.000Z","IaC, Infra, AWS, EKS, Terraform, Terragrunt, FluxCD, GitLab",{"published":214},"/blog/2024/08/06/tf-tg-flux-eks",{"title":731,"description":32},"tf-tg-flux-eks","blog/2024/08/06/tf-tg-flux-eks",[723,724,1191,1192,46,1193,1194,1195],"AWS","EKS","Terragrunt","FluxCD","GitLab","iQMUr0D9yZDXUPKSEgcLleE6IMzJWyAxM5yjkryFUvU"]