Infograb logo
Kubernetes 접근 문제 해결

이 페이지에서는 Kubernetes의 일반적인 문제와 이를 해결하는 방법을 설명합니다.

"호스트 이름에 대한 권한 없음"으로 클러스터에 조인하지 못한 에이전트

증상

에이전트가 재시작 후 Teleport 클러스터에 다시 조인하지 못하고 다음과 유사한 오류를 보고합니다:

ssh: handshake failed: ssh: no authorities for hostname

설명

Teleport는 각 구성 요소에 대한 인증서를 서명하기 위해 인증 기관(CA)을 사용합니다. 구성 요소가 클러스터에 처음 조인할 때, 클러스터의 CA에 의해 서명된 인증서를 수신하고 이를 상태 디렉토리에 저장합니다. 구성 요소가 재시작하면 상태 디렉토리에 저장된 인증서를 사용하여 클러스터에 다시 조인합니다.

이 오류는 구성 요소가 Teleport 클러스터에 다시 조인하려고 할 때 발생하지만, 클러스터의 CA가 변경되어 구성 요소의 인증서가 더 이상 유효하지 않을 때 발생합니다.

이는 클러스터의 CA가 회전되거나 클러스터가 재생성되거나 이름이 변경될 때 발생할 수 있습니다.

해결 방법

에이전트의 상태를 재설정해야 하므로 새 인증서를 요청하고 클러스터에 다시 조인할 수 있습니다.

에이전트의 상태를 삭제하는 과정은 에이전트가 Kubernetes 내부에서 실행되는지 외부에서 실행되는지에 따라 다릅니다.

Kubernetes 외부에서 실행되는 에이전트 (독립형)

에이전트가 Kubernetes 외부에서 실행되는 경우, 상태 디렉토리는 기본적으로 /var/lib/teleport/proc 에 있습니다. 다음 명령어를 사용하여 상태 디렉토리를 삭제할 수 있습니다:

sudo rm -rf /var/lib/teleport/proc

그런 다음 에이전트를 재시작합니다:

sudo systemctl restart teleport

Kubernetes에서 실행되는 에이전트 (teleport-kube-agent )

Teleport 11부터 teleport-kube-agent 파드의 상태는 설치 네임스페이스에 존재하는 Kubernetes 비밀 - 이름:{pod-name}-state - 에 저장됩니다. 상태를 삭제하려면 아래 단계를 따르십시오:

teleport-kube-agent 파드의 비밀 가져오기

kubectl get secret -o name -n teleport-agent | grep "state"
teleport-agent-0-stateteleport-agent-1-state

비밀 삭제

kubectl delete secret -n teleport-agent teleport-agent-0-state teleport-agent-1-state

컨테이너에 /var/lib/teleport 를 마운트하고 있다면, 컨테이너 내부의 /var/lib/teleport/proc 내용을 청소한 다음 컨테이너를 재시작하십시오.

상태가 삭제된 후 각 에이전트 파드를 재시작합니다.

GKE Autopilot 클러스터에 연결할 수 없음

GKE Warden authz [denied by user-impersonation-limitation]: impersonating system identities are not allowed

증상

Teleport에서 GKE Autopilot 클러스터를 구성한 후, Kubernetes 객체를 검색하려고 시도할 때 모든 시도가 다음과 유사한 오류로 실패합니다:

또는 다음과 같은 오류가 발생합니다:

GKE Autopilot denies requests that impersonate "system:masters" group

이 문제는 GKE Autopilot 클러스터에만 영향을 미칩니다. 표준 GKE 클러스터를 사용하는 경우 이 문제는 적용되지 않습니다.

설명

표준 Kubernetes 클러스터와 달리 Autopilot 클러스터는 시스템 ID를 가장하는 요청을 금지합니다. 이는 사용자가 클러스터의 제어 평면에 접근하고 관리 작업을 수행하는 것을 방지하기 위한 보안 기능입니다. 사용자가 다른 사용자 또는 그룹을 가장할 수 있는 경우 타 사용자와 그룹의 권한을 강화합니다. GKE Autopilot 보안에 대해 더 알아보기.

