본문 바로가기

Backend/Docker, k8s

k8s - Pod

 

Pod란?

 - 컨테이너 애플리케이션의 기본 실행단위.

 - 배포할 수 있는 가장 작고 간단한 단위

 - 파드 내부에는 여러개의 컨테이너가 있음. 보통 2개, 많으면 3개

 - 같은 목적으로 자원을 공유하기 위해서 동일한 워커노드에서 실행

 - 동일 IP로 접근하며, Pod 안 컨테이너와 통신할 때는 포트를 통해 접속

 - .yaml파일을 통해 pod를 생성한다.

 

yaml 파일 예시 (app.yaml)

apiVersion: v1
kind: Pod
metadata:
  name: app
  labels:
    app: app
spec:
  containers:
  - image: takytaky/app:v1
    name: app-container
    ports:
    - containerPort: 80
      protocol: TCP

 

이 yaml 파일을 실행하려면 다음과 같이 입력한다.

kubectl apply -f app.yaml

 

pod의 실행현황을 보고싶다면 다음과 같이 입력한다.

kubectl get pods -o wide	# 전체 pod 확인
kube describe pod app		# 특정 pod 확인

 

pod에 bash로 붙고싶다면 다음과 같이 입력한다.

kubectl exec -it app -- /bin/bash

 

 

pod를 지우고 싶다면 다음과 같이 입력한다.

kubectl delete pod app						# app이란 pod 지우기
kubectl delete pods --all -n cpu-example	# 특정 namespace의 pods 전부 지우기

 

 

 

yaml에서 환경변수 설정하기

yaml에서 환경변수를 설정할 수 있다.

apiVersion: v1
kind: Pod
metadata:
  name: app-env
  labels:
    app: app-env
spec:
  containers:
  - name: container-env
    image: takytaky/app:v1
    ports:
    - containerPort: 80
    env:
    - name: ENV01
      value: "value01"
    - name: HOSTNAME
      valueFrom:
        fieldRef:
          fieldPath: spec.nodeName
    - name: POD_NAME
      valueFrom:
        fieldRef:
          fieldPath: metadata.name
    - name: POD_IP
      valueFrom:
        fieldRef:
          fieldPath: status.podIP
    - name: CPU_REQUEST
      valueFrom:
        resourceFieldRef:
          containerName: container-env
          resource: requests.cpu
    - name: CPU_LIMIT
      valueFrom:
        resourceFieldRef:
          containerName: container-env
          resource: limits.cpu

 

 

liveness probe : 컨테이너가 동작중인지 확인. 이 진단이 실패하면 정책에 따라 컨데이터 재 시작

 

liveness probe 예시 (exec-liveness.yaml)

apiVersion: v1
kind: Pod
metadata:
  labels:
    test: liveness
  name: liveness-exec
spec:
  containers:
  - name: liveness
    image: registry.k8s.io/busybox
    args:
    - /bin/sh
    - -c
    - touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600
    livenessProbe:
      exec:
        command:
        - cat
        - /tmp/healthy
      initialDelaySeconds: 5
      periodSeconds: 5

 

Readiness probe : 이 probe가 존재한다면 초기상태는 failure로 시작한다. 무조건 통과해야 하는 절차가 됨. 진단이 실패하면 pod의 ip주소를 제거한다. 그러면 master가 다른 pod에게 해당 업무를 전달할 것이다.

 

Readiness probe 예시 (tcp-liveness-readiness-failure.yaml) : 이 pod는 port 8181이 잘못입력되어 바로 제거될 것이다.

apiVersion: v1
kind: Pod
metadata:
  name: goproxy
  labels:
    app: goproxy
spec:
  containers:
  - name: goproxy
    image: registry.k8s.io/goproxy:0.1
    ports:
    - containerPort: 8080
    readinessProbe:
      tcpSocket:
        port: 8181
      initialDelaySeconds: 5
      periodSeconds: 10
    livenessProbe:
      tcpSocket:
        port: 8181
      initialDelaySeconds: 15
      periodSeconds: 20

 

