Kubernetes 生態系蓬勃發展,提供從自助支援到商業服務等多元選項。Canonical 等公司支援 Kubeadm、MicroK8s 和 Charmed Kubernetes 等工具,涵蓋多種平台和雲端環境。選擇 Kubernetes 發行版時,需考量 OpenShift、Rancher、EKS、AKS 和 GCP 等選項,它們在功能和管理工具上有所差異。本文以通用 Kubernetes 為主,程式碼範例也適用於部分雲端原生服務。OpenShift 提供易於設定和維護的優勢,但需要訂閱和 Red Hat 作業系統支援。與 Kubernetes 相比,OpenShift 使用不同的命令列工具、安全策略、路由機制和映像管理方式。Red Hat OpenShift Local 是一款可在本地快速啟動 OpenShift 叢集的工具,而 OKD 則為開源版本。公有雲 Kubernetes 服務包含 AWS EKS、GCP GKE、Azure Container Service 等。

Kubernetes 支援與發行版

Kubernetes 的支援建立在活躍的社群、外部專家和顧問服務之上。雖然 Kubernetes 官方採用自助支援模式,但仍有許多私人組織提供支援和客製化服務。Canonical 作為 Ubuntu 專案的長官者,為 Kubeadm、MicroK8s 和 Charmed Kubernetes 提供支援,涵蓋的平台包括 VMWare、OpenStack、裸機、AWS、Azure、Google、Oracle Cloud、IBM Cloud 和 Rackspace。

Kubernetes 發行版:OpenShift、Rancher、EKS、AKS 和 GCP

目前有多種 Kubernetes 發行版可供選擇。這些發行版都整合了核心的 Kubernetes 功能,但在包含的模組和管理軟體方面存在差異。Kubernetes 是開發商業產品和雲端服務的主要框架。

本文重點關注通用 Kubernetes,而大多數程式碼也適用於某些雲端原生 Kubernetes 服務。

Red Hat OpenShift

OpenShift Container Platform(OCP)是 Red Hat 多雲策略的重要產品。它在市場上獲得了關注,因為它易於設定和維護。Red Hat 將核心 Kubernetes 體驗與一系列有價值的實用工具封裝在一起,以簡化新使用者的入門流程。使用 OpenShift Container Platform 需要訂閱 OpenShift,其中包括 Red Hat 的支援。因此,它僅支援 Red Hat 作業系統,即 Red Hat Enterprise Linux(RHEL)和 Red Hat CoreOS(已停產)。

Red Hat 與雲端供應商建立了強大的合作夥伴關係,提供完全託管的 OpenShift 服務,例如 Red Hat OpenShift Service on AWS(ROSA)、Azure Red Hat OpenShift 和 Red Hat OpenShift on Google Cloud Marketplace。

OpenShift 與 Kubernetes 的主要差異

OpenShift 與 Kubernetes 的主要差異在於:

  • 需要付費訂閱
  • 作業系統支援有限(Red Hat Enterprise Linux(RHEL)和 Red Hat CoreOS)
  • 使用 oc 命令列工具而不是 kubectl
  • 比預設的 Kubernetes 有更嚴格的安全政策
  • 禁止以 root 身份執行容器
  • 使用根據角色的存取控制(RBAC)安全機制
  • 使用 Route 物件而不是 Kubernetes 的 Ingress,根據 HAproxy
  • 使用 ImageStreams 管理容器映像
  • 使用 OpenShift 專案而不是 Kubernetes 名稱空間

OpenShift 使用 Helm 作為軟體套件管理器,簡化了應用程式和服務在 OpenShift Container Platform 叢集上的封裝和佈署。對於 Kubernetes 原生應用程式,建議使用 Kubernetes Operator,因為 Operator 會持續檢查應用程式的狀態,並根據軟體開發人員定義的組態確定應用程式是否正常執行。

Red Hat OpenShift Local

Red Hat OpenShift Local(前身為 Red Hat CodeReady Containers)是在桌面/筆記型電腦上快速啟動 OpenShift 叢集的最佳方式,僅需幾分鐘即可完成。它支援 Linux(x86)、Windows(x86)和 macOS,甚至包括 Intel 和 Apple Silicon(M1 和 M2 處理器)。它是一個簡化版本,依賴虛擬機器(~20GB)來設定、執行、測試和模擬雲端開發環境。它使用 crc 命令列工具來啟動一個完整的實驗室,包括 API 和網頁介面。最新版本 2.10 的需求為四個實體 CPU 核心、9 GB 的可用記憶體和 35 GB 的儲存空間。