Teleport는 사용자를 대신하여 Kubernetes 객체를 검색하기 위해 가장을 사용합니다. 이는 Kubernetes API 서버에 사용자의 신원을 Impersonate-User 헤더에, 사용자가 사용할 수 있는 모든 Kubernetes 그룹을 Impersonate-Group 헤더에 포함하여 요청을 보내는 방식으로 이루어집니다.

system:masters 는 모든 클러스터에서 built-in Kubernetes 그룹이므로, 관리자가 클러스터의 제어 평면에 대한 관리 액세스를 얻기 위해 이를 사용하는 것이 일반적입니다. 그러나 Autopilot 클러스터는 이 그룹을 가장하는 것을 금지하며 대신 다른 그룹을 사용해야 합니다.

해결책

위 설명에 따라, 솔루션은 Teleport에서 임시 권한 부여를 위해 다른 그룹을 구성하는 것입니다. 이는 역할의 kubernetes_group 매개변수를 Autopilot 클러스터가 임시 권한을 부여하는 그룹으로 설정함으로써 수행할 수 있습니다.

teleport-kube-agent 차트는 대상 클러스터가 GKE 클러스터일 때 system:masters 그룹과 동일한 접근 수준을 가진 Kubernetes 그룹을 구성합니다. 이 그룹은 기본적으로 cluster-admin 이라고 명명되지만, adminClusterRoleBinding.name 매개변수를 설정하여 이름을 변경할 수 있습니다.

Kubernetes 그룹은 비-GKE 클러스터에 차트를 설치할 때 자동으로 생성되지 않으므로, 그룹을 수동으로 생성하거나 adminClusterRoleBinding.create 매개변수를 true 로 설정하여 차트를 설치하지 않는 한 kubernetes_groups 매개변수를 cluster-admin 으로 변경하지 마십시오.

그룹은 임시 권한 부여에 사용되기 전에 클러스터에 구성되어야 한다는 점에 유의하는 것이 중요합니다. 그룹이 구성되지 않으면 임시 권한 요청이 403 Forbidden 오류와 함께 실패하며 사용자는 클러스터에 접근할 수 없습니다.

비-Autopilot 클러스터에서 임시 권한 부여를 위해 system:masters 그룹을 계속 사용하기로 선택한 경우, system:masters 접근을 부여하는 Teleport 역할이 GKE Autopilot 클러스터에 접근하는 데 사용될 수 없도록 해야 합니다.

예를 들어, 다음 역할을 가진 사용자는 모든 Kubernetes 클러스터에서 system:masters 그룹을 임시로 부여할 수 있습니다:

kind: role
version: v7
metadata:
  name: k8s-admin
spec:
  allow:
    kubernetes_labels:
      "*": "*"
    kubernetes_groups: ["system:masters"]

kubernetes_labels 의 와일드카드 *는 사용자가 Teleport 클러스터의 모든 Kubernetes 클러스터에 접근할 수 있도록 허용합니다. 해당 역할로 GKE Autopilot 클러스터에 접근하는 것을 방지하려면, 클러스터를 Autopilot 클러스터로 식별하는 레이블로 teleport-kube-agent 차트를 설치할 수 있습니다. 예를 들어:

PROXY_ADDR=teleport.example.com:443
CLUSTER=cookie

values.yaml 파일 생성

cat > values.yaml << EOFauthToken: "${TOKEN}"proxyAddr: "${PROXY_ADDR}"roles: "kube,app,discovery"joinParams: method: "token" tokenName: "${TOKEN}"kubeClusterName: "${CLUSTER}"labels: "type" : "autopilot"EOF

values.yaml 설정으로 helm 차트 설치

helm install teleport-agent teleport/teleport-kube-agent \ -f values.yaml \ --create-namespace \ --namespace=teleport-agent \ --version 17.0.0-dev

