LabHub
배우기 러닝패스 코스

KCNA — Kubernetes・クラウドネイティブ入門

Serviceでポッドを見つけ設定とストレージを付ける

LabHub 에서 이어서 보기

한국어 원문으로 표시합니다.

목표

Service 가 파드를 어떻게 찾는지, 못 찾으면 어떤 모습인지 직접 만들어 보고, ConfigMap/Secret 주입과 PVC 요청, 서비스 DNS 이름 규칙까지 손으로 확인합니다.

왜 중요한가

Service 관련 장애의 압도적 다수는 "서비스가 안 만들어졌다"가 아니라 "서비스는 만들어졌는데 뒤에 아무것도 없다" 입니다. 쿠버네티스는 셀렉터가 실제로 파드를 잡는지 검증해 주지 않기 때문입니다. 오타 하나로 엔드포인트가 0 건이 되어도 kubectl get svc 는 멀쩡해 보입니다. 그래서 이 실습에서는 일부러 그 상황을 만들어 봅니다. 한 번 손으로 만들어 본 실패는 현장에서 3분 만에 진단됩니다.

ConfigMap/Secret 은 12-factor 의 "설정은 환경에서"를 쿠버네티스가 구현한 형태입니다. 이미지는 어디서나 같고, 다른 건 주입되는 값이어야 합니다. 다만 Secret 은 이름과 달리 기본 설정에서 암호화되지 않는다는 점을 기억해 두세요 — 이건 KCSA 의 중요한 주제입니다.

PVC 는 '요청서'라는 비유가 전부입니다. 파드는 "NFS 서버 10.0.0.5 의 /export/data" 를 가리키지 않고 "1Gi 짜리 RWO 저장소"를 요청합니다. 이 간접 계층 덕분에 같은 매니페스트가 노트북 클러스터에서도 프로덕션에서도 돕니다.

단계

  1. 네임스페이스 kcna-net 을 만들고 그 안에 Deployment shop 을 만듭니다 — 이미지 nginx:1.27-alpine, replicas 2, 파드 템플릿 라벨 app=shop.
  2. Service shop-svc 를 만듭니다 — 타입 ClusterIP, port 80, 셀렉터 app=shop. 엔드포인트가 2 건 잡히는지 확인합니다.
  3. Service broken-svc 를 같은 네임스페이스에 만듭니다 — port 80 이지만 셀렉터는 일부러 app=shopp(p 하나 더). 엔드포인트가 0 건인 것을 확인하고, 이 서비스를 고치는 올바른 셀렉터를 /root/kcna-net/diagnosis.txtapp=shop 형태로 한 줄 저장합니다.
  4. Service shop-np 를 만듭니다 — 타입 NodePort, port 80, nodePort 는 30080, 셀렉터 app=shop.
  5. ConfigMap shop-config 를 만듭니다(키 APP_MODE, 값 production). Secret shop-secret 을 만듭니다(키 API_KEY, 값은 아무 문자열). 그리고 파드 shop-client 를 만들어 환경변수 APP_MODEshop-configAPP_MODE 키에서, 환경변수 API_KEYshop-secretAPI_KEY 키에서 가져오게 합니다. 이미지는 nginx:1.27-alpine 입니다.
  6. PVC shop-data 를 만듭니다 — 요청 용량 1Gi, accessModes ReadWriteOnce, storageClassName standard.
  7. shop-svc 의 정규화된 DNS 이름(FQDN)을 /root/kcna-net/dns.txt 에 한 줄로 저장하고, 같은 네임스페이스에 헤드리스 서비스 shop-headless 를 만듭니다 — 셀렉터 app=shop, port 80, clusterIP 는 헤드리스로 지정.

참고

백엔드 디플로이먼트 세우기

네임스페이스 kcna-net 을 만들고 그 안에 Deployment shop 을 만듭니다 — 이미지 nginx:1.27-alpine, replicas 2, 파드 템플릿 라벨 app=shop.

