From 56f8a68444e5ce4139a556c0aebd70f19a9dcfa2 Mon Sep 17 00:00:00 2001 From: Michail Kargakis Date: Sat, 4 Mar 2017 18:51:54 +0100 Subject: [PATCH 01/21] Remove redundant section in deployments The status of the deployment is already covered in a later section in this doc. --- docs/user-guide/deployments.md | 55 ---------------------------------- 1 file changed, 55 deletions(-) diff --git a/docs/user-guide/deployments.md b/docs/user-guide/deployments.md index 0b4ae0d85a..58daee9c2e 100644 --- a/docs/user-guide/deployments.md +++ b/docs/user-guide/deployments.md @@ -80,61 +80,6 @@ The created Replica Set will ensure that there are three nginx Pods at all times **Note:** You must specify appropriate selector and pod template labels of a Deployment (in this case, `app = nginx`), i.e. don't overlap with other controllers (including Deployments, Replica Sets, Replication Controllers, etc.) Kubernetes won't stop you from doing that, and if you end up with multiple controllers that have overlapping selectors, those controllers will fight with each other's and won't behave correctly. -## The Status of a Deployment - -After creating or updating a Deployment, you would want to confirm whether it succeeded or not. The simplest way to do this is through `kubectl rollout status`. - -```shell -$ kubectl rollout status deployment/nginx-deployment -deployment "nginx-deployment" successfully rolled out -``` - -This verifies the Deployment's `.status.observedGeneration` >= `.metadata.generation`, and its up-to-date replicas -(`.status.updatedReplicas`) matches the desired replicas (`.spec.replicas`) to determine if the rollout succeeded. -It also expects that the available replicas running (`.spec.availableReplicas`) will be at least the minimum required -based on the Deployment strategy. If the rollout is still in progress, it watches for Deployment status changes and -prints related messages. - -```shell -$ kubectl rollout status deployment/nginx-deployment -Waiting for rollout to finish: 2 out of 10 new replicas have been updated... -Waiting for rollout to finish: 2 out of 10 new replicas have been updated... -Waiting for rollout to finish: 2 out of 10 new replicas have been updated... -Waiting for rollout to finish: 3 out of 10 new replicas have been updated... -Waiting for rollout to finish: 3 out of 10 new replicas have been updated... -Waiting for rollout to finish: 4 out of 10 new replicas have been updated... -Waiting for rollout to finish: 4 out of 10 new replicas have been updated... -Waiting for rollout to finish: 4 out of 10 new replicas have been updated... -Waiting for rollout to finish: 4 out of 10 new replicas have been updated... -Waiting for rollout to finish: 4 out of 10 new replicas have been updated... -Waiting for rollout to finish: 5 out of 10 new replicas have been updated... -Waiting for rollout to finish: 5 out of 10 new replicas have been updated... -Waiting for rollout to finish: 5 out of 10 new replicas have been updated... -Waiting for rollout to finish: 5 out of 10 new replicas have been updated... -Waiting for rollout to finish: 6 out of 10 new replicas have been updated... -Waiting for rollout to finish: 6 out of 10 new replicas have been updated... -Waiting for rollout to finish: 6 out of 10 new replicas have been updated... -Waiting for rollout to finish: 6 out of 10 new replicas have been updated... -Waiting for rollout to finish: 6 out of 10 new replicas have been updated... -Waiting for rollout to finish: 7 out of 10 new replicas have been updated... -Waiting for rollout to finish: 7 out of 10 new replicas have been updated... -Waiting for rollout to finish: 7 out of 10 new replicas have been updated... -Waiting for rollout to finish: 7 out of 10 new replicas have been updated... -Waiting for rollout to finish: 8 out of 10 new replicas have been updated... -Waiting for rollout to finish: 8 out of 10 new replicas have been updated... -Waiting for rollout to finish: 8 out of 10 new replicas have been updated... -Waiting for rollout to finish: 9 out of 10 new replicas have been updated... -Waiting for rollout to finish: 9 out of 10 new replicas have been updated... -Waiting for rollout to finish: 9 out of 10 new replicas have been updated... -Waiting for rollout to finish: 1 old replicas are pending termination... -Waiting for rollout to finish: 1 old replicas are pending termination... -Waiting for rollout to finish: 1 old replicas are pending termination... -Waiting for rollout to finish: 9 of 10 updated replicas are available... -deployment "nginx-deployment" successfully rolled out -``` - -For more information about the status of a Deployment [read more here](#deployment-status). - ## Updating a Deployment From 979686122a4878a5bd74858da1a101b4ae5460c0 Mon Sep 17 00:00:00 2001 From: mlambert890b Date: Sun, 5 Mar 2017 20:44:47 -0800 Subject: [PATCH 02/21] Repair Spotinst logo Corrected size --- images/square-logos/spotinst.png | Bin 86339 -> 5239 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/images/square-logos/spotinst.png b/images/square-logos/spotinst.png index b933c77546138512c3a36c907f37cced6bdfac76..645abbed45c5cd16f3196e27a0e37a718129b19d 100644 GIT binary patch literal 5239 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 LG=NoW*v9?`NY|+G literal 86339 zcmeD^i9eKU+mA?zQc9*yhtya?3@R0&v>3aPWScCh>?CBH>L5#tvA3WkM`S&beIzt3 zXhTOrDLTX?YqsyYXUvTA{tMr^f4}d1d7gW@_Vs?|jW9Aew0zn6Wf+DnCu;9MjA1Kq z7`EihQeJqn^jfbm{69VqZ3}M<;}=5z$Mw1+cpAetV#NJ>P5u5J=y<7b#kW4R`%U_L zE#4Dm?PqyU`1_v4B$8JyJ-T@u3j9Zh|LB1I=P#H-@E;xiqr*aT@Si;VClCM0!+&8jO9uYGgv}%Fs{v(=)40sf z)e|GfDJ2>cTW1HI-D9oxd^%J%ojp`=Og?w|A&V>+)-@G8`D-*=7{k(@5)9mx!-HuX zrd&VHDbA|u44*Iz{;rVxx$g4wB|~|wh7_y3ged1Z3C`+mD{+f3YKq^=6`~JP@w;rQ zMIA%zY7z@0gv4yjDvpK7?dN2-q+UJ&E{t?Y;PaV^;HidI-xmMvzNJ@JsI2@HO*|<2Fx)Q^RpAZbfi66htF6#ce={DKJ*LBg8{!#DvUFsFvmUAZO>64aXn1Tx~ zGyMfuw`bL5KEWK5FOuW0y1$N|erWaKI!gPQgPgb#@@cZuaMz~pue&0h|Cp|P`L6b* z_xDfYtSK1Qv={AXND7MgSS=*laA04`NBzO{+UJkX!sGctH55XqZ;s%5ze$CdtGpyU zans?Cr+s(+t)_DsOf${ zqk^!6y%)8AH872Se}AYE(S^gy{KaTx#ZF^!I=KzRZhmydF9m`1TXkn&*OE)iIS1KX zLnLt89{q;6Ka~2})vnes`^%?i8(8Z=bPN$SV}Gmvwv$Hunop;0q8gUbf?WQESEe}N z)kOq#i0j$rZ8}lEiK;wF=~1Iio-Tc~eF4xKQfQ(W>_+f5^1I$+9)&3kR3~fI@|$pu zR7*iX9bz6yx!QsiQ?0*dhov5QUiWYpXIgMHnkJ?c{l<7OPq?aJX?}*f)0O24FzvyD zX|o!LeVu?}_>0zMotE5f;=V+ACEM*4N(%r>MG8F;3j|j_6q+l%XsXMb@)H!<4He#) zgB*ZZ91P;(33N!`PTq4Su}AHvS*`N|Vfl{8?|{pUg|k8)@)~_Y$muRX?g5&R5$3u3 zS>OZuHrn|EJuVNetZr~jOxt!KE%|r698cTsg(vr-lh0ntUrFj; zxaBP*Zf#tT_mOXH-p0|vVk9@DC_a9!vnkCS*>5|BHs6XiS6#SyKia&QiPmO#X+B5W zu>Rw94pe@wjD`6t_?sALe`KI7bsNNKe$cNY(&e4RW!AokiO64>)@1$lDgDJ7)_aWV zjJ!(41)rmSWx=5BM&BiA?@yQRTtI$01?_<>e(Vc#{?JfNZA60h4fJLkhedQD#vG6< zLEyDY3)ZEoF15>It4QlT_EA_$ETG?&48~=L_tA;Q^_bdY_hf~CW3&Qcj@Yq%nr-l1mNBgV;Wlrb;0o{)IEmBF&TW6DmDAN@((6PtsH}l8ayX@V`AI{@^ zbQ+gkqU~NSIV4jfyRvf8URlD!MSIO|-FUWJ`O%`-Q&RVi(1m2XM7E6(KgT%4EP6WY zpCS`Ca6OA}#jc>d`@g!F2$bJJf~w`%(fH=UTJ>07EWjf<_oSZ$NBz1EZ2?jaXj+sU zA|4?cWN=Y8`^7rEH?4ah&87i4{4hwy1earnsHBCY|CZ&L=zGbI>)kpFIHDyD+o%~? zltkfsi7W1MQCFAgnQyBQ;!xW|Y#DH5+_dGpF~y8xatdqS>`sxpasQDpXAXVO8jzkU z6N{2?P>Ko)FSh3)vE;;~1>4XK8B??@N{Y^8hc>}Un3bf(HZ#x73y^YV%sF0u?2*o} z)p|^zx&NL_f*l(ntZIJ^FhllP*&f|OJ+F<+G2Q{KvhB4G7vS84=rXMjboq9K-w^0> zse)MOa{tp24$_*GX}Luh+3;DJwdADivrsI$={a5nh<$+L3h-+IAqw8HBjv8;R<#6P zY&Bh-_V_wS*!6BK*1|}`#o3`D2TNCyzxjze1DWOr!5@~BX@$p@V#J(vY#pLHSO7yL zX{W`p>5vvUV1AJ9$N|u?b`Mu#RkVd?Tta6k<*Z#q)hIl{acisXfDE`j*`XMH;}GSh zg)&>~$v+A~a-xq}lsFMvjOBUAQ|DrO?&q{8b0|c*i4IE#ejcYp;WJ-@(-#=<0R^nQHGph(TCRqJm1j6O-r@NJCx~Cw(a6vM$Q-mWE z0;w0oF~Twq1qV8&&Nzpa++iJqk-L9c@L<&Dc%OiTo+fFLMO1tLl>deH5rX!j89-b1 z?r|?bEA{h#p!Gx0?v?2u!_y8>oX`y4WQULc(gf1Z;I&*BVVh%zeC+hPFZ-~*s5cCb z?`QJ>t38e|iY{~$jLo5_CGuh;E&rB2@~jDPkN0*?dn{h009dQ#@xSM!Riks7eF15S zNo9~M!kSE?Td^(2{9+? zkR{TqpTbAolW|+1D~4KV&S4-fX!LR6R3g z92bB5WK-+`6JhfOg3yo&Qmd9+=$1&dAudXJE1CN2yvn30Z^g4rp>BN>VHNJ6#y}eb zwZDTYbMjkLer+d9g{*ja4Y}aUQ*U(tIWQpba51)&^ z*?*&-oZ9swbJM4SKS)FWLv=bsj1GaI8B?O9`>FEQ_hgsbe0j61+ss6`hcZSFzW*j&wtg8hEN5|7pQbY6KKFX%M+ z7uio{o!_;7ymFHYdtsXf$U>KKoKLy7m*|&$6QZq?rg*DEF&)7nzT{8#K07?dwgvCv(J(y@uR@ zgnrDR|4uKeG8ubweIY)uiRST8GzdFLC>aM6Vdb(8s^UG^ab!iR$soQ+5AX zRc@d(F2LpxSq#b7z<%WA+$Cz3T4%~O=7I+kTEcx!zUfW;^4+0=JFx1o-z%^x+PE6;U((jEJl6JyMfdyfaldc3mE*$vaEPVhz*3#z zeL?~s!d-Mj!E#=@7^6`l_%q98r=izIVcx<2A@UR=vZ#Zl(XOjr;zLbV&#w($H z005}vXPiTqZ6s7FpGbjNO=fw@Q^^j>ZDqC;VkoE!JXm^7YDAnSV_iT$vVrjH=T~W( z5>1VEe!riC4kv)f&w#mjWBDGMRi>*VZ zPi)~tJ%n9gtO$Fbg$^X!iRWJ}>X(iT8>Jx(u+lG5`8(RB!KX|@%V|A(QaaM})y6H~i4-3S_o@8N zk)fJmjU{NifQ8^+K;V6U#6gJ1 zYVj(-+y<+AmU326i*SAZkF>o8)q0lvk7ubrh~}TPl($00S8zn!y1+wX842I}>HS#x z$){Qisk|FeS?O8mbeeuyM&3_w(REzW1JPYdRH!YRr1kp{2zPVZ&2p4HLlTJz`er!?xby}-SlzXB-E)n1 z{4U2pP^G~(Q?;c|hmsmddO#|6Mwv!->gUutalI|aqqq$SM zL_b2DT_LyBVMorhA;N7y4F9vx&5)8~ ze>@^&Or5sx2Upi#r|&Yff^8E^7O-3Z$-hAJS&MIy&q4#+!_U+`h8!fg@53J5l9PQO zzF7W`nbjIDT8fd57Jqr{6SrZaScPa1$IlgPWg^^5G@w}NTy*yXnbqNhfC3Q+l%zs8 z1+c+9ww|}#9@4@62kZ(LAvUJ>HMP#XHmzGYADJqFr)PzGL-7-l%n&Yr{O1ILCbMiV zup{L9{YML2Z4lBD?gDGQbFzF@)YIbBH#cAY1lBu;O?ODrUc6_+q1g$Rn2NdZ3smb~ zP{=>Fl>V2~U)!~+zG_io{}lpi+QLN5CU7GZhu{0Pr&S;|nc1BOz}{+|o~dxV|7kya zQ*7j2(-`qz=f)&ydZjDVG_K!2DzS^`wPm@wx7ELhF%l2N=qo66%cE@2 zz3@Pv0_Miq7#sODt*$$K13&R152BAKHXF%R1%Te3ht}nwVd>+C?)Psru}!NJmOYrfi(DwZii<>jnCjc>)yqTv|?h5x$ye_gZcpmtOyX zhMreUkLmi@heRdke?^#T!a#ICJ4lKt)8Y}dzws7FxAG(n>>(xh#N#FVwaP|6El5b{ zYf#>!cB`o+D(PPTnT$o%+}P@OrgciRkk`VE$th061tDcu7P1m=j!ErWS&OgKMF$^T zgS{!M)prV`x*Hc9Ax!DZ#;u~4HpU+C5pTM_pJKQH^!-`zZt!1?f>(tBNv zQUNxb$PITv0t^Aw1C$a<(oKEH9KjZKrBFo%`40UnG$A)2&Fu0-lIwQs(y3Ad^YupZ zJY6@6WlQFC%y-)FUO~y>q(fADlwM!`6Abtng)3sZ_J`*ceY`?tgG8x^d(zE+hr;9r z5>Q>V)jy8s-dA%-JVhasyMZsl58YMV0t~vf5NgI$A~Q%;Tz3NxHoWByMp`m{$&q4C zNqW2IlY^xaJHaMbB00YbSjL{|57ny;$1B7BXETrh*uEBS!c||yi*N#YQYW&9P0aLY z{LaqLzPH>w`@pCS95xZo#urJiGpPG2i%ssj1s6Z?|H!G5<@l2pU0VJKec0x8PW(8}wv8!hqb~42*y@cr1!_Tn?>>j|JegLfwEW3UN5fkkX4;@;%ZuSfD+8L@0e+!B>ziWoJ=fdo~AU_8~fUZ*yZ` zKz6WdF}A1d;tTt|{>yx?S)e44J)b0kg?J>@Y zu|yF6RgQeK895OMHVB88sC^YsW!=nGrQ z(yy5l!V-D)+hKM~!JM5;tY<~793lQocqRXB*pMaR2Qv5+J zC=}gs*tu`+)csGNB0@4xO#Y?gN9lQcHKRoSXI7ve*z03>)>^{vfCT*(OA2pWEyd=7 zS}j0i<#rIS055{>cHXim6Y6egDiEvbf{glin*-n2X~{u-P^c;>_J)63yJy8+#bqE% z^e?JSGCE=QKdQ1KCq;t~U7@^qEzIX+EP0c1HKW$2>~(j%HtTrO1W0R_s^9xyQ$U+q z=_E5dlm6U0^}*`KVlmrCHHU7vJP#wb99h947byuX5OcA;KdU8_PG^<~yKeZV)}F}_ ze}1NRT%1M(@{U(b1yA3MycSUQL0w}FXZ1$3`nO_*Hd_gQ$;&kXt)_MR1TcDsZ<-H? zQ5Te;oH{2gLaGcVtgHsw94S#}LThC`S(0LXVn`H70hw2uR(E*mzajUHaQRnbTt-NB zqDTw7gVgm69c2zj8F@8=8R&*`jJF#b?>=OpbL6eW%P@N)lC+mQ&A83gPEJ23v z;@MjcEsWx5SNPCDoiM8Xxm3eYt#N(8*WkqqOdY31%A>*=wb$tXsTKP zVsm{V>gs@02N1qcX%+}w-Sd-kV{hu%(&2W=RxCKr|fe_=c<)wr3b}?T*6k%N%kbYoSSD;D-mNvvEG>@*A0Yvl{|^ zvgo9+nXmb~8`eWtd-K`CB3+th&vboz{{T7Ta0InT&cPNfm`|5X4C+?!1AAQVG@^ zHT71FHblXAKWUYj)y8x7zX#RpI# zVtbPDyz{j^^2d$`$Ve~3rS;=`XH!@@M12c_La;zZ@(Rk6E(qK0w(w$o-+%9i1PJ#2 zbS4k6kZv2#IQ@7`m0 ze_1}#{*MwCP(tM3Y7Yf`@|N8qHC=LGGe}2KLgBv|CfeX9Ap-ZYC{bo>EP)qo9`{{0 zEkxVSXg*L87@PHp?>Q<&T?*Ve#%`sOojv61Gn&O5{GqVmY1t;!3gKtM<16^aM4UZiyicp0(G_$qVBKIMeQw!py$U( zJlK;qE*?YG2*sHR*8!*lTYx$d+Irj8|ju>LM% z{hpU}|Kr`M!gx-;L0^M7a-xMle4foMuepZ}a3?2g~NLD-+nKr(Ih}41t$>EJN z{BN-{D<~CP`=OLB^gCElfQfX_2HEGvnDR zugn`L%*1R*B|Bs)s?AxpfL@D8Ea_w{KTsZ;Na7;9L)5Uz+Mk!K5Rm+Y)1y>HN@tvJ zvvcVX1bmRqOf;5vn4vb@ge0dSI=vF{A$0U{a62C9{)A}zo#=9IszwpJt4S3!Ch(Bx z#r!Hxl)i_d2bN=9>L9q8mR}cjwL>=zG#JV^^TPvK*yx%~E&NjhK_=1(4-HI6gl*p&LO~%(rQ?y>Vu-5eAiW`HkheSYY*Md`N;%{}7EeF)%T8aB%Q0 zMkPUG1^LR#QL+9|jJjelFdMIc=kid1%65ApyHXt(13U|J+j8M!nW;PvcD6^ZLrDqi z9NI>M_A>`q`gQZp(EqwZuMj?xl1-FWbXuo7zHYj(Y7@L|O?H z+CBiO+Ty<}4QJpn(H=*O66oECvYW7E)aoW^qZIw7&YeVPXyjjkq@;FJ$6+OG-1jEx zq?WRM>I9S?$+wSPqBikjNeSQg6)GrUevdBVs}p_tEm$I}N$Ht4H_~vD#H6lJ<;cCP zNM%LHx~c?iGAutW>gtBHNN1~xj2NKPqI7GPaAu`nZlgKiFqfZ|zy$%v2s zP)NB9d}x4B$e-d�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 Date: Sun, 5 Mar 2017 20:56:00 -0800 Subject: [PATCH 03/21] fixed ASM blurb --- _includes/partner-script.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_includes/partner-script.js b/_includes/partner-script.js index ad8b4ea61a..da3cf15ee0 100644 --- a/_includes/partner-script.js +++ b/_includes/partner-script.js @@ -313,7 +313,7 @@ name: 'ASM Technologies Limited', logo: 'asmtech', link: 'http://www.asmtech.com/', - blurb: 'http://www.asmtech.com/audience-channels/software_publisher/' + blurb: 'Our technology supply chain portfolio enables your software products to be accessible, viable and available more effectively.' }, { type: 1, From 61c6266815ab7337d29a74354e85827dcc1bb8a9 Mon Sep 17 00:00:00 2001 From: mlambert890b Date: Sun, 5 Mar 2017 20:58:01 -0800 Subject: [PATCH 04/21] Correct ASM logo filename --- _includes/partner-script.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_includes/partner-script.js b/_includes/partner-script.js index da3cf15ee0..43352b0f03 100644 --- a/_includes/partner-script.js +++ b/_includes/partner-script.js @@ -311,7 +311,7 @@ { type: 0, name: 'ASM Technologies Limited', - logo: 'asmtech', + logo: 'asm', link: 'http://www.asmtech.com/', blurb: 'Our technology supply chain portfolio enables your software products to be accessible, viable and available more effectively.' }, From f5c7bc79ff1494d566da8e91f76a4058b35d0ed2 Mon Sep 17 00:00:00 2001 From: Andrew Chen Date: Fri, 17 Mar 2017 17:17:42 -0700 Subject: [PATCH 05/21] Move Guide topic: Admin Guide --- _data/tasks.yml | 1 + docs/admin/index.md | 89 +--------------------- docs/tasks/administer-cluster/overview.md | 92 +++++++++++++++++++++++ 3 files changed, 95 insertions(+), 87 deletions(-) create mode 100644 docs/tasks/administer-cluster/overview.md diff --git a/_data/tasks.yml b/_data/tasks.yml index 6a85713142..33432d6541 100644 --- a/_data/tasks.yml +++ b/_data/tasks.yml @@ -59,6 +59,7 @@ toc: - title: Administering a Cluster section: + - docs/tasks/administer-cluster/overview.md - docs/tasks/administer-cluster/assign-pods-nodes.md - docs/tasks/administer-cluster/dns-horizontal-autoscaling.md - docs/tasks/administer-cluster/safely-drain-node.md diff --git a/docs/admin/index.md b/docs/admin/index.md index f1904aa470..2867d40703 100644 --- a/docs/admin/index.md +++ b/docs/admin/index.md @@ -1,92 +1,7 @@ --- -assignees: -- davidopp -- lavalamp title: Admin Guide --- -The cluster admin guide is for anyone creating or administering a Kubernetes cluster. -It assumes some familiarity with concepts in the [User Guide](/docs/user-guide/). +{% include user-guide-content-moved.md %} -* TOC -{:toc} - -## Planning a cluster - -There are many different examples of how to setup a Kubernetes cluster. Many of them are listed in this -[matrix](/docs/getting-started-guides/). We call each of the combinations in this matrix a *distro*. - -Before choosing a particular guide, here are some things to consider: - - - Are you just looking to try out Kubernetes on your laptop, or build a high-availability many-node cluster? Both - models are supported, but some distros are better for one case or the other. - - Will you be using a hosted Kubernetes cluster, such as [GKE](https://cloud.google.com/container-engine), or setting - one up yourself? - - Will your cluster be on-premises, or in the cloud (IaaS)? Kubernetes does not directly support hybrid clusters. We - recommend setting up multiple clusters rather than spanning distant locations. - - Will you be running Kubernetes on "bare metal" or virtual machines? Kubernetes supports both, via different distros. - - Do you just want to run a cluster, or do you expect to do active development of Kubernetes project code? If the - latter, it is better to pick a distro actively used by other developers. Some distros only use binary releases, but - offer is a greater variety of choices. - - Not all distros are maintained as actively. Prefer ones which are listed as tested on a more recent version of - Kubernetes. - - If you are configuring Kubernetes on-premises, you will need to consider what [networking - model](/docs/admin/networking) fits best. - - If you are designing for very high-availability, you may want [clusters in multiple zones](/docs/admin/multi-cluster). - - You may want to familiarize yourself with the various - [components](/docs/admin/cluster-components) needed to run a cluster. - -## Setting up a cluster - -Pick one of the Getting Started Guides from the [matrix](/docs/getting-started-guides/) and follow it. -If none of the Getting Started Guides fits, you may want to pull ideas from several of the guides. - -One option for custom networking is *OpenVSwitch GRE/VxLAN networking* ([ovs-networking.md](/docs/admin/ovs-networking)), which -uses OpenVSwitch to set up networking between pods across - Kubernetes nodes. - -If you are modifying an existing guide which uses Salt, this document explains [how Salt is used in the Kubernetes -project](/docs/admin/salt). - -## Managing a cluster, including upgrades - -[Managing a cluster](/docs/admin/cluster-management). - -## Managing nodes - -[Managing nodes](/docs/admin/node). - -## Optional Cluster Services - -* **DNS Integration with SkyDNS** ([dns.md](/docs/admin/dns)): - Resolving a DNS name directly to a Kubernetes service. - -* [**Cluster-level logging**](/docs/user-guide/logging/overview): - Saving container logs to a central log store with search/browsing interface. - -## Multi-tenant support - -* **Resource Quota** ([resourcequota/](/docs/admin/resourcequota/)) - -## Security - -* **Kubernetes Container Environment** ([docs/user-guide/container-environment.md](/docs/user-guide/container-environment)): - Describes the environment for Kubelet managed containers on a Kubernetes - node. - -* **Securing access to the API Server** [accessing the api](/docs/admin/accessing-the-api) - -* **Authentication** [authentication](/docs/admin/authentication) - -* **Authorization** [authorization](/docs/admin/authorization) - -* **Admission Controllers** [admission controllers](/docs/admin/admission-controllers) - -* **Sysctls** [sysctls](/docs/admin/sysctls.md) - -* **Audit** [audit](/docs/admin/audit) - -* **Securing the kubelet** - * [Master-Node communication](/docs/admin/master-node-communication/) - * [TLS bootstrapping](/docs/admin/kubelet-tls-bootstrapping/) - * [Kubelet authentication/authorization](/docs/admin/kubelet-authentication-authorization/) +[Cluster Administration Overview](/docs/tasks/administer-cluster/overview/) diff --git a/docs/tasks/administer-cluster/overview.md b/docs/tasks/administer-cluster/overview.md new file mode 100644 index 0000000000..3aead8a3a4 --- /dev/null +++ b/docs/tasks/administer-cluster/overview.md @@ -0,0 +1,92 @@ +--- +assignees: +- davidopp +- lavalamp +title: Cluster Administration Overview +--- + +The cluster administration overview is for anyone creating or administering a Kubernetes cluster. +It assumes some familiarity with concepts in the [User Guide](/docs/user-guide/). + +* TOC +{:toc} + +## Planning a cluster + +There are many different examples of how to setup a Kubernetes cluster. Many of them are listed in this +[matrix](/docs/getting-started-guides/). We call each of the combinations in this matrix a *distro*. + +Before choosing a particular guide, here are some things to consider: + + - Are you just looking to try out Kubernetes on your laptop, or build a high-availability many-node cluster? Both + models are supported, but some distros are better for one case or the other. + - Will you be using a hosted Kubernetes cluster, such as [GKE](https://cloud.google.com/container-engine), or setting + one up yourself? + - Will your cluster be on-premises, or in the cloud (IaaS)? Kubernetes does not directly support hybrid clusters. We + recommend setting up multiple clusters rather than spanning distant locations. + - Will you be running Kubernetes on "bare metal" or virtual machines? Kubernetes supports both, via different distros. + - Do you just want to run a cluster, or do you expect to do active development of Kubernetes project code? If the + latter, it is better to pick a distro actively used by other developers. Some distros only use binary releases, but + offer is a greater variety of choices. + - Not all distros are maintained as actively. Prefer ones which are listed as tested on a more recent version of + Kubernetes. + - If you are configuring Kubernetes on-premises, you will need to consider what [networking + model](/docs/admin/networking) fits best. + - If you are designing for very high-availability, you may want [clusters in multiple zones](/docs/admin/multi-cluster). + - You may want to familiarize yourself with the various + [components](/docs/admin/cluster-components) needed to run a cluster. + +## Setting up a cluster + +Pick one of the Getting Started Guides from the [matrix](/docs/getting-started-guides/) and follow it. +If none of the Getting Started Guides fits, you may want to pull ideas from several of the guides. + +One option for custom networking is *OpenVSwitch GRE/VxLAN networking* ([ovs-networking.md](/docs/admin/ovs-networking)), which +uses OpenVSwitch to set up networking between pods across + Kubernetes nodes. + +If you are modifying an existing guide which uses Salt, this document explains [how Salt is used in the Kubernetes +project](/docs/admin/salt). + +## Managing a cluster, including upgrades + +[Managing a cluster](/docs/admin/cluster-management). + +## Managing nodes + +[Managing nodes](/docs/admin/node). + +## Optional Cluster Services + +* **DNS Integration with SkyDNS** ([dns.md](/docs/admin/dns)): + Resolving a DNS name directly to a Kubernetes service. + +* [**Cluster-level logging**](/docs/user-guide/logging/overview): + Saving container logs to a central log store with search/browsing interface. + +## Multi-tenant support + +* **Resource Quota** ([resourcequota/](/docs/admin/resourcequota/)) + +## Security + +* **Kubernetes Container Environment** ([docs/user-guide/container-environment.md](/docs/user-guide/container-environment)): + Describes the environment for Kubelet managed containers on a Kubernetes + node. + +* **Securing access to the API Server** [accessing the api](/docs/admin/accessing-the-api) + +* **Authentication** [authentication](/docs/admin/authentication) + +* **Authorization** [authorization](/docs/admin/authorization) + +* **Admission Controllers** [admission controllers](/docs/admin/admission-controllers) + +* **Sysctls** [sysctls](/docs/admin/sysctls.md) + +* **Audit** [audit](/docs/admin/audit) + +* **Securing the kubelet** + * [Master-Node communication](/docs/admin/master-node-communication/) + * [TLS bootstrapping](/docs/admin/kubelet-tls-bootstrapping/) + * [Kubelet authentication/authorization](/docs/admin/kubelet-authentication-authorization/) From 0d19a29ef622e86b704f148923469488737371a6 Mon Sep 17 00:00:00 2001 From: Xiaoyu Zhang Date: Sun, 19 Mar 2017 19:10:04 +0800 Subject: [PATCH 06/21] update out-of-resource.md change "thresholds" to "threshold" --- docs/concepts/cluster-administration/out-of-resource.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/concepts/cluster-administration/out-of-resource.md b/docs/concepts/cluster-administration/out-of-resource.md index 76e7125e7e..27a84464f3 100644 --- a/docs/concepts/cluster-administration/out-of-resource.md +++ b/docs/concepts/cluster-administration/out-of-resource.md @@ -106,7 +106,7 @@ To configure hard eviction thresholds, the following flag is supported: * `eviction-hard` describes a set of eviction thresholds (e.g. `memory.available<1Gi`) that if met would trigger a pod eviction. -The `kubelet` has the following default hard eviction thresholds: +The `kubelet` has the following default hard eviction threshold: * `--eviction-hard=memory.available<100Mi` From 069a2dabc66ac076901f9befa4c992cd22497626 Mon Sep 17 00:00:00 2001 From: Xiaoyu Zhang Date: Sun, 19 Mar 2017 19:17:05 +0800 Subject: [PATCH 07/21] update init-containers.md change "apply" to "application" --- docs/concepts/workloads/pods/init-containers.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/concepts/workloads/pods/init-containers.md b/docs/concepts/workloads/pods/init-containers.md index 1a43dea943..d3dc7beb88 100644 --- a/docs/concepts/workloads/pods/init-containers.md +++ b/docs/concepts/workloads/pods/init-containers.md @@ -227,7 +227,7 @@ validation error is thrown for any Container sharing a name with another. ### Resources Given the ordering and execution for Init Containers, the following rules -for resource usage apply: +for resource usage application: * The highest of any particular resource request or limit defined on all Init Containers is the *effective init request/limit* From 501d851eef92c2d4e87f11466bef4627322e6984 Mon Sep 17 00:00:00 2001 From: Xiaoyu Zhang Date: Sun, 19 Mar 2017 21:03:39 +0800 Subject: [PATCH 08/21] amend monitor-node-health.md Amend the url link. --- docs/tasks/debug-application-cluster/monitor-node-health.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tasks/debug-application-cluster/monitor-node-health.md b/docs/tasks/debug-application-cluster/monitor-node-health.md index 08ca3208dd..1db42a39ab 100644 --- a/docs/tasks/debug-application-cluster/monitor-node-health.md +++ b/docs/tasks/debug-application-cluster/monitor-node-health.md @@ -36,7 +36,7 @@ it to [support other log format](/docs/admin/node-problem/#support-other-log-for ## Enable/Disable in GCE cluster -Node problem detector is [running as a cluster addon](cluster-large.md/#addon-resources) enabled by default in the +Node problem detector is [running as a cluster addon](/docs/admin/cluster-large/#addon-resources) enabled by default in the gce cluster. You can enable/disable it by setting the environment variable From 4282f695c92582b77b95563f8a7d230bfc939748 Mon Sep 17 00:00:00 2001 From: Xiaoyu Zhang Date: Mon, 20 Mar 2017 14:23:19 +0800 Subject: [PATCH 09/21] Fix monitor-node-health.md The url link does not exist. --- docs/tasks/debug-application-cluster/monitor-node-health.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/tasks/debug-application-cluster/monitor-node-health.md b/docs/tasks/debug-application-cluster/monitor-node-health.md index 08ca3208dd..7576728fc4 100644 --- a/docs/tasks/debug-application-cluster/monitor-node-health.md +++ b/docs/tasks/debug-application-cluster/monitor-node-health.md @@ -194,8 +194,8 @@ and detects known kernel issues following predefined rules. The Kernel Monitor matches kernel issues according to a set of predefined rule list in [`config/kernel-monitor.json`](https://github.com/kubernetes/node-problem-detector/blob/v0.1/config/kernel-monitor.json). -The rule list is extensible, and you can always extend it by [overwriting the -configuration](/docs/admin/node-problem/#overwrite-the-configuration). +The rule list is extensible, and you can always extend it by overwriting the +configuration. ### Add New NodeConditions From 9c9d359fb3efe654d3ae1e62c9202fd7a086c6da Mon Sep 17 00:00:00 2001 From: Xiaoyu Zhang Date: Mon, 20 Mar 2017 14:49:37 +0800 Subject: [PATCH 10/21] fix a typo in /docs/user-guide/configmap/index.md change "value" to "values" --- docs/user-guide/configmap/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/user-guide/configmap/index.md b/docs/user-guide/configmap/index.md index 1355e599f2..8249f55084 100644 --- a/docs/user-guide/configmap/index.md +++ b/docs/user-guide/configmap/index.md @@ -46,7 +46,7 @@ of configuration files. Configuration data can be consumed in pods in a variety of ways. ConfigMaps can be used to: -1. Populate the value of environment variables +1. Populate the values of environment variables 2. Set command-line arguments in a container 3. Populate config files in a volume From 7cdcff78137b3b641f1ac8a0d27b78f739fcaa8d Mon Sep 17 00:00:00 2001 From: Ahmet Alp Balkan Date: Mon, 20 Mar 2017 12:49:47 -0700 Subject: [PATCH 11/21] View $PAGE on Github without forking the repo Adding a "View docs/bla-bla.md on GitHub" button next to the "Edit docs/bla-bla.md" button so that people can view the file first without clicking the Edit button (which does not work without forking the repository). I did not need this because I was trying to do something without forking. I just found it to be bit difficult to view source of a page on GitHub. I'm open to ideas, perhaps we can instead add an article footer button named "View on GitHub" next to the "Edit this Page". Signed-off-by: Ahmet Alp Balkan --- editdocs.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/editdocs.md b/editdocs.md index b089db1c43..0a5ff53c88 100644 --- a/editdocs.md +++ b/editdocs.md @@ -13,6 +13,8 @@ $( document ).ready(function() { $("#continueEdit").show(); $("#continueEditButton").text("Edit " + forwarding); $("#continueEditButton").attr("href", "https://github.com/kubernetes/kubernetes.github.io/edit/master/" + forwarding) + $("#viewOnGithubButton").text("View " + forwarding + " on GitHub"); + $("#viewOnGithubButton").attr("href", "https://github.com/kubernetes/kubernetes.github.io/tree/master/" + forwarding) } else { $("#generalInstructions").show(); $("#continueEdit").hide(); @@ -26,6 +28,7 @@ $( document ).ready(function() {

