kjh00abc 2020-05-31
文档: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
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 # 查看版本 [ 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‘
# 使用模板动态生成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
# 更新 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
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 [ ~]# 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
#添加 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 # 插看索引
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
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
###host字段指定授权使用该证书的etcd节点IP或子网列表,需要将etcd集群的3个节点都添加其中。cp etcd-v3.3.13-linux-amd64/etcd* /opt/k8s/bin/