PKOS-kOps-2Week

ㅠㅠ 울고 시작하려한다. 스터디에 집중을 하려고 한다.
가시다님 그동안 숙제 너무 조금해서 죄송했어요...ㅠㅠ엉엉흑흑

일단 사과를 드리고 시작하며, 이제 살짝 각잡고 kOps 부터 설명하겠다.

kOps는 Kubernetes Operations의 약자로, Kubernetes 클러스터를 AWS (Amazon Web Services)에서 손쉽게 설치, 업그레이드 및 관리할 수 있도록 해주는 오픈 소스 도구이다. Kops를 사용하면 CLI(Command Line Interface)를 통해 클러스터를 구성할 수 있으며, YAML 파일을 사용하여 쉽게 클러스터를 정의할 수 있다

Kops는 여러 가지 기능을 제공한다

  1. 클러스터 구성: Kops를 사용하여 Kubernetes 클러스터를 쉽게 구성할 수 있다. YAML 파일을 사용하여 클러스터 구성을 정의하고, AWS 리소스를 프로비저닝하고 구성을 배포한다.
  2. 노드 그룹: Kops는 노드 그룹을 사용하여 클러스터 내에서 다양한 유형의 노드를 정의할 수 있다. 예를 들어, CPU 또는 메모리 요구 사항이 높은 애플리케이션을 실행하는 데 필요한 노드 그룹을 만들 수 있다.
  3. 클러스터 업그레이드: Kops를 사용하여 클러스터를 업그레이드하면, 기존 클러스터의 구성 및 애플리케이션 상태가 유지된다. 이는 클러스터 업그레이드가 더욱 안정적이며 안전하게 진행될 수 있도록 도와준다.
  4. 롤링 업데이트: Kops는 클러스터의 노드 그룹을 업데이트할 때 롤링 업데이트를 수행할 수 있다. 이를 통해 클러스터에 대한 서비스 중단 없이 노드 그룹의 업데이트를 진행할 수 있다.

Kops는 쉽게 시작할 수 있는 Kubernetes 설치 및 관리 도구 중 하나이다, AWS에서 Kubernetes 클러스터를 운영하는 데 매우 유용하다.

PKOS에서는 24단계 실습으로 정복하는 쿠버네티스 로 실습을 진행하면서 kOps를 사용한다.

나는 EKS 를 근래에 주로 다루고 있다.

kOps 와 EKS를 간략하게 비교해봤다.

기능 / 속성kOpsEKS
관리 형태오픈 소스 도구완전 관리형 서비스
클라우드 플랫폼AWS, GCP 등 다양한 플랫폼AWS 전용
클러스터 구축사용자 정의 구성 가능표준화된 구성 사용
클러스터 업그레이드사용자가 직접 관리AWS가 제공하는 관리형 업그레이드
클러스터 유효성 검사kOps 도구를 사용하여 제공AWS 콘솔 및 API를 통해 제공
비용인프라 리소스 비용만 발생인프라 리소스 및 EKS 서비스 비용
운영의 편의성사용자가 더 많은 관리를 수행함AWS가 더 많은 관리를 처리함

역시 관리형이 편하다.

이번주에는 K8S의 네트워킹에 대해서 공부를 했는데 다른점이 많은 kOps 와 EKS지만 kOps 를 사용하면 EKS를 배우기 편한 부분이 있다. 이유는 에드온이나, CNI를 같은것을 사용할수 있다.

awsLoadBalancerController / CNI로는 amazonvpc 를 사용한다.

내가 이야기할 것은 CNI다.

amazonvpc CNI 같은 경우에는 한가지 특징이 있는데 AWS ENI를 컨테이너에 연결하여 일반적으로 우리가 사용하는 kube-proxy의 동작이 현저하게 줄어들게 된다.

kube-proxy의 동작이 줄어드는 아키텍처는 노드에서의 네트워크 처리횟수가 줄어들어 CPU의 사용량이 줄어든다. 기본적으로 리눅스 네트워크 스택은 자원의 사용량이 적지만 네트워크의 미학을 가진 K8S는 적극적으로 리눅스네트워크 스택을 사용한다. 그러므로 노드의 부하는 커진다. 이런 문제를 amazonvpc CNI는 회피할수 있는 방법을 제시한것이다.

POD가 클러스터를 통하지 않고 통신하는 방식은 Network Hop을 줄이기 때문에 일반적인 오버레이 네트워크의 Network Hop보다 현저하게 줄어들고 빠른 방식이 가능한것이다.

이때문에 kube-proxy를 쓰는 nodeport 같은 형태의 Sevice는 EKS에 어울리지 않는다.

