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 服务器,如下图所示:

k8s学习-Helm

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

# 查看版本
[ 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
# 注意,必须在当前文件夹下面使用
# 文件夹结构
[ hello-word]# tree ./
./
├── Chart.yaml
└── templates
    ├── deployment.yaml
    └── service.yaml

# 运行chart
# --name 可指定一个固定的名字,如果没有指定,helm会生成一个随机的名字
# helm install --name <名字> .
[ 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

# 查看镜像版本
[ 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
# 再次查看镜像版本
[ 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
[ 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

[ 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

  1. MetricServer:是kubernetes集群资源使用情况的聚合器,收集数据给kubernetes集群内使用,如kubectl,hpa,scheduler等。

  2. PrometheusOperator:是一个系统监测和警报工具箱,用来存储监控数据。

  3. NodeExporter:用于各node的关键度量指标状态数据。

  4. KubeStateMetrics:收集kubernetes集群内资源对象数据,制定告警规则。

  5. Prometheus:采用pull方式收集apiserver,scheduler,controller-manager,kubelet组件数据,通过http协议传输。

  6. 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

[ ~]# 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

相关推荐