Kubernetes #3

임상규·2023년 12월 12일
1

Kubernetes

목록 보기
3/19

Kubernetes Object

  • kubernetes 시스템 내에서 영속성을 가지는 오브젝트
  • 클러스터의 의도한 상태를 나타내기 위해 오브젝트를 이용
  • status 필드는 kubernetes 시스템과 컴포넌트에 의한 오브젝트의 현재 상태를 나타내며, kubernetes control plane은 이 status를 사용자가 의도한 상태와 일치시키기 위해
    끊임없이 / 능동적으로 관리

의도한 상태

  • 오브젝트에 대한 기본적인 정보와 의도한 상태를 기술한 오브젝트 spec을 제시
  • 오브젝트 생성을 위한 kubernetes API 요청은 JSON 형식 정보를 포함
  • 대부분의 경우 정보를 .yaml 파일로 kubectl에 제공
  • kubectl은 API 요청이 이루어질 때, JSON 형식으로 정보를 변환

YAML의 기본 구조

  • apiVersion (string)
  • kind (string)
  • metadata (dictionary)
  • spec (dictionary)
  • status (dictionary)
    • 오브젝트의 실제 상태를 기술
    • 쿠버네티스 control plane은 오브젝트의 실제 상태를 의도한 상태에 일치시키는 방향으로 동작
apiVersion: apps/v1
kind: Deployment // 파스칼 표기법
metadata:
  name: nginx-deployment
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 2
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80

$ kubectl apply -f deployment.yaml

kubectl apply

  • 선언적 형태 (Declarative)
  • 오브젝트가 없으면 create하고, 있으면 replace 하는 등 더 유연하고 지능적으로 동작

kubectl create, replace ...

  • 명령적 형태 (Imperative)
  • 오브젝트가 없으면 create하고, 있으면 replace하는 등 더 유연하고 지능적으로 동작
$ kubectl run --image=nginx nginx

Node (Worker node)

  • 워크로드가 돌아가는 컨테이너를 배치하는 물리(가상)머신
  • Control plane에 의해 관리
  • 일반적인 운영환경에서는 multi node로 운영
  • 각 노드는 kubelet / container-runtime / kube-proxy가 포함

Node의 상태

  • node의 condition 필드에서 확인 가능
  • Ready, DiskPressure, MemoryPressure, PIDPressure, NetworkUnavailable

Node 정보 확인

alias k=kubectl

$ k get node
$ k get node -o wide
$ k get node <node명> -o yaml
$ k describe node <node명>

Node cordon / drain

cordon: 현재 노드에 배포된 Pod은 그대로 유지하면서, 추가적인 Pod의 배포를 제한하는 명령어
해제 방법: uncordon

drain: Pod를 더이상 사용하지 않을 경우

$ k cordon <node명>
$ k uncordon <node명>
$ k drain <node명> 
$ k drain <node명> --ignore-daemonsets // daemonset으로 생성된 Pod일 경우

Namespace

  • 동일 물리 클러스터를 기반으로 하는 복수의 가상 클러스터를 지원하는 개념
  • 클러스터를 논리적으로 나누고 액세스를 제한하여 리소스를 생성, 관리
  • 논리적으로 구분이 되지만 격리가 되는 것은 아님. (격리를 위해서는 network policy와 같은 다른 오브젝트를 추가로 사용 해야함)

Namespace 예시

  • 기본 namespace
    • default: pod, deployment가 생성될 때 기본적으로 생성되는 namespace
    • kube-system: DNS, kube-proxy나 kubernetes dashboard 처럼 시스템 제어 리소스가 사용하는 namespace
    • kube-public: 전체 클러스터에 대한 가시성을 제공하는 경우 사용 (일반적으로 사용X)
  • custom namespace
    • prometheus, argo, istio 등등의 시스템 관련 솔루션들은 독자 namespace를 할당
    • microservice별로 namespace를 할당하여 논리적으로 분리
# namespace 생성 및 확인
$ k create ns my-app
$ k get ns --show-labels
$ k delete ns my-app

# 특정 namespace내에 있는 자원 확인
$ k get pod -n kube-system
$ k get all -n kube-system

# 모든 namespace내의 자원을 확인
$ k get all -A

create vs apply

create: 단순히 오브젝트를 생성하는것이라 트래킹이 제한
apply: yaml 파일을 생성 후 yaml파일로 오브젝트를 생성, yaml로 트래킹

