主頁 > 軟體設計 > 用Helm3構建多層微服務

用Helm3構建多層微服務

2020-09-14 13:17:33 軟體設計

Helm是一款非常流行的k8s包管理工具,以前就一直想用它,但看到它產生的檔案比k8s要復雜許多,就一直猶豫,不知道它的好處能不能抵消掉它的復雜度,但如果不用,而是用Kubectl來進行調式真的很麻煩,正好最近Helm3正式版出來了,比原來的Helm2簡單了不少,就決定還是試用一下,結果證明確實很復雜,它的好處和壞處大致相當,有了它確實能大大簡化對k8s的調式,但也需要花費比較多的時間來學習,而且產生的組態檔要復雜許多,但是事實是現在沒有什么很方便的幫助調式k8s的工具,在沒有更好的方案之前,我還是建議用它,只是前期需要花些功夫學習和掌握它,

Helm3和Helm2的語法差不太多,只是使用起來更方便,不用安裝Tiller,一個比較明顯的變化是不再需要“requirements.yaml”, 依賴關系是直接在“chart.yaml”中定義,有關Helm3和Helm2的區別,詳情請參見CHANGES SINCE HELM 2,

網上有不少講述Helm的文章,但大部分都是主要講解安裝和舉一個簡單的例子,但Helm使用起來還是比較復雜的,一定要有一個復雜的例子才能把它的功能講清楚,里面有不少設計方面的問題需要思考,我剛開始接觸的時候就覺得頭緒繁多,不知從哪下手,本文就通過一個相對復雜的例子來講解用Helm3來設計組態檔的思路,使上手更容易,

這里不講Helm3的安裝,它比較很容易,也不講解Helm的基本語法,你可以自己去看其他檔案,即使你不懂Helm,應該也能猜出七八成,剩下的就要讀檔案了(Charts),Helm的語法還是比較復雜的,要想搞懂可能要花一兩天時間,

本文假設你對helm有一個大概的了解,想要構建一個復雜的微服務,但有不知如何下手;或者你想了解一下構建Helm的最佳實踐,那就請你繼續讀下去,

Helm檔案結構

chart里一個很重要的概念就是模板(template),它就是Go語言模板,它是里面加入了編程邏輯的k8s檔案,這些模板檔案在使用時都要先進行模板決議,把其中的程式邏輯轉化成對應的編碼,最終生成k8s組態檔,

file

以上就是Helm自動生成的chart目錄結構,在Helm里每個專案叫一個chart,它由下面幾個組成部分:

  • "Chart.yaml":存有這個chart的基本資訊,
  • "values.yaml":定義模板中要用到的常量,
  • “template”目錄:里面存有全部的模板檔案,其中最重要的是“deployment.yaml”和“service.yaml”,分別是部署和服務檔案. "helpers.tpl"用來定義變數,"ingress.yaml"和"serviceaccount.yaml"分別是對外介面和服務賬戶,這里暫時沒用, “NOTES.txt”是注釋檔案,
  • “charts”目錄: 存有這個chart依賴的所有子chart,

Helm的基本元素

Helm有四個基本元素,值,常量,變數和共享常量(這個后面會講)

值(literal)

Helm在k8s的基礎之上增加了模板功能,使k8s的組態檔更加靈活,里面的主要概念就是模板(Template),也就是在k8s的組態檔里增加了常量和變數以及編程邏輯,如果你不用這些新增功能,那么就是普通的YAML檔案(k8s組態檔),里面用到的基本元素就是值,

常量

節點定位(Node Anchor):

如果你想復用重復的值,能把它定義成常量嗎?YAML有一個功能叫節點定位(Node Anchor),類似于定義一個常量,然后參考,但它有一些限制,定義的必須是一個節點,因此不如真正的常量靈活,
例如如下檔案中,用“&”定義了一個常量“&k8sdemoDatabaseService”,然后用“*k8sdemoDatabaseService”參考它,

global:
  k8sdemoDatabaseService: &k8sdemoDatabaseService k8sdemo-database-service
  mysqlHost: *k8sdemoDatabaseService