Teleport 에이전트 포드가 실행되고 있는지 확인하십시오. 준비된 컨테이너 하나를 가진 텔레포트 에이전트 포드가 하나 있어야 합니다:

kubectl -n teleport-agent get pods
NAME READY STATUS RESTARTS AGEteleport-agent-0 1/1 Running 0 32s

이제 클러스터가 레이블이 지정되었으므로, k8s-admin 역할을 두 개의 역할로 나눌 수 있습니다: 하나는 모든 비-Autopilot 클러스터에 대한 접근을 허용하고, 다른 하나는 Autopilot 클러스터에만 접근을 허용합니다.

kind: role
version: v7
metadata:
  name: k8s-admin-non-gke-autopilot
spec:
  allow:
    kubernetes_labels_expression: 'labels["type"] != "autopilot"'
    kubernetes_groups: ["system:masters"]
---
kind: role
version: v7
metadata:
  name: k8s-admin-gke-autopilot
spec:
  allow:
    kubernetes_labels_expression: 'labels["type"] == "autopilot"'
    kubernetes_groups: ["cluster-admin"]

역할이 생성되면, 이를 사용자에게 일반적으로 할당할 수 있지만 즉시 적용되려면 사용자들은 로그아웃한 후 다시 로그인 해야 합니다.

Kubernetes 1.30+에서 Pod에 exec할 수 없음

pods "<pod_name>"은 금지되었습니다: 사용자 "<user>"는 네임스페이스 "<namespace>"에서 API 그룹 ""의 "pods/exec" 리소스를 가져올 수 없습니다.

증상

kubectl 을 버전 1.30 이상으로 업그레이드한 후, Pod에 exec 하려고 하면 다음과 유사한 오류가 발생합니다:

pods "<pod_name>"은 금지되었습니다: 사용자 "<user>"는 네임스페이스 "<namespace>"에서 API 그룹 ""의 "pods/exec" 리소스를 가져올 수 없습니다.

설명

Kubernetes 1.30부터 kubectl exec 명령은 Kubernetes API 서버와 통신하기 위해 SPDY 프로토콜 대신 WebSocket 프로토콜을 사용하도록 변경되었습니다. 이 변경은 kubectl exec 명령의 성능과 신뢰성을 향상시키기 위한 것으로, SPDY 프로토콜은 더 이상 사용되지 않게 되었습니다.

WebSocket은 SPDY를 대체하기 위한 것이라고 여겨졌지만, pods/exec 리소스에 대한 접근을 오직 create 동사만으로 제한하도록 RBAC가 구성된 Kubernetes 클러스터에 대해 중단되는 변경 사항을 초래했습니다. 이전에는 SPDY 프로토콜이 연결을 생성하기 위한 GET (Kubernetes RBAC에서 get 으로 매핑됨) 또는 POST (Kubernetes RBAC에서 create 으로 매핑됨)를 모두 허용했었습니다.

WebSocket 프로토콜을 사용하면 kubectl exec 명령이 항상 GET 방법을 사용하여 연결을 생성합니다. 이는 RBAC 정책이 오직 create 동사만 허용하는 경우 연결이 거부된다는 것을 의미합니다.

해결 방법

이 문제를 해결하려면 RBAC 정책을 업데이트하여 pods/exec (하위) 리소스에 대한 get 동사를 허용해야 합니다. 이는 사용자가 접근할 수 있는 ClusterRole 또는 Role 을 수정하여 수행할 수 있습니다.

예를 들어, pods/exec 리소스에 대한 create 동사를 허용하는 ClusterRole 이 있다면, 이를 get 동사를 허용하도록 업데이트해야 합니다:

- apiGroups: [""]
  resources: ["pods/exec"]
  verbs: ["create", "get"]

ClusterRole 이 업데이트되면 이제 kubectl 버전 1.30 이상을 사용하여 Pod에 exec할 수 있어야 합니다.

Teleport 원문 보기