EKS 란?

EKS란 Elastic Kubernetes Service의 약자로 AWS의 쿠버네티스 서비스입니다. Master Node가 따로 필요한 기존의 쿠버네티스와는 다르게 

EKS의 마스터 노드 (컨트롤 플레인) 는 AWS에서 관리해 주어 따로 구성 및 관리할 필요가 없다는 장점이 있습니다.

 

자세한 내용은 아래의 문서[1]를 참고 해 주세요.

[1] https://docs.aws.amazon.com/ko_kr/eks/latest/userguide/what-is-eks.html

 

이번 장은 저희 최종 목표인 EKS 클러스터 내에 Pod를 배포하기 위해 앞장에서 다뤘던 Jenkins Pipeline에 추가 구성을 해보도록 하겠습니다.

 

kubectl 설치 및 설정

 

CI/CD로 Pod 배포를 하려면 jenkins 서버에서 해당 EKS 클러스터에 접근 할 수 있도록 kubectl이 설정되어 있어야합니다.

 

일단, jenkins 서버의 jenkins 유저로 접속 해 봅시다.

 

kubectl 설치

 

$ curl -o kubectl https://amazon-eks.s3-us-west-2.amazonaws.com/1.14.6/2019-08-22/bin/linux/amd64/kubectl

  % Total     % Received % Xferd  Average Speed   Time    Time      Time  Current

                                 Dload  Upload    Total   Spent    Left   Speed

100 41.0M  100 41.0M    0      0  8835k      0   0:00:04  0:00:04 --:--:-- 9304k

 

$ chmod +x ./kubectl

 

$ mkdir -p $HOME/bin && cp ./kubectl $HOME/bin/kubectl && export PATH=$HOME/bin:$PATH

 

$ echo 'export PATH=$HOME/bin:$PATH' >> ~/.bashrc

 

$ kubectl version --short --client

Client Version: v1.14.7-eks-1861c5

 

IAM AccessKey/ SecretAccessKey 설정

 

IAM 엔티티가 EKS 클러스터의 RBAC에 제어받기 때문에, Jenkins 서버에 클러스터를 생성한 IAM 계정의

Access Key를 설정 해 줍니다.

 

물론, Jenkins 서버에서만 사용하는 계정을 생성하여 최소한의 권한만 부여하는 것이 Best Practice입니다.

다른 IAM 사용자에 클러스터 액세스 권한을 주기 위해서는 아래 문서[2]를 참고 하시면 됩니다.

 

[2] https://aws.amazon.com/ko/premiumsupport/knowledge-center/amazon-eks-cluster-access/

 

aws configure 커맨드로 설정 가능하며, 파일 저장 위치는 .aws/credentials 입니다.

 

$ aws configure

AWS Access Key ID [****************IWTW]:

AWS Secret Access Key [****************5CIJ]:

Default region name [ap-northeast-2]:

Default output format [None]:

 

$ aws sts get-caller-identity

{

    "UserId": "*******************",

    "Account": "************",

    "Arn": "arn:aws:iam::************:user/sanghyeon.park"

}   

 

aws eks 커맨드로 kubeconfig 파일을 자동으로 생성합니다.

 

$ aws eks update-kubeconfig --region ap-northeast-2 --name srebgk_cluster

Added new context arn:aws:eks:ap-northeast-2:************:cluster/srebgk_cluster to /home/jenkins/.kube/config

 

$ kubectl get pods

NAME                                            READY   STATUS    RESTARTS    AGE

 

여기 까지 잘 따라 오셨다면, kubectl 설정은 끝이납니다.

 


Jenkins Pipeline 추가 구성

 

다시 Jenkins 대시보드로 돌아갑니다.

구성에 해당 Job에 들어가 Pipeline에 아래와 같이 Deployment를 배포하는 Step을 추가 해 줍니다.

 

[Stage: Deploy pod]

 

        stage('Deploy pods'){

            when {

                expression {

                    return env.dockerBuildResult ==~ /(?i)(Y|YES|T|TRUE|ON|RUN)/

                }

            }

            steps{

                script{

                    try{

                        sh """

                        sudo rm -rf deployfiles

                        mkdir deployfiles && cd deployfiles

                        #!/bin/bash

                         cat>monthly_deploy.yaml<

apiVersion: apps/v1

kind: Deployment

metadata:

  name: monthly-deployment

  labels:

    app: monthly

spec:

  replicas: 3

  selector:

    matchLabels:

      app: monthly

  template:

    metadata:

      labels:

        app: monthly

    spec:

      containers:

      - name: monthly-cont

        image: ${ECR_TASK_URI}:ver${env.BUILD_NUMBER}

        ports:

        - containerPort: 5000

EOF"""

                        sh "pwd"

                        sh "/home/jenkins/bin/kubectl apply -f /var/lib/jenkins/workspace/Deploy_SREBGK_MonthlyReport/deployfiles/monthly_deploy.yaml"

                         env.deployPodsResult=true

                    }catch(error){

                        print(error)

                         env.deployPodsResult=false

                         currnetBuild.result='FAILURE'

                    }

                    

                }

            }

            

        }

 

