kubernetes環境搭建
安裝kubernetes集群
kubernetes的安裝過程極其復雜,對Linux運維不熟悉的情況下安裝kubernetes極為困難,再加上國內無法訪問google服務器,我們安裝k8s就更加困難
kubeasz項目(https://github.com/easzlab/kubeasz)極大的簡化了k8s集群的安裝過程,使我們可以離線一鍵安裝k8s集群
准備第一台虛擬機
設置虛擬機cpu
上傳離線安裝文件
- 將
ansible
目錄上傳到/etc/
目錄下 - 將
easzup
上傳到/root
目錄下
准備離線安裝環境
在CentOS7虛擬機中執行下面操作
cd ~/
## 下載 kubeasz 的自動化安裝腳本文件: easzup,如果已經上傳過此文件,則不必執行這一步
export release=2.2.0
curl -C- -fLO --retry 3 https://github.com/easzlab/kubeasz/releases/download/${release}/easzup
## 對easzup文件設置執行權限
chmod +x ./easzup
## 下載離線安裝文件,並安裝配置docker,
## 如果離線文件已經存在則不會重復下載,
## 離線安裝文件存放路徑: /etc/ansible
./easzup -D
## 啟動kubeasz工具使用的臨時容器
./easzup -S
## 進入該容器
docker exec -it kubeasz sh
## 下面命令在容器內執行
## 配置離線安裝
cd /etc/ansible
sed -i 's/^INSTALL_SOURCE.*$/INSTALL_SOURCE: "offline"/g' roles/chrony/defaults/main.yml
sed -i 's/^INSTALL_SOURCE.*$/INSTALL_SOURCE: "offline"/g' roles/ex-lb/defaults/main.yml
sed -i 's/^INSTALL_SOURCE.*$/INSTALL_SOURCE: "offline"/g' roles/kube-node/defaults/main.yml
sed -i 's/^INSTALL_SOURCE.*$/INSTALL_SOURCE: "offline"/g' roles/prepare/defaults/main.yml
exit
## 安裝 python,已安裝則忽略這一步
yum install python -y
導入鏡像
為了節省時間,后面課程中使用的docker鏡像不用再花時間從網絡下載
將課前資料中 images.gz 中的鏡像導入 docker
docker load -i images.gz
准備三台服務器
准備三台服務器,一台master,兩台工作節點,他們的ip地址可以用任意的地址,最好設置為固定ip
下面測試中使用的ip為:
- 192.168.64.191
- 192.168.64.192
- 192.168.64.193
從第一台虛擬機克隆兩台虛擬機
這三台虛擬機,第一台虛擬機作為master,另兩台作為工作節點
在master上繼續配置安裝環境
## 安裝pip,已安裝則忽略這一步
wget -O /etc/yum.repos.d/epel-7.repo https://mirrors.aliyun.com/repo/epel-7.repo
yum install git python-pip -y
## pip安裝ansible(國內如果安裝太慢可以直接用pip阿里雲加速),已安裝則忽略這一步
pip install pip --upgrade -i https://mirrors.aliyun.com/pypi/simple/
pip install ansible==2.6.12 netaddr==0.7.19 -i https://mirrors.aliyun.com/pypi/simple/
## 在ansible控制端配置免密碼登陸其他節點服務器
ssh-keygen -t ed25519 -N '' -f ~/.ssh/id_ed25519
## 公鑰復制到所有節點,包括master自己
## 按提示輸入yes和root管理員的密碼
ssh-copy-id 192.168.64.191
ssh-copy-id 192.168.64.192
ssh-copy-id 192.168.64.193
配置集群服務器的ip
cd /etc/ansible && cp example/hosts.multi-node hosts && vim hosts
如果內存有限, 可以只部署兩台服務器進行測試
- 主服務器既作為控制節點, 又作為工作節點
- 減少etcd服務數量
## 檢查集群主機狀態
ansible all -m ping
一鍵安裝k8s集群
安裝步驟非常多,時間較長,耐心等待安裝完成
cd /etc/ansible
ansible-playbook 90.setup.yml
設置kubectl命令別名
## 設置 kubectl 命令別名 k
echo "alias k='kubectl'" >> ~/.bashrc
## 使設置生效
source ~/.bashrc
驗證安裝
k get cs
---------------------------------------------------------
NAME STATUS MESSAGE ERROR
etcd-1 Healthy {"health":"true"}
scheduler Healthy ok
controller-manager Healthy ok
etcd-2 Healthy {"health":"true"}
etcd-0 Healthy {"health":"true"}
k get node
---------------------------------------------------------------------
NAME STATUS ROLES AGE VERSION
192.168.64.191 Ready,SchedulingDisabled master 5d23h v1.15.2
192.168.64.192 Ready node 5d23h v1.15.2
192.168.64.193 Ready node 5d23h v1.15.2
初步嘗試 kubernetes
kubectl run 命令是最簡單的部署引用的方式,它自動創建必要組件,這樣,我們就先不必深入了解每個組件的結構
使用 ReplicationController 和 pod 部署應用
Pod是用來封裝Docker容器的對象,它具有自己的虛擬環境(端口, 環境變量等),一個Pod可以封裝多個Docker容器.
RC是用來自動控制Pod部署的工具,它可以自動啟停Pod,對Pod進行自動伸縮.
下面我們用命令部署一個RC
cd ~/
k run \
--image=luksa/kubia \
--port=8080 \
--generator=run/v1 kubia
k get rc
---------------------------------------
NAME DESIRED CURRENT READY AGE
kubia 1 1 1 24s
k get pods
----------------------------------------------
NAME READY STATUS RESTARTS AGE
kubia-9z6kt 1/1 Running 0 28s
kubectl run 幾個參數的含義
-
--image=luksa/kubia
- 鏡像名稱
-
--port=8080
- pod 對外暴露的端口
-
--generator=run/v1 kubia
- 創建一個ReplicationController
使用 service 對外暴露 pod
k expose \
rc kubia \
--type=NodePort \
--name kubia-http
k get svc
------------------------------------------------------------------------------
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubia-http NodePort 10.68.194.195 <none> 8080:20916/TCP 4s
這里創建了一個 service 組件,用來對外暴露pod訪問,在所有節點服務器上,暴露了20916端口,通過此端口,可以訪問指定pod的8080端口
訪問以下節點服務器的20916端口,都可以訪問該應用
注意: 要把端口修改成你生成的隨機端口
pod自動伸縮
k8s對應用部署節點的自動伸縮能力非常強,只需要指定需要運行多少個pod,k8s就可以完成pod的自動伸縮
## 將pod數量增加到3個
k scale rc kubia --replicas=3
k get po -o wide
----------------------------------------------------------------------------------------------------------------
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
kubia-q7bg5 1/1 Running 0 10s 172.20.3.29 192.168.64.193 <none> <none>
kubia-qkcqh 1/1 Running 0 10s 172.20.2.30 192.168.64.192 <none> <none>
kubia-zlmsn 1/1 Running 0 16m 172.20.3.28 192.168.64.193 <none> <none>
## 將pod數量減少到1個
k scale rc kubia --replicas=1
## k8s會自動停止兩個pod,最終pod列表中會只有一個pod
k get po -o wide
---------------------------------------------------------------------------------------------------------------------
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
kubia-q7bg5 1/1 Terminating 0 6m1s 172.20.3.29 192.168.64.193 <none> <none>
kubia-qkcqh 1/1 Terminating 0 6m1s 172.20.2.30 192.168.64.192 <none> <none>
kubia-zlmsn 1/1 Running 0 22m 172.20.3.28 192.168.64.193 <none> <none>
pod
使用部署文件手動部署pod
創建kubia-manual.yml
部署文件
cat <<EOF > kubia-manual.yml
apiVersion: v1 ## k8s api版本
kind: Pod ## 該部署文件用來創建pod資源
metadata:
name: kubia-manual ## pod名稱前綴,后面會追加隨機字符串
spec:
containers: ## 對pod中容器的配置
- image: luksa/kubia ## 鏡像名
name: kubia ## 容器名
ports:
- containerPort: 8080 ## 容器暴露的端口
protocol: TCP
EOF
使用部署文件創建pod
k create -f kubia-manual.yml
k get po
-----------------------------------------------
NAME READY STATUS RESTARTS AGE
kubia-manual 1/1 Running 0 19s
查看pod的部署文件
## 查看pod的部署文件
k get po kubia-manual -o yaml
查看pod日志
k logs kubia-manual
pod端口轉發
使用 kubectl port-forward 命令設置端口轉發,對外暴露pod.
使用服務器的 8888 端口,映射到 pod 的 8080 端口
k port-forward kubia-manual --address localhost,192.168.64.191 8888:8080
## 或在所有網卡上暴露8888端口
k port-forward kubia-manual --address 0.0.0.0 8888:8080
在瀏覽器中訪問 http://192.168.64.191:8888/
pod 標簽
可以為 pod 指定標簽,通過標簽可以對 pod 進行分組管理
ReplicationController,ReplicationSet,Service中,都可以通過 Label 來分組管理 pod
創建pod時指定標簽
通過kubia-manual-with-labels.yml
部署文件部署pod
在部署文件中為pod設置了兩個自定義標簽:creation_method
和env
cat <<EOF > kubia-manual-with-labels.yml
apiVersion: v1 ## api版本
kind: Pod ## 部署的資源類型
metadata:
name: kubia-manual-v2 ## pod名
labels: ## 標簽設置,鍵值對形式
creation_method: manual
env: prod
spec:
containers: ## 容器設置
- image: luksa/kubia ## 鏡像
name: kubia ## 容器命名
ports: ## 容器暴露的端口
- containerPort: 8080
protocol: TCP
EOF
使用部署文件創建資源
k create -f kubia-manual-with-labels.yml
查看pod的標簽
列出所有的pod,並顯示pod的標簽
k get po --show-labels
------------------------------------------------------------
NAME READY STATUS RESTARTS AGE LABELS
kubia-5rz9h 1/1 Running 0 109s run=kubia
kubia-manual 1/1 Running 0 52s <none>
kubia-manual-v2 1/1 Running 0 10s creation_method=manual,env=prod
以列的形式列出pod的標簽
k get po -L creation_method,env
-----------------------------------------------------------------------------
NAME READY STATUS RESTARTS AGE CREATION_METHOD ENV
kubia-5rz9h 1/1 Running 0 4m19s
kubia-manual 1/1 Running 0 3m22s
kubia-manual-v2 1/1 Running 0 2m40s manual prod
修改pod的標簽
pod kubia-manual-v2
的env標簽值是prod
, 我們把這個標簽的值修改為 debug
修改一個標簽的值時,必須指定 --overwrite
參數,目的是防止誤修改
k label po kubia-manual-v2 env=debug --overwrite
k get po -L creation_method,env
---------------------------------------------------------------------------
NAME READY STATUS RESTARTS AGE CREATION_METHOD ENV
kubia-5rz9h 1/1 Running 0 15m
kubia-manual 1/1 Running 0 14m
kubia-manual-v2 1/1 Running 0 13m manual debug
為pod kubia-manual
設置標簽
k label po kubia-manual creation_method=manual env=debug
為pod kubia-5rz9h
設置標簽
k label po kubia-5rz9h env=debug
查看標簽設置的結果
k get po -L creation_method,env
--------------------------------------------------------------------------
AME READY STATUS RESTARTS AGE CREATION_METHOD ENV
kubia-5rz9h 1/1 Running 0 18m debug
kubia-manual 1/1 Running 0 17m manual debug
kubia-manual-v2 1/1 Running 0 16m manual debug
使用標簽來查詢 pod
查詢 creation_method=manual
的pod
## -l 查詢
k get po \
-l creation_method=manual \
-L creation_method,env
---------------------------------------------------------------------------
NAME READY STATUS RESTARTS AGE CREATION_METHOD ENV
kubia-manual 1/1 Running 0 28m manual debug
kubia-manual-v2 1/1 Running 0 27m manual debug
查詢有 env 標簽的 pod
## -l 查詢
k get po \
-l env \
-L creation_method,env
---------------------------------------------------------------------------
NAME READY STATUS RESTARTS AGE CREATION_METHOD ENV
kubia-5rz9h 1/1 Running 0 31m debug
kubia-manual 1/1 Running 0 30m manual debug
kubia-manual-v2 1/1 Running 0 29m manual debug
查詢 creation_method=manual
並且 env=debug
的 pod
## -l 查詢
k get po \
-l creation_method=manual,env=debug \
-L creation_method,env
---------------------------------------------------------------------------
NAME READY STATUS RESTARTS AGE CREATION_METHOD ENV
kubia-manual 1/1 Running 0 33m manual debug
kubia-manual-v2 1/1 Running 0 32m manual debug
查詢不存在 creation_method 標簽的 pod
## -l 查詢
k get po \
-l '!creation_method' \
-L creation_method,env
-----------------------------------------------------------------------
NAME READY STATUS RESTARTS AGE CREATION_METHOD ENV
kubia-5rz9h 1/1 Running 0 36m debug
其他查詢舉例:
creation_method!=manual
env in (prod,debug)
env notin (prod,debug)
把pod部署到指定的節點服務器
我們不能直接指定服務器的地址來約束pod部署的節點
通過為node設置標簽,在部署pod時,使用節點選擇器,來選擇把pod部署到匹配的節點服務器
下面為名稱為192.168.64.193
的節點服務器,添加標簽gpu=true
k label node \
192.168.64.193 \
gpu=true
k get node \
-l gpu=true \
-L gpu
------------------------------------------------------
NAME STATUS ROLES AGE VERSION GPU
192.168.64.193 Ready node 14d v1.15.2 true
部署文件,其中節點選擇器nodeSelector
設置了通過標簽gpu=true
來選擇節點
cat <<EOF > kubia-gpu.yml
apiVersion: v1
kind: Pod
metadata:
name: kubia-gpu ## pod名
spec:
nodeSelector: ## 節點選擇器,把pod部署到匹配的節點
gpu: "true" ## 通過標簽 gpu=true 來選擇匹配的節點
containers: ## 容器配置
- image: luksa/kubia ## 鏡像
name: kubia ## 容器名
EOF
創建pod kubia-gpu
,並查看pod的部署節點
k create -f kubia-gpu.yml
k get po -o wide
----------------------------------------------------------------------------------------------------------------------
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
kubia-5rz9h 1/1 Running 0 3m13s 172.20.2.35 192.168.64.192 <none> <none>
kubia-gpu 1/1 Running 0 8m7s 172.20.3.35 192.168.64.193 <none> <none>
kubia-manual 1/1 Running 0 58m 172.20.3.33 192.168.64.193 <none> <none>
kubia-manual-v2 1/1 Running 0 57m 172.20.3.34 192.168.64.193 <none> <none>
查看pod kubia-gpu
的描述
k describe po kubia-gpu
------------------------------------------------
Name: kubia-gpu
Namespace: default
Priority: 0
Node: 192.168.64.193/192.168.64.193
......
pod 注解
可以為資源添加注解
注解不能被選擇器使用
## 注解
k annotate pod kubia-manual tedu.cn/shuoming="foo bar"
k describe po kubia-manual
namespace
可以使用命名空間對資源進行組織管理
不同命名空間的資源並不完全隔離,它們之間可以通過網絡互相訪問
查看命名空間
## namespace
k get ns
k get po --namespace kube-system
k get po -n kube-system
創建命名空間
新建部署文件custom-namespace.yml
,創建命名空間,命名為custom-namespace
cat <<EOF > custom-namespace.yml
apiVersion: v1
kind: Namespace
metadata:
name: custom-namespace
EOF
123456
## 創建命名空間
k create -f custom-namespace.yml
k get ns
--------------------------------
NAME STATUS AGE
custom-namespace Active 2s
default Active 6d
kube-node-lease Active 6d
kube-public Active 6d
kube-system Active 6d
將pod部署到指定的命名空間中
創建pod,並將其部署到命名空間custom-namespace
## 創建 Pod 時指定命名空間
k create \
-f kubia-manual.yml \
-n custom-namespace
## 默認訪問default命名空間,默認命名空間中不存在pod kubia-manual
k get po kubia-manual
## 訪問custom-namespace命名空間中的pod
k get po kubia-manual -n custom-namespace
----------------------------------------------------------
NAME READY STATUS RESTARTS AGE
kubia-manual 0/1 ContainerCreating 0 59s
刪除資源
## 按名稱刪除, 可以指定多個名稱
## 例如: k delete po po1 po2 po3
k delete po kubia-gpu
## 按標簽刪除
k delete po -l creation_method=manual
## 刪除命名空間和其中所有的pod
k delete ns custom-namespace
## 刪除當前命名空間中所有pod
k delete po --all
## 由於有ReplicationController,所以會自動創建新的pod
[root@master1 ~]## k get po
NAME READY STATUS RESTARTS AGE
kubia-m6k4d 1/1 Running 0 2m20s
kubia-rkm58 1/1 Running 0 2m15s
kubia-v4cmh 1/1 Running 0 2m15s
## 刪除工作空間中所有類型中的所有資源
## 這個操作會刪除一個系統Service kubernetes,它被刪除后會立即被自動重建
k delete all --all
存活探針
有三種存活探針:
-
HTTP GET
返回 2xx 或 3xx 響應碼則認為探測成功
-
TCP
與指定端口建立 TCP 連接,連接成功則為成功
-
Exec
在容器內執行任意的指定命令,並檢查命令的退出碼,退出碼為0則為探測成功
HTTP GET 存活探針
luksa/kubia-unhealthy 鏡像
在kubia-unhealthy鏡像中,應用程序作了這樣的設定: 從第6次請求開始會返回500錯
在部署文件中,我們添加探針,來探測容器的健康狀態.
探針默認每10秒探測一次,連續三次探測失敗后重啟容器
cat <<EOF > kubia-liveness-probe.yml
apiVersion: v1
kind: Pod
metadata:
name: kubia-liveness ## pod名稱
spec:
containers:
- image: luksa/kubia-unhealthy ## 鏡像
name: kubia ## 容器名
livenessProbe: ## 存活探針配置
httpGet: ## HTTP GET 類型的存活探針
path: / ## 探測路徑
port: 8080 ## 探測端口
EOF
創建 pod
k create -f kubia-liveness-probe.yml
## pod的RESTARTS屬性,每過1分半種就會加1
k get po kubia-liveness
--------------------------------------------------
NAME READY STATUS RESTARTS AGE
kubia-liveness 1/1 Running 0 5m25s
查看上一個pod的日志,前5次探測是正確狀態,后面3次探測是失敗的,則該pod會被刪除
k logs kubia-liveness --previous
-----------------------------------------
Kubia server starting...
Received request from ::ffff:172.20.3.1
Received request from ::ffff:172.20.3.1
Received request from ::ffff:172.20.3.1
Received request from ::ffff:172.20.3.1
Received request from ::ffff:172.20.3.1
Received request from ::ffff:172.20.3.1
Received request from ::ffff:172.20.3.1
Received request from ::ffff:172.20.3.1
1234567891011
查看pod描述
k describe po kubia-liveness
---------------------------------
......
Restart Count: 6
Liveness: http-get http://:8080/ delay=0s timeout=1s period=10s #success=1 #failure=3
......
delay
0表示容器啟動后立即開始探測timeout
1表示必須在1秒內響應,否則視為探測失敗period
10s表示每10秒探測一次failure
3表示連續3次失敗后重啟容器
通過設置 delay 延遲時間,可以避免在容器內應用沒有完全啟動的情況下就開始探測
cat <<EOF > kubia-liveness-probe-initial-delay.yml
apiVersion: v1
kind: Pod
metadata:
name: kubia-liveness
spec:
containers:
- image: luksa/kubia-unhealthy
name: kubia
livenessProbe:
httpGet:
path: /
port: 8080
initialDelaySeconds: 15 ## 第一次探測的延遲時間
EOF
控制器
ReplicationController
RC可以自動化維護多個pod,只需指定pod副本的數量,就可以輕松實現自動擴容縮容
當一個pod宕機,RC可以自動關閉pod,並啟動一個新的pod替代它
下面是一個RC的部署文件,設置啟動三個kubia容器:
cat <<EOF > kubia-rc.yml
apiVersion: v1
kind: ReplicationController ## 資源類型
metadata:
name: kubia ## 為RC命名
spec:
replicas: 3 ## pod副本的數量
selector: ## 選擇器,用來選擇RC管理的pod
app: kubia ## 選擇標簽'app=kubia'的pod,由當前RC進行管理
template: ## pod模板,用來創建新的pod
metadata:
labels:
app: kubia ## 指定pod的標簽
spec:
containers: ## 容器配置
- name: kubia ## 容器名
image: luksa/kubia ## 鏡像
ports:
- containerPort: 8080 ## 容器暴露的端口
EOF
創建RC
RC創建后,會根據指定的pod數量3,自動創建3個pod
k create -f kubia-rc.yml
k get rc
----------------------------------------
NAME DESIRED CURRENT READY AGE
kubia 3 3 2 2m11s
k get po -o wide
------------------------------------------------------------------------------------------------------------------------------
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
kubia-fmtkw 1/1 Running 0 9m2s 172.20.1.7 192.168.64.192 <none> <none>
kubia-lc5qv 1/1 Running 0 9m3s 172.20.1.8 192.168.64.192 <none> <none>
kubia-pjs9n 1/1 Running 0 9m2s 172.20.2.11 192.168.64.193 <none> <none>
RC是通過指定的標簽app=kubia
對匹配的pod進行管理的
允許在pod上添加任何其他標簽,而不會影響pod與RC的關聯關系
k label pod kubia-fmtkw type=special
k get po --show-labels
----------------------------------------------------------------------
NAME READY STATUS RESTARTS AGE LABELS
kubia-fmtkw 1/1 Running 0 6h31m app=kubia,type=special
kubia-lc5qv 1/1 Running 0 6h31m app=kubia
kubia-pjs9n 1/1 Running 0 6h31m app=kubia
但是,如果改變pod的app標簽的值,就會使這個pod脫離RC的管理,這樣RC會認為這里少了一個pod,那么它會立即創建一個新的pod,來滿足我們設置的3個pod的要求
k label pod kubia-fmtkw app=foo --overwrite
k get pods -L app
-------------------------------------------------------------------
NAME READY STATUS RESTARTS AGE APP
kubia-fmtkw 1/1 Running 0 6h36m foo
kubia-lc5qv 1/1 Running 0 6h36m kubia
kubia-lhj4q 0/1 Pending 0 6s kubia
kubia-pjs9n 1/1 Running 0 6h36m kubia
修改 pod 模板
pod模板修改后,只影響后續新建的pod,已創建的pod不會被修改
可以刪除舊的pod,用新的pod來替代
## 編輯 ReplicationController,添加一個新的標簽: foo=bar
k edit rc kubia
------------------------------------------------
......
spec:
replicas: 3
selector:
app: kubia
template:
metadata:
creationTimestamp: null
labels:
app: kubia
foo: bar ## 任意添加一標簽
spec:
......
## 之前pod的標簽沒有改變
k get pods --show-labels
----------------------------------------------------------------------
NAME READY STATUS RESTARTS AGE LABELS
kubia-lc5qv 1/1 Running 0 3d5h app=kubia
kubia-lhj4q 1/1 Running 0 2d22h app=kubia
kubia-pjs9n 1/1 Running 0 3d5h app=kubia
## 通過RC,把pod擴容到6個
## 可以使用前面用過的scale命令來擴容
## k scale rc kubia --replicas=6
## 或者,可以編輯修改RC的replicas屬性,修改成6
k edit rc kubia
---------------------
spec:
replicas: 6 ## 從3修改成6,擴容到6個pod
selector:
app: kubia
## 新增加的pod有新的標簽,而舊的pod沒有新標簽
k get pods --show-labels
----------------------------------------------------------------------
NAME READY STATUS RESTARTS AGE LABELS
kubia-8d9jj 0/1 Pending 0 2m23s app=kubia,foo=bar
kubia-lc5qv 1/1 Running 0 3d5h app=kubia
kubia-lhj4q 1/1 Running 0 2d22h app=kubia
kubia-pjs9n 1/1 Running 0 3d5h app=kubia
kubia-wb8sv 0/1 Pending 0 2m17s app=kubia,foo=bar
kubia-xp4jv 0/1 Pending 0 2m17s app=kubia,foo=bar
## 刪除 rc, 但不級聯刪除 pod, 使 pod 處於脫管狀態
k delete rc kubia --cascade=false
ReplicaSet
ReplicaSet 被設計用來替代 ReplicationController,它提供了更豐富的pod選擇功能
以后我們總應該使用 RS, 而不適用 RC, 但在舊系統中仍會使用 RC
cat <<EOF > kubia-replicaset.yml
apiVersion: apps/v1 ## RS 是 apps/v1中提供的資源類型
kind: ReplicaSet ## 資源類型
metadata:
name: kubia ## RS 命名為 kubia
spec:
replicas: 3 ## pod 副本數量
selector:
matchLabels: ## 使用 label 選擇器
app: kubia ## 選取標簽是 "app=kubia" 的pod
template:
metadata:
labels:
app: kubia ## 為創建的pod添加標簽 "app=kubia"
spec:
containers:
- name: kubia ## 容器名
image: luksa/kubia ## 鏡像
EOF
創建 ReplicaSet
k create -f kubia-replicaset.yml
## 之前脫離管理的pod被RS管理
## 設置的pod數量是3,多出的pod會被關閉
k get rs
----------------------------------------
NAME DESIRED CURRENT READY AGE
kubia 3 3 3 4s
## 多出的3個pod會被關閉
k get pods --show-labels
----------------------------------------------------------------------
NAME READY STATUS RESTARTS AGE LABELS
kubia-8d9jj 1/1 Pending 0 2m23s app=kubia,foo=bar
kubia-lc5qv 1/1 Terminating 0 3d5h app=kubia
kubia-lhj4q 1/1 Terminating 0 2d22h app=kubia
kubia-pjs9n 1/1 Running 0 3d5h app=kubia
kubia-wb8sv 1/1 Pending 0 2m17s app=kubia,foo=bar
kubia-xp4jv 1/1 Terminating 0 2m17s app=kubia,foo=bar
## 查看RS描述, 與RC幾乎相同
k describe rs kubia
使用更強大的標簽選擇器
cat <<EOF > kubia-replicaset.yml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: kubia
spec:
replicas: 4
selector:
matchExpressions: ## 表達式匹配選擇器
- key: app ## label 名是 app
operator: In ## in 運算符
values: ## label 值列表
- kubia
- foo
template:
metadata:
labels:
app: kubia
spec:
containers:
- name: kubia
image: luksa/kubia
EOF
## 先刪除現有 RS
k delete rs kubia --cascade=false
## 再創建 RS
k create -f kubia-replicaset.yml
## 查看rs
k get rs
## 查看pod
k get po --show-labels
可使用的運算符:
In
: label與其中一個值匹配NotIn
: label與任何一個值都不匹配Exists
: 包含指定label名稱(值任意)DoesNotExists
: 不包含指定的label
清理
k delete rs kubia
k get rs
k get po
DaemonSet
在每個節點上運行一個 pod,例如資源監控,kube-proxy等
DaemonSet不指定pod數量,它會在每個節點上部署一個pod
cat <<EOF > ssd-monitor-daemonset.yml
apiVersion: apps/v1
kind: DaemonSet ## 資源類型
metadata:
name: ssd-monitor ## DS資源命名
spec:
selector:
matchLabels: ## 標簽匹配器
app: ssd-monitor ## 匹配的標簽
template:
metadata:
labels:
app: ssd-monitor ## 創建pod時,添加標簽
spec:
containers: ## 容器配置
- name: main ## 容器命名
image: luksa/ssd-monitor ## 鏡像
EOF
創建 DS
DS 創建后,會在所有節點上創建pod,包括master
k create -f ssd-monitor-daemonset.yml
k get po -o wide
-------------------------------------------------------------------------------------------------------------------------
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
ssd-monitor-g7fjb 1/1 Running 0 57m 172.20.1.12 192.168.64.192 <none> <none>
ssd-monitor-qk6t5 1/1 Running 0 57m 172.20.2.14 192.168.64.193 <none> <none>
ssd-monitor-xxbq8 1/1 Running 0 57m 172.20.0.2 192.168.64.191 <none> <none>
可以在所有選定的節點上部署pod
通過節點的label來選擇節點
cat <<EOF > ssd-monitor-daemonset.yml
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: ssd-monitor
spec:
selector:
matchLabels:
app: ssd-monitor
template:
metadata:
labels:
app: ssd-monitor
spec:
nodeSelector: ## 節點選擇器
disk: ssd ## 選擇的節點上具有標簽: 'disk=ssd'
containers:
- name: main
image: luksa/ssd-monitor
EOF
## 先清理
k delete ds ssd-monitor
## 再重新創建
k create -f ssd-monitor-daemonset.yml
查看 DS 和 pod, 看到並沒有創建pod,這是因為不存在具有disk=ssd
標簽的節點
k get ds
k get po
為節點’192.168.64.192’設置標簽 disk=ssd
這樣 DS 會在該節點上立即創建 pod
k label node 192.168.64.192 disk=ssd
k get ds
---------------------------------------------------------------------------------------
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
ssd-monitor 1 1 0 1 0 disk=ssd 37m
k get po -o wide
----------------------------------------------------------------------------------------------------------------------------------
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
ssd-monitor-n6d45 1/1 Running 0 16s 172.20.1.13 192.168.64.192 <none> <none>
同樣,進一步測試,為節點’192.168.64.193’設置標簽 disk=ssd
k label node 192.168.64.193 disk=ssd
k get ds
k get po -o wide
刪除’192.168.64.193’節點上的disk
標簽,那么該節點中部署的pod會被立即銷毀
## 注意刪除格式: disk-
k label node 192.168.64.193 disk-
k get ds
k get po -o wide
清理
k delete ds ssd-monitor
Job
Job 用來運行單個任務,任務結束后pod不再重啟
cat <<EOF > exporter.yml
apiVersion: batch/v1 ## Job資源在batch/v1版本中提供
kind: Job ## 資源類型
metadata:
name: batch-job ## 資源命名
spec:
template:
metadata:
labels:
app: batch-job ## pod容器標簽
spec:
restartPolicy: OnFailure ## 任務失敗時重啟
containers:
- name: main ## 容器名
image: luksa/batch-job ## 鏡像
EOF
創建 job
鏡像 batch-job 中的進程,運行120秒后會自動退出
k create -f exporter.yml
k get job
-----------------------------------------
NAME COMPLETIONS DURATION AGE
batch-job 0/1 7s
k get po
-------------------------------------------------------------
NAME READY STATUS RESTARTS AGE
batch-job-q97zf 0/1 ContainerCreating 0 7s
等待兩分鍾后,pod中執行的任務退出,再查看job和pod
k get job
-----------------------------------------
NAME COMPLETIONS DURATION AGE
batch-job 1/1 2m5s 2m16s
k get po
-----------------------------------------------------
NAME READY STATUS RESTARTS AGE
batch-job-q97zf 0/1 Completed 0 2m20s
使用Job讓pod連續運行5次
先創建第一個pod,等第一個完成后后,再創建第二個pod,以此類推,共順序完成5個pod
cat <<EOF > multi-completion-batch-job.yml
apiVersion: batch/v1
kind: Job
metadata:
name: multi-completion-batch-job
spec:
completions: 5 ## 指定完整的數量
template:
metadata:
labels:
app: batch-job
spec:
restartPolicy: OnFailure
containers:
- name: main
image: luksa/batch-job
EOF
k create -f multi-completion-batch-job.yml
共完成5個pod,並每次可以同時啟動兩個pod
cat <<EOF > multi-completion-parallel-batch-job.yml
apiVersion: batch/v1
kind: Job
metadata:
name: multi-completion-parallel-batch-job
spec:
completions: 5 ## 共完成5個
parallelism: 2 ## 可以有兩個pod同時執行
template:
metadata:
labels:
app: batch-job
spec:
restartPolicy: OnFailure
containers:
- name: main
image: luksa/batch-job
EOF
k create -f multi-completion-parallel-batch-job.yml
Cronjob
定時和重復執行的任務
cron時間表格式:
"分鍾 小時 每月的第幾天 月 星期幾"
cat <<EOF > cronjob.yml
apiVersion: batch/v1beta1 ## api版本
kind: CronJob ## 資源類型
metadata:
name: batch-job-every-fifteen-minutes
spec:
## 0,15,30,45 - 分鍾
## 第一個* - 每個小時
## 第二個* - 每月的每一天
## 第三個* - 每月
## 第四個* - 每一周中的每一天
schedule: "0,15,30,45 * * * *"
jobTemplate:
spec:
template:
metadata:
labels:
app: periodic-batch-job
spec:
restartPolicy: OnFailure
containers:
- name: main
image: luksa/batch-job
EOF
創建cronjob
k create -f cronjob.yml
## 立即查看 cronjob,此時還沒有創建pod
k get cj
----------------------------------------------------------------------------------------------
NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE
batch-job-every-fifteen-minutes 0,15,30,45 * * * * False 1 27s 2m17s
## 到0,15,30,45分鍾時,會創建一個pod
k get po
--------------------------------------------------------------------------------------
NAME READY STATUS RESTARTS AGE
batch-job-every-fifteen-minutes-1567649700-vlmdw 1/1 Running 0 36s
Service
通過Service資源,為多個pod提供一個單一不變的接入地址
cat <<EOF > kubia-svc.yml
apiVersion: v1
kind: Service ## 資源類型
metadata:
name: kubia ## 資源命名
spec:
ports:
- port: 80 ## Service向外暴露的端口
targetPort: 8080 ## 容器的端口
selector:
app: kubia ## 通過標簽,選擇名為kubia的所有pod
EOF
k create -f kubia-svc.yml
k get svc
--------------------------------------------------------------------
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.68.0.1 <none> 443/TCP 2d11h
kubia ClusterIP 10.68.163.98 <none> 80/TCP 5s
如果沒有pod具有app:kubia標簽,可以創建前面的ReplicaSet資源,並讓RS自動創建pod
k create -f kubia-replicaset.yml
從內部網絡訪問Service
執行curl http://10.68.163.98
來訪問Service
執行多次會看到,Service會在多個pod中輪訓發送請求
curl http://10.68.163.98
## [root@localhost ~]## curl http://10.68.163.98
## You've hit kubia-xdj86
## [root@localhost ~]## curl http://10.68.163.98
## You've hit kubia-xmtq2
## [root@localhost ~]## curl http://10.68.163.98
## You've hit kubia-5zm2q
## [root@localhost ~]## curl http://10.68.163.98
## You've hit kubia-xdj86
## [root@localhost ~]## curl http://10.68.163.98
## You've hit kubia-xmtq2
回話親和性
來自同一個客戶端的請求,總是發給同一個pod
cat <<EOF > kubia-svc-clientip.yml
apiVersion: v1
kind: Service
metadata:
name: kubia-clientip
spec:
sessionAffinity: ClientIP ## 回話親和性使用ClientIP
ports:
- port: 80
targetPort: 8080
selector:
app: kubia
EOF
k create -f kubia-svc-clientip.yml
k get svc
------------------------------------------------------------------------
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.68.0.1 <none> 443/TCP 2d12h
kubia ClusterIP 10.68.163.98 <none> 80/TCP 38m
kubia-clientip ClusterIP 10.68.72.120 <none> 80/TCP 2m15s
## 進入kubia-5zm2q容器,向Service發送請求
## 執行多次會看到,每次請求的都是同一個pod
curl http://10.68.72.120
在pod中,可以通過一個環境變量來獲知Service的ip地址
該環境變量在舊的pod中是不存在的,我們需要先刪除舊的pod,用新的pod來替代
k delete po --all
k get po
-----------------------------------------------
NAME READY STATUS RESTARTS AGE
kubia-k66lz 1/1 Running 0 64s
kubia-vfcqv 1/1 Running 0 63s
kubia-z257h 1/1 Running 0 63s
k exec kubia-k66lz env
------------------------------------------------------------------
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=kubia-k66lz
KUBIA_SERVICE_PORT=80 ## kubia服務的端口
KUBIA_PORT=tcp://10.68.163.98:80
KUBIA_CLIENTIP_SERVICE_PORT=80 ## kubia-clientip服務的端口
KUBIA_CLIENTIP_PORT_80_TCP=tcp://10.68.72.120:80
KUBIA_CLIENTIP_PORT_80_TCP_PROTO=tcp
KUBERNETES_SERVICE_HOST=10.68.0.1
KUBERNETES_PORT_443_TCP=tcp://10.68.0.1:443
KUBIA_SERVICE_HOST=10.68.163.98 ## kubia服務的ip
KUBIA_CLIENTIP_SERVICE_HOST=10.68.72.120 ## kubia-clientip服務的ip
......
通過全限定域名
來訪問Service
## 進入一個容器
k exec -it kubia-k66lz bash
ping kubia
curl http://kubia
curl http://kubia.default
curl http://kubia.default.svc.cluster.local
endpoint
endpoint是在Service和pod之間的一種資源
一個endpoint資源,包含一組pod的地址列表
## 查看kubia服務的endpoint
k describe svc kubia
------------------------------
......
Endpoints: 172.20.2.40:8080,172.20.3.57:8080,172.20.3.58:8080
......
## 查看所有endpoint
k get ep
--------------------------------------------------------------------------
NAME ENDPOINTS AGE
kubia 172.20.2.40:8080,172.20.3.57:8080,172.20.3.58:8080 95m
kubia-clientip 172.20.2.40:8080,172.20.3.57:8080,172.20.3.58:8080 59m
## 查看名為kubia的endpoint
k get ep kubia
不含pod選擇器的服務,不會創建 endpoint
cat <<EOF > external-service.yml
apiVersion: v1
kind: Service
metadata:
name: external-service ## Service命名
spec:
ports:
- port: 80
EOF
## 創建沒有選擇器的 Service,不會創建Endpoint
k create -f external-service.yml
## 查看Service
k get svc
## 通過內部網絡ip訪問Service,沒有Endpoint地址列表,會拒絕連接
curl http://10.68.191.212
創建endpoint關聯到Service,它的名字必須與Service同名
cat <<EOF > external-service-endpoints.yml
apiVersion: v1
kind: Endpoints ## 資源類型
metadata:
name: external-service ## 名稱要與Service名相匹配
subsets:
- addresses: ## 包含的地址列表
- ip: 120.52.99.224 ## 中國聯通的ip地址
- ip: 117.136.190.162 ## 中國移動的ip地址
ports:
- port: 80 ## 目標服務的的端口
EOF
## 創建Endpoint
k create -f external-service-endpoints.yml
12
## 進入一個pod容器
k exec -it kubia-k66lz bash
## 訪問 external-service
## 多次訪問,會在endpoints地址列表中輪訓請求
curl http://external-service
通過完全限定域名
訪問外部服務
cat <<EOF > external-service-externalname.yml
apiVersion: v1
kind: Service
metadata:
name: external-service-externalname
spec:
type: ExternalName
externalName: www.chinaunicom.com.cn ## 域名
ports:
- port: 80
EOF
創建服務
k create -f external-service-externalname.yml
## 進入一個容器
k exec -it kubia-k66lz bash
## 訪問 external-service-externalname
curl http://external-service-externalname
服務暴露給客戶端
前面創建的Service只能在集群內部網絡中訪問,那么怎么讓客戶端來訪問Service呢?
三種方式
- NodePort
- 每個節點都開放一個端口
- LoadBalance
- NodePort的一種擴展,負載均衡器需要雲基礎設施來提供
- Ingress
NodePort
在每個節點(包括master),都開放一個相同的端口,可以通過任意節點的端口來訪問Service
cat <<EOF > kubia-svc-nodeport.yml
apiVersion: v1
kind: Service
metadata:
name: kubia-nodeport
spec:
type: NodePort ## 在每個節點上開放訪問端口
ports:
- port: 80 ## 集群內部訪問該服務的端口
targetPort: 8080 ## 容器的端口
nodePort: 30123 ## 外部訪問端口
selector:
app: kubia
EOF
創建並查看 Service
k create -f kubia-svc-nodeport.yml
k get svc kubia-nodeport
-----------------------------------------------------------------------------
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubia-nodeport NodePort 10.68.140.119 <none> 80:30123/TCP 14m
可以通過任意節點的30123
端口來訪問 Service
磁盤掛載到容器
卷
卷的類型:
- emptyDir: 簡單的空目錄
- hostPath: 工作節點中的磁盤路徑
- gitRepo: 從git克隆的本地倉庫
- nfs: nfs共享文件系統
創建包含兩個容器的pod, 它們共享同一個卷
cat <<EOF > fortune-pod.yml
apiVersion: v1
kind: Pod
metadata:
name: fortune
labels:
app: fortune
spec:
containers:
- image: luksa/fortune ## 鏡像名
name: html-genrator ## 容器名
volumeMounts:
- name: html ## 卷名為 html
mountPath: /var/htdocs ## 容器中的掛載路徑
- image: nginx:alpine ## 第二個鏡像名
name: web-server ## 第二個容器名
volumeMounts:
- name: html ## 相同的卷 html
mountPath: /usr/share/nginx/html ## 在第二個容器中的掛載路徑
readOnly: true ## 設置為只讀
ports:
- containerPort: 80
protocol: TCP
volumes: ## 卷
- name: html ## 為卷命名
emptyDir: {} ## emptyDir類型的卷
EOF
k create -f fortune-pod.yml
k get po
創建Service, 通過這個Service訪問pod的80端口
cat <<EOF > fortune-svc.yml
apiVersion: v1
kind: Service
metadata:
name: fortune
spec:
type: NodePort
ports:
- port: 8088
targetPort: 80
nodePort: 38088
selector:
app: fortune
EOF
1234567891011121314
k create -f fortune-svc.yml
k get svc
## 用瀏覽器訪問 http://192.168.64.191:38088/
NFS 文件系統
在 master 節點 192.168.64.191 上創建 nfs 目錄 /etc/nfs_data
,
並允許 1921.68.64 網段的主機共享訪問這個目錄
## 創建文件夾
mkdir /etc/nfs_data
## 在exports文件夾中寫入配置
## no_root_squash: 服務器端使用root權限
cat <<EOF > /etc/exports
/etc/nfs_data 192.168.64.0/24(rw,async,no_root_squash)
EOF
systemctl enable nfs
systemctl enable rpcbind
systemctl start nfs
systemctl start rpcbind
嘗試在客戶端主機上,例如192.168.64.192,掛載遠程的nfs目錄
## 新建掛載目錄
mkdir /etc/web_dir/
## 在客戶端, 掛載服務器的 nfs 目錄
mount -t nfs 192.168.64.191:/etc/nfs_data /etc/web_dir/
持久化存儲
創建 PersistentVolume - 持久卷資源
cat <<EOF > mongodb-pv.yml
apiVersion: v1
kind: PersistentVolume
metadata:
name: mongodb-pv
spec:
capacity:
storage: 1Gi ## 定義持久卷大小
accessModes:
- ReadWriteOnce ## 只允許被一個客戶端掛載為讀寫模式
- ReadOnlyMany ## 可以被多個客戶端掛載為只讀模式
persistentVolumeReclaimPolicy: Retain ## 當聲明被釋放,持久卷將被保留
nfs: ## nfs遠程目錄定義
path: /etc/nfs_data
server: 192.168.64.191
EOF
## 創建持久卷
k create -f mongodb-pv.yml
## 查看持久卷
k get pv
----------------------------------------------------------------------------------------------------------
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
mongodb-pv 1Gi RWO,ROX Retain Available 4s
持久卷聲明
使用持久卷聲明,使應用與底層存儲技術解耦
cat <<EOF > mongodb-pvc.yml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mongodb-pvc
spec:
resources:
requests:
storage: 1Gi ## 申請1GiB存儲空間
accessModes:
- ReadWriteOnce ## 允許單個客戶端讀寫
storageClassName: "" ## 參考動態配置章節
EOF
k create -f mongodb-pvc.yml
k get pvc
-----------------------------------------------------------------------------------
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
mongodb-pvc Bound mongodb-pv 1Gi RWO,ROX 3s
cat <<EOF > mongodb-pod-pvc.yml
apiVersion: v1
kind: Pod
metadata:
name: mongodb
spec:
containers:
- image: mongo
name: mongodb
securityContext:
runAsUser: 0
volumeMounts:
- name: mongodb-data
mountPath: /data/db
ports:
- containerPort: 27017
protocol: TCP
volumes:
- name: mongodb-data
persistentVolumeClaim:
claimName: mongodb-pvc ## 引用之前創建的"持久卷聲明"
EOF
驗證 pod 中加掛載了 nfs 遠程目錄作為持久卷
k create -f mongodb-pod-pvc.yml
k exec -it mongodb mongo
use mystore
db.foo.insert({name:'foo'})
db.foo.find()
查看在 nfs 遠程目錄中的文件
cd /etc/nfs_data
ls
配置啟動參數
docker 的命令行參數
Dockerfile中定義命令和參數的指令
ENTRYPOINT
啟動容器時,在容器內執行的命令CMD
對啟動命令傳遞的參數
CMD
可以在docker run
命令中進行覆蓋
例如:
......
ENTRYPOINT ["java", "-jar", "/opt/sp05-eureka-0.0.1-SNAPSHOT.jar"]
CMD ["--spring.profiles.active=eureka1"]
啟動容器時,可以執行:
docker run <image>
或者啟動容器時覆蓋CMD
docker run <image> --spring.profiles.active=eureka2
k8s中覆蓋docker的ENTRYPOINT
和CMD
command
可以覆蓋ENTRYPOINT
args
可以覆蓋CMD
在鏡像luksa/fortune:args
中,設置了自動生成內容的間隔時間參數為10秒
......
CMD ["10"]
可以通過k8s的args
來覆蓋docker的CMD
cat <<EOF > fortune-pod-args.yml
apiVersion: v1
kind: Pod
metadata:
name: fortune
labels:
app: fortune
spec:
containers:
- image: luksa/fortune:args
args: ["2"] ## docker鏡像中配置的CMD是10,這里用args把這個值覆蓋成2
name: html-genrator
volumeMounts:
- name: html
mountPath: /var/htdocs
- image: nginx:alpine
name: web-server
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html
readOnly: true
ports:
- containerPort: 80
protocol: TCP
volumes:
- name: html
emptyDir: {}
EOF
k create -f fortune-pod-args.yml
## 查看pod
k get po -o wide
--------------------------------------------------------------------------------------------------------------
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
fortune 2/2 Running 0 34s 172.20.2.55 192.168.64.192 <none> <none>
重復地執行curl命令,訪問該pod,會看到數據每2秒刷新一次
注意要修改成你的pod的ip
curl http://172.20.2.55
環境變量
在鏡像luksa/fortune:env
中通過環境變量INTERVAL
來指定內容生成的間隔時間
下面配置中,通過env
配置,在容器中設置了環境變量INTERVAL
的值
cat <<EOF > fortune-pod-env.yml
apiVersion: v1
kind: Pod
metadata:
name: fortune
labels:
app: fortune
spec:
containers:
- image: luksa/fortune:env
env: ## 設置環境變量 INTERVAL=5
- name: INTERVAL
value: "5"
name: html-genrator
volumeMounts:
- name: html
mountPath: /var/htdocs
- image: nginx:alpine
name: web-server
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html
readOnly: true
ports:
- containerPort: 80
protocol: TCP
volumes:
- name: html
emptyDir: {}
EOF
123456789101112131415161718192021222324252627282930313233
k delete po fortune
k create -f fortune-pod-env.yml
## 查看pod
k get po -o wide
--------------------------------------------------------------------------------------------------------------
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
fortune 2/2 Running 0 8s 172.20.2.56 192.168.64.192 <none> <none>
## 進入pod
k exec -it fortune bash
## 查看pod的環境變量
env
------------
INTERVAL=5
......
## 從pod推出,回到宿主機
exit
重復地執行curl命令,訪問該pod,會看到數據每5秒刷新一次
注意要修改成你的pod的ip
curl http://172.20.2.56
ConfigMap
通過ConfigMap資源,可以從pod中把環境變量配置分離出來,是環境變量配置與pod解耦
可以從命令行創建ConfigMap資源:
## 直接命令行創建
k create configmap fortune-config --from-literal=sleep-interval=20
或者從部署文件創建ConfigMap:
## 或從文件創建
cat <<EOF > fortune-config.yml
apiVersion: v1
kind: ConfigMap
metadata:
name: fortune-config
data:
sleep-interval: "10"
EOF
## 創建ConfigMap
k create -f fortune-config.yml
## 查看ConfigMap的配置
k get cm fortune-config -o yaml
從ConfigMap獲取配置數據,設置為pod的環境變量
cat <<EOF > fortune-pod-env-configmap.yml
apiVersion: v1
kind: Pod
metadata:
name: fortune
labels:
app: fortune
spec:
containers:
- image: luksa/fortune:env
env:
- name: INTERVAL ## 環境變量名
valueFrom:
configMapKeyRef: ## 環境變量的值從ConfigMap獲取
name: fortune-config ## 使用的ConfigMap名稱
key: sleep-interval ## 用指定的鍵從ConfigMap取數據
name: html-genrator
volumeMounts:
- name: html
mountPath: /var/htdocs
- image: nginx:alpine
name: web-server
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html
readOnly: true
ports:
- containerPort: 80
protocol: TCP
volumes:
- name: html
emptyDir: {}
EOF
config-map–>env–>arg
配置環境變量后,可以在啟動參數中使用環境變量
cat <<EOF > fortune-pod-args.yml
apiVersion: v1
kind: Pod
metadata:
name: fortune
labels:
app: fortune
spec:
containers:
- image: luksa/fortune:args
env:
- name: INTERVAL
valueFrom:
configMapKeyRef:
name: fortune-config
key: sleep-interval
args: ["\$(INTERVAL)"] ## 啟動參數中使用環境變量
name: html-genrator
volumeMounts:
- name: html
mountPath: /var/htdocs
- image: nginx:alpine
name: web-server
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html
readOnly: true
ports:
- containerPort: 80
protocol: TCP
volumes:
- name: html
emptyDir: {}
EOF
從磁盤文件創建 ConfigMap
先刪除之前創建的ComfigMap
d delete cm fortune-config
創建一個文件夾,存放配置文件
cd ~/
mkdir configmap-files
cd configmap
創建nginx的配置文件,啟用對文本文件和xml文件的壓縮
cat <<EOF > my-nginx-config.conf
server {
listen 80;
server_name www.kubia-example.com;
gzip on;
gzip_types text/plain application/xml;
location / {
root /ur/share/nginx/html;
index index.html index.htm;
}
}
EOF
添加sleep-interval
文件,寫入值25
cat <<EOF > sleep-interval
25
EOF
從configmap-files文件夾創建ConfigMap
cd ~/
k create configmap fortune-config \
--from-file=configmap-files
Deployment
Deployment 是一種更高級的資源,用於部署或升級應用.
創建Deployment時,ReplicaSet資源會隨之創建,實際Pod是由ReplicaSet創建和管理,而不是由Deployment直接管理
Deployment可以在應用滾動升級過程中, 引入另一個RepliaSet, 並協調兩個ReplicaSet.
cat <<EOF > kubia-deployment-v1.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: kubia
spec:
replicas: 3
selector:
matchLabels:
app: kubia
template:
metadata:
name: kubia
labels:
app: kubia
spec:
containers:
- image: luksa/kubia:v1
name: nodejs
EOF
1234567891011121314151617181920
k create -f kubia-deployment-v1.yml --record
k get deploy
-----------------------------------------------
NAME READY UP-TO-DATE AVAILABLE AGE
kubia 3/3 3 3 2m35s
k get rs
----------------------------------------------------
NAME DESIRED CURRENT READY AGE
kubia-66b4657d7b 3 3 3 3m4s
k get po
------------------------------------------------------------
NAME READY STATUS RESTARTS AGE
kubia-66b4657d7b-f9bn7 1/1 Running 0 3m12s
kubia-66b4657d7b-kzqwt 1/1 Running 0 3m12s
kubia-66b4657d7b-zm4xd 1/1 Running 0 3m12s
k rollout status deploy kubia
------------------------------------------
deployment "kubia" successfully rolled out
rs 和 pod 名稱中的數字,是 pod 模板的哈希值
升級 Deployment
只需要在 pod 模板中修改鏡像的 Tag, Deployment 就可以自動完成升級過程
Deployment的升級策略
- 滾動升級 Rolling Update - 漸進的刪除舊的pod, 同時創建新的pod, 這是默認的升級策略
- 重建 Recreate - 一次刪除所有舊的pod, 再重新創建新的pod
minReadySeconds
設置為10秒, 減慢滾動升級速度, 便於我們觀察升級的過程.
k patch deploy kubia -p '{"spec": {"minReadySeconds": 10}}'
觸發滾動升級
修改 Deployment 中 pod 模板使用的鏡像就可以觸發滾動升級
為了便於觀察, 在另一個終端中執行循環, 通過 service 來訪問pod
while true; do curl http://192.168.64.191:30123; sleep 0.5s; done
k set image deploy kubia nodejs=luksa/kubia:v2
通過不同的命令來了解升級的過程和原理
k rollout status deploy kubia
k get rs
k get po --show-labels
k describe rs kubia-66b4657d7b
回滾 Deployment
luksa/kubia:v3 鏡像中的應用模擬一個 bug, 從第5次請求開始, 會出現 500 錯誤
k set image deploy kubia nodejs=luksa/kubia:v3
手動回滾到上一個版本
k rollout undo deploy kubia
控制滾動升級速率
滾動升級時
- 先創建新版本pod
- 再銷毀舊版本pod
可以通過參數來控制, 每次新建的pod數量和銷毀的pod數量:
maxSurge
- 默認25%
允許超出的 pod 數量.
如果期望pod數量是4, 滾動升級期間, 最多只允許實際有5個 pod.maxUnavailable
- 默認 25%
允許有多少 pod 處於不可用狀態.
如果期望pod數量是4, 滾動升級期間, 最多只允許 1 個 pod 不可用, 也就是說任何時間都要保持至少有 3 個可用的pod.
查看參數
k get deploy -o yaml
--------------------------------
......
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
......
暫停滾動升級
將 image 升級到 v4 版本觸發更新, 並立即暫停更新.
這時會有一個新版本的 pod 啟動, 可以暫停更新過程, 讓少量用戶可以訪問到新版本, 並觀察其運行是否正常.
根據新版本的運行情況, 可以繼續完成更新, 或回滾到舊版本.
k set image deploy kubia nodejs=luksa/kubia:v4
## 暫停
k rollout pause deploy kubia
## 繼續
k rollout resume deploy kubia
自動阻止出錯版本升級
minReadySeconds
- 新創建的pod成功運行多久后才,繼續升級過程
- 在該時間段內, 如果容器的就緒探針返回失敗, 升級過程將被阻止
修改Deployment配置,添加就緒探針
cat <<EOF > kubia-deployment-v3-with-readinesscheck.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: kubia
spec:
replicas: 3
selector:
matchLabels:
app: kubia
minReadySeconds: 10
strategy:
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
type: RollingUpdate
template:
metadata:
name: kubia
labels:
app: kubia
spec:
containers:
- image: luksa/kubia:v3
name: nodejs
readinessProbe:
periodSeconds: 1
httpGet:
path: /
port: 8080
EOF
k apply -f kubia-deployment-v3-with-readinesscheck.yml
就緒探針探測間隔設置成了 1 秒, 第5次請求開始每次請求都返回500錯, 容器會處於未就緒狀態. minReadySeconds
被設置成了10秒, 只有pod就緒10秒后, 升級過程才會繼續.所以這是滾動升級過程會被阻塞, 不會繼續進行.
默認升級過程被阻塞10分鍾后, 升級過程會被視為失敗, Deployment描述中會顯示超時(ProgressDeadlineExceeded).
k describe deploy kubia
-----------------------------
......
Conditions:
Type Status Reason
---- ------ ------
Available True MinimumReplicasAvailable
Progressing False ProgressDeadlineExceeded
......
這是只能通過手動執行 rollout undo 命令進行回滾
k rollout undo deploy kubia
Dashboard 儀表盤
查看 Dashboard 部署信息
## 查看pod
k get pod -n kube-system | grep dashboard
-------------------------------------------------------------------------------
kubernetes-dashboard-5c7687cf8-s2f9z 1/1 Running 0 10d
## 查看service
k get svc -n kube-system | grep dashboard
------------------------------------------------------------------------------------------------------
kubernetes-dashboard NodePort 10.68.239.141 <none> 443:20176/TCP 10d
## 查看集群信息
k cluster-info | grep dashboard
-------------------------------------------------------------------------------------------------------------------------------------------------------------
kubernetes-dashboard is running at https://192.168.64.191:6443/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy
根據上面信息可以看到 dashboard 的訪問地址:
https://192.168.64.191:6443/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy
現在訪問 dashboard 由於安全設置的原因無法訪問
證書驗證訪問
使用集群CA 生成客戶端證書,該證書擁有所有權限
cd /etc/kubernetes/ssl
## 導出證書文件
openssl pkcs12 -export -in admin.pem -inkey admin-key.pem -out kube-admin.p12
1234
下載 /etc/kubernetes/ssl/kube-admin.p12
證書文件, 在瀏覽器中導入:
訪問 dashboard 會提示登錄, 這里我們用令牌的方式訪問 (https://192.168.64.191:6443/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy)
令牌
## 創建Service Account 和 ClusterRoleBinding
k apply -f /etc/ansible/manifests/dashboard/admin-user-sa-rbac.yaml
## 獲取 Bearer Token,復制輸出中 ‘token:’ 開頭那一行
k -n kube-system describe secret $(kubectl -n kube-system get secret | grep admin-user | awk '{print $1}')