<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                ## 1. 簡介 Helm 圖表是[在 Kubernetes 中構建高效集群的最佳實踐之一](https://phoenixnap.com/kb/kubernetes-best-practices)。它是一種使用 Kubernetes 資源集合的打包形式。Helm 圖表使用這些資源來定義應用程序。 Helm 圖表使用模板方法來部署應用程序。模板為項目提供結構,適用于任何類型的應用程序。 ![在這里插入圖片描述](https://img-blog.csdnimg.cn/236c924c74944ce0ae649ce954f9fa77.png) ## 2. 條件 - 安裝并配置了 Minikube 集群(請按照我們的指南[如何在 Ubuntu 上安裝 Minikube](https://ghostwritten.blog.csdn.net/article/details/113527867)和[如何在 CentOS 上安裝 Minikube](https://ghostwritten.blog.csdn.net/article/details/123796854) - 你需要懂得[Helm 安裝](https://phoenixnap.com/kb/install-helm)和配置; - 你需要掌握基本[helm語法編寫技巧](https://helm.sh/docs/howto/charts_tips_and_tricks/) ## 3. 應用 以 Ghost 博客應用為例來演示如何開發一個完整的 Helm Chart 包,Ghost 是基于 Node.js 的開源博客平臺。在開發 Helm Chart 包之前最需要做的的就是要知道應用應該如何使用、如何部署,不然是不可能編寫出對應的 Chart 包的。 啟動 Ghost 最簡單的方式是直接使用鏡像啟動: ```bash docker run -d --name my-ghost -p 2368:2368 ghost ``` ![在這里插入圖片描述](https://img-blog.csdnimg.cn/996506d986324cf68022e79307afe53f.png) 后我們就可以通過 `http://localhost:2368` 訪問 Ghost 博客了。 ```bash docker rm -f my-ghost ``` 如果我們想要在 Kubernetes 集群中部署兩個副本的 Ghost,可以直接應用下面的資源清單文件即可: ```bash # ghost/deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: ghost spec: selector: matchLabels: app: ghost-app replicas: 2 template: metadata: labels: app: ghost-app spec: containers: - name: ghost-app image: ghost ports: - containerPort: 2368 --- # ghost/service.yaml apiVersion: v1 kind: Service metadata: name: ghost spec: type: NodePort selector: app: ghost-app ports: - protocol: TCP port: 80 targetPort: 2368 ``` 直接通過 kubectl 應用上面的資源對象即可: ```bash $ kubectl apply -f ghost/ service/ghost created deployment.apps/ghost created $ kubectl get pod -l app=ghost-app NAME READY STATUS RESTARTS AGE ghost-ddb558557-7szrc 1/1 Running 0 2m13s ghost-ddb558557-brn9p 1/1 Running 0 2m13s $ kubectl get svc ghost NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE ghost NodePort 10.97.232.158 <none> 80:30152/TCP 2m44s ``` 通過 `http://<nodeip>:31950` 訪問到 `Ghost` : ![在這里插入圖片描述](https://img-blog.csdnimg.cn/8c06ef1764c543369de6876780be5c5b.png) 清理 deployment ```bash $ delete -f ghost/ deployment.apps "ghost" deleted service "ghost" deleted ``` 看上去要部署 Ghost 是非常簡單的,但是如果我們需要針對不同的環境進行不同的設置呢?比如我們想將它部署到不同環境(staging、prod)中去,是不是我們需要一遍又一遍地復制我們的 Kubernetes 資源清單文件,這還只是一個場景,還有很多場景可能需要我們去部署應用,這種方式維護起來是非常困難的,這個時候就可以理由 Helm 來解放我們了。 - [官方安裝 helm](https://helm.sh/docs/helm/helm_install/) - [helm v3.8.0 命令入門指南](https://blog.csdn.net/xixihahalelehehe/article/details/122866004?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522164846338516780271926382%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=164846338516780271926382&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~blog~first_rank_ecpm_v1~rank_v31_ecpm-2-122866004.nonecase&utm_term=helm&spm=1018.2226.3001.4450) ## 4. 基礎模板 現在我們開始創建一個新的 Helm Chart 包。直接使用 `helm create` 命令即可: ```bash $ helm create my-ghost Creating my-ghost ? tree my-ghost my-ghost ├── Chart.yaml ├── charts ├── templates │ ├── NOTES.txt │ ├── _helpers.tpl │ ├── deployment.yaml │ ├── hpa.yaml │ ├── ingress.yaml │ ├── service.yaml │ ├── serviceaccount.yaml │ └── tests │ └── test-connection.yaml └── values.yaml 3 directories, 10 files ``` 該命令會創建一個默認 `Helm Chart` 包的腳手架,[helm charts 細節說明請參閱該片文章](https://ghostwritten.blog.csdn.net/article/details/123400829),可以刪掉下面的這些使用不到的文件: ```bash rm -f my-ghost/templates/tests/test-connection.yaml rm -f my-ghost/templates/serviceaccount.yaml rm -f my-ghost/templates/ingress.yaml rm -f my-ghost/templates/hpa.yaml rm -f my-ghost/templates/NOTES.txt ``` 然后修改 `templates/deployment.yaml` 模板文件: ```yaml # templates/deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: ghost spec: selector: matchLabels: app: ghost-app replicas: {{ .Values.replicaCount }} template: metadata: labels: app: ghost-app spec: containers: - name: ghost-app image: {{ .Values.image }} ports: - containerPort: 2368 env: - name: NODE_ENV value: {{ .Values.node_env | default "production" }} {{- if .Values.url }} - name: url value: http://{{ .Values.url }} {{- end }} ``` 這和我們前面的資源清單文件非常類似,只是將 `replicas` 的值使用 `{{ .Values.replicaCount }}` 模板來進行替換了,表示會用 `replicaCount` 這個 `Values` 值進行渲染,然后還可以通過設置環境變量來配置 Ghost,同樣修改 `templates/service.yaml` 模板文件的內容: ```yaml # templates/service.yaml apiVersion: v1 kind: Service metadata: name: ghost spec: selector: app: ghost-app type: {{ .Values.service.type }} ports: - protocol: TCP targetPort: 2368 port: {{ .Values.service.port }} {{- if (and (or (eq .Values.service.type "NodePort") (eq .Values.service.type "LoadBalancer")) (not (empty .Values.service.nodePort))) }} nodePort: {{ .Values.service.nodePort }} {{- else if eq .Values.service.type "ClusterIP" }} nodePort: null {{- end }} ``` 同樣為了能夠兼容多個場景,這里我們允許用戶來定制 `Service` 的 `type`,如果是 `NodePort` 類型則還可以配置 `nodePort` 的值,不過需要注意這里的判斷,因為有可能即使配置為 `NodePort` 類型,用戶也可能不會主動提供 `nodePort`,所以這里我們在模板中做了一個條件判斷: ```yaml {{- if (and (or (eq .Values.service.type "NodePort") (eq .Values.service.type "LoadBalancer")) (not (empty .Values.service.nodePort))) }} ``` 需要 `service.type` 為 `NodePort` 或者 `LoadBalancer` 并且 `service.nodePort` 不為空的情況下才會渲染 `nodePort`。 然后最重要的就是要在 `values.yaml` 文件中提供默認的 `Values` 值,如下所示是我們提供的默認的 `Values` 值: ```yaml # values.yaml replicaCount: 1 image: ghost node_env: production url: ghost.k8s.local service: type: NodePort port: 80 ``` 然后我們可以使用 `helm template` 命令來渲染我們的模板輸出結果: ```yaml $ helm template --debug my-ghost install.go:178: [debug] Original chart version: "" install.go:195: [debug] CHART PATH: /Users/ych/devs/workspace/yidianzhishi/course/k8strain3/content/helm/manifests/my-ghost --- # Source: my-ghost/templates/service.yaml apiVersion: v1 kind: Service metadata: name: ghost spec: selector: app: ghost-app type: NodePort ports: - protocol: TCP targetPort: 2368 port: 80 --- # Source: my-ghost/templates/deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: ghost spec: selector: matchLabels: app: ghost-app replicas: 1 template: metadata: labels: app: ghost-app spec: containers: - name: ghost-app image: ghost ports: - containerPort: 2368 env: - name: NODE_ENV value: production - name: url value: http://ghost.k8s.local ``` 上面的渲染結果和我們上面的資源清單文件基本上一致了,只是我們現在的靈活性更大了,比如可以控制環境變量、服務的暴露方式等等。 ## 5. 命名模板 雖然現在我們可以使用 `Helm Charts` 模板來渲染安裝 `Ghost` 了,但是上面我們的模板還有很多改進的地方,比如資源對象的名稱我們是固定的,這樣我們就沒辦法在同一個命名空間下面安裝多個應用了,所以一般我們也會根據 `Chart` 名稱或者 `Release` 名稱來替換資源對象的名稱。 前面默認創建的模板中包含一個 `_helpers.tpl` 的文件,該文件中包含一些和名稱、標簽相關的[命名模板](https://ghostwritten.blog.csdn.net/article/details/120311148),我們可以直接使用即可,下面是默認生成的已有的命名模板: ```yaml {{/* Expand the name of the chart. */}} {{- define "my-ghost.name" -}} {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} {{- end }} {{/* Create a default fully qualified app name. We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). If release name contains chart name it will be used as a full name. */}} {{- define "my-ghost.fullname" -}} {{- if .Values.fullnameOverride }} {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} {{- else }} {{- $name := default .Chart.Name .Values.nameOverride }} {{- if contains $name .Release.Name }} {{- .Release.Name | trunc 63 | trimSuffix "-" }} {{- else }} {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} {{- end }} {{- end }} {{- end }} {{/* Create chart name and version as used by the chart label. */}} {{- define "my-ghost.chart" -}} {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} {{- end }} {{/* Common labels */}} {{- define "my-ghost.labels" -}} helm.sh/chart: {{ include "my-ghost.chart" . }} {{ include "my-ghost.selectorLabels" . }} {{- if .Chart.AppVersion }} app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} {{- end }} app.kubernetes.io/managed-by: {{ .Release.Service }} {{- end }} {{/* Selector labels */}} {{- define "my-ghost.selectorLabels" -}} app.kubernetes.io/name: {{ include "my-ghost.name" . }} app.kubernetes.io/instance: {{ .Release.Name }} {{- end }} ``` 然后我們可以將 `Deployment` 的名稱和標簽替換掉: ```yaml apiVersion: apps/v1 kind: Deployment metadata: name: {{ template "my-ghost.fullname" . }} labels: {{ include "my-ghost.labels" . | indent 4 }} spec: selector: matchLabels: {{ include "my-ghost.selectorLabels" . | indent 6 }} replicas: {{ .Values.replicaCount }} template: metadata: labels: {{ include "my-ghost.selectorLabels" . | indent 8 }} spec: containers: - name: ghost-app image: {{ .Values.image }} ports: - containerPort: 2368 env: - name: NODE_ENV value: {{ .Values.node_env | default "production" }} {{- if .Values.url }} - name: url value: http://{{ .Values.url }} {{- end }} ``` 為 Deployment 增加 label 標簽,同樣 `labelSelector` 中也使用 `my-ghost.selectorLabels` 這個命名模板進行替換,同樣對 Service 也做相應的改造: ```yaml apiVersion: v1 kind: Service metadata: name: {{ template "my-ghost.fullname" . }} labels: {{ include "my-ghost.labels" . | indent 4 }} spec: selector: {{ include "my-ghost.selectorLabels" . | indent 4 }} type: {{ .Values.service.type }} ports: - protocol: TCP targetPort: 2368 port: {{ .Values.service.port }} {{- if (and (or (eq .Values.service.type "NodePort") (eq .Values.service.type "LoadBalancer")) (not (empty .Values.service.nodePort))) }} nodePort: {{ .Values.service.nodePort }} {{- else if eq .Values.service.type "ClusterIP" }} nodePort: null {{- end }} ``` 現在我們可以再使用 helm template 渲染驗證結果是否正確: ```yaml $ helm template --debug my-ghost install.go:178: [debug] Original chart version: "" install.go:195: [debug] CHART PATH: /Users/ych/devs/workspace/yidianzhishi/course/k8strain3/content/helm/manifests/my-ghost --- # Source: my-ghost/templates/service.yaml apiVersion: v1 kind: Service metadata: name: release-name-my-ghost labels: helm.sh/chart: my-ghost-0.1.0 app.kubernetes.io/name: my-ghost app.kubernetes.io/instance: release-name app.kubernetes.io/version: "1.16.0" app.kubernetes.io/managed-by: Helm spec: selector: app.kubernetes.io/name: my-ghost app.kubernetes.io/instance: release-name type: NodePort ports: - protocol: TCP targetPort: 2368 port: 80 --- # Source: my-ghost/templates/deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: release-name-my-ghost labels: helm.sh/chart: my-ghost-0.1.0 app.kubernetes.io/name: my-ghost app.kubernetes.io/instance: release-name app.kubernetes.io/version: "1.16.0" app.kubernetes.io/managed-by: Helm spec: selector: matchLabels: app.kubernetes.io/name: my-ghost app.kubernetes.io/instance: release-name replicas: 1 template: metadata: labels: app.kubernetes.io/name: my-ghost app.kubernetes.io/instance: release-name spec: containers: - name: ghost-app image: ghost ports: - containerPort: 2368 env: - name: NODE_ENV value: production - name: url value: http://ghost.k8s.local ``` ## 6. 版本兼容 于 Kubernetes 的版本迭代非常快,所以我們在開發 Chart 包的時候有必要考慮到對不同版本的 Kubernetes 進行兼容,最明顯的就是 Ingress 的資源版本。`Kubernetes` 在 `1.19` 版本為 Ingress 資源引入了一個新的 API:`networking.k8s.io/v1`,這與之前的 `networking.k8s.io/v1beta1 beta` 版本使用方式基本一致,但是和前面的 `extensions/v1beta1` 這個版本在使用上有很大的不同,資源對象的屬性上有一定的區別,所以要兼容不同的版本,我們就需要對模板中的 Ingress 對象做兼容處理。 > 創建ingress對象,確保你已經安裝了[ingress controller組件](https://blog.csdn.net/xixihahalelehehe/article/details/112831123?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522164865488016780265453513%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=164865488016780265453513&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~blog~first_rank_ecpm_v1~rank_v31_ecpm-1-112831123.nonecase&utm_term=ingress&spm=1018.2226.3001.4450) 新版本的資源對象格式如下所示: ```yaml apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: minimal-ingress annotations: nginx.ingress.kubernetes.io/rewrite-target: / spec: ingressClassName: nginx rules: - http: paths: - path: /testpath pathType: Prefix backend: service: name: test port: number: 80 ``` 而舊版本的資源對象格式如下: ```yaml apiVersion: extensions/v1beta1 kind: Ingress metadata: name: minimal-ingress annotations: kubernetes.io/ingress.class: nginx nginx.ingress.kubernetes.io/rewrite-target: / spec: rules: - http: paths: - path: /testpath backend: serviceName: test servicePort: 80 ``` 現在我們再為 Ghost 添加一個 `Ingress` 的模板,新建 `templates/ingress.yaml` 模板文件,先添加一個 `v1` 版本的 ```yaml Ingress 模板: apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: ghost spec: ingressClassName: nginx rules: - host: ghost.k8s.local http: paths: - path: / pathType: Prefix backend: service: name: ghost port: number: 80 ``` 然后同樣將名稱和服務名稱這些使用模板參數進行替換: ```yaml apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: {{ template "my-ghost.fullname" . }} labels: {{ include "my-ghost.labels" . | indent 4 }} spec: ingressClassName: nginx rules: - host: {{ .Values.url }} http: paths: - path: / pathType: Prefix backend: service: name: {{ template "my-ghost.fullname" . }} port: number: {{ .Values.service.port }} ``` 然后接下來我們來兼容下其他的版本格式,這里需要用到 `Capabilities` 對象,在 `Chart` 包的 `_helpers.tpl` 文件中添加幾個用于判斷集群版本或 API 的命名模板: ```yaml {{/* Allow KubeVersion to be overridden. */}} {{- define "my-ghost.kubeVersion" -}} {{- default .Capabilities.KubeVersion.Version .Values.kubeVersionOverride -}} {{- end - {{/* Get Ingress API Version */}} {{- define "my-ghost.ingress.apiVersion" -}} {{- if and (.Capabilities.APIVersions.Has "networking.k8s.io/v1") (semverCompare ">= 1.19-0" (include "my-ghost.kubeVersion" .)) -}} {{- print "networking.k8s.io/v1" -}} {{- else if .Capabilities.APIVersions.Has "networking.k8s.io/v1beta1" -}} {{- print "networking.k8s.io/v1beta1" -}} {{- else -}} {{- print "extensions/v1beta1" -}} {{- end -}} {{- end -}} {{/* Check Ingress stability */}} {{- define "my-ghost.ingress.isStable" -}} {{- eq (include "my-ghost.ingress.apiVersion" .) "networking.k8s.io/v1" -}} {{- end -}} {{/* Check Ingress supports pathType */}} {{/* pathType was added to networking.k8s.io/v1beta1 in Kubernetes 1.18 */}} {{- define "my-ghost.ingress.supportsPathType" -}} {{- or (eq (include "my-ghost.ingress.isStable" .) "true") (and (eq (include "my-ghost.ingress.apiVersion" .) "networking.k8s.io/v1beta1") (semverCompare ">= 1.18-0" (include "my-ghost.kubeVersion" .))) -}} {{- end -}} ``` 上面我們通過 `.Capabilities.APIVersions.Has` 來判斷我們應該使用的 `APIVersion`,如果版本為 `networking.k8s.io/v1`,則定義為 `isStable`,此外還根據版本來判斷是否需要支持 `pathType` 屬性,然后在 `Ingress` 對象模板中就可以使用上面定義的命名模板來決定應該使用哪些屬性,如下所示: ```yaml {{- if .Values.ingress.enabled }} {{- $apiIsStable := eq (include "my-ghost.ingress.isStable" .) "true" -}} {{- $ingressSupportsPathType := eq (include "my-ghost.ingress.supportsPathType" .) "true" -}} apiVersion: {{ include "my-ghost.ingress.apiVersion" . }} kind: Ingress metadata: name: {{ template "my-ghost.fullname" . }} annotations: nginx.ingress.kubernetes.io/ssl-redirect: "false" {{- if and .Values.ingress.ingressClass (not $apiIsStable) }} kubernetes.io/ingress.class: {{ .Values.ingress.ingressClass }} {{- end }} labels: {{- include "my-ghost.labels" . | nindent 4 }} spec: {{- if and .Values.ingress.ingressClass $apiIsStable }} ingressClassName: {{ .Values.ingress.ingressClass }} {{- end }} rules: {{- if not (empty .Values.url) }} - host: {{ .Values.url }} http: {{- else }} - http: {{- end }} paths: - path: / {{- if $ingressSupportsPathType }} pathType: Prefix {{- end }} backend: {{- if $apiIsStable }} service: name: {{ template "my-ghost.fullname" . }} port: number: {{ .Values.service.port }} {{- else }} serviceName: {{ template "my-ghost.fullname" . }} servicePort: {{ .Values.service.port }} {{- end }} {{- end }} ``` 由于有的場景下面并不需要使用 `Ingress` 來暴露服務,所以首先我們通過一個 `ingress.enabled` 屬性來控制是否需要渲染,然后定義了一個 `$apiIsStable` 變量,來表示當前集群是否是穩定版本的 API,然后需要根據該變量去渲染不同的屬性,比如對于 `ingressClass`,如果是穩定版本的 API 則是通過 `spec.ingressClassName` 來指定,否則是通過 `kubernetes.io/ingress.class` 這個 `annotations` 來指定。然后這里我們在 `values.yaml` 文件中添加如下所示默認的 `Ingress` 的配置數據: ```yaml ingress: enabled: true ingressClass: nginx ``` 現在我們再次渲染 `Helm Chart` 模板來驗證資源清單數據: ```yaml $ helm template --debug my-ghost install.go:178: [debug] Original chart version: "" install.go:195: [debug] CHART PATH: /Users/ych/devs/workspace/yidianzhishi/course/k8strain3/content/helm/manifests/my-ghost --- # Source: my-ghost/templates/service.yaml apiVersion: v1 kind: Service metadata: name: release-name-my-ghost labels: helm.sh/chart: my-ghost-0.1.0 app.kubernetes.io/name: my-ghost app.kubernetes.io/instance: release-name app.kubernetes.io/version: "1.16.0" app.kubernetes.io/managed-by: Helm spec: selector: app.kubernetes.io/name: my-ghost app.kubernetes.io/instance: release-name type: NodePort ports: - protocol: TCP targetPort: 2368 port: 80 --- # Source: my-ghost/templates/deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: release-name-my-ghost labels: helm.sh/chart: my-ghost-0.1.0 app.kubernetes.io/name: my-ghost app.kubernetes.io/instance: release-name app.kubernetes.io/version: "1.16.0" app.kubernetes.io/managed-by: Helm spec: selector: matchLabels: app.kubernetes.io/name: my-ghost app.kubernetes.io/instance: release-name replicas: 1 template: metadata: labels: app.kubernetes.io/name: my-ghost app.kubernetes.io/instance: release-name spec: containers: - name: ghost-app image: ghost ports: - containerPort: 2368 env: - name: NODE_ENV value: production - name: url value: http://ghost.k8s.local --- # Source: my-ghost/templates/ingress.yaml apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: release-name-my-ghost annotations: nginx.ingress.kubernetes.io/ssl-redirect: "false" labels: helm.sh/chart: my-ghost-0.1.0 app.kubernetes.io/name: my-ghost app.kubernetes.io/instance: release-name app.kubernetes.io/version: "1.16.0" app.kubernetes.io/managed-by: Helm spec: ingressClassName: nginx rules: - host: ghost.k8s.local http: paths: - path: / pathType: Prefix backend: service: name: release-name-my-ghost port: number: 80 ``` 從上面的資源清單可以看出是符合我們的預期要求的,在我們安裝測試前,一定要確認我們的kubernetes集群是否[安裝ingress controller](https://blog.csdn.net/xixihahalelehehe/article/details/112831123?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522164848305116782248543408%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=164848305116782248543408&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~blog~first_rank_ecpm_v1~rank_v31_ecpm-2-112831123.nonecase&utm_term=ingress&spm=1018.2226.3001.4450), 你也可以[minikube安裝nginx ingress controller](https://kubernetes.io/docs/tasks/access-application-cluster/ingress-minikube/) ,我們可以來安裝測試下結果: ```yaml $ helm upgrade --install my-ghost ./my-ghost -n default Release "my-ghost" does not exist. Installing it now. NAME: my-ghost LAST DEPLOYED: Mon Mar 28 20:03:51 2022 NAMESPACE: default STATUS: deployed REVISION: 1 TEST SUITE: None $ helm ls -n default NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION my-ghost default 1 2022-03-28 20:03:51.782130568 +0800 CST deployed my-ghost-0.1.0 1.16.0 $ kubectl get pods -n default NAME READY STATUS RESTARTS AGE my-ghost-6f698dc49d-ccphv 1/1 Running 0 29s $ kubectl get svc -n default NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 163m my-ghost NodePort 10.102.53.53 <none> 80:32204/TCP 39s $ kubectl get ingress -n default NAME CLASS HOSTS ADDRESS PORTS AGE my-ghost nginx ghost.k8s.local 80 49s $ k get ingress -oyaml apiVersion: v1 items: - apiVersion: networking.k8s.io/v1 kind: Ingress metadata: annotations: meta.helm.sh/release-name: my-ghost meta.helm.sh/release-namespace: default nginx.ingress.kubernetes.io/ssl-redirect: "false" creationTimestamp: "2022-03-28T15:50:43Z" generation: 1 labels: app.kubernetes.io/instance: my-ghost app.kubernetes.io/managed-by: Helm app.kubernetes.io/name: my-ghost app.kubernetes.io/version: 1.16.0 helm.sh/chart: my-ghost-0.1.0 name: my-ghost namespace: default resourceVersion: "17132" uid: d94aa7b8-6631-4e6f-aa2e-4317615cef76 spec: ingressClassName: nginx rules: - host: ghost.k8s.local http: paths: - backend: service: name: my-ghost port: number: 80 path: / pathType: Prefix status: loadBalancer: ingress: - ip: 192.168.211.51 kind: List metadata: resourceVersion: "" selfLink: "" ``` 正常就可以部署成功 Ghost 了,并且可以通過域名 `http://ghost.k8s.local` 進行訪問了: 當然虛擬機部署要配置域名解析: ```yaml echo '192.168.211.51 ghost.k8s.local' >> /etc/hosts ``` ![在這里插入圖片描述](https://img-blog.csdnimg.cn/0245e238de4e4eaf919d2b66d40c193b.png) ## 7. 持久化 上面我們使用的 Ghost 鏡像默認使用 SQLite 數據庫,所以非常有必要將數據進行持久化,當然我們要將這個開關給到用戶去選擇,修改 `templates/deployment.yaml` 模板文件,增加 volumes 相關配置: ```yaml # other spec... spec: volumes: - name: ghost-data {{- if .Values.persistence.enabled }} persistentVolumeClaim: claimName: {{ .Values.persistence.existingClaim | default (include "my-ghost.fullname" .) }} {{- else }} emptyDir: {} {{ end }} containers: - name: ghost-app image: {{ .Values.image }} volumeMounts: - name: ghost-data mountPath: /var/lib/ghost/content # other spec... ``` 這里我們通過 `persistence.enabled` 來判斷是否需要開啟持久化數據,如果開啟則需要看用戶是否直接提供了一個存在的 PVC 對象,如果沒有提供,則我們需要自己創建一個合適的 PVC 對象,如果不需要持久化,則直接使用 `emptyDir:{}` 即可,添加 `templates/pvc.yaml` 模板,內容如下所示: ```bash {{- if and .Values.persistence.enabled (not .Values.persistence.existingClaim) }} kind: PersistentVolumeClaim apiVersion: v1 metadata: name: {{ template "my-ghost.fullname" . }} labels: {{- include "my-ghost.labels" . | nindent 4 }} spec: {{- if .Values.persistence.storageClass }} storageClassName: {{ .Values.persistence.storageClass | quote }} {{- end }} accessModes: - {{ .Values.persistence.accessMode | quote }} resources: requests: storage: {{ .Values.persistence.size | quote }} {{- end -}} ``` 其中訪問模式、存儲容量、`StorageClass`、存在的 PVC 都通過 Values 來指定,增加了靈活性。對應的 `values.yaml` 配置部分我們可以給一個默認的配置: ```bash ## 是否使用 PVC 開啟數據持久化 persistence: enabled: true ## 是否使用 storageClass,如果不適用則補配置 # storageClass: "xxx" ## ## 如果想使用一個存在的 PVC 對象,則直接傳遞給下面的 existingClaim 變量 # existingClaim: your-claim accessMode: ReadWriteOnce # 訪問模式 size: 1Gi # 存儲容量 ``` ## 8. 定制 除了上面的這些主要的需求之外,還有一些額外的定制需求,比如用戶想要配置更新策略,因為更新策略并不是一層不變的,這里和之前不太一樣,我們需要用到一個新的函數 `toYaml`: ```bash {{- if .Values.updateStrategy }} strategy: {{ toYaml .Values.updateStrategy | nindent 4 }} {{- end }} ``` 意思就是我們將 `updateStrategy` 這個 Values 值轉換成 YAML 格式,并保留4個空格。然后添加其他的配置,比如是否需要添加 `nodeSelector`、容忍、親和性這些,這里我們都是使用 `toYaml` 函數來控制空格,如下所示: ```bash {{- if .Values.nodeSelector }} nodeSelector: {{- toYaml .Values.nodeSelector | nindent 8 }} {{- end -}} {{- with .Values.affinity }} affinity: {{- toYaml . | nindent 8 }} {{- end }} {{- with .Values.tolerations }} tolerations: {{- toYaml . | nindent 8 }} {{- end }} ``` 接下來當然就是鏡像的配置了,如果是私有倉庫還需要指定 `imagePullSecrets`: ```bash {{- if .Values.image.pullSecrets }} imagePullSecrets: {{- range .Values.image.pullSecrets }} - name: {{ . }} {{- end }} {{- end }} containers: - name: ghost image: {{ printf "%s:%s" .Values.image.name .Values.image.tag }} imagePullPolicy: {{ .Values.image.pullPolicy | quote }} ports: - containerPort: 2368 ``` 對應的 Values 值如下所示: ```bash image: name: ghost tag: latest pullPolicy: IfNotPresent ## 如果是私有倉庫,需要指定 imagePullSecrets # pullSecrets: # - myRegistryKeySecretName ``` 然后就是 `resource` 資源聲明,這里我們定義一個默認的 `resources` 值,同樣用 `toYaml` 函數來控制空格: ```bash resources: {{ toYaml .Values.resources | indent 10 }} ``` 最后是健康檢查部分,雖然我們之前沒有做 `livenessProbe`,但是我們開發 Chart 模板的時候就要盡可能考慮周全一點,這里我們加上存活性和可讀性、啟動三個探針,并且根據 `livenessProbe.enabled` 、`readinessProbe.enabled` 以及 `startupProbe.enabled` 三個 Values 值來判斷是否需要添加探針,探針對應的參數也都通過 Values 值來配置: ```bash {{- if .Values.startupProbe.enabled }} startupProbe: httpGet: path: / port: 2368 initialDelaySeconds: {{ .Values.startupProbe.initialDelaySeconds }} periodSeconds: {{ .Values.startupProbe.periodSeconds }} timeoutSeconds: {{ .Values.startupProbe.timeoutSeconds }} failureThreshold: {{ .Values.startupProbe.failureThreshold }} successThreshold: {{ .Values.startupProbe.successThreshold }} {{- end }} {{- if .Values.livenessProbe.enabled }} livenessProbe: httpGet: path: / port: 2368 initialDelaySeconds: {{ .Values.livenessProbe.initialDelaySeconds }} periodSeconds: {{ .Values.livenessProbe.periodSeconds }} timeoutSeconds: {{ .Values.livenessProbe.timeoutSeconds }} failureThreshold: {{ .Values.livenessProbe.failureThreshold }} successThreshold: {{ .Values.livenessProbe.successThreshold }} {{- end }} {{- if .Values.readinessProbe.enabled }} readinessProbe: httpGet: path: / port: 2368 initialDelaySeconds: {{ .Values.readinessProbe.initialDelaySeconds }} periodSeconds: {{ .Values.readinessProbe.periodSeconds }} timeoutSeconds: {{ .Values.readinessProbe.timeoutSeconds }} failureThreshold: {{ .Values.readinessProbe.failureThreshold }} successThreshold: {{ .Values.readinessProbe.successThreshold }} {{- end }} ``` 默認的 `values.yaml` 文件如下所示: ```bash replicaCount: 1 image: name: ghost tag: latest pullPolicy: IfNotPresent node_env: production url: ghost.k8s.local service: type: ClusterIP port: 80 ingress: enabled: true ingressClass: nginx ## 是否使用 PVC 開啟數據持久化 persistence: enabled: true ## 是否使用 storageClass,如果不適用則補配置 # storageClass: "xxx" ## ## 如果想使用一個存在的 PVC 對象,則直接傳遞給下面的 existingClaim 變量 # existingClaim: your-claim accessMode: ReadWriteOnce # 訪問模式 size: 1Gi # 存儲容量 nodeSelector: {} affinity: {} tolerations: {} resources: {} startupProbe: enabled: false livenessProbe: enabled: false readinessProbe: enabled: false ``` 現在我們再去更新 Release: ```bash $ helm upgrade --install my-ghost ./my-ghost -n default Release "my-ghost" has been upgraded. Happy Helming! NAME: my-ghost LAST DEPLOYED: Thu Mar 17 16:03:02 2022 NAMESPACE: default STATUS: deployed REVISION: 2 TEST SUITE: None ? helm ls -n default NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION my-ghost default 2 2022-03-17 16:05:07.123349 +0800 CST deployed my-ghost-0.1.0 1.16.0 ? kubectl get pods -n default NAME READY STATUS RESTARTS AGE my-ghost-6dbc455fc7-cmm4p 1/1 Running 0 2m42s ? kubectl get pvc -n default NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE my-ghost Bound pvc-2f0b7d5a-04d4-4331-848b-af21edce673e 1Gi RWO nfs-client 4m59s k get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE pvc-d62828dd-56ba-4819-a67a-0cd67b65dcd2 1Gi RWO Delete Bound default/my-ghost standard 7s $ k get pv pvc-d62828dd-56ba-4819-a67a-0cd67b65dcd2 -oyaml apiVersion: v1 kind: PersistentVolume metadata: annotations: hostPathProvisionerIdentity: d798e478-e315-4720-abba-dd9e6af28464 pv.kubernetes.io/provisioned-by: k8s.io/minikube-hostpath creationTimestamp: "2022-03-30T13:02:22Z" finalizers: - kubernetes.io/pv-protection name: pvc-d62828dd-56ba-4819-a67a-0cd67b65dcd2 resourceVersion: "1594" uid: b1edac7a-c960-4152-bf3b-a1038790b3a8 spec: accessModes: - ReadWriteOnce capacity: storage: 1Gi claimRef: apiVersion: v1 kind: PersistentVolumeClaim name: my-ghost namespace: default resourceVersion: "1591" uid: d62828dd-56ba-4819-a67a-0cd67b65dcd2 hostPath: path: /tmp/hostpath-provisioner/default/my-ghost type: "" persistentVolumeReclaimPolicy: Delete storageClassName: standard volumeMode: Filesystem status: phase: Bound ? kubectl get ingress -n default NAME CLASS HOSTS ADDRESS PORTS AGE my-ghost nginx ghost.k8s.local 192.168.31.31 80 3h24m ``` 到這里我們就基本完成了這個簡單的 Helm Charts 包的開發,當然以后可能還會有新的需求,我們需要不斷去迭代優化。 當我們設置`storageclass: ""`或者注釋`storageclass`時,minikube會自動一個hostpath本地pv `my-ghost/value.yaml`配置 當設置持久`enabled: false`,它為非持久化部署。 ```bash persistence: enabled: false ``` ## 9. 共享 Charts Helm Charts 包開發完成了,如果別人想要使用我們的包,則需要我們共享出去,我們可以通過 Chart 倉庫來進行共享,Helm Charts 可以在遠程存儲庫或本地環境/存儲庫中使用,遠程存儲庫可以是公共的,如 Bitnami Charts 也可以是托管存儲庫,如 Google Cloud Storage 或 GitHub。為了演示方便,這里我們使用 GitHub 來托管我們的 Charts 包。 我們可以使用 `GitHub Pages` 來創建 Charts 倉庫,GitHub 允許我們以兩種不同的方式提供靜態網頁: - 通過配置項目提供其 `docs/` 目錄的內容 - 通過配置項目來服務特定的分支 這里我們將采用第二種方法,首先在 GitHub 上創建一個代碼倉庫:`https://github.com/Ghostwritten/helm-demo`,將上面我們創建的 `my-ghost` 包提交到倉庫 charts 目錄下,然后打包 chart 包: ```bash $ helm package helm-demo/my-ghost Successfully packaged chart and saved it to: /root/my-ghost-0.1.0.tgz ``` 我們可以將打包的壓縮包放到另外的目錄 `repo/stable` 中去,現在倉庫的結構如下所示: ```bash $ tree . . ├── charts │ └── my-ghost │ ├── Chart.yaml │ ├── templates │ │ ├── deployment.yaml │ │ ├── _helpers.tpl │ │ ├── ingress.yaml │ │ ├── pvc.yaml │ │ └── service.yaml │ └── values.yaml ├── LICENSE ├── README.md └── repo └── stable └── my-ghost-0.1.0.tgz 5 directories, 10 files ``` 執行如下所示命令生成 index 索引文件: ```bash helm repo index repo/stable --url https://raw.githubusercontent.com/cnych/helm101/main/repo/stable ``` 上述命令會在 `repo/stable` 目錄下面生成一個如下所示的 `index.yaml` 文件: ```bash $ cat repo/stable/index.yaml apiVersion: v1 entries: my-ghost: - apiVersion: v2 appVersion: 1.16.0 created: "2022-03-30T21:39:37.202992379+08:00" description: A Helm chart for Kubernetes digest: 44d40c93d408f4d109a66b8ca61b14417c6d6b465cf636ae0a0767b73d5c6d13 name: my-ghost type: application urls: - https://raw.githubusercontent.com/ghostwritten/helm-demo/main/repo/stable/my-ghost-0.1.0.tgz version: 0.1.0 generated: "2022-03-30T21:39:37.201867108+08:00" ``` 該 `index.yaml` 文件是我們通過倉庫獲取 Chart 包的關鍵。然后將代碼推送到 `GitHub`,[如何學習本地項目上傳github請參閱](https://ghostwritten.blog.csdn.net/article/details/105240194): ```bash![在這里插入圖片描述](https://img-blog.csdnimg.cn/93c8052cb6f34a909afd0d99a482951b.png) $ yum -y install git $ git config --global user.name "ghostwritten" $ git config --global user.email "1zoxun1@gmail.com" $ git config list #查看 /root/.ssh/id_rsa.pub 并復制到github的設置頁面的SSH keys $ cat /root/.ssh/id_rsa.pub ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCqgcbG1iD0m/6KWZPu4uJv+vM7ZBfrbnCib6egfz8+YGWMpTYnD8EgFZ1j/cH6G3odktP0ZjvUriFY+SZIYQtpIdvQ7ciG25HQC9WRREAchGbTcvyw0Jt4F2S5EJJVBzEYFwlhz2JH1iUqbzyPjyRH 1zoxun1@gmail.com ``` 并復制到github的設置頁面的SSH keys ![在這里插入圖片描述](https://img-blog.csdnimg.cn/69f964cd8b7e42f7854407d3baed9834.png) ```bash $ pwd /root/helm-demo $ git init $ git add * $ git commit -m "add helm-demo" $ git remote add origin https://github.com/Ghostwritten/helm-demo.git $ git push origin main ``` ![在這里插入圖片描述](https://img-blog.csdnimg.cn/d9402dab05b3445db077103fa50a859d.png) 接下來為該倉庫設置 `GitHub Pages`,首先在本地新建一個 `gh-pages` 分支: 只將 `repo/stable/index.yaml` 文件保留到根目錄下面,其他文件忽略,然后推送到遠程倉庫: ```bash $ tree . ├── index.yaml ├── LICENSE └── README.md 0 directories, 3 files ``` ```bash $ git push origin gh-pages ``` 在 `GitHub Pages` 頁面選擇使用 gh-pages 分支即可: ![在這里插入圖片描述](https://img-blog.csdnimg.cn/733184a2036c4f05a7271451f6ad6407.png) 現在我們就可以通過 `http://smoothies.com.cn/helm-demo/` 來獲取我們的 Chart 包了。 使用如下所示命令添加 repo 倉庫: ```bash $ helm repo add helm-demo http://smoothies.com.cn/helm-demo/ "helm-demo" has been added to your repositories ``` 我們也可以使用 `helm search` 來搜索倉庫中的 Chart 包,正常就包含上面我們的 `my-ghost` 了: ```bash $ helm search repo helm-demo NAME CHART VERSION APP VERSION DESCRIPTION helm-demo/my-ghost 0.1.0 1.16.0 A Helm chart for Kubernetes ``` 接下來就可以正常使用 chart 包進行操作了,比如進行安裝: ```bash helm install hello-ghost helm-demo/my-ghost ``` ?<font color= #FF4500 size=4 style="font-family:Courier New">推薦閱讀:</font> - [Helm Charts 開發完整示例](https://mp.weixin.qq.com/s/HRFrmvWYDdwjMzHn8sco5w) - [git 本地項目上傳github或gitlab詳解](https://ghostwritten.blog.csdn.net/article/details/105240194) - [Minikube 在 Centos 7 部署 Kubernetes](https://ghostwritten.blog.csdn.net/article/details/123796854) - [Hello Minikube](https://kubernetes.io/docs/tutorials/hello-minikube/) ![在這里插入圖片描述](https://img-blog.csdnimg.cn/d6ce9fa621b04e0a97101c5ff22136d3.gif#pic_center)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看