간단한 암/복호화
암복호화는 평문을 제 3자가 해독할 수 없는 문장인 암호문으로 변환하여 전송하고,
수신측에서 평문으로 암호문으로부터 평문을 복원하는 과정
아래와 같은 과정에서 사용하는 알고리즘을 암호 알고리즘이라고 하며, 암호화하고 복호화하는데 핵심이 되는 것이 KEY라고 한다.
암호화 과정에서 필요한 키를 쌍방이 확보할 수 있는 방법에서 공유 비밀 키 방식 (shared secret key)과 공개키 (public key)가 있다.
- 공유 비밀키 암호화 방식 (shared secret key) : DES, 3DES, RC4/5
- 공개키 암호화 방식 (Public Key) : RSA
- 키 분배 방식 : 'DH방식, RSA공개키, 키 분배 센터(KDC)'를 이용한 공유 비밀키 분배 방법

실습 환경 배포
EKS : 1EA
Bastion : 2EA
## CloudFormation 스크립트 다운로드
curl -O https://s3.ap-northeast-2.amazonaws.com/cloudformation.cloudneta.net/K8S/myeks-6week.yaml
## 변수 지정
CLUSTER_NAME=myeks
SSHKEYNAME=<SSH 키 페이 이름>
MYACCESSKEY=<IAM Uesr 액세스 키>
MYSECRETKEY=<IAM Uesr 시크릿 키>
## CloudFormation 배포
aws cloudformation deploy --template-file myeks-6week.yaml --stack-name $CLUSTER_NAME --parameter-overrides KeyName=$SSHKEYNAME SgIngressSshCidr=$(curl -s https://ipinfo.io/ip)32 MyIamUserAccessKeyID=$MYACCESSKEY MyIamUserScretAccessKey=$MYSECRETKEY ClusterBaseName=$CLUSTER_NAME --region ap-northeast-2
## bastion 서버 IP 확인
aws cloudformation describe-stack --stack-name myeks --query 'Stacks[*].Outputs[0].OutputValue' --output text
### 로컬 PC에서 EKS 접속 설정
# Cluster 조회
eksctl get clusters
# kubeconfig 업데이트
aws sts get-caller-identity --query Arn
aws eks update-kubeconfig --name myeks --user-alis <위 명령어 출력 값 입력>
생성 리소스 확인
## 노드 IP 및 SSH 접속 테스트
export N1=$(aws ec2 describe-instances --filters "Name=tag:Name,Values=myeks-ng1-Node" "Name=availability-zone,Values=ap-northeast-2a" --query 'Reservations[*].Instances[*].PublicIpAddress' --output text)
export N2=$(aws ec2 describe-instances --filters "Name=tag:Name,Values=myeks-ng1-Node" "Name=availability-zone,Values=ap-northeast-2b" --query 'Reservations[*].Instances[*].PublicIpAddress' --output text)
export N3=$(aws ec2 describe-instances --filters "Name=tag:Name,Values=myeks-ng1-Node" "Name=availability-zone,Values=ap-northeast-2c" --query 'Reservations[*].Instances[*].PublicIpAddress' --output text)
echo $N1, $N2, $N3
# *remoteAccess* 포함된 보안그룹 ID
aws ec2 describe-security-groups --filters "Name=group-name,Values=*remoteAccess*" | jq
export MNSGID=$(aws ec2 describe-security-groups --filters "Name=group-name,Values=*remoteAccess*" --query 'SecurityGroups[*].GroupId' --output text)
# 해당 보안그룹 inbound 에 자신의 집 공인 IP 룰 추가
aws ec2 authorize-security-group-ingress --group-id $MNSGID --protocol '-1' --cidr $(curl -s ipinfo.io/ip)/32
# 해당 보안그룹 inbound 에 운영서버 내부 IP 룰 추가
aws ec2 authorize-security-group-ingress --group-id $MNSGID --protocol '-1' --cidr 172.20.1.100/32
aws ec2 authorize-security-group-ingress --group-id $MNSGID --protocol '-1' --cidr 172.20.1.200/32
# 워커 노드 SSH 접속
for i in $N1 $N2 $N3; do echo ">> node $i <<"; ssh -o StrictHostKeyChecking=no ec2-user@$i hostname; echo; done



운영 EC2 접속
## default 네임 스페이스 전환
k ns default
## 환경 변수 정보 확인
export | egrep 'ACCOUNT|AWS_|CLUSTER|KUBERNETS|VPC|Subnet' | egrep -v 'KEY'
## 인스턴스 정보 확인
aws ec2 describe-instances --query "Reservations[*].Instances[*].{InstanceID:InstanceId, PublicIPAdd:PublicIpAddress, PrivateIPAdd:PrivateIpAddress, InstanceName:Tags[?Key=='Name']|[0].Value, Status:State.Name}" --filters Name=instance-state-name,Values=running --output table
## 노드 IP 확인 및 PrivateIP 변수 지정
aws ec2 describe-instances --query "Reservations[*].Instances[*].{PublicIPAdd:PublicIpAddress,PrivateIPAdd:PrivateIpAddress,InstanceName:Tags[?Key=='Name']|[0].Value,Status:State.Name}" --filters Name=instance-state-name,Values=running --output table
N1=$(kubectl get node --label-columns=topology.kubernetes.io/zone --selector=topology.kubernetes.io/zone=ap-northeast-2a -o jsonpath={.items[0].status.addresses[0].address})
N2=$(kubectl get node --label-columns=topology.kubernetes.io/zone --selector=topology.kubernetes.io/zone=ap-northeast-2b -o jsonpath={.items[0].status.addresses[0].address})
N3=$(kubectl get node --label-columns=topology.kubernetes.io/zone --selector=topology.kubernetes.io/zone=ap-northeast-2c -o jsonpath={.items[0].status.addresses[0].address})
echo "export N1=$N1" >> /etc/profile
echo "export N2=$N2" >> /etc/profile
echo "export N3=$N3" >> /etc/profile
echo $N1, $N2, $N3
## 노드 IP 로 ping 테스트
for i in $N1 $N2 $N3; do echo ">> node $i <<"; ping -c 1 $i ; echo; done

- Kube-Ops-View, AWS LoadBalancer Controller, ExternalDNS gp3 Storageclass 설치
[설치 방법은 이전 게시글 참고]



K8S(API 접근) 인증/인가
- API 서버 사용 : kubectl(config, 다수 클러스터 관리 가능), 서비스 어카운트, https(x.509 Client Certs)
- API 서버 접근 과정 : 인증 -> 인가 -> Admission Control(API 요청 검증, 필요 시 변형 - 예) ResouceQuota, LimitRange)

인증
- X.509 Client Certs : kubeconfig 에 CA crt(발급 기관 인증서), Client crt(클라이언트 인증서), Client key(클라이언트 개인키) 를 통해 인증
- kubectl : 여러 클러스터(kubeconfig)를 관리 가능 - contexts 에 클러스터와 유저 및 인증서/키
- Service Account : 기본 어카운트 (default) - 시크릿(CA crt와 token)

인가
- 인가 방식 : RBAC(role, rolebinding), ABAC, Webook, Node Authorization
- RBAC : 역할 기반의 권한 관리, 사용자와 역할을 별개로 선언 후 두가지를 조합(binding)해서 사용자에게 권한을 부여하여 kubectl or API로 관리 가능
- Namespace / cluster - role/clusterrole, rolebinding/clusterrolebinding, service account
- role(롤) - (rolebinding 롤 바인딩) - Service Account(서비스 어카운트) : 롤 바인딩은 롤과 서비스 어카운트를 연결
- Role(네임스페이스 내 자원의 권한) vs ClusterRole(클러스터 수준의 자원의 권한)

.kube/config 파일 내용
- clusters : kubectl 이 사용할 쿠버네티스 API 서버의 접속 정보 목록. 원격의 쿠버네티스 API 서버의 주소를 추가해 사용 가능
- users : 쿠버네티스의 API 서버에 접속하기 위한 사용자 인증 정보 목록 (서비스 어카운트의 토큰, 혹은 인증서의 데이터 등)
- contexts : cluster 항목과 users 항목에 정의된 값을 조합해 최종적으로 사용할 쿠버네티스 클러스터의 정보(컨텍스트)를 설정
- 예를 들어 clusters 항목에 클러스터 A,B가 정의되어 있고, users 항목에 사용자 a,b가 정의돼 있다면 cluster A + user a를 조합해 'cluster A에 user a로 인증해 쿠버네티스를 사용한다' 라는 새로운 컨텍스트를 정의할 수 있다.
- kubectl을 사용하려면 여러 개의 컨텍스트 중 하나를 선택
apiVersion: v1
clusters:
- cluster:
┆ certificate-authority-data: Lap-northeast-2.eks.amazonaws.com
name: arn:aws:eks:ap-northeast-2::cluster/myeks
contexts:
- context:
┆ cluster: arn:aws:eks:ap-northeast-2::cluster/myeks
┆ namespace: monitoring
┆ user: hoontest1
name: hoontest1
current-context: hoontest1
kind: Config
preferences: {}
users:
- name: hoontest1
user:
┆ exec:
┆ ┆ apiVersion: client.authentication.k8s.io/v1beta1
┆ ┆ args:
┆ ┆ - --region
┆ ┆ - ap-northeast-2
┆ ┆ - eks
┆ ┆ - get-token
┆ ┆ - --cluster-name
실습 환경
- 쿠버네티스에 사용자를 위한 서비스 어카운트 (Service Account, SA)를 생성 : dev-k8s, infra-k8s
- 사용자는 각기 다른 권한(Role, 인가)을 갖음 : dev-k8s(dev-team 네임스페이스 내 모든 동작), infra-k8s(dev-team 네임스페이스 내 모든 동작)
- 각각 별도의 kubectl 파드를 생성하고, 해당 파드에 SA를 지정하여 권한에 대한 테스트를 진행

