Menonaktifkan port hanya baca kubelet di cluster GKE


Halaman ini menunjukkan cara menonaktifkan port hanya baca kubelet yang tidak aman di cluster Google Kubernetes Engine (GKE) untuk mengurangi risiko akses tidak sah ke kubelet, dan cara memigrasikan aplikasi ke port yang lebih aman.

Di cluster Kubernetes, termasuk GKE, proses kubelet yang berjalan di node menyajikan API hanya baca menggunakan port tidak aman 10255. Kubernetes tidak melakukan pemeriksaan autentikasi atau otorisasi apa pun di port ini. Kubelet menyediakan endpoint yang sama di port 10250 yang lebih aman dan diautentikasi.

Nonaktifkan port hanya baca kubelet dan alihkan workload apa pun yang menggunakan port 10255 untuk menggunakan port 10250 yang lebih aman.

Sebelum memulai

Sebelum memulai, pastikan Anda telah melakukan tugas berikut:

  • Aktifkan Google Kubernetes Engine API.
  • Aktifkan Google Kubernetes Engine API
  • Jika ingin menggunakan Google Cloud CLI untuk tugas ini, instal lalu lakukan inisialisasi gcloud CLI. Jika sebelumnya Anda telah menginstal gcloud CLI, dapatkan versi terbaru dengan menjalankan gcloud components update.

Persyaratan

  • Anda hanya dapat menonaktifkan port kubelet hanya baca yang tidak aman di GKE versi 1.26.4-gke.500 atau yang lebih baru.

Memeriksa penggunaan port yang tidak aman dan memigrasikan aplikasi

Sebelum menonaktifkan port hanya baca yang tidak aman, migrasikan aplikasi yang sedang berjalan dan menggunakan port tersebut ke port hanya baca yang lebih aman. Workload yang mungkin perlu dimigrasikan mencakup pipeline metrik kustom dan workload yang mengakses endpoint kubelet.

  • Untuk workload yang memerlukan akses ke informasi yang ditayangkan oleh kubelet API di node, seperti metrik, gunakan port 10250.
  • Untuk workload yang mendapatkan informasi Kubernetes menggunakan kubelet API di node, seperti mencantumkan Pod di node, gunakan Kubernetes API.

Memeriksa apakah aplikasi menggunakan port hanya baca kubelet yang tidak aman

Bagian ini menunjukkan cara memeriksa penggunaan port yang tidak aman di cluster Anda.

Memeriksa penggunaan port pada mode Autopilot

Untuk memeriksa penggunaan port di cluster Autopilot, pastikan Anda memiliki setidaknya satu workload yang bukan DaemonSet yang berjalan di cluster. Jika Anda melakukan langkah-langkah berikut pada cluster Autopilot yang kosong, hasilnya mungkin tidak valid.

  1. Simpan manifes berikut sebagai 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
    

    Manifes ini melakukan hal berikut:

    1. Membuat namespace dan menyiapkan peran RBAC untuk mengizinkan pembacaan metrik node.
    2. Men-deploy DaemonSet yang memeriksa metrik kubelet untuk port hanya baca yang tidak aman.
  2. Deploy manifes:

    kubectl create -f read-only-port-metrics.yaml
    
  3. Periksa log DaemonSet:

    kubectl logs --namespace=node-metrics-printer-namespace \
        --all-containers --prefix \
        --selector=app=node-metrics-printer
    

    Jika output memiliki hasil yang berisi string server_type=readonly, berarti aplikasi menggunakan port hanya baca yang tidak aman.

Memeriksa penggunaan port pada mode Standar

Jalankan perintah berikut di setidaknya satu node di setiap node pool dalam cluster Anda:

kubectl get --raw /api/v1/nodes/NODE_NAME/proxy/metrics | grep http_requests_total | grep readonly

Ganti NODE_NAME dengan nama node.

Jika output berisi entri dengan string server_type="readonly", skenario berikut dapat terjadi:

  • Workload di node menggunakan port hanya baca kubelet yang tidak aman.
  • Setelah menonaktifkan port yang tidak aman, perintah tetap menampilkan string server_type="readonly". Hal ini karena metrik kubelet_http_requests_total menampilkan jumlah kumulatif permintaan HTTP yang diterima oleh server kubelet sejak dimulai ulang terakhir kali. Nomor ini tidak disetel ulang saat port tidak aman dinonaktifkan. Jumlah ini direset setelah GKE memulai ulang server kubelet, seperti selama upgrade node. Untuk mempelajari lebih lanjut, lihat Referensi Metrik Kubernetes.

