diff --git a/README.md b/README.md index b4c6d5b..f9dd846 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,87 @@ Based on the `KUBECONFIG` value, the helm chart will be installed on that partic > Due to an on-going issue with Terraform Helm Provider [[reference](https://github.com/hashicorp/terraform-provider-helm/issues/932)] which prevents the Terraform resource to pull a chart from a private GitHub repository (even after providing a GitHub PAT), we are forced to install the Helm chart locally. +## Kubernetes Provider + +We make use of the [`Terraform Kubernetes Provider`](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/namespace) to help setup the namespaces with appropriate labels. We will use these labels to install/inject [`Istio Service Mesh`](https://istio.io/v1.16/docs/setup/install/helm/) `Envoy proxy` sidecar pods to inject the ingress/egress Istio gateway. + +To setup namespaces on a cluster using the Kubernetes provider, we need to configure the `config_path` for the cluster configuration, which will tell terraform to create and configure the namespaces on that cluster. + +```tf +provider "kubernetes" { + config_path = "~/.kube/config" +} +``` + +## [Istio Service Mesh](https://istio.io/latest/docs/setup/getting-started/) + +Istio is an open-source service mesh platform designed to connect, secure, and manage microservices-based applications. A service mesh is a dedicated infrastructure layer that facilitates communication between microservices in a decentralized and resilient manner. Istio provides a set of powerful features and capabilities to address common challenges associated with microservices architectures. + +Istio is suitable for organizations adopting microservices architectures where the number of services and their interactions can become complex. It provides a centralized and consistent way to manage and secure these interactions, improving the overall reliability and observability of microservices-based applications. + +Here are key aspects and advantages of Istio: + +- **`Traffic Management`**: + - Load Balancing: Istio can evenly distribute incoming traffic across multiple instances of a service to ensure optimal resource utilization and high availability. + - Canary Releases: Istio allows you to perform controlled rollouts by gradually shifting traffic from one version of a service to another (canary releases), minimizing the risk of introducing bugs or performance issues. + +- **`Security`**: + - **Authentication and Authorization**: Istio enforces authentication and authorization policies for communication between services, ensuring that only authorized services can interact with each other. + - **Encryption**: Istio supports automatic mutual TLS (mTLS) encryption between services, adding an extra layer of security to communication. + +- **`Observability`**: + - **Monitoring**: Istio provides detailed monitoring and logging capabilities, allowing you to observe the behavior of your microservices and diagnose issues. + - **Tracing**: Istio supports distributed tracing, helping you understand the flow of requests through your microservices architecture and identify performance bottlenecks. + +- **`Resilience`**: + - **Circuit Breaking**: Istio can automatically detect when a service is failing and prevent further requests from being sent to it, allowing the system to gracefully degrade instead of cascading failures. + - **Timeouts and Retries**: Istio enables you to configure timeouts and retries for service-to-service communication, improving the resilience of your applications. + +- **`Policy Enforcement`**: + - **Rate Limiting**: Istio allows you to enforce rate limits on incoming requests to prevent abuse or ensure fair resource utilization. + - **Access Control Lists (ACLs)**: Istio lets you define fine-grained access control policies for services, restricting communication based on various criteria. + +- **`Service Mesh Federation`**: + - **Multi-Cluster Support**: Istio can be used to create a service mesh that spans multiple Kubernetes clusters, enabling communication and management across diverse environments. + +- **`Easier Development and Operations`**: + - **Automatic Sidecar Injection**: Istio deploys a sidecar proxy alongside each microservice, which handles communication and offloads concerns such as security and monitoring. This simplifies the development and operation of individual services. + +### Working with Istio + +- The istio helm charts are installed automatically and in their own namespaces. To install these charts manually without terraform, but using helm, [refer the official documentation](https://istio.io/v1.16/docs/setup/install/helm/). + +- There are 3 main Istio [charts](https://istio-release.storage.googleapis.com/charts) that we require for Istio service mesh to be fully functional: + - `istio/base`: The Istio base chart which contains cluster-wide resources used by the Istio control plane + - `istio/istiod`: The Istio discovery chart which deploys the `istiod` service + - `istio/gateway`: (Optional) Install an ingress gateway + +- To inject Envoy proxy sidecar pods to all pods in a namespace, simply add the label `istio-injection=enabled` to the namespace: + + ```bash + kubectl label namespace <namespace-name>istio-injection=enabled + ``` + +- To exclude a namespace from Envoy proxy sidecar pods, use the label `istio-injection=disabled` + + ```bash + kubectl label namespace <namespace-name>istio-injection=disabled + ``` + +- (Optional) Install `istioctl`: + +> NOTE: We will use this tool to analyze namespaces and to verify if the pods have been injected with Istio sidecar pods + +```bash +brew install istioctl +# Prints out build version information +istioctl version +# Analyze Istio configuration and print validation messages +istioctl analyze +``` + +> **NOTE**: Add the `sidecar.istio.io/inject: "false"` annotation to the metadata section of the pod template. This will prevent the Istio sidecar from being injected into that specific pod. + ## Configuring the chart values For specific `values.yaml`, refer their specific charts and create their respective `values.yaml` files based on the dummy `values.yaml` file. diff --git a/modules/istio_base/main.tf b/modules/istio_base/main.tf new file mode 100644 index 0000000..400bd9a --- /dev/null +++ b/modules/istio_base/main.tf @@ -0,0 +1,17 @@ +resource "helm_release" "istio_base_chart" { + name = "istio-base" + namespace = "istio-system" + create_namespace = true + repository = "https://istio-release.storage.googleapis.com/charts" + chart = "base" + timeout = var.timeout + cleanup_on_fail = true + force_update = false + wait = false + # When performing a revisioned installation, the base chart requires the + # `--defaultRevision` value to be set for resource validation to function. + set { + name = "defaultRevision" + value = "default" + } +} diff --git a/modules/istio_base/output.tf b/modules/istio_base/output.tf new file mode 100644 index 0000000..e69de29 diff --git a/modules/istio_base/variables.tf b/modules/istio_base/variables.tf new file mode 100644 index 0000000..038b046 --- /dev/null +++ b/modules/istio_base/variables.tf @@ -0,0 +1 @@ +variable "timeout" {} diff --git a/modules/istio_gateway/main.tf b/modules/istio_gateway/main.tf new file mode 100644 index 0000000..a24140d --- /dev/null +++ b/modules/istio_gateway/main.tf @@ -0,0 +1,11 @@ +resource "helm_release" "istio_gateway_chart" { + name = "istio-ingress" + namespace = "istio-ingress" + create_namespace = true + repository = "https://istio-release.storage.googleapis.com/charts" + chart = "gateway" + timeout = var.timeout + cleanup_on_fail = true + force_update = false + wait = false +} diff --git a/modules/istio_gateway/output.tf b/modules/istio_gateway/output.tf new file mode 100644 index 0000000..e69de29 diff --git a/modules/istio_gateway/variables.tf b/modules/istio_gateway/variables.tf new file mode 100644 index 0000000..038b046 --- /dev/null +++ b/modules/istio_gateway/variables.tf @@ -0,0 +1 @@ +variable "timeout" {} diff --git a/modules/istiod/main.tf b/modules/istiod/main.tf new file mode 100644 index 0000000..e824c62 --- /dev/null +++ b/modules/istiod/main.tf @@ -0,0 +1,11 @@ +resource "helm_release" "istiod_chart" { + name = "istiod" + namespace = "istio-system" + create_namespace = true + repository = "https://istio-release.storage.googleapis.com/charts" + chart = "istiod" + timeout = var.timeout + cleanup_on_fail = true + force_update = false + wait = true +} diff --git a/modules/istiod/output.tf b/modules/istiod/output.tf new file mode 100644 index 0000000..e69de29 diff --git a/modules/istiod/variables.tf b/modules/istiod/variables.tf new file mode 100644 index 0000000..038b046 --- /dev/null +++ b/modules/istiod/variables.tf @@ -0,0 +1 @@ +variable "timeout" {} diff --git a/modules/namespace/main.tf b/modules/namespace/main.tf new file mode 100644 index 0000000..b6aaead --- /dev/null +++ b/modules/namespace/main.tf @@ -0,0 +1,33 @@ +resource "kubernetes_namespace" "webapp_proxy_setup" { + metadata { + labels = { + istio-injection = "enabled" + } + name = "webapp" + } +} + +resource "kubernetes_namespace" "deps_proxy_setup" { + metadata { + labels = { + istio-injection = "enabled" + } + name = "deps" + } +} + +resource "kubernetes_namespace" "istio_system" { + metadata { + name = "istio-system" + } +} + +# The namespace the gateway is deployed in must not have a `istio-injection=disabled` label +resource "kubernetes_namespace" "istio_ingress" { + metadata { + labels = { + istio-injection = "enabled" + } + name = "istio-ingress" + } +} diff --git a/root/example.tfvars b/root/example.tfvars index 338ba5e..871c853 100644 --- a/root/example.tfvars +++ b/root/example.tfvars @@ -1,5 +1,6 @@ -namespace = "webapp" -timeout = 600 -values_file = "./values.yaml" -chart_path = "../modules/infra_helm/charts" -release_name = "infra-helm-release" +timeout = 600 +infra_values_file = "./infra_values.yaml" +webapp_values_file = "./webapp_values.yaml" +chart_path = "../modules/charts" +webapp_chart = "webapp-helm-chart-1.1.3.tar.gz" +infra_chart = "infra-helm-chart-1.4.0.tar.gz" diff --git a/root/main.tf b/root/main.tf index 09e14b2..f9a55a7 100644 --- a/root/main.tf +++ b/root/main.tf @@ -1,4 +1,43 @@ +module "webapp_namespace" { + source = "../modules/namespace" +} + +module "istio_base" { + depends_on = [module.webapp_namespace] + source = "../modules/istio_base" + timeout = var.timeout +} + +resource "time_sleep" "istall_istio_crds" { + depends_on = [module.istio_base] + create_duration = "20s" +} + +module "istio_discovery" { + depends_on = [time_sleep.istall_istio_crds] + source = "../modules/istiod" + timeout = var.timeout +} + +resource "time_sleep" "istall_istio_discovery" { + depends_on = [module.istio_discovery] + create_duration = "20s" +} + +module "istio_gateway" { + depends_on = [time_sleep.istall_istio_discovery] + source = "../modules/istio_gateway" + timeout = var.timeout +} + + +resource "time_sleep" "istall_istio_gateway" { + depends_on = [module.istio_gateway] + create_duration = "20s" +} + module "infra_dependencies" { + depends_on = [time_sleep.istall_istio_gateway] source = "../modules/infra_helm" timeout = var.timeout infra_values_file = var.infra_values_file diff --git a/root/provider.tf b/root/provider.tf index 16a68c7..6b9c017 100644 --- a/root/provider.tf +++ b/root/provider.tf @@ -4,6 +4,10 @@ terraform { source = "hashicorp/helm" version = "2.11.0" } + kubernetes = { + source = "hashicorp/kubernetes" + version = "2.24.0" + } } } @@ -12,3 +16,9 @@ provider "helm" { config_path = "~/.kube/config" } } + + +provider "kubernetes" { + config_path = "~/.kube/config" +} +