NEXTSTEP - 인프라공방 마지막 4주차 후기다.
인프라공방은 직접 인프라를 경험해보는 실습 강의로
AWS, 성능 테스트 및 개선, 모니터링, 스케일 아웃, 쿼리 최적화, MySQL Replication 등을 진행해볼 수 있다.
미션 진행과정을 요약하기 때문에 자세한 내용이 궁금하면 수강을 추천한다.
♾️ 확장하는 인프라 만들기 - 학습 목표
🎯 기존 인프라의 구성요소들 (Network, Container, Reverse Proxy 등)이 어떻게 추상화되어 있는지 학습해봅니다.
🎯 쿠버네티스 환경에서도 테스트를 진행해보고 리소스를 어떻게 구성하고 관리할지 고민해봅니다.
4주차 후기
지금까지 직접 서버를 세팅하고 배포하고 프록시 서버 등을 진행해오면서 느꼈던 불편한 점이 있었다.
서버를 늘리면 세팅을 일일히 확인해야 하는 등, 수동적인 요소가 너무 많았다.
단순히 미션을 통해서 이렇게 느낀건데, 이런 방식으로 서비스하면 규모가 커질수록 유지보수가 매우 힘들어 보였다.
4주차는 1~3주차 과정을 쿠버네티스로 전환하여 어떻게 달라지는지 경험하는게 목표다.
강의에서는 쿠버네티스 개념, 구성요소, 아키텍처 그리고 미션 설명을 순서대로 진행된다.
4주차 미션은 1단계 쿠버네티스로 구성하기와 추가 미션 2개로 구성되어 있다.
사실상 1단계만 진행해도 4주차는 끝나는 걸로 인정된다.
우선 다른 주차별 후기와 다르게 후기 먼저 작성한 이유는
4주차는 1단계 미션 막바지에 완료하지 못하고 인프라공방이 끝나게 되었다.
마지막 4주차 강의가 진행된 시점엔 나는 아직 3주차 초반 미션을 진행하고 있었고 3주차 미션을 끝내고 나서
4주차 강의를 복습과 미션을 진행했던 시점이 인프라공방의 마지막 날이었다.
다급한 마음에 가이드를 따라 쿠버네티스로 전환 중에 삽질을 하다가 그대로 끝나게 되었다.
해결해보고 싶었지만 계정이 끊기면서 종료가 되었다.
재진행하려면 AWS 프리티어로 처음부터 시작해야한다.
시간을 낸다면 계속 진행할 수 있겠지만, 더 이상 강사님에게 도움 요청을 드리기 힘들 거 같아서 인프라공방은 여기서 마무리하고
추후 정리를 끝내고 나서 나중에 다시 4주차를 도전하고 추가 미션까지 마무리해보려 한다.
4주차에서 정리할 내역
- 쿠버네티스 개념 정리
- 쿠버네티스 클러스터 정리
- 미션에서 사용된 도구들 개념과 명령어 간단히 정리
- kops, kubectl, ingress, helm, cert-manager 등
🚀1단계 - 쿠버네티스로 구성하기 (삽질 원인 찾아보기)
요구사항
- 쿠버네티스 설치하기
- 쿠버네티스로 배포하기
- Deployment 구성하고 배포하기
- Service 구성하기
- Ingress 구성하기
1~3주차 과정을 쿠버네티스로 전환하는 미션을 쿠버네티스 설치로 시작한다.
삽질하다가 중간에 종료가 되어서 PR 요청을 못했지만 그 과정을 다시 짚어보면서 어디서 문제가 발생했는지 알아보려한다.
1. 쿠버네티스 설치
설치할 EC2 인스턴스를 정하고 진행한다.
kops 실행 바이너리를 다운로드한다.
curl -Lo kops https://github.com/kubernetes/kops/releases/download/$(curl -s https://api.github.com/repos/kubernetes/kops/releases/latest | grep tag_name | cut -d '"' -f 4)/kops-linux-amd64
chmod +x kops
sudo mv kops /usr/local/bin/kops
kubectl 실행 바이너리를 다운로드한다.
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
chmod +x kubectl
sudo mv kubectl /usr/local/bin/
EC2에서 IAM role 변경한다.
role 이 변경되었으면 CLI 설정을 한다.
sudo apt update
sudo apt install awscli
aws configure
...
Default region name [None]: ap-northeast-2
...
aws ec2 describe-instances
aws configure 진행중에 AWS Access 관련 Key 설정은 IAM role 때문에 생략하고 넘어간다.
이제 EC2 인스턴스에 배포할 SSH 키를 생성하자.
ssh-keygen -t rsa -N "" -f ~/.ssh/id_rsa
클러스터의 설정 정보를 저장한다
export BUCKET_NAME=[자신의 github id]-k8s-bucket
export NAME=[자신의 github id].k8s.local
export KOPS_STATE_STORE=s3://$BUCKET_NAME
aws s3api create-bucket --bucket $BUCKET_NAME --create-bucket-configuration LocationConstraint=ap-northeast-2
aws s3api put-bucket-versioning --bucket $BUCKET_NAME --versioning-configuration Status=Enabled
kops create cluster --zones ap-northeast-2a --networking calico --ssh-public-key ~/.ssh/id_rsa.pub $NAME
클러스터 수정으로 노드 갯수와 인스턴스 타입 등을 변경해보자 (아마 여기서부터 어디선가 잘못되어 삽질한 이유가 있을거 같다.)
kops get cluster
kops edit cluster $NAME
kops edit ig --name=$NAME nodes-ap-northeast-2a
kops edit ig --name=$NAME master-ap-northeast-2a
kops update cluster --name $NAME --yes --admin
클러스터가 생성되었는지 확인해보자. 10분 정도 기다려야 할 수 있기 때문에 잠깐 볼일을 보고 온다.
kops validate cluster
생성이 되었다면 클러스터 상태를 확인해보자
kubectl cluster-info
kubectl get nodes --show-labels
처음에 호스를 찾을 수 없다고 뜨는데 클러스트 생성 요청하자마자 곧바로 조회 요청을 보내서다.
2. Deployment 구성하기
deploy.yaml 파일을 생성을 하는데 인프라공방에서 제공하는 이미지를 사용하거나 직접 이미지를 생성해서 넣어준다.
나는 강의에서 제공하는 이미지를 사용했다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
replicas: 10
# 컨테이너의 라벨을 선택
selector:
matchLabels:
run: app
strategy:
# RollingUpdate | Recreate (잘 안쓰임)
type: RollingUpdate
rollingUpdate:
# RollingUpdate 중 최대 중단 Pod 허용개수 (또는 비율)
maxUnavailable: 25%
# RollingUpdate 중 최대 초과 Pod 허용개수 (또는 비율)
maxSurge: 25%
template:
metadata:
labels:
run: app
# Pod의 spec과 같음
spec:
containers:
- name: subway
image: [이미지]
쿠버네티스에 deploy.yaml를 적용해보자.
kubectl apply --record -f deploy.yaml
아래는 쿠버네티스 관련 명령어 몇가지 모음이다.
## 업데이트
kubectl set image deployment my-app subway=[이미지]:[새로운버전] --record
## 배포 상태 확인
kubectl rollout status deployment my-app
## 이미지 태그 확인
kubectl get deployments my-app -oyaml | grep image
## 배포 히스토리 확인
kubectl rollout history deployment my-app
## 롤백
kubectl rollout undo deployment my-app
kubectl rollout undo deployment my-app --to-revision=1
## Scale out
kubectl scale deployment my-app --replicas=5
## 수정
kubectl edit deploy my-app
3. Service 구성
deployment처럼 service.yaml 파일을 생성하고 적용한다.
apiVersion: v1
kind: Service
metadata:
labels:
hello: world
name: subway-service
spec:
# type: ClusterIP 가 생략되어 있음
ports:
# Service의 inbound port
- port: 80
protocol: TCP
# port forwarding 하는 port
targetPort: 8080
# 트래픽을 전달할 컨테이너의 라벨을 선택
selector:
run: app
kubectl apply -f service.yaml
4. Ingress 구성
helm을 설치한다
curl https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 | bash -s -- --version v3.2.2
helm repo add stable https://charts.helm.sh/stable/
helm repo update
helm repo list
helm search repo stable
Nginx Ingress Controller를 별도로 설치해야한다.
kubectl create ns ingress-nginx
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update
helm install ingress-nginx ingress-nginx/ingress-nginx --namespace ingress-nginx
설치가 되었는지 정보를 조회해보고
kubectl get pod -n ingress-nginx
kubectl get svc -n ingress-nginx
# 조회된 값을 DNS CName으로 등록해준다.
kubectl get svc -n ingress-nginx ingress-nginx-controller -ojsonpath="{.status.loadBalancer.ingress[0]}"
여기서 진행 중간에 잠깐 삽질을 했었다.
명령어로 조회된 값으로 DNS Cname으로 변경해야했는데 계속 찾을 수 없다고 로그가 뜬다.
kubectl get svc -n ingress-nginx ingress-nginx-controller 이 명령어를
kubectl get svc -n ingress-nginx nginx-ingress-controller 로 잘못 치고 있었다.
정상적으로 조회된 값으로 내도메인.한국 Cname을 변경해주고 다음을 진행한다.
Ingress.yaml 파일을 생성해서 쿠버네티스에 적용해준다.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
# 라벨링과 달리 필터링은 안됨. 단순 메타데이터를 저장하는 용도
# NGINX Ingress Controller에 의해 처리될 것을 명시
annotations:
kubernetes.io/ingress.class: nginx
name: subway-ingress
spec:
# 외부 트래픽을 어떻게 처리할 지 정의
rules:
# 특정 도메인으로 들어오는 트래픽에 대해 라우팅 정의, 생략시 모든 트래픽 처리
- host: loopstudy.kro.kr
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: subway-service
port:
number: 80
kubectl apply -f ingress.yaml
5. TLS 설치
인증서를 관리하는 cert-manager 설치한다.
kubectl create ns cert-manager
## cert-manager 관련 사용자 정의 리소스 생성
kubectl apply --validate=false -f https://github.com/jetstack/cert-manager/releases/download/v1.6.2/cert-manager.crds.yaml
## jetstack repo 추가
helm repo add jetstack https://charts.jetstack.io
## cert-manager 설치
helm install cert-manager jetstack/cert-manager --namespace cert-manager --version v1.6.2
인증서를 관리하는 clusterissuer.yaml 를 생성한다
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: http-issuer
spec:
# 자동으로 인증서의 생성 및 연장을 관리해주는 타입
acme:
email: [이메일주소]
# 어떤 acme 서버(인증서 발급 CA)를 사용할지 지정
server: https://acme-v02.api.letsencrypt.org/directory
# 사용자의 개인키를 저장할 Secret 리소스 이름을 지정
privateKeySecretRef:
name: issuer-key
# 도메인 주소에 대한 소유권을 증명하기 위한 방법 선택. http 요청(http01)과 DNS Lookup(dns01) 방법이 있음
solvers:
- http01:
# Ingress 컨트롤러로 NGINX를 사용
ingress:
class: nginx
$ kubectl apply -f clusterissuer.yaml
$ kubectl get clusterissuer
이전에 작성했던 Ingress.yaml 에 인증서 정보를 추가한다
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: nginx
# 앞서 생성한 발급자 지정
cert-manager.io/cluster-issuer: http-issuer
name: nginx-tls
spec:
rules:
- host: loopstudy.kro.kr
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: subway-service
port:
number: 80
### 인증서 정보를 추가
tls:
- hosts:
- loopstudy.kro.kr
# Secret 리소스를 생성하지 않아도 cert-manager에서 자동으로 인증서를 발급받아서 Secret을 생성한다. 사용자는 생성될 Secret의 이름만 지정하면 된다.
secretName: nginx-tls
수정된 Ingress.yaml를 업데이트한다.
마지막으로 쿠버네티스 인증서가 True가 될때까지 기다려본다.
# True가 될 때까지 기다린다.
watch kubectl get certificate
기다리면서 AWS 콘솔을 확인했더니 쿠버네티스로 생성된 로드밸런서가 새롭게 추가된 걸 볼 수 있다.
...
잠깐 다른 서적을 읽고 왔는데 아무리 기다려도 반응이 없다.
뒤늦게 가이드를 처음부터 확인하면서 비교해봤지만 어디서 문제가 발생했는지 찾을 수가 없었다.
그렇게 인프라공방이 종료되었다.
'교육 및 인강 > 인프라 공방' 카테고리의 다른 글
인프라 공방 3주차 - ⏱️안정적인 인프라 만들기 후기 2부 (0) | 2022.05.19 |
---|---|
인프라 공방 3주차 - ⏱️안정적인 인프라 만들기 후기 1부 (0) | 2022.05.18 |
인프라 공방 2주차 - 🕵🏻♂️ 성능 진단하기 후기 (0) | 2022.05.16 |
인프라 공방 1주차 - 👨🏻💻그럴듯한 인프라 만들기 후기 (0) | 2022.05.16 |
인프라공방 시작글... (0) | 2022.05.13 |