Red Hat 也發布了一個名為 OKD 的開源版本的 OpenShift。它是免費使用的,並且包含了其商業產品的大部分功能,但不提供支援。

公有雲中的 Kubernetes

許多雲端供應商都建立了自己的容器協調和管理產品。最流行的雲端原生服務包括:

  • Amazon Elastic Container Service(Amazon ECS)由 Amazon Web Services(AWS)提供
  • Google Container Engine(GKE)由 Google Cloud Platform(GCP)提供
  • Azure Container Service 由 Microsoft Azure 提供
  • IBM Bluemix Cloud Kubernetes Container Service 由 IBM Cloud 提供
  • Oracle Container Cloud Service(OCCS)由 Oracle Cloud 提供
  • Alibaba Cloud Container Registry

Amazon EKS

Amazon Elastic Kubernetes Service(Amazon EKS)是 Amazon Web Services(AWS)的服務。它新增了 eksctl 命令列工具,用於處理 EKS 叢集,並在底層使用 kubectl 命令。

Amazon 也提供了 Amazon Elastic Container Registry(Amazon ECR),一個 AWS 管理的容器映像登入服務,跨區域且完全整合在 AWS 生態系統中。根據 IAM 策略中定義的使用者或 Amazon EC2 例項,可以存取 ECR 容器儲存函式庫和映像。Amazon ECR 管理私有映像儲存函式庫,包括 Docker 和 Open Container Initiative(OCI)映像和工件。Amazon Linux 容器映像已經在 ECR 中可用,使用與 Amazon EC2 中的 Amazon Linux AMI 相同的軟體元件構建。

容器和 Pod

容器是交付軟體的單一單位。但現實世界更為複雜;有時需要多個容器才能提供完整的解決方案。

程式碼範例:建立 Pod

apiVersion: v1
kind: Pod
metadata:
  name: hello-pod
spec:
  containers:
  - name: hello-container
    image: hello-world:latest
    ports:
    - containerPort: 80

內容解密:

此 YAML 程式碼定義了一個名為 hello-pod 的 Pod,其中包含一個名為 hello-container 的容器,使用 hello-world:latest 映像,並暴露了 80 連線埠。

此範例展示瞭如何使用 YAML 組態檔案建立一個簡單的 Pod。Pod 是 Kubernetes 中最小的可佈署單位,它可以包含一個或多個容器。這裡我們只佈署了一個容器,使用了公開的 hello-world 映像,並且指定了容器的連線埠號碼。

在實際應用中,你可以根據需求調整此組態,例如修改映像名稱、新增更多的容器或組態其他資源。透過這種方式,你可以輕鬆地在 Kubernetes 環境中佈署和管理你的應用程式。

現代 IT 基礎設施與 Hello App 簡介

在 Kubernetes 中,Pod 是最小的可佈署單元。Pod 包含一組分享儲存和網路資源的容器,以及執行這些容器的規範。Pod 的名稱來源於一群鯨魚被稱為 pod 的事實。Pod 使得微服務佈署成為可能,其優勢在於它們是鬆散耦合的,並且執行是自治和獨立的。

Pod 的基本概念

Pod 的內容是共置、共同排程的,並在分享的上下文中執行。最佳實踐是將緊密耦合的容器插入 Pod 中,以實作特定的應用程式任務或功能。除了容器之外,Pod 可能還包含在 Pod 啟動期間執行的初始容器。

重點注意事項

  • 為了除錯目的,如果叢集已啟用此功能,可以注入臨時容器。
  • Pod 是 Kubernetes 中最小的可佈署物件。

建立 Hello App

“Hello” 應用程式是一個簡單的容器化實作,它在螢幕上列印 “Hello world” 文字訊息並終止執行。

定義 Dockerfile

首先,您需要定義一個 Dockerfile。您可以將 Dockerfile 重新命名為 Containerfile 以完全符合 OCI 規範。此簡單任務需要您將 UNIX 命令 echo 放入 Dockerfile 中。在執行命令之前,您需要新增一些程式碼行來指示 Docker(或 Podman)有關系統需求、一些後設資料,最後是要執行的命令。

