k8s階段05 Operator, DaemonSet, Job, CronJob, Ingress和Ingress Controller(藍綠/恢復釋出), helm

战斗小人發表於2024-12-03

StatefulSet:編排有狀態應用

基本要求:
    需要給每個例項惟一且固定的標識,依賴於一個專用的Headless Service; 
    需要給每個例項一個專用的PVC卷,該卷要來自volumeTemplateClaim,卷的標識 “template_name-pod_name”;
    
Pod Management Policy: 
    OrderedReady:按順序,依次
    Parallel:並行
    
StatefulSet僅負責為有狀態應用的編排,提供一個基礎框架;

Operator

Operator Framework:    #go開發框架
    宣告式API

    自定義的資源型別:
        外接、獨立的API Server; #透過k8s的api server調到自己開發的API Server
        CRD: #K8S裡自定義資源型別
    自定義Controller #自己開發控制器
    
    基於專用的Operator編排執行某有狀態應用的邏輯:
        1、部署Operator及其專用的資源型別;
        2、使用專用的資源型別,來宣告一個有狀態應用的編排需求;

#社群中心網站
https://operatorhub.io/

#示例(透過Operator安裝es)
#參考文件: https://www.elastic.co/guide/en/cloud-on-k8s/current/k8s-deploy-eck.html
#1.部署crd (就會擁有crd資源物件)
[root@master01 ~]#kubectl create -f https://download.elastic.co/downloads/eck/2.15.0/crds.yaml
#檢視crd
[root@master01 ~]#kubectl get crd
#生成的資源型別
[root@master01 ~]#kubectl explain Elasticsearch

#2.基於RBAC規則部署operator (也就是執行上面資源物件的控制器)
[root@master01 ~]#kubectl apply -f https://download.elastic.co/downloads/eck/2.15.0/operator.yaml
[root@master01 ~]#kubectl get pods -n elastic-system 
NAME                 READY   STATUS    RESTARTS   AGE
elastic-operator-0   1/1     Running   0          91s

#3.定義es叢集(注意記憶體,每個節點4g)
[root@master01 eck-operator]#vim elasticsearch-myes-cluster.yaml
apiVersion: elasticsearch.k8s.elastic.co/v1
kind: Elasticsearch
metadata:
  name: 
  namespace: mall
spec:
  version: 8.13.0 #es叢集版本
  nodeSets: #每個例項設定
  - name: default #這個配置叫default
    count: 3
    config:
      node.store.allow_mmap: false #是否啟用記憶體對映
    volumeClaimTemplates: #卷請求模板
    - metadata:
        name: elasticsearch-data
      spec:
        accessModes:
        - ReadWriteOnce
        resources:
          requests:
            storage: 5Gi
       #storageClassName: nfs-csi
        storageClassName: openebs-hostpath #儲存類
[root@master01 eck-operator]#kubectl create namespace  mall
#會建立pod,service,statefulset
[root@master01 eck-operator]#kubectl apply -f elasticsearch-myes-cluster.yaml
[root@master01 eck-operator]#kubectl get all -n mall
NAME                    READY   STATUS    RESTARTS   AGE
pod/myes-es-default-0   1/1     Running   0          18m
pod/myes-es-default-1   1/1     Running   0          18m
pod/myes-es-default-2   1/1     Running   0          18m

NAME                            TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
service/myes-es-default         ClusterIP   None             <none>        9200/TCP   18m
service/myes-es-http            ClusterIP   10.106.251.132   <none>        9200/TCP   18m
service/myes-es-internal-http   ClusterIP   10.107.141.153   <none>        9200/TCP   18m
service/myes-es-transport       ClusterIP   None             <none>        9300/TCP   18m

NAME                               READY   AGE
statefulset.apps/myes-es-default   3/3     18m

#獲取es首次登陸密碼
[root@master01 eck-operator]#kubectl get secret -n mall
myes-es-elastic-user                 Opaque   1      24m
[root@master01 eck-operator]#kubectl get secret myes-es-elastic-user -o yaml -n mall
  elastic: MTdZMU1YN2RNOG4zcDlWeFRmcjA4TGEw
#base64解碼
]#echo MTdZMU1YN2RNOG4zcDlWeFRmcjA4TGEw | base64 -d
17Y1MX7dM8n3p9VxTfr08La0
#訪問es服務(透過service/myes-es-http服務)
]#curl -u "elastic:17Y1MX7dM8n3p9VxTfr08La0" -k https://10.106.251.132:9200
#也可生成一個互動式pod來訪問,這樣可以透過服務名地址訪問
]#kubectl run client-$RANDOM --image ikubernetes/admin-box:v1.2 -it --rm --restart=Never --command -- /bin/bash
root@client-17621 /# curl -u "elastic:17Y1MX7dM8n3p9VxTfr08La0" -k https://myes-es-http.mall:9200

#定義kibana
[root@master01 eck-operator]#vim kibana-myes.yaml
apiVersion: kibana.k8s.elastic.co/v1
kind: Kibana
metadata:
  name: kibana
  namespace: mall
spec:
  version: 8.13.0
  count: 1
  elasticsearchRef: #應用es叢集名
    name: "myes"
  http:
    tls: #使用tls通訊
      selfSignedCertificate:
        disabled: true
    service:
      spec:
        type: LoadBalancer
#會建立kibana的pod,deployment和service
[root@master01 eck-operator]#kubectl apply -f kibana-myes.yaml
#直接有一個kibana的資源物件 (當前為red是因為要下載pod並執行)
[root@master01 eck-operator]#kubectl get kibana -n mall
NAME     HEALTH   NODES   VERSION   AGE
kibana   red              8.13.0    25s
[root@master01 eck-operator]#kubectl get all -n mall
NAME                            READY   STATUS    RESTARTS   AGE
pod/kibana-kb-dfc656fdc-snrth   1/1     Running   0          6m
...
NAME                            TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
service/kibana-kb-http          LoadBalancer   10.97.83.49      10.0.0.53     5601:31706/TCP   6m
...
#瀏覽器輸入,訪問kibana,使用者名稱/密碼:elastic/17Y1MX7dM8n3p9VxTfr08La0
10.0.0.53:5601

#定義filebeat(上面Operator建立crd已包含filebeat)
[root@master01 eck-operator]#vim beats-filebeat.yaml
apiVersion: beat.k8s.elastic.co/v1beta1
kind: Beat
metadata:
  name: filebeat
  namespace: mall #把整個檔案中的namespace都改成mall,下面還有
spec:
  type: filebeat
  version: 8.13.0
  elasticsearchRef: #引用的es
    name: "myes"
  kibanaRef: #引用的kibana
    name: "kibana"
... #下面有排除一些名稱空間下的pod(和系統有關,防止敏感資訊洩露)
#會用daemonset部署filebeat
[root@master01 eck-operator]#kubectl apply -f beats-filebeat.yaml
#會有filebeat的資源型別
[root@master01 eck-operator]#kubectl get beat -n mall
NAME       HEALTH   AVAILABLE   EXPECTED   TYPE       VERSION   AGE
filebeat   red                  3          filebeat             37s
#檢視daemonset
[root@master01 eck-operator]#kubectl get ds -n mall

#擴容,升級等操作只要修改配置檔案並應用即可,升級會用內建的滾動更新策略,eck operator 會自動完成

3 DaemonSet

