Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
junha-ahn opened this issue Jul 1, 2023 · 9 comments
Closed

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

junha-ahn opened this issue Jul 1, 2023 · 9 comments
Assignees
Labels
enhancement New feature or request

Comments

@junha-ahn
Copy link
Member

junha-ahn commented Jul 1, 2023

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번 작업 후 curl x.x.x.x:port (public IP) 를 통해 "Hello World"가 출력되어야 합니다.
  • 3번 작업 후 해당 레퍼지토리의 push 이벤트마다 새롭게 이미지가 배포되어야 합니다.

학습 시나리오2

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

Finally

image

  • image from
  • but, we dont use jenkins, we just use git actions for build and push image

Tech Stack

  • terraform (AWS)
  • git actions (to push image)
  • kubernetes
  • helm
  • EKS
  • argoCD
@junha-ahn junha-ahn added the enhancement New feature or request label Jul 1, 2023
@junha-ahn junha-ahn moved this to Todo in Kanban backend Jul 1, 2023
@junha-ahn junha-ahn changed the title CD: 가장 간단한 배포를 위한 환경 세팅 CD: 배포를 위한 환경 세팅 Jul 1, 2023
@junha-ahn junha-ahn self-assigned this Jul 7, 2023
@junha-ahn
Copy link
Member Author

junha-ahn commented Jul 7, 2023

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

@junha-ahn
Copy link
Member Author

junha-ahn commented Jul 8, 2023

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

완료

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

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

  • 본인의 ubuntu 버전과 맞아야 설치할 것

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

  • 스크립트를 만들어서 자동화를 한다면?
  • terrafrom 에서 해당 스크립트를 먼저 실행하게 하면 모든 worker EC2가 쉽게쉽게 마스터와의 연결을 끝낸다.

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

  • 그리고 연결 과정은 스크립트를 사용한다

3. 언제 EKS로 넘어갈까?

위 설명된 불편함 관련

  • k8s를 직접 세팅해야함

scale up 관련

  • terraform autoscaling group은 ELB 등을 트리거로 scale up 한다
  • 만약 내가 가진 kube pod의 특정 트리거로 scale up을 하고 싶다면?
  • 이때 EKS를 사용하는게 맞을까?

plugin 관련

  • 예를들어 APM 을 k8s 와 연결하고 싶다면?
  • 어디서 설정해야할까? (당장은 모르지만) 아마 eks를 사용할때보다, 설정과 관리 포인트가 증가할 것 같다.

ETC. gitops의 사용 포인트는?

@jacepark12
Copy link
Collaborator

EKS의 단점 : 좀 비싸다

@jacepark12 jacepark12 moved this from Todo to In Progress in Kanban backend Jul 8, 2023
@junha-ahn
Copy link
Member Author

junha-ahn commented Jul 9, 2023

학습 시나리오 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는 해당 패키지를 신뢰할 수 없다고 판단

해결 방법

공개키를 등록한다

sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys <KEYID>
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

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

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에 시간이 엄청 걸리나?...
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   <none>          21s    v1.27.3

Node NotReady

접기/펼치기
$ 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   <none>          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 

kubernetes/kubeadm#2222

$ 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로 안보내지??
$ 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 복사 구성

어떻게 하면 worker node가 자동으로 master에 연결되도록 할 수 있을까?

  1. terraform EC2 생성간 의존성 부여

    • 무조건 master가 생성되어야 worker가 생성 될 수 있다.
    • terraform depends on
  2. master 에서 생성된 kube join token을 worker에 전달할 수 있는 방법 ? - 이 token을 통해 worker에서 master에 join이 가능해진다

    • IP는 terraform output IP & depens_on 조합으로 가능
    • MASTER EC2 => AWS secret 관리 툴 => WORKER EC2??...
  3. master는 고정 token 을 .env 등으로 관리해서 worker만 증가시키기

  4. k8s worker node join 다른 방법 있는지 조사하기