簡單的 Dockerfile 範例
# 一個簡單的 Docker 容器映像檔。
FROM busybox
LABEL org.opencontainers.image.title="Hello World image"
LABEL maintainer="Luca Berton"
# 執行命令
CMD echo "Hello World"

內容解密:

  1. FROM busybox:此指令告訴 Docker 您想要使用另一個映像檔作為起點開始一個新的映像檔。這裡使用的是名為 busybox 的映像檔。
  2. LABEL org.opencontainers.image.title=“Hello World image”:此指令為映像檔新增後設資料,使 Container Registry 能夠搜尋和組織映像檔。
  3. LABEL maintainer=“Luca Berton”:同樣是新增後設資料,這裡指定了映像檔的維護者。
  4. CMD echo “Hello World”:此指令告訴 Docker 在容器啟動時要執行的命令,這裡是列印 “Hello World”。

Linux 基礎映像檔

在 Container Registries 中有大量的基礎映像檔可供應用程式開發使用,您可以在 FROM 指令中使用它們。從另一個映像檔衍生出一個映像檔實際上是重複使用程式碼並從原始映像檔維護者那裡獲得安全更新的最佳方式。

Fedora Linux 和 Ubuntu Linux

您可以選擇使用 Fedora 或 Ubuntu 映像檔作為基礎映像檔。例如:

FROM fedora:latest
FROM ubuntu:latest

這些指令分別選擇了最新版本的 Fedora 和 Ubuntu Linux 發行版。您也可以指定特定的版本,如 FROM fedora:37FROM ubuntu:22.04

版本選擇

  • 使用 latest 標籤可以獲得最新的發行版。
  • 指定版本號(如 3722.04)可以獲得特定的發行版。
  • 使用 rawhide 或特定代號(如 jammy)也可以選擇特定的發行版或版本。

容器映像檔的基礎:選擇適合的Linux發行版

在建立容器映像檔時,選擇一個合適的Linux發行版作為基礎映像檔至關重要。不同的發行版提供了不同的功能、大小和安全性特點,以滿足各種應用需求。

Ubuntu映像檔

Ubuntu是一個流行的Linux發行版,也被廣泛用作容器映像檔的基礎。您可以指定特定的Ubuntu版本,例如使用版本號或代號。使用ubuntu:rolling可以獲得最新的發行版本。然而,需要注意的是,滾動發行版本的支援時間有限,例如目前的22.10版本(Kinetic Kudu)僅支援至2023年7月。

FROM ubuntu:22.04
# 或使用代號
FROM ubuntu:jammy
# 使用滾動發行版本
FROM ubuntu:rolling

內容解密:

  1. FROM ubuntu:22.04:使用Ubuntu 22.04 LTS版本作為基礎映像檔。
  2. FROM ubuntu:jammy:同樣使用Ubuntu 22.04 LTS版本,因為"jammy"是其代號。
  3. FROM ubuntu:rolling:使用最新的Ubuntu發行版本。

Alpine Linux映像檔

Alpine Linux是另一個流行的選擇,特別是因為其小巧的尺寸和安全性。Alpine Linux使用了musl libc和BusyBox,使其映像檔大小約為5 MB。它透過Alpine Package Keeper(apk)包管理器提供對Alpine軟體包倉函式庫的存取。

FROM alpine:latest

內容解密:

  1. FROM alpine:latest:使用最新的Alpine Linux版本作為基礎映像檔。

企業級Linux映像檔

企業級Linux發行版,如Red Hat Enterprise Linux(RHEL)和SUSE Linux Enterprise Server,也提供了容器映像檔。這些映像檔對於需要在企業環境中佈署應用程式的使用者尤其有用。

Red Hat Universal Base Images (UBI)

Red Hat提供了Universal Base Images(UBI),這些映像檔是為RHEL設計的,並且可以在非Red Hat平台上自由重新分發。UBI有多個版本,包括標準版、最小化版、微型版和多服務版,以滿足不同的需求。

# 使用標準UBI映像檔
FROM registry.access.redhat.com/ubi8/ubi
# 使用最小化UBI映像檔
FROM registry.access.redhat.com/ubi8/ubi-minimal

內容解密:

  1. FROM registry.access.redhat.com/ubi8/ubi:使用標準的UBI 8映像檔。
  2. FROM registry.access.redhat.com/ubi8/ubi-minimal:使用最小化的UBI 8映像檔。

