iT邦幫忙

2025 iThome 鐵人賽

DAY 25
0
DevOps

不爆肝學習 Ansible 的短暫30天系列 第 25

Day25 - Ansilbe 也可以管理 Container 與雲端資源

  • 分享至 

  • xImage
  •  

今日目標

  • 學會使用 Ansible 管理 container and image
  • 介紹如何透過 Ansible 去做 Podman 部署流程

Why Container not Docker

筆者這裡不以 Docker 為名,而是以 Container 為名,因為 Docker 只是眾多容器技術中的一種,雖然目前最流行,但並非唯一選擇。

其他如 Podman、CRI-O 等也都是不錯的選擇。

使用 Ansible 管理容器化應用時,重點在於理解容器的概念和操作,而非侷限於某一特定技術。

Podman is good 😆

在講解這篇文章之前,筆者從 macOS 被人詬病的 docker desktop 再到後面出的 orbstack,筆者都有使用過,但在遇到 Podman 之後,就毅然決然地將 docker 從系統中移除了,原因有以下幾點:

  1. 無需守護進程:Podman 不需要像 Docker 一樣有一個長時間運行的守護進程,這降低了系統資源的消耗。
  2. 更好的安全性:Podman 支持無根運行,這意味著用戶可以在不需要 root 權限的情況下運行容器,降低了安全風險。
  3. 兼容 Docker CLI:Podman 的命令行界面與 Docker 非常相似,這使得從 Docker 過渡到 Podman 非常容易。
  4. Kubernetes 支持:Podman 可以直接生成 Kubernetes YAML 文件,這對於需要將容器部署到 Kubernetes 集群的用戶來說非常方便。
  5. 開源社區支持:Podman 是由 Red Hat 支持的開源項目,擁有活躍的社區和持續的開發。 <- Ansible 現在也被 Red Hat 收購,沒道理喜歡 Ansible 卻不喜歡 Podman 吧

為什麼 Docker 很流行?因為它是第一個讓容器技術變得易於使用和普及的工具,所以不知不覺就變成了一個代名詞,但各位還是要深入了解容器技術的本質,這樣才能在不同的技術選擇中做出最適合自己的決定。

另外 Podman 在 4.4 版本的時候整合了 Quadlet,有興趣的人可以參考這篇文章

那該怎麼結合 Ansible 與 Container 技術呢?

Ansible 官方有提供 Podman Module 可以使用。

剛剛有提到 Podman 有整合了 Quadlet,所以我們可以直接使用 systemd 來管理 Podman 的容器,這樣就可以很方便地將容器的啟動和停止納入系統服務的管理範疇。

舉個例子

---
- name: "拉取一個 traefik image"
  containers.podman.podman_image:
    # 大家都在介紹 nginx,但是還是有其他好用的,所以筆者這裡來分享 traefik 哈哈
    name: "docker.io/library/traefik:v3.5.2"
    pull: true

# 因為我們要用 Podman 的 systemd 整合,所以要將 application container 的服務單元產生出來
- name: "產生 application systemd 服務單元"
  ansible.builtin.template:
    src: application.template.j2
    dest: "/home/deploy/.config/containers/systemd/application.container"
    mode: "0644"

# 重新載入 systemd 配置並啟動 application container
# daemon_reload: true 確保新的配置檔被讀取
- name: "重新載入 systemd 並重啟 application 服務"
  ansible.builtin.systemd:
    name: "application"
    # 這邊要注意哦,因為 podman 的特性,所以 systemd 服務要加上 scope: user
    scope: user
    state: restarted
    daemon_reload: true

# 建立一個臨時的容器
- name: "建立臨時容器"
  containers.podman.podman_container:
    name: application_tmp
    image: "application:latest"
    state: present

# src 和 dest 的路徑要根據實際情況調整,因為筆者都先隨便打的
- name: "從容器內部複製檔案到 host 上"
  containers.podman.podman_container_copy:
    container: application_tmp
    src: "/application/public/."
    dest: "/home/deploy/application/public"
    from_container: true

# 清理臨時容器,釋放資源
# state: absent 表示完全移除容器
- name: "移除臨時容器"
  containers.podman.podman_container:
    name: application_tmp
    state: absent

# 取得 container 的資訊,確保 container 已經啟動
# retries 和 delay 用於 retry,確保容器有足夠時間重啟
- name: "等待 predeploy 容器啟動完成"
  containers.podman.podman_container_info:
    name: "application"
  register: container_info
  # retries * delay = 60s,因為每次間隔 1s,最多重試 60 次,所以我們就獲得了 60s 的等待時間
  retries: "60"
  delay: "1"
  until: container_info.containers | length > 0 and container_info.containers[0].State.Status == 'running'

- name: "透過 container 執行一些任務,ex: pnpm install"
  containers.podman.podman_container_exec:
    name: "application"
    command: bash -eo pipefail -c "cd /tmp && pnpm install"

# 剛剛介紹了 copy,這邊多補充個要如何 copy 多個 files
- name: "將多個檔案複製 host 主機內"
  containers.podman.podman_container_copy:
    container: "application"
    src: "{{ item }}"
    dest: "/home/deploy/application/shared"
    from_container: true
  loop:
    - "/application/config/prod.yaml"
    - "/application/config/stage.yaml"
    - "/application/config/qa.yaml"

# 停止 application container
# 看到這,各位可能會想:不對啊!剛剛都用 podman module 在控制,啊為什麼這邊會用 systemd stop container,因為剛剛有提到 podman 具備跟 systemd 整合的特性,有這麼方便的特性當然要好好善加利用才對
- name: "停止 application container"
  ansible.builtin.systemd:
    name: "application"
    scope: user
    state: stopped

作業練習時間

練習一:大家可以玩玩 Podman,看看跟 docker 有什麼差異

明日預告

明天我們來學習一些故障排除與維運技巧


上一篇
Day24 - 監控做得好,晚上就睡好
下一篇
Day26 - Ansible 的除錯與維運
系列文
不爆肝學習 Ansible 的短暫30天26
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言