2021了,還不會Kubernetes嗎系列文章(三)—— 發佈篇

1.灰度發佈

  • 灰度發佈是一種發佈方式,也叫金絲雀發佈
  • 起源是礦工在下井以前會先放一隻金絲雀到井裏,若是金絲雀不叫了,就表明瓦斯濃度高。緣由是金絲雀對瓦斯氣體很敏感
  • 灰度發佈的作法是:會在現存舊應用的基礎上,啓動一個新版應用
  • 可是新版應用並不會直接讓用戶訪問。而是先讓測試同窗去進行測試。若是沒有問題,則能夠將真正的用戶流量慢慢導入到新版
  • 在這中間,持續對新版本運行狀態作觀察,直到慢慢切換過去,這就是所謂的 A/B 測試。固然,你也能夠招募一些灰度用戶,給他們設置獨有的灰度標示(Cookie,Header),來讓他們能夠訪問到新版應用
  • 固然,若是中間切換出現問題,也應該將流量迅速地切換到老應用上 jinsique

1.1 準備新版本 Service

cp deployment-user-v1.yaml deployment-user-v2.yaml
apiVersion: apps/v1  #API 配置版本
kind: Deployment     #資源類型
metadata:
+  name: user-v2     #資源名稱
spec:
  selector:
    matchLabels:
+      app: user-v2 #告訴deployment根據規則匹配相應的Pod進行控制和管理,matchLabels字段匹配Pod的label值
  replicas: 3 #聲明一個 Pod,副本的數量
  template:
    metadata:
      labels:
+        app: user-v2 #Pod的名稱
    spec:   #組內建立的 Pod 信息
      containers:
      - name: nginx #容器的名稱
+        image: registry.cn-beijing.aliyuncs.com/zhangyaohuang/nginx:user-v2
        ports:
        - containerPort: 80 #容器內映射的端口
複製代碼

service-user-v2.yaml前端

apiVersion: v1
kind: Service
metadata:
+ name: service-user-v2
spec:
  selector:
+ app: user-v2
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
  type: NodePort
kubectl apply -f deployment-user-v2.yaml service-user-v2.yaml
複製代碼

1.2 根據 Cookie 切分流量

  • 基於 Cookie 切分流量。這種實現原理主要根據用戶請求中的 Cookie 是否存在灰度標示 Cookie 去判斷是否爲灰度用戶,再決定是否返回灰度版本服務node

  • nginx.ingress.kubernetes.io/canary:可選值爲 true / false 。表明是否開啓灰度功能mysql

  • nginx.ingress.kubernetes.io/canary-by-cookie
    複製代碼

    :灰度發佈 cookie 的 key。當 key 值等於 always 時,灰度觸發生效。等於其餘值時,則不會走灰度環境 ingress-gray.yamlnginx

    apiVersion: extensions/v1beta1
    kind: Ingress
    metadata:
    name: user-canary
    annotations:
      kubernetes.io/ingress.class: nginx
      nginx.ingress.kubernetes.io/rewrite-target: /
      nginx.ingress.kubernetes.io/canary: "true"
      nginx.ingress.kubernetes.io/canary-by-cookie: "vip_user"
    spec:
    rules:
    - http:
        paths:
         - backend:
            serviceName: service-user-v2
            servicePort: 80
    backend:
       serviceName: service-user-v2
       servicePort: 80
    複製代碼
  • 生效配置文件正則表達式

    kubectl apply -f ./ingress-gray.yaml
    複製代碼
  • 來獲取 ingress 的外部端口sql

  • -n: 根據資源名稱進行模糊查詢docker

    kubectl -n ingress-nginx get svc
    複製代碼
    curl http://172.31.178.169:31234/user
    curl http://118.190.156.138:31234/user
    curl --cookie "vip_user=always"  http://172.31.178.169:31234/user
    複製代碼

    1.3 基於 Header 切分流量

  • 基於 Header 切分流量,這種實現原理主要根據用戶請求中的 header 是否存在灰度標示 header 去判斷是否爲灰度用戶,再決定是否返回灰度版本服務shell

vi ingress-gray.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: user-canary
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/rewrite-target: /
    nginx.ingress.kubernetes.io/canary: "true"
+    nginx.ingress.kubernetes.io/canary-by-header: "name"
+    nginx.ingress.kubernetes.io/canary-by-header-value: "vip"
spec:
  rules:
  - http:
      paths:
       - backend:
          serviceName: service-user-v2
          servicePort: 80
  backend:
     serviceName: service-user-v2
     servicePort: 80
