1 . Deploy EKS
eksctl create cluster --name myeks --region ap-northeast-2 --version 1.24 --instance-types t3.medium
eksctl utils associate-iam-oidc-provider --cluster myeks --approve
eksctl create iamserviceaccount \
--name ebs-csi-controller-sa \
--namespace kube-system \
--cluster myeks \
--attach-policy-arn arn:aws:iam::aws:policy/service-role/AmazonEBSCSIDriverPolicy \
--approve \
--role-only \
--role-name AmazonEKS_EBS_CSI_DriverRole
aws sts get-caller-identity --output text
# service-account를 복사한다
# 숫자로만 이루어져있다
eksctl create addon --name aws-ebs-csi-driver --cluster myeks --service-account-role-arn arn:aws:iam::<ACCOUNT_ID>:role/AmazonEKS_EBS_CSI_DriverRole --force
# 복사한 account_ID를 붙여넣기
2 . Deploy Jenkins on EKS with Helm
kubectl create namespace jenkins
helm repo add jenkinsci https://charts.jenkins.io
helm repo update
vi jenkins-values.yaml
controller:
tag: "lts-jdk11"
serviceType: LoadBalancer
installPlugins:
- kubernetes
- workflow-aggregator
- git
- configuration-as-code
- pipeline-stage-view
adminPassword: "P@ssw0rd"
persistence:
storageClass: "gp2"
# YAML파일 작성
helm install jenkins jenkinsci/jenkins -n jenkins -f jenkins-values.yaml
# EKS에 Jenkins 생성
브라우저에 로드밸런서주소:8080으로 Jenkins접속
id : Admin
password : P@ssw0rd
1 . jenkinsfile 작성
pipeline{
agent{
kubernetes{
yaml '''
apiVersion: v1
kind: Pod
spec:
containers:
- name: maven
image: maven:3-openjdk-8
command: ['sleep']
args: ['infinity']
'''
}
}
triggers {
pollSCM '* * * * *'
}
stages{
stage('checkout'){
steps{
container('maven'){
git branch: 'main', url:'https://github.com/suhwan12/abc.git'
}
}
}
stage('maven build project'){
steps{
container('maven'){
sh 'mvn clean package -DskipTests=true'
}
}
}
stage('test maven project'){
steps{
container('maven'){
sh 'mvn test'
}
}
}
}
}
1 . kaniko를 포함한 Jenkinsfile작성
kubectl create secret docker-registry regcred -n jenkins --docker-username=suhwan11 --docker-password=< 토큰 > --docker-server=https://index.docker.io/v1/
pipeline{
agent{
kubernetes{
yaml '''
apiVersion: v1
kind: Pod
spec:
containers:
- name: maven
image: maven:3-openjdk-8
command: ['sleep']
args: ['infinity']
- name: kaniko # kaniko파드 생성
image: gcr.io/kaniko-project/executor:debug # latest보다 debug가 더 좋다
command: ['sleep']
args: ['infinity']
volumeMounts: # 시클릿 볼륨 마운트
- name: registry-credentials
mountPath: /kaniko/.docker
volumes: # 시크릿을 볼륨화
- name: registry-credentials
secret:
secretName: regcred # 생성한 시크릿
items:
- key: .dockerconfigjson
path: config.json
'''
}
}
triggers {
pollSCM '* * * * *'
}
stages{
stage('checkout'){
steps{
container('maven'){
git branch: 'main', url:'https://github.com/suhwan12/abc.git'
}
}
}
stage('maven build project'){
steps{
container('maven'){
sh 'mvn clean package -DskipTests=true'
}
}
}
stage('test maven project'){
steps{
container('maven'){
sh 'mvn test'
}
}
}
stage('Build & Tag docker image'){ # kaniko를 이용한 dockerfile 빌드
steps{
container('kaniko'){ # kaniko 컨테이너(노드) 일시적으로 생성
sh "executor --dockerfile=Dockerfile \ # dockerfile 지정
--context=dir://${env.WORKSPACE} \ # dockerfile이 존재하는 directory경로 지정
--destination=suhwan11/hello-world:latest \
--destination=suhwan11/hello-world:${env.BUILD_NUMBER}"
# dockerhub의 registry에 이미지 push
}
}
}
}
}
Argo CD설치
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
kubectl patch svc argocd-server -n argocd -p '{"spec": {"type": "LoadBalancer"}}'
kubectl get svc -n argocd
# 로드밸런서 외부용 IP 확인
브라우저에 외부용IP입력 후 접속
ID : admin
Password : 시크릿 오브젝트에 저장되어 있다
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d; echo
# 패스워드 찾아내기
새로운 git repo , workdir 생성 및 remote로 연결
1 . deployment
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: default
name: hello-world
spec:
replicas: 2
selector:
matchLabels:
app: hello-world
template:
metadata:
labels:
app: hello-world
spec:
containers:
- name: hello-world
image: suhwan11/hello-world:21
ports:
- containerPort: 8080
2 . service
apiVersion: v1
kind: Service
metadata:
namespace: default
name: hello-world
spec:
type: LoadBalancer
selector:
app: hello-world
ports:
- protocol: TCP
port: 80
targetPort: 8080
ArgoCD접속 및 새로운 APP생성
stage('Update Kubernetes Manifests'){
steps{
container('maven'){
git branch: 'main', url:'https://github.com/suhwan12/hello-kube.git'
sh 'sed -i "s/image:.*/image: suhwan11\\/hello-world:${BUILD_NUMBER}/g" deployment.yaml'
sh 'git add deployment.yaml'
sh 'git config --global user.name suhwan12'
sh 'git config --global user.email xman0120@naver.com'
sh 'git commit -m "Jenkins Build Number - ${BUILD_NUMBER}"'
withCredentials([gitUsernamePassword(credentialsId: 'github-credential', gitToolName: 'Default')]) {
sh 'git push origin main'
}
}
}
}
최종적으로 빌드를 하게 되면 dockerhub에 이미지가 생성된다
이후 deployment.yaml의 컨테이너의 이미지를 결정하는 부분을 위의 이미지로 변경한뒤 commit과 push가 된다
현재 deployment.yaml을 통해 파드를 배포한 Argo CD에서 자신에게 등록된 git을 계속 monitoring하다가 deployment.yaml이 commit되어 push된 것을 인지하고 새로운 레플리카셋을 만들어 변경된 이미지가 적용된 컨테이너가 존재하는 파드를 롤링 업데이트로 배포한다
deployment로 배포된 파드와 해당 파드를 외부로 노출시키는 로드밸런서 타입의 서비스가 존재한다. 브라우저에 로드밸런서의 외부용ip/hello-world를 입력하면 원하는 웹페이지가 뜬다
만일 git에서 버전을 바꾸는 등의 새로운 작업 후 commit과 push가 되면 변경사항이 적용된 새로운 이미지가 생성되는 작업부터 위의 과정이 자동으로 수행된다.
= Pipeline , Automation
정리
이 모든 과정이 파이프라이닝을 통해 자동화 시킬 수 있다 .