這時,“k8sdemoDatabaseService:”是YAML檔案節點的鍵名,“&k8sdemoDatabaseService”是節點定位的名字,相當于常量名,“k8sdemo-database-service”是YAML節點的鍵值,在上述代碼中,k8sdemoDatabaseService和mysqlHost的值都是“k8sdemo-database-service”,

有關節點定位(Node Anchor)的詳細內容,請參見 YAML,

常量:

由于節點定位的局限性,Helm引入了真正的常量,也就是在"values.yaml"里定義的內容,它可以定義是任何東西,不只限于節點,

在"values.yaml"里定義常量:

replicaCount: 1

在部署模板里參考:

replicas: {{ .Values.replicaCount }}

那么什么時候用常量,什么時候用值(Literal)呢?如果一個值在模板中出現多次,就要定義常量,避免重復,例如“accessModes”,既要在存盤卷里出現,又要在存盤卷申請里出現,另外如果值有可能變化(不論是隨部署環境變化,還是隨時間變化),那么就定義成常量,這樣在修改時就只用改"values.yaml",而不必修改模板檔案,例如“replicas”的值(也就是集群的個數)是可能變化的,就要定義成常量,在模板里可以參考常量的,但在"values.yaml"里不行,因為它只是普通YAML檔案,沒有模板決議功能,因此不支持常量,這里就只能用節點定位(來代替常量),

有關Helm常量的詳細內容,請參見 Use placeholders in yaml和Use YAML with variables,

變數

節點定位的功能是有限的,例如你想利用已有的節點定位,對它進行轉換,定義一個新的節點定位,這在"values.yaml"里就不行了,
例如你已有節點定位“name”,你想在這個基礎上定義一個新的節點定位“serviceName”,這個"values.yaml"就不支持了,你必須要用模板,

如下所示,這在"values.yaml"里是不支持的,

name: &name k8sdemo-backend
serviceName:*name-service

這就引出了變數的概念,但它只能在模板里才行, 換句話說,模板既支持常量,也支持變數,但如果把變數的定義邏輯放在Helm每個模板里,就顯得很亂,因此一般的做法是把這些邏輯放在一個單獨的模板檔案里,這個就是前面講到的"_helpers.tpl"檔案,當你需要對常量進行轉換,生成新的常量,你就在定義變數,這部分代碼就放在"_helpers.tpl"里,

下面就是"_helpers.tpl"中定義"k8sdemo.name"的代碼,

