후니의 IT인프라 사전
[KANS-6주차] istio Gateway API 활용하기 본문
해당 실습은 블로그 글을 참조해서 작성했습니다.
이번 포스팅은 kubernetes의 Gateway API를 istio 서비스 매시와 결합하여 활용하는 방법을 실습해봅니다. Service Mesh와 Gateway API를 통합하게 되면 트래픽 모니터링, 통제, 보안성 옵션을 좀 더 다양하고 쉽게 활용할 수 있으므로 매우 유용할 것 입니다.
아키텍처
기본적으로 Gateway API를 통해서 north-south 통신(외부서비스-내부서비스 간 통신)가 가능한 단일 게이트웨이 엔드포인트를 만들어 여러 애플리케이션을 노출 할 수 있도록 합니다.
또한 istio가 담당하는 Service mesh 기능을 통해서 east-west 통신(내부 서비스 간 통신)을 제공합니다.
사전에 설치할 것들
- docker
- kubernetes cluster (Kind)
- istioctl
- kubectl
1. 사전 준비
Kind Cluster 준비
실습에서는 1대의 control-plane과 2대의 worker node를 사용합니다. 저는 가시다님 스터디에서 늘 활용하는 kind cluster yaml을 사용하여 설치하도록 하겠습니다.
cat <<EOT> kind-1node.yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
extraPortMappings:
- containerPort: 30000
hostPort: 30000
- containerPort: 30001
hostPort: 30001
EOT
# Install KinD Cluster
kind create cluster --image kindest/node:v1.30.0 --config kind-1node.yaml --name myk8s
# 노드에 기본 툴 설치
docker exec -it myk8s-control-plane sh -c 'apt update && apt install tree psmisc lsof wget bsdmainutils bridge-utils net-tools dnsutils tcpdump ngrep iputils-ping git vim -y'
# 노드/파드 확인
kubectl get nodes -o wide
kubectl get pod -A
Namespace 생성
이번 gateway api 실습을 할 gateway-api-demo 네임스페이스를 생성합니다.
kubectl create namespace gateway-api-demo
kubectl config set-context --current --namespace=gateway-api-demo
Gateway API CRD 생성
kubernetes-sigs에서 제공하는 yaml을 활용해서 설치합니다.
kubectl apply -k "github.com/kubernetes-sigs/gateway-api/config/crd?ref=v0.8.0"
Istio 설치
서비스 매시로 사용할 istio를 설치합니다. istio는 sidecar로 envoy를 사용해서 트래픽을 관리합니다. 그래서 sidecar injection을 우리가 사용할 네임스페이스에 허용해주므로써 자동으로 sidecar 생성이 될 수 있도록 합니다. 또한 활용하기 편하도록 자체 cli를 제공하고 있어 istioctl도 설치해줍니다.
brew install istioctl
istioctl install --set profile=default
kubectl label namespace gateway-api-demo istio-injection=enabled
mTLS 설정
내부 서비스들 간의 통신할 때 mTLS를 강제하기 위해서 해당 기능을 설정합니다. mTLS 설정이 없다면 평문으로 데이터를 주고 받기 때문에 보안적으로 취약합니다.
해당 기능을 설정하기 위해서 istio CRD인 PeerAuthentication 리소스를 사용합니다. 해당 리소스는 서비스들 간의 통신 보안에 관여할 수 있어 암호화나 인증설정에 사용합니다.
cat <<EOF | kubectl apply -f -
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
name: gateway-api-demo
namespace: gateway-api-demo
spec:
mtls:
mode: STRICT
EOF
2. 네트워크 설정
클러스터 내에 GatewayClass를 지정해서 네트워크 룰들을 관리합니다. 주로 회사 내의 인프라 엔지니어의 역할입니다.
GatewayClass 생성
GatewayClass는 Gateway에 대한 설정을 관리합니다. 이번 실습 간에는 Istio Gateway를 사용하기 때문에 istio gateway Controller에 관여하는 설정을 한다고 생각하면 됩니다.
cat <<EOF | kubectl apply -f -
apiVersion: gateway.networking.k8s.io/v1beta1
kind: GatewayClass
metadata:
name: my-istio-gatewayclass
spec:
controllerName: istio.io/gateway-controller
EOF
3. 트래픽 제어 설정
클러스터의 트래픽 정책과 Gateway 리소스를 생성하고 서비스 매시와 Gateway API를 통합하는 등 실질적인 설정을 진행합니다.
Gateway 리소스 생성
shared-gateway라는 단일 gateway를 생성합니다. 이 gateway는 외부에서 내부로 접근하는데 쓰이게 되며, HTTP(80)으로 접근해 backend로 다양한 애플리케이션을 제공할 예정입니다.
cat <<EOF | kubectl apply -f -
apiVersion: gateway.networking.k8s.io/v1beta1
kind: Gateway
metadata:
name: my-shared-gateway
spec:
gatewayClassName: my-istio-gatewayclass
listeners:
- name: http
protocol: HTTP
port: 80
allowedRoutes:
namespaces:
from: All
EOF
4. 애플리케이션 배포 및 트래픽 라우팅
실질적으로 사용할 애플리케이션을 배포해보겠습니다. 여기서부터는 개발자들의 영역입니다. Gateway를 통해서 접근한 트래픽이 실질적으로 여러 애플리케이션에 도달할 수 있도록 설정하게 됩니다.
Frontend 애플리케이션
먼저 frontend 입니다. 2개의 nginx파드를 가지는 deployment와 이를 연결하는 서비스를 생성합니다. 모두 TCP/80포트를 사용합니다.
cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend
spec:
replicas: 2
selector:
matchLabels:
app: frontend
template:
metadata:
labels:
app: frontend
spec:
containers:
- name: frontend
image: nginx:1.21
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: frontend
spec:
selector:
app: frontend
ports:
- protocol: TCP
port: 80
targetPort: 80
type: ClusterIP
EOF
Backend 애플리케이션
다음은 backend 애플리케이션입니다.
이 애플리케이션은 http-echo라는 컨테이너에서 hello from backend라는 글자를 표기하는 컨테이너입니다. 내부 포트는 5678을 사용하고 있습니다.
cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend
spec:
replicas: 2
selector:
matchLabels:
app: backend
template:
metadata:
labels:
app: backend
spec:
containers:
- name: backend
image: hashicorp/http-echo
args:
- "-text=Hello from Backend"
ports:
- containerPort: 5678
---
apiVersion: v1
kind: Service
metadata:
name: backend
spec:
selector:
app: backend
ports:
- protocol: TCP
port: 5678
targetPort: 5678
type: ClusterIP
EOF
5. 라우팅 설정
gateway에서 지원하는 HTTPRoute 리소스를 설정해 트래픽이 애플리케이션에 잘 도달할 수 있도록 합니다.
외부-Frontend 설정 (외부통신)
cat <<EOF | kubectl apply -f -
apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
name: frontend-route
spec:
parentRefs:
- name: my-shared-gateway
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: frontend
port: 80
EOF
Frontend-Backend 설정 (내부통신)
cat <<EOF | kubectl apply -f -
apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
name: backend-route
spec:
parentRefs:
- name: my-shared-gateway
rules:
- matches:
- path:
type: PathPrefix
value: /backend
backendRefs:
- name: backend
port: 5678
EOF
검증
Gateway의 external IP를 통해서 검증해 보겠습니다.
포트포워딩
접근이 가능하도록 호스트 로컬 컴퓨터에 포트포워딩을 설정합니다.
kubectl port-forward svc/shared-gateway 8080:80
frontend 접근
curl을 통해서 오픈한 포트인 8080을 입력하면 자동으로 80의 Frontend를 찌르게 됩니다. 정상적으로 접근됨을 확인할 수 있습니다.
curl http://localhost:8080
backend 접근
이제 백앤드로 접근이 가능한지 확인해 보겠습니다. 앞서 HTTPRoute에서 /backend 경로에 해당 backend 애플리케이션으로 접속하라고 지정했으므로 접근이 확인됩니다. 성공적으로 접근됨을 확인할 수 있습니다.
curl http://localhost:8080/backend
이상으로 istio와 gateway API를 통합해서 사용하는 실습을 마치겠습니다.