소개
Kubernetes API 는 지속적으로 발전합니다. 이전 클러스터에서 작동하던 매니페스트가 새로운 클러스터에서는 API 버전이 제거되었거나 필드 구조가 변경되어 실패할 수 있습니다. CKAD 업무에서 이는 일반적으로 실무적인 유지보수 작업으로 나타납니다. 즉, 오류를 읽고, 현재 API 를 식별하며, 매니페스트를 업데이트하고, 새로운 버전이 정상적으로 수용되는지 확인하는 과정입니다.
이 실습에서는 오래된 Ingress 매니페스트를 networking.k8s.io/v1beta1에서 networking.k8s.io/v1으로 마이그레이션합니다. 먼저 Ingress 가 참조할 서비스를 생성한 다음, 이전 매니페스트가 실패하는 것을 확인하고, kubectl 검색 명령을 사용하여 현재 API 를 검사하고, 매니페스트를 다시 작성한 뒤 수정된 Ingress 를 적용합니다.
서비스 참조 준비
이 단계에서는 깨끗한 네임스페이스와 간단한 서비스를 준비합니다. 이전 및 새로운 Ingress 매니페스트 모두 이 서비스를 가리키게 하여, 마이그레이션 작업이 파드 (Pod) 준비 상태나 트래픽 라우팅이 아닌 API 구조에 집중되도록 합니다.
/home/labex/project에서 시작합니다:
mkdir -p /home/labex/project
cd /home/labex/project
Kubernetes API 서버에 연결할 수 있는지 확인합니다. VM 이 막 시작되어 노드가 아직 준비되지 않았다면 몇 초 기다린 후 명령을 다시 실행하세요.
kubectl get nodes --request-timeout=5s
예상 출력은 다음과 같습니다:
NAME STATUS ROLES AGE VERSION
labex-v135 Ready control-plane ... v1.35...
ckad-prep-api-migration이라는 이름의 네임스페이스를 생성하고 현재 네임스페이스로 설정합니다:
kubectl create namespace ckad-prep-api-migration
kubectl config set-context --current --namespace=ckad-prep-api-migration
app-web이라는 이름의 ClusterIP 서비스를 생성합니다. --tcp=80:80 옵션은 서비스가 포트 80에서 수신 대기하며, 일치하는 파드가 있을 경우 대상 포트 80으로 전달함을 의미합니다. 이 마이그레이션 실습에서는 HTTP 트래픽이 아닌 Ingress API 필드를 검증하는 것이 목적이므로 서비스 객체 자체만으로 충분합니다.
kubectl create service clusterip app-web --tcp=80:80
서비스가 존재하는지 확인합니다:
kubectl get service app-web
예상 출력은 다음과 같습니다:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
app-web ClusterIP ... <none> 80/TCP ...
사용 중단된 매니페스트 실패 확인
이 단계에서는 오래된 Ingress 매니페스트를 생성하고 현재 클러스터에서 거부되도록 합니다. 마이그레이션 작업의 첫 번째 단서는 종종 API 서버의 오류 메시지이므로, 이는 유용한 실습입니다.
old-ingress.yaml을 생성합니다:
cat > old-ingress.yaml <<'EOF'
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: app-web
spec:
rules:
- host: app.example.local
http:
paths:
- path: /
backend:
serviceName: app-web
servicePort: 80
EOF
파일의 상단을 읽어봅니다. apiVersion 필드는 어떤 API 그룹과 버전이 이 객체를 처리해야 하는지 Kubernetes 에 알려줍니다.
sed -n '1,20p' old-ingress.yaml
예상 출력은 다음과 같습니다:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
...
serviceName: app-web
servicePort: 80
API 서버에 매니페스트를 생성하지 않고 검증하도록 요청합니다. --dry-run=server는 검증을 위해 객체를 API 서버로 전송하며, || true는 이 실패가 예상된 결과이므로 튜토리얼이 중단되지 않도록 합니다.
kubectl apply --dry-run=server -f old-ingress.yaml || true
예상 출력에는 다음과 유사한 오류가 포함됩니다:
error: resource mapping not found for name: "app-web" namespace: "" from "old-ingress.yaml": no matches for kind "Ingress" in version "networking.k8s.io/v1beta1"
중요한 증거는 no matches for kind "Ingress" in version "networking.k8s.io/v1beta1"입니다. 이는 현재 클러스터가 더 이상 해당 API 버전을 제공하지 않음을 의미합니다.
현재 Ingress API 구조 탐색
이 단계에서는 파일을 다시 작성하기 전에 현재 Ingress API 를 검사합니다. 이는 마이그레이션 작업을 체계적으로 수행하는 방법입니다. 클러스터가 허용하는 구조를 보여줄 수 있을 때 새로운 필드를 추측하지 마세요.
제공되는 Ingress 리소스를 나열합니다:
kubectl api-resources | grep -i '^ingresses'
예상 출력은 다음과 같습니다:
ingresses ing networking.k8s.io/v1 true Ingress
kubectl explain을 사용하여 현재 백엔드 서비스 필드를 검사합니다. 서비스 백엔드는 spec.rules[].http.paths[].backend.service 아래에 중첩되어 있어 경로가 깁니다.
kubectl explain ingress.spec.rules.http.paths.backend.service --recursive | sed -n '1,80p'
예상 출력은 다음과 같습니다:
GROUP: networking.k8s.io
KIND: Ingress
VERSION: v1
FIELD: service <IngressServiceBackend>
...
name <string> -required-
port <ServiceBackendPort> -required-
이제 마이그레이션된 current-ingress.yaml을 생성합니다. 새로운 매니페스트는 networking.k8s.io/v1을 사용하고, pathType을 추가하며, serviceName과 servicePort를 중첩된 service.name 및 service.port.number 필드로 대체합니다.
cat > current-ingress.yaml <<'EOF'
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app-web
spec:
rules:
- host: app.example.local
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: app-web
port:
number: 80
EOF
서버 측 드라이 런 (dry run) 으로 마이그레이션된 매니페스트를 검증합니다:
kubectl apply --dry-run=server -f current-ingress.yaml
예상 출력:
ingress.networking.k8s.io/app-web created (server dry run)
마이그레이션된 Ingress 적용 및 검사
이 단계에서는 마이그레이션된 Ingress 를 생성하고 Kubernetes 에 저장된 필드를 검사합니다. 리소스를 적용하는 것은 매니페스트가 현재 API 서버와 일치한다는 최종 증명입니다.
마이그레이션된 매니페스트를 적용합니다:
kubectl apply -f current-ingress.yaml
예상 출력:
ingress.networking.k8s.io/app-web created
Ingress 를 나열합니다:
kubectl get ingress app-web
예상 출력은 다음과 같습니다:
NAME CLASS HOSTS ADDRESS PORTS AGE
app-web ... app.example.local ... 80 ...
저장된 객체에서 마이그레이션된 백엔드 필드를 직접 검사합니다:
kubectl get ingress app-web -o jsonpath='{.apiVersion}{" "}{.spec.rules[0].http.paths[0].pathType}{" "}{.spec.rules[0].http.paths[0].backend.service.name}{":"}{.spec.rules[0].http.paths[0].backend.service.port.number}{"\n"}'
예상 출력:
networking.k8s.io/v1 Prefix app-web:80
이 출력은 세 가지를 동시에 증명합니다. 객체가 현재 API 버전을 사용하고 있고, 경로에 명시적인 pathType이 있으며, 백엔드가 networking.k8s.io/v1에서 요구하는 중첩된 서비스 참조를 사용하고 있다는 점입니다.
요약
실무적인 API 마이그레이션 워크플로우를 실습했습니다. 오래된 networking.k8s.io/v1beta1 Ingress 매니페스트를 생성하고, 서버 측 드라이 런을 사용하여 현재 클러스터가 이를 거부함을 확인했으며, 제공되는 networking.k8s.io/v1 API 를 검사하고, pathType과 중첩된 서비스 참조를 사용하여 백엔드 필드를 다시 작성한 뒤, 마이그레이션된 Ingress 를 적용하고 검사했습니다.


