티스토리 뷰

반응형

Kubernetes Object

가장 기본적인 구성단위

상태를 관리하는 역할

 

가장 기본적인 오브젝트

Pod, Service, Volume, Namespace

 

Pod = 컨테이너를 담아두는 통이다.

Service = Pod로 연결을 하기 위해서 만들어주는 것

Volume = 말 그대로 용량

Namespace = namespace

 

오브젝트의 Spec, Status 필드

Spec : 정의된 상태 - 관리자가 원하는 상태가 들어 있다.

Pod는 컨테이너를 담아두는 오브젝트인데, Spec 안에는 Pod 안에 들어 있는 컨테이너의 이미지가 뭔지, port가 뭔지, 이름은 뭔지, 명령어는 뭔지, 해당하는 목적에 대한 상태가 있다.

그런 옵션들을 정의해두게 된다.

 

Status : 현재 상태

위에서 정의한 Spec으로 만들어진 것들이 현재 상태이다.

 

그러면 당연히, Spec 필드하고, Status 필드는 같아야 한다.

그런데 어떤 장애에 대해서, Spec 필드하고 Status 필드가 달라지는 경우가 있다.

그럴 때 컨트롤러가 활약한다.

 

Kubernetes Controller

마스터 노드의 구성요소이다.

클러스터의 상태를 관찰하고, 필요한 경우에 오브젝트를 생성, 변경을 요청하는 역할

각 컨트롤러는 현재 상태를 정의된 상태에 가깝게(=같게) 유지하려는 특징이 있다.

컨트롤러 유형 : Deployment, Replicaset, Daemonset, Job, CronJob 등

 

Controller Cycle

Current State(현재 상태)를 관찰한다.

상태 변동(Current State과 Desired State이 다르다면)이 된다면

Current State를 Desired State로 update 한다.

 

다시 돌아간다.

 

Auto Healing

Controller에서 Pod1이 삭제 되었을 때, Pod1을 다시 살려낸다.

 

Controller에서 Node 1안에 Pod1이 있는데, Node1이 없어졌을 때, Node 2번에 Pod1을 옮겨서 다시 만들어준다.

 

Auto Scaling

컨트롤러는 Pod1이 리소스 부하가 올라가면 Pod2를 만들고, 그 이후에 리소스 부하가 내려가면 다시 Pod1만 남긴다.

 

Update & Rollback

전체 pod를 v1에서 v2로 업데이트하거나, v2에서 v1으로 Rollback 할 수 있다.

 

Job

작업을 하게 되면, 컨트롤러가 Pod1을 만드는 작업을 자동으로 실행하고,

작업이 종료되면 자동으로 Pod1을 삭제한다.

 

YAML 구조

apiVersion: 연결할 API server의 버전 - 버전에 따라 속해 있는 kind와 같은 오브젝트들이 다양하게 있다.

내가 사용하고 싶은 컨트롤러나 오브젝트 버전에 따라서 다양하게 달라진다.


kind : 리소스의 유형

yaml파일이 발생시키는 오브젝트의 종류


metadata : 리소스가 기본 정보를 갖고 있는 필드

이 Pod의 이름, 스티커를 뭘 달고 있는지 등

name, label, namespace 등


spec : 배포되는 리소스의 원하는 상태

사용자가 이 Pod에게 원하는 것

 

파일을 만드는 구조

 

kubectl

  • Kubernetes에 명령을 내리는 CLI(Command Line Interface)
  • kubectl명령 구조 : kubectl[COMMAND] [TYPE] [NAME] [FLAGS]
  • kubectl get/create/delete/edit / node(생성할 것, 지울 것, 등등의 오브젝트 종류) / master만 보고 싶으면 이름 / 그리고 보여주는 형태나 이런 걸 바꾸는 옵션이 있다.
  • 오브젝트와 컨트롤러를 생성, 수정, 삭제

yaml파일은 무조건 띄어쓰기가 맞아야 제대로 들어간다.

양식을 지킨다.

 

Pod

Kubernetes의 가장 작은, 최소 단위 Object

컨테이너를 배포하는 가장 작은 단위, 컨테이너만 만들 수는 없다.

Pod에 담아서 관리를 하는 형태로 만든다.

Pod 안에는 다수의 컨테이너가 존재할 수 있다.

그러나 특별한 이유가 없는 이상, Pod 하나에 컨테이너 하나만 넣는 걸 권장한다.

많아지면 느려지기 때문.
볼륨을 구성하면, 컨테이너가 데이터를 공유하는 상태로 사용할 수 있다.
네트워크와 볼륨을 공유

 

컨테이너 2개를 하려면 yaml 파일에 

