소개
Kubernetes 는 새로운 리소스 유형을 통해 확장할 수 있습니다. 일반적으로 CRD 라고 불리는 CustomResourceDefinition 은 새로운 API 리소스를 Kubernetes API 서버에 등록합니다. 등록 후에는 익숙한 kubectl 명령어를 사용하여 해당 유형의 객체를 생성, 조회, 상세 확인, 레이블 지정 및 패치할 수 있습니다.
이번 실습에서는 AppProfile이라는 작은 네임스페이스 범위의 CRD 를 생성하고, Kubernetes API 발견 명령어를 통해 이를 확인하며, YAML 파일로부터 사용자 정의 리소스를 생성하고 일반적인 Kubernetes 객체처럼 업데이트해 봅니다. 이 실습에서는 컨트롤러가 필요하지 않으며, 사용자 정의 리소스 유형이 어떻게 나타나고 해당 객체를 어떻게 다루는지 이해하는 데 중점을 둡니다.
사용자 정의 리소스를 위한 네임스페이스 준비
이 단계에서는 사용자 정의 리소스 실습을 위한 깨끗한 네임스페이스를 준비합니다.
/home/labex/project에서 시작합니다. 이 디렉토리에 CRD 와 사용자 정의 리소스 매니페스트를 작성할 것입니다.
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...
애플리케이션 객체를 생성하기 전에 클러스터 네트워킹 Pod 가 준비 (Ready) 상태가 될 때까지 기다립니다.
kubectl wait --namespace kube-system --for=condition=Ready pod -l k8s-app=calico-node --timeout=120s
예상 출력:
pod/calico-node-... condition met
ckad-prep-customresources라는 이름의 네임스페이스를 생성합니다:
kubectl create namespace ckad-prep-customresources
이 네임스페이스를 현재 컨텍스트의 네임스페이스로 설정합니다:
kubectl config set-context --current --namespace=ckad-prep-customresources
현재 네임스페이스를 확인합니다:
kubectl config view --minify --output 'jsonpath={..namespace}'; echo
예상 출력:
ckad-prep-customresources
CRD 를 사용하여 새로운 리소스 유형 등록
이 단계에서는 AppProfile이라는 이름의 CustomResourceDefinition 을 생성합니다.
CRD 에는 두 가지 중요한 명명 계층이 있습니다. metadata.name은 복수형 리소스 이름과 API 그룹을 결합한 형태 (예: appprofiles.training.labex.io) 입니다. spec.names 섹션은 사용자가 리소스를 참조할 방법을 정의합니다: kind: AppProfile, plural: appprofiles, singular: appprofile, 그리고 단축어 appprof입니다.
app-profile-crd.yaml 파일을 생성합니다:
cat > app-profile-crd.yaml <<'EOF'
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: appprofiles.training.labex.io
spec:
group: training.labex.io
scope: Namespaced
names:
plural: appprofiles
singular: appprofile
kind: AppProfile
shortNames:
- appprof
versions:
- name: v1
served: true
storage: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
required:
- image
- replicas
properties:
image:
type: string
replicas:
type: integer
minimum: 1
tier:
type: string
EOF
CRD 를 적용합니다:
kubectl apply -f app-profile-crd.yaml
예상 출력:
customresourcedefinition.apiextensions.k8s.io/appprofiles.training.labex.io created
API 서버가 CRD 를 'Established' 상태로 보고할 때까지 기다립니다:
kubectl wait --for=condition=Established crd/appprofiles.training.labex.io --timeout=120s
예상 출력:
customresourcedefinition.apiextensions.k8s.io/appprofiles.training.labex.io condition met
CRD 의 이름과 범위를 확인합니다:
kubectl get crd appprofiles.training.labex.io -o 'jsonpath={.spec.names.kind}{" "}{.spec.names.plural}{" "}{.spec.scope}{"\n"}'
예상 출력:
AppProfile appprofiles Namespaced
사용자 정의 리소스 발견 및 생성
이 단계에서는 새로운 리소스 유형을 발견하고 첫 번째 AppProfile을 생성합니다.
kubectl api-resources는 API 서버가 알고 있는 리소스 유형을 나열합니다. CRD 가 설정되면, 내장 리소스 유형과 함께 이 발견 목록에 나타납니다.
kubectl api-resources --api-group=training.labex.io
예상 출력:
NAME SHORTNAMES APIVERSION NAMESPACED KIND
appprofiles appprof training.labex.io/v1 true AppProfile
kubectl explain을 사용하여 CRD 로부터 학습한 스키마를 확인합니다. spec 필드는 애플리케이션별 설정이 위치하는 곳입니다.
kubectl explain appprofile.spec
예상 출력:
GROUP: training.labex.io
KIND: AppProfile
VERSION: v1
FIELD: spec <Object>
frontend-profile.yaml 파일을 생성합니다:
cat > frontend-profile.yaml <<'EOF'
apiVersion: training.labex.io/v1
kind: AppProfile
metadata:
name: frontend
labels:
app.kubernetes.io/part-of: storefront
tier: web
spec:
image: nginx:1.27
replicas: 2
tier: web
EOF
사용자 정의 리소스를 적용합니다:
kubectl apply -f frontend-profile.yaml
예상 출력:
appprofile.training.labex.io/frontend created
복수형 이름을 사용하여 사용자 정의 리소스를 나열합니다:
kubectl get appprofiles
예상 출력:
NAME AGE
frontend ...
jsonpath를 사용하여 사용자 정의 리소스의 필드를 읽어옵니다:
kubectl get appprofile frontend -o 'jsonpath={.spec.image}{" "}{.spec.replicas}{" "}{.spec.tier}{"\n"}'
예상 출력:
nginx:1.27 2 web
사용자 정의 리소스 업데이트 및 선택
이 단계에서는 내장 객체에 사용하는 것과 동일한 kubectl 패턴으로 사용자 정의 리소스를 관리합니다.
frontend 사용자 정의 리소스를 패치하여 원하는 복제본 (replica) 수를 변경합니다. --type=merge 옵션은 전체 리소스를 교체하는 대신 JSON 객체를 기존 객체에 병합하도록 Kubernetes 에 지시합니다.
kubectl patch appprofile frontend --type=merge -p '{"spec":{"replicas":3}}'
예상 출력:
appprofile.training.labex.io/frontend patched
업데이트된 값을 확인합니다:
kubectl get appprofile frontend -o 'jsonpath={.spec.replicas}{"\n"}'
예상 출력:
3
worker라는 이름의 두 번째 사용자 정의 리소스를 생성합니다:
cat > worker-profile.yaml <<'EOF'
apiVersion: training.labex.io/v1
kind: AppProfile
metadata:
name: worker
labels:
app.kubernetes.io/part-of: storefront
tier: worker
spec:
image: busybox:1.36
replicas: 1
tier: worker
EOF
kubectl apply -f worker-profile.yaml
예상 출력:
appprofile.training.labex.io/worker created
storefront 애플리케이션에 속한 사용자 정의 리소스만 나열합니다. 사용자 정의 리소스도 일반적인 Kubernetes 레이블을 지원하기 때문에 가능합니다.
kubectl get appprofiles -l app.kubernetes.io/part-of=storefront
예상 출력:
NAME AGE
frontend ...
worker ...
단축어 appprof를 사용하여 각 리소스 이름과 복제본 수를 출력합니다:
kubectl get appprof -o 'jsonpath={range .items[*]}{.metadata.name}{"="}{.spec.replicas}{"\n"}{end}'
예상 출력:
frontend=3
worker=1
요약
CRD 를 생성하고, 설정될 때까지 기다린 후, kubectl api-resources와 kubectl explain을 통해 새로운 API 리소스를 발견하고, 사용자 정의 리소스를 생성 및 패치하고, 레이블로 선택하며, 단축어를 사용하는 방법을 실습했습니다. 이는 CKAD 시험에서 오퍼레이터, 컨트롤러 또는 플랫폼 확장에 의해 설치된 리소스를 다룰 때 사용하게 될 핵심 운영 기술입니다.


