Kubernetes 環境的日誌資料不僅是除錯的依據,更是安全監控和異常檢測的根本。建立完善的日誌系統,如同佈署縝密的監控網路,能協助追蹤問題根源,確保系統穩定與安全。本文將探討如何利用 DaemonSet 佈署日誌代理,並結合 Seccomp 與 Syslog 等工具,強化日誌收集能力。此外,文章也將介紹如何整合 SIEM 平台,並運用服務網格技術,提升 Kubernetes 叢集的整體安全監控水平。更進一步,我們將探討如何分析日誌以偵測威脅,並組態警示系統以即時應對安全事件。最後,文章將分享如何整合監控工具與入侵偵測系統,開發更堅實的 Kubernetes 安全防線。

Kubernetes日誌管理:開發堅不可摧的監控防線

在 Kubernetes 環境中,日誌不僅僅是除錯的工具,更是安全監控和異常檢測的根本。如同在迷宮中佈下追蹤線索,完善的日誌系統能幫助我們追蹤問題根源,確保系統的穩定與安全。

DaemonSet:確保日誌代理無處不在

為了確保每個節點上的日誌代理都能持續運作,我們通常會使用 DaemonSet。這種組態方式就像是在每個房間都安排一位警衛,確保任何風吹草動都能被記錄下來。透過 DaemonSet,每個節點都會執行一個日誌代理的副本,並且任何對日誌代理的變更都會在整個叢集中保持一致。

對於擁有眾多團隊和 Kubernetes 叢集的大型組織來說,建立統一的日誌需求和標準架構至關重要。這就像制定一套共同的語言,確保所有團隊都能有效地溝通和協作,從而建立一個高效的日誌解決方案。

Seccomp:系統呼叫的守門員

除了節點和容器日誌外,記錄系統呼叫也極具價值。在 Kubernetes 中,可以使用 seccomp 工具來稽核容器的系統呼叫。Seccomp 就像是一位嚴格的門衛,可以限制容器的系統呼叫能力,從而降低核心的攻擊面。

Seccomp 也能透過稽核模式記錄呼叫行為。自訂的 seccomp Profile 定義了允許、拒絕或記錄哪些系統呼叫,以及未指定呼叫的預設操作。要啟用自訂的 seccomp Profile,Kubernetes 管理員可以將 seccomp Profile JSON 檔案寫入 /var/lib/kubelet/seccomp/ 目錄,並將 seccompProfile 新增到 Pod 的 securityContext 中。

一個自訂的 seccompProfile 應包含兩個欄位:Type: LocalhostlocalhostProfile: myseccomppolicy.json。記錄所有系統呼叫可以幫助管理員瞭解標準操作所需的系統呼叫,從而進一步限制 seccomp Profile,而不會失去系統功能。這也能幫助管理員建立 Pod 標準操作模式的基準,從而識別可能指示惡意活動的任何重大偏差。

Syslog:統一日誌格式的標準

Kubernetes 預設情況下會將 kubelet 日誌和容器執行時日誌寫入 journald(如果該服務可用)。如果組織希望使用 syslog 實用程式,或者從整個叢集收集日誌並將其轉發到 syslog 伺服器或其他日誌儲存和聚合平台,則可以手動組態該功能。

Syslog 協定定義了一種日誌訊息格式化標準。Syslog 訊息包含一個標頭和一條以純文字寫入的訊息。Syslog 常駐程式(如 syslog-ng® 和 rsyslog)能夠以統一的格式收集和聚合來自整個系統的日誌。

許多 Linux 作業系統預設使用 rsyslog 或 journald(一種事件日誌記錄常駐程式,可最佳化日誌儲存並透過 journalctl 以 syslog 格式輸出日誌)。預設情況下,syslog 實用程式會在執行特定 Linux 發行版本的節點上,於主機層級記錄事件。

執行這些 Linux 發行版本的容器預設也會使用 syslog 收集日誌。Syslog 實用程式會將日誌儲存在每個適用節點或容器上的本機檔案系統中,除非組態了日誌聚合平台來收集它們。應組態 syslog 常駐程式或另一個此類別工具,以聚合這兩者以及正在整個叢集中收集的所有其他日誌,並將它們轉發到外部後端以進行儲存和監控。

SIEM 平台:全方位的安全情報中心

安全資訊和事件管理 (SIEM) 軟體會從整個組織的網路收集日誌。它將防火牆日誌、應用程式日誌等匯集在一起,對它們進行剖析,以提供一個集中式的平台,分析師可以從中監控系統安全。SIEM 工具的功能各不相同。通常,這些平台提供日誌收集、聚合、威脅檢測和警示功能。有些平台包含機器學習功能,可以更好地預測系統行為並幫助減少錯誤警示。在環境中使用這些平台的組織應將它們與 Kubernetes 整合,以更好地監控和保護叢集。作為 SIEM 平台的替代方案,存在用於管理來自 Kubernetes 環境的日誌的開放原始碼平台。

容器化環境在節點、Pod、容器和服務之間有許多相互依賴關係。在這些環境中,Pod 和容器會不斷地被刪除並重新佈署在不同的節點上。這種環境對傳統的 SIEM 提出了額外的挑戰,傳統的 SIEM 通常使用 IP 位址來關聯日誌。即使是下一代 SIEM 平台也可能並不總是適合複雜的 Kubernetes 環境。然而,隨著 Kubernetes 成為使用最廣泛的容器協調平台,許多開發 SIEM 工具的組織都開發了專門設計用於與 Kubernetes 環境協同工作,為這些容器化環境提供完整的監控解決方案的產品變體。管理員應瞭解其平台的功能,並確保其日誌記錄充分捕捉環境,以支援未來的事件回應。

