Kubernetes 環境的安全性與資源管理至關重要,本篇探討如何運用 Kubernetes 內建功能與 Ansible 自動化工具強化叢集安全及管理效率。首先介紹 Kustomize 的 YAML 檔案組態與使用方法,接著說明 Pod Security Admission (PSA) 的設定方式與安全標準,並比較 AppArmor 與 SELinux 的差異與應用場景。此外,文章也提供 Seccomp 設定檔範例與 Ansible Dynamic Inventory 的使用技巧,讓讀者瞭解如何動態管理 Kubernetes 資源。最後,文章示範 Ansible Playbook 的撰寫與執行方式,並提供常見問題的解決方案,協助讀者有效運用 Ansible 管理 Kubernetes 叢集。

Kubernetes 安全性與資源管理實務

在 Kubernetes 環境中,安全性與資源管理是至關重要的議題。本章節將探討如何利用 Kubernetes 的內建功能來加強叢集的安全性,並介紹如何使用 Ansible 來自動化佈署和管理 Kubernetes 資源。

使用 Kustomize 管理 Kubernetes 資源

Kustomize 是一種 Kubernetes 組態管理工具,允許使用者自定義和管理 Kubernetes 資源的組態。以下是使用 Kustomize 管理 WordPress 和 MySQL 佈署的範例:

mysql.yaml

apiVersion: v1
kind: Service
metadata:
  name: wordpress-mysql
  labels:
    app: wordpress
spec:
  ports:
  - port: 3306
  selector:
    app: wordpress
    tier: mysql
  clusterIP: None
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-pv-claim
  labels:
    app: wordpress
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 20Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: wordpress-mysql
  labels:
    app: wordpress
spec:
  selector:
    matchLabels:
      app: wordpress
      tier: mysql
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: wordpress
        tier: mysql
    spec:
      containers:
      - image: mysql:5.7.41
        name: mysql
        env:
        - name: MYSQL_ROOT_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysql-pass
              key: password
        ports:
        - containerPort: 3306
          name: mysql
        volumeMounts:
        - name: mysql-persistent-storage
          mountPath: /var/lib/mysql
      volumes:
      - name: mysql-persistent-storage
        persistentVolumeClaim:
          claimName: mysql-pv-claim

wordpress.yaml

apiVersion: v1
kind: Service
metadata:
  name: wordpress
  labels:
    app: wordpress
spec:
  ports:
  - port: 80
  selector:
    app: wordpress
    tier: frontend
  type: LoadBalancer
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: wp-pv-claim
  labels:
    app: wordpress
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 20Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: wordpress
  labels:
    app: wordpress
spec:
  selector:
    matchLabels:
      app: wordpress
      tier: frontend
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: wordpress
        tier: frontend
    spec:
      containers:
      - image: wordpress:6.1.1-apache
        name: wordpress
        env:
        - name: WORDPRESS_DB_HOST
          value: wordpress-mysql
        - name: WORDPRESS_DB_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysql-pass
              key: password
        ports:
        - containerPort: 80
          name: wordpress
        volumeMounts:
        - name: wordpress-persistent-storage
          mountPath: /var/www/html
      volumes:
      - name: wordpress-persistent-storage
        persistentVolumeClaim:
          claimName: wp-pv-claim

Kustomize 的使用

要套用這些資源到 Kubernetes 叢集,可以手動執行以下命令:

$ kubectl apply -k ./

或者,可以使用 Ansible 的 kubernetes.core.kustomize lookup plugin 自動化執行 Kustomization 目錄。

Pod Security Admission (PSA)

Pod Security Admission (PSA) 是 Kubernetes 的一個內建功能,用於在名稱空間層級實施 Pod 安全標準。從 Kubernetes v1.23 版本開始,PSA 已預設啟用。

設定 Pod 安全標準

可以使用以下標籤來設定 Pod 安全標準:

pod-security.kubernetes.io/<MODE>: <LEVEL>

其中,<MODE> 可以是 enforceauditwarn,而 <LEVEL> 可以是 privilegedbaselinerestricted

例如,以下命令在 example 名稱空間上啟用 warn Pod 安全標準:

$ kubectl label --overwrite ns example pod-security.kubernetes.io/warn=baseline pod-security.kubernetes.io/warn-version=latest

