폐쇄망에서 ingress/egress gateway 테스트 랩 — 외부 세계를 클러스터 안에 모사하기
폐쇄망(air-gapped) 클러스터에서 Istio ingress/egress gateway를 테스트할 수 있는 자기완결형 랩을 구성했다. 인터넷이 없어서 막히는 지점을 하나씩 대체하는 방식이며, 부품은 전부 홈랩에서 실측 검증을 거친 패턴(DNS/GSLB 재현 랩, 이중 egress gateway)의 재조립이다. 전체 manifest는 files/에 있고, 구성은 6절에서 한 단계씩 실행 → 확인 쌍으로 밟는다.
상태: 초안. manifest는
kubectl --dry-run+istioctl analyze(이슈 0)까지 통과했고, 조립체 전체의 트래픽 완주는 아직이다. 개별 패턴의 실측 근거는 각 절에 명시했다.
1. 문제를 셋으로 쪼갠다
폐쇄망에서 안 되는 것은 정확히 세 가지고, 각각 독립적으로 해결된다.
| 막히는 것 | 전략 | 수단 |
|---|---|---|
| 이미지·차트를 인터넷에서 못 받음 | 반입 | 사내 레지스트리 미러 + Helm chart tgz |
| 외부 도메인 DNS 질의 불가 | 모사 | 전용 CoreDNS가 가짜 외부 도메인을 authoritative로 서빙 |
| 실제 외부 서버 호출 불가 | 모사 | sidecar 미주입 nginx + 사설 CA = “mesh 밖 세계” |
이렇게 쪼갤 수 있는 근거: Istio 입장에서 “외부"란 인터넷이 아니라 (a) mesh 밖(sidecar 없음) + (b) 클러스터 서비스 디스커버리에 없는 도메인 + (c) 사설이 아닌 CA의 TLS라는 세 가지 조건일 뿐이다. 세 조건을 클러스터 안에서 충족시키면 Envoy는 그것을 외부와 구별하지 못하므로, ingress/egress의 모든 시나리오가 인터넷 없이 성립한다.
등장인물의 배치는 흐름이 없는 정적 정보라 표가 정확한 도구다 (트래픽 흐름은 4절·5절에서 하나씩 그린다):
| ns | 구성원 | 역할 |
|---|---|---|
lab-ext — 외부 세계 (sidecar 없음) |
fake-dns | 외부 DNS 모사 (CoreDNS hosts, ttl 5s) |
| ext-a · ext-b | 외부 HTTPS 서버 모사 (사설 CA TLS) | |
| ext-client | 외부 사용자 모사 — ingress 트래픽 소스 | |
istio-system — mesh 경계 |
ingressgateway · egressgateway | 진입·진출 지점 |
| Gateway lab-ingress · lab-egress / Secret www-lab-tls | gateway 설정·인증서는 workload ns에 둔다는 규율로 통일 | |
lab-apps — 우리 서비스 (sidecar 주입) |
web-a · web-b | ingress 백엔드 |
| mesh-client | egress 트래픽 소스·관측 지점 |
namespace를 둘로 나눴다(00-namespaces.yaml). DNS 랩에서는 단일 ns + pod annotation으로 주입을 껐지만, 이 랩은 “mesh 안/밖” 경계 자체가 테스트 대상이므로 ns 경계로 명시하는 쪽이 읽는 사람에게 정직하고, blast radius도 ns 2개로 한정된다.
2. 반입 — 폐쇄망 고유 작업은 이것뿐
이 절만 폐쇄망 특유의 작업이고, 이후는 온라인 클러스터와 완전히 같다.
이미지 6종 (images.txt) — Istio 본체는 2개가 전부다 (base 차트는 CRD만이라 이미지가 없다):
docker.io/istio/pilot:1.30.0 # istiod
docker.io/istio/proxyv2:1.30.0 # gateway pod + 모든 sidecar
registry.k8s.io/coredns/coredns:v1.11.3
docker.io/library/nginx:1.27-alpine
docker.io/library/busybox:1.36
docker.io/nicolaka/netshoot:latest # 반입 시점에 태그 고정 권장
차트 3종 + istioctl — 온라인 측에서 helm pull istio/{base,istiod,gateway} --version 1.30.0
으로 tgz를 만들어 반입하고, 폐쇄망에서는 repo add 없이 로컬 파일로 설치한다.
순서는 온라인과 동일하게 base → istiod → gateway ×2:
helm upgrade --install istio-base ./base-1.30.0.tgz -n istio-system --create-namespace
helm upgrade --install istiod ./istiod-1.30.0.tgz -n istio-system -f values-istiod.yaml
helm upgrade --install istio-ingressgateway ./gateway-1.30.0.tgz -n istio-system -f values-ingress-gateway.yaml
helm upgrade --install istio-egressgateway ./gateway-1.30.0.tgz -n istio-system -f values-egress-gateway.yaml
values에서 이미지 소스를 바꾸는 한 줄이 폐쇄망 설치의 핵심이다:
global:
hub: registry.corp.example/docker.io/istio # docker.io/istio 대신 사내 미러
tag: 1.30.0
여기서 함정 하나. hub는 설치 시점이 아니라 sidecar 주입 시점에 발화한다.
istiod 자체는 정상 기동했는데 주입 템플릿이 여전히 docker.io를 가리키면, 이후 뜨는
모든 워크로드가 ImagePullBackOff로 죽는다 — 원인이 한 단계 떨어져 있어 추적이 늦다.
그래서 설치 직후 검증 1순위는 컨트롤플레인 상태가 아니라 주입된 이미지 주소다:
kubectl -n <ns> get pod -o jsonpath='{.items[*].spec.containers[*].image}'
istioctl도 1.30.0으로 맞춰 반입한다. 1.27 클라이언트로 1.30 컨트롤플레인을 조회하면 진단 착시가 나는 것을 실측으로 확인한 바 있다.
3. 외부 세계 모사 — 검증된 패턴 세 개의 재사용
3-1. 가짜 외부 DNS (10-fake-dns.yaml)
전용 CoreDNS 하나가 가짜 외부 도메인 3개만 authoritative(ttl 5s)로 응답하고, 나머지는 클러스터 DNS로 넘긴다:
hosts /hosts/addn api.lab.external blocked.lab.external www.lab.external {
ttl 5
reload 2s
fallthrough
}
forward . __CLUSTER_DNS__
forward를 남기는 이유가 이 구성의 급소다. 이 DNS를 바라보는 pod의 sidecar는
istiod(클러스터 이름)를 계속 resolve해야 xDS를 받는다. forward가 없으면 sidecar가
아예 안 뜬다 — 자기완결형 DNS의 함정으로, DNS 랩에서 실제로 밟고 정리한 지점이다.
레코드 변경은 존파일(/hosts/addn) 재작성이고 reload 2s가 자동 재적재하므로,
운영 중 GSLB 절체 모사까지 이 장치 하나로 된다. 단 두 가지 규율: 존파일은 항상
전체 줄을 한 번에 재작성할 것(한 줄만 쓰면 나머지 소실), Corefile 자체를 바꿨으면
rollout restart가 필요하다는 것(존파일과 달리 자동 재적재 안 됨).
호스트 3개의 역할 분담:
| 호스트 | 가리키는 곳 | 용도 |
|---|---|---|
api.lab.external |
ext-a pod IP | egress 대상 (ServiceEntry 등록됨) |
blocked.lab.external |
ext-b pod IP | REGISTRY_ONLY 차단 검증 (DNS는 되지만 SE 없음) |
www.lab.external |
ingressgateway Service IP | ingress 진입 호스트 (외부 사용자가 보는 이름) |
blocked.lab.external 뒤에도 살아있는 서버를 뒀다. 차단 테스트가 실패했을 때
“서버가 없어서"인지 “정책 때문"인지 갈리지 않도록, 실패 원인을 sidecar 정책 하나로
고립시키기 위해서다.
3-2. 가짜 외부 서버 (20-ext-servers.yaml)
sidecar 미주입 nginx 2대가 사설 CA로 발급한 인증서(SAN 일치)로 TLS를 말한다. DNS 랩과 다른 결정 하나: Kubernetes Service를 만들지 않았다.
Service를 만들면 ClusterIP가 mesh service registry에 올라가고 모든 sidecar에
per-VIP 전용 리스너가 생긴다. SE 호스트가 그 VIP로 resolve되면 L4(SNI passthrough)
경로에서 VIP 리스너가 0.0.0.0:443 캐치올보다 먼저 매치되어, 트래픽이 SE cluster가
아닌 in-mesh 경로를 타 버린다. curl은 200이 나오기 때문에 무증상인 채로 실험이
무효가 되는 함정 — DNS 랩에서 실제로 밟았다. 그래서 fake-dns의 A 레코드는 pod IP를
직접 가리키고, “서비스 디스커버리에 없는 외부 서버"라는 모사 취지에도 이쪽이 충실하다.
대가는 pod 재시작 시 레코드가 낡는 것인데, 6절 ⑤단계(A 레코드 3줄 재기록)를 다시
실행하면 된다.
3-3. 사설 CA (6절 ①·②단계에서 직접 생성)
CA 하나를 만들어 외부 서버 인증서(SAN=api/blocked.lab.external)와 ingress
인증서(SAN=www.lab.external)를 같은 체인으로 발급한다. 폐쇄망은 공인 CA가 애초에
불가능하므로 사설 CA가 제약이 아니라 정상 경로다. ca.crt는 ConfigMap으로 양쪽 ns에
배포해 클라이언트가 --cacert로 검증을 생략하지 않고 테스트한다 — DNS 랩은
insecureSkipVerify로 우회했지만, gateway 테스트에서는 인증서 체인 자체가 검증
대상이므로 이번엔 검증을 포함시켰다.
클라이언트 pod의 DNS 연결은 dnsPolicy: None + dnsConfig.nameservers=[fake-dns]다
(30·40-*.yaml). app 컨테이너와
istio-proxy가 같은 resolv.conf를 공유하므로 Envoy(STRICT_DNS의 c-ares)도 자동으로
fake-dns를 본다. searches의 cluster domain은 하드코딩하지 않고 6절 ⑥단계에서 coredns
ConfigMap을 조회해 주입한다 — cluster.local을 하드코딩했다가 커스텀 도메인
클러스터에서 sidecar가 안 뜨는 장애를 실제로 겪었다.
4. Ingress 테스트 (50-ingress.yaml)
폐쇄망에서 ingress의 유일한 고민은 “외부 클라이언트가 없다"인데, 답은 egress와
대칭이다: sidecar 미주입 pod가 곧 외부 클라이언트다. ext-client는 fake-dns를
바라보므로 www.lab.external을 실제 DNS 경로로 resolve해서 들어온다.
sequenceDiagram
autonumber
participant C as ext-client (mesh 밖)
participant D as fake-dns
participant G as ingressgateway
participant W as web-a / web-b
C->>D: www.lab.external A?
D-->>C: ingressgateway IP (ttl 5s)
C->>G: https 요청 (SNI: www.lab.external)
Note over G: TLS 종단 - credentialName: www-lab-tls
G->>W: HTTP 라우팅 (/ 는 web-a, /b 는 web-b)
W-->>C: 200 "web-a"# T1. host/path 분기 (평문) — 기대: / -> web-a, /b -> web-b
kubectl -n lab-ext exec deploy/ext-client -- curl -sS http://www.lab.external/
kubectl -n lab-ext exec deploy/ext-client -- curl -sS http://www.lab.external/b
# T2. TLS termination + 사설 CA 검증 포함 — 기대: 200
kubectl -n lab-ext exec deploy/ext-client -- \
curl -sS --cacert /etc/lab-ca/ca.crt https://www.lab.external/
HTTP:80과 HTTPS:443을 둘 다 열었다. 80이 되고 443이 안 되면 인증서·secret 쪽,
둘 다 안 되면 라우팅 쪽 — 실패 원인을 반씩 자르는 용도다. TLS 종단 인증서는
credentialName: www-lab-tls로 참조하는데, 이 secret은 gateway workload의
ns(istio-system) 에 있어야 한다. 같은 규율로 Gateway 리소스(lab-ingress·lab-egress)도
istio-system에 통일했다 — 다른 ns에 있는 VS는 istio-system/lab-ingress 정규화
형식으로 Gateway를 참조한다.
한 가지 용도 구분: curl --resolve로도 SNI/Host 분기는 테스트할 수 있지만, 그건
DNS 경로를 우회한다. DNS 동작 자체(절체 전파 등)를 검증하는 시나리오에서는 쓰면 안
된다. 클러스터 밖(폐쇄망 내 다른 VM)에서 진짜 L4 경로까지 보려면 NodePort로 같은
테스트를 반복하면 된다.
5. Egress 테스트 (60-egress.yaml, 65-sidecar-registry-only.yaml)
가동 검증된 이중 egress gateway 랩의 passthrough
패턴을 복제하되, 전용 gateway 대신 공용 istio-egressgateway를 썼다 — 폐쇄망 첫
검증은 추가 gateway 반입·배포 없이 시작하는 게 부담이 적다. 체인은 SE(resolution: DNS, exportTo로 client ns + istio-system만) + PASSTHROUGH Gateway + VS 2단(mesh
route / gateway route)이다.
sequenceDiagram
autonumber
participant M as mesh-client (+ sidecar)
participant D as fake-dns
participant E as egressgateway
participant A as ext-a (api.lab.external)
M->>D: api.lab.external A?
D-->>M: ext-a pod IP (ttl 5s)
M->>E: TLS/SNI - sidecar의 VS mesh route가 gateway로 보냄
E->>A: SNI passthrough - SE cluster(STRICT_DNS)
A-->>M: 200 "ext-a" (TLS는 client와 ext-a의 end-to-end)
Note over M: blocked.lab.external은 그림에 없다 - SE 미등록이라<br/>sidecar가 차단(connection reset), 트래픽이 mesh를 떠나지 않음REGISTRY_ONLY는 전역 meshConfig가 아니라 Sidecar 리소스로 ns에만 걸었다. 공유 테스트 클러스터에서 전역 REGISTRY_ONLY는 다른 워크로드의 외부 호출까지 일괄 차단하기 때문이다:
apiVersion: networking.istio.io/v1beta1
kind: Sidecar
metadata: { name: default, namespace: lab-apps }
spec:
outboundTrafficPolicy:
mode: REGISTRY_ONLY
# T3. egress gateway 경유 — 기대: ext-a 응답
kubectl -n lab-apps exec deploy/mesh-client -c netshoot -- \
curl -sS --cacert /etc/lab-ca/ca.crt https://api.lab.external/
# T4. 미등록 외부 차단 — 기대: 실패(connection reset) = PASS
kubectl -n lab-apps exec deploy/mesh-client -c netshoot -- \
curl -sS --cacert /etc/lab-ca/ca.crt https://blocked.lab.external/
T4의 실패 형태는 HTTP 502가 아니라 connection reset이다. 이 경로는 L4(SNI)라서 sidecar가 HTTP 응답을 만들어 줄 계층이 없다. 경유·반영은 명령으로 직접 확인한다:
istioctl proxy-config listeners deploy/mesh-client -n lab-apps --port 443
istioctl proxy-config endpoints deploy/mesh-client -n lab-apps \
--cluster "outbound|443||api.lab.external" # 기대: fake-dns A레코드 = ext-a pod IP
kubectl -n istio-system logs deploy/istio-egressgateway --tail=20
부수 효과 하나 — 이 구조는 gateway 테스트를 넘어 GSLB 절체 시나리오로 그대로
확장된다. 존파일의 api.lab.external을 ext-a → ext-b로 재기록하면 STRICT_DNS의
endpoint 갱신·drain 거동을 폐쇄망 안에서 재현할 수 있다. 그 자체의 실측 결과는
DNS/GSLB 재현 랩 참조.
6. 구성 순서 — 하나씩 확인하며 올리기
전 과정을 손으로 밟는 절차다. 각 단계는 실행 → 확인 한 쌍이고, 확인이 실패하면 다음 단계로 넘어가지 않는 것이 규율이다 — 뒤로 갈수록 원인이 겹쳐서 추적이 어려워진다. manifest는 files/에서 받는다.
폐쇄망이라면 apply 전에 이미지 참조 앞에 미러 주소를 붙인다. manifest의 이미지가 전부 fully-qualified라 prepend만 하면 Harbor proxy-cache 레이아웃이 그대로 나온다 (flat 미러면 image를 직접 수정하거나 containerd registry mirror 설정 사용):
sed -E 's#^([[:space:]]*image:[[:space:]]*)#\1registry.corp.example/#' <manifest>.yaml | kubectl apply -f -
① 사설 CA와 인증서 — CA 하나, 서버 인증서 둘
openssl req -x509 -newkey rsa:2048 -nodes -days 365 \
-keyout ca.key -out ca.crt -subj "/CN=Airgap Lab CA"
# 외부 서버용 (ext-a/ext-b가 같은 인증서 공유 — SAN에 두 호스트)
openssl req -newkey rsa:2048 -nodes -keyout ext.key -out ext.csr -subj "/CN=api.lab.external"
openssl x509 -req -in ext.csr -CA ca.crt -CAkey ca.key -CAcreateserial -days 365 -out ext.crt \
-extfile <(echo "subjectAltName=DNS:api.lab.external,DNS:blocked.lab.external")
# ingress 종단용
openssl req -newkey rsa:2048 -nodes -keyout www.key -out www.csr -subj "/CN=www.lab.external"
openssl x509 -req -in www.csr -CA ca.crt -CAkey ca.key -CAcreateserial -days 365 -out www.crt \
-extfile <(echo "subjectAltName=DNS:www.lab.external")
확인 — SAN이 비어 있으면 이후 curl이 전부 인증서 오류로 죽는다:
openssl x509 -in ext.crt -noout -ext subjectAltName # 기대: api + blocked 두 호스트
② namespace + secret/ConfigMap
kubectl apply -f 00-namespaces.yaml
kubectl -n lab-ext create secret tls ext-tls --cert=ext.crt --key=ext.key
kubectl -n istio-system create secret tls www-lab-tls --cert=www.crt --key=www.key
kubectl -n lab-ext create configmap lab-ca --from-file=ca.crt
kubectl -n lab-apps create configmap lab-ca --from-file=ca.crt
www-lab-tls만 istio-system에 만드는 이유: credentialName은 Gateway 리소스의 ns가
아니라 gateway workload의 ns에서 secret을 찾는다.
③ fake-dns — cluster DNS를 발견해서 주입
__CLUSTER_DNS__ 자리에 클러스터 DNS의 ClusterIP를 넣는다. forward 대상이 틀리면
sidecar가 istiod를 resolve하지 못해 아예 뜨지 않으므로, 값부터 눈으로 확인한다:
CLUSTER_DNS=$(kubectl -n kube-system get svc coredns -o jsonpath='{.spec.clusterIP}') # 없으면 kube-dns
echo $CLUSTER_DNS
sed "s/__CLUSTER_DNS__/$CLUSTER_DNS/g" 10-fake-dns.yaml | kubectl apply -f -
kubectl -n lab-ext rollout status deploy/fake-dns
④ 외부 서버 모사
kubectl apply -f 20-ext-servers.yaml
kubectl -n lab-ext rollout status deploy/ext-a
kubectl -n lab-ext rollout status deploy/ext-b
⑤ A 레코드 기록 — pod IP를 조회해서 3줄 일괄로
Service가 없으므로(3-2절) pod IP를 직접 넣는다. 3줄을 한 번에 쓰는 게 규율이다 (한 줄만 쓰면 나머지 레코드 소실):
IP_API=$(kubectl -n lab-ext get pod -l app=ext-a -o jsonpath='{.items[0].status.podIP}')
IP_BLOCKED=$(kubectl -n lab-ext get pod -l app=ext-b -o jsonpath='{.items[0].status.podIP}')
IP_INGRESS=$(kubectl -n istio-system get svc istio-ingressgateway -o jsonpath='{.spec.clusterIP}')
kubectl -n lab-ext exec deploy/fake-dns -c writer -- sh -c \
"printf '%s api.lab.external\n%s blocked.lab.external\n%s www.lab.external\n' \
$IP_API $IP_BLOCKED $IP_INGRESS > /hosts/addn"
확인:
kubectl -n lab-ext exec deploy/fake-dns -c writer -- cat /hosts/addn # 기대: 3줄
ext pod를 재시작했다면 IP가 바뀌므로 이 단계만 다시 반복하면 된다.
⑥ 클라이언트 — fake-dns IP와 cluster domain을 발견해서 주입
cluster domain은 하드코딩하지 않고 coredns ConfigMap에서 발견한다. cluster.local을
박아 넣었다가 커스텀 도메인 클러스터에서 sidecar가 안 뜨는 장애를 실제로 겪었다(3-3절):
LABDNS_IP=$(kubectl -n lab-ext get svc fake-dns -o jsonpath='{.spec.clusterIP}')
CLUSTER_DOMAIN=$(kubectl -n kube-system get cm coredns -o jsonpath='{.data.Corefile}' \
| grep -oE 'kubernetes[[:space:]]+[^ ]+' | awk '{print $2}')
echo "$LABDNS_IP / $CLUSTER_DOMAIN" # 둘 다 값이 있는지 먼저 확인
for f in 30-ext-client.yaml 40-mesh-client.yaml; do
sed -e "s/__LABDNS_IP__/$LABDNS_IP/g" -e "s/__CLUSTER_DOMAIN__/$CLUSTER_DOMAIN/g" $f \
| kubectl apply -f -
done
확인 두 가지 — 이 단계가 이 랩에서 가장 잘 깨지는 곳이다:
# (a) mesh-client가 2/2인가 — sidecar가 떴다 = istiod resolve가 fake-dns forward 경로로 성공했다는 증거
kubectl -n lab-apps get pod -l app=mesh-client
# (b) 가짜 도메인이 fake-dns에서 풀리는가
kubectl -n lab-ext exec deploy/ext-client -- dig +short www.lab.external # 기대: ingressgateway IP
(a)가 1/2에서 멈추면 십중팔구 ③의 forward 대상이나 ⑥의 cluster domain이 틀린 것이다.
⑦ ingress 시나리오 → 4절의 T1·T2로 검증
kubectl apply -f 50-ingress.yaml
istioctl analyze -n lab-apps && istioctl analyze -n istio-system # 경고 0 확인 후 트래픽
⑧ egress + REGISTRY_ONLY 시나리오 → 5절의 T3·T4로 검증
kubectl apply -f 60-egress.yaml
kubectl apply -f 65-sidecar-registry-only.yaml
# 트래픽 전에 설정 반영부터 — SE cluster의 endpoint가 ⑤에서 넣은 ext-a pod IP인가
istioctl proxy-config endpoints deploy/mesh-client -n lab-apps \
--cluster "outbound|443||api.lab.external"
(참고) airgap-lab-setup.sh는 위 ①~⑧과 동일한 절차의 자동화 버전이다. 이 랩의 기본 경로는 어디까지나 위처럼 파일을 하나씩 apply 하며 확인하는 것이고, 스크립트는 랩을 여러 번 재구축하게 됐을 때만 참고.
7. 함정 목록 (실측 기반)
global.hub오설정은 주입 시점 발화 — istiod 정상인데 신규 pod 전멸. 2절.- cluster domain 하드코딩 금지 — searches가 틀리면 istiod resolve 실패 → sidecar 안 뜸.
- ext 서버에 Service를 만들면 실험 무효 — VIP 리스너 선점, curl 200이라 무증상. 3-2절.
- Corefile 변경은 rollout restart — 존파일만 reload 2s 자동.
- 존파일은 전체 줄 일괄 재기록 — 부분 기록 시 나머지 레코드 소실.
- ext pod 재시작 = A 레코드 낡음 — 6절 ⑤단계 재실행으로 재동기화.
- VS/DR destination은
cluster.local고정 — Istio service registry는 kubelet clusterDomain과 무관하게*.svc.cluster.local로 등록한다. pod resolv.conf의 search 도메인(커스텀 도메인)과 별개 축이라, 커스텀 도메인 클러스터에서도 destination은 cluster.local로 쓴다.
첨부
| 파일 | 내용 |
|---|---|
| README.md | 시나리오 운영 문서(반입 체크리스트·합격선·설계 결정) |
| 00-namespaces.yaml | ns 2개 — mesh 안/밖 경계 |
| 10-fake-dns.yaml | 가짜 외부 DNS (CoreDNS hosts, ttl 5s) |
| 20-ext-servers.yaml | 가짜 외부 HTTPS 서버 ×2 (Service 없음) |
| 30-ext-client.yaml / 40-mesh-client.yaml | 외부/내부 클라이언트 |
| 50-ingress.yaml | ingress 백엔드·Gateway·VS |
| 60-egress.yaml | SE + PASSTHROUGH Gateway + VS 2단 |
| 65-sidecar-registry-only.yaml | ns 스코프 REGISTRY_ONLY |
| airgap-lab-setup.sh | (참고) 6절 ①~⑧ 동일 절차의 자동화 — 반복 재구축용 |
| images.txt | 반입 이미지 체크리스트 |
Files
- 00-namespaces.yaml 1 KB
- 10-fake-dns.yaml 3 KB
- 20-ext-servers.yaml 3 KB
- 30-ext-client.yaml 1 KB
- 40-mesh-client.yaml 2 KB
- 50-ingress.yaml 4 KB
- 60-egress.yaml 3 KB
- 65-sidecar-registry-only.yaml 1012 B
- airgap-lab-setup.sh 9 KB
- readme.md 25 KB
- images.txt 756 B
- Raw Markdown (index.md)