Docker&Kubernetes 스터디 - 2

배채윤·2023년 4월 19일
0

03 kubernetes 시작하기

정의

  • 쿠버네티스:
    컨테이너화된 워크로드와 서비스를 관리하기 위한 이식 & 확장 가능한 오픈소스 플랫폼
    선언적 구성 & 자동화 모두 용이

  • 오케스트레이션:
    여러 대상을 조율하여 하나의 큰 작업을 수행하는 것
    일반적으로 컴퓨팅에서 사용되며, 여러 대상을 조정하여 복잡한 작업을 자동화하거나 관리하는 것.

  • pod:
    컨테이너 어플리케이션의 기본 단위, 1개 이상의 컨테이너로 구성된 컨테이너 집합

쿠버네티스 특징

  • 모든 리소스는 오브젝트 형태로 관리된다.
  • kuberctl 명령어나 .yaml 를 이용하여 리소스 오브젝트를 정의하고 생성한다.
  • 도커를 포함하여 매우 많은 컴포넌트로 구성돼있다.
    • 마스터 노드: 쿠버네티스가 제대로 동작할 수 있게 클러스터를 관리하는 역할
      • API서버
      • 컨트롤러 매니저
      • 스케줄러
      • DNS 서버 등의 컴포넌트들이 컨테이너로서 실행된다.
    • 워커 노드: 애플리케이션 컨테이너가 생성되는 노드

쿠버네티스가 왜 필요할까?

  • 프로덕션 환경에서는 앱을 실행하고 컨테이너를 관리하고 가동 중지 시간이 없는지 확인해야 한다.
  • 컨테이너가 다운되면 다른 컨테이너를 다시 시작해야 한다.
  • 로컬 저장소, 공용 클라우드
  • 자동화된 롤아웃과 롤백
  • 자동화된 빈 패킹
  • 자동화된 복구

pod vs container

  • ip 주소가 있어 클러스터 내부까지 접근 가능하고 exec 명령으로 접속이 가능하며 logs 명령으로 로그도 확인이 가능하다. -> container와 동일해보임

  • pod으로는 여러 linux namespaces를 공유하는 여러 컨테이너들을 추상화된 집합을 사용하는 것이 가능하기 때문에 pod을 씀

  • pod 내 container들은 같은 리눅스 네임스페이스를 동일하게 공유함.

  • ex) pod 내에서 설정 파일을 갱신해주는 프로세스, 로그 수집 프로세스 등 부가 기능하는 컨테이너를 sidecar 컨테이너를 같이 운영할 수도 있는 것임.

  • 즉, pod은 구조 및 원리에 따라 여러 개의 컨테이너가 모여 하나의 완전한 애플리케이션으로서 동작할 수 있음.

Replica Set

일정 개수의 파드를 유지하는 컨트롤러
정해진 수의 동일한 파드가 항상 실행되도록 관리해줌.
노드 장애 등의 이유로 파드를 사용할 수 없다면 다른 노드에서 파드를 다시 생성함.

프로덕션 환경에서 사용하는 파드는 단순 yaml로 정의해서 생성하는 방식으로는 운영하기 어려움.

사용해보기

# 레플리카셋 정의
$ vi k8s_yaml/replicaset-nginx.yaml
$ cat k8s_yaml/replicaset-nginx.yaml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: replicaset-nginx
spec:
  replicas: 3 	# replica를 몇 개 유지할 것인지 정함
  selector:
    matchLabels:
      app: my-nginx-pods-label
  template:		# pod 생성 템플릿. (동일한 pod을 1번만 정의)
    metadata:
      name: my-nginx-pod
      labels: 
        app: my-nginx-pods-label
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80

# 적용
$ kubectl apply -f k8s_yaml/replicaset-nginx.yaml
$ kubectl get pods
NAME                     READY   STATUS    RESTARTS   AGE
replicaset-nginx-9jxj8   0/1     Pending   0          6s
replicaset-nginx-bbqbp   0/1     Pending   0          6s
replicaset-nginx-kthmc   0/1     Pending   0          6s
$ kubectl get rs
NAME               DESIRED   CURRENT   READY   AGE
replicaset-nginx   3         3         0       75s