這樣,每當嘗試檢索 latest 標籤時,就會收到警告訊息,提醒您違反了 Pod 安全標準。

AppArmor

AppArmor 是一種 Linux 安全工具,透過授予存取許可權來控制對系統資源的存取。它與 SELinux 不同,主要差異在於 AppArmor 是根據路徑的安全設定檔,而 SELinux 是根據檔案標籤的安全策略。

AppArmor 與 SELinux 的比較

功能AppArmorSELinux
存取控制根據路徑的安全設定檔根據檔案標籤的安全策略
Linux 發行版主要用於 SUSE 和 Ubuntu主要用於 RHEL/Fedora
控制級別中等

Kubernetes 安全強化:AppArmor 與 Seccomp 應用

Kubernetes 在版本 1.4 之後開始支援 AppArmor,提供了一種限制容器存取資源的方法。AppArmor 是一種 Linux 核心模組,能夠透過定義安全規則來控管容器的行為,包括檔案存取、系統呼叫以及與其他容器或行程的互動。

AppArmor 設定與應用

要使用 AppArmor,首先需要為容器建立一個設定檔,定義容器的存取許可權。這個設定檔將決定容器可以存取哪些檔案和目錄、可以進行哪些系統呼叫,以及可以與哪些其他容器或行程互動。此外,還需要設定容器執行環境,以確保在容器啟動時載入 AppArmor 設定檔。Kubernetes 支援的容器執行環境,如 Docker、CRI-O 和 containerd,都能夠支援 AppArmor。

設定 AppArmor

AppArmor 設定檔是針對每個 Pod 進行設定的,可以透過加入以下註解來指定:

container.apparmor.security.beta.kubernetes.io/<container_name>: <profile_ref>

例如,若要為名為 nginx 的容器套用名為 localhost/nginx-profile 的 AppArmor 設定檔,可以在 Pod 的設定檔中加入以下註解:

metadata:
  annotations:
    container.apparmor.security.beta.kubernetes.io/nginx: localhost/nginx-profile

佈署與管理

可以使用 kubectl 或 Ansible 的 kubernetes.core.k8s 模組來佈署受 AppArmor 保護的應用程式。不過,Kubernetes 並沒有原生的方法來將 AppArmor 設定檔載入到節點上,但可以透過 Ansible 作為初始化指令碼來實作。

Seccomp:限制系統呼叫

Seccomp(Secure Computing Mode)是 Linux 核心提供的一種安全機制,可以用來限制行程的系統呼叫。透過建立 Seccomp 設定檔,可以定義容器可以進行哪些系統呼叫,以及這些系統呼叫的引數和引數。

設定 Seccomp

要使用 Seccomp,需要在 Kubernetes 設定檔中指定 Seccomp 設定檔的位置。例如:

securityContext:
  seccompProfile:
    type: localhost
    localhostProfile: profiles/audit.json

上述設定指定了使用位於 profiles/audit.json 的 Seccomp 設定檔。

Seccomp 設定檔範例

以下是一個簡單的 Seccomp 設定檔範例,內容如下:

{
  "defaultAction": "SCMP_ACT_LOG"
}

這個設定檔將所有系統呼叫記錄到日誌中。

Ansible Dynamic Inventory:動態管理 Kubernetes 資源

Ansible Dynamic Inventory 能夠自動從外部來源(如雲端服務供應商、CMDB 等)產生 Ansible Inventory。這使得使用者能夠動態地佈署基礎架構和應用程式,並且快速地自動化它們。

設定 Ansible Dynamic Inventory

要使用 Ansible Dynamic Inventory,需要在 ansible.cfg 中啟用 kubernetes.core.k8s 外掛:

[inventory]
enable_plugins = kubernetes.core.k8s

然後,可以建立一個名為 inventory.k8s.yml 的檔案,內容如下:

plugin: kubernetes.core.k8s
connections:
  - namespaces:
      - ansible-examples

這個設定將會列出 ansible-examples 名稱空間中的所有容器。

使用 Ansible Inventory 管理 Kubernetes 資源

可以使用 ansible-inventory 命令來列出或以圖形方式顯示指定名稱空間中的 Pod。例如:

$ ansible-inventory -i inventory.k8s.yml --list
$ ansible-inventory -i inventory.k8s.yml --graph