반드시 awsLoadBalancerController 를 사용할떈 target option을 IP로 사용하길 추천한다.

pod graceful shutdown

    spec:
      containers:
        - name: nginx
          image: nginx:latest
          ports:
            - containerPort: 80
          resources:
            limits:
              cpu: 500m
            requests:
              cpu: 200m
          lifecycle:
            preStop:
              exec:
                command: ["/bin/sleep", "30"]

.

.

hpa 발생시 pod의 갑작스런 종료로 pod에 연결된 사용자가 502를 받게된다.

모든 리퀘스트를 처리 후에 종료되도록 30초간의 유예를 준다 설정 변경 lifecycle preStop 를 이용하여 우아한 종료를!

PKOS-kOps-1Week

이번에 스터디에 참가하게 되었다.

가시다님의 PKOS!

스터디할시에 사용하는 책은 24단계 실습으로 정복하는 쿠버네티스 이다.

kOps를 프로비저닝하는데 오타가 발생해서 심심해서 스크립트를 만들었다.
그덕에 한번 다시 만들었다.

#!/bin/bash

echo "클러스터명-도메인을 입력해주세요 : "
read KOPS_CLUSTER_NAME
echo "버킷명을 입력해 주세요 s3:// 는 입력하지 않아도 됩니다. : "
read  KOPS_STATE_STORE
# Access Key를 입력 받음
read -p "엑세스키를 입력해주세요 : " ACCESS_KEY

# Secret Access Key를 입력 받음
read -p "시크릿키를 입력해주세요 : " SECRET_KEY

# AWS 계정 구성
aws configure set aws_access_key_id $ACCESS_KEY
aws configure set aws_secret_access_key $SECRET_KEY
echo 'export AWS_PAGER=""' >>~/.bashrc
echo "export REGION=ap-northeast-2" >>~/.bashrc
echo "export KOPS_CLUSTER_NAME=$KOPS_CLUSTER_NAME" >>~/.bashrc
echo "export KOPS_STATE_STORE=s3://$KOPS_STATE_STORE" >>~/.bashrc

kops create cluster --zones="$REGION"a,"$REGION"c --networking amazonvpc --cloud aws \
--master-size t3.medium --node-size t3.medium --node-count=2 --network-cidr 172.30.0.0/16 \
--ssh-public-key ~/.ssh/id_rsa.pub --name=$KOPS_CLUSTER_NAME --kubernetes-version "1.24.10" --dry-run -o yaml > mykops.yaml


kops create cluster --zones="$REGION"a,"$REGION"c --networking amazonvpc --cloud aws \
--master-size t3.medium --node-size t3.medium --node-count=2 --network-cidr 172.30.0.0/16 \
--ssh-public-key ~/.ssh/id_rsa.pub --name=$KOPS_CLUSTER_NAME --kubernetes-version "1.24.10" -y

source <(kubectl completion bash)
echo 'source <(kubectl completion bash)' >> ~/.bashrc
echo 'alias k=kubectl' >> ~/.bashrc
echo 'complete -F __start_kubectl k' >> ~/.bashrc

read 명령어를 이용하여 스크립트에 변수를 부여하고 입력받은 변수를 이용하여 aws configure 를 설정하고, kops 명령어로 k8s 클러스터를 프로비저닝한다.

이거다음에는 사실 initscript 에 내가원하는 값을 넣는게 제일 편하나 그건..좀 공개하기 애매하니 스크립트라도 공개한다.

2022 회고

2022년은 나에게도 많은 일이 있었던 해이다.

나는 네이버클라우드 솔루션아키텍트에서 밀리의서재 인프라스트럭처 엔지니어로 이직했다.

그사이에 책도 출간했다. 차도 샀다. 이직 후에 ISMS인증 심사도 받았다.

네이버클라우드에서는 나는 주로 설계를하고 내부적문제를 분석하고 에스컬레이션하는 업무를 맡았다. 그리고 CSAP 인증관련 프로젝트를 하며, 기약없는 나날을 보내고 있었다. 성장에 목이 말랐고, 뭘해야할지 모르는 안타까운 날들이었다. 회사의 성장은 느껴지는데, 나의 성장은 멈춰있는 느낌이었다.

문제는 회사가 아니라 나에게 있었다.

일상에서의 자극들이 아이디어와 성장으로 이루어지는 나의 방식이 알맞지 않았다. 또 기술적 성장을 더욱 하고싶었다.

그래서 이직을 선택했다.
다양한 회사를 알아봤고, 그러다 밀리의서재로 오게되었다.