name부터 ports까지 전부 하나 더 정의해준다.

해당하는 걸 pod.yaml이라고 하자

 

Pod - Kubectl

yaml 파일을 사용하여 Pod를 생성하는 명령어를 만들 수 있다.

kubectl create -f pod.yaml
kubectl create -f <yaml파일명>

kubectl명령으로 Pod를 생성하는 명령어

kubectl run pod \--image=nginx:1.14.0 \--port=80
kubectl run <pod명> \--image=<이미지명:버전> \--port=<포트번호>

 

Kubernetes Object -Namespace

단일 클러스터 내 리소스 그룹 격리를 위한 오브젝트

 

사용자가 여러 팀으로 구성하는 경우, 프로젝트를 진행함에 있어 환경을 분리해야 하는 경우에 사용된다.

물리적으로는 장비가 1개인데, 논리적으로 분할을 시켜서 마치 2개인 것처럼 사용한다.

 

하나의 클러스터에는 구성원 (master, node 등등이 있을 수 있는데)

Service 1 에 pod1과 pod2

Service 2에 pod1과 pod2 로 따로 만들 수 있다.

 

권한 관리를 해서 , 각 namespace 사이에 간섭 불가능하게 만들 수도 있다.

 

ReplicaSet Controller

컨트롤러를 Pod 안에 담아서 관리를 하는데,

Pod는 autoscaling이나 이런 기능이 하나도 없이, 컨테이너만 만들어서 구동시킨다.

 

ReplicaSet은 Pod의 개수를 유지

yaml을 작성할 때, Spec: 에 replicas:3 와 같이 개수를 지정하면, 그 개수에 따라 유지된다.

 

리플리카 셋을 만들면, Pod를 3개를 자동으로 만들어준다.

apiVersion: v1
kind: ReplicaSet
metadata:
	name:rep1
spec:
	replicas : 3

 

그래서 리플리카 셋으로 3개를 만들고, 3번째 pod가 사라지면,

그러면 Pod4가 새로 생성된다.

총 3개가 된다.

이때는 앞에

컨테이너 이미지, pod 설정 등이 나머지 pod와 동일하다.

 

Template

파드를 생성하기 위한 명세

Delpoyment, ReplicaSet과 같은 Controller의 yaml 내용에 포함된다.

Template에는 Pod 세부사항을 결정한다.

 

apiVersion: apps/v1
kind: Deployment
metadata:
	name:nginx-deployment
template:
	metadata:
    labels:
   	app:nginx
spec:
	....

 

Deployment Controller

Deployment는 ReplicaSet을 관리하며, 애플리케이션의 배포를 더욱 세밀하게 관리

세밀하게 관리 - 업데이트와 롤백 기능을 가지고 있다.

 

Deployment에는 Replicas :3, template: pod, image가 들어 있으면

해당하는 Replicaset이 만들어지고, Pod의 개수가 만들어진다.

 

만약에 Replicaset이 사라지면, Deployment에 의해서 새로운 Replicaset이 만들어진다.

 

Deployment Update

운영중인 서비스의 업데이트시 재배포를 관리한다.

 

2가지 재배포 방식
–Recreate : 현재 운영중인 Pod들을 삭제하고, 업데이트 된 Pod들을 생성합니다. 이 방식은 Downtime 이 발생하기 때문에 실시간으로 사용해야 한다면 권장하는 방식은 아닙니다.

 

만약에 image가 1.7.9에서 1.9.1 같이 업데이트 한다고 해보자.

그러면 Replicaset 1은 사라지고, Replicaset 2가 새로 생기면서, 이미지는 1.9.1로 다시 깔린다.

 

이 방식으로 업데이트를 하려면, v1 이 있는 기존 Pod를 전부 지우고, v2 pod 를 전부 새로 만들어준다.

그 동안에는 Downtime(사용자가 접근하지 못하는 시간)이 발생한다.

 

 

–Rolling Update : 먼저 업데이트 된 Pod를 하나 생성하고, 구버전의 Pod를 삭제하여, Downtime 없이 업데이트가 가능합니다.

 

Downtime이 발생하지 않도록, Pod를 순차적으로 만들고 삭제하고를 반복하여 업데이트한다.

 

Pod 하나만으로 운영하지 않는다.

똑같은 역할을 하는 Deployment 개수만큼 여분이 있어야 Rolling update를 할 수 있다.

그렇기에 여분이 있어야 무중단 업데이트를 할 수 있다.

 

Deployment Rollback

Deployment는 삭제 되지 않은 이전 버전의 ReplicaSet을 10개까지 저장한다.