Jika outputnya kosong, berarti tidak ada workload di node tersebut yang menggunakan port hanya baca yang tidak aman.

Mengidentifikasi workload yang menggunakan port baca-saja kubelet yang tidak aman

Untuk mengidentifikasi workload yang menggunakan port tidak aman, periksa file konfigurasi workload seperti ConfigMaps dan Pod.

Jalankan perintah berikut:

    kubectl get pods --all-namespaces -o yaml | grep 10255
    kubectl get configmaps --all-namespaces -o yaml | grep 10255

Jika output perintah tidak kosong, gunakan skrip berikut untuk mengidentifikasi nama ConfigMap atau Pod yang menggunakan port tidak aman:

# This function checks if a Kubernetes resource is using the insecure port 10255.
#
# Arguments:
#  $1 - Resource type (e.g., pod, configmap, )
#  $2 - Resource name
#  $3 - Namespace
#
# Output:
#  Prints a message indicating whether the resource is using the insecure port.
isUsingInsecurePort() {
  resource_type=$1
  resource_name=$2
  namespace=$3

  config=$(kubectl get $resource_type $resource_name -n $namespace -o yaml)

  # Check if kubectl output is empty
  if [[ -z "$config" ]]; then
    echo "No configuration file detected for $resource_type: $resource_name (Namespace: $namespace)"
    return
  fi

  if echo "$config" | grep -q "10255"; then
    echo "Warning: The configuration file ($resource_type: $namespace/$resource_name) is using insecure port 10255. It is recommended to migrate to port 10250 for enhanced security."
  else
    echo "Info: The configuration file ($resource_type: $namespace/$resource_name) is not using insecure port 10255."
  fi
}

# Get the list of ConfigMaps with their namespaces
configmaps=$(kubectl get configmaps -A -o custom-columns=NAMESPACE:.metadata.namespace,NAME:.metadata.name | tail -n +2 | awk '{print $1"/"$2}')

# Iterate over each ConfigMap
for configmap in $configmaps; do
  namespace=$(echo $configmap | cut -d/ -f1)
  configmap_name=$(echo $configmap | cut -d/ -f2)
  isUsingInsecurePort "configmap" "$configmap_name" "$namespace"
done

# Get the list of Pods with their namespaces
pods=$(kubectl get pods -A -o custom-columns=NAMESPACE:.metadata.namespace,NAME:.metadata.name | tail -n +2 | awk '{print $1"/"$2}')

# Iterate over each Pod
for pod in $pods; do
  namespace=$(echo $pod | cut -d/ -f1)
  pod_name=$(echo $pod | cut -d/ -f2)
  isUsingInsecurePort "pod" "$pod_name" "$namespace"
done

Setelah Anda mengidentifikasi beban kerja yang relevan, migrasikan beban kerja tersebut untuk menggunakan port 10250 yang aman dengan menyelesaikan langkah-langkah di bagian berikut.

Bermigrasi dari port hanya baca kubelet yang tidak aman

Biasanya, memigrasikan aplikasi ke port aman melibatkan langkah-langkah berikut:

  1. Perbarui URL atau endpoint yang merujuk ke port hanya baca yang tidak aman untuk menggunakan port hanya baca yang aman. Misalnya, ubah http://203.0.113.104:10255 menjadi http://203.0.113.104:10250.

  2. Tetapkan sertifikat certificate authority (CA) klien HTTP ke sertifikat CA cluster. Untuk menemukan sertifikat ini, jalankan perintah berikut:

    gcloud container clusters describe CLUSTER_NAME \
        --location=LOCATION \
        --format="value(masterAuth.clusterCaCertificate)"
    

    Ganti kode berikut:

    • CLUSTER_NAME: nama cluster Anda.
    • LOCATION: lokasi cluster Anda.

Port 10250 yang diautentikasi mengharuskan Anda memberikan peran RBAC yang sesuai kepada subjek untuk mengakses resource tertentu. Untuk mengetahui detailnya, lihat otorisasi kubelet dalam dokumentasi Kubernetes.

