仓库
Helm 的 Repo 仓库和 Docker Registry 比较类似,Chart 库可以用来存储和共享打包 Chart 的位置,我们在安装了 Helm 后,默认的仓库地址是 google 的一个地址,拉取应用很难成功。通过阿里云镜像安装的服务器端可以看到已经安装了很多charts。
修改charts地址为阿里云地址。(注:上一节https://www.jianshu.com/p/3cc3de00dad0我们安装tiller时已经指定,可通过helm repo list查看)
$ helm repo list
NAME URL
stable https://kubernetes-charts.storage.googleapis.com/
local http://127.0.0.1:8879/charts
除了一个默认的 stable 的仓库配置外,还有一个 local 的本地仓库,这是我们本地测试的一个仓库地址。
设置helm仓库地址为阿里云的仓库地址
$ helm repo remove stable
"stable" has been removed from your repositories
$ helm repo add 存储库名 存储库URL
例如添加阿里云的仓库地址
$ helm init --client-only --stable-repo-url https://aliacs-app-catalog.oss-cn-hangzhou.aliyuncs.com/charts/
$ helm repo add repo_name1 https://aliacs-app-catalog.oss-cn-hangzhou.aliyuncs.com/charts-incubator/
仓库添加完成后,可以使用 update 命令进行仓库更新。
$ helm repo update
Hang tight while we grab the latest from your chart repositories...
...Skip local chart repository
...Successfully got an update from the "stable" chart repository
Update Complete. ⎈ Happy Helming!⎈
$ helm repo list
NAME URL
stable https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts
local http://127.0.0.1:8879/charts
安装 chart
要安装新的软件包,直接使用 helm install 命令即可。最简单的情况下,它只需要一个 chart 的名称参数:
$ helm install stable/mysql
NAME: mewing-squid
LAST DEPLOYED: Tue Sep 4 23:31:23 2019
NAMESPACE: default
STATUS: DEPLOYED
RESOURCES:
==> v1/PersistentVolumeClaim
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
mewing-squid-mysql Pending 1s
==> v1/Service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
mewing-squid-mysql ClusterIP 10.108.197.48 3306/TCP 1s
==> v1beta1/Deployment
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
mewing-squid-mysql 1 0 0 0 1s
==> v1/Pod(related)
NAME READY STATUS RESTARTS AGE
mewing-squid-mysql-69f587bdf9-z7glv 0/1 Pending 0 0s
==> v1/Secret
NAME TYPE DATA AGE
mewing-squid-mysql Opaque 2 1s
==> v1/ConfigMap
NAME DATA AGE
mewing-squid-mysql-test 1 1s
NOTES:
MySQL can be accessed via port 3306 on the following DNS name from within your cluster:
mewing-squid-mysql.default.svc.cluster.local
To get your root password run:
MYSQL_ROOT_PASSWORD=$(kubectl get secret --namespace default mewing-squid-mysql -o jsonpath="{.data.mysql-root-password}" | base64 --decode; echo)
To connect to your database:
1. Run an Ubuntu pod that you can use as a client:
kubectl run -i --tty ubuntu --image=ubuntu:16.04 --restart=Never -- bash -il
2. Install the mysql client:
$ apt-get update && apt-get install mysql-client -y
3. Connect using the mysql cli, then provide your password:
$ mysql -h mewing-squid-mysql -p
To connect to your database directly from outside the K8s cluster:
MYSQL_HOST=127.0.0.1
MYSQL_PORT=3306
# Execute the following command to route the connection:
kubectl port-forward svc/mewing-squid-mysql 3306
mysql -h ${MYSQL_HOST} -P${MYSQL_PORT} -u root -p${MYSQL_ROOT_PASSWORD}
现在 mysql chart 已经安装上了,安装 chart 会创建一个新 release 对象。上面的 release 被命名为 hmewing-squid。如果你想使用你自己的 release 名称,只需使用--name参数指定即可,比如:
$ helm install stable/mysql --name mydb
在安装过程中,helm 客户端将打印有关创建哪些资源的有用信息,release 的状态以及其他有用的配置信息,比如这里的有访问 mysql 服务的方法、获取 root 用户的密码以及连接 mysql 的方法等信息。
值得注意的是 Helm 并不会一直等到所有资源都运行才退出。因为很多 charts 需要的镜像资源非常大,所以可能需要很长时间才能安装到集群中去。
要跟踪 release 状态或重新读取配置信息,可以使用 helm status 查看:
$ helm status mewing-squid
LAST DEPLOYED: Tue Sep 4 23:31:23 2018
NAMESPACE: default
STATUS: DEPLOYED
RESOURCES:
...
可以看到当前 release 的状态是DEPLOYED,下面还有一些安装的时候出现的信息。
自定义chart
上面的安装方式是使用 chart 的默认配置选项。但是在很多时候,我们都需要自定义 chart 以满足自身的需求,要自定义 chart,我们就需要知道我们使用的 chart 支持的可配置选项才行。
要查看 chart 上可配置的选项,使用helm inspect values命令即可,比如我们这里查看上面的 mysql 的配置选项:
$ helm inspect values stable/mysql
## mysql image version
## ref: https://hub.docker.com/r/library/mysql/tags/
##
image: "mysql"
imageTag: "5.7.14"
## Specify password for root user
##
## Default: random 10 character string
# mysqlRootPassword: testing
## Create a database user
##
# mysqlUser:
## Default: random 10 character string
# mysqlPassword:
## Allow unauthenticated access, uncomment to enable
##
# mysqlAllowEmptyPassword: true
## Create a database
##
# mysqlDatabase:
## Specify an imagePullPolicy (Required)
## It's recommended to change this to 'Always' if the image tag is 'latest'
## ref: http://kubernetes.io/docs/user-guide/images/#updating-images
##
imagePullPolicy: IfNotPresent
extraVolumes: |
# - name: extras
# emptyDir: {}
extraVolumeMounts: |
# - name: extras
# mountPath: /usr/share/extras
# readOnly: true
extraInitContainers: |
# - name: do-something
# image: busybox
# command: ['do', 'something']
# Optionally specify an array of imagePullSecrets.
# Secrets must be manually created in the namespace.
# ref: https://kubernetes.io/docs/concepts/containers/images/#specifying-imagepullsecrets-on-a-pod
# imagePullSecrets:
# - name: myRegistryKeySecretName
## Node selector
## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector
nodeSelector: {}
livenessProbe:
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
successThreshold: 1
failureThreshold: 3
readinessProbe:
initialDelaySeconds: 5
periodSeconds: 10
timeoutSeconds: 1
successThreshold: 1
failureThreshold: 3
## Persist data to a persistent volume
persistence:
enabled: true
## database data Persistent Volume Storage Class
## If defined, storageClassName:
## If set to "-", storageClassName: "", which disables dynamic provisioning
## If undefined (the default) or set to null, no storageClassName spec is
## set, choosing the default provisioner. (gp2 on AWS, standard on
## GKE, AWS & OpenStack)
##
# storageClass: "-"
accessMode: ReadWriteOnce
size: 8Gi
annotations: {}
## Configure resource requests and limits
## ref: http://kubernetes.io/docs/user-guide/compute-resources/
##
resources:
requests:
memory: 256Mi
cpu: 100m
# Custom mysql configuration files used to override default mysql settings
configurationFiles: {}
# mysql.cnf: |-
# [mysqld]
# skip-name-resolve
# ssl-ca=/ssl/ca.pem
# ssl-cert=/ssl/server-cert.pem
# ssl-key=/ssl/server-key.pem
# Custom mysql init SQL files used to initialize the database
initializationFiles: {}
# first-db.sql: |-
# CREATE DATABASE IF NOT EXISTS first DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci;
# second-db.sql: |-
# CREATE DATABASE IF NOT EXISTS second DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci;
metrics:
enabled: false
image: prom/mysqld-exporter
imageTag: v0.10.0
imagePullPolicy: IfNotPresent
resources: {}
annotations: {}
# prometheus.io/scrape: "true"
# prometheus.io/port: "9104"
livenessProbe:
initialDelaySeconds: 15
timeoutSeconds: 5
readinessProbe:
initialDelaySeconds: 5
timeoutSeconds: 1
## Configure the service
## ref: http://kubernetes.io/docs/user-guide/services/
service:
## Specify a service type
## ref: https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services---service-types
type: ClusterIP
port: 3306
# nodePort: 32000
ssl:
enabled: false
secret: mysql-ssl-certs
certificates:
# - name: mysql-ssl-certs
# ca: |-
# -----BEGIN CERTIFICATE-----
# ...
# -----END CERTIFICATE-----
# cert: |-
# -----BEGIN CERTIFICATE-----
# ...
# -----END CERTIFICATE-----
# key: |-
# -----BEGIN RSA PRIVATE KEY-----
# ...
# -----END RSA PRIVATE KEY-----
## Populates the 'TZ' system timezone environment variable
## ref: https://dev.mysql.com/doc/refman/5.7/en/time-zone-support.html
##
## Default: nil (mysql will use image's default timezone, normally UTC)
## Example: 'Australia/Sydney'
# timezone:
# To be added to the database server pod(s)
podAnnotations: {}
然后,我们可以直接在 YAML 格式的文件中来覆盖上面的任何配置,在安装的时候直接使用该配置文件即可,新建如下文件:(config.yaml)
mysqlUser: qiendaUser
mysqlDatabase: k8sDB
service:
type: NodePort
我们这里通过 config.yaml 文件定义了 mysqlUser 和 mysqlDatabase,并且把 service 的类型更改为了 NodePort,然后现在我们来安装的时候直接指定该 yaml 文件:
$ helm install -f config.yaml stable/mysql --name mydb
NAME: mydb
LAST DEPLOYED: Wed Sep 5 00:09:44 2018
NAMESPACE: default
STATUS: DEPLOYED
RESOURCES:
==> v1/Secret
NAME TYPE DATA AGE
mydb-mysql Opaque 2 1s
==> v1/ConfigMap
NAME DATA AGE
mydb-mysql-test 1 1s
==> v1/PersistentVolumeClaim
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
mydb-mysql Pending 1s
==> v1/Service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
mydb-mysql NodePort 10.96.150.198 3306:32604/TCP 0s
==> v1beta1/Deployment
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
mydb-mysql 1 1 1 0 0s
==> v1/Pod(related)
NAME READY STATUS RESTARTS AGE
mydb-mysql-dfc999888-hbw5d 0/1 Pending 0 0s
...
可以看到当前 release 的名字已经变成 mydb 了。然后可以查看下 mydb 关联的 Service 是否变成 NodePort 类型的了:
$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 443/TCP 110d
mewing-squid-mysql ClusterIP 10.108.197.48 3306/TCP 46m
mydb-mysql NodePort 10.96.150.198 3306:32604/TCP 8m
看到服务 mydb-mysql 变成了 NodePort 类型的,之前默认创建的 mewing-squid-mysql 是 ClusterIP 类型的,证明上面我们通过 YAML 文件来覆盖 values 是成功的。
接下来我们查看下 Pod 的状况:
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
mewing-squid-mysql-69f587bdf9-z7glv 0/1 Pending 0 49m
mydb-mysql-dfc999888-hbw5d 0/1 Pending 0 11m
比较奇怪的是之前默认创建的和现在的 mydb 的 release 创建的 Pod 都是 Pending 状态,直接使用 describe 命令查看下:
$ kubectl describe pod mydb-mysql-dfc999888-hbw5d
Name: mydb-mysql-dfc999888-hbw5d
Namespace: default
Node:
Labels: app=mydb-mysql
pod-template-hash=897555444
...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning FailedScheduling 2m (x37 over 12m) default-scheduler pod has unbound PersistentVolumeClaims (repeated 2 times)
可以发现两个 Pod 处于 Pending 状态的原因都是 PVC 没有被绑定上,所以这里我们可以通过 storageclass 或者手动创建一个合适的 PV 对象来解决这个问题。
另外为了说明 helm 更新的用法,我们这里来直接禁用掉数据持久化,可以在上面的 config.yaml 文件中设置:
persistence:
enabled: false
另外一种方法就是在安装过程中使用--set来覆盖对应的 value 值,比如禁用数据持久化,我们这里可以这样来覆盖:
$ helm install stable/mysql --set persistence.enabled=false --name mydb
升级
使用upgrade将数据持久化禁用掉来对上面的 mydb 进行升级:
$ echo config.yaml
mysqlUser: haimaxyUser
mysqlDatabase: haimaxyDB
service:
type: NodePort
persistence:
enabled: false
$ helm upgrade -f config.yaml mydb stable/mysql
helm upgrade -f config.yaml mydb stable/mysql
Release "mydb" has been upgraded. Happy Helming!
LAST DEPLOYED: Wed Sep 5 00:38:33 2018
NAMESPACE: default
STATUS: DEPLOYED
RESOURCES:
...
可以看到已经变成 DEPLOYED 状态了,现在我们再去看看 Pod 的状态呢:
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
mewing-squid-mysql-69f587bdf9-z7glv 0/1 Pending 0 1h
mydb-mysql-6ffc84bbf6-lcn4d 0/1 PodInitializing 0 49s
...
我们看到 mydb 关联的 Pod 已经变成了 Pod Initializing 的状态,已经不是 Pending 状态了,同样的,使用 describe 命令查看:
$ kubectl describe pod mydb-mysql-6ffc84bbf6-lcn4d
Name: mydb-mysql-6ffc84bbf6-lcn4d
Namespace: default
Node: node02/10.151.30.63
Start Time: Wed, 05 Sep 2018 00:38:33 +0800
Labels: app=mydb-mysql
pod-template-hash=2997406692
Annotations:
Status: Pending
...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal SuccessfulMountVolume 58s kubelet, node02 MountVolume.SetUp succeeded for volume "data"
Normal SuccessfulMountVolume 58s kubelet, node02 MountVolume.SetUp succeeded for volume "default-token-n9w2d"
Normal Scheduled 57s default-scheduler Successfully assigned mydb-mysql-6ffc84bbf6-lcn4d to node02
Normal Pulling 57s kubelet, node02 pulling image "busybox:1.25.0"
Normal Pulled 45s kubelet, node02 Successfully pulled image "busybox:1.25.0"
Normal Created 44s kubelet, node02 Created container
Normal Started 44s kubelet, node02 Started container
Normal Pulling 41s kubelet, node02 pulling image "mysql:5.7.14"
可以看到现在没有任何关于 PVC 的错误信息了,这是因为我们刚刚更新的版本中就是禁用掉了的数据持久化的,证明 helm upgrade 和 --values 是生效了的。现在我们使用 helm ls 命令查看先当前的 release:
$ helm ls
NAME REVISION UPDATED STATUS CHART APP VERSION NAMESPACE
mewing-squid 1 Tue Sep 4 23:31:23 2018 DEPLOYED mysql-0.10.1 5.7.14 default
mydb 2 Wed Sep 5 00:38:33 2018 DEPLOYED mysql-0.10.1 5.7.14
可以看到 mydb 这个 release 的REVISION已经变成2了,这是因为 release 的版本是递增的,每次安装、升级或者回滚,版本号都会加1,第一个版本号始终为1,同样我们可以使用 helm history 命令查看 release 的历史版本:
$ helm history mydb
REVISION UPDATED STATUS CHART DESCRIPTION
1 Wed Sep 5 00:09:44 2018 SUPERSEDED mysql-0.10.1 Install complete
2 Wed Sep 5 00:38:33 2018 DEPLOYED mysql-0.10.1 Upgrade complete
当然如果我们要回滚到某一个版本的话,使用 helm rollback 命令即可,比如我们将 mydb 回滚到上一个版本:
$ helm rollback mydb 1