namespace에 종속된 리소스 확인

# namespace에 종속된 리소스 확인
$ kubectl api-resources --namespaced=true

# namespace에 종속되지 않는 글로벌 서비스 확인
$ kubectl api-resources -namespaced=false

Pod

  • 최소단위 쿠버네티스 객체
  • docker 컨테이너와는 조금 다르게, pod는 하나 이상의 컨테이너를 포함가능
  • 애플리케이션 컨테이너(하나 또는 다수), 스토리지, 네트워크 등의 정보를 포함

Pod의 디자인 패턴

같은 IP 주소를 가지고 localhost 통신

  • Sidecar: Pod안의 App container를 확장하고 향상시키며 개선시키는 역할을 하는 컨테이너를 Sidecar라고 하며, App container와 같은 파일시스템을 공유하는 로그수집기가 사이드카 컨테이너가 되는 구조
  • Adapter: App container의 출력을 표준화
  • Ambassador: App container의 네트워크 연결을 전담하는 프록시 컨테이너를 두는 패턴

pod Yaml 구조

포드 할당

apiVersion:v1
kind: Pod
metadata:
  name: myapp-prod
  namespace: app
  labels:
    app: myapp
    type: front-end
spec:
  containers:
    - name: nginx-container
      image: nginx
      ports:
      - containerports: 8080

멀티 컨테이너

apiVersion:v1
kind: Pod
metadata:
  name: myapp2-prod
  namespace: app
  labels:
    app: myapp
    type: front-end
spec:
  containers:
    - name: nginx-container
      image: nginx
    - name: redis-container
      image: redis:3.2

Pod 생성 및 확인

# pod 생성 및 확인
$ kubectl run nginx --image=nginx
$ kubectl run nginx2 --image=nginx --dry-run=client -o yaml > pod.yaml
$ k apply -f pod.yaml
$ k get pod
$ k get pod -o wide

# pod의 로그 확인
$ k logs nginx

# pod에 라벨 할당
$ k label pods nginx app=front-end
$ k get pod --show-labels

Replicaset

  • pod의 레플리카를 생성하고 지정한 pod수를 유지하는 리소스
  • 기존의 replicaset controller에서 replicaset으로 변경
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: myapp-replicaset
  labels:
    app: myapp
    type: front-end
spec:
  template:
    metadata: // pod의 metadata 이하를 그대로 가져옴
      name: myapp-replicaset
      labels:
        app: myapp
        type: front-end
    spec:
    containers:
      - name: nginx-container
        image: nginx
  replicas: 3
  selector: // 어떤 파드가 해당 replicaset에 할당되는지를 나타냄
    matchLabels:
      type: front-end

replicaset 생성 및 확인

# replicaset 생성
$ kubectl apply -f test-replicaset.yaml
$ k get rs
$ k get rs -o wide

# replicaset와 연결된 pod 확인
$ k get pod -l type=front-end --show-labels

# 자동 복구 확인
$ k delete pod <pod명>
$ k get pod

replicaset 스케일링

$ k scale replicaset myapp-replicaset --replicas 6

$ k get rs
$ k get pod

Deployment

  • 복제된(replicated) 애플리케이션(Pod)을 관리하는 오브젝트
  • 롤링 업데이트나 롤백 등을 구현하는 리소스

deployment YAML 구조

  • replicaset과 유사
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-deployment
  labels:
    app: myapp
    type: front-end
spec:
  template:
    metadata: 
      name: myapp-pod
      labels:
        app: myapp
        type: front-end
    spec:
    containers:
      - name: nginx-container
        image: nginx:1.22
  replicas: 3
  strategy:
    type: RollingUpdate
  selector: 
    matchLabels:
      type: front-end

deployment의 배포 전략

  • recreate: 모든 파드를 삭제하고 다시 생성, 다운타임 발생, 하지만 정해진 파드 개수 외에 추가 리소스 활용 안하고, 전환이 빠르며 비용 효율적
  • rollingupdate: 하나씩, 몇개씩 업데이트 하여 다운타임 발생 x, 하지만 일시적으로 동시에 2가지 버전이 서버스 됨
    • maxUnavailable: 업데이트 중 동시에 정지할 수 있는 최대 파드수
    • maxSurge: 업데이트 중 동시에 생성할 수 있는 최대 파드수

