istio 스터디 2주차 내용을 정리하였다.

Istio 프록시의 실제 동작 도구인 Envoy 프록시에 대한 내용과 secure istio에 대한 내용을 다루었다.

그럼시작한다.

Envoy란 ?

Envoy는 원래 Lyft에서 개발된 고성능 오픈소스 프록시(proxy)입니다. 주로 마이크로서비스 아키텍처에서 서비스 간 트래픽을 중계하고, 로드밸런싱, 서비스 디스커버리, TLS 암호화, 서킷 브레이커, 트래픽 라우팅, 모니터링 등 다양한 네트워크 기능을 제공한다. Envoy의 가장 큰 특징은 API 기반의 실시간 설정 업데이트와 뛰어난 가시성과 성능이다.

istio가 Envoy 프록시를 사이드카로 활용하여 서비스 메시를 구현하고, 트래픽 관리·보안·모니터링 등 다양한 기능을 제공하는 오픈소스 플랫폼이기 때문에 Envoy 프록시를 필히 알아야 한다.

Envoy의 가장 큰 장점은 동적 구성(Dynamic Configuration)과 API 기반 관리이다.
이 장점 덕분에 실시간으로 프록시 설정(트래픽 라우팅, 보안 정책, 로드밸런싱 등)을 변경할 수 있고, 서비스 중단 없이 네트워크 정책을 빠르게 반영할 수 있다.

예를 들어, 대규모 마이크로서비스 환경에서 특정 서비스에 장애가 발생했을 때, 운영자는 Envoy의 xDS API를 통해 실시간으로 트래픽을 우회하거나 라우팅 정책을 수정할 수 있다. 이 과정에서 애플리케이션이나 프록시를 재시작할 필요가 없으므로, 서비스 연속성과 가용성을 향상 시킬 수 있다. DevOps 엔지니어 입장에서는 배포 자동화 파이프라인이나 운영 도구와 연동해 네트워크 정책을 코드로 관리하고, 장애 대응이나 신규 서비스 추가 시에도 빠르고 유연하게 대응할 수 있다.

Envoy 실습

docker pull envoyproxy/envoy:v1.19.0
docker pull curlimages/curl
docker pull mccutchen/go-httpbin

# mccutchen/go-httpbin 는 기본 8080 포트여서, 책 실습에 맞게 8000으로 변경
# docker run -d -e PORT=8000 --name httpbin mccutchen/go-httpbin -p 8000:8000
docker run -d -e PORT=8000 --name httpbin mccutchen/go-httpbin 
docker ps

# curl 컨테이너로 httpbin 호출 확인
docker run -it --rm --link httpbin curlimages/curl curl -X GET http://httpbin:8000/headers

여기까지는 envoy를 타지않고 httpbin 컨테이너로 바로 접속한 모습이다.

admin:  # Envoy 관리 인터페이스 설정
  address:  # 관리 인터페이스 주소 구성
    socket_address: { address: 0.0.0.0, port_value: 15000 }  # 모든 IP에서 15000 포트로 관리 인터페이스 개방

static_resources:  # 정적 리소스 정의(리스너, 클러스터 등)
  listeners:  # 트래픽 수신을 위한 리스너 목록
  - name: httpbin-demo  # 리스너 식별 이름
    address:  # 리스너 바인딩 주소
      socket_address: { address: 0.0.0.0, port_value: 15001 }  # 모든 IP에서 15001 포트로 트래픽 수신
    filter_chains:  # 필터 체인 구성
    - filters:  # 네트워크 필터 목록
      - name:  envoy.filters.network.http_connection_manager  # HTTP 연결 관리 필터 사용
        typed_config:  # 타입 지정 구성
          "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager  # gRPC API 타입 지정
          stat_prefix: ingress_http  # 메트릭 접두사 설정
          http_filters:  # HTTP 필터 스택
          - name: envoy.filters.http.router  # 라우터 필터 사용(기본 요청 라우팅)
          route_config:  # 라우팅 구성
            name: httpbin_local_route  # 라우트 구성 이름
            virtual_hosts:  # 가상 호스트 목록
            - name: httpbin_local_service  # 가상 호스트 이름
              domains: ["*"]  # 모든 도메인 매칭
              routes:  # 라우팅 규칙 목록
              - match: { prefix: "/" }  # 모든 경로(/로 시작) 매칭
                route:  # 라우팅 대상 설정
                  auto_host_rewrite: true  # 업스트림 호스트 헤더 자동 재작성
                  cluster: httpbin_service  # 타겟 클러스터 지정
  clusters:  # 업스트림 서비스 클러스터 정의
    - name: httpbin_service  # 클러스터 이름
      connect_timeout: 5s  # 연결 타임아웃 설정(5초)
      type: LOGICAL_DNS  # DNS 기반 서비스 디스커버리 사용
      dns_lookup_family: V4_ONLY  # IPv4 전용 DNS 조회
      lb_policy: ROUND_ROBIN  # 라운드 로빈 로드 밸런싱 정책
      load_assignment:  # 엔드포인트 할당 정보
        cluster_name: httpbin  # 대상 클러스터 이름(실제 서비스 이름)
        endpoints:  # 엔드포인트 그룹
        - lb_endpoints:  # 로드밸런싱 대상 엔드포인트
          - endpoint:  # 단일 엔드포인트 설정
              address:  # 대상 주소
                socket_address:  # 소켓 주소 지정
                  address: httpbin  # 서비스 도메인 주소(httpbin)
                  port_value: 8000  # 대상 포트(8000)

위의 설정파일을 사용하여 엔보이를 실행시킨다.

그리고 다음 명령어로 envoy

docker run --name proxy --link httpbin envoyproxy/envoy:v1.19.0 --config-yaml "$(cat ch3/simple.yaml)"

그다음 다시 다음 명령어로 엔보이 컨테이너로 붙어본다.

docker run -it --rm --link proxy curlimages/curl curl -X GET http://proxy:15001/headers

그럼 다음 화면처럼 아까완 다른 헤더값

  • X-Envoy-Expected-Rq-Timeout-Ms
  • X-Request-Id

들이 추가되면서 결국 httpbin 의 결과가 출력되는것을 알 수 있다. 이는 곧 엔보이 프록시를 통해 httpbin 컨테이너에 접속된것을 알 수 있다.

이것들은 envoy의 설정을 바꾸면 해당값도 바뀐다.

              - match: { prefix: "/" }
                route:
                  auto_host_rewrite: true
                  cluster: httpbin_service
                  timeout: 1s

보는것처럼 타임아웃 값이 1.5초에서 1초로 바뀐것을 알 수 있다.

# 추가 테스트 : Envoy Admin API(TCP 15000) 를 통해 delay 설정
docker run -it --rm --link proxy curlimages/curl curl -X POST http://proxy:15000/logging
docker run -it --rm --link proxy curlimages/curl curl -X POST http://proxy:15000/logging?http=debug

docker run -it --rm --link proxy curlimages/curl curl -X GET http://proxy:15001/delay/0.5
docker run -it --rm --link proxy curlimages/curl curl -X GET http://proxy:15001/delay/1
docker run -it --rm --link proxy curlimages/curl curl -X GET http://proxy:15001/delay/2
upstream request timeout

위와같이 현재 엔보이 프록시의 로그 설정을 확인할 수 있고 또 debug 모드로도 변경할 수 있다.

그리고 아까 타임아웃을 1초로 해둔 상태인데, delay를 0.5와 1초 했을 때의 결과를 다음과같이 확인 할 수 있다.

Envoy's Admin API를 사용하면 프록시 동작에 대해 이해할 수 있고 메트릭과 설정에 접근 할 수 있다.

docker run -it --rm --link proxy curlimages/curl curl -X GET http://proxy:15000/stats/prometheus # 엔보이 통계(프로메테우스 레코드 형식)

특히 위와같은 접근으로 프로메테우스 형식의 메트릭을 접근할 수 있다.

이를 활용하여 이스티오 관련 모니터링 대시보드를 만들 수 있을것이다. 예를들면 다음과 같다.

https://grafana.com/orgs/istio/dashboards

