[교육] PAAS 2일차

kubernetes

구성

  1. 설정파일을 다운로드 후 메모리 관련 약간 수정하여 구성 https://gitlab.com/junkoks/board/-/raw/main/Work.zip

쿠버네티스란

컨테이너화된 워크로드와 서비스를 관리하기 위하여 이식성있고, 확장가능한 오픈소스 플랫폼이다.

독립서버에서 하나의 애플리케이션

자원 효율적으로 관리 어려움

독립서버에서 복수의 애플리케이션

자원을 서로 잡아먹음

가상서버에서 하나의 애플리케이션

자원 관리 및 차단에 좋지만 OS자원 낭비 발생

컨테이너

운영체제 공유하고 개별 서비스는 고립됨

구성요소

마스터노드 워커노드

마스터 컴포넌트

cloud-controller-manager

  • 컨트롤 플레인의 한 종류. 클라우드(aws, azure..)별 컨트롤 로직을 포함한다.

노드 컴포넌트

  • kubelet : 클러스터의 노드에서 실행되는 에이전트. 파드에서 컨테이너가 동작하도록 관리. 쿠버네티스를 통해 생성되지 않은 컨테이너는 관리하지 않는다(ex. docker run 등으로 수행 중인 컨테이너)

  • kubeproxy :

  • 컨테이너 런타임 : 런타임

애드온

애드온은 쿠버네티스 리소스를 통하여 구현(데몬셋, 디플로이먼트)

  • dns : 거의 기본적인 애드온
  • 웹 UI
  • 컨테이너 리소스 모니터링
  • 클러스터 레벨 로깅

쿠버네티스 API

클러스터 아키텍처

노드 관리

각 노드에 대하여 스케줄링 가능/불가능 여부를 설정할 수 있다.

kubectl get nodes
kubectl cordon node-1
kubectl get nodes
kubectl uncordon node-1

노드상태 kubectl get node

NAME STATUS ROLES AGE VERSION
docker-desktop Ready control-plane 18d v1.25.4

컨트롤 플레인과 노드간의 통신

노드->컨트롤플레인

  • 패턴 : 허브 앤 스포크 API 패턴.

컨트롤플레인->노드

  • apiserver -> kubelet
  • proxy -> node or pod

API 서버에서의 노드, 파드 및 서비스로의 통신

api->other component : http연결. 암호화되지 않음. https로 통신 가능하나 검증하지 않음

컨트롤러

컨테이너 런타임 인터페이스

이미지와 이미지 레지스트리

이미지 풀 정책

  • imagepullpolicy
  • always : 컨테이너를 기동할때 마다 땡겨서(이미지 다이제스트에 변경을 판단해서) 실행. 레지스트리에 연결되어 있는 경우 추천 옵션
  • ifnotpresent : 없는 경우에만 땡김
  • never : 안 땡겨온다. 이미지가 없으면 실행이 되지 않음

이미지풀백오프

imagepullbackoff -> waiting 제일 실패가 많은 상태. 뭔가 이미지를 가져올 수 있는 권한이 없거나, 이미지 이름이나 태그를 잘못 적었거나 등의 이유로 컨테이너 이미지를 가져올 수 없는 상태라 실행할 수 없음을 의미한다. 이미지를 가져오려고 재시도를 계속하는데 재시도마다 재시도 주기가 늘어나며 최대 주기는 300초(5분)으로 쿠버네티스 코드에 고정되어 있다.

워크로드

파드 : 가장 작은 컴퓨팅 단위. 컨테이너의 그룹. deployment등에 포함되어 있지 않을 경우 singleton pod라고 부른다.

nginx 예제

apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80

이것저것 클러스터 전체 내용 가져오기

kubectl get all -A

파드 템플릿

파드는 최소 수행 단위이므로 다른 리소스에 포함되어 배포될 수 있다. 아래 예제는 잡 내부에서 정의된 파드이다. 디플로이먼트, 데몬셋 등에 포함되어 함께 정의될 수 있다.

apiVersion: batch/v1
kind: Job
metadata:
name: hello
spec:
template:
# 여기서부터 파드 템플릿이다
spec:
containers:
- name: hello
image: busybox
command: ['sh', '-c', 'echo "Hello, Kubernetes!" && sleep 3600']
restartPolicy: OnFailure
# 여기까지 파드 템플릿이다

파드의 수정

변화할 수 있는 값이 있고, 아닌 값이 있다. 아닌 값을 수정하려면 파드 삭제 후 재생성(kubectl apply -f pod.yaml --force)하여야 한다.

파드 네트워킹

각 파드에는 고유 ip가 할당된다.

컨테이너에 대한 특권모드

컨테이너 프로브

약간 하트비트. 주기적인 진단 수행. execaction tcpscoketaction httpgetaction

파드 라이프사이클(단계)

PodStatus. 상태 머신을 표현하도록 의도되지는 않았다.

  1. pending : 이미지 다운로드 등
  2. running : 하나의 파드라도 실행 성공 3.1. succeeded : 정상 종료 3.2. failed : 에러 종료
  3. unknown : pod의 상태를 얻을 수 없는 상태

파드는 자체적으로 자가 치유되지 않으며, deployment등의 자원을 통하여 스케줄링되고 자가 치유된다.

재시작 정책

restartpolicy

  • never :
  • always
  • onfailure

최대 5분으로 제한되며(10초, 20초..). 컨테이너가 10분동안 아무 문제없이 실행되면 백오프 타이머 설정

pod의 컨디션

PodStatus. 다음과 같은 타입이 있다. ㄴㅅㅁ션 ㅣㅁㄴ세개ㅠ

Status

