CKA

[CKA] Workloads & Scheduling

테런 2023. 5. 14. 14:00
  • CKA 시험 비중 (15%)
  • Pod란
* Pod란 컨테이너를 표현하는 k8s API의 최소 단위
* Pod에는 하나 또는 여러 개의 컨테이너가 포함될 수 있음
$ kubectl run web --image=nginx --port=80

 

  • 실습1
'cka-exam'이라는 네임스페이스를 만들고, 'cka-exam' 네임스페이스에 아래와 같은 Pod를 생성하세요.
* pod Name: pod-01
* image: busybox
* 환경변수: CERT="CKA-cert"
* command: /bin/sh
* args: "-c", "while true; do echo $(CERT); sleep 10;done"
$ kubectl create namespace cka-exam

# docs 적극 참고
$ vi pod-01.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-01
  namespace: cka-exam
spec:
  containers:
  - image: busybox
    name: pod-01
    env:
    - name: CERT
      value: "CKA-cert"
    command: ["/bin/sh"]
    args: ["-c", "while true; do echo $(CERT); sleep 10;done"]

 

  • 실습2
Pod "custom-app"의 log를 모니터링하고 'file not found' 메시지를 포함하는 로그 라인을 추출하세요.
추출된 결과는 custom-app-log에 기록하세요.
$ kubectl logs custom-app | grep 'file not found' > custom-app-log

 

  • Static Pod란
* API 서버 없이 특정 노드에 있는 kubelet에 의해 직접 관리
* /etc/kubernetes/manifests/ 디렉토리에 pod yaml 파일을 저장 시 적용, 삭제할 때도 yaml 파일을 삭제해야한다.
* 수정 시 kubelet 데몬 재실행 -> systemctl restart kubelet
$ cat /var/lib/kubelet/config.yaml # staticPodPath: /etc/kubernetes/manifests 확인​

 

  • 실습1
What is the docker image used to deploy the kube-api server as a static pod?
$ cat /etc/kubernetes/manifests/kube-apiserver.yaml | grep -i image

 

  • Multi Container Pod란
* 하나의 Pod에 여러 개의 컨테이너가 포함되어 함께 실행

 

  • 실습1
4개의 컨테이너를 동작시키는 eshop-frontend Pod를 생성하세요.
* pod image: nginx, redis, memcached, consul
$ kubectl run eshop-frontend --image=nginx --dry-run=client -o yaml > multi-container.yaml

$ vi multi-container.yaml
apiVersion: v1
kind: Pod
metadata:
  name: eshop-frontend
spec:
  containers:
  - image: nginx
    name: nginx-container
  - image: redis
    name: redis-container
  - image: memcached
    name: memcached-container
  - image: consul
    name: consul-container

$ kubectl apply -f multi-container.yaml

 

  • Sidecar Container Pod란 (문제 정말 많이 나옴!)
* 기본 컨테이너 기능을 확장하기 위해 사용
* 본래의 컨테이너는 기본 서비스에 충실하고, 추가 기능을 별도의 컨테이너를 이용해 적용
* 웹서버는 기본 서비스에 충실하고, 추가로 생성되는 웹서버 로그는 별도의 사이드 카 컨테이너가 수집하여 외부 log aggregator로 전송하는 형태의 서비스

 

  • 실습1
현재 운영 중인 eshop-cart-app Pod의 로그를 kubectl logs에 통합하는 로그 스트리밍 사이드카 컨테이너를 운영하세요.
* busybox 이미지를 사용하여 price라는 이름의 사이드카 컨테이너를 기존 eshop-cart-app에 추가합니다.
* 새 price 컨테이너는 다음과 같은 command를 실행해야 합니다.
Command: /bin/sh, -c, "tail -n+1 -f /var/log/cart-app.log"
* /var/log에 마운트 된 볼륨을 사용하여 사이드카 컨테이너에서 로그 파일 cart-app.log를 사용해야 합니다.
* eshop-cart-app Pod와 cart-app 컨테이너를 수정하지 마세요.
$ kubectl get pod eshop-cart-app -o yaml > eshop-cart-app.yaml
$ vi eshop-cart-app.yaml

