[Kubernetes] 5일차 수업 정리

soyeon·2022년 10월 6일
0
post-thumbnail

NFS

## 양쪽 노드에서 설치 및 확인
kevin@k8s-node1:~$ sudo apt -y install nfs-kernel-server
kevin@k8s-node1:~$ sudo systemctl enable --now nfs-server
kevin@k8s-node1:~$ sudo systemctl status nfs-server

## nfs server(1번)에서만 수행
## /etc/exports 파일은 서버가 클라이언트에 반출하는 모든 디렉토리를 표시한다
kevin@k8s-node1:~$ sudo vi /etc/exports
/data_dir       *(rw,sync,no_root_squash,no_subtree_check)

## NFS에서 사용하는 고정포트 2049
kevin@k8s-node1:~$ sudo netstat -nlp | grep 2049
tcp        0      0 0.0.0.0:2049            0.0.0.0:*               LISTEN      -

## nfs client 설치
## node2에서 수행
kevin@k8s-node2:~$ sudo apt -y install nfs-common
kevin@k8s-node2:~$ sudo mkdir -p /data_dir/nfs

## node1에서 확인
kevin@k8s-node1:~$ sudo systemctl restart nfs-server
kevin@k8s-node1:~$ sudo systemctl status nfs-server

## mount 시키기
kevin@k8s-node2:~$ sudo mount -t nfs k8s-node1:/data_dir /data_dir/nfs

## mount 확인
kevin@k8s-node2:~$ df -h
Filesystem           Size  Used Avail Use% Mounted on
k8s-node1:/data_dir   66G   13G   53G  20% /data_dir/nfs
...

## node2에 nfs1을 생성한다
kevin@k8s-node2:~$ cd /data_dir/nfs/
kevin@k8s-node2:/data_dir/nfs$ sudo touch nfs1
kevin@k8s-node2:/data_dir/nfs$ ls
k8s-2.txt  nfs1

## node1에도 nfs1이 생겼다.
kevin@k8s-node1:~$ cd /data_dir/
kevin@k8s-node1:/data_dir$ ls
k8s-2.txt  nfs1

PV, PVC

docker container 내부 용량 제한?
default는 unlimit이었다.
--storage-opt size= : container 내부의 / 용량을 잡아주었다.
dd명령 임시 파일 -> fdisk -> mount : mount된 directory 용량 제한
ㄴ OS 의존적이라는 단점이 있다.
=> kubernetes에서는 PV,PVC로 제어할 수 있다.

  • volume 용량 제한하기
## mysql-pod describe
kevin@k8s-master:~/LABs$ kubectl describe po mysql-pod
...
    Mounts:
      /var/lib/mysql from host-path (rw)
...
Volumes:
  host-path:
    Type:          HostPath (bare host directory volume)
    Path:          /data_dir/mysql-data
...

## /var/lib/mysql이 /와 같은 공간을 차지하고 있다. 제어 필요
## mysql-pod가 만들어진 node2에서 수행
kevin@k8s-node2:~$ sudo su -
root@k8s-node2:~# dd if=/dev/zero of=temphdd.img count=512 bs=1M
root@k8s-node2:~# ls -lh
total 512M
drwx------ 3 root root   24  929 10:49 snap
-rw-r--r-- 1 root root 512M 106 09:27 temphdd.img

## 파일 시스템 붙이기
root@k8s-node2:~# mkfs.xfs temphdd.img

## backup_dir directory 생성해서 mount
root@k8s-node2:~# mkdir /backup_dir
root@k8s-node2:~# mount -o loop temphdd.img /backup_dir

## 확인
root@k8s-node2:~# df -h | grep /backup_dir
/dev/loop11          507M   30M  478M   6% /backup_dir

## 권한 주기
root@k8s-node2:~# chown -R kevin.kevin /backup_dir/

## master에서 수행
## 이동
kevin@k8s-master:~/LABs$ mkdir hostpath
kevin@k8s-master:~/LABs$ cd hostpath/

## yaml 파일 작성
kevin@k8s-master:~/LABs/hostpath$ vi hostpath-2.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-vol5
spec:
  nodeSelector:
    kubernetes.io/hostname: k8s-node2
  containers:
  - name: container
    image: dbgurum/k8s-lab:initial
    volumeMounts:
    - name: host-path
      mountPath: /backup
  volumes:
  - name: host-path
    hostPath:
      path: /backup_dir
      type: DirectoryOrCreate
      
## apply
kevin@k8s-master:~/LABs/hostpath$ kubectl apply -f hostpath-2.yaml

## 확인
kevin@k8s-master:~/LABs/hostpath$ kubectl get po -o wide
NAME              READY   STATUS    RESTARTS       AGE   IP               NODE        NOMINATED NODE   READINESS GATES
pod-vol5          1/1     Running   0              4s    10.109.131.62    k8s-node2   <none>           <none>

## describe
kevin@k8s-master:~/LABs/hostpath$ kubectl describe po pod-vol5
...
    Mounts:
      /backup from host-path (rw)
...
Volumes:
  host-path:
    Type:          HostPath (bare host directory volume)
    Path:          /backup_dir
    HostPathType:  DirectoryOrCreate
...

## 500M로 용량이 제한되었다.
kevin@k8s-master:~/LABs/hostpath$ kubectl exec -it pod-vol5 -- df -h
Filesystem      Size  Used Avail Use% Mounted on
/dev/loop11     507M   30M  478M   6% /backup
  • GCP에 디스크 추가하기
## Google Cloud SDK Shell에서 실행
C:\k8s>gcloud container clusters list
NAME         LOCATION           MASTER_VERSION    MASTER_IP      MACHINE_TYPE  NODE_VERSION      NUM_NODES  STATUS
k8s-cluster  asia-northeast3-a  1.22.12-gke.2300  34.64.237.123  e2-medium     1.22.12-gke.2300  3          RUNNING

