0524_Kubernetes_Dynamic Provisioning : StorageClass, Default SC / Deployment : RollOut & Roll Back / ConfigMap & Secret / Nginx HTTPS

HYOJU DO·2022년 5월 24일
0

Kubernetes

목록 보기
9/13
post-thumbnail

동적 프로비저닝


정적 vs 동적 프로비저닝

보통 동적 프로비저닝 더 많이 사용

  • 정적 프로비저닝
    매번 pv ➜ pvc -> RS(pod) 만들어줘야 함
  • 동적 프로비저닝
    pvc 생성 ➜ pvc에 바운딩 될 pv 자동으로 생성 후 연결

💡 동적 프로비저닝은 어떤 정보로 pv를 생성하는가?
StorageClass 라는 오브젝트를 통해 생성
storageClass는 pv 를 생성하기 위한 탬플릿 을 가지고 있음

  • 관리자 - storageClass 생성
  • 개발자 - pvc 생성 설정

🌟StorageClass🌟(스토리지 클라스)

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 연결 모드
    • Immediate : 파드를 만들기 전 pvc-pv 연결
    • WaitForFirstConsumer : pvc를 만들면 pv를 안만들고 있다가 pod가 생성되면 pv를 만들어서 pvc-pv 연결 -> 비용 절약 가능



NFS 동적 프로비저닝


NFS subdir external provisioner 사용

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



Deployment


버전 관리
보통 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
    Rollout 중에 지정된 replicas 수를 얼마나 초과할 수 있는가
    Default : 지정된 replicas 개수의 25% (올림하여 계산)
    ➜ 비율 or 값 둘 다 지정 가능
  • maxUnavailable
    최대 몇 개까지 지울 수 있는가
    Default : 25% (올림)
    ➜ 이 과정을 통해 롤백을 하기 위해 rs를 삭제하지 않는 것
    만약 이 것을 2로 설정하면 2개씩 지움
    ➜ 기본적으로 설정해야 함

2) minReadySeconds : 최소 대기시간

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 배포 방법

deploy.spec.strategy

  • Recreate : 기존의 것을 삭제하고 새롭게 RS 생성해서 연결
    (label 지정하여 서로 연결되도록 함)
    ➜ 무조건 Downtime 발생
    Planned Downtime에 주로 사용 (ex. 게임 서버 정기 점검)
    롤백 시간 오래 걸리고 다수의 client에게 오류 발생 가능성 높
  • RollingUpdate : 하나씩 천천히 옮겨가는 형태
    🌟 무중단 시스템
    RS가 2개 존재
    ➜ label이 모두 같다면 LB의 label selector가 selecting 하여 각 RS로 트래픽 분산



Roll Out & Roll Back

  • 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 옵션 : 명령을 히스토리에 저장

🎈

Rollback

$ 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...



ConfigMap & Secret


환경변수로 제공

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"

ConfigMap(CM)

비기밀데이터 저장 (key-value)

다른 오브젝트가 사용할 구성을 저장할 수 있는 API 오브젝트
파드와 동일한 NS(Name Space)에 존재해야 함

🎈 제공 방법

  • 환경변수 로 제공
  • 볼륨/파일 로 제공
    ➜ KEY : 파일명(이름) / VALUE : 내용
    보통 읽기 전용 파일
    ex. 설정파일, 인증서, 암호화 키 ...

🎈 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



Secret

기밀데이터 저장 (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 HTTPs 서버


Nginx ➜ 비동기방식

🎈 사용 디렉토리

  • Documentation Root : /urs/share/nginx/html
  • 설정파일 : /etc/nginx
    ➜ 이 밑에 conf.d에 설정 파일 추가
    == /etc/nginx/conf.d

🎈 생성할 디렉토리

  • conf : Nginx를 위한 설정 ➜ configMap 사용
  • x509 : 인증 ➜ Secret 사용

➕ lets encrypt ➜ 도메인 가지고 있으면 무료 인증 서명 가능한 사이트 (갱신기간 : 3년)


Self Signed Certificate (자체 서명 인증서) 생성

보안상 위험하지만 테스트에는 유용
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 페이지 뜨는 것 확인 가능



+ RookCeph


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']
  • unless xxx : './.disk/ceph1.vdi' 디스크 파일이 없으면 설치, 존재하면 skip
  • end xxx : 디스크를 스토리지로 사용하기 위해 연결

디스크 추가 확인

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'

Rook 설치 (20분정도 소요)

실제 Rook 소스코드

터미널 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,b,c-xxx : 3개
  • rook-ceph-osd-0,1,2-xxx : 3개
  • rook-ceph-mrg-a-xxx : 1개

문제 발생

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 부족

😂 결국 실패 후 스냅샷으로 복구

profile
Be on CLOUD nine! ☁️ ( 수정 예정 == 📌)

0개의 댓글