服務網格:微服務通訊的守護者

服務網格是一種平台,透過允許將這些通訊的邏輯編碼到服務網格中,而不是在每個微服務中,來簡化應用程式中的微服務通訊。將此通訊邏輯編碼到個別微服務中難以擴充套件,在發生故障時難以除錯,並且難以保護。使用服務網格可以簡化開發人員的編碼。在此層級收集日誌還可以讓叢集管理員深入瞭解整個叢集中的標準服務到服務通訊流程。網格可以:

  • 在服務關閉時重新導向流量,
  • 收集效能指標以最佳化通訊,
  • 允許管理服務到服務通訊加密,
  • 收集服務到服務通訊的日誌,
  • 從每個服務收集日誌,
  • 協助開發人員診斷微服務或通訊機制的問

Kubernetes 叢集威脅偵測:日誌分析與異常警示

在 Kubernetes 環境中,有效的日誌記錄解決方案至關重要。它由兩個關鍵部分組成:收集所有必要的資料,並主動監控這些資料,以儘可能即時地發現異常。如果收集到的資料從未被檢查,那麼再好的日誌記錄解決方案也是無用的。大部分的日誌檢查過程可以自動化,但無論是編寫日誌解析策略還是手動檢查日誌,瞭解該注意什麼至關重要。當攻擊者試圖利用叢集時,他們會在日誌中留下痕跡。

以下表格包含了一些攻擊者可能試圖利用叢集的方式,以及這些行為可能如何在日誌中呈現。(注意:此表格列出了一些已知的可疑指標。管理員還應注意其環境中的特定問題和新出現的威脅,並對此發出警示。最有效的警示是專門用於識別特定叢集的異常活動。)

表 IV:偵測建議

| 攻擊者行為

Kubernetes 叢集安全警示組態實戰

Kubernetes 本身不支援原生警示功能,但許多具有警示功能的監控工具與 Kubernetes 相容。如果 Kubernetes 管理員選擇組態警示工具以在 Kubernetes 環境中工作,則管理員可以使用多種指標來監控和組態警示。

可觸發警示的可操作事件示例包括但不限於:

  • 環境中任何機器的磁碟空間不足,
  • 日誌記錄捲上的可用儲存空間不足,
  • 外部日誌記錄服務離線,
  • Pod 或應用程式以 root 許可權執行,
  • 帳戶請求其沒有許可權的資源,
  • 向 API 伺服器提交匿名請求,
  • Pod 或 Worker 節點 IP 位址被列為 Pod 建立請求的來源 ID,
  • 異常系統呼叫或失敗的 API 呼叫,
  • 使用者/管理員行為異常(即在異常時間或從異常位置),以及
  • 與標準操作指標基準的大幅偏差。

Kubernetes 專案的貢獻者在其 2021 年的 Kubernetes 部落格文章中對此列表進行了以下三項新增 [7]:

  • 變更 Pod 的 securityContext,
  • 更新 admission controller configs,以及
  • 存取某些敏感檔案/URL。

在可能的情況下,應組態系統以採取措施來緩解風險,同時管理員應對警示做出回應。如果 Pod IP 被列為 Pod 建立請求的來源 ID,則自動逐出 Pod 是一種可以實施的緩解措施,以保持應用程式可用,但暫時停止對叢集的任何入侵。這樣做將允許將 Pod 的乾淨版本重新安排到其中一個節點上。調查人員可以檢查日誌以確定是否發生了違規行為,如果是,惡意行為者如何執行入侵,以便可以佈署修補程式。自動化此類別回應有助於提高安全專業人員對關鍵事件的回應時間。

Kubernetes 監控工具與入侵偵測系統整合

Kubernetes 本身不包含廣泛的稽核功能。但是,該系統是可擴充套件的,允許使用者自由開發自己的自訂解決方案或選擇適合其需求的現有附加元件。Kubernetes 叢集管理員通常將其他後端服務連線到其叢集,以為使用者執行其他功能,例如擴充套件的搜尋引數、資料對應功能和警示功能。已經使用 SIEM 平台的組織可以將 Kubernetes 與這些現有功能整合。開源監控工具(例如 Cloud Native Computing Foundation 的 Prometheus®、Grafana Labs 的 Grafana® 和 Elasticsearch 的 Elastic Stack (ELK)®)也可用。這些工具可以執行事件監控、執行威脅分析、管理警示以及收集有關執行中容器的資源隔離引數、歷史使用情況和網路統計資訊。

玄貓建議,掃描工具可用於稽核存取控制和許可權組態,以識別 RBAC 中有風險的許可權組態。

美國國家安全域性 (NSA) 和網路安全和基礎設施安全域性 (CISA) 鼓勵在其現有環境中使用入侵偵測系統 (IDS) 的組織考慮將該服務整合到其 Kubernetes 環境中。這種整合將允許組織監控(並可能終止顯示異常行為跡象的容器),以便可以從初始乾淨映像重新啟動容器。許多 CSP 也為那些想要更託管和可擴充套件解決方案的人提供容器監控服務。

Kubernetes安全強化:玄貓的實戰經驗分享

