쿠버네티스 읽기 전용 ServiceAccount 생성 및 kubeconfig

💡 핵심 요약 (Executive Summary)

본 가이드는 readonly sa와 kubeconfig 핵심 가이드 및 실전 아키텍처의 핵심 개념, 실전 구성 명령어 및 아키텍처 베스트 프랙티스를 다룹니다. 클라우드 네이티브 및 인프라 엔지니어링 실무에 즉시 활용 가능하도록 체계적으로 정리했습니다.

📑 Table of Contents

readonly SA, Secrets, Kubeconfig

권한 생성
env
bash
export prefix=read-only
export ns=default
SA, token, CRB 생성
bash
kubectl create serviceaccount ${prefix}-sa -n ${ns}

kubectl apply -f - << EOF
apiVersion: v1
kind: Secret
metadata:
  name: ${prefix}-sa-token
  namespace: ${ns}
  annotations:
    kubernetes.io/service-account.name: "${prefix}-sa"
type: kubernetes.io/service-account-token
EOF

kubectl apply -f - << EOF
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: ${prefix}-clusterrolebinding
subjects:
  - kind: ServiceAccount
    name: ${prefix}-sa
    namespace: ${ns}
roleRef:
  kind: ClusterRole
  name: ${prefix}-clusterrole
  apiGroup: rbac.authorization.k8s.io
EOF

kubectl get secret ${prefix}-sa-token -n ${ns} -o jsonpath="{.data.token}" | base64 --decode
ClusterRole 정의
  • 최소 권한 정책(Principle of Least Privilege, POLP)을 적용
bash
kubectl apply -f - << EOF
  apiVersion: rbac.authorization.k8s.io/v1
  kind: ClusterRole
  metadata:
    name: ${prefix}-clusterrole
  rules:
    - apiGroups: ["","apps","batch","autoscaling","app.k8s.io"]
      resources: ["pods","services","replicasets","deployments","daemonsets","statefulsets","replicationcontrollers","horizontalpodautoscalers","cronjobs","jobs","applications"]
      verbs: ["get", "list", "watch"]
    - apiGroups: ["apiextensions.k8s.io"]
      resources: ["customresourcedefinitions"]
      verbs: ["get", "list", "watch"]
  EOF
  • OPA를 통한 예외사항 관리
bash
kubectl apply -f - << EOF
  apiVersion: rbac.authorization.k8s.io/v1
  kind: ClusterRole
  metadata:
    name: ${prefix}-clusterrole
  rules:
    - apiGroups: ["*"]
      resources: ["*"]
      verbs: ["get", "list", "watch"]
  EOF

  #ex) read-only로 시작하는 sa or clusterrole or role을 제한
  kubectl apply -f - << EOF
  apiVersion: templates.gatekeeper.sh/v1
  kind: ConstraintTemplate
  metadata:
    name: deny-read-only-access
  spec:
    crd:
      spec:
        names:
          kind: DenyReadOnlyAccess
    targets:
      - target: admission.k8s.gatekeeper.sh
    rego: |
      package denyreadonlyaccess

      violation[{"msg": msg}] {
        # 요청된 리소스가 Secret 또는 ServiceAccount인지 확인
        input.review.object.kind == "Secret" || input.review.object.kind == "ServiceAccount"

        # 요청된 동작이 get, list, watch 중 하나인지 확인
        input.review.operation == "GET" || input.review.operation == "LIST" || input.review.operation == "WATCH"

        # 요청한 사용자 정보 추출
        factor := "read-only"
        subject := input.review.userInfo.username

        # ServiceAccount, Role, ClusterRole 이름이 "read-only"로 시작하는지 확인
        startswith(subject, "system:serviceaccount:") {
          sa_name := split(subject, ":")[2]
          startswith(sa_name, factor)
        }
        startswith(subject, factor)

        msg := sprintf("'%s'로 시작하는 Role이나 ServiceAccount인 '%s'는 Secret 리소스에 접근할 수 없습니다.", [factor,subject])
      }
  EOF

  kubectl apply -f - << EOF
  apiVersion: constraints.gatekeeper.sh/v1beta1
  kind: DenySecretAccessConstraint
  metadata:
    name: deny-secret-access-for-users
  spec:
    match:
      kinds:
        - apiGroups: [""]
          kinds: ["Secret"]
      subjects:
        - kind: User
          name: "example-user"  # 특정 사용자
        - kind: Group
          name: "example-group" # 특정 그룹
  EOF
접근정보 생성
env
bash
export prefix=read-only
export ns=default
export clustername=kubernetes
export SERVER=
1안: certificate-authority-data를 포함한 kubeconfig 생성
bash
cat <<EOF >> kubeconfig
apiVersion: v1
kind: Config
clusters:
- name: ${clustername}
  cluster:
    certificate-authority-data: $(kubectl config view --raw -o jsonpath="{.clusters[0].cluster.certificate-authority-data}")
    server: ${SERVER}
contexts:
- name: ${prefix}-context
  context:
    cluster: ${clustername}
    namespace: ${ns}
    user: ${prefix}-user
current-context: ${prefix}-context
users:
- name: ${prefix}-user
  user:
    token: $(kubectl get secret ${prefix}-sa-token -n ${ns} -o jsonpath="{.data.token}" | base64 --decode)
EOF
2안: insecure-skip-tls-verify를 enable하고 kubeconfig 생성
bash
cat <<EOF >> kubeconfig
apiVersion: v1
kind: Config
clusters:
- name: ${clustername}
  cluster:
    insecure-skip-tls-verify: true
    server: ${SERVER}
contexts:
- name: ${prefix}-context
  context:
    cluster: ${clustername}
    namespace: ${ns}
    user: ${prefix}-user
current-context: ${prefix}-context
users:
- name: ${prefix}-user
  user:
    token: $(kubectl get secret ${prefix}-sa-token -n ${ns} -o jsonpath="{.data.token}" | base64 --decode)
EOF
클라이언트 설정
bash
export prefix=read-only
kubectl config use-context ${prefix}-context

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *