f-lab-clone / ticketing-backend

[2023] Ticketing Service - PerformanceTest, Terraform, EKS, Grafana
https://github.com/f-lab-clone/ticketing-infra
5 stars 3 forks source link

CD: 배포를 위한 환경 세팅 [학습] #7

Closed junha-ahn closed 1 year ago

junha-ahn commented 1 year ago

Description

배포를 위한 최소 환경 세팅 (학습)

To do

학습 시나리오 1

  1. terraform을 이용해 AWS에 EC2 띄우기
  2. k8s 직접 세팅하기 (1 master node / 1 worker node~~ / spring boot hello world)
  3. git deployment 등으로 repo code(or image) 자동으로 올리기

Test Checklist

학습 시나리오2

  1. Terraform EKS로 Hello World 띄우기
  2. CD pipeline 구축
  3. Helm으로 Prod/QA 환경 구축

Finally

image

Tech Stack

junha-ahn commented 1 year ago

codespace (postCreateCommand)를 제 개인 ubuntu machine으로 써서 테스트 해보겠습니다. codespace를 이용하면 무료 ubuntu machine이 빠르게 on/off가 가능하네요

junha-ahn commented 1 year ago

1. 구성도를 직접 손으로 그려보기

완료

2. kubernetes를 어떻게 설치할지?

https://www.skyer9.pe.kr/wordpress/?p=6630

마스터와 워커 노드에 k8s를 각각 설치를 해야한다.

다만 해당 설치는 오래걸리니까, worker AMI 이미지를 만들어놓고 복제 떠서 EC2 worker를 생성한다.

3. 언제 EKS로 넘어갈까?

위 설명된 불편함 관련

scale up 관련

plugin 관련

ETC. gitops의 사용 포인트는?

jacepark12 commented 1 year ago

EKS의 단점 : 좀 비싸다

junha-ahn commented 1 year ago

학습 시나리오 1

1. Terraform EC2

https://github.com/junha-ahn/kotlin-boot-deployment/tree/main/terraform

2. Hello world App

install k8s (설치 중 오류)

NO_PUBKEY (solved)

접기/펼치기 Ubuntu는 패키지를 관리하기 위해 public key를 사용 - 사용자는 pubkey를 가지고, 다운받을때 해당 패키지와의 비교 검증을 통해 변조되지 않았음을 보장 - pubkey는 패키지 개발자 측에 의해 생성되며, Ubuntu 시스템에는 해당 pubkey 저장소가 있다. (APT는 이 저장소에서 pubkey를 가져와 사용) `NO_PUBKEY` 에러는 Ubuntu에서 사용하는 Public key가 등록되지 않았기에 발생. - APT install, update를 사용할때 자주 발생한다 - pubkey가 없기 때문에 APT는 해당 패키지를 신뢰할 수 없다고 판단 ### 해결 방법 공개키를 등록한다 ```bash sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys sudo apt-get update ``` Q. ubuntu keysystem에 등록되어있어서 APT에 의해 자동으로 진행되는 과정이라고 이해 되는데, 왜 해당 `NO_PUBKEY`에러가 발생했을까? - 그리고 해결방법도 결국 KEYSERVER에서 install하는것이라면 왜 이런 에러가 발생한거지? - 추측1. keyserver.ubuntu.com은 APT가 접근하는 keyserver가 아니다. 따라서 `apt-key` 명령을 통해 수동으로 키를 등록해야 한다. - 그럴 가능성은 낮아보인다. - 추측2. `apt-key` 명령을 사용 후에도 에러가 발생하는것을 봤을땐, 어떤 이유에서인지 등록된 pubkey로 인해 덮어씌울 수 없고, 해당 이유로 `pubkey`에러가 발생하는 것 ## 추가 오류 발생 ``` gpg: key B53DC80D13EDEF05: "Rapture Automatic Signing Key (cloud-rapture-signing-key-2022-03-07-08_01_01.pub)" not changed ```` ### 해결방법 > This script worked for me on Ubuntu 22.04.2 LTS using WSL ```bash curl -fsSL https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo gpg --yes --dearmor -o /usr/share/keyrings/kubernetes-archive-keyring.gpg echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list > /dev/null ``` reference - https://github.com/kubernetes/release/issues/2862

Connection Refused

접기/펼치기 master (CP) ec2 안에서.., ``` > kubectl get nodes NAME STATUS ROLES AGE VERSION ip-10-0-1-191 NotReady control-plane 2m4s v1.27.3 # 바로 실행 > kubectl get nodes The connection to the server 10.0.1.191:6443 was refused - did you specify the right host or port? > docker ps -a permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get "http://%2Fvar%2Frun%2Fdocker.sock/v1.24/containers/json?all=1": dial unix /var/run/docker.sock: connect: permission denied ``` kubectl 로 계속 접근이 불가능해짐... 이유가 뭘까?... ### 해결 어째서인지 terraform으로 모든 EC2 재빌드 후 해결 - 자꾸 이랬다 저랬다 하는거보면, kubeapi는 원래 init에 시간이 엄청 걸리나?... ```bash ubuntu@ip-10-0-1-139:~$ kubectl get nodes NAME STATUS ROLES AGE VERSION ip-10-0-1-139 NotReady control-plane 117s v1.27.3 ip-10-0-1-63 NotReady 21s v1.27.3 ```