Deployment

여러 개의 레플리카셋을 관리하기 위한 오브젝트

실제 프로덕션 환경에서는 레플리카셋을 직접 구현하는 게 아니라 더 상위개념인 Deployment를 정의해서 레플리카셋을 사용한다.

사용해보기

# 디플로이먼트 정의
$ vi k8s_yaml/deployment-nginx.yaml
$ cat k8s_yaml/deployment-nginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nginx-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-nginx
  template:
    metadata:
      name: my-nginx-pod
      labels:
        app: my-nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.10
        ports:
        - containerPort: 80

Service

디플로이먼트를 통해 생성한 파드를 연결하여 외부에 노출해주는 오브젝트

서비스가 필요한 이유

pod의 ip는 영속적이지 않고 동일 대역폭 간 통신만 가능함.
여러 개의 deployment를 하나의 완벽한 앱으로 연동 ⇒ pod ip가 아닌 서로를 발견(Discovery)할 수 있는 다른 방법이 필요

  • 여러 개의 파드에 쉽게 접근할 수 있도록 고유한 도메인 이름을 부여한다.
  • 여러 개의 파드에 접근할 때, 요청을 분산하는 로드 밸런서 기능을 수행합니다.
  • 클라우드 플랫폼의 로드 밸런서, 클러스터 노드의 포트 등을 통해 파드를 외부로 노출한다.

종류

  • Cluster IP 타입: 쿠버네티스 내부에서만 파드들에 접근할 떄 사용. 외부로 파드를 노출 X
  • NodePort 타입: 파드에 접근할 수 있는 포트를 클러스터의 모든 노드에 동일하게 개방. -> 외부에서 파드에 접근 가능하게 함.
  • LoadBalancer 타입: 클라우드 플랫폼에서 제공하는 로드 밸런서를 동적으로 프로비저닝하여 파드에 연결함. NodePort타입과 마친가지로 외부에서 파드에 접근할 수 있는 서비스 타입.

Cluster IP 타입

apiVersion: v1
kind: Service
metadata:
  name: hostname-svc-clusterip
spec:
  ports:	# 서비스 ip에 접근할 떄 사용할 포트
    - name: web-port
      port: 8080
      targetPort: 80	# 접근 대상 파드들이 내부적으로 사용하고 있는 포트 
      					# 파드 템플릿의 containerPort와 같은 값.
  selector: # 접근할 수 있는 서비스 지정.(파드의 라벨명으로)
    app: webserver
  type: ClusterIP

07 쿠버네티스 리소스의 관리와 설정

pod, replicaset, deployment, service는 쿠버네티스에서 애플리케이션을 배포하기 위한 필수 오브젝트.
이외에 많이 사용하는 리소스로는 Namespace, Configmap, Secret 등이 있음.

Namespace

리소스를 논리적으로 구분하는 장벽
파드, 레플리카셋, 디플로이먼트, 서비스 등과 같은 쿠버네티스 리소스들이 묶여있는 하나의 가상 공간이라고 이해하면 됨.

kube-system이라는 네임스페이스에 생성된 파드들 확인
** kube-system: 쿠버네티스 클러스터 구성에 필수적인 컴포넌트들과 설정값 등이 존재하는 네임스페이스

$ kubectl get pod -n kube-system
NAME                                                       READY   STATUS    RESTARTS   AGE
anetd-8xwnw                                                1/1     Running   0          135m
antrea-controller-horizontal-autoscaler-6fb4bf7847-mbzhr   1/1     Running   0          17h
egress-nat-controller-799976cbcb-9smgm                     1/1     Running   0          17h
event-exporter-gke-857959888b-wsjgx                        2/2     Running   0          17h
filestore-node-2nz5n                                       3/3     Running   0          135m
...
  • Label과의 차이
    label 도 리소스를 논리적으로 분류할 수 있는 것으로 동일.
    다만 네임스페이스는 더 넓은 용도로 사용 가능함.
    EX) 특정 네임스페이스 내 파드는 자원 사용량 제한, 특정 네임스페이스 내 파드는 사이드 카 컨테이너를 항상 붙이기