#DaemonSet用於確保所有或選定的工作節點上都執行有一個Pod副本
DaemonSet:編排系統級應用   
    資源規範:
        selector: {}
        template:{}
   
    系統級存在共享宿主資訊或資源需要:
        1、hostNet/hostPid/hostUser
        2、hostPath volume 
   
    更新:
        updateStrategy
            rollingUpdate: #預設滾動更新
                maxSurge    #預設0,一般都設定為0,否則就有2個衝突了
                maxUnavailable #預設1
        #預設如下設定,也比較合理        
        updateStrategy:
            rollingUpdate:
                maxSurge: 0
                maxUnavailable: 1
            type: RollingUpdate
                
#示例
[root@master01 daemonsets]#vim daemonset-demo.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: daemonset-demo
  namespace: prom
  labels:
    app: prometheus
    component: node-exporter
spec:
  selector:
    matchLabels:
      app: prometheus
      component: node-exporter
  template:
    metadata:
      name: prometheus-node-exporter
      labels:
        app: prometheus
        component: node-exporter
    spec:
      containers:
      - image: prom/node-exporter:v1.5.0
        name: prometheus-node-exporter
        ports:
        - name: prom-node-exp
          containerPort: 9100
          hostPort: 9100
        livenessProbe:
          tcpSocket:
            port: prom-node-exp
          initialDelaySeconds: 3
        readinessProbe:
          httpGet:
            path: '/metrics'
            port: prom-node-exp
            scheme: HTTP
          initialDelaySeconds: 5
      hostNetwork: true #共享宿主機網路
      hostPID: true
[root@master01 daemonsets]#kubectl create namespace prom
[root@master01 daemonsets]#kubectl apply -f daemonset-demo.yaml -n prom
#檢視(這裡3個是因為叢集節點3個)
[root@master01 daemonsets]#kubectl get ds -n prom
NAME             DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
daemonset-demo   3         3         0       3            0           <none>          58s
[root@master01 daemonsets]#kubectl get ds -n prom -o wide
NAME             DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE    CONTAINERS                 IMAGES                      SELECTOR
daemonset-demo   3         3         3       3            3           <none>          101s   prometheus-node-exporter   prom/node-exporter:v1.5.0   app=prometheus,component=node-exporter
#檢視pod(因為共享宿主機網路,所以ip顯示的是節點地址)
[root@master01 daemonsets]#kubectl get pods -n prom -o wide
NAME                   READY   STATUS    RESTARTS   AGE     IP           NODE     NOMINATED NODE   READINESS GATES
daemonset-demo-cfdbq   1/1     Running   0          5m24s   10.0.0.154   node03   <none>           <none>
daemonset-demo-nggp7   1/1     Running   0          5m24s   10.0.0.152   node01   <none>           <none>
daemonset-demo-zhqrd   1/1     Running   0          5m24s   10.0.0.153   node02   <none>           <none>
#檢視隨便一臺的指標
[root@master01 daemonsets]#curl 10.0.0.154:9100/metrics

#升級
[root@master01 daemonsets]#vim daemonset-demo.yaml
...
    spec:
      containers:
      - image: prom/node-exporter:v1.6.0 #修改版本
#更新
[root@master01 daemonsets]#kubectl apply -f daemonset-demo.yaml
#可以看到是逐一更新的
]#kubectl get pods -n prom -w

5 Job和CronJob

#一次性任務用job,週期性任務用cronjob
#本質是cronjob是不斷建立一個新job來實現
#注:Job和CronJob型別重啟策略應該設定為OnFailure或Never,OnFailure最合適(可設重啟次數,預設6)

#有時候有些服務pod會使用job來做環境初始化

Job控制器的應用編排機制

Job負責編排執行有結束時間的“一次性”任務,而前面的Deployment和DaemonSet主要負責編排始終執行的守護程序類應用;
  ◼ 控制器要確保Pod內的程序“正常(成功完成任務)”地退出
  ◼ 非正常退出的Pod可以根據需要重啟,並在重試一次的次數後終止
  ◼ 有些Job是單次任務,也有些Job需要執行多次(次數通常固定)
  ◼ 有些任務支援同時建立及並行執行多個Pod以加快任務處理速度,Job控制器還允許使用者自定義其並行度
  
需要週期性執行的Job,則由CronJob控制器負責編排
  ◼ CronJob建立在Job的功能之上,是更高層級的控制器
  ◼ 它以Job控制器完成單批次的任務編排,而後為這種Job作業提供需要執行的週期定義