pod resource(cpu, memory 할당)

 - momory는 컨테이너에 2GB가 있고, 물리적으로는 4GB가 있으면 4GB를 다 쓸 수 있다. 이로 인해 OOM에러가 발생하는 것을 막기 위해 .spec.containers[].resources.limits.memory 설정을 해야 한다.

 - CPU는 자원을 쪼개서 사용이 가능하다.

apiVersion: v1
kind: Pod
metadata:
  name: app
  labels:
    app: app
spec:
  containers:
  - name: app
    image: takytaky/app
    resources:
      requests:
        cpu: 0.1
        memory: 200M
      limits:
        cpu: 0.5
        memory: 1G
    ports:
    - containerPort: 8080

 

초기화 컨테이너 (initContainer)

 - 초기화 할 목적으로

 - 보안상의 이유로 이미자와 같이 두면 안되는 앱 소스 코드를 별도로 관리할 때 유용

 - initContainer가 실패하면 계속 재시작되며, init container가 모두 실행된 후 앱 컨테이너가 실행된다.

apiVersion: v1
kind: Pod
metadata:
  name: init-demo
spec:
  containers:
  - name: nginx
    image: nginx
    ports:
    - containerPort: 80
    volumeMounts:
    - name: workdir
      mountPath: /usr/share/nginx/html
  initContainers:
  - name: install
    image: busybox
    command:
    - wget
    - "-O"
    - "/work-dir/index.html"
    - http://info.cern.ch
    volumeMounts:
    - name: workdir
      mountPath: "/work-dir"
  dnsPolicy: Default
  volumes:
  - name: workdir
    emptyDir: {}

 

멀티 컨테이너 파드 디자인 패턴

 - SideCar Pattern : 확장, 강화용도로 컨테이너를 추가

 - Ambassador Pattern : 프록시 역할을 하는 컨테이너를 추가

 - Adapter Pattern : 파드 외부로 노출되는 정보를 표준화 하기 위해 컨테이너를 추가

 

 

Label, Selector, Annotation

labels: 에 정의된 것들을 key-value로 구성(key만 있어도 됨)

Selector : kubectl get pods {pod name}이 아닌 label을 기반으로 검색할 수 있다.

Annotation : k8s에서 필요한 사항을 메타데이터에 기록하는 추가정보(주석)

# label01.yaml
apiVersion: v1
kind: Pod
metadata:
  name: label-app01
  labels:
    app: nodejs
    environment: develop
    release: beta
spec:
  containers:
    - name: nodejs
      image: takytaky/app:v1
      ports:
      - containerPort: 80

# label02.yaml
apiVersion: v1
kind: Pod
metadata:
  name: label-app02
  labels:
    app: nodejs
    environment: production
    release: beta
spec:
  containers:
    - name: nodejs
      image: takytaky/app:v1
      ports:
      - containerPort: 80

# label03.yaml
apiVersion: v1
kind: Pod
metadata:
  name: label-app03
  labels:
    app: nodejs
    environment: develop
    release: stable
spec:
  containers:
    - name: nodejs
      image: takytaky/app:v1
      ports:
      - containerPort: 80

# label04.yaml
apiVersion: v1
kind: Pod
metadata:
  name: label-app04
  labels:
    app: nodejs
    environment: production
    release: stable
spec:
  containers:
    - name: nodejs
      image: takytaky/app:v1
      ports:
      - containerPort: 80

 

이 모든 것을 실행하면 4개의 pod가 생성된다.

pods의 label을 전체 보려면 다음과 같다.

kubectl get pods --show-labels

 

pod들을 selector를 통해 검색하려면 다음과 같다.

kubectl get pods -l app=nodejs

 

노드에도 label이 있다.

kubectl get nodes --show-labels

 

노드에 label을 추가하려면 다음과 같다.

kubectl label nodes {node name} {key}={value}

 

노드에 label을 삭제하고 싶으면 다음과 같다.