kubectl apply -f ingress-gray.yaml
curl --header "name:vip"  http://172.31.178.169:31234/user
複製代碼

1.4 基於權重切分流量

  • 這種實現原理主要是根據用戶請求,經過根據灰度百分比決定是否轉發到灰度服務環境中
  • nginx.ingress.kubernetes.io/canary-weight:值是字符串,爲 0-100 的數字,表明灰度環境命中機率。若是值爲 0,則表示不會走灰度。值越大命中機率越大。當值 = 100 時,表明全走灰度
vi ingress-gray.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: user-canary
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/rewrite-target: /
    nginx.ingress.kubernetes.io/canary: "true"
+   nginx.ingress.kubernetes.io/canary-weight: "50"
spec:
  rules:
  - http:
      paths:
       - backend:
          serviceName: service-user-v2
          servicePort: 80
  backend:
     serviceName: service-user-v2
     servicePort: 80
kubectl apply -f ingress-gray.yaml
for ((i=1; i<=10; i++)); do curl http://172.31.178.169:31234/user; done
複製代碼

1.5 優先級

  • canary-by-header -> canary-by-cookie -> canary-weight
  • k8s 會優先去匹配 header ,若是未匹配則去匹配 cookie ,最後是 weight

2.滾動發佈

  • 滾動發佈,則是咱們通常所說的無宕機發布。其發佈方式如同名稱同樣,一次取出一臺/多臺服務器(看策略配置)進行新版本更新。當取出的服務器新版確保無問題後,接着採用同等方式更新後面的服務器
  • k8s 建立副本應用程序的最佳方法就是部署(Deployment),部署自動建立副本集(ReplicaSet),副本集能夠精確地控制每次替換的 Pod 數量,從而能夠很好的實現滾動更新
  • k8s 每次使用一個新的副本控制器(replication controller)來替換已存在的副本控制器,從而始終使用一個新的 Pod 模板來替換舊的 pod 模板
    • 建立一個新的 replication controller
    • 增長或減小 pod 副本數量,直到知足當前批次指望的數量
    • 刪除舊的 replication controller

2.1 發佈流程和策略

  • 優勢
    • 不須要停機更新,無感知平滑更新。
    • 版本更新成本小,不須要新舊版本共存
  • 缺點
    • 更新時間長:每次只更新一個/多個鏡像,須要頻繁連續等待服務啓動緩衝
    • 舊版本環境沒法獲得備份:始終只有一個環境存在
    • 回滾版本異常痛苦:若是滾動發佈到一半出了問題,回滾時須要使用一樣的滾動策略回滾舊版本

img img img img img

2.2 配置文件

  • 先擴容爲 10 個副本數據庫

    kubectl get deploy
    kubectl scale deployment user-v1  --replicas=10
    複製代碼

deployment-user-v1.yamljson

apiVersion: apps/v1  #API 配置版本
kind: Deployment     #資源類型
metadata:
  name: user-v1     #資源名稱
spec:
  minReadySeconds: 1
+ strategy:
+ type: RollingUpdate
+ rollingUpdate:
+ maxSurge: 1
+ maxUnavailable: 0
+ selector:
+ matchLabels:
+ app: user-v1 #告訴deployment根據規則匹配相應的Pod進行控制和管理,matchLabels字段匹配Pod的label值
  replicas: 10 #聲明一個 Pod,副本的數量
  template:
    metadata:
      labels:
        app: user-v1 #Pod的名稱
    spec:   #組內建立的 Pod 信息
      containers:
      - name: nginx #容器的名稱
+ image: registry.cn-beijing.aliyuncs.com/zhangyaohuang/nginx:user-v3 #使用哪一個鏡像
        ports:
        - containerPort: 80 #容器內映射的端口
