View

지난 글에서 Container에 대한 내용과 kubernetes에 대한 기본적인 기능들에 대해서 소개했었다. 오늘은 Kubernetes에 대해서 더 자세히 알아보려고 한다. GCP 자료이다보니 내용에 GKE(Google Kubernetes Engine)에 대한 내용이 혼재되어 있다. 따라서 이를 최대한 정리하여 구분하려 한다. 그래야 OSS로 제공되는 K8s의 기능과 GKE로 향상된 기능을 명확하게 알 수 있기 때문이다. 

 

 


* Kubernetes Objects

> 공식적으로, Kubernetes Object는 persistent entity로써 현재 수행되고 있는 클러스터의 상태를 나타낸다. 상태 값은 그 클러스터가 가져야 하는 desired state와 현재의 상태를 나타내는 current state가 존재한다. 다양한 종류의 K8s object들이 containerized app과 그것들이 사용할 수 있는 resource를 나타내며 정책policies들에 의해 K8s Object의 동작이 영향을 받는다. K8s Object는 두 가지 중요한 요소를 갖는다. 

- Object spec : 각 오브젝트를 생성하기 위해서 desired state를 정의.
- Object status : K8s control plane으로부터 제공된 쿠버 오브젝트의 현재 상태를 나타낸다. (쿠버 클러스터의 동작을 참조하기 위해서 K8s control plane을 활용한다.)  


* Kubernetes - Pods

> Kubernetes는 여러 종류의 Object 타입(kind)를 가지고 있으며 가장 기본이 되는 object가 Pods이다.

> Pods 
- 기본적인 K8s의 build 단위 모듈이자, 배포될 수 있는 쿠버 오브젝트의 가장 작은 단위이다. 
- container가 K8s object의 가장 단위라고 생각하기 쉬우나 모든 container는 Pods 안에서 동작한다. 
- Pod는 container가 수행될 수 있도록 환경의 정보를 가지고 있으며, 하나 이상의 Container에 적용될 수 있다. 
- 하나의 Pod안에 만약 두 개 이상의 container들이 있다면, 그 container들은 서로 강하게 연계되어 storage/ network 같은 resource들을 공유하게 된다. 
- K8s에서는 Pod 단위로 IP 주소를 할당한다. 모든 container는 Pod의 N/W namespace를 공유하는데 그것에는 IP 주소 및 network port가 포함되어 있다. 
- 같은 Pod안에서 container들은 서로 통신할 수 있는데 localhost(127.0.0.1)을 활용한다. 
- Pod는 또한 storage 볼륨의 집합을 명시하여 container끼리 공유하도록 할 수도 있다. (별도의 방법을 통해서 storage를 여러 Pod에서도 공유가 가능하다) 


* Example - Running 3 nginx container 

> 만약 nginx 웹 서버 인스턴스를 K8s로 운영하고 싶은 경우, nginx container들을 갖는 Pods를 정의해야 한다. Pods 는 자체적으로 reovery가 되지 않기 때문에, 단순히 nginx 웹 서버가 존재하는 것이 아니라, 서로 통신하며 동작하기를 원하는 경우에는 Pod가 아닌 다른 K8s Object를 사용해야 한다. (해당 내용은 조금 뒤에 나온다)

 

> K8s의 desired state가 3개의 nginx Pod를 계속 수행하는 것이라고 가정해보자. 
> K8s에게 하나 이상의 objects를 생성하면서 이러한 작업을  요청한다면, 3개의 nginx container는 이제 시작했기 때문에 current state는 desired state와 다른 형태일 것이다.
> K8s의 control plane은 current state가 desired state와 맞지 않음으로 계속해서 치료하려고 할 것이다.
> K8s의 control plane은 계속적으로 이러한 클러스터의 상태를 모니터링 할것이고 끝없이 그것의 선언시 요구한 상태와 현재 상태를 비교하여 필요하다면 복구할 것이다. 


* Kubernetes cluster Architecture 

> 당연한 이야기지만, K8s 클러스터를 구성하기 위해서는 컴퓨터(서버)가 필요하다. 요즘은 VM으로 클러스터를 구성하는게 일반적인데, GKE 또한 VM을 통해서 클러스터를 구성한다.   

> GKE 클러스터는 master와 nodes들로 구성된다. Nodes의 역할은 Pods를 수행시키는 것이고 Master의 역할은 전체 클러스터를 관리하는 것이다. 이러한 작업을 위해서는 control plane component가 존재해야 한다. 

>K8s 클러스터의 주요 컴포넌트들은 master위에 있다. 

