Kubernetes
Kubernetes是一个用于容器编排的开源工具。它在管理容器工作负载和实现集群及其部署的自动化方面有很大帮助。你可以在这里找到更多关于它的信息。
本文档将解释基本的Kubernetes概念以及在Azure AKS上设置自己的SKIL集群所需的步骤。AKS是一个由Azure提供的云服务,它允许你在后端使用kubernetes创建、管理和部署集群。
概念
以下是有Kubernetes的一些重要的基本概念。
Pods
Pods是Kubernetes最小的可部署单元。在kubernetes中,一组一个或多个容器称为pod。pod中的容器一起部署,并作为一个组启动、停止和复制。pod容器可以支持不同的容器运行时,例如docker,每个容器创建后都是用共享存储/网络,并带有如何运行容器的规范。
部署
在Kubernetes中,部署是管理应用程序伸缩性的一种方法。部署对象定义POD创建模板和所需的副本计数。部署使用“标签选择器(label selector)”来标识它管理的pods,并将根据需要创建或删除pods以满足副本计数。部署还用于管理安全地展开对下在运行的pods的更改。
服务
服务提供了一种引用具有单个静态IP地址的一组pods的方法。它还使用“标签选择器(label selectors)”来标识它需要服务的资源。它还可以提供负载均衡,并允许为应用程序提供外部服务。
安装工具
你需要在你的环境中安装docker、azure-cli和kubectl以进行后续操作。对于CentOS,可以按以下方式安装:
# 安装 docker
sudo yum install -y docker && sudo yum install docker && sudo systemctl start docker && sudo systemctl status docker && sudo systemctl enable docker
# 安装 azure-cli
sudo rpm --import https://packages.microsoft.com/keys/microsoft.asc
sudo sh -c 'echo -e "[azure-cli]\nname=Azure CLI\nbaseurl=https://packages.microsoft.com/yumrepos/azure-cli\nenabled=1\ngpgcheck=1\ngpgkey=https://packages.microsoft.com/keys/microsoft.asc" > /etc/yum.repos.d/azure-cli.repo'
sudo yum install -y azure-cli
# 安装 kubectl
sudo az aks install-cli
对于其他操作系统中的安装,可以访问以下链接:
- Docker
- Azure CLI
这里,对于kubectl,安装命令一般是:az aks install-cli
需要Docker镜像
集群设置需要以下Docker镜像:
- https://hub.docker.com/_/zookeeper/
- https://hub.docker.com/_/mysql/ (版本 5.5.59)
- https://hub.docker.com/r/skymind/skil/
分布式skil镜像不包括JDBC驱动程序。这是与远程mysql容器实例通信所必需的。我们必须在skil ce docker镜像中手动安装mysql jdbc驱动程序。要将其安装在已拉取的skil镜像中,首先创建一个Dockerfile(nano Dockerfile),并将以下内容放入其中。
FROM skymind/skil
USER root
RUN yum install -y mysql-connector-java && ln -s /usr/share/java/mysql-connector-java.jar /opt/skil/lib/mysql-connector-java.jar
# PLD
EXPOSE 9008
# File Server
EXPOSE 9508
# Zeppelin
EXPOSE 8080
# DL4J UI first port
EXPOSE 9002
# ModelHistoryServer port
EXPOSE 9100
CMD ["/start-skil.sh"]
保存文件并运行以下命令以为你的Kubernetes设置拉取和构建所需的SKIL docker镜像
sudo docker pull zookeeper
sudo docker pull mysql:5.5.59
sudo docker build -t skymind/skil:jdbc .
架构
你可以使用的基本架构是将zookeeper和mysql容器实例保存在单个pod中,并将复制的skil实例保存在部署中。一个服务将向skil部署公开pod容器,另一个服务将负载均衡并公开skil部署pod实例。它看起来像这样:
SKIL集群的kubernetes布局架构
Kubernetes配置
这里定义的配置与上面描述的架构相对应。
创建Zookeeper与MySQL Pod
这个pod将有两个容器用于ZooKeeper和MySQL。它被标记为app:zksql,用于能够被公开服务选择。将有三卷用于保存ZooKeeper(zk-data
和 zk-datalog
)和mysql(mysql-data
)数据。其他配置部分包括设置环境变量、主机设置和端口公开。配置在下面的代码段中定义:
Shell
apiVersion: v1
kind: Pod
metadata:
name: zookeeper-mysql
labels:
app: zksql
spec:
hostname: zksql
subdomain: zksqlsrv
containers:
- name: zookeeper
image: /zookeeper # You'll find the loginServerName at the end of this document as you follow along
ports:
- name: zkmain
containerPort: 2181
protocol: TCP
volumeMounts:
- mountPath: /data
name: zk-data
- mountPath: /datalog
name: zk-datalog
- name: mysql
image: /mysql # You'll find the loginServerName at the end of this document as you follow along
ports:
- name: sqlmain
containerPort: 3306
protocol: TCP
volumeMounts:
- mountPath: /var/lib/mysql
name: mysql-data
env:
- name: MYSQL_ALLOW_EMPTY_PASSWORD
value: "true"
- name: MYSQL_DATABASE
value: "skil_migrations"
volumes:
- name: zk-data
emptyDir: {}
- name: zk-datalog
emptyDir: {}
- name: mysql-data
emptyDir: {}
创建Skil部署
此部署设置包括用于SKIL容器的“2”个pod单元大小的复本。它们按标签分组:app:skil。然后,服务(负载均衡器)可以选择此标签公开它,并对传入的请求进行负载均衡。此外,zookeeper和mysql pod中定义的主机设置可以转换为DNS,即:zksql.zksqlsrv.default.svc.cluster.local
。查看下面的代码片段,了解如何在环境变量(skil_db_url和zookeeper_host)中使用它。
YAML
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: skil
spec:
replicas: 2
template:
metadata:
labels:
app: skil
spec:
containers:
- name: skil
image: /skymind/skil # You'll find the loginServerName at the end of this document as you follow along
ports:
- name: skilmain
containerPort: 9008
protocol: TCP
- name: skilzep
containerPort: 8080
protocol: TCP
env:
- name: SKIL_USE_EMBEDDED_DB
value: "false"
- name: SKIL_DB_NAME
value: "skil_migrations"
- name: SKIL_DB_DRIVER
value: "com.mysql.jdbc.Driver"
- name: SKIL_DB_URL
value: "jdbc:mysql://zksql.zksqlsrv.default.svc.cluster.local:3306/skil_migrations"
- name: SKIL_DB_USER
value: "root"
- name: MODEL_HISTORY_SERVER_LAUNCH_DEFAULT
value: "false"
- name: ZEPPELIN_LAUNCH_DEFAULT
value: "false"
- name: ZOOKEEPER_HOST
value: "zksql.zksqlsrv.default.svc.cluster.local"
- name: ZOOKEEPER_PORT
value: "2181"
- name: ZOOKEEPER_EMBEDDED
value: "false"
创建服务
下面定义的两个服务使用app:zksql选择器将zookeeper和mysql内部公开到SKIL部署,使用app:skil将SKIL部署外部公开。
YAML
apiVersion: v1
kind: Service
metadata:
name: zksqlsrv
spec:
ports:
- port: 2181
targetPort: 2181
protocol: TCP
name: zkmain
- port: 3306
targetPort: 3306
protocol: TCP
name: sqlmain
selector:
app: zksql
clusterIP: None
---
apiVersion: v1
kind: Service
metadata:
name: skil
spec:
type: LoadBalancer
ports:
- port: 9008
targetPort: 9008
protocol: TCP
name: skilmain
- port: 8080
targetPort: 8080
protocol: TCP
name: skilzep
selector:
app: skil
汇总配置文件
下面汇总了上面创建的所有kubernetes组件。创建名为skil-app.yaml(nano skil-app.yaml)的文件,并将以下内容放入其中。
YAML
apiVersion: v1
kind: Pod
metadata:
name: zookeeper-mysql
labels:
app: zksql
spec:
hostname: zksql
subdomain: zksqlsrv
containers:
- name: zookeeper
image: /zookeeper # You'll find the loginServerName at the end of this document as you follow along
ports:
- name: zkmain
containerPort: 2181
protocol: TCP
volumeMounts:
- mountPath: /data
name: zk-data
- mountPath: /datalog
name: zk-datalog
- name: mysql
image: /mysql # You'll find the loginServerName at the end of this document as you follow along
ports:
- name: sqlmain
containerPort: 3306
protocol: TCP
volumeMounts:
- mountPath: /var/lib/mysql
name: mysql-data
env:
- name: MYSQL_ALLOW_EMPTY_PASSWORD
value: "true"
- name: MYSQL_DATABASE
value: "skil_migrations"
volumes:
- name: zk-data
emptyDir: {}
- name: zk-datalog
emptyDir: {}
- name: mysql-data
emptyDir: {}
---
apiVersion: v1
kind: Service
metadata:
name: zksqlsrv
spec:
ports:
- port: 2181
targetPort: 2181
protocol: TCP
name: zkmain
- port: 3306
targetPort: 3306
protocol: TCP
name: sqlmain
selector:
app: zksql
clusterIP: None
---
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: skil
spec:
replicas: 2
template:
metadata:
labels:
app: skil
spec:
containers:
- name: skil
image: /skymind/skil # You'll find the loginServerName at the end of this document as you follow along
ports:
- name: skilmain
containerPort: 9008
protocol: TCP
- name: skilzep
containerPort: 8080
protocol: TCP
env:
- name: SKIL_USE_EMBEDDED_DB
value: "false"
- name: SKIL_DB_NAME
value: "skil_migrations"
- name: SKIL_DB_DRIVER
value: "com.mysql.jdbc.Driver"
- name: SKIL_DB_URL
value: "jdbc:mysql://zksql.zksqlsrv.default.svc.cluster.local:3306/skil_migrations"
- name: SKIL_DB_USER
value: "root"
- name: MODEL_HISTORY_SERVER_LAUNCH_DEFAULT
value: "false"
- name: ZEPPELIN_LAUNCH_DEFAULT
value: "false"
- name: ZOOKEEPER_HOST
value: "zksql.zksqlsrv.default.svc.cluster.local"
- name: ZOOKEEPER_PORT
value: "2181"
- name: ZOOKEEPER_EMBEDDED
value: "false"
---
apiVersion: v1
kind: Service
metadata:
name: skil
spec:
type: LoadBalancer
ports:
- port: 9008
targetPort: 9008
protocol: TCP
name: skilmain
- port: 8080
targetPort: 8080
protocol: TCP
name: skilzep
selector:
app: skil
这些是在使用kubernetes集群之前准备容器镜像所需的一些初始步骤。这些镜像需要存在于在线注册表中,以便在上面为每个容器模板定义的规范中的镜像选择器中解析。
在ACR中创建和注册镜像
ACR是“Azure容器注册表”,用于在Azure上上载和注册容器镜像,稍后可与AKS一起使用。为此,首先使用az登录名登录到Azure,如下所示:
Shell
sudo az login
按照命令行输出上显示的步骤完成登录过程。 登录后,确保所需的
Azure service providers与 az provider register
已启用 。
Shell
az provider register -n Microsoft.Network
az provider register -n Microsoft.Storage
az provider register -n Microsoft.Compute
az provider register -n Microsoft.ContainerService
你需要一个资源组来包含你的ACR。创建一个资源组,然后创建一个ACR,然后登录到它。
Shell
export RESOURCE_GROUP_NAME= # 将此替换为唯一的资源组名称
export ACR_NAME= # 将其替换为唯一的ACR名称
az group create --name $RESOURCE_GROUP_NAME --location eastus
az acr create --resource-group $RESOURCE_GROUP_NAME --name $ACR_NAME --sku Basic
sudo az acr login --name $ACR_NAME
每个容器镜像都需要用注册表的“loginServer”名称进行标记。当将容器镜像推送到镜像注册表时,此标记用于路由。你可以使用以下命令获取登录服务器名称:
Shell
export ACR_LOGIN_SERVER="$(az acr list --resource-group $RESOURCE_GROUP_NAME --query "[].{acrLoginServer:loginServer}" --output table | tail -n1)"
echo $ACR_LOGIN_SERVER # 打印loginServer名称
运行上述命令时,请确保将skil-app.yaml
文件中的loginServerName
替换为控制台中打印的登录服务器名称。要标记和推送Docker镜像,请运行以下命令
Shell
sudo docker tag zookeeper ${ACR_LOGIN_SERVER}/zookeeper
sudo docker tag mysql:5.5.59 ${ACR_LOGIN_SERVER}/mysql
sudo docker tag skymind/skil:jdbc ${ACR_LOGIN_SERVER}/skymind/skil
sudo docker push ${ACR_LOGIN_SERVER}/zookeeper
sudo docker push ${ACR_LOGIN_SERVER}/mysql
sudo docker push ${ACR_LOGIN_SERVER}/skymind/skil
az acr repository list --name $ACR_NAME --output table # Outputs the list of images present in the registry
创建K8集群
你可以通过如下方式提供集群名称、节点数量、VM大小和OS磁盘大小来创建集群:
Shell
export K8_CLUSTER_NAME= # Replace this with the cluster name
export NODE_VM_SIZE= # Replace this with the cluster size. Standard_D4_v2 is preferable
export NODE_OSDISK_SIZE=100 # Size in GB for a single cluster VM node.
export NODE_COUNT=1 # Number of nodes in the cluster
az aks create --resource-group $RESOURCE_GROUP_NAME --name $K8_CLUSTER_NAME --node-count $NODE_COUNT --node-osdisk-size $NODE_OSDISK_SIZE --node-vm-size $NODE_VM_SIZE --generate-ssh-keys
配置ACR身份验证
需要在AKS集群和ACR注册表之间配置身份验证。这涉及授予AKS标识从ACR注册表中拉取镜像的适当权限。运行以下命令以完成该任务。
Shell
export CLIENT_ID=$(az aks show --resource-group $RESOURCE_GROUP_NAME --name $K8_CLUSTER_NAME --query "servicePrincipalProfile.clientId" --output tsv)
export ACR_ID=$(az acr show --name $ACR_NAME --resource-group $RESOURCE_GROUP_NAME --query "id" --output tsv)
az role assignment create --assignee $CLIENT_ID --role Reader --scope $ACR_ID
现在,你可以使用创建的kubernetes集群配置已安装的kubectl工具。
Shell
az aks get-credentials --resource-group $RESOURCE_GROUP_NAME --name $K8_CLUSTER_NAME
使用kubectl查询集群,并使用先前创建的保存的skil-app.yaml文件创建skil集群部署。
Shell
kubectl get nodes # 获取群集中的节点详细信息
kubectl create -f skil-app.yaml #使用提供的配置创建集群
kubectl get service skil --watch # 监控服务可用性的看门狗
监视过程中的外部-IP将在开始时挂起,一旦外部-IP地址从挂起更改为有效的IP地址,你可以停止Kubectl监控进程。访问url“http://external-ip:9008”,查看已部署的SKIL应用程序。
扩展应用程序
您可以分别使用az aks scale和kubectl scale增加集群大小和扩展部署。
Shell
az aks scale --resource-group $RESOURCE_GROUP_NAME --name $K8_CLUSTER_NAME --node-count 2
kubectl scale --replicas=3 deployment/skil