이력서를 제출전에 본부장인 리나와 커피챗을 했다.

밀리의 사용 스택과 필요한 부분등 여러가지가 나와 핏이 잘맞았다. 흔히 말하는 저스트핏. 바로 이력서를 작성했고 면접을 봤다. 1차면접부터 2차면접 합격까지 10일의 시간이 걸렸고, 바로 입사를 결정했다.

이렇게 빠른 결정이 가능했던건 정말 나와 밀리가 핏이 너무 잘맞았기 때문이라 생각한다.

인프라팀을 정돈해가며 스크럼에 적응하고, 내 서비스를 가지게 된 나는 서비스와 친해지기 위해 많은 정성을 쏟았다.

또 리더로서 다시 일하게 되어 더욱 동료의 생각에 공감하려 노력했고, 내가하는 일이 동료가 공감할수 있도록 노력했다.

기계처럼 일만하는게 아니라 동료의 신뢰를 얻고 싶었고, 내가 엔지니어로 같은 회사에 있을 때 느껴지는 든든함을 동료들이 가지길 원했다.

새로운 모니터링 시스템을 만들고 분석 플랫폼을 만들어서 이슈의 원인과 분석을 하는 속도를 높여갔다.

그 결과 동료들과의 유대는 깊어졌고, 나는 자리잡았다.

좋은 동료와 같이 일하는 즐거움을 13년차가 되어서야 배운다.

2022년은 항상 새롭고 즐거웠다.

2023년 또한 새롭고 즐겁도록 만들것이다.


T101-AWS-To-SLACK-Noti - EventBridge

이제야 블로그가 손에 잡혀서 오랜만에 글을 쓰기위해 책상앞에 앉았다. 이게다 내 게으름 때문이다.

맨날 이 뻔한 핑계를 치면서 한번 웃고야 말았다.

이번에 쓸 블로깅은 T101에서 한번 발표한 적인 있는 내용이다.

이 포스팅에선 EventBridge와 CloudTrail을 집중적으로 다룬다.

https://nyyang.tistory.com/126 이블로그를 보고 작업을 시작했다.

먼저 시작하기전에 EventBridge Bus 규칙에서 Trail에서 패턴을 감지하기위해선 이벤트버스는 무조건 Default여야한다. 다른 버스에 만들면 버스 지나간 다음 손 흔들어야 한다. 패턴을 감지할수 없다는 이야기다.

골자는 이렇다.

CloudTrail 에서 발생하는 이벤트를 EventBridge 는 특정 패턴을 감지해서 이벤트를 발생시킬수 있다.

아래 예가 그렇다.

{
  "source": ["aws.iam", "aws.ec2"],
  "detail-type": ["AWS API Call via CloudTrail"],
  "detail": {
    "eventSource": ["iam.amazonaws.com", "ec2.amazonaws.com"],
    "eventName": ["AttachGroupPolicy", "AttachRolePolicy", "AttachUserPolicy", "ChangePassword", "CreateAccessKey", "CreateGroup", "CreatePolicy", "CreateRole", "CreateUser", "DeleteAccessKey", "DeleteGroup", "DeleteGroupPolicy", "DeletePolicy", "DeleteRole", "DeleteRolePolicy", "DeleteUser", "DeleteUserPolicy", "DetachGroupPolicy", "DetachRolePolicy", "DetachUserPolicy", "PutGroupPolicy", "PutRolePolicy", "PutUserPolicy", "AuthorizeSecurityGroupIngress", "AuthorizeSecurityGroupEgress", "RevokeSecurityGroupIngress", "RevokeSecurityGroupEgress"]
  }
}

AWS ec2와 iam에서 발생하는 특정 패턴을 감지하여 이벤트를 발생시키는것이다.

여기에서 내가 굉장히 많은시간 고민을했다. 이유는 패턴 때문이다. 내가 감지하고 싶은 패턴은 AWSConsoleLogin 이다. 이 API가 속하는 source 와 detail-type 이 정리된 곳이 없었기 때문이다. 또한 EventBridge에서 템플릿으로 제공하는 이벤트 패턴으로 테스트했을 땐 잘되지 않았다. 고민했던 부분은 총 3가지 였다.

첫번째로 이벤트 패턴을 감지하기위해서 일반적으로 source 와 detail-type 을 지정해줘야했는데 모든예제는 Source 를 무조건 사용하도록 되어있었다. EventBridge 에선 3가지 이벤트 패턴을 사용할수 있는데 그중 하나만 사용해도 문제가 없다.
source / detail-type / detail 이렇게 세가지이다.