在容器化技術普及的今天,Kubernetes (K8s) 已成為許多企業佈署和管理應用程式的首選平台。然而,隨著 K8s 的廣泛應用,其安全性也日益受到重視。最近,美國國家安全域性 (NSA) 和網路安全暨基礎設施安全域性 (CISA) 聯合發布了一份 Kubernetes 安全強化,為 K8s 環境的安全組態提供了具體的建議。今天,玄貓將根據這份,結合我多年來在金融科技公司設計分散式系統的經驗,探討 K8s 安全強化的關鍵要點。

為何需要強化 Kubernetes 安全?

許多人認為,只要容器映象是安全的,K8s 環境就自然安全了。但事實並非如此。K8s 是一個複雜的系統,包含多個元件,每個元件都可能存在安全漏洞。此外,錯誤的組態也可能導致安全風險。例如,如果未正確組態 K8s 的存取控制,攻擊者可能會利用 Pod 的許可權來存取敏感資料或執行惡意程式碼。

玄貓在過去的經驗中就曾遇過類別似的案例。當時,我們的一個 K8s 叢集由於 RBAC (Role-Based Access Control) 策略組態不當,導致一個低許可權的 Pod 意外獲得了管理員許可權。幸好我們及時發現並修復了這個漏洞,否則後果不堪設想。

Kubernetes 安全強化的核心策略

NSA 和 CISA 的涵蓋了 K8s 安全強化的多個方面,包括:

  • 升級與應用程式安全實踐
  • 遵循 CIS Kubernetes Benchmark
  • 定期執行弱點掃描與滲透測試
  • 移除未使用的舊元件
  • 使用容器執行身分
  • 檔案系統設定為唯讀
  • 使用 Pod 安全策略 (PSP)

接下來,玄貓將針對其中幾個關鍵策略進行探討,並分享我在實務中的經驗。

升級與應用程式安全實踐:永遠保持在最新狀態

軟體安全的一個基本原則是:永遠保持在最新狀態。這同樣適用於 K8s 環境。K8s 社群會定期發布安全更新,修補已知的漏洞。因此,管理員應定期檢查並安裝最新的更新。

此外,應用程式安全也是 K8s 安全的重要組成部分。開發者應遵循安全的編碼實踐,例如避免使用不安全的函式庫、驗證使用者輸入等。同時,應定期掃描容器映象,確保其中不包含已知的漏洞。

玄貓建議,企業可以考慮使用高用性 (HA) 叢集,以便在不中斷服務的情況下進行更新。HA 叢集允許可將服務從實體機器上逐一解除安裝,以便及時佈署韌體、核心和作業系統更新,同時保持服務可用性。

遵循 CIS Kubernetes Benchmark:建立安全基準線

網路安全中心 (CIS) 發布了 Kubernetes 的安全基準,為 K8s 環境的安全組態提供了詳細的建議。這些基準涵蓋了 K8s 的多個方面,包括控制平面、節點、網路和應用程式。

管理員應定期檢查其 K8s 環境是否符合 CIS 基準。這有助於建立一個安全基準線,並及早發現潛在的安全風險。

使用容器執行身分:最小許可權原則

在 K8s 中,容器預設以 root 使用者身分執行。這意味著容器擁有系統的完全控制權。如果容器被攻破,攻擊者可以利用 root 許可權來執行惡意操作。

為了降低這種風險,玄貓強烈建議使用非 root 使用者身分執行容器。這可以透過在 Dockerfile 中新增 USER 指令來實作。例如:

FROM ubuntu:latest
#Update and install the make utility
RUN apt update && apt install -y make
#Copy the source from a folder called “code” and build the application with
the make utility
COPY . /code
RUN make /code
#Create a new user (user1) and new group (group1); then switch into that
user’s context
RUN useradd user1 && groupadd group1
USER user1:group1
#Set the default entrypoint for the container
CMD /code/app

內容解密

  • FROM ubuntu:latest: 指定使用 Ubuntu 最新版本作為基礎映象。
  • RUN apt update && apt install -y make: 更新 apt 套件列表,並安裝 make 工具。-y 引數表示自動確認安裝過程中的所有提示。
  • COPY . /code: 將目前目錄下的所有檔案複製到容器內的 /code 目錄。
  • RUN make /code: 在容器內的 /code 目錄下執行 make 命令,用於編譯或構建應用程式。
  • RUN useradd user1 && groupadd group1: 建立一個名為 user1 的新使用者,並建立一個名為 group1 的新群組。
  • USER user1:group1: 指定後續的指令以 user1 使用者和 group1 群組的身分執行。這有助於降低容器的許可權,提高安全性。
  • CMD /code/app: 設定容器啟動時執行的預設命令。這裡假設編譯後的應用程式位於 /code/app

透過使用非 root 使用者身分執行容器,可以有效降低容器被攻破後造成的損害。

檔案系統設定為唯讀:防止惡意寫入

另一個重要的安全措施是將容器的檔案系統設定為唯讀。這可以防止攻擊者在容器中寫入惡意程式碼或修改系統設定。

可以透過在 K8s 的 Deployment 範本中設定 readOnlyRootFilesystem: true 來實作。例如:

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: web
  name: web
spec:
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
      name: web
    spec:
      containers:
      - command: ["sleep"]
        args: ["999"]
        image: ubuntu:latest
        name: web
        securityContext:
          readOnlyRootFilesystem: true
        volumeMounts:
        - mountPath: /writeable/location/here
          name: volName
      volumes:
      - emptyDir: {}
        name: volName

