파이널 프로젝트 - 14주차 4일(3/23)

최수환·2023년 3월 23일
0

Kubernetes

목록 보기
64/75
post-thumbnail

Jenkins 설치 오류 해결

  • Jenkins를 배포하고나서 하루가 지난뒤 갑자기 접속이 안되는 현상이 발생했다. Jenkins를 띄우는 파드의 로그를 확인해보니 볼륨 마운트에 문제가 발생했다. 내 생각으로는 원래 gp2볼륨을 스토리지로 사용했는데 gp2-csi-driver가 설치되있지 않아서 그냥 EFS를 스토리지로 사용해서 발생한 문제 같았다. 왜냐하면 로그에서 Mount지점이 공유되있어서 문제가 발생했다는 것을 확인했기 때문이다.
  • 따라서 Jenkins의 스토리지를 다시 gp2볼륨으로 설정할 것이다.
vi jenkins-values.yaml

. . . 
persistence:
  storageClass: "gp2" # EFS -> gp2로 수정 
. . .
  • 문제는 gp2스토리지 클래스를 사용하려면 ebs-csi-driver가 있어야 하는데 ebs-csi-driver는 애드온으로 추가하여야 한다.
  • 애드온으로 ebs-csi-driver를 설치하려면 ebs-csi-controller가 필요하기때문에 ebs-csi-controller를 사용할 수 있는 IAM정책이 부여된 IAM롤을 가진 서비스 계정이 있어야 한다.
  • 이러한 서비스 계정은 클러스터 배포과정에서 OIDC를 이용해 IAM 롤을 붙여 생성했었다.
eksctl get iamserviceaccount --cluster finalproject --name ebs-csi-controller-sa
#서비스계정의 role-arn확인

eksctl create addon --name aws-ebs-csi-driver --cluster finalproject --service-account-role-arn < role-arn > --force
#확인한 role-arn을 사용, 자신의 클러스터 이름 사용하여 애드온 생성

eksctl get addon --cluster finalproject
#생성한 애드온 확인 
  • 배포과정에서 OIDC를 통해 생성된 IAM서비스계정인 ebs-csi-controller-sa에는 IAM 롤이 붙어있고 IAM롤에는 IAM정책을 통해 ebs-csi-controller에 대한 권한을 가지고 있다. 따라서 해당 IAM서비스 계정은 ebs-csi-controller를 통해 ebs-csi-driver를 설치할 수 있다.
  • 서비스계정에 붙어있는 IAM 롤의 arn을 확인한다. 이후 확인한 arn을 이용하여 ebs-csi-controller가 ebs-csi-driver라는 애드온을 설치한다.
helm install jenkins jenkinsci/jenkins -n jenkins -f jenkins-values.yaml
  • 위의 과정으로 ebs-csi-driver가 설치되었다면, 기존에 생성되어있던 gp2스토리지 클래스를 다시 이용할 수 있게 되기 때문에
    jenkins-values.yaml파일을 helm으로 다시 설치해보면 jenkins가 정상적으로 배포되는 것을 확인.
  • AWS콘솔에 가보면 기존에 EFS에서 Jenkins에 마운트되어있는 볼륨의 엑세스포인트가 하나 사라지고, gp2볼륨이 새로 생성되어있는 것을 확인

< gp2에서 gp3로 교체 >

  • gp3의 최고 성능은 gp2 볼륨의 최대 처리량보다 4배 빠르지만 gp3 볼륨은 범용 SSD(gp2) 볼륨보다 GiB당 20% 저렴하다. gp3 볼륨은 한 자릿수 밀리초의 대기 시간과 99.8% ~ 99.9%의 볼륨 내구성을 0.2% 이하의 연간 고장률(AFR)로 제공한다
  • gp3가 gp2보다 효율도 좋고 가격도 저렴하기때문에 위에서 Jenkins에 마운트한 gp2볼륨을 gp3볼륨으로 교체하려 한다.