Click the button below to edit the page you were just on. When you are done, click Commit Changes at the bottom of the screen. This creates a copy of our site in your GitHub account called a fork. You can make other changes in your fork after it is created, if you want. When you are ready to send us all your changes, go to the index page for your fork and click New Pull Request to let us know about it.

+

From f0cd49a00759ae00b467ef37c3228b000263cdf3 Mon Sep 17 00:00:00 2001 From: Andrew Chen Date: Mon, 20 Mar 2017 15:35:51 -0700 Subject: [PATCH 12/21] Move Guide topics: Container Lifestyle Hooks, Images, Volumes --- _data/concepts.yml | 9 + .../manage-compute-resources-container.md | 2 +- docs/concepts/configuration/overview.md | 2 +- .../containers/container-lifecycle-hooks.md | 105 ++++ docs/concepts/containers/images.md | 320 ++++++++++ docs/concepts/overview/what-is-kubernetes.md | 2 +- docs/concepts/storage/volumes.md | 578 ++++++++++++++++++ .../workloads/controllers/statefulset.md | 4 +- docs/concepts/workloads/pods/pod-lifecycle.md | 2 +- docs/getting-started-guides/minikube.md | 2 +- docs/getting-started-guides/vsphere.md | 2 +- docs/tasks/administer-cluster/overview.md | 2 +- .../attach-handler-lifecycle-event.md | 4 +- .../configure-pod-initialization.md | 2 +- .../configure-volume-storage.md | 6 +- .../distribute-credentials-secure.md | 2 +- .../pull-image-private-registry.md | 2 +- .../index.md | 2 +- .../basic-stateful-set.md | 4 +- .../run-stateful-application.md | 2 +- .../stateful-application/zookeeper.md | 2 +- docs/user-guide/container-environment.md | 102 +--- docs/user-guide/docker-cli-to-kubectl.md | 2 +- docs/user-guide/images.md | 317 +--------- docs/user-guide/index.md | 6 +- docs/user-guide/persistent-volumes/index.md | 2 +- docs/user-guide/petset.md | 2 +- docs/user-guide/pods/index.md | 4 +- docs/user-guide/secrets/index.md | 4 +- docs/user-guide/service-accounts.md | 2 +- docs/user-guide/ui.md | 4 +- docs/user-guide/volumes.md | 575 +---------------- docs/user-guide/walkthrough/index.md | 2 +- test/examples_test.go | 2 +- 34 files changed, 1055 insertions(+), 1025 deletions(-) create mode 100644 docs/concepts/containers/container-lifecycle-hooks.md create mode 100644 docs/concepts/containers/images.md create mode 100644 docs/concepts/storage/volumes.md diff --git a/_data/concepts.yml b/_data/concepts.yml index 80d336f98b..b2a8efb30c 100644 --- a/_data/concepts.yml +++ b/_data/concepts.yml @@ -14,6 +14,11 @@ toc: - docs/concepts/overview/working-with-objects/annotations.md - docs/concepts/overview/kubernetes-api.md +- title: Containers + section: + - docs/concepts/containers/images.md + - docs/concepts/containers/container-lifecycle-hooks.md + - title: Workloads section: - title: Pods @@ -48,6 +53,10 @@ toc: - docs/concepts/cluster-administration/access-cluster.md - docs/concepts/cluster-administration/authenticate-across-clusters-kubeconfig.md +- title: Storage + section: + - docs/concepts/storage/volumes.md + - title: Services, Load Balancing, and Networking section: - docs/concepts/services-networking/dns-pod-service.md diff --git a/docs/concepts/configuration/manage-compute-resources-container.md b/docs/concepts/configuration/manage-compute-resources-container.md index 2754260d65..ad83ae955d 100644 --- a/docs/concepts/configuration/manage-compute-resources-container.md +++ b/docs/concepts/configuration/manage-compute-resources-container.md @@ -395,7 +395,7 @@ spec: Kubernetes version 1.5 only allows resource quantities to be specified on a Container. It is planned to improve accounting for resources that are shared by all Containers in a Pod, such as -[emptyDir volumes](/docs/user-guide/volumes/#emptydir). +[emptyDir volumes](/docs/concepts/storage/volumes/#emptydir). Kubernetes version 1.5 only supports Container requests and limits for CPU and memory. It is planned to add new resource types, including a node disk space diff --git a/docs/concepts/configuration/overview.md b/docs/concepts/configuration/overview.md index 0d2192b03a..2d3a2103ad 100644 --- a/docs/concepts/configuration/overview.md +++ b/docs/concepts/configuration/overview.md @@ -93,7 +93,7 @@ This document is meant to highlight and consolidate in one place configuration b ## Container Images -- The [default container image pull policy](/docs/user-guide/images/) is `IfNotPresent`, which causes the +- The [default container image pull policy](/docs/concepts/containers/images/) is `IfNotPresent`, which causes the [Kubelet](/docs/admin/kubelet/) to not pull an image if it already exists. If you would like to always force a pull, you must specify a pull image policy of `Always` in your .yaml file (`imagePullPolicy: Always`) or specify a `:latest` tag on your image. diff --git a/docs/concepts/containers/container-lifecycle-hooks.md b/docs/concepts/containers/container-lifecycle-hooks.md new file mode 100644 index 0000000000..dd00180bb7 --- /dev/null +++ b/docs/concepts/containers/container-lifecycle-hooks.md @@ -0,0 +1,105 @@ +--- +assignees: +- mikedanese +- thockin +title: Container Lifecycle Hooks +--- + +This document describes the environment for Kubelet managed containers on a Kubernetes node (kNode).  In contrast to the Kubernetes cluster API, which provides an API for creating and managing containers, the Kubernetes container environment provides the container access to information about what else is going on in the cluster. + +This cluster information makes it possible to build applications that are *cluster aware*. +Additionally, the Kubernetes container environment defines a series of hooks that are surfaced to optional hook handlers defined as part of individual containers.  Container hooks are somewhat analogous to operating system signals in a traditional process model.   However these hooks are designed to make it easier to build reliable, scalable cloud applications in the Kubernetes cluster.  Containers that participate in this cluster lifecycle become *cluster native*. + +Another important part of the container environment is the file system that is available to the container. In Kubernetes, the filesystem is a combination of an [image](/docs/concepts/containers/images/) and one or more [volumes](/docs/concepts/storage/volumes/). + +The following sections describe both the cluster information provided to containers, as well as the hooks and life-cycle that allows containers to interact with the management system. + +* TOC +{:toc} + +## Cluster Information + +There are two types of information that are available within the container environment.  There is information about the container itself, and there is information about other objects in the system. + +### Container Information + +Currently, the Pod name for the pod in which the container is running is set as the hostname of the container, and is accessible through all calls to access the hostname within the container (e.g. the hostname command, or the [gethostname][1] function call in libc), but this is planned to change in the future and should not be used. + +The Pod name and namespace are also available as environment variables via the [downward API](/docs/user-guide/downward-api). Additionally, user-defined environment variables from the pod definition, are also available to the container, as are any environment variables specified statically in the Docker image. + +In the future, we anticipate expanding this information with richer information about the container.  Examples include available memory, number of restarts, and in general any state that you could get from the call to GET /pods on the API server. + +### Cluster Information + +Currently the list of all services that are running at the time when the container was created via the Kubernetes Cluster API are available to the container as environment variables.  The set of environment variables matches the syntax of Docker links. + +For a service named **foo** that maps to a container port named **bar**, the following variables are defined: + +```shell +FOO_SERVICE_HOST= +FOO_SERVICE_PORT= +``` + +Services have dedicated IP address, and are also surfaced to the container via DNS (If [DNS addon](http://releases.k8s.io/{{page.githubbranch}}/cluster/addons/dns/) is enabled).  Of course DNS is still not an enumerable protocol, so we will continue to provide environment variables so that containers can do discovery. + +## Container Hooks + +Container hooks provide information to the container about events in its management lifecycle.  For example, immediately after a container is started, it receives a *PostStart* hook.  These hooks are broadcast *into* the container with information about the life-cycle of the container.  They are different from the events provided by Docker and other systems which are *output* from the container.  Output events provide a log of what has already happened.  Input hooks provide real-time notification about things that are happening, but no historical log. + +### Hook Details + +There are currently two container hooks that are surfaced to containers: + +*PostStart* + +This hook is sent immediately after a container is created.  It notifies the container that it has been created.  No parameters are passed to the handler. It is NOT guaranteed that the hook will execute before the container entrypoint. + +*PreStop* + +This hook is called immediately before a container is terminated. No parameters are passed to the handler. This event handler is blocking, and must complete before the call to delete the container is sent to the Docker daemon. The SIGTERM notification sent by Docker is also still sent. A more complete description of termination behavior can be found in [Termination of Pods](/docs/user-guide/pods/#termination-of-pods). + +### Hook Handler Execution + +When a management hook occurs, the management system calls into any registered hook handlers in the container for that hook.  These hook handler calls are synchronous in the context of the pod containing the container. This means that for a `PostStart` hook, the container entrypoint and hook will fire asynchronously. However, if the hook takes a while to run or hangs, the container will never reach a "running" state. The behavior is similar for a `PreStop` hook. If the hook hangs during execution, the Pod phase will stay in a "running" state and never reach "failed." If a `PostStart` or `PreStop` hook fails, it will kill the container. + +Typically we expect that users will make their hook handlers as lightweight as possible, but there are cases where long running commands make sense (e.g. saving state prior to container stop). + +### Hook delivery guarantees + +Hook delivery is intended to be "at least once", which means that a hook may be called multiple times for any given event (e.g. "start" or "stop") and it is up to the hook implementer to be able to handle this +correctly. + +We expect double delivery to be rare, but in some cases if the Kubelet restarts in the middle of sending a hook, the hook may be resent after the Kubelet comes back up. + +Likewise, we only make a single delivery attempt. If (for example) an http hook receiver is down, and unable to take traffic, we do not make any attempts to resend. + +Currently, there are (hopefully rare) scenarios where PostStart hooks may not be delivered. + +### Hook Handler Implementations + +Hook handlers are the way that hooks are surfaced to containers.  Containers can select the type of hook handler they would like to implement.  Kubernetes currently supports two different hook handler types: + + * Exec - Executes a specific command (e.g. pre-stop.sh) inside the cgroups and namespaces of the container.  Resources consumed by the command are counted against the container. + + * HTTP - Executes an HTTP request against a specific endpoint on the container. + +[1]: http://man7.org/linux/man-pages/man2/gethostname.2.html + +### Debugging Hook Handlers + +Currently, the logs for a hook handler are not exposed in the pod events. If your handler fails for some reason, it will emit an event. For `PostStart`, this is the `FailedPostStartHook` event. For `PreStop` this is the `FailedPreStopHook` event. You can see these events by running `kubectl describe pod `. An example output of events from runing this command is below: + +``` +Events: + FirstSeen LastSeen Count From SubobjectPath Type Reason Message + --------- -------- ----- ---- ------------- -------- ------ ------- + 1m 1m 1 {default-scheduler } Normal Scheduled Successfully assigned test-1730497541-cq1d2 to gke-test-cluster-default-pool-a07e5d30-siqd + 1m 1m 1 {kubelet gke-test-cluster-default-pool-a07e5d30-siqd} spec.containers{main} Normal Pulling pulling image "test:1.0" + 1m 1m 1 {kubelet gke-test-cluster-default-pool-a07e5d30-siqd} spec.containers{main} Normal Created Created container with docker id 5c6a256a2567; Security:[seccomp=unconfined] + 1m 1m 1 {kubelet gke-test-cluster-default-pool-a07e5d30-siqd} spec.containers{main} Normal Pulled Successfully pulled image "test:1.0" + 1m 1m 1 {kubelet gke-test-cluster-default-pool-a07e5d30-siqd} spec.containers{main} Normal Started Started container with docker id 5c6a256a2567 + 38s 38s 1 {kubelet gke-test-cluster-default-pool-a07e5d30-siqd} spec.containers{main} Normal Killing Killing container with docker id 5c6a256a2567: PostStart handler: Error executing in Docker Container: 1 + 37s 37s 1 {kubelet gke-test-cluster-default-pool-a07e5d30-siqd} spec.containers{main} Normal Killing Killing container with docker id 8df9fdfd7054: PostStart handler: Error executing in Docker Container: 1 + 38s 37s 2 {kubelet gke-test-cluster-default-pool-a07e5d30-siqd} Warning FailedSync Error syncing pod, skipping: failed to "StartContainer" for "main" with RunContainerError: "PostStart handler: Error executing in Docker Container: 1" + 1m 22s 2 {kubelet gke-test-cluster-default-pool-a07e5d30-siqd} spec.containers{main} Warning FailedPostStartHook +``` \ No newline at end of file diff --git a/docs/concepts/containers/images.md b/docs/concepts/containers/images.md new file mode 100644 index 0000000000..80d349c3ea --- /dev/null +++ b/docs/concepts/containers/images.md @@ -0,0 +1,320 @@ +--- +assignees: +- erictune +- thockin +title: Images +--- + +Each container in a pod has its own image. Currently, the only type of image supported is a [Docker Image](https://docs.docker.com/engine/tutorials/dockerimages/). + +You create your Docker image and push it to a registry before referring to it in a Kubernetes pod. + +The `image` property of a container supports the same syntax as the `docker` command does, including private registries and tags. + +* TOC +{:toc} + + +## Updating Images + +The default pull policy is `IfNotPresent` which causes the Kubelet to not +pull an image if it already exists. If you would like to always force a pull +you must set a pull image policy of `Always` or specify a `:latest` tag on +your image. + +If you did not specify tag of your image, it will be assumed as `:latest`, with +pull image policy of `Always` correspondingly. + +Note that you should avoid using `:latest` tag, see [Best Practices for Configuration](/docs/concepts/configuration/overview/#container-images) for more information. + +## Using a Private Registry + +Private registries may require keys to read images from them. +Credentials can be provided in several ways: + + - Using Google Container Registry + - Per-cluster + - automatically configured on Google Compute Engine or Google Container Engine + - all pods can read the project's private registry + - Using AWS EC2 Container Registry (ECR) + - use IAM roles and policies to control access to ECR repositories + - automatically refreshes ECR login credentials + - Using Azure Container Registry (ACR) + - Configuring Nodes to Authenticate to a Private Registry + - all pods can read any configured private registries + - requires node configuration by cluster administrator + - Pre-pulling Images + - all pods can use any images cached on a node + - requires root access to all nodes to setup + - Specifying ImagePullSecrets on a Pod + - only pods which provide own keys can access the private registry +Each option is described in more detail below. + + +### Using Google Container Registry + +Kubernetes has native support for the [Google Container +Registry (GCR)](https://cloud.google.com/tools/container-registry/), when running on Google Compute +Engine (GCE). If you are running your cluster on GCE or Google Container Engine (GKE), simply +use the full image name (e.g. gcr.io/my_project/image:tag). + +All pods in a cluster will have read access to images in this registry. + +The kubelet will authenticate to GCR using the instance's +Google service account. The service account on the instance +will have a `https://www.googleapis.com/auth/devstorage.read_only`, +so it can pull from the project's GCR, but not push. + +### Using AWS EC2 Container Registry + +Kubernetes has native support for the [AWS EC2 Container +Registry](https://aws.amazon.com/ecr/), when nodes are AWS EC2 instances. + +Simply use the full image name (e.g. `ACCOUNT.dkr.ecr.REGION.amazonaws.com/imagename:tag`) +in the Pod definition. + +All users of the cluster who can create pods will be able to run pods that use any of the +images in the ECR registry. + +The kubelet will fetch and periodically refresh ECR credentials. It needs the following permissions to do this: + +- `ecr:GetAuthorizationToken` +- `ecr:BatchCheckLayerAvailability` +- `ecr:GetDownloadUrlForLayer` +- `ecr:GetRepositoryPolicy` +- `ecr:DescribeRepositories` +- `ecr:ListImages` +- `ecr:BatchGetImage` + +Requirements: + +- You must be using kubelet version `v1.2.0` or newer. (e.g. run `/usr/bin/kubelet --version=true`). +- If your nodes are in region A and your registry is in a different region B, you need version `v1.3.0` or newer. +- ECR must be offered in your region + +Troubleshooting: + +- Verify all requirements above. +- Get $REGION (e.g. `us-west-2`) credentials on your workstation. SSH into the host and run Docker manually with those creds. Does it work? +- Verify kubelet is running with `--cloud-provider=aws`. +- Check kubelet logs (e.g. `journalctl -t kubelet`) for log lines like: + - `plugins.go:56] Registering credential provider: aws-ecr-key` + - `provider.go:91] Refreshing cache for provider: *aws_credentials.ecrProvider` + +### Using Azure Container Registry (ACR) +When using [Azure Container Registry](https://azure.microsoft.com/en-us/services/container-registry/) +you can authenticate using either an admin user or a service principal. +In either case, authentication is done via standard Docker authentication. These instructions assume the +[azure-cli](https://github.com/azure/azure-cli) command line tool. + +You first need to create a registry and generate credentials, complete documentation for this can be found in +the [Azure container registry documentation](https://docs.microsoft.com/en-us/azure/container-registry/container-registry-get-started-azure-cli). + +Once you have created your container registry, you will use the following credentials to login: + * `DOCKER_USER` : service principal, or admin username + * `DOCKER_PASSWORD`: service principal password, or admin user password + * `DOCKER_REGISTRY_SERVER`: `${some-registry-name}.azurecr.io` + * `DOCKER_EMAIL`: `${some-email-address}` + +Once you have those variables filled in you can [configure a Kubernetes Secret and use it to deploy a Pod] +(/docs/concepts/containers/images/#specifying-imagepullsecrets-on-a-pod). + + +### Configuring Nodes to Authenticate to a Private Repository + +**Note:** if you are running on Google Container Engine (GKE), there will already be a `.dockercfg` on each node +with credentials for Google Container Registry. You cannot use this approach. + +**Note:** if you are running on AWS EC2 and are using the EC2 Container Registry (ECR), the kubelet on each node will +manage and update the ECR login credentials. You cannot use this approach. + +**Note:** this approach is suitable if you can control node configuration. It +will not work reliably on GCE, and any other cloud provider that does automatic +node replacement. + +Docker stores keys for private registries in the `$HOME/.dockercfg` or `$HOME/.docker/config.json` file. If you put this +in the `$HOME` of user `root` on a kubelet, then docker will use it. + +Here are the recommended steps to configuring your nodes to use a private registry. In this +example, run these on your desktop/laptop: + + 1. Run `docker login [server]` for each set of credentials you want to use. This updates `$HOME/.docker/config.json`. + 1. View `$HOME/.docker/config.json` in an editor to ensure it contains just the credentials you want to use. + 1. Get a list of your nodes, for example: + - if you want the names: `nodes=$(kubectl get nodes -o jsonpath='{range.items[*].metadata}{.name} {end}')` + - if you want to get the IPs: `nodes=$(kubectl get nodes -o jsonpath='{range .items[*].status.addresses[?(@.type=="ExternalIP")]}{.address} {end}')` + 1. Copy your local `.docker/config.json` to the home directory of root on each node. + - for example: `for n in $nodes; do scp ~/.docker/config.json root@$n:/root/.docker/config.json; done` + +Verify by creating a pod that uses a private image, e.g.: + +```yaml +$ cat < /tmp/private-image-test-1.yaml +apiVersion: v1 +kind: Pod +metadata: + name: private-image-test-1 +spec: + containers: + - name: uses-private-image + image: $PRIVATE_IMAGE_NAME + imagePullPolicy: Always + command: [ "echo", "SUCCESS" ] +EOF +$ kubectl create -f /tmp/private-image-test-1.yaml +pods/private-image-test-1 +$ +``` + +If everything is working, then, after a few moments, you should see: + +```shell +$ kubectl logs private-image-test-1 +SUCCESS +``` + +If it failed, then you will see: + +```shell +$ kubectl describe pods/private-image-test-1 | grep "Failed" + Fri, 26 Jun 2015 15:36:13 -0700 Fri, 26 Jun 2015 15:39:13 -0700 19 {kubelet node-i2hq} spec.containers{uses-private-image} failed Failed to pull image "user/privaterepo:v1": Error: image user/privaterepo:v1 not found +``` + + +You must ensure all nodes in the cluster have the same `.docker/config.json`. Otherwise, pods will run on +some nodes and fail to run on others. For example, if you use node autoscaling, then each instance +template needs to include the `.docker/config.json` or mount a drive that contains it. + +All pods will have read access to images in any private registry once private +registry keys are added to the `.docker/config.json`. + +**This was tested with a private docker repository as of 26 June with Kubernetes version v0.19.3. +It should also work for a private registry such as quay.io, but that has not been tested.** + +### Pre-pulling Images + +**Note:** if you are running on Google Container Engine (GKE), there will already be a `.dockercfg` on each node +with credentials for Google Container Registry. You cannot use this approach. + +**Note:** this approach is suitable if you can control node configuration. It +will not work reliably on GCE, and any other cloud provider that does automatic +node replacement. + +Be default, the kubelet will try to pull each image from the specified registry. +However, if the `imagePullPolicy` property of the container is set to `IfNotPresent` or `Never`, +then a local image is used (preferentially or exclusively, respectively). + +If you want to rely on pre-pulled images as a substitute for registry authentication, +you must ensure all nodes in the cluster have the same pre-pulled images. + +This can be used to preload certain images for speed or as an alternative to authenticating to a private registry. + +All pods will have read access to any pre-pulled images. + +### Specifying ImagePullSecrets on a Pod + +**Note:** This approach is currently the recommended approach for GKE, GCE, and any cloud-providers +where node creation is automated. + +Kubernetes supports specifying registry keys on a pod. + +#### Creating a Secret with a Docker Config + +Run the following command, substituting the appropriate uppercase values: + +```shell +$ kubectl create secret docker-registry myregistrykey --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL +secret "myregistrykey" created. +``` + +If you need access to multiple registries, you can create one secret for each registry. +Kubelet will merge any `imagePullSecrets` into a single virtual `.docker/config.json` +when pulling images for your Pods. + +Pods can only reference image pull secrets in their own namespace, +so this process needs to be done one time per namespace. + +##### Bypassing kubectl create secrets + +If for some reason you need multiple items in a single `.docker/config.json` or need +control not given by the above command, then you can [create a secret using +json or yaml](/docs/user-guide/secrets/#creating-a-secret-manually). + +Be sure to: + +- set the name of the data item to `.dockerconfigjson` +- base64 encode the docker file and paste that string, unbroken + as the value for field `data[".dockerconfigjson"]` +- set `type` to `kubernetes.io/dockerconfigjson` + +Example: + +```yaml +apiVersion: v1 +kind: Secret +metadata: + name: myregistrykey + namespace: awesomeapps +data: + .dockerconfigjson: UmVhbGx5IHJlYWxseSByZWVlZWVlZWVlZWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGx5eXl5eXl5eXl5eXl5eXl5eXl5eSBsbGxsbGxsbGxsbGxsbG9vb29vb29vb29vb29vb29vb29vb29vb29vb25ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubmdnZ2dnZ2dnZ2dnZ2dnZ2dnZ2cgYXV0aCBrZXlzCg== +type: kubernetes.io/dockerconfigjson +``` + +If you get the error message `error: no objects passed to create`, it may mean the base64 encoded string is invalid. +If you get an error message like `Secret "myregistrykey" is invalid: data[.dockerconfigjson]: invalid value ...` it means +the data was successfully un-base64 encoded, but could not be parsed as a `.docker/config.json` file. + +#### Referring to an imagePullSecrets on a Pod + +Now, you can create pods which reference that secret by adding an `imagePullSecrets` +section to a pod definition. + +```yaml +apiVersion: v1 +kind: Pod +metadata: + name: foo + namespace: awesomeapps +spec: + containers: + - name: foo + image: janedoe/awesomeapp:v1 + imagePullSecrets: + - name: myregistrykey +``` + +This needs to be done for each pod that is using a private registry. + +However, setting of this field can be automated by setting the imagePullSecrets +in a [serviceAccount](/docs/user-guide/service-accounts) resource. + +You can use this in conjunction with a per-node `.docker/config.json`. The credentials +will be merged. This approach will work on Google Container Engine (GKE). + +### Use Cases + +There are a number of solutions for configuring private registries. Here are some +common use cases and suggested solutions. + +1. Cluster running only non-proprietary (e.g. open-source) images. No need to hide images. + - Use public images on the Docker hub. + - no configuration required + - on GCE/GKE, a local mirror is automatically used for improved speed and availability +1. Cluster running some proprietary images which should be hidden to those outside the company, but + visible to all cluster users. + - Use a hosted private [Docker registry](https://docs.docker.com/registry/) + - may be hosted on the [Docker Hub](https://hub.docker.com/account/signup/), or elsewhere. + - manually configure .docker/config.json on each node as described above + - Or, run an internal private registry behind your firewall with open read access. + - no Kubernetes configuration required + - Or, when on GCE/GKE, use the project's Google Container Registry. + - will work better with cluster autoscaling than manual node configuration + - Or, on a cluster where changing the node configuration is inconvenient, use `imagePullSecrets`. +1. Cluster with a proprietary images, a few of which require stricter access control + - ensure [AlwaysPullImages admission controller](/docs/admin/admission-controllers/#alwayspullimages) is active, otherwise, all Pods potentially have access to all images + - Move sensitive data into a "Secret" resource, instead of packaging it in an image. +1. A multi-tenant cluster where each tenant needs own private registry + - ensure [AlwaysPullImages admission controller](/docs/admin/admission-controllers/#alwayspullimages) is active, otherwise, all Pods of all tenants potentially have access to all images + - run a private registry with authorization required. + - generate registry credential for each tenant, put into secret, and populate secret to each tenant namespace. + - tenant adds that secret to imagePullSecrets of each namespace. diff --git a/docs/concepts/overview/what-is-kubernetes.md b/docs/concepts/overview/what-is-kubernetes.md index 378a1f2c47..0c71b6caea 100644 --- a/docs/concepts/overview/what-is-kubernetes.md +++ b/docs/concepts/overview/what-is-kubernetes.md @@ -67,7 +67,7 @@ At a minimum, Kubernetes can schedule and run application containers on clusters Kubernetes satisfies a number of common needs of applications running in production, such as: * [co-locating helper processes](/docs/user-guide/pods/), facilitating composite applications and preserving the one-application-per-container model, -* [mounting storage systems](/docs/user-guide/volumes/), +* [mounting storage systems](/docs/concepts/storage/volumes/), * [distributing secrets](/docs/user-guide/secrets/), * [application health checking](/docs/user-guide/production-pods/#liveness-and-readiness-probes-aka-health-checks), * [replicating application instances](/docs/user-guide/replication-controller/), diff --git a/docs/concepts/storage/volumes.md b/docs/concepts/storage/volumes.md new file mode 100644 index 0000000000..762518fc8f --- /dev/null +++ b/docs/concepts/storage/volumes.md @@ -0,0 +1,578 @@ +--- +assignees: +- jsafrane +- mikedanese +- saad-ali +- thockin +title: Volumes +--- + +On-disk files in a container are ephemeral, which presents some problems for +non-trivial applications when running in containers. First, when a container +crashes kubelet will restart it, but the files will be lost - the +container starts with a clean state. Second, when running containers together +in a `Pod` it is often necessary to share files between those containers. The +Kubernetes `Volume` abstraction solves both of these problems. + +Familiarity with [pods](/docs/user-guide/pods) is suggested. + +* TOC +{:toc} + + +## Background + +Docker also has a concept of +[volumes](https://docs.docker.com/userguide/dockervolumes/), though it is +somewhat looser and less managed. In Docker, a volume is simply a directory on +disk or in another container. Lifetimes are not managed and until very +recently there were only local-disk-backed volumes. Docker now provides volume +drivers, but the functionality is very limited for now (e.g. as of Docker 1.7 +only one volume driver is allowed per container and there is no way to pass +parameters to volumes). + +A Kubernetes volume, on the other hand, has an explicit lifetime - the same as +the pod that encloses it. Consequently, a volume outlives any containers that run +within the Pod, and data is preserved across Container restarts. Of course, when a +Pod ceases to exist, the volume will cease to exist, too. Perhaps more +importantly than this, Kubernetes supports many type of volumes, and a Pod can +use any number of them simultaneously. + +At its core, a volume is just a directory, possibly with some data in it, which +is accessible to the containers in a pod. How that directory comes to be, the +medium that backs it, and the contents of it are determined by the particular +volume type used. + +To use a volume, a pod specifies what volumes to provide for the pod (the +[`spec.volumes`](http://kubernetes.io/kubernetes/third_party/swagger-ui/#!/v1/createPod) +field) and where to mount those into containers(the +[`spec.containers.volumeMounts`](http://kubernetes.io/kubernetes/third_party/swagger-ui/#!/v1/createPod) +field). + +A process in a container sees a filesystem view composed from their Docker +image and volumes. The [Docker +image](https://docs.docker.com/userguide/dockerimages/) is at the root of the +filesystem hierarchy, and any volumes are mounted at the specified paths within +the image. Volumes can not mount onto other volumes or have hard links to +other volumes. Each container in the Pod must independently specify where to +mount each volume. + +## Types of Volumes + +Kubernetes supports several types of Volumes: + + * `emptyDir` + * `hostPath` + * `gcePersistentDisk` + * `awsElasticBlockStore` + * `nfs` + * `iscsi` + * `flocker` + * `glusterfs` + * `rbd` + * `cephfs` + * `gitRepo` + * `secret` + * `persistentVolumeClaim` + * `downwardAPI` + * `azureFileVolume` + * `azureDisk` + * `vsphereVolume` + * `Quobyte` + +We welcome additional contributions. + +### emptyDir + +An `emptyDir` volume is first created when a Pod is assigned to a Node, and +exists as long as that Pod is running on that node. As the name says, it is +initially empty. Containers in the pod can all read and write the same +files in the `emptyDir` volume, though that volume can be mounted at the same +or different paths in each container. When a Pod is removed from a node for +any reason, the data in the `emptyDir` is deleted forever. NOTE: a container +crashing does *NOT* remove a pod from a node, so the data in an `emptyDir` +volume is safe across container crashes. + +Some uses for an `emptyDir` are: + +* scratch space, such as for a disk-based merge sort +* checkpointing a long computation for recovery from crashes +* holding files that a content-manager container fetches while a webserver + container serves the data + +By default, `emptyDir` volumes are stored on whatever medium is backing the +machine - that might be disk or SSD or network storage, depending on your +environment. However, you can set the `emptyDir.medium` field to `"Memory"` +to tell Kubernetes to mount a tmpfs (RAM-backed filesystem) for you instead. +While tmpfs is very fast, be aware that unlike disks, tmpfs is cleared on +machine reboot and any files you write will count against your container's +memory limit. + +#### Example pod + +```yaml +apiVersion: v1 +kind: Pod +metadata: + name: test-pd +spec: + containers: + - image: gcr.io/google_containers/test-webserver + name: test-container + volumeMounts: + - mountPath: /cache + name: cache-volume + volumes: + - name: cache-volume + emptyDir: {} +``` + +### hostPath + +A `hostPath` volume mounts a file or directory from the host node's filesystem +into your pod. This is not something that most Pods will need, but it offers a +powerful escape hatch for some applications. + +For example, some uses for a `hostPath` are: + +* running a container that needs access to Docker internals; use a `hostPath` + of `/var/lib/docker` +* running cAdvisor in a container; use a `hostPath` of `/dev/cgroups` + +Watch out when using this type of volume, because: + +* pods with identical configuration (such as created from a podTemplate) may + behave differently on different nodes due to different files on the nodes +* when Kubernetes adds resource-aware scheduling, as is planned, it will not be + able to account for resources used by a `hostPath` +* the directories created on the underlying hosts are only writable by root. You + either need to run your process as root in a + [privileged container](/docs/user-guide/security-context) or modify the file + permissions on the host to be able to write to a `hostPath` volume + +#### Example pod + +```yaml +apiVersion: v1 +kind: Pod +metadata: + name: test-pd +spec: + containers: + - image: gcr.io/google_containers/test-webserver + name: test-container + volumeMounts: + - mountPath: /test-pd + name: test-volume + volumes: + - name: test-volume + hostPath: + # directory location on host + path: /data +``` + +#### Example pod + +```yaml +apiVersion: v1 +kind: Pod +metadata: + name: test-hostpath +spec: + containers: + - image: myimage + name: test-container + volumeMounts: + - mountPath: /test-hostpath + name: test-volume + volumes: + - name: test-volume + hostPath: + path: /path/to/my/dir +``` + +### gcePersistentDisk + +A `gcePersistentDisk` volume mounts a Google Compute Engine (GCE) [Persistent +Disk](http://cloud.google.com/compute/docs/disks) into your pod. Unlike +`emptyDir`, which is erased when a Pod is removed, the contents of a PD are +preserved and the volume is merely unmounted. This means that a PD can be +pre-populated with data, and that data can be "handed off" between pods. + +__Important: You must create a PD using `gcloud` or the GCE API or UI +before you can use it__ + +There are some restrictions when using a `gcePersistentDisk`: + +* the nodes on which pods are running must be GCE VMs +* those VMs need to be in the same GCE project and zone as the PD + +A feature of PD is that they can be mounted as read-only by multiple consumers +simultaneously. This means that you can pre-populate a PD with your dataset +and then serve it in parallel from as many pods as you need. Unfortunately, +PDs can only be mounted by a single consumer in read-write mode - no +simultaneous writers allowed. + +Using a PD on a pod controlled by a ReplicationController will fail unless +the PD is read-only or the replica count is 0 or 1. + +#### Creating a PD + +Before you can use a GCE PD with a pod, you need to create it. + +```shell +gcloud compute disks create --size=500GB --zone=us-central1-a my-data-disk +``` + +#### Example pod + +```yaml +apiVersion: v1 +kind: Pod +metadata: + name: test-pd +spec: + containers: + - image: gcr.io/google_containers/test-webserver + name: test-container + volumeMounts: + - mountPath: /test-pd + name: test-volume + volumes: + - name: test-volume + # This GCE PD must already exist. + gcePersistentDisk: + pdName: my-data-disk + fsType: ext4 +``` + +### awsElasticBlockStore + +An `awsElasticBlockStore` volume mounts an Amazon Web Services (AWS) [EBS +Volume](http://aws.amazon.com/ebs/) into your pod. Unlike +`emptyDir`, which is erased when a Pod is removed, the contents of an EBS +volume are preserved and the volume is merely unmounted. This means that an +EBS volume can be pre-populated with data, and that data can be "handed off" +between pods. + +__Important: You must create an EBS volume using `aws ec2 create-volume` or +the AWS API before you can use it__ + +There are some restrictions when using an awsElasticBlockStore volume: + +* the nodes on which pods are running must be AWS EC2 instances +* those instances need to be in the same region and availability-zone as the EBS volume +* EBS only supports a single EC2 instance mounting a volume + +#### Creating an EBS volume + +Before you can use an EBS volume with a pod, you need to create it. + +```shell +aws ec2 create-volume --availability-zone eu-west-1a --size 10 --volume-type gp2 +``` + +Make sure the zone matches the zone you brought up your cluster in. (And also check that the size and EBS volume +type are suitable for your use!) + +#### AWS EBS Example configuration + +```yaml +apiVersion: v1 +kind: Pod +metadata: + name: test-ebs +spec: + containers: + - image: gcr.io/google_containers/test-webserver + name: test-container + volumeMounts: + - mountPath: /test-ebs + name: test-volume + volumes: + - name: test-volume + # This AWS EBS volume must already exist. + awsElasticBlockStore: + volumeID: + fsType: ext4 +``` + +### nfs + +An `nfs` volume allows an existing NFS (Network File System) share to be +mounted into your pod. Unlike `emptyDir`, which is erased when a Pod is +removed, the contents of an `nfs` volume are preserved and the volume is merely +unmounted. This means that an NFS volume can be pre-populated with data, and +that data can be "handed off" between pods. NFS can be mounted by multiple +writers simultaneously. + +__Important: You must have your own NFS server running with the share exported +before you can use it__ + +See the [NFS example](https://github.com/kubernetes/kubernetes/tree/{{page.githubbranch}}/examples/volumes/nfs) for more details. + +### iscsi + +An `iscsi` volume allows an existing iSCSI (SCSI over IP) volume to be mounted +into your pod. Unlike `emptyDir`, which is erased when a Pod is removed, the +contents of an `iscsi` volume are preserved and the volume is merely +unmounted. This means that an iscsi volume can be pre-populated with data, and +that data can be "handed off" between pods. + +__Important: You must have your own iSCSI server running with the volume +created before you can use it__ + +A feature of iSCSI is that it can be mounted as read-only by multiple consumers +simultaneously. This means that you can pre-populate a volume with your dataset +and then serve it in parallel from as many pods as you need. Unfortunately, +iSCSI volumes can only be mounted by a single consumer in read-write mode - no +simultaneous writers allowed. + +See the [iSCSI example](https://github.com/kubernetes/kubernetes/tree/{{page.githubbranch}}/examples/volumes/iscsi) for more details. + +### flocker + +[Flocker](https://clusterhq.com/flocker) is an open-source clustered container data volume manager. It provides management +and orchestration of data volumes backed by a variety of storage backends. + +A `flocker` volume allows a Flocker dataset to be mounted into a pod. If the +dataset does not already exist in Flocker, it needs to be first created with the Flocker +CLI or by using the Flocker API. If the dataset already exists it will be +reattached by Flocker to the node that the pod is scheduled. This means data +can be "handed off" between pods as required. + +__Important: You must have your own Flocker installation running before you can use it__ + +See the [Flocker example](https://github.com/kubernetes/kubernetes/tree/{{page.githubbranch}}/examples/volumes/flocker) for more details. + +### glusterfs + +A `glusterfs` volume allows a [Glusterfs](http://www.gluster.org) (an open +source networked filesystem) volume to be mounted into your pod. Unlike +`emptyDir`, which is erased when a Pod is removed, the contents of a +`glusterfs` volume are preserved and the volume is merely unmounted. This +means that a glusterfs volume can be pre-populated with data, and that data can +be "handed off" between pods. GlusterFS can be mounted by multiple writers +simultaneously. + +__Important: You must have your own GlusterFS installation running before you +can use it__ + +See the [GlusterFS example](https://github.com/kubernetes/kubernetes/tree/{{page.githubbranch}}/examples/volumes/glusterfs) for more details. + +### rbd + +An `rbd` volume allows a [Rados Block +Device](http://ceph.com/docs/master/rbd/rbd/) volume to be mounted into your +pod. Unlike `emptyDir`, which is erased when a Pod is removed, the contents of +a `rbd` volume are preserved and the volume is merely unmounted. This +means that a RBD volume can be pre-populated with data, and that data can +be "handed off" between pods. + +__Important: You must have your own Ceph installation running before you +can use RBD__ + +A feature of RBD is that it can be mounted as read-only by multiple consumers +simultaneously. This means that you can pre-populate a volume with your dataset +and then serve it in parallel from as many pods as you need. Unfortunately, +RBD volumes can only be mounted by a single consumer in read-write mode - no +simultaneous writers allowed. + +See the [RBD example](https://github.com/kubernetes/kubernetes/tree/{{page.githubbranch}}/examples/volumes/rbd) for more details. + +### cephfs + +A `cephfs` volume allows an existing CephFS volume to be +mounted into your pod. Unlike `emptyDir`, which is erased when a Pod is +removed, the contents of a `cephfs` volume are preserved and the volume is merely +unmounted. This means that a CephFS volume can be pre-populated with data, and +that data can be "handed off" between pods. CephFS can be mounted by multiple +writers simultaneously. + +__Important: You must have your own Ceph server running with the share exported +before you can use it__ + +See the [CephFS example](https://github.com/kubernetes/kubernetes/tree/{{page.githubbranch}}/examples/volumes/cephfs/) for more details. + +### gitRepo + +A `gitRepo` volume is an example of what can be done as a volume plugin. It +mounts an empty directory and clones a git repository into it for your pod to +use. In the future, such volumes may be moved to an even more decoupled model, +rather than extending the Kubernetes API for every such use case. + +Here is an example for gitRepo volume: + +```yaml +apiVersion: v1 +kind: Pod +metadata: + name: server +spec: + containers: + - image: nginx + name: nginx + volumeMounts: + - mountPath: /mypath + name: git-volume + volumes: + - name: git-volume + gitRepo: + repository: "git@somewhere:me/my-git-repository.git" + revision: "22f1d8406d464b0c0874075539c1f2e96c253775" +``` + +### secret + +A `secret` volume is used to pass sensitive information, such as passwords, to +pods. You can store secrets in the Kubernetes API and mount them as files for +use by pods without coupling to Kubernetes directly. `secret` volumes are +backed by tmpfs (a RAM-backed filesystem) so they are never written to +non-volatile storage. + +__Important: You must create a secret in the Kubernetes API before you can use +it__ + +Secrets are described in more detail [here](/docs/user-guide/secrets). + +### persistentVolumeClaim + +A `persistentVolumeClaim` volume is used to mount a +[PersistentVolume](/docs/user-guide/persistent-volumes) into a pod. PersistentVolumes are a +way for users to "claim" durable storage (such as a GCE PersistentDisk or an +iSCSI volume) without knowing the details of the particular cloud environment. + +See the [PersistentVolumes example](/docs/user-guide/persistent-volumes/) for more +details. + +### downwardAPI + +A `downwardAPI` volume is used to make downward API data available to applications. +It mounts a directory and writes the requested data in plain text files. + +See the [`downwardAPI` volume example](/docs/user-guide/downward-api/volume/) for more details. + +### FlexVolume + +A `FlexVolume` enables users to mount vendor volumes into a pod. It expects vendor +drivers are installed in the volume plugin path on each kubelet node. This is +an alpha feature and may change in future. + +More details are in [here](https://github.com/kubernetes/kubernetes/tree/{{page.githubbranch}}/examples/volumes/flexvolume/README.md) + +### AzureFileVolume + +A `AzureFileVolume` is used to mount a Microsoft Azure File Volume (SMB 2.1 and 3.0) +into a Pod. + +More details can be found [here](https://github.com/kubernetes/kubernetes/tree/{{page.githubbranch}}/examples/volumes/azure_file/README.md) + +### AzureDiskVolume + +A `AzureDiskVolume` is used to mount a Microsoft Azure [Data Disk](https://azure.microsoft.com/en-us/documentation/articles/virtual-machines-linux-about-disks-vhds/) into a Pod. + +More details can be found [here](https://github.com/kubernetes/kubernetes/tree/{{page.githubbranch}}/examples/volumes/azure_disk/README.md) + +### vsphereVolume + +__Prerequisite: Kubernetes with vSphere Cloud Provider configured. +For cloudprovider configuration please refer [vSphere getting started guide](http://kubernetes.io/docs/getting-started-guides/vsphere/).__ + +A `vsphereVolume` is used to mount a vSphere VMDK Volume into your Pod. The contents +of a volume are preserved when it is unmounted. It supports both VMFS and VSAN datastore. + +__Important: You must create VMDK using one of the following method before using with POD.__ + +#### Creating a VMDK volume + +* Create using vmkfstools. + + First ssh into ESX and then use following command to create vmdk, + +```shell + vmkfstools -c 2G /vmfs/volumes/DatastoreName/volumes/myDisk.vmdk +``` + +* Create using vmware-vdiskmanager. +```shell + vmware-vdiskmanager -c -t 0 -s 40GB -a lsilogic myDisk.vmdk +``` + +#### vSphere VMDK Example configuration + +```yaml +apiVersion: v1 +kind: Pod +metadata: + name: test-vmdk +spec: + containers: + - image: gcr.io/google_containers/test-webserver + name: test-container + volumeMounts: + - mountPath: /test-vmdk + name: test-volume + volumes: + - name: test-volume + # This VMDK volume must already exist. + vsphereVolume: + volumePath: "[DatastoreName] volumes/myDisk" + fsType: ext4 +``` +More examples can be found [here](https://github.com/kubernetes/kubernetes/tree/master/examples/volumes/vsphere). + + +### Quobyte + +A `Quobyte` volume allows an existing [Quobyte](http://www.quobyte.com) volume to be mounted into your pod. + +__Important: You must have your own Quobyte setup running with the volumes created +before you can use it__ + +See the [Quobyte example](https://github.com/kubernetes/kubernetes/tree/{{page.githubbranch}}/examples/volumes/quobyte) for more details. + +## Using subPath + +Sometimes, it is useful to share one volume for multiple uses in a single pod. The `volumeMounts.subPath` +property can be used to specify a sub-path inside the referenced volume instead of its root. + +Here is an example of a pod with a LAMP stack (Linux Apache Mysql PHP) using a single, shared volume. +The HTML contents are mapped to its `html` folder, and the databases will be stored in its `mysql` folder: + +```yaml +apiVersion: v1 +kind: Pod +metadata: + name: my-lamp-site +spec: + containers: + - name: mysql + image: mysql + volumeMounts: + - mountPath: /var/lib/mysql + name: site-data + subPath: mysql + - name: php + image: php + volumeMounts: + - mountPath: /var/www/html + name: site-data + subPath: html + volumes: + - name: site-data + persistentVolumeClaim: + claimName: my-lamp-site-data +``` + +## Resources + +The storage media (Disk, SSD, etc.) of an `emptyDir` volume is determined by the +medium of the filesystem holding the kubelet root dir (typically +`/var/lib/kubelet`). There is no limit on how much space an `emptyDir` or +`hostPath` volume can consume, and no isolation between containers or between +pods. + +In the future, we expect that `emptyDir` and `hostPath` volumes will be able to +request a certain amount of space using a [resource](/docs/user-guide/compute-resources) +specification, and to select the type of media to use, for clusters that have +several media types. diff --git a/docs/concepts/workloads/controllers/statefulset.md b/docs/concepts/workloads/controllers/statefulset.md index 6995702821..ea87d418eb 100644 --- a/docs/concepts/workloads/controllers/statefulset.md +++ b/docs/concepts/workloads/controllers/statefulset.md @@ -55,7 +55,7 @@ The example below demonstrates the components of a StatefulSet. * A Headless Service, named nginx, is used to control the network domain. * The StatefulSet, named web, has a Spec that indicates that 3 replicas of the nginx container will be launched in unique Pods. -* The volumeClaimTemplates will provide stable storage using [PersistentVolumes](/docs/user-guide/volumes/) provisioned by a +* The volumeClaimTemplates will provide stable storage using [PersistentVolumes](/docs/concepts/storage/volumes/) provisioned by a PersistentVolume Provisioner. ```yaml @@ -144,7 +144,7 @@ Note that Cluster Domain will be set to `cluster.local` unless ### Stable Storage -Kubernetes creates one [PersistentVolume](/docs/user-guide/volumes/) for each +Kubernetes creates one [PersistentVolume](/docs/concepts/storage/volumes/) for each VolumeClaimTemplate. In the nginx example above, each Pod will receive a single PersistentVolume with a storage class of `anything` and 1 Gib of provisioned storage. When a Pod is (re)scheduled onto a node, its `volumeMounts` mount the PersistentVolumes associated with its diff --git a/docs/concepts/workloads/pods/pod-lifecycle.md b/docs/concepts/workloads/pods/pod-lifecycle.md index 540ba506fc..878df7166b 100644 --- a/docs/concepts/workloads/pods/pod-lifecycle.md +++ b/docs/concepts/workloads/pods/pod-lifecycle.md @@ -274,7 +274,7 @@ spec: * Get hands-on experience [configuring liveness and readiness probes](/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/). -* [Container Lifecycle Hooks](/docs/user-guide/container-environment/) +* [Container Lifecycle Hooks](/docs/concepts/containers/container-lifecycle-hooks/) {% endcapture %} diff --git a/docs/getting-started-guides/minikube.md b/docs/getting-started-guides/minikube.md index e0e79364cf..1fb35c3d6f 100644 --- a/docs/getting-started-guides/minikube.md +++ b/docs/getting-started-guides/minikube.md @@ -266,7 +266,7 @@ Some drivers will mount a host folder within the VM so that you can easily share ## Private Container Registries -To access a private container registry, follow the steps on [this page](http://kubernetes.io/docs/user-guide/images/). +To access a private container registry, follow the steps on [this page](/docs/concepts/containers/images/). We recommend you use ImagePullSecrets, but if you would like to configure access on the minikube VM you can place the `.dockercfg` in the `/home/docker` directory or the `config.json` in the `/home/docker/.docker` directory. diff --git a/docs/getting-started-guides/vsphere.md b/docs/getting-started-guides/vsphere.md index a22d38609f..9c442d858e 100644 --- a/docs/getting-started-guides/vsphere.md +++ b/docs/getting-started-guides/vsphere.md @@ -34,7 +34,7 @@ Documentation for how to use vSphere managed storage can be found in the [persistent volumes user guide](http://kubernetes.io/docs/user-guide/persistent-volumes/#vsphere) and the [volumes user -guide](http://kubernetes.io/docs/user-guide/volumes/#vspherevolume) +guide](/docs/concepts/storage/volumes/#vspherevolume) Examples can be found [here](https://github.com/kubernetes/kubernetes/tree/master/examples/volumes/vsphere) diff --git a/docs/tasks/administer-cluster/overview.md b/docs/tasks/administer-cluster/overview.md index 3aead8a3a4..b544885d45 100644 --- a/docs/tasks/administer-cluster/overview.md +++ b/docs/tasks/administer-cluster/overview.md @@ -70,7 +70,7 @@ project](/docs/admin/salt). ## Security -* **Kubernetes Container Environment** ([docs/user-guide/container-environment.md](/docs/user-guide/container-environment)): +* **Kubernetes Container Environment** ([docs/user-guide/container-environment.md](/docs/concepts/containers/container-lifecycle-hooks/)): Describes the environment for Kubelet managed containers on a Kubernetes node. diff --git a/docs/tasks/configure-pod-container/attach-handler-lifecycle-event.md b/docs/tasks/configure-pod-container/attach-handler-lifecycle-event.md index a46f910714..68c2977fc4 100644 --- a/docs/tasks/configure-pod-container/attach-handler-lifecycle-event.md +++ b/docs/tasks/configure-pod-container/attach-handler-lifecycle-event.md @@ -79,8 +79,8 @@ unless the Pod's grace period expires. For more details, see {% capture whatsnext %} -* Learn more about [Container lifecycle hooks](/docs/user-guide/container-environment/.) -* Learn more about the [lifecycle of a Pod](https://kubernetes.io/docs/user-guide/pod-states/). +* Learn more about [Container lifecycle hooks](/docs/concepts/containers/container-lifecycle-hooks/). +* Learn more about the [lifecycle of a Pod](/docs/user-guide/pod-states/). ### Reference diff --git a/docs/tasks/configure-pod-container/configure-pod-initialization.md b/docs/tasks/configure-pod-container/configure-pod-initialization.md index 7aa2bff40a..0c72d7ab84 100644 --- a/docs/tasks/configure-pod-container/configure-pod-initialization.md +++ b/docs/tasks/configure-pod-container/configure-pod-initialization.md @@ -84,7 +84,7 @@ The output shows that nginx is serving the web page that was written by the init * Learn more about [communicating between Containers running in the same Pod](/docs/tasks/configure-pod-container/communicate-containers-same-pod/). * Learn more about [init Containers](/docs/user-guide/pods/init-container/). -* Learn more about [Volumes](/docs/user-guide/volumes/). +* Learn more about [Volumes](/docs/concepts/storage/volumes/). {% endcapture %} diff --git a/docs/tasks/configure-pod-container/configure-volume-storage.md b/docs/tasks/configure-pod-container/configure-volume-storage.md index 92756615a8..f639e3cf00 100644 --- a/docs/tasks/configure-pod-container/configure-volume-storage.md +++ b/docs/tasks/configure-pod-container/configure-volume-storage.md @@ -9,7 +9,7 @@ This page shows how to configure a Pod to use a Volume for storage. A Container's file system lives only as long as the Container does, so when a Container terminates and restarts, changes to the filesystem are lost. For more consistent storage that is independent of the Container, you can use a -[Volume](/docs/user-guide/volumes). This is especially important for stateful +[Volume](/docs/concepts/storage/volumes/). This is especially important for stateful applications, such as key-value stores and databases. For example, Redis is a key-value cache and store. @@ -27,7 +27,7 @@ key-value cache and store. In this exercise, you create a Pod that runs one Container. This Pod has a Volume of type -[emptyDir](/docs/user-guide/volumes/#emptydir) +[emptyDir](/docs/concepts/storage/volumes/#emptydir) that lasts for the life of the Pod, even if the Container terminates and restarts. Here is the configuration file for the Pod: @@ -103,7 +103,7 @@ of `Always`. supports many different network-attached storage solutions, including PD on GCE and EBS on EC2, which are preferred for critical data, and will handle details such as mounting and unmounting the devices on the nodes. See -[Volumes](/docs/user-guide/volumes) for more details. +[Volumes](/docs/concepts/storage/volumes/) for more details. {% endcapture %} diff --git a/docs/tasks/configure-pod-container/distribute-credentials-secure.md b/docs/tasks/configure-pod-container/distribute-credentials-secure.md index 6dcd642262..eb812577d2 100644 --- a/docs/tasks/configure-pod-container/distribute-credentials-secure.md +++ b/docs/tasks/configure-pod-container/distribute-credentials-secure.md @@ -161,7 +161,7 @@ Here is a configuration file you can use to create a Pod: {% capture whatsnext %} * Learn more about [Secrets](/docs/user-guide/secrets/). -* Learn about [Volumes](/docs/user-guide/volumes/). +* Learn about [Volumes](/docs/concepts/storage/volumes/). ### Reference diff --git a/docs/tasks/configure-pod-container/pull-image-private-registry.md b/docs/tasks/configure-pod-container/pull-image-private-registry.md index f54d881178..45faf7b4a9 100644 --- a/docs/tasks/configure-pod-container/pull-image-private-registry.md +++ b/docs/tasks/configure-pod-container/pull-image-private-registry.md @@ -122,7 +122,7 @@ Create a Pod that uses your Secret, and verify that the Pod is running: * Learn more about [Secrets](/docs/user-guide/secrets/). * Learn more about -[using a private registry](/docs/user-guide/images/#using-a-private-registry). +[using a private registry](/docs/concepts/containers/images/#using-a-private-registry). * See [kubectl create secret docker-registry](/docs/user-guide/kubectl/kubectl_create_secret_docker-registry/). * See [Secret](/docs/api-reference/v1/definitions/#_v1_secret) * See the `imagePullSecrets` field of diff --git a/docs/tasks/job/fine-parallel-processing-work-queue/index.md b/docs/tasks/job/fine-parallel-processing-work-queue/index.md index 5442026205..e01a1c8a8b 100644 --- a/docs/tasks/job/fine-parallel-processing-work-queue/index.md +++ b/docs/tasks/job/fine-parallel-processing-work-queue/index.md @@ -134,7 +134,7 @@ docker push /job-wq-2 ``` You need to push to a public repository or [configure your cluster to be able to access -your private repository](/docs/user-guide/images). +your private repository](/docs/concepts/containers/images/). If you are using [Google Container Registry](https://cloud.google.com/tools/container-registry/), tag diff --git a/docs/tutorials/stateful-application/basic-stateful-set.md b/docs/tutorials/stateful-application/basic-stateful-set.md index 2a72070ac8..309efb2946 100644 --- a/docs/tutorials/stateful-application/basic-stateful-set.md +++ b/docs/tutorials/stateful-application/basic-stateful-set.md @@ -24,7 +24,7 @@ following Kubernetes concepts. * [Pods](/docs/user-guide/pods/single-container/) * [Cluster DNS](/docs/admin/dns/) * [Headless Services](/docs/user-guide/services/#headless-services) -* [PersistentVolumes](/docs/user-guide/volumes/) +* [PersistentVolumes](/docs/concepts/storage/volumes/) * [PersistentVolume Provisioning](http://releases.k8s.io/{{page.githubbranch}}/examples/persistent-volume-provisioning/) * [StatefulSets](/docs/concepts/abstractions/controllers/statefulsets/) * [kubectl CLI](/docs/user-guide/kubectl) @@ -265,7 +265,7 @@ www-web-0 Bound pvc-15c268c7-b507-11e6-932f-42010a800002 1Gi RWO www-web-1 Bound pvc-15c79307-b507-11e6-932f-42010a800002 1Gi RWO 48s ``` The StatefulSet controller created two PersistentVolumeClaims that are -bound to two [PersistentVolumes](/docs/user-guide/volumes/). As the cluster used +bound to two [PersistentVolumes](/docs/concepts/storage/volumes/). As the cluster used in this tutorial is configured to dynamically provision PersistentVolumes, the PersistentVolumes were created and bound automatically. diff --git a/docs/tutorials/stateful-application/run-stateful-application.md b/docs/tutorials/stateful-application/run-stateful-application.md index dc7655831f..7a0856abb6 100644 --- a/docs/tutorials/stateful-application/run-stateful-application.md +++ b/docs/tutorials/stateful-application/run-stateful-application.md @@ -214,7 +214,7 @@ gcloud compute disks delete mysql-disk * [kubectl run documentation](/docs/user-guide/kubectl/kubectl_run/) -* [Volumes](/docs/user-guide/volumes/) and [Persistent Volumes](/docs/user-guide/persistent-volumes/) +* [Volumes](/docs/concepts/storage/volumes/) and [Persistent Volumes](/docs/user-guide/persistent-volumes/) {% endcapture %} diff --git a/docs/tutorials/stateful-application/zookeeper.md b/docs/tutorials/stateful-application/zookeeper.md index e31d8e280b..9ee4b77713 100644 --- a/docs/tutorials/stateful-application/zookeeper.md +++ b/docs/tutorials/stateful-application/zookeeper.md @@ -25,7 +25,7 @@ Kubernetes concepts. * [Pods](/docs/user-guide/pods/single-container/) * [Cluster DNS](/docs/admin/dns/) * [Headless Services](/docs/user-guide/services/#headless-services) -* [PersistentVolumes](/docs/user-guide/volumes/) +* [PersistentVolumes](/docs/concepts/storage/volumes/) * [PersistentVolume Provisioning](http://releases.k8s.io/{{page.githubbranch}}/examples/persistent-volume-provisioning/) * [ConfigMaps](/docs/user-guide/configmap/) * [StatefulSets](/docs/concepts/abstractions/controllers/statefulsets/) diff --git a/docs/user-guide/container-environment.md b/docs/user-guide/container-environment.md index cf8cb037f7..c15c8a3e50 100644 --- a/docs/user-guide/container-environment.md +++ b/docs/user-guide/container-environment.md @@ -1,105 +1,7 @@ --- -assignees: -- mikedanese -- thockin title: Container Lifecycle Hooks --- -This document describes the environment for Kubelet managed containers on a Kubernetes node (kNode).  In contrast to the Kubernetes cluster API, which provides an API for creating and managing containers, the Kubernetes container environment provides the container access to information about what else is going on in the cluster. +{% include user-guide-content-moved.md %} -This cluster information makes it possible to build applications that are *cluster aware*. -Additionally, the Kubernetes container environment defines a series of hooks that are surfaced to optional hook handlers defined as part of individual containers.  Container hooks are somewhat analogous to operating system signals in a traditional process model.   However these hooks are designed to make it easier to build reliable, scalable cloud applications in the Kubernetes cluster.  Containers that participate in this cluster lifecycle become *cluster native*. - -Another important part of the container environment is the file system that is available to the container. In Kubernetes, the filesystem is a combination of an [image](/docs/user-guide/images) and one or more [volumes](/docs/user-guide/volumes). - -The following sections describe both the cluster information provided to containers, as well as the hooks and life-cycle that allows containers to interact with the management system. - -* TOC -{:toc} - -## Cluster Information - -There are two types of information that are available within the container environment.  There is information about the container itself, and there is information about other objects in the system. - -### Container Information - -Currently, the Pod name for the pod in which the container is running is set as the hostname of the container, and is accessible through all calls to access the hostname within the container (e.g. the hostname command, or the [gethostname][1] function call in libc), but this is planned to change in the future and should not be used. - -The Pod name and namespace are also available as environment variables via the [downward API](/docs/user-guide/downward-api). Additionally, user-defined environment variables from the pod definition, are also available to the container, as are any environment variables specified statically in the Docker image. - -In the future, we anticipate expanding this information with richer information about the container.  Examples include available memory, number of restarts, and in general any state that you could get from the call to GET /pods on the API server. - -### Cluster Information - -Currently the list of all services that are running at the time when the container was created via the Kubernetes Cluster API are available to the container as environment variables.  The set of environment variables matches the syntax of Docker links. - -For a service named **foo** that maps to a container port named **bar**, the following variables are defined: - -```shell -FOO_SERVICE_HOST= -FOO_SERVICE_PORT= -``` - -Services have dedicated IP address, and are also surfaced to the container via DNS (If [DNS addon](http://releases.k8s.io/{{page.githubbranch}}/cluster/addons/dns/) is enabled).  Of course DNS is still not an enumerable protocol, so we will continue to provide environment variables so that containers can do discovery. - -## Container Hooks - -Container hooks provide information to the container about events in its management lifecycle.  For example, immediately after a container is started, it receives a *PostStart* hook.  These hooks are broadcast *into* the container with information about the life-cycle of the container.  They are different from the events provided by Docker and other systems which are *output* from the container.  Output events provide a log of what has already happened.  Input hooks provide real-time notification about things that are happening, but no historical log. - -### Hook Details - -There are currently two container hooks that are surfaced to containers: - -*PostStart* - -This hook is sent immediately after a container is created.  It notifies the container that it has been created.  No parameters are passed to the handler. It is NOT guaranteed that the hook will execute before the container entrypoint. - -*PreStop* - -This hook is called immediately before a container is terminated. No parameters are passed to the handler. This event handler is blocking, and must complete before the call to delete the container is sent to the Docker daemon. The SIGTERM notification sent by Docker is also still sent. A more complete description of termination behavior can be found in [Termination of Pods](/docs/user-guide/pods/#termination-of-pods). - -### Hook Handler Execution - -When a management hook occurs, the management system calls into any registered hook handlers in the container for that hook.  These hook handler calls are synchronous in the context of the pod containing the container. This means that for a `PostStart` hook, the container entrypoint and hook will fire asynchronously. However, if the hook takes a while to run or hangs, the container will never reach a "running" state. The behavior is similar for a `PreStop` hook. If the hook hangs during execution, the Pod phase will stay in a "running" state and never reach "failed." If a `PostStart` or `PreStop` hook fails, it will kill the container. - -Typically we expect that users will make their hook handlers as lightweight as possible, but there are cases where long running commands make sense (e.g. saving state prior to container stop). - -### Hook delivery guarantees - -Hook delivery is intended to be "at least once", which means that a hook may be called multiple times for any given event (e.g. "start" or "stop") and it is up to the hook implementer to be able to handle this -correctly. - -We expect double delivery to be rare, but in some cases if the Kubelet restarts in the middle of sending a hook, the hook may be resent after the Kubelet comes back up. - -Likewise, we only make a single delivery attempt. If (for example) an http hook receiver is down, and unable to take traffic, we do not make any attempts to resend. - -Currently, there are (hopefully rare) scenarios where PostStart hooks may not be delivered. - -### Hook Handler Implementations - -Hook handlers are the way that hooks are surfaced to containers.  Containers can select the type of hook handler they would like to implement.  Kubernetes currently supports two different hook handler types: - - * Exec - Executes a specific command (e.g. pre-stop.sh) inside the cgroups and namespaces of the container.  Resources consumed by the command are counted against the container. - - * HTTP - Executes an HTTP request against a specific endpoint on the container. - -[1]: http://man7.org/linux/man-pages/man2/gethostname.2.html - -### Debugging Hook Handlers - -Currently, the logs for a hook handler are not exposed in the pod events. If your handler fails for some reason, it will emit an event. For `PostStart`, this is the `FailedPostStartHook` event. For `PreStop` this is the `FailedPreStopHook` event. You can see these events by running `kubectl describe pod `. An example output of events from runing this command is below: - -``` -Events: - FirstSeen LastSeen Count From SubobjectPath Type Reason Message - --------- -------- ----- ---- ------------- -------- ------ ------- - 1m 1m 1 {default-scheduler } Normal Scheduled Successfully assigned test-1730497541-cq1d2 to gke-test-cluster-default-pool-a07e5d30-siqd - 1m 1m 1 {kubelet gke-test-cluster-default-pool-a07e5d30-siqd} spec.containers{main} Normal Pulling pulling image "test:1.0" - 1m 1m 1 {kubelet gke-test-cluster-default-pool-a07e5d30-siqd} spec.containers{main} Normal Created Created container with docker id 5c6a256a2567; Security:[seccomp=unconfined] - 1m 1m 1 {kubelet gke-test-cluster-default-pool-a07e5d30-siqd} spec.containers{main} Normal Pulled Successfully pulled image "test:1.0" - 1m 1m 1 {kubelet gke-test-cluster-default-pool-a07e5d30-siqd} spec.containers{main} Normal Started Started container with docker id 5c6a256a2567 - 38s 38s 1 {kubelet gke-test-cluster-default-pool-a07e5d30-siqd} spec.containers{main} Normal Killing Killing container with docker id 5c6a256a2567: PostStart handler: Error executing in Docker Container: 1 - 37s 37s 1 {kubelet gke-test-cluster-default-pool-a07e5d30-siqd} spec.containers{main} Normal Killing Killing container with docker id 8df9fdfd7054: PostStart handler: Error executing in Docker Container: 1 - 38s 37s 2 {kubelet gke-test-cluster-default-pool-a07e5d30-siqd} Warning FailedSync Error syncing pod, skipping: failed to "StartContainer" for "main" with RunContainerError: "PostStart handler: Error executing in Docker Container: 1" - 1m 22s 2 {kubelet gke-test-cluster-default-pool-a07e5d30-siqd} spec.containers{main} Warning FailedPostStartHook -``` \ No newline at end of file +[Container Lifecycle Hooks](/docs/concepts/containers/container-lifecycle-hooks/) \ No newline at end of file diff --git a/docs/user-guide/docker-cli-to-kubectl.md b/docs/user-guide/docker-cli-to-kubectl.md index e288d237ef..0de0d03b7d 100644 --- a/docs/user-guide/docker-cli-to-kubectl.md +++ b/docs/user-guide/docker-cli-to-kubectl.md @@ -209,7 +209,7 @@ Notice that we don't delete the pod directly. With kubectl we want to delete the #### docker login -There is no direct analog of `docker login` in kubectl. If you are interested in using Kubernetes with a private registry, see [Using a Private Registry](/docs/user-guide/images/#using-a-private-registry). +There is no direct analog of `docker login` in kubectl. If you are interested in using Kubernetes with a private registry, see [Using a Private Registry](/docs/concepts/containers/images/#using-a-private-registry). #### docker version diff --git a/docs/user-guide/images.md b/docs/user-guide/images.md index 0d12db8904..2605a436b8 100644 --- a/docs/user-guide/images.md +++ b/docs/user-guide/images.md @@ -1,320 +1,7 @@ --- -assignees: -- erictune -- thockin title: Images --- -Each container in a pod has its own image. Currently, the only type of image supported is a [Docker Image](https://docs.docker.com/engine/tutorials/dockerimages/). +{% include user-guide-content-moved.md %} -You create your Docker image and push it to a registry before referring to it in a Kubernetes pod. - -The `image` property of a container supports the same syntax as the `docker` command does, including private registries and tags. - -* TOC -{:toc} - - -## Updating Images - -The default pull policy is `IfNotPresent` which causes the Kubelet to not -pull an image if it already exists. If you would like to always force a pull -you must set a pull image policy of `Always` or specify a `:latest` tag on -your image. - -If you did not specify tag of your image, it will be assumed as `:latest`, with -pull image policy of `Always` correspondingly. - -Note that you should avoid using `:latest` tag, see [Best Practices for Configuration](/docs/concepts/configuration/overview/#container-images) for more information. - -## Using a Private Registry - -Private registries may require keys to read images from them. -Credentials can be provided in several ways: - - - Using Google Container Registry - - Per-cluster - - automatically configured on Google Compute Engine or Google Container Engine - - all pods can read the project's private registry - - Using AWS EC2 Container Registry (ECR) - - use IAM roles and policies to control access to ECR repositories - - automatically refreshes ECR login credentials - - Using Azure Container Registry (ACR) - - Configuring Nodes to Authenticate to a Private Registry - - all pods can read any configured private registries - - requires node configuration by cluster administrator - - Pre-pulling Images - - all pods can use any images cached on a node - - requires root access to all nodes to setup - - Specifying ImagePullSecrets on a Pod - - only pods which provide own keys can access the private registry -Each option is described in more detail below. - - -### Using Google Container Registry - -Kubernetes has native support for the [Google Container -Registry (GCR)](https://cloud.google.com/tools/container-registry/), when running on Google Compute -Engine (GCE). If you are running your cluster on GCE or Google Container Engine (GKE), simply -use the full image name (e.g. gcr.io/my_project/image:tag). - -All pods in a cluster will have read access to images in this registry. - -The kubelet will authenticate to GCR using the instance's -Google service account. The service account on the instance -will have a `https://www.googleapis.com/auth/devstorage.read_only`, -so it can pull from the project's GCR, but not push. - -### Using AWS EC2 Container Registry - -Kubernetes has native support for the [AWS EC2 Container -Registry](https://aws.amazon.com/ecr/), when nodes are AWS EC2 instances. - -Simply use the full image name (e.g. `ACCOUNT.dkr.ecr.REGION.amazonaws.com/imagename:tag`) -in the Pod definition. - -All users of the cluster who can create pods will be able to run pods that use any of the -images in the ECR registry. - -The kubelet will fetch and periodically refresh ECR credentials. It needs the following permissions to do this: - -- `ecr:GetAuthorizationToken` -- `ecr:BatchCheckLayerAvailability` -- `ecr:GetDownloadUrlForLayer` -- `ecr:GetRepositoryPolicy` -- `ecr:DescribeRepositories` -- `ecr:ListImages` -- `ecr:BatchGetImage` - -Requirements: - -- You must be using kubelet version `v1.2.0` or newer. (e.g. run `/usr/bin/kubelet --version=true`). -- If your nodes are in region A and your registry is in a different region B, you need version `v1.3.0` or newer. -- ECR must be offered in your region - -Troubleshooting: - -- Verify all requirements above. -- Get $REGION (e.g. `us-west-2`) credentials on your workstation. SSH into the host and run Docker manually with those creds. Does it work? -- Verify kubelet is running with `--cloud-provider=aws`. -- Check kubelet logs (e.g. `journalctl -t kubelet`) for log lines like: - - `plugins.go:56] Registering credential provider: aws-ecr-key` - - `provider.go:91] Refreshing cache for provider: *aws_credentials.ecrProvider` - -### Using Azure Container Registry (ACR) -When using [Azure Container Registry](https://azure.microsoft.com/en-us/services/container-registry/) -you can authenticate using either an admin user or a service principal. -In either case, authentication is done via standard Docker authentication. These instructions assume the -[azure-cli](https://github.com/azure/azure-cli) command line tool. - -You first need to create a registry and generate credentials, complete documentation for this can be found in -the [Azure container registry documentation](https://docs.microsoft.com/en-us/azure/container-registry/container-registry-get-started-azure-cli). - -Once you have created your container registry, you will use the following credentials to login: - * `DOCKER_USER` : service principal, or admin username - * `DOCKER_PASSWORD`: service principal password, or admin user password - * `DOCKER_REGISTRY_SERVER`: `${some-registry-name}.azurecr.io` - * `DOCKER_EMAIL`: `${some-email-address}` - -Once you have those variables filled in you can [configure a Kubernetes Secret and use it to deploy a Pod] -(http://kubernetes.io/docs/user-guide/images/#specifying-imagepullsecrets-on-a-pod). - - -### Configuring Nodes to Authenticate to a Private Repository - -**Note:** if you are running on Google Container Engine (GKE), there will already be a `.dockercfg` on each node -with credentials for Google Container Registry. You cannot use this approach. - -**Note:** if you are running on AWS EC2 and are using the EC2 Container Registry (ECR), the kubelet on each node will -manage and update the ECR login credentials. You cannot use this approach. - -**Note:** this approach is suitable if you can control node configuration. It -will not work reliably on GCE, and any other cloud provider that does automatic -node replacement. - -Docker stores keys for private registries in the `$HOME/.dockercfg` or `$HOME/.docker/config.json` file. If you put this -in the `$HOME` of user `root` on a kubelet, then docker will use it. - -Here are the recommended steps to configuring your nodes to use a private registry. In this -example, run these on your desktop/laptop: - - 1. Run `docker login [server]` for each set of credentials you want to use. This updates `$HOME/.docker/config.json`. - 1. View `$HOME/.docker/config.json` in an editor to ensure it contains just the credentials you want to use. - 1. Get a list of your nodes, for example: - - if you want the names: `nodes=$(kubectl get nodes -o jsonpath='{range.items[*].metadata}{.name} {end}')` - - if you want to get the IPs: `nodes=$(kubectl get nodes -o jsonpath='{range .items[*].status.addresses[?(@.type=="ExternalIP")]}{.address} {end}')` - 1. Copy your local `.docker/config.json` to the home directory of root on each node. - - for example: `for n in $nodes; do scp ~/.docker/config.json root@$n:/root/.docker/config.json; done` - -Verify by creating a pod that uses a private image, e.g.: - -```yaml -$ cat < /tmp/private-image-test-1.yaml -apiVersion: v1 -kind: Pod -metadata: - name: private-image-test-1 -spec: - containers: - - name: uses-private-image - image: $PRIVATE_IMAGE_NAME - imagePullPolicy: Always - command: [ "echo", "SUCCESS" ] -EOF -$ kubectl create -f /tmp/private-image-test-1.yaml -pods/private-image-test-1 -$ -``` - -If everything is working, then, after a few moments, you should see: - -```shell -$ kubectl logs private-image-test-1 -SUCCESS -``` - -If it failed, then you will see: - -```shell -$ kubectl describe pods/private-image-test-1 | grep "Failed" - Fri, 26 Jun 2015 15:36:13 -0700 Fri, 26 Jun 2015 15:39:13 -0700 19 {kubelet node-i2hq} spec.containers{uses-private-image} failed Failed to pull image "user/privaterepo:v1": Error: image user/privaterepo:v1 not found -``` - - -You must ensure all nodes in the cluster have the same `.docker/config.json`. Otherwise, pods will run on -some nodes and fail to run on others. For example, if you use node autoscaling, then each instance -template needs to include the `.docker/config.json` or mount a drive that contains it. - -All pods will have read access to images in any private registry once private -registry keys are added to the `.docker/config.json`. - -**This was tested with a private docker repository as of 26 June with Kubernetes version v0.19.3. -It should also work for a private registry such as quay.io, but that has not been tested.** - -### Pre-pulling Images - -**Note:** if you are running on Google Container Engine (GKE), there will already be a `.dockercfg` on each node -with credentials for Google Container Registry. You cannot use this approach. - -**Note:** this approach is suitable if you can control node configuration. It -will not work reliably on GCE, and any other cloud provider that does automatic -node replacement. - -Be default, the kubelet will try to pull each image from the specified registry. -However, if the `imagePullPolicy` property of the container is set to `IfNotPresent` or `Never`, -then a local image is used (preferentially or exclusively, respectively). - -If you want to rely on pre-pulled images as a substitute for registry authentication, -you must ensure all nodes in the cluster have the same pre-pulled images. - -This can be used to preload certain images for speed or as an alternative to authenticating to a private registry. - -All pods will have read access to any pre-pulled images. - -### Specifying ImagePullSecrets on a Pod - -**Note:** This approach is currently the recommended approach for GKE, GCE, and any cloud-providers -where node creation is automated. - -Kubernetes supports specifying registry keys on a pod. - -#### Creating a Secret with a Docker Config - -Run the following command, substituting the appropriate uppercase values: - -```shell -$ kubectl create secret docker-registry myregistrykey --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL -secret "myregistrykey" created. -``` - -If you need access to multiple registries, you can create one secret for each registry. -Kubelet will merge any `imagePullSecrets` into a single virtual `.docker/config.json` -when pulling images for your Pods. - -Pods can only reference image pull secrets in their own namespace, -so this process needs to be done one time per namespace. - -##### Bypassing kubectl create secrets - -If for some reason you need multiple items in a single `.docker/config.json` or need -control not given by the above command, then you can [create a secret using -json or yaml](/docs/user-guide/secrets/#creating-a-secret-manually). - -Be sure to: - -- set the name of the data item to `.dockerconfigjson` -- base64 encode the docker file and paste that string, unbroken - as the value for field `data[".dockerconfigjson"]` -- set `type` to `kubernetes.io/dockerconfigjson` - -Example: - -```yaml -apiVersion: v1 -kind: Secret -metadata: - name: myregistrykey - namespace: awesomeapps -data: - .dockerconfigjson: UmVhbGx5IHJlYWxseSByZWVlZWVlZWVlZWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGx5eXl5eXl5eXl5eXl5eXl5eXl5eSBsbGxsbGxsbGxsbGxsbG9vb29vb29vb29vb29vb29vb29vb29vb29vb25ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubmdnZ2dnZ2dnZ2dnZ2dnZ2dnZ2cgYXV0aCBrZXlzCg== -type: kubernetes.io/dockerconfigjson -``` - -If you get the error message `error: no objects passed to create`, it may mean the base64 encoded string is invalid. -If you get an error message like `Secret "myregistrykey" is invalid: data[.dockerconfigjson]: invalid value ...` it means -the data was successfully un-base64 encoded, but could not be parsed as a `.docker/config.json` file. - -#### Referring to an imagePullSecrets on a Pod - -Now, you can create pods which reference that secret by adding an `imagePullSecrets` -section to a pod definition. - -```yaml -apiVersion: v1 -kind: Pod -metadata: - name: foo - namespace: awesomeapps -spec: - containers: - - name: foo - image: janedoe/awesomeapp:v1 - imagePullSecrets: - - name: myregistrykey -``` - -This needs to be done for each pod that is using a private registry. - -However, setting of this field can be automated by setting the imagePullSecrets -in a [serviceAccount](/docs/user-guide/service-accounts) resource. - -You can use this in conjunction with a per-node `.docker/config.json`. The credentials -will be merged. This approach will work on Google Container Engine (GKE). - -### Use Cases - -There are a number of solutions for configuring private registries. Here are some -common use cases and suggested solutions. - -1. Cluster running only non-proprietary (e.g. open-source) images. No need to hide images. - - Use public images on the Docker hub. - - no configuration required - - on GCE/GKE, a local mirror is automatically used for improved speed and availability -1. Cluster running some proprietary images which should be hidden to those outside the company, but - visible to all cluster users. - - Use a hosted private [Docker registry](https://docs.docker.com/registry/) - - may be hosted on the [Docker Hub](https://hub.docker.com/account/signup/), or elsewhere. - - manually configure .docker/config.json on each node as described above - - Or, run an internal private registry behind your firewall with open read access. - - no Kubernetes configuration required - - Or, when on GCE/GKE, use the project's Google Container Registry. - - will work better with cluster autoscaling than manual node configuration - - Or, on a cluster where changing the node configuration is inconvenient, use `imagePullSecrets`. -1. Cluster with a proprietary images, a few of which require stricter access control - - ensure [AlwaysPullImages admission controller](/docs/admin/admission-controllers/#alwayspullimages) is active, otherwise, all Pods potentially have access to all images - - Move sensitive data into a "Secret" resource, instead of packaging it in an image. -1. A multi-tenant cluster where each tenant needs own private registry - - ensure [AlwaysPullImages admission controller](/docs/admin/admission-controllers/#alwayspullimages) is active, otherwise, all Pods of all tenants potentially have access to all images - - run a private registry with authorization required. - - generate registry credential for each tenant, put into secret, and populate secret to each tenant namespace. - - tenant adds that secret to imagePullSecrets of each namespace. +[Images](/docs/concepts/containers/images/) diff --git a/docs/user-guide/index.md b/docs/user-guide/index.md index 69d4a9c193..929a1fa523 100644 --- a/docs/user-guide/index.md +++ b/docs/user-guide/index.md @@ -55,7 +55,7 @@ Before running examples in the user guides, please ensure you have completed [in [**Service**](/docs/user-guide/services/) : A service defines a set of pods and a means by which to access them, such as single stable IP address and corresponding DNS name. -[**Volume**](/docs/user-guide/volumes/) +[**Volume**](/docs/concepts/storage/volumes/) : A volume is a directory, possibly with some data in it, which is accessible to a Container as part of its filesystem. Kubernetes volumes build upon [Docker Volumes](https://docs.docker.com/engine/tutorials/dockervolumes/), adding provisioning of the volume directory and/or device. [**Secret**](/docs/user-guide/secrets/) @@ -79,11 +79,11 @@ API resources Pods and containers * [Pod lifecycle and restart policies](/docs/user-guide/pod-states/) - * [Lifecycle hooks](/docs/user-guide/container-environment/) + * [Lifecycle hooks](/docs/concepts/containers/container-lifecycle-hooks/) * [Compute resources, such as cpu and memory](/docs/user-guide/compute-resources/) * [Specifying commands and requesting capabilities](/docs/user-guide/containers/) * [Downward API: accessing system configuration from a pod](/docs/user-guide/downward-api/) - * [Images and registries](/docs/user-guide/images/) + * [Images and registries](/docs/concepts/containers/images/) * [Migrating from docker-cli to kubectl](/docs/user-guide/docker-cli-to-kubectl/) * [Configuration Best Practices and Tips](/docs/concepts/configuration/overview/) * [Assign pods to selected nodes](/docs/user-guide/node-selection/) diff --git a/docs/user-guide/persistent-volumes/index.md b/docs/user-guide/persistent-volumes/index.md index e2d2661d13..41497c548a 100644 --- a/docs/user-guide/persistent-volumes/index.md +++ b/docs/user-guide/persistent-volumes/index.md @@ -7,7 +7,7 @@ assignees: title: Persistent Volumes --- -This document describes the current state of `PersistentVolumes` in Kubernetes. Familiarity with [volumes](/docs/user-guide/volumes/) is suggested. +This document describes the current state of `PersistentVolumes` in Kubernetes. Familiarity with [volumes](/docs/concepts/storage/volumes/) is suggested. * TOC {:toc} diff --git a/docs/user-guide/petset.md b/docs/user-guide/petset.md index afdca343a0..1a3dcf6b66 100644 --- a/docs/user-guide/petset.md +++ b/docs/user-guide/petset.md @@ -41,7 +41,7 @@ This doc assumes familiarity with the following Kubernetes concepts: * [Pods](/docs/user-guide/pods/single-container/) * [Cluster DNS](/docs/admin/dns/) * [Headless Services](/docs/user-guide/services/#headless-services) -* [Persistent Volumes](/docs/user-guide/volumes/) +* [Persistent Volumes](/docs/concepts/storage/volumes/) * [Persistent Volume Provisioning](http://releases.k8s.io/{{page.githubbranch}}/examples/persistent-volume-provisioning/README.md) You need a working Kubernetes cluster at version >= 1.3, with a healthy DNS [cluster addon](http://releases.k8s.io/{{page.githubbranch}}/cluster/addons/README.md) at version >= 15. You cannot use PetSet on a hosted Kubernetes provider that has disabled `alpha` resources. diff --git a/docs/user-guide/pods/index.md b/docs/user-guide/pods/index.md index 47e2dcaf3b..6b1119dc3b 100644 --- a/docs/user-guide/pods/index.md +++ b/docs/user-guide/pods/index.md @@ -40,7 +40,7 @@ filesystem. In terms of [Docker](https://www.docker.com/) constructs, a pod is modelled as a group of Docker containers with shared namespaces and shared -[volumes](/docs/user-guide/volumes/). PID namespace sharing is not yet implemented in Docker. +[volumes](/docs/concepts/storage/volumes/). PID namespace sharing is not yet implemented in Docker. Like individual application containers, pods are considered to be relatively ephemeral (rather than durable) entities. As discussed in [life of a @@ -162,7 +162,7 @@ An example flow: 2. The Pod in the API server is updated with the time beyond which the Pod is considered "dead" along with the grace period. 3. Pod shows up as "Terminating" when listed in client commands 4. (simultaneous with 3) When the Kubelet sees that a Pod has been marked as terminating because the time in 2 has been set, it begins the pod shutdown process. - 1. If the pod has defined a [preStop hook](/docs/user-guide/container-environment/#hook-details), it is invoked inside of the pod. If the `preStop` hook is still running after the grace period expires, step 2 is then invoked with a small (2 second) extended grace period. + 1. If the pod has defined a [preStop hook](/docs/concepts/containers/container-lifecycle-hooks/#hook-details), it is invoked inside of the pod. If the `preStop` hook is still running after the grace period expires, step 2 is then invoked with a small (2 second) extended grace period. 2. The processes in the Pod are sent the TERM signal. 5. (simultaneous with 3), Pod is removed from endpoints list for service, and are no longer considered part of the set of running pods for replication controllers. Pods that shutdown slowly can continue to serve traffic as load balancers (like the service proxy) remove them from their rotations. 6. When the grace period expires, any processes still running in the Pod are killed with SIGKILL. diff --git a/docs/user-guide/secrets/index.md b/docs/user-guide/secrets/index.md index 8b7c7ae2fb..5ff2ef6a75 100644 --- a/docs/user-guide/secrets/index.md +++ b/docs/user-guide/secrets/index.md @@ -22,7 +22,7 @@ more control over how it is used, and reduces the risk of accidental exposure. Users can create secrets, and the system also creates some secrets. To use a secret, a pod needs to reference the secret. -A secret can be used with a pod in two ways: as files in a [volume](/docs/user-guide/volumes) mounted on one or more of +A secret can be used with a pod in two ways: as files in a [volume](/docs/concepts/storage/volumes/) mounted on one or more of its containers, or used by kubelet when pulling images for the pod. ### Built-in Secrets @@ -428,7 +428,7 @@ password to the Kubelet so it can pull a private image on behalf of your Pod. **Manually specifying an imagePullSecret** -Use of imagePullSecrets is described in the [images documentation](/docs/user-guide/images/#specifying-imagepullsecrets-on-a-pod) +Use of imagePullSecrets is described in the [images documentation](/docs/concepts/containers/images/#specifying-imagepullsecrets-on-a-pod) ### Arranging for imagePullSecrets to be Automatically Attached diff --git a/docs/user-guide/service-accounts.md b/docs/user-guide/service-accounts.md index ad1c0a68bf..5fc2490297 100644 --- a/docs/user-guide/service-accounts.md +++ b/docs/user-guide/service-accounts.md @@ -138,7 +138,7 @@ namespace: 7 bytes ## Adding ImagePullSecrets to a service account -First, create an imagePullSecret, as described [here](/docs/user-guide/images/#specifying-imagepullsecrets-on-a-pod) +First, create an imagePullSecret, as described [here](/docs/concepts/containers/images/#specifying-imagepullsecrets-on-a-pod) Next, verify it has been created. For example: ```shell diff --git a/docs/user-guide/ui.md b/docs/user-guide/ui.md index cb330f1f9b..00a5a49f2d 100644 --- a/docs/user-guide/ui.md +++ b/docs/user-guide/ui.md @@ -68,7 +68,7 @@ The deploy wizard expects that you provide the following information: The application name must be unique within the selected Kubernetes [namespace](/docs/admin/namespaces/). It must start with a lowercase character, and end with a lowercase character or a number, and contain only lowercase letters, numbers and dashes (-). It is limited to 24 characters. Leading and trailing spaces are ignored. -- **Container image** (mandatory): The URL of a public Docker [container image](/docs/user-guide/images/) on any registry, or a private image (commonly hosted on the Google Container Registry or Docker Hub). The container image specification must end with a colon. +- **Container image** (mandatory): The URL of a public Docker [container image](/docs/concepts/containers/images/) on any registry, or a private image (commonly hosted on the Google Container Registry or Docker Hub). The container image specification must end with a colon. - **Number of pods** (mandatory): The target number of Pods you want your application to be deployed in. The value must be a positive integer. @@ -104,7 +104,7 @@ track=stable - **Image Pull Secret**: In case the specified Docker container image is private, it may require [pull secret](/docs/user-guide/secrets/) credentials. - Dashboard offers all available secrets in a dropdown list, and allows you to create a new secret. The secret name must follow the DNS domain name syntax, e.g. `new.image-pull.secret`. The content of a secret must be base64-encoded and specified in a [`.dockercfg`](/docs/user-guide/images/#specifying-imagepullsecrets-on-a-pod) file. The secret name may consist of a maximum of 253 characters. + Dashboard offers all available secrets in a dropdown list, and allows you to create a new secret. The secret name must follow the DNS domain name syntax, e.g. `new.image-pull.secret`. The content of a secret must be base64-encoded and specified in a [`.dockercfg`](/docs/concepts/containers/images/#specifying-imagepullsecrets-on-a-pod) file. The secret name may consist of a maximum of 253 characters. In case the creation of the image pull secret is successful, it is selected by default. If the creation fails, no secret is applied. diff --git a/docs/user-guide/volumes.md b/docs/user-guide/volumes.md index 762518fc8f..cc8862fd52 100644 --- a/docs/user-guide/volumes.md +++ b/docs/user-guide/volumes.md @@ -1,578 +1,7 @@ --- -assignees: -- jsafrane -- mikedanese -- saad-ali -- thockin title: Volumes --- -On-disk files in a container are ephemeral, which presents some problems for -non-trivial applications when running in containers. First, when a container -crashes kubelet will restart it, but the files will be lost - the -container starts with a clean state. Second, when running containers together -in a `Pod` it is often necessary to share files between those containers. The -Kubernetes `Volume` abstraction solves both of these problems. +{% include user-guide-content-moved.md %} -Familiarity with [pods](/docs/user-guide/pods) is suggested. - -* TOC -{:toc} - - -## Background - -Docker also has a concept of -[volumes](https://docs.docker.com/userguide/dockervolumes/), though it is -somewhat looser and less managed. In Docker, a volume is simply a directory on -disk or in another container. Lifetimes are not managed and until very -recently there were only local-disk-backed volumes. Docker now provides volume -drivers, but the functionality is very limited for now (e.g. as of Docker 1.7 -only one volume driver is allowed per container and there is no way to pass -parameters to volumes). - -A Kubernetes volume, on the other hand, has an explicit lifetime - the same as -the pod that encloses it. Consequently, a volume outlives any containers that run -within the Pod, and data is preserved across Container restarts. Of course, when a -Pod ceases to exist, the volume will cease to exist, too. Perhaps more -importantly than this, Kubernetes supports many type of volumes, and a Pod can -use any number of them simultaneously. - -At its core, a volume is just a directory, possibly with some data in it, which -is accessible to the containers in a pod. How that directory comes to be, the -medium that backs it, and the contents of it are determined by the particular -volume type used. - -To use a volume, a pod specifies what volumes to provide for the pod (the -[`spec.volumes`](http://kubernetes.io/kubernetes/third_party/swagger-ui/#!/v1/createPod) -field) and where to mount those into containers(the -[`spec.containers.volumeMounts`](http://kubernetes.io/kubernetes/third_party/swagger-ui/#!/v1/createPod) -field). - -A process in a container sees a filesystem view composed from their Docker -image and volumes. The [Docker -image](https://docs.docker.com/userguide/dockerimages/) is at the root of the -filesystem hierarchy, and any volumes are mounted at the specified paths within -the image. Volumes can not mount onto other volumes or have hard links to -other volumes. Each container in the Pod must independently specify where to -mount each volume. - -## Types of Volumes - -Kubernetes supports several types of Volumes: - - * `emptyDir` - * `hostPath` - * `gcePersistentDisk` - * `awsElasticBlockStore` - * `nfs` - * `iscsi` - * `flocker` - * `glusterfs` - * `rbd` - * `cephfs` - * `gitRepo` - * `secret` - * `persistentVolumeClaim` - * `downwardAPI` - * `azureFileVolume` - * `azureDisk` - * `vsphereVolume` - * `Quobyte` - -We welcome additional contributions. - -### emptyDir - -An `emptyDir` volume is first created when a Pod is assigned to a Node, and -exists as long as that Pod is running on that node. As the name says, it is -initially empty. Containers in the pod can all read and write the same -files in the `emptyDir` volume, though that volume can be mounted at the same -or different paths in each container. When a Pod is removed from a node for -any reason, the data in the `emptyDir` is deleted forever. NOTE: a container -crashing does *NOT* remove a pod from a node, so the data in an `emptyDir` -volume is safe across container crashes. - -Some uses for an `emptyDir` are: - -* scratch space, such as for a disk-based merge sort -* checkpointing a long computation for recovery from crashes -* holding files that a content-manager container fetches while a webserver - container serves the data - -By default, `emptyDir` volumes are stored on whatever medium is backing the -machine - that might be disk or SSD or network storage, depending on your -environment. However, you can set the `emptyDir.medium` field to `"Memory"` -to tell Kubernetes to mount a tmpfs (RAM-backed filesystem) for you instead. -While tmpfs is very fast, be aware that unlike disks, tmpfs is cleared on -machine reboot and any files you write will count against your container's -memory limit. - -#### Example pod - -```yaml -apiVersion: v1 -kind: Pod -metadata: - name: test-pd -spec: - containers: - - image: gcr.io/google_containers/test-webserver - name: test-container - volumeMounts: - - mountPath: /cache - name: cache-volume - volumes: - - name: cache-volume - emptyDir: {} -``` - -### hostPath - -A `hostPath` volume mounts a file or directory from the host node's filesystem -into your pod. This is not something that most Pods will need, but it offers a -powerful escape hatch for some applications. - -For example, some uses for a `hostPath` are: - -* running a container that needs access to Docker internals; use a `hostPath` - of `/var/lib/docker` -* running cAdvisor in a container; use a `hostPath` of `/dev/cgroups` - -Watch out when using this type of volume, because: - -* pods with identical configuration (such as created from a podTemplate) may - behave differently on different nodes due to different files on the nodes -* when Kubernetes adds resource-aware scheduling, as is planned, it will not be - able to account for resources used by a `hostPath` -* the directories created on the underlying hosts are only writable by root. You - either need to run your process as root in a - [privileged container](/docs/user-guide/security-context) or modify the file - permissions on the host to be able to write to a `hostPath` volume - -#### Example pod - -```yaml -apiVersion: v1 -kind: Pod -metadata: - name: test-pd -spec: - containers: - - image: gcr.io/google_containers/test-webserver - name: test-container - volumeMounts: - - mountPath: /test-pd - name: test-volume - volumes: - - name: test-volume - hostPath: - # directory location on host - path: /data -``` - -#### Example pod - -```yaml -apiVersion: v1 -kind: Pod -metadata: - name: test-hostpath -spec: - containers: - - image: myimage - name: test-container - volumeMounts: - - mountPath: /test-hostpath - name: test-volume - volumes: - - name: test-volume - hostPath: - path: /path/to/my/dir -``` - -### gcePersistentDisk - -A `gcePersistentDisk` volume mounts a Google Compute Engine (GCE) [Persistent -Disk](http://cloud.google.com/compute/docs/disks) into your pod. Unlike -`emptyDir`, which is erased when a Pod is removed, the contents of a PD are -preserved and the volume is merely unmounted. This means that a PD can be -pre-populated with data, and that data can be "handed off" between pods. - -__Important: You must create a PD using `gcloud` or the GCE API or UI -before you can use it__ - -There are some restrictions when using a `gcePersistentDisk`: - -* the nodes on which pods are running must be GCE VMs -* those VMs need to be in the same GCE project and zone as the PD - -A feature of PD is that they can be mounted as read-only by multiple consumers -simultaneously. This means that you can pre-populate a PD with your dataset -and then serve it in parallel from as many pods as you need. Unfortunately, -PDs can only be mounted by a single consumer in read-write mode - no -simultaneous writers allowed. - -Using a PD on a pod controlled by a ReplicationController will fail unless -the PD is read-only or the replica count is 0 or 1. - -#### Creating a PD - -Before you can use a GCE PD with a pod, you need to create it. - -```shell -gcloud compute disks create --size=500GB --zone=us-central1-a my-data-disk -``` - -#### Example pod - -```yaml -apiVersion: v1 -kind: Pod -metadata: - name: test-pd -spec: - containers: - - image: gcr.io/google_containers/test-webserver - name: test-container - volumeMounts: - - mountPath: /test-pd - name: test-volume - volumes: - - name: test-volume - # This GCE PD must already exist. - gcePersistentDisk: - pdName: my-data-disk - fsType: ext4 -``` - -### awsElasticBlockStore - -An `awsElasticBlockStore` volume mounts an Amazon Web Services (AWS) [EBS -Volume](http://aws.amazon.com/ebs/) into your pod. Unlike -`emptyDir`, which is erased when a Pod is removed, the contents of an EBS -volume are preserved and the volume is merely unmounted. This means that an -EBS volume can be pre-populated with data, and that data can be "handed off" -between pods. - -__Important: You must create an EBS volume using `aws ec2 create-volume` or -the AWS API before you can use it__ - -There are some restrictions when using an awsElasticBlockStore volume: - -* the nodes on which pods are running must be AWS EC2 instances -* those instances need to be in the same region and availability-zone as the EBS volume -* EBS only supports a single EC2 instance mounting a volume - -#### Creating an EBS volume - -Before you can use an EBS volume with a pod, you need to create it. - -```shell -aws ec2 create-volume --availability-zone eu-west-1a --size 10 --volume-type gp2 -``` - -Make sure the zone matches the zone you brought up your cluster in. (And also check that the size and EBS volume -type are suitable for your use!) - -#### AWS EBS Example configuration - -```yaml -apiVersion: v1 -kind: Pod -metadata: - name: test-ebs -spec: - containers: - - image: gcr.io/google_containers/test-webserver - name: test-container - volumeMounts: - - mountPath: /test-ebs - name: test-volume - volumes: - - name: test-volume - # This AWS EBS volume must already exist. - awsElasticBlockStore: - volumeID: - fsType: ext4 -``` - -### nfs - -An `nfs` volume allows an existing NFS (Network File System) share to be -mounted into your pod. Unlike `emptyDir`, which is erased when a Pod is -removed, the contents of an `nfs` volume are preserved and the volume is merely -unmounted. This means that an NFS volume can be pre-populated with data, and -that data can be "handed off" between pods. NFS can be mounted by multiple -writers simultaneously. - -__Important: You must have your own NFS server running with the share exported -before you can use it__ - -See the [NFS example](https://github.com/kubernetes/kubernetes/tree/{{page.githubbranch}}/examples/volumes/nfs) for more details. - -### iscsi - -An `iscsi` volume allows an existing iSCSI (SCSI over IP) volume to be mounted -into your pod. Unlike `emptyDir`, which is erased when a Pod is removed, the -contents of an `iscsi` volume are preserved and the volume is merely -unmounted. This means that an iscsi volume can be pre-populated with data, and -that data can be "handed off" between pods. - -__Important: You must have your own iSCSI server running with the volume -created before you can use it__ - -A feature of iSCSI is that it can be mounted as read-only by multiple consumers -simultaneously. This means that you can pre-populate a volume with your dataset -and then serve it in parallel from as many pods as you need. Unfortunately, -iSCSI volumes can only be mounted by a single consumer in read-write mode - no -simultaneous writers allowed. - -See the [iSCSI example](https://github.com/kubernetes/kubernetes/tree/{{page.githubbranch}}/examples/volumes/iscsi) for more details. - -### flocker - -[Flocker](https://clusterhq.com/flocker) is an open-source clustered container data volume manager. It provides management -and orchestration of data volumes backed by a variety of storage backends. - -A `flocker` volume allows a Flocker dataset to be mounted into a pod. If the -dataset does not already exist in Flocker, it needs to be first created with the Flocker -CLI or by using the Flocker API. If the dataset already exists it will be -reattached by Flocker to the node that the pod is scheduled. This means data -can be "handed off" between pods as required. - -__Important: You must have your own Flocker installation running before you can use it__ - -See the [Flocker example](https://github.com/kubernetes/kubernetes/tree/{{page.githubbranch}}/examples/volumes/flocker) for more details. - -### glusterfs - -A `glusterfs` volume allows a [Glusterfs](http://www.gluster.org) (an open -source networked filesystem) volume to be mounted into your pod. Unlike -`emptyDir`, which is erased when a Pod is removed, the contents of a -`glusterfs` volume are preserved and the volume is merely unmounted. This -means that a glusterfs volume can be pre-populated with data, and that data can -be "handed off" between pods. GlusterFS can be mounted by multiple writers -simultaneously. - -__Important: You must have your own GlusterFS installation running before you -can use it__ - -See the [GlusterFS example](https://github.com/kubernetes/kubernetes/tree/{{page.githubbranch}}/examples/volumes/glusterfs) for more details. - -### rbd - -An `rbd` volume allows a [Rados Block -Device](http://ceph.com/docs/master/rbd/rbd/) volume to be mounted into your -pod. Unlike `emptyDir`, which is erased when a Pod is removed, the contents of -a `rbd` volume are preserved and the volume is merely unmounted. This -means that a RBD volume can be pre-populated with data, and that data can -be "handed off" between pods. - -__Important: You must have your own Ceph installation running before you -can use RBD__ - -A feature of RBD is that it can be mounted as read-only by multiple consumers -simultaneously. This means that you can pre-populate a volume with your dataset -and then serve it in parallel from as many pods as you need. Unfortunately, -RBD volumes can only be mounted by a single consumer in read-write mode - no -simultaneous writers allowed. - -See the [RBD example](https://github.com/kubernetes/kubernetes/tree/{{page.githubbranch}}/examples/volumes/rbd) for more details. - -### cephfs - -A `cephfs` volume allows an existing CephFS volume to be -mounted into your pod. Unlike `emptyDir`, which is erased when a Pod is -removed, the contents of a `cephfs` volume are preserved and the volume is merely -unmounted. This means that a CephFS volume can be pre-populated with data, and -that data can be "handed off" between pods. CephFS can be mounted by multiple -writers simultaneously. - -__Important: You must have your own Ceph server running with the share exported -before you can use it__ - -See the [CephFS example](https://github.com/kubernetes/kubernetes/tree/{{page.githubbranch}}/examples/volumes/cephfs/) for more details. - -### gitRepo - -A `gitRepo` volume is an example of what can be done as a volume plugin. It -mounts an empty directory and clones a git repository into it for your pod to -use. In the future, such volumes may be moved to an even more decoupled model, -rather than extending the Kubernetes API for every such use case. - -Here is an example for gitRepo volume: - -```yaml -apiVersion: v1 -kind: Pod -metadata: - name: server -spec: - containers: - - image: nginx - name: nginx - volumeMounts: - - mountPath: /mypath - name: git-volume - volumes: - - name: git-volume - gitRepo: - repository: "git@somewhere:me/my-git-repository.git" - revision: "22f1d8406d464b0c0874075539c1f2e96c253775" -``` - -### secret - -A `secret` volume is used to pass sensitive information, such as passwords, to -pods. You can store secrets in the Kubernetes API and mount them as files for -use by pods without coupling to Kubernetes directly. `secret` volumes are -backed by tmpfs (a RAM-backed filesystem) so they are never written to -non-volatile storage. - -__Important: You must create a secret in the Kubernetes API before you can use -it__ - -Secrets are described in more detail [here](/docs/user-guide/secrets). - -### persistentVolumeClaim - -A `persistentVolumeClaim` volume is used to mount a -[PersistentVolume](/docs/user-guide/persistent-volumes) into a pod. PersistentVolumes are a -way for users to "claim" durable storage (such as a GCE PersistentDisk or an -iSCSI volume) without knowing the details of the particular cloud environment. - -See the [PersistentVolumes example](/docs/user-guide/persistent-volumes/) for more -details. - -### downwardAPI - -A `downwardAPI` volume is used to make downward API data available to applications. -It mounts a directory and writes the requested data in plain text files. - -See the [`downwardAPI` volume example](/docs/user-guide/downward-api/volume/) for more details. - -### FlexVolume - -A `FlexVolume` enables users to mount vendor volumes into a pod. It expects vendor -drivers are installed in the volume plugin path on each kubelet node. This is -an alpha feature and may change in future. - -More details are in [here](https://github.com/kubernetes/kubernetes/tree/{{page.githubbranch}}/examples/volumes/flexvolume/README.md) - -### AzureFileVolume - -A `AzureFileVolume` is used to mount a Microsoft Azure File Volume (SMB 2.1 and 3.0) -into a Pod. - -More details can be found [here](https://github.com/kubernetes/kubernetes/tree/{{page.githubbranch}}/examples/volumes/azure_file/README.md) - -### AzureDiskVolume - -A `AzureDiskVolume` is used to mount a Microsoft Azure [Data Disk](https://azure.microsoft.com/en-us/documentation/articles/virtual-machines-linux-about-disks-vhds/) into a Pod. - -More details can be found [here](https://github.com/kubernetes/kubernetes/tree/{{page.githubbranch}}/examples/volumes/azure_disk/README.md) - -### vsphereVolume - -__Prerequisite: Kubernetes with vSphere Cloud Provider configured. -For cloudprovider configuration please refer [vSphere getting started guide](http://kubernetes.io/docs/getting-started-guides/vsphere/).__ - -A `vsphereVolume` is used to mount a vSphere VMDK Volume into your Pod. The contents -of a volume are preserved when it is unmounted. It supports both VMFS and VSAN datastore. - -__Important: You must create VMDK using one of the following method before using with POD.__ - -#### Creating a VMDK volume - -* Create using vmkfstools. - - First ssh into ESX and then use following command to create vmdk, - -```shell - vmkfstools -c 2G /vmfs/volumes/DatastoreName/volumes/myDisk.vmdk -``` - -* Create using vmware-vdiskmanager. -```shell - vmware-vdiskmanager -c -t 0 -s 40GB -a lsilogic myDisk.vmdk -``` - -#### vSphere VMDK Example configuration - -```yaml -apiVersion: v1 -kind: Pod -metadata: - name: test-vmdk -spec: - containers: - - image: gcr.io/google_containers/test-webserver - name: test-container - volumeMounts: - - mountPath: /test-vmdk - name: test-volume - volumes: - - name: test-volume - # This VMDK volume must already exist. - vsphereVolume: - volumePath: "[DatastoreName] volumes/myDisk" - fsType: ext4 -``` -More examples can be found [here](https://github.com/kubernetes/kubernetes/tree/master/examples/volumes/vsphere). - - -### Quobyte - -A `Quobyte` volume allows an existing [Quobyte](http://www.quobyte.com) volume to be mounted into your pod. - -__Important: You must have your own Quobyte setup running with the volumes created -before you can use it__ - -See the [Quobyte example](https://github.com/kubernetes/kubernetes/tree/{{page.githubbranch}}/examples/volumes/quobyte) for more details. - -## Using subPath - -Sometimes, it is useful to share one volume for multiple uses in a single pod. The `volumeMounts.subPath` -property can be used to specify a sub-path inside the referenced volume instead of its root. - -Here is an example of a pod with a LAMP stack (Linux Apache Mysql PHP) using a single, shared volume. -The HTML contents are mapped to its `html` folder, and the databases will be stored in its `mysql` folder: - -```yaml -apiVersion: v1 -kind: Pod -metadata: - name: my-lamp-site -spec: - containers: - - name: mysql - image: mysql - volumeMounts: - - mountPath: /var/lib/mysql - name: site-data - subPath: mysql - - name: php - image: php - volumeMounts: - - mountPath: /var/www/html - name: site-data - subPath: html - volumes: - - name: site-data - persistentVolumeClaim: - claimName: my-lamp-site-data -``` - -## Resources - -The storage media (Disk, SSD, etc.) of an `emptyDir` volume is determined by the -medium of the filesystem holding the kubelet root dir (typically -`/var/lib/kubelet`). There is no limit on how much space an `emptyDir` or -`hostPath` volume can consume, and no isolation between containers or between -pods. - -In the future, we expect that `emptyDir` and `hostPath` volumes will be able to -request a certain amount of space using a [resource](/docs/user-guide/compute-resources) -specification, and to select the type of media to use, for clusters that have -several media types. +[Volumes](/docs/concepts/storage/volumes/) diff --git a/docs/user-guide/walkthrough/index.md b/docs/user-guide/walkthrough/index.md index 9b795cf136..f8cddb543e 100644 --- a/docs/user-guide/walkthrough/index.md +++ b/docs/user-guide/walkthrough/index.md @@ -115,7 +115,7 @@ Notes: - **EmptyDir**: Creates a new directory that will exist as long as the Pod is running on the node, but it can persist across container failures and restarts. - **HostPath**: Mounts an existing directory on the node's file system (e.g. `/var/logs`). -See [volumes](/docs/user-guide/volumes/) for more details. +See [volumes](/docs/concepts/storage/volumes/) for more details. #### Multiple Containers diff --git a/test/examples_test.go b/test/examples_test.go index e9855bdeef..0732d228da 100644 --- a/test/examples_test.go +++ b/test/examples_test.go @@ -411,7 +411,7 @@ func TestReadme(t *testing.T) { file string expectedType []runtime.Object }{ - {"../docs/user-guide/volumes.md", []runtime.Object{&api.Pod{}}}, + {"../docs/concepts/storage/volumes.md", []runtime.Object{&api.Pod{}}}, } for _, path := range paths { From b144d991a08a75675cf1f0ee15369ecdd217cfd5 Mon Sep 17 00:00:00 2001 From: xilabao Date: Mon, 20 Mar 2017 13:49:38 +0800 Subject: [PATCH 13/21] fix to taint the master node --- docs/getting-started-guides/kubeadm.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/docs/getting-started-guides/kubeadm.md b/docs/getting-started-guides/kubeadm.md index 03cf546eaa..a45c2f1319 100644 --- a/docs/getting-started-guides/kubeadm.md +++ b/docs/getting-started-guides/kubeadm.md @@ -173,10 +173,9 @@ The key is used for mutual authentication between the master and the joining nod By default, your cluster will not schedule pods on the master for security reasons. If you want to be able to schedule pods on the master, for example if you want a single-machine Kubernetes cluster for development, run: - # kubectl taint nodes --all dedicated- - node "test-01" tainted - taint key="dedicated" and effect="" not found. - taint key="dedicated" and effect="" not found. + # MASTER_NODE="actual_master_node_name" + # TAINT_KEY=$(kubectl get no ${MASTER_NODE} --template="{{(index .spec.taints 0).key}}") + # kubectl taint nodes ${MASTER_NODE} ${TAINT_KEY}- This will remove the "dedicated" taint from any nodes that have it, including the master node, meaning that the scheduler will then be able to schedule pods everywhere. From 5f96e8a39a3586e2691e6486a7866395a2f3f137 Mon Sep 17 00:00:00 2001 From: mlambert890b Date: Mon, 20 Mar 2017 20:18:40 -0700 Subject: [PATCH 14/21] Add files via upload --- images/square-logos/mirantis.png | Bin 17311 -> 17623 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/images/square-logos/mirantis.png b/images/square-logos/mirantis.png index 9dc83103d938ccc6c829f80141e5c8e0b7ca7697..a738e02f5fee4e4d0b9c5c6595117a49c5c4f4e1 100644 GIT binary patch literal 17623 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

>52LK36D#}Re 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 From 75fc7284a87790ec846d186d55b3cdcfc5239ff7 Mon Sep 17 00:00:00 2001 From: Xiaoyu Zhang Date: Tue, 21 Mar 2017 15:36:25 +0800 Subject: [PATCH 15/21] fix the link of ogging-elasticsearch-kibana.md fix the link of url --- .../debug-application-cluster/logging-elasticsearch-kibana.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tasks/debug-application-cluster/logging-elasticsearch-kibana.md b/docs/tasks/debug-application-cluster/logging-elasticsearch-kibana.md index 4441067d60..9931bab209 100644 --- a/docs/tasks/debug-application-cluster/logging-elasticsearch-kibana.md +++ b/docs/tasks/debug-application-cluster/logging-elasticsearch-kibana.md @@ -75,7 +75,7 @@ Elasticsearch, and is part of a service named `kibana-logging`. The Elasticsearch and Kibana services are both in the `kube-system` namespace and are not directly exposed via a publicly reachable IP address. To reach them, -follow the instructions for [Accessing services running in a cluster](/docs/user-guide/accessing-the-cluster/#accessing-services-running-on-the-cluster). +follow the instructions for [Accessing services running in a cluster](/docs/concepts/cluster-administration/access-cluster/#accessing-services-running-on-the-cluster). If you try accessing the `elasticsearch-logging` service in your browser, you'll see a status page that looks something like this: From d4b42e9c7eca0adbc351dba1a56a0120719fbea2 Mon Sep 17 00:00:00 2001 From: Steve Perry Date: Tue, 21 Mar 2017 13:11:03 -0700 Subject: [PATCH 16/21] Remove from TOC/Search: pods/init-containers ... (#2694) --- _data/guides.yml | 5 ----- robots.txt | 8 ++++++++ skip_toc_check.txt | 9 ++++++++- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/_data/guides.yml b/_data/guides.yml index 0a06052579..46a33a8ef8 100644 --- a/_data/guides.yml +++ b/_data/guides.yml @@ -54,16 +54,12 @@ toc: - title: Containers and Pods section: - docs/user-guide/pods/multi-container.md - - docs/user-guide/pods/init-container.md - docs/user-guide/pod-templates.md - docs/user-guide/environment-guide/index.md - docs/user-guide/compute-resources.md - - docs/user-guide/pod-states.md - docs/user-guide/liveness/index.md - docs/user-guide/container-environment.md - docs/user-guide/node-selection/index.md - - docs/user-guide/downward-api/index.md - - docs/user-guide/downward-api/volume/index.md - docs/user-guide/petset/bootstrapping/index.md - title: Monitoring, Logging, and Debugging Containers @@ -74,7 +70,6 @@ toc: - docs/user-guide/logging/overview.md - docs/user-guide/logging/stackdriver.md - docs/user-guide/logging/elasticsearch.md - - docs/user-guide/getting-into-containers.md - docs/user-guide/connecting-to-applications-proxy.md - docs/user-guide/connecting-to-applications-port-forward.md - title: Using Explorer to Examine the Runtime Environment diff --git a/robots.txt b/robots.txt index 3fbd70eb24..3b38c25967 100644 --- a/robots.txt +++ b/robots.txt @@ -9,12 +9,20 @@ Disallow: 404.html Disallow: /docs/user-guide/configuring-containers Disallow: /docs/user-guide/containers Disallow: /docs/user-guide/deploying-applications +Disallow: /docs/user-guide/getting-into-containers +>>>>>>> fb2ab359... Remove from TOC/Search: pods/init-containers ... Disallow: /docs/user-guide/liveness/index +Disallow: /docs/user-guide/pod-states Disallow: /docs/user-guide/simple-nginx Disallow: /docs/user-guide/production-pods Disallow: /docs/user-guide/quick-start +Disallow: /docs/user-guide/downward-api/index +Disallow: /docs/user-guide/downward-api/volume/index + Disallow: /docs/user-guide/persistent-volumes/walkthrough + +Disallow: /docs/user-guide/pods/init-container Disallow: /docs/user-guide/pods/single-container Disallow: /docs/user-guide/secrets/walkthrough diff --git a/skip_toc_check.txt b/skip_toc_check.txt index 255bb26d10..7299c12c1f 100644 --- a/skip_toc_check.txt +++ b/skip_toc_check.txt @@ -8,4 +8,11 @@ docs/user-guide/walkthrough/k8s201.md docs/user-guide/logging-demo/README.md docs/user-guide/downward-api/README.md docs/user-guide/configmap/README.md -docs/concepts/abstractions/pod-termination.md \ No newline at end of file +docs/concepts/abstractions/pod-termination.md + +docs/user-guide/pods/init-container.md +docs/user-guide/pod-states.md +docs/user-guide/downward-api/index.md +docs/user-guide/downward-api/volume/index.md +docs/user-guide/getting-into-containers.md + From b401010d3a549557df101a5cd703788cd6ba9a78 Mon Sep 17 00:00:00 2001 From: Simon Wydooghe Date: Tue, 21 Mar 2017 21:17:35 +0100 Subject: [PATCH 17/21] Fix typo --- docs/concepts/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/concepts/index.md b/docs/concepts/index.md index 39e44fbc97..8c28d98b59 100644 --- a/docs/concepts/index.md +++ b/docs/concepts/index.md @@ -8,7 +8,7 @@ The Concepts section helps you learn about the parts of the Kubernetes system an To work with Kubernetes, you use *Kubernetes API objects* to describe your cluster's *desired state*: what applications or other workloads you want to run, what container images they use, the number of replicas, what network and disk resources you want to make available, and more. You set your desired state by creating objects using the Kubernetes API, typically via the command-line interface, `kubectl`. You can also use the Kubernetes API directly to interact with the cluster and set or modify your desired state. -Once you've set your desired state, the *Kubernetes Control Plane* works to make the cluster's current state match the desired state. To do so, Kuberentes performs a variety of tasks automatically--such as starting or restarting containers, scaling the number of replicas of a given application, and more. The Kubernetes Control Plane consists of a collection of processes running on your cluster: +Once you've set your desired state, the *Kubernetes Control Plane* works to make the cluster's current state match the desired state. To do so, Kubernetes performs a variety of tasks automatically--such as starting or restarting containers, scaling the number of replicas of a given application, and more. The Kubernetes Control Plane consists of a collection of processes running on your cluster: * The **Kubernetes Master** is a collection of four processes that run on a single node in your cluster, which is designated as the master node. * Each individual non-master node in your cluster runs two processes: From d4107d0a088974f96cb57b1041e3bb9293fe559e Mon Sep 17 00:00:00 2001 From: mlambert890b Date: Tue, 21 Mar 2017 12:42:33 -0700 Subject: [PATCH 18/21] Add files via upload --- images/square-logos/mirantis.png | Bin 17623 -> 22038 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/images/square-logos/mirantis.png b/images/square-logos/mirantis.png index a738e02f5fee4e4d0b9c5c6595117a49c5c4f4e1..677b9f78a5f2c8289399b1c260d1a2587a48c1d2 100644 GIT binary patch literal 22038 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 Date: Thu, 16 Mar 2017 18:16:09 -0400 Subject: [PATCH 19/21] Create hyperlink Create hyperlink for kubernetes repo link. --- docs/user-guide/kubectl/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/user-guide/kubectl/index.md b/docs/user-guide/kubectl/index.md index 75fc6c06bf..58a0655bc1 100644 --- a/docs/user-guide/kubectl/index.md +++ b/docs/user-guide/kubectl/index.md @@ -11,7 +11,7 @@ kubectl controls the Kubernetes cluster manager kubectl controls the Kubernetes cluster manager. -Find more information at https://github.com/kubernetes/kubernetes. +Find more information at [https://github.com/kubernetes/kubernetes](https://github.com/kubernetes/kubernetes). ``` kubectl From 180db357d01ccfe304a38258e6a196d55c98f1e4 Mon Sep 17 00:00:00 2001 From: Gurvinder Singh Date: Wed, 22 Mar 2017 00:09:37 +0100 Subject: [PATCH 20/21] updated PSP documentation with RBAC (#2552) Added info about controller manager setup and current implementation when using PSP with RBAC support. --- docs/user-guide/pod-security-policy/index.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/user-guide/pod-security-policy/index.md b/docs/user-guide/pod-security-policy/index.md index d3b40902ea..7a4091558a 100644 --- a/docs/user-guide/pod-security-policy/index.md +++ b/docs/user-guide/pod-security-policy/index.md @@ -163,5 +163,6 @@ following ## Working With RBAC -In Kubernetes 1.5 and newer, you can use PodSecurityPolicy to control access to privileged containers based on user role and groups. -(see [more details](https://github.com/kubernetes/kubernetes/blob/master/examples/podsecuritypolicy/rbac/README.md)). +In Kubernetes 1.5 and newer, you can use PodSecurityPolicy to control access to privileged containers based on user role and groups. Access to different PodSecurityPolicy objects can be controlled via authorization. To limit access to PodSecurityPolicy objects for pods created via a Deployment, ReplicaSet, etc, the [Controller Manager](/docs/admin/kube-controller-manager/) must be run against the secured API port, and must not have superuser permissions. + +PodSecurityPolicy authorization uses the union of all policies available to the user creating the pod and the service account specified on the pod. When pods are created via a Deployment, ReplicaSet, etc, it is Controller Manager that creates the pod, so if it is running against the unsecured API port, all PodSecurityPolicy objects would be allowed, and you could not effectively subdivide access. Access to given PSP policies for a user will be effective only when deploying Pods directly. For more details, see the [PodSecurityPolicy RBAC example](https://github.com/kubernetes/kubernetes/blob/master/examples/podsecuritypolicy/rbac/README.md) of applying PodSecurityPolicy to control access to privileged containers based on role and groups when deploying Pods directly. From 17daa9837f0251bf751a7c73a379fb2e69224838 Mon Sep 17 00:00:00 2001 From: Everett Toews Date: Thu, 9 Mar 2017 09:59:38 -0600 Subject: [PATCH 21/21] Use kubectl config current-context to simplify the instructions --- docs/user-guide/namespaces.md | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/docs/user-guide/namespaces.md b/docs/user-guide/namespaces.md index d162139358..1ce6861760 100644 --- a/docs/user-guide/namespaces.md +++ b/docs/user-guide/namespaces.md @@ -64,16 +64,8 @@ $ kubectl --namespace= get pods You can permanently save the namespace for all subsequent kubectl commands in that context. -First get your current context: - ```shell -$ export CONTEXT=$(kubectl config view | awk '/current-context/ {print $2}') -``` - -Then update the default namespace: - -```shell -$ kubectl config set-context $CONTEXT --namespace= +$ kubectl config set-context $(kubectl config current-context) --namespace= # Validate it $ kubectl config view | grep namespace: ```