複製代碼
參數 含義
minReadySeconds 容器接受流量延緩時間:單位爲秒,默認爲 0。若是沒有設置的話,k8s 會認爲容器啓動成功後就能夠用了。設置該值能夠延緩容器流量切分
strategy.type = RollingUpdate ReplicaSet 發佈類型,聲明爲滾動發佈,默認也爲滾動發佈
strategy.rollingUpdate.maxSurge 最多 Pod 數量:爲數字類型/百分比。若是 maxSurge 設置爲 1,replicas 設置爲 10,則在發佈過程當中 pod 數量最多爲 10 + 1 個(多出來的爲舊版本 pod,平滑期不可用狀態)。maxUnavailable 爲 0 時,該值也不能設置爲 0
strategy.rollingUpdate.maxUnavailable 升級中最多不可用 pod 的數量:爲數字類型/百分比。當 maxSurge 爲 0 時,該值也不能設置爲 0
kubectl apply -f ./deployment-user-v1.yaml
deployment.apps/user-v1 configured
kubectl rollout status deployment/user-v1
Waiting for deployment "user-v1" rollout to finish: 3 of 10 updated replicas are available...
Waiting for deployment "user-v1" rollout to finish: 3 of 10 updated replicas are available...
Waiting for deployment "user-v1" rollout to finish: 4 of 10 updated replicas are available...
Waiting for deployment "user-v1" rollout to finish: 4 of 10 updated replicas are available...
Waiting for deployment "user-v1" rollout to finish: 4 of 10 updated replicas are available...
Waiting for deployment "user-v1" rollout to finish: 4 of 10 updated replicas are available...
Waiting for deployment "user-v1" rollout to finish: 4 of 10 updated replicas are available...
Waiting for deployment "user-v1" rollout to finish: 4 of 10 updated replicas are available...
deployment "user-v1" successfully rolled out
複製代碼

3.服務可用性探針

3.1 什麼是健康度檢查?

  • 當 Pod 的狀態爲 Running 時,該 Pod 就能夠被分配流量(能夠訪問到)了
  • 一個後端容器啓動成功,不必定不表明服務啓動成功

3.2 什麼是服務探針?

  • define-a-TCP-liveness-probe

  • 3.2.1 存活探針 LivenessProbe

  • 第一種是存活探針。存活探針是對運行中的容器檢測的。若是想檢測你的服務在運行中有沒有發生崩潰,服務有沒有中途退出或無響應,可使用這個探針

  • 若是探針探測到錯誤, Kubernetes 就會殺掉這個 Pod;不然就不會進行處理。若是默認沒有配置這個探針, Pod 不會被殺死

3.2.2 可用探針 ReadinessProbe

  • 第二種是可用探針。做用是用來檢測 Pod 是否容許被訪問到(是否準備好接受流量)。若是你的服務加載不少數據,或者有其餘需求要求在特定狀況下不被分配到流量,那麼能夠用這個探針
  • 若是探針檢測失敗,流量就不會分配給該 Pod。在沒有配置該探針的狀況下,會一直將流量分配給 Pod。固然,探針檢測失敗,Pod 不會被殺死

3.2.3 啓動探針 StartupProbe

  • 第三種是啓動探針。做用是用來檢測 Pod 是否已經啓動成功。若是你的服務啓動須要一些加載時長(例如初始化日誌,等待其餘調用的服務啓動成功)才表明服務啓動成功,則能夠用這個探針。
  • 若是探針檢測失敗,該 Pod 就會被殺死重啓。在沒有配置該探針的狀況下,默認不會殺死 Pod 。在啓動探針運行時,其餘全部的探針檢測都會失效
探針名稱 在哪一個環節觸發 做用 檢測失敗對 Pod 的反應
啓動探針 Pod 運行時 檢測服務是否啓動成功 殺死 Pod 並重啓
存活探針 Pod 運行時 檢測服務是否崩潰,是否須要重啓服務 殺死 Pod 並重啓
可用探針 Pod 運行時 檢測服務是否是容許被訪問到 中止 Pod 的訪問調度,不會被殺死重啓

3.3 探測方式

3.3.1 ExecAction

  • 經過在 Pod 的容器內執行預約的 Shell 腳本命令。若是執行的命令沒有報錯退出(返回值爲 0),表明容器狀態健康。不然就是有問題的

vi shell-probe.yaml

apiVersion: v1
kind: Pod
metadata:
  labels:
    test: shell-probe
  name: shell-probe
spec:
  containers:
  - name: shell-probe
    image: registry.aliyuncs.com/google_containers/busybox
    args:
    - /bin/sh
    - -c
    - touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600
    livenessProbe:
      exec:
        command:
        - cat
        - /tmp/healthy
      initialDelaySeconds: 5
      periodSeconds: 5
kubectl apply -f liveness.yaml
kubectl get pods | grep liveness-exec
kubectl describe pods liveness-exec