1 . gp3 스토리지 클래스 생성

  • 기존의 ebs-csi-driver로 설치한 스토리지 클래스는 gp2이기때문에 ebs-csi-driver를 이용하여 새로 gp3스토리지 클래스를 설치한다.
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: gp3
provisioner: ebs.csi.aws.com # ebs-csi-driver이용
volumeBindingMode: WaitForFirstConsumer
reclaimPolicy: Delete
parameters:
  csi.storage.k8s.io/fstype: ext4
  type: gp3 # gp3로 스토리지 클래스 생성 
  • 이전에 gp2스토리지 클래스를 생성하는 과정에서 설치된 ebs-csi-driver를 이용해서 gp3스토리지 클래스 또한 생성한다.

2 . Jenkins-values.yaml 파일 수정

vi jenkins-values.yaml

. . .
persistence:
  storageClass: "gp3" # gp2 -> gp3로 교체 
. . .

helm install jenkins jenkinsci/jenkins -n jenkins -f jenkins-values.yaml 
# helm으로 Jenkins 설치 

  • AWS콘솔에 새로운 로드밸런서가 추가되었고 해당 로드밸런서의 DNS Name:8080을 브라우저에 입력하면 Jenkins에 접속할 수 있다.

  • AWS 콘솔에서 Jenkins용 파드에 마운트된 gp3볼륨이 생성되어있는 것을 확인

PodScheduling

  • 두개의 인스턴스(=노드)가 있고 각 인스턴스에는 서비스를 구현하기위한 리소스들이 똑같이 배포되어 있다. 즉, 이중화 구현을 한것이고, 만약 인스턴스가 포함된 AZ OR 서브넷에 장애가 발생해도 로드밸런싱을 통해 다른 AZ OR 서브넷에 있는 인스턴스에 트래픽이 전달되기 때문에 클라이언트는 다운타임없이 서비스를 이용할 수 있다.
  • 만약 서비스를 구현하기위한 리소스들을 파드로 배포하는데 어떤 기능을 담당하는 파드가 각 인스턴스에 replica로 복제되어 동일하게 배치되어야하는데 한쪽 인스턴스에 몰려서 배치되게 된다면 다른 쪽 인스턴스는 해당 파드가 담당하는 기능을 갖지 못하게 된다.

    쉽게말해, 백엔드 파드와 프론트 파드가 있고, 두개의 인스턴스에 각각 한 세트로 배치되어서 각 인스턴스가 동일한 서비스를 가능하게 해야한다. 하지만 백엔드 파드 두개가 모두 하나의 인스턴스에 스케줄링된다면, 다른쪽 인스턴스는 서비스를 배포할 수 없다.

vi back-deployment.yaml

spec:
. . . 
  affinity:
    podAntiAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          - key: tier
            operator: In
            values:
            - backend
        topologyKey: "kubernetes.io/hostname"
  • backend파드에 PodAntiAffinity 설정으로 label이 tier: backend인 파드를 배척해서 스케줄링(= 배치) 되게 하였다.
  • baceknd파드가 아무리 늘어나도 파드들의 레이블은 모두 동일하기 때문에 backend파드끼리 같은 노드에 배치되는 일은 존재하지 않는다.
vi front-deployment.yaml

spec:
. . .
  affinity:
    podAntiAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          - key: tier
            operator: In
            values:
            - frontend
        topologyKey: "kubernetes.io/hostname"
    podAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          - key: tier
            operator: In
            values:
            - backend
        topologyKey: "kubernetes.io/hostname"
  • frontend파드에 마찬가지로 PodAntiAffinity 설정으로 label이
    tier: frontend인 파드를 배척해서 스케줄링(= 배치) 되게 하였다.
  • frontend파드가 아무리 늘어나도 파드들의 레이블은 동일하므로 frontend파드끼리 같은 노드에 배치되는 일은 존재하지 않는다.
  • 이때 PodAffinity 설정으로 label이 tier: backend인 파드에 대해서는 해당 파드와 묶여서 노드에 배치되도록 하였다. 즉, 서비스를 구성하는 backend파드와 frontend파드가 한쌍이 되어서 각 노드(= EC2 인스턴스) 에 배치된다. 단, 동일한 기능을 하는 파드가 묶여서 배치되는 일은 없다.
profile
성실하게 열심히!

0개의 댓글