CKA 대비 kubernetes 스터디 - 1. Core Concept
https://www.udemy.com/course/certified-kubernetes-administrator-with-practice-tests/
Cluster Architecture
kubernetes의 목적은
- host your application
- in the form of containers
- in an automated fashion.
따라서 많은 수의 container 기반 애플리케이션을 배포하고, 애플리케이션 간 통신이 가능하다.
비유를 통해 쉽게 설명하면
Kubernetes가 하는 역할은 크게 보면 두 가지로 나뉜다. 배로 비유하자면
- Cargo Ships that Carrys Containers
- Monitoring / Managing the Cargo Ships.
Kubernetes Cluster는 위의 역할을 담당하기 위한 Nodes의 집합이다.
- Worker Node : container를 Loading하기 위한 용도의 Cargo Ship.
- Master Node : 컨테이너를 올릴 Cargo Ship(Worker Node)을 관리하는 Controll Ship.
- 어떤 종류의 컨테이너를 올릴 것인지 정의한다
- 관리하고 있는 Ship의 정보를 저장한다
- 컨테이너의 상태를 모니터링하고 추적한다 (Manage the Whole Loading Process 등등)
마스터 노드는 위에 정의한 작업들을 수행하기 위해 Control Plane Component라는 것을 사용한다.
구성요소는 아래와 같다.
- Etcd Cluster: 언제, 어떤 컨테이너가 어떤 Node에 올라갔는지를 저장하기 위한 key-value Store.
- Kube-Scheduler: 어떤 노드가 컨테이너를 올릴 수 있는 상태인지 확인하고, 컨테이너를 노드에 동작시키는 역할.
- resource requirement
- worker node의 capacity
- 기타 policy / constraint 고려. (node-affinity rule이라던가)
- Controller-Manager를 구성하는 두 개의 component. 컨테이너의 상태를 체크하고, 정상적으로 작동하게끔 만들어주는 역할
- Node Controller: 클러스터에 있는 노드를 관리. 새 노드가 추가되거나, unavailable / destroyed 대응
- Replication Controller: Desired Number of Containers와 actual running containers를 일치시키는 역할.
- kube-apiserver: 1,2,3 각 구성요소끼리 서로 필요한 정보 교환이 가능하도록 Orchestrating을 담당한다. Orchestrating Component
- 클러스터 내부 컴포넌트에 접근해서 특정 기능을 수행하거나 확인할 수 있도록 사용자에게도 api가 제공된다.
- component끼리의 통신 / worker node도 접근 가능하다.
- Container runtime Engine : 모든 컴포넌트의 최소 단위가 Container. 따라서 container Compatible해야 한다. 컨테이너를 실행할 수 있는 런타임 엔진을 의미하며, 대표적으로 docker.
- 마스터 노드의 control plane component도 컨테이너 기반으로 동작함.
- k8s는 docker 외에도 rocket, ContainerD 등을 지원한다.
- Kubelet: 각 노드에서 실행되는 agent.
- worker node의 kubelet은 마스터 노드에게 'status of container'와 같은 정보를 수집해서 전달.
- 컨테이너 생성 or 삭제와 같이 kube-api에서 오는 요청을 받아서 노드에 적용한다.
- kube-api에서 주기적으로 node / container의 status report를 요청하면 응답하는 역할.
- kube-proxy: 실행 중인 container application 간 통신을 담당하는 component.
- 클러스터의 각 worker node에서 개별적으로 실행되는 service이기도 하다.
Etcd in k8s Overview
Etcd의 정의: a distributed, reliable key-value store that is simple, secure & fast.
key-value Storage: 일반적인 table 형태로 저장하는 대신, configuration처럼 적은 용량을 빠르게 R/W 하기 위해 사용함.
로컬에서 실행할 경우 2379 포트를 사용한다.
- Etcd 클러스터에 node, pods, config, secrets, accounts, role, bindings 등등의 k8s object 정보를 저장함.
- 여기에 값이 정상적으로 저장되거나 변경되면 task가 완전히 complete된 것으로 간주함.
kubectl get
명령어를 사용했을 때 리턴되는 값이 Etcd에 저장된 값을 불러온다.- etcd의 배포방식은 두 개. 직접 배포 / kubeadm 사용한 배포.
직접 설치할 경우
설치에 필요한 옵션들 중 눈여겨볼만한 것.
- TLS certificate 관련한 내용. 별도로 분리해서 깊게 다룰 예정
- Etcd를 하나의 클러스터로 구축 - high availability 확보를 위해 필요한 작업.
- advertise-client-urls 필드: address on which etcd listens. 옵션을 보면 internal_ip주소 + etcd의 디폴트 포트인 2379를 사용한다.
- kube-api 서버에서 etcd cluster에 접근하기 위해 설정해줘야 하는 필드.
kubeadm을 사용해 설치할 경우
- kube-system 이라는 namespace에 pod 형태로 etcd server가 생성된다.
- pod 내부의 container로 들어가서 etcdctl 명령어로 리소스 접근이 가능함.
- pod 내부의 디렉토리를 확인해보면 registry 하위경로에 여러 k8s constructs가 존재한다.
- minions of nodes
- pods
- replicasets
- deployments
- roles / secrets
High availability를 지원하기 위한 etcd 세팅은 위의 그림과 같다.
- multiple master node 세팅 = multiple etcd instance가 생성됨.
- etcd.service 필드의
initial-cluster controller-0
항목에 etcd server의 경로를 입력해준다.
(Optional) Additional information about ETCDCTL Utility
ETCDCTL is the CLI tool used to interact with ETCD.
ETCDCTL can interact with ETCD Server using 2 API versions - Version 2 and Version 3. By default its set to use Version 2. Each version has different sets of commands.
For example ETCDCTL version 2 supports the following commands:
etcdctl backup
etcdctl cluster-health
etcdctl mk
etcdctl mkdir
etcdctl set
Whereas the commands are different in version 3
etcdctl snapshot save
etcdctl endpoint health
etcdctl get
etcdctl put
To set the right version of API set the environment variable ETCDCTL_API command
export ETCDCTL_API=3
버전을 명시하지 않으면 기본적으로 설치되는 버전은 version 2. 버전 2와 3은 명령어가 다르며, 호환되지 않는다.
Apart from that, you must also specify path to certificate files so that ETCDCTL can authenticate to the ETCD API Server.The certificate files are available in the etcd-master at the following path.
--cacert /etc/kubernetes/pki/etcd/ca.crt
--cert /etc/kubernetes/pki/etcd/server.crt
--key /etc/kubernetes/pki/etcd/server.key
강의는 기본적으로 version 3을 사용하고 있으므로, etcd 명령어가 작동하려면 아래의 명령어로 etcdctl 버전을 설정하고 cert 키값을 세팅해야 한다.
kubectl exec etcd-master -n kube-system -- sh -c "ETCDCTL_API=3 etcdctl get / --prefix --keys-only --limit=10 --cacert /etc/kubernetes/pki/etcd/ca.crt --cert /etc/kubernetes/pki/etcd/server.crt --key /etc/kubernetes/pki/etcd/server.key"
Kube-API Server
kubectl 명령어를 실행하면 기본적으로 kube-apiserver로 요청이 전달된다. 또는 kubectl 대신 직접 post api를 호출할 수 있다.
ex) Creating a pod: 요청이 들어오면 kube-apiserver는
- authenticate / validate request.
- api server에서 pod를 생성한다. (아직 어느 node에서 실행될 pod인지는 결정하지 않았다.)
- update the information in the Etcd Server.
- Scheduler는 node에 할당되지 않은 상태인 새 pod가 생성된 것을 모니터링에서 확인한다.
- 어느 node에 할당할 것인지를 api server에 전달한다.
- api server는
- scheduler가 전달한 정보를 Etcd server에 전달해서 저장하도록 한다.
- pod를 생성해야 할 worker node의 kubelet에 요청을 전달한다.
- kubelet은 새 pod를 생성하라는 요청을 수행한다.
- 실행해야 할 애플리케이션 이미지를 Container Runtime Engine이 실행하도록 한다.
- Status가 변경되면, kubelet은 api server에 pod가 생성되었다는 변경사항을 전달한다.
- api server는 Etcd server에 변경사항을 전달한다.
다른 형태의 요청도 대부분 위와 같은 절차를 거쳐 이루어진다.
즉 kubernetes에서 리소스와 오브젝트를 관리하는 주체가 kube-apiServer.
- Etcd datastore에 유일하게 직접 접근할 수 있다.
- k8s의 다른 오브젝트 / 리소스 (scheduler, kubelet, kube-controller-manager 등)는 kube-apiServer를 사용해서 Etcd에 접근해야 한다.
kubeadm을 사용할 경우 kube-apiserver를 직접 설치할 필요는 없지만, binary 형태로 직접 설치할 수도 있다.
k8s release page에서 다운로드 받고, 마스터 노드에 설치하면 됨.
음영처리된 부분 = etcd-server에 연결하기 위한 url을 설정하는 필드.
kubeadm으로 설치했다면, master node의 kube-system Namespace에 kube-apiserver-master 라는 이름의 Pod가 생성된다.
pod를 정의한 yaml 파일은 아래 경로를 통해 확인할 수 있다.
kube-apiserver 실행에 적용한 옵션은 아래의 yaml파일에서 확인할 수 있다.
마스터 노드에서 실행중인 프로세스 중 apiserver에서 실행되는 것들은 아래 명령어로 확인하면 된다.
ps -aux | grep kube-apiserver
Kube-Controller-Manager
kube-controller-manager: Master Node에서 각 container들의 status를 확인하고, 문제가 생겼을 경우 해결하는 역할을 담당함.
- Node Controller: kube-apiserver에 매 5초마다 요청을 보내서 노드의 상태를 체크함.
- 만약 5초마다 체크하는 노드가 unhealthy한 상태로 40초가 지나면, 노드의 상태를 unreachable로 변경한다.
- unreachable 상태가 5분 이상 지속될 경우, unreachable 노드에 있는 pod (replicaSet)을 다른 master node에 대신 생성한다.
- Replication Controller: 5초마다 각 노드의 pod 상태를 체크해서 desired 상태를 유지하는지 확인.
- pod가 죽었을 경우 새로운 pod를 생성해서 대체한다.
이외에도 k8s에는 다양한 종류의 controller가 있다. k8s에서는 Object를 관리하기 위해 여러 종류의 Controller를 사용한다.
- 위 그림에 있는 여러 가지 Controller들은 Kube-Controller-Manager 라는 single process로 관리된다.
- 즉 kube-controller-manager를 설치하면 k8s에서 사용하는 controller들이 전부 설치된다.
직접 설치하는 방법
- 상태 체크 옵션, unreachable / pod recreate 조건 등은 위에 표시한 옵션으로 설정할 수 있다.
- 디폴트 옵션으로는 모든 종류의 controller가 전부 활성화된다.
어떤 controller가 제대로 설치되지 않았거나 작동하지 않는다면, 이 단계에서 controller를 활성화할 수 있다.
kube controller manager 확인하기
kubectl get pods -n kube-system
에서 kube-controller-manager-master pod를 확인한다.
pod definition yaml 파일
kubeadm 없이 직접 설치할 경우, kube-controller-manager service의 옵션은 아래의 경로에서 확인할 수 있다.
현재 실행중인 kube-controller-manager 프로세스를 확인하려면 ps -aux | grep kube-controller-manager
명령어를 이용하면 된다.
Kube Scheduler
Which pod goes on which Node 를 결정하는 object. 실제로 pod를 배치하는 역할을 하지는 않는다.
- 실제로 배치하는 작업은 kubelet이 수행함. 각 worker node마다 설치되어 있으며, 해당 node를 관리하는 주체.
- filter Node / Rank Node 작업을 통해 pod를 설치할 수 있는 최적의 node를 선정함
- Filter out the Node that do not fit the profile for this pod.
- 예시 그림의 cpu 요구량은 10. 따라서 cpu 4인 노드는 대상에서 제외된다.
- node의 우선순위를 0~10까지 값을 매기는 function을 사용한다.
- cpu 10을 할당하고 나면 얼마의 리소스 여유가 남게 되는지... 많이 남을수록 가중치가 높다.
- 예시의 경우 cpu 16개가 있는 Node의 가중치가 더 높기 때문에 선택된다.
High Level에서는 위와 같은 방식으로 작동하며, configuration 설정에 따라 값이 변할 수 있다.
직접 설치하는 방법. Running as a Service이기 때문에 configuration file을 지정해줘야 한다.
kubeadm으로 설치했을 경우 pod의 옵션은 아래 명령어로 확인할 수 있다.
running process 확인 방법
Kubelet
worker node의 작업을 총괄하는 object.
- Register the Node. 자신이 실행되고 있는 노드를 클러스터에 등록한다.
- kube-apiserver에게서 load a container (pod) 요청을 받으면, container runtime engine에 이미지 실행을 요청한다. -> runtime instance를 생성한다.
- 실행중인 pod의 상태를 모니터링하고, timely-base로 kube-apiserver에 모니터링 정보를 전달한다.
설치 방법: kubeadm으로 설치할 수 없다. worker node에 직접 설치해야 함.
https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/ 문서의 installing kubeadm, kubelet and kubectl 항목에서 확인할 수 있다.
프로세스 확인은 ps -aux | grep kubelet
로 가능하다.
Kube-proxy
기본적으로 같은 클러스터에 배포된 pod끼리는 통신이 자유롭다. pod-networking solution을 사용하기 때문.
- Pod Network : internal virtual network. 클러스터의 모든 노드 / 각 노드에서 실행중인 pod을 서로 연결하는 역할.
ex) Web App을 첫 번째 노드에 배포하고, DB를 두 번째 노드에 배포한 상황이라고 하면
- DB가 실행중인 pod의 ip주소가 생성되지만, 이 ip주소는 가변적이다. pod 재배포 등의 이슈로 재실행되면 변경됨.
- 따라서, web app이 db에 접근하기 위해서는 보통 service를 사용한다.
- service는 별도의 ip주소를 가지고 있으며, service는 backend pod로 트래픽을 포워딩하는 역할.
- service는 actual Object가 아니다. in-Memory Process in K8s임.
- pod나 container 개념이 아니므로, pod network에 접근하는 방식으로 포워딩하지 않는다.
- service가 여러 노드의 각 pod에 접근할 수 있는 이유는 kube-proxy의 존재 때문이다.
- 각 노드에서 실행되는 k8s process 중 하나.
- service를 탐지하고, 새로운 service가 등장할 경우 appropriate rules on each node 을 설정해서 traffic forwarding을 가능하게 해준다.
- ex) ipTable rules. 10.96.0.12에서 넘어온 트래픽을 내부 pod 주소인 10.32.0.15 로 포워딩한다.
직접 설치하기
kubeadm으로 설치할 경우 pod과 daemonSet으로 확인할 수 있다.
Pod
kubernetes의 최종적인 목표는 Deploy the Application in a form of Containers on a set of machines - configured as worker nodes in a cluster.
- 단, 노드에 직접 배포하지는 않는다. Encapsulated into k8s Object known as Pod.
- 만약 트래픽이 많아져서 컨테이너의 개수를 늘려야 하는 상황이라면, pod 개수를 늘린다.
- node의 리소스가 부족할 만큼 pod 개수가 많아지면, 새 node를 생성해서 pod을 올릴 수 있다.
일반적으로 pod과 container는 1:1관계를 유지하며, scaling을 위해서는 container 개수가 아니라 pod 개수를 조절한다.
- pod 하나에 여러 개의 container를 생성하는 경우는 보통 app의 모니터링이나 health check 기능을 적용하기 위해서.
- 동일한 network space를 사용하므로, 두 개의 container는 localhost로 통신 가능하며, same storage를 사용할 수 있다.
- container 기반 애플리케이션을 실행한다
- 애플리케이션의 상태를 모니터링할 helper를 생성한다
- 애플리케이션과 helper를 매칭할 수 있도록 매핑 테이블을 생성하고 관리한다
위의 작업을 kubernetes에서는 pod가 담당한다. Architectural stability / scalability에 유리한 구조.
pod with yamls
k8s에서는 pod 생성을 위한 input으로 yaml파일을 사용한다.
k8s의 모든 오브젝트는 기본적으로 4개의 yaml required field가 존재한다.
- apiVersion: object를 생성하기 위한 k8s 버전을 의미함. 생성하고자 하는 객체에 맞는 버전을 명시한다.
- kind: 어떤 종류의 object를 생성할 것인지 명시한다.
- metadata: object를 설명하는 기본적인 데이터. name이나 labels 등. key-value 형식으로 데이터를 정의한다.
- name과 label은 동일한 line에 있어야 한다. 서로는 siblings 관계이고, metadata의 children 관계이다.
- k8s에서 metadata 필드는 k8s api에 정의된 필드만 사용할 수 있다.
- 대신, labels 필드에서는 어떤 값이던 key-value 형태로 정의해서 사용할 수 있다.
kubectl create -f fileName.yaml
명령어로 pod를 생성할 수 있다.
ReplicaSets (replication controller)
single pod 위에서 돌고 있는 애플리케이션이 어떤 이유로든 죽을 수 있다. 하지만 pod가 죽었다고 애플리케이션이 바로 먹통이 되어선 안 된다.
- replication controller: 하나의 클러스터에서 multiple instances of a single pod 가 동작하도록 지원하는 컨트롤러. high availability의 핵심
- 지정된 특정 개수의 pod (desired state)이 항상 유지될 수 있도록 하는 기능이라고 보면 된다.
- pod가 하나만 있도록 설계된 애플리케이션이라고 해도, replication controller는 해당 pod에 문제가 생겼을 경우 정상으로 복구하는 기능을 수행한다.
- 여러 개의 pod간 로드밸런싱 기능도 수행한다. pod에 들어오는 요청이 많을 경우 추가로 pod을 생성할 수 있게 지원하며,
- 노드 리소스가 부족하면 다른 노드에서라도 pod을 생성하고 로드밸런싱을 수행한다.
Replication Controller와 replicaSet의 차이?
- 동일한 목적으로 만들어진 object이며, replicaSet이 업그레이드된 버전.
- 현재 replication 기능을 수행하려면 replicaSet을 사용하도록 권장하고 있다.
- 같은 목적을 위해 수행하는 방법이 서로 다른 셈.
replication Controller의 경우, 위와 같은 형식으로 사용한다.
- spec.template 하위항목에 pod에서 사용하던 metadata, spec을 그대로 적용한다. indentation 확인.
- 몇 개의 pod를 유지할 것인지를 spec.replicas 필드에 정의함.
replicaSet의 경우
- apiVersion은 apps/v1. replicationController와 다르다.
- selector 필드가 required로 변경되었다.
- selector 필드는 replicaSet을 생성하기 전에 만들었던 pod 중 selector에 포함되는 pod까지도 통제할 수 있다.
- matchLabels.type 형태로 labels에 정의한 key-value 값을 선택해서 통제 가능.
- replicationController 에서는 제공하지 않는 옵션이 replicaset에서는 지원됨.
labels and selectors: k8s에 떠 있는 수많은 Pod 중, replicaSet이 모니터링하고 관리해야 할 pod를 구별하기 위해 사용함.
- 다른 controller에서도 비슷한 목적으로 label / selector를 사용한다.
Scale
Note
kubectl scale --replicas=6 -f replicaset-definition.yaml
명령어를 사용할 경우, replica 옵션을 6으로 변경했다고 해서 replicaset-definition.yaml 파일의 replicas 필드가 자동으로 변경되지는 않는다.
Deployment
Deployment : replicaset보다 high level 개념의 object.
- 무중단 배포 기능 (rolling updates)
- 롤백 기능
- scaling / monitoring 같은 기능을 모든 pod에 일괄 적용하기 위한 pause / resume 기능 제공.
Namespace
k8s에서 생성하는 resource의 구분 / 관리를 위해 만들어진 영역.
namespace별로 resource quota를 정할 수 있다.
- 같은 namespace 내부에 있는 리소스끼리는 name만으로 호출이 가능하다.
- 다른 namespace의 리소스를 호출하려면 Service의 DNS 전체 이름을 입력해야 한다.
- service를 생성할 때 dns가 자동으로 생성되기 때문에 다른 ns에서도 호출 가능.
k8s DNS의 의미는 위 그림과 같다.
디폴트 namespace를 default 대신 다른 ns로 변경하는 방법.
kubectl config set-context $(kubectl config current-context) -n=dev
namespace별로 리소스 제한 정하기.
Service
사용자와 k8s component, 서로 다른 k8s component간 간 통신을 가능하도록 해 주는 object. decoupling을 가능하게 해 주는 핵심기능.
- NodePortService: 노드의 특정 포트를 열어서 service가 해당 포트를 담당하고, 요청이 들어오면 pod network에 포워딩.
- 클러스터 노드의 특정 포트를 열고, 해당 포트로 요청 들어오는 Request를 service가 포워딩하는 식.
- ClusterIP: service가 클러스터 내에서 virtual IP를 생성한 뒤, virtual IP를 사용해서 다른 service와 통신하는 식.
- LoadBalancer : service 앞에 로드밸런서를 붙이는 방식.
NodePort
- 클러스터 노드의 port(30008)가 service (clusterIP)의 80포트로 연결된다.
- nodePort로 사용할 수 있는 port는 30000 ~ 32767.
- service의 80포트가 pod의 80포트와 연결된다.
- spce.Type은 nodeport로 설정한다.
- targetPort: 실제로 접근할 Pod 포트
- port: service (clusterIP)와 pod가 통신할 포트
- nodePort: 클러스터 노드의 포트.
targetPort필드는 입력하지 않을 경우 port 필드의 값과 동일하며, nodeport를 입력하지 않을 경우 범위 내에서 사용가능한 포트가 랜덤으로 배정된다.
어떤 종류의 pod와 연결할 것인지는 pod label에 정의한 값을 selector로 불러온다. pod의 label이 app: myapp, type: front-end 로 정의되어 있다면, selector 필드에도 동일하게 입력하는 식.
- selector로 확인할 수 있는 pod가 여러 개라면, 여러 개의 pod에 요청을 알아서 loadBalancing하는 역할을 겸하고 있다.
- 로드밸런싱 디폴트 방법은 random.
pod selector로 확인할 수 있는 pod가 여러 노드에 걸쳐있을 경우
- service를 생성할 때 별다른 옵션을 주지 않았다면, 노드 전체에서 접근할 수 있도록 cross-board Service를 생성한다.
- 각각의 nodeport와 service port, targetport를 매핑하고 있으며, 어느 클러스터에 접근해도 pod로 요청을 전달할 수 있다.
pod가 추가로 생성되거나 삭제된다 해도 flexible하게 조정 가능함.
Service - ClusterIP
frontend, backend, DB처럼 여러 layer로 구성된 애플리케이션을 k8s에서 사용할 경우, 여러 개의 pod 간 통신을 원활하게 하기 위한 endpoint 역할. 각 레이어는 다른 레이어에 미칠 영향을 고려할 필요 없이 scale out 가능함.
- 각 service마다 IP, name, address가 있으며, 이 정보를 토대로 다른 pod에서 호출할 수 있음.
Service - LoadBalancer
예컨대 두 개의 서비스가 있고, 각각의 service를 nodePort로 생성해둔 상황.
- 각각의 Service (ClusterIP) + port 조합을 사용하면 service에 접근할 수 있다.
- 하지만, 실 사용자에게는 접근할 수 있는 단 하나의 DNS만 있으면 충분하다. 굳이 여러 개를 제공할 필요가 없음
해결 방법으로 하나의 VM을 생성하고, 로드밸런서 기능을 할 수 있도록 설정하는 방식이 있다.
- nginx 같은 프로그램을 설치해서 route traffic할 수 있다.
- 이런 설정작업을 직접 해내는 건 꽤나 번거로운 작업임.
k8s에서는 supported Cloud Platform (AWS, GCP, Azure 등) 에서 제공하는 loadBalancer를 붙일 수 있도록 지원하고 있다.
yaml파일에서 type을 LoadBalancer로 지정하면, AWS나 GCP 같은 클라우드 플랫폼에서 실행 시 native Loadbalancer를 지원한다.
- 만약 실행환경이 virtualbox처럼 loadbalancer를 지원하는 환경이 아닐 경우 NodePort와 동일하게 동작함.
Imperative vs Declarative
IaaS에서 인프라를 관리하는 두 가지 방식을 의미함.
- Imperative: 순차적으로 what to do, how to do 를 입력하는 방식. Step By Step
- 재현성이 보장되진 않음. 설치환경이나 실행환경에 따라 절차를 추가 / 변경해야 할 수 있음.
- Declarative: 목표를 지정하고, 방법은 설정하지 않음.
- Ansible, Terraform, Puppet 등.
kubectl apply -f [yaml file]
: k8s에서 yaml파일의 변경된 부분을 탐지하고, 파일에서 지정한 state를 반영한다.
- 시험에서 단순한 작업을 수행해야 할 때에는 편리하지만, 요구사항이 복잡해지면 대응이 어려움.
- 재사용이 어렵고 tracking이 힘들다.
따라서 해당 작업을 수행할 때, 작업의 결과를 Declarative하게 사용할 수 있도록 파일 형태로 생성해두는 게 좋다.
로컬에 파일 형태로 생성해서 사용할 수도 있고, k8s 메모리에 저장되어있는 yaml 파일을 edit 명령어로 불러와 사용할 수 있다.
- 단, edit으로 수정했을 경우 변경사항은 메모리에만 저장되므로 object configuration 확인이 번거롭다.
- create, replace로 imperative approach를 수행하는데,
- create는 이미 생성된 object가 있을 경우 에러를 내고
- replace는 해당 object가 없으면 에러를 낸다.
- 따라서 명령어를 수행하기 전에 Status를 확인해서, 에러가 나지 않는 환경인지를 확인해야 함
- 로컬 환경에 yaml파일이 있다면, apply 명령어로 yaml에 정의한 state로 변경할 수 있다.
- 구체적인 작업방법은 kubectl apply 명령어에 의존한다 (알아서 하게 둔다)
시험 팁
- 시간 아끼는 차원에서는 imperative를 권장한다. 단순한 명령어 수행을 가장 빨리 할 수 있다
- multiple containers / environment variables / command 상태라면 object configuration file을 만들어서 사용하는 편이 낫다.
kubectl apply의 작동방식
apply cmd를 실행한다
- object가 존재하지 않을 경우, 생성한다
- 이미 생성된 object가 있을 경우 Live Object Configuration을 생성한다.
- 로컬에서 apply에 파라미터로 넣은 manifest yaml 파일에
- status 저장을 위한 필드값이 추가된 형태의 configuration 파일을 메모리에 생성한다.
- apply 명령어일 경우, lastAppliedConfiguration을 생성한다
- 로컬 yaml 파일을 json으로 변환한 뒤 저장함.
예컨대 nginx 버전을 1.19로 변경하고 apply를 진행하면
- k8s의 live object와 apply에 적용한 yaml파일을 비교한다.
- 변경사항이 있을 경우 live configuration object가 변경된다.
- 변경이 끝나면, last applied configuration에도 변경사항이 업데이트되어 저장된다.
만악 label에서 특정 필드를 삭제하고 apply할 경우
- k8s live object에서는 필수적으로 요구하는 필드가 아니므로 변경사항을 감지하지 못하지만
- last applied configuration과 비교해서 값이 달라졌을 경우 변경사항이 있음을 감지할 수 있다.
last applied configuration 값은
k8s의 live object configuration에서 last-applied-configuration 어노테이션에 포함되어 있다.