From 287cba34b52f0ba5768689e823250f30c7e2c320 Mon Sep 17 00:00:00 2001 From: sushantdivate Date: Wed, 21 Aug 2019 16:18:26 -0700 Subject: [PATCH 01/18] added image creation script for web app --- ml_service/util/create_scoring_image.py | 62 +++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 ml_service/util/create_scoring_image.py diff --git a/ml_service/util/create_scoring_image.py b/ml_service/util/create_scoring_image.py new file mode 100644 index 00000000..76d0641a --- /dev/null +++ b/ml_service/util/create_scoring_image.py @@ -0,0 +1,62 @@ +import os +from azureml.core import Workspace +from azureml.core.image import ContainerImage, Image +from azureml.core.model import Model +from dotenv import load_dotenv +from azureml.core.authentication import ServicePrincipalAuthentication + +load_dotenv() + +TENANT_ID = os.environ.get('TENANT_ID') +APP_ID = os.environ.get('APP_ID') +APP_SECRET = os.environ.get('APP_SECRET') +WORKSPACE_NAME = os.environ.get('WORKSPACE_NAME') +SUBSCRIPTION_ID = os.environ.get('SUBSCRIPTION_ID') +RESOURCE_GROUP = os.environ.get('RESOURCE_GROUP') +MODEL_NAME = os.environ.get('MODEL_NAME') +MODEL_VERSION = os.environ.get('MODEL_VERSION') +IMAGE_NAME = os.environ.get('IMAGE_NAME') + + +SP_AUTH = ServicePrincipalAuthentication( + tenant_id=TENANT_ID, + service_principal_id=APP_ID, + service_principal_password=APP_SECRET) + +ws = Workspace.get( + WORKSPACE_NAME, + SP_AUTH, + SUBSCRIPTION_ID, + RESOURCE_GROUP +) + + +model = Model(ws, name=MODEL_NAME, version=MODEL_VERSION) +os.chdir("./code/scoring") + +image_config = ContainerImage.image_configuration( + execution_script="score.py", + runtime="python", + conda_file="conda_dependencies.yml", + description="Image with ridge regression model", + tags={"area": "diabetes", "type": "regression"}, +) + +image = Image.create( + name=IMAGE_NAME, models=[model], image_config=image_config, workspace=ws +) + +image.wait_for_creation(show_output=True) + +if image.creation_state != "Succeeded": + raise Exception("Image creation status: {image.creation_state}") + +print( + "{}(v.{} [{}]) stored at {} with build log {}".format( + image.name, + image.version, + image.creation_state, + image.image_location, + image.image_build_log_uri, + ) +) From 9f0ba63214ca0795e3631815ef115a7827bc9552 Mon Sep 17 00:00:00 2001 From: sushantdivate Date: Wed, 21 Aug 2019 16:30:14 -0700 Subject: [PATCH 02/18] added model version as variable --- .env.example | 1 + 1 file changed, 1 insertion(+) diff --git a/.env.example b/.env.example index 90e25cec..a4a87bca 100644 --- a/.env.example +++ b/.env.example @@ -22,6 +22,7 @@ AML_CLUSTER_MIN_NODES = '' AML_CLUSTER_PRIORITY = 'lowpriority' # Training Config MODEL_NAME = '' +MODEL_VERSION = '' # AML Pipeline Config TRAINING_PIPELINE_NAME = '' PIPELINE_CONDA_PATH = 'aml_config/conda_dependencies.yml' From 1c31f15f211b58202e690e491a5473d0f41aab66 Mon Sep 17 00:00:00 2001 From: sushantdivate Date: Wed, 21 Aug 2019 16:59:54 -0700 Subject: [PATCH 03/18] images for webapp release --- docs/images/release-task-createimage.PNG | Bin 0 -> 26794 bytes docs/images/release-task-webappdeploy.PNG | Bin 0 -> 33428 bytes docs/images/release-webapp-pipeline.PNG | Bin 0 -> 10362 bytes 3 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/images/release-task-createimage.PNG create mode 100644 docs/images/release-task-webappdeploy.PNG create mode 100644 docs/images/release-webapp-pipeline.PNG diff --git a/docs/images/release-task-createimage.PNG b/docs/images/release-task-createimage.PNG new file mode 100644 index 0000000000000000000000000000000000000000..e24ab5ce0c6aef3a156ad710c6397726f3905f3a GIT binary patch literal 26794 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 literal 0 HcmV?d00001 diff --git a/docs/images/release-task-webappdeploy.PNG b/docs/images/release-task-webappdeploy.PNG new file mode 100644 index 0000000000000000000000000000000000000000..0f23c08de903ee3fd8fc1688b3d857c05481a56d GIT binary patch literal 33428 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

