실습
Authentication - EKS
kubeconfig 파일 리뷰
kubectl config view
kubeconfig에 명시된 users 확인 - https://kubernetes.io/docs/reference/access-authn-authz/authentication/#client-go-credential-plugins
kubectl config view | yq e '.users' -
user에 명시된 명령어 실행
$(kubectl config view \ -o=jsonpath='{.users[0].user.exec.command} {.users[0].user.exec.args[*]}')
토큰값을 환경변수로 지정 - Base64로 인코딩된 부분만 캡쳐
{ export TOKEN=$($(kubectl config view \ -o=jsonpath='{.users[0].user.exec.command} {.users[0].user.exec.args[*]}') \ | jq -r '.status.token' | grep -oP '(?<=k8s-aws-v1.).*') echo $TOKEN }
Base64URL 유틸리티 설치
npm install -g base64-url-cli
토큰값을 디코딩해서 환경변수로 지정
{ export DECODED_URL=$(base64url decode $TOKEN) echo $DECODED_URL }
Node에 부여된 Label을 통해서 EKS 클러스터 이름 확인하고 환경변수로 저장
{ export CLUSTER_NAME=$(kubectl get node \ -o=jsonpath='{.items[0].metadata.labels.alpha\.eksctl\.io\/cluster-name}') echo $CLUSTER_NAME }
디코딩한 URL 호출
curl -H "x-k8s-aws-id: $CLUSTER_NAME" $DECODED_URL
현재 설정된 AWS 자격증명을 확인
aws sts get-caller-identity
API 서버 주소를 확인하고 환경변수로 지정
{ export K8S_SERVER=$(kubectl config view \ -o=jsonpath='{.clusters[*].cluster.server}') echo $K8S_SERVER }
Node 목록을 보는 API 호출
curl -k -X GET \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ $K8S_SERVER/api/v1/nodes
토큰값을 환경변수로 지정
{ export TOKEN=$($(kubectl config view \ -o=jsonpath='{.users[0].user.exec.command} {.users[0].user.exec.args[*]}') \ | jq -r '.status.token') echo $TOKEN }
Node 목록을 보는 API 호출
curl -k -X GET \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ $K8S_SERVER/api/v1/nodes
IAM 유저 생성
aws iam create-user --user-name john
위에서 생성한 IAM 유저의 Access Key 생성
aws iam create-access-key --user-name john > key.txt
Access Key가 정상적으로 생성되었는지 확인
cat key.txt
AWS CLI 자격증명 파일 및 설정 파일 백업
{ cp ~/.aws/credentials ~/.aws/credentials_backup cp ~/.aws/config ~/.aws/config_backup }
위에서 생성한 Access Key를 AWS CLI 자격증명 파일에 반영
{ cat <<EOF >> ~/.aws/credentials [john] aws_access_key_id=$(cat key.txt | jq -r '.AccessKey.AccessKeyId') aws_secret_access_key=$(cat key.txt | jq -r '.AccessKey.SecretAccessKey') EOF cat <<EOF >> ~/.aws/config [profile john] region = ap-northeast-2 EOF }
위에서 명시한 프로필을 통해서 AWS API 호출
aws sts get-caller-identity --profile john
kubeconfig 파일 삭제
rm -rf ~/.kube/config
쿠버네티스 API 호출 시도
kubectl get pod -A
새로 생성한 IAM 유저의 자격증명으로 AWS CLI를 이용해서 kubeconfig 파일 생성
aws eks update-kubeconfig --name $CLUSTER_NAME --profile john
IAM 유저에서 eks:DescribeCluster 권한 부여
aws iam put-user-policy --user-name john --policy-name eks-admin --policy-document \ '{ "Version": "2012-10-17", "Statement": [ { "Action": [ "eks:DescribeCluster" ], "Resource": "*", "Effect": "Allow" } ] }'
IAM 정책이 부여되었는지 확인
{ aws iam list-user-policies --user-name john aws iam get-user-policy --user-name john --policy-name eks-admin }
새로 생성한 IAM 유저의 자격증명으로 AWS CLI를 이용해서 kubeconfig 파일 생성 - 정책 적용까지 시간이 걸릴수 있음
aws eks update-kubeconfig --name $CLUSTER_NAME --profile john
새로 생성된 kubeconfig 파일 리뷰
kubectl config view
쿠버네티스 API 호출 시도
kubectl get pod -A
user에 명시된 명령어 실행
{ export $(kubectl config view -o=jsonpath='{.users[0].user.exec.env[0].name}={.users[0].user.exec.env[0].value}') $(kubectl config view \ -o=jsonpath='{.users[0].user.exec.command} {.users[0].user.exec.args[*]}') }
토큰값을 환경변수로 지정 - Base64로 인코딩된 부분만 캡쳐
{ export TOKEN=$($(kubectl config view \ -o=jsonpath='{.users[0].user.exec.command} {.users[0].user.exec.args[*]}') \ | jq -r '.status.token' | grep -oP '(?<=k8s-aws-v1.).*') echo $TOKEN }
토큰값을 디코딩해서 환경변수로 지정
{ export DECODED_URL=$(base64url decode $TOKEN) echo $DECODED_URL }
디코딩한 URL 호출
curl -H "x-k8s-aws-id: $CLUSTER_NAME" $DECODED_URL
어드민 IAM 유저의 자격증명으로 AWS CLI를 이용해서 kubeconfig 파일 업데이트
{ rm -rf ~/.kube/config unset AWS_PROFILE aws eks update-kubeconfig --name $CLUSTER_NAME }
Authorization
aws-auth ConfigMap 리뷰 - https://docs.aws.amazon.com/eks/latest/userguide/add-user-role.html, https://aws.amazon.com/premiumsupport/knowledge-center/amazon-eks-cluster-access
kubectl -n kube-system get configmap aws-auth -o yaml
ClusterRole 목록 확인
kubectl get clusterrole
cluster-admin ClusterRole 리뷰
kubectl get clusterrole cluster-admin -o yaml
ClusterRoleBinding 목록 확인
kubectl get clusterrolebinding
cluster-admin ClusterRoleBinding 리뷰
kubectl get clusterrolebinding cluster-admin -o yaml
현재 kubeconfig에 설정된 유저의 자격증명으로 수행할수 있는 API 목록 확인
kubectl auth can-i --list
aws-auth ConfigMap에 명시된 MapRoles 내용 확인 - https://kubernetes.io/docs/reference/access-authn-authz/node/
kubectl -n kube-system get configmap aws-auth -o yaml | yq e '.data' -
한개의 Node의 인스턴스 ID를 확인하고 환경변수로 지정
{ export INSTANCE_ID=$(kubectl get node -o jsonpath='{.items[0].spec.providerID}' \ | grep -oE "i-[a-z0-9]+") echo $INSTANCE_ID }
Node에 부여된 IAM 인스턴스 프로필을 확인하고 환경변수로 지정
{ export INSTANCE_PROFILE=$(aws ec2 describe-instances --instance-ids $INSTANCE_ID \ --query 'Reservations[0].Instances[0].IamInstanceProfile.Arn' \ --output text | grep -oE "[a-z0-9-]+$") echo $INSTANCE_PROFILE }
위에서 확인한 인스턴스 프로필에 연동된 IAM 역할 확인
aws iam get-instance-profile --instance-profile-name $INSTANCE_PROFILE \ --query 'InstanceProfile.Roles[0].Arn' --output text
view ClusterRole 리뷰
kubectl get clusterrole view -o yaml
ClusterRoleBinding 생성
cat <<EOF | kubectl apply -f - kind: ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: readonly subjects: - kind: Group name: readonly apiGroup: rbac.authorization.k8s.io roleRef: kind: ClusterRole name: view apiGroup: rbac.authorization.k8s.io EOF
Node에 부여된 Label을 통해서 EKS 클러스터 이름을 확인하고 환경변수로 저장
{ export CLUSTER_NAME=$(kubectl get node \ -o=jsonpath='{.items[0].metadata.labels.alpha\.eksctl\.io\/cluster-name}') echo $CLUSTER_NAME }
EKS 클러스터가 생성되어 있는 AWS 계정번호 확인하고 환경변수로 저장
{ export ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text) echo $ACCOUNT_ID }
aws-auth ConfigMap에 규칙 추가
eksctl create iamidentitymapping --cluster $CLUSTER_NAME \ --arn arn:aws:iam::$ACCOUNT_ID:user/john \ --username arn:aws:iam::$ACCOUNT_ID:user/john \ --group readonly
aws-auth ConfigMap 변경분 확인
kubectl -n kube-system get configmap aws-auth -o yaml
john IAM 유저의 자격증명으로 AWS CLI를 이용해서 kubeconfig 파일 업데이트
{ rm -rf ~/.kube/config aws eks update-kubeconfig --name $CLUSTER_NAME --profile john }
현재 kubeconfig에 설정된 유저의 자격증명으로 수행할수 있는 API 목록 확인
kubectl auth can-i --list
클러스터에 생성된 Pod 목록 확인
kubectl get pod -A
Pod 생성 시도
kubectl run nginx --image=nginx
IAM 역할 생성
{ cat > trust-policy.json <<EOF { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "AWS": [ "arn:aws:iam::$ACCOUNT_ID:root" ] }, "Action": "sts:AssumeRole" } ] } EOF aws iam create-role --role-name eks-admin-role \ --assume-role-policy-document file://trust-policy.json }
aws-auth ConfigMap에 규칙 추가
eksctl create iamidentitymapping --cluster $CLUSTER_NAME \ --arn arn:aws:iam::$ACCOUNT_ID:role/eks-admin-role \ --username devops \ --group system:masters
aws-auth ConfigMap 변경분 확인
kubectl -n kube-system get configmap aws-auth -o yaml
john IAM 유저의 자격증명으로 위에서 생성한 IAM 역할 전환하는 설정 추가해서 kubeconfig 파일 업데이트
{ rm -rf ~/.kube/config aws eks update-kubeconfig --name $CLUSTER_NAME --profile john \ --role-arn arn:aws:iam::$ACCOUNT_ID:role/eks-admin-role }
새로 생성된 kubeconfig 파일 리뷰
kubectl config view
쿠버네티스 API 호출 시도
kubectl get pod -A
john IAM 유저에서 sts:AssumeRole 권한 부여
aws iam put-user-policy --user-name john --policy-name assume-role --policy-document \ '{ "Version": "2012-10-17", "Statement": [ { "Action": [ "sts:AssumeRole" ], "Resource": "*", "Effect": "Allow" } ] }'
IAM 정책이 부여되었는지 확인
{ aws iam list-user-policies --user-name john aws iam get-user-policy --user-name john --policy-name assume-role }
쿠버네티스 API 호출 시도 - 정책 적용까지 시간이 걸릴수 있음
kubectl get pod -A
user에 명시된 명령어 실행
{ export $(kubectl config view -o=jsonpath='{.users[0].user.exec.env[0].name}={.users[0].user.exec.env[0].value}') $(kubectl config view \ -o=jsonpath='{.users[0].user.exec.command} {.users[0].user.exec.args[*]}') }
토큰값을 환경변수로 지정 - Base64로 인코딩된 부분만 캡쳐
{ export TOKEN=$($(kubectl config view \ -o=jsonpath='{.users[0].user.exec.command} {.users[0].user.exec.args[*]}') \ | jq -r '.status.token' | grep -oP '(?<=k8s-aws-v1.).*') echo $TOKEN }
토큰값을 디코딩해서 환경변수로 지정
{ export DECODED_URL=$(base64url decode $TOKEN) echo $DECODED_URL }
디코딩한 URL 호출
curl -H "x-k8s-aws-id: $CLUSTER_NAME" $DECODED_URL
어드민 IAM 유저의 자격증명으로 AWS CLI를 이용해서 kubeconfig 파일 업데이트
{ rm -rf ~/.kube/config unset AWS_PROFILE aws eks update-kubeconfig --name $CLUSTER_NAME }
리소스 삭제
{ aws iam delete-access-key --user-name john --access-key-id $(cat key.txt | jq -r '.AccessKey.AccessKeyId') aws iam delete-user-policy --user-name john --policy-name eks-admin aws iam delete-user-policy --user-name john --policy-name assume-role aws iam delete-user --user-name john kubectl delete clusterrolebinding readonly aws iam delete-role --role-name eks-admin-role eksctl delete iamidentitymapping --cluster $CLUSTER_NAME --arn arn:aws:iam::$ACCOUNT_ID:role/eks-admin-role eksctl delete iamidentitymapping --cluster $CLUSTER_NAME --arn arn:aws:iam::$ACCOUNT_ID:user/john mv ~/.aws/credentials_backup ~/.aws/credentials mv ~/.aws/config_backup ~/.aws/config rm key.txt trust-policy.json }
Service Account
Pod 생성
kubectl run nginx --image=nginx
Pod 생성 확인
kubectl get pod nginx
Pod에 부여된 ServiceAccount 확인
kubectl get pod nginx -o=jsonpath='{.spec.serviceAccountName}{"\n"}'
default 네임스페이스에 존재하는 ServiceAccount 목록 확인
kubectl get sa
ServiceAccount 생성
kubectl create sa kubectl-access
Pod 생성
cat <<EOF | kubectl apply -f - apiVersion: v1 kind: Pod metadata: name: kubectl spec: serviceAccountName: kubectl-access containers: - image: bitnami/kubectl name: kubectl command: ["sleep", "3600"] EOF
생성된 Pod 안에서 포함된 kubectl을 통해서 kube-system 네임스페이스에 있는 Pod 목록 확인
kubectl exec kubectl -- kubectl get pod -n kube-system
위에서 생성한 ServiceAccount에 부여된 권한 확인
kubectl auth can-i --list --as system:serviceaccount:default:kubectl-access
ClusterRole 생성
cat <<EOF | kubectl apply -f - kind: ClusterRole apiVersion: rbac.authorization.k8s.io/v1 metadata: name: pod-access rules: - apiGroups: [""] resources: ["pods"] verbs: ["get", "list", "watch"] EOF
RoleBinding 생성
cat <<EOF | kubectl apply -f - kind: RoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: pod-access namespace: kube-system subjects: - kind: ServiceAccount name: kubectl-access namespace: default roleRef: kind: ClusterRole name: pod-access apiGroup: rbac.authorization.k8s.io EOF
생성된 Pod 안에서 포함된 kubectl을 통해서 kube-system 네임스페이스에 있는 Pod 목록 확인
kubectl exec kubectl -- kubectl get pod -n kube-system
생성된 Pod 안에서 포함된 kubectl을 통해서 default 네임스페이스에 있는 Pod 목록 확인
kubectl exec kubectl -- kubectl get pod
위에서 생성한 ServiceAccount에 부여된 권한 확인
kubectl auth can-i --list --as system:serviceaccount:default:kubectl-access
위에서 생성한 ServiceAccount에 kube-system 네임스페이스에 대해서 부여된 권한 확인
kubectl auth can-i --list -n kube-system \ --as system:serviceaccount:default:kubectl-access
리소스 삭제
{ kubectl delete pod kubectl nginx kubectl delete rolebinding pod-access -n kube-system kubectl delete clusterrole pod-access kubectl delete sa kubectl-access }
IAM roles for service accounts
Pod 생성
kubectl run aws-cli --image=amazon/aws-cli --command -- sleep 3600
Pod 생성 확인
kubectl get pod aws-cli
생성된 Pod에 부여된 AWS 자격증명 확인
kubectl exec aws-cli -- aws sts get-caller-identity
Pod가 배포된 Node 확인
kubectl get pod aws-cli -o wide
Pod가 배포된 Node의 인스턴스 ID를 확인하고 환경변수로 지정
{ export INSTANCE_ID=$(kubectl get node $(kubectl get pod aws-cli -o=jsonpath='{.spec.nodeName}') \ -o jsonpath='{.spec.providerID}{"\n"}' | grep -oE "i-[a-z0-9]+") echo $INSTANCE_ID }
Node에 부여된 IAM 인스턴스 프로필을 확인하고 환경변수로 지정
{ export INSTANCE_PROFILE=$(aws ec2 describe-instances --instance-ids $INSTANCE_ID \ --query 'Reservations[0].Instances[0].IamInstanceProfile.Arn' \ --output text | grep -oE "[a-z0-9-]+$") echo $INSTANCE_PROFILE }
위에서 확인한 인스턴스 프로필에 연동된 IAM 역할 확인
aws iam get-instance-profile --instance-profile-name $INSTANCE_PROFILE \ --query 'InstanceProfile.Roles[0].Arn' --output text
Pod에 부여된 AWS 자격증명 확인
kubectl exec aws-cli -- aws sts get-caller-identity
Pod에서 EC2 인스턴스 메타데이터를 통해서 상속받는 자격증명 확인
kubectl exec aws-cli -- \ curl -s -w "\n" http://169.254.169.254/latest/meta-data/iam/security-credentials
위에서 확인한 자격증명에 부여된 Access Key 확인
kubectl exec aws-cli -- bash -c \ 'curl -s -w "\n" http://169.254.169.254/latest/meta-data/iam/security-credentials/$(curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials)'
AWS CLI가 자격증명을 불러오는 순서 확인
kubectl exec aws-cli -- aws sts get-caller-identity --debug
Node에 부여된 Label을 통해서 EKS 클러스터 이름을 확인하고 환경변수로 저장
{ export CLUSTER_NAME=$(kubectl get node \ -o=jsonpath='{.items[0].metadata.labels.alpha\.eksctl\.io\/cluster-name}') echo $CLUSTER_NAME }
ServiceAccount 생성
eksctl create iamserviceaccount \ --cluster=$CLUSTER_NAME \ --namespace=default \ --name=aws-cli \ --attach-policy-arn=arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess \ --override-existing-serviceaccounts \ --approve
생성된 ServiceAccount 확인
kubectl get sa aws-cli
ServiceAccount에 명시된 IAM 역할 이을 확인하고 환경변수로 지정
{ IAM_ROLE_NAME=$(kubectl get sa aws-cli \ -o=jsonpath='{.metadata.annotations.eks\.amazonaws\.com\/role-arn}' \ | grep -oP '(?<=role.).*') echo $IAM_ROLE_NAME }
ServiceAccount와 연동된 IAM 역할에 부여된 IAM 정책 확인
aws iam list-attached-role-policies --role-name $IAM_ROLE_NAME
ServiceAccount와 연동된 IAM 역할에 부여된 신뢰관계 정책 확인
aws iam get-role --role-name $IAM_ROLE_NAME
EKS 클러스터에 연동된 OIDC 제공자 확인
aws eks describe-cluster --name $CLUSTER_NAME \ --query "cluster.identity.oidc.issuer" --output text
Pod를 재생성하고 위에서 생성한 ServiceAccount 부여
cat <<EOF | kubectl replace --force -f - apiVersion: v1 kind: Pod metadata: name: aws-cli spec: serviceAccountName: aws-cli containers: - name: aws-cli image: amazon/aws-cli command: ["sleep", "3600"] EOF
Pod에 부여된 AWS 자격증명 확인
kubectl exec aws-cli -- aws sts get-caller-identity
Pod에서 EC2 인스턴스 메타데이터를 통해서 상속받는 자격증명 확인
kubectl exec aws-cli -- \ curl -s -w "\n" http://169.254.169.254/latest/meta-data/iam/security-credentials
AWS CLI가 자격증명을 불러오는 순서 확인
kubectl exec aws-cli -- aws sts get-caller-identity --debug
Pod에 지정된 환경변수 확인
kubectl exec aws-cli -- printenv
Pod에 생성된 AWS 임시토큰 파일 내용 확인
kubectl exec aws-cli -- bash -c 'cat $AWS_WEB_IDENTITY_TOKEN_FILE'
위에서 확인한 토큰 내용 확인
jq -R 'split(".") | .[0],.[1] | @base64d | fromjson' <<<\ $(kubectl exec aws-cli -- bash -c 'cat $AWS_WEB_IDENTITY_TOKEN_FILE')
ServiceAccount와 연동된 IAM 역할에 부여된 신뢰관계 정책 확인
aws iam get-role --role-name $IAM_ROLE_NAME
Pod에서 AWS CLI를 통해서 S3 버킷 목록 확인
kubectl exec aws-cli -- aws s3 ls
리소스 삭제
{ eksctl delete iamserviceaccount --cluster $CLUSTER_NAME --name aws-cli kubectl delete pod aws-cli }
Last updated