InfoGrab Docs

Kubernetes 접근 문제 해결

요약

이 페이지에서는 Kubernetes와 관련된 일반적인 문제와 해결 방법을 설명합니다. 에이전트가 재시작 후 Teleport 클러스터에 다시 조인할 수 없고 다음과 유사한 오류를 보고합니다: Teleport는 인증 기관(CA)을 사용하여 각 구성 요소의 인증서에 서명합니다.

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

에이전트가 "no authorities for hostname"으로 인해 클러스터 조인 실패#

증상#

에이전트가 재시작 후 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-state
teleport-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
Note

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

설명#

표준 Kubernetes 클러스터와 달리 Autopilot 클러스터는 시스템 자격 증명을 가장(impersonate)하는 요청을 금지합니다. 이는 사용자 또는 그룹을 가장할 수 있다면 클러스터의 제어 플레인에 접근하여 관리 작업을 수행하는 것을 방지하기 위한 보안 기능입니다. GKE Autopilot 보안에 대해 자세히 알아보기.

Teleport는 가장(impersonation)을 사용하여 사용자를 대신하여 Kubernetes 객체를 검색합니다. 이는 Impersonate-User 헤더에 사용자의 자격 증명을 넣고 Impersonate-Group 헤더에 사용할 수 있는 모든 Kubernetes 그룹을 넣어 Kubernetes API 서버에 요청을 보내는 방식으로 이루어집니다.

system:masters는 모든 클러스터의 내장 Kubernetes 그룹이므로 관리자가 클러스터 제어 플레인에 대한 관리 접근 권한을 얻기 위해 이를 사용하는 것이 일반적입니다. 그러나 Autopilot 클러스터는 이 그룹을 가장하는 것을 금지하고 대신 다른 그룹을 사용하도록 요구합니다.

해결#

위의 설명에 따라 해결책은 Teleport에서 가장을 위한 다른 그룹을 구성하는 것입니다. 이는 역할의 kubernetes_groups 매개변수를 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 << EOF
authToken: "${TOKEN}"
proxyAddr: "${PROXY_ADDR}"
roles: "kube,app,discovery"
joinParams:
  method: "token"
  tokenName: "${TOKEN}"
kubeClusterName: "${CLUSTER}"
tags:
  "type" : "autopilot"
EOF
# values.yaml 설정으로 helm 차트 설치
$ helm install teleport-agent teleport/teleport-kube-agent \
  -f values.yaml \
  --create-namespace \
  --namespace=teleport-agent \
  --version (=teleport.version=)

Teleport 에이전트 파드가 실행 중인지 확인합니다. 단일 준비 컨테이너가 있는 하나의 Teleport 에이전트 파드가 표시되어야 합니다:

$ kubectl -n teleport-agent get pods
NAME               READY   STATUS    RESTARTS   AGE
teleport-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"]

역할이 생성되면 평소와 같이 사용자에게 할당할 수 있지만, 즉시 적용되려면 로그아웃 후 다시 로그인해야 합니다.

kubectl 1.30+에서 파드에 exec 불가#

pods "<pod_name>" is forbidden: User "<user>" cannot get resource "pods/exec" in API group "" in the namespace "<namespace>"

증상#

kubectl을 버전 1.30 이상으로 업그레이드한 후 파드에 exec하려는 시도가 다음과 유사한 오류로 실패합니다:

pods "<pod_name>" is forbidden: User "<user>" cannot get resource "pods/exec" in API group "" in the namespace "<namespace>"

설명#

Kubernetes 1.30부터 kubectl exec 명령은 Kubernetes API 서버와 통신하기 위해 SPDY 프로토콜에서 WebSocket 프로토콜로 전환했습니다. 이 변경은 SPDY 프로토콜이 더 이상 사용되지 않음에 따라 kubectl exec 명령의 성능과 신뢰성을 향상시키기 위한 것입니다.

WebSocket은 SPDY를 완전히 대체하기 위한 것이었지만, RBAC가 create 동사만으로 pods/exec 리소스에 대한 접근을 제한하도록 구성된 Kubernetes 클러스터에 대한 호환성 문제를 도입했습니다. 이전에는 SPDY 프로토콜이 GET(Kubernetes RBAC에서 get에 매핑됨) 또는 POST(Kubernetes RBAC에서 create에 매핑됨)을 사용하여 연결 생성을 허용했습니다.

WebSocket 프로토콜에서 kubectl exec 명령은 항상 연결 생성에 GET 메서드를 사용합니다. 이는 RBAC 정책이 create 동사만 허용하는 경우 연결이 거부된다는 것을 의미합니다.

해결#

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