kube-apiserver직접적으로 client가 kubectl명령을 통해서 커뮤니케이션 하는 컴포넌트.클러스터 상태 확인/변경 등의 명령어를 받고, Pods를 시작한다.  kubectl 명령어를 통해서 많은 작업들이 이루어지는데 K8s API를 사용해서, 그때마다 kube-apiserver와 통신하게 된다. kube-apiserver는 또한 요청받는 권한을 확인하여, 그것이 유효한 요청인지 확인하고 관리자 제어를 한다. 내부적인 요청이나 변경사항들 또한 반드시 kube-apiserver로 전달이 된다. 

etcd : K8s 클러스터의 DB이다. 이것의 역할은 clsuter의 상태를 저장하는 것이다. 이것은 모든 cluster의 설정 데이터를 가지고 있다. 그리고 또한 어떠한 노드들이 cluster에서 사용되고 있는지, 어떠한 Pod가 실행중이어야 하는지와 같은 동적인 정보들도 가지고 있다.  client는 직접적으로 etcd와 통신하지 않는다 대신에 kube-apiserver를 통해서 datbase와 통신할 수 있있다. 

kube-scheduler : node위의 Pod들의 스케쥴링을 담당한다. 각 Pod들이 필요한 리소스를 확인하고 각 node들이 이것을 부합시킬 수 있는지 확인한다. 그러나 kube-scheduler가 직접적으로 nodes 위에 Pods를 기동시키는 것은 아니다. 
대신에 node에 pods들이 아직 할당되지 않았음을 발견할 때마다, node를 단순히 선택하고 nodes의 이름을 Pod object에 써주는 역할만 한다. 

kube-controller-manager : 다양한 역할을 가지고 있는데, 지속적으로 kube-apiserver를 통해서 클러스터 상태를 모니터링한다. 클러스터의 current state가  desired state가 아닐때 마다 kube-controller-manager는 desired state를 맞춰주기 위한 작업들을 수행한다. 이것을 controller manager라고 부르는데  왜냐하면 많은 k8s 오브젝트들이 contoller라고 불리는 루프 코드를 이용하여 관리되기 때문이다.  이러한 루프 코드들은 복구를 위한 프로세스를 처리한다. 
이러한 controller는 매우 유용한데, 사용자는 워크로드를 관리하기 위해서 k8s controller의 타입을 설정해야 한다.  

 예를 들어 3개의 nginx Pods이 항상 기동중이여야 한다고 할때, 이 3개의 Pod를 하나의 Deployment 라고 불리는 controller object안에 넣어서, 그들이 기동되도록 유지하는 것 뿐만 아니라 그 노드들이 확장될 수 있도록 해준다. 

 다른 종류의 컨트롤러들은 system-level의 제어권을 가지고 있다. 예를들어 Node controller는 node들을 모니터링되고 오프라일때 응답을 준다. 

- kube-cloud-manager : cloud provider와 통신하는 controller를 관리한다. 예를들어 만약 K8s 클러스터가 GCE를 사용하는 경우 kube-cloud-manager는 GCP로부터 제어권을 가져와 load-balancing과 storage volume을 추가할 수 있다. 

> Master가 아닌 각 node들도 작은 그룹의 control-plane 컴포넌트를 가지고 있다. 

- kubelet  각 노드들은 kubelet 을 수행시키는데 이것이 K8s 에이전트 역할을 수행한다. 
kube-apiserver가 각 노드들에 Pod를 수행시키려고 할때 각 노드의 kubelet과 연결된다.  Kubelet은 container runtime을 사용하여 Pod를 실행하고 그것의 lifecycle을 관리하여 kube-apiserver로 전달한다. 

- container runtime : container 이미지로부터 container를 어떻게 기동할 것인지 방법을 알고 있는 S/W인데, K8s에서는 몇가지 종류의 container runtime을 제공한다.  KE에서 linux 환경에서 nodes에서 container를 기동시키기 위해서 사용하는 runtime component는 Docker이다. (일반적으로 OSS K8s에서 사용하는 것도 Docker이다) 

kube-proxy : 역할은 클러스터 내의 Pod들에 대해서 N/W연결을 시켜주는 것이다. K8s가 OSS로 구성되어 있음으로, 리눅스에서 제공하는 것 처럼 iptables 을 이용하여 방화벽 기능을 제공한다. 


* GKE -  K8s cluster management

> K8s 클러스터를 설정하기 위해 많은 설정값 정의가 필요한데, kubeadm 을 통해서 클러스터에 대한 설정을 자동화 할 수 있다. 그러나 만약 노드에 장애가 발생하거나 별도의 유지보수작업이 필요할 때에는 관리자는 수동으로 해당 작업을 처리할 수도 있다. 