네임스페이스와 서비스 어카운트 생성 후 확인
- 파드 기동 시 서비스 아카운트 한 개가 할당되며, 서비스 어카운트 기반 인증/인가를 하며, 미지정 시 기본 서비스 어카운트 할당
- 서비스 어카운트에 자동 생성된 시크릿에 저장된 토큰으로 쿠버네티스 API에 대한 인증 정보로 사용 할 수 있다. <- 1.23 이전 대상
## namespcae 생성 및 확인
k create ns dev-team
k create ns infra-team
## namespace 확인
k get ns
## namespace에 서브어카운트 생성
k create sa dev-k8s -n dev-team
k create sa infra-k8s -n infra-team
## SA 정보 확인
k get sa -n dev-team
k get sa -n infra-team
k get sa -n dev-team -o yaml
k get sa -n infra-team -o yaml
각 네임스페이스에 파드 생성
cat <<EOF | kubectl create -f -
apiVersion: v1
kind: Pod
metadata:
name: dev-kubectl
namespcae: dev-team
spec:
serviceAccountName: dev-k8s
containers:
- name: kubectl-pod
image: bitnami/kubectl:1.31.4
command: ["tail"]
args: ["-f", "/dev/null"]
terminationGracePeriodSeconds: 0
EOF
cat <<EOF | kubectl create -f -
apiVersion: v1
kind: Pod
metadata:
name: infra-kubectl
namespace: infra-team
spec:
serviceAccountName: infra-k8s
containers:
- name: kubectl-pod
image: bitnami/kubectl:1.31.4
command: ["tail"]
args: ["-f", "/dev/null"]
terminationGracePeriodSeconds: 0
EOF
## 생성 확인
k get pod -A
k get pod dev-kubectl -n dev-team -o yaml
k get pod infra-kubectl -n infra-team -o yaml
## 파드에 기본 적용되는 서비스 어카운트 정보 확인
k exec -it dev-kubectl -n dev-team -- ls /run/secrets/kubernetes.io/serviceaccount
k exec -it dev-kubectl -n dev-team -- cat /run/secrets/kubernetes.io/serviceaccount/token
k exec -it dev-kubectl -n dev-team -- cat /run/secrets/kubernetes.io/serviceaccount/namespace
k exec -it dev-kubectl -n dev-team -- cat /run/secrets/kubernetes.io/serviceaccount/ca.crt
## 각 파드로 shell 접속 후 정보 확인
alias k1='kubectl exec -it dev-kubectl -n dev-team -- kubectl'
alias k2='kubectl exec -it infra-kubectl -n infra-team -- kubectl'
## 권한 테스트
k1 get pods
k1 run nginx --image nginx:1.20-alpine
k1 get pods -n kube-system
k2 get pods
k2 run nginx --image nginx:1.20-alpine
k2 get pod -n kube-system
## k auth can-i를 통해 kubectl 실행 사용자가 특정 권한을 가지고 있는지 확인 가능
k1 auth can-i get pods

각각 네임스페이스에 Role 생성 후 서비스 어카운트와 바인딩
- Role: apiGroups와 resources로 지정된 리소스에 대해 verbs 권한을 인가
- 실행 가능한 조작(verbs) : *(모두 처리), create(생성), delete(삭제), get(조회), list(목록조회), patch(일부업데이트), update(업데이트), watch(변경감시)



## 클러스터에서 지원하는 api 리소스 출력
k api-resources
## 상세 정보 출력
k api-resources -o wide
## 별도 리소스 조회
k api-resource --api-group=""
k api-resource --api-group="apps"
k api-resources --api-group=metrics.k8s.io
k api-resources --api-group=admissionregistration.k8s.io
k api-resources --api-group=rbac.authorization.k8s.io
k api-resources --api-group=apiextensions.k8s.io
## 각각 네임스페이스내의 모든 권한에 대한 룰 생성
cat <<EOF | kubectl create -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: role
metadata:
name: role-dev-team
namespace: dev-team
rules:
- apiGroups: ["*"]
resources: ["*"]
verbs: ["*"]
EOF
cat <<EOF | kubectl create -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: role-infra-team
namespace: infra-team
rules:
- apiGroups: ["*"]
resources: ["*"]
verbs: ["*"]
EOF
## 생성 룰 확인
k get roles -n dev-team
k get roles -n infra-team
k get roles -n dev-team -o yaml
k get roles -n infra-team -o yaml
k describe roles role-dev-team -n dev-team
## 롤 바인딩 생성
cat <<EOF | kubectl create -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: roleB-dev-team
namespace: dev-team
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: role-dev-team
subjects:
- kind: ServiceAccount
name: dev-k8s
namespace: dev-team
EOF
cat <<EOF | kubectl create -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: roleB-infra-team
namespace: infra-team
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: role-infra:team
subjects:
- kind: ServiceAccount
name: infra-k8s
namespace: infra-team
EOF
## 롤 바인딩 확인
k get rolebindings -n dev-team
k get rolebindings -n infra-team
k get rolebindings -n dev-team -o yaml
k get rolebindings -n infra-team -o yaml
k describe rolebindings roleB-dev-team -n dev-team


- Kubernetes RBAC에서 Role과 RoleBinding을 이용한 권한 할당 방식

- Kubernetes RBAC에서 User, Group, ServiceAccount

- Role과 ClusterRole의 차이점

- Kubernetes에서 자주 사용되는 ClusterRole의 권한 수준(view, edit, admin, cluster-admin)

서비스 어카운트를 지정하여 생성한 파드에서 다시 권한 테스트
## 각 파드로 shell 접속하여 정보 확인
alias k1='kubectl exec -it dev-kubectl -n dev-team -- kubectl'
alias k2='kubectl exec -it infra-kubectl -n infra-team -- kubectl'
## 권한 테스트
k1 get pods
k1 run nginx --image nginx:1.20-alpine
k1 get pods
k1 delete pods nginx
k1 get pods -n kube-system
k1 get pods -n kube-system -v=6
k1 get nodes
k1 get nodes -v=6
k2 get pods
k2 run nginx --image nginx:1.20-alpine
k2 get pods
k2 delete pods nginx
k2 get pods -n kube-system
k2 get nodes
## kubectl 사용자가 특정 권한을 갖고 있는지 확인
k1 auth can-i get pods
yes

EKS 인증/인가
사용자 / 어플리케이션 -> k8s 사용 시 => 인증은 AWS IAM, 인가는 k8s rbac



확장 프로그램 설치
- access-matrix: Kubernetes RBAC(Role-Based Access Control) 권한을 매트릭스로 시각화하여 분석하는 도구.
- rbac-tool: Kubernetes RBAC 정책을 검사하고, 권한 분석 및 정책 최적화를 돕는 CLI 기반 유틸리티.
- rolesum: Kubernetes 클러스터 내 사용자, 그룹, 서비스 계정의 역할(Role)과 권한을 요약하여 보여주는 도구.
- whoami: 현재 사용자의 Kubernetes RBAC 권한을 조회하여 어떤 리소스에 접근할 수 있는지 확인하는 플러그인.
## Plugin install
k krew install access-matrix rbac-tool rolesum whoami
## 인증 확인
k whoami
## access-matrix로 권한 확인
k access-matrix -h
k access-matrix
k access-matrix --namespace default
## rbac lookup
k rbac-tool -h
k rbac-tool lookup
k rbac-tool lookup system:masters
## rbac policy rules
k rbac-tool policy-rules
k rbac-tool policy-rules -e '^system:.*'
k rbac-tool policy-rules -e '^system:authenticated'
k rbac-tool show
k rbac-tool whoami
## rolesum
k rolesum -h
k rolesum aws-node -n kube-system # sa
k rolesum -k User system:kube-proxy # user
k rolesum -k Group system:masters # group
k rolesum -k Group system:nodes
k rolesum -k Group system:authenticated
## rbac-view (visualize rbac permissions
k rbac-view
open "https://$(curl -s ipinfo.io/ip):8080"



약어 | Verbs | 설명 |
G | Get | 리소스를 조회 (get) |
L | List | 리소스를 목록으로 나열 (List) |
W | Watch | 리소스를 감시 (watch) |
C | Create | 새 리소스를 생성 (create) |
U | Update | 기존 리소스를 수정 (update) |
P | Patch | 리소스의 일부를 패치 (patch) |
D | Delete | 리소스를 삭제 (Delete) |
DC | Delete Collection | 리소스의 컬렉션(여러 개)을 삭제 (deletecollection) |
EKS 인증/인가 확인

- 핵심 : 인증은 AWS IAM, 인가는 k8s rbac에서 처리

1. kubectl 명령 -> aws eks get-token -> STS에 토큰 요청 => 응답값 디코드(Pre-signed URL이며 getcallerindetity..)
- STS Security Token Service : AWS 리소스에 대한 액세스를 제어할 수 있는 임시 보안 자격 증명(STS)을 생성하여 신뢰받는 사용자에게 제공 할 수 있음
- AWS CLI 1.16.156 이상에서는 별도 aws-iam-authenticator 설치 없이 aws eks get-token으로 사용 가능
## sts caller id의 ARN 확인
aws sts get-caller-identity --query Arn
"arn:aws:iam::<Account ID>>:user/<인증한 유저>"
## kubeconfig 정보 확인
cat ~/.kube/config
user:
exec:
apiVersion: client.authentication.k8s.io/v1beta1
args:
- eks
- get-token
- --output
- json
- --cluster-name
- myeks
- --region
- ap-northeast-2
command: aws
env:
- name: AWS_STS_REGIONAL_ENDPOINTS
## 임시 보안 자격 증명을 요청 : expirationTimestamp 시간 경과 시 토큰 재발급
aws eks get-token --cluster-name $CLUSTER_NAME | jq
aws eks get-token --cluster-name $CLUSTER_NAME | jq -r '.status.token'
aws eks get-token --cluster-name $CLUSTER_NAME --debug | jq

2. kubectl의 Client-Go 라이브러리는 Pre-Signed URL을 bearer token으로 EKS API Cluster Endpoint 로 요청

3. EKS API는 Token Review를 Webhook token authenticator에 요청
AWS IAM 해당 호출 인증 오나료 후 User/role에 대한 ARN 반환
## tokenreviews api 리소스 확인
k api-resources | grep authentication
##
k explain tokenreviews
4. ConfigMap 방식
- 해당 IAM User/Role 확인이 되면 k8s aws-auth configmap에서 mapping 정보를 확인하게 됩니다.
- aws-auth 컨피그맵에 'IAM 사용자, 역할 arm, k8s 오브젝트'로 권한 확인 후 k8s 인가 허가가 되면 최종적으로 동작 실행
- 참고로 EKS를 생성한 IAM principal은 aws-auth와 상관없지 kubernetes-admin Username으로
system:maters 그룹에 권한을 가짐
- 시스템 그룹

- 기본 유저

## aws-auth 컨피그맵 확인
k get cm -n kube-system aws-auth -o yaml
## EKS 설치한 IAM User 정보
k rbac-tool whoami
## system:masters, system:authenticated 그룹의 정보 확인
k rbac-tool lookup system:masters
k rbac-tool lookup system:authenticated
k rolesum -k Group system:masters
k rolesum -k Group system:authenticated
## system:masters 그룹이 사용 가능한 클러스터 롤 확인
k describe clusterrolebindings.rbac.authorization.k8s.io cluster-admin
## cluster-admin의 policyrule 확인
k describe clusterrole cluster-admin
## system:authenticated 그룹이 사용 가능한 클러스터 롤 확인
k describe ClusterRole system:discovery
k describe ClusterRole system:public-info-viewer
k describe ClusterRole system:basic-user
k describe ClusterRole eks:podsecuritypolicy:privileged


실습
[운영 서버1 or local pc] testuser 생성
## 유저 생성
aws iam create-user --user-name testuser
## 사용자에게 프로그래밍 방식 액세스 권한 부여
aws iam create-access-key --user-name testuser
## testuser 사용자에 정책을 추가
aws iam attach-user-policy --policy-arn arn:aws:iam::aws:policy/AdministratorAccess --user-name testuser
## get-caller-identity 확인
aws sts get-caller-identity --query Arn
k whoami
## EC2 IP 확인
aws ec2 describe-instances --query "Reservations[*].Instances[*].{PublicIPAdd:PublicIpAddress,PrivateIPAdd:PrivateIpAddress,InstanceName:Tags[?Key=='Name']|[0].Value,Status:State.Name}" --filters Name=instance-state-name,Values=running --output table