內容解密

  • apiVersion: apps/v1: 指定使用的 Kubernetes API 版本。
  • kind: Deployment: 宣告這是一個 Deployment 資源,用於管理 Pod 的佈署和擴充套件。
  • metadata: 包含 Deployment 的中繼資料,例如標籤和名稱。
  • spec: 定義 Deployment 的規格,包括選擇器、範本等。
  • selector: 指定 Deployment 如何選擇要管理的 Pod。
  • matchLabels: 定義選擇 Pod 的標籤。
  • template: 定義用於建立 Pod 的範本。
  • containers: 定義 Pod 中執行的容器。
  • command: 指定容器啟動時執行的命令。
  • args: 傳遞給命令的引數。
  • image: 指定容器使用的 Docker 映象。
  • name: 容器的名稱。
  • securityContext: 定義容器的安全上下文。
  • readOnlyRootFilesystem: true: 設定容器的根檔案系統為唯讀。
  • volumeMounts: 定義要掛載到容器中的 Volume。
  • mountPath: 指定 Volume 掛載到容器中的路徑。
  • name: Volume 的名稱。
  • volumes: 定義 Pod 中使用的 Volume。
  • emptyDir: {}: 建立一個空的 Volume,用於儲存需要寫入的資料。

如果應用程式需要寫入檔案系統,可以建立一個可寫入的 Volume,並將其掛載到容器中。

Pod 安全策略 (PSP):設定最低安全標準

Pod 安全策略 (PSP) 是一種叢集範圍的策略,用於指定 Pod 在叢集中執行的安全需求。PSP 可以設定預設值,並拒絕建立不符合安全需求的 Pod。

雖然 K8s 已經棄用 PSP,但瞭解 PSP 的概念對於理解 K8s 安全仍然很有幫助。目前,K8s 建議使用 Pod Security Admission (PSA) 來替代 PSP。PSA 提供了更靈活和易於使用的安全策略管理方式。

Kubernetes強化:利用Pod安全策略、名稱空間、網路策略、資源限制與配額提升安全性

在雲原生應用程式的佈署中,Kubernetes已成為領先的容器協調平台。然而,隨著其普及,安全性也成為了關注焦點。玄貓將探討如何透過Pod安全策略(PSP)、名稱空間(Namespace)、網路策略(Network Policy)、資源限制(LimitRange)和資源配額(ResourceQuota),來強化Kubernetes叢集的安全性。

1. Pod安全策略(PSP):強化容器安全

Pod安全策略(PSP)是一種叢集層級的資源,用於控制Pod的安全相關屬性。透過PSP,玄貓可以限制容器的能力,例如禁止特權提升、設定使用者ID、限制可使用的Volume型別等。

1.1 關鍵欄位與建議
  • allowPrivilegeEscalation

    • 用途:限制容器提升至root許可權。
    • 建議:設定為false,以有效強制執行runAsUser: MustRunAsNonRoot設定。
    • 玄貓解說:這項設定能避免容器透過某些漏洞取得root許可權,是強化安全性的重要一步。
  • seLinux

    • 用途:設定容器的SELinux上下文。
    • 建議:若環境支援SELinux,加入SELinux標籤以進一步強化容器。
    • 玄貓解說:SELinux提供強制存取控制,能有效隔離容器,減少潛在的攻擊面。
  • AppArmor annotations

    • 用途:設定容器使用的AppArmor profile。
    • 建議:盡可能使用AppArmor限制容器化應用程式的行為。
    • 玄貓解說:AppArmor能限制容器的系統呼叫,降低遭受利用的風險。
  • seccomp annotations

    • 用途:設定容器使用的seccomp profile,用於沙箱化容器。
    • 建議:使用seccomp稽核profile識別應用程式所需的系統呼叫,然後啟用seccomp profile以封鎖所有其他系統呼叫。
    • 玄貓解說:Seccomp能有效限制容器的系統呼叫,是強化容器安全性的重要手段。
1.2 PSP的應用注意事項
  • PSP不會自動應用於整個叢集,需要啟用PodSecurityPolicy admission controller並透過RBAC授權。
  • 在多個PSP存在的環境中,Pod建立會遵循限制最少的授權策略,因此需要謹慎管理PSP。
1.3 範例PSP組態

以下是一個範例PSP組態,用於強制執行強大的安全需求:

apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
  name: restricted
  annotations:
    seccomp.security.alpha.kubernetes.io/allowedProfileNames: 'docker/default,runtime/default'
    apparmor.security.beta.kubernetes.io/allowedProfileNames: 'runtime/default'
    seccomp.security.alpha.kubernetes.io/defaultProfileName: 'runtime/default'
    apparmor.security.beta.kubernetes.io/defaultProfileName: 'runtime/default'
spec:
  privileged: false # 必須設定以防止提升至root許可權
  allowPrivilegeEscalation: false
  requiredDropCapabilities:
    - ALL
  volumes:
    - 'configMap'
    - 'emptyDir'
    - 'projected'
    - 'secret'
    - 'downwardAPI'
    - 'persistentVolumeClaim' # 假設persistentVolumes由管理員安全設定
  hostNetwork: false
  hostIPC: false
  hostPID: false
  runAsUser:
    rule: 'MustRunAsNonRoot' # 要求容器以非root使用者執行
  seLinux:
    rule: 'RunAsAny' # 假設節點使用AppArmor而非SELinux
  supplementalGroups:
    rule: 'MustRunAs'
    ranges: # 禁止新增root群組
      - min: 1
        max: 65535
  runAsGroup:
    rule: 'MustRunAs'
    ranges: # 禁止新增root群組
      - min: 1
        max: 65535
  fsGroup:
    rule: 'MustRunAs'
    ranges: # 禁止新增root群組
      - min: 1
        max: 65535
  readOnlyRootFilesystem: true