O|)2aJv46Gi;9@fCD*b!M8AIA^I4T82#EY zQDcx`@^a76N=)$bYVKMGsT!}MR zs$%2RrouMg2N;u&nkz|kr79>~ZNNVZ)Efd(ImuZHA~2`?*FPP+Y!@@Q?ZfxR|KjF> z4`F})IGXD`zAe>tKskVLE0f7P!wn0GQZv4irg%dl&fd!;BNm_Ug@-JsSN4_DHc=_= z+d31-ZSB0~Na?`X2I|BITk^3Fe41D8aEJ~|bz{(-Np`z760TU+OiPza;nM@SK|c;Q z`z}@Z7AtOed38Mml=PUEQsz()Ag6MZ+dNxy#jvV*k(a6})G}F=p-b0y+Y2MRmJ}~< z(%r)t1CbK1)%UPL2p8X}?U1UIpOK?P0sLG7>45Fg)JaMH9|GkbR*F zAn3Gp?|T|&hT3nm>#NyqX+{(J(_Vf&AA*&RVL!HTn#J@B!E{6}B1|o8>E`qIMCmh` z!4^7ftE7>-+(o744|R+?xdobsE(;G$i5Kn5+h-1jyW*h{c{5kA%zbKZxp9_84BbeD zU2eHoJ}$kx<6TekTdnPJnG`3Q7Z7u+7Lgnf`@U}~(kZ;^SwJ#?s!aaZqJQtG~EkHWCi<wO5rr!M zZijoq=p#F-e)Z)g{=3a<5!B0%Yhcw5oSDvdE)PnQWJ<=G$4-}7`a}hD2rvO8!$Gr% zW>$H-%wMk6au-#mW2wXIqU&8&9e36%-*h%id>%nEzpF=5CN8CsjakHq}w3-f{DN~PhsEGFUO3$5kBNqPJX@*$zNE^Pt| z@$6wRe>cJItiAwnS(EkX1iI|2KkRH-VJ|b`^k`Ghh?k$vy+@i_)&mhLvA~a7h%T@m zOKFccoqTqr*EriKBG@M8VVrbf=ic4qnS)3tSJGVcTX%B(7mFtc_yhE}8KU-VYTjb? zk*sL(Sm|4LYGhk-{Q=_XpYbk4N{2R=Zd=Cr?P<^*7A?^$Hh6G!!=Ud2()<{gm4ur? zPTa{Q8Hk*!B0G) z`aPa=9e1aFN!6g~D>S_1-Qt9J6dMXBCOHG*$VXaW^icm`Wf|C*cU0pc8vREq3Vum>E+BuolVMk|sV9us>lJ9ShhS%Y-JmrFXX=y7 z8)b*Vd$S{O2H&~aPec02bJfb+@x&MgZI3z1Cgxq8Iep^Vt)C{KR_8w1b44t1;}WnGZDmOZ-K9NWLu2q?W@Hx>_}c!4fP3< zG)~PGI`e31sgrTWkN^~^S6`@Vr)(dkP-cUJx)a?dc+M@I2K6{DIz9uDLH?XI6swLQ zg&i;+1Q*`?<=Bax`B|~BET0%q3FqFvZlY=tQC>K_|LKb~>J|{P54(XXl2&SEeS5&- z&N=A@R=a%_QV?6UP+U~<8v-aO{{cBV<;RYx!8g&C25D|P54H}JZl@+Po4}|gOn*@M z$P`~1!ie1u+a0?Ger0}LCVY{VUWp;?)`Smk>Cb#3$(5{U$>hEBwl{_x+@&;2uN~oM zzcqJNDUR6@Zx;5e%-l5DqD^>6b=OL!j{FH+np`0qG_C)_N?Pwl zuj*MLQw*PwIrR93l(`aYx2V zx&p1nqf5dKUEhOz-v;^J>(2&quGLQ81(P%!`pTYanqFpF?+f%AYkdCp4YdfJx@*TE zFM~X2e>q>{`<&Ya9S06Wl+ivJ-Hdn8_DcWO)QO(_IHh>2iC~>}lb9-nV)xoTw|H+p zWU9>q2>`oCK;0`lD(=0EK>f=t!U`QPAo-l{>Br5aKz?wmzsnepLl0->PFn3mHG z3%DwLI9D6pKMpn<*Fk^ZS;vX+-ltKG&F<-7cuREF+Z_wEfuj1(+?Tqw*p4=`bUI&4 zI53D384ea(R@XYZ=D$aSBDOTu(wT`n8VU|5n7>g1O$xEncd2!x`SpF(sNm$G%npK_ z*AwTgG}*Dwa9+r~WLfn=u5*#?1eW{iAs5_oX10?iVeCni{2rn|sLM?!&^FElQosImh`U<4D!6IMvdl|R z-eXmT91iJmE<4yeSR+3a;h!4?BJ-C&te^D~nYsLYFDHt^KUMzq770Ye*3-VhX{x+T zr4xuJ7$ZbwJwY=|IvpPvpE)?E_EB-|x-&u0tecC+4{Ql8x$o2W?yFiRCL?d89arKW znFzAghG01-+kRrL46hO(V z5hVs7pWxL+!&NK!@2IjE9+qTu7&NY}4veI!rM=v?j&+ zqW5dWBZe=(p-7EUpXv#jh*R;y5Nu=*AoMrWttH}ZuGM;mPy0F;3YEU-R~`9Gg7(6- z_xV)6d85$+nnX3Vz`cCIh@XzVwoy}6$c1=Zuj&uJ+v*#URZ?118IV7ATc_6>IcRntNAW98KZs*0eSbb2vN4w zp6z+p)co1FEBh!lGC5kkSuk%_5ay&mZ`Ew4h^VP0wgVK5IDUSs|0-3htIO}$}D!pZ=<6cX^XG}WdJpIF49vq6<*1>?{zfeQ1e2e++wHDsaO6gIf`~vVmD9kEZ!*sbBcXCaXAL$sJE^9|6ryM z#-5LRpK(9y7Ya|AZ~-{|(Af+}v=}Ens)e$XuMMeR#XL4 zRO$PSSWiNq@eLS6h02F9HiOJ6k)GNe0wSQOk&Qb=o+fIUQNc3Zc5mGdLC$&Bvt%-{ zHzN53#Bk`Bl;W;0A~PeWR4sjCVrG|g4Pr>qpa{G&2;CsNu3H++p|G0T|4R?f0Jm2X1G>Xyg& zl@Bd1pZPqc?JlmJP>x>ST|>?|OCBI-PSlN11cLX%Kz_RHUUR1-QCZg62udZ2$k7h# zMw1^wUIsiqceMI+*O}0^IG8t;h)4<^Xkbzxj7i2+w4KnJoU8>u4K)3i27J3wsBj$n z;oOV8J(?!=>_?5cn{h2OufUx`)2rugt}z*CJ;Rog?sq822@d)pIK(L9%s0iA)0);G zx0sjMH?`3A1;=j-E|FgQ#hdQKR@<$+orY@(`B;4&yekiPa#xny49#C6d z8)G^WTnGHEoXW4vITciA;&gO!L=CIy^lZRS6U&b_4X_T1K5P2|K}0v#L1bRVZ(@w> z_VH|y`muYGF$iU$zhf1Y$9cT%^t3E?LeK;p2r+RwwovdolJcaPTNPVFita$MaV;kq zdIfyLLFhifUWqI23?A)olM5}M_In^OjDYh;7MmAp7{>QBNZ~3PKR>AwM?__YalhmF zrn7QEyw}|O(%sAH_dq#>keJhsX6jE z^B9uh_P`canr58d%(RUYIRqq91N}FD`TApKlSEaoXZ<+C+_&*|G|`3%@x6SlW$Nq% z$`a1luq-8*4EVYCV66J-c_`~=7~A_jVz2u7gLAB~Dn>lRcG-Lu|wXgl>W2m>*I=Rw?m!{uJ zrFyfh_Ozflqe8x2;i?z5rpt!;qIAncL_$kEL>$M{hKun&*exg|C-iFOgUO^+6XcEu zfBmf)6YSE-(t`p51-hqBv{=yQtc#5qYn*|j#u>N!L5)AE+R0b%FCGZlt=1ejR|?Od zpmLm-JGElff~D|YOzLjlB=!{EN=j9D*DqWM{3 zDeEPRa{kyV?6THzd4!mW7N5=iCJ}C?*a+)nIGBp+7uQ&_pFR`y9cPHLWHu|X<7|Y9 z(D`wN$Nw@#RjpF@K0j=yyq4WqvznK|d~7kOViNa~Vc+Z%52zR=QgBQRe=W6kZIx1v z0L&<{IA%D2EqJgnHdkGH9f%N1=D!T+wt#t+M*v|Uxy<7Sb2O}$nG{iMpi@R019qWE z1{4>gfx)yT|Gi7n?lDTDGuF#NxjPcCnx~*+1yaLWP~NK6Vh94M!z zjjrZ#6iuQI7)LIpP73V)W)n1SuXWhwRDIM$r{WeYYD_ZCv(=6z&uOIXsDR2uVV~4r z#y;hrLrx*f4&qa}=S*eHQyfcPZ&w;B?SLwxk|>pEy6k)Qm}crK5p{iHvv)7-XP7qr`RH%fHHQ`kEW9Zn~~7q-XHECMlIpRyh-anKXt>+7x8AW1n^j?^Y{96UbB ztg}CRVB>e>2-g?Z-_aiLGAHJ^bGlmU=FjcdbA#f96ru0E?kWgViuq8sgqf)Y-b8jF$)=E zZWU(n;^nK=qs)@?kAH@~|Bs>0cx`WwhC<8x5HCV%{Vh{TNwIHFS^a+?SJyo&-G_ht zOmm48Z89%xt}n2pJWoY=G&#aF*FWLUhrMtIv7j}PPGa73Q5}yJi*~Ce??c8 z{^W4H=$-dUn}B5Z>+yIpgTkZ@zwI!3LVssrl55U;Em^gyQ<5 zqbUV=>9yPR38tJua%#hVqQ*f660%0CAusigeUUSgICfEQsW-;>s#G7 z&&$eEM+vOsmFsS!l_?2nhBxd^J~mv*D6W;k4NtN;IpRtTnR8_-`-SQZIqWI-8mr&s z>^pFbwwIR*158J++K^xEyVus6J7#)?IR+mUEJ4TFh{Tw@N)Th282bA=t)YJKRe3`m zlVK5fiSi>06~Uz+BBG+izB->{d{H*v#G%f6zb1cBB%EjWi%jIw?Fi7f$mf+D*q<_v zIcFYQe)Rv~W1GXA>lx30Jvr|EAJY5xxqX8!1*QBVM)1rpH?kLHC4Bv&XJKP~-(7R} zc4du$bcM!llkb{!U*Kd(@*?3uQ+;-R+{VOJ>$!M0a|yu}Hre{GJg&_(GPwDDJJw-d zxU4w7gAlfwqwbtTj??UoTY10d2-9QpY{^9pGZ9dv&vW5 zMT3d>0o{AQ5hCH+fHsKl)_F0;(`KG~RxUj=M;p-BgY>k$UF)ycH!WkaCOPAC{BAmg z=E4>;6-xyu8%!&if5NWu8qB*Qx9iS)Q>u^|gguqAE$1@Tgi}zNOVorQ=Ifr$gi!w; zEN@RCEMs!3R`~W=nEb`Dy3qAo&tO8o^5f`}-O>72;rA_H>HMYMvNu?ea+98smS=pL zm$s;sH5aTdIp)%)Z{T0N>$PEgm*6g=IL&&8-d-J@N$@8BJ5_@#p>^b7Ty!oxR@ ziK4YbeoksfH$1)m@=SX4W^sqvbu0ZuyAS-IixYKc-RAm#{sFdH2lS?&T>pkHb|`;G z4Y<^8(ImTGQ;ve885hB~$tI*6G+EZ&tH9q4dMfF7ZOE4367w z!}{1j@j#KA#Z`KiDyCM_FPQ^m3|y|mMQ=hAfs%2l;>VVkB;JaNDHf2!mrk^YAc7%K zHfR7}dnG9buLYX1&)PxgV)W73%5h$I>|7r7R6fwSKJdR~kN=){;#T_@+#09<41YWCyfoeD5%ask zDH$d7XE?V;@4eTn=UGoV<^TUQG0- z8dDIK<`vn*4evE3tU64vuO7E9CL9BPAF&=x#b zK|%ALApZh!XJR(WV+xI_O}^NSSx>N^POnmKgRBs^HjFJrFQ)ooBiESnaGuf{GD)vD z&OGDHX<2+-U9Rhonv8T=N^xRj{Z7K4aFXDcf$LeeefqU4i>u2)qm47DXg z8U&J~>|xC}z~XQ>ZA4Vwn8_cF#Tzz|gisY1J~5KoD_T~{V>gAh1vV03SbQ1kkBxpFjXo1Fhi3ZrWzQUD87Kg+#bU1xGY z%nRzlq2do8ptG@lAT^5jcQGI&F&#D097u2u4HlrWA|9E%lLs>QZ)m2GFLX!e zNpC^D^6VxmI`RTCAH2aKN zty}X-zi}b+r2f|9xP6o5 zL6^;^V-2?pR<((z3mOcW;yLU)Im?rfc4{I10;&^LzeDmz{A5Y^ZoYnp-qJgi!=lkp z*laJFNSL9g#N^#4Wd_yCB`+2GAk3gfa2>D=rR9$Q6Ir6=n$z1Sya&#b%%dbLV1*n1Fo zK#O8lkJSIhmVfVE;a^CZs|7yu8@b;up{<8$1Y|Q4#hHMfd~#TfS)RW5lw0LD?7w9D zf6-8?I2??I;Cu_OQKDIl;&gFq@3^q(M#lnRyj5+dGBf@Xa9Ob~L9; zCY~*TRL&K3M{QFQl#brX42sEfLo<$xFoj&s%#hwdN(Sq=Gd3SYTqfWl!KVo0=p_m& zQW@@ON-)c?ejS>FB4#~5Y~Scxq2!$+t?FDgRM8D<+-vvXDpVX2fwQK`SAp4Z;0n@F zuj$7r2UH|saIU2+bWw4T*jA~!HFFmB*lKa(!MfW#_S%Gx@9o(_OvY0|MU_U-G5N&S zK%k&jB2)3Uer^tS%0GAl{fj%uWDoZx*F3L*9L5|U41cfu%WF*vMLz=7y>y^W*|W*r z4#f!s?5_#oC;5Z3q#gP(t;opMh*os1-f((;XUfKRfo|*p0$&=n_r)$!`3*&RtL$(z$cb zpWyHitdz$TGyQHbA?5*YzF>bmc!+OF8f^y{TTs;A;Tl7KyOZPm#F>I z?p*kGRb0fjLCd{MBn0@A-@A}-Ipek>#SYwEd(ND5Y^`VKecKa=`uJZkOPugCT{VLi z_Z;`XDrnv`{{D0*2p@}Q$ZCN+CEt!ew?{!AW2vF|vCg%pEd{|);4=~9X8orxT+0Jn{M8&YlW*PjHS)5tybQt&Rzyy zVWAG?bOc4OmPB1njm13=N?z2MUv~SmmlufWu!!!cH>>e; zIDAHX@!=-QG*}T$$#_z&Jx}R#s3~oG`7B0zC|V=s$jQElLJ_F09=bm0O?ybF?c!uc0z*==LobqdsFy zS#{4qItT!=+D3%ZiKv)%`V)Fdrbkj#ZfDaC)M|vOf?+m+b46bdaYAfa-&wEL8;D ziOMso1uZ`sB%Vtlz41rIuEM53x%;jJ-Ed>ft%eP0@$k2!nFeH1huXkAqQ=PXoA?#tT7;jt30b(-`7ZpU z6(^L)|9qY}vugwcQ?9i1InEM{9PZAg2Nv!Qd`PA;b$R+vU`|UkuF{NP7R;07(Ut=^ zUC?X0^V~`cT(hyFpXE4vQJmEculT{1oUGG4FE;r%mmMr)Fg54{e9mR>iPQdSx=stL zOV$njUCQ-sqjK=Nt`?}>4=|G!D@;V4^LkFzB(ubmb51`LY`6I^_F+eUZa7x$rHAl$ zmyKDAM4$7&V*rCJX9hg&_w%UL@kAGI27Z&2m!_=j5b8P@ZBJIhpf49P?J@lAw}ET? z|AY;XPyH)wfb;%t;jXh*|Gk<9+a(s^F(Kyt|BVK``0xDb$B_RFtXa|2zm-S*S8ViO zQ?UIr+8gn7G1yRq3Prf10ok!TOeBC*o?Fn%=UShLhN0W?mFkfS(rZY`Q#xK!tN<-D zm3egam~-QaZY{LY9INsE4g2V=l`uxde$&wMcF9^I5tcVf?24P3GDb=w-5q-jza-Zd zDOg&K^*==$o)c_sN1~s7<~p34;92K*Vb(jKy%8DEz}T8GqyWQ)`mu^3%Q5?|V4SgV zXb>1-0cyLbG*f*@tITVz&Y-6Nz06Io2GVep1H<|dOV4<+wy$$BKUL0c{}ZYJjAUQd zs4Lv^I5+`ds7l|j7JjWV-?|QAH=7m)cJ;;N(RWi^1A2}XHY+hT8arU14JLg>V7_4D zD(OBzc$mS8*uzEC<}@w|{vrLV_n7Zh;$d!2H8R6{@Nb`Lz>X3QwDcKI%`QSHT(g-W0%xCxFY z_(J@?Cn15BXBUEzd)90pY`AyeHv;853 z7RrLLeLHuiyE|uk-U|iV%0utl1xOMyq=XY4XDm8Zyr#z&(3UI7F;4l#Xyy3CZYa2M zW(_;?X=@KShGZ1P& zY*hP*?p&(38h7-*oGI6d)FuhK28;))I%UMi-t9g+x1p@ir(H&Q<@^y?P!Ux*r%U#4 zcWWUOFO|-+*H54Gzo=V}29r}6bhwd97ikLv_ zh|g@(`VsDt*44gKptd;rDA4;;i|iKrOy?eLCn0}^N)v#5_uZ{}$QHKxOMtM_3D>7@ z4R4p_6f?I=VX4Og#d7vBSHy_Y7<#)oG&5?lI`lJ@8AK2(YsTqwDzh!^!^xuiHSq;7hT@{+&Sau`k=eN0Wjg*Cv9{dul;?rgj5O>tTS?KJvwzk zNslI31rl74cFc?Sk+Yl0_qlkp6dxIg_kOvlG>{~_1B(p9Xb}Ol>gev0hW3T-xoX}C z$mQ4fM`QtOzs$0&EFi0zwjHHzmw`h0rN6ib>h|}NQC2!dA$gG72d#x4L0h4Ld(C_e zZXdQ)S5_K*df1MHlbN~HXIqD}iY@2B2TMbC-$|=Mp?3O^tNxD{Ye}79aLmjSR?__0 z@^k?_MS9y+@dF|pf?Ac&e>cDmRLSaPmuTf~%3W0{?j0Afs)17@w`?lg@1 zKYp4mY>cw*Ugt0bd~ymMWp7>A67mex^G~`yAv^!AEc&O9$mIGqMF-#sp1$vx(^NBm zi0rv}u_xVeFhdrhOQ^Jw`9THg3rB@#+6b(GF_Q1ZGH7Zy_4jqXlqaJwp~ z=6FcYp-W=lkrvVq!?75*5T`UJTgk3N-JCk3$)+2LJ-4U979kA%1<}Rr_1g{RZ%Xl> z&aDK_1RN>DTaXtKchBEy8QobY391Ci=ZJ3L`W&&wB=NBOvDoQt#c_;&K*nahLv0{e z7y;etHMqD4%oV|F7vZ%`+djwL9v0~0B|4e&I1|o-<6y17BAPWJJ*qFK6=EIB%$lcu zJ^8WZl%E{086T$^Jlofycd?b8z?A!|qr)GC4Gs~Z`;Lu4cT@0BIv3=IC*_UTykAcE z&QCV1A!ABq6PE!AIa~|Eji4|9#!XbvufYGnpSlaGr&D_pbw)66Jvn>g6MH7yrrEDo z?^wyOm8!{sE}_#^EmFI+Pp`CYYboLIK6ysLT~uDE@{!Z+(Rm?1G&**Td~F!?bkJlE za_g$%;vm2)tHzrBOhsvgVGkBrDHPqJ%ytqlI4OK6~FBZ!J(>IG{t37>v<$$?N zu&f3Qb7Gbw)nrdi-qD%*=IRMKi>NFfF?5yBeK(sq4poSIJnf~4Sf_g@H#&vZGL2jX zA0Yq3zd&~x&@8rYH8C_YS+bpse-idn&T+S@lqfrGD=j$ZvrvWizY#EHZ}_-_Y%!g& z|5H{_$4xD@37CZ$Q`EF=a=Tna&Fuyj_{ZVvAoCXunNtw}b;0 zBb6e2e1w5g9kn;_#CE*j`uV(se*H2C4-W|5UZ~EN9y5_nAvv^HE$l17kR%92Dk9d`Q`L*}~;AzE-8ugh4pDZR}oSjZMoz-^~=Y zj$43;wJtkHQ1QOgPq3=Zs}xJ~`^(L_tGsplUs8N-?i5; z2+pgnGBx8@=4#>!ON#5v7R8<_O{9KOY&Ka~`k;qOuE82UOh$~q65Lk8?-e`8pq0tU z>Ykw*P*;<^asrGV9sWmROL5%ai5b^_-T8LNe>L7vb>fx{^<%tI&y&XxdAD}FZ>#{? zzqMOvs6;`(2P_Ag1~esnOtcA}Qq}FQMeoHSH66RJQ+Hi^YCg_Q4+@TdYG7a!7zhGo zbO8qjLbVr0ov}wn3KfTG_PY_?TlFqoQuKT^tLNv2RyI@vW)HTsdof-@<(*3%+1jFN z!8`h44Xzzesls8uBKMcJgNNTJFRqLfzYEEdyK!fU!|%R2{O{EB(Ze@ZrFS{{26|S) zSGT;w%CKBAn#_2ciu!~4wF*$nsJQZ-19B~}-MqsQxUt(e+c|P4nL+lX59Uj|lMee% zsXZE2C%+e~@5ltvWFuFZ33}ciIje{-u4{om*?rBxs^TU*w}h#LG>OI7w+w2^4!u== zE2m}Ns-m|Qu~oon?a!^U+G_w>7EJu2%{I*Z-X!tfYB;48{_0>5syi~$3v|tSo3A5T zB{szwdgtsggrC(vPI`G<`H4PlVB+OJOA?D9Em#TRkBF@bM4*@LwARMYDlrPsAA!Fk zH&g?J>gL=V%(b(|yvW39Z2$)+Ypkff=pE%vy}2yFa*e9Lp$cp~RHOMUHK8qxI(Bw@FfT+f z)`9URf69Wf-A0F}1zuhtTCk$|NF$~#&*cM0DBiOG368nD%f~Nn>0clkaV}w`gy8gh zDv0%uzl`Q?*)2Pq5FUBEdu*vwxbt}&$bfZe<$_XsG>%W|@z%EMT-g#a4WdJMl>n#< z+l(MC2R_?S3Pgt(FF+G}^2_LlLk=~e7d5w*d#ZCN`n@xZYGP90cJbP;uw&orkxdxP z*#3_03}0#!#$tw?Fm0>9yzW`iNP*g+Ud}=raZPs}C$OGG2MEM0N2N`^z21!|m-STn z!@X{QsM!WHtNdcAL~)ombcTMXJ4`v)Oy$ynT;zeE=tGIlAW73zbg>QMXQb533&s_$ zAg8;0zUp%`W4rz@y&ZUu0h|5D*+y_dZcg7c}U zhc+2#twUyq^80FR8~zl=ojzG}ZOblbu9V0b2HJJ)FlFd<|9TtS(TcR-t|s_Aru53B zg+F^pQiWDPrGOseMOHTU7?S|u);zmK8t)(nBY|e2`Paj&>sMk~fImH>|y|al3D31Fk`a^n1n(oUuZ?NNB!ijT>{hQ zUWDT9$cqU%A+ymLwPAn|rK0eIj`ik0LV2xJ%l-^J^(E-=3m|!86xs`VYM?ECr`C8p zyep|+M+q8H&~ZF19g3W@+mmcLJ#lvb!rV)aex;-s@uJD}QfLmAaNA3u)b1$Dtu}u3?nHTqs(#mh7Xr*5^C`omFgo6^n;g<=^6P|u?n$1riw|X6|MV4r4|%wm zcw4GmJbbh~Q)w#7ls}Gez9jvnvBcuW{;!gTw275{0lny=1}P1qLi6}dbpg1#xJ_uz zU5Y|upKZ?DsXHT0#KY8`i2Olf8j2tbLwBtkHn(TzJ<9KGuuo@c>+_AQ=v8*GtxBa6 znAFindk(c#Q!<5QoEzIoJ0MytsN{{)+)O%=DS*V8Z%g(vGU5!S0MI#F!N7pYJsC|`9N6jDaHLyDXzWZM%;g1 zwOu_fN_{Ig?AU88t#u5A`>S@nnijai3C~N9+Wb}4kh^QcOZftR1G|m#^fObj!*X{8 zj8M9E2IkJfPP@!%#rV&+uHf zdi#Q^yaeb4(w{TrkG!GWUBeS3^pnG-CfE)g#`O8IC}$Nv2r qasNvuhnXWXjbf#o!f!x?EE&RIqA>u=G)D{z-F3B%w5l~8z4{+n{{m0| literal 0 HcmV?d00001 From 1279bb07ac9af62d0356ed1180ebdc2fa8a570cf Mon Sep 17 00:00:00 2001 From: sushantdivate Date: Wed, 21 Aug 2019 17:02:01 -0700 Subject: [PATCH 04/18] corrected indentation --- ml_service/util/create_scoring_image.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/ml_service/util/create_scoring_image.py b/ml_service/util/create_scoring_image.py index 76d0641a..8461fb45 100644 --- a/ml_service/util/create_scoring_image.py +++ b/ml_service/util/create_scoring_image.py @@ -51,12 +51,11 @@ if image.creation_state != "Succeeded": raise Exception("Image creation status: {image.creation_state}") -print( - "{}(v.{} [{}]) stored at {} with build log {}".format( - image.name, - image.version, - image.creation_state, - image.image_location, - image.image_build_log_uri, - ) +print("{}(v.{} [{}]) stored at {} with build log {}".format( + image.name, + image.version, + image.creation_state, + image.image_location, + image.image_build_log_uri, +) ) From 4e4b7ce2498f05a02867e83d3b1e3ea1eae7ef91 Mon Sep 17 00:00:00 2001 From: sushantdivate Date: Thu, 22 Aug 2019 15:50:05 -0700 Subject: [PATCH 05/18] updated doc for web app release --- docs/getting_started.md | 107 ++++++++++++++++++++++++---------------- 1 file changed, 64 insertions(+), 43 deletions(-) diff --git a/docs/getting_started.md b/docs/getting_started.md index abd67d10..e0e9a01f 100644 --- a/docs/getting_started.md +++ b/docs/getting_started.md @@ -20,7 +20,7 @@ Please make note of the following values after creating a service principal, we - Application Secret -**Note:** You must have sufficient permissions to register an application with your Azure AD tenant, and assign the application to a role in your Azure subscription. Contact your subscription adminstator if you don't have the permissions. Normally a subscription admin can create a Service principal and can provide you the details. +**Note:** You must have sufficient permissions to register an application with your Azure AD tenant, and assign the application to a role in your Azure subscription. Contact your subscription administrator if you don't have the permissions. Normally a subscription admin can create a Service principal and can provide you the details. ### 4. Create a Variable Group @@ -29,26 +29,26 @@ We make use of variable group inside Azure DevOps to store variables and their v Please name your variable group **``devopsforai-aml-vg``** as we are using this name within our build yaml file. -The varibale group should contain the following variables: - -| Variable Name | Suggested Value | -| --- | --- | -| AML_COMPUTE_CLUSTER_CPU_SKU | STANDARD_DS2_V2 | -| AML_COMPUTE_CLUSTER_NAME | train-cluster | -| AML_WORKSPACE_NAME | mlops-AML-WS | -| BASE_NAME | mlops | -| EVALUATE_SCRIPT_PATH | evaluate/evaluate_model.py | -| EXPERIMENT_NAME | mlopspython | -| LOCATION | centralus | -| MODEL_NAME | sklearn_regression_model.pkl | -| REGISTER_SCRIPT_PATH | register/register_model.py | -| RESOURCE_GROUP | mlops-AML-RG | -| SOURCES_DIR_TRAIN | code | -| SP_APP_ID | | -| SP_APP_SECRET | | -| SUBSCRIPTION_ID | | -| TENANT_ID | | -| TRAIN_SCRIPT_PATH | training/train.py | +The variable group should contain the following variables: + +| Variable Name | Suggested Value | +| --------------------------- | ---------------------------- | +| AML_COMPUTE_CLUSTER_CPU_SKU | STANDARD_DS2_V2 | +| AML_COMPUTE_CLUSTER_NAME | train-cluster | +| AML_WORKSPACE_NAME | mlops-AML-WS | +| BASE_NAME | mlops | +| EVALUATE_SCRIPT_PATH | evaluate/evaluate_model.py | +| EXPERIMENT_NAME | mlopspython | +| LOCATION | centralus | +| MODEL_NAME | sklearn_regression_model.pkl | +| REGISTER_SCRIPT_PATH | register/register_model.py | +| RESOURCE_GROUP | mlops-AML-RG | +| SOURCES_DIR_TRAIN | code | +| SP_APP_ID | | +| SP_APP_SECRET | | +| SUBSCRIPTION_ID | | +| TENANT_ID | | +| TRAIN_SCRIPT_PATH | training/train.py | Mark **SP_APP_SECRET** variable as a secret one. @@ -173,15 +173,15 @@ Create a stage **QA (ACI)** and add a single task to the job **Azure ML Model De Specify task parameters as it is shown in the table below: -| Parameter | Value | -| --- | --- | -| Display Name | Azure ML Model Deploy | -| Azure ML Workspace | mlops-AML-WS | -| Inference config Path | `$(System.DefaultWorkingDirectory)/_ci-build/mlops-pipelines/code/scoring/inference_config.yml` | -| Model Deployment Target | Azure Container Instance | -| Deployment Name | mlopspython-aci | +| Parameter | Value | +| ----------------------------- | ---------------------------------------------------------------------------------------------------- | +| Display Name | Azure ML Model Deploy | +| Azure ML Workspace | mlops-AML-WS | +| Inference config Path | `$(System.DefaultWorkingDirectory)/_ci-build/mlops-pipelines/code/scoring/inference_config.yml` | +| Model Deployment Target | Azure Container Instance | +| Deployment Name | mlopspython-aci | | Deployment Configuration file | `$(System.DefaultWorkingDirectory)/_ci-build/mlops-pipelines/code/scoring/deployment_config_aci.yml` | -| Overwrite existing deployment | X | +| Overwrite existing deployment | X | In a similar way create a stage **Prod (AKS** and add a single task to the job **Azure ML Model Deploy**: @@ -190,25 +190,46 @@ In a similar way create a stage **Prod (AKS** and add a single task to the job * Specify task parameters as it is shown in the table below: -| Parameter | Value | -| --- | --- | -| Display Name | Azure ML Model Deploy | -| Azure ML Workspace | mlops-AML-WS | -| Inference config Path | `$(System.DefaultWorkingDirectory)/_ci-build/mlops-pipelines/code/scoring/inference_config.yml` | -| Model Deployment Target | Azure Kubernetes Service | -| Select AKS Cluster for Deployment | YOUR_DEPLOYMENT_K8S_CLUSTER | -| Deployment Name | mlopspython-aks | -| Deployment Configuration file | `$(System.DefaultWorkingDirectory)/_ci-build/mlops-pipelines/code/scoring/deployment_config_aks.yml` | -| Overwrite existing deployment | X | +| Parameter | Value | +| --------------------------------- | ---------------------------------------------------------------------------------------------------- | +| Display Name | Azure ML Model Deploy | +| Azure ML Workspace | mlops-AML-WS | +| Inference config Path | `$(System.DefaultWorkingDirectory)/_ci-build/mlops-pipelines/code/scoring/inference_config.yml` | +| Model Deployment Target | Azure Kubernetes Service | +| Select AKS Cluster for Deployment | YOUR_DEPLOYMENT_K8S_CLUSTER | +| Deployment Name | mlopspython-aks | +| Deployment Configuration file | `$(System.DefaultWorkingDirectory)/_ci-build/mlops-pipelines/code/scoring/deployment_config_aks.yml` | +| Overwrite existing deployment | X | **Note:** Creating of a Kubernetes cluster on AKS is out of scope of this tutorial, so you should take care of it on your own. -Save the pipeline and craete a release to trigger it manually. Once the pipeline exection is finished, check out deployments in the **mlops-AML-WS** workspace. +**Deploy trained model to Azure Web App for containers** + +[Create Image Script](./ml_service/util/create_scoring_image.py) +can be used to create a scoring image from the release pipeline. Image created by this script will be registered under Azure Container Registry(ACR) instance that belongs to Azure Machine Learning Service. Any dependencies that scoring file depends on can also be packaged with the container with Image config. To learn more on how to create a container with AML SDK click [here](https://docs.microsoft.com/en-us/python/api/azureml-core/azureml.core.image.image.image?view=azure-ml-py#create-workspace--name--models--image-config-). + +Below is release pipeline with two tasks one to create an image using the above script and second is the deploy the image to Web App for containers +![release_webapp](./images/release-webapp-pipeline.PNG) + +Using bash script task to invoke [Create Image Script](./ml_service/util/create_scoring_image.py) +![release_createimage](./images/release-task-createimage.PNG) + +Specify task parameters as it is shown in the table below: +| Parameter | Value | +| ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Azure Subscription | Subscription used to deploy Web App | +| App name | Web App for Containers name | +| Image name | $(acr_url)/$(image_name):$(image_version) where pipeline variables forms the fully qualified container image name. For example, 'myregistry.azurecr.io/nginx:latest' | + +![release_webapp](./images/release-task-webappdeploy.PNG) + + +Save the pipeline and create a release to trigger it manually. Once the pipeline execution is finished, check out deployments in the **mlops-AML-WS** workspace. Congratulations! You have three pipelines set up end to end: - - Build pipeline: triggered on code change to master branch on GitHub, performs linting, unit testing and publishing a trainig pipeline - - Release Trigger pipeline: runs a published training pipeline to trian, evaluate and register a model - - Release Deployment pipeline: deploys a model to QA (ACI) and Prod (AKS) environemts + - Build pipeline: triggered on code change to master branch on GitHub, performs linting, unit testing and publishing a training pipeline + - Release Trigger pipeline: runs a published training pipeline to train, evaluate and register a model + - Release Deployment pipeline: deploys a model to QA (ACI) and Prod (AKS) environments From 65712106e9774626ea23405560100b60f6f1c2c8 Mon Sep 17 00:00:00 2001 From: Sushant Divate Date: Thu, 22 Aug 2019 15:56:11 -0700 Subject: [PATCH 06/18] Update getting_started.md --- docs/getting_started.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/docs/getting_started.md b/docs/getting_started.md index e0e9a01f..b92ab800 100644 --- a/docs/getting_started.md +++ b/docs/getting_started.md @@ -216,10 +216,8 @@ Using bash script task to invoke [Create Image Script](./ml_service/util/create_ Specify task parameters as it is shown in the table below: | Parameter | Value | -| ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Azure Subscription | Subscription used to deploy Web App | -| App name | Web App for Containers name | -| Image name | $(acr_url)/$(image_name):$(image_version) where pipeline variables forms the fully qualified container image name. For example, 'myregistry.azurecr.io/nginx:latest' | +| ------------------ | --------------------------- | +| Azure Subscription | Subscription used to deploy Web App | | App name | Web App for Containers name| | Image name | $(acr_url)/$(image_name):$(image_version) where pipeline variables forms the fully qualified container image name. For example, 'myregistry.azurecr.io/nginx:latest' | ![release_webapp](./images/release-task-webappdeploy.PNG) From 9d49b9f6fd8442a38421c65856966b6d2a762452 Mon Sep 17 00:00:00 2001 From: Sushant Divate Date: Thu, 22 Aug 2019 15:57:19 -0700 Subject: [PATCH 07/18] Update getting_started.md --- docs/getting_started.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/getting_started.md b/docs/getting_started.md index b92ab800..ebace8bb 100644 --- a/docs/getting_started.md +++ b/docs/getting_started.md @@ -215,7 +215,7 @@ Using bash script task to invoke [Create Image Script](./ml_service/util/create_ ![release_createimage](./images/release-task-createimage.PNG) Specify task parameters as it is shown in the table below: -| Parameter | Value | +| Parameter | Value| | ------------------ | --------------------------- | | Azure Subscription | Subscription used to deploy Web App | | App name | Web App for Containers name| | Image name | $(acr_url)/$(image_name):$(image_version) where pipeline variables forms the fully qualified container image name. For example, 'myregistry.azurecr.io/nginx:latest' | From f5fd2c7b78f6fb8edd442127436a8e4134a947d1 Mon Sep 17 00:00:00 2001 From: Sushant Divate Date: Thu, 22 Aug 2019 15:59:34 -0700 Subject: [PATCH 08/18] Update getting_started.md --- docs/getting_started.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/getting_started.md b/docs/getting_started.md index ebace8bb..26f9ff3e 100644 --- a/docs/getting_started.md +++ b/docs/getting_started.md @@ -215,9 +215,11 @@ Using bash script task to invoke [Create Image Script](./ml_service/util/create_ ![release_createimage](./images/release-task-createimage.PNG) Specify task parameters as it is shown in the table below: -| Parameter | Value| -| ------------------ | --------------------------- | -| Azure Subscription | Subscription used to deploy Web App | | App name | Web App for Containers name| | Image name | $(acr_url)/$(image_name):$(image_version) where pipeline variables forms the fully qualified container image name. For example, 'myregistry.azurecr.io/nginx:latest' | +| Parameter | Value | +| --------------------------------- | ---------------------------------------------------------------------------------------------------- | +| Azure Subscription | Subscription used to deploy Web App | +| App name | Web App for Containers name | +| Image name | $(acr_url)/$(image_name):$(image_version) where pipeline variables forms the fully qualified container image name. For example, 'myregistry.azurecr.io/nginx:latest' | ![release_webapp](./images/release-task-webappdeploy.PNG) From fadf372669e3f719988ea93a342fd5ccb01c7590 Mon Sep 17 00:00:00 2001 From: Sushant Divate Date: Thu, 22 Aug 2019 16:02:50 -0700 Subject: [PATCH 09/18] Update getting_started.md --- docs/getting_started.md | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/docs/getting_started.md b/docs/getting_started.md index 26f9ff3e..13e82e60 100644 --- a/docs/getting_started.md +++ b/docs/getting_started.md @@ -215,11 +215,9 @@ Using bash script task to invoke [Create Image Script](./ml_service/util/create_ ![release_createimage](./images/release-task-createimage.PNG) Specify task parameters as it is shown in the table below: -| Parameter | Value | -| --------------------------------- | ---------------------------------------------------------------------------------------------------- | -| Azure Subscription | Subscription used to deploy Web App | -| App name | Web App for Containers name | -| Image name | $(acr_url)/$(image_name):$(image_version) where pipeline variables forms the fully qualified container image name. For example, 'myregistry.azurecr.io/nginx:latest' | +| Parameter | Value | | --------------------------------- | ------------------------------------------------------------------------------------- | +| Azure Subscription | Subscription used to deploy Web App | +| App name | Web App for Containers name | ![release_webapp](./images/release-task-webappdeploy.PNG) From 3a55d510810557fd67dc239631e9d70f4200a720 Mon Sep 17 00:00:00 2001 From: sushantdivate Date: Thu, 22 Aug 2019 16:07:07 -0700 Subject: [PATCH 10/18] correcting doc --- docs/getting_started.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/getting_started.md b/docs/getting_started.md index 13e82e60..5f2746bb 100644 --- a/docs/getting_started.md +++ b/docs/getting_started.md @@ -215,9 +215,10 @@ Using bash script task to invoke [Create Image Script](./ml_service/util/create_ ![release_createimage](./images/release-task-createimage.PNG) Specify task parameters as it is shown in the table below: -| Parameter | Value | | --------------------------------- | ------------------------------------------------------------------------------------- | -| Azure Subscription | Subscription used to deploy Web App | -| App name | Web App for Containers name | +| Parameter | Value | +| ------------------ | ----------------------------------- | +| Azure Subscription | Subscription used to deploy Web App | +| App name | Web App for Containers name | ![release_webapp](./images/release-task-webappdeploy.PNG) From ffd37fd239827bdf993328b29adf41427e18b4cc Mon Sep 17 00:00:00 2001 From: sushantdivate Date: Thu, 22 Aug 2019 16:08:34 -0700 Subject: [PATCH 11/18] correcting doc --- docs/getting_started.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/getting_started.md b/docs/getting_started.md index 5f2746bb..604b0788 100644 --- a/docs/getting_started.md +++ b/docs/getting_started.md @@ -215,6 +215,7 @@ Using bash script task to invoke [Create Image Script](./ml_service/util/create_ ![release_createimage](./images/release-task-createimage.PNG) Specify task parameters as it is shown in the table below: + | Parameter | Value | | ------------------ | ----------------------------------- | | Azure Subscription | Subscription used to deploy Web App | From 85f19ac1fedae464d304d4ad6a52ab8b0d07a28c Mon Sep 17 00:00:00 2001 From: sushantdivate Date: Thu, 22 Aug 2019 16:10:39 -0700 Subject: [PATCH 12/18] correcting doc --- docs/getting_started.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/docs/getting_started.md b/docs/getting_started.md index 604b0788..b1b796cb 100644 --- a/docs/getting_started.md +++ b/docs/getting_started.md @@ -216,10 +216,12 @@ Using bash script task to invoke [Create Image Script](./ml_service/util/create_ Specify task parameters as it is shown in the table below: -| Parameter | Value | -| ------------------ | ----------------------------------- | -| Azure Subscription | Subscription used to deploy Web App | -| App name | Web App for Containers name | + +| Parameter | Value | +| --------------------- | ----------------------------------------------------------------------------------------------- | +| Azure Subscription | Subscription used to deploy Web App | +| App name | Web App for Containers name | +| Inference config Path | `$(System.DefaultWorkingDirectory)/_ci-build/mlops-pipelines/code/scoring/inference_config.yml` | ![release_webapp](./images/release-task-webappdeploy.PNG) From 7ea160e68ea3ea667c9e2d3f742e7b3a068902bc Mon Sep 17 00:00:00 2001 From: sushantdivate Date: Thu, 22 Aug 2019 16:12:19 -0700 Subject: [PATCH 13/18] correcting doc --- docs/getting_started.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/getting_started.md b/docs/getting_started.md index b1b796cb..8c5f12ce 100644 --- a/docs/getting_started.md +++ b/docs/getting_started.md @@ -217,11 +217,11 @@ Using bash script task to invoke [Create Image Script](./ml_service/util/create_ Specify task parameters as it is shown in the table below: -| Parameter | Value | -| --------------------- | ----------------------------------------------------------------------------------------------- | -| Azure Subscription | Subscription used to deploy Web App | -| App name | Web App for Containers name | -| Inference config Path | `$(System.DefaultWorkingDirectory)/_ci-build/mlops-pipelines/code/scoring/inference_config.yml` | +| Parameter | Value | +| ------------------ | --------------------------------------------------------------------------------------------------- | +| Azure Subscription | Subscription used to deploy Web App | +| App name | Web App for Containers name | +| Image Name | Specify the fully qualified container image name. For example, 'myregistry.azurecr.io/nginx:latest' | ![release_webapp](./images/release-task-webappdeploy.PNG) From 7c8206ac3a737bca5b2ff6815e4154a5d994448e Mon Sep 17 00:00:00 2001 From: sushantdivate Date: Thu, 22 Aug 2019 16:13:22 -0700 Subject: [PATCH 14/18] correcting doc --- docs/getting_started.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/getting_started.md b/docs/getting_started.md index 8c5f12ce..ac574d42 100644 --- a/docs/getting_started.md +++ b/docs/getting_started.md @@ -219,9 +219,9 @@ Specify task parameters as it is shown in the table below: | Parameter | Value | | ------------------ | --------------------------------------------------------------------------------------------------- | -| Azure Subscription | Subscription used to deploy Web App | +| Azure subscription | Subscription used to deploy Web App | | App name | Web App for Containers name | -| Image Name | Specify the fully qualified container image name. For example, 'myregistry.azurecr.io/nginx:latest' | +| Image name | Specify the fully qualified container image name. For example, 'myregistry.azurecr.io/nginx:latest' | ![release_webapp](./images/release-task-webappdeploy.PNG) From a6ec9a233364b3c6302e426959bfba49812d60fc Mon Sep 17 00:00:00 2001 From: Sushant Divate Date: Thu, 22 Aug 2019 16:49:14 -0700 Subject: [PATCH 15/18] Update getting_started.md --- docs/getting_started.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/getting_started.md b/docs/getting_started.md index ac574d42..c30e52e2 100644 --- a/docs/getting_started.md +++ b/docs/getting_started.md @@ -204,6 +204,7 @@ Specify task parameters as it is shown in the table below: **Note:** Creating of a Kubernetes cluster on AKS is out of scope of this tutorial, so you should take care of it on your own. **Deploy trained model to Azure Web App for containers** +Note: This is optional step and can be used only if you are deploying your scoring services on web apps. [Create Image Script](./ml_service/util/create_scoring_image.py) can be used to create a scoring image from the release pipeline. Image created by this script will be registered under Azure Container Registry(ACR) instance that belongs to Azure Machine Learning Service. Any dependencies that scoring file depends on can also be packaged with the container with Image config. To learn more on how to create a container with AML SDK click [here](https://docs.microsoft.com/en-us/python/api/azureml-core/azureml.core.image.image.image?view=azure-ml-py#create-workspace--name--models--image-config-). From 65b4ce3f2d7dffc221111dd03f7e6ea0707c00e6 Mon Sep 17 00:00:00 2001 From: sushantdivate Date: Thu, 22 Aug 2019 16:50:47 -0700 Subject: [PATCH 16/18] PR comments --- docs/getting_started.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/getting_started.md b/docs/getting_started.md index c30e52e2..cbaa8925 100644 --- a/docs/getting_started.md +++ b/docs/getting_started.md @@ -204,9 +204,10 @@ Specify task parameters as it is shown in the table below: **Note:** Creating of a Kubernetes cluster on AKS is out of scope of this tutorial, so you should take care of it on your own. **Deploy trained model to Azure Web App for containers** -Note: This is optional step and can be used only if you are deploying your scoring services on web apps. -[Create Image Script](./ml_service/util/create_scoring_image.py) +Note: This is an optional step and can be used only if you are deploying your scoring services on web apps. + +[Create Image Script](/../ml_service/util/create_scoring_image.py) can be used to create a scoring image from the release pipeline. Image created by this script will be registered under Azure Container Registry(ACR) instance that belongs to Azure Machine Learning Service. Any dependencies that scoring file depends on can also be packaged with the container with Image config. To learn more on how to create a container with AML SDK click [here](https://docs.microsoft.com/en-us/python/api/azureml-core/azureml.core.image.image.image?view=azure-ml-py#create-workspace--name--models--image-config-). Below is release pipeline with two tasks one to create an image using the above script and second is the deploy the image to Web App for containers From a610ad1b2e0f08bf34d37401fd316b24e8360695 Mon Sep 17 00:00:00 2001 From: sushantdivate Date: Thu, 22 Aug 2019 16:54:46 -0700 Subject: [PATCH 17/18] updating link --- docs/getting_started.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/getting_started.md b/docs/getting_started.md index cbaa8925..3b7c02df 100644 --- a/docs/getting_started.md +++ b/docs/getting_started.md @@ -205,7 +205,7 @@ Specify task parameters as it is shown in the table below: **Deploy trained model to Azure Web App for containers** -Note: This is an optional step and can be used only if you are deploying your scoring services on web apps. +Note: This is an optional step and can be used only if you are deploying your scoring service on Azure Web Apps. [Create Image Script](/../ml_service/util/create_scoring_image.py) can be used to create a scoring image from the release pipeline. Image created by this script will be registered under Azure Container Registry(ACR) instance that belongs to Azure Machine Learning Service. Any dependencies that scoring file depends on can also be packaged with the container with Image config. To learn more on how to create a container with AML SDK click [here](https://docs.microsoft.com/en-us/python/api/azureml-core/azureml.core.image.image.image?view=azure-ml-py#create-workspace--name--models--image-config-). @@ -213,7 +213,7 @@ can be used to create a scoring image from the release pipeline. Image created b Below is release pipeline with two tasks one to create an image using the above script and second is the deploy the image to Web App for containers ![release_webapp](./images/release-webapp-pipeline.PNG) -Using bash script task to invoke [Create Image Script](./ml_service/util/create_scoring_image.py) +Using bash script task to invoke [Create Image Script](/../ml_service/util/create_scoring_image.py) ![release_createimage](./images/release-task-createimage.PNG) Specify task parameters as it is shown in the table below: From 984399b375c06e48e331edcb465c53e9f524ce08 Mon Sep 17 00:00:00 2001 From: sushantdivate Date: Thu, 22 Aug 2019 16:56:43 -0700 Subject: [PATCH 18/18] updating links to script --- docs/getting_started.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/getting_started.md b/docs/getting_started.md index 3b7c02df..00ae2e6e 100644 --- a/docs/getting_started.md +++ b/docs/getting_started.md @@ -207,13 +207,13 @@ Specify task parameters as it is shown in the table below: Note: This is an optional step and can be used only if you are deploying your scoring service on Azure Web Apps. -[Create Image Script](/../ml_service/util/create_scoring_image.py) +[Create Image Script](../ml_service/util/create_scoring_image.py) can be used to create a scoring image from the release pipeline. Image created by this script will be registered under Azure Container Registry(ACR) instance that belongs to Azure Machine Learning Service. Any dependencies that scoring file depends on can also be packaged with the container with Image config. To learn more on how to create a container with AML SDK click [here](https://docs.microsoft.com/en-us/python/api/azureml-core/azureml.core.image.image.image?view=azure-ml-py#create-workspace--name--models--image-config-). Below is release pipeline with two tasks one to create an image using the above script and second is the deploy the image to Web App for containers ![release_webapp](./images/release-webapp-pipeline.PNG) -Using bash script task to invoke [Create Image Script](/../ml_service/util/create_scoring_image.py) +Using bash script task to invoke [Create Image Script](../ml_service/util/create_scoring_image.py) ![release_createimage](./images/release-task-createimage.PNG) Specify task parameters as it is shown in the table below: