본 포스팅은 CKA 자격증 준비를 위해 해당 강의를 보고 정리한 자료입니다.
일부 생략되었으니 꼭 강의를 수강하시고 내용 정리 용도로만 참고하시길 바랍니다.
Cluster Architecture
쿠버네티스의 구조에 대한 내용으로, 구성 요소에 대한 간략한 설명을 포함.
-> 강의 자료 또는 쿠버네티스 문서 참고
ETCD
정보를 key-value 형태로 저장하는 데이터베이스로, 컨테이너가 어떤 ship에 있는지,언제 load되었는지 등 각기 다른 ship들에 대한 정보를 저장
ETCD in K8S
- nodes, pods, configs, secrets, accounts, roles, bindings .. 등 cluster에 관한 정보 저장
- kubectl 의 모든 정보들은 ETCD 서버에서 오는 것
- 모든 변화(노드 추가, 파드 배포 등) 또한 ETCD 서버에 업데이트
ETCD pod
- kubeadm으로 설치했다면 kube-system 에 etcd-master라는 이름으로 배포됨
- 다음 명령어로 저장된 key들 확인 가능
$ kubectl exec etcd-master -n kube-system etcdctl get / --prefix -keys-only
ETCD in High Availability Environment
- 여러 master 노드의 환경이면, 여러 instance가 있을 것
- 각 ETCD instance가 서로를 알 수 있도록 etcd.service에 올바른 파라미터를 지정해야함
Kube-API server
클러스터 내 변화를 수행하기 위한 모든 다양한 작업들의 중심 역할
- Authenticate User
- Validate Request
- Retrieve data
- Update ETCD
- Scheduler
- Kubelet
Kube API server work pattern
kubectl 사용시 kube api 서버 동작
kube api 서버는 request를 인증/확인 후 etcd cluster에서 데이터를 검색해 반환
Pod 생성시 kube api 서버 동작
- api 서버는 pod object 생성 (노드에 할당하지 않고)
- etcd 서버에 pod이 생성되었음을 업데이트
- scheduler는 api 서버를 모니터링 하고 있으므로, 새로운 pod이 생겼음을 인지, 배포할 노드 확인
- api 서버는 etcd에 정보 업데이트
- api 서버가 해당 정보를 적합한 노드의 kubelet에 전달
- kubelet이 노드에 pod 생성, container runtime engine에 application image을 배포하도록 지시
- kubelet 은 api 서버에 상태 업데이트, api 서버는 data를 etcd 에 저장
⇒ pod 생성을 예시로 들었지만, pod 생성 뿐만 아니라 모든 변화가 이러한 패턴을 따름
Kube API server Pod
kubeadm으로 설치한 경우
- kube-system의 kube-apiserver-master
- apiserver 정의 파일 : /etc/kubernetes/manifests/kube-apiserver.yaml
다른 방법으로 설치한 경우
- apiserver 정의 파일 : /etc/systemd/system/kube-apiserver.service.yaml
Process 확인
master node process의 kube-apiserver 통해 실행중인 process 확인 및 effective option 확인
$ ps -aux | grep kube-apiserver
Kube Controller Manager
- 시스템 내 다양한 구성 요소의 상태를 지속적으로 모니터링하고, 전체 시스템을 원하는 상태로 만들기 위해 작동하는 프로세스
- Kube Controller Manager는 여러 controller가 하나의 프로세스로 패키징되어 실행되는 형태
- Node Controller, Namespace-Controller, Replication-Controller ... 등등
Node Controller
- 노드들의 상태를 모니터링, application이 계속 실행될 수 있도록 필요한 조치를 수행
Node Controller Parameters
- --node-monitor-periods=5s : 노드 컨트롤러가 5초마다 노드의 상태를 체크
- --node-monitor-grace-period=40s : 노드의 상태가 정상적이지 않은 경우, 40초를 기다린 후 unreachble 상태로 표기
- --pod-eviction-timeout=5m0s : 노드가 5분안에 정상화 되지 않을 경우, 해당 노드에 할당된 pod을 삭제하고 다른 정상 노드에 생성할 수 있도록 함
Replication Controller
- replica set의 상태를 모니터링하고, 의도된 수의 pod이 available한지 확인하는 역할
- pod이 하나 삭제되면, 하나 더 생성
Kube Controller Manager pod
kubeadm으로 설치한 경우
- kube-system의 kube-controller-manager-master
- apiserver 정의 파일 : /etc/kubernetes/manifests/kube-controller-manager.yaml
다른 방법으로 설치한 경우
- apiserver 정의 파일 : etc/systemd/system/kube-controller-manager.service
Process 확인
$ ps -aux | grep kube-controller-manager
Kube Scheduler
- pod이 어떤 노드로 갈 것인지 결정하는 역할
- 실제로 노드에 pod을 배치하는 것은 아니다. -> kubelet의 역할
- 노드 선정 방식
- pod이 요구하는 resource를 보고 filtering
- pod을 배치하고 해당 노드에 더 많은 resource가 남는 경우를 상위로 rank 지정
Kube Scheduler pod
- kube-scheduler 라는 이름으로 다른 controller들과 동일
Kubelet
- master의 scheduler의 지시에 따라, 컨테이너를 load/unload하는 역할
- 또한 컨테이너의 상태를 일정 간격에 따라 report
- kubelet은 worker 노드에 pod을 생성하기 위해 container runtime(ex. docker) 에 요청을 전달
- kubelet은 pod과 컨테이너의 상태를 지속적으로 모니터링하고, 결과를 kube-apiserver에 주기적으로 전송
kubelet 설치
- kubeadm으로 worker 노드를 구성할 경우, kubelet이 자동으로 설치되지 않으므로 별도로 kubelet 을 설치해야함
Kube Proxy
- 쿠버네티스 클러스터의 모든 pod은 서로 다른 pod과 통신할 수 있음
- 클러스터 내 pod 네트워크를 담당하는 기능이 배포되어 있음
- pod 네트워크는 모든 pod이 통신할 수 있도록 클러스터의 모든 노드에 생성되는 가상 네트워크
- 특정 pod에서 다른 pod에 접근하기 위한 가장 좋은 방법은 service를 이용하는 것
- service 도 ip를 할당 받으며, pod이 이 ip로 서비스에 접근하고자하면, traffic이 pod으로 forward 됨
- 그렇다면 service가 무엇이며, ip를 어떻게 얻는 것인가?
- service는 실제로 존재하는 것이 아님
- pod과 같이 컨테이너 형태로 실행되지 않으며, 어떤 인터페이스나 요청을 기다리는 프로세스가 존재하는 것이 아님
- 그저 쿠버네티스 메모리 상에 존재하는 가상 컴포넌트 개념
- → 하지만 서비스는 접근 가능해야 하는데? → kube-proxy 를 통해 가능
- Kube Proxy
- 쿠버네티스 클러스터 내 모든 노드에서 실행되는 프로세스
- 새로운 서비스를 찾는 역할
- 서비스가 생성되면 어떤 서비스에 대해 어떤 pod으로 traffic을 forward 할지에 대한 rule을 생성함
- → 이러한 네트워크 rule을 만드는 방법 중 하나가 IPTABLES 를 사용하는 것
- 모든 노드에 service의 ip로 들어오는 트래픽에 대해 해당 pod으로 보낼 수 있는 규칙을 IPTABLES에 만들어줌
Kube proxy pod
- kubeadm은 모든 노드에 kube-proxy를 배포하며, daemon set으로 배포된다.
- 모든 클러스터의 노드마다 오직 하나의 kube-proxy pod이 실행될 수 있음
$ kubectl get daemonset -n kube-system
PODs
- 쿠버네티스는 컨테이너를 직접적으로 worker 노드에 배포하지 않음
- 컨테이너는 pod이라는 object로 캡슐화 되며, pod은 쿠버네티스에서 가장 작은 object에 해당
- pod과 컨테이너는 기본적으로는 1:1
- 클러스터 내 노드에 pod이 하나 배포된 상황에서, application을 scale up할 경우, 새로운 pod이 생성됨
- 노드가 unsufficient할 경우, 새로운 노드에 pod을 추가하게 됨
- (필요에 따라 pod이 컨테이너를 여러개 가지도록 할 수 있음)
$ kubectl run nginx —image nginx
$ kubectl get pods
PODs with YAML
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
labels:
app: myapp
type: front-en
spec:
containers:
- name: nginx-container
image: nginx
Practice
- dry-run 으로 pod 생성 없이 yaml 뽑고 yaml 으로 pod 생성
$ kubectl run redis --image=redis123 --dry-run=client -o yaml > pod.yaml kubectl apply -f pod.yaml
- pod 수정
$ kubectl edit pod redis
ReplicaSets
Replica & Replication Controller
- Replication Controller는 쿠버네티스 클러스터에서 단일 pod의 여러 instance가 가능하도록 해주고 이는 고가용성을 제공
- 지정된 수의 pod을 보장하는 역할
- Replication Controller가 필요한 또 다른 이유는, 여러 pod을 만들어 load를 공유하기 위함
- 예를 들어 사용자 집합에 서비스를 제공하는 단일 pod이 있을 때, 사용자가 늘어나면 추가 pod을 배포하여 두 pod에 load balance를 맞추는 것
Replication Controller | Replica Set
- Replication Controller는 Replica Set 으로 대체 됨
Replication Controller
apiVersion: v1
kind: ReplicationController
metadata:
name: myapp-rc
labels:
app: myapp
type: frontend
spec: # Replication Controller
template:
metadata:
name: myapp-pod
labels:
app: myapp
type: front-end
spec: # Pod
containers:
- name: nginx-container
image: nginx
replicas: 3
Replica set
apiVersion: v1
kind: ReplicaSet
metadata:
name: myapp-replicaset
labels:
app: myapp
type: frontend
spec: # Replication Controller
template:
metadata:
name: myapp-pod
labels:
app: myapp
type: front-end
spec: # Pod
containers:
- name: nginx-container
image: nginx
replicas: 3
selector:
matchLabels:
type: front-end
→ RC와 차이점은, ReplicaSet은 해당 ReplicaSet으로 생성되지 않은 pod에 대해서도, selector를 지정해서 일치하는 labels를 가진 pod에 대한 replica를 관리할 수 있다는 점
Labels & Selectors
- Labels
- ReplicaSet은 pod들을 모니터링하고, 누가 fail나면 새로운 pod을 배포한다. 모니터링할 pod들은 labeling으로 선택한다.
Scale 수정
$ kubectl replace -f replication-definition.yml
$ kubectl scale —replicas=6 -f replicaset-definition.yml
$ kubectl scale —replicas=6 replicaset myapp-replicas
Deployments
- rolling update, undo change, pause, resume 과 같이 instance를 원활하게 업그레이드 할 수 있는 기능을 제공
- Replication Controller 또는 Replica Set을 통해 pod을 배포하는 상위 object
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-deployment
labels:
app: myapp
type: frontend
spec:
template:
metadata:
name: myapp-pod
labels:
app: myapp
type: front-end
spec:
containers:
- name: nginx-container
image: nginx
replicas: 3
selector:
matchLabels:
type: front-end
deployment, rc, pod을 모두 보고싶을 땐 "kubectl get all" 을 활용한다.
+TIP : Use Kubectl RUN
Create an NGINX Pod
$ kubectl run nginx --image=nginx
Generate POD Manifest YAML file (-o yaml). Don't create it(--dry-run)
$ kubectl run nginx --image=nginx --dry-run=client -o yaml
Create a deployment
$ kubectl create deployment --image=nginx nginx
Generate Deployment YAML file (-o yaml). Don't create it(--dry-run)
$ kubectl create deployment --image=nginx nginx --dry-run=client -o yaml
Generate Deployment YAML file (-o yaml). Don't create it(--dry-run) with 4 Replicas (--replicas=4)
$ kubectl create deployment --image=nginx nginx --replicas=4 --dry-run=client -o yaml > nginx-deployment.yaml
파일로 저장하고, 필요한 변경을 수행한 다음 deployment 생성
$ kubectl create -f nginx-deployment.yaml
Namespace
- 각 namespace는 그 만의 정책을 가지게됨
- resource를 할당하여 특정 양의 resource를 보장할 수 있음
- kube-system : networking solution 또는 dns 서비스 등을 위해 내부적인 목적을 가진 pod또는 서비스가 배포되며, 삭제할 수 없도록 방지함
- kube-public : 모든 사용자에게 available한 resource가 생성되는 곳
DNS
- namespace 내 pod들은 그들의 이름으로 서로를 알 수 있음
- mysql.connect('db-service')
- 다른 namespace 일 경우 servicename.namespace.svc.clutser.local 포맷 이용
- mysql.connect('db-service.dev.svc.cluster.local')
Command
$ kubectl create namespace dev
$ kubectl create -f pod-def.yaml —namespace=dev
apiVersion: v1
kind: Namespace
metadata:
name: dev
Namespace switch
default namespace 변경
$ kubectl config set-context $(kubectl config current-context) —namespace=dev
Resource Quota
namespace에 리소스 할당(제한)
apiVersion: v1
kind: Namespace
metadata:
name: dev
spec:
hard:
pods: "10"
requests.cpu: "4"
requests.memory: 5Gi
limits.cpu: "10"
limits.memory: 10Gi
Services
- 다양한 내부 component와 application 바깥이 통신할 수 있도록 도와줌
- application을 다른 application 또는 user들과 연결할 수 있도록 도와줌
Service Types
NodePort
- 노드에서 port로 들어오는 요청을 듣고 있다가, 요청이 오면 pod port로 전달
apiVersion: v1
kind: Service
metadata:
name: myapp-service
spec:
type: NodePort
ports:
- targetPort: 80 # app(pod)의 port
port: 80 # service port
nodePort: 30008 # 없을 경우 자동 지정, 실제로 user가 app에 접근하기 위한 port
selector: # pod selection
app: myapp
type: front-end
- 해당 label의 여러 pod이 있을 경우 service는 여러 pod을 외부 request를 전달할 endpoint로서 선택함
- 한 노드의 여러 pod, 여러 노드에 있는 여러 pod의 경우에도 동일하게 service를 생성하면 됨
ClusterIP
service가 각기 다른 서비스들이 통신할 수 있도록 가상의 ip를 생성
- pod의 ip는 바뀔 수 있기 때문에 application 통신에는 적합하지 않음
- 쿠버네티스 서비스는 pod들을 그룹화하고 접근하기위한 하나의 interface를 제공
- 각 service는 ip name을 할당받고, 해당 name은 다른 pod이 service에 접근하기 위해 사용됨
- ⇒ 이런 type의 서비스가 ClusterIP
apiVersion: v1
kind: Service
metadata:
name: back-end
spec:
type: ClusterIP
ports:
- targetPort: 80 # pod expose
port: 80 # service expose
selector:
app: my-app
type: back-end
LoadBalancer
- 지원되는 클라우드 제공 업체에서, 서비스에 대한 로드 밸런서를 공급
- 여러 노드에 걸쳐 여러 pod이 있을 경우, 서비스를 통해 접근 할 수 있는 ip는 여러개
- → 하나의 url을 통해 하나의 app에 접근하기 위해 load balancer 필요
- Google Cloud 또는 A.W 또는 Azure와 같은 클라우드 플랫폼위에 있을 경우, native load balancer 사용 가능
- 여러 노드에 걸쳐 여러 pod이 있을 경우, 서비스를 통해 접근 할 수 있는 ip는 여러개
Imperative vs Declarative
Imperative
- step by step 지시
- yaml 을 정의하지 않아도 빠르게 object를 만들 수 있음
- functionality에 제한이 있고, 길고 복잡한 command가 될 수 있음
- 한번 실행되고 저장되지 않으므로 다른 사람이 해당 obj가 어떻게 생성되었는지 파악 어려움
- 현재의 configuration을 파악하고 있어야함
생성 command
$ kubectl run —image==nginx nginx
$ kubectl create deployment —image=nginx nginx
$ kubectl expose deployment nginx —port 80
업데이트 command
$ kubectl edit deployment nginx
$ kubectl scale deployment nginx —replicas=5
$ kubectl set image deployment nginx nginx=nginx:1.18
kubectl edit 은 K8s 메모리 상에 반영될 뿐 local yaml file에는 반영되지 않는다. local yaml file을 수정하고 replace 명령어를 쓰는게 나을 때도 있음. (kubectl replace -f nginx.yaml)
Declarative
- final destination 정의, 그 과정은 system이 수행
생성 command
$ kubectl apply -f nginx.yaml
$ kubectl apply -f /path/to/config-files # 한번에 여러 object apply
업데이트 command
$ kubectl apply -f nginx.yaml
Kubectl Apply Command
- local file을 통해 obect 생성
- local로 생성한 것과 비슷한 K8s memory 상에 object configuration 이 생성됨 ⇒ live configuration
- 상태를 저장하기 위한 항목이 추가됨
- local obj configuration file이 json format으로 변환되고, 최근 apply된 configuration 으로 저장됨
- → 이 내용 또한 live config 에 annotation으로 저장됨 (last-applied-configuration)
- imperative command 사용시 해당 내용이 생기지 않으므로, create/replace 등 imerative command와 apply 를 혼용해서 사용하지 않는 게 좋음
- 변경된 local file과 이 last updated config 의 차이를 통해 live obj config를 변경할 수 있음
[DevOps/Kubernetes] - [CKA] CKA 자격증 준비 자료 정리 2 (Scheduling)
'DevOps > Kubernetes' 카테고리의 다른 글
[CKA] CKA 자격증 준비 자료 정리 4 (Application Lifecycle Management) (0) | 2021.12.11 |
---|---|
[CKA] CKA 자격증 준비 자료 정리 3 (Logging & Monitoring) (0) | 2021.12.07 |
[CKA] CKA 자격증 준비 자료 정리 2 (Scheduling) (0) | 2021.12.06 |
[kubernetes] 쿠버네티스의 로깅 아키텍쳐와 python client를 통한 로그 수집 (0) | 2021.04.12 |
[kubernetes] 쿠버네티스 watch API 사용하기 (python) (0) | 2021.04.05 |