SUSE Linux Enterprise Server Base Container Images (BCI)

SUSE也提供了BCI,這些映像檔針對不同的應用場景進行了最佳化,包括基本映像檔、init映像檔、最小化映像檔、微型映像檔和BusyBox映像檔。

# 使用SUSE BCI基本映像檔
FROM registry.suse.com/bci/bci-base

內容解密:

  1. FROM registry.suse.com/bci/bci-base:使用SUSE BCI基本映像檔。

容器安全

容器映像檔可能包含安全漏洞,因此選擇由維護者持續更新的映像檔非常重要。此外,使用漏洞分析引擎掃描映像檔中的已知安全缺陷也是必要的。許多容器倉函式庫整合了靜態分析工具來檢查映像檔的安全性。

現代IT基礎設施與容器化技術

容器映像檔的安全性掃描工具

在現代的DevSecOps流程中,容器映像檔的安全性掃描是至關重要的一環。有許多工具可以掃描每個容器映像檔層,並通知您可能存在的安全威脅。這些工具使用流行的網路漏洞資料函式庫來搜尋安全模式,例如NIST Common Vulnerabilities and Exposures資料函式庫(CVE)、Red Hat Security Bulletins(RHSB)、Ubuntu Security Notices(USN)和Debian Security Advisories(DSA)。

市場上有許多開源和商業產品可供選擇,例如Anchore、Datadog Cloud SIEM、Sophos Cloud Native Security、Bitdefender GravityZone、Sysdig Secure、Red Hat Advanced Cluster Security for Kubernetes和Aqua Security。將其中一個或多個產品整合到您的DevSecOps流程中,是解決和降低安全風險的好方法。

Hello Dockerfile解析

現在您已經瞭解了Dockerfile的格式,接下來可以繼續開發Hello App。Hello App是一個根據Python 3和Flask Restful框架的應用程式。Flask是一個流行的Python網頁應用程式框架,實作於Werkzeug和Jinja2之上。Flask-RESTful是一個流行的Flask擴充功能,用於快速建立REST API。

Dockerfile內容

FROM python:3
LABEL org.opencontainers.image.title="Hello World image"
LABEL maintainer="Luca Berton"
ADD helloworld.py /
RUN pip install flask
RUN pip install flask_restful
EXPOSE 8080
CMD [ "python", "./helloworld.py"]

內容解密:

  1. FROM python:3:指定基礎映像檔為python:3,這是Python官方映像檔的最新版本。
  2. LABEL指令:新增映像檔的後設資料,包括標題和維護者的名稱。
  3. ADD helloworld.py /:將當前目錄下的helloworld.py檔案新增到映像檔的根目錄中。
  4. RUN pip install flaskRUN pip install flask_restful:安裝Flask和Flask-RESTful套件。
  5. EXPOSE 8080:指定容器對外開放的網路埠號。
  6. CMD [ "python", "./helloworld.py"]:指定容器啟動時執行的命令。

Hello應用程式

Hello應用程式是一個簡單的Python程式,將在容器中執行。以下是helloworld.py的內容:

#!/usr/bin/env python3
from flask import Flask, request
from flask_restful import Resource, Api
app = Flask(__name__)
api = Api(app)

class Hello (Resource):
    def get(self):
        return 'Hello World'

api.add_resource(Hello, '/') # Route_1

if __name__ == '__main__':
    app.run('0.0.0.0','8080')

內容解密:

  1. 程式碼使用Flask和Flask-RESTful建立一個簡單的網頁伺服器,監聽8080埠。
  2. 當存取根目錄(’/’)時,傳回’Hello World’字串。
  3. 程式碼使用app.run('0.0.0.0','8080')啟動伺服器,監聽所有網路介面上的8080埠。

依賴管理

為了執行helloworld.py,需要安裝必要的依賴套件,包括Flask和Flask-RESTful。可以使用pip指令安裝這些套件:

pip install flask flask_restful

也可以使用requirements.txt檔案來管理依賴套件:

pip install -r requirements.txt
python helloworld.py

這樣就可以安裝所有必要的依賴套件並執行應用程式。預期的輸出結果是:

* Serving Flask app 'helloworld'
* Running on http://127.0.0.1:8080