서비스가 찾아갈 대상이 먼저 있어야 합니다. 파드 템플릿에 붙는 라벨이 나중에 셀렉터와 맞아야 하니 어떤 라벨이 붙는지 확인해 두세요.

ClusterIP 서비스와 엔드포인트 확인

Service shop-svc 를 만듭니다 — 타입 ClusterIP, port 80, 셀렉터 app=shop. 엔드포인트가 2 건 잡히는지 확인합니다.

kubectl expose 로 만들 수도 있고 YAML 로 써도 됩니다. 만든 뒤 엔드포인트가 실제로 잡혔는지 반드시 확인하세요 — 서비스가 만들어졌다는 것과 트래픽이 갈 곳이 있다는 것은 다른 얘기입니다.

셀렉터 오타를 일부러 재현하기

Service broken-svc 를 같은 네임스페이스에 만듭니다 — port 80 이지만 셀렉터는 일부러 app=shopp(p 하나 더). 엔드포인트가 0 건인 것을 확인하고, 이 서비스를 고치는 올바른 셀렉터를 /root/kcna-net/diagnosis.txtapp=shop 형태로 한 줄 저장합니다.

이 단계는 실패를 만드는 것이 목표입니다. 셀렉터 값에 글자 하나를 더 넣은 서비스를 만들고, 오류가 나지 않는다는 것과 엔드포인트가 0 건이라는 것을 둘 다 확인하세요. 진단 파일에는 이 서비스를 고칠 올바른 셀렉터를 key=value 한 줄로 적습니다.

NodePort 로 밖에서 들어오는 문 만들기

Service shop-np 를 만듭니다 — 타입 NodePort, port 80, nodePort 는 30080, 셀렉터 app=shop.

NodePort 범위는 기본적으로 30000-32767 입니다. 번호를 지정하지 않으면 임의로 배정되니, 채점되는 번호를 쓰려면 매니페스트에 명시해야 합니다.

ConfigMap 과 Secret 주입하기

ConfigMap shop-config 를 만듭니다(키 APP_MODE, 값 production). Secret shop-secret 을 만듭니다(키 API_KEY, 값은 아무 문자열). 그리고 파드 shop-client 를 만들어 환경변수 APP_MODEshop-configAPP_MODE 키에서, 환경변수 API_KEYshop-secretAPI_KEY 키에서 가져오게 합니다. 이미지는 nginx:1.27-alpine 입니다.

kubectl create configmap 과 kubectl create secret generic 에 --from-literal 을 쓰면 빠릅니다. 파드 쪽은 env 항목마다 valueFrom 으로 configMapKeyRef / secretKeyRef 를 지정하는 형태입니다. 어떤 키를 어느 이름으로 노출할지 두 군데를 다 적어야 합니다.

PVC 로 저장소 요청서 쓰기

PVC shop-data 를 만듭니다 — 요청 용량 1Gi, accessModes ReadWriteOnce, storageClassName standard.

PVC 는 '요청서'입니다. 이 실습 클러스터에는 동적 프로비저너가 없어 Pending 에 머무를 수 있는데, 그것 자체가 정상이며 채점은 spec 을 봅니다. accessModes 는 배열이고 storageClassName 은 문자열입니다.

DNS 이름 규칙과 헤드리스 서비스

shop-svc 의 정규화된 DNS 이름(FQDN)을 /root/kcna-net/dns.txt 에 한 줄로 저장하고, 같은 네임스페이스에 헤드리스 서비스 shop-headless 를 만듭니다 — 셀렉터 app=shop, port 80, clusterIP 는 헤드리스로 지정.

서비스의 정규화된 DNS 이름은 네 조각으로 되어 있습니다. 그리고 헤드리스 서비스는 clusterIP 필드에 특정 값을 명시해 만듭니다 — 이 값은 kubectl expose 로는 지정하기 어려우니 YAML 을 쓰는 편이 낫습니다.