Kubernetes
분산 시스템에서 컨테이너를 운용하기 위한 노하우로 가득 채워진 세련된 오픈소스 소프트웨어
쿠버네티스는 컨테이너화된 워크로드와 서비스를 관리하기 위한 이식성이 있고, 확장가능한 오픈소스 플랫폼이다. 쿠버네티스는 선언적 구성과 자동화를 모두 용이하게 해준다. 쿠버네티스는 크고, 빠르게 성장하는 생태계를 가지고 있다. 쿠버네티스 서비스, 기술 지원 및 도구는 어디서나 쉽게 이용할 수 있다.
쿠버네티스란 명칭은 키잡이(helmsman)나 파일럿을 뜻하는 그리스어에서 유래했다. 구글이 2014년에 쿠버네티스 프로젝트를 오픈소스화했다. 쿠버네티스는 프로덕션 워크로드를 대규모로 운영하는 15년 이상의 구글 경험과 커뮤니티의 최고의 아이디어와 적용 사례가 결합되어 있다.
- 서비스 디스커버리와 로드 밸런싱
- 스토리지 오케스트레이션
- 자동화된 롤아웃과 롤백
- 자동화된 빈 패킹(bin packing)
- 자동화된 복구(self-healing)
- 시크릿과 구성 관리
쿠버네티스 장점 3가지
- 컨테이너관리
- 로드밸런싱 3 .롤링업데이트
스케줄링
- 애플리케이션을 적절한 곳에 디플로이하는 장치를 스케줄링(scheduling)
오케스트레이션
클러스터링
서비스 매시
Service Discovery (서비스 발견)
Load Balancing (부하 분산)
Routing Management (경로 관리)
Traffic Management (트래픽 관리)
Resilient (운영 탄력성)
Fault Injection (오류 주입)
Logging / Monitoring (로깅/모니터링)
Distributed Tracing (분산 추적)
Security (보안)
Authentication, Authorization (인증, 인가)
서비스 디스커버리
- 서비스간의 호출은 서비스 디스커버리가 수행
- 고정 IP 주소 : 서비스 고정 IP주소를 결정
- 호스트 파일의 엔트리 : 파일을 사용하여 서버명과 P주소를 매핑
- DNS : 서버를 사용하여 도메인명과 IP 주소를 매핑
- 구성 레지스트리 : 인프라스트럭처와 서비스를 연결하여 일원 관리
Pod
파드(Pod) 는 쿠버네티스에서 생성하고 관리할 수 있는 배포 가능한 가장 작은 컴퓨팅 단위이다.
파드 (고래 떼(pod of whales)나 콩꼬투리(pea pod)와 마찬가지로)는 하나 이상의 컨테이너의 그룹이다. 이 그룹은 스토리지/네트워크를 공유하고, 해당 컨테이너를 구동하는 방식에 대한 명세를 갖는다. 파드의 콘텐츠는 항상 함께 배치되고, 함께 스케줄되며, 공유 콘텍스트에서 실행된다. 파드는 애플리케이션 별 “논리 호스트”를 모델링한다. 여기에는 상대적으로 밀접하게 결합된 하나 이상의 애플리케이션 컨테이너가 포함된다. 클라우드가 아닌 콘텍스트에서, 동일한 물리 또는 가상 머신에서 실행되는 애플리케이션은 동일한 논리 호스트에서 실행되는 클라우드 애플리케이션과 비슷하다.
애플리케이션 컨테이너와 마찬가지로, 파드에는 파드 시작 중에 실행되는 초기화 컨테이너가 포함될 수 있다. 클러스터가 제공하는 경우, 디버깅을 위해 임시 컨테이너를 삽입할 수도 있다
값 의미 - Pending 파드가 쿠버네티스 클러스터에서 승인되었지만, 하나 이상의 컨테이너가 설정되지 않았고 실행할 준비가 되지 않았다. 여기에는 파드가 스케줄되기 이전까지의 시간 뿐만 아니라 네트워크를 통한 컨테이너 이미지 다운로드 시간도 포함된다. - Running 파드가 노드에 바인딩되었고, 모든 컨테이너가 생성되었다. 적어도 하나의 컨테이너가 아직 실행 중이거나, 시작 또는 재시작 중에 있다. Succeeded 파드에 있는 모든 컨테이너들이 성공적으로 종료되었고, 재시작되지 않을 것이다. - Failed 파드에 있는 모든 컨테이너가 종료되었고, 적어도 하나 이상의 컨테이너가 실패로 종료되었다. 즉, 해당 컨테이너는 non-zero 상태로 빠져나왔거나(exited) 시스템에 의해서 종료(terminated)되었다. - Unknown 어떤 이유에 의해서 파드의 상태를 얻을 수 없다. 이 단계는 일반적으로 파드가 실행되어야 하는 노드와의 통신 오류로 인해 발생한다.
컨테이너 상태
-
Waiting 만약 컨테이너가 Running 또는 Terminated 상태가 아니면, Waiting 상태이다. Waiting 상태의 컨테이너는 시작을 완료하는 데 필요한 작업(예를 들어, 컨테이너 이미지 레지스트리에서 컨테이너 이미지 가져오거나, 시크릿(Secret) 데이터를 적용하는 작업)을 계속 실행하고 있는 중이다. kubectl 을 사용하여 컨테이너가 Waiting 인 파드를 쿼리하면, 컨테이너가 해당 상태에 있는 이유를 요약하는 Reason 필드도 표시된다.
-
Running Running 상태는 컨테이너가 문제없이 실행되고 있음을 나타낸다. postStart 훅이 구성되어 있었다면, 이미 실행이 완료되었다. kubectl 을 사용하여 컨테이너가 Running 인 파드를 쿼리하면, 컨테이너가 Running 상태에 진입한 시기에 대한 정보도 볼 수 있다.
-
Terminated Terminated 상태의 컨테이너는 실행을 시작한 다음 완료될 때까지 실행되었거나 어떤 이유로 실패했다. kubectl 을 사용하여 컨테이너가 Terminated 인 파드를 쿼리하면, 이유와 종료 코드 그리고 해당 컨테이너의 실행 기간에 대한 시작과 종료 시간이 표시된다.
컨테이너에 구성된 preStop 훅이 있는 경우, 컨테이너가 Terminated 상태에 들어가기 전에 실행된다
컨테이너 프로브(probe)
프로브는 컨테이너에서 kubelet에 의해 주기적으로 수행되는 진단(diagnostic)이다.
- Success: 컨테이너가 진단을 통과함.
- Failure: 컨테이너가 진단에 실패함.
- Unknown: 진단 자체가 실패하였으므로 아무런 액션도 수행되면 안됨.
스테이트풀셋
디플로이먼트와 스케일링 보증
kubeadm
kubernetes 클러스터를 구축하기 위해 사용하는 툴이다. kubeadm이란, kubernetes에서 제공하는 기본적인 도구이며, kubernetes 클러스터를 가장 빨리 구축하기 위한 다양한 기능을 제공한다.
kubeadm init
- Kubernetes 컨트롤 플레인 노드를 초기화한다.
- 즉, 마스터 노드를 초기화한다.
kubeadm join
- Kubernetes 워커 노드를 초기화하고 클러스터에 연결한다.
kubeadm upgrade
- Kubernetes 클러스터를 업그레이드 한다.
kubeadm config
kubeadm token
- 부트 스트랩 토큰을 사용한 인증에 설명된대로 부트 스트랩 토큰은 클러스터에 참여하는 노드와 제어 평면 노드 사이에 양방향 신뢰를 설정하는 데 사용된다.
kubeadm reset
- kubeadm init 혹은 kubeadm join의 변경사항을 최대한 복구한다.
kubeadm version
- kubeadm 버젼은 보여준다.
kubeadm alpha
- 정식으로 배포된 기능은 아니지만 kubernetes측에서 사용자 피드백을 얻기 위해 인증서 갱신, 인증서 만료 확인, 사용자 생성, kubelet 설정 등 다양한 기능을 제공하고 있다.
kubelet
클러스터의 모든 머신에서 실행되며 Pod 및 컨테이너 시작 등의 작업을 수행하는 구성 요소이다.
kubectl
클러스터와 통신하는 커맨드라인 인터페이스 유틸이다.
각 노드와 상태를 확인할 수 있습니다
kubectl get no
NAME STATUS ROLES AGE VERSION
master Ready master 6m44s v1.13.3
worker-1 Ready <none> 5m20s v1.13.3
worker-2 Ready <none> 5m19s v1.13.3
각 노드와 상태를 확인
각 노드와 상태를 확인할 수 있습니다
kubectl get no
NAME STATUS ROLES AGE VERSION
master Ready master 6m44s v1.13.3
worker-1 Ready <none> 5m20s v1.13.3
worker-2 Ready <none> 5m19s v1.13.3
설치 확인하기
kubectl get componentstatuses
NAME STATUS MESSAGE ERROR
scheduler Healthy ok
controller-manager Healthy ok
etcd-0 Healthy {"health": "true"}
Pod 을 배포
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
labels:
app: myapp
spec:
containers:
- name: myapp-container
image: busybox
command: ['sh', '-c', 'echo Hello Kubernetes! && sleep 3600']
kubectl apply -f pod-test.yaml
Pod 이 정상적으로 실행 확인
kubectl get po
NAME READY STATUS RESTARTS AGE
myapp-pod 1/1 Running 0 6s
로그 확인
kubectl logs myapp-pod
Hello Kubernetes!
로그 확인
kubectl describe pod nginx-test
kubectl logs nginx-test
kubectl get pods --all-namespaces
kubectl get events
Kubernetes 종료
- 쿠버네티스 클러스터를 삭제하는 방법입니다
Master에서 :
$ kubectl drain {노드이름} --delete-local-data --force --ignore-daemonsets
$ kubectl delete node {노드이름}
$ kubeadm reset
Node에서 :
$ kubeadm reset
노드 | 프로토콜 | 방향 | 포트 범위 | 목적 | 누가 사용? |
Master | TCP | Inbound | 6443 | Kubernetes API server | All |
Master | TCP | Inbound | 2379-2380 | etcd server client API | kube-apiserver, etcd |
Master | TCP | Inbound | 10250 | Kubelet API | Self, Control plane |
Master | TCP | Inbound | 10251 | kube-scheduler | Self |
Master | TCP | Inbound | 10252 | kube-controller-manager | Self |
Worker | TCP | Inbound | 10250 | Kubelet API | Self, Control plane |
Worker | TCP | Inbound | 30000-32767 | NodePort Services | All |
실습 k3s
https://github.com/subicura/workshop-init [https://github.com/subicura/workshop-init]
docker 실습 — network : app-network
docker 실습 — Exam 1. 방명록 만들기
docker run --name=mongodb --network=app-network mongo:4
docker run -d --name=backend --network=app-network -e PORT=8003 -e GUESTBOOK_DB_ADDR=mongodb:27017 subicura/guestbook-backend:latest
docker run -d -p 3000:8004 -e PORT=8004 -e GUESTBOOK_API_ADDR=backend:8003 --network=app-network subicura/guestbook-frontend:latest
http://13.125.200.94:3000/
Docker Compose 실습 — Exam 1. 방명록 만들기
version: '3'
services:
web:
image: subicura/docker-workshop-app:1
ports:
- "4567:4567"
docker-compose up -d
version: '3'
services:
wordpress:
image: wordpress
environment:
WORDPRESS_DB_HOST: mysql
WORDPRESS_DB_NAME: wp
WORDPRESS_DB_USER: wp
WORDPRESS_DB_PASSWORD: wp
ports:
- "8000:80"
restart: always
mysql:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: wp
MYSQL_DATABASE: wp
MYSQL_USER: wp
MYSQL_PASSWORD: wp
docker-compose up -d
docker-compose ps //목록
docker-compose logs -f //로그
docker-compose down //종료 후 제거
version: '3'
services:
frontend:
image: subicura/guestbook-frontend:latest
environment:
PORT: 8000
GUESTBOOK_API_ADDR: backend:8000
ports:
- "3000:8000"
restart: always
backend:
image: subicura/guestbook-backend:latest
environment:
PORT: 8000
GUESTBOOK_DB_ADDR: mongodb:27017
ports:
- "8002:80"
restart: always
mongodb:
image: mongo:4
docker-compose up -d
docker system prune -a //이미지 정리
Kubernetes 실습
kubectl
- 명령어
kubectl
apply
Apply a configuration to a resource by filename or stdin
get
Display one or many resources
describe
Show details of a specific resource or group of resources
delete
Delete resources by filenames, stdin, resources and names, or by resources and label selector
logs
Print the logs for a container in a pod
exec
Execute a command in a container
- 기본 오브젝트
kubectl api-resources
node
pod
replicaset
deployment
service
loadbalancer
ingress
volume
configmap
secret
namespace
- 다양한 사용법 – get
# pod, replicaset, deployment, service 조회
kubectl get all
# node 조회
kubectl get no
kubectl get node
kubectl get nodes
# 결과 포멧 변경
kubectl get nodes -o wide
kubectl get nodes -o yaml
kubectl get nodes -o json
kubectl get nodes -o json |
jq ".items[] | {name:.metadata.name} + .status.capacity"
– describe
# kubectl describe type/name
# kubectl describe type name
kubectl describe node <node name>
kubectl describe node/<node name>
– 그외 자주 사용하는 명령어
kubectl exec -it <POD_NAME>
kubectl logs -f <POD_NAME|TYPE/NAME>
kubectl apply -f <FILENAME>
kubectl delete -f <FILENAME>
Pod
kubectl run whoami –image subicura/whoami:1 # deprecated soon.. kubectl describe pods whoami kubectl describe po/whoami
- Events 확인
Successfully assigned -> Pulling image -> Successfully pulled image -> Created container -> Started container
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute for 300s
node.kubernetes.io/unreachable:NoExecute for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled <unknown> default-scheduler Successfully assigned default/whoami to ip-172-26-1-227
Normal Pulling 4m kubelet, ip-172-26-1-227 Pulling image "subicura/whoami:1"
Normal Pulled 3m52s kubelet, ip-172-26-1-227 Successfully pulled image "subicura/whoami:1"
Normal Created 3m50s kubelet, ip-172-26-1-227 Created container whoami
Normal Started 3m50s kubelet, ip-172-26-1-227 Started container whoami
kubectl delete po/whoami
kubectl delete deployment/whoami
- livenessProbe 예제 (살아 있는지 조사)
apiVersion: v1
kind: Pod
metadata:
name: whoami-lp
labels:
type: app
spec:
containers:
- name: app
image: subicura/whoami:1
livenessProbe:
httpGet:
path: /not/exist
port: 8080
initialDelaySeconds: 5
timeoutSeconds: 2 # Default 1
periodSeconds: 5 # Defaults 10
failureThreshold: 1 # Defaults 3
- readinessProbe 예제 (준비가 되었는지 조사)
apiVersion: v1
kind: Pod
metadata:
name: whoami-rp
labels:
type: app
spec:
containers:
- name: app
image: subicura/whoami:1
readinessProbe:
httpGet:
path: /not/exist
port: 8080
initialDelaySeconds: 5
timeoutSeconds: 2 # Default 1
periodSeconds: 5 # Defaults 10
failureThreshold: 1 # Defaults 3
- health check 예제
apiVersion: v1
kind: Pod
metadata:
name: whoami-health
labels:
type: app
spec:
containers:
- name: app
image: subicura/whoami:1
livenessProbe:
httpGet:
path: /
port: 4567
readinessProbe:
httpGet:
path: /
port: 4567
- multi container 예제
apiVersion: v1
kind: Pod
metadata:
name: whoami-redis
labels:
type: stack
spec:
containers:
- name: app
image: subicura/whoami-redis:1
env:
- name: REDIS_HOST
value: "localhost"
- name: db
image: redis
Replicaset
레플리카셋의 목적은 레플리카 파드 집합의 실행을 항상 안정적으로 유지하는 것이다. 이처럼 레플리카셋은 보통 명시된 동일 파드 개수에 대한 가용성을 보증하는데 사용한다.
apiVersion: apps/v1beta2
kind: ReplicaSet
metadata:
name: whoami-rs
spec:
replicas: 4
selector:
matchLabels:
type: app
service: whoami
template:
metadata:
labels:
type: app
service: whoami
spec:
containers:
- name: whoami
image: subicura/whoami:1
livenessProbe:
httpGet:
path: /
port: 4567
Deployment
디플로이먼트(Deployment) 는 파드와 레플리카셋(ReplicaSet)에 대한 선언적 업데이트를 제공한다.
디플로이먼트에서 의도하는 상태 를 설명하고, 디플로이먼트 컨트롤러(Controller)는 현재 상태에서 의도하는 상태로 비율을 조정하며 변경한다. 새 레플리카셋을 생성하는 디플로이먼트를 정의하거나 기존 디플로이먼트를 제거하고, 모든 리소스를 새 디플로이먼트에 적용할 수 있다.
kubectl get rs -w
apiVersion: apps/v1beta2
kind: Deployment
metadata:
name: whoami-deploy
spec:
replicas: 3
selector:
matchLabels:
type: app
service: whoami
template:
metadata:
labels:
type: app
service: whoami
spec:
containers:
- name: whoami
image: subicura/whoami:1
livenessProbe:
httpGet:
path: /
port: 4567
- 배포 오류로 이전으로 되돌아가야 할 때 kubectl rollout undo deploy/whoami-deploy
service
파드 집합에서 실행중인 애플리케이션을 네트워크 서비스로 노출하는 추상화 방법 쿠버네티스를 사용하면 익숙하지 않은 서비스 디스커버리 메커니즘을 사용하기 위해 애플리케이션을 수정할 필요가 없다. 쿠버네티스는 파드에게 고유한 IP 주소와 파드 집합에 대한 단일 DNS 명을 부여하고, 그것들 간에 로드-밸런스를 수행할 수 있다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis
spec:
selector:
matchLabels:
type: db
service: redis
template:
metadata:
labels:
type: db
service: redis
spec:
containers:
- name: redis
image: redis
ports:
- containerPort: 6379
protocol: TCP
---
apiVersion: v1
kind: Service
metadata:
name: redis
spec:
ports:
- port: 6379
protocol: TCP
selector:
type: db
service: redis
$ kubectl describe service/redis
Name: redis
Namespace: default
Labels: <none>
Annotations: Selector: service=redis,type=db
Type: ClusterIP
IP: 10.43.109.181
Port: <unset> 6379/TCP
TargetPort: 6379/TCP
Endpoints: 10.42.0.12:6379,10.42.0.13:6379,10.42.0.14:6379
Session Affinity: None
Events: <none>
apiVersion: apps/v1
kind: Deployment
metadata:
name: whoami
spec:
selector:
matchLabels:
type: app
service: whoami
template:
metadata:
labels:
type: app
service: whoami
spec:
containers:
- name: whoami
image: subicura/whoami-redis:1
env:
- name: REDIS_HOST
value: "redis"
- name: REDIS_PORT
value: "6379"
kubectl exec -it pod/whoami-68f4d76b9-nxr47 sh
- telnet 설치
apk add curl busybox-extras
- 노드 포트
apiVersion: v1
kind: Service
metadata:
name: whoami
spec:
type: NodePort
ports:
- port: 4567
protocol: TCP
selector:
type: app
service: whoami
$kubectl get all
4567:31807/TCP
http://13.125.200.94:31807/
load balancer
- 노드밸런스
apiVersion: v1
kind: Service
metadata:
name: whoami
spec:
type: LoadBalancer
ports:
- port: 8000
targetPort: 4567
protocol: TCP
selector:
type: app
service: whoami
ingress
클러스터 내의 서비스에 대한 외부 접근을 관리하는 API 오브젝트이며, 일반적으로 HTTP를 관리함. 인그레스는 부하 분산, SSL 종료, 명칭 기반의 가상 호스팅을 제공할 수 있다.
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: whoami-v1
annotations:
ingress.kubernetes.io/rewrite-target: "/"
ingress.kubernetes.io/ssl-redirect: "false"
spec:
rules:
- host: v1.whoami.13.125.200.94.sslip.io
http:
paths:
- path: /
backend:
serviceName: whoami-v1
servicePort: 4567
---
apiVersion: apps/v1beta2
kind: Deployment
metadata:
name: whoami-v1
spec:
replicas: 3
selector:
matchLabels:
type: app
service: whoami
version: v1
template:
metadata:
labels:
type: app
service: whoami
version: v1
spec:
containers:
- name: whoami
image: subicura/whoami:1
livenessProbe:
httpGet:
path: /
port: 4567
---
apiVersion: v1
kind: Service
metadata:
name: whoami-v1
spec:
ports:
- port: 4567
protocol: TCP
selector:
type: app
service: whoami
version: v1
http://v1.whoami.13.125.200.94.sslip.io/