Run The Bridge

docker-registry를 이용해 toyproject k8s에 deployment로 올리기 본문

Cloud/k8s

docker-registry를 이용해 toyproject k8s에 deployment로 올리기

anfrhrl5555 2021. 8. 16. 15:05
728x90

0. 실습과제


1. Private docker-registry를 k8s의 RelicaSet으로 올리기

해당 작업을 하기 위해서는 먼저 docker-registry를 올려야 한다. 

 

docker-registry를 올릴 때, NFS를 사용하기 때문에 pv, pvc 설정도 해주어야 하며, registry의 config.yml 파일의 위치도 지정해주어야 한다.

 

docker-registry.yaml 파일 구조는 다음과같다.

# vi docker-registry.yaml

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: docker-registry
  labels:
    app: docker-registry

spec:
  replicas: 1  # replicas 설정
  selector:
    matchLabels:
      app: docker-registry  # template 이름과 맞춰준다.
  template:
    metadata:
      name: docker-registry
      labels:
        app: docker-registry  # 임의설정
    spec:
      containers:
        - name: docker-registry  # pod 이름지정
          image: registry:2.6  # image 버전
          volumeMounts:  # NFS mount 지점 설정
            - name: docker-config-yml
              mountPath: /etc/docker/registry  # 마운트포인트
            - name: nfs-volume
              mountPath: /mnt  # NFS 파일공유 위치
          ports:
            - containerPort: 5000  # 사용할 port

      volumes:
       - name: docker-config-yml
         configMap:
           name: config-envfile  # config.yml를 configMap으로 만든다음 설정
       - name: nfs-volume
         persistentVolumeClaim:  # NFS 사용을 위한 pv, pvc 설정
          claimName: docker-registry-pvc

 

docker-registry에 들어가는 config.yml 파일의 구조는 다음과 같다. filesystem의 rootdirectory만 '/mnt'로 바꿔주었다.

# vi config.yml

version: 0.1
log:
  level: info
storage:
  filesystem:
    rootdirectory: /mnt
  delete:
    enabled: true
http:
  addr: 0.0.0.0:5000

 

NFS 연결을 위한 pv 파일 구조는 다음과같다.

# vi docker-registry-pv.yaml

apiVersion: v1
kind: PersistentVolume
metadata:
  name: docker-registry-pv  # 임의의 이름
spec:
  capacity:
    storage: 5Gi  # 5gb
  accessModes:
    - ReadWriteMany
  volumeMode: Filesystem
  persistentVolumeReclaimPolicy: Retain
  nfs:
    server: 192.168.100.140  # NFS, master Node의 IP
    path: /nfs/images  # /nfs에 images 디렉토리를 생성하고 경로를 잡는다.

 

pv를 보았으니 이제 pvc도 필요하므로 pvc 구조는 다음과같다.

# vi docker-registry-pvc.yaml

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: docker-registry-pvc  # 임의이름
spec:
  storageClassName: ""
  accessModes:
    - ReadWriteMany  # 1:N
  resources:
    requests:
      storage: 5Gi  # 5GB

 

또한 실습과제에서 NodePort로 노출해야 하므로 NodePort.yaml 파일도 짜야한다. 다음과 같다

# vi docker-registry-nodeport.yaml

apiVersion: v1
kind: Service
metadata:
  name: docker-registry-nodeport
spec:
  ports:
    - name: docker-registry-nodeport
      port: 5000  # 외부 통신 포트
      targetPort: 5000  # 내부 통신 포트
      nodePort: 30000 # 노출할 NodePort
  selector:
    app: docker-registry  # docker-registry.yaml에 정의한 이름
  type: NodePort

 

여기까지 하면 registry 설정은 끝난다. 이제 마지막인 'myregistry.images.io:30000'로 접속 부분을 해결해야 한다.

 

예전에도 한 번 설명했는데 /etc/hosts 와 /etc/docker/daemon.json 파일을 건드려줘야 한다.

 

