반응형
3장에서 다루는 내용
- 파드의 생성, 실행, 정지
- 파드와 다른 리소스를 레이블로 조직화하기
- 특정 레이블을 가진 모든 파드에서 작업 수행
- 네임스페이스를 사용해 파드를 겹치지 않는 그룹으로 나누기
- 특정한 형식을 가진 워커 노드에 파드 배치
3.1 파드 소개
- 파드는 함께 배치된 컨테이너 그룹이며 쿠버네티스의 기본 빌딩 블록이다.
- 컨테이너를 개별적으로 배포하기보다는 컨테이너를 가진 파드를 배포하고 운영한다.
- 파드는 단일 컨테이너일 수도 여러 개의 컨테이너일 수도 있다.
3.1.1 파드가 필요한 이유
- 로그를 쌓는 과정에서 A 컨테이너에서 X와 Y 프로세스를 실행한다고 가정했을 때, 모든 프로세스는 동일한 표준 출력으로 로그를 기록하기 때문에 어떤 프로세스가 남긴 로그인지 파악하는 것이 어렵다. 또한, 개별 프로세스가 실패하는 경우 자동으로 재시작하는 매커니즘을 포함해야 하는데 이러한 이유로 여러 프로세스를 실행하는 단일 컨테이너보다 다중 컨테이너가 낫다.
3.1.2 파드 이해하기
- 여러 프로세스를 단일 컨테이너로 묶지 않기 때문에 여러 컨테이너를 함께 묶고 하나의 단위로 관리할 수 있는 또 다른 상위 구조인 파드로 관리를 한다.
- 컨테이너 모음을 사용해 밀접하게 연관된 프로세스를 함께 실행하고 단일 컨테이너 안에서 모두 함께 실행되는 것처럼 동일한 환경을 제공할 수 있으면서도 이들을 격리된 상태로 유지할 수 있다. 이런 방식으로 두 개의 장점으로 모두 활용한다.
- 컨테이너를 완벽하게 격리하는 것 뿐만 아니라 컨테이너 그룹을 분리할수도 있다.
- 그룹 안에 있는 특정한 리소스를 공유하기 위해 각 컨테이너가 완벽하게 격리되지 않도록 한다.
- 쿠버네티스는 파드 안에 있는 모든 컨테이너가 자체 네임스페이스가 아닌 동일한 리눅스 네임스페이스를 공유하도록 도커를 설정한다.
- 파드의 모든 컨테이너는 동일한 네트워크 네임스페이스와 UTS 네임스페이스 안에서 실행되기 때문에, 모든 컨테이너는 같은 호스트 이름과 네트워크 인터페이스를 공유한다.
- 파드 안에 있는 컨테이너가 별도 PID 네임스페이스를 사용할 경우 해당 컨테이너 안에서 실행되는 프로세스만을 볼 수 있다.
- 그러나 파일시스템은 컨테이너 이미지에서 나오기 때문에, 다른 컨테이너와 완전히 분리된다.
- 여기서 강조할 한 가지는 파드 안의 컨테이너가 동일한 네트워크 네임스페이스에서 실행되기 때문에, 동일한 IP 주소와 포트 공간을 공유한다는 것이다. 포트 충돌을 주의해야 한다는 것
- 쿠버네티스 클러스터의 모든 파드는 하나의 플랫한 공유 네트워크 주소 공간에 상주한다. 두 파드가 서로 네트워크 패킷을 보내면, 상대방의 실제 IP 주소를 패킷 안에 있는 출발지 IP 주소에서 찾을 수 있다.
- 결과적으로 파드 사이에서 통신은 항상 단순하다. 두 파드가 동일 혹은 서로 다른 워커 노드에 있는지는 중요하지 않으며, 두 경우 모두 파드 안에 있는 컨테이너는 NAT 없는 플랫 네트워크를 통해 서로 통신하는 것이 가능하다.
- 이것은 LAN에 있는 컴퓨터 간의 통신과 비슷하다.
3.1.3 파드에서 컨테이너의 적절한 구성
- 파드는 특정한 애플리케이션만을 호스팅한다.
- 한 호스트에 모든 유형의 애플리케이션을 넣었던 이전과는 달리 파드는 그렇게 사용하지 않는다.
- 다계층 애플리케이션 즉, 프론트엔드 서버와 데이터베이스 컨테이너 두 개로 구성된 단일 파드를 실행하지 못할 것은 아니지만 적절하지는 않다.
- 프론트엔드와 백엔드가 같은 파드에 있다면, 둘은 항상 동일한 노드에서 실행된다. 만약 두 개의 노드로 구성된 클러스터에 이 하나의 파드만 있다면, 하나의 노드만 사용하고 나머지 노드의 컴퓨팅 리소스는 활용하지 못한다.
- 두 컨테이너를 하나의 파드에 넣지 말아야 하는 또 다른 이유는 스케일링 때문이다.
- 파드는 스케일링의 기본 단위이기 때문에 개별 컨테이너를 수평으로 확장할 수 있는 방법은 없다.
- 파드에서 여러 컨테이너를 사용하는 경우는 애플리케이션이 하나의 주요 프로세스와 하나 이상의 보완 프로세스로 구성된 경우 사용한다.
- 컨테이너를 파드로 묶어 그룹으로 만들 때 아래와 같은 질문을 할 필요가 있다.
- 컨테이너를 함께 실행해야 하는가, 혹은 서로 다른 호스트에서 실행할 수 있는가?
- 여러 컨테이너가 모여 하나의 구성 요소를 나타내는가, 혹은 개별적인 구성 요소인가?
- 컨테이너가 함께, 혹은 개별적으로 스케일링돼야 하는가?
3.2 YAML 또는 JSON 디스크립터로 파드 생성
- 파드를 포함한 쿠버네티스 리소스는 일반적으로 쿠버네티스 REST API 엔드포인트에 JSON 혹은 YAML 매니페스트를 전송해 생성한다.
- 기존 파드의 YAML 디스크립터는 -o yaml 옵션을 사용해서 확인 가능하다.
$ kubectl get po kubia-zxzij -o yaml
apiVersion: v1
kind: Pod
metadata:
annotations:
kubernetes.io/created-by: ...
creationTimestamp: 2016-03-18T12:37:50Z
generateName: kubia-
labels:
run: kubia
name: kubia-zxzij
namespace: default
resourceVersion: "294"
selfLink: /api/v1/namespaces/default/pods/kubia-zxzij
uid: 3a564dc0-ed06-11e5-ba3b-42010af00004
spec:
containers:
- image: luksa/kubia
imagePullPolicy: IfNotPresent
name: kubia
ports:
- containerPort: 8080
protocol: TCP
resources:
requests:
cpu: 100m
terminationMessagePath: /dev/termination-log
volumeMounts:
- mountPath: /var/run/secrets/k8s.io/servacc
name: default-token-kvcqa
readOnly: true
dnsPolicy: ClusterFirst
nodeName: gke-kubia-e8fe08b8-node-txje
restartPolicy: Always
serviceAccount: default
serviceAccountName: default
terminationGracePeriodSeconds: 30
volumes:
- name: default-token-kvcqa
secret:
secretName: default-token-kvcqa
status:
conditions:
- lastProbeTime: null
lastTransitionTime: null
status: "True"
type: Ready
containerStatuses:
- containerID: docker://f0276994322d247ba...
image: luksa/kubia
imageID: docker://4c325bcc6b40c110226b89fe...
lastState: {}
name: kubia
ready: true
restartCount: 0
state:
running:
startedAt: 2016-03-18T12:46:05Z
hostIP: 10.132.0.4
phase: Running
podIP: 10.0.2.3
startTime: 2016-03-18T12:44:32Z
- 파드 정의는 몇 부분으로 구성된다. 그 중 거의 모든 쿠버네티스 리소스가 갖고 있는 세 가지 중요한 부분이 있다.
- Metadata : 이름, 네임스페이스, 레이블 및 파드에 관한 기타 정보를 포함
- Spec : 파드 컨테이너, 볼륨, 기타 데이터 등 파드 자체에 관한 실제 명세를 가진다.
- Status : 파드 상태, 각 컨테이너 설명과 상태, 파드 내부 IP, 기타 기본 정보 등 현재 실행 중인 파드에 관한 현재 정보를 포함한다.
- 아래의 예제에서는 실행 중인 파드의 상태를 포함한 자세한 설명을 보여준다.
- status 부분에는 특정 시간의 리소스 상태를 보여주는 읽기 전용의 런타임 데이터가 포함돼 있다.
- 앞서 설명한 세 부분은 쿠버네티스 API 오브젝트의 일반적인 구조를 보여준다.
3.2.2 파드를 정의하는 간단한 YAML 정의 작성하기
apiVersion: v1 # 디스크립터는 api 버전 1을 사용한다.
kind: Pod # 오브젝트 종류가 pod이다.
metadata:
name: kubia-manual # 파드의 이름
spec:
containers:
- image: luksa/kubia # 컨테이너를 만드는 이미지
name: kubia # 컨테이너 이름
ports:
- containerPort: 8080 # 애플리케이션이 수신하는 포트
protocol: TCP
- 포트 지정 안에서 포트를 지정해둔 것은 단지 정보에 불과하다. 이를 생략해도 다른 클라이언트에서 포트를 통해 파드에 연결할 수 있는 여부에 영향을 미치지 않는다.
- 컨테이너가 0.0.0.0 주소에 열어 둔 포트를 통해 접속을 허용할 경우 파드 스펙에 포트를 명시적으로 나열하지 않아도 다른 파드에서 항상 해당 파드에 접속할 수 있다.
3.2.3 kubectl create 명령으로 파드 만들기
- YAML 파일을 이용해 파드를 만들려면, kubectl create 명령을 이용한다.
$ kubectl create -f kubia-manual.yaml
pod "kubia-manual" created
- 파드를 만든 뒤에 쿠버네티스에 파드의 전체 YAML을 요청할 수 있다. 요청한 결과를 보면 앞서 본 YAML과 비슷하다는 것을 알 수 있다.
- 다음 명령어를 사용해 파드의 전체 정의를 볼 수 있다.
$ kubectl get po kubia-manual -o yaml
$ kubectl get po kubia-manual -o json
3.2.4 애플리케이션 로그 보기
- 위에서 생성한 애플리케이션은 로그를 프로세스의 표준 출력에 기록한다.
- 컨테이너화된 애플리케이션은 로그를 파일에 쓰기보다는 표준 출력과 표준 에러에 로그를 남기는 게 일반적이다.
- 컨테이너 런타임은 이런 스트림을 파일로 전달하고, 다음 명령을 이용해 컨테이너 로그를 가져온다.
$ docker logs <container id>
- 파드 로그를 보기 위해서는 로컬 머신에서 다음 명령을 실행한다.
$ kubectl logs kubia-manual
Kubia server starting...
- 여러 컨테이너를 포함한 파드인 경우는 컨테이너 이름을 kubectl logs 명령에 -c <컨테이너 이름> 옵션과 함께 명시적으로 포함해야 한다.
- kubia-manual 파드에서는 컨테이너 이름을 kubia로 지정했다. 만약 다른 컨테이너가 존재한다면 로그를 가져오기 위해 다음과 같은 명령을 사용한다.
$ kubectl logs kubia-manual -c kubia
Kubia server starting...
- 현재 존재하는 파드의 컨테이너 로그만 가져올 수 있다는 점에 유의해야 한다. 파드가 삭제되면 해당 로그도 같이 삭제된다.
- 파드가 삭제된 후에도 파드의 로그를 보기 위해서는 모든 로그를 중앙 저장소에 저장하는 클러스터 전체의 중앙집중식 로깅을 설정해야 한다.
3.2.5 파드에 요청 보내기
- 어떻게 하면 실제 파드의 동작을 볼 수 있는가? 바로 포트 포워딩이다.
- 서비스를 거치지 않고 특정 파드와 대화하고 싶을 때 쿠버네티스는 해당 파드로 향하는 포트 포워딩을 구성해준다.
$ kubectl port-forward kubia-manual 8888:8080
... Forwarding from 127.0.0.1:8888 -> 8080
... Forwarding from [::1]:8888 -> 8080
- 이제 다른 터미널에서 curl을 이용해 localhost:8888에서 실행되고 있는 kubectl port forward 프록시를 통해 HTTP 요청을 해당 파드에 보낼 수 있다.
$ curl localhost:8888
You’ve hit kubia-manual
- 요청을 보낼 때 발생하는 상황을 간략하게 보여준다. 실제로는 몇 가지 추가적인 구성 요소가 kubectl 프로세스와 파드 사이에 있지만, 지금은 관련이 없다.
3.3 레이블을 이용한 파드 구성
- 실제 애플리케이션을 배포할 때 대부분의 사용자는 더 많은 파드를 실행한다. 파드 수가 증가함에 따라 파드를 부분 집합으로 분류할 필요가 있다.
- 모든 개발자와 시스템 관리자는 어떤 파드가 어떤 것인지 쉽게 알 수 있도록 임의의 기준에 따라 작은 그룹으로 조직하는 방법이 필요하다.
- 각 파드에 대해 개별적으로 작업을 수행하기보다 특정 그룹에 속한 모든 파드에 관해 한 번에 작업하기를 원할 것이다.
- 레이블을 통해 파드와 기타 다른 쿠버네티스 오브젝트의 조직화가 이뤄진다.
3.3.1 레이블 소개
- 레이블은 리소스에 첨부하는 키-값 쌍으로, 이 쌍은 레이블 셀렉터를 사용해 리소스를 선택할 때 활용된다.(리소스는 셀렉터에 지정된 레이블을 포함하는지 여부에 따라 필터링된다.)
- 레이블 키가 해당 리소스 내에서 고유하다면, 하나 이상 원하는 만큼 레이블을 가질 수 있다.
- 일반적으로 리소스를 생성할 때 레이블을 붙이지만, 나중에 레이블을 추가 하거나 기존 레이블 값을 수정할 수도 있다.
- 예제에서는 레이블을 두 개 붙였다.
- app : 파드가 속한 애플리케이션, 구성 요소 혹은 마이크로서비스를 지정한다.
- rel : 파드에서 실행 중인 애플리케이션이 stable, 베타 혹은 카나리 릴리스인지 보여준다.
- 클러스터에 접속할 수 있는 개발자와 운영자는 이제 파드 레이블을 보고 시스템 구조와 각 파드가 적합한 위치에 있는지 볼 수 있다.
3.3.2 파드를 생성할 때 레이블 지정
- 레이블 두 개를 가진 파드를 생성해 실제로 레이블이 어떻게 동작하는지 살펴보자.
apiVersion: v1
kind: Pod
metadata:
name: kubia-manual-v2
labels:
creation_method: manual
env: prod
spec:
containers:
- image: luksa/kubia
name: kubia
ports:
- containerPort: 8080
protocol: TCP
$ kubectl create -f kubia-manual-with-labels.yaml
pod "kubia-manual-v2" created
- kubectl get pods 명령은 레이블을 표시하지 않는 것이 기본값이라 --show-labels 스위치를 사용해 레이블을 볼 수 있다.
$ kubectl get po --show-labels
NAME READY STATUS RESTARTS AGE LABELS
kubia-manual 1/1 Running 0 16m <none>
kubia-manual-v2 1/1 Running 0 2m creat_method=manual,env=prod
kubia-zxzij 1/1 Running 0 1d run=kubia
- 모든 레이블을 나열하는 대신 특정 레이블을 보고자 한다면 -L 옵션을 이용해 각 레이블을 자체 열에 표시할 수 있다.
$ kubectl get po -L creation_method,env
NAME READY STATUS RESTARTS AGE CREATION_METHOD ENV
kubia-manual 1/1 Running 0 16m <none> <none>
kubia-manual-v2 1/1 Running 0 2m manual prod
kubia-zxzij 1/1 Running 0 1d <none> <none>
3.3.3 기존 파드 레이블 수정
- 기존 파드에 레이블을 추가하거나 수정할 수 있다. kubia-manual 파드에 레이블을 추가해보자
$ kubectl label po kubia-manual creation_method=manual
pod "kubia-manual" labeled
- v2 파드 기존에 있던 레이블은 변경해보자
- 변경시에는 overwrite 옵션을 사용하면 된다.
$ kubectl label po kubia-manual-v2 env=debug --overwrite
pod "kubia-manual-v2" labeled
$ kubectl get po -L creation_method,env
NAME READY STATUS RESTARTS AGE CREATION_METHOD ENV
kubia-manual 1/1 Running 0 16m manual <none>
kubia-manual-v2 1/1 Running 0 2m manual debug
kubia-zxzij 1/1 Running 0 1d <none> <none>
- 레이블을 붙이거나 수정한 결과를 볼 수 있다.
3.4 레이블 셀렉터를 이용한 파드 부분 집합 나열
- 레이블 셀렉터는 특정 값과 레이블을 갖는지 여부에 따라 리소스를 필터링하는 기준이 된다.
- 레이블 셀렉터는 리소스 중에서 다음 기준에 따라 리소스를 선택한다.
- 특정한 키를 포함하거나 포함하지 않는 레이블
- 특정한 키와 값을 가진 레이블
- 특정한 키를 갖고 있지만, 다른 값을 가진 레이블
3.4.1 레이블 셀렉터를 사용해 파드 나열
- 파드에 레이블 셀렉터 사용해보기
$ kubectl get po -l creation_method=manual # creation_method 키와 manual 값을 가지고 있는 레이블 출력
NAME READY STATUS RESTARTS AGE
kubia-manual 1/1 Running 0 51m
kubia-manual-v2 1/1 Running 0 37m
$ kubectl get po -l env # env 레이블을 갖고 있는 것을 출력
NAME READY STATUS RESTARTS AGE
kubia-manual-v2 1/1 Running 0 37m
$ kubectl get po -l '!env' # env 레이블을 갖고 있지 않은 것을 출력
NAME READY STATUS RESTARTS AGE
kubia-manual 1/1 Running 0 51m
kubia-zxzij 1/1 Running 0 10d
- 다음 레이블 셀렉터를 이용해 일치하는 파드를 찾을 수 있다.
- creation_method!=manual : creation_method 레이블을 가지고 있는 파드 중에 값이 manual이 아닌 것
- env in (prod,devel) : env 레이블 값이 prod 또는 devel로 설정돼 있는 파드
- env notin (prod,devel) : env 레이블 값이 prod, devel이 아닌 파드
3.4.2 레이블 셀렉터에서 여러 조건 사용
- 셀렉터는 쉼표로 구분된 여러 기준을 포함하는 것도 가능하다.
- 예를 들어 app=pc,rel=beta 이런 식으로
- 레이블 셀렉터는 파드 목록을 나열하는 것뿐만 아니라, 파드 부분 집합에 작업을 수행 할 때도 유용하다.
- 레이블 셀렉터는 kubectl에서만 사용하는 것이 아니고 내부적으로도 사용된다.
3.5 레이블과 셀렉터를 이용해 파드 스케줄링 제한
- 쿠버네티스는 모든 노드를 하나의 대규모 배포 플랫폼으로 노출하기 때문에, 파드가 어느 노드에 스케줄링됐는지는 중요하지 않다.
- 각 파드는 요청한 만큼의 정확한 컴퓨팅 리소스를 할당받고 다른 파드에서 해당 파드로 접근하는 것은 파드가 스케줄링된 노드에 아무런 영향을 받지 않는다.
- 하지만 파드를 스케줄링할 위치를 결정할 때 약간이라도 영향을 미치고 싶은 상황이 있다.
- 예를 들어 하드웨어 인프라가 동일하지 않은 경우를 들 수 있다.
- 워커 노드 일부는 HDD를 가지고 있고 나머지에는 SSD를 가지고 있는 경우, 특정 파드를 한 그룹에 나머지 파드는 다른 그룹에 스케줄링되도록 할 수 있다.
- GPU 가속을 제공하는 노드에만 GPU 계산이 필요한 파드를 스케줄링하는 것도 예가 된다.
- 쿠버네티스의 전체적인 아이디어는 그 위에 실행되는 애플리케이션으로부터 실제 인프라를 숨기는 것에어떤 노드에 스케줄링돼야 하는지 구체적으로 지정하지않고 필요한 노드 요구 사항을 기술하고 쿠버네티스가 요구 사항을 만족하는 노드를 선택하도록 한다.
3.5.1 워커 노드 분류에 레이블 사용
- 앞서 배운 것처럼 노드를 포함한 모든 쿠버네티스 오브젝트에 레이블을 부착할 수 있다.
- 일반적으로 ops 팀은 새 노드를 클러스터에 추가할 때, 노드가 제공하는 하드웨어나 파드를 스케줄링할 때 유용하게 사용할 수 있는 기타 사항을 레이블로 지정해 노드를 분류한다.
$ kubectl label node gke-kubia-85f6-node-0rrx gpu=true
node "gke-kubia-85f6-node-0rrx" labeled
$ kubectl get nodes -l gpu=true
NAME STATUS AGE
gke-kubia-85f6-node-0rrx Ready 1d
3.5.2 특정 노드에 파드 스케줄링
- 위에서 생성한 gpu 레이블을 기반으로 노드 셀렉터를 추가하는 방법이다.
apiVersion: v1
kind: Pod
metadata:
name: kubia-gpu
spec:
nodeSelector: # nodeSelector 를 추가해서 gpu=true 인 노드에만 pod를 생성한다.
gpu: "true"
containers:
- image: luksa/kubia
name: kubia
3.5.3 하나의 특정 노드로 스케줄링
- 마찬가지로 각 노드에는 키를 kubernetes.io/hostname으로 하고 값에는 호스트 이름이 설정돼 있는 고유한 레이블이 있기 때문에, 파드를 특정한 노드로 스케줄링하는 것도 가능하다.
- 그러나 nodeSelector에 실제 호스트 이름을 지정할 경우 해당 노드가 오프라인 상태인 경우 파드가 스케줄링되지 않을 수 있다.
3.6 파드에 어노테이션 달기
- 파드 및 다른 오브젝트는 레이블 외에 어노테이션을 가질 수 있다. 어노테이션은 키-값 쌍으로 레이블과 거의 비슷하지만 식별 정보를 갖지 않는다.
- 반면 어노테이션은 훨씬 더 많은 정보를 보유할 수 있다. 이는 주로 tools에서 사용된다. 특정 어노테이션은 쿠버네티스에 의해 자동으로 오브젝트에 추가되지만, 나머지 어노테이션은 사용자에 의해 수동으로 추가된다.
- 어노테이션은 쿠버네티스에 새로운 기능을 추가할 때 흔히 사용된다. 일반적으로 새 기능의 알파 혹은 베타 버전은 API 오브젝트에 새로운 필드를 바로 도입하지 않는다. 필드 대신 어노테이션을 사용하고, 필요한 API 변경이 명확해지고 쿠버네티스 개발자가 이에 동의하면 새로운 필드가 도입된다. 그리고 관련된 어노테이션은 사용이 중단된다.
- 어노테이션이 유용하게 사용되는 경우는 파드나 다른 API 오브젝트에 설명을 추가해두는 것이다. 예를 들어 오브젝트를 만든 사람 이름을 어노테이션으로 지정해두면, 클러스터에서 작업하는 사람들이 좀 거 쉽게 협업할 수 있다.
3.6.1 오브젝트의 어노테이션 조회
$ kubectl get po kubia-zxzij -o yaml
apiVersion: v1
kind: Pod
metadata:
annotations:
kubernetes.io/created-by: |
{"kind":"SerializedReference", "apiVersion":"v1",
"reference":{"kind":"ReplicationController", "namespace":"default", ...
- kubernetes.io/created-by 어노테이션이 오브젝트를 사용할 때 사용한 JSON 데이터를 갖고 있는 것을 볼 수 있다.
- 레이블에는 짧은 데이터를, 그에 비해 어노테이션에는 상대적으로 큰 데이터를 넣을 수 있다.
3.6.2 어노테이션 추가 및 수정
- annotate 명령어를 사용해서 이미 존재하는 파드에 어노테이션을 추가하거나 수정하는 것도 가능하다.
$ kubectl annotate pod kubia-manual mycompany.com/someannotation="foo bar"
pod "kubia-manual" annotated
3.7 네임스페이스를 사용한 리소스 그룹화
- 오브젝트는 여러 레이블을 가질 수 있기 때문에 오브젝트 그룹은 서로 겹쳐질 수 있다. 오브젝트를 겹치지 않는 그룹으로 분할하고자 할 때는 어떻게 해야하는 가?
- 쿠버네티스는 오브젝트를 네임스페이스로 그룹화한다.
- 여기서 사용하는 네임스페이스는 프로세스를 격리하기 위해 사용하는 네임스페이스가 아니다.
- 쿠버네티스 네임스페이스는 오브젝트 이름의 범위를 제공한다. 모든 리소스를 하나의 단일 네임스페이스에 두는 대신에 여러 네임스페이스로 분할할 수 있으며, 이렇게 분리된 네임스페이스는 같은 리소스 이름을 다른 네임스페이스에 걸쳐 여러 번 사용할 수 있게 해준다.
3.7.1 네임스페이스의 필요성
- 여러 네임스페이스를 사용하면 많은 구성 요소를 가진 복잡한 시스템을 좀 더 작은 개별 그룹으로 분리할 수 있다.
- 또한 멀티테넌트 환경처럼 리소스를 분리하는 데 사용된다. 리소스를 프로덕션, 개발, QA 환경 혹은 원하는 다른 방법으로 나누어 사용할 수 있다. 리소스의 이름은 네임스페이스 안에서만 고유하면 된다.
- 노드 리소스는 네임스페이스 안에 속하지 않는데 이 리소스는 전역이며 단일 네임스페이스에 얽매이지 않는다.
3.7.2 다른 네임스페이스와 파드 살펴보기
$ kubectl get ns
NAME LABELS STATUS AGE
default <none> Active 1h
kube-public <none> Active 1h
kube-system <none> Active 1h
$ kubectl get po --namespace kube-system
NAME READY STATUS RESTARTS AGE
fluentd-cloud-kubia-e8fe-node-txje 1/1 Running 0 1h
heapster-v11-fz1ge 1/1 Running 0 1h
kube-dns-v9-p8a4t 0/4 Pending 0 1h
kube-ui-v4-kdlai 1/1 Running 0 1h
l7-lb-controller-v0.5.2-bue96 2/2 Running 92 1h
- kube-system 네임스페이스는 쿠버네티스 시스템 자체와 관련이 되어있다.
- 이런 분리된 네임스페이스에 리소스를 포함시켜 모든 것이 깔끔하게 정돈되도록 유지한다.
- 정돈되지 않고 default 네임스페이스에 있다면 구분하기 어렵고 실수로 시스템 리소스를 삭제할 수도 있다.
- 네임스페이스는 리소스를 격리하는 것 외에도 특정 사용자가 지정된 리소스에 접근할 수 있도록 허용하고, 개별 사용자가 사용할 수 있는 컴퓨팅 리소스를 제한하는 데에도 사용된다.
3.7.3 네임스페이스 생성
- 네임스페이스는 YAML 파일을 쿠버네티스 API 서버에 요청해 생성할 수 있다.
apiVersion: v1
kind: Namespace
metadata:
name: custom-namespace
$ kubectl create -f custom-namespace.yaml
namespace "custom-namespace" created
- kubectl create namespace 명령을 사용해서 네임스페이스 생성이 가능하다.
$ kubectl create namespace custom-namespace
namespace "custom-namespace" created
3.7.4 다른 네임스페이스의 오브젝트 관리
- 생성한 네임스페이스 안에 리소스를 만들기 위해서는 metadata 섹션에 namespace: custom-namespace 항목을 넣거나 kubectl create 명령을 사용할 때 네임스페이스를 지정한다.
$ kubectl create -f kubia-manual.yaml -n custom-namespace
pod "kubia-manual" created
- 다른 네임스페이스 안에 있는 오브젝트를 나열하거나 어노테이션 달기, 수정 또는 삭제를할 때는 --namespace 또는 -n 플래그를 지정해줘야 한다.
3.7.4 다른 네임스페이스의 오브젝트 관리
- 네임스페이스는 오브젝트를 별도 그룹으로 분리해 특정한 네임스페이스 안에 속한 리소스를 대상으로 작업할 수 있게 해주지만, 실행 중인 오브젝트에 대한 격리는 제공하지 않는다.
- 예를 들어 서로 다른 네임스페이스에 파드를 배포할 때 해당 파드가 서로 격리돼 통신할 수 없다고 생각할 수 있지만, 반드시 그런 것은 아니다.
- 네임스페이스에서 네트워크 격리를 제공하는지는 쿠버네티스와 함게 배포하는 네트워킹 솔루션에 따라 다르다.
3.8 파드 중지와 제거
3.8.1 이름으로 파드 삭제
$ kubectl delete po kubia-gpu
pod "kubia-gpu" deleted
- 파드를 삭제하면 쿠버네티스는 파드 안에 있는 모든 컨테이너를 종료하도록 지시한다.
- 쿠버네티스는 SIGTERM 신호를 프로세스에 보내고 지정된 시간(기본 30초) 동안 기다린다.
- 시간 내에 종료되지 않으면 SIGKILL 신호를 통해 종료한다. 프로세스가 항상 정상적으로 종료되게 하기 위해서는 SIGTERM 신호를 올바르게 처리해야 한다.
- 여러 파드 이름을 공백으로 구분하면 두 개 이상의 파드를 삭제할 수 있다.
- 예를 들어 kubectl delete po pod1 pod2
3.8.2 레이블 셀렉터를 이용한 파드 삭제
$ kubectl delete po -l creation_method=manual
pod "kubia-manual" deleted
pod "kubia-manual-v2" deleted
$ kubectl delete po -l rel=canary
3.8.3 네임스페이스를 삭제한 파드 제거
$ kubectl delete ns custom-namespace
namespace "custom-namespace" deleted
3.8.4 네임스페이스를 유지하면서 네임스페이스 안에 있는 모든 파드 삭제
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
kubia-zxzij 1/1 Running 0 1d
$ kubectl delete po --all
pod "kubia-zxzij" deleted
- all 옵션을 사용하면 쿠버네티스가 현재 네임스페이스에 있는 모든 파드를 삭제하도록 한다.
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
kubia-09as0 1/1 Running 0 1d
kubia-zxzij 1/1 Terminating 0 1d
- kubia-09as0 파드는 앞서 만든 레플리케이션컨트롤러에 의해서 재생성 된 파드이다.
3.8.5 네임스페이스에서 (거의) 모든 리소스 삭제
$ kubectl delete all --all
pod "kubia-09as0" deleted
replicationcontroller "kubia" deleted
service "kubernetes" deleted
service "kubia-http" deleted
- all 옵션을 사용해도 시크릿 등 특정 리소스는 보존돼 있으며, 명시적으로 삭제할 필요가 있다.
느낀 점
레이블, 레이블 셀렉터, 네임스페이스에 대해서 이해를 많이 한 것 같다. 그 외에도 여러 명령어가 있는데 써보면서 익히는 게 가장 좋기 때문에 차차 익혀보도록 해야겠다.
정리
파드
- 파드란 컨테이너 여러개를 한 그룹으로 묶은 쿠버네티스의 최소 단위
- 컨테이너를 개별, 단일로 배포하기보다 기능적으로 한 가지의 역할을 하는 다중 컨테이너 파드로 구성하는 게 효율적이고 좋다.
- 왜? 로그를 쌓는 과정에서 한 서버에 여러 프로세스가 있으면 어떤 프로세스가 남긴 로그인 지 파악하는 것이 어렵고, 개별 프로세스가 실패하는 경우 개별적으로 재시작 해야하는 데 실패한 프로세스만 재시작하기 어렵기 때문에.
- 파드의 모든 컨테이너는 동일한 네임스페이스와 UTS 네임스페이스 안에서 실행되기 때문에, 모든 컨테이너는 같은 호스트 이름과 네트워크 인터페이스를 공유한다.
- 그래서 동일 파드안에 있는 컨테이너는 포트 충돌을 주의해야 한다.
- 파드 사이에서 통신은 단순히 대상 파드의 IP만을 통해서 통신이 가능하다. LAN과 동일한 구조라고 생각하면 됨
- 컨테이너를 파드로 묶어 그룹으로 만들 때 해야 할 질문
- 컨테이너를 함께 실행해야 하는가, 혹은 서로 다른 호스트에서 실행할 수 있는가?
- 여러 컨테이너가 모여 하나의 구성 요소를 나타내는가, 혹은 개별적인 구성요소인가?
- 컨테이너가 함께, 혹은 개별적으로 스케일링돼야 하는가?
- 파드 정의는 세가지 중요한 부분이 있음
- Metadata : 이름, 네임스페이스, 레이블 및 파드에 관한 기타 정보를 포함
- Spec : 파드 컨테이너, 볼륨, 기타 데이터 등 파드 자체에 관한 실제 명세
- Status : 파드 상태, 각 컨테이너 설명과 상태, 파드 내부 IP, 기타 기본 정보 등
- 실제 파드의 동작을 보고 싶다? 서비스를 거치지 않고 특정 파드와 대화를 할 수 있는 방법이 있다. 포트 포워딩을 구성해주면 된다.
kubectl port-forward kubia-manual 8888:8000
... Forwarding from 127.0.0.1:8888 -> 8080
- 파드 명령어
- 파드 생성 :
kubectl create -f \<yaml 파일 이름>
- 파드의 전체 yaml 확인 :
kubectl get po \<pod 네임> -o yaml # json 도 가능
- 파드 로그 확인 :
kubectl logs \<pod 네임>
- 컨테이너 로그 확인 :
kubectl logs \<pod 네임> -c \<컨테이너 이름>
- 파드 제거
$ kubectl delete po kubia-gpu
파드를 삭제하면 쿠버네티스는 SIGTERM 신호를 프로세스에 보내고 지정된 시간(기본 30초) 동안 기다리고, 시간 내에 종료되지 않는다면 SIGKILL 신호를 통해 종료한다.$ kubectl delete po pod1 pod2
이렇게 여러 파드를 삭제할 수도 있다.
- 파드 생성 :
레이블
- 레이블을 이용해서 파드를 특정 그룹에 속하게 할 수 있다. 레이블은 키-값 쌍으로 이 쌍은 레이블 셀렉터를 이용해서 리소스를 선택할 때 활용한다.
- 레이블은 아래와 같이 metadata에 들어간다.
metadata:
name: kubia-manual-v2
labels:
creation_method: manual
env: prod
- 모든 레이블을 나여하는 대신 특정 레이블을 보고자 한다면 -L 옵션을 이용해 각 레이블을 자체 열에 표시할 수 있다.
- 레이블 명령어
- 기존 파드에 레이블 추가
$ kubectl label po kubia-manual creation_method=manual
- 존재하는 레이블 변경
$ kubectl label po kubia-manual-v2 env=debug --overwrite
- 특정 레이블 기반 출력
$ kubectl get po -l env # env 레이블을 갖고 있는 것을 출력
- 특정 레이블 기반의 여집합 출력
$ kubectl get po -l '!env' # env 레이블을 갖고 있지 않은 것을 출력
- 레이블 자체 열 표시
$ kubectl get po -L creation_method,env
NAME READY STATUS RESTARTS AGE CREATION_METHOD ENV
- 레이블 셀렉터를 이용한 파드 삭제
$ kubectl delete po -l creation_method=manual
- 기존 파드에 레이블 추가
- 다음 레이블 셀렉터를 이용해 일치하는 파드를 찾을 수 있다.
- creation_method!=manual : creation_method 레이블을 가지고 있는 파드 중에 값이 manual이 아닌 것
- env in (prod,devel) : env 레이블 값이 prod 또는 devel로 설정돼 있는 파드
- env notin (prod,devel) : env 레이블 값이 prod, devel이 아닌 파드
- 레이블을 이용해서 파드를 스케줄링할 때 특정 노드 그룹에 스케줄링되도록 할 수 있다.
$ kubectl label node gke-kubia-85f6-node-0rrx gpu=true
spec:
nodeSelector: # nodeSelector 를 추가해서 gpu=true 인 노드에만 pod를 생성한다.
gpu: "true"
- 각 노드에는 키를 kubernetes.io/hostname으로 하고 값에는 호스트 이름으로 되어 있는 레이블이 있어서 특정한 노드로 스케줄링하는 것도 가능하다. 그러나 nodeSelector에 실제 호스트 이름을 지정할 경우 해당 노드가 오프라인일 때 파드가 스케줄링되지 않을 수 있다.
어노테이션
- 파드 및 다른 오브젝트는 어노테이션을 가질 수 있다. 어노테이션은 키-값 쌍으로 주로 오브젝트에 대한 설명을 추가해두는 용도로 사용한다.
- 명령어
- 어노테이션 추가
$ kubectl annotate pod kubia-manual mycompany.com/someannotation="foo bar"
- 어노테이션 추가
네임스페이스
- 쿠버네티스는 오브젝트를 네임스페이스로 그룹화한다. 여러 네임스페이스를 사용하면 많은 구성 요소를 가진 복잡한 시스템을 좀 더 작은 개별 그룹으로 분리할 수 있다.
- 네임스페이스는 리소스를 격리하는 것 외에도 특정 사용자가 지정된 리소스에 접근할 수 있도록 허용하고, 개별 사용자가 사용할 수 있는 컴퓨팅 리소스를 제한하는 데에도 사용된다.
- 네임스페이스는
- 명령어
- 네임 스페이스 확인
$ kubectl get ns
- 특정 네임스페이스의 파드 확인
$ kubectl get po --namespace kube-system
- 네임스페이스 생성(YAML 파일 이용)
$ kubectl create -f custom-namespace.yaml
- 네임스페이스 생성(그냥 생성)
$ kubectl create namespace custom-namespace
- 네임스페이스 안에 오브젝트 넣기
$ kubectl create -f kubia-manual.yaml -n custom-namespace
- metadata 섹션에 namespace: 를 기입 해주거나 -n 옵션을 이용해서 네임스페이스를 지정해준다.
- 네임스페이스 삭제
$ kubectl delete ns custom-namespace
- 네임스페이스 기반으로 네임스페이스 안의 파드 삭제
$ kubectl delete po --all # 현재 네임스페이스의 파드 모두 삭제
$ kubectl delete po --all -n # n 옵션을 통해서 네임스페이스 지정 가능
- all 옵션을 사용해도 시크릿 등 특정 리소스는 보존돼 있다. 명시적으로 삭제할 필요가 있다.
- 네임 스페이스 확인
참고 자료
쿠버네티스 인 액션
반응형
'책, 강의' 카테고리의 다른 글
[쿠버네티스 인 액션] 5장 - 서비스: 클라이언트가 파드를 검색하고 통신을 가능하게 함 (1) | 2023.11.21 |
---|---|
[쿠버네티스 인 액션] 4장 - 레플리케이션과 그 밖의 컨트롤러: 관리되는 파드 배포 (1) | 2023.11.02 |
[쿠버네티스 인 액션] 2장 - 도커와 쿠버네티스 첫걸음 (1) | 2023.10.29 |
[쿠버네티스 인 액션] 1장 - 쿠버네티스 소개 (1) | 2023.10.29 |