Updates are available for some Google Cloud CLI components.  To install them,
please run:
  $ gcloud components update
  
## 디스크 만들기
C:\k8s>gcloud compute disks create mongo-storage --size=10G --zone=asia-northeast3-a

## 확인
C:\k8s>gcloud compute disks list
NAME                                        LOCATION           LOCATION_SCOPE  SIZE_GB  TYPE         STATUS
gke-k8s-cluster-k8s-nodepool-bc541242-jgo3  asia-northeast3-a  zone            100      pd-standard  READY
gke-k8s-cluster-k8s-nodepool-bc541242-o1ji  asia-northeast3-a  zone            100      pd-standard  READY
gke-k8s-cluster-k8s-nodepool-bc541242-zuc3  asia-northeast3-a  zone            100      pd-standard  READY
mongo-storage                               asia-northeast3-a  zone            10       pd-standard  READY

## yaml 파일 작성
C:\k8s>notepad gce-mongo.yaml
apiVersion: v1
kind: Pod
metadata:
  name: gce-mongo-pod
spec:
  containers:
  - image: mongo
    name: mongo-container
    volumeMounts:
    - name: mongodb-data
      mountPath: /data/db
    ports:
    - containerPort: 27017
      protocol: TCP
  volumes:
  - name: mongodb-data
    gcePersistentDisk:
      pdName: mongo-storage
      fsType: ext4

## apply
C:\k8s>kubectl apply -f gce-mongo.yaml

## 확인
C:\k8s>kubectl get po -o wide
NAME            READY   STATUS    RESTARTS   AGE   IP          NODE                                         NOMINATED NODE   READINESS GATES
gce-mongo-pod   1/1     Running   0          33s   10.12.3.9   gke-k8s-cluster-k8s-nodepool-bc541242-o1ji   <none>           <none>

## pod describe
C:\k8s>kubectl describe po gce-mongo-pod
...
    Mounts:
      /data/db from mongodb-data (rw)
...
Volumes:
  mongodb-data:
    Type:       GCEPersistentDisk (a Persistent Disk resource in Google Compute Engine)
    PDName:     mongodb-storage
    FSType:     ext4
    Partition:  0
    ReadOnly:   false
...

C:\k8s>kubectl delete -f gce-mongo.yaml


: mongo-sorage가 생성되었다.


: GKE dashboard로도 확인 가능하다.

PV(Persistent Volume)
: 지속적 볼륨, 가상 스토리지 인스턴스(dd)
관리자에 의해서 생성된다.
OS, Cloud 등에서 실제 storage의 물리적 공간(disk)을 활용해서 PV를 만든다.
용량, 권한(AccessModes)을 잘 부여해야 한다.

PVC(Persistent Volume Claim)
: PV를 요청한다.
사용자(개발자)에 의해 PV를 프로비저닝하는 요청이다.
PV를 얼마만큼 어떤 권한으로 쓸지를 요청한다.
용량, 권한을 부여하면 매칭되는 PV에 자동 연결이 된다.

AccessModes

  • ReadWriteOnce(RWO) : 하나의 Node가 volume을 RW 가능하도록 mount
  • ReadWriteMany(RWX) : 여러 Node가 volume을 RW 가능하도록 mount
  • ReadOnlyMany(ROX) : 여러 Node가 volume을 RO 가능하도록 mount
  • PV, PVC 생성
## persistentvolumes v1 확인
kevin@k8s-master:~/LABs/hostpath$ kubectl api-resources | grep -i persis
persistentvolumeclaims            pvc          v1                                     true         PersistentVolumeClaim
persistentvolumes                 pv           v1                                     false        PersistentVolume

## yaml 파일 작성
kevin@k8s-master:~/LABs$ mkdir pv-pvc && cd $_
kevin@k8s-master:~/LABs/pv-pvc$ vi pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv1
spec:
  capacity: 
    storage: 1G
  accessModes:
  - ReadWriteOnce
  ## persistentVolumeReclaimPolicy : pod가 날아가도 데이터가 남아있게 할 것인지
  ## Retain(남겨놓기), Recycle(안에 있고 재사용), Delete(pv 자체가 사라진다)
  persistentVolumeReclaimPolicy: Retain
  local:
    path: /data_dir
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - {key: kubernetes.io/hostname, operator: In, values: [k8s-node1]}

## yaml 파일 작성
kevin@k8s-master:~/LABs/pv-pvc$ vi pv2.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv2
spec:
  capacity:
    storage: 1G
  accessModes:
  - ReadOnlyMany
  persistentVolumeReclaimPolicy: Retain
  local:
    path: /data_dir
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - {key: kubernetes.io/hostname, operator: In, values: [k8s-node1]}

## yaml 파일 작성
kevin@k8s-master:~/LABs/pv-pvc$ vi pv3.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv3
spec:
  capacity:
    storage: 2G
  accessModes:
  - ReadWriteMany
  persistentVolumeReclaimPolicy: Retain
  local:
    path: /data_dir
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - {key: kubernetes.io/hostname, operator: In, values: [k8s-node1]}
        
## apply
kevin@k8s-master:~/LABs/pv-pvc$ kubectl apply -f pv.yaml
kevin@k8s-master:~/LABs/pv-pvc$ kubectl apply -f pv2.yaml
kevin@k8s-master:~/LABs/pv-pvc$ kubectl apply -f pv3.yaml

## 확인
kevin@k8s-master:~/LABs/pv-pvc$ kubectl get pv
NAME   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
pv1    1G         RWO            Retain           Available                                   2m30s
pv2    1G         ROX            Retain           Available                                   64s
pv3    2G         RWX            Retain           Available                                   6s