Node NotReady

접기/펼치기 ```bash $ kubectl get nodes NAME STATUS ROLES AGE VERSION ip-10-0-1-16 NotReady control-plane 14m v1.27.3 ip-10-0-1-70 NotReady 13m v1.27.3 $ top top - 14:29:34 up 23 min, 1 user, load average: 0.08, 0.23, 0.31 Tasks: 120 total, 1 running, 119 sleeping, 0 stopped, 0 zombie %Cpu(s): 2.0 us, 1.0 sy, 0.0 ni, 95.5 id, 0.2 wa, 0.0 hi, 0.0 si, 1.3 st MiB Mem : 1937.3 total, 411.5 free, 319.9 used, 1205.9 buff/cache MiB Swap: 0.0 total, 0.0 free, 0.0 used. 1450.1 avail Mem ``` 위 커넥션 불안정 문제와 상관 있어 보인다. - 부하도 없는데... ``` $ kubectl get cs Warning: v1 ComponentStatus is deprecated in v1.19+ NAME STATUS MESSAGE ERROR controller-manager Unhealthy Get "https://127.0.0.1:10257/healthz": dial tcp 127.0.0.1:10257: connect: connection refused etcd-0 Unhealthy Get "https://127.0.0.1:2379/health": dial tcp 127.0.0.1:2379: connect: connection refused scheduler Unhealthy Get "https://127.0.0.1:10259/healthz": net/http: TLS handshake timeout ``` https://github.com/kubernetes/kubeadm/issues/2222 ```bash $ kubectl version --output=json { "clientVersion": { "major": "1", "minor": "27", "gitVersion": "v1.27.3", "gitCommit": "25b4e43193bcda6c7328a6d147b1fb73a33f1598", "gitTreeState": "clean", "buildDate": "2023-06-14T09:53:42Z", "goVersion": "go1.20.5", "compiler": "gc", "platform": "linux/amd64" }, "kustomizeVersion": "v5.0.1" } The connection to the server 10.0.1.171:6443 was refused - did you specify the right host or port? ``` - 이상한점 master에 있는데 왜 `127.0.0.1`로 안보내지?? ```bash $ sudo kubectl version --output=json { "clientVersion": { "major": "1", "minor": "27", "gitVersion": "v1.27.3", "gitCommit": "25b4e43193bcda6c7328a6d147b1fb73a33f1598", "gitTreeState": "clean", "buildDate": "2023-06-14T09:53:42Z", "goVersion": "go1.20.5", "compiler": "gc", "platform": "linux/amd64" }, "kustomizeVersion": "v5.0.1" } The connection to the server localhost:8080 was refused - did you specify the right host or port? ``` - sudo를 붙였을때는 왜 달라지지?


해결책

모든 이슈가 우분투 버전과 맞지 않은 설치 메뉴얼을 실행한 것

오랜만에 하니 설치방법을 정확하게 찾아야 한다는걸 ... 그냥 편한 한국어 글로 찾아버렸음

기존 설치방법에서 ubuntu 22.x 에 맞는 설치방법으로 변경

As we can see nodes status is ‘NotReady’, so to make it active. We must install CNI (Container Network Interface) or network add-on plugins like Calico, Flannel and Weave-net.

OS에 맞는 설치방법 적용 후 해결


1. git actions - docker image push

2. download image from hub and deployment

3. 외부에서 curl <public-ip>:80 접속 가능화 (kube service 등)

# service.yaml
apiVersion: v1
kind: Service
metadata:
  name: kotlin-app-service
spec:
  type: NodePort
  ports:
    - port: 80
      targetPort: 8080
      protocol: TCP
      nodePort: 30001
  selector:
    app: kotlin-app
resource "aws_security_group_rule" "cicd_sg_ingress_nodeport" {
  type        = "ingress"
  from_port   = 30001
  to_port     = 30001
  protocol    = "tcp"
  cidr_blocks = ["0.0.0.0/0"]
  security_group_id = aws_security_group.cicd_sg.id
}
외부PC $  curl <master-public-ip>:30001
Hello world~~

80 포트에 띄우진 않았으나, 성공으로 간주 (어차피 실제 환경에서는 LB 등을 사용할 예정)

3. CD pipeline

  1. git push on main branch
  2. push docker image to hub - git actions
  3. auto deployment k8s

Todo

  1. ArgoCD 구축
  2. git push 후 자동 배포 확인

image

최적화