Events:
  Type     Reason     Age                  From               Message
  ----     ------     ----                 ----               -------
  Normal   Scheduled  2m44s                default-scheduler  Successfully assigned default/liveness-exec to node1
  Normal   Pulled     2m41s                kubelet            Successfully pulled image "registry.aliyuncs.com/google_containers/busybox" in 1.669600584s
  Normal   Pulled     86s                  kubelet            Successfully pulled image "registry.aliyuncs.com/google_containers/busybox" in 605.008964ms
  Warning  Unhealthy  41s (x6 over 2m6s)   kubelet Liveness probe failed: cat: can't open '/tmp/healthy': No such file or directory
  Normal   Killing    41s (x2 over 116s)   kubelet            Container liveness failed liveness probe, will be restarted
  Normal   Created    11s (x3 over 2m41s)  kubelet            Created container liveness
  Normal   Started    11s (x3 over 2m41s)  kubelet            Started container liveness
  Normal   Pulling    11s (x3 over 2m43s)  kubelet            Pulling image "registry.aliyuncs.com/google_containers/busybox"
  Normal   Pulled     11s                  kubelet            Successfully pulled image "registry.aliyuncs.com/google_containers/busybox" in 521.70892ms
複製代碼

3.3.2 TCPSocketAction

  • 這種方式是使用 TCP 套接字檢測。 Kubernetes 會嘗試在 Pod 內與指定的端口進行鏈接。若是能創建鏈接(Pod 的端口打開了),這個容器就表明是健康的,若是不能,則表明這個 Pod 就是有問題的

tcp-probe.yaml

apiVersion: v1
kind: Pod
metadata:
  name: tcp-probe
  labels:
    app: tcp-probe
spec:
  containers:
  - name: tcp-probe
    image: nginx
    ports:
    - containerPort: 80
    readinessProbe:
      tcpSocket:
        port: 80
      initialDelaySeconds: 5
      periodSeconds: 10
kubectl apply -f tcp-probe.yaml
kubectl get pods | grep tcp-probe
kubectl describe pods tcp-probe
kubectl exec -it tcp-probe  -- /bin/sh
apt-get update
apt-get install vim -y
vi  /etc/nginx/conf.d/default.conf
80=>8080
nginx -s reload
kubectl describe pod tcp-probe
Warning Unhealthy 6s kubelet Readiness probe failed: dial tcp 10.244.1.47:80: connect: connection
複製代碼

3.3.3 HTTPGetAction

  • 這種方式是使用 HTTP GET 請求。Kubernetes 會嘗試訪問 Pod 內指定的 API 路徑。若是返回 200,表明容器就是健康的。若是不能,表明這個 Pod 是有問題的

vi http-probe.yaml

apiVersion: v1
kind: Pod
metadata:
  labels:
    test: http-probe
  name: http-probe
spec:
  containers:
  - name: http-probe
    image: registry.cn-beijing.aliyuncs.com/zhangyaohuang/http-probe:1.0.0
    livenessProbe:
      httpGet:
        path: /liveness
        port: 80
        httpHeaders:
        - name: source
          value: probe
      initialDelaySeconds: 3
      periodSeconds: 3
vim ./http-probe.yaml
kubectl apply -f ./http-probe.yaml
kubectl describe pods http-probe
Normal   Killing    5s                kubelet            Container http-probe failed liveness probe, will be restarted
docker pull registry.cn-beijing.aliyuncs.com/zhangyaohuang/http-probe:1.0.0
kubectl replace --force -f http-probe.yaml
複製代碼

Dockerfile

FROM node
COPY ./app /app
WORKDIR /app
EXPOSE 3000
CMD node index.js
let http = require('http');
let start = Date.now();
http.createServer(function(req,res){
if(req.url === '/liveness'){
let value = req.headers['source'];
if(value === 'probe'){
let duration = Date.now()-start;
if(duration>10*1000){
res.statusCode=500;
res.end('error');
}else{
res.statusCode=200;
res.end('success');
}
}else{
res.statusCode=200;
res.end('liveness');
}
}else{
res.statusCode=200;
res.end('liveness');
}
}).listen(3000,function(){console.log("http server started on 3000")}); 複製代碼

4.儲存機密信息

4.1 什麼是 Secret

  • Secret 是 Kubernetes 內的一種資源類型,能夠用它來存放一些機密信息(密碼,token,密鑰等)
  • 信息被存入後,咱們可使用掛載卷的方式掛載進咱們的 Pod 內。固然也能夠存放 docker 私有鏡像庫的登陸名和密碼,用於拉取私有鏡像。

4.2 Opaque 類型

  • 通常拿來存放密碼,密鑰等信息,存儲格式爲 base64

4.2.1 命令行建立

  • account 爲 自定義的名稱
  • --from-literal 的後面則跟隨一組 key=value