두번째 문제는 Trail에 찍히는 로그와 EventBridge 에 전달되는 이벤트의 내용이 다르다.

{
'version':'0',
'id':'1',
'detail-type':'AWS Console Sign In via CloudTrail',
'source':'aws.signin',
'account':'1',
'time':'2022-12-17T01:09:08Z',
'region':'ap-northeast-2',
'resources':[
],
'detail':{
'eventVersion':'1.08',
'userIdentity':{
'type':'IAMUser',
'principalId':'1',
'accountId':'1',
'accessKeyId':'',
'userName':'1'
},
'eventTime':'2022-12-17T01:09:08Z',
'eventSource':'signin.amazonaws.com',
'eventName':'CheckMfa',
'awsRegion':'ap-northeast-2',
'sourceIPAddress':'58.227.0.134',
'userAgent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML,
like Gecko) Chrome/106.0.5249.114 Safari/537.36', 'requestParameters':None,
'responseElements':{
'CheckMfa':'Success'
},
'additionalEventData':{
'MfaType':'Virtual MFA'
},
'eventID':'1',
'readOnly':False,
'eventType':'AwsConsoleSignIn',
'managementEvent':True,
'recipientAccountId':'1',
'eventCategory':'Management',
'tlsDetails':{
'tlsVersion':'TLSv1.2',
'cipherSuite':'ECDHE-RSA-AES128-GCM-SHA256',
'clientProvidedHostHeader':'ap-northeast-2.signin.aws.amazon.com'
}
}
}
{
    "eventVersion": "1.08",
    "userIdentity": {
        "type": "IAMUser",
        "principalId": "1",
        "arn": "arn:aws:iam::1:",
        "accountId": "1",
        "accessKeyId": ""
    },
    "eventTime": "2022-12-17T02:29:28Z",
    "eventSource": "signin.amazonaws.com",
    "eventName": "ConsoleLogin",
    "awsRegion": "ap-northeast-2",
    "sourceIPAddress": "58.227.0.134",
    "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.5249.207 Safari/537.36",
    "requestParameters": null,
    "responseElements": {
        "ConsoleLogin": "Success"
    },
    "additionalEventData": {
        "LoginTo": "https://ap-northeast-2.console.aws.amazon.com/console/home?hashArgs=%23&isauthcode=true&region=ap-northeast-2&state=hashArgsFromTB_ap-northeast-2_b149694953e40e5b",
        "MobileVersion": "No",
        "MFAIdentifier": "arn:aws:iam::1:mfa/root-account-mfa-device",
        "MFAUsed": "Yes"
    },
    "eventID": "1",
    "readOnly": false,
    "eventType": "AwsConsoleSignIn",
    "managementEvent": true,
    "recipientAccountId": "1",
    "eventCategory": "Management",
    "tlsDetails": {
        "tlsVersion": "TLSv1.2",
        "cipherSuite": "1",
        "clientProvidedHostHeader": "signin.aws.amazon.com"
    }
}

민감 정보는 지웠다. 이렇게 두가지 내용이 다르다. 처음에 Trail Log를 보고서 패턴을 작성하다가 놀랐다. 그리고 이 이벤트를 보려면 이벤트 브릿지에선 넘어온 데이터를 볼수없다. 이벤트 카운트 뿐이다.

세번째는 리전에 대한 이야기다.

우리의 Console 로그인은 리전기반이다. 이게 나를 오랜시간 고민하게 하고 괴롭혔다.

Trail은 글로벌 서비스 이벤트가 있다.

https://docs.aws.amazon.com/ko_kr/awscloudtrail/latest/userguide/cloudtrail-concepts.html#cloudtrail-concepts-global-service-events

이 글로벌 서비스중 sts에 우리는 주목해야한다. 로그인할때 STS 를 호출하기 때문이다. 그럼 STS 를 설명하기 전에 Console Login 부터 알아야한다.

로그인을 시도할때 우리는 AWS Console 을 통해 그냥 로그인한다고 생각하지만, 그렇지 않다. AWS Console은 로그인 할때 이런 URL 을 가지고 있다.

https://signin.aws.amazon.com/signin?redirect_uri=https%3A%2F%2Fconsole.aws.amazon.com%2Fconsole%2Fhome%3FhashArgs%3D%2523%26isauthcode%3Dtrue%26state%3DhashArgsFromTB_ap-northeast-1_6b240714978b3994&client_id=arn%3Aaws%3Asignin%3A%3A%3Aconsole%2Fcanvas&forceMobileApp=0&code_challenge=U8A4YkTPRIIvi-8Gj7-tIx4RB_PR9IT-4fVs7diVUoc&code_challenge_method=SHA-256

