우선 글을 작성하기 전에 GCE 위에서 쿠버네티스를 설치하는 실습은 이번 포스팅까지임을 말씀드립니다.

Ingress까지 공부를 진행하였으나 GCP에서 부하분산을 지원하기도하고

슬슬 GKE를 이용해서 프로젝트를 진행하고 싶어 다음 포스팅 부터는 GKE 관련 포스팅이 될 것입니다.

실습 위주로 진행된 부분이 많아 내용정리에 부족한 부분들은 별도로 추가 포스팅을 진행할 계획입니다.


Service

서비스에 대해서 다시 한번 짚고 넘어갑니다~

서비스는 파드 집합에서 실행중인 애플리케이션을 네트워크 서비스로 노출하는 추상화 방법이라고 한다.

서비스가 대상으로 하는 파드의 집합은 일반적으로 셀렉터가 결정합니다. => 셀렉터를 맞춰준 이유!

apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    pori: nginx
  ports:
    - protocol: TCP
      port: 80
      targetPort: 9376
      type: NodePort
      

 

nginx 서비스 코드를 예시로 뜯어보겠습니다.

프로토콜을 TCP를 사용하고, 파드의 9376번 포트를 대상으로하는 서비스를 만든다면 위와 같이 생성 가능합니다.

서비스의 이름은 my-service가 될것이고 서비스의 80번 포트로 연결될 것입니다.

 

Docs의 아래에 재미있는 코드가 하나 더 있습니다. 바로 Pod의 컨테이너 포트에 이름을 생성해주고 서비스에서 타겟포트를 해당 이름으로 지원하는 방법입니다.

apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    app.kubernetes.io/name: proxy
spec:
  containers:
  - name: nginx
    image: nginx:stable
    ports:
      - containerPort: 80
        name: http-web-svc

---
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  selector:
    app.kubernetes.io/name: proxy
  ports:
  - name: name-of-service-port
    protocol: TCP
    port: 80
    targetPort: http-web-svc

 

Kind를 잘 봐주세요!!

위쪽은 Pod의 정의 입니다. spec > containers > ports > name을 보면 해당 포트에 이름을 지정해둔 것을 확인 가능합니다.

아래의 Service의 targetPort를 보면 원하는 Pod의 포트 이름으로 연결한 것을 확인 가능합니다.

 

Service type

  • ClusterIP: 클러스터 내부에서만 접근할 수 있는 IP를 할당한다.
  • NodePort: 노드의 특정 포트를 사용해서 접근하는 방법이다. 포트당 하나의 서비스만 사용가능하다고 한다.
  • LoadBalancer: 노드포트의 앞에 특정 LoadBalancer를 사용해서 접근한다.
  • ExternalName: DNS이름에 대한 서비스를 매핑한다.

NodePort

사용할 NodePort에 대해서 조금 더 알아보겠다.

NodePort는 특정 포트를 사용해서 접근을 허용합니다.

--service-node-port-range 플래그로 지정된 범위에서 포트를 할당한다. (3000~32767 범위의 포트를 사용한다.)

(뭔가 오버라이딩이 될것만 같은 형태..)

서비스는 할당된 포트를 .spec.ports[*].nodePort필드에 나타낸다고한다.

 

실습

우선 디플로이먼트로 파드를 생성해준다. 서비스가 대상으로하는 파드의 집합은 셀렉터에서 가져오니까 셀렉터를 잘 기억해두겠습니다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx # 이거는 pod에 영향을 주지 않는다.
spec:
  replicas: 2
  selector:
    matchLabels:
      pori: nginx   # MatchLable의 값이 아래의 metadata의 labels와 동일한 값이여야 동작
  template:
    metadata:
      labels:
        pori: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80

 

네 지난 실습코드와 동일합니다! 여기서 selector의 matchLabes를 기억하면 pori:nginx입니다.

그럼 이제 service를 만들면

apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    pori: nginx
  ports:
    - protocol: TCP
      nodePort: 31299
      port: 80
      targetPort: 80
  type: NodePort

31299번 포트를 지정해서 사용할것이기 때문에 다음과 같이 작성했습니다.

spec > selector를 보면 우리가 위에서 지정한 라벨을 똑같이 적용함을 알 수 있습니다.

 

이렇게 서비스로 연결된 파드는 worker1, worker2가되고 GCE의 외부IP와 열어둔 포트를 이용해서 접근하면?