玄貓提醒:請根據組織的需求調整此策略。

2. 名稱空間(Namespace):資源隔離與管理

名稱空間提供了一種在單個Kubernetes叢集中劃分資源的方法。玄貓可以使用名稱空間來隔離不同的團隊、專案或環境,從而提高安全性與管理效率。

2.1 建立名稱空間

可以使用kubectl命令或YAML檔案建立名稱空間。

  • 使用kubectl命令
kubectl create namespace <insert-namespace-name-here>
  • 使用YAML檔案
apiVersion: v1
kind: Namespace
metadata:
  name: <insert-namespace-name-here>

然後使用以下命令應用:

kubectl create -f ./my-namespace.yaml
2.2 在現有名稱空間中建立Pod

可以使用以下命令切換到所需的名稱空間:

kubectl config use-context <insert-namespace-here>

然後應用新的佈署:

kubectl apply -f deployment.yaml

或者,可以在kubectl命令中指定名稱空間:

kubectl apply -f deployment.yaml --namespace=<insert-namespace-here>

也可以在YAML宣告中指定名稱空間:

metadata:
  namespace: <insert-namespace-here>

玄貓提示:資源一旦建立,就不能在名稱空間之間移動,必須先刪除再於新的名稱空間中建立。

3. 網路策略(Network Policy):限制網路流量

網路策略用於控制Pod之間的網路流量。透過網路策略,玄貓可以限制哪些Pod可以與其他Pod通訊,從而降低潛在的橫向移動風險。

3.1 範例網路策略

以下是一個範例網路策略,用於限制對nginx服務的存取:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: example-access-nginx
  namespace: prod # 可以是任何名稱空間,如果未使用名稱空間則可以省略
spec:
  podSelector:
    matchLabels:
      app: nginx
  ingress:
    - from:
      - podSelector:
          matchLabels:
            access: "true"

可以使用以下命令應用新的網路策略:

kubectl apply -f policy.yaml
3.2 預設拒絕所有流量策略
  • 拒絕所有進入流量
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-all-ingress
spec:
  podSelector: {}
  policyType:
    - Ingress
  • 拒絕所有出去流量
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-all-egress
spec:
  podSelector: {}
  policyType:
    - Egress

4. 資源限制(LimitRange):限制資源使用

資源限制用於限制名稱空間中Pod的資源使用量。透過資源限制,玄貓可以確保Pod不會過度消耗資源,從而影響其他應用程式的效能。

4.1 範例資源限制組態
apiVersion: v1
kind: LimitRange
metadata:
  name: cpu-min-max-demo-lr
spec:
  limits:
    - default:
        cpu: 1
      defaultRequest:
        cpu: 0.5
      max:
        cpu: 2
      min:
        cpu: 0.5
      type: Container

可以使用以下命令將資源限制應用於名稱空間:

kubectl apply -f <example-LimitRange>.yaml --namespace=<Enter-Namespace>

玄貓說明:應用此範例資源限制組態後,所有在名稱空間中建立的容器都會被分配預設的CPU請求和限制(如果未指定)。名稱空間中的所有容器都必須具有大於或等於最小值與小於或等於最大值的CPU請求,否則容器將不會被例項化。

5. 資源配額(ResourceQuota):限制總體資源使用

資源配額用於限制名稱空間中的總體資源使用量。透過資源配額,玄貓可以確保名稱空間不會過度消耗資源,從而影響其他名稱空間的效能。

5.1 範例資源配額組態
apiVersion: v1
kind: ResourceQuota
metadata:
  name: example-cpu-mem-resourcequota
spec:
  hard:
    requests.cpu: "1"
    requests.memory: 1Gi
    limits.cpu: "2"
    limits.memory: 2Gi

可以使用以下命令應用此資源配額:

kubectl apply -f example-cpu-mem-resourcequota.yaml --namespace=<insert-namespace-here>

玄貓說明:此資源配額對所選名稱空間施加以下約束:

  • 每個容器必須具有記憶體請求、記憶體限制、CPU請求和CPU限制。
  • 所有容器的總記憶體請求不應超過1 GiB。
  • 所有容器的總記憶體限制不應超過2 GiB。
  • 所有容器的總CPU請求不應超過1 CPU。
  • 所有容器的總CPU限制不應超過2 CPUs。

透過上述Pod安全策略、名稱空間、網路策略、資源限制和資源配額,玄貓可以更有效地強化Kubernetes叢集的安全性,確保應用程式在安全可靠的環境中執行。

Kubernetes Secrets 加密:實戰範例與組態

在 Kubernetes 中,Secrets 管理一直以來都是安全性的重要一環。為了保護儲存在 Secrets 中的敏感資料,例如密碼、API 金鑰和憑證,對 Secrets 進行加密是不可或缺的步驟。本文將探討幾種在 Kubernetes 中加密 Secrets 的方法,並提供實作範例,幫助你提升叢集的安全性。

使用 AES-CBC 本機加密

組態步驟

  1. 建立加密設定檔: 首先,你需要建立一個 YAML 檔案,定義加密的型別和金鑰。以下是一個範例:
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
- resources:
  - secrets
providers:
- aescbc:
    keys:
    - name: key1
      secret: <base 64 編碼後的金鑰>
- identity: {}