## PVC 생성
## yaml 코드 작성
kevin@k8s-master:~/LABs/pv-pvc$ vi pvc.yaml
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc2
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 1G
  storageClassName: ""
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc3
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 5G
  storageClassName: ""
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc4
spec:
  accessModes:
  - ReadWriteMany
  resources:
    requests:
      storage: 1G
  storageClassName: ""

## apply
kevin@k8s-master:~/LABs/pv-pvc$ kubectl apply -f pvc.yaml

## 확인 - 용량과 접근방식에 따라 PV를 선택한다
## 조건이 맞지 않으면 pending 상태가 된다.
kevin@k8s-master:~/LABs/pv-pvc$ kubectl get pv,pvc
NAME                   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM          STORAGECLASS   REASON   AGE
persistentvolume/pv1   1G         RWO            Retain           Bound    default/pvc2                           8m12s
persistentvolume/pv2   1G         ROX            Retain           Bound    default/pvc1                           6m46s
persistentvolume/pv3   2G         RWX            Retain           Bound    default/pvc4                           5m48s

NAME                         STATUS    VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
persistentvolumeclaim/pvc1   Bound     pv2      1G         ROX                           9s
persistentvolumeclaim/pvc2   Bound     pv1      1G         RWO                           9s
persistentvolumeclaim/pvc3   Pending                                                     9s
persistentvolumeclaim/pvc4   Bound     pv3      2G         RWX                           9s
  • pod에 pvc 연결하기
## PVC가 pod에 붙는다. PV는 pod에 붙지 않는다.
## yaml 파일 작성
kevin@k8s-master:~/LABs/pv-pvc$ vi mynode.yaml
apiVersion: v1
kind: Pod
metadata:
  name: mynode-pod
spec:
  containers:
  - image: dbgurum/mynode:1.0
    name: mynode-container
    ports:
    - containerPort: 8000
    volumeMounts:
    - name: mynode-path
      mountPath: /mynode
  volumes:
  - name: mynode-path
    persistentVolumeClaim:
      claimName: pvc1

## apply
kevin@k8s-master:~/LABs/pv-pvc$ kubectl apply -f mynode.yaml

## 확인
kevin@k8s-master:~/LABs/pv-pvc$ kubectl get po -o wide
NAME              READY   STATUS    RESTARTS       AGE    IP               NODE        NOMINATED NODE   READINESS GATES
mynode-pod        1/1     Running   0              13s    10.111.156.127   k8s-node1   <none>           <none>

## mynode-pod로 들어가기
kevin@k8s-master:~/LABs/pv-pvc$ kubectl exec -it mynode-pod -- bash

## mount 확인
root@mynode-pod:/# df -h
Filesystem      Size  Used Avail Use% Mounted on
/dev/sda1        66G   13G   53G  20% /mynode
...

## mynode-pod에 파일 생성
root@mynode-pod:/# echo 'i love k8s' > /mynode/pvc1.txt
root@mynode-pod:/# ls /mynode/
k8s-2.txt  nfs1  pvc1.txt

## node1의 /data_dir에 pvc1.txt가 있다.
kevin@k8s-node1:/data_dir$ ls -l /data_dir/
total 8
-rw-r--r-- 1 root root 11 105 16:45 k8s-2.txt
-rw-r--r-- 1 root root  0 106 09:15 nfs1
-rw-r--r-- 1 root root 11 106 11:19 pvc1.txt

## pvc를 원하는 pv에 붙이기
## yaml 파일 작성
kevin@k8s-master:~/LABs/pv-pvc$ vi pv-pvc-select.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv4
  labels:
    name: pv4
spec:
  capacity:
    storage: 1G
  accessModes:
  - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  local:
    path: /data_dir
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - {key: kubernetes.io/hostname, operator: In, values: [k8s-node1]}
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc5
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 1G
  storageClassName: ""
  selector:
    matchLabels:
      name: pv4
      
## apply
kevin@k8s-master:~/LABs/pv-pvc$ kubectl apply -f pv-pvc-select.yaml

## pv4가 pvc5에 붙었다.
kevin@k8s-master:~/LABs/pv-pvc$ kubectl get pv,pvc
NAME                   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM          STORAGECLASS   REASON   AGE
persistentvolume/pv1   1G         RWO            Retain           Bound    default/pvc2                           40m
persistentvolume/pv2   1G         ROX            Retain           Bound    default/pvc1                           39m
persistentvolume/pv3   2G         RWX            Retain           Bound    default/pvc4                           38m
persistentvolume/pv4   1G         RWO            Retain           Bound    default/pvc5                           4s

NAME                         STATUS    VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
persistentvolumeclaim/pvc1   Bound     pv2      1G         ROX                           32m
persistentvolumeclaim/pvc2   Bound     pv1      1G         RWO                           32m
persistentvolumeclaim/pvc3   Pending                                                     32m
persistentvolumeclaim/pvc4   Bound     pv3      2G         RWX                           32m
persistentvolumeclaim/pvc5   Bound     pv4      1G         RWO                           4s
  • pv는 nfs 사용가능
## yaml 파일 작성
kevin@k8s-master:~/LABs/pv-pvc$ vi nfs-pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfs-pv
spec:
  capacity:
    storage: 1G
  accessModes:
  - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  nfs:
    path: /data_dir
    server: 192.168.56.101

## apply
kevin@k8s-master:~/LABs/pv-pvc$ kubectl apply -f nfs-pv.yaml

## nfs-pv 생성 확인
kevin@k8s-master:~/LABs/pv-pvc$ kubectl get pv,pvc
NAME                      CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM          STORAGECLASS   REASON   AGE
persistentvolume/nfs-pv   1G         RWO            Retain           Available                                          3s
persistentvolume/pv1      1G         RWO            Retain           Bound       default/pvc2                           44m
persistentvolume/pv2      1G         ROX            Retain           Bound       default/pvc1                           42m
persistentvolume/pv3      2G         RWX            Retain           Bound       default/pvc4                           41m
persistentvolume/pv4      1G         RWO            Retain           Bound       default/pvc5                           3m15s

