Kubernetes Pod 的安全強化對於保障容器化應用程式至關重要。本文從容器映像建置到 Pod 執行階段,提供多層次的安全強化策略,包含最小化基礎映像、設定安全上下文、資源限制以及使用 PodSecurityPolicy 等。透過強化容器映像,減少攻擊面,並透過設定 Pod 的安全屬性,限制容器的許可權和資源使用。同時,本文也探討瞭如何利用 PodSecurityPolicy 提升叢集整體安全性,並提供最佳實踐建議,協助開發者和維運人員建構更安全的 Kubernetes 環境。
強化 Kubernetes Pod 的安全性
強化 Kubernetes Pod 的安全性是一個龐大的課題,涵蓋了整個 DevOps 流程:建置、佈署和執行階段。在本章中,我們將重點關注建置和執行階段。為了在建置階段強化 Kubernetes Pod 的安全性,我們將討論如何強化容器映像並設定 Pod(或 Pod 範本)的安全屬性,以減少攻擊面。
強化容器映像
強化容器映像意味著遵循安全最佳實踐或基準來設定容器映像,以減少攻擊面。映像掃描工具只專注於在映像內捆綁的應用程式中尋找公開披露的問題。但是,在建置映像時遵循最佳實踐和安全設定,可以確保應用程式具有最小的攻擊面。
容器映像和 Dockerfile
容器映像是一個檔案,捆綁了微服務二進位制檔案、其依賴項和組態等。容器是映像的執行個體。如今,應用程式開發人員不僅需要寫程式碼來建置微服務,還需要建置 Dockerfile 來容器化微服務。Docker 提供了一個標準化的方法,稱為 Dockerfile。Dockerfile 包含一系列指令,例如複製檔案、設定環境變數、設定開放埠和容器入口點,可以被 Docker 守護程式理解,以建構映像檔。
每個 Dockerfile 指令都會在映像中建立一個檔案層。以下是一些基本的 Dockerfile 指令:
FROM:從基礎映像或父映像初始化新的建置階段。RUN:執行命令並將結果提交到前一個檔案層上。ENV:為執行中的容器設定環境變數。CMD:指定容器將執行的預設命令。COPY/ADD:將檔案或目錄從本地(或遠端)URL 複製到映像的檔案系統中。EXPOSE:指定微服務在容器執行階段將監聽的埠。ENTRYPOINT:與CMD相似,但ENTRYPOINT使容器以可執行檔的形式執行。WORKDIR:為後續指令設定工作目錄。USER:為容器的CMD/ENTRYPOINT設定使用者和群組 ID。
Dockerfile 範例
FROM ubuntu
# 安裝依賴項
RUN apt-get install -y software-properties-common python
RUN add-apt-repository ppa:chris-lea/node.js
RUN echo "deb http://us.archive.ubuntu.com/ubuntu/ precise universe" >> /etc/apt/sources.list
RUN apt-get update
RUN apt-get install -y nodejs
# 建立目錄
RUN mkdir /var/www
# 複製 app.js
ADD app.js /var/www/app.js
# 設定預設命令
CMD ["/usr/bin/node", "/var/www/app.js"]
CIS Docker 基準
CIS Docker 基準提供了有關 Docker 容器管理和管理的。以下是 CIS Docker 基準中關於容器映像的安全建議:
- 為容器映像建立使用者以執行微服務:以非 root 身份執行容器是一個好的做法。使用
USER指令在 Dockerfile 中建立使用者。 - 使用可信賴的基礎映像來建置自己的映像:從公用儲存函式庫下載的映像不能完全信任。建議從頭開始建置映像或使用最小的可信賴映像,例如 Alpine。
- 不要在映像中安裝不必要的套件:安裝不必要的套件會增加攻擊面。建議保持映像精簡。
- 掃描並重新建置映像以套用安全補丁:很可能會在基礎映像或安裝在映像中的套件中發現新的漏洞。建議頻繁掃描映像,並在發現漏洞時重新建置映像。
- 為 Docker 啟用內容信任:內容信任使用數位簽章來確保客戶端和 Docker 登入檔之間的資料完整性。
- 在容器映像中新增
HEALTHCHECK指令:HEALTHCHECK指令定義了一個命令,要求 Docker Engine 定期檢查容器的健康狀態。
程式碼解析
以下是 Dockerfile 的範例:
FROM ubuntu:20.04
# 設定工作目錄
WORKDIR /app
# 複製 package*.json 到 /app 目錄下
COPY package*.json ./
# 安裝依賴項
RUN npm install
# 複製應用程式碼到 /app 目錄下
COPY . .
# 對外暴露 3000 埠
EXPOSE 3000
# 設定環境變數
ENV NAME World
# 設定容器啟動後執行的命令
CMD [ "node", "app.js" ]
內容解密
FROM ubuntu:20.04:使用 Ubuntu 20.04 作為基礎映像。WORKDIR /app:設定工作目錄為/app。COPY package*.json ./:將package*.json複製到/app目錄下。RUN npm install:安裝依賴項。COPY . .:將應用程式碼複製到/app目錄下。EXPOSE 3000:對外暴露 3000 埠。ENV NAME World:設定環境變數NAME為World。CMD [ "node", "app.js" ]:設定容器啟動後執行的命令為node app.js。
這個 Dockerfile 範例示範瞭如何使用 Ubuntu 20.04 作為基礎映像,安裝 Node.js 應用程式的依賴項,並設定容器的啟動命令。
設定 Pod 的安全屬性
為了進一步強化 Kubernetes Pod 的安全性,可以設定 Pod 的安全屬性,例如使用非 root 身份執行容器、限制容器的資源使用等。
PodSecurityPolicy 的強大功能
PodSecurityPolicy(PSP)是一種 Kubernetes 資源,用於控制 Pod 的安全相關設定。PSP 可以用來限制 Pod 的安全屬性,例如容器的執行身份、容器的資源使用等。
組態 Pod 的安全屬性
為了確保 Kubernetes 中的 Pod 安全性,開發人員和安全工程師需要共同努力,在 Pod 和容器層級上透過組態 Kubernetes 提供的安全上下文來增強微服務的安全性。
Pod 安全屬性的分類別
主要的安全屬性可以分為四類別:
- 設定 Pod 的主機名稱空間
- 容器層級的安全上下文
- Pod 層級的安全上下文
- AppArmor 組態檔
設定主機層級的名稱空間給 Pod 使用
在 Pod 規格中的以下屬性用於組態主機名稱空間的使用:
hostPID:預設為false。設為true時允許 Pod 檢視工作節點上的所有行程。hostNetwork:預設為false。設為true時允許 Pod 檢視工作節點上的所有網路堆疊。hostIPC:預設為false。設為true時允許 Pod 檢視工作節點上的所有 IPC 資源。
設定範例
apiVersion: v1
kind: Pod
metadata:
name: ubuntu-1
labels:
app: util
spec:
containers:
- name: ubuntu
image: ubuntu
imagePullPolicy: Always
hostPID: true
hostNetwork: true
hostIPC: true
內容解密:
hostPID: true:允許 Pod 檢視工作節點上的所有行程,這可能會洩露敏感資訊。hostNetwork: true:允許 Pod 檢視工作節點上的所有網路堆疊,可能會導致網路隔離失效。hostIPC: true:允許 Pod 檢視工作節點上的所有 IPC 資源,可能會導致 IPC 資源被未授權存取。
除非必要,否則不應將這些屬性設為 true,因為這會削弱同一工作節點上其他工作負載的安全邊界。
容器的安全上下文
多個容器可以被分組在同一個 Pod 中,每個容器都可以有自己的安全上下文,用於定義許可權和存取控制。容器層級的安全上下文設計提供了更細粒度的 Kubernetes 工作負載安全控制。
主要屬性:
privileged:預設為false。設為true時,使容器內的程式等同於工作節點上的 root 使用者。capabilities:容器執行時預設授予容器一組能力。可以透過組態此屬性新增額外能力或丟棄某些預設能力。allowPrivilegeEscalation:預設為true。設定此屬性直接控制no_new_privs標誌,決定程式是否能獲得比其父程式更多的許可權。readOnlyRootFilesystem:預設為false。設為true時,使容器的根檔案系統唯讀,防止函式庫檔案、組態檔案等被篡改。
範例組態
apiVersion: v1
kind: Pod
metadata:
name: secure-pod
spec:
containers:
- name: secure-container
image: secure-image
securityContext:
privileged: false
capabilities:
drop:
- CAP_SYS_ADMIN
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
內容解密:
privileged: false:確保容器不以特權模式執行,防止容器內的程式擁有過高許可權。capabilities.drop: - CAP_SYS_ADMIN:丟棄CAP_SYS_ADMIN能力,防止容器內的程式執行管理操作。allowPrivilegeEscalation: false:防止程式獲得比其父程式更多的許可權,增強安全性。readOnlyRootFilesystem: true:使容器的根檔案系統唯讀,防止檔案被篡改。
Kubernetes Pod 安全強化策略
Kubernetes Pod 的安全設定對於確保容器化應用程式的安全至關重要。Pod 的安全上下文(Security Context)定義了容器執行時的許可權和行為,進而影響到整個 Pod 的安全性。
容器層級的安全上下文(SecurityContext)
在容器層級,可以透過 SecurityContext 設定多項安全屬性,以控制容器的執行方式。以下是一些重要的安全屬性:
runAsNonRoot:預設為false,設為true時,kubelet 會驗證容器是否以非 root 使用者(UID=0)執行。如果容器嘗試以 root 使用者執行,kubelet 將阻止其啟動。這是一種良好的安全實踐。runAsUser和runAsGroup:用於指定容器入口點程式執行的 UID 和 GID。如果未指定,則預設使用容器映像檔中的使用者設定(例如 Dockerfile 中的USER指令)。這些屬性也可以在 Pod 層級的PodSecurityContext中設定,但容器層級的設定優先順序更高。seLinuxOptions:用於指定容器的 SELinux 上下文。如果未指定,容器執行時將分配一個隨機的 SELinux 上下文給容器。這個屬性同樣可以在PodSecurityContext中設定。
設定容器安全上下文範例
以下是一個設定容器 SecurityContext 的範例 YAML 檔案:
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
labels:
app: web
spec:
hostNetwork: false
hostIPC: false
hostPID: false
containers:
- name: nginx
image: kaizheh/nginx
securityContext:
privileged: false
capabilities:
add:
- NETWORK_ADMIN
readOnlyRootFilesystem: true
runAsUser: 100
runAsGroup: 1000
程式碼詳解:
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
labels:
app: web
spec:
hostNetwork: false
hostIPC: false
hostPID: false
- 這段 YAML 定義了一個名為
nginx-pod的 Pod,並設定了相關的標籤和規格。 hostNetwork、hostIPC和hostPID都設為false,表示該 Pod 不會分享主機的網路、IPC 和 PID 名稱空間,這增強了隔離性。
containers:
- name: nginx
image: kaizheh/nginx
securityContext:
privileged: false
capabilities:
add:
- NETWORK_ADMIN
readOnlyRootFilesystem: true
runAsUser: 100
runAsGroup: 1000
- 在
securityContext中:privileged設為false,表示容器不會以特權模式執行。capabilities.add新增了NETWORK_ADMIN功能,使容器具備管理網路的能力。然而,在生產環境中,除非必要,否則不建議新增此類別功能。readOnlyRootFilesystem設為true,表示容器的根檔案系統是唯讀的,這防止了對系統檔案的意外或惡意修改。runAsUser和runAsGroup分別設為100和1000,表示容器將以 UID 為 100 和 GID 為 1000 的使用者身份執行。
Pod 層級的安全上下文(PodSecurityContext)
Pod 層級的安全上下文會應用到 Pod 中的所有容器。以下是一些重要的 Pod 層級安全屬性:
fsGroup:這是一個特殊的補充群組,用於設定掛載卷的擁有權。具體效果取決於卷的型別。sysctls:用於在執行時組態核心引數。某些 sysctls 命令是名稱空間化的核心引數,適用於 Pod。預設情況下,不安全的 sysctls 是被停用的,不建議在生產環境中啟用。- 與容器層級相同的屬性,如
runAsUser、runAsGroup、runAsNonRoot和seLinuxOptions,但這些屬性在容器層級的設定優先順序更高。
Kubernetes 安全最佳實踐
- 除非必要,否則不要以特權模式執行容器。
- 除非必要,否則不要新增額外的功能(Capabilities)。
- 移除未使用的預設功能。
- 以非 root 使用者執行容器。
- 啟用
runAsNonRoot檢查。 - 將容器的根檔案系統設為唯讀。
遵循這些最佳實踐和正確組態 Pod 及容器的安全上下文,可以顯著提高 Kubernetes 環境的安全性,降低潛在的安全風險。
Kubernetes Pod 安全設定深度解析
在 Kubernetes 環境中,確保 Pod 的安全性是至關重要的。Pod 的安全屬性可以透過多種方式進行設定,包括 SecurityContext、PodSecurityContext 和 AppArmor profiles 等。
SecurityContext 與 PodSecurityContext 的靈活性
SecurityContext 和 PodSecurityContext 提供了對容器和 Pod 的安全屬性進行精細控制的能力。例如,runAsUser、runAsGroup、runAsNonRoot 和 seLinuxOptions 等屬性可以在容器層級的 SecurityContext 和 Pod 層級的 PodSecurityContext 中進行設定。這種靈活性使得使用者能夠根據具體需求對安全屬性進行調整。
apiVersion: v1
kind: Pod
metadata:
name: security-context-demo
spec:
securityContext:
runAsUser: 1000
runAsGroup: 3000
fsGroup: 2000
containers:
- name: demo-container
image: busybox
command: ["sleep", "1h"]
securityContext:
runAsNonRoot: true
seLinuxOptions:
level: "s0:c123,c456"
內容解密:
securityContext定義了 Pod 的安全屬性,包括執行使用者、群組和檔案系統群組。runAsUser和runAsGroup指定了容器內程式的執行使用者和群組。fsGroup指定了與 Pod 相關的檔案系統群組。- 容器層級的
securityContext設定了runAsNonRoot為 true,確保容器內的程式不會以 root 使用者執行。 seLinuxOptions設定了 SELinux 的相關選項。
AppArmor Profiles 的應用
AppArmor profiles 可以用來定義容器內程式的 Linux 許可權、網路資源存取許可權和檔案存取許可權等。為了使用 AppArmor profile,需要在每個節點上載入 profile,並在 Pod 的 annotation 中指定要使用的 profile。
apiVersion: v1
kind: Pod
metadata:
name: hello-apparmor
annotations:
container.apparmor.security.beta.kubernetes.io/hello: localhost/k8s-apparmor-example-deny-write
spec:
containers:
- name: hello
image: busybox
command: ["sh", "-c", "echo 'Hello AppArmor!' && sleep 1h"]
內容解密:
- annotation 中的
container.apparmor.security.beta.kubernetes.io/hello指定了容器hello要使用的 AppArmor profile 名稱。 localhost/k8s-apparmor-example-deny-write表示使用名稱為k8s-apparmor-example-deny-write的 AppArmor profile。- 該 profile 定義了禁止寫入檔案的規則,從而增強了容器的安全性。
PodSecurityPolicy 的強大功能
PodSecurityPolicy(PSP)是一種叢集層級的資源,用於控制 Pod 的安全敏感屬性。透過 PSP,可以限制 Pod 的存取許可權,確保叢集的安全性。
主要的安全屬性控制
privileged:決定 Pod 是否可以以特權模式執行。hostPID、hostNetwork和hostIPC:分別控制 Pod 是否可以使用主機的 PID、網路和 IPC namespace。allowedCapabilities、defaultAddCapabilities和requiredDropCapabilities:控制容器的能力(capabilities)。
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
name: restricted-psp
spec:
privileged: false
hostPID: false
hostNetwork: false
hostIPC: false
allowedCapabilities:
- NET_BIND_SERVICE
defaultAddCapabilities: []
requiredDropCapabilities:
- ALL
內容解密:
privileged: false禁止 Pod 以特權模式執行。hostPID、hostNetwork和hostIPC都設為 false,限制了 Pod 對主機 namespace 的存取。allowedCapabilities指定了允許新增的能力列表。requiredDropCapabilities指定了必須移除的能力列表,增強了容器的安全性。