한 번 해보자.

# vi /etc/hosts

127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.100.140 kube-master1
192.168.100.140 myregistry.images.io
192.168.100.141 kube-worker1
192.168.100.142 kube-worker2
# vi /etc/docker/daemon.json

{
        "insecure-registries": ["192.168.100.140:5000", "myregistry.images.io:30000"]
}

위의 세팅을 3개의 Node 전부 다 해줘야 한다.

 

윈도의 DNS 설정이라고 보면 된다.

C:\Windows\System32\drivers\etc\hosts

위의 경로에 위치한 hosts 파일과 똑같다 보면 된다.

 

위의 설정이 전부 끝났다면 'kubectl apply -f'으로 yaml파일을 모두 실행시켜주자

 

모두 잘 올라왔다.

 

우리가 수정한 대로 yml 파일이 잘 들어갔다. mkdir || touch를 사용해서 아무 파일이나 만든 뒤, /nfs/images에서 확인

 

test 디렉터리가 잘 만들어진다. 이제 image를 Pull 하면 /nfs/images로 저장되게 하면 된다.


2. toyproject에 작성한 app을 k8s에 Deployment로 올리기

2-1 mariadb01

 

예전에 사용한 파일들을 '.yaml'파일로 고쳐야한다.

 

천천히 Database 먼저 구축해보자. 먼저 mariadb01부터 한다

 

요구조건

  • replicas 1
  • Cluster IP type
  • app간 호출은 service name
  • db의 데이터 NFS를 이용하여 PV를 사용

그리고 하기전에 imaeg를 먼저 아까만든 /nfs/images에 mount 시켜놓고, yaml파일로 불러와야 한다.

(공개망이면 docker hub를 쓰면되지만, 폐쇄망이면 private-registry를 사용해야하기 때문)

# vi Dockerfile_mariaDB_01

FROM mariadb:10.6.3

ENV MYSQL_ROOT_PASSWORD=root

ENV MYSQL_DATABASE=flask01_db

ENV MYSQL_USER=flask01

ENV MYSQL_PASSWORD=flask01

COPY my.cnf /etc/mysql/my.cnf

EXPOSE 3000

CMD ["mysqld"]
docker build -t mariadb01:0.0 -f Dockerfile_mariaDB_01  # build
 
docker images  # build 확인

docker tag mariadb01:0.0 myregistry.images.io:30000/mariadb01:0.0  # tag명 변경

docker images # 결과 확인


--------------------------result--------------------------
myregistry.images.io:30000/mariadb01   0.0                 52b730d4f0e9        About a minute ago   409MB
--------------------------result--------------------------

docker push myregistry.images.io:30000/mariadb01:0.0  # /nfs/images로 push

mariadb01이 push된 것을 볼 수 있다. 

 

이제 push가 되었으니 .yaml 파일을 만들어야 한다.

# vi mariadb01.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: mariadb01
  labels:
    app: mariadb01
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mariadb01
  template:
    metadata:
      name: mariadb01
      labels:
        app: mariadb01
    spec:
      containers:
      - name: mariadb01
        image: myregistry.images.io:30000/mariadb01:0.0  # push된 image를 받는다.
        volumeMounts:
        - name: maraidb01-database
          mountPath: /var/lib/mysql  # my.cnf 저장
        ports:
          - containerPort: 3000

      volumes:
      - name: maraidb01-database  # DB data를 위해 volume 사용
        persistentVolumeClaim:
          claimName: mariadb01-pvc

/NFS에 mariadb_database 디렉토리를 생성해놨다.

다음은 포트를 열어주어야 한다.

# vi mariadb01-clusterIP.yaml

apiVersion: v1
kind: Service
metadata:
  name: mariadb01-clusterip

spec:
  ports:
    - name: mariadb01-clusterip
      port: 3000
      targetPort: 3000
  selector:
    app: mariadb01
  type: ClusterIP

 

