SaevOps
[OCI] OKE 구성 본문
1. 구획 생성
- ID 및 보안 - 구획에서 생성
2. OKE 클러스터 생성
1) 빠른 생성 클릭
2) 이름 설정 후 버전 체크, 노드 수(기본적으로 3개) 변경
- 검토 후 생성 버튼 클릭하면 15분 정도 시간이 지난 후 생성됨.
3. 어플리케이션 파일 업로드
1) 홈페이지에서 터미널을 연 다음 파일을 드래그 앤 드롭으로 업로드
4. Docker로 Mysql Container 실행
1) 3306 포트로 포트포워딩 설정 후 run
saehyunkim@cloudshell:sample (ap-seoul-1)$ docker run -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD=password --name mysql mysql:5.7
……………
saehyunkim@cloudshell:sample (ap-seoul-1)$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
mysql 5.7 eef0fab001e8 2 weeks ago 495MB
saehyunkim@cloudshell:sample (ap-seoul-1)$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
703a680ddf19 mysql:5.7 "docker-entrypoint.s…" 27 seconds ago Up 17 seconds 0.0.0.0:3306->3306/tcp, 33060/tcp mysql
2) docker에 접속 , mysql 접속
$ docker exec -it mysql /bin/sh
$ mysql –u root –p
3) 데이타베이스 데이터 넣기
CREATE USER 'test'@'%' IDENTIFIED WITH mysql_native_password BY 'Welcome1';
GRANT USAGE ON *.* TO 'test'@'%';
GRANT ALL PRIVILEGES ON *.* TO 'test'@'%';
CREATE DATABASE sample DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
USE sample;
CREATE TABLE IF NOT EXISTS `players` (
`id` int(5) NOT NULL AUTO_INCREMENT,
`first_name` varchar(255) NOT NULL,
`last_name` varchar(255) NOT NULL,
`position` varchar(255) NOT NULL,
`number` int(11) NOT NULL,
`user_name` varchar(20) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1;
4. 환경변수 설정 및 node js app 실행
# 환경 변수 설정
$ export MYSQL_SERVICE_HOST=localhost
$ export MYSQL_SERVICE_USER=test
$ export MYSQL_SERVICE_PASSWORD=Welcome1
$ export MYSQL_SERVICE_DATABASE=sample
# Node js app 실행
$ cd ~/app-sample/sample/oke-sample
$ npm install
$ npm start &
# 홈페이지 조회
& curl localhost:8080
5. DockerFile 작성 및 이미지 생성
1) dockerfile 작성
saehyunkim@cloudshell:oke-sample (ap-seoul-1)$ cat dockerfile
# Node 버젼8의 이미지를 기본으로 합니다.
FROM node
# 애플리케이션이 위치할 디렉토리를 생성합니다.
WORKDIR /user/src/app
# npm을 이용하여 필요한 패키지를 설치합니다.
COPY package*.json ./
RUN npm install
# 모든 애플리케이션 파일을 복사합니다.
COPY . .
# 포트를 익스포즈합니다.
EXPOSE 8080
# 애플리케이션을 실행합니다.
CMD ["npm", "start"]
2) docker 이미지 생성 (빌드)
saehyunkim@cloudshell:oke-sample (ap-seoul-1)$ docker build -t oke-sample .
3) 만든 docker 이미지 확인 (oke-sample)
saehyunkim@cloudshell:oke-sample (ap-seoul-1)$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
oke-sample latest c288dedb074d About a minute ago 1.01GB
node latest c71adfc6ec58 7 days ago 995MB
mysql 5.7 eef0fab001e8 2 weeks ago 495MB
5. 이미지 등록 (OCIR)
1) 로그인을 위한 Token 생성
- 프로필 > 이메일 -> 인증토큰 -> 토큰 생성 -> 생성된 키값 복사
2) 컨테이너 레지스트리 저장소 생성
- 개발자 서비스 - 컨테이너 레지스트리 - 저장소 생성
- OKE-TEST - oke-mysql
- OKE-TEST - oke-app
3) OCIR 로그인
- 터미널 접속 후 다음 코드 입력
$ docker login icn.ocir.io
Username: <Namespace>/oracleidentitycloudservice/<사용자 계정>
Password: <사용자 Auth token>
# 예시
$ docker login icn.ocir.io
Username: cnob43ghjvg2/oracleidentitycloudservice/saehyunkim@idatabank.com
Password: Zkq1W+_diou~
...
Login Succeeded
4) Docker Image에 OCIR Tagging
$ docker tag mysql:5.7 icn.ocir.io/<Namespace>/oke-mysql:5.7
$ docker tag oke-sample icn.ocir.io/<Namespace>/oke-app:v1
# 예시
$ docker tag mysql:5.7 icn.ocir.io/cnob43ghjvg2/oke-mysql:5.7
$ docker tag oke-sample icn.ocir.io/cnob43ghjvg2/oke-app:v1
5) Docker Image를 OCIR로 Push
$ docker push icn.ocir.io/<Namespace>/oke-mysql:5.7
$ docker push icn.ocir.io/<Namespace>/oke-app:v1
#예시
$ docker push icn.ocir.io/cnob43ghjvg2/oke-mysql:5.7
$ docker push icn.ocir.io/cnob43ghjvg2/oke-app:v1
6. OKE Cluster 연결
- 개발자 서비스 - OKE - 클러스터에 엑세스
1) [ Cloud Shell 엑세스 ] - 명령어 복사한 것 붙여넣기
2) OCIR 연결을 위한 Secret 생성 및 확인
$ kubectl create secret docker-registry ocirsecret --docker-server=icn.ocir.io \
--docker-username='<Namespace>/oracleidentitycloudservice/<사용자 계정>' --docker-password='<사용자 Auth token>'
$ kubectl get secret
#예시
$ kubectl create secret docker-registry ocirsecret --docker-server=icn.ocir.io \
--docker-username='<Namespace>/oracleidentitycloudservice/saehyunkim@idatabank.com' --docker-password='Zkq1W+_di~'
$ kubectl get secret
NAME TYPE DATA AGE
ocirsecret kubernetes.io/dockerconfigjson 1 23s
3) MySQL의 pv, pvc 생성
$ kubectl create -f ~/app-sample/sample/yaml-sample/mysql-pv.yaml
$ kubectl get pv,pvc
# 예시
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
persistentvolume/mysql-pv-volume 2Gi RWO Retain Bound default/mysql-pv-claim manual 23s
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
persistentvolumeclaim/mysql-pv-claim Bound mysql-pv-volume 2Gi RWO manual 23s
4) MySQL 배포
$ sed -i 's/cntazks6zuxc/<Namespace>/g' ~/app-sample/sample/yaml-sample/mysql-deployment.yaml
$ kubectl create -f ~/app-sample/sample/yaml-sample/mysql-deployment.yaml
$ kubectl get pod,deployment,service
#예시
$ sed -i 's/cntazks6zuxc/cnob43ghjvg2/g' ~/app-sample/sample/yaml-sample/mysql-deployment.yaml
$ kubectl create -f ~/app-sample/sample/yaml-sample/mysql-deployment.yaml
$ kubectl get pod,deployment,service
5) Mysql 접속
$ kubectl get pod
$ kubectl exec <mysql pod_이름> -it -- /bin/sh
# mysql -u root -p
Enter password : <root_password>
# 예시
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
mysql-78647f56b8-kzs9x 1/1 Running 0 15h
$ kubectl exec mysql-78647f56b8-kzs9x -it -- /bin/sh
$ mysql -uroot -p
6) Mysql Table 삽입
CREATE USER 'test'@'%' IDENTIFIED WITH mysql_native_password BY 'Welcome1';
GRANT USAGE ON *.* TO 'test'@'%';
GRANT ALL PRIVILEGES ON *.* TO 'test'@'%';
CREATE DATABASE sample DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
USE sample;
CREATE TABLE IF NOT EXISTS `players` (
`id` int(5) NOT NULL AUTO_INCREMENT,
`first_name` varchar(255) NOT NULL,
`last_name` varchar(255) NOT NULL,
`position` varchar(255) NOT NULL,
`number` int(11) NOT NULL,
`user_name` varchar(20) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1;
7. OKE-APP 배포
1) NameSpace 변경 후 yaml파일을 이용하여 생성
$ sed -i 's/cntazks6zuxc/<Namespace>/g' ~/app-sample/sample/yaml-sample/app-deployment.yaml
$ kubectl create -f ~/app-sample/sample/yaml-sample/app-deployment.yaml
$ kubectl get pod,deployment,service
# 예시
$ sed -i 's/cntazks6zuxc/cnob43ghjvg2/g' ~/app-sample/sample/yaml-sample/app-deployment.yaml
$ kubectl create -f ~/app-sample/sample/yaml-sample/app-deployment.yaml
$ kubectl get pod,deployment,service
2) 상태 조회 예시 보고 oke-app IP:8080 홈페이지 접속
saehyunkim@cloudshell:~ (ap-seoul-1)$ kubectl get pod,deployment,service
NAME READY STATUS RESTARTS AGE
pod/mysql-78647f56b8-kzs9x 1/1 Running 0 15h
pod/oke-app-6f59fd8db4-8bh5z 0/1 ContainerCreating 0 5s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/mysql 1/1 1 1 15h
deployment.apps/oke-app 0/1 1 0 5s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP,12250/TCP 7d18h
service/mysql ClusterIP 10.96.252.157 <none> 3306/TCP 15h
service/oke-app LoadBalancer 10.96.194.230 <pending> 8080:31129/TCP 5s
saehyunkim@cloudshell:~ (ap-seoul-1)$ kubectl get pod,deployment,service
NAME READY STATUS RESTARTS AGE
pod/mysql-78647f56b8-kzs9x 1/1 Running 0 15h
pod/oke-app-6f59fd8db4-8bh5z 1/1 Running 0 31s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/mysql 1/1 1 1 15h
deployment.apps/oke-app 1/1 1 1 31s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP,12250/TCP 7d18h
service/mysql ClusterIP 10.96.252.157 <none> 3306/TCP 15h
service/oke-app LoadBalancer 10.96.194.230 152.70.94.x 8080:31129/TCP 31s
3) 서비스 페이지 예시
9. Scale-Out
현재에는 파드가 하나도 돌아가고 있는 중
이를 3개의 파드로 늘리는 과정을 통해 여러 노드에서 사용하게 하여 부하를 분산시킨다.
$ kubectl scale deployment oke-app --replicas=3
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
mysql-78647f56b8-kzs9x 1/1 Running 0 16h
oke-app-6f59fd8db4-8bh5z 1/1 Running 0 19m
oke-app-6f59fd8db4-gbc85 1/1 Running 0 26s
oke-app-6f59fd8db4-jwsrb 1/1 Running 0 26s
9. 홈페이지를 각기 다른 브라우저(크롬,엣지,익스플로러,...)로 연결하여 확인
IP Address가 변하는 것을 보며 스케일 아웃도 잘 확인된 것을 확인 가능
트러블 슈팅
파드 상태조회 결과 ImagePullBackOff라고 뜨며 변한 것을 볼 수 있다.
원인은 다음과 같다.
- 이미지 경로가 존재하지 않음 (주이유)
- 이미지 이름을 잘못입력
- 이미지 등록시 권한 필요
- 이미지 용량 초과
NAME READY STATUS RESTARTS AGE
mysql-78647f56b8-nrdtc 0/1 ImagePullBackOff 0 9m14s
해결
deployment를 제거하고 새로 yaml파일을 만들면, ErrImagePull로 변한 모습이 확인가능하다.
# yaml파일로 생성한 파일들 모두 삭제
kubectl delete -f ~/app-sample/sample/yaml-sample/mysql-pv.yaml
kubectl delete -f ~/app-sample/sample/yaml-sample/mysql-deployment.yaml
# yaml 파일로 파일 다시 생성
kubectl create -f ~/app-sample/sample/yaml-sample/mysql-pv.yaml
kubectl create -f ~/app-sample/sample/yaml-sample/mysql-deployment.yaml
NAME READY STATUS RESTARTS AGE
mysql-78647f56b8-kccgq 0/1 ErrImagePull 0 7s
이후 시간이 지나면 (환경마다 다름) pod가 running 상태로 잘 돌아가는 모습을 확인할 수 있다.
saehyunkim@cloudshell:~ (ap-seoul-1)$ kubectl get pod
NAME READY STATUS RESTARTS AGE
mysql-78647f56b8-kzs9x 1/1 Running 0 15h
Pod 상태 상세조회를 위해서는 describe 명령어를 사용하면 디테일한 정보를 알 수 있다.
# Pod 조회로 이름 검색
kubectl get pod
# 조회한 이름으로 상세 확인
kubectl describe pod/mysql-78647f56b8-kzs9x

간단한 서비스를 프라이빗 레지스트리에 등록하고 배포하는 과정을 통해 전체적인 흐름을 이해할 수 있는 과정이었다.
하루면 될 줄 알았던 과정이었으나 생각지도 못한 에러로 일주일정도 시간을 보낸 것 같다.
많은 에러를 겪어보고 빠르게 실력이 늘길 바라며 포스팅을 마무리 한다.
'클라우드 > Kubernetes' 카테고리의 다른 글
[ELK] ElasticSearch 설치 (1) | 2023.10.17 |
---|---|
[k8s] 명령어 자동 완성 / 별칭 / 약어 정리 (0) | 2023.02.16 |
[쿠버네티스] 아키텍처 및 구성도 (0) | 2022.11.23 |
[쿠버네티스] 인그레스 / 인그레스 컨트롤러 (0) | 2022.10.26 |
[쿠버네티스] 노드포트 / 클러스터 내부 접속 / 부하분산 (0) | 2022.10.25 |