revisionHistoryLimit 속성을 설정하면 개수를 변경 가능하다.

 

저장된 이전 버전의 ReplicaSet을 활용하여 Rollback한다.

 

Deployment의 yaml에서 revisionHistoryLimit :1 하면, 1개만 남겨두겠다는 의미

spec:
replicas :1
	strategy:
    type : Recreate
    RevisionHistoryLimit : 1

Deployment -Kubectl

yaml파일을 사용하여 생성 하는 명령어
–kubectl create -f deployment.yaml
–kubectl create -f <yaml파일명>

•kubectl명령으로 생성하는 명령어
–kubectl create deployment dp\--image=nginx:1.14.0 \--replicas=3
–kubectl create deployment <이름> \--image=<이미지명:버전> \--replicas=<Pod수>

 

pod scale도 조절해줄 수 있다.

 

Deployment -Kubectl

Deployment로 생성된 Pod 수를 조정(Scale)하는 명령어
–kubectl scale deployment/dp--replicas=3
–kubectl scale deployment/<Deployment명> --replicas=<조정할 Pod 수>

•ReplicaSet으로 생성된 Pod 수를 조정(Scale)하는 명령어
–kubectl scale rs/rs--replicas=3
–kubectl scale rs/<ReplicaSet명> --replicas=<조정할 Pod 수>

 

Service - Kubectl

 

Pod는 언제든지 공격이나 장애에 의해서 Ip나 이런 게 변경될 수 있다.

고정된 주소를 이용하게끔 설정해준다.

 

기존적으로 Pod에 접근하기 위해서는 Ip가 필요하다.

 

kubectl run pod --image:nginx

만들어진 것에서 describe를 보면, IP가 있지만 이건 고정된 게 아니다.

따라서 고정된 주소를 서비스에 전달을 하면, 해당하는 주소를 Pod에 부요해서 Pod에서 실행중인 애플리케이션을 네트워크 서비스로 노출시킨다.

 

Label과 Selector를 이용해서 연결한다. 

 

Label : Pod와 같은 Object에 첨부된 키와 값 쌍

apiVersion : v1
kind: Pod
metadata:
	name: label
    labels:
    	environment: production
        app:nginx
        
apiVersion : v1
kind: Service
metadata:
	name: service1
	selector
        app:nginx

키 값과 동일한 형태로 라벨 셀렉터가 있다면 연결된다.

 

또, 연결 조건이 필요하다. 포트가 맞아야 되기 때문에, 포트 포워딩을 해줘야 한다.

Pod1 = 80포트, 서비스 = 9090 포트면, 연결해줘야 한다.

 

즉, 셀렉터 라벨 매칭, 포트포워딩이 기본적인 조건이다.

annotation

 

Object를 식별하고 선택하는 데에는 사용되지 않으나 참조할 만한 내용들을 Label처럼 첨부

 

Service 유형

ClusterIP(default)
–Service가 기본적으로 갖고있는 ClusterIP를 활용하는 방식입니다.
•NodePort
–모든 Node에 Port를 할당하여 접근하는 방식입니다.
•Load Balancer
–Load Balancer Plugin 을 설치하여 접근하는 방식입니다

 

ClusterIP(default)

클러스터가 있고, 디플로이먼트가 있다.

replicas:3

template:

Label:app=test

port:8080

 

이때 사용자는 하드에 접근하고 싶다.

고정 주소를 사용해서 접근하게 된다.

 

클러스터 IP에 9090으로 주면, 8080을 가진 pod들로 접속하라는 서비스를 만든다.

 

만약 똑같은 조건으로 8080으로 같은 pod들이 있으면?

그러면 트래픽을 Roundrobin으로 전달한다.

 

즉, 로드밸런서 역할을 한다.

 

다만 클러스터 IP 타입은, 내부 IP이므로 외부에서는 접근이 불가능하다.

서비스 이름 자체도 클러스터 IP이고, 클러스터 IP를 만들어낸다.

 

ClusterIP YAML

apiVersion: v1
kind: Service
metadata:
	name: svc1
spec:
	selector:
    app: pod
  ports:
  	port: 9090
    targetPort: 8080
  type: ClusterIP
  
  
apiVersion: v1
kind: Pod
metadata:
	name:pod1
    labels:
    app:pod
spec:
containers:
	name:container
    image:cluster/app
    ports:
      containerPort:8080

 

ClusterIP-kubectl

ClusterIP유형의 Service를 생성하는 명령어
–kubectlcreate service clusteripclip --tcp=8080:80
–kubectlcreate service clusterip<Service명> --tcp=<포트:타켓포트>

