[Service Discovery?]
Service Discovery 패턴은 분산 시스템, 특히 마이크로서비스 아키텍처에서 서비스 간의 통신을 용이하게 하기 위한 핵심 패턴으로 작용한다. 이 패턴은 네트워크 위치가 동적으로 변경될 수 있는 서비스 인스턴스의 위치를 자동으로 감지하고 추적하는 메커니즘을 제공한다.
Service Discovery는 크게 클라이언트 사이드와 서버 사이드 두 가지 방식으로 구현된다. 클라이언트 사이드 방식에서는 서비스를 호출하는 클라이언트가 직접 레지스트리에 쿼리하여 가용한 서비스 인스턴스 목록을 받아 선택한다. 반면 서버 사이드 방식에서는 중앙 로드 밸런서나 API 게이트웨이가 레지스트리를 참조하여 클라이언트 요청을 적절한 서비스 인스턴스로 라우팅한다.
이 패턴의 핵심 구성 요소는 서비스 레지스트리로, 모든 서비스 인스턴스의 네트워크 위치 정보를 저장하고 관리한다. 각 서비스 인스턴스는 시작 시 자신의 위치 정보를 레지스트리에 등록하고, 종료 시 등록을 해제한다. 또한 대부분의 서비스 디스커버리 솔루션은 헬스 체크 메커니즘을 통해 각 서비스 인스턴스의 가용성을 주기적으로 확인한다.
실제 구현에는 Consul, Eureka, etcd, ZooKeeper 등과 같은 도구들이 널리 사용되며, Kubernetes와 같은 컨테이너 오케스트레이션 플랫폼에서는 내장된 서비스 디스커버리 기능을 제공한다. 클라우드 제공업체들도 AWS의 Route 53, Azure의 Service Fabric과 같은 관리형 서비스 디스커버리 솔루션을 제공한다.
Service Discovery 패턴을 통해 개발자는 하드코딩된 서비스 위치 정보에 의존할 필요 없이 동적이고 탄력적인 서비스 환경을 구축할 수 있다. 이는 자동 확장, 장애 복구, 무중단 배포와 같은 클라우드 네이티브 기능을 효과적으로 지원하며, 시스템의 전반적인 복원력과 확장성을 향상시킨다. 결과적으로 마이크로서비스 아키텍처의 복잡성을 관리하고 신뢰성 높은 서비스 간 통신을 보장하는 데 필수적인 패턴으로 자리 잡고 있다.
(출처: https://www.f5.com/company/blog/nginx/service-discovery-in-a-microservices-architecture)
그러다가 마이크로 서비스가 늘어나면서 네트워크 복잡성 증가 및 공통 기능 적용(서킷브레이커, 재시도 로직, 타임아웃, 인증 등)의 요구사항 이 생김 → Service Mesh의 탄생!
[Service Mesh]
https://aws.amazon.com/what-is/service-mesh/
서비스 메시는 애플리케이션의 서비스 간 모든 통신을 처리하는 소프트웨어 계층이다. 이 계층은 컨테이너화된 마이크로서비스로 구성된다. 애플리케이션이 확장되고 마이크로서비스의 수가 증가함에 따라 서비스의 성능을 모니터링하기가 점점 어려워지고 있다. 서비스 메시는 서비스 간 연결을 관리하기 위해 모니터링, 로깅, 추적, 트래픽 제어와 같은 새로운 기능을 제공한다. 이러한 기능은 각 서비스의 코드와 독립적이므로 네트워크 경계를 넘어 여러 서비스 관리 시스템에서 작동할 수 있다.
동작 원리 -> 컨테이너 애플리케이션 앞에 AWS AppMesh, Istio, Linkerd 등의 사이드카 프록시 컨테이너를 배치
즉, 컨테이너 애플리케이션으로 들어오고 나가는 모든 트래픽은 프록시 컨테이너를 통해 라우팅 되는 방식
[이러한 방식의 애플리케이션 네트워킹의 한계점]
Ingress의 한계
Service Mesh의 한계
또한, 클라우드 환경에서 점차 마이크로 서비스가 확장되고 인프라 구성이 복잡해짐에 따라 아래와 같은 요구사항도 생겨났다.
이러한 한계를 극복하기 위해 SIG-NETWORK 커뮤니티에서 Gateway API가 고안되었습니다. Gateway API는 다음과 같은 목표를 가지고 설계되었다.
[주요 구성 요소]
Amazon VPC Lattice 는 AWS에서 제공하는 완전관리형 애플리케이션 네트워킹 서비스로, 다양한 컴퓨팅 환경에서 애플리케이션 서비스를 연결, 보호 및 모니터링하는 통합 솔루션입니다. VPC Lattice는 단일 VPC 내에서는 물론, 계정 간 여러 VPC에 걸쳐 서비스를 연결하는 데 활용할 수 있다.
[구성 요소]
AWS Gateway API Controller는 Gateway API에 의해 정의된 사용자 지정 리소스를 확장하여 Kubernetes API를 사용하여 VPC Lattice 리소스를 생성한다. 이 Controller가 클러스터에 설치되면 Controller는 Gateway API의 리소스(Gateway 및 Route)의 생성을 감시하고 적절한 Amazon VPC Lattice 오브젝트를 프로비저닝 하며, 이를 통해 사용자는 커스텀 코드를 작성하거나 사이드카 프록시를 관리할 필요 없이 Kubernetes API를 사용하여 VPC Lattice Service, VPC Lattice Service Network 및 Target Group을 구성할 수 있게 된다.
해당 실습에서는 Amazon EKS Blueprints for Terraform : Amazon VPC Lattice - Simple Client to Server Communication
을 활용하며, VPC quota가 늘려져 있지 않은 상태라 실습하는 화면의 캡처본으로 대신했다.
git clone https://github.com/aws-ia/terraform-aws-eks-blueprints.git
cd terraform-aws-eks-blueprints/patterns/vpc-lattice/client-server-communication
# region 값 수정
terraform init
terraform apply -target="module.client_vpc" -auto-approve
terraform apply -target="module.cluster_vpc" -auto-approve
terraform apply -target=aws_route53_zone.primary -auto-approve
terraform apply -target="module.client_sg" -auto-approve
terraform apply -target="module.endpoint_sg" -auto-approve
terraform apply -target="module.client" -auto-approve
terraform apply -target="module.vpc_endpoints" -auto-approve
terraform apply -target="module.eks" -auto-approve
terraform apply -target="module.addons" -auto-
kubectl get po -A
파드가 조회되는 것을 확인할 수 있다.
[프로비저닝 된 인프라 확인]
2개의 VPC가 생성된 것을 확인할 수 있다.
10.1.0.0/16
CIDR 주소 범위로 구성되어 있다.10.0.0.0/16
CIDR 주소 범위로 구성되어 있다.Service networks에 association된 VPC들을 확인할 수 있다.
[VPC Lattice를 통한 Client to Server 통신 테스트]
kubectl logs -f deployment/server -n apps --all-containers=true --since=1m
아래에서는 kubectl logs 명령어로 애플리케이션 로그를 실시간으로 모니터링하고,
curl -i http://server.example.com
위 터미널에서는 curl 명령어로 네트워크 통신 테스트를 진행한다.
되는 이유: VPC Lettice를 사용해 도메인이 등록되었기 때문이다.
(확인) Route53에서 확인하면 server.example.com => vpc lattice service에 등록이 되어 있다
[AWS Gateway API Controller의 동작 체크]
kubectl logs deployment/aws-gateway-api-controller-aws-gateway-controller-chart -n aws-application-networking-system --all-containers=true > lattice.log
아래의 vi 명령을 통해 로그를 조회하면, AWS Gateway API Controller의 동작을 확인 해볼 수 있다.
vi lattice.log
로그의 내용처럼 EKS 클러스터 내에 GatewayClass, Gateway, Route에 대한 오브젝트가 추가되면 AWS Gateway API Controller에서 이를 감지하여 조정(reconcile)하게 되는 것이다.
server
라는 이름의 service와 my-services
라는 이름의 gateway의 생성을 감지하여, reconcile 작업을 수행한다.server-apps
라는 이름(HTTPRoute의 metadata.name 및 metadata.namespace를 사용)으로 구성된 Route 대상에 라우팅 하기 위해 server.example.com
이라는 사용자 지정 도메인 이름을 세팅하고, VPC Lattice Service를 구성한다. 멀티 클러스터 환경 간에서 Amazon VPC Lattice를 활용한 안전한 통신 방법에 대해 실습을 진행한다.
이 패턴에서는 Amazon VPC Lattice와 IAM authorization을 사용하여 서로 다른 VPC에 있는 두 EKS 클러스터 간의 안전한 멀티 클러스터 통신 방식을 보여주게 된다.
[envoy proxy란?]
Envoy Proxy는 고성능 C++ 기반의 오픈소스 에지 및 서비스 프록시로, 2016년 Lyft에서 처음 개발되었으며 현재는 Cloud Native Computing Foundation(CNCF)의 졸업 프로젝트이다. 모던 서비스 아키텍처 환경에서 네트워크 통신을 단순화하고 추상화하기 위해 설계되었다.
주요 특징
1. 고성능 아키텍처
C++로 작성된 고성능 단일 프로세스 멀티스레드 설계를 가진다.
작은 메모리 공간에서 높은 처리량과 낮은 지연 시간을 제공한다.
비동기 이벤트 기반 아키텍처로 많은 연결을 효율적으로 처리한다.
L3/L4 프록시
TCP 프록싱, HTTP/1.1, HTTP/2, HTTP/3, gRPC 등을 위한 견고한 지원을 제공한다.
소켓 수준에서 작동하여 모든 TCP 기반 프로토콜을 처리할 수 있다.
SNI(Server Name Indication) 기반 라우팅을 지원한다.
L7 프록시
풍부한 라우팅 기능, 경로 기반 분할, 리트라이, 서킷 브레이킹 등을 지원한다.
HTTP 헤더 조작, URL 재작성, 속도 제한 등의 고급 기능을 제공한다.
gRPC를 포함한 다양한 프로토콜에 대한 심층 통합을 제공한다.
동적 구성
xDS API라고 하는 동적 구성 API를 통해 런타임에 구성을 업데이트할 수 있다.
제어 플레인과의 느슨한 결합을 통해 다양한 환경에서 유연하게 사용할 수 있다.
핫 리스타트 기능으로 다운타임 없이 구성을 변경할 수 있다.
관찰성
포괄적인 통계, 로깅, 분산 추적 기능을 제공한다.
Prometheus, Grafana, Zipkin, Jaeger 등의 도구와 통합이 용이하다.
상세한 모니터링 데이터를 통해 시스템 동작 및 성능에 대한 인사이트를 제공한다.
확장성
필터 체인을 통한 확장 가능한 아키텍처를 가진다.
WebAssembly(WASM) 필터를 통해 안전한 사용자 정의 확장을 지원한다.
Lua 스크립팅을 통한 런타임 구성 조정이 가능하다.
environment 프로비저닝을 진행한다.
테라폼 코드 살펴보기!
main.tf
provider "aws" {
region = local.region
}
locals {
name = "vpc-lattice"
region = "us-west-2" # 이 부분을 ap-northeast-2로 수정
domain = var.custom_domain_name
tags = {
Blueprint = local.name
GithubRepo = "github.com/aws-ia/terraform-aws-eks-blueprints"
}
}
#-------------------------------
# Create Private Hosted Zone
#-------------------------------
resource "aws_route53_zone" "private_zone" {
name = local.domain
vpc {
vpc_id = aws_vpc.example.id
}
#we will add vpc association in other terraform stack, prevent this one to revert this
lifecycle {
ignore_changes = [
vpc,
]
}
force_destroy = true
tags = local.tags
}
#dummy VPC that will not be used, but needed to create private hosted zone
resource "aws_vpc" "example" {
cidr_block = "10.0.0.0/16"
tags = {
Name = "Example VPC"
}
}
Route 53 프라이빗 호스티드 존을 생성한다:
local.domain
값을 사용한다.example
VPC와 연결된다.lifecycle
설정으로 향후 다른 테라폼 스택에서 VPC 연결을 변경해도 이 구성이 덮어쓰지 않도록 한다.force_destroy = true
는 리소스 삭제 시 연결된 레코드도 함께 삭제하도록 설정한다.예시용 VPC를 생성한다:
################################################################################
# Create IAM role to talk to VPC Lattice services and get Certificate from Manager
################################################################################
data "aws_iam_policy_document" "eks_assume" {
statement {
effect = "Allow"
principals {
type = "Service"
identifiers = ["pods.eks.amazonaws.com"]
}
actions = ["sts:AssumeRole", "sts:TagSession"]
}
}
resource "aws_iam_role" "vpc_lattice_role" {
name = "${local.name}-sigv4-client"
description = "IAM role for aws-sigv4-client VPC Lattice access"
assume_role_policy = data.aws_iam_policy_document.eks_assume.json
}
resource "aws_iam_role_policy_attachment" "vpc_lattice_invoke_access" {
role = aws_iam_role.vpc_lattice_role.name
policy_arn = "arn:aws:iam::aws:policy/VPCLatticeServicesInvokeAccess"
}
resource "aws_iam_role_policy_attachment" "private_ca_read_only" {
role = aws_iam_role.vpc_lattice_role.name
policy_arn = "arn:aws:iam::aws:policy/AWSCertificateManagerPrivateCAReadOnly"
}
IAM 정책 문서를 정의한다:
pods.eks.amazonaws.com
서비스가 sts:AssumeRole
과 sts:TagSession
작업을 수행할 수 있도록 허용한다.VPC Lattice 접근을 위한 IAM 역할을 생성한다:
vpc-lattice-sigv4-client
로 설정된다.이 역할에 두 가지 관리형 정책을 연결한다:
VPCLatticeServicesInvokeAccess
: VPC Lattice 서비스 호출 권한을 제공한다.AWSCertificateManagerPrivateCAReadOnly
: ACM Private CA에 대한 읽기 전용 권한을 제공한다.pca.tf
#-------------------------------
# Associates a certificate with an AWS Certificate Manager Private Certificate Authority (ACM PCA Certificate Authority).
# An ACM PCA Certificate Authority is unable to issue certificates until it has a certificate associated with it.
# A root level ACM PCA Certificate Authority is able to self-sign its own root certificate.
#-------------------------------
# # https://docs.aws.amazon.com/acm-pca/latest/userguide/pca-rbp.html
resource "aws_acmpca_certificate_authority" "this" {
enabled = true
type = "ROOT"
certificate_authority_configuration {
key_algorithm = "RSA_4096"
signing_algorithm = "SHA512WITHRSA"
subject {
common_name = var.custom_domain_name
organization = var.organization
}
}
permanent_deletion_time_in_days = 7
tags = local.tags
}
resource "aws_acmpca_certificate" "this" {
certificate_authority_arn = aws_acmpca_certificate_authority.this.arn
certificate_signing_request = aws_acmpca_certificate_authority.this.certificate_signing_request
signing_algorithm = "SHA512WITHRSA"
template_arn = "arn:aws:acm-pca:::template/RootCACertificate/V1"
validity {
type = "YEARS"
value = 10
}
}
resource "aws_acmpca_certificate_authority_certificate" "this" {
certificate_authority_arn = aws_acmpca_certificate_authority.this.arn
certificate = aws_acmpca_certificate.this.certificate
certificate_chain = aws_acmpca_certificate.this.certificate_chain
}
#-------------------------------
# Create certificate in AWS Certificate Manager
#-------------------------------
resource "aws_acm_certificate" "private_domain_cert" {
domain_name = var.custom_domain_name
#validation_method = "DNS"
subject_alternative_names = [
"*.${var.custom_domain_name}"
]
options {
certificate_transparency_logging_preference = "DISABLED"
}
certificate_authority_arn = aws_acmpca_certificate_authority.this.arn
tags = local.tags
}
VPC Lattice 서비스에서 사용할 프라이빗 CA와 인증서를 설정하는 과정이다. 프라이빗 CA를 사용하면 조직 내부에서만 신뢰되는 인증서를 발급할 수 있으며, 이는 내부 서비스 간의 암호화된 통신에 유용하다. 특히, 이 설정은 내부 전용 서비스에 대한 커스텀 도메인을 설정하고 보안 통신을 가능하게 한다.
terraform init
terraform apply --auto-approve
그 이후에 cluster도 마찬가지로 배포한다.
./deploy.sh cluster1
# 배포 완료 후, 아래 명령으로 kubectl config 설정을 완료합니다.
eval `terraform output -raw configure_kubectl`
./deploy.sh cluster2
# 배포 완료 후, 아래 명령으로 kubectl config 설정을 완료합니다.
eval `terraform output -raw configure_kubectl`
vpc 1, 2 두 개의 vpc가 만들어지게 된다.
eks-cluster1의 pod identity가 기본적으로 설정되어 있는데, iam의 권한을 받아서 private ca를 활용해서 https 프로토콜을 사용하게 하기 위해서이다.
[VPC Lattice]
VPC 콘솔 > PrivateLink and Lattice > Service networks > VPC Lattice Service network 콘솔로 이동
각 데모 애플리케이션으로 들어가는 타겟 그룹이 설정되어 있다.
[통신 테스트 및 동작 방식 확인]
kubectl --context eks-cluster1 \
exec -ti -n apps deployments/demo-cluster1-v1 -c demo-cluster1-v1 \
-- curl demo-cluster2.example.com
결과가 잘 나온다.
kubectl --context eks-cluster1 \
exec -ti -n apps deployments/demo-cluster1-v1 -c demo-cluster1-v1 \
-- curl demo-cluster1.example.com
권한 오류가 난다.
=> IAMAuthPolicy가 적용이 되어서 eks-cluster2로만 호출이 가능하기 때문
kubectl --context eks-cluster1 \
get IAMAuthPolicy -n apps demo-cluster1-iam-auth-policy \
-o json | jq ".spec.policy | fromjson"
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::12345678910:root"
},
"Action": "vpc-lattice-svcs:Invoke",
"Resource": "*",
"Condition": {
"StringEquals": {
"aws:PrincipalTag/eks-cluster-name": "eks-cluster2",
"aws:PrincipalTag/kubernetes-namespace": "apps"
}
}
}
]
}
=> VPC Lattice Serivce를 invoke하는 액션 중에서 클러스터 명(eks-cluster-name)이 eks-cluster2 여야하고, 네임스페이스가 apps일 때에만 Invoke를 허용한다.
결과적으로 이 데모 애플리케이션 Pod가 IAMAuthPolicy의 규칙을 적용받고 있음을 확인할 수 있다.
이렇게 IAMAuthPolicy를 사용하면 멀티 클러스터 간에 각 애플리케이션에 대한 액세스 제어를 쉽게 구성할 수 있게 된다.
[Kyverno의 역할]
kubectl --context eks-cluster1 \
exec -it deploy/demo-cluster1-v1 -c envoy-sigv4 -n apps \
-- cat /usr/local/bin/launch_envoy.sh
#!/bin/sh
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: MIT-0
cat /etc/envoy/envoy.yaml.in | envsubst \$AWS_REGION,\$JWT_AUDIENCE,\$JWT_JWKS,\$JWT_ISSUER,\$JWKS_HOST,\$APP_DOMAIN > /etc/envoy/envoy.yaml
aws acm-pca get-certificate-authority-certificate --certificate-authority-arn $CA_ARN --region $AWS_REGION --output text > /etc/pki/ca-trust/source/anchors/internal.pem
update-ca-trust extract
cat /etc/envoy/envoy.yaml
/usr/local/bin/envoy --base-id 1 -l trace -c /etc/envoy/envoy.yaml
launch_envoy.sh에서 활용하는 envoy.yaml.in 스크립트
static_resources:
listeners:
- name: http_connect
address:
socket_address:
protocol: TCP
address: 0.0.0.0
port_value: 8080
filter_chains:
- filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
stat_prefix: ingress_http
route_config:
name: local_route
virtual_hosts:
- name: local_service
domains:
- "*"
routes:
- match:
prefix: '/'
route:
cluster: outbound_proxy
# Ignore traffic to /health and respond with a 200
http_filters:
- name: envoy.filters.http.dynamic_forward_proxy
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.dynamic_forward_proxy.v3.FilterConfig
dns_cache_config:
name: dynamic_forward_proxy_cache_config
dns_lookup_family: V4_ONLY
typed_dns_resolver_config:
name: envoy.network.dns_resolver.cares
typed_config:
"@type": type.googleapis.com/envoy.extensions.network.dns_resolver.cares.v3.CaresDnsResolverConfig
use_resolvers_as_fallback: true
resolvers:
- socket_address:
address: "127.0.0.1"
port_value: 53
dns_resolver_options:
use_tcp_for_dns_lookups: true
no_default_search_domain: true
# SigV4 signing configuration
- name: envoy.filters.http.aws_request_signing
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.aws_request_signing.v3.AwsRequestSigning
service_name: vpc-lattice-svcs
region: ${AWS_REGION}
use_unsigned_payload: true
match_excluded_headers:
- prefix: x-envoy
- prefix: x-forwarded
- exact: x-amzn-trace-id
- name: envoy.filters.http.router
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
clusters:
- name: outbound_proxy
lb_policy: CLUSTER_PROVIDED
cluster_type:
name: envoy.clusters.dynamic_forward_proxy
typed_config:
"@type": type.googleapis.com/envoy.extensions.clusters.dynamic_forward_proxy.v3.ClusterConfig
dns_cache_config:
name: dynamic_forward_proxy_cache_config
dns_lookup_family: V4_ONLY
typed_dns_resolver_config:
name: envoy.network.dns_resolver.cares
typed_config:
"@type": type.googleapis.com/envoy.extensions.network.dns_resolver.cares.v3.CaresDnsResolverConfig
use_resolvers_as_fallback: true
resolvers:
- socket_address:
address: "127.0.0.1"
port_value: 53
dns_resolver_options:
use_tcp_for_dns_lookups: true
no_default_search_domain: true
transport_socket:
name: envoy.transport_sockets.tls
typed_config:
"@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext
common_tls_context:
validation_context:
trusted_ca:
filename: /etc/ssl/certs/ca-bundle.crt
이 YAML 파일은 Envoy 프록시의 구성 파일로, AWS VPC Lattice 서비스와 통합하기 위한 설정을 포함한다. Envoy는 오픈소스 에지/서비스 프록시로, 이 구성은 특히 VPC Lattice 서비스로 요청을 전달하고 AWS SigV4 인증을 수행하도록 설정되어 있다.
listeners:
- name: http_connect
address:
socket_address:
protocol: TCP
address: 0.0.0.0
port_value: 8080
http_connect
라는 이름의 리스너를 설정한다.0.0.0.0
)의 8080 포트에서 들어오는 연결을 수신한다.filter_chains:
- filters:
- name: envoy.filters.network.http_connection_manager
route_config:
name: local_route
virtual_hosts:
- name: local_service
domains:
- "*"
routes:
- match:
prefix: '/'
route:
cluster: outbound_proxy
"*"
)에 대한 요청을 처리한다./
)로 시작하는 모든 요청을 outbound_proxy
클러스터로 라우팅한다.a. 동적 포워드 프록시 필터
- name: envoy.filters.http.dynamic_forward_proxy
b. AWS 요청 서명 필터
- name: envoy.filters.http.aws_request_signing
vpc-lattice-svcs
)에 대한 AWS SigV4 인증을 수행한다.${AWS_REGION}
)을 사용한다.use_unsigned_payload: true
)을 사용한다.x-envoy
, x-forwarded
, x-amzn-trace-id
)는 서명 계산에서 제외한다.c. 라우터 필터
- name: envoy.filters.http.router
clusters:
- name: outbound_proxy
lb_policy: CLUSTER_PROVIDED
cluster_type:
name: envoy.clusters.dynamic_forward_proxy
outbound_proxy
라는 이름의 클러스터를 정의한다.transport_socket:
name: envoy.transport_sockets.tls
typed_config:
"@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext
common_tls_context:
validation_context:
trusted_ca:
filename: /etc/ssl/certs/ca-bundle.crt
/etc/ssl/certs/ca-bundle.crt
)을 사용하여 서버 인증서를 검증한다.[실습 리소스 정리]
cd /workshop/terraform-aws-eks-blueprints/patterns/vpc-lattice/cross-cluster-pod-communication/cluster/
./destroy.sh cluster2
./destroy.sh cluster1
SN=$(aws vpc-lattice list-service-networks --query 'items[?name==`lattice-gateway`].id' --output text)
if [ -n "$SN" ]; then
aws vpc-lattice delete-service-network --service-network-id "$SN"
fi
cd /workshop/terraform-aws-eks-blueprints/patterns/vpc-lattice/cross-cluster-pod-communication/environment/
terraform destroy -auto-approve
나중에 추가로 도전해볼 것