k8s学习-Helm
4.9、Helm
4.9.1、简单使用
概念
文档:https://github.com/helm/helm/blob/master/docs/charts.md
阿里云apphub:https://developer.aliyun.com/hub/
在没使用 helm 之前,向 kubernetes 部署应用,我们要依次部署 deployment、svc 等,步骤较繁琐。况且随着很多项目微服务化,复杂的应用在容器中部署以及管理显得较为复杂,helm 通过打包的方式,支持发布的版本管理和控制,很大程度上简化了 Kubernetes 应用的部署和管理
Helm 本质就是让 K8s 的应用管理(Deployment,Service 等 ) 可配置,能动态生成。通过动态生成 K8s 资源清单文件(deployment.yaml,service.yaml)。然后调用 Kubectl 自动执行 K8s 资源部署
Helm 是官方提供的类似于 YUM 的包管理器,是部署环境的流程封装。Helm 有两个重要的概念:chart 和release
- chart 是创建一个应用的信息集合,包括各种 Kubernetes 对象的配置模板、参数定义、依赖关系、文档说明等。chart 是应用部署的自包含逻辑单元。可以将 chart 想象成 apt、yum 中的软件安装包
- release 是 chart 的运行实例,代表了一个正在运行的应用。当 chart 被安装到 Kubernetes 集群,就生成一个 release。chart 能够多次安装到同一个集群,每次安装都是一个 release
Helm 包含两个组件:Helm 客户端和 Tiller 服务器,如下图所示:
Helm 客户端负责 chart 和 release 的创建和管理以及和 Tiller 的交互。Tiller 服务器运行在 Kubernetes 集群中,它会处理 Helm 客户端的请求,与 Kubernetes API Server 交互
安装
wget https://storage.googleapis.com/kubernetes-helm/helm-v2.13.1-linux-amd64.tar.gz
tar -zxvf helm-v2.13.1-linux-amd64.tar.gz
cd linux-amd64/
cp helm /usr/local/bin/
# 安装 helm-tiller的docker镜像(k8s节点上都pull)
docker pull gcr.io/kubernetes-helm/tiller:v2.13.1
# 如果安装不下来的可以从阿里云的镜像仓库中下载
https://cr.console.aliyun.com/cn-hangzhou/instances/repositories
# 搜索:kubernetes-helm/tiller 然后 pull 下来在后修改tag
docker pull registry.cn-hangzhou.aliyuncs.com/marico/gcr.io_kubernetes-helm_tiller
docker tag registry.cn-hangzhou.aliyuncs.com/marico/gcr.io_kubernetes-helm_tiller:v2.13.1 gcr.io/kubernetes-helm/tiller:v2.13.1
因为 Kubernetes APIServer 开启了 RBAC 访问控制,所以需要创建 tiller 使用的 service account: tiller 并分配合适的角色给它。详细内容可以查看helm文档中的Role-based Access Control。这里简单起见直接分配cluster- admin 这个集群内置的 ClusterRole 给它。创建 rbac-config.yaml
文件
mkdir -p /usr/local/docker/kubernetes/plugins/test/helm
cd /usr/local/docker/kubernetes/plugins/test/helm
vim rbac-config.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: tiller
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
name: tiller
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: tiller
namespace: kube-system
kubectl create -f rbac-config.yaml
helm init --service-account tiller --skip-refresh
# 查看版本
[root@k8s-master helm]# helm version
Client: &version.Version{SemVer:"v2.13.1", GitCommit:"618447cbf203d147601b4b9bd7f8c37a5d39fbb4", GitTreeState:"clean"}
Server: &version.Version{SemVer:"v2.13.1", GitCommit:"618447cbf203d147601b4b9bd7f8c37a5d39fbb4", GitTreeState:"clean"}
tiller 默认被部署在 k8s 集群中的 kube-system 这个namespace 下:
kubectl get pod -n kube-system -l app=helm
NAME READY STATUS RESTARTS AGE
tiller-deploy-58565b5464-rdq68 1/1 Running 0 42s
自定义模板
mkdir -p /usr/local/docker/kubernetes/plugins/test/helm/hello-word
cd /usr/local/docker/kubernetes/plugins/test/helm/hello-word
# 创建自描述文件 Chart.yaml , 这个文件必须有 name 和 version 定义
cat > Chart.yaml <<EOF
name: hello-world
version: 1.0.0
EOF
创建模板文件,用于生成 Kubernetes 资源清单(manifests)
# 必须是 templates文件夹名字
mkdir ./templates
vim ./templates/deployment.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: hello-world
spec:
replicas: 1
template:
metadata:
labels:
app: hello-world
spec:
containers:
- name: hello-world
image: habor-repo.com/library/nginx:v1
ports:
- containerPort: 80
protocol: TCP
vim ./templates/service.yaml
apiVersion: v1
kind: Service
metadata:
name: hello-world
spec:
type: NodePort
selector:
app: hello-world
ports:
- name: http
port: 8000
targetPort: 80
protocol: TCP
# 使用命令 helm install RELATIVE_PATH_TO_CHART 创建一次Release
# 注意,必须在当前文件夹下面使用
# 文件夹结构
[root@k8s-master hello-word]# tree ./
./
├── Chart.yaml
└── templates
├── deployment.yaml
└── service.yaml
# 运行chart
# --name 可指定一个固定的名字,如果没有指定,helm会生成一个随机的名字
# helm install --name <名字> .
[root@k8s-master hello-word]# helm install .
NAME: bold-termite
LAST DEPLOYED: Tue Mar 10 11:29:02 2020
NAMESPACE: default
STATUS: DEPLOYED
RESOURCES:
==> v1/Pod(related)
NAME READY STATUS RESTARTS AGE
hello-world-6fd86c7d6d-xzcdn 0/1 ContainerCreating 0 0s
==> v1/Service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
hello-world NodePort 10.101.112.26 <none> 8000:32503/TCP 1s
==> v1beta1/Deployment
NAME READY UP-TO-DATE AVAILABLE AGE
hello-world 0/1 1 0 0s
常用命令:
# 列出已经部署的 Release
helm ls
# 查询一个特定的 Release 的状态
helm status <RELEASE_NAME>
# 移除所有与这个 Release 相关的 Kubernetes 资源
helm delete <RELEASE_NAME>
# 查看历史
helm history <RELEASE_NAME>
# 回滚版本(回滚后版本会加1)
helm rollback <RELEASE_NAME> <REVISION_NUMBER>
# (完全删除!!!)
# 使用 helm delete --purge RELEASE_NAME 移除所有与指定 Release 相关的 Kubernetes 资源和所有这个Release 的记录
helm delete --purge <RELEASE_NAME>
helm ls --deleted # 发现没有了
版本升级:
对于已经创建好的release资源我们想要升级其中容器镜像的版本:
在Chart.yaml
同级中创建values.yaml
cat >values.yaml <<EOF
image:
repository: habor-repo.com/library/nginx
tag: v1
EOF
然后修改templates/deployment.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: hello-world
spec:
replicas: 1
template:
metadata:
labels:
app: hello-world
spec:
containers:
- name: hello-world
image: {{.Values.image.repository}}:{{.Values.image.tag}}
ports:
- containerPort: 80
protocol: TCP
# install
helm install --name hello-world .
# 查看版本
helm ls
# 查看镜像版本
[root@k8s-master hello-word]# kubectl get deploy hello-world -o wide
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
hello-world 1/1 1 1 2m hello-world habor-repo.com/library/nginx:v1 app=hello-world
# 把 values.yaml 中的tag修改为v2
# 升级版本
helm upgrade hello-world .
# 查看版本发现成了2
helm ls
# 再次查看镜像版本
[root@k8s-master hello-word]# kubectl get deploy hello-world -o wide
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
hello-world 1/1 1 1 2m22s hello-world habor-repo.com/library/nginx:v2 app=hello-world
# 注意!!!还有个命令行修改版本的方式
# 在 values.yaml 中的值可以被部署 release 时用到的参数 --values YAML_FILE_PATH 或 --setkey1=value1, key2=value2 覆盖掉
helm upgrade hello-world . --set image.tag='v3'
debug
# 使用模板动态生成K8s资源清单,非常需要能提前预览生成的结果。
# 使用--dry-run --debug 选项来打印出生成的清单文件
helm install --name hello-world . --dry-run --debug --set image.tag=latest
使用国内镜像
helm repo remove stable
helm repo add apphub https://apphub.aliyuncs.com/
helm repo add incubator http://mirror.azure.cn/kubernetes/charts-incubator/
helm repo add elastic https://helm.elastic.co
helm repo add stable http://mirror.azure.cn/kubernetes/charts/
helm repo list
4.9.2、dashboard安装
helm方式安装
# 更新 helm 仓库
helm repo update
# 查看helm仓库
helm repo list
# 下载镜像(如果下载不下来上阿里云下载后修改tag即可)
docker pull k8s.gcr.io/kubernetes-dashboard-amd64
mkdir -p /usr/local/docker/kubernetes/plugins/test/helm/dashboard
cd /usr/local/docker/kubernetes/plugins/test/helm/dashboard
# 导入资源
helm fetch stable/kubernetes-dashboard
vim kubernetes-dashboard.yaml
image:
repository: k8s.gcr.io/kubernetes-dashboard-amd64
tag: v1.10.1
ingress:
enabled: true
hosts:
- k8s.frognew.com
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
tls:
- secretName: frognew-com-tls-secret
hosts:
- k8s.frognew.com
rbac:
clusterAdminRole: true
helm install . \
-n kubernetes-dashboard \
--namespace kube-system \
-f kubernetes-dashboard.yaml
# 修改 ClusterIp 为 NodePort
kubectl edit svc kubernetes-dashboard -n kube-system
# 查看token
kubectl -n kube-system get secret | grep kubernetes-dashboard-token
# 访问浏览器使用token登录
kubectl get secret -n kube-system | grep dashboard
kubectl describe -n kube-system
# 复制上面的token (端口为你修改我NodePort之后的为准)
https://192.168.0.120:30443
直接安装
# 下载镜像
docker pull k8s.gcr.io/kubernetes-dashboard-amd64:v1.10.1
https://github.com/kubernetes/dashboard/blob/v1.10.1/src/deploy/recommended/kubernetes-dashboard.yaml
# 下载 kubernetes-dashboard.yaml
kubectl apply -f kubernetes-dashboard.yaml
# 查看服务
kubectl get svc -n kube-system | grep dashboard
kubectl get deploy -n kube-system | grep dashboard
kubectl get pod -n kube-system | grep dashboard
# 删除(如果出现异常情况删除重来)
kubectl delete svc kubernetes-dashboard -n kube-system
kubectl delete deploy kubernetes-dashboard -n kube-system
重新创建一个可以供外网访问的Service
vim kubernetes-dashboard-service.yaml
apiVersion: v1
kind: Service
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard-service
namespace: kube-system
spec:
clusterIP: 10.97.242.98 # 这的IP不能上面svc的ip相同
externalTrafficPolicy: Cluster
ports:
- nodePort: 30443 # 暴露的外网IP
port: 443
protocol: TCP
targetPort: 8443 # dashboard的默认端口
selector:
k8s-app: kubernetes-dashboard
sessionAffinity: None
type: NodePort
status:
loadBalancer: {}
kubectl create -f kubernetes-dashboard-service.yaml
[root@k8s-master dashboard]# kubectl get svc -n kube-system | grep dashboard
kubernetes-dashboard ClusterIP 10.97.242.97 <none> 443/TCP 3m32s
kubernetes-dashboard-service NodePort 10.97.242.98 <none> 443:30443/TCP 14s
创建一个ServiceAccount:
vim service-account.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: dashboard
namespace: kube-system
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: dashboard
subjects:
- kind: ServiceAccount
name: dashboard
namespace: kube-system
roleRef:
kind: ClusterRole
name: cluster-admin
apiGroup: rbac.authorization.k8s.io
kubectl create -f service-account.yaml
[root@k8s-master dashboard]# kubectl get secret -n kube-system | grep dashboard
dashboard-token-tsxsg kubernetes.io/service-account-token 3 32s
kubernetes-dashboard-certs Opaque 0 33m
kubernetes-dashboard-key-holder Opaque 2 6m45s
kubernetes-dashboard-token-mrxz2 kubernetes.io/service-account-token 3 33m
# dashboard-token-tsxsg 这个理以你自己的为准
kubectl describe secret dashboard-token-tsxsg -n kube-system
# 复制token登录 (因为是NodePort,所以k8s任意节点IP都可以登录)
https://192.168.0.120:30443
4.9.3、Prometheus
github 地址:https://github.com/coreos/kube-prometheus
-
MetricServer:是kubernetes集群资源使用情况的聚合器,收集数据给kubernetes集群内使用,如kubectl,hpa,scheduler等。
-
PrometheusOperator:是一个系统监测和警报工具箱,用来存储监控数据。
-
NodeExporter:用于各node的关键度量指标状态数据。
-
KubeStateMetrics:收集kubernetes集群内资源对象数据,制定告警规则。
-
Prometheus:采用pull方式收集apiserver,scheduler,controller-manager,kubelet组件数据,通过http协议传输。
-
Grafana:是可视化数据统计和监控平台
# 拉镜像
quay.io/prometheus/prometheus:v2.11.0
quay.io/prometheus/alertmanager:v0.18.0
quay.io/coreos/prometheus-config-reloader:v0.31.1
quay.io/coreos/prometheus-operator:v0.31.1
quay.io/prometheus/node-exporter:v0.18.1
quay.io/coreos/k8s-prometheus-adapter-amd64:v0.4.1
k8s.gcr.io/addon-resizer:1.8.4
quay.io/coreos/configmap-reload:v0.0.1
grafana/grafana:6.2.2
quay.io/coreos/kube-rbac-proxy:v0.4.1
quay.io/coreos/kube-state-metrics:v1.7.1
# 修改yaml文件
git clone https://github.com/coreos/kube-prometheus.git
cd kube-prometheus/manifests
vim grafana-service.yaml
apiVersion: v1
kind: Service
metadata:
labels:
app: grafana
name: grafana
namespace: monitoring
spec:
type: NodePort # 修改
ports:
- name: http
port: 3000
targetPort: http
nodePort: 30100 # 修改
selector:
app: grafana
vim prometheus-service.yaml
apiVersion: v1
kind: Service
metadata:
labels:
prometheus: k8s
name: prometheus-k8s
namespace: monitoring
spec:
type: NodePort # 修改
ports:
- name: web
port: 9090
targetPort: web
nodePort: 30200 # 修改
selector:
app: prometheus
prometheus: k8s
sessionAffinity: ClientIP
vim alertmanager-service.yaml
apiVersion: v1
kind: Service
metadata:
labels:
alertmanager: main
name: alertmanager-main
namespace: monitoring
spec:
type: NodePort
ports:
- name: web
port: 9093
targetPort: web
nodePort: 30300 # 修改
selector:
alertmanager: main
app: alertmanager
sessionAffinity: ClientIP
cd kube-prometheus/manifests
kubectl apply -f ./
# 查看所有的pod都为running状态(启动的pod比较多,需等待一会儿)
kubectl get pod -n monitoring
[root@k8s-master ~]# kubectl get svc -n monitoring | grep NodePort
alertmanager-main NodePort 10.96.149.134 <none> 9093:30300/TCP 81m
grafana NodePort 10.101.118.123 <none> 3000:30100/TCP 90m
prometheus-k8s NodePort 10.100.22.169 <none> 9090:30200/TCP 90m
#浏览器访 prometheus
http://192.168.0.110:30200
#prometheus 的 WEB 界面上提供了基本的查询 K8S 集群中每个 POD 的 CPU 使用情况,查询条件如下:
sum by (pod_name)( rate(container_cpu_usage_seconds_total{image!="", pod_name!=""}[1m] ) )
# 访问 grafana 默认用户名密码都是admin,登录成功后会提示修改密码
http://192.168.0.110:30100
4.9.4、EFK日志收集
1)部署elasticsearch
#添加 Google incubator 仓库
helm repo remove stable # 删除 stable
helm repo add incubator http://mirror.azure.cn/kubernetes/charts-incubator/
helm repo add elastic https://helm.elastic.co
helm repo add stable http://mirror.azure.cn/kubernetes/charts/
helm repo list
# 创建文件夹
mkdir -p /usr/local/docker/kubernetes/plugins/test/efk/es
cd /usr/local/docker/kubernetes/plugins/test/efk/es
# k8s日志文件位置(每个节点都一样的,此处在安装的时候可以配置为nfs共享文件)
/var/log/containers/
#部署 Elasticsearch
# 创建名称空间
kubectl create namespace efk
helm fetch incubator/elasticsearch
# googl的拉不下来就用 elastic 的repo
helm fetch elastic/elasticsearch --version 6.4.2
# 解压缩
tar -zxvf elasticsearch-6.4.2.tgz
cd elasticsearch
# 修改一些参数(如果你的机器性能足够就不需要修改)
vim values.yaml
minimumMasterNodes: 1
replicas: 1
volumeClaimTemplate:
accessModes: [ "ReadWriteOnce" ]
storageClassName: "standard"
resources:
requests:
storage 10Gi # 修改为10Gi
# 然后保存并退出
# 添加一个PV大小为10Gi
# 查看配置说明:kubectl explain PersistentVolume.spec.hostPath
# 在所有的node节点创建 /data/es 并赋权限
mkdir -p /data/es
chmod 777 /data/es
# pv 定义
cat >es-pv.yml << EOF
apiVersion: v1
kind: PersistentVolume
metadata:
name: es-pv-10gi
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce # 这里和 values.yaml 中的保持一致
persistentVolumeReclaimPolicy: Recycle # 回收策略,这里是基础擦除 rm-rf /thevolume/*
storageClassName: standard # 这里和 values.yaml 中的保持一致
hostPath:
path: /data/es # 在所有的node节点创建 /data/es
EOF
# 创建
kubectl create -f es-pv.yml
# 查看
kubectl get pv
# 先拉取一下镜像
cat values.yaml | grep image # 插看image和版本
# 拉不下来去阿里云搜索参考 https://mp.weixin.qq.com/s/kf0SrktAze3bT7LcIveDYw
docker pull docker.elastic.co/elasticsearch/elasticsearch:6.4.2
# 安装
helm install --name els1 --namespace=efk -f values.yaml .
# 查看
kubectl get svc -n efk
kubectl get deploy -n efk
kubectl get pod -n efk -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
elasticsearch-master-0 1/1 Running 0 82s 10.244.2.224 k8s-node2 <none> <none>
# 检测
curl http://10.244.2.224:9200/_cat/nodes # 查看节点
# 10.244.2.224 11 96 2 0.00 0.10 0.14 mdi * elasticsearch-master-0
curl http://10.244.2.224:9200/_cat/indices # 插看索引
2)部署 Fluentd
helm fetch stable/fluentd-elasticsearch --version 2.0.7
tar -zxvf fluentd-elasticsearch-2.0.7.tgz
cd fluentd-elasticsearch
# 更改其中 Elasticsearch 访问地址
vim values.yaml
helm install --name flu1 --namespace=efk -f values.yaml .
# 查看
kubectl get svc -n efk
kubectl get deploy -n efk
kubectl get pod -n efk -o wide
3)部署kibana
helm fetch elastic/kibana --version 6.4.2
cd kibana
# 修改es地址
vim values.yaml
elasticsearchURL: "http://10.101.190.94:9200"
#保存并退出
helm install --name kib1 --namespace=efk -f values.yaml .
# 查看
kubectl get svc -n efk
kubectl get deploy -n efk
kubectl get pod -n efk -o wide
# 修改为 NodePort
kubectl edit svc kib1-kibana -n efk
# 查看IP地址
kubectl get svc -n efk | grep kibana
kib1-kibana NodePort 10.104.33.70 <none> 5601:32151/TCP 20m
# 访问浏览器
http://192.168.0.110:32151/app/kibana#/home?_g=()
删除
# 查看所有的
helm list
NAME REVISION UPDATED STATUS CHART APP VERSION NAMESPACE
els1 1 Tue Mar 10 18:50:09 2020 DEPLOYED elasticsearch-6.4.2 6.4.2 efk
flu1 1 Tue Mar 10 20:27:24 2020 DEPLOYED fluentd-elasticsearch-2.0.7 2.3.2 efk
hello-world 2 Tue Mar 10 11:57:06 2020 DEPLOYED hello-world-1.0.0 default
kib1 1 Tue Mar 10 19:50:35 2020 DEPLOYED kibana-6.4.2 6.4.2 efk
# 删除
helm delete els1 flu1 hello-world kib1