在現代系統管理中,容器技術已成為不可或缺的一部分。Podman 作為新一代容器引擎,不僅提供與 Docker 相容的介面,更能與 Systemd 和 Kubernetes 無縫整合,簡化容器化服務的管理和佈署。本文將以實際案例逐步說明如何使用 Podman 建立和管理根據容器的 Systemd 服務,並示範如何產生 Kubernetes YAML 資源,方便將應用程式佈署到 Kubernetes 叢集。首先,我們會利用 Podman 建立 MariaDB 和 Gitea 容器,並將它們轉換為 Systemd 服務,確保服務的啟動順序和依賴關係。接著,我們將使用 podman generate kube 命令,從現有的容器生成 Kubernetes YAML 資源,包含 Pod 和 Service 的定義,以便快速佈署到 Kubernetes 叢集。
與 systemd 及 Kubernetes 的互動
技術需求
要完成本章節,您需要一台具備正常運作的 Podman 安裝的機器。與第三章「執行第一個容器」中提到的相同,本文中的所有範例都是在 Fedora 34 系統或更新版本上執行,但您也可以在您選擇的作業系統上重現這些範例。
設定主機作業系統的先決條件
容器技術的誕生是為了簡化並建立可以在獨立主機上分發的系統服務。在下面的章節中,我們將學習如何在容器中執行 MariaDB 和 GIT 服務,同時像管理其他服務一樣管理這些容器,即透過 Systemd 和 systemctl 命令。
首先,讓我們介紹 systemd,一個 Linux 的系統和服務管理器,它在啟動時作為第一個行程(PID 1)執行,並充當 init 系統,啟動和維護使用者空間服務。一旦新的使用者登入主機系統,就會執行單獨的例項來啟動他們的服務。
建立 systemd 單元檔案
單元檔案定義了 systemd 如何啟動和執行服務。每個單元檔案代表一個單一元件,是一個簡單的文字檔案,描述了其行為、在其之前或之後需要執行的內容等。
單元檔案儲存在系統上的幾個不同位置,systemd 按照以下順序尋找它們:
/etc/systemd/system/run/systemd/system/usr/lib/systemd/system
我們可以透過詢問 systemd 來取得預設單元檔案的位置:
# systemctl status sshd
○ sshd.service - OpenSSH server daemon
Loaded: loaded (/usr/lib/systemd/system/sshd.service; disabled; vendor preset: disabled)
Active: inactive (dead)
Docs: man:sshd(8)
man:sshd_config(5)
Podman 使 systemd 整合變得更加容易,它有一個專用的子命令:
# podman generate systemd -h
Generate systemd units.
Description:
Generate systemd units for a pod or container.
The generated units can later be controlled via systemctl(1).
Usage:
podman generate systemd [options] {CONTAINER|POD}
...
管理根據容器的 systemd 服務
在本文中,您將透過一個實際範例學習如何使用 podman generate systemd 命令。我們將建立兩個根據容器的系統服務來建立一個 GIT 儲存函式庫。
範例:建立 GIT 儲存函式庫
對於這個範例,我們將利用兩個著名的開源專案:
- Gitea:GIT 儲存函式庫,也提供了一個漂亮的網頁介面來進行程式碼管理
- MariaDB:用於儲存 Gitea 服務產生的資料的 SQL 資料函式庫
首先,我們需要為我們的資料函式庫使用者生成一個密碼:
# export MARIADB_PASSWORD=my-secret-pw
# podman secret create --env MARIADB_PASSWORD
53149b678d0dbd34fb56800cc
#### 內容解密:
此步驟中,我們首先設定了一個環境變數 MARIADB_PASSWORD 來儲存我們的資料函式庫密碼。接著,我們使用了 podman secret create 命令來建立一個秘密。這個命令將我們的密碼以純文字形式儲存,但對於我們的用途來說已經足夠。由於我們是以 root 身份執行這些容器,這些秘密會以 root-only 許可權儲存在檔案系統上。
# podman secret ls
ID NAME DRIVER CREATED UPDATED
53149b678d0dbd34fb56800cc MARIADB_PASSWORD file 10 hours ago 10 hours ago
# podman secret inspect 53149b678d0dbd34fb56800cc
[
{
"ID": "53149b678d0dbd34fb56800cc",
"CreatedAt": "2022-02-16T00:54:21.01087091+01:00",
"UpdatedAt": "2022-02-16T00:54:21.01087091+01:00",
"Spec": {
"Name": "MARIADB_PASSWORD",
"Driver": {
"Name": "file",
...
#### 內容解密:
這裡,我們列出了所有使用 podman secret ls 命令建立的秘密,並檢查了特定秘密的詳細資訊。這有助於我們驗證秘密是否正確建立和儲存。輸出的 JSON 格式提供了有關秘密的詳細資訊,包括其 ID、建立時間和更新時間等。
管理容器化系統服務的探討
在現代化的系統管理中,容器化技術已經成為不可或缺的一部分。Podman作為一種領先的容器管理工具,不僅提供了與Docker相容的介面,還具備了將容器轉換為系統服務的能力,從而實作了與systemd的無縫整合。本文將探討如何利用Podman與systemd管理容器化服務,並透過具體範例展示其操作流程。
容器化服務的管理挑戰
在容器化技術日益普及的今天,如何有效地管理和監控容器化服務已經成為系統管理員面臨的一大挑戰。傳統的服務管理方式往往無法直接套用於容器化環境,因此需要新的工具和方法來解決這一問題。
Podman與systemd的整合
Podman提供了一個強大的命令podman generate systemd,可以用來生成systemd服務單元檔案,從而實作對容器化服務的管理。下面,我們將透過一個具體的範例來展示這一過程。
建立MariaDB資料函式庫容器
首先,我們需要建立一個MariaDB資料函式庫容器。為此,我們需要先建立一個本地目錄來儲存容器的資料:
# mkdir -p /opt/var/lib/mariadb
接下來,我們可以使用Podman來啟動MariaDB容器:
# podman run -d --network host --name mariadb-service \
-v /opt/var/lib/mariadb:/var/lib/mysql:Z \
-e MARIADB_DATABASE=gitea \
-e MARIADB_USER=gitea \
--secret=MARIADB_PASSWORD,type=env \
docker.io/mariadb:latest
將容器轉換為系統服務
在成功啟動MariaDB容器後,我們可以使用podman generate systemd命令來生成systemd服務單元檔案:
# podman generate systemd --name mariadb-service
內容解密:
此命令會生成一個systemd服務單元檔案,內容如下:
[Unit]
Description=Podman container-mariadb-service.service
Documentation=man:podman-generate-systemd(1)
Wants=network-online.target
After=network-online.target
RequiresMountsFor=/run/containers/storage
[Service]
Environment=PODMAN_SYSTEMD_UNIT=%n
Restart=on-failure
TimeoutStopSec=70
ExecStart=/usr/bin/podman start mariadb-service
ExecStop=/usr/bin/podman stop -t 10 mariadb-service
ExecStopPost=/usr/bin/podman stop -t 10 mariadb-service
PIDFile=/run/containers/storage/overlay-containers/61ae055ef6512cb34c4b3fe1d8feafe6ec174a25547728873932f064921762d1/userdata/conmon.pid
Type=forking
[Install]
WantedBy=default.target
這個檔案定義瞭如何啟動和停止MariaDB容器化服務。
建立Gitea服務
與建立MariaDB容器類別似,我們需要為Gitea服務建立一個本地目錄來儲存資料:
# mkdir -p /opt/var/lib/gitea/data
然後,使用Podman啟動Gitea容器:
# podman run -d --network host --name gitea-service \
-v /opt/var/lib/gitea/data:/data:Z \
docker.io/gitea/gitea:latest
內容解密:
此命令啟動了一個Gitea容器,並將主機上的/opt/var/lib/gitea/data目錄掛載到容器的/data目錄,同時設定了SELinux標籤。
驗證Gitea服務
啟動Gitea容器後,我們可以透過檢查其日誌來驗證服務是否正常執行:
# podman logs gitea-service
內容解密:
此命令輸出了Gitea服務的日誌,顯示了服務的監聽地址和埠等資訊。
管理根據容器的 systemd 服務
在現代的系統管理中,使用容器來佈署應用程式已經變得越來越普遍。Podman 作為一種無守護程式的容器引擎,為管理容器化應用程式提供了極大的靈活性。在本章中,我們將探討如何使用 Podman 將容器化的服務與 systemd 整合,以便更好地管理和控制這些服務。
生成 systemd 單元檔案
要將容器化的服務納入 systemd 管理,首先需要生成對應的 systemd 單元檔案。Podman 提供了 generate systemd 命令來實作這一點。以下是一個具體的例子,展示瞭如何為名為 gitea-service 和 mariadb-service 的容器生成 systemd 單元檔案:
# podman generate systemd --name gitea-service > /etc/systemd/system/container-gitea-service.service
# podman generate systemd --name mariadb-service > /etc/systemd/system/container-mariadb-service.service
內容解密:
podman generate systemd命令用於根據容器的組態生成 systemd 單元檔案。--name引數指定了要為哪個容器生成單元檔案。- 生成的單元檔案被重定向到
/etc/systemd/system/目錄下,以便 systemd 可以找到並管理這些服務。
編輯 Gitea 服務單元檔案以新增依賴
為了確保 Gitea 服務在 MariaDB 服務啟動後才啟動,我們需要在 Gitea 的 systemd 單元檔案中新增對 MariaDB 服務的依賴。這可以透過在單元檔案的 [Unit] 部分新增 Requires 指令來實作。
[Unit]
Description=Podman container-gitea-service.service
Documentation=man:podman-generate-systemd(1)
Wants=network-online.target
After=network-online.target
RequiresMountsFor=/run/containers/storage
Requires=container-mariadb-service.service
內容解密:
Requires=container-mariadb-service.service指令告訴 systemd,Gitea 服務依賴於 MariaDB 服務,必須在 MariaDB 服務啟動後才啟動 Gitea 服務。- 這種依賴關係確保了服務啟動的正確順序,避免因資料函式庫服務未啟動而導致應用程式啟動失敗。
載入並啟動服務
生成並編輯好 systemd 單元檔案後,我們需要通知 systemd 有新的單元檔案可用,然後才能啟動這些服務。
# systemctl daemon-reload
# systemctl start container-mariadb-service.service
# systemctl status container-mariadb-service.service
# systemctl start container-gitea-service.service
# systemctl status container-gitea-service.service
內容解密:
systemctl daemon-reload命令重新載入 systemd 組態,以便它可以發現新的單元檔案。systemctl start命令用於啟動指定的服務。systemctl status命令用於檢查服務的狀態,確認它們是否成功啟動。
設定服務開機自啟
為了讓這些容器化的服務在系統啟動時自動執行,我們需要使用 systemctl enable 命令。
# systemctl enable container-mariadb-service.service
# systemctl enable container-gitea-service.service
內容解密:
systemctl enable命令為指定的服務建立符號連結,使其在系統預設的 target(通常是default.target)被啟動時自動啟動。
生成 Kubernetes YAML 資源
Kubernetes 已成為多節點容器協調的事實標準。Podman 提供了一個有用的功能,可以生成符合 Kubernetes API 規範的 YAML 資源。這些資源可以用於在 Kubernetes 叢集中佈署和管理容器化應用程式。
從執行中的容器生成基本的 Pod 資源
Podman 的 generate kube 命令可以用於從執行中的容器或 Pod 生成 Kubernetes YAML 資源。
$ podman generate kube [options] {CONTAINER|POD|VOLUME}
例如,從一個名為 nginx 的容器生成 Pod 資源:
$ podman run -d -p 8080:80 --name nginx docker.io/library/nginx
$ podman generate kube nginx
內容解密:
podman generate kube命令根據指定的容器或 Pod 的組態生成 Kubernetes YAML 資源。-s或--service選項可以用於生成 Service 資源,以公開容器的埠。-f或--filename選項可以將生成的 YAML 資源輸出到檔案,而不是標準輸出。
透過這種方式,我們可以輕鬆地將現有的容器化應用程式遷移到 Kubernetes 環境中,或者利用 Podman 和 Kubernetes 的強大功能來管理和協調我們的容器化工作負載。
使用Podman產生Kubernetes YAML資源
Podman提供了一個強大的功能,可以將現有的容器轉換成Kubernetes YAML資源。這使得使用者能夠輕鬆地將容器化的應用程式佈署到Kubernetes叢集中。
產生的YAML資源結構
當使用podman generate kube命令時,Podman會產生一個包含Kubernetes資源定義的YAML檔案。這個檔案至少包含四個主要欄位:
apiVersion:定義資源的API版本,例如Pod資源屬於Kubernetes核心API的v1版本。kind:定義資源的種類別,例如Pod或Service。metadata:包含資源的中繼資料,如名稱、名稱空間、標籤和註解等。spec:定義資源的規格,例如Pod中的容器列表、啟動引數、埠號和安全上下文等。
程式碼範例:Pod資源定義
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: "2022-02-10T23:14:25Z"
labels:
app: nginxpod
name: nginx_pod
spec:
containers:
- args:
- nginx
- -g
- daemon off;
image: docker.io/library/nginx:latest
name: nginx
ports:
- containerPort: 80
hostPort: 8080
securityContext:
capabilities:
drop:
- CAP_MKNOD
- CAP_NET_RAW
- CAP_AUDIT_WRITE
內容解密:
apiVersion和kind欄位:這兩個欄位定義了資源的API版本和種類別,在這個例子中,是一個v1版本的Pod資源。metadata欄位:包含了Pod的中繼資料,如建立時間、標籤和名稱等。spec欄位:定義了Pod的規格,包括容器列表、容器名稱、使用的映像檔、啟動引數、埠號對映和安全上下文等。- 容器埠號對映:在這個例子中,容器的80埠被對映到主機的8080埠。
- 安全上下文:定義了容器的安全相關設定,在這個例子中,某些Linux能力(如CAP_MKNOD、CAP_NET_RAW和CAP_AUDIT_WRITE)被丟棄,以提高安全性。
將產生的YAML資源套用到Kubernetes叢集
使用者可以將產生的YAML資源套用到Kubernetes叢集中。首先,可以使用-f選項將輸出儲存到檔案中:
$ podman generate kube nginx –f nginx-pod.yaml
然後,可以使用kubectl create命令將YAML檔案套用到叢集中:
$ kubectl create -f nginx-pod.yaml
或者,可以直接將podman generate kube的輸出導向到kubectl create命令:
$ podman generate kube nginx | kubectl create -f -
產生Pod和Service資源
除了產生Pod資源外,Podman還支援產生Service資源,以提供對Pod的網路存取。可以使用-s選項來產生Service資源:
$ podman generate kube -s nginx
產生的YAML檔案將包含Service資源的定義,例如:
apiVersion: v1
kind: Service
metadata:
creationTimestamp: "2022-02-12T21:54:02Z"
labels:
app: nginxpod
name: nginx_pod
spec:
ports:
- name: "80"
nodePort: 30582
port: 80
targetPort: 80
selector:
app: nginxpod
type: NodePort
---
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: "2022-02-12T21:54:02Z"
labels:
app: nginxpod
name: nginx_pod
spec:
containers:
- args:
- nginx
- -g
- daemon off;
image: docker.io/library/nginx:latest
name: nginx
ports:
- containerPort: 80
內容解密:
Service資源定義:定義了一個名為nginx_pod的Service資源,使用NodePort型別,將外部流量匯入到Pod的80埠。selector欄位:指定了Service所選擇的Pod,根據標籤app: nginxpod進行選擇。ports欄位:定義了Service的埠號組態,將外部的30582埠對映到Pod的80埠。