정상적으로 접근이 가능한 것을 확인 가능합니다.

  • 디플로이먼트는 쿠버네티스가 애플리케이션의 인스턴스를 어떻게 생성하고 업데이트해야 하는지를 지시한다.
  • 디플로이먼트가 만들어지면, 쿠버네티스 컨트롤 플레인이 해당 디플로이먼트에 포함된 애플리케이션 인스턴스가 클러스터의 개별 노드에서 실행되도록 스케줄한다.
  • 이렇게 머신의 장애나 정비에 대응할 수 있는 자동 복구(self-healing) 메커니즘을 제공한다.

 

그럼 이제 디플로이먼트를 사용해서 간단한 Pod들을 배포해보려한다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx # 이거는 pod에 영향을 주지 않는다.
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx   # MatchLable의 값이 아래의 metadata의 labels와 동일한 값이여야 동작
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80

 

주의!!: 라벨의 정보를 변경하면 pod를 새로 생성한다. 도중에 변경하는일을 최소화하자!

 

spec의 matchLabels와 metadata의 labels가 동일해야 정상적으로 동작한다.

 

그럼 이제 다음 명령어로 디플로이를 생성한다. kubectl apply -f  deploy-nginx.yaml

 

정상적으로 pod들이 생성되었다. 그런데 이름이 조금 신기하다. 이름이 무엇을 뜻하는지 알아보고자 한다.

우선 앞의 nginx-deployment는 익숙하다. 우리가 생성한 yaml파일에 metadata를 보면 작성한 이름이 나와있다.

그렇다면 그 뒤는 무엇일까? replicaset을 확인해보면 답을 찾을 수 있다.

 

metadata 이름 뒤에 replicaset의 이름이 붙은것을 확인가능하다!

그렇다면 자연스레 마지막부분은 pod의 이름이 되는 것을 알 수 있고 pod의 이름은 다음과 같은 구조를 지니는 것을 확인가능하다.

 

pod 전체 구조 = deployment의 이름 + replicaset 이름 + pod 이름

아마 이름 보다는 해시값이라 해야 맞지않을까 라고 생각한다.

<Docs>
디플로이먼트는 파드와 레플리카셋에 대한 선언적 업데이트를 제공한다. 디플로이먼트에서 의도하는 상태를 설명하고, 디플로이먼트 컨트롤러는 현재 상태에서 의도하는 상태로 비율을 조정하며 변경한다. 새 레플리카셋을 생성하는 디플로이먼트를 정의하거나 기존 디플로이먼트를 제거하고, 모든 리소스를 새 디플로이먼트에 적용할 수 있다.

디플로이먼트란

쿠버네티스에서 상태가 없는(stateless) 앱을 배포할 때 사용하는 가장 기본적인 컨트롤러

레플리카셋을 관리하며 앱 배포를 더 세밀하게 관리하는 것이다.

⇒ 레플리카셋 기능을 활용해 실행되는 파드(애플리케이션)을 무중단으로 업데이트하는 기능

디플로이먼트로 가능한 것.

  • Pod의 롤아웃, 롤백
  • 롤아웃 방식의 지정
  • 롤아웃 조건이나 속도 제어

컨테이너 이미지 버전업등의 업데이트가 있을 때 새로운 사양의 레플리카셋을 작성하고 순서대로 새로운 파드로 대체하여 롤아웃을 수행한다. 디플로이먼트는 이력을 관리하기 때문에 1세대 이전으로 돌리는 롤백이 가능하다.

기본적인 매니페스트 파일 작성

# deployment-nginx.yaml
# [1] 기본 항목
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx-deployment

#  [2] Deployment 스펙
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx-deployment

 # [3] Pod 템플릿
  template:
    metadata:
      labels:
        app: nginx-deployment
    # [4] Pod 스펙
    spec:
      containers:
        - name: nginx-deployment
          image: nginx # 컨테이너 이미지 위치
          ports:
            - containerPort: 80 # 포트 번호

매니페스트 기본 항목

  • apiVersion: API버전, 존재하지 않는 값을 설정하면 오류가 난다고한다. ex) apps/v1
  • kind: 쿠버네티스 리소스의 종류 ex) Deployment
  • metadata: 레플리카셋의 이름이나 Label과 같은 메타데이터 ex) name: nginx-deployment
  • spec: 레플리카셋의 상세정보를 설정한다.