이 URL로 로그인하면 Console Login log는 ap-northeast-1 로 연결된다. 그러니까 우리는 도쿄로 연결되는 로그인때문에 이것을 재대로 트래킹 할수 없다는 이야기다. 놓치는 로그인들을 해결하고 싶었다.

글로벌 서비스를 추적하면 도쿄로 연결되는 로그인을 추적할수 있을까?

정답은 "그렇다" 하지만 문제가 생길수도 있다.

슬프게도 글로벌서비스 추적이란 그냥 글로벌 엔드포인트를 이용하면 그 로그가 us-east-1 에 쌓일 뿐 모든 리전의 STS로그가 글로벌서비스 추적에 쌓이는건 아니다.

그렇기에 로그인 추적은 어렵다. 그렇다고 해서 아주 못하는것은 아니다. 로그인은 반드시 STS를 호출한다. 극단적으로 가기로 했다.

IAM > 계정설정 > 엔드포인트

위에서 로그인 URL에 도쿄리전으로 파라미터가 들어가있는데 그 대로 로그인 해보겠다. 그전에 나의 계정에선 도쿄의 STS 엔드포인트를 비활성화하였다.

{
    "eventVersion": "1.08",
    "userIdentity": {
        "type": "1",
        "principalId": "1",
        "arn": "arn:aws:iam::1:1",
        "accountId": "1",
        "accessKeyId": ""
    },
    "eventTime": "2022-12-17T04:02:18Z",
    "eventSource": "signin.amazonaws.com",
    "eventName": "ConsoleLogin",
    "awsRegion": "us-east-1",
    "sourceIPAddress": "1",
    "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36",
    "requestParameters": null,
    "responseElements": {
        "ConsoleLogin": "Success"
    },
    "additionalEventData": {
        "LoginTo": "https://console.aws.amazon.com/console/home?hashArgs=%23&isauthcode=true&state=hashArgsFromTB_ap-northeast-1_6b240714978b3994",
        "MobileVersion": "No",
        "MFAIdentifier": "arn:aws:iam::1:mfa/1-account-mfa-device",
        "MFAUsed": "Yes"
    },
    "eventID": "1",
    "readOnly": false,
    "eventType": "AwsConsoleSignIn",
    "managementEvent": true,
    "recipientAccountId": "1",
    "eventCategory": "Management",
    "tlsDetails": {
        "tlsVersion": "TLSv1.2",
        "cipherSuite": "ECDHE-RSA-AES128-GCM-SHA256",
        "clientProvidedHostHeader": "signin.aws.amazon.com"
    }
}

로그 보면 이렇다. LoginTo 에서는 ap-northeast-1 로 로그인했으나, 실제 리전은 us-east-1 로 연결되었다. 글로벌서비스 STS로 연결된것이다. 아마 가까운 리전엔드포인트를 제공해주는것으로 보는데 실제로는 잘모른다.

이렇게 세가지의 고민을 끝내고 Trail의 추적을 생성하였는데, 문제를 찾을수 있었다.

우리는 필연적으로 버지니아 북부와 실제사용리전에서 Trail의 추적을 생성해야하는데 이걸 콘솔에선 생성해선 안된다.

이전에는 Trail 에서는 콘솔에서 다중추적의 온오프를 옵션으로 제공했는데 이젠 그렇지 않다. 이전의 기억만 믿고 진행했다가 다중추적이 여러군데 생성되었다.

https://aws.amazon.com/ko/premiumsupport/knowledge-center/remove-duplicate-cloudtrail-events/

다중추적의 중복은 비용이 발생한다.

PaidEventsRecorded 이 지표가 증가한다면 다중추적이 여러개가 생성된거다.

그렇기에 추적을 생성할땐 주요사용리전에만 다중리전 추적을 생성하고 버지니아 북부에서는 글로벌서비스 추적만 활성화 해야한다. 그러면 비용이 추가되지 않는다.

글로벌 서비스 추적을 만들려면 AWSCLI를 이용해서 만들어야 한다.

# aws cloudtrail update-trail --name my-trail --no-include-global-service-events

https://docs.aws.amazon.com/ko_kr/awscloudtrail/latest/userguide/cloudtrail-create-and-update-a-trail-by-using-the-aws-cli-update-trail.html#cloudtrail-create-and-update-a-trail-by-using-the-aws-cli-examples-gses

EventBridge 와 Trail에 대한 삽질기를 이렇게 정리해둔다.

조금이나마 도움이 되길 빈다.