spec:
  containers:
  - image: busybox
    name: price
    args: [/bin/sh, -c, 'tail -n+1 -f /var/log/cart-app.log']
    volumeMounts:
      - mountPath: /var/log
      name: varlog
      
$ kubectl logs eshop-cart-app -c price

 

  • 실습2
Edit the pod to add a sidecar container to send logs to Elastic Search. Mount the log volume to the sidecar container. Only add a new container. Do not modify anything else. Use the spec provided below.Note: State persistence concepts are discussed in detail later in this course. For now please make use of the below documentation link for updating the concerning pod.

https://kubernetes.io/docs/tasks/access-application-cluster/communicate-containers-same-pod-shared-volume/

Name: appContainer
Name: sidecarContainer
Image: kodekloud/filebeat-configuredVolume
Mount: log-volumeMount
Path: /var/log/event-simulator/
Existing Container Name: app
Existing Container Image: kodekloud/event-simulator
$ kubectl edit pod app -n elastic-stack

spec:
  containers:
  - image: kodekloud/filebeat-configured
    name: sidecar
    volumeMounts:
    - mountPath: /var/log/event-simulator/
      name: log-volume
      
$ kubectl replace --force -f /tmp/kubectl-edit-XXXXXXXXX.yaml

 

  • Deployment란
* 쿠버네티스 클러스터에서 애플리케이션을 배포하는 가장 일반적인 방식
* ReplicaSet 컨트롤러를 통해 replica 수 보장 및 scaling 가능
* Rolling update 또는 Roll back 지원
$ kubectl scale deployment {Deployment Name} --replicas=3

 

  • Rolling Update & Roll back이란
* Rolling Update: 동작중인 애플리케이션의 서비스 중단 없이 점진적으로 Pod 업데이트
* Rollback: 동작중인 애플리케이션 서비스 중단 없이 이전 버전으로 되돌리기
$ kubectl set image deployment {Deployment Name} {Container Name}={New Version} --record
$ kubelet rollout history deployment {Deployment Name}
$ kubelet rollout undo deployment {Deployment Name}
$ kubelet rollout undo deployment {Deployment Name} --to-revision=NUMBER

 

  • Node 관리 - Node 스케줄링 중단 및 허용
* 컨테이너를 포함한 Pod는 node에서 실행됨
* node는 Control-plane에 의해 관리
* 특정 node의 스케줄링 중단(cordon) 및 허용(uncordon)
* Node가 중단될 때, 속해있는 Pod들은 영향을 받지 않는다.
$ kubectl cordon {Node Name}
$ kubectl uncordon {Node Name}

 

  • Node 관리 - Node 비우기
* 노드 비우기 (drain)
* 특정 node에서 실행중인 pod 비우기(drain) 및 제거(delete)
$ kubectl drain {Node Name} --ignore-daemonsets --force
$ kubectl uncordon {Node Name}

 

  • 실습1
node01 노드를 스케줄링 불가능하게 설정하고, 해당 노드에서 실행 중인 모든 Pod을 다른 node로 reschedule 하세요.
$ kubectl drain node01 --ignore-daemonsets --force

 

  • Node Taint & Toleration
* Taint는 바이러스라고 생각하고, Toleration은 백신이라고 생각하면 이해가 쉽다.
* Worker Node에 Taint (바이러스 A)가 설정된 경우 Toleration (백신 A)가 있는 Pod만 배치된다.
* effect 필드 종류
1. NoSchedule: Toleration이 맞지 않으면 배치되지 않는다.
2. PreferNoSchedule: Toleration이 맞지 않으면 배치되지 않으나, 클러스터 리소스가 부족하면 할당된다.
3. NoExecute: Toleration이 맞으면 동작중인 Pod를 종료한다.
# Taint 추가
$ kubectl taint nodes node1 key1=value1:NoSchedule-

# Toleration 추가
tolerations:
- key: "key1"
  operator: "Equal"
  value: "value1"
  effect: "NoSchedule"​

 

  • 실습1
Ready 상태(NoSchedule로 Taint된 node는 제외)인 node를 찾아 그 수를 알아보세요.
$ kubectl get nodes
$ kubectl describe node {Node Name} | grep -i -e taint -e noschedule

 

  • Pod Scheduling: NodeSelector