[istio Dashboards | Grafana Labs

uploaded on February 28, 2020 Downloads: 33513582 Reviews: 0

grafana.com](https://grafana.com/orgs/istio/dashboards)

docker rm -f proxy

#
cat ch3/simple_retry.yaml
docker run -p 15000:15000 --name proxy --link httpbin envoyproxy/envoy:v1.19.0 --config-yaml "$(cat ch3/simple_retry.yaml)"
docker run -it --rm --link proxy curlimages/curl curl -X POST http://proxy:15000/logging?http=debug

# /stats/500 경로로 프록시를 호출 : 이 경로로 httphbin 호출하면 오류가 발생
docker run -it --rm --link proxy curlimages/curl curl -X GET http://proxy:15001/status/500

# 호출이 끝났는데 아무런 응답도 보이지 않는다. 엔보이 Admin API에 확인
docker run -it --rm --link proxy curlimages/curl curl -X GET http://proxy:15000/stats | grep retry

위 스크립트는 1주차때 진행했던 500 에러 발생시 재시도 하는 테스트이다.

앞선 1주차때 했떤 이스티오 설정과 동일하게 엔보이에서도(당연히) 3회 시도에 대한 메트릭을 확인할 수 있다.

Summary

  • Envoy는 애플리케이션이 애플리케이션 수준의 동작에 사용할 수 있는 프록시입니다.
  • Envoy는 이스티오의 데이터 플레인입니다.
  • Envoy는 클라우드 신뢰성 문제(네트워크 장애, 토폴로지 변경, 탄력성)를 일관되고 정확하게 해결하는 데 도움을 줄 수 있습니다.
  • Envoy는 런타임 제어를 위해 동적 API를 사용합니다(Istio는 이를 사용합니다).
  • Envoy는 애플리케이션 사용 및 프록시 내부에 대한 강력한 지표와 정보를 많이 노출합니다.

istio 실습

실습 환경 구성

실제 실습을 진행하면서, 추가로 현재 운영중인 istio 환경도 함께 확인해볼 예정이다.

K8s 설치

#
git clone https://github.com/AcornPublishing/istio-in-action
cd istio-in-action/book-source-code-master
pwd # 각자 자신의 pwd 경로
code .

# 아래 extramounts 생략 시, myk8s-control-plane 컨테이너 sh/bash 진입 후 직접 git clone 가능
kind create cluster --name myk8s --image kindest/node:v1.23.17 --config - <<EOF
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
  extraPortMappings:
  - containerPort: 30000 # Sample Application (istio-ingrssgateway) HTTP
    hostPort: 30000
  - containerPort: 30001 # Prometheus
    hostPort: 30001
  - containerPort: 30002 # Grafana
    hostPort: 30002
  - containerPort: 30003 # Kiali
    hostPort: 30003
  - containerPort: 30004 # Tracing
    hostPort: 30004
  - containerPort: 30005 # Sample Application (istio-ingrssgateway) HTTPS
    hostPort: 30005
  - containerPort: 30006 # TCP Route
    hostPort: 30006
  - containerPort: 30007 # New Gateway 
    hostPort: 30007
  extraMounts: # 해당 부분 생략 가능
  - hostPath: /Users/gasida/Downloads/istio-in-action/book-source-code-master # 각자 자신의 pwd 경로로 설정
    containerPath: /istiobook
networking:
  podSubnet: 10.10.0.0/16
  serviceSubnet: 10.200.1.0/24
EOF

# 설치 확인
docker ps

# 노드에 기본 툴 설치
docker exec -it myk8s-control-plane sh -c 'apt update && apt install tree psmisc lsof wget bridge-utils net-tools dnsutils tcpdump ngrep iputils-ping git vim -y'

# (옵션) metrics-server
helm repo add metrics-server https://kubernetes-sigs.github.io/metrics-server/
helm install metrics-server metrics-server/metrics-server --set 'args[0]=--kubelet-insecure-tls' -n kube-system
kubectl get all -n kube-system -l app.kubernetes.io/instance=metrics-server

istio 설치

# myk8s-control-plane 진입 후 설치 진행
docker exec -it myk8s-control-plane bash
-----------------------------------
# (옵션) 코드 파일들 마운트 확인
tree /istiobook/ -L 1
혹은
git clone ... /istiobook

# istioctl 설치
export ISTIOV=1.17.8
echo 'export ISTIOV=1.17.8' >> /root/.bashrc

curl -s -L https://istio.io/downloadIstio | ISTIO_VERSION=$ISTIOV sh -
cp istio-$ISTIOV/bin/istioctl /usr/local/bin/istioctl
istioctl version --remote=false

# default 프로파일 컨트롤 플레인 배포
istioctl install --set profile=default -y

# 설치 확인 : istiod, istio-ingressgateway, crd 등
kubectl get istiooperators -n istio-system -o yaml
kubectl get all,svc,ep,sa,cm,secret,pdb -n istio-system
kubectl get cm -n istio-system istio -o yaml
kubectl get crd | grep istio.io | sort

# 보조 도구 설치
kubectl apply -f istio-$ISTIOV/samples/addons
kubectl get pod -n istio-system

# 빠져나오기
exit
-----------------------------------

# 실습을 위한 네임스페이스 설정
kubectl create ns istioinaction
kubectl label namespace istioinaction istio-injection=enabled
kubectl get ns --show-labels

# istio-ingressgateway 서비스 : NodePort 변경 및 nodeport 지정 변경 , externalTrafficPolicy 설정 (ClientIP 수집)
kubectl patch svc -n istio-system istio-ingressgateway -p '{"spec": {"type": "NodePort", "ports": [{"port": 80, "targetPort": 8080, "nodePort": 30000}]}}'
kubectl patch svc -n istio-system istio-ingressgateway -p '{"spec": {"type": "NodePort", "ports": [{"port": 443, "targetPort": 8443, "nodePort": 30005}]}}'
kubectl patch svc -n istio-system istio-ingressgateway -p '{"spec":{"externalTrafficPolicy": "Local"}}'
kubectl describe svc -n istio-system istio-ingressgateway

# NodePort 변경 및 nodeport 30001~30003으로 변경 : prometheus(30001), grafana(30002), kiali(30003), tracing(30004)
kubectl patch svc -n istio-system prometheus -p '{"spec": {"type": "NodePort", "ports": [{"port": 9090, "targetPort": 9090, "nodePort": 30001}]}}'
kubectl patch svc -n istio-system grafana -p '{"spec": {"type": "NodePort", "ports": [{"port": 3000, "targetPort": 3000, "nodePort": 30002}]}}'
kubectl patch svc -n istio-system kiali -p '{"spec": {"type": "NodePort", "ports": [{"port": 20001, "targetPort": 20001, "nodePort": 30003}]}}'
kubectl patch svc -n istio-system tracing -p '{"spec": {"type": "NodePort", "ports": [{"port": 80, "targetPort": 16686, "nodePort": 30004}]}}'

# Prometheus 접속 : envoy, istio 메트릭 확인
open http://127.0.0.1:30001

# Grafana 접속
open http://127.0.0.1:30002

# Kiali 접속 1 : NodePort
open http://127.0.0.1:30003

# (옵션) Kiali 접속 2 : Port forward
kubectl port-forward deployment/kiali -n istio-system 20001:20001 &
open http://127.0.0.1:20001

# tracing 접속 : 예거 트레이싱 대시보드
open http://127.0.0.1:30004


# 접속 테스트용 netshoot 파드 생성
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
  name: netshoot
spec:
  containers:
  - name: netshoot
    image: nicolaka/netshoot
    command: ["tail"]
    args: ["-f", "/dev/null"]
  terminationGracePeriodSeconds: 0
EOF

실습 진행

이스티오 인그레스 게이트웨이는 클러스터 외부에서 내부로 들어오는 트래픽의 진입점을 제어하는 역할을 한다. 인그레스 게이트웨이는 Envoy 프록시 기반의 로드밸런서로 동작하며, 외부 트래픽을 받아 필요한 포트와 프로토콜을 지정해 노출한다. 하지만 실제 트래픽 라우팅(어떤 서비스로 전달할지)은 VirtualService 리소스를 통해 L7(애플리케이션 레이어)에서 세밀하게 제어한다.

즉, Gateway는 L4/L5 계층에서 트래픽을 받아들이고, VirtualService는 L7 계층에서 트래픽의 목적지와 라우팅 정책을 결정한다. 이 구조를 통해 이스티오는 외부 트래픽의 보안, 로드밸런싱, 가상 호스트 라우팅 등 다양한 네트워크 기능을 유연하게 제공한다.

현재 운영중인 istio 환경 정보

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: live-ops-query-gateway
  namespace: istio-system
spec:
  selector:
    istio: ingressgateway
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - "ops-query.test.co.kr"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: ops-query-vs
  namespace: devops
spec:
  hosts:
  - "ops-query.test.co.kr"
  gateways:
  - istio-system/live-ops-query-gateway
  http:
  - match:
    - uri:
        prefix: /
    route:
    - destination:
        host: ops-query-svc-active
      weight: 100
    - destination:
        host: ops-query-svc-preview
      weight: 0

 

 

아래는 실습환경이다.

404 에러가 발생한다. 이는 host 헤더가 알맞지 않아서 발생하는 문제이다.

 

헤더 수정후 다시 입력하면 정상적으로 응답되는것을 알 수 있다.

 

 

securing gateway traffic 실습

실무환경에서는 앞단의 ALB에 인증서만 적용해두고 내부의 이스티오간 인증서는 적용돼있지 않은상태다. 추후 보안심사때 문제가 발생하면 그때 적용해야겠다....

 

어쨋든.. 실습 환경에서 현재 적용 돼 있는 인증서는 다음과 같다.

kubectl create -n istio-system secret tls webapp-credential \
--key ch4/certs/3_application/private/webapp.istioinaction.io.key.pem \
--cert ch4/certs/3_application/certs/webapp.istioinaction.io.cert.pem

 kubectl apply -f ch4/coolstore-gw-tls.yaml -n istioinaction

 

이제 위 명령어로 시크릿을 만들고 게이트웨이를 재배포한다.

 

그러면 위와같이 새로운 인증서가 추가된것을 볼 수 있다.

그리고 curl 로 접속 테스트를 하면 에러가 나는것을 볼 수 있다.

 

이는 서버(istio-ingressgateway 파드)에서 제공하는 인증서는 기본 CA 인증서 체인을 사용해 확인할 수 없다는 의미다.

다시  cacert 옵션을 줘서 테스트를 한다. 또 에러가 난다. 이번엔 Local host로 접속해서 발생한 문제이다.

 

echo "127.0.0.1       webapp.istioinaction.io" | sudo tee -a /etc/hosts

위 명령어를 입력해서 임시로 dns 를 설정해준다.

 

다시 호출 테스트를 진행하면 정상적으로 접속되는것을 알 수 있다.

 

 

이번에는 https만 사용하도록 하는 리다이렉트 설정이다.

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: coolstore-gateway
spec:
  selector:
    istio: ingressgateway
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - "webapp.istioinaction.io"
    tls:
      httpsRedirect: true 
  - port:
      number: 443
      name: https
      protocol: HTTPS
    tls:
      mode: SIMPLE
      credentialName: webapp-credential
    hosts:
    - "webapp.istioinaction.io"

 

 

이번엔  mTLS이다.

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: coolstore-gateway
spec:
  selector:
    istio: ingressgateway
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - "webapp.istioinaction.io"
  - port:
      number: 443
      name: https
      protocol: HTTPS
    tls:
      mode: MUTUAL # mTLS 설정
      credentialName: webapp-credential-mtls # 신뢰할 수 있는 CA가 구성된 자격 증명
    hosts:
    - "webapp.istioinaction.io"

 

다음과 같이 클라이언트 인증서 없이 에러가 발생한다.

 

 

클라이언트 인증서를 명시하면 정상적으로 동작하는것을 알 수 있다.

 

 

Serving multiple virtual hosts with TLS

이스티오 인그레스 게이트웨이는 동일한 HTTPS 포트(443)에서 각기 다른 인증서와 비밀 키를 사용해 여러 도메인(가상 호스트)의 트래픽을 동시에 처리할 수 있다.

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: coolstore-gateway
spec:
  selector:
    istio: ingressgateway
  servers:
  - port:
      number: 443
      name: https-webapp
      protocol: HTTPS
    tls:
      mode: SIMPLE
      credentialName: webapp-credential
    hosts:
    - "webapp.istioinaction.io"
  - port:
      number: 443
      name: https-catalog
      protocol: HTTPS
    tls:
      mode: SIMPLE
      credentialName: catalog-credential
    hosts:
    - "catalog.istioinaction.io"

두개의 버추어 서비스를 처리하는것을 확인 할 수 있다. 이를 처리하는 플로우는 클라이언트가 게이트웨이(엔보이)로 HTTPS 연결을 시작하면, TLS 핸드셰이크의 ClientHello 단계에서 SNI(서버 이름 표시) 확장에 접근하려는 서비스의 도메인을 명시해 전달하고, 엔보이는 이 SNI 정보를 기반으로 올바른 인증서를 선택해 제시하고 해당 서비스로 트래픽을 라우팅한다.

 

TCP 트래픽에 대한 실습이다.

이스티오 게이트웨이는 TCP 기반 서비스도 외부에 노출할 수 있지만, HTTP처럼 세밀한 트래픽 제어나 고급 기능은 사용할 수 없다.
이는 엔보이가 프로토콜을 이해하지 못해 단순 TCP 프록시만 가능하기 때문이다.
클러스터 외부에서 내부 TCP 서비스를 이용하려면 게이트웨이에서 해당 포트를 노출하면 된다.

#
cat ch4/echo.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: tcp-echo-deployment
  labels:
    app: tcp-echo
    system: example
spec:
  replicas: 1
  selector:
    matchLabels:
      app: tcp-echo
  template:
    metadata:
      labels:
        app: tcp-echo
        system: example
    spec:
      containers:
        - name: tcp-echo-container
          image: cjimti/go-echo:latest
          imagePullPolicy: IfNotPresent
          env:
            - name: TCP_PORT
              value: "2701"
            - name: NODE_NAME
              valueFrom:
                fieldRef:
                  fieldPath: spec.nodeName
            - name: POD_NAME
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name
            - name: POD_NAMESPACE
              valueFrom:
                fieldRef:
                  fieldPath: metadata.namespace
            - name: POD_IP
              valueFrom:
                fieldRef:
                  fieldPath: status.podIP
            - name: SERVICE_ACCOUNT
              valueFrom:
                fieldRef:
                  fieldPath: spec.serviceAccountName
          ports:
            - name: tcp-echo-port
              containerPort: 2701
---
apiVersion: v1
kind: Service
metadata:
  name: "tcp-echo-service"
  labels:
    app: tcp-echo
    system: example
spec:
  selector:
    app: "tcp-echo"
  ports:
    - protocol: "TCP"
      port: 2701
      targetPort: 2701

kubectl apply -f ch4/echo.yaml -n istioinaction

#
kubectl get pod -n istioinaction
NAME                                   READY   STATUS    RESTARTS   AGE
tcp-echo-deployment-584f6d6d6b-xcpd8   2/2     Running   0          27s
...

 

# tcp 서빙 포트 추가 : 편집기는 vi 대신 nano 선택 <- 편한 툴 사용
KUBE_EDITOR="nano"  kubectl edit svc istio-ingressgateway -n istio-system
...
  - name: tcp
    nodePort: 30006
    port: 31400
    protocol: TCP
    targetPort: 31400
...

# 확인
kubectl get svc istio-ingressgateway -n istio-system -o jsonpath='{.spec.ports[?(@.name=="tcp")]}'
{"name":"tcp","nodePort":30006,"port":31400,"protocol":"TCP","targetPort":31400}


# 게이트웨이 생성
cat ch4/gateway-tcp.yaml
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: echo-tcp-gateway
spec:
  selector:
    istio: ingressgateway
  servers:
  - port:
      number: 31400
      name: tcp-echo
      protocol: TCP
    hosts:
    - "*"
    
kubectl apply -f ch4/gateway-tcp.yaml -n istioinaction
kubectl get gw -n istioinaction

# 에코 서비스로 라우팅하기 위해 VirtualService 리소스 생성
cat ch4/echo-vs.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: tcp-echo-vs-from-gw
spec:
  hosts:
  - "*"
  gateways:
  - echo-tcp-gateway
  tcp:
  - match:
    - port: 31400
    route:
    - destination:
        host: tcp-echo-service
        port:
          number: 2701

#
kubectl apply -f ch4/echo-vs.yaml -n istioinaction
kubectl get vs -n istioinaction
NAME                  GATEWAYS                HOSTS                          AGE
catalog-vs-from-gw    ["coolstore-gateway"]   ["catalog.istioinaction.io"]   44m
tcp-echo-vs-from-gw   ["echo-tcp-gateway"]    ["*"]                          6s
webapp-vs-from-gw     ["coolstore-gateway"]   ["webapp.istioinaction.io"]    3h59m


# mac 에 telnet 설치
brew install telnet

#
telnet localhost 30006
Trying ::1...
Connected to localhost.
Escape character is '^]'.
Welcome, you are connected to node myk8s-control-plane.
Running on Pod tcp-echo-deployment-584f6d6d6b-xcpd8.
In namespace istioinaction.
With IP address 10.10.0.20.
Service default.
hello istio! # <-- type here
hello istio! # <-- echo here

# telnet 종료하기 : 세션종료 Ctrl + ] > 텔넷 종료 quit

 

 

 

SNI passthrough 실습

이스티오 인그레스 게이트웨이는 TLS 연결을 종료하지 않고 SNI 호스트네임을 기반으로 TCP 트래픽을 라우팅하며, 백엔드 서비스에서 TLS 처리를 담당함으로써 다양한 레거시 애플리케이션 및 TCP 서비스를 서비스 메시에 통합할 수 있다.

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: sni-passthrough-gateway
spec:
  selector:
    istio: ingressgateway
  servers:
  - port:
      number: 31400 #1 HTTP 포트가 아닌 특정 포트 열기
      name: tcp-sni
      protocol: TLS
    hosts:
    - "simple-sni-1.istioinaction.io" #2 이 호스트를 포트와 연결
    tls:
      mode: PASSTHROUGH #3 통과 트래픽으로 처리

 

# TLS 인증을 직접 처리하는 앱 배포. (gw는 route 만 처리, pass through )
cat ch4/sni/simple-tls-service-1.yaml
kubectl apply -f ch4/sni/simple-tls-service-1.yaml -n istioinaction
kubectl get pod -n istioinaction

# 기존 Gateway 명세(echo-tcp-gateway) 제거 : istio-ingressgateway의 동일한 port (31400, TCP)를 사용하므로 제거함
kubectl delete gateway echo-tcp-gateway -n istioinaction

# 신규 Gateway 설정
kubectl apply -f ch4/sni/passthrough-sni-gateway.yaml -n istioinaction
kubectl get gw -n istioinaction

 

# 두 번째 서비스 배포
cat ch4/sni/simple-tls-service-2.yaml
kubectl apply -f ch4/sni/simple-tls-service-2.yaml -n istioinaction

# gateway 설정 업데이트
cat ch4/sni/passthrough-sni-gateway-both.yaml
kubectl apply -f ch4/sni/passthrough-sni-gateway-both.yaml -n istioinaction

# VirtualService 설정
cat ch4/sni/passthrough-sni-vs-2.yaml
kubectl apply -f ch4/sni/passthrough-sni-vs-2.yaml -n istioinaction

# 호출테스트2
echo "127.0.0.1       simple-sni-2.istioinaction.io" | sudo tee -a /etc/hosts

curl https://simple-sni-2.istioinaction.io:30006 \
--cacert ch4/sni/simple-sni-2/2_intermediate/certs/ca-chain.cert.pem

 

 

Split gateway responsibilities 실습

여러 인그레스 게이트웨이를 배포하면 서비스별 요구사항이나 팀별로 트래픽 경로와 설정을 독립적으로 관리·격리할 수 있다.

apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
metadata:
  name: my-user-gateway-install
  namespace: istioinaction
spec:
  profile: empty
  values:
    gateways:
      istio-ingressgateway:
        autoscaleEnabled: false
  components:
    ingressGateways:
    - name: istio-ingressgateway
      enabled: false    
    - name: my-user-gateway
      namespace: istioinaction
      enabled: true
      label:
        istio: my-user-gateway
      k8s:
        service:
          ports:
            - name: tcp  # my-user-gateway 에서 사용할 포트 설정
              port: 30007
              targetPort: 31400
#
docker exec -it myk8s-control-plane bash
------------------------------------------
# istioinaction 네임스페이스에 Ingress gateway 설치
cat <<EOF > my-user-gateway-edited.yaml
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
metadata:
  name: my-user-gateway-install
  namespace: istioinaction
spec:
  profile: empty
  values:
    gateways:
      istio-ingressgateway:
        autoscaleEnabled: false
  components:
    ingressGateways:
    - name: istio-ingressgateway
      enabled: false    
    - name: my-user-gateway
      namespace: istioinaction
      enabled: true
      label:
        istio: my-user-gateway
      k8s:
        service:
          ports:
            - name: tcp  # my-user-gateway 에서 사용할 포트 설정
              port: 31400
              targetPort: 31400
              nodePort: 30007 # 외부 접속을 위해 NodePort Number 직접 설정
EOF

# istioctl manifest generate -n istioinaction -f my-user-gateway-edited.yaml
istioctl install -y -n istioinaction -f my-user-gateway-edited.yaml

exit
------------------------------------------

# IstioOperator 확인
kubectl get IstioOperator -A
NAMESPACE       NAME                      REVISION   STATUS   AGE
istio-system    installed-state                               5h48m
istioinaction   my-user-gateway-install                       17s

#
kubectl get deploy my-user-gateway -n istioinaction
NAME              READY   UP-TO-DATE   AVAILABLE   AGE
my-user-gateway   1/1     1            1           65s

# 포트 확인
kubectl get svc my-user-gateway -n istioinaction -o yaml
...
  - name: tcp
    nodePort: 30007
    port: 31400
    protocol: TCP
    targetPort: 31400
...

 

 

 

Gateway injection

게이트웨이 주입(gateway injection)을 사용하면, 사용자가 IstioOperator 리소스 전체 권한 없이도 미완성(서브된) 게이트웨이 Deployment 리소스를 배포할 수 있고, Istio가 나머지 설정을 자동으로 채워준다. 이 방식은 사이드카 주입과 유사하게, 각 팀이 필요한 최소한의 리소스만 정의하면 Istio가 필요한 프록시와 설정을 자동으로 붙여준다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-user-gateway-injected
  namespace: istioinaction
spec:
  selector:
    matchLabels:
      ingress: my-user-gateway-injected
  template:
    metadata:
      annotations:
        sidecar.istio.io/inject: "true" #1 주입 활성화
        inject.istio.io/templates: gateway #2 gateweay 템플릿  
      labels:
        ingress: my-user-gateway-injected
    spec:
      containers:
      - name: istio-proxy #3 반드시 이 이름이어야 한다
        image: auto #4 미완성 이미지
...

 

Ingress gateway access logs 실습

이스티오 데모 프로필에서는 엔보이 프록시의 액세스 로그가 표준 출력으로 기록되어 컨테이너 로그를 통해 쉽게 확인할 수 있다.

#
kubectl get cm -n istio-system istio -o yaml
data:
  mesh: |-
    defaultConfig:
      discoveryAddress: istiod.istio-system.svc:15012
      proxyMetadata: {}
      tracing:
        zipkin:
          address: zipkin.istio-system:9411
    enablePrometheusMerge: true
    rootNamespace: istio-system
    trustDomain: cluster.local
  meshNetworks: 'networks: {}'
..

#
docker exec -it myk8s-control-plane bash
------------------------------------------
# 표준 출력 스트림으로 출력하도록 accessLogFile 속성을 변경
istioctl install --set meshConfig.accessLogFile=/dev/stdout
y 입력

exit
------------------------------------------

# configmap 에 mesh 바로 아래에 accessLogFile 부분 추가됨
kubectl get cm -n istio-system istio -o yaml
...
  mesh: |-
    accessLogFile: /dev/stdout
...

# 애플리케이션 호출에 대한 로그도 출력됨!
kubectl stern -n istioinaction -l app=webapp -c istio-proxy
webapp-7685bcb84-h5knf istio-proxy [2025-04-14T09:30:47.764Z] "GET /items HTTP/1.1" 200 - via_upstream - "-" 0 502 1 1 "172.18.0.1" "beegoServer" "4c10dba4-f49a-4b58-9805-ac30515dd417" "catalog.istioinaction:80" "10.10.0.8:3000" outbound|80||catalog.istioinaction.svc.cluster.local 10.10.0.9:60052 10.200.1.251:80 172.18.0.1:0 - default
webapp-7685bcb84-h5knf istio-proxy [2025-04-14T09:30:48.805Z] "GET /items HTTP/1.1" 200 - via_upstream - "-" 0 502 6 6 "172.18.0.1" "beegoServer" "7733f4d0-6e3a-4138-a126-fe25c30e51f4" "catalog.istioinaction:80" "10.10.0.8:3000" outbound|80||catalog.istioinaction.svc.cluster.local 10.10.0.9:60898 10.200.1.251:80 172.18.0.1:0 - default
...

운영 환경에서는 트래픽과 로그량이 많기 때문에, 텔레메트리 API를 이용해 필요한 워크로드에만 액세스 로그를 selectively 활성화하는 것이 효율적이다.

apiVersion: telemetry.istio.io/v1alpha1
kind: Telemetry
metadata:
  name: ingress-gateway
  namespace: istio-system
spec:
  selector:
    matchLabels:
      app: istio-ingressgateway #1 레이블과 일치하는 파드는 텔레메트리 설정을 가져온다
  accessLogging:
  - providers:
    - name: envoy #2 액세스 로그를 위한 프로바이더 설정
    disabled: false #3 disable 를 false 로 설정해 활성화한다

 

Reducing gateway configuration

이스티오는 기본적으로 모든 프록시가 메시 내 모든 서비스를 알도록 설정되어 있어 서비스가 많아지면 프록시 설정이 비대해지고 성능 및 확장성 문제가 발생할 수 있다. 이를 해결하기 위해 게이트웨이 프록시에는 필요한 설정만 포함하도록 "게이트웨이 설정 잘라내기" 기능을 명시적으로 활성화할 수 있다.

개인적으로 오늘 스터디에서 배운것중 가장 필요했던것이다. 일전에 istio 설정 잘못해서 서비스 연결이 제대로 안됐었는데, 디버깅 하기가 너무 힘들었다. 해당 설정때문에 앞으로 좀 더 수월해질듯 하다.

apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
metadata:
  name: control-plane
spec:
  profile: minimal
  components:
    pilot:
      k8s:
        env:
        - name: PILOT_FILTER_GATEWAY_CLUSTER_CONFIG
          value: "true"
  meshConfig:
    defaultConfig:
      proxyMetadata:
        ISTIO_META_DNS_CAPTURE: "true"
    enablePrometheusMerge: true

'job > devops' 카테고리의 다른 글

istio-1  (0) 2025.04.08
taskfile  (0) 2024.03.10
kubewarden  (0) 2024.01.20
openfunction  (0) 2023.12.01
git common flow(또는 gitlab flow) 브랜치 전략에 대한 설명  (0) 2023.06.13

사내에서 istio 프록시로 구성하여 사용중인데, 뭐랄까. 제대로 못쓰고 있는듯하다. 굳이 istio를 붙인것같은.. 제대로 못쓸꺼면 아에 빼버리던가(네트워크 문제시 파악 구간이 더 많아져서 싫다.) 아니면 제대로 쓸 수 있는 실력이 필요했다. 예를들어, 서비스 장애가 발생할 경우 istio가 없었다면 단순히 네트워크 구간만 살펴보면 됐다. 그런데 현재는 istio 구간까지 추가로 살펴봐야 한다. 문제는 해당 구간에 대한 모니터링이 안되고 있는 상황. 그래서 명확히 이 구간은 문제가 없다라고 판단하기가 어렵다. 이를 해결하려면 istio에 빠삭히 알아야 할 것 같았다. 그래서 작년에 istio 시험을 사두기만 했다. 그렇게 시간을 보내다 때마침 가시다님께서 istio 스터디를 진행하신다기에 재빨리 신청했다. (과거 여러 스터디를 운영하셨던 분들을 포함한 가시다님, 김원일님, 김석필님 감사합니다.)

스터디를 끝낼 때 istio 운영을 유지하며 시스템을 더욱 고도화(모니터링 추가등)할 지, 아니면 istio를 걷어낼지를 판단 할 수 있는 실력이 쌓였으면 좋겠다.

현재 사내에 istio를 사용중이다. 따라서 실습하면서 실제 운영환경과 비교하고 다른점이 있다면 어떤 설정에 의해 왜 다른지도 다뤄보고자 한다.

그럼 1주차 시작

Istio에 대한 간략한 설명

Istio를 왜 사용해야 하는가 ? Istio를 사용하지 않을 경우 발생할 수 있는 문제.

서비스 간 통신의 복잡성 증가:
네트워크 장애, 과부하, 버그 등으로 인해 서비스 간 요청이 실패하거나 성능 저하가 발생할 수 있음.
예를 들어, 다운스트림 서비스가 느리거나 장애가 발생하면 연쇄적인 서비스 장애로 이어질 가능성이 큼.

복원력 패턴 구현의 어려움:
타임아웃, 재시도, 서킷 브레이커 등의 복원력 패턴을 각 애플리케이션에서 직접 구현해야 함.
여러 언어와 프레임워크를 사용하는 환경에서는 이러한 패턴을 일관되게 구현하기 어려움.

운영 및 유지보수 부담 증가:
라이브러리 의존성을 관리하고 각 애플리케이션에 맞게 코드를 수정해야 하며, 이는 시간이 많이 소요되고 오류 가능성을 높임.
새로운 언어나 프레임워크 도입 시 추가적인 구현 작업이 필요함.

관찰 가능성 부족:
서비스 간 트래픽, 요청 실패율, 성능 병목 등을 실시간으로 파악하기 어려움.
장애 원인을 추적하거나 시스템 상태를 모니터링하는 데 한계가 있음.

Istio를 사용하면 해결되는 점

서비스 간 통신의 표준화:
Istio는 Envoy 프록시를 통해 서비스 간 통신을 관리하며, 재시도, 타임아웃, 서킷 브레이커 등의 기능을 애플리케이션 외부에서 제공.
이를 통해 서비스 간 통신의 안정성과 복원력을 높일 수 있음.

언어 및 프레임워크 독립성:
애플리케이션 코드 수정 없이 네트워크 관련 기능을 제공하므로 언어나 프레임워크에 구애받지 않음.
다양한 기술 스택에서도 일관된 네트워킹 정책 적용 가능.

운영 부담 감소:
Istio가 네트워킹 및 보안 정책을 중앙에서 관리하므로 각 애플리케이션에서 이를 구현할 필요가 없음.
새로운 서비스 추가나 변경 시에도 운영 부담이 줄어듦.

강화된 관찰 가능성:
Istio는 메트릭, 로그, 분산 트레이싱을 통해 실시간으로 시스템 상태를 모니터링 가능.
장애 원인 분석 및 성능 최적화 작업이 용이해짐.

결론
Istio는 네트워킹 관련 문제를 애플리케이션에서 인프라로 전가(내가 생각하는 devops 엔지니어는, 개발자는 회사의 이익에 필요한 개발만 할 수 있도록 환경을 만들어주는거라 생각하는데.. 이 모토랑 일치하는듯)하여 운영 효율성을 높이고, 복잡한 클라우드 환경에서도 안정적으로 서비스를 운영할 수 있도록 돕습니다.

Istio란? 서비스메시란 ? 엔보이프록시? 사이드카?

서비스 메시 (Service Mesh)

서비스 메시란, 여러 서비스가 서로 대화할 때 그 대화를 도와주는 네트워크의 "통신 감독관" 같은 역할을 합니다.
예를 들어, 학교에서 선생님이 학생들끼리 조용히 대화하도록 도와주는 것과 비슷합니다.

엔보이 프록시 (Envoy Proxy)

엔보이 프록시는 서비스들 사이에서 주고받는 메시지를 대신 전달하는 "우체부" 역할을 합니다.
예를 들어, 친구에게 편지를 보낼 때 우체부가 대신 전달해 주는 것처럼, 엔보이는 서비스 간 데이터를 안전하고 빠르게 전달합니다.

사이드카 (Sidecar)

사이드카는 주 컨테이너(주요 프로그램)를 도와주는 "조수" 컨테이너입니다.
예를 들어, 오토바이에 붙어 있는 작은 캐빈처럼, 사이드카는 옆에서 필요한 일을 돕습니다. Istio에서는 이 사이드카가 엔보이 프록시로 동작합니다.

Istio 프록시

Istio 프록시는 엔보이 프록시를 사용하여 각 서비스 옆에 사이드카로 배치됩니다.
예를 들어, 학교에서 각 반마다 선생님(프록시)이 배치되어 학생들(서비스)이 서로 잘 소통하도록 돕는 것과 같습니다. 이 프록시는 메시지를 가로채고, 어디로 보내야 할지 알려주며, 보안도 책임집니다.

연관 관계

  • 서비스 메시 안에는 여러 서비스가 있고, 이들이 서로 대화할 때 엔보이 프록시가 중간에서 도와줍니다.
  • 엔보이 프록시는 각 서비스 옆에 사이드카 형태로 배치되어 Istio라는 시스템의 일부로 작동합니다.
  • Istio는 전체 네트워크를 관리하며 트래픽을 안전하고 효율적으로 제어합니다.

즉 정리하자면, Istio를 사용하지 않는다면 애플리케이션 레벨에서의 리소스가 많이 사용되는데, Istio를 사용하면 효율적으로 인프라 레벨로 옮길 수 있다. 어떻게? 사이드카 프록시로.

Istio의 단점은 ?

디버깅 복잡성 증가

Envoy 프록시가 추가되면서 네트워크 요청 경로가 복잡해지고, 프록시에 익숙하지 않은 경우 디버깅이 어려워질 수 있음.

테넌시 관리의 어려움
서비스 메시 구성 시 적절한 정책과 자동화가 없으면 잘못된 설정으로 인해 다수의 서비스에 영향을 미칠 가능성이 있음.

운영 복잡성 증가
서비스 메시 도입으로 새로운 레이어가 추가되어 시스템 아키텍처와 운영 절차가 복잡해질 수 있음.

조직의 기존 거버넌스 및 팀 간 협업과의 통합이 어려울 수 있음.

실습 진행

istio 설치

$ istioctl version --remote=false
$ kubectl get all,svc,ep,sa,cm,secret,pdb -n istio-system
NAME                                       READY   STATUS    RESTARTS   AGE
pod/grafana-b854c6c8-rhsvm                 1/1     Running   0          19h
pod/istio-ingressgateway-996bc6bb6-lwqq5   1/1     Running   0          19h
pod/istiod-7df6ffc78d-r4jvv                1/1     Running   0          19h
pod/jaeger-5556cd8fcf-8z2zz                1/1     Running   0          19h
pod/kiali-648847c8c4-wcw8l                 1/1     Running   0          19h
pod/prometheus-7b8b9dd44c-zzsr8            2/2     Running   0          19h

NAME                           TYPE           CLUSTER-IP     EXTERNAL-IP   PORT(S)                                      AGE
service/grafana                ClusterIP      10.200.1.30    <none>        3000/TCP                                     19h
service/istio-ingressgateway   LoadBalancer   10.200.1.103   <pending>     15021:31155/TCP,80:30491/TCP,443:30079/TCP   19h
service/istiod                 ClusterIP      10.200.1.116   <none>        15010/TCP,15012/TCP,443/TCP,15014/TCP        19h
service/jaeger-collector       ClusterIP      10.200.1.31    <none>        14268/TCP,14250/TCP,9411/TCP                 19h
service/kiali                  ClusterIP      10.200.1.99    <none>        20001/TCP,9090/TCP                           19h
service/prometheus             ClusterIP      10.200.1.130   <none>        9090/TCP                                     19h
service/tracing                ClusterIP      10.200.1.38    <none>        80/TCP,16685/TCP                             19h
service/zipkin                 ClusterIP      10.200.1.200   <none>        9411/TCP                                     19h

NAME                                   READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/grafana                1/1     1            1           19h
deployment.apps/istio-ingressgateway   1/1     1            1           19h
deployment.apps/istiod                 1/1     1            1           19h
deployment.apps/jaeger                 1/1     1            1           19h
deployment.apps/kiali                  1/1     1            1           19h
deployment.apps/prometheus             1/1     1            1           19h

NAME                                             DESIRED   CURRENT   READY   AGE
replicaset.apps/grafana-b854c6c8                 1         1         1       19h
replicaset.apps/istio-ingressgateway-996bc6bb6   1         1         1       19h
replicaset.apps/istiod-7df6ffc78d                1         1         1       19h
replicaset.apps/jaeger-5556cd8fcf                1         1         1       19h
replicaset.apps/kiali-648847c8c4                 1         1         1       19h
replicaset.apps/prometheus-7b8b9dd44c            1         1         1       19h

NAME                                                       REFERENCE                         TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
horizontalpodautoscaler.autoscaling/istio-ingressgateway   Deployment/istio-ingressgateway   8%/80%    1         5         1          19h
horizontalpodautoscaler.autoscaling/istiod                 Deployment/istiod                 0%/80%    1         5         1          19h

NAME                             ENDPOINTS                                                     AGE
endpoints/grafana                10.10.0.10:3000                                               19h
endpoints/istio-ingressgateway   10.10.0.8:15021,10.10.0.8:8080,10.10.0.8:8443                 19h
endpoints/istiod                 10.10.0.7:15012,10.10.0.7:15010,10.10.0.7:15017 + 1 more...   19h
endpoints/jaeger-collector       10.10.0.9:9411,10.10.0.9:14250,10.10.0.9:14268                19h
endpoints/kiali                  10.10.0.11:9090,10.10.0.11:20001                              19h
endpoints/prometheus             10.10.0.12:9090                                               19h
endpoints/tracing                10.10.0.9:16685,10.10.0.9:16686                               19h
endpoints/zipkin                 10.10.0.9:9411                                                19h

NAME                                                  SECRETS   AGE
serviceaccount/default                                1         19h
serviceaccount/grafana                                1         19h
serviceaccount/istio-ingressgateway-service-account   1         19h
serviceaccount/istio-reader-service-account           1         19h
serviceaccount/istiod                                 1         19h
serviceaccount/istiod-service-account                 1         19h
serviceaccount/kiali                                  1         19h
serviceaccount/prometheus                             1         19h

NAME                                            DATA   AGE
configmap/grafana                               4      19h
configmap/istio                                 2      19h
configmap/istio-ca-root-cert                    1      19h
configmap/istio-gateway-deployment-leader       0      19h
configmap/istio-gateway-status-leader           0      19h
configmap/istio-grafana-dashboards              2      19h
configmap/istio-leader                          0      19h
configmap/istio-namespace-controller-election   0      19h
configmap/istio-services-grafana-dashboards     4      19h
configmap/istio-sidecar-injector                2      19h
configmap/kiali                                 1      19h
configmap/kube-root-ca.crt                      1      19h
configmap/prometheus                            5      19h

NAME                                                      TYPE                                  DATA   AGE
secret/default-token-lmqrr                                kubernetes.io/service-account-token   3      19h
secret/grafana-token-74qt2                                kubernetes.io/service-account-token   3      19h
secret/istio-ca-secret                                    istio.io/ca-root                      5      19h
secret/istio-ingressgateway-service-account-token-tlq54   kubernetes.io/service-account-token   3      19h
secret/istio-reader-service-account-token-8zz99           kubernetes.io/service-account-token   3      19h
secret/istiod-service-account-token-zrr8b                 kubernetes.io/service-account-token   3      19h
secret/istiod-token-x64kr                                 kubernetes.io/service-account-token   3      19h
secret/kiali-token-84msl                                  kubernetes.io/service-account-token   3      19h
secret/prometheus-token-vqmbw                             kubernetes.io/service-account-token   3      19h

NAME                                              MIN AVAILABLE   MAX UNAVAILABLE   ALLOWED DISRUPTIONS   AGE
poddisruptionbudget.policy/istio-ingressgateway   1               N/A               0                     19h
poddisruptionbudget.policy/istiod                 1               N/A               0                     19h

이중 istio-ingressgateway 서비스 리소스의 경우 실제 운영환경은 다음과 같이 EXTERNAL-IP에 CSP의 LB 도메인이 들어가있다. 실습 환경에서는 PENDING이다.

$ k get svc -n istio-system
NAME                   TYPE           CLUSTER-IP       EXTERNAL-IP                                                                   PORT(S)                                      AGE
istio-ingressgateway   LoadBalancer   198.19.240.44    istio-syste-istio-ingres-xxx.kr-fin.lb.naverncp.com   15021:31396/TCP,80:30616/TCP,443:31295/TCP   527d
istiod                 ClusterIP      198.19.157.147   <none>                                                                        15010/TCP,15012/TCP,443/TCP,15014/TCP        527d

이는 CSP(NCP)에서 설치된 쿠버네티스 클러스터(NKS)에는 기본적으로 cloud controller manager의 service controller에 의해 자동으로 NKS의 LB를 생성한다. 관련 설정은 kube-system 네임스페이스에 ncloud-config라는 ConfigMap이 적용 돼 있다.

$ k get cm -n kube-system -o yaml ncloud-config
apiVersion: v1
data:
  acgNo: "11111"
  apiUrl: https://nks.apigw.fin-ntruss.com
  basePath: /ncloud-api/v1
  clusterId: "1111"
  lbPublicSubnetNo: "11111"
  lbSubnetNo: "11111"
  regionCode: FKR
  regionNo: "1"
  vpcNo: "1111"
  zoneNo: "111"
kind: ConfigMap
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
생략
  creationTimestamp: "2023-10-30T02:09:49Z"
  name: ncloud-config
  namespace: kube-system
  resourceVersion: "1111111"
  uid: 11111-1a71-457e-813c-4b2d13f00446

해당 설정에 의해 서비스타입이 로드밸런서인경우 NCP API와 상호작용하여, 자동으로 NCP의 LB(기본값은 프록시 로드밸런서)를 생성하게 된다.
참고로 로드밸런서 이름(익스터널IP에 들어가는 도메인명)의 생성 규칙은 다음과 같다.
<네임스페이스-서비스이름-포트번호-랜덤문자열>

파드배포(사이드카로 Istio 도 같이 배포)

이제 배포되는 모든 파드들에 사이드카로 istio가 같이 배포되도록 해야 한다. 이는 2가지 방법이 있는데,
docker exec -it myk8s-control-plane istioctl kube-inject -f /istiobook/services/catalog/kubernetes/catalog.yaml
으로 매니페스트에 사이드카 설정을 추가하는 방법과

kubectl label namespace istioinaction istio-injection=enabled
으로, 네임스페이스에 istio-injection=enabled Label에 설정 돼 있는 경우 해당 네임스페이스의 파드 스펙에 자동으로 사이드카 설정을 한다.

이제 파드를 배포하면 다음과 같이 앱이 배포된다.

하나의 파드에 두개의 컨테이너가 있음이 확인된다. 이를 describe로 확인해보면 보는것처럼 catalog라는 메인 컨테이너외에 istio-proxy라는 사이드카 컨테이너가 올라온것을 알 수 있다.

istio proxy 상태 확인

# istioctl proxy-status : 단축어 ps
docker exec -it myk8s-control-plane istioctl proxy-status
NAME                                                  CLUSTER        CDS        LDS        EDS        RDS        ECDS         ISTIOD                      VERSION
catalog-6cf4b97d-nccfj.istioinaction                  Kubernetes     SYNCED     SYNCED     SYNCED     SYNCED     NOT SENT     istiod-7df6ffc78d-bj7h7     1.17.8
istio-ingressgateway-996bc6bb6-mz544.istio-system     Kubernetes     SYNCED     SYNCED     SYNCED     SYNCED     NOT SENT     istiod-7df6ffc78d-bj7h7     1.17.8
webapp-7685bcb84-c55ck.istioinaction                  Kubernetes     SYNCED     SYNCED     SYNCED     SYNCED     NOT SENT     istiod-7df6ffc78d-bj7h7     1.17.8

ISTIOIGW=istio-ingressgateway-996bc6bb6-647tx.istio-system
WEBAPP=webapp-7685bcb84-nfntj.istioinaction

# istioctl proxy-config : 단축어 pc
docker exec -it myk8s-control-plane istioctl proxy-config all $ISTIOIGW
docker exec -it myk8s-control-plane istioctl proxy-config all $WEBAPP

docker exec -it myk8s-control-plane istioctl proxy-config listener $ISTIOIGW
docker exec -it myk8s-control-plane istioctl proxy-config route $ISTIOIGW
docker exec -it myk8s-control-plane istioctl proxy-config cluster $ISTIOIGW
docker exec -it myk8s-control-plane istioctl proxy-config endpoint $ISTIOIGW
docker exec -it myk8s-control-plane istioctl proxy-config log $ISTIOIGW

docker exec -it myk8s-control-plane istioctl proxy-config listener $WEBAPP
docker exec -it myk8s-control-plane istioctl proxy-config route $WEBAPP
docker exec -it myk8s-control-plane istioctl proxy-config cluster $WEBAPP
docker exec -it myk8s-control-plane istioctl proxy-config endpoint $WEBAPP
docker exec -it myk8s-control-plane istioctl proxy-config log $WEBAPP

# envoy 가 사용하고 있는 인증서 정보 확인
docker exec -it myk8s-control-plane istioctl proxy-config secret $ISTIOIGW
docker exec -it myk8s-control-plane istioctl proxy-config secret $WEBAPP

위 명령어들은 istio 서비스 매쉬 내 프록시의 상태를 확인(istioctl proxy-status)하고, 특정 프록시의 상세 구성 정보를 조회(istioctl proxy-config)하는 명령어다.

Istio 프록시(Envoy)의 네트워크 흐름에서 Listener, Route, Cluster, Endpoint는 트래픽 처리 단계에 따라 아래와 같은 순서로 작동합니다:

1. Listener
역할: Envoy가 수신하는 트래픽을 처리할 준비를 합니다. Listener는 특정 IP와 포트에 바인딩되어 들어오는 요청을 수신하고, 트래픽을 처리하기 위한 첫 번째 진입점입니다.

작동 위치: 네트워크에서 Envoy 프록시가 요청을 가로채고, 트래픽의 방향을 결정하기 위해 필터 체인을 적용합니다.

예시: HTTP 요청이 들어오면 Listener는 이를 처리할 라우팅 규칙을 찾습니다.

2. Route
역할: Listener에서 수신된 요청을 분석하여 어떤 서비스로 전달할지 결정합니다. Route는 요청 경로와 매칭되는 규칙을 기반으로 클러스터를 선택합니다.

작동 위치: Listener에서 필터 체인을 통해 전달된 요청은 Route에서 적절한 클러스터로 연결됩니다.

예시: 특정 URL 경로(/api/v1)에 대한 요청을 특정 클러스터로 라우팅.

3. Cluster
역할: 라우팅된 요청을 처리할 논리적인 서비스 그룹입니다. Cluster는 여러 Endpoint(IP와 포트)로 구성되며, Envoy가 외부 서비스와 연결하는 단위입니다.

작동 위치: Route가 선택한 클러스터는 실제 엔드포인트로 트래픽을 포워드합니다.

예시: service-cluster라는 클러스터가 외부 API 서버를 대표하며, 해당 클러스터의 엔드포인트로 트래픽을 전달.

4. Endpoint
역할: 클러스터 내에서 실제 요청이 전달되는 대상입니다. Endpoint는 IP 주소와 포트를 포함하며, 클라이언트의 요청이 최종적으로 도달하는 곳입니다.

작동 위치: Cluster에서 선택된 엔드포인트로 트래픽이 전달됩니다.

예시: 특정 API 서버의 IP 주소(예: 192.168.1.100)와 포트(예: 8080)이 Endpoint로 설정됩니다.

네트워크 흐름 순서 요약
단계    구성 요소    역할 및 작업
1    Listener    요청 수신 및 필터 체인을 통해 초기 처리
2    Route    요청 경로 분석 및 적절한 클러스터 선택
3    Cluster    논리적 서비스 그룹으로 요청 전달
4    Endpoint    실제 대상(IP/포트)으로 최종 트래픽 전달
이 순서는 Istio 프록시의 기본적인 트래픽 처리 흐름이며, 각 단계는 Envoy 내부의 설정과 xDS API를 통해 동적으로 구성됩니다.

의도적으로 ingress, gateway, VirtualService 설정중 한곳에 문제를 주고 해당 서비스가 어떤 문제가 있는지 한번 위 명령어들로 확인해보고자 한다.

먼저 문제있는 서비스의 Ingress와 gateway, Virtual Service 설정은 다음과 같이 진행했다.

$ k get ingress -n istio-system | grep query
query-ingress   alb     query.test.com                                                        query-server-ingress-fin.lb.naverncp.com    80      107d

위와같이 query-ingress는 현재 NCP ALB로 연결 된 상태다.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
중략
  labels:
    app: query-server-ingress
  name: query-server-ingress
  namespace: istio-system
spec:
  ingressClassName: alb
  defaultBackend:
    service:
      name: istio-ingressgateway
      port:
        number: 80
  rules:
  - host: query-test.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: ssl-redirect
            port: 
              name: use-annotation            

GW와 VS 매니페스트는 다음과 같다.

apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
중략
  creationTimestamp: "2024-12-13T01:46:08Z"
  generation: 1
  labels:
    app.kubernetes.io/instance: opsquery
  name: query-gateway
  namespace: istio-system
  resourceVersion: "441696723"
  uid: 19fc1bd0-5c30-4dc1-b624-b956da859c15
spec:
  selector:
    istio: ingressgateway
  servers:
  - hosts:
    - query.test.co.kr
    port:
      name: http
      number: 80
      protocol: HTTP


---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: ops-query-vs
  namespace: devops
spec:
  hosts:
  - "ops-query.test.co.kr"
  gateways:
  - istio-system/devops-gateway
  http:
  - match:
    - uri:
        prefix: /
    route:
    - destination:
        host: query-svc-active
      weight: 100
    - destination:
        host: query-svc-preview
      weight: 0

이제 proxy-status와 proxy-config 명령어로 한번 원인을 찾아보고자 한다.

$ istioctl proxy-status | grep ops-query
ops-query-7cc7fc6f69-b6sml.devops                                    Kubernetes     SYNCED     SYNCED     SYNCED     SYNCED     NOT SENT     istiod-784bcfdd5d-2fgbs     1.16.2

$ istioctl proxy-config all ops-query-7cc7fc6f69-b6sml.devops | grep ops 
##결과 없음

결과가 없다는건 Gateway나 VirtualService에 문제가 있을 가능성이 크다(고한다.)

Gateway 설정 문제:
Gateway가 Istio IngressGateway Pod와 제대로 연결되지 않았을 수 있습니다.
Gateway의 selector가 IngressGateway Pod의 라벨과 일치하지 않으면 트래픽을 수신할 Listener가 생성되지 않습니다.

VirtualService 설정 누락 또는 연결 문제:
VirtualService가 Gateway와 연계되어 있지 않거나, VirtualService에서 트래픽 라우팅 규칙이 제대로 정의되지 않았을 경우 Listener가 생성되지 않습니다.
VirtualService가 없으면 Gateway는 트래픽 처리 규칙을 알 수 없어 Listener를 생성하지 않습니다.

Istiod 구성 전달 문제:
Istiod(Control Plane)에서 Envoy 프록시(데이터 플레인)로 Gateway 및 VirtualService 설정이 전달되지 않았을 가능성이 있습니다.
이는 Istiod와 IngressGateway 간의 통신 문제, 혹은 설정 동기화 실패(STALE 상태)가 원인일 수 있습니다.

그럼 Ingress, GW, VS설정에 문제가 없는지 찾아보면 될것이다. 사실 VS 설정중 게이트웨이 설정하는부분을 잘못 넣어놨었다.

gateways:
-   istio-system/devops-gateway

정상적으로 하려면 devops-gateway가 아니라 query-gateway 으로 설정해줘야 한다.

$ istioctl proxy-config all ops-query-7cc7fc6f69-b6sml.devops  | grep ops-query
ops-query-svc-active.devops.svc.cluster.local                                  80        -          outbound      EDS              
ops-query-svc-preview.devops.svc.cluster.local                                 80        -          outbound      EDS              
80                                                                                   ops-query-svc-active, ops-query-svc-active.devops + 1 more...                                                            /*                     
80                                                                                   ops-query-svc-preview, ops-query-svc-preview.devops + 1 more...                                                          /*     

서비스도 정상적으로 동작하고, proxy-config 의 결과에도 정상적으로 출력되는것이 확인된다.
proxy-config에 대한(리스너, 라우드, 클러스터, 엔드포인트등 xDS)자세한 설명은 다음 주차때 envoy프록시 설명에서 자세히 다룰듯 하다.

다시 실습으로 넘어가서...

# istio-ingressgateway 서비스 NodePort 변경 및 nodeport 30000로 지정 변경
kubectl get svc,ep -n istio-system istio-ingressgateway
kubectl patch svc -n istio-system istio-ingressgateway -p '{"spec": {"type": "NodePort", "ports": [{"port": 80, "targetPort": 8080, "nodePort": 30000}]}}'
kubectl get svc -n istio-system istio-ingressgateway

# istio-ingressgateway 서비스 externalTrafficPolicy 설정 : ClientIP 수집 확인
kubectl patch svc -n istio-system istio-ingressgateway -p '{"spec":{"externalTrafficPolicy": "Local"}}'
kubectl describe svc -n istio-system istio-ingressgateway

curl -s http://127.0.0.1:30000/api/catalog | jq
curl -s http://127.0.0.1:30000/api/catalog/items/1 | jq
curl -s http://127.0.0.1:30000/api/catalog -I | head -n 1

위 명령어들로 실습환경의 30000포트로 접속가능하도록 설정해주고 curl로 접속을 확인하면 다음과 같이 정상적으로 접속됨을 확인 할 수 있다.

옵저버빌리티

이제 옵저버빌리티를 하기 위해 추가 설치한 프로메테우스, 그라파나, 키알리, 트레이싱에 대한 노드포트를 설정해준다.

kubectl patch svc -n istio-system prometheus -p '{"spec": {"type": "NodePort", "ports": [{"port": 9090, "targetPort": 9090, "nodePort": 30001}]}}'
kubectl patch svc -n istio-system grafana -p '{"spec": {"type": "NodePort", "ports": [{"port": 3000, "targetPort": 3000, "nodePort": 30002}]}}'
kubectl patch svc -n istio-system kiali -p '{"spec": {"type": "NodePort", "ports": [{"port": 20001, "targetPort": 20001, "nodePort": 30003}]}}'
kubectl patch svc -n istio-system tracing -p '{"spec": {"type": "NodePort", "ports": [{"port": 80, "targetPort": 16686, "nodePort": 30004}]}}'

이후 localhost:서비스포트 로 접속하면 정상적으로 접속됨을 확인할 수 있다. 이중 Kiali를 살펴보면..

 

이미지와 같이 서비스매쉬의 트래픽 흐름을 확인 할 수 있다. 아까 장애 상황에서 라면 istio-ingressgateway에서 webapp으로 흐르는 트래픽이 안나왔을것이다.

 

이제 해당 서비스에 강제로 500에러를 50프로 빈도로 발생하도록 하면 kiali에서 다음 화면 처럼 실패가 나고 있는것을 볼 수 있다.

 

실무환경에서도 여러가지 이유로 간헐적으로 5xx대 에러가 발생할 수 있는데, 이때 다음 설정으로 5xx에러 발생시 재시도를 하도록 조치 할 수 있다.

cat <<EOF | kubectl -n istioinaction apply -f -
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: catalog
spec:
  hosts:
  - catalog
  http:
  - route:
    - destination:
        host: catalog
    retries:
      attempts: 3
      retryOn: 5xx
      perTryTimeout: 2s
EOF

 

위 설정은 만약 5xx대 에러 발생시 2초 뒤 3번 재시도 하도록 할 수 있다. 사이드카 방식 istio의 큰 장점이라고 본다.

 

이밖에, istio 만으로 트래픽을 컨트롤하여 여러가지 배포방법을 이용할 수 있다.

 

우리는 argocd를 사용중인데, VS에서 route 설정으로 weight으로 active, preview를 설정하여 블루/그린 배포방법을 이용중이다.

 

추가로 다음과같이 VS에 헤더를 기반으로 매칭을 확인하여 트래픽을 보낼 수 있다.

cat <<EOF | kubectl -n istioinaction apply -f -
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: catalog
spec:
  hosts:
  - catalog
  http:
  - match:
    - headers:
        x-dark-launch:
          exact: "v2"
    route:
    - destination:
        host: catalog
        subset: version-v2
  - route:
    - destination:
        host: catalog
        subset: version-v1
EOF

 

현재 운영환경에서 아르고 롤아웃으로 프리뷰가 배포 됐을 때, promote 하기 전에 해당 배포버전으로 미리 접속하여 QA를 진행하고자 할 수 있다. 이때 굉장히 유용할듯 하다.

 

마지막으로...

istio를 사용하면서 istio 컨테이너의 로그를 자세히 봐야 할 필요가 있었다.

실사례로, 프론트에서는 아무런 값이 안들어왔고, 백앤드에서는 데이터를 정상적으로 전송했다고 한다. 이때 istio 컨테이너 로그를 확인 할 필요가 있었다. 왜냐하면 결국 데이터가 전송됐다면 istio 로그에 찍혔을테니까 말이다. 

 

그래서 다음과같은 설정을 적용해서 로그를 찍었다.

 

apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
  name: request-size-limit
  namespace: test
spec:
  workloadSelector:
    labels:
      app: test-api
  configPatches:
  - applyTo: HTTP_FILTER
    match:
      context: ANY
      listener:
        filterChain:
          filter:
            name: envoy.filters.network.http_connection_manager
            subFilter:
              name: envoy.filters.http.router
    patch:
      operation: INSERT_BEFORE
      value:
        name: envoy.filters.http.buffer
        typed_config:
          "@type": type.googleapis.com/envoy.extensions.filters.http.buffer.v3.Buffer
          max_request_bytes: 50485760


  - applyTo: HTTP_FILTER
    match:
      context: ANY
      listener:
        filterChain:
          filter:
            name: envoy.filters.network.http_connection_manager
            subFilter:
              name: envoy.filters.http.router
    patch:
      operation: INSERT_BEFORE
      value:
        name: envoy.filters.http.lua
        typed_config:
          "@type": type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua
          inlineCode: |
            function envoy_on_response(response_handle)
              local headers = response_handle:headers()
              for key, value in pairs(headers) do
                response_handle:logInfo("response Header:" .. key .. ":"  .. value)
              end
              local response_body = response_handle:body():getBytes(0,response_handle:body():length())
              response_handle:logInfo("response body:" .. response_body)
            end

  - applyTo: LISTENER
    match:
      context: ANY
    patch:
      operation: MERGE
      value:
        per_connection_buffer_limit_bytes: 20480000

 

해당 설정은 요청에 대한 response body 용량과 실제 body 내용을 로그로 남기는 설정이다.

 

마무리..

1주차부터 좋은 지식을 많이 얻었다. 스터디 운영진님들 감사합니다.

'job > devops' 카테고리의 다른 글

istio-2  (1) 2025.04.17
taskfile  (0) 2024.03.10
kubewarden  (0) 2024.01.20
openfunction  (0) 2023.12.01
git common flow(또는 gitlab flow) 브랜치 전략에 대한 설명  (0) 2023.06.13

1. 패키지 관리 도구 및 저장소별로 nexus 프록시 타입 레포 생성

2. maven, npm등 포맷별로 만들어진 proxy 레포를 하나의 그룹으로 묶기

3. 깃헙에서 소스 패키지를 태그나 릴리즈등으로 받는 경우는 raw host 만들어서 직접 파일 업로드하여 패키지 관리. 물론 raw host들도 그룹으로 묶기

4. 빌드 환경에 따라 기존 디폴트 퍼블릭 저장소를 넥서스 그룹 저장소로 변경하기

5. 패키지 설치 후 빌드하는 과정에서 디펜던시 패키지가 또다시 패키지를 설치하는경우가 있음. 따라서 패키지 설치후 디펜던시 패키지내에 추가적으로 기존 디폴트 퍼블릭 저장소를 넥서스 그룹 저장소로 변경해야 할 수 있음

큰 틀로 보면 위 순서대로 하면 된다. 

 

구축된 환경들을 나열해보면

React Native, Flutter, Yarn, Maven, NPM, Docker image, composer, python, cocoapod, rubygem

그리고 apk, yum, homebrew, nuget까지.. 많이 사용되는 대부분의 환경은 다 한 것 같다.

 

해당 업무를 하면서 조언을 얻기가 쉽지 않았다.  우리나라에 망분리 환경에서 개발하는 개발자들이 그렇게 많겠지만 개발자는 인프라영역을 모르고, 인프라담당자는 개발영역을 잘 몰르니 말이다. 그래서 난관이 좀 많았다. 망분리 개발환경 구축만큼은 나름 목소리좀 낼 수 있을듯 하다.

어쨌든 뭐. 이정도면 나름 만족스러운 결과(개발자도 최대한 불편하지 않고, 보안에도 위법되지 않고)인듯 하다.

 

마지막으로 각 단계에서 발생했던 난관들을 적어보자면...

1. 패키지 관리 도구 및 저장소별로 nexus 프록시 타입 레포 생성

넥서스 캐시등의 설정에 유의해야하고.

넥서스에서 기본적으로 제공하는 레시피가 제한적이다. 그럴땐 넥서스 레포 '패키지관리도구이름' 검색해보면 직접 레시피 만들 수 있도록 깃헙에 등록돼있는 경우가 있음.(ex apk)

 

2. maven, npm등 포맷별로 만들어진 proxy 레포를 하나의 그룹으로 묶기

이건 뭐 어려울껀 없다.. 가장 많이 사용하는 레포를 순서상 가장 위로 하도록

 

3. 깃헙에서 소스 패키지를 태그나 릴리즈등으로 받는 경우는 raw host 만들어서 직접 파일 업로드하여 패키지 관리. 물론 raw host들도 그룹으로 묶기

Nexus는 기본적으로 바이너리 컴포넌트 관리 솔루션으로 설계되었으며, 소스 코드 관리 시스템이 아니다. 따라서 GitHub과 같은 소스 코드 저장소를 직접적으로 프록시하거나 통합하는 데 적합하지 않다.

그래서 패키지를 깃헙에서 받는 경우에는 어떻게 해야할까 고민이 많았다. 기 구축된 내부 깃랩 서버가 있어서 처음엔 깃헙>깃랩을 동일하게 구성(미러링 되도록)해서 해결해볼까 했다.

그러나 이경우 깃헙에서 기본적으로 사용하는 태그/아카이브/릴리즈 경로와 깃랩의 경로가 서로 달랐다. 미러링하다보니까 모든 패키지를 다 다운받아야하니 불필요하게 깃랩의 용량이 커지는것도 싫었다.

그래서 결국 필요한 패키지를 깃헙에서 다운받아 raw host 넥서스 레포로 업로드 하도록 했다. 현재 내가 다니는 회사의 규모가 크진 않아서 필요한 패키지를 직접 수동으로 업로드하긴 했는데, 만약 자동화가 필요하다면 구글 시트에 개발자가 필요한 패키지이름/깃헙 경로 업로드하면 스케쥴링 걸어서 자동으로 넥서스 레포에 업로드 하도록 하면 될듯 싶다.

 

4. 빌드 환경에 따라 기존 디폴트 퍼블릭 저장소를 넥서스 그룹 저장소로 변경하기

CI/CD 자동화 환경에서는 dockerfile에서 직접 설정을 해야 하고, 개발자 개인 개발 PC에서의 설정은 개발자가 해야 할 일이다.

패키지 저장소별 설정 방법 가이드는 https://help.sonatype.com/en/formats.html 를 참고하면 된다.

 

5. 패키지 설치 후 빌드하는 과정에서 디펜던시 패키지가 또다시 패키지를 설치하는경우가 있음. 따라서 패키지 설치후 디펜던시 패키지내에

추가적으로 기존 디폴트 퍼블릭 저장소를 넥서스 그룹 저장소로 변경해야 할 수 있음

앞서 깃헙과 함께 가장 골치 아픈 상황이였다. 특히 프론트개발환경에 React Native에서 많았다. 이건 뭐.. 어쩔 수 없다. 이것도 찾아서 다 바꿔야 한다. 빌드 도구별로 패치 기능이 또 있어서 잘 활용하면 된다.

패키지 설치 -> 패치 -> 빌드 가 가능한 환경이면 devops가 replace(기존 저장소를 내부 넥서스로)를 할 수 있다. 근데 애매한게... 빌드 하는 과정에서 패치가 필요한경우가 있다. 이때는 개발자가 소스코드에서 직접 수정해줬다. 예를들어 Gradle 같은 경우는 init.gradle에서 설정이 가능하다.

 

 

+ Recent posts