NAME                         STATUS    VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
persistentvolumeclaim/pvc1   Bound     pv2      1G         ROX                           35m
persistentvolumeclaim/pvc2   Bound     pv1      1G         RWO                           35m
persistentvolumeclaim/pvc3   Pending                                                     35m
persistentvolumeclaim/pvc4   Bound     pv3      2G         RWX                           35m
persistentvolumeclaim/pvc5   Bound     pv4      1G         RWO                           3m15s
  • pv 수정
## 3G로 수정하기
kevin@k8s-master:~/LABs/pv-pvc$ kubectl edit pv pv3
 22     storage: 3G
 
## pv3 CAPACITY가 수정되었다
kevin@k8s-master:~/LABs/pv-pvc$ kubectl get pv,pvc
NAME                      CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM          STORAGECLASS   REASON   AGE
persistentvolume/nfs-pv   1G         RWO            Retain           Available                                          2m52s
persistentvolume/pv1      1G         RWO            Retain           Bound       default/pvc2                           46m
persistentvolume/pv2      1G         ROX            Retain           Bound       default/pvc1                           45m
persistentvolume/pv3      3G         RWX            Retain           Bound       default/pvc4                           44m
persistentvolume/pv4      1G         RWO            Retain           Bound       default/pvc5                           6m4s

NAME                         STATUS    VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
persistentvolumeclaim/pvc1   Bound     pv2      1G         ROX                           38m
persistentvolumeclaim/pvc2   Bound     pv1      1G         RWO                           38m
persistentvolumeclaim/pvc3   Pending                                                     38m
persistentvolumeclaim/pvc4   Bound     pv3      2G         RWX                           38m
persistentvolumeclaim/pvc5   Bound     pv4      1G         RWO                           6m4s
  • 실습
    PV, PVC를 이용한 Pod
## yaml 파일 작성
kevin@k8s-master:~/LABs/pv-pvc$ vi pv-pvc-pod.yaml
    storage: 10G
  accessModes:
  - ReadWriteOnce
  hostPath:
    path: "/mnt/data"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-volume
spec:
  storageClassName: manual
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 3G
---
apiVersion: v1
kind: Pod
metadata:
  name: web-pod
spec:
  volumes:
  - name: web-pv-storage
    persistentVolumeClaim:
      claimName: pvc-volume
  containers:
  - name: web-container
    image: nginx
    ports:
    - containerPort: 80
      name: "web-server"
    volumeMounts:
    - mountPath: "/usr/share/nginx/html"
      name: web-pv-storage

## apply
kevin@k8s-master:~/LABs/pv-pvc$ kubectl apply -f pv-pvc-pod.yaml

## 확인
kevin@k8s-master:~/LABs/pv-pvc$ kubectl get pv,pvc
NAME                         CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM                STORAGECLASS   REASON   AGE
persistentvolume/pv-volume   10G        RWO            Retain           Bound       default/pvc-volume   manual                  7s

NAME                               STATUS    VOLUME      CAPACITY   ACCESS MODES   STORAGECLASS   AGE
persistentvolumeclaim/pvc-volume   Bound     pv-volume   10G        RWO            manual         7s

## storage 20G로 수정
kevin@k8s-master:~/LABs/pv-pvc$ kubectl edit pv pv-volume
...
 22   - ReadWriteOnce
 23   capacity:
 24     storage: 20G

## 확인
kevin@k8s-master:~/LABs/pv-pvc$ kubectl get pv,pvc
NAME                         CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM                STORAGECLASS   REASON   AGE
persistentvolume/pv-volume   20G        RWO            Retain           Bound       default/pvc-volume   manual                  2m56s

NAME                               STATUS    VOLUME      CAPACITY   ACCESS MODES   STORAGECLASS   AGE
persistentvolumeclaim/pvc-volume   Bound     pv-volume   10G        RWO            manual         2m56s

## node1에서 mount 확인
kevin@k8s-node1:/mnt$ cd
kevin@k8s-node1:~$ cd /mnt/data
kevin@k8s-node1:/mnt/data$ ls
  • Google Cloud SDK Shell에서 pv,pvc,pod 생성
## yaml 파일 작성
C:\k8s>notepad pv-pvc-pod.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: mongodb-pv
spec:
  capacity: 
    storage: 1G
  accessModes:
  - ReadWriteOnce
  - ReadOnlyMany
  persistentVolumeReclaimPolicy: Retain
  gcePersistentDisk:
    pdName: mongo-storage
    fsType: ext4
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mongodb-pvc
spec:
  resources:
    requests:
      storage: 1G
  accessModes:
  - ReadWriteOnce
  storageClassName: ""
---
apiVersion: v1
kind: Pod
metadata:
  name: mongo-pod
spec:
  containers:
  - image: mongo
    name: mongodb
    volumeMounts:
    - name: mongo-data
      mountPath: /data/db
    ports:
    - containerPort: 27017
      protocol: TCP
  volumes:
  - name: mongo-data
    persistentVolumeClaim:
      claimName: mongodb-pvc

## apply
C:\k8s>kubectl apply -f pv-pvc-pod.yaml

## 확인
C:\k8s>kubectl get pv,pvc
NAME                          CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                 STORAGECLASS   REASON   AGE
persistentvolume/mongodb-pv   1G         RWO,ROX        Retain           Bound    default/mongodb-pvc                           12s

NAME                                STATUS   VOLUME       CAPACITY   ACCESS MODES   STORAGECLASS   AGE
persistentvolumeclaim/mongodb-pvc   Bound    mongodb-pv   1G         RWO,ROX                       12s

C:\k8s>kubectl delete -f pv-pvc-pod.yaml

