보통 동적 프로비저닝 더 많이 사용
💡 동적 프로비저닝은 어떤 정보로 pv를 생성하는가?
➜ StorageClass
라는 오브젝트를 통해 생성
storageClass는 pv
를 생성하기 위한 탬플릿
을 가지고 있음
pv
를 생성하기 위한 탬플릿
을 보유한 오브젝트
🎈 StorageClass 리소스 확인
$ kubectl api-resources | grep storageclass
storageclasses sc storage.k8s.io/v1 false StorageClass
StrotageClass yaml 파일 예시
spec이 없는 대신 중요한 것 ➜ provisioner
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: standard
provisioner: kubernetes.io/aws-ebs
parameters:
type: gp2
reclaimPolicy: Retain
allowVolumeExpansion: true # 볼륨 확장 허용 ➜ 실제로 거의 다 지원
mountOptions:
- debug
volumeBindingMode: Immediate
🌟 provisioner와 parameter가 가장 중요
provisioner
: 어느 스토리지에서 pv를 만들 것인가parameters
: 어떤 정보를 가지고 pv를 만들 것인가 (프로비저너에 따라 다름volumeBindingMode
: pvc - pv 연결 모드1) 사전 준비
exports 파일 수정
/etc/exports
$ sudo cat /etc/exports
...
/nfsvolume 192.168.100.0/24(rw,sync,no_subtree_check,no_root_squash)
nfs 커널 서버 재시작
$ sudo systemctl restart nfs-kernel-server
NFS 연결할 디렉토리 생성
$ sudo mkdir /nfsvolume
생성 된 볼륨 확인
$ sudo ls /nfsvolume
index.html
2) 프로비저너 동기화
~
$ git clone https://github.com/kubernetes-sigs/nfs-subdir-external-provisioner.git
deploy 디렉토리로 이동
$ cd ~/nfs-subdir-external-provisioner/deploy
3) NFS 서버 역할 파드 배포
deployment.yaml
...
env:
- name: PROVISIONER_NAME
value: k8s-sigs.io/nfs-subdir-external-provisioner
- name: NFS_SERVER
value: 192.168.100.100 ✔️
- name: NFS_PATH
value: /nfsvolume ✔️
volumes:
- name: nfs-client-root
nfs:
server: 192.168.100.100 ✔️
path: /nfsvolume ✔️
배포
$ kubectl create -f deployment.yaml
배포 확인
$ kubectl get deploy,rs,po
4) 스토리지 클래스 생성
kubectl create -f class.yaml
스토리지 클래스 확인
$ kubectl get sc
볼륨 바인딩 모드 ➜ 클라우드가 아니기 때문에 보통 immediate
로 설정 ➜ 체크표시 하기
🎈 NFS 동적 프로비저닝 실습
"nfs-client"라는 SC를 사용해서 pv 동적 할당
pvc만 생성하면 자동으로 pv 할당
mypvc-dynamic.yaml
apiVersion: v1
kind: PersistentVolumeClaim ✔️
metadata:
name: mypvc-dynamic
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 1G
storageClassName: 'nfs-client' ✔️
생성
$ kubectl create -f mypvc-dynamic.yaml
pvc 생성 확인
$ kubectl get pvc
생성 확인
# 디렉토리가 만들어져있음 -> 디렉토리 이름 : [NS][PVC][PV]
sudo ls /nfsvolume
sudo ls -l /nfsvolume/default-myvpc xxx
생성된 볼륨에 index.html 파일 생성
$ echo "Hello NFS Dynamic Provision" | sudo tee /nfsvolume/xxx/index.html
myweb-rs-dynamic.yaml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: myweb-rs
spec:
replicas: 3
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: myweb
image: httpd
volumeMounts:
- name: myvol
mountPath: /usr/local/apache2/htdocs
volumes:
- name: myvol
persistentVolumeClaim:
claimName: mypvc-dynamic
웹 서버 rs 생성
$ kubectl create -f myweb-rs-dynamic.yaml
"Hello NFS Dynamic Provision" 나오는지 확인
$ curl 192.168.100.240
➕ pvc 지우면 pv도 지워짐
➜ reclaimpolicy를 delete로 설정했기 때문
➜ 데이터 남기고 싶으면 retain 정책으로 설정
특정 스토리지 클래스가 필요하지 않은 pvc에 대해 스토리지를 동적으로 프로비저닝 하기 위해 사용
sc는 pvc를 생성할 때, pv에 대한 정보를 가지고 알아서 pv를 생성해주기 때문에 pv 생성을 신경 쓸 필요 x
➕ pvc 생성 파일에서 StorageClassName 주석처리 ➜ 스토리지 형식 지정 안한 것
💡
스토리지 클래스
의 metadata 필드에annotation
설정
~/nfs-subdir-external-provisioner/deploy/class.yaml
annotations: ✔️
storageclass.kubernetes.io/is-default-class: "true"
이름 옆에 defualt 생성되어있음
$ kubectl get sc
nfs-client(default)✔️
annotation 삭제
$ kubectl annotate sc nfs-client storageclass.kubernetes.io/is-default-class-
이름 옆에 default x
$ kubectl get sc
nfs-client✔️ # default 없어져있음
➕
클라우드
에서 프로비저닝 하면기본 스토리지 클래스
지정해줌
ex. 아마존 EBS
버전 관리
보통 statless 리소스는 전부 Deploy로 생성
🎈 Deployment 리소스 확인
$ kubectl api-resources | grep deployment
deployments deploy apps/v1 true Deployment
🎈 spec 확인
replicaset과 동일한 필드
$ kubectl explain deploy.spec
1) Deployment RollingUpdate
✔️ 기본 replicas 수 확인 필수
recreate 차입에선 쓸모 x
deploy.spec.strategy.rollingUpdate
maxSurge
초과
할 수 있는가maxUnavailable
지울
수 있는가deploy.spec.minReadySeconds
준비 된 상태가 될 때까지 대기시간을 벌어주는 것
➜ 초 단위
Default : 0 초
liveness probe, startup probe 설정 시, 쓸모 x
➜ probe
로 세팅하는 것이 현명
3) Revision History 제한 개수
deploy.spec.revisionHistoryLimit
표시할 수 있는 히스토리 개수 제한
Default : 10개
➜ rs가 최대 10개까지 남아있다는 말과 동일
🎈 Deploy 생성 실습
Deploy 생성 yaml 파일
myweb-deploy.yaml
apiVersion: apps/v1
kind: Deployment ✔️
metadata:
name: myweb-deploy
spec:
replicas: 3 ✔️
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: myweb
image: ghcr.io/c1t1d0s7/go-myweb
ports:
- containerPort: 8080
Deploy 생성
작업 디렉토리 : ~/yaml/deploy
$ kubectl create -f .
생성 확인
kubectl get deploy,rs,po
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/myweb-deploy 3/3 3 3 6m9s
NAME DESIRED CURRENT READY AGE
replicaset.apps/myweb-deploy-657f957c85 3 3 3 6m9s
NAME READY STATUS RESTARTS AGE
pod/myweb-deploy-657f957c85-mcfbt 1/1 Running 0 6m9s
pod/myweb-deploy-657f957c85-nngsx 1/1 Running 0 6m9s
pod/myweb-deploy-657f957c85-v4vtq 1/1 Running 0 6m9s
➜ Deploy가 RS와 Pod도 만드는 형태
기본 기능은 RS와 동일
🌟 애플리케이션 배포 전략 모델 참고 : Six Strategies for Application Deployment
➜ k8s 및 모든 애플리케이션 배포 시 사용
deploy.spec.strategy
Recreate
: 기존의 것을 삭제하고 새롭게 RS 생성해서 연결Downtime
발생RollingUpdate
: 하나씩 천천히 옮겨가는 형태무중단 시스템
Roll Out
(롤 아웃) == 버전 이동
Roll Back
(롤백) == 이전 롤아웃 상태로 복구
💡 주의
두 RS가 혼재하고 있기 때문에 각 API, DB 등의 매칭 상태 확인 후 미리 환경 구축
LB 제어 불가 ➜ 네트워크 트래픽 컨트롤 방법 x
🎈 Deploy Rollout & Rollback 실습
mydeploy-v1
apiVersion: apps/v1
kind: Deployment ✔️
metadata:
name: myweb-deploy
spec:
replicas: 3
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: myweb
image: ghcr.io/c1t1d0s7/go-myweb:v1.0
ports:
- containerPort: 8080
myweb-svc-lb
apiVersion: v1
kind: Service
metadata:
name: myweb-svc-lb
spec:
type: LoadBalancer ✔️
selector:
app: web
ports:
- port: 80
targetPort: 8080
생성
작업 디렉토리 : ~/yaml/deployment
$ kubectl create -f .
생성 확인
kubectl get deploy,rs,po,svc,ep
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/myweb-deploy 3/3 3 3 108s
NAME DESIRED CURRENT READY AGE
replicaset.apps/myweb-deploy-7d649cccb8 3 3 3 108s
NAME READY STATUS RESTARTS AGE
pod/myweb-deploy-7d649cccb8-2b44l 1/1 Running 0 108s
pod/myweb-deploy-7d649cccb8-btbwj 1/1 Running 0 108s
pod/myweb-deploy-7d649cccb8-dx6k5 1/1 Running 0 108s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.233.0.1 <none> 443/TCP 37h
service/myweb-svc-lb LoadBalancer 10.233.9.184 192.168.100.240 80:30365/TCP 108s
NAME ENDPOINTS AGE
endpoints/kubernetes 192.168.100.100:6443 37h
endpoints/myweb-svc-lb 10.233.90.33:8080,10.233.92.50:8080,10.233.96.69:8080 108s
Rollout 상태 확인
$ kubectl rollout status deployment
myweb-deploy
deployment "myweb-deploy" successfully rolled out
배포 완료 상태
실시간 확인
1) Deploy, RS, 파드 확인
$ watch -d -n1 kubectl get deploy,rs,po
2) 버전 변경 확인
➜ 버전 부분 계속해서 변경
$ watch -d -n1 curl 192.168.100.240
...
===Version 4.0=== ✔️
Hello World!
myweb-deploy-54948b568c-tkrb9
🎈 Rollout 히스토리 확인
➜ 어떤 방식으로 롤아웃 했는지 확인 가능
$ kubectl rollout history
$ kubectl rollout history deployment myweb-deploy
REVISION CHANGE-CAUSE
1 <none>
2 <none>
3 kubectl set image deployments myweb-deploy myweb=ghcr.io/c1t1d0s7/go-myweb:v2.0 --record=true
5 Change Go Myweb version from 3 to 4
6 Change Go Myweb version from 3 to 4
--revision=xx
: 상세 revision의 히스토리 확인 가능
🎈 일반적인 방법
➜ replace, apply, patch, edit..
$ kubectl replace -f mydeploy.yaml
$ kubectl apply -f mydeploy.yaml
$ kubectl patch deploy mydeploy --patch [설정 : YAML, JSON]
--record
옵션 불가
🎈 kubectl set 명령어
$ kubectl set image
➜ 이미지, 셀렉터 등 변경 가능
kubectl set image deployments myweb-deploy myweb=ghcr.io/c1t1d0s7/go-myweb:v2.0 --record
--record
옵션 : 명령을 히스토리에 저장
🎈
$ kubectl rollout undo
kubectl rollout undo deploy myweb-deploy
--to-revision
: 특정 차수의 revision으로 변경
Rollback 하기위해 버전을 변경해도 존 RS 남겨 둠
$ kubectl get rs
NAME DESIRED CURRENT READY AGE
replicaset.apps/myweb-deploy-54f877ddcb 1 1 0 117s
replicaset.apps/myweb-deploy-7d649cccb8 3 3 3 12m ✔️ # 기존 버전
Deploy Rollout 상태 확인
$ kubectl rollout status deploy myweb-deploy
다시 Rollback
$ kubectl rollout undo deploy myweb-deploy
변경되는 과정 실시간 확인
$ kubectl rollout status deploy myweb-deploy
Waiting for deployment "myweb-deploy" rollout to finish: 2 out of 3 new replicas have been updated...
Waiting for deployment "myweb-deploy" rollout to finish: 2 out of 3 new replicas have been updated...
Waiting for deployment "myweb-deploy" rollout to finish: 2 out of 3 new replicas have been updated...
Waiting for deployment "myweb-deploy" rollout to finish: 1 old replicas are pending termination...
Waiting for deployment "myweb-deploy" rollout to finish: 1 old replicas are pending termination...
pods.spec.containers.env
작업 디렉토리 : ~/env/
컨테이너 내에 환경변수를 별도로 지정
myweb.yaml
apiVersion: v1
kind: Pod
metadata:
name: myweb-env
spec:
containers:
- name: myweb
image: ghcr.io/c1t1d0s7/go-myweb:alpine
env: ✔️
- name: MESSAGE
value: "Customized Hello World"
비기밀데이터
저장 (key-value)
다른 오브젝트가 사용할 구성을 저장할 수 있는 API 오브젝트
파드와 동일한 NS(Name Space)에 존재해야 함
🎈 제공 방법
환경변수
로 제공볼륨/파일
로 제공🎈 ConfigMap 리소스 정보 확인
$ kubectl api-resources | grep configmap
configmaps cm v1 true ConfigMap
cm.data
구성에 대한 데이터를 포함하는 필드
KIND: ConfigMap
VERSION: v1
FIELD: data <map[string]string>
DESCRIPTION:
Data contains the configuration data. Each key must consist of alphanumeric
characters, '-', '_' or '.'. Values with non-UTF-8 byte sequences must use
the BinaryData field. The keys stored in Data must not overlap with the
keys in the BinaryData field, this is enforced during validation process.
cm.immutable
immutable을 true로 설정하면 값을 바꿀 수 x
mymessage.yaml
환경 변수를 키 : 벨류 값으로 선언
apiVersion: v1
kind : ConfigMap
metadata:
name: mymessage ✔️
data:
MESSAGE: Customized Hello ConfigMap ✔️
ConfigMap 생성
kubectl create -f .
생성 확인
➜ (키 : 벨류) 여러개 세팅하면 data 갯수 증가
kubectl get cm
NAME DATA AGE
kube-root-ca.crt 1 40h
mymessage 1 ✔️ 4s
ConfigureMap 상세 정보 확인
$ kubectl describe cm mymessage
Name: mymessage
...
Data
====
MESSAGE: ✔️
----
Customized Hello ConfigMap ✔️
...
💡 환경 변수를 ConfigMap에 써놓고 참조
myweb.yaml
파드 생성 시 ConfigureMap 이름으로 참조
apiVersion: v1
kind: Pod
metadata:
name: myweb-env-config
spec:
containers:
- name: myweb
image: ghcr.io/c1t1d0s7/go-myweb:alpine
envFrom:
- configMapRef: ✔️
name: mymessage
참조 확인
$ kubectl exec -it myweb-env-config -- sh
> env
...
MESSAGE=Customized Hello ConfigMap ✔️
...
🎈 참고 필드
pods.spec.volumes.configMap
: 볼륨 생성시 참조할 컨피그 맵의 이름
pods.spec.containers.env.valueFrom
: 환경변수 값의 source
pods.spec.containers.env.valueFrom.configMapKeyRef
: 컨피그 맵의 키(이름) select
pods.spec.containers.envFrom
: 컨피그 맵 지정하면 컨피그 맵의 모든 데이터 참조 가능
pods.spec.containers.env.valueFrom
: 컨피그 맵 몇 개만 추려서 하고싶다
🎈 볼륨/파일로 제공 실습
myweb-cm-vol.yaml
볼륨 생성 시 ConfigMap을 참조해서 데이터 생성
apiVersion: v1
kind: Pod
metadata:
name: myweb-cm-vol
spec:
containers:
- name: myweb
image: ghcr.io/c1t1d0s7/go-myweb:alpine
volumeMounts:
- name: cmvol
mountPath: /myvol
volumes:
- name: cmvol
configMap: ✔️
name: mymessage
기밀데이터
저장 (key-value)
암호, 토큰 또는 키와 같은 소량의 중요한 데이터를 포함
사용자의 기밀 데이터를 애플리케이션 코드에 넣을 필요가 없음을 뜻함
➜ 안전하진 x
💡 반드시 함께 사용
- 클라우드 : 각 클라우드의 Key Management System과 연동해서 사용 (ex. KMS of AWS)
- 온프렘 : Hashicorp의 Vault와 연동시켜서 암호화
시크릿의 타입 : 벨류가 어떤 형태인가
➜ 여러 종류의 기밀 데이터를 프로그래밍 방식으로 용이하게 처리하기 위해 사용
ex. kubernetes.io/dockercfg, kubernetes.io/tls ... ➜ Docker, HTTPS 등에 대한 증명 설정 가능
➕ base64를 사용하여 인코딩
value--base64➜
encoded data
base64는 암호화 x
secret.yaml
data 필드를 인코딩하여 선언해야 함
apiVersion: v1
kind: Secret
metadata:
name: mydata
type: Opaque ✔️
data:
id: admin # 이 것과
pwd: P@ssw0rd # 이 것을 인코딩 해야함
$ echo "admin" | base64
YWRtaW4K
$ echo "p@ssw0rd" | base64
cEBzc3cwcmQK
apiVersion: v1
kind: Secret
metadata:
name: mydata
type: Opaque
data:
id: YWRtaW4K ✔️
pwd: cEBzc3cwcmQK ✔️
참조 방법
1) envFrom.secretRef : 시크릿의 전체
데이터를 이름
으로 참조
apiVersion: v1
kind: Pod
metadata:
name: myweb-secret
spec:
containers:
- name: myweb
image: ghcr.io/c1t1d0s7/go-myweb:alpine
envFrom: ✔️
- secretRef: ✔️
name: mydata
2) env.valueFrom : 시크릿의 데이터 중 일부
를 키
를 사용하여 참조
apiVersion: v1
kind: Pod
metadata:
name: myweb-env
spec:
containers:
- name: myweb
image: ghcr.io/c1t1d0s7/go-myweb:alpine
env:
valueFrom: ✔️
secretKeyRef: ✔️
name: mydata
key: id
myweb-sec-vol.yaml
볼륨 생성 시 시크릿 파일의 전체
데이터를 시크릿 이름
으로 참조
apiVersion: v1
kind: Pod
metadata:
name: myweb-sec-vol
spec:
containers:
- name: myweb
image: ghcr.io/c1t1d0s7/go-myweb:alpine
volumeMounts:
- name: secvol
mountPath: /secvol
volumes:
- name: secvol
secret:
secretName: mydata
Nginx ➜ 비동기방식
🎈 사용 디렉토리
/etc/nginx/conf.d
🎈 생성할 디렉토리
conf
: Nginx를 위한 설정 ➜ configMap
사용x509
: 인증 ➜ Secret
사용➕ lets encrypt ➜ 도메인 가지고 있으면 무료 인증 서명 가능한 사이트 (갱신기간 : 3년)
보안상 위험하지만 테스트에는 유용
Secret
사용
Type: kubernetes.io/tls
✔️ 원래는 제 3자(CA)가 내 인증서에 서명을 해줘야하지만 현재 상황에선는 불가하므로 자체서명인증서 생성
x509 디렉토리 생성
$ mkdir x509 && cd x509
프라이빗 키 생성
➜ RSA 방식 / 키 이름 / 키 길이 지정
$ openssl genrsa -out nginx-tls.key 2048
Generating RSA private key, 2048 bit long modulus (2 primes)
.......+++++
..+++++
e is 65537 (0x010001)
퍼블릭 키 생성
$ oenssl rsa -in nginx-tls.key -pubout -out nginx-tls
csr 파일 생성
➜ 원래는 csr
(certificate signing request : 인증 서명 요청) 파일 생성하여 CA 기관(서명 사이트)에 전송
$ openssl req -new -key nginx-tls.key -out nginx-tls.csr
You are about to be asked to enter information that will be incorporated
...
-----
Country Name (2 letter code) [AU]: KR
State or Province Name (full name) [Some-State]:Seoul
Locality Name (eg, city) []:Seoul
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Encore Inc.
Organizational Unit Name (eg, section) []:IT
Common Name (e.g. server FQDN or YOUR name) []:www.example.com
Email Address []:admin@encore.com
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
자체 서명 인증서 발급 (crt 파일)
$ openssl req -x509 -days 3650 -key nginx-tls.key -in nginx-tls.csr -out nginx-tls.crt
생성 확인 및 파일 정리
$ ls
nginx-tls nginx-tls.crt nginx-tls.csr nginx-tls.key
$ rm nginx-tls nginx-tls.csr
$ ls
nginx-tls.crt nginx-tls.key
crt 파일(자체 서명 인증서), key 파일만 있으면 인증 가능하므로 나머지 삭제
configMap
사용
conf 디렉토리 생성
mkdir conf && cd conf
nginx-tls.conf
TLS 설정파일(conf) ➜ crt 파일, key 파일 필요함을 확인
server {
listen 80;
listen 443 ssl;
server_name myapp.example.com;
ssl_certificate /etc/nginx/ssl/tls.crt; ✔️
ssl_certificate_key /etc/nginx/ssl/tls.key; ✔️
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!MD5;
location / {
root /usr/share/nginx/html;
index index.html;
}
}
💡 TLS 시크릿 참고하여 만들기
CM 생성
nginx-tls-config.yaml
데이터의 키가 파일 명이 되어야함
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-tls-config
data:
nginx-tls.conf: |
server {
listen 80;
listen 443 ssl;
server_name myapp.example.com;
ssl_certificate /etc/nginx/ssl/tls.crt;
ssl_certificate_key /etc/nginx/ssl/tls.key;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!MD5;
location / {
root /usr/share/nginx/html;
index index.html;
}
}
Secret 생성
nginx-tls-secret.yaml
인증서와 키 파일 변환해서 삽입
base x509/[변환할 파일] -w 0 ➜ 한 줄로 출력
apiVersion: v1
kind: Secret
metadata:
name: nginx-tls-secret
type: kubernetes.io/tls
data:
# base64 x509/nginx-tls.crt -w 0
tls.crt: |
LS0tLS1C... ✔️
# base64 x509/nginx-tls.key -w 0
tls.key: |
LS0tLS1C... ✔️
Pod 생성
nginx-https-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx-https-pod
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
volumeMounts:
- name: nginx-config
mountPath: /etc/nginx/conf.d
- name: nginx-certs
mountPath: /etc/nginx/ssl
volumes:
- name: nginx-config
configMap:
name: nginx-tls-config
- name: nginx-certs
secret:
secretName: nginx-tls-secret
SVC 생성
서비스 만들던 포트포워딩을 하던 상관 없지만 현재 서비스 생성
nginx-svc-lb.yaml
apiVersion: v1
kind: Service
metadata:
name: nginx-svc-lb
spec:
type: LoadBalancer
selector:
app: nginx
ports:
- name: http
port: 80
targetPort: 80
- name: https
port: 443
targetPort: 443
🎈 Test
1) Curl Test
$ curl -k https://192.168.100.x
자체 서명 인증서로 curl 테스트 할 때는
curl -k (--insecure)라는 옵션을 사용하여 https 인증
2) 웹 브라우저 Test
https://192.168.100.x
로 접속
오류 발생
인증서가 올바르지 않음 ➜ 내가 나에게 인증했기 떄문에 상위 경로가 없기 때문
안전하지 않은 페이지로 돌아가서 확인해보면 Nginx 페이지 뜨는 것 확인 가능
Ceph
실제 스토리지를 구현하는 오픈소스
Integrated Storage
(통합 스토리지)
하나의 스토리지에서 Block, File, Object 스토리지를 모두 제공
(보통은 Block, File, Object 스토리지를 따로 구매 -> 비용 높)
Rook
쿠버네티스에 맞게 스토리지를 구현해주는 오픈소스
ROOK
쿠버네티스 스토리지를 생성하기 위한 오픈소스
주의사항 : 스토리지로 사용할 디스크가 우리 VM에 있어야함
VM에 디스크 추가 및 스토리지 연결
Vagrantfile
Vagrant.configure("2") do |config|
# Define VM
config.vm.define "k8s-node1" do |ubuntu|
ubuntu.vm.box = "ubuntu/focal64"
ubuntu.vm.hostname = "k8s-node1"
ubuntu.vm.network "private_network", ip: "192.168.100.100"
ubuntu.vm.provider "virtualbox" do |vb|
vb.name = "k8s-node1"
vb.cpus = 2
vb.memory = 4000
unless File.exist?('./.disk/ceph1.vdi')
vb.customize ['createmedium', 'disk', '--filename', './.disk/ceph1.vdi', '--size', 10240]
end
vb.customize ['storageattach', :id, '--storagectl', 'SCSI', '--port', 2, '--device', 0, '--type', 'hdd', '--medium', './.disk/ceph1.vdi']
end
end
config.vm.define "k8s-node2" do |ubuntu|
ubuntu.vm.box = "ubuntu/focal64"
ubuntu.vm.hostname = "k8s-node2"
ubuntu.vm.network "private_network", ip: "192.168.100.101"
ubuntu.vm.provider "virtualbox" do |vb|
vb.name = "k8s-node2"
vb.cpus = 2
vb.memory = 3000
unless File.exist?('./.disk/ceph2.vdi')
vb.customize ['createmedium', 'disk', '--filename', './.disk/ceph2.vdi', '--size', 10240]
end
vb.customize ['storageattach', :id, '--storagectl', 'SCSI', '--port', 2, '--device', 0, '--type', 'hdd', '--medium', './.disk/ceph2.vdi']
end
end
config.vm.define "k8s-node3" do |ubuntu|
ubuntu.vm.box = "ubuntu/focal64"
ubuntu.vm.hostname = "k8s-node3"
ubuntu.vm.network "private_network", ip: "192.168.100.102"
ubuntu.vm.provider "virtualbox" do |vb|
vb.name = "k8s-node3"
vb.cpus = 2
vb.memory = 3000
unless File.exist?('./.disk/ceph3.vdi')
vb.customize ['createmedium', 'disk', '--filename', './.disk/ceph3.vdi', '--size', 10240]
end
vb.customize ['storageattach', :id, '--storagectl', 'SCSI', '--port', 2, '--device', 0, '--type', 'hdd', '--medium', './.disk/ceph3.vdi']
end
end
config.vm.provision "shell", inline: <<-SHELL
sed -i 's/PasswordAuthentication no/PasswordAuthentication yes/g' /etc/ssh/sshd_config
sed -i 's/archive.ubuntu.com/mirror.kakao.com/g' /etc/apt/sources.list
sed -i 's/security.ubuntu.com/mirror.kakao.com/g' /etc/apt/sources.list
systemctl restart ssh
SHELL
end
추가 소스 코드 의미
unless File.exist?('./.disk/ceph1.vdi')
vb.customize ['createmedium', 'disk', '--filename', './.disk/ceph1.vdi', '--size', 10240]
end
vb.customize ['storageattach', :id, '--storagectl', 'SCSI', '--port', 2, '--device', 0, '--type', 'hdd', '--medium', './.disk/ceph1.vdi']
디스크 추가 확인
PS C:\Users\Playdata\vagrant\k8s> ls
디렉터리: C:\Users\Playdata\vagrant\k8s
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 2022-05-24 오전 9:36 .disk ✔️
d----- 2022-05-22 오후 9:05 .vagrant
-a---- 2022-05-24 오전 9:29 2453 Vagrantfile
+) Rook 설치 전, 스냅샷 생성 / 복구
- 생성 : vagrant snapshot save before-rook
- 복구 : vagrant snapshot restore before-rook
node1에서 디스크 마운드 확인
작업 디렉토리 : ~
$ ansible all -i ~/kubespray/inventory/mycluster/inventory.ini -m command -a 'sudo lsblk'
터미널 1
$ git clone --single-branch --branch v1.9.3 https://github.com/rook/rook.git
🌟 --branch
로 버전 맞춰서 잘 설치하기!! (홈페이지의 master는 아직 test mode)
터미널 1
$ cd rook/deploy/examples
$ kubectl create -f crds.yaml -f common.yaml -f operator.yaml
operator : 설치를 위한 ###
확인
터미널2
$ watch kubectl get po -n rook-ceph
rook-ceph-operator-xx 파드 : Runnung
상태 확인
k8s-node1: Tue May 24 00:58:40 2022ceph
NAME READY STATUS RESTARTS AGE
rook-ceph-operator-7c89b8d585-4r9qb 1/1 Running ✔️ 0 5m36s
터미널 1
$ kubectl create -f cluster.yaml
확인
터미널2
$ watch -d -n1 kubectl get po -n rook-ceph
k8s-node1: Tue May 24 00:57:21 2022
ceph
NAME READY STATUS RESTARTS AGE
필수 생성 요소 확인
문제 발생
rook-ceph-mon-a-6db45d4bb9-vpwlb 0/1 CrashLoopBackOff 7 (2m11s ago) 14m
rook-ceph-mon-b-5d9ff4f6cd-zt5cq 1/1 Running 2 (64s ago) 9m36s
rook-ceph-mon-c-666674cdfd-dn9rf 0/1 Init:0/2 0 4m52s
문제 : 해당 파드들이 probe에 의해 계속 생성/삭제 반복
원인 : cpu 부족
😂 결국 실패 후 스냅샷으로 복구