들어가며
이번 글에서는 Kubernetes Ingress 및 Kubernetes Storage에 대해 스터디에서 배운 내용을 정리하도록 한다.
Ingress (네트워크 스터디 과정의 연속)
Ingress는 kubernetes cluster 내부의 서비스들을 외부로 노출하는 데 사용한다. 스터디 환경에서는 AWS Load Balacer Controller를 Ingress에 연결하여 사용했다. NLB의 경우 TCP, UDP 등 많은 프로토콜을 지원하지만, Ingress ALB의 경우 HTTP/HTTPS 프로토콜만 지원한다.
IAM Policy에 AllowExtenerDNSUpdates policy와 AllowExternalDNSUpdates를 각 Leader/Follow Node에 할당한다.
참고:
AWSLoadBalancerControllerIAMPolicy
AllowExternalDNSUpdates
aws iam attach-role-policy-arn arn:aws:iam::$ACCOUNT_ID:policy/<POLICY> --role-name master.$KOPS_CLUSTER_NAME
aws iam attach-role-policy-arn arn:aws:iam::$ACCOUNT_ID:policy/<POLICY> --role-name node.$KOPS_CLUSTER_NAME
kops cluster에 다음의 기능을 추가한다
-----
spec:
certManager:
enabled: true
awsLoadBalancerController:
enabled: true
externalDns:
provider: external-dns
-----
#클러스터 롤링 업데이트
kops update cluster --yes && echo && sleep 3 && kops rolling-update cluster
EC2 Instance Store
EC2 Instance Store는 고속의 속도를 제공하는 스토리지다. EC2 Instance Store는 NVMe(Non-Volatile Memory Express) SSD 기반으로 구성되어 있고, 여기서 NVMe는 호스트 컨트롤러에서 기존 데이터 버스를 사용하지 않고도 SSD에 저장된 데이터에 액세스 하는 속도를 크게 높이는 장치 사양이다. 쉽게 말해서 겁나 빠른 SSD이다.
EC2 Instance Store를 제공하는 인스턴스 유형은 아래의 링크와 같으며, 스터디에서는 이를 제공하는 c5d.large 인스턴스를 이용하여 클러스터의 Leader/Follow Node를 구성했다. 참고로 c5d.large 인스턴스는 50Gi의 아담한 용량을 자랑한다.
참고 : NVMe 인스턴스 스토어 볼륨
하지만 EC2 Instance Storage는 데이터가 날아갈 수 있는 위험이 있다. 데이터 손실은 기본 디스크 드라이브에 오류가 발생하거나, 인스턴스가 멈추거나 삭제되는 상황에 발생할 수 있다. 그래서 높은 워크로드 스펙이 필요한 POD에서는 사용하더라도, 영속성이 필요한 DB 운영용 스토리지로는 적합하지 않다.
인스턴스 생성 후 명령어를 통해 스토어 볼륨을 확인해 보면 루트에 마운트 된 nvme0n1 디스크 외에도 nvme1n1로 구성된 디스크가 추가로 달려있다.
실습을 위해 /data path에 디스크를 마운트 해준다.
W1PIP=<Node1IP>
W2PIP=<Node2IP>
ssh -i ~/.ssh/id_rsa ubuntu@$W1PIP sudo mkdir /data
ssh -i ~/.ssh/id_rsa ubuntu@$W2PIP sudo mkdir /data
ssh -i ~/.ssh/id_rsa ubuntu@$W1PIP sudo mount /dev/nvme1n1 /data
ssh -i ~/.ssh/id_rsa ubuntu@$W2PIP sudo mount /dev/nvme1n1 /data
# 정상 마운트 확인
ssh -i ~/.ssh/id_rsa ubuntu@$W1PIP df -hT -t ext4 -t xfs
ssh -i ~/.ssh/id_rsa ubuntu@$W2PIP df -hT -t ext4 -t xfs
다음으로는 ALB Ingress를 이용하여 서비스를 배포해 본다.
apiVersion: v1
kind: Service
metadata:
namespace: game-2048
name: service-2048
spec:
ports:
- port: 80
targetPort: 80
protocol: TCP
type: NodePort
selector:
app.kubernetes.io/name: app-2048
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
namespace: game-2048
name: ingress-2048
annotations:
alb.ingress.kubernetes.io/scheme: internet-facing # 인터넷으로 연결되는 Pods 로 로드밸런싱 설정
alb.ingress.kubernetes.io/target-type: ip # 타겟을 IP로 설정
spec:
ingressClassName: alb
rules:
- http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: service-2048
port:
number: 80
Pod는 생략하고 Service와 Ingress의 설정을 살펴보도록 한다. services는 80 -> 80 Port로 동작하게끔 되어있고 NodePort타입을 사용하고 있다.
Ingress의 경우 alb.ingress 어노테이션들을 사용하고 있다. 이 설정을 통해 ALB가 파드로 다이렉트로 연결된다.
참고: 애플리케이션로드밸런싱, ALB Rule
Ingress 구성을 좀 더 살펴보면 다음과 같이 alb Ingress Class를 사용하고, 위에서 설정한 Annotation이 잘 적용된 것을 확인할 수 있다.
EC2 > Target groups 을 살펴보면 각 Follow Node에 배포된 Pod와 ALB가 잘 연결된 것을 확인해 볼 수 있다.
과제 1
Ingress(with 도메인, 단일 ALB 사용)에 PATH /mario 는 mario, /tetris 는 tetris 게임에 접속하게 설정 (SSL 적용)
1. SSL 인증서 가져오기
CERT_ARN=`aws acm list-certificates --query 'CertificateSummaryList[].CertificateArn[]' --output text`
2. Deployment 및 Service 생성
가시다님께서 공유해 주신 Mutiple Application Using Single Application Load Balacer 문서를 보면 경로 기반 라우팅에 대한 설명이 나온다.
ALB(Application Load Balancer)는 경로를 기반으로 요청을 라우팅 할 수 있는 규칙을 정의할 수 있다. 이때 주의 할 것은 ALB가 각 애플리케이션의 상태를 체크할 수 있도록 헬스체크 경로를 따로 설정해 줘야 한다는 것이다.
다음으로는 Ingress로 접속할 수 있는 공통 도메인을 설정해 주고, 배포를 위한 games namespace를 추가해 준다.
MYDOMAIN=game.devlos.click
kubectl create namespace games
Ingress 설정은 다음과 같다.
cat<<EOF | k apply -f -
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
namespace: games
name: games-ingress
annotations:
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/target-type: ip
alb.ingress.kubernetes.io/certificate-arn: ${CERT_ARN}
alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS": 443}]'
alb.ingress.kubernetes.io/healthcheck-protocol: HTTP
alb.ingress.kubernetes.io/healthcheck-port: traffic-port
alb.ingress.kubernetes.io/healthcheck-interval-seconds: '15'
alb.ingress.kubernetes.io/healthcheck-timeout-seconds: '5'
alb.ingress.kubernetes.io/success-codes: '200'
alb.ingress.kubernetes.io/healthy-threshold-count: '2'
alb.ingress.kubernetes.io/unhealthy-threshold-count: '2'
spec:
ingressClassName: alb
rules:
- host: ${MYDOMAIN}
http:
paths:
- path: /tetris
pathType: Prefix
backend:
service:
name: tetris
port:
number: 80
- path: /mario
pathType: Prefix
backend:
service:
name: mario
port:
number: 80
EOF
Kubernetes Storage
Kubernetes의 Pod에 별도의 Volume을 할당해 주지 않으면, Pod가 삭제될 때 모든 정보가 삭제된다. 그래서 Pod의 정보를 영구적으로 보존해야 할 필요가 있다면 PV(Persistent Volume)을 사용해야 한다.
Pod의 스토리지 종류는 emptyDir, hostPath, PVC/PV로 나뉘는데, emptyDir는 앞서 이야기한 휘발성 스토리지로써 Pod 안에 생성되고 Pod가 죽으면 삭제된다. hostPath는 각 Node(Host)의 스토리지를 사용하는 방법이고, PVC/PV는 클러스터 단위로 스토리지를 어느 노드에서든 연결해서 쓸 수 있도록 하는 방법이다.
과제 2 - 호스트 Path(local-path-provisioner) 실습 및 문제점 확인
hostPath를 사용할 경우 Pod는 자신이 배포된 Node의 스토리지를 사용하게 되는데, 만약 Pod가 다른 Node로 배포된다면 기존 스토리지를 사용할 수 없게 된다. 스터디에서는 이런 환경을 만들어 내기 위해 drain과 uncordon을 활용하여 Pod를 옮겨가며 실습을 진행했다.
실습 시 storage class는 다음과 같이 local path provisioner를 사용했다.
Pod가 배포된 Node를 Drain 처리하여 Pod가 다른 Node로 이동되자 정상동작 되지 못하는 상황을 확인했다.
그다음 Node를 Uncordon 처리하여 다시 Pod가 정상적으로 동작하게 만들었다.
다시 원래의 노드로 돌아오게 되어 기존 데이터를 그대로 불러오게 된다.
과제 2 - local path provisioner 성능 측정 - 평균 IPOS 3019 출력
curl -s -O https://raw.githubusercontent.com/wikibook/kubepractice/main/ch10/fio-read.fio
kubestr fio -f fio-read.fio -s local-path --size 10G
AWS EBS Controller
Volume을 EBS CSI controller를 이용하여 동작시킬 수 있다. API를 통해 ebs-csi-controller pod를 통해 AWS API를 호출하여 gp3 볼륨을 만들고, kubelet에서 ebs-csi-node 파드를 통해 실제 Volume을 사용할 Pod와 gp3를 연결하는 형태로 동작한다.
이러한 역할은 하는 Pod 들은 kOps로 인해 kube-system namespace에 기본적으로 배포되어 있다.
기본적으로 배포되어 있는 ebs 중에서도 default로 되어 있는 것이 gp3 볼륨이다. 별다른 설정 없이는 PVC 생성 시 기본으로 kops-cso-1-21 storage class를 사용한다.
ebs를 이용한 PV의 볼륨은 Pod를 재구동 하지 않고도 용량을 늘릴 수 있다. 명령어를 통해서 용량을 증가시킬 수 있지만, 줄일 수는 없다고 한다.
과제 3 - AWS EBS를 PVC로 사용 후 온라인 볼륨 증가
과제 4 - AWS Volume SnapShots 실습
1. kOps 환경설정
kops edit cluster
-----
spec:
snapshotController:
enabled: true
# 롤링 업데이트
kops update cluster --yes && sleep 3 && kops rolling-update cluster
2. Volume SnapShots Controller 생성
kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/aws-ebs-csi-driver/master/examples/kubernetes/snapshot/manifests/classes/snapshotclass.yaml
3. 스냅숏 생성
4. 스냅샷 생성 확인
5. Pod, Pvc 강제 제거
6. 스냅샷에서 PVC 로 복원
# 스냅샷에서 PVC 로 복원
kubectl apply -f ~/pkos/3/ebs-snapshot-restored-claim.yaml
# 파드 생성
kubectl apply -f ~/pkos/3/ebs-snapshot-restored-pod.yaml
좋았던 점
hostPath의 개념을 단지 Node에 데이터를 저장하는 것 정도로만 알고 있었는데, Pod가 삭제 후 다른 클러스터에 배치가 되었을 때 스토리지 문제로 인해 장애가 발생할 수 있다는 사실을 알게 되었다.
Kubernets 오브젝트인 Ingress를 이용해서도 NLB와 동일한 방식으로 Pod를 Bypass target으로 지정할 수 있다는 점도 흥미로웠다. 우리 부서는 마이크로 서비스들을 연결하기 위해 Ingress의 Path 방식을 사용하고 있기 때문에, 지금보다 향상된 형태로 네트워크 적용이 가능할 것 같다. (다만 실습과정이 정말 힘들었다..)
힘들었던 점
클러스터 생성 이슈
클러스터 생성 시 아래와 같은 오류로 인해 클러스터 접근 자격증명 문제가 발생했다. 3시간 정도 스택 삭제 생성을 반복하고 9~10분 정도 기다려봐도 동일한 증상이 발생했다.
Route 53의 도메인 레코드 정보가 꼬인 것 같아서 결국 새로운 도메인을 구입했고.. 바로 잘 동작하는 모습을 확인할 수 있었다.
(다행.. ㅎㅎ;)
마치며
이번 글에서는 쿠버네티스 실무 실습 스터디 3주 차에 진행한 내용을 정리해 보았다.
이번에 1번 과제를 진행하면서 위기를 좀 느꼈지만.. 그래도 무사히 잘 마무리가 되어서 다행이다.
과제 시작시기를 좀 더 앞당겨서 시간적 여유를 더 가져야겠다.
'클라우드 컴퓨팅 & NoSQL > [PKOS] 쿠버네티스 실무 실습 스터디' 카테고리의 다른 글
[6주차] PKOS 쿠버네티스 실무 실습 스터디 (23.02.19) (1) | 2023.02.26 |
---|---|
[5주차] PKOS 쿠버네티스 실무 실습 스터디 (23.02.12) (0) | 2023.02.18 |
[4주차] PKOS 쿠버네티스 실무 실습 스터디 (23.02.04) (0) | 2023.02.11 |
[2주차] PKOS 쿠버네티스 실무 실습 스터디 (23.01.15) (0) | 2023.01.29 |
[1주차] PKOS 쿠버네티스 실무 실습 스터디 (23.01.08) (2) | 2023.01.13 |