디플로이먼트 스펙

  • replicas: 클러스터 안에서 가동시킬 파드의 수, default = 1
  • selector: 어떤 파드를 가동시킬지에 대한 셀렉터, 파드의 템플릿에 설정된 라벨과 일치해야한다.
  • template: 실제 클러스터에서 동작하는 파드의 수가 replicas에 설정된 파드의 수를 만족시키지 않는 경우에 새로 작성되는 파드의 템플릿
  • 주의: Selector에 설정된 라벨과 Pod의 Template에 설정된 라벨은 일치해야한다.

Pod template

  • metadata: 템플릿의 이름이나 라벨과 같은 데이터
  • spec: 파드의 상세정보

디플로이먼트 사용

디플로이먼트 생성

  • 생성 코드: kubectl apply -f deploy-nginx.yaml
  • 확인을 위해서 다음 명령을 입력한다. kubectl get deploy,rs,pods
    • deploy = deployment, rs = replica set, pods = pod
  • 파드의 이름은 다음 형태로 구성된다.
    • deployment 이름 + replica set 이름 + 해시

디플로이먼트 수정

업데이트의 방법은 크게 세 가지가 존재한다.

  1. kubectl set 명령으로 직접 컨테이너 이미지를 지정
  2. kubectl edit 명령으로 현재 파드의 설정 정보를 연 다음 컨테이너 이미지 정보를 수정
  3. 처음 적용했던 템플릿의 컨테이너 이미지 정보를 수정한 다음 kubectl apply 명령을 이용

kubectl set 명령으로 직접 컨테이너 이미지를 지정

  • code: kubectl set image deployment/nginx-deployment nginx-deployment=nginx:1.9.1

디플로이먼트 롤백

  • 컨테이너 이미지 변경 내역 확인: kubectl rollout history deploy {deployment_name}

  • 만약에 버전이 변경된다면 버전2가 추가된다. ⇒ 2가 현재버전이 되는거!
  • 리비전 2의 상세 내용을 확인하는 코드: kubectl rollout history deploy {deployment_name} --version=1
  • 버전1로 롤백하는 코드: kubectl rollout undo deploy {deployment_name} —to-revision={revision_number}
  • 롤아웃 히스토리 확인: kubectl rollout history deploy {deployment_name}

참고 및 출처

https://kimjingo.tistory.com/133

 

[k8s] 디플로이먼트(Deployment)

디플로이먼트 디플로이먼트(Deployment)는 쿠버네티스에서 상태가 없는(stateless) 앱을 배포할 때 사용하는 가장 기본적인 컨트롤러입니다. 쿠버네티스가 처음 등장했을 때는 Replication Controller에서

kimjingo.tistory.com

https://huisam.tistory.com/entry/k8s-deployment

 

[k8s/쿠버네티스] - Deployment로 애플리케이션 배포

안녕하세요~ 오늘은 쿠버네티스 환경에서 Application을 배포하는 과정에 대한 설명으로 간단하게 Deployment 를 소개해드릴까 합니다 ㅎㅎ 제가 최근에 도커 이미지를 만들어보는 Dockerfile만들기라는

huisam.tistory.com

 

채용 공고를 보면서 데이터 엔지니어 직무의 우대사항에 왜 쿠버네티스가 들어간걸까?

이런 생각이 들어 GPT의 힘을 빌려 정리해두었다.

막연하게 배워야한다라고 생각하는게 아니라 글로 작성해보니 체감이 더 잘되는 것 같다.

🥡 데이터 엔지니어가 쿠버네티스를 배우는 이유?
- 효율적인 리소스 관리
쿠버네티스를 통해 애플리케이션과 서비스의 배포, 확장 및 관리를 자동화할 수 있습니다. 이는 인프라 운영의 복잡성을 줄이고, 자원을 더 효율적으로 사용할 수 있게 합니다.

- 확장성 및 가용성 향상
자동 확장 기능과 함께 노드 장애가 발생했을 때 서비스의 지속적인 운영을 보장합니다. ⇒ 고가용성과 확장성

- 다양한 환경과의 호환성

우선 포스팅 작성 전에 이번 포스팅의 거의 모든 내용은 다음 블로그를 참고하였다.

따라서 더 자세한 정보를 원한다면 해당 블로그를 참고하는 것을 추천한다.

이번 포스팅은 단순하게 내가 공부한 내용을 타이핑해보면서 기록하는 용도이다.

https://easyitwanner.tistory.com/174

 

[Kubernetes] 쿠버네티스의 구성 요소