kubectl create secret generic mysql-account --from-literal=username=james --from-literal=password=123456
kubectl get secret
複製代碼
字段 含義
NAME Secret 的名稱
TYPE Secret 的類型
DATA 存儲內容的數量
AGE 建立到如今的時間
//編輯值
kubectl edit secret account
//輸出yaml格式
kubectl get secret account -o yaml
//輸出json格式
kubectl get secret account -o json
//對Base64進行解碼
echo MTIzNDU2 | base64 -d
複製代碼

4.2.2 配置文件建立

mysql-account.yaml

apiVersion: v1
kind: Secret
metadata:
  name: mysql-account
stringData:
  username: root
  password: root
type: Opaque
kubectl apply -f mysql-account.yaml
secret/mysql-account created
kubectl get secret mysql-account -o yaml
複製代碼

4.3 私有鏡像庫認證

  • 第二種是私有鏡像庫認證類型,這種類型也比較經常使用,通常在拉取私有庫的鏡像時使用

4.3.1 命令行建立

kubectl create secret docker-registry private-registry \
--docker-username=[用戶名] \
--docker-password=[密碼] \
--docker-email=[郵箱] \
--docker-server=[私有鏡像庫地址]
//查看私有庫密鑰組
kubectl get secret private-registry -o yaml
echo [value] | base64 -d
複製代碼

4.3.2 經過文件建立

vi private-registry-file.yaml

apiVersion: v1
kind: Secret
metadata:
  name: private-registry-file
data:
  .dockerconfigjson: eyJhdXRocyI6eyJodHRwczo
type: kubernetes.io/dockerconfigjson
kubectl apply -f ./private-registry-file.yaml
kubectl get secret private-registry-file -o yaml
複製代碼

4.4 使用

4.4.1 Volume 掛載

  • 經過存儲卷的方式掛載進去
apiVersion: apps/v1  #API 配置版本
kind: Deployment     #資源類型
metadata:
  name: user-v1     #資源名稱
spec:
  minReadySeconds: 1
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
  selector:
    matchLabels:
      app: user-v1 #告訴deployment根據規則匹配相應的Pod進行控制和管理,matchLabels字段匹配Pod的label值
+ replicas: 1 #聲明一個 Pod,副本的數量
  template:
    metadata:
      labels:
        app: user-v1 #Pod的名稱
    spec:   #組內建立的 Pod 信息
+ volumes:
+ - name: mysql-account
+ secret:
+ secretName: mysql-account
      containers:
      - name: nginx #容器的名稱
        image: registry.cn-beijing.aliyuncs.com/zhangyaohuang/nginx:user-v3 #使用哪一個鏡像
+ volumeMounts:
+ - name: mysql-account
+ mountPath: /mysql-account
+ readOnly: true
        ports:
        - containerPort: 80 #容器內映射的端口
kubectl describe pods  user-v1-b88799944-tjgrs
kubectl exec -it user-v1-b88799944-tjgrs  -- ls /root
複製代碼

4.4.2 環境變量注入

  • 第二種是將 Secret 注入進容器的環境變量

deployment-user-v1.yaml

apiVersion: apps/v1  #API 配置版本
kind: Deployment     #資源類型
metadata:
  name: user-v1     #資源名稱
spec:
  minReadySeconds: 1
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
  selector:
    matchLabels:
      app: user-v1 #告訴deployment根據規則匹配相應的Pod進行控制和管理,matchLabels字段匹配Pod的label值
  replicas: 1 #聲明一個 Pod,副本的數量
  template:
    metadata:
      labels:
        app: user-v1 #Pod的名稱
    spec:   #組內建立的 Pod 信息
      volumes:
        - name: mysql-account
          secret:
            secretName: mysql-account
      containers:
      - name: nginx #容器的名稱
+ env:
+ - name: USERNAME
+ valueFrom:
+ secretKeyRef:
+ name: mysql-account
+ key: username
+ - name: PASSWORD
+ valueFrom:
+ secretKeyRef:
+ name: mysql-account
+ key: password
        image: registry.cn-beijing.aliyuncs.com/zhangyaohuang/nginx:user-v3 #使用哪一個鏡像
        volumeMounts:
        - name: mysql-account
          mountPath: /mysql-account
          readOnly: true
        ports:
        - containerPort: 80 #容器內映射的端口
kubectl apply -f deployment-user-v1.yaml
kubectl get pods
kubectl describe pod  user-v1-5f48f78d86-hjkcl
kubectl exec -it user-v1-688486759f-9snpx -- env | grep USERNAME
複製代碼