ClusterIP유형의 Service를 nginx라는 Deployment와 연결하여 생성하는 명령어
–kubectl expose deployment nginx \--port=8080 \--target-port=80 \--type=ClusterIP
–kubectl expose <연결할오브젝트> <오브젝트명> \--port=<포트>\--target-port=<타겟포트>\--type=ClusterIP

 

 

NodePort

 

각 Node에 동일한 포트 번호를 부여한다.

이건 외부에서 접근 가능하다.

 

워커 노드, 마스터 노드에 포트를 하나씩 뚫어준다.

 

포트 넘버를 지정하지 않으면 랜덤하게 3만~32767번으로 할당된다.

 

해당 Node의 IP와 Node에 할당된 포트 번호 30010으로 접속을 하면, 해당 서비스에 연결된다.

Service는 자신에게 연결 되어 있는 Pod에 트래픽을 전달한다.

 

apiVersion: v1
kind: Service
metadata:
	name: svc2
spec:
	selector:
    app: pd
  ports:
  	port:9090
    targetPort: 8080
    nodePort: 30010
  type: NodePort
  externalTrafficPolicy: Local

 

NodePort유형의 Service를 생성하는 명령어
–kubectlcreate service nodeportnp --tcp=8080:80
–kubectlcreate service nodeport<Service명> --tcp=<포트:타켓포트>

NodePort유형의 Service를 nginx라는 Deployment와 연결하여 생성하는 명령어
–kubectl expose deployment nginx \--port=8080 \--target-port=80 \--type=NodePort
–kubectl expose <연결할오브젝트> <오브젝트명> \--port=<포트>\--target-port=<타겟포트>\--type=NodePort

 

Load Balancer 

AWS -EKS

Azure-aks

gcp-gke

를 쓰면, external IP를 자동으로 할당해준다.

 

Nodeport는 Load Balancer와 같이 쓰게 된다.

온전한 Load Balancer 의 기능을 사용하려면, 추가 플러그인 설치가 필요
또는 로드밸런서를 지원해주는 클라우드 환경에서 사용가능

 

apiVersion: v1
kind: Service
metadata:
	name: svc2
spec:
	selector:
    app: pㅐd
  ports:
  	port:9090
    targetPort: 8080
  type: LoadBalancer
LoadBalancer유형의 Service를 생성하는 명령어
–kubectlcreate service loadbalancerlb--tcp=5678:8080
–kubectlcreate service loadbalancer<Service명> --tcp=<포트:타켓포트>

LoadBalancer유형의 Service를 nginx라는 Deployment와 연결하여 생성하는 명령어
–kubectl expose deployment nginx \--port=8080 \--target-port=80 \--type=LoadBalancer
–kubectl expose <연결할오브젝트> <오브젝트명> \--port=<포트>\--target-port=<타겟포트>\--type=LoadBalancer

 

Kubernetes DNS

Kubernets는 Pod와 Service에 DNS 레코드를 생성합니다.
IP 대신, 이 DNS를 활용하여 접근 할수 있습니다.

 

FQDN으로 구성이 되어서, 서비스 이름과 

 

ns1 이라는 Namespace 안에
ip가 10.10.10.10 이고,
pod1 이라는 Pod의 FQDN
구성은 다음과 같습니다.

 

svc1.ns1.svc.cluster.local

10-10-10-10.ns1.pod.cluster.local

 

IP 기반을 벗어나기 위해서 사용하는데, IP 기반이 되어버렸다.

그래서 DNS YAML에서 다양하게 대체할 수 있다.

 

hostname, subdomain 설정 도메인
• hn1.sd1.ns1.svc.cluster.local
• Hostname명.Subdomain명.Namespace명.svc.cluster.local

 

spec:

hostname:hn1

subdomain:sd1

 

Volume

쿠버네티스에서 volume은 Pod 컨테이너에서 접근할 수 있는 디렉터리라고 생각할 수 있습니다.

 

Volume 1의 하위에 Container 1과 Container 2가 존재해서 하위로 들어갈 수 있다.

Volume의 유형은 EmptyDIr, HostPath, PV/PVC가 있다.

 

Emptydir

Pod가 생성될 때 함께 생성되고,

Pod가 삭제될 때 함께 삭제되는 임시 Volume

 

Volume 1 - type: Emptydir

 

Emptydir YAML

apiVersion: v1
kind: Pod
metadata:
	name: test-pd

spec:
	containers:
    -image: k8s.gcr.io/test-webserver
    name: test-container
    volumeMounts:
    -mountPath: /cache
    name: cache-volume
  volumes:
   -name: cache-volume
    emptyDir :{}

 

임시 볼륨이기 때문에 중요한 데이터를 저장하지 않는다.

