learn.lianglianglee.com/专栏/Serverless 技术公开课(完)/17 低成本运行 Spark 数据计算.md.html
2022-08-14 03:40:33 +08:00

293 lines
18 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<!-- saved from url=(0046)https://kaiiiz.github.io/hexo-theme-book-demo/ -->
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=no">
<link rel="icon" href="/static/favicon.png">
<title>17 低成本运行 Spark 数据计算.md.html</title>
<!-- Spectre.css framework -->
<link rel="stylesheet" href="/static/index.css">
<!-- theme css & js -->
<meta name="generator" content="Hexo 4.2.0">
</head>
<body>
<div class="book-container">
<div class="book-sidebar">
<div class="book-brand">
<a href="/">
<img src="/static/favicon.png">
<span>技术文章摘抄</span>
</a>
</div>
<div class="book-menu uncollapsible">
<ul class="uncollapsible">
<li><a href="/" class="current-tab">首页</a></li>
</ul>
<ul class="uncollapsible">
<li><a href="../">上一级</a></li>
</ul>
<ul class="uncollapsible">
<li>
<a href="/专栏/Serverless 技术公开课(完)/01 架构的演进.md.html">01 架构的演进</a>
</li>
<li>
<a href="/专栏/Serverless 技术公开课(完)/02 Serverless 的价值.md.html">02 Serverless 的价值</a>
</li>
<li>
<a href="/专栏/Serverless 技术公开课(完)/03 常见 Serverless 架构模式.md.html">03 常见 Serverless 架构模式</a>
</li>
<li>
<a href="/专栏/Serverless 技术公开课(完)/04 Serverless 技术选型.md.html">04 Serverless 技术选型</a>
</li>
<li>
<a href="/专栏/Serverless 技术公开课(完)/05 函数计算简介.md.html">05 函数计算简介</a>
</li>
<li>
<a href="/专栏/Serverless 技术公开课(完)/06 函数计算是如何工作的?.md.html">06 函数计算是如何工作的?</a>
</li>
<li>
<a href="/专栏/Serverless 技术公开课(完)/07 函数粘合云服务提供端到端解决方案.md.html">07 函数粘合云服务提供端到端解决方案</a>
</li>
<li>
<a href="/专栏/Serverless 技术公开课(完)/08 函数计算的开发与配置.md.html">08 函数计算的开发与配置</a>
</li>
<li>
<a href="/专栏/Serverless 技术公开课(完)/09 函数的调试与部署.md.html">09 函数的调试与部署</a>
</li>
<li>
<a href="/专栏/Serverless 技术公开课(完)/10 自动化 CI&amp;CD 与灰度发布.md.html">10 自动化 CI&amp;CD 与灰度发布</a>
</li>
<li>
<a href="/专栏/Serverless 技术公开课(完)/11 函数计算的可观测性.md.html">11 函数计算的可观测性</a>
</li>
<li>
<a href="/专栏/Serverless 技术公开课(完)/12 典型案例 1函数计算在音视频场景实践.md.html">12 典型案例 1函数计算在音视频场景实践</a>
</li>
<li>
<a href="/专栏/Serverless 技术公开课(完)/13 典型案例 3十分钟搭建弹性可扩展的 Web API.md.html">13 典型案例 3十分钟搭建弹性可扩展的 Web API</a>
</li>
<li>
<a href="/专栏/Serverless 技术公开课(完)/14 Serverless Kubernetes 容器服务介绍.md.html">14 Serverless Kubernetes 容器服务介绍</a>
</li>
<li>
<a href="/专栏/Serverless 技术公开课(完)/15 Serverless Kubernetes 应用部署及扩缩容.md.html">15 Serverless Kubernetes 应用部署及扩缩容</a>
</li>
<li>
<a href="/专栏/Serverless 技术公开课(完)/16 使用 Spot 低成本运行 Job 任务.md.html">16 使用 Spot 低成本运行 Job 任务</a>
</li>
<li>
<a class="current-tab" href="/专栏/Serverless 技术公开课(完)/17 低成本运行 Spark 数据计算.md.html">17 低成本运行 Spark 数据计算</a>
</li>
<li>
<a href="/专栏/Serverless 技术公开课(完)/18 GPU 机器学习开箱即用.md.html">18 GPU 机器学习开箱即用</a>
</li>
<li>
<a href="/专栏/Serverless 技术公开课(完)/19 基于 Knative 低成本部署在线应用,灵活自动伸缩.md.html">19 基于 Knative 低成本部署在线应用,灵活自动伸缩</a>
</li>
<li>
<a href="/专栏/Serverless 技术公开课(完)/20 快速构建 JenkinsGitlab 持续集成环境.md.html">20 快速构建 JenkinsGitlab 持续集成环境</a>
</li>
<li>
<a href="/专栏/Serverless 技术公开课(完)/21 在线应用的 Serverless 实践.md.html">21 在线应用的 Serverless 实践</a>
</li>
<li>
<a href="/专栏/Serverless 技术公开课(完)/22 通过 IDEMaven 部署 Serverless 应用实践.md.html">22 通过 IDEMaven 部署 Serverless 应用实践</a>
</li>
<li>
<a href="/专栏/Serverless 技术公开课(完)/23 企业级 CICD 工具部署 Serverless 应用的落地实践.md.html">23 企业级 CICD 工具部署 Serverless 应用的落地实践</a>
</li>
<li>
<a href="/专栏/Serverless 技术公开课(完)/24 Serverless 应用如何管理日志&amp;持久化数据.md.html">24 Serverless 应用如何管理日志&amp;持久化数据</a>
</li>
<li>
<a href="/专栏/Serverless 技术公开课(完)/25 Serverless 应用引擎产品的流量负载均衡和路由策略配置实践.md.html">25 Serverless 应用引擎产品的流量负载均衡和路由策略配置实践</a>
</li>
<li>
<a href="/专栏/Serverless 技术公开课(完)/26 Spring CloudDubbo 应用无缝迁移到 Serverless 架构.md.html">26 Spring CloudDubbo 应用无缝迁移到 Serverless 架构</a>
</li>
<li>
<a href="/专栏/Serverless 技术公开课(完)/27 SAE 应用分批发布与无损下线的最佳实践.md.html">27 SAE 应用分批发布与无损下线的最佳实践</a>
</li>
<li>
<a href="/专栏/Serverless 技术公开课(完)/28 如何通过压测工具+ SAE 弹性能力轻松应对大促.md.html">28 如何通过压测工具+ SAE 弹性能力轻松应对大促</a>
</li>
<li>
<a href="/专栏/Serverless 技术公开课(完)/29 SAE 极致应用部署效率.md.html">29 SAE 极致应用部署效率</a>
</li>
</ul>
</div>
</div>
<div class="sidebar-toggle" onclick="sidebar_toggle()" onmouseover="add_inner()" onmouseleave="remove_inner()">
<div class="sidebar-toggle-inner"></div>
</div>
<script>
function add_inner() {
let inner = document.querySelector('.sidebar-toggle-inner')
inner.classList.add('show')
}
function remove_inner() {
let inner = document.querySelector('.sidebar-toggle-inner')
inner.classList.remove('show')
}
function sidebar_toggle() {
let sidebar_toggle = document.querySelector('.sidebar-toggle')
let sidebar = document.querySelector('.book-sidebar')
let content = document.querySelector('.off-canvas-content')
if (sidebar_toggle.classList.contains('extend')) { // show
sidebar_toggle.classList.remove('extend')
sidebar.classList.remove('hide')
content.classList.remove('extend')
} else { // hide
sidebar_toggle.classList.add('extend')
sidebar.classList.add('hide')
content.classList.add('extend')
}
}
function open_sidebar() {
let sidebar = document.querySelector('.book-sidebar')
let overlay = document.querySelector('.off-canvas-overlay')
sidebar.classList.add('show')
overlay.classList.add('show')
}
function hide_canvas() {
let sidebar = document.querySelector('.book-sidebar')
let overlay = document.querySelector('.off-canvas-overlay')
sidebar.classList.remove('show')
overlay.classList.remove('show')
}
</script>
<div class="off-canvas-content">
<div class="columns">
<div class="column col-12 col-lg-12">
<div class="book-navbar">
<!-- For Responsive Layout -->
<header class="navbar">
<section class="navbar-section">
<a onclick="open_sidebar()">
<i class="icon icon-menu"></i>
</a>
</section>
</header>
</div>
<div class="book-content" style="max-width: 960px; margin: 0 auto;
overflow-x: auto;
overflow-y: hidden;">
<div class="book-post">
<p id="tip" align="center"></p>
<div><h1>17 低成本运行 Spark 数据计算</h1>
<h3>产品介绍</h3>
<h4>阿里云弹性容器实例 ECI</h4>
<p>ECI 提供安全的 Serverless 容器运行服务。无需管理底层服务器,只需要提供打包好的 Docker 镜像,即可运行容器,并仅为容器实际运行消耗的资源付费。</p>
<p><img src="assets/2020-08-26-031216.png" alt="image.png" /></p>
<h4>阿里云容器服务产品族</h4>
<p><img src="assets/2020-08-26-031217.png" alt="image.png" /></p>
<p>不论是托管版的 KubernetesACK还是 Serverless 版 KubernetesASK都可以使用 ECI 作为容器资源层,其背后的实现就是借助虚拟节点技术,通过一个叫做 Virtual Node 的虚拟节点对接 ECI。</p>
<p><img src="assets/2020-08-26-031219.png" alt="image.png" /></p>
<h4>Kubernetes + ECI</h4>
<p>有了 Virtual Kubelet标准的 Kubernetes 集群就可以将 ECS 和虚拟节点混部,将 Virtual Node 作为应对突发流量的弹性资源池。</p>
<p><img src="assets/2020-08-26-031228.png" alt="image.png" /></p>
<h4>ASKServerless Kubernetes+ ECI</h4>
<p>Serverless 集群中没有任何 ECS worker 节点,也无需预留、规划资源,只有一个 Virtual Node所有的 Pod 的创建都是在 Virtual Node 上,即基于 ECI 实例。</p>
<p><img src="assets/2020-08-26-031231.png" alt="image.png" /></p>
<p>Serverless Kubernetes 是以容器和 Kubernetes 为基础的 Serverless 服务,它提供了一种简单易用、极致弹性、最优成本和按需付费的 Kubernetes 容器服务,其中无需节点管理和运维,无需容量规划,让用户更关注应用而非基础设施的管理。</p>
<h3>Spark on Kubernetes</h3>
<p>Spark 自 2.3.0 开始试验性支持 Standalone、on YARN 以及 on Mesos 之外的新的部署方式:<a href="https://spark.apache.org/docs/2.3.0/running-on-kubernetes.html">Running Spark on Kubernetes</a>,如今支持已经非常成熟。</p>
<h4>Kubernetes 的优势</h4>
<p><img src="assets/2020-08-26-031232.png" alt="image.png" /></p>
<p>Spark on kubernetes 相比于 on Yarn 等传统部署方式的优势:</p>
<ul>
<li>统一的资源管理。不论是什么类型的作业都可以在一个统一的 Kubernetes 集群中运行,不再需要单独为大数据作业维护一个独立的 YARN 集群。</li>
<li>传统的将计算和存储混合部署常常会为了扩存储而带来额外的计算扩容这其实就是一种浪费同理只为了提升计算能力也会带来一段时期的存储浪费。Kubernetes 直接跳出了存储限制,将离线计算的计算和存储分离,可以更好地应对单方面的不足。</li>
<li>弹性的集群基础设施。</li>
<li>轻松实现复杂的分布式应用的资源隔离和限制,从 YRAN 复杂的队列管理和队列分配中解脱。</li>
<li>容器化的优势。每个应用都可以通过 Docker 镜像打包自己的依赖,运行在独立的环境,甚至包括 Spark 的版本,所有的应用之间都是完全隔离的。</li>
<li>大数据上云。目前大数据应用上云常见的方式有两种1用 ECS 自建 YARN不限于 YARN集群2购买 EMR 服务,目前所有云厂商都有这类 PaaS如今多了一个选择——Kubernetes。</li>
</ul>
<h4>Spark 调度</h4>
<p><img src="assets/2020-08-26-031234.png" alt="image.png" /></p>
<p>图中橙色部分是原生的 Spark 应用调度流程,而 Spark on Kubernetes 对此做了一定的扩展(黄色部分),实现了一个 <strong>KubernetesClusterManager</strong>。其中 **KubernetesClusterSchedulerBackend <strong>扩展了原生的</strong>CoarseGrainedSchedulerBackend**新增了 **ExecutorPodsLifecycleManager、ExecutorPodsAllocator 和 KubernetesClient **等组件,实现了将标准的 Spark Driver 进程转换成 Kubernetes 的 Pod 进行管理。</p>
<h4>Spark submit</h4>
<p>在 Spark Operator 出现之前,在 Kubernetes 集群提交 Spark 作业只能通过 Spark submit 的方式。创建好 Kubernetes 集群,在本地即可提交作业。</p>
<p><img src="assets/2020-08-26-031237.png" alt="image.png" /></p>
<p>作业启动的基本流程:</p>
<ul>
<li>Spark 先在 K8s 集群中创建 Spark Driverpod</li>
<li>Driver 起来后,调用 K8s API 创建 ExecutorspodsExecutors 才是执行作业的载体。</li>
<li>作业计算结束Executor Pods 会被自动回收Driver Pod 处于 Completed 状态(终态)。可以供用户查看日志等。</li>
<li>Driver Pod 只能被用户手动清理,或者被 K8s GC 回收。</li>
</ul>
<p>直接通过这种 Spark submit 的方式,参数非常不好维护,而且不够直观,尤其是当自定义参数增加的时候;此外,没有 Spark Application 的概念了,都是零散的 Kubernetes Pod 和 Service 这些基本的单元,当应用增多时,维护成本提高,缺少统一管理的机制。</p>
<h4>Spark Operator</h4>
<p><a href="https://github.com/GoogleCloudPlatform/spark-on-k8s-operator">Spark Operator</a> 就是为了解决在 Kubernetes 集群部署并维护 Spark 应用而开发的Spark Operator 是经典的 CRD + Controller即 Kubernetes Operator 的实现。</p>
<p><img src="assets/2020-08-26-031240.png" alt="image.png" /></p>
<p>下图为 SparkApplication 状态机:</p>
<p><img src="assets/2020-08-26-031242.png" alt="image.png" /></p>
<h4>Serverless Kubernetes + ECI</h4>
<p>那么,如果在 Serverless Kubernetes 集群中运行 Spark其实际上是对原生 Spark 的进一步精简。</p>
<p><img src="assets/2020-08-26-031247.png" alt="image.png" /></p>
<h4>存储选择</h4>
<p><img src="assets/2020-08-26-031248.png" alt="image.png" /></p>
<p>对于批量处理的数据源,由于集群不是基于 HDFS 的所以数据源会有不同需要计算与存储分离Kubernetes 集群只负责提供计算资源。</p>
<ul>
<li>数据源的存储可以采用阿里云对象存储 OSS、阿里云分布式存储 HDFS 等。</li>
<li>计算的临时数据、Shuffle 数据可以采用 ECI 提供的免费的 40GB 的系统盘存储空间,还可以自定义挂载阿里云数据盘、以及 CPFS/NAS 文件系统等,都拥有非常不错的性能。</li>
</ul>
</div>
</div>
<div>
<div style="float: left">
<a href="/专栏/Serverless 技术公开课(完)/16 使用 Spot 低成本运行 Job 任务.md.html">上一页</a>
</div>
<div style="float: right">
<a href="/专栏/Serverless 技术公开课(完)/18 GPU 机器学习开箱即用.md.html">下一页</a>
</div>
</div>
</div>
</div>
</div>
</div>
<a class="off-canvas-overlay" onclick="hide_canvas()"></a>
</div>
<script defer src="https://static.cloudflareinsights.com/beacon.min.js/v652eace1692a40cfa3763df669d7439c1639079717194" integrity="sha512-Gi7xpJR8tSkrpF7aordPZQlW2DLtzUlZcumS8dMQjwDHEnw9I7ZLyiOj/6tZStRBGtGgN6ceN6cMH8z7etPGlw==" data-cf-beacon='{"rayId":"7099747c7d103d60","version":"2021.12.0","r":1,"token":"1f5d475227ce4f0089a7cff1ab17c0f5","si":100}' crossorigin="anonymous"></script>
</body>
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-NPSEEVD756"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag() {
dataLayer.push(arguments);
}
gtag('js', new Date());
gtag('config', 'G-NPSEEVD756');
var path = window.location.pathname
var cookie = getCookie("lastPath");
console.log(path)
if (path.replace("/", "") === "") {
if (cookie.replace("/", "") !== "") {
console.log(cookie)
document.getElementById("tip").innerHTML = "<a href='" + cookie + "'>跳转到上次进度</a>"
}
} else {
setCookie("lastPath", path)
}
function setCookie(cname, cvalue) {
var d = new Date();
d.setTime(d.getTime() + (180 * 24 * 60 * 60 * 1000));
var expires = "expires=" + d.toGMTString();
document.cookie = cname + "=" + cvalue + "; " + expires + ";path = /";
}
function getCookie(cname) {
var name = cname + "=";
var ca = document.cookie.split(';');
for (var i = 0; i < ca.length; i++) {
var c = ca[i].trim();
if (c.indexOf(name) === 0) return c.substring(name.length, c.length);
}
return "";
}
</script>
</html>