k8s에서 HTTP/2 (gRPC 서버)를로드 밸런싱하고 싶습니다.
6470 단어 GKEgRPCkubernetesenvoyhttp2
kubernetes에서 HTTP / 2를로드 밸런싱했습니다.
소개
배경
현재 학생 프로젝트에서 인프라로 GKE (Google Kubernetes Engine)를 이용하고 있습니다.
REST API 서버를 gRPC로 환장하려고 할 때 어떤 문제에 부딪혔습니다.
전제지식으로
Kubernetes의 로드 밸런서
Services are a “layer 4” (TCP/UDP over IP) construct, the proxy was purely in userspace
현재의 Kubernetes Ingress는 OSI 참조 모델의 전송 계층(L4) 로드 밸런서를 제공합니다. (베타 버전은 그러하지 않습니다!)
gRPC 통신 방법
gRPC 통신은 하나의 TCP 연결을 사용합니다.
즉, 연결이 설정되는 동안 서버와 클라이언트는 계속 연결됩니다.
문제란?
gRPC is a modern RPC protocol implemented on top of HTTP/2. HTTP/2 is a Layer 7 (Application layer) protocol
(참조: 공식 사이트에서)
그렇듯이 gRPC는 애플리케이션 계층 (L7)에서 작동합니다.
즉, L4 로드 밸런서는 제대로 부하를 분산하지 못할 수 있습니다!
Ingrees 사용할 수 없잖아!
Envoy를 만났습니다.
L7 LoadBalancer라고 조사하고 있으면 기사를 찾아왔습니다.
ref : kubernetes로 gRPC 할 때 envoy를 끼워 보았습니다.
Envoy는 클라우드 네이티브용 마이크로서비스용 프록시로 설계된 오픈 소스 소프트웨어입니다.
L7 프록시도 물론 대응입니다!
설정
그럼 조속히 도입해 갑시다!
흐름은 이런 느낌입니다.
1. gRPC 서버의 서비스를 Load Balancer에서 Headless Service로 설정
2. Envoy를 클러스터에 배포하고 외부 게시
gRPC 서버의 서비스를 Load Balancer에서 Headless Service로 설정
Envoy의 구성 파일은 이런 느낌입니다.
apiVersion: v1
kind: ConfigMap
metadata:
name: "envoy-config"
data:
envoy.json: |
{
"listeners": [
{
"address": "tcp://0.0.0.0:15001",
"filters": [
{
"type": "read",
"name": "http_connection_manager",
"config": {
"codec_type": "auto",
"stat_prefix": "ingress_http",
"route_config": {
"virtual_hosts": [
{
"name": "service",
"domains": ["*"],
"routes": [
{
"timeout_ms": 0,
"prefix": "/",
"cluster": ""
}
]
}
]
},
"filters": [
{
"type": "decoder",
"name": "router",
"config": {}
}
]
}
}
]
}
],
"admin": {
"access_log_path": "/dev/stdout",
"address": "tcp://127.0.0.1:8001"
},
"cluster_manager": {
"clusters": [
{
"name": "rakusale-grpc",
"features": "http2",
"connect_timeout_ms": 250,
"type": "strict_dns",
"lb_type": "round_robin",
"hosts": [{"url": "tcp://Host名:Port番号"}]
}
]
}
}
주목하고 싶은 곳은 여기입니다!
"cluster_manager": {
"clusters": [
{
"name": "rakusale-grpc",
"features": "http2",
"connect_timeout_ms": 250,
"type": "strict_dns",
"lb_type": "round_robin",
"hosts": [{"url": "tcp://Host名:Port番号"}]
}
]
}
clusters["hosts"]에서 서버 측 IP와 포트를 지정합니다.
즉, Envoy 측이 부하 분산을 위해 Pod의 IP를 알아야 합니다.
여기서 Headless Service
헤드리스 서비스는 서비스에 DNS 요청을 보내면 포드의 IP를 반환합니다.
움직이고 싶은 서버의 서비스는 이렇게 설정하고 있습니다.
apiVersion: v1
kind: Service
metadata:
labels:
name: ""
name: ""
spec:
clusterIP: None
ports:
- name: ""
port: 3001
protocol: TCP
targetPort: 3001
selector:
app: ""
ClusterIP: None으로만 하면 Headless Service가 됩니다!
Envoy를 클러스터에 배포하고 외부 게시
필요한 것은 세 가지입니다.
- envoy_configmap.yaml : 아까 소개하고 있습니다!
- envoy_deployment.yaml
- envoy_service.yaml
envoy_deployment.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: "envoy"
spec:
replicas: 2
template:
metadata:
labels:
app: "envoy"
spec:
volumes:
- name: envoy
configMap:
name: "envoy-config"
# - name: tls
# secret:
# secretName: tlssecret
containers:
- name: envoy
image: envoyproxy/envoy:6e3633496f5a9412abdca8bac7db6b701ae8ce14
command:
- "/usr/local/bin/envoy"
args:
- "--config-path /etc/envoy/envoy.json"
resources:
limits:
memory: 512Mi
ports:
- containerPort: 15001
name: app
- containerPort: 8001
name: envoy-admin
volumeMounts:
- name: envoy
mountPath: /etc/envoy
# - name: tls
# mountPath: /etc/tlssecret
# readOnly: true
envoy_service.yaml
apiVersion: v1
kind: Service
metadata:
labels:
name: "envoy"
name: "envoy-service"
spec:
type: LoadBalancer
selector:
app: "envoy"
ports:
- name: tcp
port: 15001
targetPort: 15001
이상을 준비해 kubectl apply
하고 GIP에 접속하면, 부하 분산이 완성되어 있을 것입니다!
끝에
Kubernetes 클러스터 내의 패킷이나 네트워크 감시하는 툴로 좋은 것이 있으면 가르쳐 주었으면 합니다!
그리고, gRPC서버 쓸 때에 로그를 제대로 쓰는 구현으로 하지 않으면 마음 불편하다고 생각했습니다,,,
항상 프레임워크를 해주었기 때문에,,,
앞으로도 정진하겠습니다.
Reference
이 문제에 관하여(k8s에서 HTTP/2 (gRPC 서버)를로드 밸런싱하고 싶습니다.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/tozastation/items/37c593b91c788e1f306d
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
apiVersion: v1
kind: ConfigMap
metadata:
name: "envoy-config"
data:
envoy.json: |
{
"listeners": [
{
"address": "tcp://0.0.0.0:15001",
"filters": [
{
"type": "read",
"name": "http_connection_manager",
"config": {
"codec_type": "auto",
"stat_prefix": "ingress_http",
"route_config": {
"virtual_hosts": [
{
"name": "service",
"domains": ["*"],
"routes": [
{
"timeout_ms": 0,
"prefix": "/",
"cluster": ""
}
]
}
]
},
"filters": [
{
"type": "decoder",
"name": "router",
"config": {}
}
]
}
}
]
}
],
"admin": {
"access_log_path": "/dev/stdout",
"address": "tcp://127.0.0.1:8001"
},
"cluster_manager": {
"clusters": [
{
"name": "rakusale-grpc",
"features": "http2",
"connect_timeout_ms": 250,
"type": "strict_dns",
"lb_type": "round_robin",
"hosts": [{"url": "tcp://Host名:Port番号"}]
}
]
}
}
"cluster_manager": {
"clusters": [
{
"name": "rakusale-grpc",
"features": "http2",
"connect_timeout_ms": 250,
"type": "strict_dns",
"lb_type": "round_robin",
"hosts": [{"url": "tcp://Host名:Port番号"}]
}
]
}
apiVersion: v1
kind: Service
metadata:
labels:
name: ""
name: ""
spec:
clusterIP: None
ports:
- name: ""
port: 3001
protocol: TCP
targetPort: 3001
selector:
app: ""
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: "envoy"
spec:
replicas: 2
template:
metadata:
labels:
app: "envoy"
spec:
volumes:
- name: envoy
configMap:
name: "envoy-config"
# - name: tls
# secret:
# secretName: tlssecret
containers:
- name: envoy
image: envoyproxy/envoy:6e3633496f5a9412abdca8bac7db6b701ae8ce14
command:
- "/usr/local/bin/envoy"
args:
- "--config-path /etc/envoy/envoy.json"
resources:
limits:
memory: 512Mi
ports:
- containerPort: 15001
name: app
- containerPort: 8001
name: envoy-admin
volumeMounts:
- name: envoy
mountPath: /etc/envoy
# - name: tls
# mountPath: /etc/tlssecret
# readOnly: true
apiVersion: v1
kind: Service
metadata:
labels:
name: "envoy"
name: "envoy-service"
spec:
type: LoadBalancer
selector:
app: "envoy"
ports:
- name: tcp
port: 15001
targetPort: 15001
Reference
이 문제에 관하여(k8s에서 HTTP/2 (gRPC 서버)를로드 밸런싱하고 싶습니다.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/tozastation/items/37c593b91c788e1f306d텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)