목차 마스터 노드(컨트롤 플레인) 워커 노드 애드온 마스터 노드(컨트롤 플레인) 컨트롤 플레인은 클러스터를 제어하고 작동시킵니다. 즉, 마스터 노드는 전체 쿠버네티스 시스템을 제어하고 관

easyitwanner.tistory.com


쿠버네티스의 장점

  • 애플리케이션 배포 단순화
  • 하드웨어 활용도 증가
  • 상태 확인과 자가 치유
  • 오토스케일링

Master node = Control plane

컨트롤 플레인은 클러스터를 제어하고 작동시킨다. 하나의 마스터 노드에서 실행하거나 여러 노드로 분할되고 복제되어 고가용성을 보장할 수 있는 요소들로 구성된다.

 

구성 요소

  • etc 분산 저장 스토리지
    • 분산형, 신뢰 가능한 키 값 저장소
    • 클러스터의 구성 데이터와 상태를 보유
    • 뗏목 합의 알고리즘 기반
  • API 서버
    • 클러스터 내의 사용자, 관리자 및 기타 구성 요소 간의 기본 상호작용 지점.
    • Restful APU 요청을 처리하고 유효성을 검사하며, etcd 데이터 저장소의 개체를 업데이트한다.
    • 클러스터의 상태를 관리하고 컨트롤 플레인의 일관성, 보안, 안전성을 보장하는 역할을 수행한다.
    • API서버가 Kubelet에 직접 접속하는 경우
      • log를 가져오는 경우
      • kubectl attach로 실행중인 컨테이너에 연결 시
      • kubectl port-foward를 실행할 때
  • 스케쥴러
    • 새로 생성되거나 예약되지 않은 파드를 클러스터 내의 적절한 노드에 할당
    • 리소스 가용성, 제약 조건 및 정의된 정책을 기반으로 포드를 실행할 위치를 결정하여 워크로드가 클러스터 전체에 효율적으로 분산되게 만듬.
  • 컨트롤러 매니저
    • 클러스터의 원하는 상태를 자동화하고 유지 관리하는 다양한 컨트롤러를 관리하는 k8s 제어 평면의 핵심구성요소
    • 클러스터의 상태를 원하는 상태와 일치하도록 필요한 조정을 수행하는 제어 루프이다.

역할

  • 클러스터 상태 관리
  • 예약: Pod 예약
  • 확장: 실행 중인 Pod수를 자동으로 확장 또는 축소
  • 배포 업데이트 및 롤백: 애플리케이션 가동 중지 시간이 없음
  • 클러스터 전체 네트워킹 관리

주요 기능

  • 고가용성: 고가용성 구성 시 마스터 노드를 여러개로 실행
  • 확장성: 마스터 노드는 수천개의 노드와 수만개의 포드가 있는 대규모 클러스터의 처리가 가능하다.
  • 보안: 클러스터에 대한 액세스를 인증하고 승인해서 인증된 사용자만 특정 작업을 수행
  • 사용자 정의 가능성

Worker node

컨테이너화된 애플리케이션을 실행하는 시스템.

 

구성 요소

  • 컨테이너 런타임
  • Kubelet: API서버와 통신하고 노드의 컨테이너를 관리한다.
    • 컨테이너가 포드 내에서 예상되로 실행되도록 하는 역할.
    • 컨트롤 플레인과 통신하고 노드에서 컨테이너의 수명 주기를 관리하는 기본 노드 에이전트 역할이다.
    • 각 노드에서 실행되는 필수 구성요소이다.
  • 쿠버네티스 서비스 프록시: 애플리케이션 구성 요소간에 네트워크 트래픽을 로드밸런싱함.

역할

  • Pod 실행: 배포 가능한 가장 작은 단위인 Pod를 실행. 포드는 동일한 네트워크 네임스페이스를 공유하는 하나 이상의 컨테이너를 포함 가능.
  • 컨테이너 관리: 필요에 따라 컨테이너 시작, 중지, 다시시작을 포함한 수명 주기를 관리
  • 네트워킹: 작업자 노드는 IP 주소 할당 및 네트워크에 서비스 노출을 포함하여 실행중인 컨테이너에서 들어오고 나가는 네트워크 트래픽 처리
  • 상태 확인
  • 리소스 관리

주요 기능

  • 확장성
  • 유연성
  • 내결함성: 하나 이상의 노드가 실패하더라도 애플리케이션이 계속 실행될 수 있다.
  • 사용자 지정 가능성
 
 

+ Recent posts