kubestl label node {node name} {key}-

 

annotation은 다음과 같이 yaml에서 작성될 수 있다.

apiVersion: v1
kind: Pod
metadata:
  name: annotation-nodejs
  labels:
    app: nodejs
  annotations:
    manufacturer: "takytaky"
    e-mail: "takytaky@example.com"
    release-version: "v1"
spec:
  containers:
  - name: nodejs
    image: takytaky/app:v1
    ports:
    - containerPort: 80

 

조회는 json형태, describe 형태 2가지가 있다.

kubectl get pod annotation-nodejs -o jsonpath='{.metadata.annotations}'

kubectl describe pod {pod name}

 

Controller

Pod를 배포, 관리하는 도구 (Replicaset, Deployment, DaemonSet)

 

Replicaset

지정한 숫자만큼 항상 클러스터 안에서 실행되도록 관리 (복제를 통한 pod 수량 유지)

 

Replicaset의 3요소

 - Label selector : (name은 중복되면 안되니까 name은 지정하지 않고, label만 지정)

 - replicas : 유지할 pod 수. 기본값은 1

 - pod template : pod의 정의(metadata, spec 등)

 

Repolicaset 예제

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: replicaset-nginx
spec:
  selector:
    matchLabels:
      app: rs-nginx
  template:
    metadata:
      labels:
        app: rs-nginx
    spec:
      containers:
      - name: replicaset-nginx-container
        image: nginx
        ports:
        - containerPort: 80
  replicas: 3

 

replica의 scale을 늘리거나 줄이고 싶은 경우

kubectl scale rs replicaset-nginx --replicas={count}

 

replicaset이 생성한 pod은 지울 수 없다 replicaset 자체를 지워야 한다.

kubectl delete rs {replicaset name}

 

replicaset만 지우고 pod를 유지하고 싶다면

kubectl delete replicaset --cascade=orphan {replicaset name}

 

Deployment(디플로이먼트)

레플리카셋을 통해서 복제된 pods를 관리하고 선언적 업데이트가 가능한 컨트롤러. 레플리카셋을 관리한다.

 

Deployment 예제

apiVersion: apps/v1
kind: Deployment
metadata:
  name: deploy-nginx
  labels:
    app: deploy-nginx
  annotations:
    kubernetes.io/change-cause: version 1.16.0
spec:
  replicas: 3
  strategy:
    type: RollingUpdate
  selector:
    matchLabels:
      app: deploy-nginx
  template:
    metadata:
      labels:
        app: deploy-nginx
    spec:
      containers:
      - name: deploy-nginx
        image: nginx:1.16.0
        ports:
        - containerPort: 80

 

Deployment로 replicaset의 pod 수를 조절 할 수 있다.

kubectl scale deploy {deployment_name} --replicas={count}

 

Deployment로 컨테이너 image를 변경할 수도 있다.

  1. set image (잘 안쓰는 명령)

# 현재 image 확인
kubectl get deploy {deployment_name} -o=jsonpath="{.spec.template.spec.containers[0].image}{'\n'}"

# 이미지 변경
kubectl set image deployment {deployment_name} {deployment_name}={image_name}

# 변경된 image 확인
kubectl get deploy {deployment_name} -o=jsonpath="{.spec.template.spec.containers[0].image}{'\n'}"

 

  2. yaml 파일을 수정한 후 apply 실행

nano {deployment}.yaml
kubectl apploy -f {deployment}.yaml

 

Deployment를 삭제할 때는 

kubectl delete deploy {deployment_name}

 

미사용중인 replicaset을 삭제할 수 있다.

kubectl delete rs {replicaset_name}

DaemonSet(데몬셋)

모든 노드에 pod를 실행해야 할 때(예 : 운영 cluster) 사용되는 컨트롤러. worker node 뿐만 아니라 master node에서도 실행된다.

예시 (deamonset.yaml)

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: daemonset-app
  labels:
    k8s-app: daemonset-app
