有時候在使用 Kubernetes 時會因為費用的考量,而讓多個不同的部門或專案使用同一個 cluster ,今天將介紹如何有效及安全的管理。
Container Sandboxing 是用來隔離容器的安全技術主要提供提供額外的隔離層,以防止容器逃逸攻擊並限制容器對主機的存取,
一般在使用 container 時會以以下方式存取 應用程式 → syscall → Linux Kernel → 硬體資源
,惡意程式可能利用kernel漏洞或者
容器逃逸的主要攻擊路徑。
會此有些應對方式,這邊會介紹三個使用: gVisor, Kata, 以及 AWS Nitro Enclaves
gVisor 主要提供 user-space kernel 使用時容器無法直接存取主機內核,相較於以往的存取kernel, gVisor 中間提供過濾功能應用程式 → Sentry (gVisor) → 過濾/模擬 → Linux Kernel
以減少對 kernel的攻擊。並且支援 kubernetes 中的 runtime。
Kata 則是建立獨立的 Kernal Container → 獨立的 Guest OS Kernel → Hypervisor → Host OS
AWS Nitro Enclaves 則是透過硬體隔離,使用 container 時會以以下方式存取 應用程式 → 完全獨立的處理器和記憶體空間 (與主機物理隔離)
安全性而言:Nitro Enclaves > Kata Containers > gVisor > 傳統容器
上述主要提供有哪些選項,在kubernetes中如果需要配置這些可以透過 Runtime Class 指定,在一個 cluster 中可以安裝多個。
在節點上配置 CRI 實作
透過 RuntimeClass 可用的配置選項會依據容器執行介面(CRI)的實作而進行配置。
建立 Runtime class
# RuntimeClass is defined in the node.k8s.io API group
apiVersion: node.k8s.io/v1
kind: RuntimeClass
metadata:
# The name the RuntimeClass will be referenced by.
# RuntimeClass is a non-namespaced resource.
name: myclass
# The name of the corresponding CRI configuration
handler: myconfiguration
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
runtimeClassName: myclass
# ...
在 Kubernetes 的配置中往往會因為費用的考量而將多個環境建立在同一個 cluster 中,這邊會探討針對單一 cluster 有多用途時可以如何管理。
其實在管理上並沒有一個 best practice ,主要會根據當下的使用情境以及組織內部分組而定
這邊主要會是探討在分類時是根據各個不同的 team 或者是 customer ,如果是以團隊為分類核心,那麼會讓各個團隊有各自的namespace並且透過 RBAC 做權限控管,另外開發者可以透過 GitOps 或者 kubectl 直接訪問;但如果是以客戶導向(customer)為主,則是以產品面做namespace分類。
除環境別上的分類,跑在什麼 Node 上也可以做限制,(1) hard multi-tenancy 可以規劃成硬體上的強制分類如使用不同的 VM (2) soft multi-tenancy 則是較為寬鬆的限制,允許可以將不同 namespace 的 application 部署在同一個 Node 中,當部署在同 Node 中時也可以透過 Resource Quotas 的方式限制各組/專案對資源的使用。
額外特別需要考慮到的是 Networking 層面,在預設條件下在 cluster 中的服務是彼此是允許溝通的,因此需要在 Network policy 中特別限制存取。
儲存方面要考量到可以有以下兩種方式(1) 每個 Tenancy 獨立的 StorageClass 完全隔離資料的儲存,team A 和 B 的資料永遠不會混在一起 (2) 如果是共用 StorageClass 需要注意是需要設定 reclaimPolicy: Delete
以避免重複使用相同 PersistentVolume。
另外就是可以使用 Container Sandboxing 做到完全隔離
前面討論的主要是隔離分類,如果需要對共用資源進行動態調配,可以使用以下配置:
API Priority: 控制哪些 API 請求優先處理
Network Quality-of-Service: 控制網路頻寬的優先使用權
Storage: 可以為不同 team 分配不同的 Storage Class 等級
Pod Priority: 設定 Pod 優先度,當高優先度服務需要資源時可以搶占其他 Pod 的資源
DNS: 限制跨 namespace 的 DNS 查詢,主要透過 CoreDNS 配置、NetworkPolicy 以及 dnsPolicy 設定來控制 DNS 解析範圍
apiVersion: v1
kind: List
items:
- apiVersion: v1
kind: ResourceQuota
metadata:
name: pods-high
spec:
hard:
cpu: "1000"
memory: "200Gi"
pods: "10"
scopeSelector:
matchExpressions:
- operator: In
scopeName: PriorityClass
values: ["high"]
- apiVersion: v1
kind: ResourceQuota
metadata:
name: pods-low
spec:
hard:
cpu: "5"
memory: "10Gi"
pods: "10"
scopeSelector:
matchExpressions:
- operator: In
scopeName: PriorityClass
values: ["low"]
apiVersion: v1
kind: Pod
metadata:
name: high-priority
spec:
containers:
- name: high-priority
image: ubuntu
command: ["/bin/sh"]
args: ["-c", "while true; do echo hello; sleep 10;done"]
resources:
requests:
memory: "10Gi"
cpu: "500m"
limits:
memory: "10Gi"
cpu: "500m"
priorityClassName: high
kubectl describe quota
Name: pods-high
Namespace: default
Resource Used Hard
-------- ---- ----
cpu 500m 1k
memory 10Gi 200Gi
pods 1 10
Name: pods-low
Namespace: default
Resource Used Hard
-------- ---- ----
cpu 0 5
memory 0 10Gi
pods 0 10
參考資料
https://kubernetes.io/docs/concepts/security/multi-tenancy/