
애플리케이션 설치
1. localhost에 Amazon EKS 차트 리포지토리를 추가한다.
2. 설치할 애플리케이션을 검색한다.
3. 애플리케이션을 설치한다.
설치된 애플리케이션 업그레이드
1. 업그레이드 실행한다.
2. 필요한 경우 롤백한다.
애플리케이션 게시
1. 새 차트를 생성한다.
2. 샘플 파일을 삭제한다.
3. 새 chart.yaml 파일을 생성한다.
4. deployment 및 service manifest를 위한 디렉터리를 생성한다.
5. manifest를 복사한다.
6. 템플릿을 테스트한다.
7. 차트를 배포한다.

helm repo add 명령어로 추가하여 사용할 수 있다.index.yaml 파일과 차트 패키지(.tgz)를 S3 버킷에 업로드하여 구성하며, 간단한 프라이빗 리포지토리를 만들 때 여전히 유용한 옵션이다.
curl -sSL https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 | bash
helm version
helm plugin install https://github.com/hypnoglow/helm-s3.git
echo "Configuring $S3_BUCKET_NAME as a private Helm repository..."
helm s3 init s3://$S3_BUCKET_NAME
aws s3 ls $S3_BUCKET_NAME 
helm repo add productcatalog s3://$S3_BUCKET_NAME 
helm package 명령은 차트 파일을 버전이 지정된 .tgz 파일로 압축한다. 차트 번호는 차트에 포함된 Chart.yaml 파일에서 가져온다.
차트패키징을 할 경우 아래 경우에 유용하게 사용된다.
helm 리포지토리 목록을 확인해보자. helm repo list
AWS 기반 컨테이너 Github 페이지에서 애플리케이션 Helm 차트를 복제 수행 : git clone https://github.com/aws-containers/eks-app-mesh-polyglot-demo.git
Helm 차트 디렉터리의 구조 및 그 안에 포함된 파일을 확인
cd eks-app-mesh-polyglot-demo/workshop
printf "The chart contains the following directory structure and files...\n \n" && tree helm-chart/

실습에 필요한 모든 이미지는 미리 빌드되어 있다. 공개 ECR에서 가져오는 대신 다음 명령을 실행하여 이미지 경로를 업데이트해야한다.
export AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
export AWS_REGION=$(aws configure get region)
sed -i "s|public.ecr.aws/[^/]*/eks-workshop-demo|${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com/eks-workshop-demo|g" ./helm-chart/values.yaml
애플리케이션 Helm 차트를 패키징 : helm package helm-chart/
애플리케이션 Helm 차트가 생성되었는지 확인 : ls -ltr 
패키징된 애플리케이션 Helm 차트를 S3 Helm 리포지토리로 푸시 : helm s3 push ./productcatalog_workshop-1.0.0.tgz productcatalog
AWS 콘솔 창에서 확인 
이 단계를 완료하면 EKS 클러스터의 Pod에서 실행되는 Frontend, Productcatalog 및 Productdetail 서비스가 포함된 샘플 애플리케이션을 얻게 된다.
S3 버킷에 저장된 Helm 차트의 버전 수를 확인 : helm search repo
리소스를 배포하지 않고 차트 설치를 테스트하기 위해 다음 helm install 명령을 –dry-run 플래그와 함께 입력 : helm install productcatalog s3://$S3_BUCKET_NAME/productcatalog_workshop-1.0.0.tgz --version 1.0.0 --dry-run --debug
Helm 차트를 설치 : helm install productcatalog s3://$S3_BUCKET_NAME/productcatalog_workshop-1.0.0.tgz --version 1.0.0
차트가 배포한 리소스를 나열 : kubectl get pod,svc,deploy -n workshop -o name
차트는 애플리케이션의 frontend, productcatalog, productdetail 구성 요소를 나타내는 3개의 Pod, 3개의 서비스 및 3개의 배포를 설치
프런트엔드 서비스를 셸 변수에 저장하고 터미널에 출력
FRONTEND_URL=http://$(kubectl get svc -n workshop frontend -o jsonpath='{.status.loadBalancer.ingress[0].hostname}')
echo "The URL pointing to the frontend is: $FRONTEND_URL"
출력된 링크 주소를 새 창에서 열면 아래와 같이 나온다. 
values.yaml 파일을 편집한 다음 Helm 차트 애플리케이션을 업그레이드 한다. 그런 다음 변경 사항을 롤백할 때 어떻게 새 Pod가 배포되고 나중에 종료되는지 관찰한다.
value.yaml 파일을 편집 수행한다. 아래 명령은 values.yaml 파일에서 기존 replicaCount 값을 새 값 3으로 변경한다. 이 새로운 Helm 차트가 배포되면 애플리케이션은 추가 Pod 복제본을 생성한다.
cd /home/ssm-user/eks-app-mesh-polyglot-demo/workshop/helm-chart
sed -i "s/replicaCount:.*/replicaCount: 3/g" values.yaml
업데이트된 Helm 값을 사용하여 애플리케이션을 구성 : helm upgrade productcatalog /home/ssm-user/eks-app-mesh-polyglot-demo/workshop/helm-chart/
버전이 업데이트 된것을 확인 가능하다.
현재 동작하는 파드를 확인해본다. : kubectl get pod -n workshop 
각 파드의 수가 3개씩으로 증가한것을 볼 수 있다.
다시 변경 사항을 롤백 하고 이전 차트를 다시 적용한다. : helm rollback productcatalog 1
롤백을 통해서 늘어난 파드가 종료되는 것을 다시 볼 수 있다.