이제 pv, pvc 설정만 하면 DB-01은 완료

# vi mariadb01-pv.yaml

apiVersion: v1
kind: PersistentVolume
metadata:
  name: mariadb01-pvc
spec:
  capacity:
    storage: 5Gi
  accessModes:
  - ReadWriteMany
  volumeMode: Filesystem
  persistentVolumeReclaimPolicy: Retain
  nfs:
    server: 192.168.100.140
    path: /nfs/mariadb_database
# vi mariadb01-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mariadb01-pvc
spec:
  storageClassName: ""
  accessModes:
  - ReadWriteMany
  resources:
    requests:
      storage: 5Gi

 

모든 파일을 작성완료했으면 'kubectl apply -f'로 실행시켜준다.

DB에 데이터를 간단하게 만들고, '/nfs'에 가서 확인한다.

registry에 mariadb 자료가 잘 들어와있다.

 

같은방법으로 mariadb02도 해주면된다.

 


2. toyproject에 작성한 app을 k8s에 Deployment로 올리기

2-2 flask01

 

flask도 크게 차이점은 없다. 오히려 pv, pvc를 사용하지 않기 때문에 간단하다. 빠르게 알아보자

 

요구조건

  • relicas 1
  • ClusterIP type
  • app간 호출은 service name

flask01도 image를 push 해야하는건 똑같다.

# vi Dockerfile_python_01

FROM python:3

WORKDIR /usr/src/app

COPY requirements.txt .

RUN pip install --no-cache-dir -r requirements.txt

RUN pip install pymysql

COPY . .

EXPOSE 8000

CMD ["python", "./app.py"]
# vi requirements.txt

flask==2.0.1
pymysql
requests==2.25.1
urllib3==1.26.4
xmltodict==0.12.0
docker build -t myregistry.images.io:30000/flask01:0.0 -f Dockerfile_python_01 . # tag명을 변경하지않고 바로 진행

docker images  # image 확인

docker push myregistry.images.io:30000/flask01:0.0  # /nfs/images로 push

flask01 image가 잘 들어갔다.

이제 .yaml파일만 작성하면 된다.

# vi flask01.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: flask01
  labels:
    app: flask01

spec:
  replicas: 1
  selector:
    matchLabels:
      app: flask01
  template:
    metadata:
      name: flask01
      labels:
        app: flask01
    spec:
      containers:
        - name: flask01
          image: myregistry.images.io:30000/flask01:0.0
          imagePullPolicy: Always  # app.py에 변동이 있으면 rebuild
          ports:
          - containerPort: 8000
# vi flask01-clusterIP.yaml

apiVersion: v1
kind: Service
metadata:
  name: flask01-clusterip
spec:
  ports:
  - name: flask01-clusterip
    port: 8000
    targetPort: 8000
  selector:
    app: flask01
  type: ClusterIP
# vi app.py
import pymysql
import time
from flask import Flask

time.sleep(5)
app = Flask(__name__)


@app.route("/select", methods=["GET"])
def select():
    juso_db = pymysql.connect(
        user='flask01',
        password='flask01',
        host='mariadb01-clusterip',  # mariadb01의 service pod에서 설정한 이름: mariadb01-clusterip
        port=3000,
        db='flask01_db',
        charset='utf8'
    )
    cursor = juso_db.cursor()
    sql = "select id, email, phone_number from private;"
    cursor.execute(sql)
    row = cursor.fetchall()
    print(row)

    lst = []
    for data in row:
        dic = {
            'id' : data[0],
            'email' : data[1],
            'phone_number' : data[2]
        }
        lst.append(dic)

    juso_db.close()

    return str(lst)



@app.route('/')
def hello_world():
    return 'Hello, world!'


if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8000)

모든 파일을 작성했으면 'kubectl apply -f'로 실행시킨다.

 