Configmap

YAML 파일과 설정값을 분리할 수 있도록 하는 오브젝트
네임스페이스 별로 컨피그맵이 있음.

생성 방법

# kubectl create configmap [컨피그맵 이름] [설정값]
$ kubectl create configmap log-level-configmap --from-literal LOG_LEVEL=DEBUG

# configmap 확인
$ kubectl get cm
NAME                  DATA   AGE
kube-root-ca.crt      1      25h
log-level-configmap   1      42m
$ kubectl get cm log-level-configmap -o yaml
apiVersion: v1
data:
  LOG_LEVEL: DEBUG
kind: ConfigMap
metadata:
  creationTimestamp: "2023-04-20T05:56:56Z"
  name: log-level-configmap
  namespace: default
  resourceVersion: "989329"
  uid: 95962cc4-a75b-4489-87f3-c80bdf0b980e

config 값 사용하는 방법

  • 컨테이너 환경변수로 가져오기
  • 컨피그맵의 데이터를 컨테이너 환경변수로 가져오기

    • envForm: 컨피그맵에 존재하는 모든 key-value 쌍을 가져옴

      ...
      envForm:
      - configMapRef:
      	name: log-level-configmap
      - configMapRef:
      	name: start-k8s
    • valueFromconfigMapKeyRef: 컨피그맵에 존재하는 key-value 쌍 중에서 원하는 데이터만 선택적으로 가져옴.

      ...
            env:
            - name: ENV_KEYNAME_1     # (1.1) 컨테이너에 새롭게 등록될 환경 변수 이름
              valueFrom: 				# 여러 개의 key-value 가 들어있는 컨피그맵에서 특정 데이터만들 선택해 환경변수로 가져올 수 있음.
                configMapKeyRef:
                  name: log-level-configmap
                  key: LOG_LEVEL
            - name: ENV_KEYNAME_2  	# (1.2) 컨테이너에 새롭게 등록될 환경 변수 이름
              valueFrom: 
                configMapKeyRef:
                  name: start-k8s      # (2) 참조할 컨피그맵의 이름
                  key: k8s             # (3) 가져올 데이터 값의 키
                                       # 최종 결과 -> ENV_KEYNAME_2=$(k8s 키에 해당하는 값)
                                       #              ENV_KEYNAME_2=kubernetes
  • 컨피그맵 값을 파드 내부의 파일로 마운트하여 사용

...
    spec:
      containers:
      	...
    	volumnMounts:				
        - name: configmap-volume	# volumes에서 정의한 컨피그맵 볼륨 이름
    	  mountPath: /etc/config	# 컨피그맵의 데이터가 위치할 경로
      volumes:						# 사용할 볼륨 목록 정의
      - name: configmap-volume		# 컨피그맵 볼륨 이름
        configMap:
          name: start-k8s		
# 컨피그맵을 파일로 마운트 하면 키 이름으로 파일이 생성됨.
$ kubectl exec configmap-volume-pod ls /etc/config
container 	# 키
k8s		# 키
$ kubectl exec configmap-volume-pod cat /ect/config/k8s
kubernetes	# 값

Secret

컨피그맵처럼 설정값을 저장해주는 오브젝트. 단, 비밀번호와 같이 민감한 정보를 저장함.

$ kubectl create generic my-password --from-literal password=1q2w3e4r
  • 환경변수로 가져오기
...
      envFrom:
      - secretRef:
          name: my-password

09 퍼시스턴트 볼륨(PV)과 퍼시스턴트 볼륨 클레임(PVC)

파드의 데이터를 영속적으로 저장하기 위해 PV를 이용하여 프로비저닝을 함.

  • 정적 프로비저닝
  • 동적 프로비저닝
profile
새로운 기술을 테스트하고 적용해보는 걸 좋아하는 서버 개발자

0개의 댓글