[운영 서버2] testuser 사격증명 설정 및 확인
## 아래 실습 진행을 위해 kind(k8s) 삭제
kind delete cluster --name myk8s
mv ~/.kube/config ~/.kube/config.old
## get-caller-identity 확인
aws sts get-caller-identity --query Arn
## testuser 자격증명 설정
aws configure
## get-caller-identity 확인
aws sts get-caller-identity --query Arn
## kubectl 시도
kubectl get node -v6

[운영 서버 1번] testuser에 system:masters 그룹 부여로 EKS 관리자 수준 권한 설정
## 방법 1
## eksctl 사용 : iamidentitymapping 실행 시 aws-auth 컨피그맵 작성
eksctl get iamidentitymapping --cluster $CLUSTER_NAME
eksctl create iamidentitymapping --cluster $CLUSTER_NAME --username testuser --group system:masters --arn arn:aws:iam::$ACCOUNT_ID:user/testuser
## 확인
k get cm -n kube-system aws-auth -o yaml
## 확인
eksctl get iamidentitymapping --cluster $CLUSTER_NAME

[운영 서버 2번] testuser kubeconfig 생성 및 kubectl 사용 확인
## testuser kubeconfig 생성
CLUSTER_NAME=myeks
aws eks update-kubeconfig --name $CLUSTER_NAME --user-alias testuser
## 운영서버의 config와 비교
cat ~/.kube/config
## kubectl 사용 확인
k ns default
k get node -v6
## rbac-tool 후 확인
k rbac-tool whoami

[운영 서버 1번] testuser의 Group 변경 (system:masters -> system:authenticated)으로 RBAC 동작 확인
## 방안2: 아래 edit으로 mapUsers 내용 직접 수정
k edit cm -n kube-system aws-auth
## 확인
eksctl get iamidentitymapping --cluster $CLUSTER_NAME


[운영 서버 2번] testuser kubectl 사용 확인
## 시도
k get node -v6
k api-resources -v5
- 권한 오류 확인

[운영 서버 1번]에서 testuser IAM 매핑 삭제
## testuser IAM 맵핑 삭제
eksctl delete iamidentitymapping --cluster $CLUSTER_NAME --arn arn:aws:iam::$ACCOUNT_ID:user/testuser
## IAM identity mapping 확인
eksctl get iamidentitymapping --cluster $CLUSTER_NAME
k get cm -n kube-system aws-auth -o yaml

[운영 서버 2번] testuser kubectl 사용 확인
## 시도
k get node -v6
k api-resources -v5
- 인증 오류 확인

EC2 Instance Profile에 맵핑된 k8s rbac 확인

1. node mapRoles 확인
## 노드에 STS ARN 정보 확인
for node in $N1 $N2 $N3; do ssh ec2-user@$node aws sts get-caller-identity --query Arn; done
## 맨 끝 값은 각 node의 instance ID
"arn:aws:sts::632128666759:assumed-role/eksctl-myeks-nodegroup-ng1-NodeInstanceRole-AW6WpgmStLFA/i-00a5941e14dcf8330"
"arn:aws:sts::632128666759:assumed-role/eksctl-myeks-nodegroup-ng1-NodeInstanceRole-AW6WpgmStLFA/i-021dfdb9aa345e92d"
"arn:aws:sts::632128666759:assumed-role/eksctl-myeks-nodegroup-ng1-NodeInstanceRole-AW6WpgmStLFA/i-074b8f4ced6e641b8"
## aws-auth 컨피그맵 확인
## Username 확인
k describe cm -n kube-system aws-auth
- groups:
- system:bootstrappers
- system:nodes
rolearn: arn:aws:iam::632128666759:role/eksctl-myeks-nodegroup-ng1-NodeInstanceRole-AW6WpgmStLFA
username: system:node:{{EC2PrivateDNSName}}
## IAM identity mapping 확인
eksctl get iamidentitymapping --cluster $CLUSTER_NAME
2. awscli 파드를 추가하고, 해당 노드의 IMDS 정보 확인
## awscli 파드 생성
cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: awscli-pod
spec:
replicas: 2
selector:
matchLabels:
app: awscli-pod
template:
metadata:
labels:
app: awscli-pod
spec:
containers:
- name: awscli-pod
image: amazon/aws-cli
command: ["tail"]
args: ["-f", "/dev/null"]
terminationGracePeriodSeconds: 0
EOF
## 파드 생성 확인
k get pod -o wide
## 파드 이름 변수 지정
APODNAME1=$(kubectl get pod -l app=awscli-pod -o jsonpath="{.items[0].metadata.name}")
APODNAME2=$(kubectl get pod -l app=awscli-pod -o jsonpath="{.items[1].metadata.name}")
echo $APODNAME1, $APODNAME2
## awscli 파드에서 ec2 InstanceProfile의 arn 정보 확인
k exec -it $APODNAME1 -- aws sts get-caller-identity --query Arn
k exec -it $APODNAME2 -- aws sts get-caller-identity --query Arn
## awscli 파드에서 ec2 Instanceprofile을 사용하여 aws 서비스 정보 확인
k exec -it $APODNAME1 -- aws ec2 describe-instances --region ap-northeast-2 --output table --no-cli-pager
k exec -it $APODNAME2 -- aws ec2 describe-vpcs --region ap-northeast-2 --otuput tabile --no-cli-pager
## ec2 메타데이터 확인
k exec -it $APODNAME1 -- bash
##(pod sh에서 실행)
curl -s http://169.254.169.254/ -v
# 토큰 요청
curl -s -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600" ; echo
curl -s -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600" ; echo
## Token을 이용한 IMDSv2 사용
TOKEN=$(curl -s -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600")
echo $TOKEN
curl -s -H "X-aws-ec2-metadata-token: $TOKEN" -v http://169.254.169.254/ ; echo
curl -s -H "X-aws-ec2-metadata-token: $TOKEN" –v http://169.254.169.254/latest/ ; echo
curl -s -H "X-aws-ec2-metadata-token: $TOKEN" –v http://169.254.169.254/latest/meta-data/iam/security-credentials/ ; echo
## 위에서 출력된 IAM Role을 아래 입력 후 확인
curl -s -H "X-aws-ec2-metadata-token?: $TOKEN" -v http://169.254.169.254/latest/meta-data/iam/security-credentials/<dfadfadf>


3. awscli 파드에 kubeconfig(mapRole) 정보 생성 및 확인
## node의 IAM Role ARN 변수 지정
eksctl get iamidentitymapping --cluster $CLUSTER_NAME
NODE_ROLE=<Node Role name>
## awscli 파드에서 kubeconfig 정보 생성 및 확인
k exec -it $APODNAME1 -- aws eks update-kubeconfig --name $CLUSTER_NAME --role-arn $NODE_ROLE
k exec -it $APODNAME1 -- cat /root/.kube/config
k exec -it $APODNAME2 -- aws eks update-kubeconfig --name $CLUSTER_NAME --role-arn $NODE_ROLE
k exec -it $APODNAME2 -- cat /root/.kube/config

EKS IRSA & Pod Identity
IRSA : 파드가 특정 IAM 역활로 Assume 할때 토큰을 AWS에 전송하고,
AWS는 토큰과 EKS IdP를 통해 IAM 역할을 사용할 수 있는지 검증


- AWS SDK는 AWS_ROLE_ARN 및 AWS_WEB_IDENTITY_TOKEN_FILE 이름의 환경 변수를 읽어
Web Identity 토큰으로 AssumeRoleWithWebIdentity를 호출함으로써 Assume Role을 시도하여 임시 자격 증명을 획득하고,
특정 IAM Role 역할을 사용할 수 있게됨 - 이때 Assume Role 동작을 위한 인증은 AWS가 아닌 외부 Web IdP(EKS IdP)에 위임하여 처리

- EKS IdP를 Identity provider로 등록하고, 파드가 Web Identity 토큰을 통해 IAM 역할을 Assume 할 수 있게
Trust Relationship 설정 필요
1) 프로젝션된 서비스 계정 토큰은 k8s 클러스터 내에서 유효한 아이덴티티, 다른 곳에서 유요한 토큰으로 교환 가능

2) Amazon IAM 서비스는 이러한 토큰을 받아 JWT 토큰의 Iss 필드를 참고

3) 아이덴티티가 합법적이라면 자체 토큰을 발급할 수 있음

4) 새로운 토큰은 AWS의 서비스에 접근하는데 사용 가능

실습1
## 파드1 생성
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: eks-iam-test1
spec:
containers:
- name: my-aws-cli
image: amazon/aws-cli:latest
args: ['s3', 'ls']
restartPolicy: Never
automountServiceAccountToken: false
terminationGracePeriodSeconds: 0
EOF
## 확인
k get pod
k describe pod
## 로그 확인
k logs eks-iam-test1
## 파드 1 삭제
k delete pod eks-iam-test1


- CloudTrail 이벤트 ListBuckets 확인 -> 기록 표시까지 약간의 시간 필요


실습2
## 파드2 생성
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: eks-iam-test2
spec:
containers:
- name: my-aws-cli
image: amazon/aws-cli:latest
command: ['sleep', '36000']
restartPolicy: Never
terminationGracePeriodSeconds: 0
EOF
## 확인
k get pod
k describe pod
k get pod eks-iam-test2 -o yaml
k exec -it eks-iam-test2 -- ls /var/run/secrets/kubernetes.io/serviceaccount
k exec -it eks-iam-test2 -- cat /var/run/secrets/kubernetes.io/serviceaccount/token ; echo
## aws 서비스 사용 시도
k exec -it eks-iam-test2 -- aws s3 ls
## 서비스 어카운트 토큰 확인
SA_TOKEN=$(kubectl exec -it eks-iam-test2 -- cat /var/run/secrets/kubernetes.io/serviceaccount/token)
echo $SA_TOKEN
## jwt 혹은 아래 JWT 웹 사이트 이용
jwt decode $SA_TOKEN --json --iso8601
## 파드2 삭제




실습 3

## iamserviceaccount 생성
eksctl create iamserviceaccount \
--name my-sa \
--namespace default \
--cluster $CLUSTER_NAME \
--approve \
--attach-policy-arn $(aws iam list-policies --query 'Policies[?PolicyName==`AmazonS3ReadOnlyAccess`].Arn' --output text)
## 확인 > 웹 관리 콘솔 CloudFormation Stack > IAM role 확인
eksctl get iamserviceaccount --cluster $CLUSTER_NAME
## 새 계정 권한 확인
k get sa
k describe sa my-sa