Script 
pipeline { 
2 
agent any 
3 
stages { 
stage('Git Clone') Z} 
20 
stage( ' Docker Build ' 
stage( ' Deploy pods 
55. 
56 
when { 
expression { 
57. 
58 
return env. dockerBui IdResuIt 
59 
60 
61. 
steps{ 
62. 
script{ 
63 
try{ 
64 
65 
sudo rm -rf deployfiles 
66 
mkdir deployfi les && cd deployfiles 
67 
/ bin/bash 
68 
cat>month ly_deploy. yaml EOF 
69 
apiVersion: apps/vl 
kind: Deployment 
70 
71 
metadata : 
72 
name: monthly-deployment 
73 
labels: 
74 
app: monthly 
75 
spec : 
76 
replicas: 3 
77 
selector: 
78 
match Labels : 
app: monthly 
79 
80 
templ ate : 
81 
metadata : 
82 
I abets: 
83 
app: monthly 
84 
spec: 
contai ners : 
85 
86 
- name: monthly-cont 
87 
image: BUILD_NUMBER} 
88 
ports : 
89 
- containerPort: 5ØØØ 
90 
EOF

 

 

 

 

전체 Script

 

pipeline {

    agent any

 

    stages {

        stage('Git Clone') {

            steps {

                script {

                    try{

                        git url: "https://$GIT_URL", branch: "master", credentialsId: "$GIT_CREDENTIALS_ID"

                        env.cloneResult=true

                    }catch(error){

                        print(error)

                        env.cloneResult=false

                         currentBuild.result='FAILURE'

                    }

                }

                

            }

        }

        stage('Docker Build'){

            when{

                expression {

                    return env.cloneResult ==~ /(?i)(Y|YES|T|TRUE|ON|RUN)/

                }

            }

            steps {

                script{

                    try{

                        sh"""

                        #!/bin/bash

                         cat>Dockerfile<

# build stage

FROM ${ECR_BASE_URI}:init as build-stage

COPY . /app

WORKDIR /app

RUN pip install -r requirements.txt

EXPOSE 8000

CMD ["gunicorn",   "--bind", "0.0.0.0:8000",  "flasktest:app", "-w", "2", "--timeout=300", "-k", "gevent"]

EOF"""

                        sh"""

                        aws ecr get-login-password --region ap-northeast-2 | docker login --username AWS --password-stdin ${ECR_URI}

                        docker build -t ${env.JOB_NAME.toLowerCase()} .

                        docker tag ${env.JOB_NAME.toLowerCase()}:latest ${ECR_TASK_URI}:ver${env.BUILD_NUMBER}

                        docker push ${ECR_TASK_URI}:ver${env.BUILD_NUMBER}

                        """

                         env.dockerBuildResult=true

                    }catch(error){

                        print(error)

                         env.dockerBuildResult=false

                         currentBuild.result='FAILURE'

                    }

                }

            }

        }

        stage('Deploy pods'){

            when {

                expression {

                    return env.dockerBuildResult ==~ /(?i)(Y|YES|T|TRUE|ON|RUN)/

                }

            }

            steps{

                script{

                    try{

                        sh """

                        sudo rm -rf deployfiles

                        mkdir deployfiles && cd deployfiles

                        #!/bin/bash

                         cat>monthly_deploy.yaml<

apiVersion: apps/v1

kind: Deployment

metadata:

  name: monthly-deployment

  labels:

    app: monthly

spec:

  replicas: 3

  selector:

    matchLabels:

      app: monthly

  template:

    metadata:

      labels:

        app: monthly

    spec:

      containers:

      - name: monthly-cont

        image: ${ECR_TASK_URI}:ver${env.BUILD_NUMBER}

        ports:

        - containerPort: 5000

EOF"""

                        sh "pwd"

                        sh "/home/jenkins/bin/kubectl apply -f /var/lib/jenkins/workspace/Deploy_SREBGK_MonthlyReport/deployfiles/monthly_deploy.yaml"

                         env.deployPodsResult=true

                    }catch(error){

                        print(error)

                         env.deployPodsResult=false

                         currnetBuild.result='FAILURE'

                    }

                    

                }

            }

            

        }

    }

}

 

최종 결과

 

코드에서 master 브랜치로의 git push를 진행하고 pod가 잘 배포되는 지 확인 해 보자.

 

% git push

Total 0 (delta 0), reused 0 (delta 0), pack-reused 0

To https://git-codecommit.ap-northeast-2.amazonaws.com/v1/repos/Monthly_Report

   8bc8c23..9d1c9c3  master -> master

 

마지막으로 추가한 Deploy pods stg View에 추가된 것을 확인 할 수 있습니다

Stage View 
Average stage times: 
(Average full run time: —1 min 44s) 
Jun 28 
commit 
14:16 
Jun 28 
commit 
00:12 
Git Clone 
2s 
Docker Build 
1 min 39s 
Imin 29s 
Imin 30s 
Deploy pods 
Is 
Is

 

클러스터에 Deployment 까지 확인 할 수있습니다.

 

monthly—deployment 
srebgk—deployment 
READY 
3/3 
3/3 
—l $ kubectl get 
UP-TO-DATE 
1 
3 
3 
deploy 
AVAILABLE 
1 
3 
3 
AGE 
89d 
2m4s 
119d

 

 

이렇게 해서, EKS 환경에서 CI/CD 구축이 완료되었습니다.

개발자 분들은 코드 배포 과정에서 더이상 고통 받지 마시고 개발에만 집중하시는게 어떨까요!

 

감사합니다.