본문 바로가기
Kubernetes (k8s)

[k8s] Kubernetes Core Concept (쿠버네티스 핵심 개념)

by moveho 2023. 4. 4.

 

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

클러스터 내 변화를 수행하기 위한 모든 다양한 작업들의 중심 역할

  1. Authenticate User
  2. Validate Request
  3. Retrieve data
  4. Update ETCD
  5. Scheduler
  6. Kubelet

Kube API server work pattern

  • kubectl 사용시
    • kube-api 서버는 request를 인증/확인 후 etcd cluster에서 데이터를 검색해 반환
  • pod 생성시⇒ 모든 변화가 이러한 패턴을 따름
    1. api 서버는 pod object 생성 (노드에 할당하지 않고)
    2. etcd 서버에 pod이 생성되었음을 업데이트
    3. scheduler는 api 서버를 모니터링 하고 있으므로, 새로운 pod이 생겼음을 인지, 배포할 노드 확인
    4. api 서버는 etcd에 정보 업데이트
    5. api 서버가 해당 정보를 적합한 노드의 kubelet에 전달
    6. kubelet이 노드에 pod 생성, container runtime engine에 application image을 배포하도록 지시
    7. kubelet 은 api 서버에 상태 업데이트, api 서버는 data를 etcd 에 저장
    • kubeadm으로 설치했다면 kube-system 에 kube-apiserver-master
      • apiserver 정의 파일 ⇒ /etc/kubernetes/manifests/kube-apiserver.yaml
    • non-kubeadm 설치시/etc/systemd/system/kube-apiserver.service.yaml
    • ps -aux | grep kube-apiserver
      • master node process의 kube-apiserver 통해 실행중인 process 확인 및 effective option 확인
  • Kube API server pod
    • kubeadm으로 설치했다면 kube-system 에 kube-apiserver-master
      • apiserver 정의 파일 ⇒ /etc/kubernetes/manifests/kube-apiserver.yaml
    • non-kubeadm 설치시 => /etc/systemd/system/kube-apiserver.service.yaml
    • $ ps -aux | grep kube-apiserver
      • master node process의 kube-apiserver 통해 실행중인 process 확인 및 effective option 확인

Kube Controller Manager

  • 시스템 내 다양한 구성 요소의 상태를 지속적으로 모니터링하고, 전체 시스템을 원하는 상태로 만들기 위해 작동하는 프로세스
  • 여러 controller가 하나의 프로세스로 패키징되어 실행되는 형태 ⇒ Kube Controller Manager
    • Node Controller, Namespace-Controller, Replication-Controller ... 등등

Node Controller

  • 노드들의 상태를 모니터링, application이 계속 실행될 수 있도록 필요한 조치를 수행
  • —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
  • non-kubeadm 설치시/etc/systemd/system/kube-controller-manager.service
  • ps -aux | grep kube-controller-manag

Kube Scheduler

  • pod이 어떤 노드로 갈 것인지 결정하는 역할 (실제로 노드에 pod을 배치하는 것X → kubelet)
  • 노드 선정 방식
    1. pod이 요구하는 resource를 보고 filtering
    2. pod을 배치하고 해당 노드에 더 많은 resource가 남는 경우를 상위로 rank 지정

Kube Scheduler pod

  • kube-scheduler 라는 이름으로 위와 동일

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
  • $ kubectl get all
    • deployment, rc, pod 모두 보고 싶을 때

-Imperative TIP-

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

apiVersion: v1
kind: Namespace
metadata:
  name: dev
  • 또는 $ kubectl create namespace dev
  • $ kubectl create -f pod-def.yaml —namespace=dev
    • 또는 yaml 의 metadata.namespace 지정
  • Namespace switch
    • $ kubectl config set-context $(kubectl config current-context) —namespace=dev
      • default namespace 변경
  • Resource Quota
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 사용 가능

Imperative vs Declarative

Imperative

  • step by step 지시
  • yaml 을 정의하지 않아도 빠르게 object를 만들 수 있음
  • functionality에 제한이 있고, 길고 복잡한 command가 될 수 있음
  • 한번 실행되고 저장되지 않으므로 다른 사람이 해당 obj가 어떻게 생성되었는지 파악 어려움
  • 현재의 configuration을 파악하고 있어야함
  • kubectl
    • create
      • $ kubectl run —image==nginx nginx
      • $ kubectl create deployment —image=nginx nginx
      • $ kubectl expose deployment nginx —port 80
    • update
      • $ kubectl edit deployment nginx
        • yaml 로 생성하고 이렇게 수정하게 되면, live로 변경이 반영되지만, local yaml file에는 반영되지 않음 (쿠버네티스 메모리 상에 반영될 뿐)
        • → 따라서 local yaml을 수정하고 replace 명령어를 쓰는게 나을 때도 있음
      • $ kubectl scale deployment nginx —replicas=5
      • $ kubectl set image deployment nginx nginx=nginx:1.18
    • $ kubectl create/replace/delete -f nginx.yaml

Declarative

  • final destination 정의, 그 과정은 system이 수행
  • kubectl
    • create
      • $ kubectl apply -f nginx.yaml
      • $ kubectl apply -f /path/to/config-files
        • 한번에 여러 object apply
    • update
      • $ kubectl apply -f nginx.yaml

Kubectl Apply Command

  1. local file을 통해 obect가 생성
  2. local로 생성한 것과 비슷한 kube memory 상에 object configuration 이 생성됨 ⇒ live configuration
    • 상태를 저장하기 위한 항목이 추가됨
  3. 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를 변경할 수 있음

'Kubernetes (k8s)' 카테고리의 다른 글

[k8s] Security  (2) 2023.04.10
[k8s] Cluster Maintenance  (0) 2023.04.08
[k8s] Application Lifecycle Management  (0) 2023.04.07
[k8s] kubernetes Scheduling  (0) 2023.04.05
[k8s-Kubecolor] Colorize kubectl  (8) 2023.04.01

댓글