본문 바로가기

Develop/DevOps

[istio] terraform istio 설치 및 Gateway & VirtualService 사용 정리

반응형

Terraform istio 설치

  • 설치 순서는 istio-base > istiod > istio-ingress 순으로 설치되게끔 dependency 설정
    • istio-base: istio의 Custom Resource Definitions(CRD)를 포함하는 기본적인 리소스 정의 역할. istio가 클러스터 내에서 작동하는데 필요한 기본적인 정의들을 포함
    • istiod: istio의 컨트롤 플레인 역할을 수행하며, 매시  내 모든 Envoy 프록시를 관리함. 서비스 간의 트래픽 제어, 인증, 관찰 가능성 제공함
    • istio-ingress: 외부에서 클러스터 내부 서비스로 트래픽을 전달하는 진입점. Kubernetes Ingress리소스와 비슷하지만 더 다양한 기능을 제공함.
locals {
  istio_charts_url = "https://istio-release.storage.googleapis.com/charts"
  istio_version    = "1.24.3"
}

resource "helm_release" "istio_base" {
  repository      = local.istio_charts_url
  chart           = "base"
  name            = "istio-base"
  namespace       = kubernetes_namespace.istio_system.metadata[0].name
  version         = local.istio_version
  cleanup_on_fail = true
}

resource "helm_release" "istiod" {
  repository      = local.istio_charts_url
  chart           = "istiod"
  name            = "istiod"
  namespace       = kubernetes_namespace.istio_system.metadata[0].name
  version         = local.istio_version
  depends_on      = [helm_release.istio_base]
  cleanup_on_fail = true
}

resource "helm_release" "istio_ingress" {
  repository      = local.istio_charts_url
  chart           = "gateway"
  name            = "istio-ingress"
  namespace       = kubernetes_namespace.istio_system.metadata[0].name
  version         = local.istio_version
  depends_on      = [helm_release.istiod]
  cleanup_on_fail = true
}

Gateway, VirtualService 관련 정리

먼저, istio를 설치하게되면 별도로 ingress controller를 설치할 필요가 없음. istio 자체가 istio ingress gateway 라는 기능을 제공하여, 이 Gateway가 istio내부 서비스로 트래픽을 전달하는 역할을 함.

 

외부 트래픽이 gateway를 통해서 들어온다면, 해당 트래픽을 어느 쿠버네티스 서비스에 보내야하는지 방향을 정해주는건 Virtualservice의 역할.

 

아래는 Gateway 리소스에서 test.jaeyung.dev로 트래픽이 들어왔을때 auth namespace에 있는 jaeyung이라는 service로 보내지게끔하는 VirtualService 리소스 예제. (Terraform 리소스 예시)

resource "kubernetes_manifest" "gateway_master" {
  manifest = {
    apiVersion = "networking.istio.io/v1"
    kind       = "Gateway"
    metadata = {
      name      = "master"
      namespace = var.istio_namespace
    }
    spec = {
      selector = {
        istio = "ingress"
      }
      servers = [
        {
          port = {
            number   = 443
            name     = "https"
            protocol = "HTTPS"
          }
          hosts = [
            "test.jaeyung.dev"
          ]
          tls = {
            mode           = "SIMPLE"
            credentialName = var.tls_secret_name
          }
        },
        {
          port = {
            number   = 80
            name     = "http"
            protocol = "HTTP"
          }
          hosts = [
            "test.jaeyung.dev"
          ]
        }
      ]
    }
  }
}

resource "kubernetes_manifest" "virtualservice_jaeyung" {
  manifest = {
    apiVersion = "networking.istio.io/v1"
    kind       = "VirtualService"
    metadata = {
      name      = "jaeyung"
      namespace = "auth"
    }
    spec = {
      hosts = ["test.jaeyung.dev"]
      gateways = [
        "${var.istio_namespace}/${kubernetes_manifest.gateway_master.manifest.metadata.name}"
      ]
      http = [
        {
          match = [
            {
              uri = {
                prefix = "/"
              }
            }
          ]
          route = [
            {
              destination = {
                host = "jaeyung"
                port = {
                  number = 80
                }
              }
            }
          ]
        },
      ]
    }
  }
}

 

Gateway에서 tls부분에 mode가 있는데 여기서 여러가지 값을 넣을수가 있음 (https://istio.io/latest/docs/reference/config/networking/gateway/#ServerTLSSettings-TLSmode)

여태까지 써본것을 적어보자면

  • SIMPLE - 제일 기본적인 TLS semantics을 적용
  • PASSTHROUGH
    • A라는 곳에서 Gateway로 외부 트래픽을 받고, A를 거쳐서 B 네트워크망에 보내야하는 상황이라면. B서비스를 접근하기 위해서는 B의 TLS를 이용해서 트래픽을 복호화 해야하는데, A의 TLS를 이용해서 복호화하게되면 문제가 발생함.
    • 따라서, 이러한 상황을 해결하기위해 A에서 받은 트래픽을 복호화 하지않고 그대로 B로 보내게끔 해주는게 PASSTHROUGH모드

 

Appendix

쿠버네티스 service에 연결된 app이 없고 특정 IP주소로 보내게끔 하려면 Service 리소스와 EndpointSlices리소스를 사용해서 만들어야한다. (Terraform 리소스 예시)

resource "kubernetes_service" "jaeyung_proxy" {
  metadata {
    name      = "jaeyung-proxy"
    namespace = var.istio_namespace
  }
  spec {
    port {
      name        = "http"
      port        = 80
      target_port = 80
    }
    port {
      name        = "https"
      port        = 443
      target_port = 443
    }
  }
}

resource "kubernetes_endpoint_slice_v1" "jaeyung_proxy" {
  metadata {
    name      = "jaeyung-proxy"
    namespace = var.istio_namespace
    labels = {
      "kubernetes.io/service-name" = "jaeyung-proxy" # endpointslice와 service의 연결
    }
  }
  address_type = "IPv4"
  endpoint {
    addresses = [
      "10.0.0.4"
    ]
    condition {
      ready = true
    }
  }
  port {
    name         = "http"
    app_protocol = "http"
    port         = 80
  }
  port {
    name         = "https"
    app_protocol = "https"
    port         = 443
  }
}
반응형