{{- define "k8sdemo.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
{{- end -}}

在以上這些元素中,常量(也就是在"values.yaml"中定義的)是最靈活的,能用它時盡量用它,而且因為它是定義在普通YAML檔案中("values.yaml"),應用程式可以直接訪問它,這樣可以實作應用程式和k8s之間的資料共享,但如果你需要對常量進行編程轉換,那就沒辦法了,只能定義變數,把它放在"_helpers.tpl"中,

ConfigMap和Secret

在k8s中ConfigMap和Secret是用來存盤共享配置引數和保密引數的,但在Helm中,由于有了上面講的Helm基本元素,它們完全可以代替ConfigMap的功能,因此ConfigMap就不需要了,但Secret還是需要的,因為要存盤加密資訊,下面會講解,

有關ConfigMap的設計局限性,請參見把應用程式遷移到k8s需要修改什么?

Chart設計

現在我們就用一個具體的例子來展示Helm的chart設計,這個例子是一個微服務應用程式,它共有三層: 前端,后端和資料庫,只有這樣才能讓Helm的一些設計問題付出水面,如果只有一層的話,就太簡單了,沒有參考價值,

在k8s中,每一層就是一個單獨的服務,它里面有各種組態檔,Helm的優勢是把這些不同的服務組成一個Chart來共同管理和調式,方便了許多,

file

上面就是最終的chart目錄結構圖,“chart”是總目錄,里面有三個子目錄“k8sdemo”,“k8sdemo-backend”,“k8sdemo-database”, 每一個對應一個服務,每個服務都是一個獨立的chart,能單獨調式部署,chart之間也可以有依賴關系,其中“k8sdemo”是父chart,同時也是前端服務,它的“charts”目錄里有它依賴的另外兩個服務,“k8sdemo-backend”是后端服務,“k8sdemo-database”是資料庫服務,

處理Chart的依賴關系有兩種方式:

  1. 嵌入式:就是直接把依賴的chart放在“charts”子目錄里,這樣子chart是父chart的一部分,它是一種緊耦合的關系,好處是比較簡單,但不夠靈活,
  2. 依賴匯入式:就是各個chart是并列關系,各自單獨除錯部署,互相獨立,需要合并時再把子chart匯入父chart里,它是一種松耦合的關系,好處是比較靈活,但設計更復雜, 在這種結構下,各個chart可以單獨作業也可以聯合作業,不過你需要更好的設計,

這里采用的是依賴匯入式方式,主要原因是我原來認為嵌入式需要一起除錯,復雜度太高,如果你覺得這不是問題,這也是個不錯的辦法,用依賴匯入式方式,可以單獨除錯各個chart,簡單了很多,后來發現其實采用嵌入式也可以單獨除錯子chart,只是父chart不能單獨除錯而已,

除錯順序:

當你采用依賴匯入式方式時,除錯順序關系不大,因為各個chart是各自獨立的,可以單獨除錯,舉個例子,雖然“k8sdemo-backend”需要“k8sdemo-database”才能正常運行,但當沒有資料庫服務時,你的程式也可以運行,只不過輸出的是錯誤資訊,但這并不影響你除錯chart,

我先除錯“k8sdemo”,它雖然依賴另外兩個chart,但沒有它們也能單獨作業,然后再除錯“k8sdemo-backend”和“k8sdemo-database”,最后再把它們匯入到“k8sdemo”中去再進行聯調,

調式“k8sdemo”

它的除錯是最容易的,由于它里面沒有真正的前端代碼,只要把Nginx除錯成功了就可以了,只要在生成的檔案基礎上做些修改就行了,

鍵入如下命令創建chart,其中“k8sdemo”是chart的名字,這個名字很重要,服務的名字和label都是由它產生的,

helm create k8sdemo

這之后,系統會自動創建前面講到的chart目錄結構,讓后就是對已經生成的檔案進行修改,

修改"values.yaml":
以下是"values.yaml"主要修改的地方

image:
  repository: nginx:1.17.6
  pullPolicy: Never

imagePullSecrets: []
nameOverride: "k8sdemo"
fullnameOverride: "k8sdemo"

service:
  type: NodePort
  port: 80
  nodePort: 31080

另外,由于"ingress.yaml"和"serviceaccount.yaml"暫時沒用,就把它們都設成了“false”

ingress:
  enabled: false

serviceAccount:
  # Specifies whether a service account should be created
  create: false

修改"service.yaml":

apiVersion: v1
kind: Service
metadata:
  name: {{ include "k8sdemo.fullname" . }}
  labels:
    {{- include "k8sdemo.labels" . | nindent 4 }}
spec:
  type: {{.Values.service.type}}
  ports:
    - port: {{.Values.service.port}}
      nodePort: {{.Values.service.nodePort}}
      targetPort: http
      protocol: TCP
      name: http
  selector:
    {{- include "k8sdemo.selectorLabels" . | nindent 4 }}

修改"deployment.yaml":

,,,
containers:
  - name: {{ .Chart.Name }}
    securityContext:
      {{- toYaml .Values.securityContext | nindent 12 }}
    image: {{ .Values.image.repository }}
    imagePullPolicy: {{ .Values.image.pullPolicy }}
,,,

以上都是簡單的修改,不涉及到設計問題,由于篇幅的關系,這里沒有列出全部原始碼,如果有興趣請在本文末尾找到原始碼地址,

共享常量

在進行下面的除錯之前,先要講一個重要概念, 前面介紹Helm的基本元素時講的都是在一個chart里共享值,如果要在不同chart之間共享值(例如k8s服務名,資料庫用戶名和埠),那么這些還不夠,你需要共享常量. 通常情況下子chart和父chart之間的常量是不能共享的,如果需要共享,需要有一種特殊的方法來定義常量,這就是共享常量,它必須是定義在父chart中,

共享常量

例如,你在“k8sdemo”的“values.yaml”加入下面代碼,注意節點的名字必須是子chart名(例如“k8sdemo-backend”)

k8sdemo-backend:
  replicaCount: 2
k8sdemo-database:
  replicaCount: 2

在“k8sdemo”的模板里就可以通過“{{ .Values.k8sdemo-backend.replicaCount }}” 來訪問,當Helm發現節點名是子chart名時,它會自動拷貝這個常量到子chart的“values.yaml”中,因此,在“k8sdemo-backend”中,你也可以通過“{{ .Values.replicaCount }}” 來訪問這個常量,注意這里并沒有包含子chart名(“k8sdemo-backend”),而是只有常量名,因為子chart名只是一個標識,而不是常量名的一部分,

全域常量

共享常量只能把常量共享給一個字chart,如果你需要多個子chart之間共享,就需要創建全域常量,它用“global”來標識,下面是示例,

在“k8sdemo-backend”的"values.yaml"中定義:

global:
  k8sdemoDatabaseService: &k8sdemoDatabaseService k8sdemo-database-service
  mysqlUserName: dbuser
  mysqlUserPassword: dbuser
  mysqlPort: 3306
  mysqlHost: *k8sdemoDatabaseService
  mysqlDatabase: service_config

在“k8sdemo-backend”的“deployment.yaml”中參考,

env:
  - name: MYSQL_USER_NAME
    value: {{ .Values.global.mysqlUserName }}
  - name: MYSQL_USER_PASSWORD
    value: {{ .Values.global.mysqlUserPassword }}
  - name: MYSQL_HOST
    value: {{ .Values.global.mysqlHost }}
  - name: MYSQL_PORT
    value: "{{ .Values.global.mysqlPort }}"
  - name: MYSQL_DATABASE
    value: {{ .Values.global.mysqlDatabase }}

在“k8sdemo-database”的"values.yaml"中定義:

global:
  k8sdemoDatabaseService: k8sdemo-database-service
  mysqlUserName: dbuser
  mysqlUserPassword: dbuser
  mysqlRootPassword: root
  mysqlDatabase: service_config

在“k8sdemo-database”的“deployment.yaml”中參考,

env:
  - name: MYSQL_ROOT_PASSWORD
    value: {{ .Values.global.mysqlRootPassword }}
  - name: MYSQL_USER_NAME
    value: {{ .Values.global.mysqlUserName }}
  - name: MYSQL_USER_PASSWORD
    value: {{ .Values.global.mysqlUserPassword }}
  - name: MYSQL_DATABASE
    value: {{ .Values.global.mysqlDatabase }}

當把“k8sdemo-backend”和“k8sdemo-database”匯入"k8sdemo"后進行聯調時, 就要把上面提到的全域常量寫入"k8sdemo"的"values.yaml"檔案中,這樣就能讓各個子chart共享這些常量,如下所示:

global:
  k8sdemoBackendService: k8sdemo-backend-service
  k8sdemoDatabaseService: &k8sdemoDatabaseService k8sdemo-database-service
  mysqlUserName: dbuser
  mysqlUserPassword: dbuser
  mysqlRootPassword: root
  mysqlPort: 3306
  mysqlHost: *k8sdemoDatabaseService
  mysqlDatabase: service_config

如果父chart和子chart有重復的全域常量,這時父chart("k8sdemo")的全域常量值就會覆寫子chart的全域常量,

它的使用原則就是如果只是子chart獨有的常量就在子chart的"values.yaml"中定義,如果是共享的常量就在父chart中定義,但如果采用的是依賴匯入方式,由于子chart也要單獨除錯,這時你在子chart里也要定義這些全域常量,這樣在進行chart總除錯時,就會使用父chart的中的值,

詳情請參見 Subcharts and Global Values,

除錯“k8sdemo-backend”

“k8sdemo-backend”的chart需要取(與“k8ssdemo”)不同的名字,
創建:

helm create k8sdemo-backend

file

上面就是“k8sdemo-backend”的目錄圖,由于它需要建持久卷,因此這里增加了兩個檔案“persistentvolume.yaml”和“persistentvolumeclaim.yaml” ( 不是自動生成的),

值得一提的是k8s物件的命名,一般情況下,如果不需要對其進行參考,用chart的全名就行了,例如部署的名稱,如下所示,

name: {{ include "k8sdemo.fullname" . }}

如果是服務名(Service Name),它需要在應用程式和k8s之間共享,也需要在父chart和子chart之間共享,這時最好單獨定義一個全域共享常量,

在“values.yaml”中定義:

global:
  k8sdemoBackendService: k8sdemo-backend-service

在“service.yaml”中參考:

name: {{.Values.global.k8sdemoBackendService}}

除錯“k8sdemo-database”

它的除錯方式與“k8sdemo-backend”大同小異,就不詳細講解了,

聯合除錯:

上面各個chart都單獨除錯成功之后,就要把它們合在一起進行聯合除錯,
在“k8sdemo”(父chart)中加入依賴關系(Chart.yaml),

dependencies:
  - name: k8sdemo-backend
    repository: file://../k8sdemo-backend
    version: 0.1.0
  - name: k8sdemo-database
    repository: file://../k8sdemo-database
    version: 0.1.0

這里為了簡單起見,沒有用到chart庫(Chart Repository),使用了本地目錄,這里的“file://”是針對chart的根的相對路徑,“file://..”就是“k8sdemo”的上級目錄,

詳情請參見How to refer to a helm chart in the same repository,

修改全域常量("values.yaml"):

global:
  k8sdemoBackendService: k8sdemo-backend-service
  k8sdemoDatabaseService: &k8sdemoDatabaseService k8sdemo-database-service
  mysqlUserName: dbuser
  mysqlUserPassword: dbuser
  mysqlRootPassword: root
  mysqlPort: 3306
  mysqlHost: *k8sdemoDatabaseService
  mysqlDatabase: service_config

只有需要在chart之間共享的常量才需要在父chart里的"values.yaml"定義,其余的在各自子chart里的"values.yaml"定義就可以了,

鍵入如下命令“helm dependency update k8sdemo”,更新依賴關系

~ # vagrant@ubuntu-xenial:~/jfeng45/k8sdemo/script/kubernetes/chart$ helm dependency update k8sdemo
Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "stable" chart repository
Update Complete. ?Happy Helming!?
Saving 2 charts
Deleting outdated charts

完成之后,生成的圖如下所示,這時在“charts”目錄下就匯入了新的依賴關系“k8sdemo-backend”和“k8sdemo-database”的chart,

file

有一點需要注意的是,單獨除錯和聯合除錯時,生成的k8s組態檔大部分都是一樣的,但有一個地方不同

下面是聯合除錯時“k8sdemo-database”的部署檔案,最后一行“app.kubernetes.io/instance: ”的值是“k8sdemo”,

# Source: k8sdemo/charts/k8sdemo-database/templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: k8sdemo-database
  labels:
    helm.sh/chart: k8sdemo-database-0.1.0
    app.kubernetes.io/name: k8sdemo-database
    app.kubernetes.io/instance: k8sdemo
,,,

下面是單獨除錯時“k8sdemo-database”的部署檔案,最后一行“app.kubernetes.io/instance: ”的值是“”k8sdemo-database”,

# Source: k8sdemo/charts/k8sdemo-database/templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: k8sdemo-database
  labels:
    helm.sh/chart: k8sdemo-database-0.1.0
    app.kubernetes.io/name: k8sdemo-database
    app.kubernetes.io/instance: k8sdemo-database
,,,

因為“instance”的名字是“{{ .Release.Name }}”,而單獨除錯和聯合除錯時給的“release”名字不同,而其他的值都是由組態檔決定的,因此不會有意外,

安裝k8sdemo:

vagrant@ubuntu-xenial:~/jfeng45/k8sdemo/script/kubernetes/chart$ helm upgrade k8sdemo ./k8sdemo
Release "k8sdemo" has been upgraded. Happy Helming!
NAME: k8sdemo
LAST DEPLOYED: Fri Nov 29 01:28:55 2019
NAMESPACE: default
STATUS: deployed
REVISION: 2
NOTES:
1. Get the application URL by running these commands:
  export NODE_PORT=$(kubectl get --namespace default -o jsonpath="{.spec.ports[0].nodePort}" services k8sdemo)
  export NODE_IP=$(kubectl get nodes --namespace default -o jsonpath="{.items[0].status.addresses[0].address}")
  echo http://$NODE_IP:$NODE_PORT

獲取Pod名稱:

vagrant@ubuntu-xenial:~/jfeng45/k8sdemo/script/kubernetes/chart$ kubectl get pod
NAME                                          READY   STATUS    RESTARTS   AGE
k8sdemo-74cb7b997c-pgcj4                      1/1     Running   0          33s
k8sdemo-backend-5cd9d79856-dqlmz              1/1     Running   0          33s
k8sdemo-database-85855485c6-jtksb             1/1     Running   0          33s
k8sdemo-jenkins-deployment-675dd574cb-r57sb   1/1     Running   3          23d

運行程式進行測設:

vagrant@ubuntu-xenial:~/jfeng45/k8sdemo/script/kubernetes/chart$ kubectl exec -ti k8sdemo-backend-5cd9d79856-dqlmz -- /bin/sh
~ # ./main.exe
time="2019-11-27T07:03:03Z" level=debug msg="connect to database "
time="2019-11-27T07:03:03Z" level=debug msg="dataSourceName:dbuser:dbuser@tcp(k8sdemo-database-service:3306)/service_config?charset=utf8"
time="2019-11-27T07:03:03Z" level=debug msg="FindAll()"
time="2019-11-27T07:03:03Z" level=debug msg="created=2019-10-21"
time="2019-11-27T07:03:03Z" level=debug msg="find user:{1 Tony IT 2019-10-21}"
time="2019-11-27T07:03:03Z" level=debug msg="find user list:[{1 Tony IT 2019-10-21}]"
time="2019-11-27T07:03:03Z" level=debug msg="user lst:[{1 Tony IT 2019-10-21}]"
~ #

其他問題:

由于篇幅有限,本文不可能把所有的問題都講清楚,還有兩個比較重要的問題,這里簡單的提一下,

1.Secret:
本文用的都是明碼,如果需要加密的話有兩種方式,一種是 helm-secrets,另一種是Vault,請閱讀相關檔案,

2.為不同環境設定不同的常量:
本文只創建了針對一種環境的檔案 ,如果你需要針對不同環境(例如DEV,QA,PROD)配置不同的引數的話,你可以在“k8sdemo”的chart里給不同的環境創建不同的"values.yaml",例如“values-dev.yaml”給DEV環境,但在子chart里,就不能這樣做,因為系統要求"values.yaml",這時,你可以在父chart的“values-dev.yaml”里為不同的子chart創建常量,這樣這些常量就能覆寫子chart里定義的常量,

在“values-dev.yaml”加入下面代碼,

k8sdemo-backend:
    replicaCount: 2
k8sdemo-database:
    replicaCount: 2

鍵入如下命令試運行:

vagrant@ubuntu-xenial:~$ cd /home/vagrant/jfeng45/k8sdemo/script/kubernetes/chart
vagrant@ubuntu-xenial:~/jfeng45/k8sdemo/script/kubernetes/chart$ helm install --dry-run --values ./k8sdemo/values-dev.yaml --debug k8sdemo ./k8sdemo

查看結果,子chart中的相應引數已被覆寫,

詳情請參閱How to set environment related values.yaml in Helm subcharts?

常見錯誤:

在除錯程序中還是遇到了不少問題,但大多數都是與語法有關的問題,因為Helm和k8s都用的是YAML檔案,而它對檔案格式有著嚴格的要求,如果不滿足要求就會報錯,幸好它報錯時包含了錯誤代碼行號,這樣查找起來比較容易,

  1. Pod的狀態是CrashLoopBackOff

它的癥狀是在用“helm install --dry-run --debug”除錯時沒有問題,但正式運行時出了問題,用下面命令檢查,Pod的狀態是“CrashLoopBackOff”,

vagrant@ubuntu-xenial:~$ kubectl get pod
NAME                                           READY   STATUS             RESTARTS   AGE
k8sdemo-74cb7b997c-gn5v2                       1/1     Running            1          47h
k8sdemo-backend-6cdbb96964-tb2xd               0/1     CrashLoopBackOff   129        9h
k8sdemo-database-deployment-578fc88c88-mm6x8   1/1     Running            12         37d
k8sdemo-jenkins-deployment-675dd574cb-r57sb    1/1     Running            3          19d

這個問題我以前除錯k8s時也碰到過,主要是與Docker鏡像有關,但這次明明鏡像是 好的,試了很多組合,最后終于發現是自動生成的代碼出了問題,
在“deployment.yaml”里有下面代碼,這是Helm自動生成用來測驗部署的,

livenessProbe:
  httpGet:
    path: /
    port: http
readinessProbe:
  httpGet:
    path: /
    port: http

把它去掉之后就沒有問題了,而且它只在特定的chart(“k8sedemo-backend”)里會出錯,在“k8sdemo”里就沒有問題,我現在也不是特別清楚問題在哪,只是把它暫時洗掉掉了,

  1. 持久卷未能系結到持久卷申請

它的癥狀是宿主機的持久卷未能系結到持久卷申請,導致持久卷申請又另外創建了一個持久卷,你用“kubectl get pv”就能看到新創建的持久卷,但實際上它是不必要的,只要把持久卷申請系結到已有的PV上就行了,這個錯誤并不是每次都發生,而是隨機的,大部分時間系結正確,少數時候系結錯誤,我開始想是不是因為執行k8s檔案的順序問題,但k8s檔案是按照檔案類別(kind)來執行的,按理來說順序應該是正確的,再有一個可能就是時間延遲,因為創建持久卷需要時間,而如果持久卷申請沒有檢測到這個持久卷,那么它就會另外創建一個,如果真是這樣的話,就要在創建時設定一個延遲,但它暫時來講對我影響不大,因此就偷了一下懶,以后有時間再來除錯,

原始碼庫

完整原始碼的github鏈接:
k8sdemo

索引:

  1. CHANGES SINCE HELM 2
  2. Charts
  3. YAML
  4. Use placeholders in yaml
  5. Use YAML with variables
  6. 把應用程式遷移到k8s需要修改什么?
  7. Subcharts and Global Values
  8. How to refer to a helm chart in the same repository
  9. helm-secrets
  10. Vault
  11. How to set environment related values.yaml in Helm subcharts?

轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/35264.html

標籤:架構設計

上一篇:分布式事務之解決方案(可靠訊息最終一致性)

下一篇:圖解 Spring:HTTP 請求的處理流程與機制【1】

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 面試突擊第一季,第二季,第三季

    第一季必考 https://www.bilibili.com/video/BV1FE411y79Y?from=search&seid=15921726601957489746 第二季分布式 https://www.bilibili.com/video/BV13f4y127ee/?spm_id_fro ......

    uj5u.com 2020-09-10 05:35:24 more
  • 第三單元作業總結

    1.前言 這應該是本學期最后一次寫作業總結了吧。總體來說,對作業的節奏也差不多掌握了,作業做起來的效率也更高了。雖然和之前的作業一樣,作業中都要用到新的知識,但是相比之前,更加懂得了如何利用工具以及資料。雖然之間卡過殼,但總體而言,這幾次作業還算完成的比較好。 2.作業程序總結 相比前兩個單元,此單 ......

    uj5u.com 2020-09-10 05:35:41 more
  • 北航OO(2020)第四單元博客作業暨課程總結博客

    北航OO(2020)第四單元博客作業暨課程總結博客 本單元作業的架構設計 在本單元中,由于UML圖具有比較清晰的樹形結構,因此我對其中需要進行查詢操作的元素進行了包裝,在樹的父節點中存盤所有孩子的參考。考慮到性能問題,我采用了快取機制,一次查詢后盡可能快取已經遍歷過的資訊,以減少遍歷次數。 本單元我 ......

    uj5u.com 2020-09-10 05:35:48 more
  • BUAA_OO_第四單元

    一、UML決議器設計 ? 先看下題目:第四單元實作一個基于JDK 8帶有效性檢查的UML(Unified Modeling Language)類圖,順序圖,狀態圖分析器 MyUmlInteraction,實際上我們要建立一個有向圖模型,UML中的物件(元素)可能與同級元素連接,也可與低級元素相連形成 ......

    uj5u.com 2020-09-10 05:35:54 more
  • 6.1邏輯運算子

    邏輯運算子 1. && 短路與 運算式1 && 運算式2 01.運算式1為true并且運算式2也為true 整體回傳為true 02.運算式1為false,將不會執行運算式2 整體回傳為false 03.只要有一個運算式為false 整體回傳為false 2. || 短路或 運算式1 || 運算式2 ......

    uj5u.com 2020-09-10 05:35:56 more
  • BUAAOO 第四單元 & 課程總結

    1. 第四單元:StarUml檔案決議 本單元采用了圖模型決議UML。 UML檔案可以抽象為圖、子圖、邊的邏輯結構。 在實作中,圖的節點包括類、介面、屬性,子圖包括狀態圖、順序圖等。 采用了三次遍歷UML元素的方法建圖,第一遍遍歷建點,第二、三次遍歷設定屬性、連邊,實作圖物件的初始化。這里借鑒了一些 ......

    uj5u.com 2020-09-10 05:36:06 more
  • 談談我對C# 多型的理解

    面向物件三要素:封裝、繼承、多型。 封裝和繼承,這兩個比較好理解,但要理解多型的話,可就稍微有點難度了。今天,我們就來講講多型的理解。 我們應該經常會看到面試題目:請談談對多型的理解。 其實呢,多型非常簡單,就一句話:呼叫同一種方法產生了不同的結果。 具體實作方式有三種。 一、多載 多載很簡單。 p ......

    uj5u.com 2020-09-10 05:36:09 more
  • Python 資料驅動工具:DDT

    背景 python 的unittest 沒有自帶資料驅動功能。 所以如果使用unittest,同時又想使用資料驅動,那么就可以使用DDT來完成。 DDT是 “Data-Driven Tests”的縮寫。 資料:http://ddt.readthedocs.io/en/latest/ 使用方法 dd. ......

    uj5u.com 2020-09-10 05:36:13 more
  • Python里面的xlrd模塊詳解

    那我就一下面積個問題對xlrd模塊進行學習一下: 1.什么是xlrd模塊? 2.為什么使用xlrd模塊? 3.怎樣使用xlrd模塊? 1.什么是xlrd模塊? ?python操作excel主要用到xlrd和xlwt這兩個庫,即xlrd是讀excel,xlwt是寫excel的庫。 今天就先來說一下xl ......

    uj5u.com 2020-09-10 05:36:28 more
  • 當我們創建HashMap時,底層到底做了什么?

    jdk1.7中的底層實作程序(底層基于陣列+鏈表) 在我們new HashMap()時,底層創建了默認長度為16的一維陣列Entry[ ] table。當我們呼叫map.put(key1,value1)方法向HashMap里添加資料的時候: 首先,呼叫key1所在類的hashCode()計算key1 ......

    uj5u.com 2020-09-10 05:36:38 more
最新发布
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:20:47 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:20:25 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:20:17 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:20:10 more
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:19:44 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:19:07 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:18:57 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:18:49 more
  • 05單件模式

    #經典的單件模式 public class Singleton { private static Singleton uniqueInstance; //一個靜態變數持有Singleton類的唯一實體。 // 其他有用的實體變數寫在這里 //構造器宣告為私有,只有Singleton可以實體化這個類! ......

    uj5u.com 2023-04-19 08:42:51 more
  • 【架構與設計】常見微服務分層架構的區別和落地實踐

    軟體工程的方方面面都遵循一個最基本的道理:沒有銀彈,架構分層模型更是如此,每一種都有各自優缺點,所以請根據不同的業務場景,并遵循簡單、可演進這兩個重要的架構原則選擇合適的架構分層模型即可。 ......

    uj5u.com 2023-04-19 08:42:41 more