EKS-NodeLess-01-CoreDNS

EKS의 관리영역중 Addon 이나 필수 컴포넌트중에 Node에서 동작해야하는 것들이 있다. 이 경우에 NodeGroup을 운영해야한다. NodeGroup에 여러 파드들이 스케줄링되고 관리형 Pod들은 다른 서비스에 운영되는 NodeGroup과 섞여서 스케줄리되어야 하는데, 이것의 가장큰 문제는 Node의 사망이 기능의 장애로 이어진다는 점이다. 따라서 Node를 전용 Node로 사용하면 좋은데 아주작은 노드를 스케줄링한다고 해도 관리되어야 하는 대상이 됨은 틀림없고, 노드를 정해서 사용해야 하는 문제점들이 생기게된다. 이러한 문제를 해결하기에 EKS에서는 Fargate가 있다. 1Node - 1Pod 라는게 아주 중요한 포인트다. ...

May 6, 2023 · 1 min · 📁 AWS, Kubernetes · 🏷️ EKS, fargeate, coredns

AWS-SQS-터져랏

일단 SQS를 터질때 까지 밀어넣어 보기로 했다. 목표 메시지수는 100만건. 100만건의 메시지를 100초안에 SQS에 넣는게 목표다. TPS 10000 이라는 소리다. 목표를 이루기위해선 첫번째 SQS의 TPS는 3000이다. 초당 3000의 메시지를 넣을수 있다. 먼저 큐를 4개를 만들었다. 목표수치에 가려면 TPS가 10000은 나와야한다. 그렇다면 큐를 병렬로 줄세운다 4개의 큐를 만든다. 이제 넣어봤다. import boto3 import json import uuid from concurrent.futures import ThreadPoolExecutor import random import string sqs = boto3.client('sqs') queue_urls = [ 'linuxer-sqs-1', 'linuxer-sqs-2', 'linuxer-sqs-3', 'linuxer-sqs-4' ] def random_string(length): return ''.join(random.choices(string.ascii_letters + string.digits, k=length)) def create_dummy_data(): return { 'id': str(uuid.uuid4()), 'data': f"host-{random_string(5)}-count", 'padding': random_string(10 * 1024 - 100) # 10KB 크기의 더미 데이터를 생성 } def send_message_batch(queue_url, messages): entries = [] for idx, message in enumerate(messages): entries.append({ 'Id': str(idx), 'MessageBody': json.dumps(message) }) response = sqs.send_message_batch( QueueUrl=queue_url, Entries=entries ) return response def generate_and_send_dummy_data(num_messages=100000, batch_size=10, num_threads=10): with ThreadPoolExecutor(max_workers=num_threads) as executor: for _ in range(num_messages // (batch_size * num_threads * len(queue_urls))): batch_futures = [] for queue_url in queue_urls: messages = [create_dummy_data() for _ in range(batch_size)] future = executor.submit(send_message_batch, queue_url, messages) batch_futures.append(future) for future in batch_futures: future.result() if __name__ == '__main__': generate_and_send_dummy_data() ```bash 대충 이코드는 TPS 100 정도이다. ![](/images/2023/04/image-5.png) 5분 정도 걸려서 10만 건의 메시지를 모두 PUT했다. 분당 20000 TPS 333정도다. 병렬처리했다. ```bash import boto3 import json import uuid from concurrent.futures import ThreadPoolExecutor from multiprocessing import Process import random import string sqs = boto3.client('sqs') queue_urls = [ 'linuxer-sqs-1', 'linuxer-sqs-2', 'linuxer-sqs-3', 'linuxer-sqs-4' ] def random_string(length): return ''.join(random.choices(string.ascii_letters + string.digits, k=length)) def create_dummy_data(): return { 'id': str(uuid.uuid4()), 'data': f"host-{random_string(5)}-count", 'padding': random_string(10 * 1024 - 100) # 10KB 크기의 더미 데이터를 생성 } def send_message_batch(queue_url, messages): entries = [] for idx, message in enumerate(messages): entries.append({ 'Id': str(idx), 'MessageBody': json.dumps(message) }) response = sqs.send_message_batch( QueueUrl=queue_url, Entries=entries ) return response def generate_and_send_dummy_data(queue_url, num_messages=1000000, batch_size=10, num_threads=10): with ThreadPoolExecutor(max_workers=num_threads) as executor: for _ in range(num_messages // (batch_size * num_threads)): batch_futures = [] for _ in range(num_threads): messages = [create_dummy_data() for _ in range(batch_size)] future = executor.submit(send_message_batch, queue_url, messages) batch_futures.append(future) for future in batch_futures: future.result() def start_processes(num_processes): processes = [] for queue_url in queue_urls: for _ in range(num_processes): process = Process(target=generate_and_send_dummy_data, args=(queue_url,)) processes.append(process) process.start() for process in processes: process.join() if __name__ == '__main__': num_processes = 4 start_processes(num_processes) ```bash ```bash 501 17512 16975 0 9:27PM ttys001 0:00.21 /Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.9/Resources/Python.app/Contents/MacOS/Python main.py 501 17513 17512 0 9:27PM ttys001 0:00.05 /Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.9/Resources/Python.app/Contents/MacOS/Python -c from multiprocessing.resource_tracker import main;main(6) 501 17514 17512 0 9:27PM ttys001 0:14.41 /Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.9/Resources/Python.app/Contents/MacOS/Python -c from multiprocessing.spawn import spawn_main; spawn_main(tracker_fd=7, pipe_handle=9) --multiprocessing-fork 501 17515 17512 0 9:27PM ttys001 0:14.50 /Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.9/Resources/Python.app/Contents/MacOS/Python -c from multiprocessing.spawn import spawn_main; spawn_main(tracker_fd=7, pipe_handle=11) --multiprocessing-fork 501 17516 17512 0 9:27PM ttys001 0:14.36 /Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.9/Resources/Python.app/Contents/MacOS/Python -c from multiprocessing.spawn import spawn_main; spawn_main(tracker_fd=7, pipe_handle=14) --multiprocessing-fork 501 17517 17512 0 9:27PM ttys001 0:14.60 /Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.9/Resources/Python.app/Contents/MacOS/Python -c from multiprocessing.spawn import spawn_main; spawn_main(tracker_fd=7, pipe_handle=16) --multiprocessing-fork 501 17518 17512 0 9:27PM ttys001 0:14.55 /Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.9/Resources/Python.app/Contents/MacOS/Python -c from multiprocessing.spawn import spawn_main; spawn_main(tracker_fd=7, pipe_handle=18) --multiprocessing-fork 501 17519 17512 0 9:27PM ttys001 0:14.21 /Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.9/Resources/Python.app/Contents/MacOS/Python -c from multiprocessing.spawn import spawn_main; spawn_main(tracker_fd=7, pipe_handle=20) --multiprocessing-fork 501 17520 17512 0 9:27PM ttys001 0:14.16 /Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.9/Resources/Python.app/Contents/MacOS/Python -c from multiprocessing.spawn import spawn_main; spawn_main(tracker_fd=7, pipe_handle=22) --multiprocessing-fork 501 17521 17512 0 9:27PM ttys001 0:14.11 /Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.9/Resources/Python.app/Contents/MacOS/Python -c from multiprocessing.spawn import spawn_main; spawn_main(tracker_fd=7, pipe_handle=24) --multiprocessing-fork 501 17522 17512 0 9:27PM ttys001 0:14.46 /Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.9/Resources/Python.app/Contents/MacOS/Python -c from multiprocessing.spawn import spawn_main; spawn_main(tracker_fd=7, pipe_handle=27) --multiprocessing-fork 501 17523 17512 0 9:27PM ttys001 0:14.55 /Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.9/Resources/Python.app/Contents/MacOS/Python -c from multiprocessing.spawn import spawn_main; spawn_main(tracker_fd=7, pipe_handle=29) --multiprocessing-fork 501 17524 17512 0 9:27PM ttys001 0:14.24 /Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.9/Resources/Python.app/Contents/MacOS/Python -c from multiprocessing.spawn import spawn_main; spawn_main(tracker_fd=7, pipe_handle=31) --multiprocessing-fork 501 17525 17512 0 9:27PM ttys001 0:14.19 /Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.9/Resources/Python.app/Contents/MacOS/Python -c from multiprocessing.spawn import spawn_main; spawn_main(tracker_fd=7, pipe_handle=33) --multiprocessing-fork 501 17526 17512 0 9:27PM ttys001 0:14.28 /Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.9/Resources/Python.app/Contents/MacOS/Python -c from multiprocessing.spawn import spawn_main; spawn_main(tracker_fd=7, pipe_handle=35) --multiprocessing-fork 501 17527 17512 0 9:27PM ttys001 0:14.18 /Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.9/Resources/Python.app/Contents/MacOS/Python -c from multiprocessing.spawn import spawn_main; spawn_main(tracker_fd=7, pipe_handle=37) --multiprocessing-fork 501 17528 17512 0 9:27PM ttys001 0:14.49 /Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.9/Resources/Python.app/Contents/MacOS/Python -c from multiprocessing.spawn import spawn_main; spawn_main(tracker_fd=7, pipe_handle=39) --multiprocessing-fork 501 17529 17512 0 9:27PM ttys001 0:14.46 /Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.9/Resources/Python.app/Contents/MacOS/Python -c from multiprocessing.spawn import spawn_main; spawn_main(tracker_fd=7, pipe_handle=41) --multiprocessing-fork ```bash 이제 멀티프로세스로 꼽는다!! ![](/images/2023/04/image-6.png) 코드보니 400만개를 넣도록 되어있어서 100만개 넣을시점에 끊었다. ![](/images/2023/04/image-7.png) 10분정도에 100만개의 메시지.. TPS 1600 정도다 아직 더 올릴수 있는 가망성이 보이지만 이건이제 컴퓨팅의 문제다. 이제 병렬처리만으로도 가능함을 알았으니..producer 의 병렬성을 더 올린다. **num_processes = 12** 4배다! 일단 터트려 보자. ```bash ps -ef | grep "multiprocessing.spawn" | wc -l 49 ```bash 49개의 프로세스가 미친듯이 공격을 한다. M1 진짜 좋다. 아...내 노트북으로 낼수있는 TPS는 1600이 한계다. 이제 컨슈밍을 할거다. SQS에 있는 데이터를 꺼내쓰는 속도를 확인할거다. 큐에는 100만개의 데이터가 쌓여있고 이걸 모두 소모하는 속도를 확인하려한다. ```bash import boto3 import time from concurrent.futures import ThreadPoolExecutor, as_completed from multiprocessing import Process sqs = boto3.client('sqs') queue_urls = [ 'linuxer-sqs-1', 'linuxer-sqs-2', 'linuxer-sqs-3', 'linuxer-sqs-4' ] def receive_and_delete_message(queue_url, wait_time=20): while True: response = sqs.receive_message( QueueUrl=queue_url, AttributeNames=['All'], MaxNumberOfMessages=1, WaitTimeSeconds=wait_time ) if 'Messages' in response: message = response['Messages'][0] receipt_handle = message['ReceiptHandle'] sqs.delete_message( QueueUrl=queue_url, ReceiptHandle=receipt_handle ) else: break def process_messages(queue_url, num_threads=10): with ThreadPoolExecutor(max_workers=num_threads) as executor: futures = [executor.submit(receive_and_delete_message, queue_url) for _ in range(num_threads)] for future in as_completed(futures): future.result() def start_processes(num_processes): processes = [] for queue_url in queue_urls: for _ in range(num_processes): process = Process(target=process_messages, args=(queue_url,)) processes.append(process) process.start() for process in processes: process.join() if __name__ == '__main__': num_processes = 100 start_time = time.time() start_processes(num_processes) end_time = time.time() print(f"Elapsed time: {end_time - start_time:.2f} seconds") ```bash 멀티프로세스 100개를 돌렸더니 M1이 뻣었다. 그렇지만 1분에 10만개 정도는 가볍게 뽑아가는걸 확인할수있었다. ![](/images/2023/04/image-8.png) 이 결과만으로 SQS는 튼튼한 큐라는걸 알수 있었다. 그럼 이렇게 하드코어하게 넣었으니 에러레이트를 확인해 봐야했다. ![](/images/2023/04/image-9-1024x870.png) 지연되거나 데드레터큐에 쌓인메시지는 없었다. 모두 정상적으로 소진된것이다. 여기서 결론은 mac book M1 air 로서 낼수 있는 퍼포먼스는 TPS1600이다. 분당 10만건의 메시지를 처리할수 있는 능력이라는것.. 이다음은 컴퓨팅 자원을 마음껏 넣어서 큐를 터트려 보겠다. 밤새 머리속에서 어떻게 하면 좋을까 고민하다가 EKS에서 Job을 이용해 병렬 처리속도를 늘려보기로 했다. 도커로 말고~ CMD로 job을 실행할때 파일을 지정해서 실행하도록 했다. ```bash # Dockerfile FROM python:3.8-slim WORKDIR /app COPY requirements.txt ./ RUN pip install --no-cache-dir -r requirements.txt COPY send.py receive.py ./ CMD ["python", "receive.py"] ```bash ```bash apiVersion: batch/v1 kind: Job metadata: name: sqs-test spec: parallelism: 20 template: spec: containers: - name: sqs-test image: sqs_test:latest command: ["python3", "send.py"] // ["python", "receive.py"] 로 변경할수 있다. resources: limits: cpu: "2" memory: "2Gi" requests: cpu: "1500m" memory: "1Gi" restartPolicy: Never backoffLimit: 4 ```bash 컨테이너 말고 parallelism 으로 20의 pod를 예약했다. ![](/images/2023/04/image-10.png) Send 는 분당 26만개 TPS 대략 4300 ![](/images/2023/04/image-11.png) receive 는 32만개 대략 TPS 5000 정도이다. 5분에 100만개를 처리할수 있는 능력이라 보이고 이 플로우의 장점은 job에서 모든 데이터를 다꺼내쓰면 Completed로 컨테이너가 완료되므로 시간에 따른 큐에 대한 스케줄링이 가능하다는 뜻이다. job을 스케줄링할때 큐에 쌓인 지연시간+큐에쌓인 갯수를 모니터링하고 job을 이용해 큐를 비우는 방식의 아키텍처를 설계할수 있다는 이야기다. ```bash k get pod NAME READY STATUS RESTARTS AGE sqs-test-send-2s6h4 0/1 Completed 0 4m23s sqs-test-send-5276z 0/1 Completed 0 4m23s sqs-test-send-72ndr 0/1 Completed 0 4m22s sqs-test-send-c24kn 0/1 Completed 0 4m22s sqs-test-send-ccz5r 0/1 Completed 0 4m23s sqs-test-send-fjfnk 0/1 Completed 0 4m23s sqs-test-send-h2jhv 0/1 Completed 0 4m22s sqs-test-send-k7b8q 0/1 Completed 0 4m22s sqs-test-send-ljbv5 0/1 Completed 0 4m23s sqs-test-send-mjvh9 0/1 Completed 0 4m23s sqs-test-send-n8wh4 0/1 Completed 0 4m23s sqs-test-send-ngskk 0/1 Completed 0 4m22s sqs-test-send-qj9ks 0/1 Completed 0 4m22s sqs-test-send-r87hf 0/1 Completed 0 4m22s sqs-test-send-rr58h 0/1 Completed 0 4m23s sqs-test-send-sf2bd 0/1 Completed 0 4m23s sqs-test-send-svn8d 0/1 Completed 0 4m22s sqs-test-send-tqfg4 0/1 Completed 0 4m23s sqs-test-send-tv68j 0/1 Completed 0 4m22s sqs-test-send-w99hx 0/1 Completed 0 4m23s ```bash 결과가 놀라운데 4분23초 만에 pod의 스케줄링+job(120만건의 메시징컨슘)이 모두 완료된건이다. 이아키텍처에는 카펜터가 사용되었는데, 카펜터의 노드는 0에서 시작하여 새로 노드를 프로비저닝해서 깔끔하게 모두 완료된것이다. 스케줄링이 놀랍다. 재미있는 테스트였다. 이다음은 KaFka를 테스트 하겠다.

April 27, 2023 · 6 min · 📁 AWS · 🏷️ SQS, python, 터저라시냅스

T101-AWS-To-SLACK-Noti - EventBridge

이제야 블로그가 손에 잡혀서 오랜만에 글을 쓰기위해 책상앞에 앉았다. 이게다 내 게으름 때문이다. 맨날 이 뻔한 핑계를 치면서 한번 웃고야 말았다. 이번에 쓸 블로깅은 T101에서 한번 발표한 적인 있는 내용이다. 이 포스팅에선 EventBridge와 CloudTrail을 집중적으로 다룬다. https://nyyang.tistory.com/126 이블로그를 보고 작업을 시작했다. 먼저 시작하기전에 EventBridge Bus 규칙에서 Trail에서 패턴을 감지하기위해선 이벤트버스는 무조건 Default여야한다. 다른 버스에 만들면 버스 지나간 다음 손 흔들어야 한다. 패턴을 감지할수 없다는 이야기다. 골자는 이렇다. CloudTrail 에서 발생하는 이벤트를 EventBridge 는 특정 패턴을 감지해서 이벤트를 발생시킬수 있다. ...

December 17, 2022 · 4 min · 📁 AWS

T101-Study-4Week

가시다님과 스터디를 한지도 5번째 이번엔 테라폼이다. 오늘 블로그를 쓰게된건 중간과제를 설명하기 위해서다. 바로 본론으로 들어간다. 내 GIT 이다 https://github.com/Cloud-Linuxer/T101/tree/main/4week variable "availability_zone" { description = "Seoul region availability zone" type = list default = ["ap-northeast-2a", "ap-northeast-2b", "ap-northeast-2c", "ap-northeast-2d"] } variable "subnet_numbers" { type = list default = [10, 20, 30, 40] } variable "az_count" { type = list default = ["A", "B", "C", "D"] } ```bash 나의 Variables는 이런식으로 구성되어있다. 모든 타입을 List로 선언하여 사용한다. 5주차에 할 테라폼 의 반복문을 사용하기 위한 형태다. 가장 중요한 부분은 subnet_numbers 부분이다. 10, 20, 30, 40 이 핵심이다. ```bash resource "aws_subnet" "pub-common" { count = "${length(var.availability_zone)}" vpc_id = "${aws_vpc.default.id}" cidr_block = [ for num in var.subnet_numbers: cidrsubnet(aws_vpc.default.cidr_block, 8, num) ][count.index] availability_zone = "${element(var.availability_zone, count.index)}" tags = { Name = "Linuxer-Dev-Pub-Common-${element(var.az_count, count.index)}" } } ```bash 이 코드만 봐서는 이게 무엇을 뜻하는지 한눈에 보기 어렵다. 그럼 하나씩 설명하겠다. 하시코프에서는 cidrsubnet 이라는 Function 을 지원한다. 이 함수를 통해서 나는 /16비트의 서브넷을 24비트로 자를거다. 간단히 보여주자면 이렇다 ```bash terraform console > cidrsubnet("10.0.0.0/16",8,10) "10.0.10.0/24" > cidrsubnet("10.0.0.0/16",8,20) "10.0.20.0/24" > cidrsubnet("10.0.0.0/16",8,30) "10.0.30.0/24" > cidrsubnet("10.0.0.0/16",8,40) "10.0.40.0/24" ```bash for로 list 에 담긴 subnet_numbers를 가져다가 CIDR 을 반환한다. 위처럼 24비트의 4개 서브넷이다. 위와같이 24비트로 나뉜 4개의 서브넷을 테라폼은 생성한다. 위의 리소스선언 한줄로 Subnet 4개를 생성하는 것이다. 서울 리전의 4개 AZ를 모두 사용하고, A zone은 10대역대 B Zone은 20대역대 C Zone은 30대역 D Zone은 40 대역인것이다. 이렇게 사용하면 장점이 있다. 한개의 존이 문제가 생긴것을 파악하기 쉽고, 아이피 대역대 만으로 서비스의 역할을 파악할수 있는 장점이 있는 것이다. 처음엔 리스트로 서브넷 선언도 모두 입력해서 하나의 리소스 선언으로 모든 서브넷을 생성하려했지만 그렇게 사용할 경우 리스트가 변경되면 모든 서브넷이 영향을 받는 이슈가 있어서 각 서브넷별 리소스 선언을 하는 방향으로 수정했다.

November 12, 2022 · 2 min · 📁 AWS

AWS-FinOps-S3-incomplete-multipart-uploads-MPU

S3는 청크 단위로 파일을 잘라서 업로드 할수있는 기능을 제공한다. 이 기능의 정식명칭은 multipart upload 이다. https://docs.aws.amazon.com/AmazonS3/latest/userguide/mpuoverview.html MPU라고 줄여서 부른다. MPU는 업로드 속도를 빠르게 해줄수있는 아주 좋은 기능이지만, 업로드에 실패할 경우 완성되지 않은 청크단위의 파일들이 S3스토리지에 저장되게 된다. 업로드가 정상적으로 이루어진 경우 청크단위로 나뉜 파일을 하나의 파일로 합쳐서 객체로 보이게 되지만, 그렇지 않은 파일은 우리의 눈에 보이지 않지만 S3의 스토리지에 비용만 발생시키며, 하등 쓸모없는 상태로 저장만 되어있는다. 이런 경우를 “incomplete multipart uploads” 라 부른다. ...

August 13, 2022 · 1 min · 📁 AWS, FinOps · 🏷️ s3, MPU, incomplete multipart uploads

AWS-IAM-Identity-Center

가시다 님과 함께하는 CASS 스터디를 시작했다. 첫시간은 OU / IAM과 함께하는 즐거운 시간. MSP에서 OU는 열심히 익힌터라 좀 자신이 있었다. 그래서 나는 IAM Center를 써봤다. 검증할것은 이것이다. 지금까지는 각 계정에 역할을 생성하고, STS를 통해서 계정에 접근했다면 IAM Center에선 통합계정을 생성하여 OU에 연결된 루트계정들에 접근할수 있도록한다. 먼저 OU에 계정을 연결한다. 3개의 계정이 연결된것을 확인할수있다. linxuer 계정이 Root OU를 관리한다. linuxer 계정에서 IAM Identity Center서비스 로 이동한다. 그리고 사용자를 생성한다. ...

August 13, 2022 · 2 min · 📁 AWS

AWS FinOps - Intro

이번엔 FinOps에 대한 이야기를 할거다. 먼저 본론으로 들어가기 전에 FinOps에 대한 정의부터 이야기할까 한다. 우리가 흔히 알고있는 DevOps는 Development 과 operations 의 합성어 이다. FinOps는 이 DevOps 에 Finance를 더한것이다. ( Finance + Development + Operations ) IT infra 상에서 발생하는 비용을 제어하고 투자하는 방식을 말하는것이다. ‘투자’ 라고 말하면 의아 할수도 있는데 클라우드 상의 자원은 무한하지만 사용자에게 할당된 비용은 유한하다. 그렇기에 제한된 비용내에서 적절한곳에 맞는 리소스를 투입하는것이 FinOps 에서 투자인것이다. ...

August 7, 2022 · 1 min · 📁 AWS, FinOps

DOIK-Study

가시다님과 함께하는 스터디는 항상 즐겁다. 이번 스터디엔 라이브로 못해서..일단 바닐라쿠버 배포하고 시작했다. Headless 서비스는 ClusterIP가 None으로 설정하며 kubeproxy를 통하지않고 pod의 endpoint가 svc에 연결된다. 나는 먼저 NFS 서버를 Headless 로 배포하기로 했다. kind: PersistentVolumeClaim apiVersion: v1 metadata: name: nfs-server-pvc spec: accessModes: - ReadWriteOnce resources: requests: storage: 10Gi --- kind: Service apiVersion: v1 metadata: name: nfs-service spec: type: ClusterIP clusterIP: None selector: role: nfs ports: # Open the ports required by the NFS server # Port 2049 for TCP - name: tcp-2049 port: 2049 protocol: TCP # Port 111 for UDP - name: udp-111 port: 111 protocol: UDP # Port 20048 for TCP - name: tcp-20048 port: 20048 protocol: TCP --- apiVersion: v1 kind: ReplicationController metadata: name: nfs-server spec: replicas: 1 selector: role: nfs-server template: metadata: labels: role: nfs-server spec: containers: - name: nfs-server image: gcr.io/google_containers/volume-nfs:0.8 ports: - name: nfs containerPort: 2049 - name: mountd containerPort: 20048 - name: rpcbind containerPort: 111 securityContext: privileged: true volumeMounts: - mountPath: /exports name: nfs-export volumes: - name: nfs-export-fast persistentVolumeClaim: claimName: nfs-server-pvc-fast ```bash ? yaml을 deploy 하면 다음과같다. 이제 프로비저너 셋팅이 좀 필요하다. 가시다님께서는 친절하게 프로비저너 셋팅도 다해주셨지만 나는 내가만든 NFS 서버를 사용할거기 때문에 프로비저너를 다시 배포할거다. ```bash #지우고 helm delete -n kube-system nfs-provisioner #다시 설치하고 helm install nfs-provisioner -n kube-system nfs-subdir-external-provisioner/nfs-subdir-external-provisioner --set nfs.server=nfs-service.default.svc.cluster.local --set nfs.path=/exports NAME: nfs-provisioner LAST DEPLOYED: Thu May 26 16:10:31 2022 NAMESPACE: kube-system STATUS: deployed REVISION: 1 TEST SUITE: None ```bash ? 응 잘됬다. ```bash (? |DOIK-Lab:default) root@k8s-m:~# k get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.200.1.1 <none> 443/TCP 4h30m nfs-service ClusterIP None <none> 2049/TCP,111/UDP 6m29s (? |DOIK-Lab:default) root@k8s-m:~# k get ep NAME ENDPOINTS AGE kubernetes 192.168.10.10:6443 4h30m nfs-service 172.16.158.2:2049,172.16.158.2:111 6m48s (? |DOIK-Lab:default) root@k8s-m:~# k get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nfs-server-pod 1/1 Running 0 7m1s 172.16.158.2 k8s-w1 <none> <none> ```bash ? 정상적으로 NFS서버가 잘 배포된것을 확인할수 있다. ```bash apiVersion: v1 kind: PersistentVolume metadata: name: mysql-nfs-pv labels: type: mysql-nfs-pv spec: storageClassName: nfs-client capacity: storage: 4Gi accessModes: - ReadWriteOnce # ReadWriteOnce RWO (1:1 마운트, 읽기 쓰기) nfs: server: 172.16.184.9 # NFS-Server 의 IP path: /1 # NFS 저장소 --- apiVersion: v1 kind: PersistentVolume metadata: name: wp-nfs-pv labels: type: wp-nfs-pv spec: storageClassName: nfs-client capacity: storage: 4Gi accessModes: - ReadWriteOnce nfs: server: 172.16.184.9 # NFS-Server 의 IP path: /2 # NFS 저장소 ```bash ? nfs-service.svc.cluster.local domain을 이용하려 하였으나, PV 에서 domain으로 설정시 nfs-provisioner 정상적으로 마운트 되지 않았다. **headless NFS를 하려고 한것이나, 실패하였다. 지원하지 않는다.(결론)** ![](/images/2022/05/image-32-1024x64.png) 다음과 같은 증상이었다. IP로 프로비저너 설치후엔 잘되었다. ```bash --- apiVersion: v1 kind: PersistentVolumeClaim metadata: labels: app: wordpress name: mysql-pv-claim spec: storageClassName: nfs-client accessModes: - ReadWriteOnce resources: requests: storage: 4Gi selector: matchLabels: type: "mysql-nfs-pv" --- apiVersion: v1 kind: PersistentVolumeClaim metadata: labels: app: wordpress name: wp-pv-claim spec: storageClassName: nfs-client accessModes: - ReadWriteOnce resources: requests: storage: 4Gi selector: matchLabels: type: "wp-nfs-pv" ```bash ? selector를 이용하여 PV를 사용하도록 설정해 주었다 ```bash Every 2.0s: kubectl get svc,pods,pv,pvc -o wide k8s-m: Thu May 26 18:10:41 2022 NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR service/kubernetes ClusterIP 10.200.1.1 <none> 443/TCP 7h56m <none> service/nfs-service ClusterIP None <none> 2049/TCP,111/UDP,20048/TCP 71m role=nfs service/wordpress NodePort 10.200.1.33 <none> 80:30387/TCP 3m25s app=wordpress,tier=frontend service/wordpress-mysql ClusterIP None <none> 3306/TCP 3m25s app=wordpress,tier=mysql NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES pod/nfs-server-rxvf7 1/1 Running 0 71m 172.16.184.9 k8s-w2 <none> <none> pod/wordpress-859f989bbb-msppd 1/1 Running 0 3m25s 172.16.158.21 k8s-w1 <none> <none> pod/wordpress-mysql-66fb7cfb68-z9vj5 1/1 Running 0 3m25s 172.16.158.20 k8s-w1 <none> <none> NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE VOLUMEMODE persistentvolume/mysql-nfs-pv 4Gi RWO Retain Bound default/mysql-pv-claim nfs-client 3m32s Filesystem persistentvolume/pvc-adc24c97-ca67-4700-b3c5-2fc51c4cce01 10Gi RWO Delete Bound default/nfs-server-pvc-fast local-path 71m Filesystem persistentvolume/wp-nfs-pv 4Gi RWO Retain Bound default/wp-pv-claim nfs-client 3m32s Filesystem NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE VOLUMEMODE persistentvolumeclaim/mysql-pv-claim Bound mysql-nfs-pv 4Gi RWO nfs-client 3m25s Filesystem persistentvolumeclaim/nfs-server-pvc-fast Bound pvc-adc24c97-ca67-4700-b3c5-2fc51c4cce01 10Gi RWO local-path 71m Filesystem persistentvolumeclaim/wp-pv-claim Bound wp-nfs-pv 4Gi RWO nfs-client 3m25s Filesystem ```bash ? 서비스가 잘 작동하는것을 확인하였다. ```bash (? |DOIK-Lab:default) root@k8s-m:~/yaml/yaml# k exec nfs-server-rxvf7 -it -- /bin/bash [root@nfs-server-rxvf7 /]# cd /exports/ [root@nfs-server-rxvf7 exports]# ll total 32 drwxr-xr-x 5 systemd-bus-proxy root 4096 May 26 09:07 1 drwxr-xr-x 5 33 33 4096 May 26 09:07 2 -rw-r--r-- 1 root root 16 May 26 07:59 index.html [root@nfs-server-rxvf7 exports]# cd 1 [root@nfs-server-rxvf7 1]# ll total 110608 -rw-rw---- 1 systemd-bus-proxy input 56 May 26 09:07 auto.cnf -rw-rw---- 1 systemd-bus-proxy input 50331648 May 26 09:07 ib_logfile0 -rw-rw---- 1 systemd-bus-proxy input 50331648 May 26 09:07 ib_logfile1 -rw-rw---- 1 systemd-bus-proxy input 12582912 May 26 09:07 ibdata1 drwx------ 2 systemd-bus-proxy input 4096 May 26 09:07 mysql drwx------ 2 systemd-bus-proxy input 4096 May 26 09:07 performance_schema drwx------ 2 systemd-bus-proxy input 4096 May 26 09:07 wordpress [root@nfs-server-rxvf7 1]# cd .. [root@nfs-server-rxvf7 exports]# cd 2 [root@nfs-server-rxvf7 2]# ll total 192 -rw-r--r-- 1 33 33 418 Sep 25 2013 index.php -rw-r--r-- 1 33 33 19935 Jan 2 2017 license.txt -rw-r--r-- 1 33 33 7413 Dec 12 2016 readme.html -rw-r--r-- 1 33 33 5447 Sep 27 2016 wp-activate.php drwxr-xr-x 9 33 33 4096 Oct 31 2017 wp-admin -rw-r--r-- 1 33 33 364 Dec 19 2015 wp-blog-header.php -rw-r--r-- 1 33 33 1627 Aug 29 2016 wp-comments-post.php -rw-r--r-- 1 33 33 2764 May 26 09:07 wp-config-sample.php -rw-r--r-- 1 33 33 3154 May 26 09:07 wp-config.php drwxr-xr-x 4 33 33 4096 Oct 31 2017 wp-content -rw-r--r-- 1 33 33 3286 May 24 2015 wp-cron.php drwxr-xr-x 18 33 33 12288 Oct 31 2017 wp-includes -rw-r--r-- 1 33 33 2422 Nov 21 2016 wp-links-opml.php -rw-r--r-- 1 33 33 3301 Oct 25 2016 wp-load.php -rw-r--r-- 1 33 33 34327 May 12 2017 wp-login.php -rw-r--r-- 1 33 33 8048 Jan 11 2017 wp-mail.php -rw-r--r-- 1 33 33 16200 Apr 6 2017 wp-settings.php -rw-r--r-- 1 33 33 29924 Jan 24 2017 wp-signup.php -rw-r--r-- 1 33 33 4513 Oct 14 2016 wp-trackback.php -rw-r--r-- 1 33 33 3065 Aug 31 2016 xmlrpc.php ```bash ? 목적이었던 NFS도 정상적으로 작동한다. ```bash (? |DOIK-Lab:default) root@k8s-m:~/yaml# k scale deployment wordpress --replicas=3 (? |DOIK-Lab:default) root@k8s-m:~/yaml# k get pod NAME READY STATUS RESTARTS AGE nfs-server-rxvf7 1/1 Running 0 77m wordpress-859f989bbb-8r5zh 1/1 Running 0 47s wordpress-859f989bbb-msppd 1/1 Running 0 8m38s wordpress-859f989bbb-xhbs9 1/1 Running 0 47s wordpress-mysql-66fb7cfb68-z9vj5 1/1 Running 0 8m38s (? |DOIK-Lab:default) root@k8s-m:~/yaml# k get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE mysql-nfs-pv 4Gi RWO Retain Bound default/mysql-pv-claim nfs-client 9m6s pvc-adc24c97-ca67-4700-b3c5-2fc51c4cce01 10Gi RWO Delete Bound default/nfs-server-pvc-fast local-path 77m wp-nfs-pv 4Gi RWO Retain Bound default/wp-pv-claim nfs-client 9m6s (? |DOIK-Lab:default) root@k8s-m:~/yaml# k get pvc NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE mysql-pv-claim Bound mysql-nfs-pv 4Gi RWO nfs-client 9m2s nfs-server-pvc-fast Bound pvc-adc24c97-ca67-4700-b3c5-2fc51c4cce01 10Gi RWO local-path 77m wp-pv-claim Bound wp-nfs-pv 4Gi RWO nfs-client 9m2s ```bash ? 볼륨도 잘공유하여 프로비저닝 된것을 확인할수 있다. ㅜㅜ

May 26, 2022 · 6 min · 📁 AWS, Linux, Kubernetes

클라우드를 시작하는 사람을 위한 안내서

시작하는 사람을 위한 안내서를 작성하고 싶었는데, 좀 늦었다. 매번 하는 말이지만 내 게으름 때문이다. 꼭 누군가에게 도움이 되는 글을 작성하고 싶었는데 그게 바로 오늘인 듯 하다. 클라우드를 하려면 먼저 계정을 생성하여야 한다. 계정을 생성 하였는가? 축하한다. 드디어 클라우드에 입문한 셈이다. 클라우드는 보통 웹 콘솔로 처음 접하게 된다. CSP 에서 제공하는 웹사이트에 가입을 했다면 뭘 해야 할지 고민이 될 것이다. ...

May 15, 2022 · 4 min · 📁 AWS

AWS Certified Data Analytics - Specialty - DAS-C01 - Review

Data Analytics 까지 시험을 봤습니다. 이 사태의 원인은 세웅님이었습니다. 치명적인 속도로 AWS 자격증을 클리어하는 것이 제가 나태한것 같이 느껴졌습니다. 그래서 MLS를 끝내고 DAS를 바로 시작했습니다. DAS는 DBS-DAS-MLS 순으로 보면 좋은시험 같았습니다. DAS는 주로 ETL 과 Analytics에 관련한 문제가 나옵니다. https://jayendrapatil.com/aws-certified-data-analytics-specialty-das-c01-exam-learning-path/ 제 블로그를 봐온 분들이라면 다들 아시겠지만 저는 jayendra 님의 블로그로 먼저 시험을 준비합니다. 도메인 분리도 잘되어있고, 요약정리가 정말 깔끔하기 때문입니다. 요약정리를 다 읽고 AWS에서 주로 사용할 서비스에 대한 이해가 필요합니다. kinesis stream와 firehose 의 차이를 알면 정말 편해집니다. ...

January 3, 2022 · 2 min · 📁 AWS, Certification · 🏷️ DAS, data, data analytics