k8s Start-up

Jayson Chiang
8 min readApr 16, 2021

假設已經有一個docker image 叫 jaysonchiang/posts:0.0.1

Pod 起手式,建立一個 post.yaml

apiVersion: v1
kind: Pod
metadata:
name: posts
spec:
containers:
- name: posts
image: jaysonchiang/posts:0.0.1

apiVersion: v1 K8s ex extensible — we can add in our own custom objects. This specifies the set of objects we want k8s to look at

kind: Pod 指定要建立的 object 的類型

metadata: Config options for the object we are about to create

name: posts 將這個 Pod 命名為 posts

spec: 實際要應用在這個 object 的屬性

containers: 我們可以在單一個 Pod 裡建立多個 container

- name: posts 將這個 container 命名為 posts

image: jaysonchiang/posts:0.0.1 實際要使用的image。如果不提供版號 0.0.1 那麼會自動被代上 latest

在 cmd 執行 > kubectl apply -f posts.yaml

kubectl get pods ( docker ps)

kubectl exec -it [podName] [cmd] (docker exec -it [containerId] [cmd])

kubectl logs [podName] (docker logs [containerId])

kubectl delete pod [podName]

kubectl describe pod [podName] 取得執行中的pod的資訊

但我們要用 Deployment object 取代 Pod object,Deployment不但同樣能建立Pod,還能當這個Pod壞掉的時侯,會直接重建一個新的Pod

Deployment 起手式 ,建立 posts-depl.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
name: posts-depl
spec:
replicas: 1
selector:
matchLabels:
app: posts
template:
metadata:
labels:
app: posts
spec:
containers:
- name: posts
image: jaysonchiang/posts:0.0.1

執行 kubectl apply -f posts-depl.yaml

kubectl get deployments 檢查正在執行的 Deployment

也可以執行 kubectl get pods 看正在執行的 Pod。此時若執行 kubectl delete pod [podName] 。因為Deployment仍在執行中,所以 k8s 會自動再起一個 pod

kubectl describe deployment [depl_name]

kubectl delete deployment [depl_name]

kubectl rollout restart deployment [depl_name]

接著建立 Service,讓 Pod 之間能互相溝通

Service 起手式 ,建立 posts-srv.yaml

apiVersion: v1
kind: Service
metadata:
name: posts-srv
spec:
type: NodePort
selector:
app: posts
ports:
- name: posts
protocol: TCP
port: 4000
targetPort: 4000

Node Port Service目的是要讓 Pod 有一個讓 Cluster 外部訪問的通道。通常只用於開發環境。(如果不指定 type: NodePort ,8ks 預設是 type: ClusterIP )

其中要注意 port 和 targetPort,分別是對應k8s/Node和對應Pod/Container,為了避免混亂,通常會設定為同一組值。可以看下簡圖:

                        +--Node---------------------------+
| +--Service---+--Pod---------+ |
+---------+ | | (NodePort) | (Container) | |
| Browser |==> 3xxxx ===> 4000 ===> 4000 | |
+---------+ nodePort | | port | targetPort | |
| +------------+--------------+ |
+---------------------------------+

執行 kubectl apply -f posts-srv.yaml

再執行 kubectl get services 應該會看到下面的結果

NAME       TYPE      CLUSTER-IP     EXTERNAL-IP PORT(S)          AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 45h
posts-srv NodePort 10.100.103.230 <none> 4000:32106/TCP 13s

其中的 4000:32106 就是上圖中 Node 內外的Port,代表使用者可以透過瀏覽器走 http://localhost:32106/posts 連到Node

因為我們的 Development 和 Service 是一對一,所以可以寫在同一支 yaml,兩個 object 之間使用 --- 做分格

建立 event-bus-depl.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
name: event-bus-depl
spec:
replicas: 1
selector:
matchLabels:
app: event-bus
template:
metadata:
labels:
app: event-bus
spec:
containers:
- name: event-bus
image: jaysonchiang/event-bus
---
apiVersion: v1
kind: Service
metadata:
name: event-bus-srv
spec:
selector:
app: event-bus
ports:
- name: event-bus
protocol: TCP
port: 4005
targetPort: 4005

其中的Service 因為沒有指定 type ,所以會是預設的 Cluster IP。Cluster IP的特色是建立一個好記的 URL 給它的 Pod. 而且這組URL只能在 Cluster 內使用。

執行 kubectl apply -f event-bus-depl.yaml 應該可以同時看到 2 object 被建立

同樣,也要仿 event-bus-depl.yaml 在原本的 posts-depl.yaml 增加 ClusterIP 的 object ,並將 metadata name: posts-clusterip-srv,避免跟本原本 NodePod object的名稱衝突。(原本的 NodePod object是讓外部Browser連進來用的, 目前仍有存在的必要)

+--Node---------------------------------------------------------+
| |
| +--Pod-------+ +--Pod----------+ |
| | Container |==> | Container | |
| | Posts | Request to | EventBus | |
| +--Service---+ http://event-bus-srv:4005 +--Service------+ |
| | (ClusterIP)| | (ClusterIP) | |
| |posts-clusterip-srv ==>| event-bus-srv | |
| +------------+ +---------------+ |
+---------------------------------------------------------------+

於是 Post Container 可以透過 http://event-bus-srv:4005 發Request 給 EventBus Service,然後EventBus Service 再將訊息傳給 EventBus Pod。

同理,EventBus Pod 裡的 Container 也可以發 Request 到http://posts-srv:4000 給 Pod的Service。

所以 Post Container 所存在的Pod ,其實接了2個 Service:一個是對外的NodePod,一個是對內的 ClusterIP.

因此使用者可以透過瀏覽器,用 http://localhost:3xxxx發 Request 進到Node。Node內部的Pod也可以透過 http://[cluster-service-name]:port 互相溝通。

--

--