內容解密

  • apiVersion:指定 API 版本。
  • kind:指定資源型別為 EncryptionConfiguration。
  • resources:指定要加密的資源型別為 secrets。
  • providers:定義加密提供者,這裡使用 aescbc
  • keys:指定加密金鑰,secret 欄位需要替換為 Base64 編碼後的金鑰。
  • identity:保留未加密資料的提供者。
  1. Base64 編碼金鑰: 使用 Base64 工具將你的加密金鑰進行編碼。例如,在 Linux 系統中,你可以使用以下命令:
echo -n "your-secret-key" | base64
  1. 設定 API Server 引數: 重新啟動 API Server,並使用 --encryption-provider-config 引數指定加密組態檔案的位置。
kube-apiserver --encryption-provider-config=/path/to/encryption-config.yaml ...

注意事項

  • 將加密金鑰儲存在加密檔案中僅能稍微提升安全性,因為金鑰仍然可以被存取。更安全的做法是使用金鑰管理服務(KMS)。

使用金鑰管理服務(KMS)加密

組態步驟

  1. 建立 KMS 組態檔案: 建立一個 YAML 檔案,設定 KMS 提供者的屬性。以下是一個範例:
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
- resources:
  - secrets
providers:
- kms:
    name: myKMSPlugin
    endpoint: unix:///tmp/socketfile.sock
    cachesize: 100
    timeout: 3s
- identity: {}

內容解密

  • apiVersion:指定 API 版本。
  • kind:指定資源型別為 EncryptionConfiguration。
  • resources:指定要加密的資源型別為 secrets。
  • providers:定義加密提供者,這裡使用 kms
  • name:KMS 外掛的名稱。
  • endpoint:KMS 服務的 Unix Socket 位址。
  • cachesize:快取大小,用於儲存加密金鑰。
  • timeout:連線 KMS 服務的逾時時間。
  • identity:保留未加密資料的提供者。
  1. 設定 API Server 引數: 重新啟動 API Server,並使用 --encryption-provider-config 引數指定 KMS 組態檔案的位置。
kube-apiserver --encryption-provider-config=/path/to/kms-config.yaml ...
  1. 切換加密提供者: 如果要從本機加密切換到 KMS,請將 KMS 提供者的組態放在現有加密方法之上。
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
- resources:
  - secrets
providers:
- kms:
    name: myKMSPlugin
    endpoint: unix:///tmp/socketfile.sock
    cachesize: 100
    timeout: 3s
- aescbc:
    keys:
    - name: key1
      secret: <base64 編碼後的金鑰>
  1. 重新加密 Secrets: 重新啟動 API Server 後,執行以下命令重新加密所有 Secrets。
kubectl get secrets --all-namespaces -o json | kubectl replace -f -

KMS 優勢

  • KMS 提供更安全的金鑰管理,將加密金鑰儲存在獨立的服務中,降低金鑰洩漏的風險。

Kubernetes RBAC 角色範例

為了更精細地控制 Kubernetes 叢集中的存取許可權,可以使用 RBAC(Role-Based Access Control)來定義角色和角色繫結。以下是一些範例,展示如何建立和應用 RBAC 角色。

建立 pod-reader 角色

  1. 建立 YAML 檔案: 建立一個 YAML 檔案,定義 pod-reader 角色。
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: your-namespace-name
  name: pod-reader
rules:
- apiGroups: [""] # "" 表示核心 API 群組
  resources: ["pods"]
  verbs: ["get", "watch", "list"]

內容解密

  • apiVersion:指定 API 版本。
  • kind:指定資源型別為 Role。
  • metadata:定義角色的中繼資料,包括名稱空間和名稱。
  • rules:定義角色的許可權規則,這裡允許讀取 pods 的資訊。
  • apiGroups:指定 API 群組,"" 表示核心 API 群組。
  • resources:指定資源型別為 pods。
  • verbs:指定允許的操作,包括 getwatchlist
  1. 應用角色: 使用 kubectl apply 命令應用該角色。
kubectl apply --f role.yaml

建立 global-pod-reader ClusterRole

  1. 建立 YAML 檔案: 建立一個 YAML 檔案,定義 global-pod-reader ClusterRole。
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: global-pod-reader
rules:
- apiGroups: [""] # "" 表示核心 API 群組
  resources: ["pods"]
  verbs: ["get", "watch", "list"]

內容解密

  • apiVersion:指定 API 版本。
  • kind:指定資源型別為 ClusterRole。
  • metadata:定義 ClusterRole 的中繼資料,包括名稱。
  • rules:定義 ClusterRole 的許可權規則,這裡允許讀取 pods 的資訊。
  • apiGroups:指定 API 群組,"" 表示核心 API 群組。
  • resources:指定資源型別為 pods。
  • verbs:指定允許的操作,包括 getwatchlist
  1. 應用 ClusterRole: 使用 kubectl apply 命令應用該 ClusterRole。
kubectl apply --f clusterrole.yaml

RBAC 角色繫結範例

角色繫結(RoleBinding)用於將角色(Role)或叢集角色(ClusterRole)的許可權授予使用者或群組。以下是一些範例,展示如何建立和應用角色繫結。

建立 RoleBinding

  1. 建立 YAML 檔案: 建立一個 YAML 檔案,定義 RoleBinding。
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: read-pods
  namespace: your-namespace-name
subjects:
- kind: User
  name: jane # "name" 區分大小寫
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role # 必須是 Role 或 ClusterRole
  name: pod-reader # 必須與要繫結的 Role 或 ClusterRole 名稱相符
  apiGroup: rbac.authorization.k8s.io