예를 들어, create 동사로 pods/exec 리소스에 대한 접근 권한을 부여하는 ClusterRole이 있다면 get 동사도 허용하도록 업데이트합니다:

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

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

헬스 체크: Kubernetes 클러스터에 연결할 수 없음#

증상#

Kubernetes 클러스터가 unhealthy로 보고되고 Teleport와 Kubernetes 클러스터 API 간의 모든 호출이 실패합니다.

설명#

Teleport Kubernetes 서비스가 Kubernetes 클러스터에 대해 여러 헬스 체크를 수행했지만 응답을 받지 못했습니다.

Kubernetes 클러스터 API 엔드포인트 /selfsubjectaccessreviews/readyz 호출이 HTTP 상태 코드 없이 오류를 반환했습니다.

해결#

근본 원인에 대해 Kubernetes 클러스터와 네트워크를 검사합니다.

Kubernetes 클러스터 상태를 확인합니다.

kubectl cluster-info
kubectl get --raw /readyz

네트워크 및 방화벽 규칙을 확인합니다.

  • 네트워크가 올바르게 구성되어 있나요?
  • 보안 그룹 확인
  • 네트워크 정책 확인

헬스 체크: 필요한 Kubernetes 권한 누락#

증상#

Kubernetes 클러스터가 unhealthy로 보고되고 사용자 가장, 그룹 가장, 서비스 계정 가장 및/또는 파드 가져오기와 같은 하나 이상의 Kubernetes 권한이 누락되었습니다.

설명#

Teleport Kubernetes 서비스가 Kubernetes 클러스터에 헬스 체크를 수행했고 필요한 Kubernetes 클러스터 기능이 거부되었다는 응답을 받았습니다.

Kubernetes 클러스터에 ClusterRole이 없거나 부분적인 ClusterRole로 구성되어 있습니다. Teleport는 네 가지 Kubernetes SelfSubjectAccessReview 권한이 필요합니다:

  • 사용자 가장
  • 그룹 가장
  • 서비스 계정 가장
  • 파드 가져오기

해결#

네 가지 권한으로 Kubernetes 클러스터에 ClusterRoleClusterRoleBinding을 추가합니다.

$ kubectl config use-context <your-kube-context>
kubectl apply -f - <<EOF
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: teleport-impersonation
rules:
  - apiGroups:
      - ""
    resources:
      - users
      - groups
      - serviceaccounts
    verbs:
      - impersonate
  - apiGroups:
      - ""
    resources:
      - pods
    verbs:
      - get
  - apiGroups:
      - "authorization.k8s.io"
    resources:
      - selfsubjectaccessreviews
    verbs:
      - create
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: teleport
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: teleport-impersonation
subjects:
  - kind: ServiceAccount
    name: teleport-serviceaccount
    namespace: default
EOF

ClusterRoleBinding은 다를 수 있습니다.

Teleport Kubernetes에서 가장 활성화도 참조하세요.

헬스 체크: 상태 코드와 함께 비정상 Kubernetes 클러스터 감지#

증상#

Kubernetes 클러스터가 unhealthy로 보고되고 Teleport가 오류 상태 코드와 함께 Kubernetes 클러스터로부터 응답을 받았습니다.

설명#

Teleport Kubernetes 서비스가 Kubernetes 클러스터에 여러 헬스 체크를 수행하고 응답을 받았습니다.

권한 엔드포인트 /selfsubjectaccessreviews 호출이 실패했고 Kubernetes 클러스터 /readyz 엔드포인트 호출이 오류 상태 코드와 함께 응답을 반환했습니다. 오류 상태 코드는 Kubernetes 클러스터의 구성 요소가 비정상 상태임을 나타냅니다.

해결#

kubectl로 Kubernetes 클러스터 오류 상태 코드를 진단합니다.

kubectl cluster-info
kubectl get --raw /readyz

헬스 체크: Kubernetes 권한을 확인할 수 없음#

증상#

Kubernetes 클러스터가 unhealthy로 보고되고 Teleport가 헬스 체크 엔드포인트로부터 혼합된 응답을 받았습니다.

설명#

Teleport Kubernetes 서비스가 Kubernetes 클러스터에 여러 헬스 체크를 수행하고 응답을 받았습니다.

권한 엔드포인트 /selfsubjectaccessreviews 호출이 실패했고 Kubernetes 클러스터 /readyz 호출이 성공했습니다. Kubernetes 클러스터 구성 요소는 정상이지만 Kubernetes SelfSubjectAccessReview API 호출을 차단하는 무언가가 있습니다.

해결#

kubectl로 Kubernetes 클러스터를 진단합니다.

kubectl cluster-info
kubectl get --raw /readyz

