Error rendering WebPanel: No renderer found for resource type: velocity Template contents: <meta name="ajs-keyboardshortcut-hash" content="$keyboardShortcutManager.shortcutsHash">
메타 데이터의 끝으로 건너뛰기
메타 데이터의 시작으로 이동


Minikube 란 ?

Kubernetes는 크게 Master Node와 Worker Node 여러 개로 구성되어 있다.

이때, 여기서 말하는 Node들은 하나의 물리 서버 혹은 VM이다.

Minikube 는 이러한 물리 서버 혹은 VM 을 구축할 필요 없이 단일 노드에서 쿠버네티스 환경을 구성해주는 툴이다.

지금부터 로컬 환경에서 minikube 를 통해 쿠버네티스 클러스터를 생성하고 TODO 애플리케이션을 구축해볼 것이다. 

Minikube 설치

https://kubernetes.io/ko/docs/tasks/tools/install-minikube/


클러스터 생성


다음 명령어로 간단히 생성 가능하다.

minikube start


이전에 실행한 적이 있다면, 다음과 같은 에러가 뜰 것이다.

machine does not exist


다음 명령어를 통해 구성을 삭제한 후 다시 생성해준다.

minikube delete



DB 설정

minikube 클러스터를 생성하면 standard 라는 이름의 기본 storageClass 가 생성되어 있다. 

기본 storageClass 를 사용하지 말아야 하는 특별한 경우가 아니라면 해당 storageClass 를 사용하면 된다.


*만약 직접 정의한 storageClass 를 사용하고 싶다면, 다음 링크 참고

https://kubernetes.io/docs/tasks/administer-cluster/change-default-storage-class/#why-change-the-default-storage-class


기본 storageClass 및 생성한 storgaClass 는 다음 명령어로 조회할 수 있다.

kubectl get storageclass




DB 서비스 (master, slave) 실행


데이터를 지속적으로 유지하기 위해 statefulSet 를 사용한다.

kubectl apply -f mysql-master.yaml
kubectl apply -f mysql-slave.yaml
mysql-master.yaml
apiVersion: v1
kind: Service
metadata:
  name: mysql-master
  labels:
    app: mysql-master
spec:
  ports:
  - port: 3306
    name: mysql
  clusterIP: None
  selector:
    app: mysql-master

---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mysql-master
  labels:
    app: mysql-master
spec:
  serviceName: "mysql-master"
  selector:
    matchLabels:
      app: mysql-master
  replicas: 1
  template:
    metadata:
      labels:
        app: mysql-master
    spec:
      terminationGracePeriodSeconds: 60
      containers:
      - name: mysql
        image: gihyodocker/tododb:latest
        imagePullPolicy: Always
        args:
        - "--ignore-db-dir=lost+found"
        ports:
        - containerPort: 3306
        env:
        - name: MYSQL_ROOT_PASSWORD
          value: "gihyo"
        - name: MYSQL_DATABASE
          value: "tododb"
        - name: MYSQL_USER
          value: "gihyo"
        - name: MYSQL_PASSWORD
          value: "gihyo"
        - name: MYSQL_MASTER
          value: "true"
        volumeMounts:
        - name: mysql-data
          mountPath: /var/lib/mysql
  volumeClaimTemplates:
  - metadata:
      name: mysql-data
    spec:
      accessModes: [ "ReadWriteOnce" ]
      storageClassName: standard   # minikube 의 기본 storageClass 를 사용한다
      resources:
        requests:
          storage: 4Gi
mysql-slave.yaml
apiVersion: v1
kind: Service
metadata:
  name: mysql-slave
  labels:
    app: mysql-slave
spec:
  ports:
  - port: 3306
    name: mysql
  clusterIP: None
  selector:
    app: mysql-slave

---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mysql-slave
  labels:
    app: mysql-slave
spec:
  serviceName: "mysql-slave"
  selector:
    matchLabels:
      app: mysql-slave
  replicas: 2
  updateStrategy:
    type: OnDelete
  template:
    metadata:
      labels:
        app: mysql-slave
    spec:
      terminationGracePeriodSeconds: 60
      containers:
      - name: mysql
        image: gihyodocker/tododb:latest
        imagePullPolicy: Always
        args:
        - "--ignore-db-dir=lost+found"
        ports:
        - containerPort: 3306
        env:
        - name: MYSQL_MASTER_HOST
          value: "mysql-master"
        - name: MYSQL_ROOT_PASSWORD
          value: "gihyo"
        - name: MYSQL_DATABASE
          value: "tododb"
        - name: MYSQL_USER
          value: "gihyo"
        - name: MYSQL_PASSWORD
          value: "gihyo"
        - name: MYSQL_REPL_USER
          value: "repl"
        - name: MYSQL_REPL_PASSWORD
          value: "gihyo"
        volumeMounts:
        - name: mysql-data
          mountPath: /var/lib/mysql
  volumeClaimTemplates:
  - metadata:
      name: mysql-data
    spec:
      accessModes: [ "ReadWriteOnce" ]
      storageClassName: standard
      resources:
        requests:
          storage: 4Gi



