diff --git a/.github/workflows/develop-pipeline.yaml b/.github/workflows/develop-pipeline.yaml index 853abf1..7137002 100644 --- a/.github/workflows/develop-pipeline.yaml +++ b/.github/workflows/develop-pipeline.yaml @@ -1,4 +1,4 @@ -name: Build and Deploy to Local Kubernetes +name: develop pipeline clean, package and push to ghcr on: push: diff --git a/.github/workflows/feature-pipeline.yaml b/.github/workflows/feature-pipeline.yaml index 28f07b1..776d1f5 100644 --- a/.github/workflows/feature-pipeline.yaml +++ b/.github/workflows/feature-pipeline.yaml @@ -1,4 +1,4 @@ -name: Build and Deploy to Local Kubernetes +name: feature pipeline and package on: push: diff --git a/.github/workflows/terraform-deploy.yaml b/.github/workflows/terraform-deploy.yaml new file mode 100644 index 0000000..816f519 --- /dev/null +++ b/.github/workflows/terraform-deploy.yaml @@ -0,0 +1,44 @@ +name: Deploy Infrastructure To Azure + +on: + push: + branches: + - 'apply/**' + +jobs: + terraform: + runs-on: ubuntu-latest + + env: + TF_VAR_db_admin_password: ${{ secrets.DB_ADMIN_PASSWORD }} + + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Parse environment from branch + id: env + run: | + BRANCH_NAME="${GITHUB_REF#refs/heads/}" + ENV_NAME="${BRANCH_NAME#apply/}" + echo "env_name=$ENV_NAME" >> $GITHUB_OUTPUT + + - name: Azure Login + uses: azure/login@v1 + with: + creds: ${{ secrets.AZURE_CREDENTIALS }} + + - name: Setup Terraform + uses: hashicorp/setup-terraform@v2 + + - name: Terraform Init + run: terraform init + working-directory: terraform/environments/${{ steps.env.outputs.env_name }} + + - name: Terraform Plan + run: terraform plan -var-file="terraform.tfvars" + working-directory: terraform/environments/${{ steps.env.outputs.env_name }} + + - name: Terraform Apply + run: terraform apply -auto-approve -var-file="terraform.tfvars" + working-directory: terraform/environments/${{ steps.env.outputs.env_name }} \ No newline at end of file diff --git a/helm/order-service/chart.yaml b/helm/order-service/chart.yaml new file mode 100644 index 0000000..67393bc --- /dev/null +++ b/helm/order-service/chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v2 +name: order-service +description: A Helm chart for Kubernetes +type: application # application or library +version: 0.1.0 # chart version +appVersion: "1.0" # version of the application \ No newline at end of file diff --git a/helm/order-service/templates/deployment.yaml b/helm/order-service/templates/deployment.yaml new file mode 100644 index 0000000..84f87f3 --- /dev/null +++ b/helm/order-service/templates/deployment.yaml @@ -0,0 +1,25 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Chart.Name }} + labels: + app: {{ .Chart.Name }} +spec: + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + app: {{ .Chart.Name }} + template: + metadata: + labels: + app: {{ .Chart.Name }} + spec: + containers: + - name: {{ .Chart.Name }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + ports: + - containerPort: {{ .Values.service.targetPort }} + env: + - name: SPRING_PROFILES_ACTIVE + value: {{ .Values.env.SPRING_PROFILES_ACTIVE }} \ No newline at end of file diff --git a/helm/order-service/templates/ingress.yaml b/helm/order-service/templates/ingress.yaml new file mode 100644 index 0000000..bce70f0 --- /dev/null +++ b/helm/order-service/templates/ingress.yaml @@ -0,0 +1,21 @@ +{{- if .Values.ingress.enabled }} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ .Chart.Name }} + labels: + app: {{ .Chart.Name }} + annotations: + kubernetes.io/ingress.class: {{ .Values.ingress.className }} +spec: + rules: + - host: {{ .Values.ingress.host }} + http: + paths: + path: {{ .Values.ingress.path }} + pathType: {{ .Values.ingress.pathType }} + backend: + service: + name: {{ .Chart.Name }} + port: + number: {{ .Values.service.port }} diff --git a/helm/order-service/templates/service.yaml b/helm/order-service/templates/service.yaml new file mode 100644 index 0000000..4a3cdf2 --- /dev/null +++ b/helm/order-service/templates/service.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ .Chart.Name }} + labels: + app: {{ .Chart.Name }} +spec: + type: {{ .Values.service.type }} + selector: + app: {{ .Chart.Name }} + ports: + - protocol: TCP + port: {{ .Values.service.port }} + targetPort: {{ .Values.service.targetPort }} \ No newline at end of file diff --git a/helm/order-service/values-prod.yaml b/helm/order-service/values-prod.yaml new file mode 100644 index 0000000..12f2add --- /dev/null +++ b/helm/order-service/values-prod.yaml @@ -0,0 +1,17 @@ +replicaCount: 2 +image: + repository: ghcr.io/devsocket/order-service # change to azure acr + pullPolicy: IfNotPresent + tag: "latest" # Overrides the image tag whose default is the chart appVersion +service: + type: ClusterIP + port: 80 + targetPort: 8085 +ingress: + enabled: true # Enable ingress for the service + className: azure/application-gateway # Specify the ingress class name + host: order-service.prod.ecommerce.com + path: /api/v1/orders + pathType: Prefix +env: + SPRING_PROFILES_ACTIVE: prod \ No newline at end of file diff --git a/helm/order-service/values-qa.yaml b/helm/order-service/values-qa.yaml new file mode 100644 index 0000000..c50ed94 --- /dev/null +++ b/helm/order-service/values-qa.yaml @@ -0,0 +1,17 @@ +replicaCount: 1 +image: + repository: ghcr.io/devsocket/order-service + pullPolicy: IfNotPresent + tag: "latest" # Overrides the image tag whose default is the chart appVersion +service: + type: ClusterIP + port: 80 + targetPort: 8081 +ingress: + enabled: true # Enable ingress for the service + className: azure/application-gateway # Specify the ingress class name + host: order-service.qa.ecommerce.com + path: /api/v1/orders + pathType: Prefix +env: + SPRING_PROFILES_ACTIVE: qa \ No newline at end of file diff --git a/helm/product-service/chart.yaml b/helm/product-service/chart.yaml new file mode 100644 index 0000000..2f46a32 --- /dev/null +++ b/helm/product-service/chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v2 +name: product-service +description: A Helm chart for Kubernetes +type: application # application or library +version: 0.1.0 # chart version +appVersion: "1.0" # version of the application \ No newline at end of file diff --git a/helm/product-service/templates/deployment.yaml b/helm/product-service/templates/deployment.yaml new file mode 100644 index 0000000..84f87f3 --- /dev/null +++ b/helm/product-service/templates/deployment.yaml @@ -0,0 +1,25 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Chart.Name }} + labels: + app: {{ .Chart.Name }} +spec: + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + app: {{ .Chart.Name }} + template: + metadata: + labels: + app: {{ .Chart.Name }} + spec: + containers: + - name: {{ .Chart.Name }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + ports: + - containerPort: {{ .Values.service.targetPort }} + env: + - name: SPRING_PROFILES_ACTIVE + value: {{ .Values.env.SPRING_PROFILES_ACTIVE }} \ No newline at end of file diff --git a/helm/product-service/templates/ingress.yaml b/helm/product-service/templates/ingress.yaml new file mode 100644 index 0000000..bce70f0 --- /dev/null +++ b/helm/product-service/templates/ingress.yaml @@ -0,0 +1,21 @@ +{{- if .Values.ingress.enabled }} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ .Chart.Name }} + labels: + app: {{ .Chart.Name }} + annotations: + kubernetes.io/ingress.class: {{ .Values.ingress.className }} +spec: + rules: + - host: {{ .Values.ingress.host }} + http: + paths: + path: {{ .Values.ingress.path }} + pathType: {{ .Values.ingress.pathType }} + backend: + service: + name: {{ .Chart.Name }} + port: + number: {{ .Values.service.port }} diff --git a/helm/product-service/templates/service.yaml b/helm/product-service/templates/service.yaml new file mode 100644 index 0000000..4a3cdf2 --- /dev/null +++ b/helm/product-service/templates/service.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ .Chart.Name }} + labels: + app: {{ .Chart.Name }} +spec: + type: {{ .Values.service.type }} + selector: + app: {{ .Chart.Name }} + ports: + - protocol: TCP + port: {{ .Values.service.port }} + targetPort: {{ .Values.service.targetPort }} \ No newline at end of file diff --git a/helm/product-service/values-prod.yaml b/helm/product-service/values-prod.yaml new file mode 100644 index 0000000..feff114 --- /dev/null +++ b/helm/product-service/values-prod.yaml @@ -0,0 +1,17 @@ +replicaCount: 2 +image: + repository: ghcr.io/devsocket/product-service + pullPolicy: IfNotPresent + tag: "latest" # Overrides the image tag whose default is the chart appVersion +service: + type: ClusterIP + port: 80 + targetPort: 8081 +ingress: + enabled: true # Enable ingress for the service + className: azure/application-gateway # Specify the ingress class name + host: product-service.prod.ecommerce.com + path: /api/v1/products + pathType: Prefix +env: + SPRING_PROFILES_ACTIVE: prod \ No newline at end of file diff --git a/helm/product-service/values-qa.yaml b/helm/product-service/values-qa.yaml new file mode 100644 index 0000000..29a598a --- /dev/null +++ b/helm/product-service/values-qa.yaml @@ -0,0 +1,17 @@ +replicaCount: 1 +image: + repository: ghcr.io/devsocket/product-service + pullPolicy: IfNotPresent + tag: "latest" # Overrides the image tag whose default is the chart appVersion +service: + type: ClusterIP + port: 80 + targetPort: 8081 +ingress: + enabled: true # Enable ingress for the service + className: azure/application-gateway # Specify the ingress class name + host: product-service.qa.ecommerce.com + path: /api/v1/products + pathType: Prefix +env: + SPRING_PROFILES_ACTIVE: qa \ No newline at end of file diff --git a/helm/user-service/chart.yaml b/helm/user-service/chart.yaml new file mode 100644 index 0000000..0d6e402 --- /dev/null +++ b/helm/user-service/chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v2 +name: user-service +description: A Helm chart for Kubernetes +type: application # application or library +version: 0.1.0 # chart version +appVersion: "1.0" # version of the application \ No newline at end of file diff --git a/helm/user-service/templates/deployment.yaml b/helm/user-service/templates/deployment.yaml new file mode 100644 index 0000000..84f87f3 --- /dev/null +++ b/helm/user-service/templates/deployment.yaml @@ -0,0 +1,25 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Chart.Name }} + labels: + app: {{ .Chart.Name }} +spec: + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + app: {{ .Chart.Name }} + template: + metadata: + labels: + app: {{ .Chart.Name }} + spec: + containers: + - name: {{ .Chart.Name }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + ports: + - containerPort: {{ .Values.service.targetPort }} + env: + - name: SPRING_PROFILES_ACTIVE + value: {{ .Values.env.SPRING_PROFILES_ACTIVE }} \ No newline at end of file diff --git a/helm/user-service/templates/ingress.yaml b/helm/user-service/templates/ingress.yaml new file mode 100644 index 0000000..bce70f0 --- /dev/null +++ b/helm/user-service/templates/ingress.yaml @@ -0,0 +1,21 @@ +{{- if .Values.ingress.enabled }} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ .Chart.Name }} + labels: + app: {{ .Chart.Name }} + annotations: + kubernetes.io/ingress.class: {{ .Values.ingress.className }} +spec: + rules: + - host: {{ .Values.ingress.host }} + http: + paths: + path: {{ .Values.ingress.path }} + pathType: {{ .Values.ingress.pathType }} + backend: + service: + name: {{ .Chart.Name }} + port: + number: {{ .Values.service.port }} diff --git a/helm/user-service/templates/service.yaml b/helm/user-service/templates/service.yaml new file mode 100644 index 0000000..4a3cdf2 --- /dev/null +++ b/helm/user-service/templates/service.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ .Chart.Name }} + labels: + app: {{ .Chart.Name }} +spec: + type: {{ .Values.service.type }} + selector: + app: {{ .Chart.Name }} + ports: + - protocol: TCP + port: {{ .Values.service.port }} + targetPort: {{ .Values.service.targetPort }} \ No newline at end of file diff --git a/helm/user-service/values-prod.yaml b/helm/user-service/values-prod.yaml new file mode 100644 index 0000000..adcdbed --- /dev/null +++ b/helm/user-service/values-prod.yaml @@ -0,0 +1,17 @@ +replicaCount: 2 +image: + repository: ghcr.io/devsocket/user-service # change to azure acr + pullPolicy: IfNotPresent + tag: "latest" # Overrides the image tag whose default is the chart appVersion +service: + type: ClusterIP + port: 80 + targetPort: 8085 +ingress: + enabled: true # Enable ingress for the service + className: azure/application-gateway # Specify the ingress class name + host: user-service.prod.ecommerce.com + path: /api/v1/users + pathType: Prefix +env: + SPRING_PROFILES_ACTIVE: prod \ No newline at end of file diff --git a/helm/user-service/values-qa.yaml b/helm/user-service/values-qa.yaml new file mode 100644 index 0000000..069046f --- /dev/null +++ b/helm/user-service/values-qa.yaml @@ -0,0 +1,17 @@ +replicaCount: 1 +image: + repository: ghcr.io/devsocket/user-service + pullPolicy: IfNotPresent + tag: "latest" # Overrides the image tag whose default is the chart appVersion +service: + type: ClusterIP + port: 80 + targetPort: 8081 +ingress: + enabled: true # Enable ingress for the service + className: azure/application-gateway # Specify the ingress class name + host: user-service.qa.ecommerce.com + path: /api/v1/users + pathType: Prefix +env: + SPRING_PROFILES_ACTIVE: qa \ No newline at end of file diff --git a/terraform/environments/qa/backend.tf b/terraform/environments/qa/backend.tf new file mode 100644 index 0000000..8f99fa4 --- /dev/null +++ b/terraform/environments/qa/backend.tf @@ -0,0 +1,8 @@ +terraform { + backend "azurerm" { + resource_group_name = "tf-state-rg" + storage_account_name = "tfstateaccount" + container_name = "tfstate" + key = "qa.terraform.tfstate" + } +} \ No newline at end of file diff --git a/terraform/environments/qa/main.tf b/terraform/environments/qa/main.tf new file mode 100644 index 0000000..43f0860 --- /dev/null +++ b/terraform/environments/qa/main.tf @@ -0,0 +1,86 @@ +terraform { + required_version = ">= 1.5.0" + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = ">= 3.50.0" + } + kubernetes = { + source = "hashicorp/kubernetes" + version = ">= 2.9.0" + } + helm = { + source = "hashicorp/helm" + version = ">= 2.20.0" + } + } +} + +module "network" { + source = "../../modules/network" + resource_group_name = var.resource_group_name + location = var.location + vnet_name = "ecommerce-qa-vnet" + aks_subnet_name = "aks-subnet" + db_subnet_name = "db-subnet" + aks_subnet_prefix = "10.0.1.0/24" + db_subnet_prefix = "10.0.2.0/24" + tags = var.tags + +} +module "aks" { + source = "../../modules/aks" + resource_group_name = var.resource_group_name + location = var.location + cluster_name = var.cluster_name +} + +module "key_vault" { + source = "../../modules/key_vault" + resource_group_name = var.resource_group_name + location = var.location + key_vault_name = var.key_vault_name +} + +module "event_hub" { + source = "../../modules/event_hub" + resource_group_name = var.resource_group_name + location = var.location + event_hub_namespace_name = var.event_hub_namespace_name +} + +module "postgresql" { + source = "../../modules/postgresql" + resource_group_name = var.resource_group_name + location = var.location + postgres_name = var.postgres_name +} + +module "product-service" { + source = "../../modules/helm-deploy" + cluster_name = module.aks.cluster_name + kube_config = module.aks.kube_config + namespace = "qa" + release_name = "product-service" + helm_chart_path = "../../helm/product-service" + values_file = "../../helm/product-service/values-qa.yaml" +} + +module "order-service" { + source = "../../modules/helm-deploy" + cluster_name = module.aks.cluster_name + kube_config = module.aks.kube_config + helm_chart_path = "../../helm/order-service" + release_name = "order-service" + namespace = "qa" + values_file = "../../helm/order-service/values-qa.yaml" +} +module "user-service" { + source = "../../modules/helm-deploy" + cluster_name = module.aks.cluster_name + kube_config = module.aks.kube_config + helm_chart_path = "../../helm/user-service" + release_name = "user-service" + namespace = "qa" + values_file = "../../helm/user-service/values-qa.yaml" +} \ No newline at end of file diff --git a/terraform/environments/qa/terraform.tfvars b/terraform/environments/qa/terraform.tfvars new file mode 100644 index 0000000..7d23598 --- /dev/null +++ b/terraform/environments/qa/terraform.tfvars @@ -0,0 +1,10 @@ +resource_group_name = "ecommerce-qa-rg" +location = "East US" +cluster_name = "ecommerce-qa-aks" +key_vault_name = "ecommerce-qa-kv" +event_hub_namespace_name = "ecommerce-qa-eh" +postgres_name = "ecommerce-qa-db" +db_admin_password = "SuperSecretPassword@123" +tags = { + environment = "qa" +} \ No newline at end of file diff --git a/terraform/environments/qa/variables.tf b/terraform/environments/qa/variables.tf new file mode 100644 index 0000000..1a3f30a --- /dev/null +++ b/terraform/environments/qa/variables.tf @@ -0,0 +1,11 @@ +variable "resource_group_name" {} +variable "location" {} +variable "cluster_name" {} +variable "key_vault_name" {} +variable "event_hub_namespace_name" {} +variable "postgres_name" {} +variable "db_admin_password" {} +variable "tags" { + type = map(string) + default = {} +} \ No newline at end of file diff --git a/terraform/modules/aks/main.tf b/terraform/modules/aks/main.tf new file mode 100644 index 0000000..70ac4de --- /dev/null +++ b/terraform/modules/aks/main.tf @@ -0,0 +1,18 @@ +resource "azurerm_kubernetes_cluster" "this" { + name = var.cluster_name + location = var.location + resource_group_name = var.resource_group_name + dns_prefix = "${var.cluster_name}-dns" + + default_node_pool { + name = "default" + node_count = 2 + vm_size = "Standard_DS2_v2" + } + + identity { + type = "SystemAssigned" + } + + tags = var.tags +} \ No newline at end of file diff --git a/terraform/modules/aks/outputs.tf b/terraform/modules/aks/outputs.tf new file mode 100644 index 0000000..323ce20 --- /dev/null +++ b/terraform/modules/aks/outputs.tf @@ -0,0 +1,9 @@ +output "cluster_name" { + description = "The name of the AKS cluster" + value = azurerm_kubernetes_cluster.this.name +} + +output "kube_config" { + description = "The kube config of the AKS cluster" + value = azurerm_kubernetes_cluster.this.kube_config_raw +} \ No newline at end of file diff --git a/terraform/modules/aks/variables.tf b/terraform/modules/aks/variables.tf new file mode 100644 index 0000000..cdfbaa2 --- /dev/null +++ b/terraform/modules/aks/variables.tf @@ -0,0 +1,11 @@ +variable "cluster_name" {} +variable "location" {} +variable "resource_group_name" {} +variable "node_count" { + type = number + default = 3 +} +variable "tags" { + type = map(string) + default = {} +} \ No newline at end of file diff --git a/terraform/modules/eventhub/main.tf b/terraform/modules/eventhub/main.tf new file mode 100644 index 0000000..e706224 --- /dev/null +++ b/terraform/modules/eventhub/main.tf @@ -0,0 +1,7 @@ +resource "azurerm_eventhub_namespace" "this" { + name = var.event_hub_namespace_name + location = var.location + resource_group_name = var.resource_group_name + sku = "Standard" + capacity = 1 +} \ No newline at end of file diff --git a/terraform/modules/eventhub/variables.tf b/terraform/modules/eventhub/variables.tf new file mode 100644 index 0000000..4cdcc50 --- /dev/null +++ b/terraform/modules/eventhub/variables.tf @@ -0,0 +1,3 @@ +variable "event_hub_namespace_name" {} +variable "location" {} +variable "resource_group_name" {} \ No newline at end of file diff --git a/terraform/modules/helm-deploy/main.tf b/terraform/modules/helm-deploy/main.tf new file mode 100644 index 0000000..f4ba0ab --- /dev/null +++ b/terraform/modules/helm-deploy/main.tf @@ -0,0 +1,17 @@ +provider "helm" { + kubernetes { + host = var.kube_config["host"] + client_certificate = base64encode(var.kube_config["client_certificate"]) + client_key = base64encode(var.kube_config["client_key"]) + cluster_ca_certificate = base64encode(var.kube_config["cluster_ca_certificate"]) + } +} + +resource "helm_release" "this" { + name = var.release_name + chart = var.helm_chart_path + namespace = var.namespace + values = [file(var.values_file)] + create_namespace = true + +} \ No newline at end of file diff --git a/terraform/modules/helm-deploy/variables.tf b/terraform/modules/helm-deploy/variables.tf new file mode 100644 index 0000000..8a1b0d2 --- /dev/null +++ b/terraform/modules/helm-deploy/variables.tf @@ -0,0 +1,6 @@ +variable "release_name" {} +variable "helm_chart_path" {} +variable "namespace" {} +variable "values_file" {} +variable "kube_config" { type = map(string)} +variable "cluster_name" {} \ No newline at end of file diff --git a/terraform/modules/keyvault/main.tf b/terraform/modules/keyvault/main.tf new file mode 100644 index 0000000..1a27cbc --- /dev/null +++ b/terraform/modules/keyvault/main.tf @@ -0,0 +1,23 @@ +data "azurerm_client_config" "current" {} + +resource "azurerm_key_vault" "this" { + name = var.key_vault_name + location = var.location + resource_group_name = var.resource_group_name + tenant_id = data.azurerm_client_config.current.tenant_id + sku_name = "standard" + purge_protection_enabled = false + soft_delete_retention_days = 7 + + access_policy { + tenant_id = data.azurerm_client_config.current.tenant_id + object_id = data.azurerm_client_config.current.object_id + + secret_permissions = [ + "Get", + "List", + "Set", + "Delete" + ] + } +} \ No newline at end of file diff --git a/terraform/modules/keyvault/variables.tf b/terraform/modules/keyvault/variables.tf new file mode 100644 index 0000000..ef6a90e --- /dev/null +++ b/terraform/modules/keyvault/variables.tf @@ -0,0 +1,3 @@ +variable "key_vault_name" {} +variable "location" {} +variable "resource_group_name" {} \ No newline at end of file diff --git a/terraform/modules/network/main.tf b/terraform/modules/network/main.tf new file mode 100644 index 0000000..6833f90 --- /dev/null +++ b/terraform/modules/network/main.tf @@ -0,0 +1,43 @@ +resource "azurerm_virtual_network" "this" { + name = var.vnet_name + address_space = var.address_space + location = var.location + resource_group_name = var.resource_group_name + tags = var.tags +} + +resource "azurerm_subnet" "aks" { + name = var.aks_subnet_name + resource_group_name = var.resource_group_name + virtual_network_name = azurerm_virtual_network.this.name + address_prefixes = [var.aks_subnet_prefix] +} +resource "azurerm_subnet" "db" { + name = var.db_subnet_name + resource_group_name = var.resource_group_name + virtual_network_name = azurerm_virtual_network.this.name + address_prefixes = [var.db_subnet_prefix] +} +resource "azurerm_network_security_group" "aks_nsg" { + name = "${var.vnet_name}-aks-nsg" + location = var.location + resource_group_name = var.resource_group_name + security_rule = [ { + name = "AllowKubeAPI" + priority = 100 + direction = "Inbound" + access = "Allow" + protocol = "Tcp" + source_port_range = "*" + destination_port_range = "443" + source_address_prefix = "*" + destination_address_prefix = "*" + } + ] + tags = var.tags +} + +resource "azurerm_subnet_network_security_group_association" "aks_nsg_association" { + subnet_id = azurerm_subnet.aks.id + network_security_group_id = azurerm_network_security_group.aks_nsg.id +} diff --git a/terraform/modules/network/outputs.tf b/terraform/modules/network/outputs.tf new file mode 100644 index 0000000..9d17294 --- /dev/null +++ b/terraform/modules/network/outputs.tf @@ -0,0 +1,14 @@ +output "vnet_id" { + description = "The ID of the VNet" + value = azurerm_virtual_network.this.id +} + +output "aks_subnet_id" { + description = "The ID of the AKS Subnet" + value = azurerm_subnet.aks.id +} + +output "db_subnet_id" { + description = "The ID of the DB Subnet" + value = azurerm_subnet.db.id +} \ No newline at end of file diff --git a/terraform/modules/network/variables.tf b/terraform/modules/network/variables.tf new file mode 100644 index 0000000..57c2271 --- /dev/null +++ b/terraform/modules/network/variables.tf @@ -0,0 +1,23 @@ +variable "vnet_name" {} +variable "location" {} +variable "resource_group_name" {} +variable "address_space" { + type = list(string) + default = ["10.0.0.0/16"] +} +variable "aks_subnet_name" { + default = "aks-subnet" +} +variable "aks_subnet_prefix" { + default = "10.0.1.0/24" +} +variable "db_subnet_name" { + default = "db-subnet" +} +variable "db_subnet_prefix" { + default = "10.0.2.0/24" +} +variable "tags" { + type = map(string) + default = {} +} \ No newline at end of file diff --git a/terraform/modules/postgres/main.tf b/terraform/modules/postgres/main.tf new file mode 100644 index 0000000..ebbbd24 --- /dev/null +++ b/terraform/modules/postgres/main.tf @@ -0,0 +1,12 @@ +resource "azurerm_postgresql_flexible_server" "this" { + name = var.postgres_name + location = var.location + resource_group_name = var.resource_group_name + administrator_login = "adminuser" + administrator_password = var.admin_password + sku_name = "Standard_B1ms" + version = "13" + storage_mb = 32768 + backup_retention_days = 7 + geo_redundant_backup_enabled = false +} \ No newline at end of file diff --git a/terraform/modules/postgres/variables.tf b/terraform/modules/postgres/variables.tf new file mode 100644 index 0000000..be84dc0 --- /dev/null +++ b/terraform/modules/postgres/variables.tf @@ -0,0 +1,4 @@ +variable "postgres_name" {} +variable "location" {} +variable "resource_group_name" {} +variable "admin_password" {} \ No newline at end of file diff --git a/terraform/shared/providers.tf b/terraform/shared/providers.tf new file mode 100644 index 0000000..ba7c0b6 --- /dev/null +++ b/terraform/shared/providers.tf @@ -0,0 +1,19 @@ +provider "azurerm" { + features {} +} + +provider "kubernetes" { + host = var.kube_config["host"] + client_certificate = base64decode(var.kube_config["client_certificate"]) + client_key = base64decode(var.kube_config["client_key"]) + cluster_ca_certificate = base64decode(var.kube_config["cluster_ca_certificate"]) +} + +provider "helm" { + kubernetes { + host = var.kube_config["host"] + client_certificate = base64decode(var.kube_config["client_certificate"]) + client_key = base64decode(var.kube_config["client_key"]) + cluster_ca_certificate = base64decode(var.kube_config["cluster_ca_certificate"]) + } +} \ No newline at end of file diff --git a/terraform/shared/versions.tf b/terraform/shared/versions.tf new file mode 100644 index 0000000..3619a51 --- /dev/null +++ b/terraform/shared/versions.tf @@ -0,0 +1,17 @@ +terraform { + required_version = ">= 1.5.0" + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = ">= 3.50.0" + } + kubernetes = { + source = "hashicorp/kubernetes" + version = ">= 2.9.0" + } + helm = { + source = "hashicorp/helm" + version = ">= 2.20.0" + } + } +} \ No newline at end of file