접기/펼치기 ### worker image AMI 복사 구성 - AWS 자체 기능 이용 - [Clone EC2 instance using Terraform - How to | Devops Junction](https://www.middlewareinventory.com/blog/clone-ec2-instance-using-terraform-how-to-devops-junction) - and don't forget `count = 3` filed ### 어떻게 하면 worker node가 자동으로 master에 연결되도록 할 수 있을까? 1. terraform EC2 생성간 의존성 부여 - 무조건 master가 생성되어야 worker가 생성 될 수 있다. - terraform [depends on](https://developer.hashicorp.com/terraform/tutorials/configuration-language/dependencies#manage-explicit-dependencies) 5. master 에서 생성된 `kube join token`을 worker에 전달할 수 있는 방법 ? - 이 token을 통해 worker에서 master에 join이 가능해진다 - IP는 terraform output IP & depens_on 조합으로 가능 - MASTER EC2 => AWS secret 관리 툴 => WORKER EC2??... 6. master는 고정 token 을 .env 등으로 관리해서 worker만 증가시키기 7. k8s worker node join 다른 방법 있는지 조사하기
junha-ahn commented 1 year ago

학습 시나리오 2

학습 자료

Terraform EKS로 Hello World 띄우기

EKS를 사용해서 어플리케이션 서비스 하기를 활용하여

 $ kubectl port-forward simon-sample-5f8bf6796-qp8md 8080:8080
Forwarding from 127.0.0.1:8080 -> 8080
Forwarding from [::1]:8080 -> 8080
Handling connection for 8080

➜ /workspaces/kotlin-boot-deployment (main) $ curl 127.0.0.1:8080
Hello world!!~

ALB 를 붙어야 Public Endpoint로 접속 가능하나 미구현

CD pipeline 구축

eks-blueprints-example-argocd를 활용하여 구성

ArgoCD 화면 image

LB DNS name 을 통해 접속 image

LB 정보 image

지금 해야하는 것

Helm으로 Prod/QA 환경 구축

hihahayoung commented 1 year ago

학습 시나리오 1

EndPoint: None 에러

접기/펼치기 ```shell master_public_ip = "43.200.254.74" master_private_ip = "10.0.1.86" worker1_public_ip = "3.35.236.70" worker1_private_ip = "10.0.1.193" $ kubectl get nodes -o wide NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME ip-10-0-1-193 Ready 47m v1.27.4 10.0.1.193 Ubuntu 22.04.2 LTS 5.19.0-1025-aws containerd://1.6.21 ip-10-0-1-86 Ready control-plane 50m v1.27.4 10.0.1.86 Ubuntu 22.04.2 LTS 5.19.0-1025-aws containerd://1.6.21 ``` ### pod + service 조합 ```yaml apiVersion: v1 kind: Pod metadata: name: kotlin-app labels: name: kotlin-app spec: containers: - name: core image: devjunha/kotlin-app:latest imagePullPolicy: Always ports: - containerPort: 8080 protocol: TCP resources: requests: cpu: 500m memory: 1000Mi ``` ```yaml apiVersion: v1 kind: Service metadata: name: kotlin-app-service spec: type: NodePort ports: - port: 8080 targetPort: 8080 protocol: TCP nodePort: 30001 selector: app: kotlin-app ``` ```shell $ kubectl describe service kotlin-app-service Name: kotlin-app-service Namespace: default Labels: Annotations: Selector: app=kotlin-app Type: NodePort IP Family Policy: SingleStack IP Families: IPv4 IP: 10.99.133.216 IPs: 10.99.133.216 Port: 8080/TCP TargetPort: 8080/TCP NodePort: 30001/TCP Endpoints: Session Affinity: None External Traffic Policy: Cluster Events: ``` ### deployment + service 조합 ```yaml apiVersion: apps/v1 kind: Deployment metadata: name: kotlin-app-deployment spec: selector: matchLabels: app: kotlin-app replicas: 1 template: metadata: labels: app: kotlin-app spec: containers: - name: core image: devjunha/kotlin-app:latest imagePullPolicy: Always ports: - containerPort: 8080 protocol: TCP resources: requests: cpu: 500m memory: 1000Mi ``` ```shell $ kubectl describe service kotlin-app-service Name: kotlin-app-service Namespace: default Labels: Annotations: Selector: app=kotlin-app Type: NodePort IP Family Policy: SingleStack IP Families: IPv4 IP: 10.96.139.200 IPs: 10.96.139.200 Port: 8080/TCP TargetPort: 8080/TCP NodePort: 30001/TCP Endpoints: 192.168.52.67:8080 Session Affinity: None External Traffic Policy: Cluster Events: ```
jacepark12 commented 1 year ago

메모

=> 2번으로 접근하기.

TODO

기타 궁금한점

연관 자료

https://developer.hashicorp.com/terraform/tutorials/kubernetes/helm-provider https://helm.sh/docs/chart_template_guide/ https://opensource.com/article/20/5/helm-charts

junha-ahn commented 1 year ago

인프라 구성

1차 설계

infra

실 환경 구현에 대한 이슈는 ticketing-infra로 이동했습니다.

해당 이슈는 학습에 대한 내용 기록 후 Close하겠습니다.

junha-ahn commented 1 year ago

학습 레퍼런스 추천

참고로 제가 위에서 완성한건 terraform-eks-blueprint라고 하는 라이브러리(?)를 사용해서 완성