그다음에 service 명을 보고 curl를 날려서 flask01이 잘 받아오는지 확인한다. (나는 성공)

 

똑같은 방식으로 flask02도 올리면된다.

 

app.py 내용만 조금 바뀐다.


2. toyproject에 작성한 app을 k8s에 Deployment로 올리기

2-3 main

 

main은 이제 외부접속이 가능해야하므로 NodePort를 사용한다.

 

요구조건

  • replicas 1
  • NodePort type
  • app간 호출은 service name

main도 마찬가지로 /nfs/images에 push 해놓고 받아야한다.

# vi Dockerfile_main

FROM python:3
WORKDIR /usr/src/app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
RUN pip install pymysql
COPY . .
EXPOSE 8000
CMD ["python", "./app_main.py"]
docker build -t myregistry.images.io:30000/main -f Dockerfile_main .  # tag명을 바로 지정

docekr images  # 확인

docker push myregistry.images.io:30000/main:latest  # /nfs/images로 push

main image가 추가되었다.

이제 yaml파일을 작성한다.

# vi main.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: main
  labels:
    app: main

spec:
  replicas: 1
  selector:
    matchLabels:
      app: main
  template:
    metadata:
      name: main
      labels:
        app: main

    spec:
      containers:
        - name: main
          image: myregistry.images.io:30000/main:0.0  # push 해논 image를 pull
          imagePullPolicy: Always
          ports:
          - containerPort: 8000
# vi main-nodeport.yaml

apiVersion: v1
kind: Service
metadata:
  name: main-nodeport
spec:
  ports:
  - name: main
    port: 8000  # 외부통신포트
    targetPort: 8000  # 내부통신포트
  selector:
    app: main
  type: NodePort

모든 yaml 파일 작성이 끝나면 이제 'kubectl apply -f'로 실행한다.

 

service가 올라갔으므로 외부접속을 통해 확인해본다.

 

master node의 IP를 적어준다.

 

위와같이 뜨면 성공!


N. 소감

어려웠던 점: pv, pvc를 직전에 배우고 바로 실습에 들어가서 응용부분에 어려움을 느꼈다. 또한 예전엔 docker-compose.yml 파일을 썼다면, 지금은 파일마다 .yaml 파을 만들어줘야해서 헷갈리지않게 생각해야 했다. 또한 port에 대해서 내부통신포트와 외부통신포트를 어떻게 지정해주어야 하는지 확신이 없었다. 마지막으로 private-registry를 사용해서 push해야해서 이때까지 해오던 실습방식과 좀 달랐다.

 

해결방안: pv, pvc는 강의시간에 사용한 파일을 사용해 test를 진행해서 동작하는것을 확인하였으며, .yaml파일도 양식이 크게 다르지 않았다. private-registry는 생각보다 금방 구현이 되었다. 이또한 ubuntu:16.04 버전으로 test를 통해 image가 올라가는것을 확인했으며, port는 강사님 도움을 받아 하나의 port를 써도된다고 하셨다. (why? → Pod마다 IP가 다르기 떄문에)

 

느낀 점: 이떄까지 사용하던 모든 실습들의 집약체라고 느껴졌다. 모든걸 다 이해하고있어야 고민하면서 파일을 작성할 수 있었고, 혼자했다면 '이게 맞나?, 아닌가?' 하면서 수없이 고민했을것이다. 그래도 꾸준히 블로그에 리뷰같은 복습을 하면서 내용을 익혀가셔 약간의 실마리를 찾으면 바로 문제를 해결할 수 있었다.


감사합니다. Thank you!

728x90

'Cloud > k8s' 카테고리의 다른 글

k8s 7일차  (0) 2021.08.18
k8s 6일차  (0) 2021.08.17
k8s 5일차  (0) 2021.08.13
Secert과 tls 타입의 시크릿 생성 후 mysql, wordpress, nginx 적용  (0) 2021.08.11
k8s 4일차  (0) 2021.08.11
Comments