기본 테이블 생성 및 확인


생성한 DB master 서비스에 테이블을 생성해보고, slave 에서 조회하여 master-slave 구성이 제대로 되었는지 확인한다.

kubectl exec -it mysql-master-0 init-data.sh
kubectl exec -it mysql-slave-0 bash
mysql -u root -pgihyo tododb -e "SHOW TABLES;"
init-data.sh
#!/bin/bash -e

for SQL in `ls /sql/*.sql`
do
  mysql -u root -p$MYSQL_ROOT_PASSWORD $MYSQL_DATABASE < $SQL > /dev/null 2>&1
done





TODO API


kubectl apply -f todo-api.yaml
todo-api.yaml
apiVersion: v1
kind: Service
metadata:
  name: todoapi
  labels:
    app: todoapi
spec:
  selector:
    app: todoapi
  ports:
    - name: http
      port: 80

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: todoapi
  labels:
    app: todoapi
spec:
  replicas: 2
  selector:
    matchLabels:
      app: todoapi
  template:
    metadata:
      labels:
        app: todoapi
    spec:
      containers:
      - name: nginx
        image: gihyodocker/nginx:latest
        imagePullPolicy: Always
        ports:
        - containerPort: 80
        env:
        - name: WORKER_PROCESSES
          value: "2"
        - name: WORKER_CONNECTIONS
          value: "1024"
        - name: LOG_STDOUT
          value: "true"
        - name: BACKEND_HOST
          value: "localhost:8080"
      - name: api
        image: gihyodocker/todoapi:latest
        imagePullPolicy: Always
        ports:
        - containerPort: 8080
        env:
        - name: TODO_BIND
          value: ":8080"
        - name: TODO_MASTER_URL
          value: "gihyo:gihyo@tcp(mysql-master:3306)/tododb?parseTime=true"
        - name: TODO_SLAVE_URL
          value: "gihyo:gihyo@tcp(mysql-slave:3306)/tododb?parseTime=true"


확인

kubectl get pod -l app=todoapi



TODO WEB


kubectl apply -f todo-web.yaml
todo-web.yaml
apiVersion: v1
kind: Service
metadata:
  name: todoweb
  labels:
    app: todoweb
spec:
  selector:
    app: todoweb
  ports:
    - name: http
      port: 80
  type: NodePort

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: todoweb
  labels:
    name: todoweb
spec:
  replicas: 2
  selector:
    matchLabels:
      app: todoweb
  template:
    metadata:
      labels:
        app: todoweb
    spec:
      volumes:
      - name: assets
        emptyDir: {}
      containers:
      - name: nginx
        image: gihyodocker/nginx-nuxt:latest
        imagePullPolicy: Always
        ports:
        - containerPort: 80
        env:
        - name: WORKER_PROCESSES
          value: "2"
        - name: WORKER_CONNECTIONS
          value: "1024"
        - name: LOG_STDOUT
          value: "true"
        - name: BACKEND_HOST
          value: "localhost:3000"
        volumeMounts:   # 정적 파일은 Node.jst 서버를 거치지 않고 Nginx 에서 바로 제공할 수 있도록 가상 볼륨 공유
        - mountPath: /var/www/_nuxt
          name: assets

      - name: web
        image: gihyodocker/todoweb:latest
        imagePullPolicy: Always
        lifecycle:
          postStart:
            exec:  # 마운트 된 경로에 있는 파일을 복사해준다
              command:  
              - cp
              - -R
              - /todoweb/.nuxt/dist 
              - /
        ports:
        - containerPort: 3000
        env:
        - name: TODO_API_URL
          value: http://todoapi
        volumeMounts:   # 정적 파일은 Node.jst 서버를 거치지 않고 Nginx 에서 바로 제공할 수 있도록 가상 볼륨 공유 
        - mountPath: /dist
          name: assets




INGRESS 로 노출하기


minikube 에서 ingress 를 사용하기 위해서는 다음 명령어를 통해 ingress 를 활성화 해주어야 한다.

minikube addons enable ingress


확인

kubectl get pods -n kube-system




kubectl apply -f ingress.yaml
ingress.yaml
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: ingress
spec:
  rules:
  - http:
      paths:
      - path: /*
        backend:
          serviceName: todoweb
          servicePort: 80



아래 명령어를 통해 얻은 url 로 접속 가능하다.

minikube service todoweb --url


*minikube 사용 시,  kubectl get ingress 를 통해 얻는 주소는 internal IP 주소이다. minikube ip 를 통해 external IP 주소를 얻을 수 있다.

https://kubernetes.io/docs/tasks/access-application-cluster/ingress-minikube/


해당 url 로 접속해보면 다음과 같은 화면을 볼 수 있다.







  • 레이블 없음