CPU 를 memory로 변경하면 된다.






helm upgrade --install 명령을 통해 EKS 클러스터에 애플리케이션을 배포하거나 업그레이드한다. 이 때 Helm 차트는 "이 컨테이너 이미지를 사용해줘"라고 ECR의 이미지 버전을 참조한다.

CodeCommit 을 검색하여 2개의 레포지토리를 생성한다.aws iam list-ssh-public-keys --user-name gitUser
KEYID=$(aws iam list-ssh-public-keys --user-name gitUser | jq -r '.[] | .[] | .SSHPublicKeyId')
echo $KEYID
cat ~/.ssh/config
cat ~/.ssh/id_rsa
ssh git-codecommit.$AWS_REGION.amazonaws.com
aws iam list-access-keys --user-name ecrUser
코드 검토를 위해 해당 디렉토리로 이동 : cd ~/appcode && ls 
Jenkinsfile을 본인의 계정 ID 및 AWS 리전으로 업데이트 수행
sed -i "s|ACCOUNTID|${ACCOUNT_ID}|g" Jenkinsfile
sed -i "s|REGION|${AWS_REGION}|g" Jenkinsfile
실습 Git 구성을 업데이트 진행
git config --global user.email "eks@example.com"
git config --global user.name "ekscourse"
git config --global init.defaultBranch main
appcode 디렉토리에서 로컬 Git 리포지토리로 변환 수행 : cd ~/appcode/ && git init 
앞서 과제 2번에서 확인한 SSH 키를 사용하여 코드를 AppCodeRepo 리포지토리의 main 브랜치에 푸쉬
git add .
git commit -m "initial commit"
git push --set-upstream ssh://git-codecommit.ap-southeast-2.amazonaws.com/v1/repos/AppCodeRepo main

이번 과제에서는 Jenkins 자동화 서버에 로그인하고 SSH 및 액세스 키를 사용하여 자격 증명을 생성한다. 또한 AppCodeRepo CodeCommit 리포지토리를 모니터링하고 새 코드가 리포지토리에 커밋될 때마다 새 컨테이너 이미지를 빌드하는 파이프라인을 생성한다.
배스천 호스트 세션에서 Jenkins 자격 증명을 검색
aws secretsmanager get-secret-value --secret-id JenkinsPassword --query SecretString --output text | tr -d '{}' | tr -d '"' | sed 's/:/: /g' | awk -F, '{print $1"\n"$2}'
실습 지침에 존재하는 탐색 패널에 있는 JenkinsServer 주소를 Url 창에 입력 후 해당 ID/password를 입력

Jenkins 사용자에게 자격 증명을 할당하기 위해서 Manage Jenkins 페이지의 Security 세션에서 Credentials를 선택한다. 
Credentials 페이지의 Stores scoped to Jenkins 섹션에서 (global) 을 선택 후 2개의 IAM 자격증명을 사용하여 자격 증명을 구성한다.이러한 액세스 관리 접근 방식은 문제 분리 원칙을 따르며 보안 상태를 개선한다. 프로덕션 환경에서는 Jenkinsfile에 적시 사용자 프로비저닝을 구축하여 파이프라인의 보안을 더욱 강화할 수 있다.
gitUser

ecrUser