spec:
  selector:
    matchLabels:
      name: daemonset-app
  updateStrategy:
    type: RollingUpdate
  template:
    metadata:
      labels:
        name: daemonset-app
    spec:
      tolerations:
      # this toleration is to have the daemonset runnable on master nodes
      # remove it if your masters can't run pods
      - key: node-role.kubernetes.io/master
        effect: NoSchedule
      - key: node-role.kubernetes.io/control-plane
        effect: NoSchedule
      containers:
      - name: daemonset-app
        image: takytaky/app:v1
        env:
        - name: appenv
          value: daemonset

 

DaemonSet 특징

 

* taint 속성은 오염되었다는 뜻으로, pod가 자동생성되지 않도록 Schedule에서 피해가는데, 이는 보통 Master node에만 있는 속성이다. 그런데 tolerations(관용, 무효)속성을 달아놓으면 master node에도 pod를 실행할 수 있다.

 

* master node의 taint 속성 보기

kubectl describe nodes master | grep Taints

 

* updateStrategy의 전략으로는 OnCreate가 없고 OnDelete가 있다. DaemonSet은 빈 노드가 없는것이 기본이라 뭔가를 생성하고 지울 수 없다. 그래서 선 삭제 후 생성하는 식으로 update가 이루어 지며, 이는 Replicaset과 반대로 동작(선 생성 후 삭제)한다.

 

Job(잡)

실행 후 종료될 pod를 생성하는 컨트롤러. pod가 실행 된 후 죽지 않기 위해 Always라는 기본 정책을 사용하지만, Job은 OnFailure나 Never로 정의한다. 종료된 Job 삭제는 수동으로 해야 하며, ttlSecondAfterFinished로 자동 종료 설정을 할 수 있다.

job 예시파일(job-batch.yaml)

apiVersion: batch/v1
kind: Job
metadata:
  name: batch
spec:
  template:
    spec:
      containers:
      - name: batch
        image: takytaky/batch
      restartPolicy: Never
  ttlSecondsAfterFinished: 100

 

Job 특징

* completions : 몇번의 완료가 필요한가? (몇개의 pod를 만들 것인가?) 기본값은 1개

* paralleism : 몇개를 동시에 실행할 것인가? 기본값은 1개

* crob job : 지정된 시간에 한 번만 Job을 실행하거나 지정한 시간동안 주기적으로 Job을 반복 실행하기 위해 생성. schedule을 적을 때 linux cron 표준을 따름 ("min  hour  date  month 요일(0: 일요일)")

예 : "*/1 * * * *" : 매월 매일 매 시간 1분마다 실행

 

예시 파일 (cronjob-hello.yaml)

apiVersion: batch/v1
kind: CronJob
metadata:
  name: hello
spec:
  schedule: "*/1 * * * *"
  successfulJobsHistoryLimit: 5
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: hello
            image: busybox
            command:
            - /bin/sh
            - -c
            - date; echo Hello from the Kubernetes cluster
          restartPolicy: OnFailure

 

* (cron job) startingDeadlineSeconds : 지정된 시간에 크론잡이 실행되지 못했을 때 설정한 시간이 지나면 시작하지 않는다.

* (cron job) concurrencyPolicy : 동시성 관리

 - Allow : cron job을 동시에 실행 가능

 - Forbid : 이전에 실행한 job이 아직 종료되지 않았다면 새로운 job을 생성하지 않는다.

 - Replace : 이전에 실행한 job이 아직 종료도히지 않았다면 이전에 실행한 job을 삭제하고 새로운 job으로 대체

 

 

 

 

 

 

 

'Backend > Docker, k8s' 카테고리의 다른 글

Docker + Frontend(Nginx, React) + Backend(Nginx, Gunicorn, Django, PostgreSQL)  (7) 2023.06.20
Docker Compose - tutorial  (0) 2023.06.18
Docker - Tutorial  (0) 2023.06.17
k8s - Service  (0) 2023.04.28
Docker - ubuntu에 Docker 설치  (0) 2023.04.26