Jika workload Anda menggunakan endpoint /pods di port hanya baca kubelet yang tidak aman, Anda perlu memberikan izin RBAC nodes/proxy untuk mengakses endpoint di port kubelet yang aman. nodes/proxy adalah izin yang kuat yang tidak dapat Anda berikan di cluster GKE Autopilot dan yang tidak boleh Anda berikan di cluster GKE Standard. Gunakan Kubernetes API dengan fieldSelector untuk nama node.

Jika Anda menggunakan aplikasi pihak ketiga yang bergantung pada port hanya baca kubelet yang tidak aman, hubungi vendor aplikasi untuk mendapatkan petunjuk cara bermigrasi ke port 10250 yang aman.

Contoh migrasi

Pertimbangkan Pod yang membuat kueri metrik dari port kubelet hanya baca yang tidak aman.

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

Aplikasi ini melakukan hal berikut:

  • Menggunakan ServiceAccount default di namespace default
  • Menjalankan perintah curl terhadap endpoint /metrics di node.

Untuk memperbarui Pod ini agar menggunakan port aman 10250, lakukan langkah-langkah berikut:

  1. Buat ClusterRole dengan akses untuk mendapatkan metrik node:

    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRole
    metadata:
      name: curl-authenticated-role
    rules:
    - apiGroups:
      - ""
      resources:
      - nodes/metrics
      verbs:
      - get
    
  2. Ikat ClusterRole ke identitas aplikasi Anda:

    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
    
  3. Perbarui perintah curl untuk menggunakan endpoint port aman dengan header otorisasi yang sesuai:

    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'
    

Mengubah aturan firewall VPC

Jika Anda memperbarui workload untuk menggunakan port 10250, buat aturan firewall agar Pod di cluster dapat menjangkau port dalam rentang alamat IP node Anda. Aturan firewall harus melakukan hal berikut:

  • Izinkan traffic masuk ke port TCP 10250 pada rentang alamat IP node Anda dari rentang alamat IP Pod internal
  • Tolak traffic masuk ke port TCP 10250 pada rentang alamat IP node Anda dari internet publik.

Anda dapat menggunakan aturan firewall GKE default berikut sebagai template untuk parameter yang akan ditentukan dalam aturan baru Anda:

  • gke-[cluster-name]-[cluster-hash]-inkubelet
  • gke-[cluster-name]-[cluster-hash]-exkubelet

Menonaktifkan port hanya baca yang tidak aman di cluster Autopilot

Anda dapat menonaktifkan port kubelet hanya baca yang tidak aman untuk cluster Autopilot baru dan yang sudah ada.

Untuk menonaktifkan port hanya baca kubelet yang tidak aman di cluster Autopilot, gunakan flag --no-autoprovisioning-enable-insecure-kubelet-readonly-port, seperti pada perintah berikut. Semua node baru dan yang sudah ada di cluster berhenti menggunakan port.

gcloud container clusters update CLUSTER_NAME \
    --location=LOCATION \
    --no-autoprovisioning-enable-insecure-kubelet-readonly-port

Ganti kode berikut:

  • CLUSTER_NAME: nama cluster yang ada.
  • LOCATION: lokasi cluster yang ada.

Anda juga dapat menggunakan flag --no-autoprovisioning-enable-insecure-kubelet-readonly-port saat membuat cluster baru menggunakan perintah gcloud container clusters create-auto.

Menonaktifkan port hanya baca yang tidak aman di cluster Standard

Anda dapat menonaktifkan port kubelet hanya baca yang tidak aman untuk seluruh cluster Standard atau untuk masing-masing node pool. Sebaiknya nonaktifkan port untuk seluruh cluster.

Jika Anda menggunakan penyediaan otomatis node, node pool yang disediakan secara otomatis akan mewarisi setelan port yang Anda tentukan di tingkat cluster. Anda dapat secara opsional menentukan setelan yang berbeda untuk node pool yang disediakan otomatis, tetapi sebaiknya Anda menonaktifkan port di semua node dalam cluster.

Anda juga dapat menggunakan file konfigurasi sistem node untuk menonaktifkan port kubelet hanya baca yang tidak aman secara deklaratif. Jika menggunakan file ini, Anda tidak dapat menggunakan perintah di bagian berikut untuk mengontrol setelan kubelet.