manifest 디렉토리 생성 : mkdir ~/manifests && cd ~/manifests
매니패스트 파일 작성
cat << EOF > deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: eks-sample-linux-deployment
namespace: eks-sample-app
labels:
app: eks-sample-linux-app
spec:
replicas: 3
selector:
matchLabels:
app: eks-sample-linux-app
template:
metadata:
labels:
app: eks-sample-linux-app
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/arch
operator: In
values:
- amd64
- arm64
containers:
- name: sample
image: ACCOUNTID.dkr.ecr.REGION.amazonaws.com/eks-gitops-demo:1.0
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
name: http
nodeSelector:
kubernetes.io/os: linux
EOF
deployment.yaml 파일을 본인의 계정 ID 및 AWS 리전으로 업데이트
sed -i "s|ACCOUNTID|${ACCOUNT_ID}|g" deployment.yaml
sed -i "s|REGION|${AWS_REGION}|g" deployment.yaml
service.yaml 파일 생성
cat << EOF > service.yaml
apiVersion: v1
kind: Service
metadata:
name: eks-sample-linux-service
namespace: eks-sample-app
labels:
app: eks-sample-linux-app
spec:
type: LoadBalancer
ports:
- port: 80
targetPort: 80
protocol: TCP
selector:
app: eks-sample-linux-app
EOF
manifests 디렉터리를 로컬 Git 리포지토리로 변환 수행 : cd ~/manifests && git init
앞서 생성한 SSH 키를 사용하고 애플리케이션 코드를 ManifestRepo CodeCommit 리포지토리의 기본 브랜치로 Push
git add .
git commit -m "initial commit"
git push --set-upstream ssh://git-codecommit.$AWS_REGION.amazonaws.com/v1/repos/ManifestRepo main



Argo CD를 설치하기 전에 Argo CD 서비스 및 애플리케이션 프로그램 리소스가 상주할 argocd라는 네임스페이스를 생성 : kubectl create namespace argocd
Argo 설치 : kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/951656f08338a0eaf10c0b1d4022056baf4c635c/manifests/install.yaml
API 서버에 액세스하기 위해 argocd-server를 가리키는 로드 밸런서를 배포하여 Argo CD를 외부화 : kubectl patch svc argocd-server -n argocd -p '{"spec": {"type": "LoadBalancer"}}'
패치 후 ArgoCD 서버 서비스의 상태 확인 : kubectl get service argocd-server -n argocd

external-ip 에 있는 DNS 주소를 웹 페이지에 입력 수행

admin 계정의 초기 암호는 자동 생성되어 Argo CD 설치 네임스페이스에 있는 argocd-initial-admin-secret이라는 Secret의 password 필드에 일반 텍스트로 저장되어있다. 관리자의 비밀번호를 찾기 위해 다음 명령을 입력한다.
: kubectl get secret argocd-initial-admin-secret -n argocd -o yaml | grep -i password && printf "\n"

해당 값을 디코딩 해야 한다. : echo <ENCODED_PASSWORD> | base64 --decode && echo
이후 admin/[디코딩 값] 을 입력하면 로그인이 성공한다.

Argo CD Applications 페이지의 왼쪽 탐색 창에서 [Settings] - [Project] 탭에서 새로운 프로젝트로 gitops-project 를 만든다. 설명은 자유롭게 작성
[Settings] - [Repository certificates and known hosts] 탭 선택 후 SSH 호스트를 새로 생성한다. 이 때 cat ~/.ssh/known_hosts 으로 나온 값을 입력한다.
[Settings] - [Repository] 탭에서 레포지토리를 연결한다.

ssh://<KEY_ID>@git-codecommit.<AWS_REGION>.amazonaws.com/v1/repos/ManifestRepo를 입력합니다. <KEY_ID> 자리 표시자 값을 GitUserSSHKeyID 값으로 바꾸고, <AWS_REGION> 자리 표시자 값을 이 지침 왼쪽에 있는 AWSRegion 값으로 바꾼다.
다시 생성한 gitops-project 에 들어가서 소스 레포지토리 경로를 추가한다.

목적지도 추가 해준다.

클러스터 리소스와 네임스페이스 리소스도 허용해주는 경로 설정






kubectl get service -n eks-sample-app 

cd ~/manifests/ && kubectl delete -f . --ignore-not-found=true
cd ~/appcode
cp Jenkinsfile-Final Jenkinsfile
cp Dockerfile-Final Dockerfile
cd ~/appcode/src/
cp v2_index.html index.htmlKEYID=$(aws iam list-ssh-public-keys --user-name gitUser | jq -r '.[] | .[] | .SSHPublicKeyId')
sed -i "s|ACCOUNTID|${ACCOUNT_ID}|g" Jenkinsfile
sed -i "s|REGION|${AWS_REGION}|g" Jenkinsfile
sed -i "s|KEYID|${KEYID}|g" Jenkinsfilecd ~/appcode/
git commit -a -m "Updated application to version 2.0"
git push



kubernetes는 아래 측면에서 VM이나 물리적 호스트와 동일한 방식으로 Pod를 처리한다.

Pod는 kuberntes의 기본 빌딩 블록이므로 kubernetes는 네트워크의 IP 주소를 각 애플리케이션 컨테이너가 아니라 Pod에 적용한다.
Pod의 컨테이너는 네트워크 네임스페이스를 공유하며 localhosts(127.0.0.1)를 사용하여 서로 통신 할 수 있다. 쉽게 말해, Pod 안에 있는 여러 컨테이너들은 마치 하나의 컴퓨터(또는 VM) 안에서 실행되는 여러 프로세스처럼 서로를 인식하고 통신할 수 있다.