@junha-ahn junha-ahn changed the title CD: 배포를 위한 환경 세팅 CD: 배포를 위한 환경 세팅 (학습) Jul 16, 2023
@junha-ahn junha-ahn changed the title CD: 배포를 위한 환경 세팅 (학습) CD: 배포를 위한 환경 세팅 Jul 16, 2023
@junha-ahn
Copy link
Member Author

junha-ahn commented Jul 23, 2023

학습 시나리오 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

지금 해야하는 것

  • terraform-aws-eks 공식 모듈을 사용해서 완성하기
  • Service: Loadbalancer, Ingeress Controller 차이와 ALB, NLB 차이 등

Helm으로 Prod/QA 환경 구축

@hihahayoung
Copy link
Collaborator

hihahayoung commented Jul 25, 2023

학습 시나리오 1

EndPoint: None 에러

접기/펼치기
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    <none>          47m   v1.27.4   10.0.1.193    <none>        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     <none>        Ubuntu 22.04.2 LTS   5.19.0-1025-aws   containerd://1.6.21

pod + service 조합

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
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
$ kubectl describe service kotlin-app-service
Name:                     kotlin-app-service
Namespace:                default
Labels:                   <none>
Annotations:              <none>
Selector:                 app=kotlin-app
Type:                     NodePort
IP Family Policy:         SingleStack
IP Families:              IPv4
IP:                       10.99.133.216
IPs:                      10.99.133.216
Port:                     <unset>  8080/TCP
TargetPort:               8080/TCP
NodePort:                 <unset>  30001/TCP
Endpoints:                <none>
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>

deployment + service 조합

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
$ kubectl describe service kotlin-app-service
Name:                     kotlin-app-service
Namespace:                default
Labels:                   <none>
Annotations:              <none>
Selector:                 app=kotlin-app
Type:                     NodePort
IP Family Policy:         SingleStack
IP Families:              IPv4
IP:                       10.96.139.200
IPs:                      10.96.139.200
Port:                     <unset>  8080/TCP
TargetPort:               8080/TCP
NodePort:                 <unset>  30001/TCP
Endpoints:                192.168.52.67:8080
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>

@jacepark12
Copy link
Collaborator

메모

  • Terraform으로 EKS deploy이후 Kubernetes 클러스터에 pod을 띄우는 방법
  1. kubectl로 클러스터에 연결하여 사전에 정의한 yaml 파일을 직접 apply 시키기
  2. 띄울 pod을 helm 차트로 만들어 놓고 terraform 파일로 EKS 정의시 helm 차트를 자동으로 배포하도록 정의하기

=> 2번으로 접근하기.

TODO

  • Terraform으로 EKS 띄우기
  • nginx + kotlin application 앱을 yaml 파일로 정의해서 띄우기
  • helm 차트로 만들기
  • Terraform으로 EKS + helm 차트 연결해서 EKS 띄우면 자동으로 helm 차트 받아와서 pod 띄우도록하기

기타 궁금한점

  • ECR, Docker hub와 같은 Docker container repository에 새로운 버전의 이미지가 푸시되면 어떻게 바로 EKS에 반영할 수 있을까

연관 자료

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
Copy link
Member Author

junha-ahn commented Jul 31, 2023

인프라 구성

1차 설계

infra

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

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

@junha-ahn junha-ahn changed the title CD: 배포를 위한 환경 세팅 CD: 배포를 위한 환경 세팅 [학습] Aug 1, 2023
@junha-ahn junha-ahn moved this to In Progress in Kanban Infra Aug 1, 2023
@junha-ahn
Copy link
Member Author

junha-ahn commented Aug 3, 2023

학습 레퍼런스 추천

  • terraform-aws-eks 공식 모듈의 eks_managed_node_group 예제
  • terraform-aws 공식 모듈을 사용했고, ArgoCD 까지 setup한 예제 (리드미에 유튜브 영상 존재)

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

  • 위 terraform-aws-eks 모듈을 한번 더 래핑해서 쉽게 사용할 수 있게...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
Status: Done
Development

No branches or pull requests

3 participants