4.4.3 Docker 私有庫認證

  • 第三種是 Docker 私有庫類型,這種方法只能用來配置 私有鏡像庫認證。

vi v4.yaml

image: [僅有鏡像庫地址]/[鏡像名稱]:[鏡像標籤]
kubectl apply -f v4.yaml
kubectl get pods
kubectl describe pods [POD_NAME]
複製代碼

vi v4.yaml

+imagePullSecrets:
+ - name: private-registry-file
containers:
  - name: nginx
kubectl apply -f v4.yaml
複製代碼

5.服務發現

  • 當 A 服務依賴另外一個 B 服務,而咱們經常不知道 B 服務 的端口和 IP,且端口和 IP 也相對不固定有可能常常更改
  • 這時候,咱們就須要服務發現

5.1 服務發現

  • 服務發現是指使用一個註冊中心來記錄分佈式系統中的所有服務的信息,以便其餘服務可以快速的找到這些已註冊的服務

5.2 CoreDNS

  • Pod 的 IP 經常是漂移且不固定的,因此咱們要使用 Service 這個神器來將它的訪問入口固定住
  • 能夠利用 DNS 的機制給每一個 Service 加一個內部的域名,指向其真實的 IP
  • 在 Kubernetes 中,對 Service 的服務發現,是經過一種叫作 CoreDNS 的組件去實現的
  • coreDNS 是使用 Go 語言實現的一個 DNS 服務器
    • -n 按命名空間過濾
    • -l 按標籤過濾
    • -o wide 輸出額外信息。對於 Pod,將輸出 Pod 所在的 Node 名
kubectl -n kube-system get all  -l k8s-app=kube-dns -o wide
複製代碼

5.3 服務發現規則

  • kubectl exec 的做用是能夠直接在容器內執行 Shell 腳本
    • 命令格式:kubectl exec -it [PodName] -- [Command]
    • -i:即便沒有鏈接,也要保持標準輸入保持打開狀態。通常與 -t 連用。
    • -t:分配一個僞 TTY(終端設備終端窗口),通常與 -i 連用。能夠分配給咱們一個 Shell 終端
kubectl get pods
kubectl get svc
kubectl exec -it user-v1-688486759f-9snpx -- /bin/sh
curl http://service-user-v2
複製代碼
  • namespace(命名空間)
    • kubernetes namespace(命名空間)是 kubernetes 裏比較重要的一個概念
    • 在啓動集羣后,kubernetes 會分配一個默認命名空間,叫 default。不一樣的命名空間能夠實現資源隔離,服務隔離,甚至權限隔離
    • 由於咱們在以前建立的服務,都沒有指定 namespace ,因此咱們的服務都是在同一個 namespace default 下
    • 在同 namespace 下的規則,咱們只須要直接訪問 http://ServiceName:Port 就能夠訪問到相應的 Service
    • 不一樣 namespace 下的規則是 [ServiceName].[NameSpace].svc.cluster.local
  • ServiceName 就是咱們建立的 Service 名稱
  • NameSpace 則是命名空間。若是你沒有命名空間,則這個值爲 default。
curl http://service-user-v2.default.svc.cluster.local
複製代碼

6.統一管理服務環境變量

  • Kubernetes Secret 的主要做用是來存放密碼,密鑰等機密信息
  • 對於環境變量的配置:例如你的數據庫地址,負載均衡要轉發的服務地址等信息。這部份內容使用 Secret 顯然不合適,打包在鏡像內耦合又太嚴重。這裏,咱們能夠藉助 Kubernetes ConfigMap 來配置這項事情

6.1 什麼是 ConfigMap

  • ConfigMap 是 Kubernetes 的一種資源類型,咱們可使用它存放一些環境變量和配置文件
  • 信息存入後,咱們可使用掛載卷的方式掛載進咱們的 Pod 內,也能夠經過環境變量注入
  • 和 Secret 類型最大的不一樣是,存在 ConfigMap 內的內容不會加密

6.2 建立

6.2.1 命令行建立

