From f1accba9d399f04dd454c22e35158eaeb5ad72fc Mon Sep 17 00:00:00 2001 From: dev-jonghoonpark Date: Wed, 13 Nov 2024 20:51:58 +0900 Subject: [PATCH] =?UTF-8?q?add=20post=20'[k8s]=20=EC=BF=A0=EB=B2=84?= =?UTF-8?q?=EB=84=A4=ED=8B=B0=EC=8A=A4=EB=A1=9C=20=EC=96=B4=ED=94=8C?= =?UTF-8?q?=EB=A6=AC=EC=BC=80=EC=9D=B4=EC=85=98=20=EB=B0=B0=ED=8F=AC?= =?UTF-8?q?=ED=95=98=EA=B8=B0'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...3\353\205\204-\355\232\214\352\263\240.md" | 7 +- _posts/2024-08-24-mysql-architecture.md | 20 +- .../2024-09-07-mysql-lock-and-transaction.md | 4 +- ...-09-28-mysql-compression-and-encryption.md | 4 +- ...024-11-03-mysql-full-scan-query-pattern.md | 2 + _posts/2024-11-06-java-guava-ratelimiter.md | 10 +- ...2024-11-13-deploy-application-using-k8s.md | 295 ++++++++++++++++++ .../plan.png | Bin 0 -> 8724 bytes 8 files changed, 322 insertions(+), 20 deletions(-) create mode 100644 _posts/2024-11-13-deploy-application-using-k8s.md create mode 100644 assets/images/2024-11-13-deploy-react-project-using-k8s/plan.png diff --git "a/_posts/2023-12-25-2023\353\205\204-\355\232\214\352\263\240.md" "b/_posts/2023-12-25-2023\353\205\204-\355\232\214\352\263\240.md" index 543c4c5..079e08c 100644 --- "a/_posts/2023-12-25-2023\353\205\204-\355\232\214\352\263\240.md" +++ "b/_posts/2023-12-25-2023\353\205\204-\355\232\214\352\263\240.md" @@ -18,6 +18,7 @@ tags: [ 커리어 커피챗, 커뮤니티, + 대전 개발자 스터디, ] date: 2023-12-25 16:30:00 +0900 --- @@ -172,7 +173,7 @@ K-DEVCON Daejeon 에서 진행한 12월 행사에서 운영자로서의 회고 ### 공부 할 것 -K-DEVCON 대전 오프라인 스터디에서는 +K-DEVCON 대전 개발자 스터디에서는 - 데이터 중심 애플리케이션 설계 - 시스템 디자인 2 @@ -232,3 +233,7 @@ K-DEVCON Daejeon과 함께 GDG Daejeon 에서도 많은 활동을 해나갈 수 올해를 마무리 하면서 개인 명함을 만들어 봤다. ![개인%20명함%20디자인](/assets/images/2023-12-25-2023년-회고/개인%20명함%20디자인.jpeg) + +## 기타 + +대전 개발자 스터디 에 관심이 있다면 [구글 폼](http://k-devcon.web.app/daejeon-membership) 을 통해 신청할 수 있다. diff --git a/_posts/2024-08-24-mysql-architecture.md b/_posts/2024-08-24-mysql-architecture.md index 1cf3fe4..d881552 100644 --- a/_posts/2024-08-24-mysql-architecture.md +++ b/_posts/2024-08-24-mysql-architecture.md @@ -16,13 +16,13 @@ tags: flow, thread, thread pool, - metadata + metadata, ] date: 2024-08-24 23:59:59 +0900 toc: true --- -[K-DEVCON](https://k-devcon.com) 대전 오프라인 스터디에서 Real Mysql 책으로 스터디를 진행해보기로 했다. +[K-DEVCON](https://k-devcon.com) 대전 개발자 스터디에서 Real Mysql 책으로 스터디를 진행해보기로 했다. 발표하면서 준비한 내용을 블로그로도 옮겨보려고 한다. @@ -30,6 +30,8 @@ toc: true 이 글의 내용은 Mysql 8.0 에서 InnoDB 를 기준으로 정리되었다. 이 글은 정리글이기에 생략이 있으며, 책에서는 이전 버전이나 다른 스토리지 엔진에 대해서도 다루기도 하고 더 자세한 내용들을 다루고 있다. 책의 구성이 이미 안다는것을 전제하에 진행된 부분들도 있어 해당 부분에 대해서 보충설명을 넣기도 하였다. +참고로 대전 개발자 스터디 에 관심이 있다면 [구글 폼](http://k-devcon.web.app/daejeon-membership) 을 통해 신청할 수 있다. + --- # 아키텍처 - Real MySQL 스터디 1회차 @@ -254,14 +256,14 @@ MySQL 은 **스레드 기반**으로 작동한다. 스레드는 크게 Foregroun ### 체인지 버퍼 -레코드 INSERT 되거나 UPDATE 될 때 변경해야 할 인덱스 페이지가 버퍼 풀에 있으면 바로 업데이트를 수행하지만 그렇지 않고 디스크로부터 읽어와서 업데이트해야 한다면 이를 즉시 실행하지 않고 임시 공간(= 체인지 버퍼)에 저장해 두고 바로 사용자에게 결과를 반환하는 형태로 성능을 향상시킨다. -\* 유니크 인덱스는 체인지 버퍼를 사용할 수 없다. 반드시 중복 여부를 체크해야 하기 때문 +레코드 INSERT 되거나 UPDATE 될 때 변경해야 할 인덱스 페이지가 버퍼 풀에 있으면 바로 업데이트를 수행하지만 그렇지 않고 디스크로부터 읽어와서 업데이트해야 한다면 이를 즉시 실행하지 않고 임시 공간(= 체인지 버퍼)에 저장해 두고 바로 사용자에게 결과를 반환하는 형태로 성능을 향상시킨다. \* 유니크 인덱스는 체인지 버퍼를 사용할 수 없다. 반드시 중복 여부를 체크해야 하기 때문 ### 어댑티브 해시 인덱스 InnoDB 스토리지 엔진에서 사용자가 자주 요청하는 데이터에 대해 자동으로 생성하는 인덱스 다음의 경우에 유용하다. + - 디스크의 데이터가 InnoDB 버퍼 풀 크기와 비슷한 경우 (디스크 읽기가 많지 않은 경우) - 동등 조건 검색(동등 비교와 IN 연산자)이 많은 경우 - 쿼리가 데이터 중에서 일부 데이터에만 집중되는 경우 @@ -275,6 +277,7 @@ SHOW ENGINE INNODB STATUS 명령어를 통해서 사용 빈도를 확인할 수 스토리지 엔진은 버퍼 풀이라는 거대한 메모리 공간을 페이지로 나누어 관리한다. 버퍼 풀은 크게 아래의 3개의 자료 구조로 관리한다. + - LRU 리스트 (Least Recently Used) - 플러시 리스트 (Flush) - 프리 리스트 (Free) : 비어있는 공간을 관리 @@ -293,7 +296,7 @@ InnoDB의 LRU 리스트는 2개의 LRU 리스트가 결합된 형태이다. 데 이 구조의 장점은 무엇일까? 자주 사용되지 않는 데이터가 LRU list에 추가되었을 때, 더 빨리 방출될 수 있을 것이다. -### 버퍼 풀과 리두 로그 +### 버퍼 풀과 리두 로그 버퍼 풀은 데이터 캐시와 쓰기 버퍼링 역할을 한다. 버퍼 풀의 메모리 용량만 늘릴 경우에는 캐시 기능만 향상된다. 쓰기 버퍼링 기능까지 향상시키려면 리두 로그의 크기도 적절히 설정해줘야 한다. @@ -398,8 +401,6 @@ transaction isolation levels described by the SQL:1992 standard ![transaction-isolation-level-compare-2](/assets/images/2024-08-24-mysql-architecture/transaction-isolation-level-compare-2.png) - - ### ACID - 원자성 (atomicity) : 부분적으로 실행되다가 중단되지 않는 것을 보장한다는 것을 의미 @@ -417,7 +418,7 @@ transaction isolation levels described by the SQL:1992 standard ## 자동 데드락 감지 -내부적으로 잠금 대기 목록을 관리한다. 데드락 감지 스레드가 주기적으로 잠금 대기 목록을 검사해 교착 상태에 빠진 트랜잭션을 찾아 그 중 하나를 강제 종료한다. +내부적으로 잠금 대기 목록을 관리한다. 데드락 감지 스레드가 주기적으로 잠금 대기 목록을 검사해 교착 상태에 빠진 트랜잭션을 찾아 그 중 하나를 강제 종료한다. innodb_table_locks 시스템 변수를 활성화 하면 스토리지 엔진 내부의 레코드 잠금뿐만 아니라 테이블 레벨의 잠금까지 감지할 수 있다. @@ -460,6 +461,3 @@ InnoDB에는 손실이나 장애로부터 데이터를 보호하기 위한 여 - 실행된 쿼리중 오래걸리는 쿼리를 기록 - long_query_time (default : 10s) - pt-query-digest 스크립트를 사용하면 쉽게 분석가능 - - - diff --git a/_posts/2024-09-07-mysql-lock-and-transaction.md b/_posts/2024-09-07-mysql-lock-and-transaction.md index c6567d1..d138a23 100644 --- a/_posts/2024-09-07-mysql-lock-and-transaction.md +++ b/_posts/2024-09-07-mysql-lock-and-transaction.md @@ -19,7 +19,7 @@ date: 2024-09-07 23:59:59 +0900 toc: true --- -[K-DEVCON](https://k-devcon.com) 대전 오프라인 스터디에서 Real Mysql 책으로 스터디를 진행해보기로 했다. +[K-DEVCON](https://k-devcon.com) 대전 개발자 스터디에서 Real Mysql 책으로 스터디를 진행해보기로 했다. 발표하면서 준비한 내용을 블로그로도 옮겨보려고 한다. @@ -27,6 +27,8 @@ toc: true 이 글의 내용은 Mysql 8.0 에서 InnoDB 를 기준으로 정리되었다. 이 글은 정리글이기에 생략이 있으며, 책에서는 이전 버전이나 다른 스토리지 엔진에 대해서도 다루기도 하고 더 자세한 내용들을 다루고 있다. 책의 구성이 이미 안다는것을 전제하에 진행된 부분들도 있어 해당 부분에 대해서 보충설명을 넣기도 하였다. +참고로 대전 개발자 스터디 에 관심이 있다면 [구글 폼](http://k-devcon.web.app/daejeon-membership) 을 통해 신청할 수 있다. + --- # 아키텍처 - Real MySQL 스터디 2회차 diff --git a/_posts/2024-09-28-mysql-compression-and-encryption.md b/_posts/2024-09-28-mysql-compression-and-encryption.md index d5d899e..f6ee2ff 100644 --- a/_posts/2024-09-28-mysql-compression-and-encryption.md +++ b/_posts/2024-09-28-mysql-compression-and-encryption.md @@ -19,12 +19,14 @@ date: 2024-09-28 23:59:59 +0900 toc: true --- -[K-DEVCON](https://k-devcon.com) 대전 오프라인 스터디에서 Real Mysql 책으로 스터디를 진행해보기로 했다. +[K-DEVCON](https://k-devcon.com) 대전 개발자 스터디에서 Real Mysql 책으로 스터디를 진행해보기로 했다. 발표하면서 준비한 내용을 블로그로도 옮겨보려고 한다. 이 글의 내용은 Mysql 8.0 에서 InnoDB 를 기준으로 정리되었다. 이 글은 정리글이기에 생략이 있으며, 책에서는 이전 버전이나 다른 스토리지 엔진에 대해서도 다루기도 하고 더 자세한 내용들을 다루고 있다. 책의 구성이 이미 안다는것을 전제하에 진행된 부분들도 있어 해당 부분에 대해서 보충설명을 넣기도 하였다. +참고로 대전 개발자 스터디 에 관심이 있다면 [구글 폼](http://k-devcon.web.app/daejeon-membership) 을 통해 신청할 수 있다. + --- # 압축 diff --git a/_posts/2024-11-03-mysql-full-scan-query-pattern.md b/_posts/2024-11-03-mysql-full-scan-query-pattern.md index 8304a40..1ff79fd 100644 --- a/_posts/2024-11-03-mysql-full-scan-query-pattern.md +++ b/_posts/2024-11-03-mysql-full-scan-query-pattern.md @@ -27,6 +27,8 @@ toc: true 이 글의 내용은 Mysql 8.0 에서 InnoDB 를 기준으로 정리되었다. 이 글은 정리글이기에 생략이 있으며, 책에서는 이전 버전이나 다른 스토리지 엔진에 대해서도 다루기도 하고 더 자세한 내용들을 다루고 있다. 책의 구성이 이미 안다는것을 전제하에 진행된 부분들도 있어 해당 부분에 대해서 보충설명을 넣기도 하였다. +참고로 대전 개발자 스터디 에 관심이 있다면 [구글 폼](http://k-devcon.web.app/daejeon-membership) 을 통해 신청할 수 있다. + --- # MySQL 풀스캔 쿼리 패턴 및 튜닝 diff --git a/_posts/2024-11-06-java-guava-ratelimiter.md b/_posts/2024-11-06-java-guava-ratelimiter.md index 2fa980c..24cb663 100644 --- a/_posts/2024-11-06-java-guava-ratelimiter.md +++ b/_posts/2024-11-06-java-guava-ratelimiter.md @@ -46,13 +46,11 @@ class documentation : [https://guava.dev/releases/snapshot-jre/api/docs/com/goog 아래는 초당 2회 api 를 호출하도록 한 테스트 코드이다. (예제이기 떄문에 그냥 `print` 메소드를 사용하였다.) ```java -public class RateLimiterTest { - RateLimiter rateLimiter = RateLimiter.create(2); +RateLimiter rateLimiter = RateLimiter.create(2); - for (int i = 0; i < Integer.MAX_VALUE; i++) { - rateLimiter.acquire(); - System.out.println(i); - } +for (int i = 0; i < Integer.MAX_VALUE; i++) { + rateLimiter.acquire(); + System.out.println(i); } ``` diff --git a/_posts/2024-11-13-deploy-application-using-k8s.md b/_posts/2024-11-13-deploy-application-using-k8s.md new file mode 100644 index 0000000..8cade8d --- /dev/null +++ b/_posts/2024-11-13-deploy-application-using-k8s.md @@ -0,0 +1,295 @@ +--- +layout: post +title: "[k8s] 쿠버네티스로 어플리케이션 배포하기 (deployment, service, ingress, load balancer)" +categories: [스터디-인프라, 개발] +tags: + [ + k8s, + kubernetes, + jenkins, + docker, + container, + deployment, + service, + private registry, + ingress, + ingress controller, + ingress class, + load balancer, + lb, + metallb, + ] +date: 2024-11-13 18:00:00 +0900 +toc: true +--- + +이 글에서는 k8s (microk8s) 에서 어플리케이션를 배포해본 경험을 정리해본다. + +틈틈이 테스트를 위한 환경을 온프레미스로 구축하고 있다. + +처음으로 k8s에 어플리케이션을 배포하는 사람에게 도움이 되기를 바란다. + +## 목표 + +오늘의 목표는 브라우저에서 `admin.jonghoonpark.com` 이라는 도메인에 접속했을 때 k8s로 배포된 어플리케이션에 접속이 되게 하는 것이다. + +![plan](/assets/images/2024-11-13-deploy-react-project-using-k8s/plan.png) + +## host 파일 수정 + +실제로 도메인을 연결해도 되지만 테스트 목적이기 떄문에 host를 수정하는 방향으로 진행하였다. +admin.jonghoonpark.com 이 10.8.0.4 를 바라보는것 처럼 되도록 세팅하였다. + +ubuntu 에서는 `/etc/hosts` 파일을 수정하였고, mac에서는 [Gas Mask](https://github.com/2ndalpha/gasmask) 라는 프로그램을 사용하여 host 파일을 수정하였다. (오늘 처음 써봤는데 쉽게 사용할 수 있어서 좋았다.) + +``` +10.8.0.4 admin.jonghoonpark.com +``` + +## k8s에서 private registry에 접근하기 위한 설정 + +로컬에서 docker 이미지를 빌드하였고, 잘 동작하는 것을 확인하였다. + +docker 이미지는 private registry 에 푸시하였다. (nexus 사용) + +deployment 파일을 통해 pod에 어떤 docker 이미지를 사용할지 지정하게 된다. 따라서 관련 설정을 먼저 해둔다. + +### private registry 에 접근하기 위한 secret 생성 + +[kubectl create secret docker-registry](https://kubernetes.io/docs/reference/kubectl/generated/kubectl_create/kubectl_create_secret_docker-registry/) + +private registry 에 접속하기 위한 정보를 secret으로 만들어 둔다. (docker-server 에는 포트 정보도 포함해야 한다. e.g. 10.8.0.4:32000) + +```sh +kubectl create secret docker-registry NAME \ + --docker-server=host \ + --docker-username=user \ + --docker-password=password +``` + +secret을 만들때 docker-email 옵션이 필수였던 시절이 있었던것 같다. nexus 에는 계정 정보에 이메일이 따로 없어 생략하였는데 문제는 없었다. (k8s v1.31.2 버전 사용중) + +### insecure registry 일 경우 + +insecure registry 일 경우, docker 쪽에서도 세팅이 필요하지만 microk8s 에서도 세팅이 필요하다. + +microk8s 공식 문서 중 [How to work with a private registry](https://microk8s.io/docs/registry-private) 문서를 참고하여 세팅한다. + +```sh +sudo mkdir -p /var/snap/microk8s/current/args/certs.d/10.8.0.4:32000 +sudo vim /var/snap/microk8s/current/args/certs.d/10.8.0.4:32000/hosts.toml +``` + +```conf +# /var/snap/microk8s/current/args/certs.d/10.8.0.4:32000/hosts.toml +server = "http://10.8.0.4:32000" + +[host."http://10.141.241.175:32000"] +capabilities = ["pull", "resolve"] +``` + +`10.8.0.4:32000` 부분을 자신의 registry 에 맞게 수정해주면 된다. + +만약 insecure 관련 세팅이 제대로 되지 않았다면 `http: server gave HTTP response to HTTPS client` 와 같은 에러가 발생된다. + +## deployment 설정 + +[deployment](https://kubernetes.io/ko/docs/concepts/workloads/controllers/deployment/) 는 파드에 대한 선언적 업데이트를 제공한다. + +deployment 는 다음과 같이 작성하였다. + +```yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: admin-web-deployment +spec: + replicas: 1 + selector: + matchLabels: + app: admin-web + template: + metadata: + labels: + app: admin-web + spec: + containers: + - name: admin-web-container + image: 10.8.0.4:32000/admin-web:latest + ports: + - containerPort: 5173 + resources: + limits: + memory: "2048Mi" + cpu: "500m" + requests: + memory: "1024Mi" + cpu: "500m" + imagePullSecrets: + - name: private-registry-secret +``` + +위에서 생성한 private registry 의 secret을 사용한다. + +vite 기반 어플리케이션을 샘플로 사용하여 5173 포트를 사용하게 되었다. 상황에 맞게 포트와 리소스를 설정해주면 된다. + +## service 설정 + +[service](https://kubernetes.io/ko/docs/concepts/services-networking/service/)는 파드 집합에서 실행중인 애플리케이션을 네트워크 서비스로 노출하는 추상화하는데 사용된다. + +```yaml +apiVersion: v1 +kind: Service +metadata: + name: admin-web-service +spec: + selector: + app: admin-web + ports: + - protocol: TCP + port: 5173 + targetPort: 5173 + type: ClusterIP +``` + +팟에서 5173 포트를 사용하였기 때문에 service 에서는 5173 포트를 사용하였다. +`targetPort` 가 pod의 port이고, `port` 가 서비스에서 노출할 port이다. + +여기까지 따라했다면 아마 포트포워딩을 통해서 pod에 접근을 할 수는 있을 것이다. +이제 ingress 설정을 통해 포트포워딩 없이도 접근 가능한 상태로 만들어보자. + +## ingress 설정 + +[ingress](https://kubernetes.io/ko/docs/concepts/services-networking/ingress/)는 쿠버네티스 API를 통해 정의한 규칙에 기반하여 트래픽을 다른 백엔드에 매핑할 수 있게 하는데 사용된다. + +### ingress controller + +클러스터 내의 인그레스가 작동하려면, **ingress controller** 가 실행되고 있어야 한다. 적어도 하나의 인그레스 컨트롤러를 선택하여 이를 클러스터 내에 설치해야한다. + +#### nginx ingress + +ingress controller 는 다양하게 구현되어 있다. 이 글에서는 **nginx ingress** 를 사용하였다. + +다음 명령어로 설치할 수 있다. + +```sh +kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/cloud/deploy.yaml +``` + +이후 아래와 같이 컨트롤러가 생성된 것을 확인할 수 있다. (아직 EXTERNAL-IP는 pending 상태이다.) + +```sh +$ kubectl get svc -n ingress-nginx +NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE +ingress-nginx-controller LoadBalancer 10.152.183.69 80:31118/TCP,443:30651/TCP +ingress-nginx-controller-admission ClusterIP 10.152.183.179 443/TCP +``` + +### ingress + +```yaml +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: admin-web-ingress + annotations: + nginx.ingress.kubernetes.io/rewrite-target: / +spec: + ingressClassName: nginx + rules: + - host: admin.jonghoonpark.com + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: admin-web-service + port: + number: 5173 +``` + +`admin.jonghoonpark.com` 도메인으로 들어오는 요청을 `admin-web-service` 서비스로 전달하도록 구성하였다. + +### ingress class + +인그레스를 처리하는 방식은 인그레스 컨트롤러에 따라 달라진다. 따라서 어떤 컨트롤러를 사용할 것인지 클래스 이름을 포함해줘야 한다. +여기서는 `ingressClassName: nginx` 를 통해 nginx 를 사용할 것이라고 명시해주었다. + +다음과 같이 IngressClass 도 생성해준다. + +```yaml +apiVersion: networking.k8s.io/v1 +kind: IngressClass +metadata: + name: nginx +spec: + controller: k8s.io/ingress-nginx +``` + +ingress class 를 설정하는 것을 놓치면 아래와 같은 에러를 마주할 수 있다. + +```sh +kubectl logs ingress-nginx-controller-546f9cf9bf-gtwn4 -n ingress-nginx +``` + +``` +"Ignoring ingress because of error while validating ingress class" ingress="default/admin-web-ingress" error="ingress does not contain a valid IngressClass" +``` + +여기까지 설정을 잘 따라왔다고 해도 아직은 `admin.jonghoonpark.com` 으로 어플리케이션에는 접근하지 못한다. (아직 EXTERNAL-IP는 pending 상태이기 때문이다.) 이를 해결하기 위해 load balancer를 추가해줘야한다. + +## load balancer 설정 + +마지막으로 load balancer를 설정해줘야 한다. + +load balancer와 ingress는 서로 보완적인 역할을 수행한다. +load balancer의 개념이 ingress 와 혼동이 되기도 하는데 정리해보자면 다음과 같은 차이를 가지고 있다. + +| 종류 | 특징 | +| ---------- | -------------------------------------- | +| 인그레스 | 애클러스터 내부에서 트래픽을 라우팅 | +| 로드밸런서 | 외부에서 트래픽을 받아 인그레스로 전달 | + +### metallb + +load balancer도 다양하게 구현되어 있다. 이 글에서는 [**metallb**](https://github.com/metallb/metallb) 를 사용하였다. + +다음 명령어로 설치할 수 있다. + +```sh +kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.14.8/config/manifests/metallb-native.yaml +``` + +설치한 후에는 ip address pool을 설정해줘야 한다. 나는 다음과 같이 설정해주었다. + +```yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: dev + namespace: metallb-system +spec: + addresses: + - 10.8.0.4/32 +``` + +address 에는 ingress controller 의 ip를 명시해주면 된다. (여기서는 한 ip 를 지정하였지만, 환경에 맞춰 여러 ip 범위를 지정할 수도 있다.) + +apply 해보면 ingress-nginx-controller 에 EXTERNAL-IP가 연결된 것을 볼 수 있다. + +```sh +$ kubectl get svc -n ingress-nginx +NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE +ingress-nginx-controller LoadBalancer 10.152.183.69 10.8.0.4 80:31118/TCP,443:30651/TCP +ingress-nginx-controller-admission ClusterIP 10.152.183.179 443/TCP +``` + +## 마무리 + +여기까지 설정하였으면 처음 목표였던 `admin.jonghoonpark.com` 으로 애플리케이션에 접근할 수 있다. + +## 기타 + +- 대부분의 내용은 k8s 공식 도큐먼트를 참고하였다. +- ingress 설정 후에도 연결이 되지 않을 경우에는 로그를 확인해보자. 바로 위에서 사용한대로 `kubectl logs` 명령어로 로그를 확인해볼 수 있다. diff --git a/assets/images/2024-11-13-deploy-react-project-using-k8s/plan.png b/assets/images/2024-11-13-deploy-react-project-using-k8s/plan.png new file mode 100644 index 0000000000000000000000000000000000000000..c95cf2c0ec53814a3b6202be733a703dba4402aa GIT binary patch literal 8724 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 PAkopdul`BZ{`vm{x@P-? literal 0 HcmV?d00001