다음일 이용해서 로컬 환경에서의 쿠버네티스 실습을 위한 환경설정을 한다.
aws있으면 그걸로한다. (하루에 천원정도 발생)
https://redbinalgorithm.tistory.com/709
기본적인 명령어
minikube status
minikube start
minikube start --driver=hyperkit
minikube ip
minikube stop
minikube delete
일단 아무거나 띄어보기
실습용 도커 컴포즈 배포
version: "3"
services:
wordpress:
image: wordpress:5.5.3-apache
environment:
WORDPRESS_DB_HOST: mysql
WORDPRESS_DB_PASSWORD: password
ports:
- "30000:80"
mysql:
image: mysql:5.6
environment:
MYSQL_ROOT_PASSWORD: password
해당 경로로 들어가서 docekr compose를 실행시켜주자.
그러면 docker필요한 이미지 다운받고 알아서 run 까지 실행
도커를 모른다면 docker와 docekr-compose 두개를 학습
https://docs.docker.com/opensource/
도커 컴포즈 실행
docker-compose up -d
잘되는거 확인 했으니 docker 내린다음 이제 쿠버네티스로 적용해보자.
docker-compose down
쿠버네티스로 배포 하기에 앞서 WordPress라는 컨테이너는 쿠버네티스에서는 Pod라는 개념으로 실행되게 된다.
Pod < ReplicaSet < Deployment 로 감싸는 식으로 구성되어 있고
외부 NodePort에 접속하면 내부 ClusterIp를 이용해서 Pod과 통신하게 된다.
쿠버네티스 설정 파일
wordpress-k8s.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: wordpress-mysql
labels:
app: wordpress
spec:
selector:
matchLabels:
app: wordpress
tier: mysql
template:
metadata:
labels:
app: wordpress
tier: mysql
spec:
containers:
- image: mariadb:10.7
name: mysql
env:
- name: MYSQL_ROOT_PASSWORD
value: password
ports:
- containerPort: 3306
name: mysql
---
apiVersion: v1
kind: Service
metadata:
name: wordpress-mysql
labels:
app: wordpress
spec:
ports:
- port: 3306
selector:
app: wordpress
tier: mysql
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: wordpress
labels:
app: wordpress
spec:
selector:
matchLabels:
app: wordpress
tier: frontend
template:
metadata:
labels:
app: wordpress
tier: frontend
spec:
containers:
- image: wordpress:5.5.3-apache
name: wordpress
env:
- name: WORDPRESS_DB_HOST
value: wordpress-mysql
- name: WORDPRESS_DB_PASSWORD
value: password
ports:
- containerPort: 80
name: wordpress
---
apiVersion: v1
kind: Service
metadata:
name: wordpress
labels:
app: wordpress
spec:
type: NodePort
ports:
- port: 80
selector:
app: wordpress
tier: frontend
실행 (wordpress-k8s 에 적용된 내용을 쿠버네티스에 적용하겠다라는 내용)
kubectl apply -f wordpress-k8s.yml
다음 명령어로 쿠버네티스에 어떤것이 있는지 알 수 있다.
kubectl get all
그럼 아까 30000이라고 임의로 주었던 포트가 쿠버네티스는 동적으로 30842라고 할당한것을 볼 수 있다.
접속하고싶으면 minikube ip에서 조회되는 ip와 포트번호로 접속하면 도커 컴포즈와 똑같은 실행을 볼 수 가 있다.
하지만 쿠버네티스로 실행 했기 때문에 내가 임의로 워드프로세스를 죽인다면 어떻게 될까??
kubectl delete {NAME}
하지만 얼마 후 다시 서버가 재실행 되는 것을 볼 수 있다.
근데 실제 서버에서는 한대로 한다면 문제가 있지 않을까?? 설정파일에 replicas 설정을 추가하자.
한번더 설정 적용
kubectl apply -f wordpress-k8s.yml
이제 다음 실습을 위해서 제거합니다.
kubectl delete -f wordpress-k8s.yml
기본 명령어
명령어 | 설명 |
apply | 원하는 상태를 적용합니다. -f 와 함께 사용 |
get | 리소스 목록 확인 : all pod node 자주씀 옵션으로 -o wide |
describe | 리소스의 상태를 자세하게 보여준다 |
delete | 리소스를 제거 |
logs | 컨테이너의 로그 확인 |
exec | 컨테이너에 명령어를 전달. 컨테이너에 접근할 때 주로 사용함 (exec -it {name} -- sh || bash) |
config | kubectl 설정 관리 |
apply
배포에서 사용하는 명렁어이다. 원하는 리소스의 상태를 yml 으로 작성 후 사용한다.
kubectl apply -f [파일명 || URL]
kubectl get pod -o wide : IP같은 상세 옵션 보기
kubectl get pod -o yaml : yaml 으로 보기 (CI 할때 파싱해서 활용가능)
kubectl get pod --show-labels : 현재 pod에 할당된 레이블을 확인할 수 있음
descrive 리소스 상세보기
get으로 못봣던애들 상세하게 볼 수 있음 pod으로 떠야하는데 안떳을 때 확인해야하는데 이때 dscribe를 사용해서 확인한다.
kubectl describe [TYPE]/[NAME] 또는 [TYPE][NAME]
Pod에 로그를 보고 싶을 때 사용
kubectl logs [NAME]
Pod에 접속하고 싶을 때
kubectl exec -it [NAME] -- bash
config
kubectl config current-context // 현재 컨텍스트 확인
kubectl config use-context minikube // 컨텍스트 설정
Pod
Pod은 쿠버네티스에서 관리하는 가장 작은 배포단위입니다.
pod안에는 하나의 컨테이너또는 여러개의 컨테이너를 만들 수 있다.
Pod 생성
kubectl run echo --image ghcr.io/subicura/echo:v1
Pod 상태를 확인해보자.
kubectl describe pod/echo
제거 해보자
kubectl delete pod/echo
근데 보통은 이렇게 명렁어로 쓰지 않고 yaml 파일에 설정을 통해서 관리한다.
echo-pod.yml 생성
apiVersion: v1
kind: Pod
metadata:
name: echo
labels:
app: echo
spec:
containers:
- name: app
image: ghcr.io/subicura/echo:v1
- apiVersion, kind,metadata 는 필수 값
쿠버네티스 컨트롤러 적용
kubectl apply -f echo-pod.yml
pod을 만들 때는 조심해야 할 점은 상태를 모니터링 해야한다. 그럴때 사용하는 것이 livenessProbe 를 사용한다.
apiVersion: v1
kind: Pod
metadata:
name: echo-lp
labels:
app: echo
spec:
containers:
- name: app
image: ghcr.io/subicura/echo:v1
livenessProbe:
httpGet:
path: /not/exist
port: 8080
initialDelaySeconds: 5
timeoutSeconds: 2 # Default 1
periodSeconds: 5 # Defaults 10
failureThreshold: 1 # Defaults 3
- initalDelaySecond : 기다렷다가 path 경로에 접속해서 실행
- failureThreadhold 1번이라도 실패하면 재시작하겠다 라는 뜻
- path : 일부러 없는 패스를 만들어서 실패를 유도함 상태를 확인하면
readinessProbe : livenessProbe는 재시작하는 거라면 컨테이너가 정상적으로 준비되어 있지 않으면 Pod으로 들어오는 요청을 제외합니다.
apiVersion: v1
kind: Pod
metadata:
name: echo-rp
labels:
app: echo
spec:
containers:
- name: app
image: ghcr.io/subicura/echo:v1
readinessProbe:
httpGet:
path: /not/exist
port: 8080
initialDelaySeconds: 5
timeoutSeconds: 2 # Default 1
periodSeconds: 5 # Defaults 10
failureThreshold: 1 # Defaults 3
이것 두개를 적절히 쓰면 어떻게 될까 livenessProbe + readinessProbe
apiVersion: v1
kind: Pod
metadata:
name: echo-health
labels:
app: echo
spec:
containers:
- name: app
image: ghcr.io/subicura/echo:v1
livenessProbe:
httpGet:
path: /
port: 3000
readinessProbe:
httpGet:
path: /
port: 3000
다중 컨테이너
하나의 Pod에 속한 컨테이너는 서로 네트워크를 localhost로 공유하고 동일한 디렉토리를 공유 할 수 잇음
apiVersion: v1
kind: Pod
metadata:
name: counter
labels:
app: counter
spec:
containers:
- name: app
image: ghcr.io/subicura/counter:latest
env:
- name: REDIS_HOST
value: "localhost"
- name: db
image: redis
logs를 사용하고 싶다면 컨테이너가 하나이기 때문에 생략해도 되지만 이제는 pod을 명시해줘야함
kubectl logs counter db || app
카운터 컨테이너에 접속
kubectl exec -it counter -c app -- sh
kubectl get po 한다음 delete 로 다삭제
현재 경로의 yml파일 설정 다삭제 가능
kubectl delete -f ./
ReplicaSet
Pod을 단독으로 만들면 Pod에 어떤 문제가 생겼을 때 자동으로 복구되지 않습니다. 이러한 Pod을 정해진 수만큼 복제하고 관리하는 것이 ReplicaSet입니다.
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: echo-rs
spec:
replicas: 1
selector:
matchLabels:
app: echo
tier: app
template:
metadata:
labels:
app: echo
tier: app
spec:
containers:
- name: echo
image: ghcr.io/subicura/echo:v1
- replicas: 몇개 사용?
- selector : 어떤 레이블을 찾을 거냐? 여기선 app은 echo면서 tier는 app
- template: 만약 셀렉터에서 못찾으면 template에서 pod을 만든다
이걸 보면 레플리카셋이 pod을 관리하는 거라고 알 수 있다. 여기서 중요한점은 pod의 레이블을 보고 레플리카셋이 관리한다는 것이다.
레이블의 정보를 변경하면 레플리카셋이 자동으로 할당하거나 제거한다.
Deployment
ReplicaSet은 단독으로 사용하지 않고 Deployment를 이용해서 ReplcaSet을 사용한다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: echo-deploy
spec:
replicas: 4
selector:
matchLabels:
app: echo
tier: app
template:
metadata:
labels:
app: echo
tier: app
spec:
containers:
- name: echo
image: ghcr.io/subicura/echo:v1
이전 레플리카셋과 대부분 차이는 없다.
실행후 get all 해보면 다음과 같이 뜬다.
여기서 만약 yml의 설정을 변경하고 다시 실행하면 어떻게 될까?
기존의거는 아직 실행중이고 새로운것을 생성하고있다. 다시 조회해보면
버전을 pod를 레플리카셋이 변경한다.
1. 버전을 업데이트하면 새로운 래플리카셋을 만든다.
2. 새로 만들어진 레플리카와 기존에 있던 레플리카가 존재하고 Pod의 개수를 조절해가면서 다음버전의 v2가 있는 리플리카셋의 개수를 늘려나가면서 이전한다.
3. 기존에 있던 레플리카가 0개가 되면 사라진다.
kubectl describe deploy/echo-deploy
버전관리
Deployment는 변경된 상태를 기록합니다.
# 히스토리 확인
kubectl rollout history deploy/echo-deploy
# revision 1 히스토리 상세 확인
kubectl rollout history deploy/echo-deploy --revision=1
# 바로 전으로 롤백
kubectl rollout undo deploy/echo-deploy
# 특정 버전으로 롤백
kubectl rollout undo deploy/echo-deploy --to-revision=2
kubectl rollout history deploy/echo-deploy
만약 버전이 문제있어서 롤백해야한다면 명령어들을 이용해서 롤백할 수도 있다.
배포전략 설정
apiVersion: apps/v1
kind: Deployment
metadata:
name: echo-deploy-st
spec:
replicas: 4
selector:
matchLabels:
app: echo
tier: app
minReadySeconds: 5
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 3
maxUnavailable: 3
template:
metadata:
labels:
app: echo
tier: app
spec:
containers:
- name: echo
image: ghcr.io/subicura/echo:v1
livenessProbe:
httpGet:
path: /
port: 3000
RollingUpdate라는 전략 설정
한번에 하나식 업데이트되던걸 3개식 변경되도록 설정을 추가함
Service
지금까지는 컨테이너를 관리하는 법을 배웠다면 이 컨테이너를 외부에 노출하는 방법을 배워보자.
Pod은 자체 IP를 가지고 다른 Pod과 통신하지만 계속 변경되서 사용하기 어렵다 그래서
Service(ClusterIp)를 이용해서 다른 Pod들과 통신하게 된다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis
spec:
selector:
matchLabels:
app: counter
tier: db
template:
metadata:
labels:
app: counter
tier: db
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:
app: counter
tier: db
service를 생성하게되는데 redis란 이름으로 등록된다. 고정 ip가 할당되면서 6379 포트를 통해서 pod의 레디스와 통신이 가능하다.
특이한점은 같은 클러스터에서 생성된 Pod이라면 redis라는 도메인으로 redis Pod에 접근 할 수 있다.
spec.ports.targetPort 도 설정해줘야하지만 containerPort와 port가 동일하기 때문에 생략가능하다.
app도 만들어본다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: counter
spec:
selector:
matchLabels:
app: counter
tier: app
template:
metadata:
labels:
app: counter
tier: app
spec:
containers:
- name: counter
image: ghcr.io/subicura/counter:latest
env:
- name: REDIS_HOST
value: "redis"
- name: REDIS_PORT
value: "6379"
NodePort
이전 가지는 kubctl 명령어를 이용해서 배시셀을 시용해서 접근가능 했다. 이제는 브라우저에서도 접근 가능하게 외부 포트를 만들어보자. 그게 노드 포트다
apiVersion: v1
kind: Service
metadata:
name: counter-np
spec:
type: NodePort
ports:
- port: 3000
protocol: TCP
nodePort: 31000
selector:
app: counter
tier: app
- 타입을 추가해야 NodePort를 해야한다. nodePort: <- 실제로 오픈되는 노드번호 내부적으로는 3000 외부적으로는 31000
- minikube ip를 이용해서 외부로 접속해보자.
이제 클러스터 외부에서도 접속 할수 있다.
LoadBalancer 만들기
minikube에 가상 LoadBalacer 만들기
Load Balancer를 사용할 수 없는 환경에서 가상 환경을 만들어 주는 것이 MetalLb 라는 것이다. minikube에서는 현재 떠 있는 노드를 Load Balancer로 설정합니다. minikube의 addons 명령어로 활성화합니다.
apiVersion: v1
kind: ConfigMap
metadata:
namespace: metallb-system
name: config
data:
config: |
address-pools:
- name: default
protocol: layer2
addresses:
- 192.168.64.2/32
config-Map을 설정한다. addresss는 minkube ip를 적습니다.
상태를 확인하면 <pending> 이라고 뜨던게 서버가 할당되어있다.
특별한 상황이 아니라면 LoadBalacer 를 이용한다 NodePort 보다
'개인공부' 카테고리의 다른 글
MySQL 쿼리 성능 진단 (0) | 2022.03.15 |
---|---|
MySQL의 특징 (0) | 2022.03.14 |
쿠버네티스 : minikube , kubelctl 로 시작해보기 (0) | 2022.02.04 |
YAML 문법 (1) | 2022.02.04 |
Server 용어정리 (0) | 2021.12.07 |