內容解密

  • apiVersion:指定 API 版本。
  • kind:指定資源型別為 RoleBinding。
  • metadata:定義 RoleBinding 的中繼資料,包括名稱空間和名稱。
  • subjects:指定要授予許可權的使用者或群組。
  • kind:指定主體的型別,這裡使用 User。
  • name:使用者的名稱,區分大小寫。
  • apiGroup:指定 API 群組。
  • roleRef:指定要繫結的 Role 或 ClusterRole。
  • kind:指定繫結的型別,必須是 Role 或 ClusterRole。
  • name:指定要繫結的 Role 或 ClusterRole 的名稱。
  • apiGroup:指定 API 群組。
  1. 應用 RoleBinding: 使用 kubectl apply 命令應用該 RoleBinding。
kubectl apply --f rolebinding.yaml

建立 ClusterRoleBinding

  1. 建立 YAML 檔案: 建立一個 YAML 檔案,定義 ClusterRoleBinding。
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: global-pod-reader
subjects:
- kind: Group
  name: manager # Name is case sensitive
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole # 必須是 Role 或 ClusterRole
  name: global-pod-reader # 必須與要繫結的 Role 或 ClusterRole 名稱相符
  apiGroup: rbac.authorization.k8s.io

內容解密

  • apiVersion:指定 API 版本。
  • kind:指定資源型別為 ClusterRoleBinding。
  • metadata:定義 ClusterRoleBinding 的中繼資料,包括名稱。
  • subjects:指定要授予許可權的使用者或群組。
  • kind:指定主體的型別,這裡使用 Group。
  • name:群組的名稱,區分大小寫。
  • apiGroup:指定 API 群組。
  • roleRef:指定要繫結的 Role 或 ClusterRole。
  • kind:指定繫結的型別,必須是 Role 或 ClusterRole。
  • name:指定要繫結的 Role 或 ClusterRole 的名稱。
  • apiGroup:指定 API 群組。
  1. 應用 ClusterRoleBinding: 使用 kubectl apply 命令應用該 ClusterRoleBinding。
kubectl apply --f clusterrolebinding.yaml

Kubernetes 稽核策略範例

稽核日誌(Audit Logs)對於監控 Kubernetes 叢集中的活動至關重要。透過組態稽核策略,你可以記錄叢集中發生的事件,並在發生安全事件時提供有用的資訊。以下是一個範例,展示如何組態稽核策略。

建立稽核策略

  1. 建立 YAML 檔案: 建立一個 YAML 檔案,定義稽核策略。
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: Metadata
  resources:
  - group: "" # 核心 API 群組
    resources: ["secrets"]
- level: RequestResponse

內容解密

  • apiVersion:指定 API 版本。
  • kind:指定資源型別為 Policy。
  • rules:定義稽核規則。
  • level:指定日誌記錄的層級。
    • Metadata:僅記錄中繼資料。
    • RequestResponse:記錄請求和回應。
  • resources:指定要稽核的資源。
  • group:指定 API 群組,"" 表示核心 API 群組。
  • resources:指定資源型別,這裡設定為 secrets。

稽核層級說明

  • RequestReceived: 記錄收到請求的階段。
  • ResponseStarted: 記錄開始發送回應的階段。
  • ResponseComplete: 記錄回應完成的階段。
  • Panic: 記錄發生 panic 的階段。

組態建議

  • 如果組織有足夠的資源來儲存和分析大量的日誌,建議將所有事件(除了涉及 Secrets 的事件)記錄在最高層級,以確保在發生安全事件時能夠取得所有必要的上下文資訊。
  • 如果資源消耗是一個問題,可以建立更多的日誌規則,降低非關鍵元件和非特權操作的日誌記錄層級。
  • 確保稽核策略以一個 catch-all 規則結束,以記錄所有先前規則未記錄的事件。

注意事項

  • Kubernetes 根據稽核策略中第一個適用於給定事件的規則來記錄稽核事件。因此,請注意規則的順序。
  • 涉及 Secrets 的規則應放在策略檔案的頂部,以確保不會因較高層級的日誌記錄而無意中捕捉 Secrets。

Kubernetes 稽核日誌:強化資安的關鍵一步

在雲原生架構中,Kubernetes (K8s) 已成為容器化應用程式佈署和管理的標準。然而,隨著 K8s 的普及,其安全性也日益受到關注。稽核日誌 (Audit Logging) 作為一種重要的安全機制,能夠記錄 K8s 叢集中的所有操作,幫助我們追蹤潛在的安全風險,並符合合規性要求。

為何需要 Kubernetes 稽核日誌?

稽核日誌不僅僅是記錄事件的工具,更是強化 K8s 安全的重要防線:

  • 安全事件追蹤: 稽核日誌詳細記錄了誰在何時對 K8s 資源進行了哪些操作。這對於調查安全事件、追蹤攻擊來源至關重要。
  • 合規性要求: 許多行業法規要求對系統操作進行詳細記錄。稽核日誌可以幫助企業滿足這些合規性要求。
  • 異常行為檢測: 透過分析稽核日誌,我們可以發現異常行為模式,例如未授權的資源存取、惡意的 Pod 佈署等,及早發現潛在的安全威脅。
  • 變更管理: 稽核日誌記錄了 K8s 資源的變更歷史,有助於追蹤組態變更、回溯錯誤操作,並確保系統的穩定性。

玄貓在為某金融科技公司匯入 K8s 時,就深刻體會到稽核日誌的重要性。當時,我們利用稽核日誌成功追蹤到一起未授權的資源存取事件,及時阻止了潛在的資料洩露風險。

