서버 유지보수가 끝없이 이어지던 시절을 기억하시나요? 늦은 밤까지 크래시 문제를 해결하고 트래픽이 폭주하는 동안 아무 일도 일어나지 않기를 바라며 밤을 지새우셨나요? 우리 모두 경험해 보셨을 겁니다. 인프라 불안정성과의 끊임없는 싸움은 보다 확장 가능하고 탄력적인 솔루션을 찾는 원동력이 되었습니다.
이 탐구는 애플리케이션 관리 및 배포를 간소화할 수 있는 컨테이너 오케스트레이션 플랫폼인 Kubernetes의 세계를 탐구하는 재미있는 프로젝트로 이어졌습니다. 초기 경험은 나름의 어려움을 가져왔지만, 얻은 소중한 교훈은 AWS EKS(Amazon Elastic Kubernetes Service) 사용으로 보다 원활하게 전환할 수 있는 기반을 마련했습니다.
이 블로그 게시물에서는 일반적인 문제를 극복하고 멀티클라우드 전략의 이점을 극대화하는 데 중점을 두고 Kubernetes를 사용한 저희의 모험에 대해 설명합니다.
클라우드에 구애받지 않는 쿠버네티스: 장점과 과제
Kubernetes로 전환하기 시작하면서 클라우드에 구애받지 않는 환경을 만드는 데 있어 여러 클라우드 제공업체에서 일관성과 기능을 유지해야 하는 중요한 과제에 직면했습니다.
저희는 여러 도구를 면밀히 검토한 결과 K3s.io의 품질이 가장 우수하다고 판단했습니다:
- 가벼움: K3s는 리소스 요구 사항이 최소화되고 지속적으로 업데이트되므로 다양한 클라우드 환경에 적합합니다.
- 간단합니다: K3s는 본격적인 Kubernetes 설정에 비해 간단하면서도 안전한 설치 프로세스를 제공합니다.
- 오픈 소스: K3의 오픈 소스 특성으로 인해 특정 클라우드 제공업체의 툴에 종속되지 않습니다. 이는 또한 개방성과 커뮤니티 주도의 발전을 위한 Facebook의 노력과도 일치합니다.
K3s 설치 방법
주요 인프라의 모습은 다음과 같습니다:
K3sCluster 설정
먼저 기본 서버에 K3를 설치하고 클러스터 모드로 시작합니다. 클러스터 모드에서 K3를 시작하면 토큰이 자동으로 생성되므로 이 단계는 매우 중요합니다. 이 토큰은 클러스터에 참여할 추가 노드를 연결하는 데 필수적입니다.
또는 이 토큰을 미리 생성하여 클러스터 초기화 명령에 통합할 수도 있습니다. (아래 코드 스니펫에서 K3S_TOKEN을 참조하세요).
K3의 노드는 초기화 스크립트의 구성에 따라 서버 또는 에이전트로 클러스터에 참여할 수 있습니다.
클러스터 모드에서 K3s 서버를 시작하는 방법
K3s는 서버를 초기화할 수 있는 간단한 단일 단계 설치 스크립트를 제공하며, 특정 요구 사항에 맞는 추가 기능을 포함할 수 있는 옵션도 제공합니다.
다음은 기본 서버 초기화를 위한 기본 스크립트입니다.
curl -sfL https://get.K3s.io | \
INSTALL_K3S_EXEC="--tls-san ${K3s_server_nlb_dns}" \
INSTALL_K3S_VERSION=${K3s_server_version} \
K3S_TOKEN=${K3s_server_token_secret}\
sh -s - server --cluster-init \
--kube-apiserver-arg encryption-provider-config=/etc/rancher/K3s/encryption_config.yaml \
--kubelet-arg="provider-id=aws:///$instanceAz/$instanceId" \
--kubelet-arg="cloud-provider=external" \
--node-taint node-role.
--node-taint node-role.kubernetes.io/control-plane:NoSchedule \
--node-label "topology.kubernetes.io/region=${region}" \
--node-label "topology.kubernetes.io/zone=${instanceAz}" \
--write-kubeconfig-mode 644
위의 코드 조각에서 볼 수 있듯이, K3 클러스터 초기화 중에 마스터 노드라는 점을 강조하기 위해 테인트를 추가했습니다. 이는 컨트롤 플레인 노드에 대해 node-role.kubernetes.io/master:NoSchedule 및 node-role.kubernetes.io/control-plane:NoSchedule 틴트를 사용하여 달성되었습니다.
에이전트 모드에서 K3s 서버를 시작하는 방법
다음 명령은 에이전트/워커 모드에서 K3s 노드를 초기화합니다:
curl -sfL https://get.K3s.io | \
INSTALL_K3S_VERSION=${K3s_agent_version} \
INSTALL_K3S_EXEC="agent" \
K3S_TOKEN=$(K3s_server_token_secret)\
sh -s - agent --server https://${K3s_server_nlb_dns}:6443 \
--kubelet-arg="provider-id=aws:///$instanceAz/$instanceId" \
--node-label "topology.kubernetes.io/region=${region}" \
--node-label "topology.kubernetes.io/zone=${instanceAz}" \
--log /var/log/agent.log
K3 용어에서 '서버'는 마스터 노드를 의미하고 '에이전트'는 워커 노드를 의미합니다.
노드와 상담원이 가입한 후 결과 출력은 다음과 같이 표시됩니다.
설계된 아키텍처에 따르면 고가용성(HA)을 위한 서버 노드 3개와 자동 확장이 가능한 에이전트 노드 2개가 있습니다.
효율적인 K3s 클러스터 운영을 위한 툴킷
디지털 시스템의 구조를 감독하기 위해 사용하는 다른 도구에는 어떤 것이 있나요?
- 액세스 관리: 랜처는 누가 시스템에 액세스하고 어떻게 식별되는지를 관리하는 데 핵심적인 역할을 합니다. 이 도구를 사용하면 권한을 더 쉽게 제어할 수 있습니다. 랜처는 다양한 로그인 방법을 지원하며, 이러한 방법을 연결하기 위해 OKTA를 사용합니다.
- 모니터링 및 로깅: 당사는 Grafana, VictoriaMetrics, Promtail을 사용하여 시스템의 상태를 주시하고 활동과 이벤트를 기록합니다.
- 스토리지 관리: 롱혼은 다양한 상황에서 가용성과 일관성을 유지해야 하는 데이터 스토리지를 관리할 수 있도록 도와줍니다.
- 비밀 관리: 해시코프 볼트는 비밀번호와 키와 같은 민감한 정보를 안전하게 보관하는 곳입니다.
- 보안 정책 시행: OPA 게이트키퍼는 시스템의 보안을 유지하기 위해 규칙을 확인하고 시행합니다.
마지막으로, 코드형 인프라(IaC)를 사용하여 이러한 도구와 환경을 설정하고 관리합니다. 특히 이러한 목적으로 AWS CloudFormation을 사용합니다.
IaC: CloudFormation 이야기
AWS 클라우드포메이션 스택
CloudFormation을 시작하기 전에 저희는 화이트보드에 업무 프로세스를 신중하게 매핑하고 배포 전략을 세웠습니다.
중첩된 스택 세트를 사용하여 CloudFormation 스택을 사용하여 설정을 격리했습니다. 이 접근 방식을 통해 체계적이고 모듈화된 인프라 배포가 가능했습니다. 그런 다음 다음 스택 세트를 순차적으로 생성하고 설정했습니다:
- root_stack: 다른 모든 스택을 연결하는 중앙 허브 역할을 합니다. 여기에는 암시적 종속성과 명시적 종속성이 모두 포함됩니다. 이 구조 내에서 아래의 주요 구성 요소를 정의합니다.
- 보안 그룹 스택: 필요한 모든 보안 그룹을 사전 프로비저닝합니다. 기본 작업을 위한 기본 방화벽 규칙을 설정하기 위해 K3 문서를 참조했습니다.
- 서버 스택 초기화: 서버 노드 설정을 초기화합니다.
- 서버노드스택: 서버 노드의 프로비저닝을 관리합니다.
- 에이전트 노드 스택: 에이전트 노드 설정을 처리합니다.
배포 스크립트 코드 베이스는 다음과 같습니다.
템플릿 엔진으로 재사용성 향상
CloudFormation 스크립트를 재사용하고 더 효율적으로 만들기 위해 템플릿 엔진을 사용하여 YAML 템플릿을 생성했습니다.
우리가 선택한 템플릿 엔진은 Jinja입니다. 이 파일은 VPC, 서브넷, 자동 확장 최소 및 최대 제약 조건, EBS 볼륨 크기, 지역, 계정 ID와 같은 주요 클러스터 세부 정보를 설명하는 `parameter.yaml` 파일을 입력으로 받습니다. 요구 사항에 따라 이 목록을 확장할 수 있습니다.
이 접근 방식은 코드에 역동성을 더합니다. 각 환경마다 매개변수-dev.yaml 및 매개변수-prod.yaml과 같은 별도의 parameter.yaml 파일을 생성합니다. 이를 통해 배포 프로세스를 간소화하고 새로운 환경을 신속하게 만들 수 있습니다.
파이썬-진자 래퍼
저희는 진자를 사용하여 CloudFormation 스크립트를 렌더링하는 Python 래퍼를 개발했습니다. 이 래퍼를 사용하면 `parameter.yaml` 파일에 지정된 값에 따라 사용자 정의 템플릿을 생성할 수 있습니다. 이 방법을 사용하면 맞춤형 인프라 구성을 간편하게 만들 수 있습니다.
AWS Cfn-lint를 사용하여 렌더링된 리소스 확인
렌더링된 리소스의 무결성을 확인하기 위해 CloudFormation 스크립트를 테스트하고 검증하기 위해 cfn-lint를 사용했습니다.
이 도구는 구문 검사 및 오류 감지 프로세스를 자동화합니다. 메이크파일과 원활하게 통합되어 `test.sh` 스크립트를 활성화합니다.
"make" 명령을 사용하여 K3 클러스터 부트스트랩 및 배포하기
여러 단계를 bash 스크립트로 자동화한 후 프로세스를 다음과 같은 핵심 스크립트로 간소화했습니다:
- deploy.sh: AWS CLI를 사용하여 스택을 CloudFormation에 배포합니다.
- test.sh: 스택에서 테스트를 실행합니다.
- destroy.sh: CloudFormation에서 스택을 제거합니다.
- render.sh: parameter.yaml` 입력에서 YAML 파일을 생성합니다.
사용성을 단순화하고 향상시키기 위해 GNU Make를 사용하여 이러한 명령을 통합했습니다. 이를 통해 'make 배포', 'make 파괴', 'make 테스트', 'make 렌더링'과 같은 간단한 명령으로 작업을 실행할 수 있어 CloudFormation 스택을 관리하기 위한 보다 직관적인 인터페이스를 제공합니다.
프로비저닝된 CloudFormation 스택은 최종적으로 다음과 같은 모양이 됩니다:
이것은 우리 여정의 마지막 장이 아닙니다. 이 글에서는 많은 도전에 직면하고 귀중한 교훈을 얻었던 Kubernetes에 대한 실제 경험을 공유했습니다. Kubernetes 구성 요소를 관리, 백업 및 복구하는 방법에 대한 인사이트를 얻었습니다. 이를 통해 AWS EKS를 사용하여 Kubernetes를 관리하는 다음 단계를 준비할 수 있었습니다.
이 공간에서 Kubernetes 모험의 다음 단계를 지켜보세요!
저자 소개
Deriv의 선임 DevOps 엔지니어인 조티마니 라드하크리슈난은 클라우드 기술에 관심이 많습니다. 엔지니어링 역할 외에도 DevOps, SRE, Python 개발에 관한 글을 쓰는 열렬한 블로거이기도 합니다.