Conditions: Type Status # 컨디션의 이름. Initialized True # 모든 초기화 컨테이너가 완료 Ready False # 파드는 요청을 처리할 수 있음 ContainersReady False # 파드의 모든 컨테이너가 레디 PodScheduled True # 파드가 노드에 스케쥴

컨테이너 프로브

프로브 =진단. kubelet이 컨테이너가 살아있는지 체크하는 메커니즘

  • exec : 컨테이너 내에서 명령 실행. return = 0 성공
  • grpc : 원격 프로시져 호출. response.status = SERVING이면 성공
  • httpGet : 200~3xx이면 성공
  • tcpsocket : 포트가 활성화 = 성공

프로브 결과

  • success : 컨테이너 진단 통과
  • failure : 컨테이너 진단 실패
  • unknown : 진단 자체가 실패

프로브 종류

  • livenessprobe : 컨테이너가 동작중인지 체크
  • readinessprobe : 요청 처리 준비중인지 체크
  • startupprobe : 애플리케이션 시작 여부 체크

파드 종료

종료에 대한 디자인이 필요하다.

  1. 종료시 term 정송
  2. stopsignal값을 보고 유예 기간을 가짐
  3. kill 시그날이 나머지 프로세스 전체에 전송
  4. 파드가 api서버로부터 삭제

초기화 컨테이너

파드의 메인 컨테이너들이 실행되기전 실행되는 특수 컨테이너 유틸리티 혹은 설정 스크립트 등이 포함됨

apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
labels:
app: myapp
spec:
containers:
- name: myapp-container
image: busybox:1.28
command: ['sh', '-c', 'echo The app is running! && sleep 3600']
initContainers:
- name: init-myservice
image: busybox:1.28
command: ['sh', '-c', "until nslookup myservice.$(cat
/var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local;
do echo waiting for myservice; sleep 2; done"]
- name: init-mydb
image: busybox:1.28
command: ['sh', '-c', "until nslookup mydb.$(cat
/var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local;
do echo waiting for mydb; sleep 2; done"]

서비스 실행을 기다리고 있으므로 해당 서비스를 만들어보자.

apiVersion: v1
kind: Service
metadata:
name: myservice
spec:
ports:
- protocol: TCP
port: 80
targetPort: 9376
---
apiVersion: v1
kind: Service
metadata:
name: mydb
spec:
ports:
- protocol: TCP
port: 80
targetPort: 9377

initcontainer가 정상 종료 되면서(nslookup으로 목표한 서비스가 확인되면서) 메인 앱인 myapp-container가 실행됨을 확인할 수 있다.

init-myservice:
...
State: Terminated
Reason: Completed
Exit Code: 0
Started: Fri, 21 Apr 2023 16:13:55 +0900
Finished: Fri, 21 Apr 2023 16:21:39 +0900
init-mydb:
...
State: Terminated
Reason: Completed
Exit Code: 0
Started: Fri, 21 Apr 2023 16:21:40 +0900
Finished: Fri, 21 Apr 2023 16:21:40 +0900
myapp-container:
...
State: Running
Started: Fri, 21 Apr 2023 16:21:41 +0900
...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 10m default-scheduler Successfully assigned default/myapp-pod to docker-desktop
Normal Pulling 10m kubelet Pulling image "busybox:1.28"
Normal Pulled 10m kubelet Successfully pulled image "busybox:1.28" in 4.087604418s
Normal Created 10m kubelet Created container init-myservice
Normal Started 10m kubelet Started container init-myservice
Normal Pulled 2m29s kubelet Container image "busybox:1.28" already present on machine
Normal Created 2m29s kubelet Created container init-mydb
Normal Started 2m29s kubelet Started container init-mydb
Normal Pulled 2m28s kubelet Container image "busybox:1.28" already present on machine
Normal Created 2m28s kubelet Created container myapp-container
Normal Started 2m28s kubelet Started container myapp-container

deployment

배치다. 일반 용례

  1. replicaset을 롤아웃하는 deployment를 만든다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80

롤아웃

deployment내의 pod를 업데이트시 한번에 쏵안하고 하나씩 갈아끼운다. 다음 명령을 확인해보면 롤아웃이 얼마나 되었는지 확인할 수 있다.

kubectl rollout status deployment <deploymentname>

replicaset

apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: frontend
labels:
app: guestbook
tier: frontend
spec:
# modify replicas according to your case
replicas: 3
selector:
matchLabels:
tier: frontend
template:
metadata:
labels:
tier: frontend
spec:
containers:
- name: php-redis
image: gcr.io/google_samples/gb-frontend:v3

다음 명령으로 디테일 확인 가능.

kubectl describe rs frontend

statefulset

상태저장 애플리케이션을 관리하는데 사용되는 워크로드 API 개체

유즈케이스

지속적인 스토리지 고유한 네트워크 식별자 배포 및 확장 롤링 업데이트

한계

  • stateful은 삭제될때까지 pod ㅈㅇ료에 대한 보장을 제공하지 않음 -롤링 업데이트를 사용하는 경우 복구 또는 수동개입이 필요할 수 있음
apiVersion: v1
kind: Service
metadata:
name: nginx
labels:
app: nginx
spec:
ports:
- port: 80
name: web
clusterIP: None
selector:
app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web
spec:
selector:
matchLabels:
app: nginx # has to match .spec.template.metadata.labels
serviceName: "nginx"
replicas: 3 # by default is 1
template:
metadata:
labels:
app: nginx # has to match .spec.selector.matchLabels
spec:
terminationGracePeriodSeconds: 10
containers:
- name: nginx
image: k8s.gcr.io/echoserver-arm:1.8
ports:
- containerPort: 80
name: web