deployment 생성 및 확인

# deployment 생성
$ kubectl apply -f test-deploy.yaml --record
// --record: 어떤 명령어를 실행하고 업데이트를 하였는지 이력을 저장, 롤백 시 참고 가능
$ k get deploy
$ k describe deploy myapp-deployment
$ k get rs
$ k get pod

deployment 업데이트

# deployment 롤링 업데이트
$ k set image deployment myapp-deployment nginx-container=nginx:1.23 --record
$ k rollout status deployment myapp-deployment
$ k get deploy
$ k get rs
$ k get pod

deployment rollback

# deployment 변경 이력 확인
$ k rollout history deployment myapp-deployment
$ k rollout history deployment myapp-deployment --revision 4

# deployment 변경 롤백
$ k rollout undo deployment myapp-deployment --to-revision 1

# 롤백 확인
$ k get replicasets

Daemonset

  • 클러스터의 각 노드에 pod를 하나씩 띄울때 사용하는 오브젝트
  • 로그수집기를 실행하거나 노드를 모니터링 하는 모니터링 하는 모니터링용 데몬 등 클러스터 전체에 항상 실행시켜 두어야 하는 pod를 실행하는데 사용
  • 가장 대표적인 daemonset의 예: kube-proxy, fluent-bit ..

daemonset YAML 구조

  • replicaset과 유사
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: monitoring-daemon
spec:
  template:
    metadata: 
      labels:
        app: monitoring-agent
    spec:
    containers:
      - name: monitoring-agent
        image: nginx
  selector: 
    matchLabels:
      app: monitoring-agent

daemonset 업데이트

# daemonset 생성
$ k apply -f test-daemonset.yaml
$ k get ds
$ k get pod -A -l app=monitoring-agent -o wide

# daemonset 재시작
$ k rollout restart daemonset/monitoring-daemon

Service

  • Pod 집합과 같은 애플리케이션에 접근 경로나 Service Discovery를 제공
  • Pod를 외부 네트워크에 연결하고, pod로의 연결을 로드밸런싱하는 네트워크 오브젝트
  • 하나의 Microservice 단위
  • 서비스이름.네임스페이스.svc.cluster.local이라는 FQDN이 생성

Service Type

Service: ClusterIP

  • kubernetes 클러스터 내부에서만 통신이 가능한 internal network 가상 IP가 할당
  • service - pod 간 통신은 kube-proxy가 담당
  • 서비스 디버깅이나 테스트시 보통 사용

Service: Nodeport

  • NAT를 이용해 클러스터 내 Node의 고정된 port를 갖는 IP로 service를 노출
  • 외부 트래픽을 서비스에 전달하는 가장 기본적인 방법
  • 클러스터 외부에서 접근은 NodeIP:NodePort
  • Port 사용 범위: 30000-32767

Service: Loadbalancer

  • 클라우드 공급자의 로드밸런서를 이용해 service를 외부로 노출
  • 외부 로드밸런서를 사용하기 때문에 SPOF에 강함
  • L4(TCP) or L7(HTTP) 레이어를 통해 service 노출

Service Type YAML 구조

apiVersion: v1
kind: Service
metadata:
  name: back-end
  
spec:
  type: ClusterIP
  ports:
    - targetPort: 80
      port: 80
  selector:
    app: myapp
    type: back-end
apiVersion: v1
kind: Service
metadata:
  name: myapp-service
  
spec:
  type: NodePort
  port:
    - targetPort: 80
      port: 80
      NodePort: 30008
  selector:
    app: myapp
    type: front-end
apiVersion: v1
kind: Service
metadata:
  name: mytest-service
  
spec:
  type: Loadbalancer
  ports:
    - targetPort: 80
      port: 80
      NodePort: 30008
  selector:
    app: myapp
    type: proxy

Service 생성

# deployment 생성
$ k create deployment nginx-svc --image=nginx
$ k get deploy

# Node Port 서비스로 노출
$ k expose deployment/nginx-svc --type="NodePort" --port 80

# 서비스 확인
$ k get svc -o wide
$ k get pod --show-labels

# 서비스 호출
$ k run curl -it --rm --image curlimages/curl -- sh
$ curl nginx-svc(:80)
$ curl <Node명>:<NodePort>
profile
Junior DevOps Engineer

0개의 댓글