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 {
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에 추가된 것을 확인 할 수 있습니다.
클러스터에 Deployment 까지 확인 할 수있습니다.
이렇게 해서, EKS 환경에서 CI/CD 구축이 완료되었습니다.
개발자 분들은 코드 배포 과정에서 더이상 고통 받지 마시고 개발에만 집중하시는게 어떨까요!
감사합니다.
아티클이 유용했나요?
훌륭합니다!
피드백을 제공해 주셔서 감사합니다.
도움이 되지 못해 죄송합니다!
피드백을 제공해 주셔서 감사합니다.
피드백 전송
소중한 의견을 수렴하여 아티클을 개선하도록 노력하겠습니다.