Menonaktifkan port hanya baca yang tidak aman di cluster Standard yang ada

Untuk menonaktifkan port hanya baca kubelet yang tidak aman di cluster Standard yang sudah ada, gunakan flag --no-enable-insecure-kubelet-readonly-port seperti pada perintah berikut. Node pool baru tidak akan menggunakan port yang tidak aman. GKE tidak mengupdate node pool yang ada secara otomatis.

gcloud container clusters update CLUSTER_NAME \
    --location=LOCATION \
    --no-enable-insecure-kubelet-readonly-port

Ganti kode berikut:

  • CLUSTER_NAME: nama cluster Standard yang ada.
  • LOCATION: lokasi cluster Standard yang ada.

Anda juga dapat menggunakan flag --no-autoprovisioning-enable-insecure-kubelet-readonly-port saat membuat cluster baru menggunakan perintah gcloud container clusters create.

Menonaktifkan port hanya baca yang tidak aman di node pool Standard

Sebaiknya Anda menetapkan setelan port hanya baca di tingkat cluster dalam semua kasus. Jika Anda menonaktifkan port hanya baca di cluster yang sudah ada dan sudah menjalankan node pool, gunakan perintah berikut untuk menonaktifkan port di node pool tersebut.

gcloud container node-pools update NODE_POOL_NAME \
    --cluster=CLUSTER_NAME \
    --location=LOCATION \
    --no-enable-insecure-kubelet-readonly-port

Ganti kode berikut:

  • NODE_POOL_NAME: nama node pool Anda.
  • CLUSTER_NAME: nama cluster.
  • LOCATION: lokasi cluster.

Pastikan port dinonaktifkan

Untuk memverifikasi bahwa port hanya baca kubelet yang tidak aman dinonaktifkan, deskripsikan resource GKE.

Memeriksa status port di cluster Autopilot

Jalankan perintah berikut:

gcloud container clusters describe CLUSTER_NAME \
    --location=LOCATION \
    --flatten=nodePoolAutoConfig \
    --format="value(nodeKubeletConfig)"

Ganti kode berikut:

  • CLUSTER_NAME: nama cluster Autopilot Anda.
  • LOCATION: lokasi cluster Autopilot Anda.

Jika port dinonaktifkan, output-nya adalah sebagai berikut:

insecureKubeletReadonlyPortEnabled: false

Memeriksa status port di cluster Standard

Status port tersedia di kolom nodePoolDefaults.nodeConfigDefaults.nodeKubeletConfig saat Anda menjelaskan cluster menggunakan GKE API.

Di cluster Standar, Anda juga akan melihat kolom nodeConfig yang menetapkan nilai untuk status port hanya baca kubelet. Kolom nodeConfig tidak digunakan lagi dan hanya berlaku untuk node pool default yang dibuat GKE saat Anda membuat cluster mode Standard baru. Status port di kolom nodeConfig yang tidak digunakan lagi tidak berlaku untuk node pool lain di cluster.

Jalankan perintah berikut:

gcloud container clusters describe CLUSTER_NAME \
    --location=LOCATION \
    --flatten=nodePoolDefaults.nodeConfigDefaults \
    --format="value(nodeKubeletConfig)"

Ganti kode berikut:

  • CLUSTER_NAME: nama cluster Standard Anda.
  • LOCATION: lokasi cluster Standard Anda.

Jika port dinonaktifkan, output-nya adalah sebagai berikut:

insecureKubeletReadonlyPortEnabled: false

Jika output perintah ini kosong, port hanya baca kubelet yang tidak aman mungkin masih diaktifkan. Untuk menonaktifkan port, jalankan perintah di bagian Menonaktifkan port hanya baca yang tidak aman di cluster Standard yang sudah ada.

Memeriksa status port di node pool Standar

Jalankan perintah berikut:

gcloud container node-pools describe NODE_POOL_NAME \
    --cluster=CLUSTER_NAME \
    --location=LOCATION \
    --flatten=config \
    --format="value(kubeletConfig)"

Ganti kode berikut:

  • NODE_POOL_NAME: nama node pool Anda.
  • CLUSTER_NAME: nama cluster.
  • LOCATION: lokasi cluster.

Jika port dinonaktifkan, output-nya adalah sebagai berikut:

insecureKubeletReadonlyPortEnabled: false