這些命令將會顯示指定名稱空間中的 Pod 資訊。

Ansible 在 Kubernetes 管理上的應用

Ansible 在 Kubernetes 環境中扮演著自動化管理的關鍵角色,特別是在佈署和管理大規模分散式系統時。透過使用 Ansible 的 Playbook,以 YAML 格式撰寫的簡單易懂的指令碼,可以快速完成諸如節點組態、網路設定和儲存卷設定等任務。

使用 Ansible 執行 Kubernetes 資源管理

在 Kubernetes 環境中,Ansible 可以用來自動化許多手動流程,例如佈署節點、組態網路設定和設定永續性資料儲存卷等。這使得在多節點叢集環境中實作一致性和高效管理成為可能。

簡化 Kubernetes 應用佈署

透過 Ansible 的 Playbook,可以輕鬆地在 Kubernetes 叢集中佈署現代化的雲原生應用。這不僅簡化了佈署流程,也確保了不同基礎設施之間的一致性,無論這些基礎設施是本地佈署還是託管在公有雲上,如 Amazon Web Services (AWS) EC2 例項或其他執行 Linux 發行版的雲端服務提供商。

開發與維運流程

現代雲原生應用的開發和維運流程通常遵循如圖 6-1 所示的工作流程:

  • DEV(開發):軟體開發團隊進行開發工作。
  • SIT(系統整合測試):軟體開發人員和 QA 工程師進行系統整合測試。
  • UAT(使用者驗收測試):選定的客戶進行使用者驗收測試。
  • PROD(生產):公開使用者使用的生產環境。

此圖示

@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

title Kubernetes 安全與資源管理實務

package "Kubernetes Cluster" {
    package "Control Plane" {
        component [API Server] as api
        component [Controller Manager] as cm
        component [Scheduler] as sched
        database [etcd] as etcd
    }

    package "Worker Nodes" {
        component [Kubelet] as kubelet
        component [Kube-proxy] as proxy
        package "Pods" {
            component [Container 1] as c1
            component [Container 2] as c2
        }
    }
}

api --> etcd : 儲存狀態
api --> cm : 控制迴圈
api --> sched : 調度決策
api --> kubelet : 指令下達
kubelet --> c1
kubelet --> c2
proxy --> c1 : 網路代理
proxy --> c2

note right of api
  核心 API 入口
  所有操作經由此處
end note

@enduml

圖表翻譯: 此圖示呈現了現代雲原生應用的典型開發和維運流程,從開發(DEV)階段開始,經過系統整合測試(SIT)、使用者驗收測試(UAT),最終到達生產(PROD)階段。

使用 Ansible Playbook 進行 Kubernetes 資源管理

一個簡單的 Ansible Playbook,例如 ping.yml,可以用來測試 Ansible 控制器與目標節點之間的連線。

---
- name: test
  hosts: all
  gather_facts: false
  tasks:
    - name: test connection
      ansible.builtin.ping:

內容解密:

  1. `

表示 YAML 檔案的開始。 2.- name: test定義了 Playbook 的名稱為 "test"。 3.hosts: all指定了該 Playbook 將在所有主機上執行。 4.gather_facts: false表示不收集主機的事實資訊,以加快 Playbook 的執行速度。 5.tasks:定義了要執行的任務列表。 6.- name: test connection是第一個任務的名稱,用於測試連線。 7.ansible.builtin.ping:使用內建的ping` 模組測試與目標主機的連線。

執行此 Playbook 可以使用如下命令:

$ ansible-playbook -i inventory.k8s.yml ping.yml

成功的執行將輸出包括 “Play recap status: ok=1 changed=0” 和任務狀態等資訊。

疑難排解與最佳實踐

在連線到遠端 Pod 時可能會遇到 “Failed to create temporary directory” 的錯誤,這通常是由於許可權問題。解決方案包括調整 ansible.cfg 檔案中的 remote_tmp 路徑到 /tmp 目錄下,以避免許可權問題。

調整 remote_tmp 路徑範例

[defaults]
remote_tmp = /tmp/.ansible-${USER}/tmp

內容解密:

  1. [defaults] 指定了 Ansible 組態檔案的預設部分。
  2. remote_tmp = /tmp/.ansible-${USER}/tmp 定義了遠端臨時目錄的路徑,以避免許可權問題。