Job資源規範

 Job資源同樣需要標籤選擇器和Pod模板,但它不需要指定replicas,而是應該給定completions,即需要完成的作業數,預設為1次;
  ◼ Job資源會為其Pod物件自動新增“job-name=JOB_NAME”和“controller-uid=UID”標籤,並使用標籤選擇器完成對controller-uid標籤的關聯,因此,selector並非必選欄位
  ◼ Pod的命名格式:`$(job-name)-$(index)-$(random-string),其中的$(index)欄位取值與completions和completionMode有關
  ◼ 注意
    ◆ Job資源所在群組為“batch/v1”
    ◆ Job資源中,Pod的RestartPolicy的取值
      只能為Never或OnFailure

#示例模板
apiVersion: batch/v1 # API群組及版本;
kind: Job # 資源型別特有標識;
metadata:
 name <string> # 資源名稱,在作用域中要惟一;
 namespace <string> # 名稱空間;Job資源隸屬名稱空間級別;
spec:
 selector <object> # 標籤選擇器,必須匹配template欄位中Pod模板中的標籤;(可不設,Job自動生成標籤夠用)
 suspend <boolean> # 是否掛起當前Job的執行,掛起作業會重置StartTime欄位的值;
 template <object> # Pod模板物件;
 completions <integer> #期望的成功完成的作業次數,成功執行結束的Pod數量;(要執行幾次)
 completionMode <string> # 追蹤Pod完成的模式,支援Indexed和NonIndexed(預設)兩種;
 ttlSecondsAfterFinished <integer> # 終止狀態作業的生存時長,超期將被刪除;
 parallelism <integer> # 作業的最大並行度,預設為1;(不超過completions執行次數,否則無意義)
 backoffLimit <integer> # 將作業標記為“Failed”之前的重試次數,預設為6;
 activeDeadlineSeconds <integer> # 作業啟動後可處於活動狀態的時長;

Job的狀態

#下面模擬一個簡單Job(序列執行)
[root@master01 jobs_and_cronjobs]#vim job-demo.yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: job-demo
spec:
  template:
    spec:
      containers:
      - name: myjob
        image: ikubernetes/admin-box:v1.2
        imagePullPolicy: IfNotPresent
        command: ["/bin/sh", "-c", "sleep 15"] #執行命令
      restartPolicy: Never
  completions: 2 #要執行2次
  ttlSecondsAfterFinished: 3600
  backoffLimit: 3
  activeDeadlineSeconds: 300
#執行並觀察,啟動一個完成後再啟動一個
]#kubectl apply -f job-demo.yaml && kubectl get pods -w
#完成後檢視pods,都是Completed狀態
[root@master01 ~]#kubectl get pods
NAME                       READY   STATUS      RESTARTS        AGE
job-demo-2rpxh             0/1     Completed   0               114s
job-demo-ct2xk             0/1     Completed   0               38s
#檢視job
[root@master01 jobs_and_cronjobs]#kubectl get jobs -o wide

#下面模擬一個簡單Job(並行執行)
[root@master01 jobs_and_cronjobs]#vim job-para-demo.yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: job-para-demo
spec:
  template:
    spec:
      containers:
      - name: myjob
        image: ikubernetes/admin-box:v1.2
        imagePullPolicy: IfNotPresent
        command: ["/bin/sh", "-c", "sleep 15"]
      restartPolicy: Never
  completions: 6 #執行6次
  parallelism: 2 #並行數改為2
  ttlSecondsAfterFinished: 3600
  backoffLimit: 3
  activeDeadlineSeconds: 1200
#執行,同一時間有2個pod執行,至於在哪個節點上是排程器決定的
[root@master01 jobs_and_cronjobs]#kubectl apply -f job-para-demo.yaml &&kubectl get pods -w

#job一般不存在更新的需求

CronJob

#每隔一段時間根據job模板建立job
  CronJob控制器用於管理Job資源的執行時間,它允許使用者在特定的時間或以指定的間隔執行Job
  CronJob控制器的功能類似於linux作業系統的週期性任務作業計劃(crontab),用於控制作業執行的時間點及週期性執行的方式:
    ◼ 僅在未來某時間點將指定的作業執行一次
    ◼ 在指定的週期性時間點重複執行指定的作業
  CronJob資源也是標準的API資源型別
  注意:
    ◼ 在CronJob中,萬用字元“?”和“*”的意義相同,它們都表示任何可用的有效值

#示例模板
apiVersion: batch/v1 # API群組及版本;
kind: CronJob # 資源型別特有標識;
metadata:
 name <string> # 資源名稱,在作用域中要惟一;
 namespace <string> # 名稱空間;CronJob資源隸屬名稱空間級別;
spec:
 jobTemplate <Object> # job作業模板,必選欄位;
  metadata <object> # 模板後設資料;
  spec <object> # 作業的期望狀態;
 schedule <string> # 排程時間設定,必選欄位;
 #前一job沒結束,後一job開始了,允許嗎?allow允許,forbid禁止,Replace替換(後job替換前job)
 concurrencyPolicy <string> # 併發策略,可用值有Allow、Forbid和Replace;
 failedJobsHistoryLimit <integer> # 失敗作業的歷史記錄數,預設為1;
 successfulJobsHistoryLimit <integer> # 成功作業的歷史記錄數,預設為3;
 startingDeadlineSeconds <integer> #因錯過時間點而未執行的作業的可超期時長;(因快到下一個執行點了)
 suspend <boolean> # 是否掛起後續的作業,不影響當前作業,預設為false;

#Cronjob說明:
#每兩小時執行一次
0 */2 * * * #分鐘不能用*,不然就會變成沒隔2小時每分鐘執行
0 7,10,16 * * * #7,10,16點各執行一次
0 8-18 * * * #8點到18點,每小時執行一次

#示例
[root@master01 jobs_and_cronjobs]#vim cronjob-demo.yaml
apiVersion: batch/v1
kind: CronJob
metadata:
  name: cronjob-demo
  namespace: default
spec:
  schedule: "* * * * *" #每分鐘執行一次
  jobTemplate:
    metadata:
      labels: #標籤加不加都可以
        controller: cronjob-demo
    spec:
      parallelism: 1 #並行度為1
      completions: 1 #執行1次
      ttlSecondsAfterFinished: 600
      backoffLimit: 3
      activeDeadlineSeconds: 60
      template:
        spec:
          containers:
          - name: myjob
            image: ikubernetes/admin-box:v1.2
            command:
            - /bin/sh
            - -c
            - date; echo Hello from CronJob, sleep a while...; sleep 10
          restartPolicy: OnFailure
  startingDeadlineSeconds: 300
[root@master01 jobs_and_cronjobs]#kubectl apply -f cronjob-demo.yaml
#檢視,每分鐘會執行job (job和pod保留最近3個,設定可改)
[root@master01 jobs_and_cronjobs]#kubectl get cronjob,job,pods
NAME                         SCHEDULE    TIMEZONE   SUSPEND   ACTIVE   LAST SCHEDULE   AGE
cronjob.batch/cronjob-demo   * * * * *   <none>     False     0        31s             44s

NAME                              STATUS     COMPLETIONS   DURATION   AGE
job.batch/cronjob-demo-28882640   Complete   1/1           13s        31s

NAME                              READY   STATUS      RESTARTS       AGE
pod/cronjob-demo-28882640-llz5p   0/1     Completed   0              31s
#檢視日誌,裡面會顯示幾點執行的
[root@master01 jobs_and_cronjobs]#kubectl logs cronjob-demo-28882640-llz5p
Sat Nov 30 09:20:00 UTC 2024
Hello from CronJob, sleep a while...

#避免一直執行,這裡刪除cronjob,對應的job和pod也會被刪除
[root@master01 jobs_and_cronjobs]#kubectl delete -f cronjob-demo.yaml

1 Ingress和Ingress Controller

將服務類應用暴露至叢集外部的方法:
    NodePort Service 
    LoadBalancer Service 
        使用專用NodePort來暴露服務
    Service with ExternalIP 
        使用專用的ExternalIP來暴露服務
       
以上四層代理
透過 Ingress + Ingress Controller 轉為七層代理,統一管理流量
#Ingress Controller直接把請求打到service下的pod上,進行負載均衡(不需要service負載均衡了)。
#service的負載均衡功能不需要了,但是需要pod發現功能,把pod資訊發給Ingress Controller

Ingress及其它相關的資源型別 + Ingress Controller 
    資源型別: 
        Ingress 
        IngressClass #告訴哪個Ingress Controller可以載入解析Ingress資源
        IngressGateway #更高階的功能,流量閘道器,業務閘道器(目前屬於alpha特性,後續版本會提供)
        
    Ingress Controller: #有如下幾種可以選擇
        Ingress-Nginx: kubernetes-sigs #用的最多
            registry.k8s.io 
        Kong       
        Traefik #用的較多
        Contour
        Gloo
        Cilium  
        #各主流Ingress Controller對比圖:
        https://blog.palark.com/wp-content/uploads/2019/10/kubernetes-ingress-comparison.png
        
七層代理多個服務的方式:
    虛擬主機:
        port
        ip 
        host: 基於主機名的虛擬主機
    基於單一虛擬主機開放多服務:
        scheme://host:port/PATH{1,2,3, ...}
    最終可用的方式:基於主機名的虛擬主機;
    SSL虛擬主機:SNI
    
    Ingress的型別: 
        簡單扇出:基於單一虛擬主機使用不同的Path開放多服務  
          http://magedu.com/blog/ --> wordpress:80/blog/ #會訪問wordpress下的blog
          url rewrite    #可以透過rewrite跳轉到wordpress/下
            --annotation nginx.ingress.kubernetes.io/rewrite-target="/"
            
        基於主機名的虛擬主機 
        SSL 

2 Ingress的型別

型別一:Simple fanout

#主機一樣,路徑不同

型別二:Name based virtual hosting

#每一個服務使用一個獨立的主機名
#例:
service1.magedu.com
service2.magedu.com

型別三:TLS

#把其中一個主機名配置為https

3 Ingress 資源

部署Ingress-Nginx

#官網
https://github.com/kubernetes/ingress-nginx #注意表中Ingress-NGINX版本對k8s版本的適配
https://kubernetes.github.io/ingress-nginx/deploy/

#部署Ingress-Nginx
]#kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.12.0-beta.0/deploy/static/provider/cloud/deploy.yaml

#檢視資源物件(會建立在ingress-nginx的名稱空間中)
[root@master01 ~]#kubectl get all -n ingress-nginx
...#因為部署了metallb,這裡ingress-nginx-controller服務自動分配了EXTERNAL-IP
service/ingress-nginx-controller             LoadBalancer   10.96.135.77   10.0.0.52     80:32563/TCP,443:30464/TCP   12m
[root@master01 ~]#kubectl get pods -n ingress-nginx
NAME                                        READY   STATUS      RESTARTS   AGE
ingress-nginx-admission-create-sx2t8        0/1     Completed   0          3h
ingress-nginx-admission-patch-4djcx         0/1     Completed   0          3h
ingress-nginx-controller-7d56585cd5-6jdp5   1/1     Running     0          3h

#瀏覽器可以嘗試訪問ingress-nginx-controller服務,會報404 nginx,因為還沒有主機
10.0.0.52
#部署Ingress-Nginx時,會自動建立叫nginx的ingressclass (部署controller都會建立一個對應ingressclass)
[root@master01 ~]#kubectl get ingressclass
NAME    CONTROLLER             PARAMETERS   AGE
nginx   k8s.io/ingress-nginx   <none>       76m

把服務開放到外部去訪問

建立使用Ingress資源:
     kubectl create ingress NAME --rule=host/path=service:port[,tls[=secret]]  [options]
         --class #指定ingressclass是誰
         注意事項:
             (1) Ingress是名稱空間級別的資源,它僅應該引用同一個名稱空間下的Service;
             (2) 主機名不是叢集上的資源物件,因而其作用範圍為叢集級別;

#實際操作示例(把demoapp服務透過ingress-nginx對外暴露):
#如果沒有service,先建立一個service
]#kubectl create service clusterip demoapp --tcp=80:80
[root@master01 ~]#kubectl get svc
NAME                        TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
service/demoapp             ClusterIP      10.107.218.150   <none>        80/TCP         14s

#建立Ingress資源(主機:demoapp.magedu.com;路徑:/表示起始路徑/*起始與所有路徑,加''防止*被shell解析)
#ingress要開發sevice通常在同一名稱空間
#先測試輸出看看效果
]#kubectl create ingress demoapp --rule='demoapp.magedu.com/*'=demoapp:80 --class=nginx --dry-run -o yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  creationTimestamp: null
  name: demoapp
spec:
  ingressClassName: nginx
  rules:
  - host: demoapp.magedu.com
    http:
      paths:
      - backend:
          service:
            name: demoapp
            port:
              number: 80
        path: /
        pathType: Prefix #/*就是Prefix;如果是/就是Exact,精確匹配/(不會代理/abc)
status:
  loadBalancer: {}
]#kubectl create ingress demoapp --rule='demoapp.magedu.com/*'=demoapp:80 --class=nginx
#也可以使用下面宣告式物件配置
]#kubectl create ingress demoapp --rule='demoapp.magedu.com/*'=demoapp:80 --class=nginx --dry-run=client -o yaml > ingress-demoapp.yaml
]#kubectl apply -f ingress-demoapp.yaml

#檢視ingress資源
[root@master01 ~]#kubectl get ingress
NAME      CLASS   HOSTS                ADDRESS   PORTS   AGE
demoapp   nginx   demoapp.magedu.com             80      10s
#檢視詳情(底下Reason為sync,Scheduled for sync表示ingress已經被Ingress-Nginx載入並生效了)
[root@master01 ~]#kubectl describe ingress demoapp
...
Rules:
  Host                Path  Backends
  ----                ----  --------
  demoapp.magedu.com  
                      /   demoapp:80 (10.244.1.145:80,10.244.2.125:80,10.244.3.91:80)
Annotations:          <none>
Events:
  Type    Reason  Age                    From                      Message
  ----    ------  ----                   ----                      -------
  Normal  Sync    4m10s (x2 over 4m51s)  nginx-ingress-controller  Scheduled for sync
  
#測試,主機host檔案配置 ingress-nginx-controller的EXTERNAL-IP給對應主機名
10.0.0.52 demoapp.magedu.com
#瀏覽器訪問即可返回,重新整理會自動跳轉到各個pod
demoapp.magedu.com
#進入nginx的pod中檢視,nginx的conf中上游透過lua指令碼實現上游怎麼發現,使用什麼balance代理(如刪除ingress資源,nginx會自動把對應配置刪除)
#ingress-nginx會讀取ingress資源變動,並將其對映為自己配置檔案上的配置,並讓niginx隨時動態按需過載


#示例(把wordpress暴露到外面)
#建立ingress
]#kubectl create ingress wordpress --rule='blog.magedu.com/*'=wordpress:80 --class=nginx -n blog
#檢視ingress
]#kubectl describe ingress wordpress -n blog

#把blog.magedu.com配入宿主機host檔案中,訪問測試

Annotation(瞭解, 早期使用)

    Annotation:#可以給ingress-nginx配置更多引數
        註解資訊;新增到資源物件上的kv型別的資料;
            鍵標識:[prefix/]key
        不適用於標籤選擇器來過濾資源物件;
            
        常用於為資源提供註釋資訊,該資訊還可以被特定的控制器解讀為應用的配置的資訊
        #yaml中使用格式    
        metadata:
            labels: 
                ...
            annotations:
                ...
              
        命令:kubectl annotate     #使用方式和label相同
        
#ingress-nginx配置引數參考
https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/
#例:
#url重寫路徑
nginx.ingress.kubernetes.io/enable-rewrite-log    "true" or "false"

把ingress配置為ssl的型別

SSL Ingress: 
    準備secret
    建立Ingress,指明要載入secret中的證書和私鑰
kubectl create ingress NAME --rule=host/path=service:port[,tls[=secret]]  [options]

#示例
#建立私鑰
[root@master01 ~]#(umask 011;openssl genrsa -out demoapp.key 2048)
#基於demoapp.key建立自簽證書(subj指定證書持有者資訊)
[root@master01 ~]#openssl req -new -x509 -key ./demoapp.key -out ./demoapp.crt -days=3655 -subj="/CN=demoapp.magedu.com"

#建立成secret(型別tls,名稱demoapp-ssl)
[root@master01 ~]#kubectl create secret tls demoapp-ssl --key=./demoapp.key --cert=./demoapp.crt
#檢視
[root@master01 ~]#kubectl get secrets

#刪除前面的ingress,重新建簡單些
[root@master01 ~]#kubectl delete ingress demoapp
#建立ingress
]#kubectl create ingress demoapp --rule='demoapp.magedu.com/*'=demoapp:80,tls=demoapp-ssl --class=nginx

#檢視是否完成同步(Scheduled for sync說明完成了同步)
[root@master01 ~]#kubectl describe ingress demoapp
...
  Normal  Sync    23s   nginx-ingress-controller  Scheduled for sync
  
#瀏覽器訪問(點高階,繼續訪問即可)
https://demoapp.magedu.com/

簡單扇出:基於單一虛擬主機使用不同的Path開放多服務(用的比較少)

#注意: 把www.magedu.com/demoapp/路徑對映出去,demoapp也需要/demoapp/路徑,沒有可以用rewrite做url重寫
簡單扇出:基於單一虛擬主機使用不同的Path開放多服務  
    http://magedu.com/blog/ --> wordpress:80/blog/ #會訪問wordpress下的blog
    url rewrite    #可以透過rewrite跳轉到wordpress/下
        --annotation nginx.ingress.kubernetes.io/rewrite-target="/"

#建立ingress
]#kubectl create ingress www --rule='www.magedu.com/demoapp/*'=demoapp:80 --class=nginx --annotation nginx.ingress.kubernetes.io/rewrite-target="/"

#修改host檔案,瀏覽器訪問測試
http://www.magedu.com/demoapp/

4 基於Ingress Nginx 進行灰度釋出

基於Ingress Nginx的灰度釋出

Ingress-Nginx支援配置Ingress Annotations來實現不同場景下的灰度釋出和測試,它能夠滿足金絲雀發
布、藍綠部署與A/B測試等不同的業務場景

基於Ingress Nginx的Canary規則

https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/
#ingress-nginx配置引數canary,true:當前ingress規則發新版本,false或沒設:接入流量發給舊版本(相當於釋出開關)
nginx.ingress.kubernetes.io/canary    "true" or "false"
#如果上面的釋出開關canary為true,流量怎麼在新舊版本之間做調整,透過下面引數
nginx.ingress.kubernetes.io/canary-by-header    string
nginx.ingress.kubernetes.io/canary-by-header-value    string
nginx.ingress.kubernetes.io/canary-by-header-pattern    string
nginx.ingress.kubernetes.io/canary-by-cookie    string
nginx.ingress.kubernetes.io/canary-weight    number
nginx.ingress.kubernetes.io/canary-weight-total    number

Ingress Nginx Annotations支援的Canary規則
  ◼ nginx.ingress.kubernetes.io/canary-by-header:基於該Annotation中指定Request Header進行流量切分,適用於灰度釋出以及A/B測試
    ◆在請求報文中,若存在該Header且其值為always時,請求將會被髮送到Canary版本
    ◆若存在該Header且其值為never時,請求將不會被髮送至Canary版本
    ◆對於任何其它值,將忽略該Annotation指定的Header,並透過優先順序將請求與其他金絲雀規則進行優先順序的比較
  ◼ nginx.ingress.kubernetes.io/canary-by-header-value:基於該Annotation中指定的Request Header的值進行流量切分,標頭名稱則由前一個Annotation(nginx.ingress.kubernetes.io/canary-by-header)進行指定
    ◆請求報文中存在指定的標頭,且其值與該Annotation的值匹配時,它將被路由到Canary版本
    ◆對於任何其它值,將忽略該Annotation
  ◼ nginx.ingress.kubernetes.io/canary-by-header-pattern
    ◆同canary-by-header-value的功能類似,但該Annotation基於正規表示式匹配Request Header的值
    ◆若該Annotation與canary-by-header-value同時存在,則該Annotation會被忽略
    
Ingress Nginx Annotations支援的Canary規則(續)
  ◼ nginx.ingress.kubernetes.io/canary-weight:基於服務權重進行流量切分,適用於藍綠部署,權重範圍0 - 100按百分比將請求路由到Canary Ingress中指定的服務
    ◆權重為 0 意味著該金絲雀規則不會向Canary入口的服務傳送任何請求
    ◆權重為100意味著所有請求都將被髮送到 Canary 入
  ◼ nginx.ingress.kubernetes.io/canary-by-cookie:基於 cookie 的流量切分,適用於灰度釋出與 A/B 測試
    ◆cookie的值設定為always時,它將被路由到Canary入口
    ◆cookie的值設定為 never時,請求不會被髮送到Canary入口
    ◆對於任何其他值,將忽略 cookie 並將請求與其他金絲雀規則進行優先順序的比較
    
規則的應用次序
  ◼ Canary規則會按特定的次序進行評估
  ◼ 次序:canary-by-header -> canary-by-cookie -> canary-weight #如果沒匹配到就發給舊版本


工作負載型控制器的高階實現(瞭解):#支援高階釋出功能(金絲雀,藍綠髮布)
    Argo Rollouts,可取代Deployment的全部功能
    OpenKruise Kruise Rollouts

實際操作示例(各種釋出規則)

#把當前default名稱空間下的資源都刪了,免得干擾
]#kubectl delete deployments,service,statefulset --all
]#kubectl delete ingress --all

#建立demoapp的Deployment和service
[root@master01 ingress-canary-demo]#kubectl apply -f deploy-demoap-v1_0.yaml
#建立ingress
[root@master01 ingress-canary-demo]#vim 01-ingress-demoapp.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: demoapp
  annotations: #改欄位已經被廢,能用,用ingressClassName代替
    kubernetes.io/ingress.class: nginx
spec:
  rules:
  - host: demoapp.magedu.com
    http:
      paths:
      - backend:
          service:
            name: demoapp-v10
            port:
              number: 80
        path: /
        pathType: Prefix

[root@master01 ingress-canary-demo]#kubectl apply -f 01-ingress-demoapp.yaml
#瀏覽器輸入,測試
demoapp.magedu.com

#建立新版本對應的Deployment和service
[root@master01 ingress-canary-demo]#kubectl apply -f deploy-demoap-v1_1.yaml

#ingress上加配置,遷一部分流量到新版本
[root@master01 ingress-canary-demo]#vim 02-canary-by-header.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    nginx.ingress.kubernetes.io/canary: "true" #啟動canary功能
    nginx.ingress.kubernetes.io/canary-by-header: "X-Canary" #有該標頭髮給新版本
  name: demoapp-canary-by-header
spec:
  ingressClassName: nginx
  rules:
  - host: demoapp.magedu.com
    http:
      paths:
      - backend:
          service:
            name: demoapp-v11 #新版本服務
            port:
              number: 80
        path: /
        pathType: Prefix
[root@master01 ingress-canary-demo]#kubectl apply -f 02-canary-by-header.yaml
#檢視,現在有2個ingress
[root@master01 ingress-canary-demo]#kubectl get ingress
NAME                       CLASS    HOSTS                ADDRESS     PORTS   AGE
demoapp                    <none>   demoapp.magedu.com   10.0.0.52   80      39m
demoapp-canary-by-header   nginx    demoapp.magedu.com   10.0.0.52   80      7m56s

#在另一臺機器上配置host做測試
[root@node01 ~]#curl demoapp.magedu.com #請求老版本
iKubernetes demoapp v1.0 !! ClientIP: 10.244.2.138, ServerName: demoapp-v10-7895f997b5-spljs, ServerIP: 10.244.1.158!
#加入請求頭X-Canary: always, 請求新版
[root@node01 ~]#curl -H "X-Canary: always" demoapp.magedu.com
iKubernetes demoapp v1.1 !! ClientIP: 10.244.2.138, ServerName: demoapp-v11-559fc44c47-27ncl, ServerIP: 10.244.1.159!
[root@node01 ~]#curl -H "X-Canary: a" demoapp.magedu.com #請求老版本(因為不是always)
iKubernetes demoapp v1.0 !! ClientIP: 10.244.2.138, ServerName: demoapp-v10-7895f997b5-spljs, ServerIP: 10.244.1.158!
#把02的釋出規則刪掉
[root@master01 ingress-canary-demo]#kubectl delete -f 02-canary-by-header.yaml

#在02基礎上追加了自定義規則值
]#vim 03-canary-by-header-value.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    nginx.ingress.kubernetes.io/canary: "true"
    nginx.ingress.kubernetes.io/canary-by-header: "IsVIP" #存在這個標頭,且值為false,就發給canary
    nginx.ingress.kubernetes.io/canary-by-header-value: "false"
  name: demoapp-canary-by-header-value
spec:
  ingressClassName: nginx
  rules:
  - host: demoapp.magedu.com
    http:
      paths:
      - backend:
          service:
            name: demoapp-v11
            port:
              number: 80
        path: /
        pathType: Prefix
[root@master01 ingress-canary-demo]#kubectl apply -f 03-canary-by-header-value.yaml
[root@master01 ingress-canary-demo]#kubectl get ingress
NAME                             CLASS    HOSTS                ADDRESS     PORTS   AGE
demoapp                          <none>   demoapp.magedu.com   10.0.0.52   80      44m
demoapp-canary-by-header-value   nginx    demoapp.magedu.com   10.0.0.52   80      35s
#測試
[root@node01 ~]#curl -H "IsVIP: false" demoapp.magedu.com
iKubernetes demoapp v1.1 !! ClientIP: 10.244.2.138, ServerName: demoapp-v11-559fc44c47-27ncl, ServerIP: 10.244.1.159!
[root@node01 ~]#curl demoapp.magedu.com
iKubernetes demoapp v1.0 !! ClientIP: 10.244.2.138, ServerName: demoapp-v10-7895f997b5-spljs, ServerIP: 10.244.1.158!
[root@node01 ~]#curl -H "IsVIP: always" demoapp.magedu.com
iKubernetes demoapp v1.0 !! ClientIP: 10.244.2.138, ServerName: demoapp-v10-7895f997b5-spljs, ServerIP: 10.244.1.158!
#把新的釋出規則刪掉,以免干擾
[root@master01 ingress-canary-demo]#kubectl delete -f 03-canary-by-header-value.yaml

[root@master01 ingress-canary-demo]#vim 04-canary-by-header-pattern.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/canary: "true"
    nginx.ingress.kubernetes.io/canary-by-header: "Username" #正規表示式匹配
    nginx.ingress.kubernetes.io/canary-by-header-pattern: "(vip|VIP)_.*"
  name: demoapp-canary-by-header-pattern
spec:
  rules:
  - host: demoapp.magedu.com
    http:
      paths:
      - backend:
          service:
            name: demoapp-v11
            port:
              number: 80
        path: /
        pathType: Prefix
[root@master01 ingress-canary-demo]#kubectl apply -f 04-canary-by-header-pattern.yaml
#測試
[root@node01 ~]#curl demoapp.magedu.com
iKubernetes demoapp v1.0 !! ClientIP: 10.244.2.138, ServerName: demoapp-v10-7895f997b5-spljs, ServerIP: 10.244.1.158!
[root@node01 ~]#curl -H "Username: vip_aaa" demoapp.magedu.com
iKubernetes demoapp v1.1 !! ClientIP: 10.244.2.138, ServerName: demoapp-v11-559fc44c47-27ncl, ServerIP: 10.244.1.159!
[root@master01 ingress-canary-demo]#kubectl delete -f 04-canary-by-header-pattern.yaml

#注意:上面3種方式,使用其中的任意一種

[root@master01 ingress-canary-demo]#vim 05-canary-by-weight.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/canary: "true"
    nginx.ingress.kubernetes.io/canary-weight: "50" #新版本權重50%
  name: demoapp-canary-by-weight
spec:
  rules:
  - host: demoapp.magedu.com
    http:
      paths:
      - backend:
          service:
            name: demoapp-v11
            port:
              number: 80
        path: /
        pathType: Prefix
[root@master01 ingress-canary-demo]#kubectl apply -f 05-canary-by-weight.yaml
#測試,檢視返回比例
[root@node01 ~]#while true; do curl demoapp.magedu.com; sleep .2; done
#刪除,避免後續測試干擾
[root@master01 ingress-canary-demo]#kubectl delete -f 05-canary-by-weight.yaml

[root@master01 ingress-canary-demo]#vim 06-canary-by-cookie.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/canary: "true" #有cookie,且vip_user=always就發給新版
    nginx.ingress.kubernetes.io/canary-by-cookie: "vip_user"
  name: demoapp-canary-by-cookie
spec:
  rules:
  - host: demoapp.magedu.com
    http:
      paths:
      - backend:
          service:
            name: demoapp-v11
            port:
              number: 80
        path: /
        pathType: Prefix
[root@master01 ingress-canary-demo]#kubectl apply -f 06-canary-by-cookie.yaml
#測試
[root@node01 ~]#curl demoapp.magedu.com
iKubernetes demoapp v1.0 !! ClientIP: 10.244.2.138, ServerName: demoapp-v10-7895f997b5-spljs, ServerIP: 10.244.1.158!
[root@node01 ~]#curl -b "vip_user=always" demoapp.magedu.com
iKubernetes demoapp v1.1 !! ClientIP: 10.244.2.138, ServerName: demoapp-v11-559fc44c47-27ncl, ServerIP: 10.244.1.159!
#刪除,避免後續測試干擾
[root@master01 ingress-canary-demo]#kubectl delete -f 06-canary-by-cookie.yaml


#模擬藍綠髮布
#藍綠髮布,實際就是透過權重控制
[root@master01 ingress-canary-demo]#vim 05-canary-by-weight.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/canary: "true"
    nginx.ingress.kubernetes.io/canary-weight: "0" #新版本權重為0
  name: demoapp-canary-by-weight
spec:
  rules:
  - host: demoapp.magedu.com
    http:
      paths:
      - backend:
          service:
            name: demoapp-v11
            port:
              number: 80
        path: /
        pathType: Prefix
[root@master01 ingress-canary-demo]#kubectl apply -f 05-canary-by-weight.yaml
#測試,檢視返回比例,全是舊版本
[root@node01 ~]#while true; do curl demoapp.magedu.com; sleep .2; done

#等部署完新版本,新版本上線,手動測試能用,立即編輯05
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/canary: "true"
    nginx.ingress.kubernetes.io/canary-weight: "100" #調整為100
  name: demoapp-canary-by-weight
spec:
  rules:
  - host: demoapp.magedu.com
    http:
      paths:
      - backend:
          service:
            name: demoapp-v11
            port:
              number: 80
        path: /
        pathType: Prefix
[root@master01 ingress-canary-demo]#kubectl apply -f 05-canary-by-weight.yaml
#測試,檢視返回比例,全是新版本
[root@node01 ~]#while true; do curl demoapp.magedu.com; sleep .2; done

Helm程式包管理器

Helm: 
    包管理器:
        rpm/rpm, deb/dpkg, ...
        yum/dnf, apt/apt-get, ...

    helm, Chart:
        包格式:Chart, tgz打包格式 
        管理工具:Helm 

        Chart倉庫:
            http/https 

            helm: 命令列客戶端
                Chart倉庫 
                API Server (kubeconfig檔案) 

            倉庫的位置:
                專案自身維護倉庫
                公共倉庫: oci://
                
        Chart中的yaml檔案格式:
            模板檔案 --> 向模板字串賦值 --> 完成模板渲染

            賦值方式:
                命令列選項:helm --set KEY=VALUE --set ...
                值檔案:helm -f /PATH/TO/YAML_FILE 
                Chart通常會附帶預設的值檔案(values.yml)
                
    部署的例項:
        Release 
        
    helm程式元件:
        v2: 
            helm --> Tiller (部署執行在Kubernetes叢集上) --> API Server 
        v3: 
            helm --> API Server 

Helm 基礎

Helm是一款簡化安裝和管理Kubernetes應用程式的工具
  ◼ 可用於Kubernetes之上的應用程式管理的資源配置檔案需要以特定的結構組織為Chart
    ◆Chart代表著可由Helm管理的有著特定格式的程式包
    ◆Chart中的資源配置檔案通常以模板(go template)形式定義,在部署時,使用者可透過向模板引數賦值實現定製化安裝
的目的
    ◆各模板引數通常也有預設值,這些預設值定義在Chart包裡一個名為values.yml的檔案中
  ◼ 類似於kubectl,Helm也是Kubernetes API Server的命令列客戶端工具
    ◆支援kubeconfig認證檔案
    ◆需要事先從倉庫或本地載入到要使用目標Chart,並基於Chart完成應用管理
    ◆Chart可快取於Helm本地主機上
  ◼ 支援倉庫管理和包管理的各類常用操作,例如Chart倉庫的增、刪、改、查,以及Chart包的製作、釋出、搜尋、下載等

Helm社群的Artifact Hub

#官網
https://artifacthub.io/

Artifact Hub
  ◼ 由Helm社群維護的一個名為Artifact Hub的Web應用,旨在便於Chart的共享與分發
  ◼ 支援查詢、安裝和釋出Kubernetes應用程式包

部署helm

#根據官網,可以下載自己所需要的版本
https://helm.sh/docs/intro/install/
#我這裡選v3.16.3最新版本, Linux amd64版本 (go開發,靜態編譯,放在/usr/local/bin或/usr/bin下可直接使用)

#下載
[root@master01 ~]#curl -LO https://get.helm.sh/helm-v3.16.3-linux-amd64.tar.gz
[root@master01 ~]#tar xf helm-v3.16.3-linux-amd64.tar.gz
[root@master01 ~]#cd linux-amd64/
[root@master01 linux-amd64]#mv helm /usr/local/bi
[root@master01 linux-amd64]#cd
#可以使用helm了

#搜尋chart,搜本地配置的倉庫是repo, 搜Artifact Hub用hub
#搜本地倉庫,這裡因為沒配本地倉庫
]#helm search repo mysql
Error: no repositories configured
#搜Artifact Hub中包含mysql的
[root@master01 wordpress]#helm search hub mysql
URL            CHART VERSION    APP VERSION                DESCRIPTION
...

使用helm部署mysql示例

#Artifact Hub上搜mysql (bitnami是一個很大的開源組織) 可以參看預設引數
https://artifacthub.io/packages/helm/bitnami/mysql

#注意:helm install下dockerhub映象,要網路代理,推薦使用環境變數的方法
]#export https_proxy="http://10.0.0.1:7890"
]#export http_proxy="http://10.0.0.1:7890"
]#export no_proxy="127.0.0.0/8,10.244.0.0/16,192.168.0.0/16,10.96.0.0/12,magedu.com,cluster.local"


#基於dockerhub上的oci倉庫部署,建立mysql的release(下面沒設的引數採用預設值)
helm install mysql  \
        --set auth.rootPassword='MageEdu' \
        --set global.storageClass=nfs-csi \ #可改為openebs-hostpath本地卷,提升效能
        --set architecture=replication \ #架構型別
        --set auth.database=wpdb \
        --set auth.username=wpuser \
        --set auth.password='magedu.com' \
        --set secondary.replicaCount=1 \ #從伺服器幾個例項
        --set auth.replicationPassword='replpass' \ #從伺服器連主服務區使用的密碼
        oci://registry-1.docker.io/bitnamicharts/mysql \
        -n wordpress --create-namespace #create-namespace如果名稱空間不存在就建立
#自動到dockerhub上下載指定的chart,建立出一個release(部署主從複製的mysql)
#返回
NAME: mysql
LAST DEPLOYED: Tue Dec  3 04:36:34 2024
NAMESPACE: wordpress
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
CHART NAME: mysql
CHART VERSION: 12.1.0
APP VERSION: 8.4.3 #mysql版本
#獲取密碼(使用者root) 獲取的其實就是設定的MageEdu
MYSQL_ROOT_PASSWORD=$(kubectl get secret --namespace wordpress mysql -o jsonpath="{.data.mysql-root-password}" | base64 -d)
  2. To connect to primary service (read/write):
      mysql -h mysql-primary.wordpress.svc.cluster.local -uroot -p"$MYSQL_ROOT_PASSWORD"
  3. To connect to secondary service (read-only):
      mysql -h mysql-secondary.wordpress.svc.cluster.local -uroot -p"$MYSQL_ROOT_PASSWORD"
      
#檢視建立的東西
[root@master01 ~]#kubectl get all -n wordpress
NAME                    READY   STATUS    RESTARTS   AGE
pod/mysql-primary-0     1/1     Running   0          17m
pod/mysql-secondary-0   1/1     Running   0          17m

NAME                               TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
service/mysql-primary              ClusterIP   10.103.149.119   <none>        3306/TCP   17m
service/mysql-primary-headless     ClusterIP   None             <none>        3306/TCP   17m
service/mysql-secondary            ClusterIP   10.108.47.42     <none>        3306/TCP   17m
service/mysql-secondary-headless   ClusterIP   None             <none>        3306/TCP   17m

NAME                               READY   AGE
statefulset.apps/mysql-primary     1/1     17m
statefulset.apps/mysql-secondary   1/1     17m

#檢視剛剛部署的例項
[root@master01 wordpress]#helm list -n wordpress
NAME     NAMESPACE    REVISION    UPDATED                                    STATUS      CHART           APP VERSION
mysql    wordpress    1           2024-12-03 04:36:34.261136708 +0000 UTC    deployed    mysql-12.1.0    8.4.3 
#修改剛剛部署的例項引數(把要修改的引數換好直接提交)
helm upgrade mysql --set ...
#解除安裝
helm uninstall mysql
#檢視狀態(返回的就是剛剛部署返回的資訊)
[root@master01 ~]#helm status mysql -n wordpress

使用helm部署wordpress示例

#artifacthub搜wordpress專案,可檢視引數
https://artifacthub.io/packages/helm/bitnami/wordpress
#裡面會內建mariadb解決依賴關係,但也是配置自己搭的mysql資料庫,這裡用上面的mysql主從架構

#基於dockerhub上的oci倉庫部署
#使用已經部署完成的現有MySQL資料庫,支援Ingress,且外部的MySQL是主從複製架構。注意修改如下命令中各引數值,以正確適配到自有環境。
helm install wordpress \
       --set mariadb.enabled=false \ #內建mariadb設為false
       --set externalDatabase.host=mysql-primary.wordpress.svc.cluster.local \
       --set externalDatabase.user=wpuser \
       --set externalDatabase.password='magedu.com' \
       --set externalDatabase.database=wpdb \
       --set externalDatabase.port=3306 \
       --set persistence.storageClass=nfs-csi \
       --set ingress.enabled=true \ #自動建立ingress
       --set ingress.ingressClassName=nginx \
       --set ingress.hostname=wordpress.magedu.com \
       --set ingress.pathType=Prefix \
       --set wordpressUsername=admin \ #管理員使用者
       --set wordpressPassword='magedu.com' \
       oci://registry-1.docker.io/bitnamicharts/wordpress \
       -n wordpress --create-namespace
#返回
   echo "WordPress URL: http://wordpress.magedu.com/"
3. Login with the following credentials below to see your blog:
  echo Username: admin
  echo Password: $(kubectl get secret --namespace wordpress wordpress -o jsonpath="{.data.wordpress-password}" | base64 -d)

#檢視release
[root@master01 wordpress]#helm list -n wordpress
NAME         NAMESPACE    REVISION    UPDATED                                    STATUS         CHART               APP VERSION
mysql        wordpress    1           2024-12-03 04:36:34.261136708 +0000 UTC    deployed       mysql-12.1.0        8.4.3      
wordpress    wordpress    1           2024-12-03 08:21:00.881921331 +0000 UTC    deployed       wordpress-24.0.8    6.7.1
#檢視pvc
[root@master01 wordpress]#kubectl get pvc -n wordpress
NAME                     STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   VOLUMEATTRIBUTESCLASS   AGE
data-mysql-primary-0     Bound    pvc-294397e1-666d-4c94-9f8d-93f008f08d4f   8Gi        RWO            nfs-csi        <unset>                 3h49m
data-mysql-secondary-0   Bound    pvc-10cc3453-0fc9-4271-9c0b-7d3e77d6220b   8Gi        RWO            nfs-csi        <unset>                 3h49m
wordpress                Bound    pvc-2071ac90-0a6b-4dc5-aacb-e5d17438c097   10Gi       RWO            nfs-csi        <unset>                 4m43s
#檢視ingress,外部IP地址10.0.0.52
[root@master01 wordpress]#kubectl get ingress -n wordpress
NAME        CLASS   HOSTS                  ADDRESS     PORTS   AGE
wordpress   nginx   wordpress.magedu.com   10.0.0.52   80      8m52s
#等待wordpress的pod啟動完成
[root@master01 ~]#kubectl get pods -n wordpress

#在windows上host配置wordpress.magedu.com,測試
#登入 admin/magedu.com
http://wordpress.magedu.com/wp-login.php

helm部署harbor示例

#artifacthub上官方的用的最多
https://artifacthub.io/packages/helm/harbor/harbor

#需要先新增倉庫,名稱為harbor
helm repo add harbor https://helm.goharbor.io
#檢視本地倉庫repo
[root@master01 ingress-canary-demo]#helm repo list
NAME      URL                     
harbor    https://helm.goharbor.io
#本地倉庫repo搜尋harbor,左側倉庫名,右側chart名
[root@master01 ingress-canary-demo]#helm search repo harbor
NAME             CHART VERSION    APP VERSION    DESCRIPTION                                       
harbor/harbor    1.16.0           2.12.0         An open source trusted cloud native registry th...

#檢視chart值檔案
[root@master01 ingress-canary-demo]#helm show values harbor/harbor

#準備部署harbor所用引數值檔案
[root@master01 harbor]#vim harbor-values.yaml
expose:
  type: ingress
  tls: #使用內建tls
    enabled: true  
    certSource: auto #自動生成自簽證書
  ingress:
    hosts:
      core: registry.magedu.com
    className: "nginx"
    annotations:
      ingress.kubernetes.io/ssl-redirect: "true"
      ingress.kubernetes.io/proxy-body-size: "0"
      nginx.ingress.kubernetes.io/ssl-redirect: "true"
      nginx.ingress.kubernetes.io/proxy-body-size: "0"

ipFamily:
  ipv4: #只支援ipv4
    enabled: true
  ipv6:
    enabled: false
#外部訪問必須透過該地址(這裡指定主機名,ip地址訪問不進來的)
externalURL: https://registry.magedu.com

# 持久化儲存配置部分
persistence:
  enabled: true 
  resourcePolicy: "keep" #刪除例項,對應儲存還是保留下來
  persistentVolumeClaim:        # 定義Harbor各個元件的PVC持久卷
    registry:          # registry元件(持久卷)
      storageClass: "nfs-csi"           # 前面建立的StorageClass,其它元件同樣配置
      accessMode: ReadWriteMany          # 卷的訪問模式,需要修改為ReadWriteMany
      size: 5Gi
    chartmuseum:     # chartmuseum元件(持久卷) 儲存chart的倉庫
      storageClass: "nfs-csi"
      accessMode: ReadWriteMany
      size: 5Gi
    jobservice:
      jobLog:
        storageClass: "nfs-csi"
        accessMode: ReadWriteOnce
        size: 1Gi
      #scanDataExports:
      #  storageClass: "nfs-csi"
      #  accessMode: ReadWriteOnce
      #  size: 1Gi
    database:        # PostgreSQl資料庫元件
      storageClass: "nfs-csi"
      accessMode: ReadWriteMany
      size: 2Gi
    redis:    # Redis快取元件
      storageClass: "nfs-csi"
      accessMode: ReadWriteMany
      size: 2Gi
    trivy:         # Trity漏洞掃描
      storageClass: "nfs-csi"
      accessMode: ReadWriteMany
      size: 5Gi

harborAdminPassword: "magedu.com"

#部署harbor (harbor倉庫下/harbor的chart)
]#helm install harbor -f harbor-values.yaml harbor/harbor -n harbor --create-namespace
#檢視harbor release
[root@master01 harbor]#helm list -n harbor
NAME      NAMESPACE    REVISION    UPDATED                                    STATUS      CHART            APP VERSION
harbor    harbor       1           2024-12-03 10:01:23.556792261 +0000 UTC    deployed    harbor-1.16.0    2.12.0     
[root@master01 harbor]#kubectl get ingress -n harbor
NAME             CLASS   HOSTS                 ADDRESS     PORTS     AGE
harbor-ingress   nginx   registry.magedu.com   10.0.0.52   80, 443   3m49s
#等待pod啟動完成
[root@master01 harbor]#kubectl get pods -n harbor

#windows下hosts中新增
10.0.0.52 registry.magedu.com
#瀏覽器輸入測試(關掉vpn就可以了,可能需要修改環境變數no_proxy)   admin/magedu.com
https://registry.magedu.com

#顯示出當時部署時的自定義值檔案內容
[root@master01 harbor]#helm get values harbor -n harbor
#顯示所有渲染出的資源配置檔案
[root@master01 harbor]#helm get manifest harbor -n harbor
##顯示出當時部署時的自定義值檔案內容,命令列引數也可以
[root@master01 harbor]#helm get values mysql -n wordpress
USER-SUPPLIED VALUES:
architecture: replication
auth:
  database: wpdb
  password: magedu.com
  replicationPassword: replpass
  rootPassword: MageEdu
  username: wpuser
global:
  storageClass: nfs-csi
secondary:
  replicaCount: 1

#顯示建立完成後的提示資訊,helm get notes也可以顯示
[root@master01 harbor]#helm get notes mysql -n wordpress

獲取並使用Helm

部署Helm
  ◼ 使用作業系統包管理器安裝,支援Homebrew、Chocolatey、Scoop、GoFish和Snap等包管理器
  ◼ 直接下載適合目標平臺的二進位制Helm程式包,展開並放置於合適的位置即可使用
    ◆https://github.com/helm/helm/releases
常用的helm命令
  ◼ Repostory管理 #倉庫裡的後設資料比較舊了,透過update更新後設資料,可以下更新的資料(和apt update一樣)
    ◆repo命令,支援repository的add、list、remove、update和index等子命令
  ◼ Chart管理
    ◆create、 package、pull、 push、dependency、search、show和verify等操作
  ◼ Release管理
    ◆install、upgrade、get、list、history、status、rollback和uninstall等操作

相關文章