Pods 에서 Persistent volume 을 사용하기 위해 각 Node 마다 50GB 볼륨을 할당하고 마운트 한다. (예제에서는 /data001 로 마운트 함)
아래 구성에서 Kubernetes 환경은 네이버클라우드플랫폼 싱가폴 리전에서 VM 으로 구성했으며, CNI 는 Calico 로 구성하였다.
1. PV (Persistent Volume) 생성
PV 는 K8S 관리자가 설정하는 클러스터의 저장소로 사용자가 PVC 를 생성하기 위해 설정해 두는 물리적인 공간이라고 볼 수 있다.
지금 구성에서는 K8S Cluster 를 스스로 운영하기 때문에 PV 설정이 필요하고, GKE 와 같이 Cluster 를 구성해 주는 서비스의 경우 PVC 만 설정해서 사용하면 된다.
50GB 파일시스템을 마운트 했으므로 25GB 짜리 PV 를 2개 생성한다.
# vi pv1.yaml
kind: PersistentVolume
apiVersion: v1
metadata:
name: pv0001
labels:
type: local
spec:
capacity:
storage: 25Gi
accessModes:
- ReadWriteOnce
hostPath:
path: "/data001/pv0001"
# vi pv2.yaml
kind: PersistentVolume
apiVersion: v1
metadata:
name: pv0002
labels:
type: local
spec:
capacity:
storage: 25Gi
accessModes:
- ReadWriteOnce
hostPath:
path: "/data001/pv0002"
# kubectl create -f pv1.yaml
# kubectl create -f pv2.yaml
# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv0001 25Gi RWO Retain Available 8s
pv0002 25Gi RWO Retain Available 5s
2. PVC (Persistent Volume Claim) 생성
PVC 는 사용자가 Pod 를 만들면서 요청하는 스토리지로 PV 가 있어야 생성된다. 별도로 PV 를 지정하지 않아도 PV 에 알아서 할당된다.
Wordpress 와 MySQL 이 각각 다른 PVC 를 사용하도록 생성한다.
# vi wordpress-volumeclaim.yaml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: wordpress-volumeclaim
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
# vi mysql-volumeclaim.yaml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: mysql-volumeclaim
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
# kubectl create wordpress-volumeclaim.yaml
# kubectl create mysql-volumeclaim.yaml
# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
mysql-volumeclaim Bound pv0002 25Gi RWO 4s
wordpress-volumeclaim Bound pv0001 25Gi RWO 12s
3. MySQL Root 패스워드 저장
mysql root 패스워드를 mysql-password 라는 secret object 에 저장한다.
# kubectl create secret generic mysql-password --from-literal=password=rP@ssw0rd
# kubectl describe secret mysql-password
Name: mysql-password
Namespace: default
Labels: <none>
Annotations: <none>
Type: Opaque
Data
====
password: 9 bytes
4. MySQL Pod 배포
MySQL 이 설치된 Pod 를 배포하면서 Database , User, User password 도 함께 설정해준다.
아래 예제에서 k8suser 의 패스워드를 노출했는데 위 Root 패스워드의 설정과 같이 secret 오브젝트 형태로 저장해도 된다.
# vi mysql.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql
labels:
app: mysql
spec:
replicas: 1
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- image: mysql:5.6
name: mysql
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-password
key: password
- name: MYSQL_DATABASE # 구성할 database명
value: k8sdb
- name: MYSQL_USER # database에 권한이 있는 user
value: k8suser
- name: MYSQL_ROOT_HOST # 접근 호스트
value: '%'
- name: MYSQL_PASSWORD # database에 권한이 있는 user의 패스워드
value: P@ssw0rd!!
ports:
- containerPort: 3306
name: mysql
volumeMounts:
- name: mysql-persistent-storage
mountPath: /var/lib/mysql
volumes:
- name: mysql-persistent-storage
persistentVolumeClaim:
claimName: mysql-volumeclaim
# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE
mysql-86bb7c99f9-62jmj 1/1 Running 0 3m28s 172.27.116.214 c2node3 <none>
5. MySQL 서비스 생성
앞에서 생성한 MySQL 컨테이너를 노출하기 위해 서비스를 생성하고 뒤에서 생성할 Wordpress 컨테이너가 접근할 수 있도록 설정한다.
# vi mysql-service.yaml
apiVersion: v1
kind: Service
metadata:
name: mysql
labels:
app: mysql
spec:
type: ClusterIP
ports:
- port: 3306
selector:
app: mysql
# kubectl create -f mysql-service.yaml
# kubectl get svc -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
mysql ClusterIP 172.20.12.226 <none> 3306/TCP 3m40s app=mysql
6. Wordpress Pod 배포
wordpress pod 배포 파일에는 MySQL 접근이 가능한 정보가 포함되어야 한다.
# vi wordpress.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: wordpress
labels:
app: wordpress
spec:
replicas: 1
selector:
matchLabels:
app: wordpress
template:
metadata:
labels:
app: wordpress
spec:
containers:
- image: wordpress
name: wordpress
env:
- name: WORDPRESS_DB_HOST
value: mysql:3306
- name: WORDPRESS_DB_NAME
value: k8sdb
- name: WORDPRESS_DB_USER
value: k8suser
- name: WORDPRESS_DB_PASSWORD
value: P@ssw0rd!!
ports:
- containerPort: 80
name: wordpress
volumeMounts:
- name: wordpress-persistent-storage
mountPath: /var/www/html
volumes:
- name: wordpress-persistent-storage
persistentVolumeClaim:
claimName: wordpress-volumeclaim
# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE
mysql-86bb7c99f9-62jmj 1/1 Running 0 3m28s 172.27.116.214 c2node3 <none>
wordpress-7ff695b6c6-vp5rc 1/1 Running 0 2m52s 172.27.116.215 c2node3 <none>
7. Wordpress 서비스 배포
Kubernetes Pod IP 를 사설 IP 로 설정하여 직접 접근이 불가하므로 Node IP 와 Node Port 를 통해 접근할 수 있도록 Wordpress 서비스를 기동한다.
# vi wordpress-service.yaml
apiVersion: v1
kind: Service
metadata:
labels:
app: wordpress
name: wordpress
spec:
type: NodePort
ports:
- port: 80
targetPort: 80
protocol: TCP
selector:
app: wordpress
# kubectl get svc -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
mysql ClusterIP 172.20.12.226 <none> 3306/TCP 3m40s app=mysql
wordpress NodePort 172.17.70.243 <none> 80:31776/TCP 26s app=wordpress
8. Wordpress 웹 접속 및 설정
Wordpress 가 기동된 Pod 의 노드 IP 와 Wordpress 서비스의 Node Port 로 웹 브라우저를 통해 접속한다.
아래와 같은 페이지가 노출되면 정상적으로 서비스 구성이 완료된 것이다.