> GKE는 모든 control plane 컴포넌트를 관리해준다. 이것은 관리자를 위해서 K8s API 요청을 보내기 위한 IP 주소를 제공하지만, 기본적으로는 GKE는 모든 K8s 마스터에 대해서 모니터링하고 관리한다. 이러한 master들에 대한 책임은 GCP에 속해 있음으로, 사용자는 master에 대해서 신경쓸 필요가 없으며, GKE에서 수행되는 master에 대해서 따로 비용이 청구되지 않는다. 

> K8s에서 자체적으로 nodes를 생성하는 기능은 없으며, OSS K8s를 사용하는 경우 nodes 생성 및 추가 작업은 cluster 관리자에 의해서 이루어진다.  GKE는 이것을 자동으로 처리해 주는데, Google Compute Engine 인스턴스를 노드로 해서 배포하고 K8s에 등록해준다. 


 > Node들이 compute engine으로 동작하기 때문에 일반적으로 GCP에서 compute engine을 생성하는 것 처럼 cluster를 이루는 node의 머신타입을 정의할 수 있다.  

> GKE에서는 node pool을 정의하여 여러 타입의 머신들을 사용할 수도 있다. node pool은 node들의 집합으로 K8s cluster에서 설정을 공유하게 된다(memory size, CPU type 등). Node pool은 워크로드가 클러스터 내에서 올바를 H/W를 사용하도록 설정하는 가장 쉬운 방법이다. 워크로드가 올바른 node pool을 사용하게 하기 위해서, 각 node pool에 label을 붙여서 관리한다.  

> Node pool은 K8s의 특성이 아닌 GKE의 특징이다. 만약 오픈소스 K8s에서 이러한 기능을 사용하기 위해서는 별도로 구성해야 한다.  또한 GKE환경에서 node pool 단위로 자동으로 node 업그레이드, node 복구, 클러스터 자동확장하는 기능도 제공한다.  

> 당연한 이야기일 수도 있으나, 각 node에 할당되는 CPU와 memory 전부가 Pods에서 작업을 위해 사용될 수 없다. (https://cloud.google.com/kubernetes-engine/docs/concepts/cluster-architecture) 


* GKE - kubernetes regional cluster 구성 

 

> 기본적으로 k8s cluster는 하나의 GCP compute zone에서 3개의  node를 가지고 수행이 된다. Node의 수는 생성 후에도 변경이 가능하다. Node를 더 추가하거나 app을 위한 다수의 복제본을 두는것은 app의 기능을 향상시킨다. 하지만 이렇게 구성한다고 하더라도 1개의 zone에 k8s cluster를 구성하는 경우 zone에 장애가 발생하면 k8s cluster는 동작하지 않는다. 

> GKE 의 regional cluster를 사용한다면 이러한 문제를 해결할 수 있다. regional cluster는 하나의 API endpoint를 가지고 있다. 하지만 그것의 master와 nodes들은 해당 region안에 여러 compute engine zone에 걸쳐서 존재하게 된다.  regional cluster는 또한 하나의 region안의 여러 zone에서 app의 가용성을 확보할 수 있다. 추가적으로 master의 가용성 또한 유지된다. 그럼으로 하나의 zone에 장애가 발생한다고 하더라도 app이나 k8s cluster가 유지될 수 있다. 

> 기본적인 설정으로 regional cluster는 3개의 zone에 배포되고, 각각 zone 마다 1개의 master와 3개의 nodes를 갖는다. 배포할 zone의 개수나 nodes의 수를 증가시킬수도 있는데, 1개의 zone에 5개의 nodes를 두는 경우 node의 개수는 전체 zone에 대해서 동일하게 설정이 되어 총 15개의 nodes를 사용하게 된다. 일단 zonal cluster로 빌드된다면 regional cluster로 변경될 수 없다. 

> K8s cluster는 public internet 망에서는 접속되지 않는다. cluster master는 내부 ip를 통해서 stackdriver와 같은 google cloud 제품에서만 접근이 가능하다.  권한이 있는 N/W에서는 외부 ip를 통해서 접근 할 수도 있다. 권한이 있는 network 는 기본적으로 IP주소 기반으로 분류하여 master에 접속할 수 있다.

>추가적으로 nodes 는 private google access 를 통해서 outboud 권한을 제한할 수도 있는데, 그것들 통해서 다른 GCP 서비스들과 통신할 수 있게 해준다. 예를들어 nodes들이 container 이미지를 google cloud repository 로 부터 외부 ip 주소 없이 가져올 수도 있다. 

Share Link
reply
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31