Kubernetes 접근 문제 해결

원문 보기
요약

이 페이지에서는 Kubernetes와 관련된 일반적인 문제와 해결 방법을 설명합니다. 에이전트가 재시작 후 Teleport 클러스터에 다시 조인할 수 없고 다음과 유사한 오류를 보고합니다: Teleport는 인증 기관(CA)을 사용하여 각 구성 요소의 인증서에 서명합니다.

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

에이전트가 "no authorities for hostname"으로 인해 클러스터 조인 실패#

증상#

에이전트가 재시작 후 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-state
teleport-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
Note

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

설명#

표준 Kubernetes 클러스터와 달리 Autopilot 클러스터는 시스템 자격 증명을 가장(impersonate)하는 요청을 금지합니다. 이는 사용자 또는 그룹을 가장할 수 있다면 클러스터의 제어 플레인에 접근하여 관리 작업을 수행하는 것을 방지하기 위한 보안 기능입니다. GKE Autopilot 보안에 대해 자세히 알아보기.

Teleport는 가장(impersonation)을 사용하여 사용자를 대신하여 Kubernetes 객체를 검색합니다. 이는 Impersonate-User 헤더에 사용자의 자격 증명을 넣고 Impersonate-Group 헤더에 사용할 수 있는 모든 Kubernetes 그룹을 넣어 Kubernetes API 서버에 요청을 보내는 방식으로 이루어집니다.

system:masters는 모든 클러스터의 내장 Kubernetes 그룹이므로 관리자가 클러스터 제어 플레인에 대한 관리 접근 권한을 얻기 위해 이를 사용하는 것이 일반적입니다. 그러나 Autopilot 클러스터는 이 그룹을 가장하는 것을 금지하고 대신 다른 그룹을 사용하도록 요구합니다.

해결#

위의 설명에 따라 해결책은 Teleport에서 가장을 위한 다른 그룹을 구성하는 것입니다. 이는 역할의 kubernetes_groups 매개변수를 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 << EOF
authToken: "${TOKEN}"
proxyAddr: "${PROXY_ADDR}"
roles: "kube,app,discovery"
joinParams:
  method: "token"
  tokenName: "${TOKEN}"
kubeClusterName: "${CLUSTER}"
tags:
  "type" : "autopilot"
EOF
# values.yaml 설정으로 helm 차트 설치
$ helm install teleport-agent teleport/teleport-kube-agent \
  -f values.yaml \
  --create-namespace \
  --namespace=teleport-agent \
  --version (=teleport.version=)

Teleport 에이전트 파드가 실행 중인지 확인합니다. 단일 준비 컨테이너가 있는 하나의 Teleport 에이전트 파드가 표시되어야 합니다:

$ kubectl -n teleport-agent get pods
NAME               READY   STATUS    RESTARTS   AGE
teleport-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"]

역할이 생성되면 평소와 같이 사용자에게 할당할 수 있지만, 즉시 적용되려면 로그아웃 후 다시 로그인해야 합니다.

kubectl 1.30+에서 파드에 exec 불가#

pods "<pod_name>" is forbidden: User "<user>" cannot get resource "pods/exec" in API group "" in the namespace "<namespace>"

증상#

kubectl을 버전 1.30 이상으로 업그레이드한 후 파드에 exec하려는 시도가 다음과 유사한 오류로 실패합니다:

pods "<pod_name>" is forbidden: User "<user>" cannot get resource "pods/exec" in API group "" in the namespace "<namespace>"

설명#

Kubernetes 1.30부터 kubectl exec 명령은 Kubernetes API 서버와 통신하기 위해 SPDY 프로토콜에서 WebSocket 프로토콜로 전환했습니다. 이 변경은 SPDY 프로토콜이 더 이상 사용되지 않음에 따라 kubectl exec 명령의 성능과 신뢰성을 향상시키기 위한 것입니다.

WebSocket은 SPDY를 완전히 대체하기 위한 것이었지만, RBAC가 create 동사만으로 pods/exec 리소스에 대한 접근을 제한하도록 구성된 Kubernetes 클러스터에 대한 호환성 문제를 도입했습니다. 이전에는 SPDY 프로토콜이 GET(Kubernetes RBAC에서 get에 매핑됨) 또는 POST(Kubernetes RBAC에서 create에 매핑됨)을 사용하여 연결 생성을 허용했습니다.

WebSocket 프로토콜에서 kubectl exec 명령은 항상 연결 생성에 GET 메서드를 사용합니다. 이는 RBAC 정책이 create 동사만 허용하는 경우 연결이 거부된다는 것을 의미합니다.

해결#

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

