# 使用Helm管理kubernetes應用
讀完本文后您應該可以自己創建chart,并創建自己的私有chart倉庫。
[Helm](http://helm.sh)是一個kubernetes應用的包管理工具,用來管理[charts](https://github.com/kubernetes/charts)——預先配置好的安裝包資源,有點類似于Ubuntu的APT和CentOS中的yum。
Helm chart是用來封裝kubernetes原生應用程序的yaml文件,可以在你部署應用的時候自定義應用程序的一些metadata,便與應用程序的分發。
Helm和charts的主要作用:
- 應用程序封裝
- 版本管理
- 依賴檢查
- 便于應用程序分發
## 安裝Helm
**前提要求**
- Kubernetes1.5以上版本
- 集群可訪問到的鏡像倉庫
- 執行helm命令的主機可以訪問到kubernetes集群
**安裝步驟**
首先需要安裝helm客戶端
```bash
curl https://raw.githubusercontent.com/kubernetes/helm/master/scripts/get > get_helm.sh
chmod 700 get_helm.sh
./get_helm.sh
```
創建tiller的`serviceaccount`和`clusterrolebinding`
```bash
kubectl create serviceaccount --namespace kube-system tiller
kubectl create clusterrolebinding tiller-cluster-rule --clusterrole=cluster-admin --serviceaccount=kube-system:tiller
```
然后安裝helm服務端tiller
```bash
helm init -i jimmysong/kubernetes-helm-tiller:v2.8.1
```
(目前最新版v2.8.2,可以使用阿里云鏡像,如:
`helm init --upgrade -i registry.cn-hangzhou.aliyuncs.com/google_containers/tiller:v2.8.2 --stable-repo-url https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts`)
我們使用`-i`指定自己的鏡像,因為官方的鏡像因為某些原因無法拉取,官方鏡像地址是:`gcr.io/kubernetes-helm/tiller:v2.8.1`,我在DockerHub上放了一個備份`jimmysong/kubernetes-helm-tiller:v2.8.1`,該鏡像的版本與helm客戶端的版本相同,使用`helm version`可查看helm客戶端版本。
為應用程序設置`serviceAccount`:
```bash
kubectl patch deploy --namespace kube-system tiller-deploy -p '{"spec":{"template":{"spec":{"serviceAccount":"tiller"}}}}'
```
檢查是否安裝成功:
```bash
$ kubectl -n kube-system get pods|grep tiller
tiller-deploy-2372561459-f6p0z 1/1 Running 0 1h
$ helm version
Client: &version.Version{SemVer:"v2.3.1", GitCommit:"32562a3040bb5ca690339b9840b6f60f8ce25da4", GitTreeState:"clean"}
Server: &version.Version{SemVer:"v2.3.1", GitCommit:"32562a3040bb5ca690339b9840b6f60f8ce25da4", GitTreeState:"clean"}
```
## 創建自己的chart
我們創建一個名為`mychart`的chart,看一看chart的文件結構。
```bash
$ helm create mongodb
$ tree mongodb
mongodb
├── Chart.yaml #Chart本身的版本和配置信息
├── charts #依賴的chart
├── templates #配置模板目錄
│?? ├── NOTES.txt #helm提示信息
│?? ├── _helpers.tpl #用于修改kubernetes objcet配置的模板
│?? ├── deployment.yaml #kubernetes Deployment object
│?? └── service.yaml #kubernetes Serivce
└── values.yaml #kubernetes object configuration
2 directories, 6 files
```
### 模板
`Templates`目錄下是yaml文件的模板,遵循[Go template](https://golang.org/pkg/text/template/)語法。使用過[Hugo](https://gohugo.io)的靜態網站生成工具的人應該對此很熟悉。
我們查看下`deployment.yaml`文件的內容。
```yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: {{ template "fullname" . }}
labels:
chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}"
spec:
replicas: {{ .Values.replicaCount }}
template:
metadata:
labels:
app: {{ template "fullname" . }}
spec:
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- containerPort: {{ .Values.service.internalPort }}
livenessProbe:
httpGet:
path: /
port: {{ .Values.service.internalPort }}
readinessProbe:
httpGet:
path: /
port: {{ .Values.service.internalPort }}
resources:
{{ toyaml .Values.resources | indent 12 }}
```
這是該應用的Deployment的yaml配置文件,其中的雙大括號包擴起來的部分是Go template,其中的Values是在`values.yaml`文件中定義的:
```yaml
# Default values for mychart.
# This is a yaml-formatted file.
# Declare variables to be passed into your templates.
replicaCount: 1
image:
repository: nginx
tag: stable
pullPolicy: IfNotPresent
service:
name: nginx
type: ClusterIP
externalPort: 80
internalPort: 80
resources:
limits:
cpu: 100m
memory: 128Mi
requests:
cpu: 100m
memory: 128Mi
```
比如在`Deployment.yaml`中定義的容器鏡像`image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"`其中的:
- `.Values.image.repository`就是nginx
- `.Values.image.tag`就是stable
以上兩個變量值是在create chart的時候自動生成的默認值。
我們將默認的鏡像地址和tag改成我們自己的鏡像`harbor-001.jimmysong.io/library/nginx:1.9`。
### 檢查配置和模板是否有效
當使用kubernetes部署應用的時候實際上講templates渲染成最終的kubernetes能夠識別的yaml格式。
使用`helm install --dry-run --debug <chart_dir>`命令來驗證chart配置。該輸出中包含了模板的變量配置與最終渲染的yaml文件。
```bash
$ helm install --dry-run --debug mychart
Created tunnel using local port: '58406'
SERVER: "localhost:58406"
CHART PATH: /Users/jimmy/Workspace/github/bitnami/charts/incubator/mean/charts/mychart
NAME: filled-seahorse
REVISION: 1
RELEASED: Tue Oct 24 18:57:13 2017
CHART: mychart-0.1.0
USER-SUPPLIED VALUES:
{}
COMPUTED VALUES:
image:
pullPolicy: IfNotPresent
repository: harbor-001.jimmysong.io/library/nginx
tag: 1.9
replicaCount: 1
resources:
limits:
cpu: 100m
memory: 128Mi
requests:
cpu: 100m
memory: 128Mi
service:
externalPort: 80
internalPort: 80
name: nginx
type: ClusterIP
HOOKS:
MANIFEST:
---
# Source: mychart/templates/service.yaml
apiVersion: v1
kind: Service
metadata:
name: filled-seahorse-mychart
labels:
chart: "mychart-0.1.0"
spec:
type: ClusterIP
ports:
- port: 80
targetPort: 80
protocol: TCP
name: nginx
selector:
app: filled-seahorse-mychart
---
# Source: mychart/templates/deployment.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: filled-seahorse-mychart
labels:
chart: "mychart-0.1.0"
spec:
replicas: 1
template:
metadata:
labels:
app: filled-seahorse-mychart
spec:
containers:
- name: mychart
image: "harbor-001.jimmysong.io/library/nginx:1.9"
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
livenessProbe:
httpGet:
path: /
port: 80
readinessProbe:
httpGet:
path: /
port: 80
resources:
limits:
cpu: 100m
memory: 128Mi
requests:
cpu: 100m
memory: 128Mi
```
我們可以看到Deployment和Service的名字前半截由兩個隨機的單詞組成,最后才是我們在`values.yaml`中配置的值。
### 部署到kubernetes
在`mychart`目錄下執行下面的命令將nginx部署到kubernetes集群上。
```bash
helm install .
NAME: eating-hound
LAST DEPLOYED: Wed Oct 25 14:58:15 2017
NAMESPACE: default
STATUS: DEPLOYED
RESOURCES:
==> v1/Service
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
eating-hound-mychart 10.254.135.68 <none> 80/TCP 0s
==> extensions/v1beta1/Deployment
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
eating-hound-mychart 1 1 1 0 0s
NOTES:
1. Get the application URL by running these commands:
export POD_NAME=$(kubectl get pods --namespace default -l "app=eating-hound-mychart" -o jsonpath="{.items[0].metadata.name}")
echo "Visit http://127.0.0.1:8080 to use your application"
kubectl port-forward $POD_NAME 8080:80
```
現在nginx已經部署到kubernetes集群上,本地執行提示中的命令在本地主機上訪問到nginx實例。
```bash
export POD_NAME=$(kubectl get pods --namespace default -l "app=eating-hound-mychart" -o jsonpath="{.items[0].metadata.name}")
echo "Visit http://127.0.0.1:8080 to use your application"
kubectl port-forward $POD_NAME 8080:80
```
在本地訪問`http://127.0.0.1:8080`即可訪問到nginx。
**查看部署的relaese**
```bash
$ helm list
NAME REVISION UPDATED STATUS CHART NAMESPACE
eating-hound 1 Wed Oct 25 14:58:15 2017 DEPLOYED mychart-0.1.0 default
```
**刪除部署的release**
```bash
$ helm delete eating-hound
release "eating-hound" deleted
```
### 打包分享
我們可以修改`Chart.yaml`中的helm chart配置信息,然后使用下列命令將chart打包成一個壓縮文件。
```bash
helm package .
```
打包出`mychart-0.1.0.tgz`文件。
### 依賴
我們可以在`requirements.yaml`中定義應用所依賴的chart,例如定義對`mariadb`的依賴:
```yaml
dependencies:
- name: mariadb
version: 0.6.0
repository: https://kubernetes-charts.storage.googleapis.com
```
使用`helm lint . `命令可以檢查依賴和模板配置是否正確。
### 安裝源
使用第三方chat庫
- 添加fabric8庫
```bash
$ helm repo add fabric8 https://fabric8.io/helm
```
- 搜索fabric8提供的工具(主要就是fabric8-platform工具包,包含了CI、CD的全套工具)
```bash
$ helm search fabric8
```
我們在前面安裝chart可以通過HTTP server的方式提供。
```bash
$ helm serve
Regenerating index. This may take a moment.
Now serving you on 127.0.0.1:8879
```
訪問`http://localhost:8879`可以看到剛剛安裝的chart。

點擊鏈接即可以下載chart的壓縮包。
## 注意事項
下面列舉一些常見問題,和在解決這些問題時候的注意事項。
### 服務依賴管理
所有使用helm部署的應用中如果沒有特別指定chart的名字都會生成一個隨機的`Release name`,例如`romping-frog`、`sexy-newton`等,跟啟動docker容器時候容器名字的命名規則相同,而真正的資源對象的名字是在YAML文件中定義的名字,我們成為`App name`,兩者連接起來才是資源對象的實際名字:`Release name`-`App name`。
而使用helm chart部署的包含依賴關系的應用,都會使用同一套`Release name`,在配置YAML文件的時候一定要注意在做服務發現時需要配置的服務地址,如果使用環境變量的話,需要像下面這樣配置。
```yaml
env:
- name: SERVICE_NAME
value: "{{ .Release.Name }}-{{ .Values.image.env.SERVICE_NAME }}"
```
這是使用了Go template的語法。至于`{{ .Values.image.env.SERVICE_NAME }}`的值是從`values.yaml`文件中獲取的,所以需要在`values.yaml`中增加如下配置:
```yaml
image:
env:
SERVICE_NAME: k8s-app-monitor-test
```
### 解決本地chart依賴
在本地當前chart配置的目錄下啟動helm server,我們不指定任何參數,直接使用默認端口啟動。
```bash
helm serve
```
將該repo加入到repo list中。
```bash
helm repo add local http://localhost:8879
```
在瀏覽器中訪問<http://localhost:8879>可以看到所有本地的chart。
然后下載依賴到本地。
```bash
helm dependency update
```
這樣所有的chart都會下載到本地的`charts`目錄下。
### 設置helm命令自動補全
為了方便helm命令的使用,helm提供了自動補全功能,如果使用zsh請執行:
```bash
source <(helm completion zsh)
```
如果使用bash請執行:
```bash
source <(helm completion bash)
```
## 部署MEAN測試案例
MEAN是用來構建網站和web應用的免費開源的JavaScript軟件棧,該軟件棧包括MongoDB、Express.js、Angular和Node.js。
**下載charts**
```bash
$ git clone https://github.com/bitnami/charts.git
$ cd charts/incubator/mean
$ helm dep list
NAME VERSION REPOSITORY STATUS
mongodb 0.4.x https://kubernetes-charts.storage.googleapis.com/ missing
```
缺少mongodb的依賴,需要更新一下chart。
**注**:`https://kubernetes-charts.storage.googleapis.com/`是Google維護的chart庫,訪問該地址可以看到所有的chart列表。
```bash
$ helm dep update
Hang tight while we grab the latest from your chart repositories...
...Unable to get an update from the "local" chart repository (http://127.0.0.1:8879/charts):
Get http://127.0.0.1:8879/charts/index.yaml: dial tcp 127.0.0.1:8879: getsockopt: connection refused
...Successfully got an update from the "stable" chart repository
Update Complete. ?Happy Helming!?
Saving 1 charts
Downloading mongodb from repo https://kubernetes-charts.storage.googleapis.com/
```
所有的image都在 `values.yaml` 文件中配置。
下載缺失的chart。
```bash
$ helm dep build
Hang tight while we grab the latest from your chart repositories...
...Unable to get an update from the "local" chart repository (http://127.0.0.1:8879/charts):
Get http://127.0.0.1:8879/charts/index.yaml: dial tcp 127.0.0.1:8879: getsockopt: connection refused
...Successfully got an update from the "stable" chart repository
Update Complete. ?Happy Helming!?
Saving 1 charts
Downloading mongodb from repo https://kubernetes-charts.storage.googleapis.com/
```
**修改mongodb chart配置**
將剛才下載的`charts/mongodb-0.4.17.tgz`給解壓后,修改其中的配置:
- 將`persistence`下的`enabled`設置為false
- 將image修改為我們的私有鏡像:harbor-001.jimmysong.io/library/bitnami-mongodb:3.4.9-r1
執行`helm install --dry-run --debug .`確定模板無誤。
將修改后的mongodb chart打包,在mongodb的目錄下執行:
```bash
helm package .
```
現在再訪問前面啟動的helm server `http://localhost:8879`將可以在頁面上看到mongodb-0.4.17這個chart。
我們對官方chart配置做了如下修改后推送到了自己的chart倉庫:
- `requirements.yaml`和`requirements.lock`文件中的`repository`為`http://localhost:8879`
- 將`values.yaml`中的`storageClass`設置為`null`
- 將`values.yaml`中的`Image`都改為私有鏡像
- `repositroy`都設置為`http://localhost:8879`
**注**:因為我們沒有使用PVC所以將所有的關于持久化存儲的配置都設置為false了。
**部署MEAN**
在`mean`目錄下執行:
```bash
helm install .
NAME: orbiting-platypus
LAST DEPLOYED: Wed Oct 25 16:21:48 2017
NAMESPACE: default
STATUS: DEPLOYED
RESOURCES:
==> v1/Secret
NAME TYPE DATA AGE
orbiting-platypus-mongodb Opaque 2 2s
==> v1/ConfigMap
NAME DATA AGE
orbiting-platypus-mean 1 2s
==> v1/Service
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
orbiting-platypus-mongodb 10.254.144.208 <none> 27017/TCP 2s
orbiting-platypus-mean 10.254.165.23 <none> 80/TCP 2s
==> extensions/v1beta1/Deployment
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
orbiting-platypus-mean 1 1 1 0 2s
orbiting-platypus-mongodb 1 1 1 0 2s
NOTES:
Get the URL of your Node app by running:
export POD_NAME=$(kubectl get pods --namespace default -l "app=orbiting-platypus-mean" -o jsonpath="{.items[0].metadata.name}")
echo http://127.0.0.1:8080/
kubectl port-forward $POD_NAME 8080:80
```
這樣MEAN軟件棧就部署到你的kuberentes集群里面了(默認是在default namespace下)。
**驗證檢查**
為了驗證MEAN是否安裝成功過,可以使用`kubectl get pods`查看pod是否啟動完成,會先啟動mongodb的pod,然后啟動MEAN中的4步init。
**訪問Web UI**
在Ingress中增加如下配置:
```yaml
- host: mean.jimmysong.io
http:
paths:
- backend:
serviceName: orbiting-platypus-mean
servicePort: 80
path: /
```
然后在頁面中更新ingress:
```bash
kubectl repalce -f ingress.yaml
```
關于Ingress配置請參考:[邊緣節點配置](../practice/edge-node-configuration.md)
然后在本地的`/etc/hosts`文件中增加一條配置:
```Ini
172.20.0.119 mean.jimmysong.io
```
**注**:172.20.0.119即邊緣節點的VIP。
因為該頁面需要加載google的angularjs、還有兩個css在國內無法訪問,可以使用curl測試:
```bash
curl mean.jimmysong.io
```
將會返回HTML內容:
```html
<!doctype html>
<!-- ASSIGN OUR ANGULAR MODULE -->
<html ng-app="scotchTodo">
<head>
<!-- META -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Optimize mobile viewport -->
<title>Node/Angular Todo App</title>
<!-- SCROLLS -->
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css">
<!-- load bootstrap -->
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.min.css">
<style>
html {
overflow-y: scroll;
}
body {
padding-top: 50px;
}
#todo-list {
margin-bottom: 30px;
}
#todo-form {
margin-bottom: 50px;
}
</style>
<!-- SPELLS -->
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.min.js"></script>
<!-- load angular -->
<script src="js/controllers/main.js"></script>
<!-- load up our controller -->
<script src="js/services/todos.js"></script>
<!-- load our todo service -->
<script src="js/core.js"></script>
<!-- load our main application -->
</head>
<!-- SET THE CONTROLLER -->
<body ng-controller="mainController">
<div class="container">
<!-- HEADER AND TODO COUNT -->
<div class="jumbotron text-center">
<h1>I'm a Todo-aholic <span class="label label-info">{{ todos.length }}</span></h1>
</div>
<!-- TODO LIST -->
<div id="todo-list" class="row">
<div class="col-sm-4 col-sm-offset-4">
<!-- LOOP OVER THE TODOS IN $scope.todos -->
<div class="checkbox" ng-repeat="todo in todos">
<label>
<input type="checkbox" ng-click="deleteTodo(todo._id)"> {{ todo.text }}
</label>
</div>
<p class="text-center" ng-show="loading">
<span class="fa fa-spinner fa-spin fa-3x"></span>
</p>
</div>
</div>
<!-- FORM TO CREATE TODOS -->
<div id="todo-form" class="row">
<div class="col-sm-8 col-sm-offset-2 text-center">
<form>
<div class="form-group">
<!-- BIND THIS VALUE TO formData.text IN ANGULAR -->
<input type="text" class="form-control input-lg text-center" placeholder="I want to buy a puppy that will love me forever" ng-model="formData.text">
</div>
<!-- createToDo() WILL CREATE NEW TODOS -->
<button type="submit" class="btn btn-primary btn-lg" ng-click="createTodo()">Add</button>
</form>
</div>
</div>
<div class="text-center text-muted">
<p>A demo by <a href="http://scotch.io">Scotch</a>.</p>
<p>Read the <a href="http://scotch.io/tutorials/javascript/creating-a-single-page-todo-app-with-node-and-angular">tutorial</a>.</p>
</div>
</div>
</body>
</html>
```
訪問 http://mean.jimmysong.io 可以看到如下界面,我在其中添加幾條todo:

**注**:Todo中的文字來自*What does the fox say?*
測試完成后可以使用下面的命令將mean chart推送的本地chart倉庫中。
在mean目錄下執行:
```bash
helm package .
```
再次刷新`http://localhost:8879`將可以看到如下三個chart:
- mean
- mean-0.1.3
- mongodb
- mongodb-0.4.17
- mychart
- mychart-0.1.0
## 參考
- [Deploy, Scale And Upgrade An Application On Kubernetes With Helm](https://docs.bitnami.com/kubernetes/how-to/deploy-application-kubernetes-helm/)
- [Helm charts](https://github.com/kubernetes/helm/blob/master/docs/charts.md)
- [Go template](https://golang.org/pkg/text/template/)
- [How To Create Your First Helm Chart](https://docs.bitnami.com/kubernetes/how-to/create-your-first-helm-chart/)
- [Speed deployment on Kubernetes with Helm Chart – Quick yaml example from scratch](https://www.ibm.com/blogs/bluemix/2017/10/quick-example-helm-chart-for-kubernetes/)
- 序言
- 云原生
- 云原生(Cloud Native)的定義
- CNCF - 云原生計算基金會簡介
- CNCF章程
- 云原生的設計哲學
- Play with Kubernetes
- 快速部署一個云原生本地實驗環境
- Kubernetes與云原生應用概覽
- 云原生應用之路——從Kubernetes到Cloud Native
- 云原生編程語言
- 云原生編程語言Ballerina
- 云原生編程語言Pulumi
- 云原生的未來
- Kubernetes架構
- 設計理念
- Etcd解析
- 開放接口
- CRI - Container Runtime Interface(容器運行時接口)
- CNI - Container Network Interface(容器網絡接口)
- CSI - Container Storage Interface(容器存儲接口)
- Kubernetes中的網絡
- Kubernetes中的網絡解析——以flannel為例
- Kubernetes中的網絡解析——以calico為例
- 具備API感知的網絡和安全性管理開源軟件Cilium
- Cilium架構設計與概念解析
- 資源對象與基本概念解析
- Pod狀態與生命周期管理
- Pod概覽
- Pod解析
- Init容器
- Pause容器
- Pod安全策略
- Pod的生命周期
- Pod Hook
- Pod Preset
- Pod中斷與PDB(Pod中斷預算)
- 集群資源管理
- Node
- Namespace
- Label
- Annotation
- Taint和Toleration(污點和容忍)
- 垃圾收集
- 控制器
- Deployment
- StatefulSet
- DaemonSet
- ReplicationController和ReplicaSet
- Job
- CronJob
- Horizontal Pod Autoscaling
- 自定義指標HPA
- 準入控制器(Admission Controller)
- 服務發現
- Service
- Ingress
- Traefik Ingress Controller
- 身份與權限控制
- ServiceAccount
- RBAC——基于角色的訪問控制
- NetworkPolicy
- 存儲
- Secret
- ConfigMap
- ConfigMap的熱更新
- Volume
- Persistent Volume(持久化卷)
- Storage Class
- 本地持久化存儲
- 集群擴展
- 使用自定義資源擴展API
- 使用CRD擴展Kubernetes API
- Aggregated API Server
- APIService
- Service Catalog
- 資源調度
- QoS(服務質量等級)
- 用戶指南
- 資源對象配置
- 配置Pod的liveness和readiness探針
- 配置Pod的Service Account
- Secret配置
- 管理namespace中的資源配額
- 命令使用
- Docker用戶過度到kubectl命令行指南
- kubectl命令概覽
- kubectl命令技巧大全
- 使用etcdctl訪問kubernetes數據
- 集群安全性管理
- 管理集群中的TLS
- kubelet的認證授權
- TLS bootstrap
- 創建用戶認證授權的kubeconfig文件
- IP偽裝代理
- 使用kubeconfig或token進行用戶身份認證
- Kubernetes中的用戶與身份認證授權
- Kubernetes集群安全性配置最佳實踐
- 訪問Kubernetes集群
- 訪問集群
- 使用kubeconfig文件配置跨集群認證
- 通過端口轉發訪問集群中的應用程序
- 使用service訪問群集中的應用程序
- 從外部訪問Kubernetes中的Pod
- Cabin - Kubernetes手機客戶端
- Kubernetic - Kubernetes桌面客戶端
- Kubernator - 更底層的Kubernetes UI
- 在Kubernetes中開發部署應用
- 適用于kubernetes的應用開發部署流程
- 遷移傳統應用到Kubernetes中——以Hadoop YARN為例
- 最佳實踐概覽
- 在CentOS上部署Kubernetes集群
- 創建TLS證書和秘鑰
- 創建kubeconfig文件
- 創建高可用etcd集群
- 安裝kubectl命令行工具
- 部署master節點
- 安裝flannel網絡插件
- 部署node節點
- 安裝kubedns插件
- 安裝dashboard插件
- 安裝heapster插件
- 安裝EFK插件
- 生產級的Kubernetes簡化管理工具kubeadm
- 使用kubeadm在Ubuntu Server 16.04上快速構建測試集群
- 服務發現與負載均衡
- 安裝Traefik ingress
- 分布式負載測試
- 網絡和集群性能測試
- 邊緣節點配置
- 安裝Nginx ingress
- 安裝配置DNS
- 安裝配置Kube-dns
- 安裝配置CoreDNS
- 運維管理
- Master節點高可用
- 服務滾動升級
- 應用日志收集
- 配置最佳實踐
- 集群及應用監控
- 數據持久化問題
- 管理容器的計算資源
- 集群聯邦
- 存儲管理
- GlusterFS
- 使用GlusterFS做持久化存儲
- 使用Heketi作為Kubernetes的持久存儲GlusterFS的external provisioner
- 在OpenShift中使用GlusterFS做持久化存儲
- GlusterD-2.0
- Ceph
- 用Helm托管安裝Ceph集群并提供后端存儲
- 使用Ceph做持久化存儲
- 使用rbd-provisioner提供rbd持久化存儲
- OpenEBS
- 使用OpenEBS做持久化存儲
- Rook
- NFS
- 利用NFS動態提供Kubernetes后端存儲卷
- 集群與應用監控
- Heapster
- 使用Heapster獲取集群和對象的metric數據
- Prometheus
- 使用Prometheus監控kubernetes集群
- Prometheus查詢語言PromQL使用說明
- 使用Vistio監控Istio服務網格中的流量
- 分布式跟蹤
- OpenTracing
- 服務編排管理
- 使用Helm管理Kubernetes應用
- 構建私有Chart倉庫
- 持續集成與發布
- 使用Jenkins進行持續集成與發布
- 使用Drone進行持續集成與發布
- 更新與升級
- 手動升級Kubernetes集群
- 升級dashboard
- 領域應用概覽
- 微服務架構
- 微服務中的服務發現
- 使用Java構建微服務并發布到Kubernetes平臺
- Spring Boot快速開始指南
- Service Mesh 服務網格
- 企業級服務網格架構
- Service Mesh基礎
- Service Mesh技術對比
- 采納和演進
- 定制和集成
- 總結
- Istio
- 安裝并試用Istio service mesh
- 配置請求的路由規則
- 安裝和拓展Istio service mesh
- 集成虛擬機
- Istio中sidecar的注入規范及示例
- 如何參與Istio社區及注意事項
- Istio教程
- Istio免費學習資源匯總
- 深入理解Istio Service Mesh中的Envoy Sidecar注入與流量劫持
- 深入理解Istio Service Mesh中的Envoy Sidecar代理的路由轉發
- Linkerd
- Linkerd 使用指南
- Conduit
- Condiut概覽
- 安裝Conduit
- Envoy
- Envoy的架構與基本術語
- Envoy作為前端代理
- Envoy mesh教程
- SOFAMesh
- SOFAMesh中的Dubbo on x-protocol
- SOFAMosn
- 使用 SOFAMosn 構建 SOFAMesh
- 大數據
- Spark standalone on Kubernetes
- 運行支持Kubernetes原生調度的Spark程序
- Serverless架構
- 理解Serverless
- FaaS-函數即服務
- OpenFaaS快速入門指南
- 邊緣計算
- 人工智能