用考拉和火花进行机器学习
实用指南
有火花后端的熊猫
andas 被认为是用 python 编写的事实上的数据分析库。大多数数据科学家或机器学习工程师在转到其他库之前都是从 Pandas 和 Numpy 开始的。没有一次可以围绕使用 Pandas 作为标准数据处理库展开辩论。使用 Pandas 有很多好处,但是 Pandas API 适应分布式处理的一个关键瓶颈是。像摩丁和达斯克这样的解决方案在一定程度上解决了这个问题。
作者使用 Canva.com 的图片
说到使用分布式处理框架,Spark 是专业人员和大型数据处理中心事实上的选择。最近,Databricks 的团队开源了一个名为考拉的库,用 spark 后端实现了熊猫 API。这个库正在积极开发中,覆盖了超过 60%的熊猫 API。要阅读更多关于使用考拉的内容,请参考我之前的文章激发熊猫的火花:数据布里克的考拉与谷歌实验室。
在本教程中,我将带领您使用 Koalas 和 PySpark 执行探索性数据分析,并使用 Spark 分布式框架构建回归模型。在处理大型数据集时,使用考拉而不是熊猫 API 有很多好处。一些关键点是
- 大数据处理变得简单
- 从熊猫到考拉的快速转变
- 与 PySpark 无缝集成
本教程的目标是利用 Spark 后端,使用考拉完成一个完整的机器学习开发周期。工作中的谷歌合作实验室将被嵌入。
在 Google 联合实验室中设置 Spark 3.0.1
作为第一步,我用 spark 安装配置 google colab 运行时。详细内容,读者可以在 Google Colab om medium 阅读我的文章入门 Spark 3.0.0。
我们将安装以下程序
- Java 8
- 火花-3.0.1
- Hadoop3.2
- Findspark
您可以使用下面的命令集安装最新版本的 Spark。
# Run below commands
!apt-get install openjdk-8-jdk-headless -qq > /dev/null
!wget -q http://apache.osuosl.org/spark/spark-3.0.1/spark-3.0.1-bin-hadoop3.2.tgz
!tar xf spark-3.0.1-bin-hadoop3.2.tgz
!pip install -q findspark
环境变量
安装完 spark 和 Java 之后,设置安装 Spark 和 Java 的环境变量。
import os
os.environ["JAVA_HOME"] = "/usr/lib/jvm/java-8-openjdk-amd64"
os.environ["SPARK_HOME"] = "/content/spark-3.0.1-bin-hadoop3.2"
火花安装试验
让我们在 google colab 环境中测试 spark 的安装。
import findspark
findspark.init()
from pyspark.sql import SparkSession
spark = SparkSession.builder.master("local[*]").getOrCreate()
# Test the spark
df = spark.createDataFrame([{"hello": "world"} for x in range(1000)])
df.show(3, False)/content/spark-3.0.1-bin-hadoop3.2/python/pyspark/sql/session.py:381: UserWarning: inferring schema from dict is deprecated,please use pyspark.sql.Row instead
warnings.warn("inferring schema from dict is deprecated,"
+-----+
|hello|
+-----+
|world|
|world|
|world|
+-----+
only showing top 3 rows
安装考拉
在安装 spark 并确保它正常工作后,我们现在可以使用 pip 安装 databrick 的考拉了。
! pip install koalasRequirement already satisfied: koalas in /usr/local/lib/python3.6/dist-packages (1.2.0)
Requirement already satisfied: numpy<1.19.0,>=1.14 in /usr/local/lib/python3.6/dist-packages (from koalas) (1.18.5)
Requirement already satisfied: matplotlib<3.3.0,>=3.0.0 in /usr/local/lib/python3.6/dist-packages (from koalas) (3.2.2)
Requirement already satisfied: pyarrow>=0.10 in /usr/local/lib/python3.6/dist-packages (from koalas) (0.14.1)
Requirement already satisfied: pandas<1.1.0,>=0.23.2 in /usr/local/lib/python3.6/dist-packages (from koalas) (1.0.5)
Requirement already satisfied: pyparsing!=2.0.4,!=2.1.2,!=2.1.6,>=2.0.1 in /usr/local/lib/python3.6/dist-packages (from matplotlib<3.3.0,>=3.0.0->koalas) (2.4.7)
Requirement already satisfied: cycler>=0.10 in /usr/local/lib/python3.6/dist-packages (from matplotlib<3.3.0,>=3.0.0->koalas) (0.10.0)
Requirement already satisfied: kiwisolver>=1.0.1 in /usr/local/lib/python3.6/dist-packages (from matplotlib<3.3.0,>=3.0.0->koalas) (1.2.0)
Requirement already satisfied: python-dateutil>=2.1 in /usr/local/lib/python3.6/dist-packages (from matplotlib<3.3.0,>=3.0.0->koalas) (2.8.1)
Requirement already satisfied: six>=1.0.0 in /usr/local/lib/python3.6/dist-packages (from pyarrow>=0.10->koalas) (1.15.0)
Requirement already satisfied: pytz>=2017.2 in /usr/local/lib/python3.6/dist-packages (from pandas<1.1.0,>=0.23.2->koalas) (2018.9)
Requirement already satisfied: pyarrow in /usr/local/lib/python3.6/dist-packages (0.14.1)
Requirement already satisfied: numpy>=1.14 in /usr/local/lib/python3.6/dist-packages (from pyarrow) (1.18.5)
Requirement already satisfied: six>=1.0.0 in /usr/local/lib/python3.6/dist-packages (from pyarrow) (1.15.0)# Install compatible version of pyarrow
! pip install pyarrowimport seaborn as sns/usr/local/lib/python3.6/dist-packages/statsmodels/tools/_testing.py:19: FutureWarning: pandas.util.testing is deprecated. Use the functions in the public API at pandas.testing instead.
import pandas.util.testing as tmimport databricks.koalas as ks
机器学习开发周期
开发机器学习模型的标准做法是执行探索性数据分析,执行特征工程,并建立模型。我将试着用考拉来接触上述观点的基础。我相信大多数 ML 工程师/科学家都使用 Pandas API 来执行 EDA 和特征工程。我演示了如何使用考拉来完成这项工作,并使用 PySpark 来构建模型。
我将使用联合循环发电厂数据集来预测每小时净电力输出(EP)。我已经把数据上传到我的 GitHub 上,这样用户就可以重现结果了。
使用考拉进行探索性数据分析
作为第一步,我想使用考拉 API 探索给定的数据、它的分布和依赖性。我将包括一个简单的例子来演示这个想法,用户可以针对手头的问题扩展它。
下载数据并保存在本地
# Downloading the clustering dataset
!wget -q 'https://raw.githubusercontent.com/amjadraza/blogs-data/master/spark_ml/ccpp.csv'
使用考拉read_csv
方法读取数据。要阅读更多关于 API 的内容,请关注考拉官方文档
# Read the iris data
kdf_ccpp = ks.read_csv("ccpp.csv")kdf_ccpp.columnsIndex(['AT', 'V', 'AP', 'RH', 'PE'], dtype='object')kdf_ccpp.head()
就像熊猫一样,考拉也有绘制数据以理解变量的功能。在下面的例子中,我绘制了原始数据和它的平滑版本。这个例子演示了plot
和rolling
窗口方法的使用
kdf_ccpp['AT'].plot(figsize=(12,6))
kdf_ccpp['AT'].rolling(window=20).mean().plot()
kdf_ccpp['AT'].rolling(window=200).mean().plot()<matplotlib.axes._subplots.AxesSubplot at 0x7f9992f63320>
作者图片:更平滑版本的 AT 特性图
就像上面的绘图一样,用户可以绘制所有的列。参见下面的命令
kdf_ccpp.plot(figsize=(12,6))<matplotlib.axes._subplots.AxesSubplot at 0x7f9993b7e668>
作者图像:原始数据图
使用 20 个数据点的移动平均值绘制所有列。
kdf_ccpp.rolling(window=20).mean().plot(figsize=(12,6))<matplotlib.axes._subplots.AxesSubplot at 0x7f99939bd358>
作者图片:平滑数据图
下面的命令演示了describe
的使用,这是一种类似于 Pandas API 中的方法。
kdf_ccpp.describe()
作者图片
特征工程
特征工程步骤通常与 EDA 结合在一起。用户准备特性的目的是获得最具预测性和分布良好的特性集。在本文中,我将演示如何使用考拉来执行特征工程。
为了理解不同变量之间的关系,paiprplot
函数seaborn
被广泛使用。使用 below 命令绘制数据集中变量的 pairplot。由于 Seaborn 不支持考拉数据帧,用户必须在调用 pairplot 之前将其转换为熊猫数据帧。
sns.pairplot(kdf_ccpp.to_pandas())<seaborn.axisgrid.PairGrid at 0x7f99989459e8>
作者提供的图片:原始要素和目标的配对图
通过查看上图,我们可以看到很多离群值,对于一些变量与目标的关系并不清楚。为了去除异常值,最简单的解决方案是计算移动平均值,我用考拉来演示。
sns.pairplot(kdf_ccpp.rolling(window=20).mean().to_pandas())<seaborn.axisgrid.PairGrid at 0x7f9993a5ada0>
作者提供的图像:平滑特征和目标的配对图
看起来 20 天移动平均线与目标变量有更好的关系,因此使用 20 天平均线更有意义。
使用 PySpark 建模
一旦 EDA 和特性工程完成,就该建立预测模型了。使用考拉数据框架的好处之一是用户可以无缝地创建 Spark 数据框架。在下一节中,我将演示如何使用 PySpark API 来构建和训练梯度推进机器(GBM)。
# Create the moving average features
kdf = kdf_ccpp.rolling(window=20, min_periods=1).mean()# Convert the Koalas DataFrame into Spark DataFrame
sdf = kdf.to_spark()sdf.show(5,False)+------------------+------+------------------+-----------------+-----------------+
|AT |V |AP |RH |PE |
+------------------+------+------------------+-----------------+-----------------+
|14.96 |41.76 |1024.07 |73.17 |463.26 |
|20.07 |52.36 |1022.055 |66.125 |453.815 |
|15.083333333333334|48.04 |1018.7566666666667|74.79666666666667|465.3966666666667|
|16.5275 |50.36 |1016.6275 |75.2575 |460.6675 |
|15.386000000000001|47.788|1015.1479999999999|79.53 |463.314 |
+------------------+------+------------------+-----------------+-----------------+
only showing top 5 rows
现在,使用 PySpark API 构建模型。关于使用 PySpark 构建模型的更多细节,请参考我的文章使用 Spark 进行机器学习。
from pyspark.ml.regression import LinearRegression
from pyspark.ml.feature import VectorAssembler
from pyspark.ml.evaluation import RegressionEvaluator
from pyspark.ml.regression import GBTRegressor
准备与 PySpark 型号兼容的功能
# Create the feature column using VectorAssembler class
vectorAssembler = VectorAssembler(inputCols =["AT", "V", "AP", "RH"], outputCol = "features")
vpp_sdf = vectorAssembler.transform(sdf)vpp_sdf.show(2, False)+-----+-----+--------+------+-------+-----------------------------+
|AT |V |AP |RH |PE |features |
+-----+-----+--------+------+-------+-----------------------------+
|14.96|41.76|1024.07 |73.17 |463.26 |[14.96,41.76,1024.07,73.17] |
|20.07|52.36|1022.055|66.125|453.815|[20.07,52.36,1022.055,66.125]|
+-----+-----+--------+------+-------+-----------------------------+
only showing top 2 rows
创建 tarin 并测试拆分
# Define train and test data split
splits = vpp_sdf.randomSplit([0.7,0.3])
train_df = splits[0]
test_df = splits[1]
建立和训练模型
# Define the GBT Model
gbt = GBTRegressor(featuresCol="features", labelCol="PE")
gbt_model = gbt.fit(train_df)
gbt_predictions = gbt_model.transform(test_df)
评估模型准确性
# Evaluate the GBT Model
gbt_evaluator = RegressionEvaluator(labelCol="PE", predictionCol="prediction", metricName="rmse")
gbt_rmse = gbt_evaluator.evaluate(gbt_predictions)
print("The RMSE of GBT Tree regression Model is {}".format(gbt_rmse))The RMSE of GBT Tree regression Model is 1.077464978110743
将预测转换回考拉数据框架
kdf_predictions = ks.DataFrame(gbt_predictions)kdf_predictions.head()
让我们从模型中画出实际值和预测值。
kdf_predictions[['PE', 'prediction']].plot(figsize=(12,8))<matplotlib.axes._subplots.AxesSubplot at 0x7f9992ba4828>
作者图片:实际 PE 与预测 PE 图
一个有效的 Google Colab
下面是工作谷歌 colab 笔记本重新创建教程。试试看,在可能的情况下,在目前用考拉代替熊猫的基础上开发机器学习算法。
结论
在本教程中,我演示了使用考拉来执行探索性数据分析和特征工程。对于熊猫用户来说,使用 Spark 后端进行分布式计算的好处是,切换到考拉是直接的。在讨论的要点下面
- 考拉过去常常表演 EDA
- 使用考拉的特征工程
- PySpark 与考拉的整合
参考资料/阅读/链接
- 【https://spark.apache.org/docs/latest/ml-features.html 号
- 【https://koalas.readthedocs.io/en/latest/?badge=latest
- https://towards data science . com/machine-learning-with-spark-f1dbc 1363986
- https://medium . com/analytics-vid hya/getting-started-spark 3-0-0-with-Google-colab-9796d 350d 78
- https://medium . com/analytics-vid hya/spark-ifying-pandas-data bricks-koala-with-Google-colab-93028890 db5
Python 中的朝鲜语自然语言处理
利用“KoNLPy”模块进行词法分析和词性标注
通过阅读这篇文章,您将学会使用 Python 为朝鲜语执行简单的自然语言处理任务,如词法分析和词性标注。我们将使用一个名为KoNLPy
的 Python 模块。基于官方文档,KoNLPy(读作为 *ko en el PIE*
):
“…是一个用于朝鲜语自然语言处理(NLP)的 Python 包。”
该模块基于以下理念:
- 保持简单。
- 让它变得简单。对人类来说。
- 网络民主让每个人都可以贡献自己的想法和建议,
本教程有 3 个部分:
- 设置
- 履行
- 结论
让我们继续下一部分,开始安装必要的模块。
1.设置
Windows 操作系统
安装有点复杂,因为您需要确保您已经安装了 Java 版本 1.7。进入以下链接为您的电脑下载必要的 JDK。
从 Python 访问 Java 类库需要JPype
。您需要根据您的操作系统和 Python 版本安装正确的JPype
。用下面的代码检查它
python --version
前往下面的链接并下载相应的文件。我将使用下面的文件,因为我在 64 位 Windows 机器上运行 Python3.7.4。
JPype1-0.7.2-cp37-cp37m-win_amd64.whl
将文件放在一个目录中,然后打开一个终端。强烈建议您事先设置一个虚拟环境。将目录更改为 wheel 文件所在的根文件夹。运行以下命令来安装它。根据您下载的内容相应地修改名称。
pip install JPype1-0.5.7-cp27-none-win_amd64.whl
通过pip install
命令继续安装koNLPy
。
pip install konlpy
其他操作系统
如果你正在使用其他种类的操作系统,请查看官方的文档,因为我还没有亲自测试过。它支持 Linux 和 MacOS,并且安装更加简单。
让我们继续下一节,开始写一些 Python 代码。
2.履行
这个模块为我们提供了几个不同的类来执行词法分析和词性标注。它们中的每一个在最终结果和性能上都是不同的。查看下面的链接,了解更多关于时间和性能分析的信息。
[Kkma](https://konlpy.org/en/latest/api/konlpy.tag/#konlpy.tag._kkma.Kkma)
[Komoran](https://konlpy.org/en/latest/api/konlpy.tag/#konlpy.tag._komoran.Komoran)
[Hannanum](https://konlpy.org/en/latest/api/konlpy.tag/#konlpy.tag._hannanum.Hannanum)
[Okt](https://konlpy.org/en/latest/api/konlpy.tag/#konlpy.tag._okt.Okt)
[Mecab](https://konlpy.org/en/latest/api/konlpy.tag/#konlpy.tag._mecab.Mecab)
—Windows 不支持
在本教程中,我将使用 Okt 来保持事情简单和容易。让我们从在 Python 文件上添加以下导入声明开始。
from konlpy.tag import Okt
from konlpy.utils import pprint
我将使用以下文本作为输入。在韩语里是I am eating an apple
的意思。希望我没弄错。
text = '나는 사과를 먹고있다'
将类初始化为对象
okt = Okt()
之后,我们可以调用其中的函数,并使用pprint
utils 类将结果打印出来。
名词
让我们尝试使用nouns
函数从句子中提取名词
pprint(okt.nouns(text))
您应该会得到以下结果。
['나', '사과']
나
—我사과
—苹果
改变
如果你想对句子进行分词,你可以使用morphs
功能。它接受三个输入参数。
phrase
—输入文本norm
—一个布尔值表示是否规范化句子stem
—布尔值表示是否对句子进行词干处理。词干化是将句子中的单词缩减成基本形式或词根形式的过程。
它可以被称为如下:
pprint(okt.morphs(text, norm=True, stem=True))
您应该在控制台上看到以下输出。
['나', '는', '사과', '를', '먹다']
你可以注意到먹고있다
(吃)这个词正在被简化为먹다
(吃)。
나
—我는
—粒子사과
—苹果公司를
—粒子먹다
—吃
词性标签
pos
如果您在标记化过程后寻找词性标签,此功能非常有用。与前面的函数不同,这个函数中的参数根据您使用的类而有所不同。有些类有flatten
参数,如果设置为 False,它会保留 eojeols。Okt 类有以下输入参数。
phrase
—输入文本norm
—一个布尔值表示是否规范化句子stem
—布尔值表示是否对句子进行词干处理。词干化是将句子中的单词缩减成基本形式或词根形式的过程。join
—一个布尔值表示是否返回由/
符号分隔的变形和标签的联合集合。
让我们用下面的代码来测试一下
pprint(okt.pos(text, norm=True, stem=True))
控制台将显示以下结果。
[('나', 'Noun'), ('는', 'Josa'), ('사과', 'Noun'), ('를', 'Josa'), ('먹다', 'Verb')]
修改前一行并将join
参数设置为True
pprint(okt.pos(text,norm=True, stem=True, join=True))
结果现在被捆绑在一起,作为一个由/
符号分隔的元素。
['나/Noun', '는/Josa', '사과/Noun', '를/Josa', '먹다/Verb']
3.结论
让我们回顾一下今天所学的内容。
我们开始安装必要的模块和库。如果您是 Windows 用户,设置会稍微复杂一些。
接下来,我们深入探讨了koNLPy
模块提供的功能。它可以用来从输入的句子中提取名词。此外,你还可以把它标记成单个的单词。您可以对它进行微调,只获得单词的基本形式作为输出。
此外,我们还测试了pos
函数,该函数允许我们识别朝鲜语的词性标签。
感谢你阅读这篇文章。希望在下一篇文章中再见到你!
参考
kot Lin——用代码片段控制流程(2020 年 3 月)
初学者的 kot Lin—# 2:控制流
如果,当,为,而,当,中断并继续…
约翰·洛克伍德在 Unsplash 上拍摄的照片
C控制流运算符可用于在计算中从两条或多条可能的路径中选择一条合适的路径。
在本文中,我们将介绍 Kotlin 中的以下控制流:
if
表情when
表情for
循环while
和do...while
循环break
操作员continue
操作员
if
表情
if
语句的传统用法:
val num1 = 10
val num2 = 20
**if** (num1 > num2) {
print("num1 > num2)
} **else if** (num1 < num2) {
print("num1 < num2")
} **else** {
print("num1 == num2")
}// Output: num1 < num2
2.而不是三元运算符(在 Java 中— condition?val1 : val2):
val num = 0
val isZero = **if** (num == 0) true **else** false
仅供参考:kotlin 中没有三元运算符。
3.在 Kotlin 中,if
也可以返回值(我们在上面一点中已经看到)。因此,它也可以用在函数的返回语句中。
fun getMinValue(a: Int, b: Int): Int {
return if (a <= b) {
a
} else {
b
}
}
参考:当使用
if
操作符返回值时,if
和else
块的最后一行应该是你想要返回的结果值。
when
表情
when
是 switch case 的替代品(java 中)。你可以说,when
表情是有超能力的开关格。when
表达式可以用来返回值,类似于if
表达式。when
的传统用法(类似于开关盒):
val color = "RED"
when(color) {
"RED" -> print("Color is RED")
"GREEN" -> print("Color is GREEN")
"BLUE" -> print("Color is BLUE")
else -> print("Color is Unknown")
}// Output: Color is RED
3.when
表情的超能力能力:
fun getValue(input: Any): String {
return when (input) {
**is String ->** "Input is a String"
**in 'A'..'Z' ->** "Input is between A to Z"
**0 ->** "Input is 0"
**1, 2 ->** "Input is either 1 or 2"
**in 3..10 ->** "Input is between 3 to 10"
**!in 11..100 ->** "Input is not between 11 to 100"
**else ->** "Inside else case"
}
}
getValue("Any String")
:输出将是Input is a String
。getValue('D')
:输出为input is between A to Z
。getValue(0)
:输出将为Input is 0
。getValue(5)
:输出将为Input is between 3 to 10
。getValue(256)
:输出将为Input is not between 11 to 100
。getValue(55)
:输出将是Inside else case
。
参考消息:
is
或!is
可用于检查输入的类型。in
或!in
将用于检查范围。
for
循环
*for*
循环迭代可迭代的任何东西(具有提供*Iterator*
对象的*iterator()*
函数的任何东西),或者本身是*Iterator*
的任何东西。
in
—最简单的 for 循环,遍历列表中的每个元素
*val fruits = listOf("Apple", "Banana", "Cherries", "Guava")
for (fruit **in** fruits) {
println(fruit)
}// Output: Apple, Banana, Cherries, Guava*
2...
—迭代 0(含)到 5(含)之间的范围
*for (number in 0..5) {
println(number)
}// Output: 0 through 5*
3.withIndex()
—使用当前项目的索引遍历列表。
*val fruits = listOf("Apple", "Banana", "Cherries", "Guava")
for ((index, fruit) in fruits.**withIndex**()) {
println("$index - $fruit")
}// Output: 0 - Apple, 1 - Banana, 2 - Cherries, 3 - Guava*
***注:*查看关于在 Kotlin 中使用 for 循环的 8 种不同方法的详细文章。如果你想知道如何使用
for
循环来迭代Map
,那么别忘了看看那篇文章的第 8 点。
while
和 do…while 循环
- 类似于
while
循环的传统用例(基于它将循环通过语句块的条件):
*var i = 5
while (i > 0) {
println(i)
i--
}// Ouput: 5 through 1*
2.在do...while
中,首先执行程序块,然后检查条件:
*var i = 5
do {
println(i)
i--
} while (i > 0)// Ouput: 5 through 1*
break
操作员
break
运算符(默认,即无任何标签)用于终止最近的封闭循环:
*for (y in 0..5) {
if (y > 5) break
println("y: $y")
}// Output:
y: 0
y: 1
y: 2
y: 3*
2.一个循环在另一个循环中的例子,其中break
操作符仅终止最近的循环:
*for (x in 0..2) {
for (y in 0..2) {
if (y > 0) break
println("x:$x - y:$y")
}
}// Output:
x:0 - y:0
x:1 - y:0
x:2 - y:0*
3.break
带有标签的操作器不仅可用于终止最近的回路,也可用于终止外部回路:
*outer@ for (x in 0..2) {
for (y in 0..2) {
if (y > 0) break@outer
println("x:$x - y:$y")
}
}// Output:
x:0 - y:0*
continue
操作员
continue
运算符终止以下语句的执行,并跳转到封闭循环中的第一条语句:
*for (i in 0..10) {
if (i%2 == 0) continue
print("$i ")
}// Output: 1 3 5 7 9*
2.continue
带标签的操作员:
*outer@ for (x in 0..3) {
for (y in 0..3) {
if (y > 1) continue@outer
println("x:$x - y:$y")
}
}// Ouput:
x:0 - y:0
x:0 - y:1
x:1 - y:0
x:1 - y:1
x:2 - y:0
x:2 - y:1
x:3 - y:0
x:3 - y:1*
注:如果你想要一篇关于
return, break and continue
(即 Kotlin 中的跳转表达式)的带有标签和代码片段的详细文章,那么请在评论中提及“是的,我感兴趣……”。当我发布相同的文章时,我会特别回复你。
您的机会…
加入我的部落后,获得我的个人 Java 收藏清单作为免费的欢迎礼物。 马上获取!
关于作者
Anand K Parmar 是一名软件工程师,热爱设计和开发移动应用程序。他是一名作家,发表关于计算机科学、编程和个人理财的文章。在 LinkedIn 或 Twitter 上与他联系。下面是他的最新文章。
关于 Kotlin 中的“for”循环,您只需要知道
medium.com](https://medium.com/quick-code/all-you-need-to-know-about-kotlin-for-loop-144dc950271d) [## 每个初学者都应该知道数据结构和算法之间的区别
理解计算机科学基础的简单指南
medium.com](https://medium.com/swlh/differences-between-data-structures-and-algorithms-eed2c1872cfc)*
Kubeflow 比以往任何时候都更容易接近
10 分钟内开始使用 Kubernetes 的最佳机器学习平台
由 Unsplash 上的 Pietro Jeng 拍摄
机器学习项目通常由多个相互关联的步骤组成:数据采集、数据处理、数据建模、微调、测试等。这些步骤中的每一步都可以是一个独立的过程,以自己的节奏运行,具有明确定义的输入和输出。因此,数据科学家和 ML 工程师倾向于认为这些项目像管道。
库巴流管道,库巴流的一个组件,就是为了解决这个设计模式。此外,Kubeflow 将在您的 ML 项目的整个生命周期中为您提供帮助:实验和元数据跟踪、与框架无关的培训、Jupyter 服务器、模型服务等等。
但是我们如何部署一个 Kubeflow 实例来开始使用它呢?我们应该创建和维护一个 Kubernetes 集群吗?
嗯,有更好的入门方式: MiniKF 。就像 minikube , MiniKF 提供了一个单节点 Kubernetes 集群,上面部署了 Kubeflow。所以,我们来看看怎么设置吧!
学习率是为那些对 AI 和 MLOps 的世界感到好奇的人准备的时事通讯。你会在每周五收到我关于最新人工智能新闻和文章的更新和想法。在这里订阅!
KubeFlow 简介
Kubeflow 是一个开源项目,致力于使 ML 项目的部署更加简单、可移植和可伸缩。来自文档:
kube flow 项目致力于使在 Kubernetes 上部署机器学习(ML)工作流变得简单、可移植和可扩展。我们的目标不是重新创建其他服务,而是提供一种简单的方法来将 ML 的最佳开源系统部署到不同的基础设施上。无论你在哪里运行 Kubernetes,你都应该能够运行 Kubeflow。
但是我们如何开始呢?我们需要 Kubernetes 集群吗?我们应该自己部署整个系统吗?我的意思是,你有没有看过 Kubeflow 的清单回购?
不要慌;最终,在 Kubeflow 上运行笔记本所需要的只是一个谷歌云平台(GCP)账户和你的旧笔记本文件!
MiniKF
我将保持简单,不使它变得愚蠢。事实是,只需几分钟就可以轻松运行 Kubeflow 的单节点实例。我们需要的只是一个 GCP 帐户和从市场部署应用程序的能力。我们要用 MiniKF!
MiniKF 部署—作者图片
- 去你的 GCP 控制台
- 搜索市场然后找到 MiniKF
- 点击它并选择启动
- 设置 VM 配置,(由于我的配额,我通常将数据磁盘更改为标准持久磁盘)并单击 deploy。
就是这样!部署最多需要十分钟,您可以按照屏幕上的说明观看进度;ssh 进入机器,在终端上运行minikf
,等待直到您的端点和凭证准备好。
MiniKF 的提供已完成—图片由作者提供
现在,我们准备访问 Kubeflow 仪表板。点击网址,输入你的凭证,你就可以开始了!
Kubeflow 仪表板—按作者分类的图像
运行 Jupyter 服务器
为了运行我们的实验,我们需要一个 Jupyter 笔记本实例。在 Kubeflow 中创建一个 Jupyter 笔记本相对容易。我们首先需要创建一个 Jupyter 服务器并连接到它。让我们这样做:
- 从左侧面板中选择笔记本
- 选择
New Server
按钮 - 填写服务器的名称,并请求您需要的 CPU 和 RAM 数量
- 保持 Jupyter 笔记本图像不变(
jupyter-kale:v0.5.0-47-g2427cc9
—注意图像标签可能不同)
创建 Jupyter 服务器—作者图片
完成这四个步骤后,等待笔记本服务器准备好并连接。你将被转移到你熟悉的 JupyterLab 工作区。如果您想要一个关于如何在不编写任何代码的情况下将您的笔记本转变为 Kubeflow 管道的端到端教程,请参见此处:
无需编写一行代码,即可将您的笔记本草稿转化为生产就绪的 Kubeflow 管道。
towardsdatascience.com](/jupyter-is-ready-for-production-as-is-b36f1d1ca8f8)
结论
在这个故事中,我们看到了如何在 10 分钟内启动并运行 Kubeflow 实例。开始使用这个强大的工具很容易;运行您的笔记本电脑,使用 Katib 启动超参数调整实验,并使用 KFServing 为您的模型提供服务。
我们已经看到了如何在不编写任何代码的情况下将您的 Jupyter 笔记本转换成 Kubeflow 管道。在未来的帖子中加入我们,了解更多:超参数调优、版本控制、调试等等!
关于作者
我叫迪米特里斯·波罗普洛斯,我是一名为阿里克托工作的机器学习工程师。我曾为欧洲委员会、欧盟统计局、国际货币基金组织、欧洲中央银行、经合组织和宜家等主要客户设计和实施人工智能和软件解决方案。
如果你有兴趣阅读更多关于机器学习、深度学习、数据科学和数据运算的帖子,请在 twitter 上关注我的媒体、 LinkedIn 或 @james2pl 。
所表达的观点仅代表我个人,并不代表我的雇主的观点或意见。
Kubeflow:简化、扩展和可操作化
来源:shutterstock
公司的成功和发展与他们在技术堆栈中使用的技术紧密相关。这一点在开发 ML 管道时表现得最为明显。
将健壮的 ML 模型和数据管道交付给生产是一件复杂的事情。无论给定项目的范围如何,每个数据科学团队都面临相同的限制和约束:
- 大规模的特征分析和准备是困难的
- 运行许多 ML 训练任务,每个任务具有不同的参数或算法,花费太多时间并且需要昂贵的资源
- 跟踪和复制实验,以及代码、数据和结果的正确版本是复杂的
- 将数据科学笔记本代码转移到生产管道需要付出大量努力
- 生产管道需要处理许多可伸缩性、可用性、自动化模型漂移检测、与实时数据集成、安全性等操作任务。
建立模型远不是旅程的终点。为了将支持人工智能的应用部署到生产中,你需要一群开发人员、数据工程师、DevOps 实践者和数据科学家,他们最好在一个平台上协作和工作。
在这个新兴领域中,没有多少解决方案能够覆盖这个特殊的领域,而 Kubeflow 在过去几年中作为开源领导者的势头越来越大。 Kubeflow 是在 Kubernetes 上编排复杂工作流的绝佳工具,但它也带来了挑战,尤其是对于不习惯使用这类解决方案的数据科学家来说。许多 ML 从业者发现它使用起来很复杂,遇到各种各样的可用性问题,并对功能差距感到沮丧。
幸运的是,可以扩展 Kubeflow 的功能,并将其转变为一个全面、易于使用的 MLOps 平台。在 Iguazio ,我们已经做到了。我们已经接受了库伯流。我们的方法是将它添加到我们的托管服务目录中,弥补现有的功能差距,用我们开发的新开源框架包装和扩展它的功能。
为什么我们需要 MLOps 解决方案?
数据科学家的生活:工具辩论者
数据科学家在开发模型时通常会经历以下过程:
- 从 CSV 或密集格式(如拼花地板)收集数据,需要从外部来源手动提取。使用的工具:ETL 和数据导出工具。
- 数据标记,探索和丰富,以确定潜在的模式和特征。使用的工具:用于数据标记、探索和模型开发的交互式工具;用于大规模聚合、连接和透视数据的分析工具/数据库。
- 模型训练和验证。使用的工具:并行模型培训框架。
- 使用自动化和/或可视化工具进行模型评估。使用的工具:CI/CD 框架,可视化库。
- 回到第 1 步并重复,直到达到预期的结果。
这导致大量耗时且复杂的跑腿工作。如果数据科学团队想要让一个模型走出实验室,那么他们必须引入一些方法。
这只是开始
但是这个漫长的过程只是第一步!您仍然需要操作模型,将它与应用程序联系起来,并自动化您的功能工程过程。这可能需要一年或更长的时间,并且需要一大批 ML 从业者用蛮力来解决这个问题。
来源:推特
一旦我们有了一个模型,我们需要检查所有的许多步骤,以便将基于 AI/ML 的应用程序交付到生产中。这包括:封装、扩展、性能调整、仪器和自动化。
Kubeflow 是 Kubernetes 的 ML 工具包
Kubeflow 是由 Google 发起的一个开源项目,它将领先的 ML 框架集合在 Kubernetes 之上。它提供了通用的安装工具和交叉验证,但是它的工具也可以独立部署。它充当模型开发的砖块和灰泥,专注于 Kubernetes 上 ML 模型开发管道的自动化、缩放和跟踪。
值得注意的 Kubeflow 组件:
集装箱式 Jupyter 笔记本
Kubeflow 在 Kubernetes 上提供了一个 Jupyter 笔记本服务,因此用户可以创建一个具有给定资源需求的 Jupyter 服务器,并获得预配的容器。
库伯弗洛管道公司(KFP)
什么是 Kubeflow 管道?简单地说,它是一个 ML 工作流及其所有组件的描述。一个组件可以负责 ML 过程中的不同步骤,如数据处理、转换、模型训练、验证等。
KFP 使您能够通过 Python SDK 描述具有单个步骤的工作流(其中每个步骤都是容器微服务或无服务器功能),在集群上执行该工作流,并跟踪进度和实验结果。
KFP 使用户能够自动化 ML 管道,而不是手动运行单个作业。
可扩展培训操作员
Kubernetes 中的应用生命周期和伸缩可以通过一个操作符来管理。Kubeflow 项目托管各种运营商,使用不同的 ML 框架( TensorFlow 、 PyTourch 、 Horovod 、 MXNet 、 Chainer )运行可扩展的 ML 训练任务。
模型服务解决方案
Kubeflow 项目托管一个基本的模型服务框架(KFServing)并支持外部服务框架(Seldon、Triton 和 Nuclio-serving )。Iguazio 领先的开源项目 Nuclio 是一个用于实时 API、ML 和数据工程任务的无服务器引擎,它有一个模型,提供风格的快速性能和大量功能(自动模型部署、金丝雀、模型监控、漂移和异常值检测、集成和实时管道等)。) .
实施 Kubeflow:主要挑战
Kubeflow 本身就是一个更广泛的 ML 操作系统的组成部分。Kubeflow 包含一些强大的组件,使其成为该领域的领跑者——它是 Kubernetes 原生的、高度可定制的、开源的和松散耦合的。但是它有一些关键的限制,需要由 ML 团队来解决。
挑战 1:复杂性
Kubeflow 是一个工具生态系统,而不是一个整体或集成的解决方案,它依赖于许多底层平台服务和工具(Kubernetes、用户管理、数据服务、数据版本、监控、日志、API 网关等。).如果没有托管解决方案,公司需要一个由开发人员、开发人员和 ML 工程师组成的团队,他们将致力于将各种 Kubeflow 和附加组件集成到一个具有统一门户和安全性的完整服务中,管理部署,支持内部用户,升级每个子服务,构建用于故障排除的工具和专业知识,并持续跟踪社区工作。如果您已经有一个大型的 DevOps 组织和廉价的资源,这可能是有意义的,但对于许多想要专注于他们的业务应用程序的精简组织来说就没有意义了。
让我们假设您想要使用 Katib 之类的工具运行超参数作业,使用 Kubeflow Pipelines、MPIJob 之类的分布式 ML 操作符,并跟踪或比较结果。您需要手动将所有这些工具缝合在一起,即使它们都是 Kubeflow 下的子项目。
正确安装 Kubeflow 意味着运行和管理十几个单独的服务,其中一些不是生产级的。喜欢 Kubernetes 上的单一 AI/ML 框架概念的 ML 从业者发现他们正在努力部署、管理和保护它。一旦他们这样做了,他们注意到他们的内部用户由于可用性和集成问题而不愿意使用它。
挑战 2: Kubeflow 说的是工程师的语言,而不是科学家的语言
Kubeflow 的核心焦点是使用 Kubernetes 的高级 ML 工程。它最初是由 Kubernetes 社区成员为 DevOps 和 MLOps 工程师设计的,而不是为数据科学家设计的。
像 Kubernetes 的其他功能一样,这一切都始于 Docker 容器、YAML 文件和脚本。数据科学家是数据科学平台的主要消费者。他们不想管理 YAML 文件——他们宁愿使用简单的用户界面和数据工程,或者 Python 中的 ML 逻辑,让一些东西在集群上为他们运行,然后收集结果,希望以可扩展和可管理的方式。
虽然在分布式管道中运行 ML 任务非常强大,但数据科学家通常从使用本地 IDE 开始,如 Jupyter、PyCharm 或 VSCode。他们希望在本地开发、调试、运行和跟踪工作,而不创建 Kubernetes 资源或复杂的管道,并且只有在他们成功完成单独运行后,他们(或团队中的 ML 工程师)才希望过渡到在可扩展的集群上运行或使用多级管道。不幸的是,这在 Kubeflow 中是不可能的,因为每个被跟踪的执行都需要构建完整的管道和 Kubernetes 资源。
数据科学团队希望基于逻辑 ML 项目来组织和管理他们的工作,具有清晰的项目级别成员关系、项目特定的资源和计费、隔离项目之间的资源和安全凭证的能力等。在 Kubeflow 中,用户可以使用提升的权限创建作业,在用户或项目级别没有隔离、监控或跟踪。
同样,许多任务是复杂的手动任务。例如,如果您想要查看管道运行的结果,您必须编写代码来存储和可视化运行工件,大多数商业工具或托管工具可以为您做到这一点。
数据科学团队应该能够使用熟悉的工具和简单的 UI 门户,并在幕后为他们调配和监控资源。
挑战 3: Kubeflow 是部分 MLOps 解决方案
Kubeflow 工具包主要应用于模型开发阶段,这意味着团队需要其他几个强制服务,这进一步增加了开销。为了快速(或完全)实现商业价值,团队需要将 Kubeflow 功能扩展到数据科学管道的其余部分,并手动与外部数据和身份管理系统集成。
MLOps 堆栈和 Kubeflow(图片由作者提供)
Kubeflow 专注于运行和跟踪 ML 实验的模型开发管道,然而大多数用户需要如上图所述的附加服务,可扩展数据和特征工程、模型管理、生产/实时管道、版本化和管理的数据仓库、管理的运行时、认证/安全等服务。
Iguazio 开发了开源框架(如 Nuclio 、 MLRun )和额外的数据服务和管理层,将 Kubeflow 补充和扩展为一个功能齐全的托管数据科学平台。这将在下一节中进一步描述。
交付端到端数据科学平台 Kubeflow Inside
将基于数据科学的产品交付到生产环境的大部分复杂性在于不同组织和技术孤岛之间的集成,采用单个“同类最佳”组件并手动集成它们需要大量资源,维护组织孤岛,并导致巨大的技术债务,因为您需要维护所有集成和粘合层。
我们认为,组织应该部署一个涵盖数据工程、数据科学、ML 工程和 DevOps 领域的数据科学解决方案。我们需要抽象掉大部分复杂性,同时实现一个高性能、可扩展且安全的平台,该平台可以部署在任何云中或内部。
以下是 Iguazio 平台上的附加功能列表(大部分是开源的):
具有用户友好的门户、API 和自动化的集成解决方案
可用性是 Kubeflow 的主要挑战之一,加上 Kubeflow 只解决了解决方案的一部分(没有离线开发、数据工程或生产部署)。用户发现自己在与多个门户和用户界面对抗,并添加了大量粘合代码。
假设所有数据科学元素和元数据由一个服务管理,您可以使用要素存储创建一个要素集对象,将其作为对象传递给培训、验证或模型服务逻辑,使用它来验证您的模型行为和概念漂移,并直接从生产管道更新它和相应的标记数据。使用粘合逻辑和脚本来实现这一点几乎是不可能的,并且会导致大量额外的开发和 ML 工程工作。
名为 MLRun 的开源框架控制着从数据摄取到生产管道的整个功能,它提供了全面的 Web UI、CLI、API/SDK,并且与 underline Kubeflow 组件(操作符、管道等)紧密集成。)
通过 MLRun ,用户可以在任何地方使用他们的原生 IDE (Jupyter、PyCharm、VSCode 等)通过 SDK 和 IDE 插件工作。),不需要在 Kubernetes 集群上运行,只需要几个简单的命令就可以运行单个任务或者完成批处理和实时管道。
执行、实验、数据、模型跟踪和自动化部署通过 MLRun 无服务器运行时引擎自动完成。MLRun 通过严格的成员关系和跨团队协作来维护项目层次结构(而不是像 Kubeflow 那样使用平面名称空间)。
示例:MLRun 项目仪表板屏幕(图片由作者提供)
您可以按照 MLRun 文档中所述部署各种组件,或者您也可以使用 Iguazio 的托管产品,该产品在 MLRun 和 Kubeflow 以及其他数据和管理服务的基础上增加了端到端安全性和完全托管的服务体验。
功能商店
特征工程可能是构建 ML 管道中最耗时的任务之一。如果没有所有特性的共享目录,团队就有浪费时间进行重新开发以及跨团队和项目重复工作的风险。需要使用数据工程框架(如 Spark、Presto、Dask 等)定期计算这些特征。)和流处理引擎(Flink、Nuclio 等。)并使用用于训练的离线/批处理 API 和用于服务的实时 API 和数据库来交付。特征存储的一个主要优点是为训练和服务层提供了一致的特征集,确保训练好的模型在生产中保持其性能。
此外,要素存储是存储版本化要素元数据和统计数据的关键元素,这对于进行模型监控、验证、概念漂移检测和持续再训练至关重要。
建立自己的功能商店是一种奢侈,通常只保留给一线网络公司,因为它需要复杂的堆栈。没有特性存储的选择意味着团队将投入大量的手工数据工程工作来构建和维护特性。
实时管道、模型管理和监控
一旦模型准备就绪,它们需要转变为运行的微服务,这些微服务通过 API 或数据流接受特征向量,并产生预测结果,这些结果需要在生产业务应用中使用。实际上,生产流水线比简单的服务端点复杂得多,它们可能包括特征检索、转换、验证、异常值检测、集合或更复杂图形下的多个模型服务、警报等步骤。
Nuclio 和 MLRun-serving 开源框架使团队能够在几分钟内根据训练结果和实时特征存储中的数据构建复杂的实时数据处理和模型服务管道,并通过单个 API/UI 命令部署或升级到生产。
将模型投入生产只是其生命周期的开始。必须记录模型的预测和行为,必须监控它们的概念漂移,有时在变化的环境下根据新数据进行重新训练。数据需要治理和审计。如果没有一个集中的系统,模型维护会很快变得难以管理并且过于昂贵。
托管服务和无服务器运行时
大量工作投入到创建和管理各种软件包,并将它们转化为具有自动扩展、配置管理、升级和安全性的生产服务。典型的数据科学堆栈可以由数十种服务组成,如数据分析工具、ML/AI 框架、开发工具、仪表盘、安全和授权服务以及日志记录。您可以雇佣一个大型团队来手动构建一个堆栈,或者您可以使用一个带有托管服务的平台,允许用户选择服务、指定参数并单击部署。
此外,将代码转化为产品服务是一个耗时的项目,涉及许多团队成员(见下图)。您需要将代码打包到容器中,针对弹性、可伸缩性、性能、强化安全性、添加工具等对其进行重新设计。许多数据科学家不精通软件开发和 DevOps,因此这些任务对他们来说更具挑战性。无服务器技术的使用使团队能够自动完成所有这些任务。
MLRun runtimes 和 Nuclio 可以获取一段代码,并自动将它转换为一个灵活的、完全托管的服务,这可以通过 UI 或在您的开发环境(如 Jupyter)中使用一行代码来完成。
无服务器功能可以独立运行,也可以作为步骤插入到更大的 Kubeflow 管道中,无需任何额外的开发。MLRun 项目支持自动化 CI/CD 管道。每次代码、数据或配置更改时,都可以通过 Git 挂钩触发工作流,项目成员可以查看结果并批准自动部署到测试或生产系统中。
从开发迁移到生产的努力(图片由作者提供)
功能市场和汽车
您可以开发自己的功能,或者使用市场上的一组预烘焙功能,然后将它们插入到您的管道中,无需任何开发工作。ML run 函数市场提供了一套用于特征分析、检测和自动化 ML 训练的 AutoML 函数。这些功能是为规模、性能而设计的,并可通过仪器和可视化报告进行生产。
团队可以实现本地功能市场/存储库,最大化协作和重用。一个成员可以构建一个可以在另一个项目中使用的功能,或者由另一个团队成员改进并返回到市场(使用不同的版本标签)。
生产就绪的托管数据服务
每一个数据科学解决方案都处理数据,数据可以以多种形式出现(文件、表格、流、时间序列等。),这需要与几个底层数据服务集成。应控制数据访问,将每个作业或用户限制在特定的数据集内,并具有特定的访问权限,此外,必须对数据进行版本控制以实现可再现性。
您可以从不同的云提供商那里获得并集成托管数据服务。Iguazio 拥有业界领先的高性能多模式数据库和低延迟分布式文件系统,采用独特的技术,使用闪存/SSD 存储,但性能类似于内存中的数据库,成本仅为其一小部分,而且规模更大。这些因素有助于加快部署、提高性能、扩大规模和降低成本。
端到端安全性
数据科学平台可能包含从多个用户聚合的非常敏感的数据。必须实施多层安全方法,包括:
- 身份验证和身份管理:使用行业标准协议,如 LDAP、OAuth2 和 OIDC,确定哪个用户或服务正在访问一段数据或另一项服务。
- 基于角色的访问控制(RBAC):强制每个用户、任务或角色的访问权限,他们可以访问哪些资源,他们可以执行哪些操作。
- 数据安全:控制数据资产的访问和隐私。
- 机密管理:保护机密和访问凭证,避免将这些机密存储在代码或数据资产中,而是在执行时将它们提供给特定的用户和作业。
MLRun 支持与安全服务的集成。您可以自己部署和集成它们,也可以使用 Iguazio 托管平台,为您提供所有固化和全面的管理。
摘要
在 Iguazio ,我们坚信 Kubeflow 的潜力,这就是我们选择将其包装并扩展为完整的端到端 MLOps 解决方案的原因。我们还相信打破数据工程、数据科学和 DevOps 从业者之间的孤岛,这样就可以抽象出复杂性,组织就不会背负沉重的技术债务。通过一些额外的服务和功能,Kubeflow 可以成为应对操作化机器学习挑战的正确解决方案,为数据科学家提供高性能、可扩展和安全的技术,可以部署在任何云、本地或混合环境中。
Kubernetes 和亚马逊 SageMaker 的机器学习——两全其美
使用 Amazon SageMaker 为机器学习工作负载扩展 Kubernetes 集群的容量和功能
Kubernetes 和亚马逊 SageMaker——两全其美
如果你是一个经常训练和部署机器学习模型的团队的一员,你可能有一个集群设置来帮助协调和管理你的机器学习工作负载。你使用 Kubernetes(和 KubeFlow)或亚马逊 SageMaker 的机会。
到目前为止,你必须选择你的编排系统,并坚持下去。您要么(1)根据数据科学团队的预期工作负载调配 Kubernetes 集群,要么(2)完全由 Amazon SageMaker 管理,根据需要自动调配和拆除资源。
如果能两全其美岂不是很好?
- 使用 Kubernetes 管理您的工作流,并使用 Amazon SageMaker 获得大规模分布式培训的爆发容量?
- 用 Kubeflow Jupyter 笔记本开发算法和模型,用亚马逊 SageMaker 大规模运行超参数实验?
- 使用 Kubeflow 训练模型,并托管一个推理端点 Amazon SageMaker,可以弹性扩展到数百万用户?
有了针对 Kubernetes 的亚马逊 SageMaker 运营商,你就可以做到这一点!您可以使用它来训练机器学习模型,优化超参数,运行批量转换作业,并使用 Amazon SageMaker 设置推理端点,而无需离开您的 Kubernetes 集群。
使用 Amazon SageMaker Operators for Kubernetes 来运行培训作业、模型调优作业、批量转换作业,并使用 Kubernetes 配置文件和 kubectl 在 Amazon sage maker 上设置推理端点
用于 Kubernetes 的 Amazon SageMaker Operators 是 Kubernetes 中的一个定制资源,它支持使用 Kubernetes CLI 和配置文件调用 Amazon SageMaker 功能。事实上,Kubernetes 的许多核心功能都是作为定制资源构建的,这种模块化使得 Kubernetes 非常具有可扩展性。对于 Kubernetes 用户来说,Amazon SageMaker Operators 使您能够以一种一致的方式与 Kubernetes 和 Amazon SageMaker 进行交互。
在这篇博文中,我将概述 Amazon sage maker Operators for Kubernetes,为什么它很重要,以及常见的使用模式,以便您可以决定这是否适合您。这篇博文中引用的所有代码、配置文件和演示 Jupyter 笔记本都可以在 GitHub 上获得:
https://github . com/shashankprasanna/kubernetes-sage maker-demos . git
要深入了解如何使用 Amazon SageMaker Operators for Kubernetes 实现分布式培训、模型调优和模型托管示例,请查看随附的帖子:
云中的一对
Kubernetes 和 Kubeflow 项目享有强大的用户社区,是机器学习领域发展最快的开源项目之一。只要您拥有设置、管理和排除 Kubernetes 集群故障的内部专业知识,您就可以获得作为数据科学家或机器学习研究人员所需的一切——Jupyter 笔记本和对 KubeFlow 分布式培训的支持,KubeFlow 和 Katib 的超参数调整,以及 KFServing 的轻松推理部署。作为 Kubernetes 用户,您可以完全灵活地选择在哪里运行它(本地或云),以及在什么系统上运行它。这也意味着您要负责保持群集的高利用率,以降低运营成本,鉴于突发性或峰值机器学习工作负载的性质,这可能是一项挑战。
亚马逊 SageMaker 采取了不同的方法。首先,它为机器学习工作流程的几乎每个部分提供了一套完全托管的服务,从数据标记、托管 Jupyter 笔记本开发环境、使用后自动供应和拆除的托管培训集群、超参数优化、托管模型托管服务等等。作为 Amazon SageMaker 用户,您不必关注基础设施管理和集群利用率之类的事情。
作为一名机器学习实践者,你应该能够利用两者的优势。例如,您应该能够将持续运行的(或多或少)固定容量自我管理的 Kubernetes 基础架构与按需、完全管理的弹性 Amazon SageMaker 基础架构配对,后者仅在您需要时供应。这是一个强大的想法——数据科学家团队可以让他们的想法自由驰骋,随心所欲地进行实验,而不受现有 Kubernetes 设置的限制。
您现在已经可以做到这一点,但是必须在这两个系统之间来回切换。有了 Amazon sage maker Operators for Kubernetes,您现在无需离开您可能已经熟悉的 Kubernetes 环境就可以做到这一点。
场景和用例
借助 Amazon SageMaker Operators for Kubernetes,您可以将单节点培训、分布式或多节点培训、大规模超参数调整和托管推理部署等工作负载卸载到 Amazon sage maker 的完全托管基础设施中。因此,问题就变成了,什么时候把工作负载转移到 Amazon SageMaker 上比在 Kubernetes 集群上运行更有意义?
让我们通过几个假设的场景来探讨这个问题。
场景#1 —大规模培训能力过剩
使用 Amazon sage maker Operators for Kubernetes 通过 kubectl 提交培训工作。Amazon SageMaker 提供所需的容量并运行培训作业。
假设您目前正在本地数据中心或使用亚马逊 EKS 的 AWS 上运行 Kubernetes 集群。在设置时,您根据当时的工作负载对数据中心的 CPU、GPU 和存储数量进行了预算和选择。现在,您的团队已经壮大,或者您拥有更多数据,需要更多计算能力。如果您有 128 个 GPU,您可以在一天内完成一个机器学习训练实验的快速截止日期,但在您的 Kubernetes 集群上,他们都在忙于其他项目。你只需要短时间的额外突发容量。
你的选择是
- 扩展您现有的 Kubernetes 集群并添加所需的资源
- 使用所需的资源启动另一个 Kubernetes 集群
- 使用 Amazon SageMaker 进行按需供应
(1)和(2)是您没有参与的额外基础设施工作。(3)是一个很好的选择,但是要求您离开您熟悉的 Kubernetes 环境,并且它没有集成到您已经设置的任何 CI/CD 自动化中。
还有第四种选择。使用 Amazon SageMaker Operators for Kubernetes 通过kubectl
提交 Amazon sage maker 作业,就像提交其他 Kubernetes 作业一样。在后台,将自动为您提供一个 Amazon SageMaker 托管集群,其中包含指定数量的实例。然后,培训作业将在 Amazon SageMaker 管理的集群上执行,一旦培训完成,该集群将自动关闭,您将看到培训的确切持续时间,这是您将支付的费用。
场景#2 —托管可伸缩的推理端点
使用 Amazon sage maker Operators for Kubernetes 通过 kubectl 托管推理端点。Amazon SageMaker 提供所需的实例并运行模型服务器。
让我们考虑另一种情况。您拥有针对 Kubernetes 的培训、验证和部署的 CI/CD 自动化设置。您使用 Kubernetes 托管的模型由您的客户通过终端、移动应用程序或网站使用。该模型托管在 GPU 实例上,因为延迟和性能对于您的客户体验至关重要。您希望释放 GPU 资源用于培训,并且需要能够自动扩展和执行实时模型监控。Amazon SageMaker 主机服务已经提供了这些功能,但是您希望在不中断现有 CI/CD 工作流的情况下利用这些功能。使用 Amazon SageMaker Operators for Kubernetes,您可以直接从 Kubernetes 部署一个经过训练的模型,以同样的声明方式使用 YAML 的配置文件,它可以轻松集成到您现有的设置中,并且仍然允许您获得 Amazon sage maker 托管的好处。
现在让我们来看看 Kubernetes 和 Amazon SageMaker 一起使用的一些常见使用模式。
使用案例#1 —利用 TensorFlow、PyTorch、MXNet 和其他框架进行分布式培训
工作流程:用户上传培训代码到亚马逊 S3。Amazon SageMaker 下载训练代码,拉出指定的框架容器,并在其中运行训练脚本。用户不必处理构建和推动容器。
借助分布式多节点训练,您可以通过在多个 GPU 之间分配工作负载来大幅减少训练模型的时间。当 Kubernetes 集群中的 GPU 容量不足时,可以配置一个分布式培训作业,在 Amazon SageMaker 管理的集群上运行。除了快速访问 AWS 上的多余容量之外,您还可以获得 Amazon SageMaker 的其他好处,如利用 Spot Instance 大幅降低培训成本的能力,在 AWS 控制台上或使用 AWS CLI 监控和跟踪培训工作的能力,以及通过几次点击托管培训模型的能力。
如果您正在使用广泛使用的框架,如 TensorFlow、PyTorch、MXNet、XGboost 等,您所要做的就是将您的培训脚本作为 tar.gz 文件上传到亚马逊 S3,并通过在 YAML 编写的 Kubernetes 配置文件向亚马逊 SageMaker 提交培训作业。看看 GitHub 存储库中的示例代码和配置文件。以下是您需要做出的更改,以便通过 Kubernetes 的 kubectl 提交您的 Amazon SageMaker 培训工作
下面是这篇博文的 GitHub 资源库中的[k8s-sm-dist-training-script.y](https://github.com/shashankprasanna/kubernetes-sagemaker-demos/blob/master/1-tf-dist-training-training-script/k8s-sm-dist-training-script.yaml)aml
文件摘录。
apiVersion: sagemaker.aws.amazon.com/v1
kind: TrainingJob
metadata:
name: k8s-sm-dist-training-script
spec:
hyperParameters:
- name: learning-rate
value: "0.001"
- name: batch-size
value: "256"
…
- name: sagemaker_program
value: 'cifar10-multi-gpu-horovod-sagemaker.py'
- name: sagemaker_submit_directory
value: 's3://sagemaker-jobs/training-scripts/sourcedir.tar.gz'
...
algorithmSpecification:
trainingImage: 763104351884.dkr.ecr.us-west-2.amazonaws.com/tensorflow-training:1.15.2-gpu-py27-cu100-ubuntu18.04
trainingInputMode: File
...
resourceConfig:
instanceCount: 128
instanceType: "ml.p3.2xlarge"
volumeSizeInGB: 50
...
这读起来像任何其他 Kubernetes 配置写在 YAML。对于培训工作,你会注意到顶部的kind: TrainingJob
以下是几个关键部分,您可以在其中指定培训工作的各个方面:
**hyperParameters**
—这些在 YAML 规范中指定,因此您可以通过更改和提交培训作业来自动运行不同的实验**sagemaker_submit_directory**
—您上传培训脚本的 S3 地点。与使用 Kubernetes 提交培训相比,这是独一无二的,因为您不必构建自定义容器!Amazon SageMaker 会自动将您的培训脚本下载到现有的 TensorFlow 容器中,然后为您运行培训。没有乱搞 Docker 文件和自定义容器。**resourceConfig**
—您需要多少个什么类型的实例。该配置将要求 128 个 V100 GPUs 来运行分布式培训。**trainingImage**
— 从预先构建的容器中挑选用于 TensorFlow、PyTorch、MXNet,用于训练或推理,用于 Python2 或 Python 3,用于 CPU 或 GPU。
像提交任何其他 Kubernetes 配置文件一样提交作业。
kubectl apply -f k8s-sm-dist-training-script.yaml
用例 2 —使用定制容器的分布式培训
工作流:用户在本地构建一个自定义容器,并将其推送到 Amazon ECR。Amazon SageMaker 提取定制容器,并在完全管理的训练集群上运行它。
如果您正在使用定制的专有算法并构建自己的 Docker 容器,那么您更愿意指定容器映像,而不是 TensorFlow、PyTorch、MXNet 等框架培训脚本。与用例 1 不同,您必须经历额外的步骤,首先在本地构建一个自定义 docker 容器,并将其推送到 Amazon Elastic Container Registry(ECR ),并在 trainingImage 下指定其 URI。如果您没有需要构建定制容器的定制算法,我推荐使用用例 1 中的方法。
apiVersion: sagemaker.aws.amazon.com/v1
kind: TrainingJob
metadata:
name: k8s-sm-dist-custom-container
spec:
hyperParameters:
- name: learning-rate
value: "0.001"
- name: weight-decay
value: "0.0002"
...
algorithmSpecification:
trainingImage: <ACCOUNT_ID>.dkr.ecr.us-west-2.amazonaws.com/<IMAGE>:latest
trainingInputMode: File
metricDefinitions:
- name: val_acc
- regex: 'val_acc: ([0-9\\.]+)'
GitHub 存储库中的代码也包括重复这些步骤的 Jupyter 笔记本。
提交作业:
kubectl apply -f k8s-sm-dist-custom-container.yaml
用例 3——大规模超参数优化
机器学习模型的超参数是在训练阶段没有优化或学习的选项。Amazon SageMaker 提供超参数优化功能,并实现贝叶斯和随机搜索。这与 KubeFlow 的 Katib 项目所提供的功能没有什么不同。要在 Amazon SageMaker 上运行大规模的超参数调优作业,需要创建一个 Kubernetes 配置文件。这里您将指定超参数范围,而不是固定的超参数。这指示亚马逊 SageMaker 尝试不同的选项,以达到最佳模式。maxNumberOfTrainingJobs 指定您希望使用不同超参数组合运行的作业总数,maxParallelTrainingJobs 指定您希望在任何给定时间对多少个实例运行此操作。
apiVersion: sagemaker.aws.amazon.com/v1
kind: HyperparameterTuningJob
metadata:
name: k8s-sm-hyperopt-training-script
spec:
hyperParameterTuningJobConfig:
resourceLimits:
maxNumberOfTrainingJobs: 32
maxParallelTrainingJobs: 8
strategy: "Bayesian"
trainingJobEarlyStoppingType: Auto
hyperParameterTuningJobObjective:
type: Maximize
metricName: 'val_acc'
parameterRanges:
continuousParameterRanges:
- name: learning-rate
minValue: '0.0001'
maxValue: '0.1'
scalingType: Logarithmic
...
categoricalParameterRanges:
- name: optimizer
values:
- 'sgd'
- 'adam'
...
提交作业:
kubectl apply -f k8s-sm-dist-custom-container.yaml
用例 4——用 BYO 模型托管一个推理端点
工作流程:用户上传一个训练有素的模型作为 tar.gz 文件到亚马逊 S3。如果模型是使用亚马逊 SageMaker 训练的,那么 model.tar.gz 将已经在亚马逊 S3 上可用。Amazon SageMaker 下载模型文件,提取服务容器,并在完全托管的实例上托管端点。
一旦模型经过训练,您就可以使用 Amazon SageMaker 托管来托管它,而不是在您的 Kubernetes 集群上托管它。使用 Amazon SageMaker,您可以利用额外的功能和节省成本的特性进行推理部署。要进行部署,您需要创建一个配置文件:HostingDeployment。在这里,您将指定实例的类型,如果您托管多个模型,则提供 A/B 测试的权重,以及经过训练的模型在亚马逊 S3 上的位置,如下所示。
apiVersion: sagemaker.aws.amazon.com/v1
kind: HostingDeployment
metadata:
name: k8s-sm-inference-host-endpoint
spec:
region: us-west-2
productionVariants:
- variantName: AllTraffic
modelName: tf-cifar10-resnet-model
initialInstanceCount: 1
instanceType: ml.c5.large
initialVariantWeight: 1
models:
- name: tf-cifar10-resnet-model
executionRoleArn: arn:aws:iam::<ACCOUNT_ID>:role/service-role/AmazonSageMaker-ExecutionRole-20190820T113591
containers:
- containerHostname: tensorflow
modelDataUrl: s3://sagemaker-jobs/trained-tf-model/model.tar.gz
image: 763104351884.dkr.ecr.us-west-2.amazonaws.com/tensorflow-inference:1.15.2-cpu-py36-ubuntu18.04
准备实施!
在这篇文章中,我简要介绍了 Amazon sage maker Operator for Kubernetes,以及如何在现有的 Kubernetes 集群中使用它。我展示了 2 个场景和 4 个不同的用例来利用 Amazon SageMaker 的优势,而无需离开您的 Kubernetes 环境。
关于如何实现这篇博文中给出的例子的分步说明,请查看这篇附带的文章:
要运行这些示例,请前往 GitHub:
https://GitHub . com/shashankprasanna/kubernetes-sage maker-demos . git
如果你有问题,请在 twitter (@shshnkp)、LinkedIn 联系我或者在下面留言。
用于 Kubernetes 的 Amazon SageMaker 操作员—分布式培训、超参数调整和模型托管的示例
了解如何编写自己的 YAML 配置文件来使用 Amazon SageMaker 操作符
使用 Amazon SageMaker Operators for Kubernetes 来运行培训作业、模型调优作业、批量转换作业,并使用 Kubernetes 配置文件和 kubectl 在 Amazon sage maker 上设置推理端点
在 re:invent 2019 上,AWS 宣布了用于 Kubernetes **、**的 亚马逊 SageMaker 操作符,使 Kubernetes 用户能够训练机器学习模型,优化超参数,运行批量转换作业,并使用亚马逊 SageMaker 设置推理端点——而无需离开您的 Kubernetes 集群。您可以通过在 YAML 编写熟悉的 Kubernetes 配置文件并使用kubectl
CLI 工具将它们应用到您的 Kubernetes 集群来调用 Amazon SageMaker 功能。
这使您可以通过将训练和推理工作负载卸载到 Amazon SageMaker 来扩展 Kubernetes 集群的容量和机器学习能力。关于亚马逊 sage maker Operators for Kubernetes 的更多介绍,请阅读以下博客文章:
在这篇博文中,我将一步一步地介绍如何创建 Kubernetes 配置文件来运行分布式训练作业、超参数调优作业以及使用 Amazon SageMaker 托管可伸缩模型推理端点。
本指南的目标读者是对 Kubernetes 有基本了解的开发人员、研究人员或 DevOps 专业人员。即使您不熟悉 Kubernetes 和 Amazon SageMaker,我也会介绍提交培训作业和托管推理端点所需的所有必要步骤。
所有代码、配置文件和演示 Jupyter 笔记本都可以在 GitHub 上获得:https://GitHub . com/shashankprasanna/kubernetes-sage maker-demos . git
用于 Kubernetes 的 Amazon SageMaker 操作符及其使用方法
Amazon SageMaker Operators for Kubernetes 是作为 Kubernetes 中的一个定制资源实现的,它使 Kubernetes 能够调用 Amazon sage maker 功能。下面,我将提供实现每个用例的逐步说明:
- 用例 1: 利用 TensorFlow、PyTorch、MXNet 等框架进行分布式训练
- 用例 2: 使用定制容器的分布式培训
- 用例 3: 使用 TensorFlow 进行大规模超参数优化
- 用例 4: 用 BYO 模型托管一个推理端点
接下来,我假设您有一个 AWS 帐户,并且在您的主机上安装了 AWS CLI 工具。
所有代码、配置文件和演示 Jupyter 笔记本都可以在 GitHub 上获得:https://GitHub . com/shashankprasanna/kubernetes-sage maker-demos . git
设置
让我们从构建一个 Kubernetes 集群开始。使用 eksctl CLI 工具,只需一个简单的命令和 15 分钟的时间,就可以构建一个包含几个节点的非常简单的集群。
按照 AWS 文档中的说明安装 eksctl CLI 工具。然后运行下面的命令,去喝杯咖啡。这个命令启动一个单节点 Amazon Elastic Kubernetes 服务(EKS)集群,这对于本文中的例子来说已经足够了。请注意,您仍然可以使用 Amazon SageMaker Operators for Kubernetes 在 Amazon sage maker 上的数百个节点上运行大规模分布式培训和超参数调优作业。
创建一个 Kubernetes 集群
eksctl create cluster \
--name sm-operator-demo \
--version 1.14 \
--region us-west-2 \
--nodegroup-name test-nodes \
--node-type c5.xlarge \
--nodes 1 \
--node-volume-size 50 \
--node-zones us-west-2a \
--timeout=40m \
--auto-kubeconfig
为 Kubernetes 安装 Amazon SageMaker 操作员
一旦集群启动并运行,按照用户指南中的说明为 Kubernetes 安装 Amazon SageMaker 操作器。你也可以参考这篇有帮助的博客文章来指导你的安装过程:为 Kubernetes 介绍 Amazon SageMaker 操作员
验证安装运行
kubectl get crd | grep sagemaker
您应该得到如下所示的输出:
batchtransformjobs.sagemaker.aws.amazon.com 2020-02-29T21:21:24Z
endpointconfigs.sagemaker.aws.amazon.com 2020-02-29T21:21:24Z
hostingdeployments.sagemaker.aws.amazon.com 2020-02-29T21:21:24Z
hyperparametertuningjobs.sagemaker.aws.amazon.com 2020-02-29T21:21:24Z
models.sagemaker.aws.amazon.com 2020-02-29T21:21:24Z
trainingjobs.sagemaker.aws.amazon.com 2020-02-29T21:21:24Z
这些都是您可以使用 Amazon SageMaker Operators for Kubernetes 在 Amazon SageMaker 上执行的任务,我们将进一步了解(1)培训作业(2)超参数调优作业(3)托管部署。
从 GitHub 下载示例
将培训脚本、配置文件和 Jupyter 笔记本下载到您的主机上。
git clone [https://github.com/shashankprasanna/kubernetes-sagemaker-demos.git](https://github.com/shashankprasanna/kubernetes-sagemaker-demos.git)
下载训练数据集并上传至亚马逊 S3
cd kubernetes-sagemaker-demos/0-upload-dataset-s3
注意: TensorFlow 必须安装在主机上才能下载数据集并转换为 TFRecord 格式
浏览[upload_dataset_s3.ipynb](https://github.com/shashankprasanna/kubernetes-sagemaker-demos/blob/master/0-upload-dataset-s3/upload_dataset_s3.ipynb)
将你的训练数据集上传到亚马逊
用例 1:使用 TensorFlow、PyTorch、MXNet 等框架的分布式培训
如果您是 Amazon SageMaker 的新手,那么在使用 TensorFlow、PyTorch、MXNet、XGBoost 等流行框架时,它的一个很好的特性是,您不必担心构建包含代码的自定义容器并将其推送到容器注册中心。Amazon SageMaker 可以自动将任何培训脚本和依赖项下载到一个框架容器中,并为您大规模运行它。所以你只需要版本化和管理你的训练脚本,根本不用处理容器。有了 Amazon sage maker Operators for Kubernetes,你仍然可以获得同样的体验。
导航到包含第一个示例的目录:
cd kubernetes-sagemaker-demos/1-tf-dist-training-training-script/
ls -1
输出:
cifar10-multi-gpu-horovod-sagemaker.py
k8s-sm-dist-training-script.yaml
model_def.py
upload_source_to_s3.ipynb
这个目录下的两个 python 文件cifar10-multi-gpu-horovod-sagemaker.py
和model_def.py
是 TensorFlow 训练脚本,实现了分布式训练的 Horovod API。
运行[upload_source_to_s3.ipynb](https://github.com/shashankprasanna/kubernetes-sagemaker-demos/blob/master/1-tf-dist-training-training-script/upload_source_to_s3.ipynb)
,用训练脚本创建一个 tar 文件,并上传到指定的亚马逊 S3 桶。
[k8s-sm-dist-training-script.yaml](https://github.com/shashankprasanna/kubernetes-sagemaker-demos/blob/master/1-tf-dist-training-training-script/k8s-sm-dist-training-script.yaml)
一个配置文件,当使用分布式培训任务的kubectl
kicks 应用时。在您最喜欢的文本编辑器中打开它,仔细查看。
首先你会注意到kind: TrainingJob
。这表明你将提交一份亚马逊 SageMaker 培训工作。
在超参数下,指定cifar10-multi-gpu-horovod-sagemaker.py
可以接受作为输入的超参数。
为分布式培训指定附加参数:
sagemaker_program
—cifar 10-multi-GPU-horo VOD-sage maker . py tensor flow 培训脚本,实现用于分布式培训的 Horovod APIsagemaker_submit_directory
—亚马逊 S3 上培训脚本所在的位置sagemaker_mpi_enabled
和sagemaker_mpi_custom_mpi_options
—为分布式培训启用 MPI 通信sagemaker_mpi_num_of_processes_per_host
—设置为请求实例上的 GPU 数量。对于有 8 个 GPU 的p3dn.24xlarge
实例,将该值设置为 8。
通过从这里选择适当的容器来指定深度学习框架容器:
https://docs . AWS . Amazon . com/dlami/latest/dev guide/deep-learning-containers-images . html
Amazon SageMaker 会自动将sagemaker_submit_directory
下指定的训练脚本下载到从 trainingImage 实例化的容器中。
要跟踪性能,您还可以指定一个指标定义。
在“资源配置”下,指定要在多少个实例或节点上运行此多节点培训。上面的配置文件指定它将在 32 个 GPU 上运行分布式训练。
最后,指定亚马逊 S3 上的数据集位置。这应该与您在运行upload _ source _ to _ S3 . ipynbJupyter notebook 以上传训练数据集时选择的存储桶名称相同。
要开始分布式培训,请运行:
kubectl apply -f k8s-sm-dist-training-script.yaml
输出:
trainingjob.sagemaker.aws.amazon.com/k8s-sm-dist-training-script created
要运行培训职务信息,请执行以下操作:
kubectl get trainingjob
输出:
NAME STATUS SECONDARY-STATUS CREATION-TIME SAGEMAKER-JOB-NAME
k8s-sm-dist-training-script InProgress Starting 2020-03-03T08:25:40Z k8s-sm-dist-training-script-91027b685d2811ea97a20e30c8d9dadc
现在导航到AWS Console > Amazon SageMaker > Training jobs
您将看到一个与kubectl get trainingjob
的输出同名的新培训作业
要查看培训日志,请单击控制台中的培训作业,然后单击监视器部分下的“查看日志”。这将带您到 CloudWatch,您可以在那里查看培训日志。
或者,如果您安装了 smlogs 插件,那么您可以使用kubectl
运行以下命令来查看日志:
kubectl smlogs trainingjob k8s-sm-dist-training-script
用例 2:使用定制容器的分布式培训
如果你正在使用定制的专有算法,那么你必须构建自己的 Docker 容器。要提交一个带有自定义容器的训练作业,首先要在本地构建容器映像,并将其推送到 Amazon Elastic Container Registry(ECR)。将映像推送到 ECR 后,您将使用 ECR 路径更新 Kubernetes 作业配置文件,而不是我们在前面的示例中提供的 TensorFlow 容器路径。
导航到第二个示例的目录:
cd kubernetes-sagemaker-demos/2-tf-dist-training-custom-container/docker
ls -1
输出:
build_docker_push_to_ecr.ipynb
cifar10-multi-gpu-horovod-sagemaker.py
Dockerfile
model_def.py
运行[build_docker_push_to_ecr.ipynb](https://github.com/shashankprasanna/kubernetes-sagemaker-demos/blob/master/2-tf-dist-training-custom-container/docker/build_docker_push_to_ecr.ipynb)
来构建 docker 文件,并将其推送到 ECR 注册表。
导航至AWS Console > Amazon ECR
。您应该会在这里看到新推出的 Docker 容器:
导航到
cd kubernetes-sagemaker-demos/2-tf-dist-training-custom-container/
在你最喜欢的文本编辑器中打开[k8s-sm-dist-custom-container.yaml](https://github.com/shashankprasanna/kubernetes-sagemaker-demos/blob/master/2-tf-dist-training-custom-container/k8s-sm-dist-custom-container.yaml)
配置文件仔细看看。
您需要做的惟一更改是 trainingImage 部分,在这里您需要提供 ECR 注册中心中您将自定义容器推送到的位置。
要使用自定义容器启动分布式培训,请运行:
kubectl apply -f k8s-sm-dist-custom-container.yaml
输出:
trainingjob.sagemaker.aws.amazon.com/k8s-sm-dist-custom-container created
用例 3:利用 TensorFlow 进行大规模超参数优化
机器学习模型的超参数是在训练阶段没有优化或学习的选项,但是影响模型的性能。要提交 Amazon SageMaker 超参数调优作业,您需要创建一个 Kubernetes 配置文件kind: hyperparameterTuningJob
,而不是前面两个例子中的trainingJob
。
另一个区别是,这里您将指定超参数的范围,而不是固定的超参数,这样 Amazon SageMaker 可以尝试不同的选项来获得最佳模型。
导航到第三个示例的目录:
cd kubernetes-sagemaker-demos/3-tf-hyperopt-training-script
ls -1
输出
cifar10-training-script-sagemaker.py
inference.py
k8s-sm-hyperopt-training-script.yaml
requirements.txt
upload_source_to_s3.ipynb
运行[upload_source_to_s3.ipynb](https://github.com/shashankprasanna/kubernetes-sagemaker-demos/blob/master/3-tf-hyperopt-training-script/upload_source_to_s3.ipynb)
将培训脚本上传至亚马逊 S3。
在您最喜欢的文本编辑器中打开[k8s-sm-hyperopt-training-script.yaml](https://github.com/shashankprasanna/kubernetes-sagemaker-demos/blob/master/3-tf-hyperopt-training-script/k8s-sm-hyperopt-training-script.yaml)
配置文件仔细查看。
kind: HyperParameterTuningJob
表明这是一项 Amazon SageMaker 模型调优工作。
在 resourceLimits 下,指定希望 hyperparameter tuner 运行多少训练作业,以便探索和找到最佳的 hyperparameter 集。maxNumberOfTrainingJobs 指定您希望使用不同超参数组合运行的作业总数,maxParallelTrainingJobs 指定您希望在任何给定时间对多少个实例运行此操作。策略可以是贝叶斯或随机的。
超参数可以是 integerParameterRanges、continuousParameterRanges 或 categoricalParameterRanges。在上面的例子中,优化器和批量大小是分类的,这意味着 Amazon SageMaker 将随机选择一个指定的值。对于学习速率和动量,Amazon SageMaker 会在指定范围内随机选取一个连续值。
要启动超参数优化作业,请运行:
kubectl apply -f k8s-sm-hyperopt-training-script.yaml
输出:
hyperparametertuningjob.sagemaker.aws.amazon.com/k8s-sm-hyperopt-training-script created
要获得有关超参数优化作业的更多详细信息,请运行:
kubectl get hyperparametertuningjob
输出
NAME STATUS CREATION-TIME COMPLETED INPROGRESS ERRORS STOPPED BEST-TRAINING-JOB SAGEMAKER-JOB-NAME
k8s-sm-hyperopt-training-script InProgress 2020-03-03T09:13:58Z 0 2 0 0 50d11d175d2f11ea89ac02f05b3bb36a
超参数调优作业产生了多个训练作业,您可以通过请求 kubectl 获得训练作业的列表来查看这些作业
kubectl get trainingjob
输出
NAME STATUS SECONDARY-STATUS CREATION-TIME SAGEMAKER-JOB-NAME
50d11d175d2f11ea89ac02f05b3bb36a-001-673da61b InProgress Starting 2020-03-03T09:14:11Z 50d11d175d2f11ea89ac02f05b3bb36a-001-673da61b
50d11d175d2f11ea89ac02f05b3bb36a-002-7952d388 InProgress Downloading 2020-03-03T09:14:11Z 50d11d175d2f11ea89ac02f05b3bb36a-002-7952d388
导航至AWS Console > Amazon SageMaker > Hyperparameter tuning jobs
您应该看到超参数调优工作正在进行中
用例 4:用 BYO 模型托管一个推理端点
要在 Amazon SageMaker 托管服务中部署模型,您只需将自己的模型放在压缩的 tar 文件中。如果您想要托管在 Amazon SageMaker 上训练的模型,那么输出将已经是所需的格式。
如果您运行上面的例子,只需导航到保存培训工作结果的亚马逊 S3 存储区AmazonS3 > YOUR_BUCKET > JOB_NAME > output
。在这里,您应该可以找到一个名为model.tar.gz
的文件,其中包含了培训模型。
导航到第四个示例的目录:
cd kubernetes-sagemaker-demos/3-tf-hyperopt-training-script
ls -1
输出
k8s-sm-inference-host-endpoint.yaml
在您喜欢的文本编辑器中打开[k8s-sm-inference-host-endpoint.yaml](https://github.com/shashankprasanna/kubernetes-sagemaker-demos/blob/master/4-tf-inference-host-endpoint/k8s-sm-inference-host-endpoint.yaml)
配置文件,仔细查看。
在instanceType
下指定托管的实例类型,如果您托管多个模型,请提供 A/B 测试的权重。在modelDataUrl
下,指定受训模特在亚马逊 S3 上的位置。
要部署模型,请运行:
kubectl apply -f k8s-sm-inference-host-endpoint.yaml
输出:
hostingdeployment.sagemaker.aws.amazon.com/k8s-sm-inference-host-endpoint created
要查看有关托管部署的详细信息,请运行:
kubectl get hostingdeployments
输出:
NAME STATUS SAGEMAKER-ENDPOINT-NAME
k8s-sm-inference-host-endpoint Creating k8s-sm-inference-host-endpoint-cdbb6db95d3111ea97a20e30c8d9dadc
导航至AWS Console > Amazon SageMaker > Endpoints
您应该能够看到服务中的 Amazon SageMaker 端点,并准备好接受请求。
结论
在这篇博文中,我介绍了如何将 Kubernetes 和 Amazon SageMaker 结合起来,在运行机器学习工作负载时发挥两者的优势。
我简要介绍了用于 Kubernetes 的 Amazon SageMaker 操作符,以及如何使用它来利用 Amazon SageMaker 的功能,如分布式培训、超参数优化和托管可弹性伸缩的推理端点。之后,我向您展示了使用 Kubernetes CLI kubect
提交培训和部署请求的一步一步的过程。
我在 GitHub 上提供了所有的配置文件,所以你可以随意使用它,修改它,让它成为你自己的。感谢阅读,所有代码和示例在 GitHub 上都有:
https://GitHub . com/shashankprasanna/kubernetes-sage maker-demos . git
如果你有问题,请在推特( @shshnkp ), LinkedIn 联系我或者在下面留言。尽情享受吧!
使用 AWS EKS 和 ECR 部署 Kubernetes 应用程序
使用 AWS EKS 和 AWS ECR 映像将应用程序部署到 Kubernetes。
库伯内特斯
Kubernetes 是 Google 在 2014 年创建的一个容器编排平台。它是一个开源平台,目前许多组织广泛用于容器部署和管理。尽管社区中有其他容器编排工具可用,如 Docker Swarm,但 Kubernetes 仍因其特性和灵活的可用性而保持容器编排的领先地位。
AWS EKS
亚马逊弹性 Kubernetes 服务是在 AWS 基础设施上为 Kubernetes 提供的服务。像 AWS 提供的任何其他服务一样,Kubernetes 资源将完全由 AWS 自己管理,这减少了开发人员维护它们的负担。AWS 还确保这些资源每次都高度可用和可靠。
AWS ECR
Amazon Elastic Container Registry 是 AWS 提供的一个完全托管的 Docker 注册表。就像流行的 docker 注册表 Dockerhub 一样,ECR 也支持非常安全的私有和公共存储库。我们可以使用 AWS CLI 将图像推送或拉入 ECR。
在本文中,我们将探讨如何使用 AWS EKS 和 ECR 服务部署 Kubernetes 应用程序。在深入了解我们将如何实施我们的 Kubernetes 解决方案的复杂细节之前,下面是我们将执行的任务的摘要。
- 使用 Node.js 创建一个简单的 web 应用程序
- 创建 web 应用程序的 docker 映像
- 将我们的 docker 图像推送到 AWS ECR
- 为我们的 EKS 集群创建一个包含公共和私有子网的 VPC
- 创建一个 Kubernetes 集群
- 创建 Kubernetes 工人(公共和私人工人)
- 在 Kubernetes 上部署我们的 web 应用程序
现在我希望你至少对我们将在这篇文章中涉及的内容有一点点概念。在我们开始实现之前,我们需要在我们的开发机器中具备以下先决条件。
先决条件
- Kubectl —我们将用来在我们的 Kubernetes 集群和我们的机器之间进行通信的通信工具。安装说明可从https://kubernetes.io/docs/tasks/tools/install-kubectl/获得
- AWS CLI — AWS 工具,我们将使用它发布与 AWS 配置相关的命令。要安装,请遵循https://docs . AWS . Amazon . com/CLI/latest/user guide/CLI-chap-configure . html
- Aws iam 认证者 —授予 iam 角色访问我们的 Kubernetes 集群的权限。用于安装https://docs . AWS . Amazon . com/eks/latest/user guide/install-AWS-iam-authenticator . html
- eks CTL—AWS EKS 官方 CLI 工具。对于安装 https://github . com/weave works/eks CTL
在满足我们的先决条件后,第一个任务将是创建一个简单的服务器。我使用 Node.js 和 express 来创建一个非常简单的 web 应用程序,它将在端口 3000 上进行侦听。
接下来,让我们对我们的 web 应用程序进行 dockerize。创建 docker 文件并发出 docker 构建命令。
docker build -t webapp .
现在,如果您发布 docker 图像,我们将看到我们的 webapp 图像。下一个任务是将我们的图像推送到 AWS ECR。
创建 ECR 存储库
在推送映像之前,我们需要在 ECR 上创建一个存储库。为此,转到 ECR 仪表板并点击创建存储库。
现在,我们有了一个存储库来推送我们的图像。但在此之前,我们需要验证我们的 AWS CLI,以便将图像推送到我们的存储库。对于下面的问题命令。
(Get-ECRLoginCommand).Password | docker login --username AWS --password-stdin 628640267234.dkr.ecr.ap-southeast-1.amazonaws.com
之后,用我们的库名标记图像。在这里作为版本,你可以给任何版本,但在这种情况下,我将使版本作为最新的。
docker tag webapp:latest 628640267234.dkr.ecr.ap-southeast-1.amazonaws.com/eks-demo:latest
现在是最后一步,将我们的映像推送到 ECR 存储库。
docker push 628640267234.dkr.ecr.ap-southeast-1.amazonaws.com/eks-demo:latest
如果您遇到任何权限问题,请确保您的 AWS CLI 角色拥有权限amazonec 2 containerregistryfull access。
现在转到我们的存储库,我们推送的图像应该在那里可用。
正在创建 AWS EKS 集群
下一步是创建我们的 EKS 集群。创建集群时,我们需要指定集群要使用的 VPC 子网。亚马逊 EKS 需要至少两个可用区域中的子网。创建 VPC 时,我们有两个选择。
- 创建公共和私有子网
- 仅创建公共子网
在本文中,我们将创建公共子网和私有子网的组合。在这种情况下,可以使用公共子网从外部访问我们的 web 应用程序,此外,如果我们需要部署数据库之类的东西,我们可以将它们设为私有,只有我们的 web 应用程序和 VPC 内的任何其他应用程序可以访问它们。
创造 VPC
如果需要,可以手动为我们的集群创建 VPC。但是让我们使用 AWS Cloudformation 创建我们的 VPC,因为 AWS 已经有了一个创建公共和私有子网 VPC 的模板。
- 转到 CloudFormation dashboard 并选择创建堆栈
- 在这里选择模板源作为亚马逊 S3 网址,并提供以下模板已经由 AWS 创建。
[https://amazon-eks.s3.us-west-2.amazonaws.com/cloudformation/2020-06-10/amazon-eks-vpc-private-subnets.yaml](https://amazon-eks.s3.us-west-2.amazonaws.com/cloudformation/2020-06-10/amazon-eks-vpc-private-subnets.yaml)
- VPC 的 CIDR 地址将是 192.168.0.0/16
- 使用 CIDR 地址块 192.168.0.0/18 和 192.168.64.0/18 创建两个公共子网
- 使用 CIDR 地址块 192.168.128.0/18 和 192.168.192.0/18 创建两个私有子网
最后,选择 Create 并等待直到栈被创建。在堆栈创建的最后,它将给出 3 个输出。
- SecurityGroups —这是为我们的 VPC 创建的安全组。
- SubnetIds —我们创建的 4 个子网的 id。A
- VpcId —创建的 VPC 的 Id。
用工人创建 EKS 集群
我们可以通过给出 eksctl create cluster 命令来轻松创建集群。但是让我们用下面的附加配置创建一个 YAML 文件。
在上面的 cluster.yaml 文件中,我们为集群定义了以下配置。
- 集群名称将为 EKS 演示集群
- 在 vpc 部分,我们提供了之前已经创建的 VPC
- 在节点组中,我们使用 t2.meduim 实例创建 3 个 workers。三个工人中有两个将被创建为公共工人,而一个将被创建为私有工人。
现在发出下面的命令,在 EKS 上创建我们的集群。
eksctl create cluster -f cluster.yaml **--kubeconfig**=C:\Users\{user}\.kube\config
之后,eksctl 将根据我们的 YAML 文件开始创建我们的集群。创建群集和节点将需要几分钟时间。在 get issue 下面的命令检查我们的集群是否已经部署。
kubectl get svc
当您发出 kubectl 命令时,有时可能会得到以下错误。这可能意味着在我们的 kubectl 配置文件中,没有定义访问集群所需的凭证和用户。
error: no configuration has been provided, try setting KUBERNETES_MASTER environment variable
要将这些配置详细信息写入配置文件,请发出以下命令。
aws eks --region {region} update-kubeconfig --name EKS-Demo-Cluster
创建部署清单
现在让我们开始在创建的 Kubernetes 集群上部署我们的应用程序。首先,要在 pods 上部署我们的应用程序,我们需要创建一个部署。下面是将用于部署的部署清单。
- 我们的应用标签将是 app:web
- 在规格:模板:规格:容器中为我们推送的 AWS ECR 图像设置图像
- 应用程序的副本数量为 2
发出以下命令来创建我们的部署。
kubectl apply -f deployment.yaml
要检查我们的部署是否已创建,请发出以下命令。
kubectl get deployments
现在,我们可以看到我们的部署已经创建并运行在两个 pod 上。
创建服务清单
现在要访问我们的应用程序,我们需要创建一个服务。我们的服务类型将是节点端口,因为我们需要我们的应用程序从外部访问。
- 服务类型为节点端口
- targetPort 是 3000 ,因为这是我们的集装箱暴露端口
- 选择器将是 app:web ,因为这是我们在部署中定义的标签
根据命令创建我们的服务问题
kubectl apply -f service.yaml
要检查我们的服务是否已创建,请发出以下命令。
kubectl get services
现在让我们尝试从外部访问我们的 web 应用程序。从服务中,我们知道我们的应用程序正在侦听端口 31479。接下来,我们需要获取应用程序节点的公共 IP 地址。让我们首先尝试确定我们的应用程序在哪里运行。
kubectl get pods -o wide
由此,我们可以识别我们的应用程序正在运行的 pod 的节点。要获取这些节点的外部 IP 地址,请发出 get nodes 命令。
kubectl get nodes -o wide
在上面的节点列表中,我们可以看到两个节点有外部 IP,而一个没有,因为我们将其配置为私有工作节点。现在我们有了我们的 IP 地址以及它正在监听的端口。下一个任务是将此端口添加到节点的安全组中,以允许流量进入。并添加入站规则以允许端口 31479 中流量。
之后,我们可以获得一个公共节点 IP 地址,并使用端口 31479 调用它。
我们也可以对其他 IP 地址做同样的事情,结果应该是一样的。
下一个任务是将数据库部署到我们的 Kubernetes 集群中。但是我会把这个任务留给你去尝试。之后,确保通过发出以下命令删除集群,以避免对我们创建的 EC2 实例收费。
eksctl delete cluster --region=ap-southeast-1 --name=EKS-Demo-Cluster
这就是如何使用 AWS EKS 和 ECR 创建和部署应用程序到 Kubernetes。在 Kubernetes 和 EKS 上还有很多其他的概念值得我们学习。因此,一定要不断学习,直到你有信心部署和管理应用程序。谢谢你。
Kubernetes 开发:超越配置文件
关注你的代码,而不是基础设施!
图片来自皮克斯拜
许多故事称赞 Kubernetes 是自动化部署、扩展和管理容器化应用程序的优秀工具。我支持这一点;Kubernetes 正在努力减轻微服务架构的痛苦并应对其挑战。
然而,Kubernetes 上的当地发展可能是一个痛点。典型的工作流程由几个步骤组成;在本地测试您的应用程序,构建并标记 docker 映像,创建部署配置,最后在 Kubernetes 上运行您的应用程序。如果有一个 bug 或者一个新的特性需要集成,开发者需要从头开始遵循同样的过程。在他们的 Next’19 演示中,谷歌工程师称之为痛苦和折磨的无限循环。
在之前的故事中,我们介绍了 Skaffold,这是 Google 的一个轻量级开源项目,它促进了本地 Kubernetes 的开发。你可以在这里了解更多信息:
在 Kubernetes 上开发时,痛苦和苦难的无限循环已经成为过去。
towardsdatascience.com](/kubernetes-local-development-the-correct-way-1bc4b11570d8)
**但是,有没有更自然的方法来解决当地 Kubernetes 发展的挑战呢?我们能不能只关注我们的代码,而把基础设施排除在我们的逻辑之外?**嗯,输入云码!
云代码(Cloud Code)是 Google 云平台的一套开发工具,包括 Visual Studio 代码和几个 JetBrains 产品的 IDE 扩展。它促进了本地或远程 Kubernetes 集群上的开发、部署和调试。它使用 Skaffold,所以让我们更深入地了解为什么以及如何使用它!
学习率是为那些对 AI 和 MLOps 的世界感到好奇的人准备的时事通讯。你会在每周五收到我关于最新人工智能新闻和文章的更新和想法。在这里订阅!
你可能需要的一切
云代码是一个 IDE 扩展,它支持迭代开发,并使本地和远程集群上的调试变得轻而易举。该工具提供了几个功能,让您专注于工作中有趣的部分。
- **帮助处理 Kubernetes 配置文件;**云代码提供了完成建议、林挺、内联文档和代码片段。编写 Kubernetes 配置文件从来没有那么容易。
- **自动化部署流程;**云代码自动化了我们在序言中看到的工作流程步骤。只需一个命令,我们就可以构建、推送和部署我们的应用程序,并在发生任何变化时自动重新部署它。此外,在远程集群上调试就像在笔记本电脑上调试代码一样。
- **提供一个公用事业的世界;**云代码为调试配置端口转发和入口点,并提供图形用户界面与部署进行交互。
装置
要安装云代码,只需将其作为扩展添加到您最喜欢的 IDE 中。例如,我更喜欢使用 Visual Studio 代码。因此,要将它添加到 VS 代码中,请在扩展面板中搜索它,然后单击 install。它会在你的工具条上添加一个或多个新图标。
简单的例子
在本节中,我们将使用一个简单的 Flask 应用程序,它将" Hello World" 打印到屏幕上。我们将使用通过云代码提供的模板。选择的 IDE 是 VS 代码,因此,从屏幕底部选择Cloud Code
,然后选择New Application
。然后,选择Kubernetes Application
、Python (Flask): Hello World
模板和路径来初始化你的项目。
使用云代码创建新的应用程序
该模板已经有一个包含我们的应用程序逻辑的src
文件夹,一个包含部署和服务 YAML 配置文件的kubernetes-manifests
文件夹,以及一个设置 Skaffold 配置的skaffold.yaml
文件。
接下来,我们可以从底部的菜单中选择Cloud Code
菜单项,选择Run on Kubernetes
。接下来,您应该选择要部署到的集群和要推送容器映像的注册表。我正在本地 docker 集群上部署应用程序;因此,不需要选择注册表。云代码将构建您的图像,标记它并将其推送到注册表。然后,它会将它部署在您选择的集群上。如果这是您第一次执行循环,可能需要一段时间!
使用云代码运行您的应用
只要该过程成功完成,就会为您提供一个链接来查看结果。然后,如果您更改了某些内容,只要您保存了文件,就可以观看它的实时更新!
最后,您可以轻松地调试代码。从 VS 代码的调试视图中选择Debug on Kubernetes
,然后按按钮!接下来,设置一个断点,从浏览器刷新应用程序,观察调试器的神奇之处。
使用云代码调试应用程序
要更深入地研究云代码,请查看它的文档,尤其是您选择的 IDE 的快速入门指南。例如,这里的是 VS 代码的向导。
结论
在这个故事中,我们看到了如何打破每个试图在 Kubernetes 上进行本地开发的开发人员所面临的痛苦和折磨的无限循环。我们引入了云代码,这是一个强大的 IDE 扩展,可用于 Visual Studio 代码和几个 JetBrains 产品。
云代码通过提供一组丰富的特性来优化开发工作流,这些特性可以自动化映像构建、标记和部署的过程。此外,它支持在本地和远程 Kubernetes 集群上进行调试,并完全支持编写 Kubernetes 配置文件。
学习率是为那些对 AI 和 MLOps 的世界感到好奇的人准备的时事通讯。你会在每周五收到我关于最新人工智能新闻和文章的更新和想法。在这里订阅!
关于作者
我叫迪米特里斯·波罗普洛斯,我是一名为阿里克托工作的机器学习工程师。我曾为欧洲委员会、欧盟统计局、国际货币基金组织、欧洲央行、经合组织和宜家等主要客户设计和实施过人工智能和软件解决方案。
如果你有兴趣阅读更多关于机器学习、深度学习、数据科学和数据运算的帖子,请关注我的 Medium 、 LinkedIn 或 Twitter 上的 @james2pl 。此外,请访问我的网站上的资源页面,这里有很多好书和顶级课程,开始构建您自己的数据科学课程吧!
Kubernetes HPA 采用来自 Prometheus 的定制指标
当需要基于自定义指标的 K8s pod 自动扩展时,可以使用一个有用的示例和分步指南。
我决定编写这些步骤,因为我最近参与了将一个复杂的应用程序从 AWS 迁移到 GCP 的工作,与其他此类系统一样,我们不能仅仅依靠 CPU 或内存使用指标来满足它们的 SLA。
自动扩展是一种根据资源使用情况自动扩大或缩小工作负载的方法。K8s 水平 Pod 自动缩放器:
- 被实现为一个控制循环,它通过 metrics.k8s.io API 定期查询资源指标 API 以获取核心指标、,如 CPU/内存和自定义指标 API 以获取应用特定指标 (external.metrics.k8s.io 或 custom.metrics.k8s.io API)。它们由 metrics 解决方案供应商提供的“适配器”API 服务器提供。有一些已知的解决方案,但是这些实现都不是 Kubernetes 的正式部分
- 根据观察到的指标,自动调整部署或副本集中的单元数量。
在下文中,我们将重点关注自定义指标,因为自定义指标 API 使得像 Prometheus 这样的监控系统能够向 HPA 控制器公开特定于应用的指标。
为了基于自定义指标进行扩展,我们需要两个组件:
- 一个从我们的应用程序中收集指标,并将它们存储到 Prometheus 时间序列数据库中。
- 第二个扩展了 Kubernetes 定制度量 API,使用收集器提供的度量,即 k8s-prometheus-adapter 。这是一个自定义指标 API 的实现,它试图支持任意指标。
配置 HPA 的分步指南
- 让我们假设我们有以下两个应用程序(名为 myapplication )特定的指标发布给 Prometheus,它正在我们的集群中监听 http://Prometheus-server . Prometheus:
**myapplication_api_response_time_count**{endpoint="api/users",environment="test",environment_type="development",instance="10.4.66.85:9102",job="myapplication-pods",namespace="myapplication",pod="myapplication-85cfb49cf6-kvl2v",status_code="2xx",verb="GET"}
和
**myapplication_api_response_time_sum**{endpoint="api/users",environment="test",environment_type="development",instance="10.4.66.85:9102",job="myapplication-pods",namespace="myapplication",pod="myapplication-85cfb49cf6-kvl2v",status_code="2xx",verb="GET"}
我们希望根据端点延迟来扩展我们的应用单元。
2.既然我们已经有了 Prometheus metrics,使用 Prometheus 适配器从 Prometheus 提供 metrics 是有意义的。Kubeapps Hub 上列出了一个舵图,名为stable/Prometheus-adapter,可用于安装适配器:
helm install --name my-release-name stable/prometheus-adapter
3.使用my application _ API _ response _ time _ avg自定义指标配置适配器:
prometheus-adapter:
prometheus:
url: http://prometheus-server.prometheus
port: 80
rules:
custom:
- seriesQuery: '{__name__=~"myapplication_api_response_time_.*",namespace!="",pod!=""}'
resources:
overrides:
namespace:
resource: namespace
pod:
resource: pod
name:
matches: ^(.*)
as: "myapplication_api_response_time_avg"
metricsQuery: 1000 * (sum(rate(myapplication_api_response_time_sum[5m]) > 0) by (<<.GroupBy>>) / sum(rate(myapplication_api_response_time_count[5m]) > 0) by (<<.GroupBy>>))
我们公开了my application _ API _ response _ time _ avg,这将被 HPA 查询。每个规则必须指定一些资源覆盖,并且 metricsQuery 告诉适配器在检索数据时应该执行哪个 Prometheus 查询。
4.使用以下命令检查指标的值,该命令向 Kubernetes API 服务器发送一个原始的 GET 请求:
kubectl get --raw "/apis/custom.metrics.k8s.io/v1beta1/namespaces/myapplication/pods/*/myapplication_api_response_time_avg" | jq .
响应:
{
"kind":"MetricValueList",
"apiVersion":"custom.metrics.k8s.io/v1beta1",
"metadata":{
"selfLink":"/apis/custom.metrics.k8s.io/v1beta1/namespaces/myapplication/pods/*/myapplication_api_response_time_avg"
},
"items":[
{
"describedObject":{
"kind":"Pod",
"namespace":"myapplication",
"name":"myapplication-85cfb49cf6-54hhf",
"apiVersion":"/v1"
},
"metricName":"myapplication_api_response_time_avg",
"timestamp":"2020-06-24T07:24:13Z",
"value":"10750m",
"selector":null
},
{
"describedObject":{
"kind":"Pod",
"namespace":"myapplication",
"name":"myapplication-85cfb49cf6-kvl2v",
"apiVersion":"/v1"
},
"metricName":"myapplication_api_response_time_avg",
"timestamp":"2020-06-24T07:24:13Z",
"value":"12",
"selector":null
}
]
}
注意,API 使用 Kubernetes 风格的数量来描述度量值。在 metrics API 中最常见的是m
后缀,这意味着毫单位,或一个单位的千分之一。如果度量正好是单位的整数,我们可能看不到后缀。
例如,在这里,10750m
将是 10,75 毫秒,12
将是 12 毫秒
5.创建一个 HPA,如果my application _ API _ response _ time _ avg暴露的延迟超过 500 ms,该 HPA 将按比例增加my application-deployment,几秒钟后,HPA 从 metrics API 中获取my application _ API _ response _ time _ avg值。
apiVersion: autoscaling/v2beta1
kind: HorizontalPodAutoscaler
metadata:
name: myapplication-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: myapplication-deployment
minReplicas: 3
maxReplicas: 15
metrics:
- type: Pods
pods:
metricName: myapplication_api_response_time_avg
targetAverageValue: "500"
6.检查新创建的 HPA。我们可能会注意到,自动缩放器不会立即对延迟峰值做出反应。默认情况下,指标同步每 30 秒发生一次,只有在过去 3-5 分钟内没有重新缩放的情况下,才会发生缩放。通过这种方式,HPA 可以防止冲突决策的快速执行,并为集群自动伸缩提供时间。
kubectl describe hpa myapplication-hpa -n myapplication
结论
处理自动伸缩基本上是每个生产就绪系统中的一项常见任务,我在引言中提到的应用程序也是如此,例如,为了处理突发流量,我们必须根据延迟进行自动伸缩。通过检测该应用程序,并通过 Prometheus 公开正确的指标进行自动扩展,我们可以对其进行微调,以更好地处理突发事件并确保高可用性。
Kubernetes 地方发展:正确的道路
在 Kubernetes 上开发时,痛苦和苦难的无限循环已经成为过去。
图片来自皮克斯拜
Kubernetes 是自动化部署、扩展和管理容器化应用程序的优秀工具。然而,Kubernetes 上的当地发展可能是一个痛苦的过程。典型的工作流程由几个不同的步骤组成;在本地检查代码的功能,构建并标记 docker 映像,创建部署配置并在 Kubernetes 上部署。如果有 bug 或需要升级,开发人员需要从头开始遵循相同的过程。在他们的 Next’19 演示中,谷歌工程师称这是痛苦和折磨的无限循环,**那么,有没有一种方法可以自动化降低生产力的部分,让开发人员专注于他们代码的逻辑?**介绍斯卡福德;
Skaffold 是 Google 的一个轻量级开源项目,它促进了本地 Kubernetes 的开发。它跨环境运行,通过提供一组丰富的特性来优化开发过程,这些特性对于原生 Kubernetes 开发是必不可少的,包括图像标记、资源端口转发和日志记录、文件同步等等。
学习率是为那些对 AI 和 MLOps 的世界感到好奇的人准备的时事通讯。你会在每周五收到我关于最新人工智能新闻和文章的更新和想法。在这里订阅!
斯卡福德来救援了!
Skaffold 提供了一个 CLI(命令行界面),可以在本地和远程集群上进行迭代开发。该工具提供了几个特性,使得在 Kubernetes 上进行本地开发成为一种乐趣。
- 轻量级开源 CLI 工具。Skaffold 没有服务器端组件,因此您在集群上没有开销或维护负担。
- **检测源代码中的变化,并自动构建/推送/部署。**ska fold 会在源代码发生变化时检测到变化(只要您保存了文件),自动启动管道来构建、标记、推送和部署您的应用程序。此外,Skaffold 聚合来自运行中的容器的日志,并将容器端口转发到主机。
- 增加项目的可移植性。斯卡福德让项目共享小菜一碟;您团队中的任何开发人员现在都可以
git clone
和skaffold run
项目,并在几秒钟内运行应用程序。此外,让新成员加入您的团队比以往任何时候都容易;不再需要安装指南和配置更改。 - 开发与生产。Skaffold 配置文件、用户级配置语句和环境标志可以描述如何在不同的环境中部署应用程序,甚至可以描述应用程序的哪个部分将被部署,从而实现细粒度的功能和集成测试。
装置
要安装 Skaffold,请遵循文档中提供的说明,或者访问 GitHub 发布页面获取特定版本。Skaffold 提供 Linux、OSX 和微软 Windows 的安装选项,以及 docker 镜像。例如,在 Linux 上安装 Skaffold CLI 就像执行以下命令一样简单:
curl -Lo skaffold https://storage.googleapis.com/skaffold/releases/latest/skaffold-linux-amd64
sudo install skaffold /usr/local/bin/
该命令安装 Skaffold 的最新稳定版本。如果您想要特定的版本(例如版本 1.10.1 ),只需将命令更改为以下内容:
curl -Lo skaffold [https://storage.googleapis.com/skaffold/releases/v1.10.1/skaffold-linux-amd64](https://storage.googleapis.com/skaffold/releases/v1.10.1/skaffold-linux-amd64) && chmod +x skaffold && sudo mv skaffold /usr/local/bin
简单的例子
在本节中,我们将使用 Skaffold GitHub 页面上提供的简单的 Go 应用程序示例。因此,有一个简单的 Go 应用程序可以打印" Hello world!“每秒钟:
现在我们需要一个 docker 文件来封装应用程序,并为 Kubernetes 部署做好准备:
FROM golang:1.12.9-alpine3.10 as builder
COPY main.go .
RUN go build -o /app main.goFROM alpine:3.10
ENV GOTRACEBACK=single
CMD ["./app"]
COPY --from=builder /app .
现在您可能会注意到这个 Dockerfile 文件的一些奇怪之处:它有两行FROM
。这种技术被称为构建器模式,用于生成较小的容器。在这种情况下,我们使用第一个容器来编译代码,因为golang:1.12.9-alpine3.1
映像为这项工作提供了所有必要的工具,而第二个映像只复制已编译的二进制文件并运行应用程序。因此,我们可以将集装箱的占地面积减少几个数量级。
现在我们有了 Dockerfile 文件,我们需要部署 YAML 配置文件:
apiVersion: v1
kind: Pod
metadata:
name: getting-started
spec:
containers:
- name: getting-started
image: skaffold-example
该文件获取图像getting-started
并将其部署在 pod 中。这就是痛苦停止的地方。我们现在可以运行skaffold init
并让工具检测我们的资源并生成斯卡福德 YAML 配置文件。
apiVersion: skaffold/v2beta4
kind: Config
metadata:
name: skaffold
build:
artifacts:
- image: skaffold-example
deploy:
kubectl:
manifests:
- pod.yaml
我们现在可以运行skaffold run
,Skaffold 将构建我们的映像并将其部署到我们本地的 Kubernetes 集群。如果这还不够,尝试运行skaffold dev
。这条语句将完全执行前面的命令,而且还会聚合容器的日志并打印出来。现在,如果您进行了更改并保存了文件,请注意,它会立即检测到更改并再次开始构建/标记/部署周期。
Kubernetes 与 Skaffold 的互动地方发展
默认情况下,Skaffold 使用 Git 标签来管理你的图片,因此如果你运行docker image ls
,你会看到类似这样的内容:
斯卡福德 git 标签
要深入了解,请查看 Skaffold 的文档示例或该工具的 GitHub 页面。最后但同样重要的是,Skaffold 与其他 Kubernetes 工具配合得很好,例如 Kustomize 和 Jib ,因此,您不必改变当前的工作流程。
结论
在这个故事中,我们介绍了每个试图在 Kubernetes 上进行本地开发的开发人员所经历的痛苦和折磨的无限循环。然后,我们介绍了 Skaffold,这是一个开源 CLI,它通过提供一组丰富的特性来优化开发工作流,这些特性对于原生 Kubernetes 开发来说是必不可少的,包括图像标记、资源端口转发和日志记录、文件同步等等。
在以后的文章中,我们将通过为 Skaffold 引入一种图形用户界面来使事情变得更简单,在这里你只需按一个按钮就可以做同样的事情。敬请期待!
编辑:新的故事现在出版了!点击下面的链接…
关注你的代码,而不是基础设施!
towardsdatascience.com](/kubernetes-development-beyond-configuration-files-f78d7ab9a43)
关于作者
我叫迪米特里斯·波罗普洛斯,我是一名为阿里克托工作的机器学习工程师。我曾为欧洲委员会、欧盟统计局、国际货币基金组织、欧洲央行、经合组织和宜家等主要客户设计和实施过人工智能和软件解决方案。
如果你有兴趣阅读更多关于机器学习、深度学习、数据科学和数据运算的帖子,请关注我的 Medium 、 LinkedIn 或 Twitter 上的 @james2pl 。此外,请访问我的网站上的资源页面,这里有很多好书和顶级课程,开始构建您自己的数据科学课程吧!
具有外部环境配置的应用程序的 Kubernetes 模式
实践教程
通过使用 git-sync、Kubernetes init-containers、配置映射和卷,将配置生命周期与应用程序生命周期分离
将配置生命周期与应用程序生命周期分离。(图片由作者提供)
每个应用程序都需要配置,我们需要在不重新创建应用程序工件或映像的情况下灵活地适应这种配置。这构成了连续交付方法的模式。
问题
在一个容器化的世界中,我们如何让应用适应不同的开发、试运行、沙盒和生产环境?答案是使用外部配置数据,这对于每个环境都是不同的。
通常,最好将所有配置数据保存在一个地方,而不是分散在不同的资源定义文件中。例如,一个这样的地方可以是具有以下两个主要优点的 Git 存储库:
- 您可以免费获得版本控制配置数据和审计。
- 所有工程师都有权限更改不同环境的配置,包括生产环境
坏处呢?您已经弄清楚了:围绕敏感配置数据的安全问题。在那里保存任何凭证是一种反模式,因此一个想法是使用占位符。
解决办法
Kubernetes 为常规和机密数据提供本地配置资源。这些是分别用于通用目的和敏感数据的配置图和秘密对象。我们可以以同样的方式使用这两者,因为它们都提供了键值对的存储和管理。除了实际的数据编码(对于机密来说是 Base64)之外,配置映射和机密的使用在技术上没有区别。
简单地说,我们问题的解决方案在于在应用程序启动之前使用 Git 存储库。占位符被替换为来自 Secrets 的值,Secrets 可以通过 Terraform 或任何用于 Kubernetes 的 GitOps 连续交付工具创建。
让我们来看一个例子:
假设您有一个 Git 存储库,其中包含为每个环境分组的文件,工程师可以在其中更改任何内容,安全凭证是不可见的,而是用占位符替换。
database . properties就是这样一个既有简单配置数据又有凭证的文件
connectionHost=${mysql_hostname}
connectionUserName=${mysql_username}
connectionPassword=${mysql_password}
connectionPort=3306connectionPool.maxIdle=90
connectionPool.maxActive=100
connectionPool.maxWait=20000
connectionPool.testSQL=SELECT 1
我们上面提到了用于替换占位符的秘密。一旦创建了秘密并保存了数据,我们就可以使用秘密的密钥作为映射到 Pod 中装载的卷的文件。一个秘密备份的卷包含与条目一样多的文件,映射的关键字作为文件名,映射的值作为文件内容。
当通过 Kubernetes API 更新密码时,安装的密码卷中的文件也会更新。因此,如果应用程序支持配置文件的热重新加载,它可以立即从这样的更新中受益。在我们的例子中,我们保持这个例子简单,我们将考虑一次性配置加载,而不是热重新加载。
输入-占位符-文件-秘密 内容:
apiVersion: v1data:input-placeholders.properties: bXlzcWxfaG9zdG5hbWU9bG9jYWxob3N0Cm15c3FsX3VzZXJuYW1lPXJvb3QKbXlzcWxfcGFzc3dvcmQ9cGFzc3dvcmQ=kind: Secretmetadata:creationTimestamp: "2020-09-27T10:04:01Z"name: input-placeholders-files-secretnamespace: my-main-applicationresourceVersion: "45565287"selfLink: /api/v1/namespaces/my-main-application/secrets/input-placeholders-files-secretuid: 818229c3-b986-44a9-a8a5-e235557f98a7type: Opaque
现在我们有了秘密和属性项目,让我们把它们粘在一起。
**Kubernetes 有另一个资源: **init 容器。它通过为与初始化相关的任务提供独立的生命周期来分离关注点,与主应用程序容器不同。这允许保持容器的单一目的,并且应用程序容器可以由只关注应用程序逻辑的工程师创建。通常,init 容器应该很小,运行迅速,并成功完成。
Kubernetes 中的 Init 容器是 Pod 定义的一部分,它们按顺序一个接一个地执行,在应用程序容器启动之前,所有这些容器都必须成功终止。从这个意义上说,init 容器就像 Java 类中帮助对象初始化的构造函数指令。
除了 Kubernetes 中的 init 容器和秘密之外,Pod 中的卷共享非常适合这种配置和应用程序容器的链接。容器可以共享(外部)卷,但是它们还不能直接共享位于容器内的目录。
在我们的示例中,我们使用了一个init 容器(properties-sync),它提供了 Git 客户端功能,其唯一目的是克隆一个 Git 存储库。在 Pod 上安装一个空目录,并在 git-sync 的帮助下将 Git 存储库克隆到其中:****
- 一个简单的命令将 Git 存储库放入本地目录。
- 可以一次或定期从分支的头、git 标签或特定的 git 散列中提取。
- 可以通过认证或不认证的 HTTP 或 SSH。
另一个init 容器( 属性-占位符-替换)用于占位符替换使用包含克隆项目的共享卷,并将最终结果移动到主应用程序容器使用这些文件的新文件夹中。
然而,对于属性-占位符-替换 init 容器,我们需要一些来自基本映像的帮助来将配置数据复制到共享 Pod 卷。 busybox 是一个不错的选择,它仍然很小,但是允许我们使用普通的 Unix cp 命令来完成这个任务。**
因为两个 init 容器都是同一个 Pod 的一部分,所以它们可以访问同一个卷来共享数据。我们使用相同的机制将克隆的文件从 init 容器共享到主应用程序容器。
替换-占位符-后缀-挂钩 ConfigMap 是用于占位符替换的实际脚本
**kind: ConfigMap
apiVersion: v1
metadata:
name: "replace-placeholders-poststart-hook"
labels:
app: "my-main-application"
data:
replace-placeholders.sh: |
replace() {
local placeholders_input_files_location=$1
local files_to_update_location=$2
local input_file=merged-secret-files.properties
rm $input_file
echo "--- Starting to merge all the secret files."
for properties_file in $placeholders_input_files_location/*.properties; do
(cat "${properties_file}"; echo) >> $input_file;
done
echo "--- Finished to merge all the secret files."
if [ -f "$input_file" ]
then
echo "--- $input_file will be used to replace the placeholders."
while IFS='=' read -r placeholder_key placeholder_value
do
local placeholder_prefix='${'
local placeholder_suffix='}'
local placeholder_to_replace="${placeholder_prefix}${placeholder_key}${placeholder_suffix}"
find $files_to_update_location -type f -exec sed -i "s+${placeholder_to_replace}+${placeholder_value}+g" {} \;
done < "$input_file"
echo "--- Copy properties files to correct location /properties"
cp -R $files_to_update_location/* /properties
else
echo "--- No input file found to replace the placeholders: $input_file."
fi
}
replace "$INPUT_PLACEHOLDERS" "$GIT_SYNC_ROOT/sync/environments/$ENVIRONMENT_TYPE"**
在主应用程序的以下部署中,它作为卷被引用和装载:
**apiVersion: apps/v1
kind: Deployment
metadata:
name: my-main-application
spec:
replicas: 1
strategy:
type: RollingUpdate
selector:
matchLabels:
app: my-main-application
template:
metadata:
labels:
app: my-main-application
spec:
imagePullSecrets:
- name: gitlab-registry
initContainers:
- name: properties-sync
image: "jlowin/git-sync"
imagePullPolicy: Always
volumeMounts:
- name: gitconfig-project
mountPath: /opt/properties_from_git
env:
- name: GIT_SYNC_REPO
value: "https://gitlab.com/my-domain/properties-project.git"
- name: GIT_SYNC_BRANCH
value: "master"
- name: GIT_SYNC_WAIT
value: "30"
- name: GIT_SYNC_USERNAME
value: "<some-username>"
- name: GIT_SYNC_PASSWORD
value: "<some-password>"
- name: GIT_SYNC_ROOT
value: /opt/properties_from_git
- name: GIT_SYNC_DEST
value: sync
- name: GIT_SYNC_ONE_TIME
value: "true"
- name: properties-placeholders-replacement
image: busybox
env:
- name: ENVIRONMENT_TYPE
value: "development"
- name: INPUT_PLACEHOLDERS
value: /opt/placeholders_from_secrets
- name: GIT_SYNC_ROOT
value: /opt/properties_from_git
volumeMounts:
- name: input-placeholders-files
mountPath: /opt/placeholders_from_secrets/input-placeholders.properties
subPath: input-placeholders.properties
- name: replace-placeholders-script-volume
mountPath: /opt/replace-placeholders.sh
subPath: replace-placeholders.sh
- name: gitconfig-project
mountPath: /opt/properties_from_git
- name: properties
mountPath: /properties
command: ['/bin/sh', '-c', '/opt/replace-placeholders.sh; echo finished;']
containers:
- name: my-main-application
image: "registry.gitlab.com/my-domain/my-main-application-image-tag:v1"
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 8080
protocol: TCP
volumeMounts:
- name: properties
mountPath: /properties
volumes:
- name: input-placeholders-files
secret:
secretName: input-placeholders-files-secret
- name: gitconfig-project
emptyDir: {}
- name: properties
emptyDir: {}
- name: replace-placeholders-script-volume
configMap:
defaultMode: 0755
name: "replace-placeholders-poststart-hook"**
部署的 Pod 模板规范包含以下内容:
- 输入-占位符-文件-包含秘密存储的*输入-占位符.属性*
- **gitconfig-project —类型为 emptyDir,它在托管此 Pod 的节点上创建为一个空目录;这里克隆了 Git 项目。
- 属性 —配置数据的最终目的地,占位符替换为 Secret 中的值,由主应用程序容器使用
- replace-placeholders-script-volume—包含用于替换 Git 项目中占位符的脚本,从 config mapreplace-placeholders-poststart-hook挂载
正如您所注意到的,部署包含两个 init 容器属性-同步和属性-占位符-替换 和主应用程序容器my-main-application。****
属性-同步:
- 在启动时被调用,并从映像jlowin/git-sync构建。
- GIT_SYNC_ONE_TIME 告诉它只同步一次,这只是为了保持示例的简单,并且不使用 sidecar。
- 从 gitconfig-project 挂载的 GIT_SYNC_ROOT 是 GIT 文件的目标文件夹。
- 与下一个 init 容器共享 gitconfig-project 卷。
属性-占位符-替换:
- 在 properties-sync 之后立即启动,并安装上述 4 个卷:输入-占位符-文件、git config-项目、属性、替换-占位符-脚本-卷
- 最后是运行从 config mapreplace-placeholders-post start-hook挂载的/opt/replace-placeholders . sh脚本****
我的主应用:
- 正在挂载卷属性以访问由属性-占位符-替换初始化容器复制的配置。****
使用这种模式,我们不仅可以使用版本化的配置数据,还可以克服存储在环境变量、配置映射或机密中的配置数据的大小限制。Kubernetes 配置资源有其局限性:由于 Secrets/ConfigMaps 的大小限制为 1 MB,它们不能存储任意大的数据,并且不太适合所有的配置应用程序数据。真实世界的 Kubernetes 集群还对每个名称空间或项目可以使用的 ConfigMap 的数量设置了单独的配额,因此 config map 并不是一个金锤。
我希望您喜欢阅读本分步指南,并理解如何使用不同的 Kubernetes 对象来定义配置模式,以便使应用程序适应云上不同的配置需求。