- 신규 파드 생성
## 파드 생성
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: eks-iam-test3
spec:
serviceAccountName: my-sa
containers:
- name: my-aws-cli
image: amazon/aws-cli:latest
command: ['sleep', '36000']
restartPolicy: Never
terminationGracePeriodSeconds: 0
EOF
## mutatingwebhookconfiguration 확인
k get mutatingwebhookconfigurations pod-identity-webhook -o yaml
## 생성한 POD 정보 조회
k get pod eks-iam-test3 -o yaml
- effect: NoExecute
key: node.kubernetes.io/not-ready
operator: Exists
tolerationSeconds: 300
- effect: NoExecute
key: node.kubernetes.io/unreachable
operator: Exists
tolerationSeconds: 300
volumes:
- name: aws-iam-token
projected:
sources:
- serviceAccountToken:
audience: sts.amazonaws.com
expirationSeconds: 86400
path: token
- name: kube-api-access-x4rwn
projected:
sources:
- serviceAccountToken:
expirationSeconds: 3607
path: token
- configMap:
items:
- key: ca.crt
path: ca.crt
name: kube-root-ca.crt
- downwardAPI:
items:
- fieldRef:
fieldPath: metadata.namespace
path: namespace
##
k exec -it eks-iam-test3 -- ls /var/run/secrets/eks.amazonaws.com/serviceaccount
k exec -it eks-iam-test3 -- cat /var/run/secrets/eks.amazonaws.com/serviceaccount/token ; echo
k describe pod eks-iam-test3
Environment:
AWS_STS_REGIONAL_ENDPOINTS: regional
AWS_DEFAULT_REGION: ap-northeast-2
AWS_REGION: ap-northeast-2
AWS_ROLE_ARN: arn:aws:iam::632128666759:role/eksctl-myeks-addon-iamserviceaccount-default--Role1-Di0Yka6Eyp3X
AWS_WEB_IDENTITY_TOKEN_FILE: /var/run/secrets/eks.amazonaws.com/serviceaccount/token
## 파드에서 aws cli 사용 확인
eksctl get iamserviceaccount --cluster $CLUSTER_NAME
k exec -it eks-iam-test3 -- aws sts get-caller-identity --query Arn
## 되고 안되는거 차이 확인
k exec -it eks-iam-test3 -- aws s3 ls
k exec -it eks-iam-test3 -- aws ec2 describe-instances --region ap-northeast-2
k exec -it eks-iam-test3 -- aws ec2 describe-vpcs --region ap-northeast-2


- 환경변수로 지정되어있는 arn 정책을 조회해보면 아래와 같이 s3에 대한 권한만 있고,
instanc, vpc에 대한 권한이 없기 때문에 오류가 발생하는 것을 확인할 수 있다
aws iam list-attached-role-policies --role-name eksctl-myeks-addon-iamserviceaccount-default--Role1-Di0Yka6Eyp3X
{
"AttachedPolicies": [
{
"PolicyName": "AmazonS3ReadOnlyAccess",
"PolicyArn": "arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess"
}
]
}

- 파드의 상세 정보를 조회해보자
## 파드에 볼륨 마운트 2개 확인
k get pod eks-iam-test3 -o json | jq -r '.spec.containers | .[].volumeMounts'

## aws-iam-token 볼륨 정보 확ㄷ인
k get pod eks-iam-test3 -o json | jq -r '.spec.volumes[] | select(.name=="aws-iam-token")'

##
k get MutatingWebhookConfiguration
## pod-identity-webhook 확인
k describe MutatingWebhookConfiguration pod-identity-webhook
k get MutatingWebhookConfiguration pod-identity-webhook -o yaml



Kubernetes 워크로드는 AWS IAM과 인증하기 위해 OIDC JWT 토큰을 사용한다.
AWS IAM은 OIDC ID 공급자를 통해 받은 토큰을 신뢰하고 인증할 수 있다.
이 토큰은 AWS STS의 AssumeRoleWithWebIdentity API를 통해 임시 IAM 자격 증명으로 변환된다.
Kubernetes의 Service Account Issuer Discovery 기능을 통해 EKS는 공개 OIDC 공급자 문서를 제공한다.
IAM은 JWKS(JSON Web Key Sets)를 사용하여 OIDC JWT 토큰의 서명을 검증한 후 인증을 수행한다.
EKS Pod Identity

출시 배경
- 버전 업그레이드 시 고충 개선
- 신규 버전의 클러스터를 구성
- IRSA를 통해 사용하던 기존 역할의 신뢰정책 전부 수정
- 마이그레이션 진행
- 보안성 향상
- IRSA에서는 신뢰정책에 (*)을 많이 쓰게 됨
- 사용성 향상
- (기존) 서비스 계정의 annotations / 역할의 신뢰 정책
- (개선) Pod Identity 등록


## Addon 추가
ADDON=eks-pod-identity-agent
aws eks describe-addon-versions \
--addon-name $ADDON \
--kubernetes-version 1.31 \
--query "addons[].addonVersions[].[addonVersion, compatibilities[].defaultVersion]" \
--output text
v1.3.5-eksbuild.2
False
v1.3.4-eksbuild.1
True
v1.3.2-eksbuild.2
False
v1.3.0-eksbuild.1
False
v1.2.0-eksbuild.1
False
v1.1.0-eksbuild.1
False
v1.0.0-eksbuild.1
False
## add-on 설치
aws eks create-addon --cluster-name $CLUSTER_NAME --addon-name eks-pod-identity-agent
## 설치 확인
eksctl get addon --cluster $CLUSTER_NAME
k -n kube-system get daemonset eks-pod-identity-agent
k -n kube-system get pods -l app.kubernetes.io/name=eks-pod-identity-agent



pod identity association 설정
## podidentityassociation 생성
eksctl create podidentityassociation \
--cluster $CLUSTER_NAME \
--namespace default \
--service-account-name s3-sa \
--role-name s3-eks-pod-identity-role \
--permission-policy-arns arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess \
--region ap-northeast-2
## 확인
kubectl get sa
eksctl get podidentityassociation --cluster $CLUSTER_NAME
aws eks list-pod-identity-associations --cluster-name $CLUSTER_NAME | jq
## ABAC 지원을 위해 sts:Tagsession 추가
aws iam get-role --query 'Role.AssumeRolePolicyDocument' --role-name s3-eks-pod-identity-role | jq .



권한 테스트
## service account 생성
k create sa s3-sa
## pod 생성
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: eks-pod-identity
spec:
serviceAccountName: s3-sa
containers:
- name: my-aws-cli
image: amazon/aws-cli:latest
command: ['sleep', '36000']
restartPolicy: Never
terminationGracePeriodSeconds: 0
EOF
## 권한 확인
k get pod eks-pod-identity -o yaml | k neat
k exec -it eks-pod-identity -- aws sts get-caller-identity --query Arn
k exec -it eks-pod-identity -- aws s3 ls
k exec -it eks-pod-identity -- env | grep AWS



OWASP kubernetes Top Ten
K8s 보안 위협
- DDoS 공격
- SSRF 공격
- 권한 상승 공격 (privilige escalation)
- 악성코드 삽입 (Cross Site scripting)
- 취약점 공격
- Public Access
- 취약한 컨테이너 이미지
- Code Repository
- Image Repository

Kyverno
1. Kyverno는 Kubernetes 클러스터에서 정책을 정의하고 적용하는 정책 엔진이다.
2. YAML 기반의 Kubernetes 네이티브 방식으로 동작하며, 추가적인 외부 정책 언어 없이 정책을 관리할 수 있다.
3. Validating, Mutating, Generating 정책을 통해 리소스 검증, 수정, 자동 생성이 가능하다.
4. OPA(Open Policy Agent)와 달리, Kubernetes 리소스와 자연스럽게 통합되도록 설계되었다.
5. 보안, 규정 준수, RBAC 강화 및 자동화된 리소스 관리에 활용된다.
동작 : Dynamic Admission Control로 실행, Mutating/Validating admission 에서 동작하여 허용/거부 결과 반환


설치
## 네임스페이스 생성
k create ns kyverno
## helm 배포
# value 파일 작성
cat << EOF > kyverno-value.yaml
config:
resourceFiltersExcludeNamespaces: [ kube-system ]
admissionController:
serviceMonitor:
enabled: true
backgroundController:
serviceMonitor:
enabled: true
cleanupController:
serviceMonitor:
enabled: true
reportsController:
serviceMonitor:
enabled: true
EOF
# helm repo 추가
helm repo add kyverno https://kyverno.github.io/kyverno/
# helm 설치
helm install kyverno kyverno/kyverno --version 3.3.7 -f kyverno-value.yaml -n kyverno
## 설치 확인
k get all -n kyverno
k get crd | grep kyverno
k get pod,svc -n kyverno
## step-cli 설치 (운영 서버에서)
wget https://dl.smallstep.com/cli/docs-cli-install/latest/step-cli_amd64.rpm
sudo rpm -i step-cli_amd64.rpm
kubectl -n kyverno get secret
kubectl -n kyverno get secret kyverno-svc.kyverno.svc.kyverno-tls-ca -o jsonpath='{.data.tls\.crt}' | base64 -d
kubectl -n kyverno get secret kyverno-svc.kyverno.svc.kyverno-tls-ca -o jsonpath='{.data.tls\.crt}' | base64 -d | step certificate inspect --short


- prometheus

- Grafana kyverno 대시보드

Policy and Role : Kyverno Policy는 rules 모음

- 각 규칙은 match 선언, 선택적 exclue 선언 및 validate, mutate, generate 또는 verifyImages 선언 중 하나로 구성됩니다.
- 각 규칙에는 단일 validate, mutate, generate 또는 verifyImages 하위 선언만 포함될 수 있습니다.
Validation : 파드에 라벨(lables) 검증
## Cluster Policy 적용
kubectl apply -f- << EOF
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: require-labels
spec:
validationFailureAction: Enforce
rules:
- name: check-team
match:
any:
- resources:
kinds:
- Pod
validate:
message: "label 'team' is required"
pattern:
metadata:
labels:
team: "?*"
EOF

- deployment 생성 시 kyverno 정책으로 오류 발생 확인

- 정책에 맞게 label 설정하여 재생성

- 정책 리포트 확인


- 이런 label 정책이 적용되어 있을 경우 위와 같이 run으로 pod를 생성하거나,
yaml 파일에 명시적으로 label을 지정해 deployment를 생성하면 정상적으로 생성할 수 있다.
Mutation : 파드에 라벨(lables) 추가
kubectl apply -f- << EOF
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: add-labels
spec:
rules:
- name: add-team
match:
any:
- resources:
kinds:
- Pod
mutate:
patchStrategicMerge:
metadata:
labels:
+(team): bravo
EOF

- 파드 생성 후 라벨 확인

- 새로운 파드 생성 후 label 확인