* Worker Node에 할당된 label을 이용해 node를 선택
* Node Label 설정
$ kubectl get nodes --show-labels
$ kubectl label node {Node Name} gpu=true
$ kubectl get nodes -L gpu

# 이미 동일한 키의 라벨이 존재하는 경우
$ kubectl label node {Node Name} gpu=false --overwrite

# 라벨 삭제
$ kubectl label node {Node Name} gpu-

# vi pod.yaml (Pod 생성 시)
spec:
  nodeSelector:
    gpu: "true"

 

  • Kubernetes ConfigMap
* 컨테이너 구성 정보를 한 곳에 모아서 관리
* 모든 컨테이너 안에 일일이 들어가서 config를 수정하기 귀찮다. 그래서 모아서 관리
$ kubectl create configmap {Config Name} --from-file={FILE}
$ kubectl create configmap {Config Name} --from-literal=key1=value1

 

  • 실습1
다음의 변수를 configMap eshop으로 등록하세요.
* DBNAME: mysql
* USER: admin
등록한 eshop configMap의 DBNAME을 eshop-configmap라는 이름의 nginx 컨테이너에 DB라는 환경변수로 할당하세요.
# configmap 생성
$ kubectl create configmap eshop --from-literal=DBNAME=mysql --from-literal=USER=admin
$ kubectl get configmaps
$ kubectl describe configmaps eshop

# pod 생성
# kubectl run eshop-configmap --image=nginx --dry-run=client -o yaml > eshop.yaml

containers:
- name: eshop-configmap
  image: nginx
  env:
    - name: DB
      valueFrom:
        configMapKeyRef:
          name: eshop
          key: DBNAME
          
$ kubectl exec -it eshop-configmap -- /bin/bash
$ env

 

  • Kubernetes Secret
* 컨테이너가 사용하는 password, auth token, ssh key와 같은 중요한 정보를 저장하고 민감한 구성 정보를 base64로 인코딩해서 한곳에 모아서 관리
* 민감하지 않은 일반 설정 파일은 configMap을 사용하고 민감한 데이터는 secret을 사용한다.
# Secret 생성
$ kubectl create secret --help
$ kubectl create secret generic eshop --from-literal=DBNAME=mysql --from-literal=USER=admin
$ kubectl get secrets
$ kubectl describe secrets eshop # 정보를 안보여주는 것을 확인
$ kubectl get secrets eshop -o yaml # 인코딩 (암호화는 아니다.)

 

  • 실습1
Secret Name: super-secret
Password: bob
1. Create a pod named pod-secrets-via-file, using the redis Image, which mounts a secret named super-secret at /secrets.

2. Create a second pod named pod-secrets-via-env, using the redis Image, which exports password as CONFIDENTIAL
# secret 생성
$ kubectl create secret generic super-secret --from-literal=Password=bob
$ kubectl describe secrets super-secrets

# pod 생성
# kubectl run pod-secret-via-file --image=redis --dry-run=client -o yaml > pod-secret-via-file.yaml
# vi pod-secret-via-file

spec:
  containers:
  - name: pod-secret-via-file
    image: redis
    volumeMounts:
    - name: foo
      mountPath: "/secrets"
  volumes:
  - name: foo
    secret:
      secretName: super-secret
          
$ kubectl apply -f pod-secret-via-file.yaml

# 확인
$ kubectl exec pod-secret-via-file -it -- /bin/bash
$ cd /secrets
$ cat Password
# pod 생성
# kubectl run pod-secret-via-env --image=redis --dry-run=client -o yaml > pod-secret-via-env.yaml
# vi pod-secret-via-env

spec:
  containers:
  - name: pod-secret-via-env
    image: redis
    env:
    - name: CONFIDENTIAL
      valueFrom:
         secretKeyRef:
            name: super-secret
            key: Password
          
$ kubectl apply -f pod-secret-via-env.yaml

# 확인
$ kubectl exec pod-secret-via-env -it -- /bin/bash
$ env

 

출처: TTABAE-LEARN - 이성미 강사, Udemy - CKA 강의