이 페이지에서는 Google Kubernetes Engine(GKE) 클러스터에서 보안이 안 된 kubelet 읽기 전용 포트를 사용 중지하여 kubelet에 대한 무단 액세스의 위험을 줄이고 애플리케이션을 보다 안전한 포트로 마이그레이션하는 방법을 설명합니다.
GKE를 포함한 Kubernetes 클러스터에서는 노드에서 실행되는 kubelet
프로세스가 비보안 포트 10255
를 사용하여 읽기 전용 API를 제공합니다.
Kubernetes는 이 포트에서 인증 또는 승인 검사를 수행하지 않습니다. kubelet은 보다 안전하고 인증된 포트 10250
에서 동일한 엔드포인트를 제공합니다.
kubelet 읽기 전용 포트를 중지하고 10255
포트를 사용하는 모든 워크로드를 대신 더 안전한 10250
포트를 사용하도록 전환합니다.
시작하기 전에
시작하기 전에 다음 태스크를 수행했는지 확인합니다.
- Google Kubernetes Engine API를 사용 설정합니다. Google Kubernetes Engine API 사용 설정
- 이 태스크에 Google Cloud CLI를 사용하려면 gcloud CLI를 설치한 후 초기화합니다. 이전에 gcloud CLI를 설치한 경우
gcloud components update
를 실행하여 최신 버전을 가져옵니다.
요구사항
- GKE 버전 1.26.4-gke.500 이상에서만 비보안 kubelet 읽기 전용 포트를 사용 중지할 수 있습니다.
비보안 포트 사용 확인 및 애플리케이션 마이그레이션
비보안 읽기 전용 포트를 사용 중지하려면 먼저 이 포트를 사용하는 실행 중인 애플리케이션을 보다 안전한 읽기 전용 포트로 마이그레이션합니다. 마이그레이션이 필요할 수 있는 워크로드에는 kubelet 엔드포인트에 액세스하는 커스텀 측정항목 파이프라인과 워크로드가 포함됩니다.
- 노드에서 kubelet API로 제공되는 정보에 대해 액세스 권한이 필요한 워크로드의 경우 포트
10250
을 사용합니다. - 노드의 포드 나열과 같이 노드에서 kubelet API를 사용하여 Kubernetes 정보를 가져오는 워크로드의 경우 Kubernetes API를 대신 사용합니다.
애플리케이션이 비보안 kubelet 읽기 전용 포트를 사용하는지 여부 확인
이 섹션에서는 클러스터에서 비보안 포트 사용을 확인하는 방법을 보여줍니다.
Autopilot 모드의 포트 사용 확인
Autopilot 클러스터에서 포트 사용을 확인하려면 클러스터에서 실행 중인 DaemonSet가 아닌 워크로드가 하나 이상 있는지 확인합니다. 빈 Autopilot 클러스터에서 다음 단계를 수행하는 경우 결과가 잘못될 수 있습니다.
다음 매니페스트를
read-only-port-metrics.yaml
로 저장합니다.apiVersion: v1 kind: Namespace metadata: name: node-metrics-printer-namespace --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: node-metrics-printer-role rules: - apiGroups: - "" resources: - nodes/metrics verbs: - get --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: node-metrics-printer-binding roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: node-metrics-printer-role subjects: - kind: ServiceAccount name: node-metrics-printer-sa namespace: node-metrics-printer-namespace --- apiVersion: v1 kind: ServiceAccount metadata: name: node-metrics-printer-sa namespace: node-metrics-printer-namespace --- apiVersion: apps/v1 kind: DaemonSet metadata: name: node-metrics-printer namespace: node-metrics-printer-namespace spec: selector: matchLabels: app: node-metrics-printer template: metadata: labels: app: node-metrics-printer spec: serviceAccountName: node-metrics-printer-sa containers: - name: metrics-printer image: us-docker.pkg.dev/cloud-builders/ga/v1/curl:latest command: ["sh", "-c"] args: - 'while true; do curl -s --cacert "${CA_CERT}" -H "Authorization: Bearer $(cat ${TOKEN_FILE})" "https://${NODE_ADDRESS}:10250/metrics"|grep kubelet_http_requests_total; sleep 20; done' env: - name: CA_CERT value: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt - name: TOKEN_FILE value: /var/run/secrets/kubernetes.io/serviceaccount/token - name: NODE_ADDRESS valueFrom: fieldRef: fieldPath: status.hostIP
이 매니페스트는 다음을 수행합니다.
- 네임스페이스를 만들고 노드 측정항목 읽기를 허용하는 RBAC 역할을 설정합니다.
- 비보안 읽기 전용 포트에 대해 kubelet 측정항목을 확인하는DaemonSet를 배포합니다.
매니페스트를 배포합니다.
kubectl create -f read-only-port-metrics.yaml
DaemonSet 로그를 확인합니다.
kubectl logs --namespace=node-metrics-printer-namespace \ --all-containers --prefix \ --selector=app=node-metrics-printer
출력에
server_type=readonly
문자열이 포함된 결과가 있으면 애플리케이션에 비보안 읽기 전용 포트가 사용됨을 나타냅니다.
표준 모드의 포트 사용 확인
클러스터의 모든 노드 풀에 있는 하나 이상의 노드에서 다음 명령어를 실행합니다.
kubectl get --raw /api/v1/nodes/NODE_NAME/proxy/metrics | grep http_requests_total | grep readonly
NODE_NAME
을 허브 이름으로 바꿉니다.
노드의 워크로드에 비보안 kubelet 읽기 전용 포트가 사용되는 경우 다음 예시와 같은 server_type="readonly"
문자열 항목이 출력에 포함됩니다.
kubelet_http_requests_total{long_running="false",method="GET",path="healthz",server_type="readonly"} 3
kubelet_http_requests_total{long_running="false",method="GET",path="metrics",server_type="readonly"} 2549
kubelet_http_requests_total{long_running="false",method="GET",path="metrics/probes",server_type="readonly"} 2546
kubelet_http_requests_total{long_running="false",method="GET",path="other",server_type="readonly"} 2
kubelet_http_requests_total{long_running="false",method="GET",path="pods",server_type="readonly"} 1
kubelet_http_requests_total{long_running="false",method="GET",path="stats",server_type="readonly"} 2549
출력이 비어 있으면 해당 노드의 애플리케이션에 비보안 읽기 전용 포트가 사용되지 않음을 나타냅니다.
비보안 kubelet 읽기 전용 포트에서 마이그레이션
일반적으로 보안 포트로 애플리케이션을 마이그레이션하기 위해서는 다음 단계가 수행됩니다.
비보안 읽기 전용 포트를 참조하는 URL 또는 엔드포인트가 보안 읽기 전용 포트를 대신 사용하도록 업데이트합니다. 예를 들어
http://203.0.113.104:10255
를http://203.0.113.104:10250
으로 변경합니다.HTTP 클라이언트의 인증 기관(CA) 인증서를 클러스터 CA 인증서로 설정합니다. 이 인증서를 찾으려면 다음 명령어를 실행합니다.
gcloud container clusters describe CLUSTER_NAME \ --location=LOCATION \ --format="value(masterAuth.clusterCaCertificate)"
다음을 바꿉니다.
CLUSTER_NAME
: 클러스터의 이름입니다.LOCATION
: 클러스터의 위치입니다.
인증 포트 10250
을 사용하려면 특정 리소스에 액세스하도록 주체에 적합한 RBAC 역할을 부여해야 합니다. 자세한 내용은 Kubernetes 문서에서 kubelet 승인을 참조하세요.
/pods
엔드포인트가 워크로드에 사용되는 경우 보안 kubelet 포트에서 엔드포인트에 액세스하도록 nodes/proxy
RBAC 권한을 부여해야 합니다. nodes/proxy
는 GKE Autopilot 클러스터에서 부여할 수 없고 GKE Standard 클러스터에서 부여하지 않아야 하는 강력한 권한입니다. 대신 노드 이름에 대해 fieldSelector
가 있는 Kubernetes API를 사용하세요.
비보안 kubelet 읽기 전용 포트에 의존하는 서드 파티 애플리케이션을 사용하는 경우 애플리케이션 공급업체에 문의하여 보안 포트 10250
으로 마이그레이션 관련 안내를 확인하세요.
마이그레이션 예시
비보안 kubelet 읽기 전용 포트에서 측정항목을 쿼리하는 포드가 있다고 가정해보세요.
apiVersion: v1
kind: Pod
metadata:
name: kubelet-readonly-example
spec:
restartPolicy: Never
containers:
- name: kubelet-readonly-example
image: us-docker.pkg.dev/cloud-builders/ga/v1/curl:latest
command:
- curl
- http://$(NODE_ADDRESS):10255/metrics
env:
- name: NODE_ADDRESS
valueFrom:
fieldRef:
fieldPath: status.hostIP
이 애플리케이션은 다음을 수행합니다.
default
네임스페이스에서default
ServiceAccount를 사용합니다.- 노드에서
/metrics
엔드포인트에 대해curl
명령어를 실행합니다.
보안 포트 10250
을 사용하도록 이 포드를 업데이트하려면 다음 단계를 수행합니다.
노드 측정항목에 액세스할 수 있는 권한이 있는 ClusterRole을 만듭니다.
apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: curl-authenticated-role rules: - apiGroups: - "" resources: - nodes/metrics verbs: - get
ClusterRole을 애플리케이션 ID에 바인딩합니다.
apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: curl-authenticated-role-binding roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: curl-authenticated-role subjects: - kind: ServiceAccount name: default namespace: default
해당 승인 헤더로 보안 포트 엔드포인트를 사용하도록
curl
명령어를 업데이트합니다.apiVersion: v1 kind: Pod metadata: name: kubelet-authenticated-example spec: restartPolicy: Never containers: - name: kubelet-readonly-example image: us-docker.pkg.dev/cloud-builders/ga/v1/curl:latest env: - name: NODE_ADDRESS valueFrom: fieldRef: fieldPath: status.hostIP command: - sh - -c - 'curl -s --cacert /var/run/secrets/kubernetes.io/serviceaccount/ca.crt -H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" https://${NODE_ADDRESS}:10250/metrics'
VPC 방화벽 규칙 수정
포트 10250
을 사용하도록 워크로드를 업데이트하는 경우 클러스터의 포드가 노드 IP 주소 범위의 포트에 연결할 수 있도록 방화벽 규칙을 만듭니다. 방화벽 규칙은 다음을 수행해야 합니다.
- 내부 포드 IP 주소 범위의 노드 IP 주소 범위에서 TCP 포트
10250
에 대한 수신 트래픽을 허용합니다. - 공개 인터넷의 노드 IP 주소 범위에서 TCP 포트
10250
에 대한 수신 트래픽을 거부합니다.
다음 기본 GKE 방화벽 규칙을 새 규칙에 지정할 매개변수의 템플릿으로 사용할 수 있습니다.
gke-[cluster-name]-[cluster-hash]-inkubelet
gke-[cluster-name]-[cluster-hash]-exkubelet
Autopilot 클러스터에서 비보안 읽기 전용 포트 사용 중지
신규 및 기존 Autopilot 클러스터에 대해 비보안 kubelet 읽기 전용 포트를 사용 중지할 수 있습니다.
새 Autopilot 클러스터에서 비보안 읽기 전용 포트 사용 중지
새 Autopilot 클러스터를 만들 때 비보안 kubelet 읽기 전용 포트를 사용 중지하려면 다음 명령어에서와 같이 --no-autoprovisioning-enable-insecure-kubelet-readonly-port
플래그를 사용합니다.
gcloud container clusters create-auto CLUSTER_NAME \
--location=LOCATION \
--no-autoprovisioning-enable-insecure-kubelet-readonly-port
다음을 바꿉니다.
CLUSTER_NAME
: 새 Autopilot 클러스터의 이름입니다.LOCATION
: 새 Autopilot 클러스터의 위치입니다.
기존 Autopilot 클러스터에서 비보안 읽기 전용 포트 사용 중지
기존 Autopilot 클러스터에서 비보안 kubelet 읽기 전용 포트를 사용 중지하려면 다음 명령어에서와 같이 --no-autoprovisioning-enable-insecure-kubelet-readonly-port
플래그를 사용합니다. 클러스터의 모든 신규 및 기존 노드가 포트 사용을 중지합니다.
gcloud container clusters update CLUSTER_NAME \
--location=LOCATION \
--no-autoprovisioning-enable-insecure-kubelet-readonly-port
다음을 바꿉니다.
CLUSTER_NAME
: 기존 클러스터의 이름입니다.LOCATION
: 기존 클러스터의 위치입니다.
표준 클러스터에서 비보안 읽기 전용 포트 사용 중지
전체 표준 클러스터에 대해 또는 개별 노드 풀에 대해 비보안 kubelet 읽기 전용 포트를 사용 중지할 수 있습니다. 전체 클러스터에 대해 포트를 사용 중지하는 것이 좋습니다.
노드 자동 프로비저닝을 사용하는 경우 자동으로 프로비저닝된 노드 풀은 클러스터 레벨에서 지정된 포트 설정을 상속합니다. 선택적으로 자동 프로비저닝된 노드 풀에 대해 다른 설정을 지정할 수 있지만 클러스터의 모든 노드 간에 포트를 사용 중지하는 것이 좋습니다.
또한 노드 시스템 구성 파일을 사용하여 비보안 kubelet 읽기 전용 포트를 선언적으로 사용 중지할 수 있습니다. 이 파일을 사용하는 경우 다음 섹션의 명령어를 사용하여 kubelet 설정을 제어할 수 없습니다.
새로운 표준 클러스터에서 비보안 읽기 전용 포트 사용 중지
새로운 표준 클러스터에서 비보안 kubelet 읽기 전용 포트를 사용 중지하려면 다음 명령어에서와 같이 --no-enable-insecure-kubelet-readonly-port
플래그를 사용합니다.
gcloud container clusters create CLUSTER_NAME \
--location=LOCATION \
--no-enable-insecure-kubelet-readonly-port
다음을 바꿉니다.
CLUSTER_NAME
: 새 Standard 클러스터의 이름입니다.LOCATION
: 새 Standard 클러스터의 위치입니다.
선택적으로 --no-autoprovisioning-enable-insure-kubelet-readonly-port
플래그를 추가하여 노드 자동 프로비저닝 설정을 개별적으로 제어할 수 있지만, 이렇게 하지 않는 것이 좋습니다.
이 플래그는 자동 프로비저닝된 노드 풀의 순차적 업데이트를 시작하므로, 실행 중인 워크로드에 중단이 발생할 수 있습니다.
기존 표준 클러스터에서 비보안 읽기 전용 포트 사용 중지
기존 표준 클러스터에서 비보안 kubelet 읽기 전용 포트를 사용 중지하려면 다음 명령어에서와 같이 --no-enable-insecure-kubelet-readonly-port
플래그를 사용합니다. 모든 새로운 노드 풀은 비보안 포트를 사용하지 않습니다.
GKE는 기존 노드 풀을 자동으로 업데이트하지 않습니다.
gcloud container clusters update CLUSTER_NAME \
--location=LOCATION \
--no-enable-insecure-kubelet-readonly-port
다음을 바꿉니다.
CLUSTER_NAME
: 기존 Standard 클러스터의 이름입니다.LOCATION
: 기존 Standard 클러스터의 위치입니다.
표준 노드 풀에서 비보안 읽기 전용 포트 사용 중지
모든 경우에 클러스터 레벨에서 읽기 전용 포트 설정을 지정하는 것이 좋습니다. 실행 중인 노드 풀이 이미 있는 기존 클러스터에서 읽기 전용 포트를 사용 중지한 경우 다음 명령어를 사용해서 해당 노드 풀에서 포트를 사용 중지합니다.
gcloud container node-pools update NODE_POOL_NAME \
--cluster=CLUSTER_NAME \
--location=LOCATION \
--no-enable-insecure-kubelet-readonly-port
다음을 바꿉니다.
NODE_POOL_NAME
: 노드 풀의 이름입니다.CLUSTER_NAME
: 클러스터의 이름입니다.LOCATION
: 클러스터의 위치입니다.
포트가 중지되었는지 확인
비보안 kubelet 읽기 전용 포트가 사용 중지되었는지 확인하려면 GKE 리소스를 기술합니다.
Autopilot 클러스터에서 포트 상태 확인
다음 명령어를 실행합니다.
gcloud container clusters describe CLUSTER_NAME \
--location=LOCATION \
--flatten=nodePoolAutoConfig \
--format="value(nodeKubeletConfig)"
다음을 바꿉니다.
CLUSTER_NAME
: Autopilot 클러스터의 이름입니다.LOCATION
: Autopilot 클러스터의 위치입니다.
포트가 사용 중지되었으면 출력이 다음과 같습니다.
insecureKubeletReadonlyPortEnabled: false
표준 클러스터에서 포트 상태 확인
포트 상태는 GKE API를 사용하여 클러스터를 기술할 때 nodePoolDefaults.nodeConfigDefaults.nodeKubeletConfig
필드에 표시됩니다.
표준 클러스터에서는 또한 kubelet 읽기 전용 포트 상태에 대한 값을 설정하는 nodeConfig
필드가 표시됩니다. nodeConfig
필드는 지원 중단되었고 새로운 표준 모드 클러스터를 만들 때 GKE가 만드는 기본 노드 풀에만 적용됩니다. 지원 중단된 nodeConfig
필드의 포트 상태는 클러스터의 다른 노드 풀에 적용되지 않습니다.
다음 명령어를 실행합니다.
gcloud container clusters describe CLUSTER_NAME \
--location=LOCATION \
--flatten=nodePoolDefaults.nodeConfigDefaults \
--format="value(nodeKubeletConfig)"
다음을 바꿉니다.
CLUSTER_NAME
: 표준 클러스터의 이름입니다.LOCATION
: 표준 클러스터의 위치입니다.
포트가 사용 중지되었으면 출력이 다음과 같습니다.
insecureKubeletReadonlyPortEnabled: false
표준 노드 풀에서 포트 상태 확인
다음 명령어를 실행합니다.
gcloud container node-pools describe NODE_POOL_NAME \
--cluster= CLUSTER_NAME \
--location=LOCATION \
--flatten=config \
--format="value(kubeletConfig)"
다음을 바꿉니다.
NODE_POOL_NAME
: 노드 풀의 이름입니다.CLUSTER_NAME
: 클러스터의 이름입니다.LOCATION
: 클러스터의 위치입니다.
포트가 사용 중지되었으면 출력이 다음과 같습니다.
insecureKubeletReadonlyPortEnabled: false