概述
R语言被广泛用于统计分析、绘图的开源语言和操作环境,也是用于统计计算和统计制图的优秀工具。 Shiny 是由Rstudio推出的一个面向R软件的产品,可让用户无需编写繁重的代码,即可从R直接构建交互式的Web应用程序,并通过 Web 应用的形式通过互联网提供给人们进行访问,使访问者可以轻松地与数据和分析进行交互。
来自全球各地的行业专家、数据科学家及分析师已基于 Shiny 创建了许多功能强大的 Web 应用在 Shiny 的开源版本中未提供诸多重要功能,如身份验证、多Shiny进程支持、Shiny应用性能监控、基于SSL的安全连接、资源分配控制等。如何实现企业级的安全认证?如何实现秒级的故障恢复?如何实现海量并发用户的访问支撑? 这些因素均使得用户在构建面向多用户场景的企业级 Shiny 生产环境时遇到了极大的障碍。
当前阶段Kubernetes是一个非常棒的容器编排平台,本文将带大家部署ShinyProxy到Kubernetes平台中。
ShinyProxy简介
Open Analytics 在Shiny开源版本的基本功能之上开发了 ShinyProxy,提供了一系列扩展的增强特性,如身份验证和授权、TLS协议支持、Shiny应用程序容器化及多并发支持等,同时 ShinyProxy 是基于 Apache 许可的100%开源项目。 ShinyProxy 前端使用成熟的企业级 Java 框架Spring Boot来完成Web应用程序的用户认证、鉴权及后端Shiny应用的调度和管理,后端基于 Docker 技术灵活运行封装了R应用的Shiny容器。
整个平台的构建过程将主要分为四个步骤:
- 创建基于vSphere With Tanzu的Kuberneter Cluster;
- 封装相关Docker Images,并上传到企业私有仓库Harbor中;
- 部署 ShinyProxy;
- 验证ShinyProxy功能;
环境需求:
- 具备管理员权限的Kubernetes集群(本环境中采用VMware vSphere With Tanzu平台);
- 一台可以Linux操作机,可以拉取镜像和访问企业Harbor;
- (可选)LDAP服务器;
创建vSphere With Tanzu的Tanzu Kubernertes集群
准备Tanzu Kubernetes集群配置文件。
cat <<EOF > /root/dev-tkg01.yaml
apiVersion: run.tanzu.vmware.com/v1alpha1
kind: TanzuKubernetesCluster
metadata:
name: dev-tkg01
spec:
topology:
controlPlane:
count: 3
class: guaranteed-large
storageClass: wcp-storage-policy
workers:
count: 4
class: guaranteed-xlarge
storageClass: wcp-storage-policy
distribution:
version: v1.17.7+vmware.1-tkg.1.154236c
settings:
network:
cni:
name: calico
services:
cidrBlocks: ["198.51.100.0/12"]
pods:
cidrBlocks: ["192.0.2.0/16"]
EOF
先登录vSphere With Tanzu,再通过配置文件创建Tanzu Kubernetes集群
kubectl vsphere login --server 10.42.1.1 -u Administrator@vsphere.lcoal
kubectl apply -f dev-tkg01.yaml
等待集群创建完成后,登录到Tanzu Kubernetes集群,并通过kubectl get nodes检查集群运行状态。
kubectl vsphere login --server 10.42.1.1 --tanzu-kubernetes-cluster-name dev-tkg01 --tanzu-kubernetes-cluster-namespace dev -u administrator@vsphere.local
kubectl config use-context dev-tkg01
[liguoqiang@jump-centos wcp]$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
dev-tkg01-control-plane-sxrcm Ready master 13d v1.17.7+vmware.1
dev-tkg01-workers-9cpsz-66c6784896-5pc69 Ready <none> 13d v1.17.7+vmware.1
dev-tkg01-workers-9cpsz-66c6784896-mkplw Ready <none> 13d v1.17.7+vmware.1
dev-tkg01-workers-9cpsz-66c6784896-wcjpq Ready <none> 13d v1.17.7+vmware.1
应用PSP安全策略。
cat <<EOF > /root/psp-allow-all.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: psp:privileged
rules:
- apiGroups: ['policy']
resources: ['podsecuritypolicies']
verbs: ['use']
resourceNames:
- vmware-system-privileged
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: all:psp:privileged
roleRef:
kind: ClusterRole
name: psp:privileged
apiGroup: rbac.authorization.k8s.io
subjects:
- kind: Group
name: system:serviceaccounts
apiGroup: rbac.authorization.k8s.io
EOF
kubectl apply -f /root/psp-allow-all.yaml
制作相关Docker Images
ShinyProxy 原生支持三种容器后端平台,单机版本的 Docker、Docker Swarm 集群以及 Kubernetes 集群。我们将完成基于VMware vSphere With Tanzu的Kubernetes平台上的部署。
下载Shinyproxy for Kubernetes的示例文件。
cd ~
git clone https://github.com/openanalytics/shinyproxy-config-examples.git
cd ~/shinyproxy-config-examples/03-containerized-kubernetes
vi kube-proxy-sidecar/Dockerfile
修改 kube-proxy-sidecar目录下的Dockerfile文件,该容器以Sidecar方式运行,负责创建pod等操作,内容为:
FROM alpine:3.6
ADD https://storage.googleapis.com/kubernetes-release/release/v1.17.8/bin/linux/amd64/kubectl /usr/local/bin/kubectl
RUN chmod +x /usr/local/bin/kubectl
EXPOSE 8001
ENTRYPOINT ["/usr/local/bin/kubectl", "proxy"]
进入到shinyproxy-example,修改shinyproxy配置文件。
cd ~/shinyproxy-config-examples/03-containerized-kubernetes/shinyproxy-example
vi application.yml
Application.yml用于Shinyproxy配置,包括认证、应用等,下面是Simple认证的配置。
proxy:
port: 8080
authentication: simple
admin-groups: admins
users:
- name: admin
password: VMware1!
groups: admins
- name: guest
password: VMware1!
container-backend: kubernetes
container-wait-time: 300000
heartbeat-rate: 10000
heartbeat-timeout: 300000
kubernetes:
internal-networking: true
url: http://localhost:8001
namespace: default
image-pull-policy: IfNotPresent
image-pull-secret:
specs:
- id: 00_demo_shiny_application
display-name: Simple Shiny Application Demo
description: Simple Shiny Application Demo
container-image: harbor.bzz.ccut.edu.cn/library/shiny-application:V1
access-groups: [admins, guest]
- id: 01_hello_shiny_application
display-name: Hello Application
description: Application which demonstrates the basics of a Shiny app
container-cmd: ["R", "-e", "shinyproxy::run_01_hello()"]
container-image: harbor.bzz.ccut.edu.cn/library/shinyproxy-demo
access-groups: [admins, guest]
spring:
servlet:
multipart:
max-file-size: 100MB
max-request-size: 100MB
logging:
file:
shinyproxy.log
(可选)LDAP认证配置。
注意1:在url中制定dn后,user-search-base和group-search-base不能重复指定。 注意2:specs中要配置访问组为Ldap组。
proxy:
port: 8080
authentication: ldap
admin-groups: LabAdmins
ldap:
url: ldap://mgmt-ad01.corp.local:389/dc=corp,dc=local
manager-dn: CN=svcadmin,CN=Users,DC=corp,DC=local
manager-password: VMware1!
user-search-base: OU=Labs
user-search-filter: (sAMAccountName={0})
group-search-base: OU=Labs
group-search-filter: (member={0})
container-backend: kubernetes
container-wait-time: 300000
heartbeat-rate: 10000
heartbeat-timeout: 300000
kubernetes:
internal-networking: true
url: http://localhost:8001
namespace: default
image-pull-policy: IfNotPresent
image-pull-secret:
specs:
- id: 00_demo_shiny_application
display-name: Simple Shiny Application Demo
description: Simple Shiny Application Demo
container-image: harbor.bzz.ccut.edu.cn/library/shiny-application:V1
access-groups: [LabAdmins]
- id: 01_hello_shiny_application
display-name: Hello Application
description: Application which demonstrates the basics of a Shiny app
container-cmd: ["R", "-e", "shinyproxy::run_01_hello()"]
container-image: harbor.bzz.ccut.edu.cn/library/shinyproxy-demo
access-groups: [LabAdmins]
spring:
servlet:
multipart:
max-file-size: 100MB
max-request-size: 100MB
logging:
file:
shinyproxy.log
完成配置文件修改后,我们开始制作所需的Docker镜像。 我们将创建用于 ShinyProxy 的一个简单 Shiny 测试应用,为了简化 Shiny 应用的编译过程,我们在本文中直接使用 Rocker 官方的示例 shiny 容器作为测试应用。您也可以使用企业制作好的Docker Images,这些应用将在Application.yml中使用。
docker pull rocker/shiny:latest
docker tag rocker/shiny:latest harbor.bzz.ccut.edu.cn/library/shiny-application:V1
docker push harbor.bzz.ccut.edu.cn/library/shiny-application:V1
构建kube-proxy-sidecar的Docker镜像。
cd ~/shinyproxy-config-examples/03-containerized-kubernetes/kube-proxy-sidecar
docker build -t harbor.bzz.ccut.edu.cn/library/kube-proxy-sidecar:1.17.8 .
docker push harbor.bzz.ccut.edu.cn/library/kube-proxy-sidecar:1.17.8
构建ShinyProxy镜像。
cd ~/shinyproxy-config-examples/03-containerized-kubernetes/shinyproxy-example
docker build -t harbor.bzz.ccut.edu.cn/library/shinyproxy-application:V1
docker push harbor.bzz.ccut.edu.cn/library/shinyproxy-application:V1
构建ShinyProxy演示应用镜像。
docker pull openanalytics/shinyproxy-demo:latest
docker tag openanalytics/shinyproxy-demo:latest harbor.bzz.ccut.edu.cn/library/shinyproxy-demo:latest
docker push harbor.bzz.ccut.edu.cn/library/shinyproxy-demo:latest
部署
上一部分我们完成了镜像制作,下一步我们就可以开始进行Shinyproxy在Kubernetes环境中的部署。
首先修改sp-service.yaml文件,更改为LoadBalancer类型,由NSX-T提供负载均衡。
cd ~/shinyproxy-config-examples/03-containerized-kubernetes/
vi sp-service.yaml
kind: Service
apiVersion: v1
metadata:
name: shinyproxy
spec:
type: LoadBalancer
selector:
run: shinyproxy
ports:
- protocol: TCP
port: 80
targetPort: 8080
再修改sp-deployment.yaml文件,包含两个container,一个是ShinyProxy,一个是Kube-proxy-sidecar,ShinyProxy是主镜像。
vi sp-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: shinyproxy
spec:
selector:
matchLabels:
run: shinyproxy
replicas: 1
template:
metadata:
labels:
run: shinyproxy
spec:
containers:
- name: shinyproxy
image: harbor.bzz.ccut.edu.cn/library/shinyproxy-application:V1
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
- name: kube-proxy-sidecar
image: harbor.bzz.ccut.edu.cn/library/kube-proxy-sidecar:1.17.8
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8001
部署
部署非常简单,切换到要部署的Tanzu Kubernetes集群,并应用三个yaml文件。
kubectl config use-context dev-tkg01
kubectl apply -f sp-authorization.yaml
kubectl apply -f sp-deployment.yaml
kubectl apply -f sp-service.yaml
部署完成后,使用下面的命令查看ShinyProxy的部署情况,正常情况下会很快显示 Running 状态
kubectl get pods -A -w
部署过程会自动创建NSX-T的负载均衡器用于访问 ShinyProxy,通过下面的命令可在 EXTERNAL-IP 列获取NSX-T负载均衡器信息的访问地址。
[liguoqiang@jump-centos shinyproxy-example]$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 198.48.0.1 <none> 443/TCP 12d
shinyproxy LoadBalancer 198.55.177.182 10.42.1.14 80:31039/TCP 7h54m
supervisor ClusterIP None <none> 6443/TCP 12d
访问和测试
访问负载均衡器地址及端口,正常可显示 ShinyProxy 的登录界面。输入之前配置的用户名和密码信息,可显示 ShinyProxy 的管理界面,点击其中已有的 Shiny 应用即可启动它们。至此,ShinyProxy 平台已经成功地运行在 vSphere With Tanzu的Tanzu Kubernetes集群服务上。
[liguoqiang@jump-centos shinyproxy-example]$ kubectl get pods
NAME READY STATUS RESTARTS AGE
shinyproxy-745df74cdd-6dk5l 2/2 Running 0 8m1s
sp-pod-92bc3c26-a641-4c63-b03c-c11621652aea 1/1 Running 0 37s
sp-pod-e3ef68de-fc09-40d7-bfcd-e6405a8ec7ae 1/1 Running 0 95s
完成
至此我们通过vSpehre With Tanzu的Tanzu Kubernetes集群部署了ShinyProxy平台。