正文
Kubernetes的包管理工具Helm的安装和使用
小程序:扫一扫查出行
【扫一扫了解最新限行尾号】
复制小程序
【扫一扫了解最新限行尾号】
复制小程序
1.源码安装
[root@master ~]# wget https://storage.googleapis.com/kubernetes-helm/helm-v2.14.0-linux-amd64.tar.gz
[root@master ~]# tar -zxvf helm-v2.14.0-linux-amd64.tar.gz
linux-amd64/
linux-amd64/tiller
linux-amd64/README.md
linux-amd64/LICENSE
linux-amd64/helm
[root@master ~]# ls
anaconda-ks.cfg helm-v2.14.0-linux-amd64.tar.gz linux-amd64 token.txt
[root@master ~]# ls linux-amd64/
helm LICENSE README.md tiller
[root@master ~]# mv linux-amd64/helm /usr/bin
[root@master ~]# helm --help
2.脚本安装
[root@master ~]# curl -LO https://git.io/get_helm.sh
[root@master ~]# chmod get_helm.sh
[root@master ~]# ./get_helm.sh
//[root@master ~]# curl -L https://git.io/get_helm.sh | bash
2.1初始化
[root@master istio-1.1.]# helm init
[root@master istio-1.1.]# helm version
Client: &version.Version{SemVer:"v2.14.0", GitCommit:"05811b84a3f93603dd6c2fcfe57944dfa7ab7fd0", GitTreeState:"clean"}
Error: could not find a ready tiller pod
//gcr.io/kubernetes-helm/tiller:v2.11.0镜像被墙,无法下载
[root@master ~]# kubectl get pod -n kube-system
NAME READY STATUS RESTARTS AGE
coredns-fb8b8dccf-7dt66 / Running 14d
coredns-fb8b8dccf-7rt9b / Running 14d
etcd-master / Running 14d
kube-apiserver-master / Running 14d
kube-controller-manager-master / Running 14d
kube-flannel-ds-amd64-dpdws / Running 14d
kube-flannel-ds-amd64-k8xnf / Running 14d
kube-flannel-ds-amd64-kmc5h / Running 13d
kube-proxy-qjtsd / Running 14d
kube-proxy-t6lpf / Running 14d
kube-proxy-t77xh / Running 13d
kube-scheduler-master / Running 14d
tiller-deploy-765dcb8745-2vswr / ImagePullBackOff 18m
2.2解决办法1.helm reset
[root@master ~]# kubectl delete pod tiller-deploy-765dcb8745-2vswr -n kube-system
pod "tiller-deploy-765dcb8745-2vswr" deleted
[root@master istio-1.1.]# docker search tiller:v2.14.0
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
hekai/gcr.io_kubernetes-helm_tiller_v2.14.0 FROM gcr.io/kubernetes-helm/tiller:v2.14.0
//[root@master ~]# helm init --service-account tiller --tiller-image hekai/gcr.io_kubernetes-helm_tiller_v2.14.0 --skip-refresh
//[root@master ~]# helm init -i hekai/gcr.io_kubernetes-helm_tiller_v2.14.0
//更新tiller,使用docker上镜像
[root@master ~]# helm init --upgrade -i hekai/gcr.io_kubernetes-helm_tiller_v2.14.0
[root@master istio-1.1.]# helm version
Client: &version.Version{SemVer:"v2.14.0", GitCommit:"05811b84a3f93603dd6c2fcfe57944dfa7ab7fd0", GitTreeState:"clean"}
Server: &version.Version{SemVer:"v2.14.0", GitCommit:"05811b84a3f93603dd6c2fcfe57944dfa7ab7fd0", GitTreeState:"clean"}
tiller默认被部署在k8s集群中的kube-system这个namespace下
[root@master istio-1.1.]# kubectl get pod -n kube-system -l app=helm
NAME READY STATUS RESTARTS AGE
tiller-deploy-58f5d95b9c-vrbbg / Running 24h
3.给予helm的rbac管理权限
帮助:https://github.com/helm/helm/blob/master/docs/rbac.md
[root@master helm]# vim rbac-config.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: tiller
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: tiller
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: tiller
namespace: kube-system
[root@master helm]]# kubectl create -f rbac-config.yaml
serviceaccount "tiller" created
clusterrolebinding "tiller" created
[root@master helm]]# helm init --service-account tiller --history-max
[root@master ~]# helm init --upgrade -i hekai/gcr.io_kubernetes-helm_tiller_v2.14.0
[root@master helm]]# kubectl get sa -n kube-system
4.使用helm
//更新镜像仓库
[root@master helm]# helm repo update
//查看帮助
[root@master helm]# helm --help
//官方仓库,stable是稳定版,incubator预发版
https://hub.helm.sh/
https://hub.kubeapps.com
//查看使用哪些仓库
[root@master helm]# helm repo list
NAME URL
stable https://kubernetes-charts.storage.googleapis.com
local http://127.0.0.1:8879/charts常用命令,release管理:
//搜索镜像
[root@master helm]# helm search redis
[root@master helm]# helm install --name redis stable/redis
//安装时要事先准备好pv,下载安装的都在$HOME/.helm/cache/archive/目录下,把.tgz的文件解压然后tree redis查看
[root@master ~]# cd .helm/cache/archive/
[root@master archive]# ls
redis-8.0.5.tgz
[root@master archive]# tar -xzvf redis-8.0.5.tgz
[root@master archive]# ls
redis redis-8.0.5.tgz
[root@master archive]# cd redis/
[root@master redis]# ls
Chart.yaml ci README.md templates values-production.yaml values.yaml
//修改values.yaml,再根据values.yaml安装
[root@master helm]# helm install --name redis -f values.yaml stable/redis
[root@master helm]# helm status redis //此命令有用,用于安装完后需要做哪些操作都有步骤
[root@master helm]# helm history redis //可以用于回滚
[root@master helm]# helm list
NAME REVISION UPDATED STATUS CHART APP VERSION NAMESPACE
redis 1 Sat Jun 1 10:09:52 2019 DEPLOYED redis-8.0.5 5.0.5 default
[root@master helm]# helm delete --help
[root@master helm]# helm delete --dry-run
[root@master helm]# helm delete jenkins
[root@master helm]# helm upgrade/rollback //结合history用于回滚
[root@master helm]# helm upgrade nginx-ingress stable/nginx-ingress --namespace ingress-nginx --install -f values.yaml常用命令,chart管理:
[root@master helm]# helm create
//下载镜像
[root@master helm]# helm fetch
[root@master helm]# helm get
[root@master helm]# helm inspect stable/redis
//打包本地
[root@master helm]# helm package ./
[root@master archive]# tree redis
redis
├── Chart.yaml
├── ci
│ ├── default-values.yaml
│ ├── dev-values.yaml
│ ├── production-sentinel-values.yaml
│ ├── production-values.yaml
│ ├── redisgraph-module-values.yaml
│ └── redis-lib-values.yaml
├── README.md
├── templates
│ ├── configmap.yaml
│ ├── headless-svc.yaml
│ ├── health-configmap.yaml
│ ├── _helpers.tpl
│ ├── metrics-deployment.yaml
│ ├── metrics-prometheus.yaml
│ ├── metrics-svc.yaml
│ ├── networkpolicy.yaml
│ ├── NOTES.txt
│ ├── redis-master-statefulset.yaml
│ ├── redis-master-svc.yaml
│ ├── redis-rolebinding.yaml
│ ├── redis-role.yaml
│ ├── redis-serviceaccount.yaml
│ ├── redis-slave-statefulset.yaml
│ ├── redis-slave-svc.yaml
│ ├── redis-with-sentinel-svc.yaml
│ └── secret.yaml
├── values-production.yaml
└── values.yaml
directories, files
//模板语法
[root@master archive]# cat redis/templates/redis-master-statefulset.yaml
apiVersion: apps/v1beta2
kind: StatefulSet
metadata:
name: {{ template "redis.fullname" . }}-master
labels:
app: {{ template "redis.name" . }}
chart: {{ template "redis.chart" . }}
release: "{{ .Release.Name }}"
heritage: "{{ .Release.Service }}"
spec:
selector:
matchLabels:
release: "{{ .Release.Name }}"
role: master
app: {{ template "redis.name" . }}
serviceName: {{ template "redis.fullname" . }}-headless
template:
metadata:
labels:
release: "{{ .Release.Name }}"
chart: {{ template "redis.chart" . }}
role: master
app: {{ template "redis.name" . }}
{{- if .Values.master.podLabels }}
{{ toYaml .Values.master.podLabels | indent }}
{{- end }}
annotations:
checksum/health: {{ include (print $.Template.BasePath "/health-configmap.yaml") . | sha256sum }}
checksum/configmap: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }}
checksum/secret: {{ include (print $.Template.BasePath "/secret.yaml") . | sha256sum }}
{{- if .Values.master.podAnnotations }}
{{ toYaml .Values.master.podAnnotations | indent }}
{{- end }}
spec:
{{- include "redis.imagePullSecrets" . | indent }}
{{- if .Values.securityContext.enabled }}
securityContext:
fsGroup: {{ .Values.securityContext.fsGroup }}
{{- end }}
serviceAccountName: "{{ template "redis.serviceAccountName" . }}"
{{- if .Values.master.priorityClassName }}
priorityClassName: "{{ .Values.master.priorityClassName }}"
{{- end }}
{{- with .Values.master.affinity }}
affinity:
{{ tpl (toYaml .) $ | indent }}
{{- end }}
{{- if .Values.master.nodeSelector }}
nodeSelector:
{{ toYaml .Values.master.nodeSelector | indent }}
{{- end }}
{{- if .Values.master.tolerations }}
tolerations:
{{ toYaml .Values.master.tolerations | indent }}
{{- end }}
{{- if .Values.master.schedulerName }}
schedulerName: "{{ .Values.master.schedulerName }}"
{{- end }}
containers:
- name: {{ template "redis.fullname" . }}
image: "{{ template "redis.image" . }}"
imagePullPolicy: {{ .Values.image.pullPolicy | quote }}
{{- if .Values.securityContext.enabled }}
securityContext:
runAsUser: {{ .Values.securityContext.runAsUser }}
{{- end }}
command:
- /bin/bash
- -c
- |
if [[ -n $REDIS_PASSWORD_FILE ]]; then
password_aux=`cat ${REDIS_PASSWORD_FILE}`
export REDIS_PASSWORD=$password_aux
fi
if [[ ! -f /opt/bitnami/redis/etc/master.conf ]];then
cp /opt/bitnami/redis/mounted-etc/master.conf /opt/bitnami/redis/etc/master.conf
fi
if [[ ! -f /opt/bitnami/redis/etc/redis.conf ]];then
cp /opt/bitnami/redis/mounted-etc/redis.conf /opt/bitnami/redis/etc/redis.conf
fi
ARGS=("--port" "${REDIS_PORT}")
{{- if .Values.usePassword }}
ARGS+=("--requirepass" "${REDIS_PASSWORD}")
{{- else }}
ARGS+=("--protected-mode" "no")
{{- end }}
ARGS+=("--include" "/opt/bitnami/redis/etc/redis.conf")
ARGS+=("--include" "/opt/bitnami/redis/etc/master.conf")
{{- if .Values.master.command }}
{{ .Values.master.command }} ${ARGS[@]}
{{- else }}
redis-server "${ARGS[@]}"
{{- end }}
env:
- name: REDIS_REPLICATION_MODE
value: master
{{- if .Values.usePassword }}
{{- if .Values.usePasswordFile }}
- name: REDIS_PASSWORD_FILE
value: "/opt/bitnami/redis/secrets/redis-password"
{{- else }}
- name: REDIS_PASSWORD
valueFrom:
secretKeyRef:
name: {{ template "redis.secretName" . }}
key: redis-password
{{- end }}
{{- else }}
- name: ALLOW_EMPTY_PASSWORD
value: "yes"
{{- end }}
- name: REDIS_PORT
value: {{ .Values.redisPort | quote }}
ports:
- name: redis
containerPort: {{ .Values.redisPort }}
{{- if .Values.master.livenessProbe.enabled }}
livenessProbe:
initialDelaySeconds: {{ .Values.master.livenessProbe.initialDelaySeconds }}
periodSeconds: {{ .Values.master.livenessProbe.periodSeconds }}
timeoutSeconds: {{ .Values.master.livenessProbe.timeoutSeconds }}
successThreshold: {{ .Values.master.livenessProbe.successThreshold }}
failureThreshold: {{ .Values.master.livenessProbe.failureThreshold }}
exec:
command:
- sh
- -c
- /health/ping_local.sh {{ .Values.master.livenessProbe.timeoutSeconds }}
{{- end }}
{{- if .Values.master.readinessProbe.enabled}}
readinessProbe:
initialDelaySeconds: {{ .Values.master.readinessProbe.initialDelaySeconds }}
periodSeconds: {{ .Values.master.readinessProbe.periodSeconds }}
timeoutSeconds: {{ .Values.master.readinessProbe.timeoutSeconds }}
successThreshold: {{ .Values.master.readinessProbe.successThreshold }}
failureThreshold: {{ .Values.master.readinessProbe.failureThreshold }}
exec:
command:
- sh
- -c
- /health/ping_local.sh {{ .Values.master.livenessProbe.timeoutSeconds }}
{{- end }}
resources:
{{ toYaml .Values.master.resources | indent }}
volumeMounts:
- name: health
mountPath: /health
{{- if .Values.usePasswordFile }}
- name: redis-password
mountPath: /opt/bitnami/redis/secrets/
{{- end }}
- name: redis-data
mountPath: {{ .Values.master.persistence.path }}
subPath: {{ .Values.master.persistence.subPath }}
- name: config
mountPath: /opt/bitnami/redis/mounted-etc
- name: redis-tmp-conf
mountPath: /opt/bitnami/redis/etc/
{{- if and .Values.cluster.enabled .Values.sentinel.enabled }}
- name: sentinel
image: "{{ template "sentinel.image" . }}"
imagePullPolicy: {{ .Values.sentinel.image.pullPolicy | quote }}
{{- if .Values.securityContext.enabled }}
securityContext:
runAsUser: {{ .Values.securityContext.runAsUser }}
{{- end }}
command:
- /bin/bash
- -c
- |
if [[ -n $REDIS_PASSWORD_FILE ]]; then
password_aux=`cat ${REDIS_PASSWORD_FILE}`
export REDIS_PASSWORD=$password_aux
fi
if [[ ! -f /opt/bitnami/redis-sentinel/etc/sentinel.conf ]];then
cp /opt/bitnami/redis-sentinel/mounted-etc/sentinel.conf /opt/bitnami/redis-sentinel/etc/sentinel.conf
{{- if .Values.usePassword }}
printf "\nsentinel auth-pass {{ .Values.sentinel.masterSet }} $REDIS_PASSWORD" >> /opt/bitnami/redis-sentinel/etc/sentinel.conf
{{- end }}
fi
echo "Getting information about current running sentinels"
# Get information from existing sentinels
existing_sentinels=$(timeout -s {{ .Values.sentinel.initialCheckTimeout }} redis-cli --raw -h {{ template "redis.fullname" . }} -a $REDIS_PASSWORD -p {{ .Values.sentinel.service.sentinelPort }} SENTINEL sentinels {{ .Values.sentinel.masterSet }})
echo "$existing_sentinels" | awk -f /health/parse_sentinels.awk | tee -a /opt/bitnami/redis-sentinel/etc/sentinel.conf redis-server /opt/bitnami/redis-sentinel/etc/sentinel.conf --sentinel
env:
{{- if .Values.usePassword }}
{{- if .Values.usePasswordFile }}
- name: REDIS_PASSWORD_FILE
value: "/opt/bitnami/redis/secrets/redis-password"
{{- else }}
- name: REDIS_PASSWORD
valueFrom:
secretKeyRef:
name: {{ template "redis.secretName" . }}
key: redis-password
{{- end }}
{{- else }}
- name: ALLOW_EMPTY_PASSWORD
value: "yes"
{{- end }}
- name: REDIS_SENTINEL_PORT
value: {{ .Values.sentinel.port | quote }}
ports:
- name: redis-sentinel
containerPort: {{ .Values.sentinel.port }}
{{- if .Values.sentinel.livenessProbe.enabled }}
livenessProbe:
initialDelaySeconds: {{ .Values.sentinel.livenessProbe.initialDelaySeconds }}
periodSeconds: {{ .Values.sentinel.livenessProbe.periodSeconds }}
timeoutSeconds: {{ .Values.sentinel.livenessProbe.timeoutSeconds }}
successThreshold: {{ .Values.sentinel.livenessProbe.successThreshold }}
failureThreshold: {{ .Values.sentinel.livenessProbe.failureThreshold }}
exec:
command:
- sh
- -c
- /health/ping_sentinel.sh {{ .Values.sentinel.livenessProbe.timeoutSeconds }}
{{- end }}
{{- if .Values.sentinel.readinessProbe.enabled}}
readinessProbe:
initialDelaySeconds: {{ .Values.sentinel.readinessProbe.initialDelaySeconds }}
periodSeconds: {{ .Values.sentinel.readinessProbe.periodSeconds }}
timeoutSeconds: {{ .Values.sentinel.readinessProbe.timeoutSeconds }}
successThreshold: {{ .Values.sentinel.readinessProbe.successThreshold }}
failureThreshold: {{ .Values.sentinel.readinessProbe.failureThreshold }}
exec:
command:
- sh
- -c
- /health/ping_sentinel.sh {{ .Values.sentinel.livenessProbe.timeoutSeconds }}
{{- end }}
resources:
{{ toYaml .Values.sentinel.resources | indent }}
volumeMounts:
- name: health
mountPath: /health
{{- if .Values.usePasswordFile }}
- name: redis-password
mountPath: /opt/bitnami/redis/secrets/
{{- end }}
- name: redis-data
mountPath: {{ .Values.master.persistence.path }}
subPath: {{ .Values.master.persistence.subPath }}
- name: config
mountPath: /opt/bitnami/redis-sentinel/mounted-etc
- name: sentinel-tmp-conf
mountPath: /opt/bitnami/redis-sentinel/etc/
{{- end }}
{{- $needsVolumePermissions := and .Values.volumePermissions.enabled (and ( and .Values.master.persistence.enabled (not .Values.persistence.existingClaim) ) .Values.securityContext.enabled) }}
{{- if or $needsVolumePermissions .Values.sysctlImage.enabled }}
initContainers:
{{- if $needsVolumePermissions }}
- name: volume-permissions
image: "{{ template "redis.volumePermissions.image" . }}"
imagePullPolicy: {{ .Values.volumePermissions.image.pullPolicy | quote }}
command: ["/bin/chown", "-R", "{{ .Values.securityContext.runAsUser }}:{{ .Values.securityContext.fsGroup }}", "{{ .Values.master.persistence.path }}"]
securityContext:
runAsUser:
resources:
{{ toYaml .Values.volumePermissions.resources | indent }}
volumeMounts:
- name: redis-data
mountPath: {{ .Values.master.persistence.path }}
subPath: {{ .Values.master.persistence.subPath }}
{{- end }}
{{- if .Values.sysctlImage.enabled }}
- name: init-sysctl
image: {{ template "redis.sysctl.image" . }}
imagePullPolicy: {{ default "" .Values.sysctlImage.pullPolicy | quote }}
resources:
{{ toYaml .Values.sysctlImage.resources | indent }}
{{- if .Values.sysctlImage.mountHostSys }}
volumeMounts:
- name: host-sys
mountPath: /host-sys
{{- end }}
command:
{{ toYaml .Values.sysctlImage.command | indent }}
securityContext:
privileged: true
runAsUser:
{{- end }}
{{- end }}
volumes:
- name: health
configMap:
name: {{ template "redis.fullname" . }}-health
defaultMode:
{{- if .Values.usePasswordFile }}
- name: redis-password
secret:
secretName: {{ template "redis.secretName" . }}
{{- end }}
- name: config
configMap:
name: {{ template "redis.fullname" . }}
{{- if not .Values.master.persistence.enabled }}
- name: "redis-data"
emptyDir: {}
{{- else }}
{{- if .Values.persistence.existingClaim }}
- name: "redis-data"
persistentVolumeClaim:
claimName: {{ .Values.persistence.existingClaim }}
{{- end }}
{{- end }}
{{- if .Values.sysctlImage.mountHostSys }}
- name: host-sys
hostPath:
path: /sys
{{- end }}
- name: redis-tmp-conf
emptyDir: {}
{{- if and .Values.cluster.enabled .Values.sentinel.enabled }}
- name: sentinel-tmp-conf
emptyDir: {}
{{- end }}
{{- if and .Values.master.persistence.enabled (not .Values.persistence.existingClaim) }}
volumeClaimTemplates:
- metadata:
name: redis-data
labels:
app: "{{ template "redis.name" . }}"
component: "master"
release: {{ .Release.Name | quote }}
heritage: {{ .Release.Service | quote }}
spec:
accessModes:
{{- range .Values.master.persistence.accessModes }}
- {{ . | quote }}
{{- end }}
resources:
requests:
storage: {{ .Values.master.persistence.size | quote }}
{{- if .Values.master.persistence.storageClass }}
{{- if (eq "-" .Values.master.persistence.storageClass) }}
storageClassName: ""
{{- else }}
storageClassName: {{ .Values.master.persistence.storageClass | quote }}
{{- end }}
{{- end }}
{{- end }}
updateStrategy:
type: {{ .Values.master.statefulset.updateStrategy }}
{{- if .Values.master.statefulset.rollingUpdatePartition }}
{{- if (eq "Recreate" .Values.master.statefulset.updateStrategy) }}
rollingUpdate: null
{{- else }}
rollingUpdate:
partition: {{ .Values.master.statefulset.rollingUpdatePartition }}
{{- end }}
{{- end }}
用法:
https://helm.sh/docs/
https://www.kubernetes.org.cn/3435.html