k8s實作
操作k8s範例
用Kind創建k8s cluster
-
假如某個服務器掛了,需要將上面的服務移植到其他服務器
-
為了部署k8s需要拿一個server當作Control plane
- 當作主節點master,控制cluster和維護
- 對k8s進行任務都會經過Control plane
-
要發送命令會先給Control plane 再發送給Compute machines
-
一個pod可以部署多個container
-
每一個Compute machines可以部署多個pod
- 每一個pod可以部署多個container
- container 裡面執行我們的應用程式
-
在只有一台電腦的情況下使用Kind來模擬多服務器
- 原理就是用docker上的container來模擬多台server
-
k8s中的所有資源接稱為resource,包括pod,service,ingress等等
- 每一個resource都有一個name
-
k8s支持多個namespace,底下的name不能重複,不使用namespace即為使用default
-
在高可用情況下會部署多個container plane並在上層增加代理,讓代理先接收資料
- 多個container plane避免單點故障發生
使用kind部署最小cluster
- 每個node本質上使用docker模擬
apiVersion: kind.x-k8s.io/v1alpha4
kind: Cluster
name: dqq
nodes:
- role: control-plane
- role: worker
- role: worker
- 創建cluster
kind create cluster --config cluster-dqq.yaml
- 查看cluster狀態
kubectl cluster-info --context kind-dqq
部署服務
- 再docker中建立image
docker build -t blog:v1.0.0 ./blog
- 將docker上的image導入k8s
kind load docker-image blog:v1.0.0 --name dqq
- 部署程式
apiVersion: apps/v1
kind: Deployment
# 描述Deployment本身的
metadata:
name: dep-blog #deploy name
labels: #可以透過labe選擇resource
app: blog
spec: #詳細描述
replicas: 2 #副本數量
selector: # 透過selector選擇resource,讓他被deployment調度
matchLabels:
app: blog #假設有兩個pod而他們的label都是app: blog的話,這兩個pod都會被調度,也就是都會有兩個副本
template: #設定pod的訊息
# 描述Pod本身的
metadata:
labels:
app: blog #pod的label,這個label會被selector選擇
spec: #pod的詳細描述
containers: #pod裡面包含的容器,此為數組,可以有多個pod
- name: blog #容器名稱
image: blog:v1.0.0 #容器使用的映像檔
imagePullPolicy: IfNotPresent #如果映像檔不存在,則拉取映像檔,反之則不進行拉曲
- 執行k8s命令,會先被control plane接收再分配
kubectl apply -f blog.yaml
- 獲得pod內容
kubectl get pod
kubectl get pod -o wide #獲得詳細內容
service
- 現在有個問題是k8s內的服務如果因為錯誤導致pod重啟時,ip也會跟著變動,因此我們需要使用service來固定pod的ip,儘管他遭到刪除等問題后重啟,ip依然不變
apiVersion: v1
kind: Service
metadata:
name: svc-blog
spec:
type: ClusterIP
ports:
- name: http
port: 5678 #外部訪問端口
targetPort: 5678 #容器內程式開啟端口(原始端口)
protocol: TCP
selector:
app: blog #對應pod的label
- 使用svc來取代直接訪問pod內部實現了loadbalance
node selector
- 假設我們有特別的pod希望部署到特殊的server上,可以使用標籤的方式在node上設定標籤
k label nodes dqq-worker hp=true
- 查看node標籤
k label nodes dqq-worker --list
- 當前標籤下node的訊息
k get node -l hp=true
- 在創建pod的時候新增node selector,來指定對應node的標籤
apiVersion: apps/v1
kind: Deployment
# ...
spec:
replicas: 1
template:
# ...
metadata:
# ...
labels:
# ...
nodeSelector:
hp: "true"
- 可以發現這一個pod永遠沒辦法調度到node-work2上,因為該node並沒有
hp: "true"
這一個標籤
ingress
- 現在問題是目前部署在k8s的服務都只能從內部訪問
- 因此使用nginx將服務代理出來
對cluster新增port映射
- 因為nginx默認開啟的port和當前服務開啟的port不一樣,因此需要新增port mapping
apiVersion: kind.x-k8s.io/v1alpha4
kind: Cluster
name: dqq
nodes:
- role: control-plane
extraPortMappings:
- containerPort: 80
hostPort: 80
protocol: TCP
- containerPort: 443
hostPort: 443
protocol: TCP
- role: worker
- role: worker
- 重新建立cluster
kind delete cluster --name dqq
kind create cluster --config cluster-dqq.yaml
- 安裝ingrss controller
- 所有的k8s都可以是一個yaml欓,這邊使用yaml檔進行安裝
- 會發現其中存在一個nodeSelector,而因為我們希望安裝在control-plane上,因此也需要新增標籤
ingress-controller.yaml
nodeSelector:
ingress-ready: "true"
kubernetes.io/os: linux
- 新增label
k label nodes dqq-control
- 安裝ingress-controller
k apply -f ingress-controller.yaml
- 查看pod情況
- 因為ingress-controller檔案中都有新增一個namespace
- 因為ingress-controller檔案中都有新增一個namespace
- 因此需要指定namespace
k get pod -n ingress-nginx
k get pod -n ingress-nginx -o wide
- 目前image還沒有加入到新cluster中,因此需要重新加入一次(先前使用docker建立完畢)
kind load docker-image blog:v1.0.0 --name dqq
- 部署pod到k8s cluster上
k apply -f dep-dqq.yaml
- 查看pod裡面的訊息
kubectl describe pod <pod-name> -n <namespace>
- 此時發現錯誤
- 發現和nodeSelector有關
{node-role.kubernetes.io/control-plane: }, 2 node(s) didn't match Pod's node affinity/selector. preemption: 0/3 nodes are available: 3 Preemption is not helpful for scheduling}
- 將之前在deployment文件裡面的nodeSelector刪除後再重新應用就可以了
- 因為要能夠被訪問,因此還需要部署service
k appliy -f svc-dqq.yaml
- 從service查看port
k get svc
配置nginx
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-nginx
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- http:
paths:
- path: /blog #訪問/blog時實際上會導向service上
pathType: Prefix
backend:
service:
name: svc-blog
port:
number: 5678 #node的port
- 之後apply後就可以從外部訪問pod了