파드 생성 시 라벨을 지정하지 않으면, kubectl run redis의 run=redis와 정책에 지정된 team=bravo가 자동으로 지정되지만
생성자가 명시적으로 label을 지정할 경우에는 run=redis 라벨은 추가되지 않습니다.
Kyverno는 정책 위반이 발생하는 경우에만 Label을 추가하거나 수정합니다.
'Cloud > AWS' 카테고리의 다른 글
[EKS] Blue-Green Migration (0) | 2025.04.06 |
---|---|
[AWS] EKS Mode/Nodes (0) | 2025.03.23 |
[AWS] EKS Autoscaler - Karpenter (0) | 2025.03.09 |
[AWS] EKS Autoscaler - CPA (0) | 2025.03.09 |
[AWS] EKS Autoscaler - CAS (0) | 2025.03.09 |
간단한 암/복호화
암복호화는 평문을 제 3자가 해독할 수 없는 문장인 암호문으로 변환하여 전송하고,
수신측에서 평문으로 암호문으로부터 평문을 복원하는 과정
아래와 같은 과정에서 사용하는 알고리즘을 암호 알고리즘이라고 하며, 암호화하고 복호화하는데 핵심이 되는 것이 KEY라고 한다.
암호화 과정에서 필요한 키를 쌍방이 확보할 수 있는 방법에서 공유 비밀 키 방식 (shared secret key)과 공개키 (public key)가 있다.
- 공유 비밀키 암호화 방식 (shared secret key) : DES, 3DES, RC4/5
- 공개키 암호화 방식 (Public Key) : RSA
- 키 분배 방식 : 'DH방식, RSA공개키, 키 분배 센터(KDC)'를 이용한 공유 비밀키 분배 방법

실습 환경 배포
EKS : 1EA
Bastion : 2EA
## CloudFormation 스크립트 다운로드
curl -O https://s3.ap-northeast-2.amazonaws.com/cloudformation.cloudneta.net/K8S/myeks-6week.yaml
## 변수 지정
CLUSTER_NAME=myeks
SSHKEYNAME=<SSH 키 페이 이름>
MYACCESSKEY=<IAM Uesr 액세스 키>
MYSECRETKEY=<IAM Uesr 시크릿 키>
## CloudFormation 배포
aws cloudformation deploy --template-file myeks-6week.yaml --stack-name $CLUSTER_NAME --parameter-overrides KeyName=$SSHKEYNAME SgIngressSshCidr=$(curl -s https://ipinfo.io/ip)32 MyIamUserAccessKeyID=$MYACCESSKEY MyIamUserScretAccessKey=$MYSECRETKEY ClusterBaseName=$CLUSTER_NAME --region ap-northeast-2
## bastion 서버 IP 확인
aws cloudformation describe-stack --stack-name myeks --query 'Stacks[*].Outputs[0].OutputValue' --output text
### 로컬 PC에서 EKS 접속 설정
# Cluster 조회
eksctl get clusters
# kubeconfig 업데이트
aws sts get-caller-identity --query Arn
aws eks update-kubeconfig --name myeks --user-alis <위 명령어 출력 값 입력>
생성 리소스 확인
## 노드 IP 및 SSH 접속 테스트
export N1=$(aws ec2 describe-instances --filters "Name=tag:Name,Values=myeks-ng1-Node" "Name=availability-zone,Values=ap-northeast-2a" --query 'Reservations[*].Instances[*].PublicIpAddress' --output text)
export N2=$(aws ec2 describe-instances --filters "Name=tag:Name,Values=myeks-ng1-Node" "Name=availability-zone,Values=ap-northeast-2b" --query 'Reservations[*].Instances[*].PublicIpAddress' --output text)
export N3=$(aws ec2 describe-instances --filters "Name=tag:Name,Values=myeks-ng1-Node" "Name=availability-zone,Values=ap-northeast-2c" --query 'Reservations[*].Instances[*].PublicIpAddress' --output text)
echo $N1, $N2, $N3
# *remoteAccess* 포함된 보안그룹 ID
aws ec2 describe-security-groups --filters "Name=group-name,Values=*remoteAccess*" | jq
export MNSGID=$(aws ec2 describe-security-groups --filters "Name=group-name,Values=*remoteAccess*" --query 'SecurityGroups[*].GroupId' --output text)
# 해당 보안그룹 inbound 에 자신의 집 공인 IP 룰 추가
aws ec2 authorize-security-group-ingress --group-id $MNSGID --protocol '-1' --cidr $(curl -s ipinfo.io/ip)/32
# 해당 보안그룹 inbound 에 운영서버 내부 IP 룰 추가
aws ec2 authorize-security-group-ingress --group-id $MNSGID --protocol '-1' --cidr 172.20.1.100/32
aws ec2 authorize-security-group-ingress --group-id $MNSGID --protocol '-1' --cidr 172.20.1.200/32
# 워커 노드 SSH 접속
for i in $N1 $N2 $N3; do echo ">> node $i <<"; ssh -o StrictHostKeyChecking=no ec2-user@$i hostname; echo; done



운영 EC2 접속
## default 네임 스페이스 전환
k ns default
## 환경 변수 정보 확인
export | egrep 'ACCOUNT|AWS_|CLUSTER|KUBERNETS|VPC|Subnet' | egrep -v 'KEY'
## 인스턴스 정보 확인
aws ec2 describe-instances --query "Reservations[*].Instances[*].{InstanceID:InstanceId, PublicIPAdd:PublicIpAddress, PrivateIPAdd:PrivateIpAddress, InstanceName:Tags[?Key=='Name']|[0].Value, Status:State.Name}" --filters Name=instance-state-name,Values=running --output table
## 노드 IP 확인 및 PrivateIP 변수 지정
aws ec2 describe-instances --query "Reservations[*].Instances[*].{PublicIPAdd:PublicIpAddress,PrivateIPAdd:PrivateIpAddress,InstanceName:Tags[?Key=='Name']|[0].Value,Status:State.Name}" --filters Name=instance-state-name,Values=running --output table
N1=$(kubectl get node --label-columns=topology.kubernetes.io/zone --selector=topology.kubernetes.io/zone=ap-northeast-2a -o jsonpath={.items[0].status.addresses[0].address})
N2=$(kubectl get node --label-columns=topology.kubernetes.io/zone --selector=topology.kubernetes.io/zone=ap-northeast-2b -o jsonpath={.items[0].status.addresses[0].address})
N3=$(kubectl get node --label-columns=topology.kubernetes.io/zone --selector=topology.kubernetes.io/zone=ap-northeast-2c -o jsonpath={.items[0].status.addresses[0].address})
echo "export N1=$N1" >> /etc/profile
echo "export N2=$N2" >> /etc/profile
echo "export N3=$N3" >> /etc/profile
echo $N1, $N2, $N3
## 노드 IP 로 ping 테스트
for i in $N1 $N2 $N3; do echo ">> node $i <<"; ping -c 1 $i ; echo; done

- Kube-Ops-View, AWS LoadBalancer Controller, ExternalDNS gp3 Storageclass 설치
[설치 방법은 이전 게시글 참고]



K8S(API 접근) 인증/인가
- API 서버 사용 : kubectl(config, 다수 클러스터 관리 가능), 서비스 어카운트, https(x.509 Client Certs)
- API 서버 접근 과정 : 인증 -> 인가 -> Admission Control(API 요청 검증, 필요 시 변형 - 예) ResouceQuota, LimitRange)

인증
- X.509 Client Certs : kubeconfig 에 CA crt(발급 기관 인증서), Client crt(클라이언트 인증서), Client key(클라이언트 개인키) 를 통해 인증
- kubectl : 여러 클러스터(kubeconfig)를 관리 가능 - contexts 에 클러스터와 유저 및 인증서/키
- Service Account : 기본 어카운트 (default) - 시크릿(CA crt와 token)

인가
- 인가 방식 : RBAC(role, rolebinding), ABAC, Webook, Node Authorization
- RBAC : 역할 기반의 권한 관리, 사용자와 역할을 별개로 선언 후 두가지를 조합(binding)해서 사용자에게 권한을 부여하여 kubectl or API로 관리 가능
- Namespace / cluster - role/clusterrole, rolebinding/clusterrolebinding, service account
- role(롤) - (rolebinding 롤 바인딩) - Service Account(서비스 어카운트) : 롤 바인딩은 롤과 서비스 어카운트를 연결
- Role(네임스페이스 내 자원의 권한) vs ClusterRole(클러스터 수준의 자원의 권한)

.kube/config 파일 내용
- clusters : kubectl 이 사용할 쿠버네티스 API 서버의 접속 정보 목록. 원격의 쿠버네티스 API 서버의 주소를 추가해 사용 가능
- users : 쿠버네티스의 API 서버에 접속하기 위한 사용자 인증 정보 목록 (서비스 어카운트의 토큰, 혹은 인증서의 데이터 등)
- contexts : cluster 항목과 users 항목에 정의된 값을 조합해 최종적으로 사용할 쿠버네티스 클러스터의 정보(컨텍스트)를 설정
- 예를 들어 clusters 항목에 클러스터 A,B가 정의되어 있고, users 항목에 사용자 a,b가 정의돼 있다면 cluster A + user a를 조합해 'cluster A에 user a로 인증해 쿠버네티스를 사용한다' 라는 새로운 컨텍스트를 정의할 수 있다.
- kubectl을 사용하려면 여러 개의 컨텍스트 중 하나를 선택
apiVersion: v1
clusters:
- cluster:
┆ certificate-authority-data: Lap-northeast-2.eks.amazonaws.com
name: arn:aws:eks:ap-northeast-2::cluster/myeks
contexts:
- context:
┆ cluster: arn:aws:eks:ap-northeast-2::cluster/myeks
┆ namespace: monitoring
┆ user: hoontest1
name: hoontest1
current-context: hoontest1
kind: Config
preferences: {}
users:
- name: hoontest1
user:
┆ exec:
┆ ┆ apiVersion: client.authentication.k8s.io/v1beta1
┆ ┆ args:
┆ ┆ - --region
┆ ┆ - ap-northeast-2
┆ ┆ - eks
┆ ┆ - get-token
┆ ┆ - --cluster-name
실습 환경
- 쿠버네티스에 사용자를 위한 서비스 어카운트 (Service Account, SA)를 생성 : dev-k8s, infra-k8s
- 사용자는 각기 다른 권한(Role, 인가)을 갖음 : dev-k8s(dev-team 네임스페이스 내 모든 동작), infra-k8s(dev-team 네임스페이스 내 모든 동작)
- 각각 별도의 kubectl 파드를 생성하고, 해당 파드에 SA를 지정하여 권한에 대한 테스트를 진행