이 볼륨을 노드로 뺄 수가 있다.

 

HostPath

호스트 노드의 경로를 Pod에 마운트하여 함께 사용하는 유형의 Volume

Pod가 사용할 볼륨

 

Pod가 손상되거나 삭제되도 불륨은 삭제되지 않는다.

 

Pod1 안에 container 1이 있고,

Pod2 안에 container 2가 있다고 하면,

Node 안에 Volume이 있어서 Pod1과 Pod2에 연결된다.

 

HostPath YAML

 

aoiVersion: v1
kind: Pod
metadata:
	name: test-pd

spec:
	containers:
    -image: k8s.gcr.io/test-webserver
    name: test-container
    volumeMounts:
    -mountPath: /test-pd
    name: test-volume
  volumes:
   -name: test-volume
   hostPath:
    path: /data

 

HostPath에서 Pod의 재생성 시, 

Node 1에 있던 Pod가 Node2로 옮겨간다.

 

워커 노드 1번이 꽉 찼고, Pod가 옮겨가면, 이 볼륨은 노드에 있기 때문에 다시 Pod를 옮겨줘야 한다.

HostPath - Node의 장애시,

볼륨을 제외하고, Pod1과 Pod2만 Node2로 옮겨간다.

 

그러면 볼륨하고 Pod를 마운트 하는데 수동성으로 해야 한다.

 

그래서 우리는 PV라는 볼륨을 사용한다.

 

PV(Persistent Volume)

PV는 pod와는 별도로 관리

클러스터 내부에서 Object처럼 관리 가능

 

Pod에 직접 연결하지 않고, PVC를 통해서 사용

클라우드 서비스에서 제공해주는 Volume 서비스를 이용할 수도 있고,

사설에 직접 구축 되어 있는 스토리지를 쓸 수도 있다.

 

PVC가 중간 다리 역할을 한다.

hostpath도 사용 가능

 

Pod와 PV의 직접 연결이 아니라,

Pod1 - PVC - PV로 연결한다.

 

볼륨을 Local 볼륨(5G) 사용
접근 모드 : RWO
다양한 접근모드
–RWO : 읽기,쓰기 / 하나의 Pod만 연결
–ROM : 읽기만 / 다수의 Pod 연결
–RWM : 읽기, 쓰기 / 다수의 Pod 연결

 

PV YAML

apiVersion : v1
kind : PersistentVolume
metadata:
	name:pv1
spec:
	capacity:
    storage: 5G
    accessModes:
    - ReadWriteOnce
    local:
    	path: /node1

 

PVC YAML

볼륨 2G 요청

접근 모드 RWO

 

요청과 접근모드에 알맞은 PV와 연결

apiVersion : v1
kind : PersistentVolumeClaim
metadata:
	name:pvc2
spec:
    accessModes:
    - ReadWriteOnce
    resources:
    	requests:
    	storage: 2G

accessMode는 앞에 있던 PV에서 내가 연결할 것과 똑같이 해줘야 

 

5G 중에 2G만 할당해서 쓴다.

 

SVC는 Pod와 유저를 연결해주는 거라면,

Pod는 PVC를 사용해서 연결한다.

 

Storage Class - YAML

자동으로 YAML 만들어서 배포하게 해준다.

PVC를 자동으로 만들어서 가능하다.

이걸 Storage Class가 있어야 가능하다.

 

AWS 의 EBS를 사용하는 StorageClass
Azure 의 Disk를 사용하는 StorageClass

apiVersion : storage.k8s.io/v1
kind : StorageClass
metadata:
	name:sc-aws-ebs
provisioner : kubernetes.io/aws-ebs
parameters:
    type:gp2
    fsType:ext4
apiVersion : storage.k8s.io/v1
kind : StorageClass
metadata:
	name:sc-azure-disk
provisioner : kubernetes.io/azure-disk
parameters:
	skuName : Standard_LRS
    location : koreacentral
   	storageAccuount : azure_storage_account_name

 

StorageClass에는 프로비저너가 있다.

제공자가 누구인지(aws-ebs)

등등 여러 파라미터가 있는데

 

이렇게 설정을 해놓고 Storage Class를 선언하면, PV로 만들 수 있다고 선언하는 것이고,

마지막에 만드는 건 PVC이다.

 

그러면 PVC YAML의 마지막에 이렇게 써주면 된다.

 

StorageClassName : sc-aws-ebs

 

그러면 이 연결된 PVC는 자기랑 연결된 PV를 구성할 때, EBS로 해서 만들어진다.

 

그리고 Pod랑도 연결해준다.

 

 

반응형