如何啟用 Kubernetes 稽核日誌?

啟用 K8s 稽核日誌需要組態 kube-apiserver,以下是具體步驟:

  1. 編輯 kube-apiserver.yaml 檔案:

    使用具有管理員許可權的帳戶,開啟 kube-apiserver.yaml 檔案。這個檔案通常位於 /etc/kubernetes/manifests/ 目錄下。

    sudo vi /etc/kubernetes/manifests/kube-apiserver.yaml
    
  2. 新增稽核日誌相關 Flag:

    在 kube-apiserver.yaml 檔案中,新增以下 flag:

    --audit-policy-file=/etc/kubernetes/policy/audit-policy.yaml
    --audit-log-path=/var/log/audit.log
    --audit-log-maxage=1825
    
    • audit-policy-file:指定稽核策略檔案的路徑。稽核策略定義了哪些事件需要被記錄。
    • audit-log-path:指定稽核日誌檔案的儲存路徑。
    • audit-log-maxage:指定稽核日誌保留的天數。

    除了上述 flag,還有其他可選 flag,例如 audit-log-maxbackup(指定保留的稽核日誌檔案數量)、audit-log-maxsize(指定稽核日誌檔案的最大大小)等。您可以根據組織的安全策略進行組態。

  3. 設定 Volume Mount (如果 kube-apiserver 以 Pod 方式執行):

    如果您的 kube-apiserver 是以 Pod 方式執行的,則需要設定 Volume Mount,以確保稽核策略檔案和日誌檔案能夠被持久化儲存。在 kube-apiserver.yaml 檔案中新增以下 sections:

    volumeMounts:
      - mountPath: /etc/kubernetes/audit-policy.yaml
        name: audit
        readOnly: true
      - mountPath: /var/log/audit.log
        name: audit-log
        readOnly: false
    volumes:
      - hostPath:
          path: /etc/kubernetes/audit-policy.yaml
          type: File
        name: audit
      - hostPath:
          path: /var/log/audit.log
          type: FileOrCreate
        name: audit-log
    

    這些設定將稽核策略檔案和日誌檔案掛載到 hostPath,確保它們在 Pod 重啟後仍然可用。

稽核策略 (Audit Policy) 的設計

稽核策略定義了哪些事件需要被記錄。一個好的稽核策略應該能夠捕捉到關鍵的安全事件,同時避免產生過多的冗餘日誌。

以下是一個稽核策略範例 (audit-policy.yaml):

apiVersion: audit.k8s.io/v1beta1
kind: Policy
rules:
  # 記錄 Pod 的佈署和變更
  - level: RequestResponse
    resources:
    - group: ""
      resources: ["pods"]
    verbs: ["create", "update", "patch", "delete"]

  # 記錄 RBAC 資源的變更
  - level: RequestResponse
    resources:
    - group: rbac.authorization.k8s.io
      resources: ["clusterrolebindings", "clusterroles"]
    verbs: ["create", "update", "patch", "delete"]

  # 記錄所有其他請求 (Metadata level)
  - level: Metadata
    verbs: ["get", "list", "watch"]

這個策略定義了三個規則:

  1. 記錄 Pod 的佈署和變更。
  2. 記錄 RBAC 資源的變更。
  3. 記錄所有其他請求 (Metadata level)。

在設計稽核策略時,需要根據組織的安全需求和合規性要求進行調整。以下是一些建議:

  • 從高層次開始: 先定義需要記錄的關鍵事件型別,例如 Pod 佈署、RBAC 資源變更、身份驗證請求等。
  • 逐步細化: 根據實際情況,逐步細化稽核策略,增加或調整規則。
  • 避免過度記錄: 過多的日誌會增加分析和管理的難度。只記錄必要的事件,避免冗餘。
  • Metadata level 的使用: Metadata level 適用於記錄不敏感的、例行性的操作。
  • Catch-all 規則: Catch-all 規則應該是策略中的最後一條規則,確保所有其他規則能夠優先比對。

以下是一些建議記錄的關鍵事件型別:

  • Critical:
    • Pod 佈署和變更
    • 身份驗證請求
    • RBAC 資源的修改
    • 排程任務的建立
    • Pod 安全策略的編輯
  • Noncritical:
    • RequestReceived stage
    • 對非關鍵資源的身份驗證請求

稽核日誌的分析與應用

啟用稽核日誌後,需要對日誌進行分析,才能發揮其價值。以下是一些建議:

  • 集中化日誌管理: 將所有 K8s 叢集的稽核日誌集中儲存和管理,方便統一分析。
  • 自動化分析: 使用日誌分析工具,例如 ELK Stack、Splunk 等,自動分析稽核日誌,檢測異常行為。
  • 建立告警機制: 針對關鍵安全事件,建立告警機制,及時通知安全團隊。
  • 定期審查: 定期審查稽核日誌,評估安全風險,並調整稽核策略。

玄貓認為,稽核日誌是 K8s 安全的重要組成部分。透過合理的組態和分析,我們可以及早發現潛在的安全風險,保護 K8s 叢集的安全。

綜上所述,Kubernetes 稽核日誌是強化雲原生環境安全不可或缺的一環。透過啟用稽核日誌、設計合理的稽核策略,以及建立有效的日誌分析機制,我們可以更全面地掌握 K8s 叢集的安全態勢,及早發現並應對潛在的安全威脅,確保應用程式和資料的安全。