네임스페이스와 서비스 어카운트 생성 후 확인
- 파드 기동 시 서비스 아카운트 한 개가 할당되며, 서비스 어카운트 기반 인증/인가를 하며, 미지정 시 기본 서비스 어카운트 할당
- 서비스 어카운트에 자동 생성된 시크릿에 저장된 토큰으로 쿠버네티스 API에 대한 인증 정보로 사용 할 수 있다. <- 1.23 이전 대상
## namespcae 생성 및 확인
k create ns dev-team
k create ns infra-team
## namespace 확인
k get ns
## namespace에 서브어카운트 생성
k create sa dev-k8s -n dev-team
k create sa infra-k8s -n infra-team
## SA 정보 확인
k get sa -n dev-team
k get sa -n infra-team
k get sa -n dev-team -o yaml
k get sa -n infra-team -o yaml
각 네임스페이스에 파드 생성
cat <<EOF | kubectl create -f -
apiVersion: v1
kind: Pod
metadata:
name: dev-kubectl
namespcae: dev-team
spec:
serviceAccountName: dev-k8s
containers:
- name: kubectl-pod
image: bitnami/kubectl:1.31.4
command: ["tail"]
args: ["-f", "/dev/null"]
terminationGracePeriodSeconds: 0
EOF
cat <<EOF | kubectl create -f -
apiVersion: v1
kind: Pod
metadata:
name: infra-kubectl
namespace: infra-team
spec:
serviceAccountName: infra-k8s
containers:
- name: kubectl-pod
image: bitnami/kubectl:1.31.4
command: ["tail"]
args: ["-f", "/dev/null"]
terminationGracePeriodSeconds: 0
EOF
## 생성 확인
k get pod -A
k get pod dev-kubectl -n dev-team -o yaml
k get pod infra-kubectl -n infra-team -o yaml
## 파드에 기본 적용되는 서비스 어카운트 정보 확인
k exec -it dev-kubectl -n dev-team -- ls /run/secrets/kubernetes.io/serviceaccount
k exec -it dev-kubectl -n dev-team -- cat /run/secrets/kubernetes.io/serviceaccount/token
k exec -it dev-kubectl -n dev-team -- cat /run/secrets/kubernetes.io/serviceaccount/namespace
k exec -it dev-kubectl -n dev-team -- cat /run/secrets/kubernetes.io/serviceaccount/ca.crt
## 각 파드로 shell 접속 후 정보 확인
alias k1='kubectl exec -it dev-kubectl -n dev-team -- kubectl'
alias k2='kubectl exec -it infra-kubectl -n infra-team -- kubectl'
## 권한 테스트
k1 get pods
k1 run nginx --image nginx:1.20-alpine
k1 get pods -n kube-system
k2 get pods
k2 run nginx --image nginx:1.20-alpine
k2 get pod -n kube-system
## k auth can-i를 통해 kubectl 실행 사용자가 특정 권한을 가지고 있는지 확인 가능
k1 auth can-i get pods

각각 네임스페이스에 Role 생성 후 서비스 어카운트와 바인딩
- Role: apiGroups와 resources로 지정된 리소스에 대해 verbs 권한을 인가
- 실행 가능한 조작(verbs) : *(모두 처리), create(생성), delete(삭제), get(조회), list(목록조회), patch(일부업데이트), update(업데이트), watch(변경감시)



## 클러스터에서 지원하는 api 리소스 출력
k api-resources
## 상세 정보 출력
k api-resources -o wide
## 별도 리소스 조회
k api-resource --api-group=""
k api-resource --api-group="apps"
k api-resources --api-group=metrics.k8s.io
k api-resources --api-group=admissionregistration.k8s.io
k api-resources --api-group=rbac.authorization.k8s.io
k api-resources --api-group=apiextensions.k8s.io
## 각각 네임스페이스내의 모든 권한에 대한 룰 생성
cat <<EOF | kubectl create -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: role
metadata:
name: role-dev-team
namespace: dev-team
rules:
- apiGroups: ["*"]
resources: ["*"]
verbs: ["*"]
EOF
cat <<EOF | kubectl create -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: role-infra-team
namespace: infra-team
rules:
- apiGroups: ["*"]
resources: ["*"]
verbs: ["*"]
EOF
## 생성 룰 확인
k get roles -n dev-team
k get roles -n infra-team
k get roles -n dev-team -o yaml
k get roles -n infra-team -o yaml
k describe roles role-dev-team -n dev-team
## 롤 바인딩 생성
cat <<EOF | kubectl create -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: roleB-dev-team
namespace: dev-team
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: role-dev-team
subjects:
- kind: ServiceAccount
name: dev-k8s
namespace: dev-team
EOF
cat <<EOF | kubectl create -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: roleB-infra-team
namespace: infra-team
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: role-infra:team
subjects:
- kind: ServiceAccount
name: infra-k8s
namespace: infra-team
EOF
## 롤 바인딩 확인
k get rolebindings -n dev-team
k get rolebindings -n infra-team
k get rolebindings -n dev-team -o yaml
k get rolebindings -n infra-team -o yaml
k describe rolebindings roleB-dev-team -n dev-team


- Kubernetes RBAC에서 Role과 RoleBinding을 이용한 권한 할당 방식

- Kubernetes RBAC에서 User, Group, ServiceAccount

- Role과 ClusterRole의 차이점

- Kubernetes에서 자주 사용되는 ClusterRole의 권한 수준(view, edit, admin, cluster-admin)

서비스 어카운트를 지정하여 생성한 파드에서 다시 권한 테스트
## 각 파드로 shell 접속하여 정보 확인
alias k1='kubectl exec -it dev-kubectl -n dev-team -- kubectl'
alias k2='kubectl exec -it infra-kubectl -n infra-team -- kubectl'
## 권한 테스트
k1 get pods
k1 run nginx --image nginx:1.20-alpine
k1 get pods
k1 delete pods nginx
k1 get pods -n kube-system
k1 get pods -n kube-system -v=6
k1 get nodes
k1 get nodes -v=6
k2 get pods
k2 run nginx --image nginx:1.20-alpine
k2 get pods
k2 delete pods nginx
k2 get pods -n kube-system
k2 get nodes
## kubectl 사용자가 특정 권한을 갖고 있는지 확인
k1 auth can-i get pods
yes

EKS 인증/인가
사용자 / 어플리케이션 -> k8s 사용 시 => 인증은 AWS IAM, 인가는 k8s rbac



확장 프로그램 설치
- access-matrix: Kubernetes RBAC(Role-Based Access Control) 권한을 매트릭스로 시각화하여 분석하는 도구.
- rbac-tool: Kubernetes RBAC 정책을 검사하고, 권한 분석 및 정책 최적화를 돕는 CLI 기반 유틸리티.
- rolesum: Kubernetes 클러스터 내 사용자, 그룹, 서비스 계정의 역할(Role)과 권한을 요약하여 보여주는 도구.
- whoami: 현재 사용자의 Kubernetes RBAC 권한을 조회하여 어떤 리소스에 접근할 수 있는지 확인하는 플러그인.
## Plugin install
k krew install access-matrix rbac-tool rolesum whoami
## 인증 확인
k whoami
## access-matrix로 권한 확인
k access-matrix -h
k access-matrix
k access-matrix --namespace default
## rbac lookup
k rbac-tool -h
k rbac-tool lookup
k rbac-tool lookup system:masters
## rbac policy rules
k rbac-tool policy-rules
k rbac-tool policy-rules -e '^system:.*'
k rbac-tool policy-rules -e '^system:authenticated'
k rbac-tool show
k rbac-tool whoami
## rolesum
k rolesum -h
k rolesum aws-node -n kube-system # sa
k rolesum -k User system:kube-proxy # user
k rolesum -k Group system:masters # group
k rolesum -k Group system:nodes
k rolesum -k Group system:authenticated
## rbac-view (visualize rbac permissions
k rbac-view
open "https://$(curl -s ipinfo.io/ip):8080"



약어 | Verbs | 설명 |
G | Get | 리소스를 조회 (get) |
L | List | 리소스를 목록으로 나열 (List) |
W | Watch | 리소스를 감시 (watch) |
C | Create | 새 리소스를 생성 (create) |
U | Update | 기존 리소스를 수정 (update) |
P | Patch | 리소스의 일부를 패치 (patch) |
D | Delete | 리소스를 삭제 (Delete) |
DC | Delete Collection | 리소스의 컬렉션(여러 개)을 삭제 (deletecollection) |
EKS 인증/인가 확인

- 핵심 : 인증은 AWS IAM, 인가는 k8s rbac에서 처리

1. kubectl 명령 -> aws eks get-token -> STS에 토큰 요청 => 응답값 디코드(Pre-signed URL이며 getcallerindetity..)
- STS Security Token Service : AWS 리소스에 대한 액세스를 제어할 수 있는 임시 보안 자격 증명(STS)을 생성하여 신뢰받는 사용자에게 제공 할 수 있음
- AWS CLI 1.16.156 이상에서는 별도 aws-iam-authenticator 설치 없이 aws eks get-token으로 사용 가능
## sts caller id의 ARN 확인
aws sts get-caller-identity --query Arn
"arn:aws:iam::<Account ID>>:user/<인증한 유저>"
## kubeconfig 정보 확인
cat ~/.kube/config
user:
exec:
apiVersion: client.authentication.k8s.io/v1beta1
args:
- eks
- get-token
- --output
- json
- --cluster-name
- myeks
- --region
- ap-northeast-2
command: aws
env:
- name: AWS_STS_REGIONAL_ENDPOINTS
## 임시 보안 자격 증명을 요청 : expirationTimestamp 시간 경과 시 토큰 재발급
aws eks get-token --cluster-name $CLUSTER_NAME | jq
aws eks get-token --cluster-name $CLUSTER_NAME | jq -r '.status.token'
aws eks get-token --cluster-name $CLUSTER_NAME --debug | jq

2. kubectl의 Client-Go 라이브러리는 Pre-Signed URL을 bearer token으로 EKS API Cluster Endpoint 로 요청

3. EKS API는 Token Review를 Webhook token authenticator에 요청
AWS IAM 해당 호출 인증 오나료 후 User/role에 대한 ARN 반환
## tokenreviews api 리소스 확인
k api-resources | grep authentication
##
k explain tokenreviews
4. ConfigMap 방식
- 해당 IAM User/Role 확인이 되면 k8s aws-auth configmap에서 mapping 정보를 확인하게 됩니다.
- aws-auth 컨피그맵에 'IAM 사용자, 역할 arm, k8s 오브젝트'로 권한 확인 후 k8s 인가 허가가 되면 최종적으로 동작 실행
- 참고로 EKS를 생성한 IAM principal은 aws-auth와 상관없지 kubernetes-admin Username으로
system:maters 그룹에 권한을 가짐
- 시스템 그룹

- 기본 유저

## aws-auth 컨피그맵 확인
k get cm -n kube-system aws-auth -o yaml
## EKS 설치한 IAM User 정보
k rbac-tool whoami
## system:masters, system:authenticated 그룹의 정보 확인
k rbac-tool lookup system:masters
k rbac-tool lookup system:authenticated
k rolesum -k Group system:masters
k rolesum -k Group system:authenticated
## system:masters 그룹이 사용 가능한 클러스터 롤 확인
k describe clusterrolebindings.rbac.authorization.k8s.io cluster-admin
## cluster-admin의 policyrule 확인
k describe clusterrole cluster-admin
## system:authenticated 그룹이 사용 가능한 클러스터 롤 확인
k describe ClusterRole system:discovery
k describe ClusterRole system:public-info-viewer
k describe ClusterRole system:basic-user
k describe ClusterRole eks:podsecuritypolicy:privileged


실습
[운영 서버1 or local pc] testuser 생성
## 유저 생성
aws iam create-user --user-name testuser
## 사용자에게 프로그래밍 방식 액세스 권한 부여
aws iam create-access-key --user-name testuser
## testuser 사용자에 정책을 추가
aws iam attach-user-policy --policy-arn arn:aws:iam::aws:policy/AdministratorAccess --user-name testuser
## get-caller-identity 확인
aws sts get-caller-identity --query Arn
k whoami
## EC2 IP 확인
aws ec2 describe-instances --query "Reservations[*].Instances[*].{PublicIPAdd:PublicIpAddress,PrivateIPAdd:PrivateIpAddress,InstanceName:Tags[?Key=='Name']|[0].Value,Status:State.Name}" --filters Name=instance-state-name,Values=running --output table

