kubernetes環境搭建


kubernetes環境搭建

安裝kubernetes集群

kubernetes的安裝過程極其復雜,對Linux運維不熟悉的情況下安裝kubernetes極為困難,再加上國內無法訪問google服務器,我們安裝k8s就更加困難

kubeasz項目(https://github.com/easzlab/kubeasz)極大的簡化了k8s集群的安裝過程,使我們可以離線一鍵安裝k8s集群

准備第一台虛擬機

設置虛擬機cpu

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

配置ip

如果內存有限, 可以只部署兩台服務器進行測試

  • 主服務器既作為控制節點, 又作為工作節點
  • 減少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
rc部署pod

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

Service

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_methodenv

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的ENTRYPOINTCMD

  • 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}')

在這里插入圖片描述


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM