跳至主要内容

Basic - Creating a Pod

什麼是 Pod?

在 Kubernetes 中,Pod 是最小的部署單位。Pod 是一組一個或多個容器的集合,這些容器共享網路、儲存資源以及運行環境。Pod 通常用來運行單一應用程式或應用的微服務,並確保容器之間能有效協作。


Pod 的特點

  1. 單一應用單元
    • 每個 Pod 內的容器通常執行相同應用程式的不同部分或密切相關的服務。
  2. 共享資源
    • 網路:Pod 內的所有容器共享同一個 IP 地址和網路端口,能夠輕鬆進行內部通信。
    • 儲存:Pod 可以掛載共用的儲存卷(Volume),用於數據共享。
  3. 短暫性
    • Pod 是短暫的資源,可能因節點失效、升級或其他原因被重新建立。
    • Kubernetes 使用控制器(如 Deployment)來管理 Pod 的生命週期。

Pod 的架構

  1. 容器組
    • Pod 可以包含一個或多個容器(如 Docker),這些容器在同一個 Pod 中運行,並共享網路空間和儲存資源。
  2. 儲存卷(Volume)
    • 提供持久性存儲,支持多種存儲解決方案(如 NFS、Persistent Volume)。
  3. 網路
    • 每個 Pod 都有唯一的 IP 地址,用於與其他 Pod 或服務進行通信。

實作一個 Pod

建立一個 Container

  1. 我們要透過 Golang 建立一個簡單的應用,他只有返回 httpOK,並告訴我他是誰,go run main.go 就可以執行他,預設在 8080port
main.go
package main

import (
"net/http"
"github.com/gin-gonic/gin"
)

func main() {
router := gin.Default()
router.GET("/", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"data": "Hello world v1!"})
})
router.Run()
}
  1. 我們需要初始化 go 的專案,此時會產生出一個 go.mod 的檔案
go mod init main
---

go: creating new go.mod: module main
go.mod
module main

go 1.22.4
  1. 執行 go mod tidy,他會幫我自動找尋所有需要的相關套件,自動添加到 go.mod,並產生 go.sum
go mod tidy
---

go: finding module for package github.com/gin-gonic/gin
go: found github.com/gin-gonic/gin in github.com/gin-gonic/gin v1.10.0
go.mod
module main

go 1.22.4

require github.com/gin-gonic/gin v1.10.0

require (
github.com/bytedance/sonic v1.11.6 // indirect
...中間省略...
gopkg.in/yaml.v3 v3.0.1 // indirect
)
  1. 我們可以使用 dockerfile,透過 docker 包成一個 image,方便後續 kubernetes 部版的時候直接使用,這邊著-t 就是 docker image 的名稱,後面:是版本號,這邊先用 v1.0.0
dockerfile
FROM golang:1.22.4-alpine3.20 as builder

WORKDIR /

COPY . .
RUN go build -o main

FROM alpine:3.20
WORKDIR /
COPY --from=builder /main .
EXPOSE 8080
ENTRYPOINT ["./main"]
docker build -t hello-world:v1.0.0 .
---

[+] Building 4.1s (13/13) FINISHED
=> => ...中間省略...
=> => naming to docker.io/library/hello-world:v1.0.0
  1. 在 docker-desktop 也能看到我們剛剛 build 出來的 image

hello-world-v1-image

  1. 我們試著將他 run 起來看看,也能在 docker desktop 的 containers 中看到他
docker run --rm -p 8080:8080 --name my-hello-world -d hello-world:v1.0.0
---

7a5a678858eb78e3661329e5e72bc94df16bf9786b9f2b0217c93c5bbfdaaa0e

hello-world-v1-container

  1. 透過網站或 curl 或 powershell 都可以看見他

hello-world-v1-http

(Invoke-WebRequest -Uri http://localhost:8080 -UseBasicParsing).Content
---

{"data":"Hello world v1!"}

建立並執行 kubernetes 的設定檔

  1. 首先我們先定義一個 pods 的 yaml 檔案
apiVersion: v1 # 指定 API 的版本,這裡使用的是核心組件 v1 版本
kind: Pod # 定義資源的類型,此處為 Pod
metadata:
name: hello-world # 為 Pod 命名,這個名稱必須在同一個命名空間內唯一
labels: # 添加標籤,用於標識 Pod,方便管理和選擇器使用
app: hello-world # 自定義標籤,標識應用名稱
spec:
containers: # 定義 Pod 中的容器
- name: hello-world # 為容器指定名稱,這是容器內部唯一標識
image: hello-world:v1.0.0 # 指定容器的映像,應包含名稱和標籤
ports: # 定義容器暴露的端口
- containerPort: 8080 # 容器內應用開放的端口,用於處理網路請求
  1. 我們可以透過 kubectl 的 apply 方式去執行他
kubectl.exe apply -f pod.yaml
---

pod/hello-world created
  1. 我們可以透過指令 get pods 取得現在執行的 pods 列表(namespace 是 default 中),也能 kubernetes dashboard 中看到他
kubectl.exe get pods
---

NAME READY STATUS RESTARTS AGE
hello-world 1/1 Running 0 2m55s

hello-world-v1-kubernetes-dashboard

  1. 接下來我們可以透過 describe pod XXX ,去取得他的詳細內容,當然也能在 kubernetes dashboard 中看到詳細內容
kubectl.exe describe pod hello-world
---

Name: hello-world # 這個是pod的名稱
Namespace: default # 這個是namespace
Priority: 0
Service Account: default
Node: docker-desktop/192.168.65.4
Start Time: Thu, 09 Jan 2025 17:00:54 +0800
Labels: app=hello-world
Annotations: <none>
Status: Running
IP: 10.1.0.188 # pod內部的IP
IPs:
IP: 10.1.0.188
Containers:
hello-world:
Container ID: docker://85d5c3654279a7f7f75d47d525638812642f0fb2fb51e856a2d560dc3ec3f01a
Image: hello-world:v1.0.0 # 我們可以看到docker image的tag名稱
Image ID: docker://sha256:7891db34f314ad5dfbb3c87b88d21c27e0625a83d3ab2c5087ddba2992c8af01
Port: 8080/TCP
Host Port: 0/TCP
State: Running
Started: Thu, 09 Jan 2025 17:00:55 +0800
Ready: True
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-r6hw8 (ro)
Conditions:
Type Status
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
kube-api-access-r6hw8:
Type: Projected (a volume that contains injected data from multiple sources)
TokenExpirationSeconds: 3607
ConfigMapName: kube-root-ca.crt
ConfigMapOptional: <nil>
DownwardAPI: true
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
node.kubernetes.io/unreachable:NoExecute op=Exists for 300s

Events: # 在這邊可以看到整個pod建立的過程,很重要,後續需要常常看他
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 7m2s default-scheduler Successfully assigned default/hello-world to docker-desktop
Normal Pulled 7m2s kubelet Container image "hello-world:v1.0.0" already present on machine
Normal Created 7m2s kubelet Created container hello-world
Normal Started 7m2s kubelet Started container hello-world

hello-world-v1-kubernetes-dashboard-pod-detail