[운영 서버2] testuser 사격증명 설정 및 확인
## 아래 실습 진행을 위해 kind(k8s) 삭제
kind delete cluster --name myk8s
mv ~/.kube/config ~/.kube/config.old
## get-caller-identity 확인
aws sts get-caller-identity --query Arn
## testuser 자격증명 설정
aws configure
## get-caller-identity 확인
aws sts get-caller-identity --query Arn
## kubectl 시도
kubectl get node -v6

[운영 서버 1번] testuser에 system:masters 그룹 부여로 EKS 관리자 수준 권한 설정
## 방법 1
## eksctl 사용 : iamidentitymapping 실행 시 aws-auth 컨피그맵 작성
eksctl get iamidentitymapping --cluster $CLUSTER_NAME
eksctl create iamidentitymapping --cluster $CLUSTER_NAME --username testuser --group system:masters --arn arn:aws:iam::$ACCOUNT_ID:user/testuser
## 확인
k get cm -n kube-system aws-auth -o yaml
## 확인
eksctl get iamidentitymapping --cluster $CLUSTER_NAME

[운영 서버 2번] testuser kubeconfig 생성 및 kubectl 사용 확인
## testuser kubeconfig 생성
CLUSTER_NAME=myeks
aws eks update-kubeconfig --name $CLUSTER_NAME --user-alias testuser
## 운영서버의 config와 비교
cat ~/.kube/config
## kubectl 사용 확인
k ns default
k get node -v6
## rbac-tool 후 확인
k rbac-tool whoami

[운영 서버 1번] testuser의 Group 변경 (system:masters -> system:authenticated)으로 RBAC 동작 확인
## 방안2: 아래 edit으로 mapUsers 내용 직접 수정
k edit cm -n kube-system aws-auth
## 확인
eksctl get iamidentitymapping --cluster $CLUSTER_NAME


[운영 서버 2번] testuser kubectl 사용 확인
## 시도
k get node -v6
k api-resources -v5
- 권한 오류 확인

[운영 서버 1번]에서 testuser IAM 매핑 삭제
## testuser IAM 맵핑 삭제
eksctl delete iamidentitymapping --cluster $CLUSTER_NAME --arn arn:aws:iam::$ACCOUNT_ID:user/testuser
## IAM identity mapping 확인
eksctl get iamidentitymapping --cluster $CLUSTER_NAME
k get cm -n kube-system aws-auth -o yaml

[운영 서버 2번] testuser kubectl 사용 확인
## 시도
k get node -v6
k api-resources -v5
- 인증 오류 확인

EC2 Instance Profile에 맵핑된 k8s rbac 확인

1. node mapRoles 확인
## 노드에 STS ARN 정보 확인
for node in $N1 $N2 $N3; do ssh ec2-user@$node aws sts get-caller-identity --query Arn; done
## 맨 끝 값은 각 node의 instance ID
"arn:aws:sts::632128666759:assumed-role/eksctl-myeks-nodegroup-ng1-NodeInstanceRole-AW6WpgmStLFA/i-00a5941e14dcf8330"
"arn:aws:sts::632128666759:assumed-role/eksctl-myeks-nodegroup-ng1-NodeInstanceRole-AW6WpgmStLFA/i-021dfdb9aa345e92d"
"arn:aws:sts::632128666759:assumed-role/eksctl-myeks-nodegroup-ng1-NodeInstanceRole-AW6WpgmStLFA/i-074b8f4ced6e641b8"
## aws-auth 컨피그맵 확인
## Username 확인
k describe cm -n kube-system aws-auth
- groups:
- system:bootstrappers
- system:nodes
rolearn: arn:aws:iam::632128666759:role/eksctl-myeks-nodegroup-ng1-NodeInstanceRole-AW6WpgmStLFA
username: system:node:{{EC2PrivateDNSName}}
## IAM identity mapping 확인
eksctl get iamidentitymapping --cluster $CLUSTER_NAME
2. awscli 파드를 추가하고, 해당 노드의 IMDS 정보 확인
## awscli 파드 생성
cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: awscli-pod
spec:
replicas: 2
selector:
matchLabels:
app: awscli-pod
template:
metadata:
labels:
app: awscli-pod
spec:
containers:
- name: awscli-pod
image: amazon/aws-cli
command: ["tail"]
args: ["-f", "/dev/null"]
terminationGracePeriodSeconds: 0
EOF
## 파드 생성 확인
k get pod -o wide
## 파드 이름 변수 지정
APODNAME1=$(kubectl get pod -l app=awscli-pod -o jsonpath="{.items[0].metadata.name}")
APODNAME2=$(kubectl get pod -l app=awscli-pod -o jsonpath="{.items[1].metadata.name}")
echo $APODNAME1, $APODNAME2
## awscli 파드에서 ec2 InstanceProfile의 arn 정보 확인
k exec -it $APODNAME1 -- aws sts get-caller-identity --query Arn
k exec -it $APODNAME2 -- aws sts get-caller-identity --query Arn
## awscli 파드에서 ec2 Instanceprofile을 사용하여 aws 서비스 정보 확인
k exec -it $APODNAME1 -- aws ec2 describe-instances --region ap-northeast-2 --output table --no-cli-pager
k exec -it $APODNAME2 -- aws ec2 describe-vpcs --region ap-northeast-2 --otuput tabile --no-cli-pager
## ec2 메타데이터 확인
k exec -it $APODNAME1 -- bash
##(pod sh에서 실행)
curl -s http://169.254.169.254/ -v
# 토큰 요청
curl -s -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600" ; echo
curl -s -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600" ; echo
## Token을 이용한 IMDSv2 사용
TOKEN=$(curl -s -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600")
echo $TOKEN
curl -s -H "X-aws-ec2-metadata-token: $TOKEN" -v http://169.254.169.254/ ; echo
curl -s -H "X-aws-ec2-metadata-token: $TOKEN" –v http://169.254.169.254/latest/ ; echo
curl -s -H "X-aws-ec2-metadata-token: $TOKEN" –v http://169.254.169.254/latest/meta-data/iam/security-credentials/ ; echo
## 위에서 출력된 IAM Role을 아래 입력 후 확인
curl -s -H "X-aws-ec2-metadata-token?: $TOKEN" -v http://169.254.169.254/latest/meta-data/iam/security-credentials/<dfadfadf>


3. awscli 파드에 kubeconfig(mapRole) 정보 생성 및 확인
## node의 IAM Role ARN 변수 지정
eksctl get iamidentitymapping --cluster $CLUSTER_NAME
NODE_ROLE=<Node Role name>
## awscli 파드에서 kubeconfig 정보 생성 및 확인
k exec -it $APODNAME1 -- aws eks update-kubeconfig --name $CLUSTER_NAME --role-arn $NODE_ROLE
k exec -it $APODNAME1 -- cat /root/.kube/config
k exec -it $APODNAME2 -- aws eks update-kubeconfig --name $CLUSTER_NAME --role-arn $NODE_ROLE
k exec -it $APODNAME2 -- cat /root/.kube/config

EKS IRSA & Pod Identity
IRSA : 파드가 특정 IAM 역활로 Assume 할때 토큰을 AWS에 전송하고,
AWS는 토큰과 EKS IdP를 통해 IAM 역할을 사용할 수 있는지 검증


- AWS SDK는 AWS_ROLE_ARN 및 AWS_WEB_IDENTITY_TOKEN_FILE 이름의 환경 변수를 읽어
Web Identity 토큰으로 AssumeRoleWithWebIdentity를 호출함으로써 Assume Role을 시도하여 임시 자격 증명을 획득하고,
특정 IAM Role 역할을 사용할 수 있게됨 - 이때 Assume Role 동작을 위한 인증은 AWS가 아닌 외부 Web IdP(EKS IdP)에 위임하여 처리

- EKS IdP를 Identity provider로 등록하고, 파드가 Web Identity 토큰을 통해 IAM 역할을 Assume 할 수 있게
Trust Relationship 설정 필요
1) 프로젝션된 서비스 계정 토큰은 k8s 클러스터 내에서 유효한 아이덴티티, 다른 곳에서 유요한 토큰으로 교환 가능

2) Amazon IAM 서비스는 이러한 토큰을 받아 JWT 토큰의 Iss 필드를 참고

3) 아이덴티티가 합법적이라면 자체 토큰을 발급할 수 있음

4) 새로운 토큰은 AWS의 서비스에 접근하는데 사용 가능

실습1
## 파드1 생성
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: eks-iam-test1
spec:
containers:
- name: my-aws-cli
image: amazon/aws-cli:latest
args: ['s3', 'ls']
restartPolicy: Never
automountServiceAccountToken: false
terminationGracePeriodSeconds: 0
EOF
## 확인
k get pod
k describe pod
## 로그 확인
k logs eks-iam-test1
## 파드 1 삭제
k delete pod eks-iam-test1


- CloudTrail 이벤트 ListBuckets 확인 -> 기록 표시까지 약간의 시간 필요


실습2
## 파드2 생성
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: eks-iam-test2
spec:
containers:
- name: my-aws-cli
image: amazon/aws-cli:latest
command: ['sleep', '36000']
restartPolicy: Never
terminationGracePeriodSeconds: 0
EOF
## 확인
k get pod
k describe pod
k get pod eks-iam-test2 -o yaml
k exec -it eks-iam-test2 -- ls /var/run/secrets/kubernetes.io/serviceaccount
k exec -it eks-iam-test2 -- cat /var/run/secrets/kubernetes.io/serviceaccount/token ; echo
## aws 서비스 사용 시도
k exec -it eks-iam-test2 -- aws s3 ls
## 서비스 어카운트 토큰 확인
SA_TOKEN=$(kubectl exec -it eks-iam-test2 -- cat /var/run/secrets/kubernetes.io/serviceaccount/token)
echo $SA_TOKEN
## jwt 혹은 아래 JWT 웹 사이트 이용
jwt decode $SA_TOKEN --json --iso8601
## 파드2 삭제




실습 3

## iamserviceaccount 생성
eksctl create iamserviceaccount \
--name my-sa \
--namespace default \
--cluster $CLUSTER_NAME \
--approve \
--attach-policy-arn $(aws iam list-policies --query 'Policies[?PolicyName==`AmazonS3ReadOnlyAccess`].Arn' --output text)
## 확인 > 웹 관리 콘솔 CloudFormation Stack > IAM role 확인
eksctl get iamserviceaccount --cluster $CLUSTER_NAME
## 새 계정 권한 확인
k get sa
k describe sa my-sa