kubectl create configmap [config_name] --from-literal=[key]=[value]
kubectl create configmap mysql-config --from-literal=MYSQL_HOST=192.168.1.172 --from-literal=MYSQL_PORT=3306
複製代碼
  • 須要注意,configmap 的名稱必須是全小寫,特殊符號只能包含 '-' 和 '.'。能夠用下面的這個正則表達式校驗下看看符不符合規則:[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*')
kubectl get cm
kubectl describe cm mysql-config
複製代碼

6.2.2 配置清單建立

  • kind 的值爲 ConfigMap,表明聲明一個 ConfigMap 類型的資源
  • metadata.name 表明是該 configmap 的名稱
  • data 是存放數據的地方,數據格式爲 key:value

mysql-config-file.yaml

apiVersion: v1
kind: ConfigMap
metadata:
  name: mysql-config-file
data:
  MYSQL_HOST: "192.168.1.172"
  MYSQL_PORT: "3306"
kubectl apply -f ./mysql-config-file.yaml
kubectl describe cm mysql-config-file
複製代碼

6.2.3 文件建立

  • --from-file表明一個文件
  • key是文件在 configmap 內的 key
  • file_path 是文件的路徑
kubectl create configmap [configname] --from-file=[key]=[file_path]
複製代碼

env.config

HOST: 192.168.0.1
PORT: 8080
kubectl create configmap env-from-file --from-file=env=./env.config
configmap/env-from-file created
kubectl get cm env-from-file -o yaml
複製代碼

6.2.4 目錄建立

  • 也能夠直接將一個目錄下的文件整個存入進去
kubectl create configmap [configname] --from-file=[dir_path]
mkdir env && cd ./env
echo 'local' > env.local
echo 'test' > env.test
echo 'prod' > env.prod
kubectl create configmap env-from-dir --from-file=./
kubectl get cm env-from-dir -o yaml
複製代碼

6.3 使用方式

6.3.1 環境變量注入

  • name 爲要選擇注入的 configmap 名稱
  • key 則爲 configmap 內的其中一個 key
containers:
  - name: nginx #容器的名稱
+ env:
+ - name: MYSQL_HOST
+ valueFrom:
+ configMapKeyRef:
+ name: mysql-config
+ key: MYSQL_HOST
kubectl apply -f ./v1.yaml
//kubectl exec -it [POD_NAME] -- env | grep MYSQL_HOST
kubectl exec  -it user-v1-744f48d6bd-9klqr -- env | grep MYSQL_HOST
kubectl exec  -it user-v1-744f48d6bd-9klqr  -- env | grep MYSQL_PORT
      containers:
      - name: nginx #容器的名稱
        env:
+ envFrom:
+ - configMapRef:
+ name: mysql-config
+ optional: true
        image: registry.cn-beijing.aliyuncs.com/zhangyaohuang/nginx:user-v3 #使用哪一個鏡像
        volumeMounts:
        - name: mysql-account
          mountPath: /mysql-account
          readOnly: true
        ports:
        - containerPort: 80 #容器內映射的端口
複製代碼

6.3.2 存儲卷掛載

  • 存儲卷掛載會將 configmap 裏內容中的每一個 key 和 value,以獨立文件方式之外部掛載卷方式掛載進去( key 是文件名,value 是文件內容)
  • 在 Pod 層面聲明一個外部存儲卷
    • name 爲存儲卷名稱
    • configMap 表明存儲卷的文件來源
    • configMap.name 要填入要加載的 configMap 名稱
  • 在容器鏡像層面配置存儲卷
    • name 的值來源於第一步配置的 name 值
    • mountPath 爲要掛載的目錄
    • readonly 則表明文件是否是隻讀
template:
    metadata:
      labels:
        app: user-v1 #Pod的名稱
    spec:   #組內建立的 Pod 信息
      volumes:
        - name: mysql-account
          secret:
            secretName: mysql-account
+ - name: envfiles
+ configMap:
+ name: env-from-dir
      containers:
      - name: nginx #容器的名稱
        env:
        - name: USERNAME
          valueFrom:
            secretKeyRef:
              name: mysql-account
              key: username
        - name: PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysql-account
              key: password
        envFrom:
        - configMapRef:
            name: mysql-config
            optional: true
        image: registry.cn-beijing.aliyuncs.com/zhangyaohuang/nginx:user-v3 #使用哪一個鏡像
        volumeMounts:
        - name: mysql-account
          mountPath: /mysql-account
          readOnly: true
+ - name: envfiles
+ mountPath: /envfiles
+ readOnly: true
        ports:
        - containerPort: 80 #容器內映射的端口
kubectl apply -f deployment-user-v1.yaml
kubectl get pods
kubectl describe pod user-v1-79b8768f54-r56kd
kubectl exec -it user-v1-744f48d6bd-9klqr -- ls /envfiles
複製代碼
  • 能夠藉助 volumes.configMap.items[] 字段來配置多個 item 項
spec:   #組內建立的 Pod 信息
      volumes:
        - name: mysql-account
          secret:
            secretName: mysql-account
        - name: envfiles
          configMap:
            name: env-from-dir
+ items:
+ - key: env.local
+ path: env.local
複製代碼

7.污點與容忍

  • 如何幹預 Pod 部署到特定的節點上能夠經過污點與容忍度去實現

7.1 麼是污點和容忍度?

  • 在 Kubernetes 中, Pod 被部署到 Node 上面去的規則和邏輯是由 Kubernetes 的調度組件根據 Node 的剩餘資源,地位,以及其餘規則自動選擇調度的

  • 但前端和後端每每服務器資源的分配都是不均衡的,甚至有的服務只能讓特定的服務器來跑

  • 在這種狀況下,咱們選擇自動調度是不均衡的,就須要人工去幹預匹配選擇規則了

  • 這時候,就須要在給 Node 添加一個叫作污點的東西,以確保 Node 不被 Pod 調度到

  • 當你給 Node 設置一個污點後,除非給 Pod 設置一個相對應的容忍度,不然 Pod 才能被調度上去。這也就是污點和容忍的來源

  • 污點的格式是 key=value,能夠自定義本身的內容,就像是一組 Tag 同樣

  • Node_Name 爲要添加污點的 node 名稱

  • key 和 value 爲一組鍵值對,表明一組標示標籤

  • NoSchedule 則爲不被調度的意思,和它同級別的還有其餘的值:PreferNoSchedule 和 NoExecute

kubectl taint nodes [Node_Name] [key]=[value]:NoSchedule
//添加污點
kubectl taint nodes node1 user-v4=true:NoSchedule
//查看污點
kubectl describe node node1
kubectl describe node master
Taints: node-role.kubernetes.io/master:NoSchedule
複製代碼

vi deployment-user-v4.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: user-v4
spec:
  minReadySeconds: 1
  selector:
    matchLabels:
      app: user-v4
  replicas: 1
  template:
    metadata:
      labels:
        app: user-v4
    spec:
      containers:
      - name: nginx
        image: registry.cn-beijing.aliyuncs.com/zhangyaohuang/nginx:user-v3
        ports:
        - containerPort: 80
kubectl apply -f deployment-user-v4.yaml
複製代碼
  • 給 Pod 設置容忍度
    • 想讓 Pod 被調度過去,須要在 Pod 一側添加相同的容忍度才能被調度到
    • 給 Pod 設置一組容忍度,以匹配對應的 Node 的污點
    • key 和 value 是你配置 Node 污點的 key 和 value
    • effect 是 Node 污點的調度效果,和 Node 的設置項也是匹配的
    • operator 是運算符,equal 表明只有 key 和 value 相等纔算數。固然也能夠配置 exists ,表明只要 key 存在就匹配,不須要校驗 value 的值

vi deployment-user-v4.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: user-v4
spec:
  minReadySeconds: 1
  selector:
    matchLabels:
      app: user-v4
  replicas: 1
  template:
    metadata:
      labels:
        app: user-v4
    spec:
+ tolerations:
+ - key: "user-v4"
+ operator: "Equal"
+ value: "true"
+ effect: "NoSchedule"
      containers:
      - name: nginx
        image: registry.cn-beijing.aliyuncs.com/zhangyaohuang/nginx:user-v3
        ports:
        - containerPort: 80
複製代碼
  • 修改 Node 的污點

    kubectl taint nodes node1 user-v4=1:NoSchedule --overwrite
    複製代碼
  • 刪除 Node 的污點

    kubectl taint nodes node1 user-v4-
    複製代碼
  • 在 master 上佈署 pod

kubectl taint nodes node1 user-v4=true:NoSchedule
kubectl describe node node1
kubectl describe node master
複製代碼

vi deployment-user-v4.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: user-v4
spec:
  minReadySeconds: 1
  selector:
    matchLabels:
      app: user-v4
  replicas: 1
  template:
    metadata:
      labels:
        app: user-v4
    spec:
+ tolerations:
+ - key: "node-role.kubernetes.io/master"
+ operator: "Exists"
+ effect: "NoSchedule"
      containers:
      - name: nginx
        image: registry.cn-beijing.aliyuncs.com/zhangyaohuang/nginx:user-v3
        ports:
        - containerPort: 80
 kubectl apply -f deployment-user-v4.yaml
複製代碼

apiVersion: v1kind: Podmetadata: name: private-regspec: containers: - name: private-reg-container image: imagePullSecrets: - name: har

相關文章
相關標籤/搜索