git

  1. 새로운 repository 생성
  2. creating a new file 클릭
  3. test 파일 생성
  4. upload files 클릭
  5. source 파일 upload
  6. upload 완료
  7. test 파일 삭제
  8. git clone 주소 복사

https://github.com/soyeonnn/whatisyourmotto.git

## 이동
kevin@k8s-master:~/LABs$ mkdir gitrepo && cd $_

## yaml 파일 작성
kevin@k8s-master:~/LABs/gitrepo$ vi gitrepo.yaml
apiVersion: v1
kind: Pod
metadata:
  name: gitrepo-pod
  labels:
    app: motto
spec:
  containers:
  - image: nginx:1.23.1-alpine
    name: web-container
    volumeMounts:
    - name: gitrepo
      mountPath: /usr/share/nginx/html
  volumes:
  - name: gitrepo
    gitRepo:
      repository: https://github.com/soyeonnn/whatisyourmotto.git
      revision: main
      directory: .

## apply
kevin@k8s-master:~/LABs/gitrepo$ kubectl apply -f gitrepo.yaml

## git에서 수정해도 그게 반영되지 않는다. => deprecated

## 확인
kevin@k8s-master:~/LABs/gitrepo$ kubectl get po -o wide | grep git
gitrepo-pod       1/1     Running   0              47s    10.111.156.65    k8s-node1   <none>           <none>

kevin@k8s-master:~/LABs/gitrepo$ kubectl describe po gitrepo-pod
...
    Mounts:
      /usr/share/nginx/html from gitrepo (rw)
...
Volumes:
  gitrepo:
    Type:        GitRepo (a volume that is pulled from git when the pod is created)
    Repository:  https://github.com/soyeonnn/whatisyourmotto.git
    Revision:    main
...

## 접속 확인
kevin@k8s-master:~/LABs/gitrepo$ curl 10.111.156.65

## yaml 파일 작성
kevin@k8s-master:~/LABs/gitrepo$ vi gitrepo-svc.yaml
apiVersion: v1
kind: Service
metadata:
  name: gitrepo-svc
spec:
  selector:
    app: motto
  ports:
  - port: 10080
    targetPort: 80
    nodePort: 30080
  type: NodePort

## apply
kevin@k8s-master:~/LABs/gitrepo$ kubectl apply -f gitrepo-svc.yaml

## 확인
kevin@k8s-master:~/LABs/gitrepo$ kubectl get po,svc -o wide
NAME                  READY   STATUS    RESTARTS       AGE     IP               NODE        NOMINATED NODE   READINESS GATES
pod/gitrepo-pod       1/1     Running   0              5m43s   10.111.156.65    k8s-node1   <none>           <none>

NAME                    TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)           AGE     SELECTOR
service/gitrepo-svc     NodePort    10.101.32.165    <none>        10080:30080/TCP   53s     app=motto

## windows에서 http://192.168.56.101:30080/ 접속해서 확인

## node1에 접속
kevin@k8s-node1:~$ sudo su -

## mount한 volume 이름으로 찾기
root@k8s-node1:~# find / -name gitrepo
/var/lib/kubelet/pods/6d7d39e6-b811-4078-9493-b3d503b19cd3/volumes/kubernetes.io~git-repo/gitrepo
/var/lib/kubelet/pods/6d7d39e6-b811-4078-9493-b3d503b19cd3/plugins/kubernetes.io~git-repo/gitrepo
find: ‘/run/user/1000/gvfs’: Permission denied
find: ‘/run/user/125/gvfs’: Permission denied

## 이동
root@k8s-node1:~# cd /var/lib/kubelet/pods/6d7d39e6-b811-4078-9493-b3d503b19cd3/volumes/kubernetes.io~git-repo/gitrepo

## git clone data 확인
root@k8s-node1:/var/lib/kubelet/pods/6d7d39e6-b811-4078-9493-b3d503b19cd3/volumes/kubernetes.io~git-repo/gitrepo# ls
assets  css  index.html  js

  • Google Cloud SDK shell에서 disk 삭제
## 삭제
C:\k8s>gcloud compute disks delete mongo-storage --zone asia-northeast3-a

## 확인
C:\k8s>gcloud compute disks list
NAME                                        LOCATION           LOCATION_SCOPE  SIZE_GB  TYPE         STATUS
gke-k8s-cluster-k8s-nodepool-bc541242-jgo3  asia-northeast3-a  zone            100      pd-standard  READY
gke-k8s-cluster-k8s-nodepool-bc541242-o1ji  asia-northeast3-a  zone            100      pd-standard  READY
gke-k8s-cluster-k8s-nodepool-bc541242-zuc3  asia-northeast3-a  zone            100      pd-standard  READY

ConfigMap & Secret

ConfigMap

: key:value 구조의 데이터(환경변수, 명령의 인수(args), 구성 파일(*.conf, nginx.conf))를 저장한다.

조회

kevin@k8s-master:~$ kubectl api-resources | grep -i configmap
configmaps                        cm           v1                                     true         ConfigMap

사용법(ConfigMap과 Secret은 사용법이 동일하다)

kubectl create configmap
--from-literal=key=value | --from-literal key=value
--from-file=[file_name] | --from-file [file_name]

Configmap 생성

  • configmap 생성 1
## configmap 생성
kevin@k8s-master:~/LABs$ kubectl create configmap log-level-cm --from-literal=LOG_LEVEL=DEBUG

## 생성 확인
kevin@k8s-master:~/LABs$ kubectl get cm
NAME               DATA   AGE
kube-root-ca.crt   1      7d
log-level-cm       1      14s
kevin@k8s-master:~/LABs$ kubectl describe cm log-level-cm
...
LOG_LEVEL:
----
DEBUG
...