예를 들어, create 동사로 pods/exec 리소스에 대한 접근 권한을 부여하는 ClusterRole이 있다면 get 동사도 허용하도록 업데이트합니다:

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

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

헬스 체크: Kubernetes 클러스터에 연결할 수 없음#

증상#

Kubernetes 클러스터가 unhealthy로 보고되고 Teleport와 Kubernetes 클러스터 API 간의 모든 호출이 실패합니다.

설명#

Teleport Kubernetes 서비스가 Kubernetes 클러스터에 대해 여러 헬스 체크를 수행했지만 응답을 받지 못했습니다.

Kubernetes 클러스터 API 엔드포인트 /selfsubjectaccessreviews/readyz 호출이 HTTP 상태 코드 없이 오류를 반환했습니다.

해결#

근본 원인에 대해 Kubernetes 클러스터와 네트워크를 검사합니다.

Kubernetes 클러스터 상태를 확인합니다.

kubectl cluster-info
kubectl get --raw /readyz

네트워크 및 방화벽 규칙을 확인합니다.

  • 네트워크가 올바르게 구성되어 있나요?
  • 보안 그룹 확인
  • 네트워크 정책 확인

헬스 체크: 필요한 Kubernetes 권한 누락#

증상#

Kubernetes 클러스터가 unhealthy로 보고되고 사용자 가장, 그룹 가장, 서비스 계정 가장 및/또는 파드 가져오기와 같은 하나 이상의 Kubernetes 권한이 누락되었습니다.

설명#

Teleport Kubernetes 서비스가 Kubernetes 클러스터에 헬스 체크를 수행했고 필요한 Kubernetes 클러스터 기능이 거부되었다는 응답을 받았습니다.

Kubernetes 클러스터에 ClusterRole이 없거나 부분적인 ClusterRole로 구성되어 있습니다. Teleport는 네 가지 Kubernetes SelfSubjectAccessReview 권한이 필요합니다:

  • 사용자 가장
  • 그룹 가장
  • 서비스 계정 가장
  • 파드 가져오기

해결#

네 가지 권한으로 Kubernetes 클러스터에 ClusterRoleClusterRoleBinding을 추가합니다.

$ kubectl config use-context <your-kube-context>
kubectl apply -f - <<EOF
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: teleport-impersonation
rules:
  - apiGroups:
      - ""
    resources:
      - users
      - groups
      - serviceaccounts
    verbs:
      - impersonate
  - apiGroups:
      - ""
    resources:
      - pods
    verbs:
      - get
  - apiGroups:
      - "authorization.k8s.io"
    resources:
      - selfsubjectaccessreviews
    verbs:
      - create
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: teleport
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: teleport-impersonation
subjects:
  - kind: ServiceAccount
    name: teleport-serviceaccount
    namespace: default
EOF

ClusterRoleBinding은 다를 수 있습니다.

Teleport Kubernetes에서 가장 활성화도 참조하세요.

헬스 체크: 상태 코드와 함께 비정상 Kubernetes 클러스터 감지#

증상#

Kubernetes 클러스터가 unhealthy로 보고되고 Teleport가 오류 상태 코드와 함께 Kubernetes 클러스터로부터 응답을 받았습니다.

설명#

Teleport Kubernetes 서비스가 Kubernetes 클러스터에 여러 헬스 체크를 수행하고 응답을 받았습니다.

권한 엔드포인트 /selfsubjectaccessreviews 호출이 실패했고 Kubernetes 클러스터 /readyz 엔드포인트 호출이 오류 상태 코드와 함께 응답을 반환했습니다. 오류 상태 코드는 Kubernetes 클러스터의 구성 요소가 비정상 상태임을 나타냅니다.

해결#

kubectl로 Kubernetes 클러스터 오류 상태 코드를 진단합니다.

kubectl cluster-info
kubectl get --raw /readyz

헬스 체크: Kubernetes 권한을 확인할 수 없음#

증상#

Kubernetes 클러스터가 unhealthy로 보고되고 Teleport가 헬스 체크 엔드포인트로부터 혼합된 응답을 받았습니다.

설명#

Teleport Kubernetes 서비스가 Kubernetes 클러스터에 여러 헬스 체크를 수행하고 응답을 받았습니다.

권한 엔드포인트 /selfsubjectaccessreviews 호출이 실패했고 Kubernetes 클러스터 /readyz 호출이 성공했습니다. Kubernetes 클러스터 구성 요소는 정상이지만 Kubernetes SelfSubjectAccessReview API 호출을 차단하는 무언가가 있습니다.

해결#

kubectl로 Kubernetes 클러스터를 진단합니다.

kubectl cluster-info
kubectl get --raw /readyz