- 신규 파드 생성
## 파드 생성
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: eks-iam-test3
spec:
serviceAccountName: my-sa
containers:
- name: my-aws-cli
image: amazon/aws-cli:latest
command: ['sleep', '36000']
restartPolicy: Never
terminationGracePeriodSeconds: 0
EOF
## mutatingwebhookconfiguration 확인
k get mutatingwebhookconfigurations pod-identity-webhook -o yaml
## 생성한 POD 정보 조회
k get pod eks-iam-test3 -o yaml
- effect: NoExecute
key: node.kubernetes.io/not-ready
operator: Exists
tolerationSeconds: 300
- effect: NoExecute
key: node.kubernetes.io/unreachable
operator: Exists
tolerationSeconds: 300
volumes:
- name: aws-iam-token
projected:
sources:
- serviceAccountToken:
audience: sts.amazonaws.com
expirationSeconds: 86400
path: token
- name: kube-api-access-x4rwn
projected:
sources:
- serviceAccountToken:
expirationSeconds: 3607
path: token
- configMap:
items:
- key: ca.crt
path: ca.crt
name: kube-root-ca.crt
- downwardAPI:
items:
- fieldRef:
fieldPath: metadata.namespace
path: namespace
##
k exec -it eks-iam-test3 -- ls /var/run/secrets/eks.amazonaws.com/serviceaccount
k exec -it eks-iam-test3 -- cat /var/run/secrets/eks.amazonaws.com/serviceaccount/token ; echo
k describe pod eks-iam-test3
Environment:
AWS_STS_REGIONAL_ENDPOINTS: regional
AWS_DEFAULT_REGION: ap-northeast-2
AWS_REGION: ap-northeast-2
AWS_ROLE_ARN: arn:aws:iam::632128666759:role/eksctl-myeks-addon-iamserviceaccount-default--Role1-Di0Yka6Eyp3X
AWS_WEB_IDENTITY_TOKEN_FILE: /var/run/secrets/eks.amazonaws.com/serviceaccount/token
## 파드에서 aws cli 사용 확인
eksctl get iamserviceaccount --cluster $CLUSTER_NAME
k exec -it eks-iam-test3 -- aws sts get-caller-identity --query Arn
## 되고 안되는거 차이 확인
k exec -it eks-iam-test3 -- aws s3 ls
k exec -it eks-iam-test3 -- aws ec2 describe-instances --region ap-northeast-2
k exec -it eks-iam-test3 -- aws ec2 describe-vpcs --region ap-northeast-2


- 환경변수로 지정되어있는 arn 정책을 조회해보면 아래와 같이 s3에 대한 권한만 있고,
instanc, vpc에 대한 권한이 없기 때문에 오류가 발생하는 것을 확인할 수 있다
aws iam list-attached-role-policies --role-name eksctl-myeks-addon-iamserviceaccount-default--Role1-Di0Yka6Eyp3X
{
"AttachedPolicies": [
{
"PolicyName": "AmazonS3ReadOnlyAccess",
"PolicyArn": "arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess"
}
]
}

- 파드의 상세 정보를 조회해보자
## 파드에 볼륨 마운트 2개 확인
k get pod eks-iam-test3 -o json | jq -r '.spec.containers | .[].volumeMounts'

## aws-iam-token 볼륨 정보 확ㄷ인
k get pod eks-iam-test3 -o json | jq -r '.spec.volumes[] | select(.name=="aws-iam-token")'

##
k get MutatingWebhookConfiguration
## pod-identity-webhook 확인
k describe MutatingWebhookConfiguration pod-identity-webhook
k get MutatingWebhookConfiguration pod-identity-webhook -o yaml



Kubernetes 워크로드는 AWS IAM과 인증하기 위해 OIDC JWT 토큰을 사용한다.
AWS IAM은 OIDC ID 공급자를 통해 받은 토큰을 신뢰하고 인증할 수 있다.
이 토큰은 AWS STS의 AssumeRoleWithWebIdentity API를 통해 임시 IAM 자격 증명으로 변환된다.
Kubernetes의 Service Account Issuer Discovery 기능을 통해 EKS는 공개 OIDC 공급자 문서를 제공한다.
IAM은 JWKS(JSON Web Key Sets)를 사용하여 OIDC JWT 토큰의 서명을 검증한 후 인증을 수행한다.
EKS Pod Identity

출시 배경
- 버전 업그레이드 시 고충 개선
- 신규 버전의 클러스터를 구성
- IRSA를 통해 사용하던 기존 역할의 신뢰정책 전부 수정
- 마이그레이션 진행
- 보안성 향상
- IRSA에서는 신뢰정책에 (*)을 많이 쓰게 됨
- 사용성 향상
- (기존) 서비스 계정의 annotations / 역할의 신뢰 정책
- (개선) Pod Identity 등록


## Addon 추가
ADDON=eks-pod-identity-agent
aws eks describe-addon-versions \
--addon-name $ADDON \
--kubernetes-version 1.31 \
--query "addons[].addonVersions[].[addonVersion, compatibilities[].defaultVersion]" \
--output text
v1.3.5-eksbuild.2
False
v1.3.4-eksbuild.1
True
v1.3.2-eksbuild.2
False
v1.3.0-eksbuild.1
False
v1.2.0-eksbuild.1
False
v1.1.0-eksbuild.1
False
v1.0.0-eksbuild.1
False
## add-on 설치
aws eks create-addon --cluster-name $CLUSTER_NAME --addon-name eks-pod-identity-agent
## 설치 확인
eksctl get addon --cluster $CLUSTER_NAME
k -n kube-system get daemonset eks-pod-identity-agent
k -n kube-system get pods -l app.kubernetes.io/name=eks-pod-identity-agent



pod identity association 설정
## podidentityassociation 생성
eksctl create podidentityassociation \
--cluster $CLUSTER_NAME \
--namespace default \
--service-account-name s3-sa \
--role-name s3-eks-pod-identity-role \
--permission-policy-arns arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess \
--region ap-northeast-2
## 확인
kubectl get sa
eksctl get podidentityassociation --cluster $CLUSTER_NAME
aws eks list-pod-identity-associations --cluster-name $CLUSTER_NAME | jq
## ABAC 지원을 위해 sts:Tagsession 추가
aws iam get-role --query 'Role.AssumeRolePolicyDocument' --role-name s3-eks-pod-identity-role | jq .



권한 테스트
## service account 생성
k create sa s3-sa
## pod 생성
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: eks-pod-identity
spec:
serviceAccountName: s3-sa
containers:
- name: my-aws-cli
image: amazon/aws-cli:latest
command: ['sleep', '36000']
restartPolicy: Never
terminationGracePeriodSeconds: 0
EOF
## 권한 확인
k get pod eks-pod-identity -o yaml | k neat
k exec -it eks-pod-identity -- aws sts get-caller-identity --query Arn
k exec -it eks-pod-identity -- aws s3 ls
k exec -it eks-pod-identity -- env | grep AWS



OWASP kubernetes Top Ten
K8s 보안 위협
- DDoS 공격
- SSRF 공격
- 권한 상승 공격 (privilige escalation)
- 악성코드 삽입 (Cross Site scripting)
- 취약점 공격
- Public Access
- 취약한 컨테이너 이미지
- Code Repository
- Image Repository

Kyverno
1. Kyverno는 Kubernetes 클러스터에서 정책을 정의하고 적용하는 정책 엔진이다.
2. YAML 기반의 Kubernetes 네이티브 방식으로 동작하며, 추가적인 외부 정책 언어 없이 정책을 관리할 수 있다.
3. Validating, Mutating, Generating 정책을 통해 리소스 검증, 수정, 자동 생성이 가능하다.
4. OPA(Open Policy Agent)와 달리, Kubernetes 리소스와 자연스럽게 통합되도록 설계되었다.
5. 보안, 규정 준수, RBAC 강화 및 자동화된 리소스 관리에 활용된다.
동작 : Dynamic Admission Control로 실행, Mutating/Validating admission 에서 동작하여 허용/거부 결과 반환


설치
## 네임스페이스 생성
k create ns kyverno
## helm 배포
# value 파일 작성
cat << EOF > kyverno-value.yaml
config:
resourceFiltersExcludeNamespaces: [ kube-system ]
admissionController:
serviceMonitor:
enabled: true
backgroundController:
serviceMonitor:
enabled: true
cleanupController:
serviceMonitor:
enabled: true
reportsController:
serviceMonitor:
enabled: true
EOF
# helm repo 추가
helm repo add kyverno https://kyverno.github.io/kyverno/
# helm 설치
helm install kyverno kyverno/kyverno --version 3.3.7 -f kyverno-value.yaml -n kyverno
## 설치 확인
k get all -n kyverno
k get crd | grep kyverno
k get pod,svc -n kyverno
## step-cli 설치 (운영 서버에서)
wget https://dl.smallstep.com/cli/docs-cli-install/latest/step-cli_amd64.rpm
sudo rpm -i step-cli_amd64.rpm
kubectl -n kyverno get secret
kubectl -n kyverno get secret kyverno-svc.kyverno.svc.kyverno-tls-ca -o jsonpath='{.data.tls\.crt}' | base64 -d
kubectl -n kyverno get secret kyverno-svc.kyverno.svc.kyverno-tls-ca -o jsonpath='{.data.tls\.crt}' | base64 -d | step certificate inspect --short


- prometheus

- Grafana kyverno 대시보드

Policy and Role : Kyverno Policy는 rules 모음

- 각 규칙은 match 선언, 선택적 exclue 선언 및 validate, mutate, generate 또는 verifyImages 선언 중 하나로 구성됩니다.
- 각 규칙에는 단일 validate, mutate, generate 또는 verifyImages 하위 선언만 포함될 수 있습니다.
Validation : 파드에 라벨(lables) 검증
## Cluster Policy 적용
kubectl apply -f- << EOF
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: require-labels
spec:
validationFailureAction: Enforce
rules:
- name: check-team
match:
any:
- resources:
kinds:
- Pod
validate:
message: "label 'team' is required"
pattern:
metadata:
labels:
team: "?*"
EOF

- deployment 생성 시 kyverno 정책으로 오류 발생 확인

- 정책에 맞게 label 설정하여 재생성

- 정책 리포트 확인


- 이런 label 정책이 적용되어 있을 경우 위와 같이 run으로 pod를 생성하거나,
yaml 파일에 명시적으로 label을 지정해 deployment를 생성하면 정상적으로 생성할 수 있다.
Mutation : 파드에 라벨(lables) 추가
kubectl apply -f- << EOF
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: add-labels
spec:
rules:
- name: add-team
match:
any:
- resources:
kinds:
- Pod
mutate:
patchStrategicMerge:
metadata:
labels:
+(team): bravo
EOF

- 파드 생성 후 라벨 확인

- 새로운 파드 생성 후 label 확인

파드 생성 시 라벨을 지정하지 않으면, kubectl run redis의 run=redis와 정책에 지정된 team=bravo가 자동으로 지정되지만
생성자가 명시적으로 label을 지정할 경우에는 run=redis 라벨은 추가되지 않습니다.
Kyverno는 정책 위반이 발생하는 경우에만 Label을 추가하거나 수정합니다.
'Cloud > AWS' 카테고리의 다른 글
[EKS] Blue-Green Migration (0) | 2025.04.06 |
---|---|
[AWS] EKS Mode/Nodes (0) | 2025.03.23 |
[AWS] EKS Autoscaler - Karpenter (0) | 2025.03.09 |
[AWS] EKS Autoscaler - CPA (0) | 2025.03.09 |
[AWS] EKS Autoscaler - CAS (0) | 2025.03.09 |