## yaml 파일 확인
kevin@k8s-master:~/LABs$ kubectl get cm log-level-cm -o yaml
apiVersion: v1
data:
  LOG_LEVEL: DEBUG
kind: ConfigMap
metadata:
  creationTimestamp: "2022-10-06T05:16:09Z"
  name: log-level-cm
  namespace: default
  resourceVersion: "221429"
  uid: fb035262-a5e2-445e-990c-f90b072a7ac9
  • configmap 생성 2
    configmap에 2개 등록하기
## configmap 생성
kevin@k8s-master:~/LABs$ kubectl create cm env-cm --from-literal=key1=value1 --from-literal=key2=value2

## 확인
kevin@k8s-master:~/LABs$ kubectl describe cm env-cm
...
Data
====
key1:
----
value1
key2:
----
value2
...
  • configmap 생성3
## conf 파일 작성
kevin@k8s-master:~/LABs$ vi redis.conf
key1=kubernetes
key2=docker
key3=linux
key4=gke

## 파일로 configmap 생성
kevin@k8s-master:~/LABs$ kubectl create cm redis-cm --from-file=redis.conf

## 확인
kevin@k8s-master:~/LABs$ kubectl get cm
NAME               DATA   AGE
env-cm             2      2m48s
kube-root-ca.crt   1      7d
log-level-cm       1      16m
redis-cm           1      8s

## 확인
kevin@k8s-master:~/LABs$ kubectl describe cm redis-cm
...
Data
====
redis.conf:
----
key1=kubernetes
key2=docker
key3=linux
key4=gke
...
  • --dry-run
    configmap을 가볍게 만들 수 있다.
## --dry-run 붙여서 configmap 생성
kevin@k8s-master:~/LABs$ kubectl create configmap my-pwd --from-literal=mypwd=k8spass# --dry-run=client -o yaml > my-pwd.yaml

## yaml 파일 확인
kevin@k8s-master:~/LABs$ cat my-pwd.yaml
apiVersion: v1
data:
  mypwd: k8spass#
kind: ConfigMap
metadata:
  creationTimestamp: null
  name: my-pwd

Pod Ref 방법

위에서 만든 configmap을 pod에 참조시킨다.
1. 환경변수로 넣기

## yaml 파일 작성
kevin@k8s-master:~/LABs$ vi cm-pod1.yaml
apiVersion: v1
kind: Pod
metadata:
  name: log-level-pod
spec:
  containers:
  - image: nginx:1.23.1-alpine
    name: log-level-container
    envFrom:
    - configMapRef:
        name: log-level-cm

## apply
kevin@k8s-master:~/LABs$ kubectl apply -f cm-pod1.yaml

## 확인
kevin@k8s-master:~/LABs$ kubectl get po -o wide
NAME              READY   STATUS    RESTARTS       AGE     IP               NODE        NOMINATED NODE   READINESS GATES
log-level-pod     1/1     Running   0              5s      10.111.156.67    k8s-node1   <none>           <none>

## pod 속에 환경변수로 들어가있는지 확인한다
kevin@k8s-master:~/LABs$ kubectl exec -it log-level-pod -- env
...
LOG_LEVEL=DEBUG
...
  1. mount로 넣기
## yaml 파일 작성
kevin@k8s-master:~/LABs$ vi cm-pod2.yaml
apiVersion: v1
kind: Pod
metadata:
  name: log-level-pod2
spec:
  containers:
  - image: nginx:1.23.1-alpine
    name: log-level-container
    volumeMounts:
    - name: cm-volume
      mountPath: /etc/config
  volumes:
    - name: cm-volume
      configMap:
        name: log-level-cm

## apply
kevin@k8s-master:~/LABs$ kubectl apply -f cm-pod2.yaml

## 확인
kevin@k8s-master:~/LABs$ kubectl get po -o wide
NAME              READY   STATUS    RESTARTS       AGE     IP               NODE        NOMINATED NODE   READINESS GATES
log-level-pod2    1/1     Running   0              19s     10.109.131.63    k8s-node2   <none>           <none>

## pod 속에서 확인
kevin@k8s-master:~/LABs$ kubectl exec -it log-level-pod2 -- ls /etc/config
LOG_LEVEL
kevin@k8s-master:~/LABs$ kubectl exec -it log-level-pod2 -- cat /etc/config/LOG_LEVEL
DEBUG
  1. 파일 작성해서 넣기
  • redis-cm을 pod에 참조 시키고 확인하기
## redis pod yaml 파일 작성
kevin@k8s-master:~/LABs$ vi redis-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: redis-cm-pod
spec:
  containers:
  - image: redis
    name: redis-container
    volumeMounts:
    - name: redis-volume
      mountPath: /opt/redis-config
  volumes:
    - name: redis-volume
      configMap:
        name: redis-cm

## apply
kevin@k8s-master:~/LABs$ kubectl apply -f redis-pod.yaml

## 확인
kevin@k8s-master:~/LABs$ kubectl get po
NAME              READY   STATUS    RESTARTS       AGE
redis-cm-pod      1/1     Running   0              15s

## pod 속에 파일이 있는지 확인
kevin@k8s-master:~/LABs$ kubectl exec -it redis-cm-pod -- cat /opt/redis-config/redis.conf
key1=kubernetes
key2=docker
key3=linux
key4=gke

Secret

key:value 구조의 데이터(암호, 기밀데이터)를 저장한다.
암호화는 하지 않고, encoding(base64)을 한다.
-> MYSQL_ROOT_PASSWORD, openssl -> *.crt -> https(tls)

  • 조회
kevin@k8s-master:~$ kubectl api-resources | grep -i secret
secrets                                        v1                                     true         Secret

Secret 생성

  • secret 생성 1
## secret 생성
kevin@k8s-master:~/LABs$ kubectl create secret generic my-pwd --from-literal=mypwd=k8spass#

