前置知识:Kubernetes 一小时轻松入门
1 使用 Multipass 创建虚拟机集群
本文的 Kubernetes 集群中包含四台虚拟机。其中包括一台 master 节点和两台 worker 节点,以及一个用于持久化存储的 NFS 服务器。它们的配置如下:
虚拟机名称 | CPU 核心数 | 内存容量 | 硬盘空间 |
---|
master | 2 | 6GB | 50GB |
worker1 | 2 | 6GB | 20GB |
worker2 | 2 | 6GB | 20GB |
storage | 2 | 4GB | 50GB |
OpenWhisk 对节点配置的最低要求
1
| sudo snap install multipass
|
1.2 创建虚拟机
1
2
3
4
| multipass launch --name master --cpus 2 --memory 6G --disk 50G
multipass launch --name worker1 --cpus 2 --memory 6G --disk 20G
multipass launch --name worker2 --cpus 2 --memory 6G --disk 20G
multipass launch --name storage --cpus 2 --memory 4G --disk 50G
|
查看创建结果:
1
2
3
4
5
| Name State IPv4 Image
master Running 10.251.200.141 Ubuntu 24.04 LTS
storage Running 10.251.200.186 Ubuntu 24.04 LTS
worker1 Running 10.251.200.142 Ubuntu 24.04 LTS
worker2 Running 10.251.200.168 Ubuntu 24.04 LTS
|
其他可能用到的命令
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| # 查看虚拟机资源使用情况
multipass info <instance-name>
# 将虚拟机移动至回收站
multipass delete <instance-name>
# 将虚拟机移出回收站
multipass recover <instance-name>
# 销毁虚拟机
multipass delete --purge <instance-name>
# 销毁所有虚拟机
multipass delete --purge --all
|
1.3 在 master 节点中安装 K3s
从宿主机连接到 master 节点:
执行 K3s 安装脚本:
1
2
3
4
| curl -sfL https://get.k3s.io | sh -
# 使用国内镜像
curl -sfL https://rancher-mirror.rancher.cn/k3s/k3s-install.sh | INSTALL_K3S_MIRROR=cn sh -
|
1.4 将 worker 节点加入集群
在宿主机中获取 master 节点的 IP 地址和 K3s 的 token:
1
2
| MASTER_IP=$(multipass info master | grep IPv4 | awk '{print $2}')
TOKEN=$(multipass exec master sudo cat /var/lib/rancher/k3s/server/node-token)
|
在所有 worker 节点上执行 K3s 安装脚本:
1
2
3
4
5
6
7
8
| for index in 1 2; do
multipass exec worker${index} -- bash -c "curl -sfL https://get.k3s.io | K3S_URL=https://${MASTER_IP}:6443 K3S_TOKEN=${TOKEN} sh -"
done
# 使用国内镜像
for index in 1 2; do
multipass exec worker${index} -- bash -c "curl -sfL https://rancher-mirror.rancher.cn/k3s/k3s-install.sh | INSTALL_K3S_MIRROR=cn K3S_URL=https://${MASTER_IP}:6443 K3S_TOKEN=${TOKEN} sh -"
done
|
查看集群节点状态:
1
| multipass exec master sudo kubectl get nodes
|
1
2
3
4
| NAME STATUS ROLES AGE VERSION
master Ready control-plane,master 10m v1.29.4+k3s1
worker1 Ready <none> 2m12s v1.29.4+k3s1
worker2 Ready <none> 2m4s v1.29.4+k3s1
|
1.5 搭建 NFS 服务器
参考文档
从宿主机连接到 storage 节点:
1
| multipass shell storage
|
安装 NFS 服务:
1
| sudo apt install nfs-kernel-server
|
创建 Kubernetes 集群数据存储目录:
1
| sudo mkdir /var/nfs/kubedata -p
|
将目录的拥有者设置为 nobody
:
1
| sudo chown nobody: /var/nfs/kubedata
|
启用 NFS 服务:
1
2
| sudo systemctl enable nfs-server.service
sudo systemctl start nfs-server.service
|
编辑 /etc/exports
文件:
在文件末尾添加集群数据存储目录的配置:
1
| /var/nfs/kubedata *(rw,sync,no_subtree_check,no_root_squash,no_all_squash)
|
应用配置文件:
1
| exporting *:/var/nfs/kubedata
|
2 安装 NFS 客户端
为 Kubernetes 集群中的所有节点安装 NFS 客户端:
1
2
3
| multipass exec master -- bash -c "sudo apt install nfs-common -y"
multipass exec worker1 -- bash -c "sudo apt install nfs-common -y"
multipass exec worker2 -- bash -c "sudo apt install nfs-common -y"
|
否则在创建 NFS Dynamic Storage 时,节点无法挂载 NFS 服务器的共享目录。
3 安装 Kubernetes 集群的包管理工具 Helm
从宿主机连接到 master 节点:
使用 snap
安装 Helm:
1
| sudo snap install helm --classic
|
4 安装 OpenWhisk Command-line Interface (wsk CLI)
从宿主机连接到 master 节点:
下载并安装 wsk CLI 二进制文件:
1
2
3
4
| mkdir ~/downloads && cd ~/downloads
wget https://github.com/apache/openwhisk-cli/releases/download/latest/OpenWhisk_CLI-latest-linux-amd64.tgz
tar -xvf OpenWhisk_CLI-latest-linux-amd64.tgz
sudo mv wsk /usr/local/bin/wsk
|
5 为 Kubernetes 集群部署 NFS Dynamic Storage
参考文档中 deployment.yaml
文件所使用的 quay.io/external_storage/nfs-client-provisioner
镜像已停止维护。Pod 运行时会报错 unexpected error getting claim reference: selfLink was empty, can’t make reference 。selfLink
字段在 Kubernetes 1.20 版本中被废弃。
根据官方文档,使用 NFS subdir 为 Kubernetes 集群提供 NFS Dynamic Storage 。
使用 Helm Chart 安装 NFS Subdirectory External Provisioner
参考文档
从宿主机连接到 master 节点:
添加 Helm Chart 仓库:
1
2
| sudo helm repo add nfs-subdir-external-provisioner https://kubernetes-sigs.github.io/nfs-subdir-external-provisioner/
sudo helm repo update
|
以名称 openwhisk-nfs
部署 NFS Subdirectory External Provisioner,并指定 NFS 服务器的 IP 地址和共享目录:
1
2
3
| sudo helm --kubeconfig /etc/rancher/k3s/k3s.yaml install openwhisk-nfs nfs-subdir-external-provisioner/nfs-subdir-external-provisioner \
--set nfs.server=10.251.200.186 \
--set nfs.path=/var/nfs/kubedata
|
在 K3s 中,需要使用 --kubeconfig
参数指定 kubeconfig 文件的路径,使得 Helm 能够访问集群。
安装成功后显示信息:
1
2
3
4
5
6
| NAME: openwhisk-nfs
LAST DEPLOYED: Wed May 8 18:15:14 2024
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
|
检查资源创建结果
1
| sudo kubectl get clusterrole,clusterrolebinding,role,rolebinding | grep nfs
|
1
2
3
4
| clusterrole.rbac.authorization.k8s.io/openwhisk-nfs-nfs-subdir-external-provisioner-runner 2024-05-08T10:15:14Z
clusterrolebinding.rbac.authorization.k8s.io/run-openwhisk-nfs-nfs-subdir-external-provisioner ClusterRole/openwhisk-nfs-nfs-subdir-external-provisioner-runner 112s
role.rbac.authorization.k8s.io/leader-locking-openwhisk-nfs-nfs-subdir-external-provisioner 2024-05-08T10:15:14Z
rolebinding.rbac.authorization.k8s.io/leader-locking-openwhisk-nfs-nfs-subdir-external-provisioner Role/leader-locking-openwhisk-nfs-nf-subdir-external-provisioner 112s
|
1
| sudo kubectl get storageclass
|
1
2
3
| NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
local-path (default) rancher.io/local-path Delete WaitForFirstConsumer false 7h16m
nfs-client cluster.local/openwhisk-nfs-nfs-subdir-external-provisioner Delete Immediate true 3m26s
|
1
2
| NAME READY STATUS RESTARTS AGE
openwhisk-nfs-nfs-subdir-external-provisioner-54846ffcfb-26j8r 1/1 Running 0 5m35s
|
其他可能用到的命令
1
2
| # 卸载 NFS Subdirectory External Provisioner
sudo helm --kubeconfig /etc/rancher/k3s/k3s.yaml uninstall openwhisk-nfs
|
6 部署 OpenWhisk
从宿主机连接到 master 节点:
6.1 为集群中的节点添加标签
在部署 OpenWhisk 之前,需要指明哪些节点运行 OpenWhisk 的控制面板(如:controller、kafka、zookeeper 和 CouchDB),哪些节点执行函数调用。
通过给节点添加标签来指明节点的角色:
1
2
3
| sudo kubectl label node master openwhisk-role=core
sudo kubectl label node worker1 openwhisk-role=invoker
sudo kubectl label node worker2 openwhisk-role=invoker
|
使用 sudo kubectl describe nodes <node-name>
命令查看节点的标签。
6.2 编写安装配置文件 mycluster.yaml
参考文档
mycluster.yaml
配置了 Kubernetes 集群的 Ingress 服务的地址和端口号(默认 31001 ),用于 wsk CLI 连接 OpenWhisk 服务。
1
2
3
4
5
6
7
8
9
10
11
12
| whisk:
ingress:
type: NodePort
apiHostName: 10.251.200.141
apiHostPort: 31001
nginx:
httpsNodePort: 31001
invoker:
containerFactory:
impl: "kubernetes"
|
将上述内容写入 ~/kubeyaml/mycluster.yaml
文件中。
6.3 配置 wsk CLI
配置 wsk CLI 的 apihost
为 Ingress 服务的地址和端口号,auth
为 OpenWhisk 的 guest 用户的默认 token :
1
2
| sudo wsk property set --apihost 10.251.200.141:31001
sudo wsk property set --auth 23bc46b1-71f6-4ed5-8c54-816aa4f8c502:123zO3xZCLrMN6v2BKK1dXYFpXlPkccOFqm12CdAsMgRU4VrNZ9lyGVCGuMDGIwP
|
6.4 使用 Helm 部署 OpenWhisk
Helm Repository 中的 OpenWhisk Chart 使用的 npm 镜像版本过低,会导致安装失败。因此使用 GitHub 上的 OpenWhisk Chart 安装。
1
2
3
4
| cd ~
git clone https://github.com/apache/openwhisk-deploy-kube.git
cd openwhisk-deploy-kube
sudo helm --kubeconfig /etc/rancher/k3s/k3s.yaml install owdev ./helm/openwhisk -n openwhisk --create-namespace -f ~/kubeyaml/mycluster.yaml
|
在 K3s 中,需要使用 --kubeconfig
参数指定 kubeconfig 文件的路径,使得 Helm 能够访问集群。
安装成功后显示信息:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
| NAME: owdev
LAST DEPLOYED: Wed May 8 18:26:12 2024
NAMESPACE: openwhisk
STATUS: deployed
REVISION: 1
NOTES:
Apache OpenWhisk
Copyright 2016-2021 The Apache Software Foundation
This product includes software developed at
The Apache Software Foundation (http://www.apache.org/).
To configure your wsk cli to connect to it, set the apihost property
using the command below:
$ wsk property set --apihost 10.251.200.141:31001
Your release is named owdev.
To learn more about the release, try:
$ helm status owdev
$ helm get owdev
Once the 'owdev-install-packages' Pod is in the Completed state, your OpenWhisk deployment is ready to be used.
Once the deployment is ready, you can verify it using:
$ helm test owdev --cleanup
|
此时可以使用命令 sudo kubectl get pvc,pv -A
查看 NFS Dynamic Storage 的创建结果。STATUS 为 Bound
时表示创建成功。
使用命令 sudo kubectl get pods -n openwhisk --watch
查看集群容器部署的状态。当 install-packages
Pod 的状态为 Completed
时,OpenWhisk 部署完成。
使用命令 sudo wsk -i package list /whisk.system
查看安装好的 OpenWhisk 包。-i
选项用于跳过 SSL 证书验证。
1
2
3
4
5
6
7
8
| packages
/whisk.system/messaging shared
/whisk.system/alarms shared
/whisk.system/websocket shared
/whisk.system/utils shared
/whisk.system/samples shared
/whisk.system/slack shared
/whisk.system/github shared
|
其他可能用到的命令
1
2
3
4
5
6
| # 查看 OpenWhisk 全部资源状态
sudo kubectl get all -n openwhisk
sudo kubectl get all -o wide -n openwhisk
# 卸载 OpenWhisk
sudo helm --kubeconfig /etc/rancher/k3s/k3s.yaml uninstall owdev -n openwhisk
|
7 函数部署示例
OpenWhisk 文档
从宿主机连接到 master 节点:
创建用于存储函数的目录:
1
| mkdir ~/functions && cd ~/functions
|
7.1 通过 wsk CLI 调用函数
创建 Node.js 函数 hello_cli.js
:
1
2
3
4
| function main(params) {
var name = params.name || 'World';
return {payload: 'Hello, ' + name + '!'};
}
|
使用 wsk CLI 部署函数:
1
| sudo wsk -i action create hellocli hello_cli.js
|
调用函数:
1
| sudo wsk -i action invoke hellocli --result
|
1
2
3
| {
"payload": "Hello, World!"
}
|
传递参数:
1
| sudo wsk -i action invoke hellocli --result --param name JavaScript
|
1
2
3
| {
"payload": "Hello, JavaScript!"
}
|
7.2 通过 web URL 调用函数
参考文档
创建 Python 函数 hello_web.py
:
1
2
3
4
5
6
| def main(args):
return {
"statusCode": 200,
"headers": { "Content-Type": "application/json" },
"body": args
}
|
使用 wsk CLI 部署函数:
1
| sudo wsk -i action create helloweb hello_web.py --web true
|
获取函数的 web URL:
1
| sudo wsk -i action get helloweb --url
|
1
| https://10.251.200.141:31001/api/v1/web/guest/default/helloweb
|
在宿主机中使用 curl
命令调用函数,-k
选项用于跳过 SSL 证书验证:
1
| curl -k https://10.251.200.141:31001/api/v1/web/guest/default/helloweb
|
1
2
3
4
5
6
7
8
9
| {
"__ow_headers": {
"accept": "*/*",
"host": "controllers",
"user-agent": "curl/7.81.0"
},
"__ow_method": "get",
"__ow_path": ""
}
|
传递参数:
1
| curl -k https://10.251.200.141:31001/api/v1/web/guest/default/helloweb?name=Python
|
1
2
3
4
5
6
7
8
9
10
| {
"__ow_headers": {
"accept": "*/*",
"host": "controllers",
"user-agent": "curl/7.81.0"
},
"__ow_method": "get",
"__ow_path": "",
"name": "Python"
}
|
8 运维相关
8.1 关闭虚拟机
关闭顺序:worker1 -> worker2 -> master -> storage
1
2
3
4
| multipass stop worker1
multipass stop worker2
multipass stop master
multipass stop storage
|
8.2 启动虚拟机
启动顺序:storage -> master -> worker1 -> worker2
1
2
3
4
| multipass start storage
multipass start master
multipass start worker1
multipass start worker2
|
9 wsk CLI 常用命令
9.1 函数相关
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| # 列出所有函数
sudo wsk -i action list
# 创建函数
sudo wsk -i action create <action_name> <action_file>
sudo wsk -i action create <action_name> <action_zip> --kind <available_runtime>
# --kind 可选的参数在 https://github.com/apache/openwhisk-deploy-kube/blob/master/helm/openwhisk/runtimes.json 中配置
# 删除函数
sudo wsk -i action delete <action_name>
# 更新函数
sudo wsk -i action update <action_name> <action_file> --docker openwhisk/action-python-v3.11
# --docker 选项可以指定函数的运行环境(必须在 Docker Hub 上存在)
# 调用函数
sudo wsk -i action invoke --result <action_name> --param <key1> <value1> ...
|
9.2 调用相关
1
2
3
4
5
6
7
8
9
10
11
| # 列出所有函数调用
sudo wsk -i activation list
# 获取函数调用的详细信息
sudo wsk -i activation get <request_id>
# 获取函数调用的结果
sudo wsk -i activation result <request_id>
# 获取函数调用的日志
sudo wsk -i activation logs <request_id>
|
9.3 利用 virtualenv 打包 Python 函数和依赖
参考文档:
将 __main__.py
和 requirements.txt
所在的目录挂载到 openwhisk/action-python-v3.12
容器的 /tmp
目录下,然后利用容器的环境创建 virtualenv 文件夹并安装 requirements.txt
中的依赖:
1
| sudo docker run --rm -v "$(pwd):/tmp" --entrypoint "/bin/bash" openwhisk/action-python-v3.12 -c "cd /tmp && virtualenv virtualenv && source virtualenv/bin/activate && pip install -r requirements.txt"
|
然后将文件夹内的内容打包成 zip 文件:
1
| zip -r ../<action_name>.zip .
|