# pod-definition.yamlapiVersion: v1 # 오브젝트 생성을 위해 사용하는 Kubernetes API 버전kind: Pod # 생성할 오브젝트의 종류metadata: # 오브젝트를 설명하는 메타데이터 (dict) name: myapp-pod labels: app: myapp type: front-endspec: # 생성할 오브젝트의 구체적인 정의 containers: - name: nginx-container image: nginx
Pod 는 하나 이상의 Container 를 실행하기 위한 쿠버네티스의 최소 단위이다.
전체 클러스터에서 고유한 IP 를 할당받는다.
일반적으로 Pod 는 애플리케이션을 실행하는 Container 와 1:1 관계를 갖는다.
하나의 Pod 는 동일한 종류의 Container 를 복제하기보다는 헬퍼(보조) Container 를 함께 두는 경우가 많다.
Pod 내 Container 간 host 폴더, localhost 네트워크를 공유한다. 즉, Container 간 localhost 통신이 가능하다.
Pod 생성
kubectl create -f pod-definition.yaml
YAML 파일로 부터 Pod 를 생성하거나,
kubectl run nginx \ --image=nginx \ # 쿠버네티스에 구성된 레지스트리(공개 Docker Hub 또는 private registries 등)에서 이미지를 가져옴 --dry-run=client -o yaml > redis.yaml # 생성 대신 YAML 파일로 저장
파드는 하나 이상의 컨테이너(프로세스 집합)를 묶은 논리적 단위일 뿐, 실제로는 같은 namespace/network/storage 를 공유하는 리눅스 프로세스들의 집합이다
즉, 쿠버네티스에서 컨테이너/파드를 생성하면 결국 리눅스 커널이 namespace 와 cgroup 을 활용해 프로세스를 격리하고 관리하는 것에 불과하다
Static Pod
Static Pod 은 kube-apiserver 나 kube-scheduler 가 아닌 kubelet 이 생성하고 관리하는 Pod 다. kubelet 은 Node 의 /etc/kubernetes/manifests 디렉터리에 정의된 YAML 파일을 주기적으로 확인하고 해당 Node 에서 실행되도록 보장한다. kubeadm 이 Master Node 를 구성할 때 Static Pod 형식으로 controller-manager, kube-apiserver, etcd 등을 생성한다. 때문에 kubectl get pods -n kube-system 으로 Pod 를 조회했을 때 Master Node 의 컴포넌트들이 Pod 로 실행되고 있는 것을 확인할 수 있는 것이다.
Namespace
Namespace 란
# namespace-dev.ymlapiVersion: v1kind: Namespacemetadata: name: dev
쿠버네티스를 구축하면 기본적으로 default, kube-system 등의 namespace 가 자동으로 생성된다. 사용자가 생성한 리소스는 기본적으로 defaultnamespace 에 속하게 된다.
kubectl get pods --namespace=kube-system
kube-system 의 경우, coredns, etcd-master, kube-apiserver-master, kube-controller-manager-master 등 쿠버네티스 기본 Component 들을 확인할 수 있다.
Namespace 생성
kubectl create -f namespace-dev.yml # YAML 파일로 생성하거나,kubectl create namespace dev # 명령어로 생성
kubectl create -f deployment-definition.ymlkubectl get deployments
위와 같이 nginx:1.7.1 을 호스팅하는 Deployment Object 가 있다고 해보자.
kubectl apply -f deployment-definiton.ymlkubectl set image deployment/myapp-deployment nginx=nginx:1.9.1
만약 버전을 1.9.1 로 업그레이드하고 싶을 경우 yaml 파일을 수정한 뒤 apply 하거나 set 명령어를 통해 전체 Container 의 버전을 업그레이드 할 수 있다.
K8s 는 기본적으로 Container 를 하나씩 업그레이드하는 Rolling Update 를 배포전략으로 사용하고, 전체 Container 를 내리고 다시 띄우는 Recreate 전략도 사용할 수 있다.
kubectl get replicasets
K8s 에서 Container 버전을 업그레이드할 때 Deployment Object 내부적으로 새로운 ReplicaSet 을 생성하여 새로운 버전의 Container 들을 하나씩 배포하기 때문에 위 명령어를 쳐보면 2개의 ReplicaSet 이 존재하는 것을 확인할 수 있다.
kubectl rollout status deployment my-deploymentkubectl rollout history deployment my-deploymentkubectl rollout history deployment my-deployment --revision=3kubectl rollout undo deployment my-deploymentkubectl rollout undo deployment my-deployment --to-revision=3 # 특정 버전으로 롤백
DaemonSet 은 모든 Node 에 1개의 Pod 를 배치하고 싶을 때 사용할 수 있는 Object 이다. 예를 들어 Datadog-Agent 와 같은 모니터링 에이전트 Pod 를 DaemonSet 을 통해 각 노드에 1개씩 배치할 수 있다. kube-proxy 역시 DaemonSet 으로 배포되어 있는 컴포넌트다.
K8s 는 DaemonSet 을 모든 Node 에 배포하기 위해 NodeAffinity 와 Default Scheduler 를 사용한다.
kubectl create -f daemon-set-definition.yamlkubectl get daemonsetskubectl describe daemonsets monitoring-daemon
위와 같은 커맨드로 DaemonSet 을 생성하고 조회할 수 있다.
Use Cases
Logging 을 위해 각 노드에 fluentd, logstash 등을 DaemonSet 으로 배포
Monitoring 을 위해 각 노드에 prometheus, datadog 등을 DaemonSet 으로 배포
Networking 을 위해 각 노드에 cilium, weave 등을 DaemonSet 으로 배포
보통 Docker 이미지 안에는 컨테이너가 시작되면 자동으로 실행될 명령어가 ENTRYPOINT 와 CMD 로 Dockerfile 안에 미리 정해져 있다. 쿠버네티스에서는 Dockerfile 을 다시 만들 필요 없이, Pod 의 command, args 설정으로 실행 방식을 덮어쓸 수 있다.
ConfigMap 과 Secret 을 볼륨으로 마운트하면 해당 데이터가 Pod 의 특정 디렉터리에 파일 형태로 저장된다. 이는 k8s 내부적으로 tmpfs(메모리 기반 파일시스템)을 사용하여 데이터를 동적으로 마운팅하는 방식이다. 환경변수의 경우 프로세스 환경변수에 직접 사용된다. 파일로 환경변수를 관리하면 여러 이점이 존재한다.
보안 강화
kubectl exec -it pod-name -- env | grep SECRET_
환경변수를 사용할 경우 Pod 내부에서 값을 쉽게 확인할 수 있다.
cat /proc/$(pgrep -f app)/environ
또 프로세스 내부에 환경변수가 남아있어 쉽게 확인할 수 있다.
Secret 을 볼륨으로 마운트하면 단순 파일로 제공되기 때문에 접근 권한을 저정하여 보안을 강화할 수 있다.
실시간 변경 반영
k8s 는 synlink 방식을 사용하여 파일을 자동으로 교체하기 때문에 값이 변경되어도 컨테이너를 재시작하지 않고도 적용된다.
일관된 관리
여러 Pod 에서 동일한 ConfigMap 또는 Secret 을 공유할 수 있다. 애플리케이션을 중앙 집중식으로 관리할 수 있어 운영이 편리해진다.
용량 제한
환경변수 방식은 시스템에 따라 길이 제한이 있으나 볼륨은 제한이 없다. TLS 인증서, SSH 키 등 길이가 긴 값들을 환경변수로 사용할 수 없을 때 유용하다.
Pod 는 보통 1개의 Container 를 포함하지만 여러개의 Container 를 포함할 수 있도록 설계되었다. 이는 Log Agent 와 같은 Helper Container 를 함께 생명주기에 포함하여 관리하기 위함이다. 위처럼 2개의 Container 를 포함하여 Pod 를 배포할 수 있다.
Multi-Container Pods Design Patterns
다수의 Container 를 포함한 Pod 를 배포할 때 따르는 디자인 패턴이다. 위 Log Agent 는 Sidecar Pattern 의 예시다.