## 확인
kevin@k8s-master:~/LABs$ kubectl describe secrets my-pwd
Type:  Opaque

## encoding 되어 저장되어 있다
kevin@k8s-master:~/LABs$ kubectl get secret -o yaml
    mypwd: azhzcGFzcyM=
    
## decoding 해보기
kevin@k8s-master:~/LABs$ echo azhzcGFzcyM= | base64 -d
k8spass#
  • secret 생성 2
    secret 2개 만들기
## secret 2개 생성
kevin@k8s-master:~/LABs/cmsecret$ kubectl create secret generic mysecret --from-literal=user_name=myuser \
> --from-literal=password=mypassword

## 확인
kevin@k8s-master:~/LABs/cmsecret$ kubectl get secrets
NAME       TYPE     DATA   AGE
mysecret   Opaque   2      8s
kevin@k8s-master:~/LABs/cmsecret$ kubectl describe secrets mysecret
Type:  Opaque

Pod Ref 방법

위에서 만든 secret을 pod에 참조시킨다.
1. 환경변수로 넣기

## yaml 파일 작성
k8spass#kevin@k8s-master:~/LABs$ vi sec-pod-1.yaml
apiVersion: v1
kind: Pod
metadata:
  name: sec-pod
spec:
  containers:
  - image: nginx:1.23.1-alpine
    name: sec-container
    envFrom:
    - secretRef:
        name: my-pwd

## apply
kevin@k8s-master:~/LABs$ kubectl apply -f sec-pod-1.yaml

## 확인
kevin@k8s-master:~/LABs$ kubectl get pod
NAME              READY   STATUS    RESTARTS        AGE
sec-pod           1/1     Running   0               33s

## decoding 되어서 환경변수로 저장되어 있다
kevin@k8s-master:~/LABs$ kubectl exec -it sec-pod -- env
mypwd=k8spass#
  1. volume 기법으로 secret 참조
## yaml 파일 작성
kevin@k8s-master:~/LABs$ vi sec-pod-2.yaml
apiVersion: v1
kind: Pod
metadata:
  name: sec-pod2
spec:
  containers:
  - image: redis
    name: redis-container
    volumeMounts:
    - name: redis-volume
      mountPath: /opt/redis-config
  volumes:
    - name: redis-volume
      secret:
        secretName: my-pwd

## apply
kevin@k8s-master:~/LABs$ kubectl apply -f sec-pod-2.yaml

## 확인
kevin@k8s-master:~/LABs$ kubectl get po
NAME              READY   STATUS    RESTARTS      AGE
sec-pod2          1/1     Running   0             12s

## pod 안에서 확인
kevin@k8s-master:~/LABs$ kubectl exec -it sec-pod2 -- ls /opt/redis-config
mypwd
kevin@k8s-master:~/LABs$ kubectl exec -it sec-pod2 -- cat /opt/redis-config/mypwd
k8spass#
  1. secret에 여러개를 설정했지만 pod에 한개만 참조할 수 있다.
    위에서 만든 mysecret에서 user_name만 참조하기
## pod yaml 파일 작성
kevin@k8s-master:~/LABs$ vi nginx-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod93
spec:
  containers:
  - image: nginx
    name: nginx-pod93
    env:
    - name: USER_NAME
      valueFrom:
        secretKeyRef:
          name: mysecret
          key: user_name
          
## apply
kevin@k8s-master:~/LABs$ kubectl apply -f nginx-pod.yaml

## 확인
kevin@k8s-master:~/LABs$ kubectl get po
NAME              READY   STATUS    RESTARTS       AGE
nginx-pod93       1/1     Running   0              12s

## user_name만 환경변수로 들어오고, password는 들어오지 않는다
kevin@k8s-master:~/LABs$ kubectl exec -it nginx-pod93 -- env
USER_NAME=myuser

Ambassador 설계 패턴

pod 속에 porxy container가 존재한다.
proxy는 toss 역할과 캐시로 저장하는 역할을 한다.

## 이동
kevin@k8s-master:~/LABs$ mkdir ambassador
kevin@k8s-master:~/LABs$ cd ambassador/

## configmap yaml 파일 작성
kevin@k8s-master:~/LABs/ambassador$ vi flaskapp-conf.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-conf
data:
  nginx.conf: |-
    user  nginx;
    worker_processes  1;

    error_log  /var/log/nginx/error.log warn;
    pid        /var/run/nginx.pid;

    events {
        worker_connections  1024;
    }

    http {
        include       /etc/nginx/mime.types;
        default_type  application/octet-stream;

        sendfile        on;
        keepalive_timeout  65;

        upstream flaskapp {
            server localhost:9000;
        }

        server {
            listen 80;

            location / {
                proxy_pass         http://flaskapp;
                proxy_redirect     off;
            }
        }
    }

## pod yaml 파일 작성
kevin@k8s-master:~/LABs/ambassador$ vi flaskapp-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: flaskapp-pod
  labels:
    app: flaskapp
spec:
  containers:
  - image: nginx:1.21-alpine
    name: proxy-container
    volumeMounts:
    - name: nginx-proxy-config
      mountPath: /etc/nginx/nginx.conf
      subPath: nginx.conf
    ports:
    - containerPort: 80
      protocol : TCP
  - image: oeckikekk/py_flask:1.0
    name: flaskapp-container
    ports:
    - containerPort: 9000
      protocol: TCP
  volumes:
    - name: nginx-proxy-config
      configMap:
        name: nginx-conf

## service yaml 파일 작성
kevin@k8s-master:~/LABs/ambassador$ vi flaskapp-svc.yaml
apiVersion: v1
kind: Service
metadata:
  name: flaskapp-svc
spec:
  selector:
    app: flaskapp
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
    nodePort: 31111
  type: NodePort

## apply
kevin@k8s-master:~/LABs/ambassador$ kubectl apply -f flaskapp-conf.yaml
kevin@k8s-master:~/LABs/ambassador$ kubectl apply -f flaskapp-pod.yaml
kevin@k8s-master:~/LABs/ambassador$ kubectl apply -f flaskapp-svc.yaml

## configmap 확인
kevin@k8s-master:~/LABs/ambassador$ kubectl get cm
nginx-conf         1      80s

## pod, service 확인 
kevin@k8s-master:~/LABs/ambassador$ kubectl get po,svc -o wide
NAME                  READY   STATUS    RESTARTS       AGE     IP               NODE        NOMINATED NODE   READINESS GATES
pod/flaskapp-pod      2/2     Running   0              98s     10.109.131.2     k8s-node2   <none>           <none>

NAME                    TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)           AGE    SELECTOR
service/flaskapp-svc    NodePort    10.111.55.47     <none>        80:31111/TCP      71s    app=flaskapp

## windows에서 http://192.168.56.102:31111/ 접속해서 확인

실습

  • kubernetes configMap + Secret
## 이동
kevin@k8s-master:~/LABs$ mkdir cmsecret
kevin@k8s-master:~/LABs$ cd cmsecret/

## configmap yaml 파일 작성
kevin@k8s-master:~/LABs/cmsecret$ vi cm-lab.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: cm-dev
data:
  SSH: 'false'
  User: kevin

## secret yaml 파일 작성
kevin@k8s-master:~/LABs/cmsecret$ vi sec-lab.yaml
apiVersion: v1
kind: Secret
metadata:
  name: sec-dev
data:
  key: YnJhdm9teWxpZmU=

## pod yaml 파일 작성
kevin@k8s-master:~/LABs/cmsecret$ vi cm-sec-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: cm-sec-pod
spec:
  containers:
  - name: cm-sec-container
    image: dbgurum/k8s-lab:initial
    envFrom:
    - configMapRef:
        name: cm-dev
    - secretRef:
        name: sec-dev

## apply
kevin@k8s-master:~/LABs/cmsecret$ kubectl apply -f cm-lab.yaml
kevin@k8s-master:~/LABs/cmsecret$ kubectl apply -f sec-lab.yaml
kevin@k8s-master:~/LABs/cmsecret$ kubectl apply -f cm-sec-pod.yaml

## configmap 확인
kevin@k8s-master:~/LABs/cmsecret$ kubectl get cm
NAME               DATA   AGE
cm-dev             2      24s

## configmap describe
kevin@k8s-master:~/LABs/cmsecret$ kubectl describe cm cm-dev
...
Data
====
SSH:
----
false
User:
----
kevin
...

## secret describe
kevin@k8s-master:~/LABs/cmsecret$ kubectl describe secrets sec-dev
Type:  Opaque

## decoding 되어서 나온다
kevin@k8s-master:~/LABs/cmsecret$ kubectl exec -it cm-sec-pod -- env
User=kevin
key=bravomylife
SSH=false
  • kubernetes 응용실습 1 - secret
## 파일로 만들기
kevin@k8s-master:~/LABs$ echo 'k8s-account' > k8s-account.txt
kevin@k8s-master:~/LABs$ echo 'k8spass#' > k8s-pwd.txt

## secret 생성
kevin@k8s-master:~/LABs$ kubectl create secret generic account-pwd-secret \
> --from-file=k8s-account.txt --from-file=k8s-pwd.txt

## deployment yaml 파일 생성
kevin@k8s-master:~/LABs$ vi sec-depl.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-deploy
  labels:
    app: src-app
spec:
  replicas: 2
  selector:
    matchLabels:
      app: sec-app
  template:
    metadata:
      labels:
        app: sec-app
    spec:
      containers:
      - name: testapp
        image: dbgurum/k8s-lab:secret-1.0
        ports:
        - containerPort: 8080
        env:
          - name: SECRET_USERNAME
            valueFrom:
              secretKeyRef:
                name: account-pwd-secret
                key: k8s-account.txt
          - name: SECRET_PASSWORD
            valueFrom:
              secretKeyRef:
                name: account-pwd-secret
                key: k8s-pwd.txt

## service yaml 파일 생성
kevin@k8s-master:~/LABs$ vi sec-svc.yaml
apiVersion: v1
kind: Service
metadata:
  labels:
    app: sec-app
  name: web-deploy-svc
spec:
  ports:
  - nodePort: 30303
    port: 8000
    protocol: TCP
    targetPort: 8080
  selector:
    app: sec-app
  type: NodePort
  
## apply
kevin@k8s-master:~/LABs$ kubectl apply -f sec-depl.yaml
kevin@k8s-master:~/LABs$ kubectl apply -f sec-svc.yaml

## 확인
kevin@k8s-master:~/LABs$ kubectl get deploy,po,svc -o wide
NAME                         READY   UP-TO-DATE   AVAILABLE   AGE   CONTAINERS   IMAGES                       SELECTOR
deployment.apps/web-deploy   2/2     2            2           17s   testapp      dbgurum/k8s-lab:secret-1.0   app=sec-app

NAME                              READY   STATUS    RESTARTS        AGE     IP               NODE        NOMINATED NODE   READINESS GATES
pod/web-deploy-595d4d579d-7nvpx   1/1     Running   0               17s     10.109.131.4     k8s-node2   <none>           <none>
pod/web-deploy-595d4d579d-x2q6n   1/1     Running   0               17s     10.111.156.69    k8s-node1   <none>           <none>
service/web-deploy-svc   NodePort    10.109.225.8     <none>        8000:30303/TCP    12s    app=sec-app

## 연결해서 확인
kevin@k8s-master:~/LABs$ curl 192.168.56.101:30303/env
... "SECRET_USERNAME=k8s-account\n","SECRET_PASSWORD=k8spass#\n" ...

0개의 댓글