From 987c1c1e761fd67e3f7a8ab51bd0f4e071317ed2 Mon Sep 17 00:00:00 2001 From: Janet Kuo Date: Tue, 22 Nov 2016 16:20:33 -0800 Subject: [PATCH 1/9] Add a task title for stateful sets --- _data/tasks.yml | 2 +- docs/tasks/index.md | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/_data/tasks.yml b/_data/tasks.yml index 4c6cd1b709..5351d1d937 100644 --- a/_data/tasks.yml +++ b/_data/tasks.yml @@ -23,4 +23,4 @@ toc: section: - title: Assigning Pods to Nodes path: /docs/tasks/administer-cluster/assign-pods-nodes/ - +- title: Managing Stateful Applications diff --git a/docs/tasks/index.md b/docs/tasks/index.md index e59f8732b2..aadfc2af84 100644 --- a/docs/tasks/index.md +++ b/docs/tasks/index.md @@ -21,6 +21,8 @@ The Tasks section of the Kubernetes documentation is a work in progress * [Assigning Pods to Nodes](/docs/tasks/administer-cluster/assign-pods-nodes/) +#### Managing Stateful Applications + ### What's next If you would like to write a task page, see From dd08e2bae9e41689b734ecb7574acd472d54a81d Mon Sep 17 00:00:00 2001 From: steveperry-53 Date: Tue, 22 Nov 2016 16:38:54 -0800 Subject: [PATCH 2/9] Fix carousel images. --- _includes/head-header.html | 1 + js/bootstrap.min.js | 7 +++++++ 2 files changed, 8 insertions(+) create mode 100644 js/bootstrap.min.js diff --git a/_includes/head-header.html b/_includes/head-header.html index 0405f3699c..17a83fa31e 100644 --- a/_includes/head-header.html +++ b/_includes/head-header.html @@ -13,6 +13,7 @@ + Kubernetes - {{ title }} diff --git a/js/bootstrap.min.js b/js/bootstrap.min.js new file mode 100644 index 0000000000..be9574d70b --- /dev/null +++ b/js/bootstrap.min.js @@ -0,0 +1,7 @@ +/*! + * Bootstrap v3.3.7 (http://getbootstrap.com) + * Copyright 2011-2016 Twitter, Inc. + * Licensed under the MIT license + */ +if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(a){"use strict";var b=a.fn.jquery.split(" ")[0].split(".");if(b[0]<2&&b[1]<9||1==b[0]&&9==b[1]&&b[2]<1||b[0]>3)throw new Error("Bootstrap's JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4")}(jQuery),+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]};return!1}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one("bsTransitionEnd",function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b(),a.support.transition&&(a.event.special.bsTransitionEnd={bindType:a.support.transition.end,delegateType:a.support.transition.end,handle:function(b){if(a(b.target).is(this))return b.handleObj.handler.apply(this,arguments)}})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var c=a(this),e=c.data("bs.alert");e||c.data("bs.alert",e=new d(this)),"string"==typeof b&&e[b].call(c)})}var c='[data-dismiss="alert"]',d=function(b){a(b).on("click",c,this.close)};d.VERSION="3.3.7",d.TRANSITION_DURATION=150,d.prototype.close=function(b){function c(){g.detach().trigger("closed.bs.alert").remove()}var e=a(this),f=e.attr("data-target");f||(f=e.attr("href"),f=f&&f.replace(/.*(?=#[^\s]*$)/,""));var g=a("#"===f?[]:f);b&&b.preventDefault(),g.length||(g=e.closest(".alert")),g.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(g.removeClass("in"),a.support.transition&&g.hasClass("fade")?g.one("bsTransitionEnd",c).emulateTransitionEnd(d.TRANSITION_DURATION):c())};var e=a.fn.alert;a.fn.alert=b,a.fn.alert.Constructor=d,a.fn.alert.noConflict=function(){return a.fn.alert=e,this},a(document).on("click.bs.alert.data-api",c,d.prototype.close)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof b&&b;e||d.data("bs.button",e=new c(this,f)),"toggle"==b?e.toggle():b&&e.setState(b)})}var c=function(b,d){this.$element=a(b),this.options=a.extend({},c.DEFAULTS,d),this.isLoading=!1};c.VERSION="3.3.7",c.DEFAULTS={loadingText:"loading..."},c.prototype.setState=function(b){var c="disabled",d=this.$element,e=d.is("input")?"val":"html",f=d.data();b+="Text",null==f.resetText&&d.data("resetText",d[e]()),setTimeout(a.proxy(function(){d[e](null==f[b]?this.options[b]:f[b]),"loadingText"==b?(this.isLoading=!0,d.addClass(c).attr(c,c).prop(c,!0)):this.isLoading&&(this.isLoading=!1,d.removeClass(c).removeAttr(c).prop(c,!1))},this),0)},c.prototype.toggle=function(){var a=!0,b=this.$element.closest('[data-toggle="buttons"]');if(b.length){var c=this.$element.find("input");"radio"==c.prop("type")?(c.prop("checked")&&(a=!1),b.find(".active").removeClass("active"),this.$element.addClass("active")):"checkbox"==c.prop("type")&&(c.prop("checked")!==this.$element.hasClass("active")&&(a=!1),this.$element.toggleClass("active")),c.prop("checked",this.$element.hasClass("active")),a&&c.trigger("change")}else this.$element.attr("aria-pressed",!this.$element.hasClass("active")),this.$element.toggleClass("active")};var d=a.fn.button;a.fn.button=b,a.fn.button.Constructor=c,a.fn.button.noConflict=function(){return a.fn.button=d,this},a(document).on("click.bs.button.data-api",'[data-toggle^="button"]',function(c){var d=a(c.target).closest(".btn");b.call(d,"toggle"),a(c.target).is('input[type="radio"], input[type="checkbox"]')||(c.preventDefault(),d.is("input,button")?d.trigger("focus"):d.find("input:visible,button:visible").first().trigger("focus"))}).on("focus.bs.button.data-api blur.bs.button.data-api",'[data-toggle^="button"]',function(b){a(b.target).closest(".btn").toggleClass("focus",/^focus(in)?$/.test(b.type))})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},c.DEFAULTS,d.data(),"object"==typeof b&&b),g="string"==typeof b?b:f.slide;e||d.data("bs.carousel",e=new c(this,f)),"number"==typeof b?e.to(b):g?e[g]():f.interval&&e.pause().cycle()})}var c=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=null,this.sliding=null,this.interval=null,this.$active=null,this.$items=null,this.options.keyboard&&this.$element.on("keydown.bs.carousel",a.proxy(this.keydown,this)),"hover"==this.options.pause&&!("ontouchstart"in document.documentElement)&&this.$element.on("mouseenter.bs.carousel",a.proxy(this.pause,this)).on("mouseleave.bs.carousel",a.proxy(this.cycle,this))};c.VERSION="3.3.7",c.TRANSITION_DURATION=600,c.DEFAULTS={interval:5e3,pause:"hover",wrap:!0,keyboard:!0},c.prototype.keydown=function(a){if(!/input|textarea/i.test(a.target.tagName)){switch(a.which){case 37:this.prev();break;case 39:this.next();break;default:return}a.preventDefault()}},c.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},c.prototype.getItemIndex=function(a){return this.$items=a.parent().children(".item"),this.$items.index(a||this.$active)},c.prototype.getItemForDirection=function(a,b){var c=this.getItemIndex(b),d="prev"==a&&0===c||"next"==a&&c==this.$items.length-1;if(d&&!this.options.wrap)return b;var e="prev"==a?-1:1,f=(c+e)%this.$items.length;return this.$items.eq(f)},c.prototype.to=function(a){var b=this,c=this.getItemIndex(this.$active=this.$element.find(".item.active"));if(!(a>this.$items.length-1||a<0))return this.sliding?this.$element.one("slid.bs.carousel",function(){b.to(a)}):c==a?this.pause().cycle():this.slide(a>c?"next":"prev",this.$items.eq(a))},c.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},c.prototype.next=function(){if(!this.sliding)return this.slide("next")},c.prototype.prev=function(){if(!this.sliding)return this.slide("prev")},c.prototype.slide=function(b,d){var e=this.$element.find(".item.active"),f=d||this.getItemForDirection(b,e),g=this.interval,h="next"==b?"left":"right",i=this;if(f.hasClass("active"))return this.sliding=!1;var j=f[0],k=a.Event("slide.bs.carousel",{relatedTarget:j,direction:h});if(this.$element.trigger(k),!k.isDefaultPrevented()){if(this.sliding=!0,g&&this.pause(),this.$indicators.length){this.$indicators.find(".active").removeClass("active");var l=a(this.$indicators.children()[this.getItemIndex(f)]);l&&l.addClass("active")}var m=a.Event("slid.bs.carousel",{relatedTarget:j,direction:h});return a.support.transition&&this.$element.hasClass("slide")?(f.addClass(b),f[0].offsetWidth,e.addClass(h),f.addClass(h),e.one("bsTransitionEnd",function(){f.removeClass([b,h].join(" ")).addClass("active"),e.removeClass(["active",h].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger(m)},0)}).emulateTransitionEnd(c.TRANSITION_DURATION)):(e.removeClass("active"),f.addClass("active"),this.sliding=!1,this.$element.trigger(m)),g&&this.cycle(),this}};var d=a.fn.carousel;a.fn.carousel=b,a.fn.carousel.Constructor=c,a.fn.carousel.noConflict=function(){return a.fn.carousel=d,this};var e=function(c){var d,e=a(this),f=a(e.attr("data-target")||(d=e.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""));if(f.hasClass("carousel")){var g=a.extend({},f.data(),e.data()),h=e.attr("data-slide-to");h&&(g.interval=!1),b.call(f,g),h&&f.data("bs.carousel").to(h),c.preventDefault()}};a(document).on("click.bs.carousel.data-api","[data-slide]",e).on("click.bs.carousel.data-api","[data-slide-to]",e),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var c=a(this);b.call(c,c.data())})})}(jQuery),+function(a){"use strict";function b(b){var c,d=b.attr("data-target")||(c=b.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"");return a(d)}function c(b){return this.each(function(){var c=a(this),e=c.data("bs.collapse"),f=a.extend({},d.DEFAULTS,c.data(),"object"==typeof b&&b);!e&&f.toggle&&/show|hide/.test(b)&&(f.toggle=!1),e||c.data("bs.collapse",e=new d(this,f)),"string"==typeof b&&e[b]()})}var d=function(b,c){this.$element=a(b),this.options=a.extend({},d.DEFAULTS,c),this.$trigger=a('[data-toggle="collapse"][href="#'+b.id+'"],[data-toggle="collapse"][data-target="#'+b.id+'"]'),this.transitioning=null,this.options.parent?this.$parent=this.getParent():this.addAriaAndCollapsedClass(this.$element,this.$trigger),this.options.toggle&&this.toggle()};d.VERSION="3.3.7",d.TRANSITION_DURATION=350,d.DEFAULTS={toggle:!0},d.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},d.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var b,e=this.$parent&&this.$parent.children(".panel").children(".in, .collapsing");if(!(e&&e.length&&(b=e.data("bs.collapse"),b&&b.transitioning))){var f=a.Event("show.bs.collapse");if(this.$element.trigger(f),!f.isDefaultPrevented()){e&&e.length&&(c.call(e,"hide"),b||e.data("bs.collapse",null));var g=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[g](0).attr("aria-expanded",!0),this.$trigger.removeClass("collapsed").attr("aria-expanded",!0),this.transitioning=1;var h=function(){this.$element.removeClass("collapsing").addClass("collapse in")[g](""),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return h.call(this);var i=a.camelCase(["scroll",g].join("-"));this.$element.one("bsTransitionEnd",a.proxy(h,this)).emulateTransitionEnd(d.TRANSITION_DURATION)[g](this.$element[0][i])}}}},d.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse in").attr("aria-expanded",!1),this.$trigger.addClass("collapsed").attr("aria-expanded",!1),this.transitioning=1;var e=function(){this.transitioning=0,this.$element.removeClass("collapsing").addClass("collapse").trigger("hidden.bs.collapse")};return a.support.transition?void this.$element[c](0).one("bsTransitionEnd",a.proxy(e,this)).emulateTransitionEnd(d.TRANSITION_DURATION):e.call(this)}}},d.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()},d.prototype.getParent=function(){return a(this.options.parent).find('[data-toggle="collapse"][data-parent="'+this.options.parent+'"]').each(a.proxy(function(c,d){var e=a(d);this.addAriaAndCollapsedClass(b(e),e)},this)).end()},d.prototype.addAriaAndCollapsedClass=function(a,b){var c=a.hasClass("in");a.attr("aria-expanded",c),b.toggleClass("collapsed",!c).attr("aria-expanded",c)};var e=a.fn.collapse;a.fn.collapse=c,a.fn.collapse.Constructor=d,a.fn.collapse.noConflict=function(){return a.fn.collapse=e,this},a(document).on("click.bs.collapse.data-api",'[data-toggle="collapse"]',function(d){var e=a(this);e.attr("data-target")||d.preventDefault();var f=b(e),g=f.data("bs.collapse"),h=g?"toggle":e.data();c.call(f,h)})}(jQuery),+function(a){"use strict";function b(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#[A-Za-z]/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}function c(c){c&&3===c.which||(a(e).remove(),a(f).each(function(){var d=a(this),e=b(d),f={relatedTarget:this};e.hasClass("open")&&(c&&"click"==c.type&&/input|textarea/i.test(c.target.tagName)&&a.contains(e[0],c.target)||(e.trigger(c=a.Event("hide.bs.dropdown",f)),c.isDefaultPrevented()||(d.attr("aria-expanded","false"),e.removeClass("open").trigger(a.Event("hidden.bs.dropdown",f)))))}))}function d(b){return this.each(function(){var c=a(this),d=c.data("bs.dropdown");d||c.data("bs.dropdown",d=new g(this)),"string"==typeof b&&d[b].call(c)})}var e=".dropdown-backdrop",f='[data-toggle="dropdown"]',g=function(b){a(b).on("click.bs.dropdown",this.toggle)};g.VERSION="3.3.7",g.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=b(e),g=f.hasClass("open");if(c(),!g){"ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a(document.createElement("div")).addClass("dropdown-backdrop").insertAfter(a(this)).on("click",c);var h={relatedTarget:this};if(f.trigger(d=a.Event("show.bs.dropdown",h)),d.isDefaultPrevented())return;e.trigger("focus").attr("aria-expanded","true"),f.toggleClass("open").trigger(a.Event("shown.bs.dropdown",h))}return!1}},g.prototype.keydown=function(c){if(/(38|40|27|32)/.test(c.which)&&!/input|textarea/i.test(c.target.tagName)){var d=a(this);if(c.preventDefault(),c.stopPropagation(),!d.is(".disabled, :disabled")){var e=b(d),g=e.hasClass("open");if(!g&&27!=c.which||g&&27==c.which)return 27==c.which&&e.find(f).trigger("focus"),d.trigger("click");var h=" li:not(.disabled):visible a",i=e.find(".dropdown-menu"+h);if(i.length){var j=i.index(c.target);38==c.which&&j>0&&j--,40==c.which&&jdocument.documentElement.clientHeight;this.$element.css({paddingLeft:!this.bodyIsOverflowing&&a?this.scrollbarWidth:"",paddingRight:this.bodyIsOverflowing&&!a?this.scrollbarWidth:""})},c.prototype.resetAdjustments=function(){this.$element.css({paddingLeft:"",paddingRight:""})},c.prototype.checkScrollbar=function(){var a=window.innerWidth;if(!a){var b=document.documentElement.getBoundingClientRect();a=b.right-Math.abs(b.left)}this.bodyIsOverflowing=document.body.clientWidth
',trigger:"hover focus",title:"",delay:0,html:!1,container:!1,viewport:{selector:"body",padding:0}},c.prototype.init=function(b,c,d){if(this.enabled=!0,this.type=b,this.$element=a(c),this.options=this.getOptions(d),this.$viewport=this.options.viewport&&a(a.isFunction(this.options.viewport)?this.options.viewport.call(this,this.$element):this.options.viewport.selector||this.options.viewport),this.inState={click:!1,hover:!1,focus:!1},this.$element[0]instanceof document.constructor&&!this.options.selector)throw new Error("`selector` option must be specified when initializing "+this.type+" on the window.document object!");for(var e=this.options.trigger.split(" "),f=e.length;f--;){var g=e[f];if("click"==g)this.$element.on("click."+this.type,this.options.selector,a.proxy(this.toggle,this));else if("manual"!=g){var h="hover"==g?"mouseenter":"focusin",i="hover"==g?"mouseleave":"focusout";this.$element.on(h+"."+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(i+"."+this.type,this.options.selector,a.proxy(this.leave,this))}}this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.getOptions=function(b){return b=a.extend({},this.getDefaults(),this.$element.data(),b),b.delay&&"number"==typeof b.delay&&(b.delay={show:b.delay,hide:b.delay}),b},c.prototype.getDelegateOptions=function(){var b={},c=this.getDefaults();return this._options&&a.each(this._options,function(a,d){c[a]!=d&&(b[a]=d)}),b},c.prototype.enter=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),b instanceof a.Event&&(c.inState["focusin"==b.type?"focus":"hover"]=!0),c.tip().hasClass("in")||"in"==c.hoverState?void(c.hoverState="in"):(clearTimeout(c.timeout),c.hoverState="in",c.options.delay&&c.options.delay.show?void(c.timeout=setTimeout(function(){"in"==c.hoverState&&c.show()},c.options.delay.show)):c.show())},c.prototype.isInStateTrue=function(){for(var a in this.inState)if(this.inState[a])return!0;return!1},c.prototype.leave=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);if(c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),b instanceof a.Event&&(c.inState["focusout"==b.type?"focus":"hover"]=!1),!c.isInStateTrue())return clearTimeout(c.timeout),c.hoverState="out",c.options.delay&&c.options.delay.hide?void(c.timeout=setTimeout(function(){"out"==c.hoverState&&c.hide()},c.options.delay.hide)):c.hide()},c.prototype.show=function(){var b=a.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(b);var d=a.contains(this.$element[0].ownerDocument.documentElement,this.$element[0]);if(b.isDefaultPrevented()||!d)return;var e=this,f=this.tip(),g=this.getUID(this.type);this.setContent(),f.attr("id",g),this.$element.attr("aria-describedby",g),this.options.animation&&f.addClass("fade");var h="function"==typeof this.options.placement?this.options.placement.call(this,f[0],this.$element[0]):this.options.placement,i=/\s?auto?\s?/i,j=i.test(h);j&&(h=h.replace(i,"")||"top"),f.detach().css({top:0,left:0,display:"block"}).addClass(h).data("bs."+this.type,this),this.options.container?f.appendTo(this.options.container):f.insertAfter(this.$element),this.$element.trigger("inserted.bs."+this.type);var k=this.getPosition(),l=f[0].offsetWidth,m=f[0].offsetHeight;if(j){var n=h,o=this.getPosition(this.$viewport);h="bottom"==h&&k.bottom+m>o.bottom?"top":"top"==h&&k.top-mo.width?"left":"left"==h&&k.left-lg.top+g.height&&(e.top=g.top+g.height-i)}else{var j=b.left-f,k=b.left+f+c;jg.right&&(e.left=g.left+g.width-k)}return e},c.prototype.getTitle=function(){var a,b=this.$element,c=this.options;return a=b.attr("data-original-title")||("function"==typeof c.title?c.title.call(b[0]):c.title)},c.prototype.getUID=function(a){do a+=~~(1e6*Math.random());while(document.getElementById(a));return a},c.prototype.tip=function(){if(!this.$tip&&(this.$tip=a(this.options.template),1!=this.$tip.length))throw new Error(this.type+" `template` option must consist of exactly 1 top-level element!");return this.$tip},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},c.prototype.enable=function(){this.enabled=!0},c.prototype.disable=function(){this.enabled=!1},c.prototype.toggleEnabled=function(){this.enabled=!this.enabled},c.prototype.toggle=function(b){var c=this;b&&(c=a(b.currentTarget).data("bs."+this.type),c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c))),b?(c.inState.click=!c.inState.click,c.isInStateTrue()?c.enter(c):c.leave(c)):c.tip().hasClass("in")?c.leave(c):c.enter(c)},c.prototype.destroy=function(){var a=this;clearTimeout(this.timeout),this.hide(function(){a.$element.off("."+a.type).removeData("bs."+a.type),a.$tip&&a.$tip.detach(),a.$tip=null,a.$arrow=null,a.$viewport=null,a.$element=null})};var d=a.fn.tooltip;a.fn.tooltip=b,a.fn.tooltip.Constructor=c,a.fn.tooltip.noConflict=function(){return a.fn.tooltip=d,this}}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof b&&b;!e&&/destroy|hide/.test(b)||(e||d.data("bs.popover",e=new c(this,f)),"string"==typeof b&&e[b]())})}var c=function(a,b){this.init("popover",a,b)};if(!a.fn.tooltip)throw new Error("Popover requires tooltip.js");c.VERSION="3.3.7",c.DEFAULTS=a.extend({},a.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:''}),c.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),c.prototype.constructor=c,c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content").children().detach().end()[this.options.html?"string"==typeof c?"html":"append":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},c.prototype.hasContent=function(){return this.getTitle()||this.getContent()},c.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")};var d=a.fn.popover;a.fn.popover=b,a.fn.popover.Constructor=c,a.fn.popover.noConflict=function(){return a.fn.popover=d,this}}(jQuery),+function(a){"use strict";function b(c,d){this.$body=a(document.body),this.$scrollElement=a(a(c).is(document.body)?window:c),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||"")+" .nav li > a",this.offsets=[],this.targets=[],this.activeTarget=null,this.scrollHeight=0,this.$scrollElement.on("scroll.bs.scrollspy",a.proxy(this.process,this)),this.refresh(),this.process()}function c(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})}b.VERSION="3.3.7",b.DEFAULTS={offset:10},b.prototype.getScrollHeight=function(){return this.$scrollElement[0].scrollHeight||Math.max(this.$body[0].scrollHeight,document.documentElement.scrollHeight)},b.prototype.refresh=function(){var b=this,c="offset",d=0;this.offsets=[],this.targets=[],this.scrollHeight=this.getScrollHeight(),a.isWindow(this.$scrollElement[0])||(c="position",d=this.$scrollElement.scrollTop()),this.$body.find(this.selector).map(function(){var b=a(this),e=b.data("target")||b.attr("href"),f=/^#./.test(e)&&a(e);return f&&f.length&&f.is(":visible")&&[[f[c]().top+d,e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){b.offsets.push(this[0]),b.targets.push(this[1])})},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.getScrollHeight(),d=this.options.offset+c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(this.scrollHeight!=c&&this.refresh(),b>=d)return g!=(a=f[f.length-1])&&this.activate(a);if(g&&b=e[a]&&(void 0===e[a+1]||b .dropdown-menu > .active").removeClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!1),b.addClass("active").find('[data-toggle="tab"]').attr("aria-expanded",!0),h?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu").length&&b.closest("li.dropdown").addClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!0),e&&e()}var g=d.find("> .active"),h=e&&a.support.transition&&(g.length&&g.hasClass("fade")||!!d.find("> .fade").length);g.length&&h?g.one("bsTransitionEnd",f).emulateTransitionEnd(c.TRANSITION_DURATION):f(),g.removeClass("in")};var d=a.fn.tab;a.fn.tab=b,a.fn.tab.Constructor=c,a.fn.tab.noConflict=function(){return a.fn.tab=d,this};var e=function(c){c.preventDefault(),b.call(a(this),"show")};a(document).on("click.bs.tab.data-api",'[data-toggle="tab"]',e).on("click.bs.tab.data-api",'[data-toggle="pill"]',e)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof b&&b;e||d.data("bs.affix",e=new c(this,f)),"string"==typeof b&&e[b]()})}var c=function(b,d){this.options=a.extend({},c.DEFAULTS,d),this.$target=a(this.options.target).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(b),this.affixed=null,this.unpin=null,this.pinnedOffset=null,this.checkPosition()};c.VERSION="3.3.7",c.RESET="affix affix-top affix-bottom",c.DEFAULTS={offset:0,target:window},c.prototype.getState=function(a,b,c,d){var e=this.$target.scrollTop(),f=this.$element.offset(),g=this.$target.height();if(null!=c&&"top"==this.affixed)return e=a-d&&"bottom"},c.prototype.getPinnedOffset=function(){if(this.pinnedOffset)return this.pinnedOffset;this.$element.removeClass(c.RESET).addClass("affix");var a=this.$target.scrollTop(),b=this.$element.offset();return this.pinnedOffset=b.top-a},c.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},c.prototype.checkPosition=function(){if(this.$element.is(":visible")){var b=this.$element.height(),d=this.options.offset,e=d.top,f=d.bottom,g=Math.max(a(document).height(),a(document.body).height());"object"!=typeof d&&(f=e=d),"function"==typeof e&&(e=d.top(this.$element)),"function"==typeof f&&(f=d.bottom(this.$element));var h=this.getState(g,b,e,f);if(this.affixed!=h){null!=this.unpin&&this.$element.css("top","");var i="affix"+(h?"-"+h:""),j=a.Event(i+".bs.affix");if(this.$element.trigger(j),j.isDefaultPrevented())return;this.affixed=h,this.unpin="bottom"==h?this.getPinnedOffset():null,this.$element.removeClass(c.RESET).addClass(i).trigger(i.replace("affix","affixed")+".bs.affix")}"bottom"==h&&this.$element.offset({top:g-b-f})}};var d=a.fn.affix;a.fn.affix=b,a.fn.affix.Constructor=c,a.fn.affix.noConflict=function(){return a.fn.affix=d,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var c=a(this),d=c.data();d.offset=d.offset||{},null!=d.offsetBottom&&(d.offset.bottom=d.offsetBottom),null!=d.offsetTop&&(d.offset.top=d.offsetTop),b.call(c,d)})})}(jQuery); From 09b5a49ec7827531690348b4bd14d4c83fc1bcd8 Mon Sep 17 00:00:00 2001 From: steveperry-53 Date: Mon, 28 Nov 2016 18:23:59 -0800 Subject: [PATCH 3/9] Expanded style guidance for API objects. --- docs/contribute/style-guide.md | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/docs/contribute/style-guide.md b/docs/contribute/style-guide.md index 219d62560d..1a23c7fac3 100644 --- a/docs/contribute/style-guide.md +++ b/docs/contribute/style-guide.md @@ -16,15 +16,26 @@ docs, follow the instructions on ## Documentation formatting standards -### Capitalize API objects +### Use Camel Case for API objects -Capitalize the names of API objects. Refer to API objects without saying -"object." +When you refer to an API object, use the same uppercase and lowercase letters +that are used in the actual object name. Typically, the names of API +objects use +[camel case](https://en.wikipedia.org/wiki/Camel_case). + +Don't split the API object name into separate words. For example, use +PodTemplateList, not Pod Template List. + +Refer to API objects without saying "object," unless omitting "object" +leads to an awkward construction. + + +
DoDon't
The Pod has two Containers.The pod has two containers.
The Deployment is responsible for ...The Deployment object is responsible for ...
A PodList is a list of Pods.A Pod List is a list of pods.
The two ContainerPorts ...The two ContainerPort objects ...
The two ContainerStateTerminated objects ...The two ContainerStateTerminateds ...
### Use angle brackets for placeholders From 53a59dda8e5e4521c05a659ad6f0fdfd98ba7233 Mon Sep 17 00:00:00 2001 From: Ian Lewis Date: Tue, 29 Nov 2016 17:55:13 +0900 Subject: [PATCH 4/9] Added local channels to Support page --- docs/troubleshooting.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md index 25fefcf7a1..63d307e911 100644 --- a/docs/troubleshooting.md +++ b/docs/troubleshooting.md @@ -59,6 +59,13 @@ interest. For example, people new to Kubernetes may also want to join the `#kubernetes-novice` channel. As another example, developers should join the `#kubernetes-dev` channel. +There are also many country specific/local language channels. Feel free to join +these channels for localized support and info: + +- France: `#fr-users`, `#fr-events` +- Germany: `#de-users`, `#de-events` +- Japan: `#jp-users`, `#jp-events` + ### Mailing List The Kubernetes / Google Container Engine mailing list is [kubernetes-users@googlegroups.com](https://groups.google.com/forum/#!forum/kubernetes-users) From 1b4f677f2157e764b3b19c2d887dbe7901b3dae8 Mon Sep 17 00:00:00 2001 From: Marcin Wielgus Date: Wed, 30 Nov 2016 11:40:08 +0100 Subject: [PATCH 5/9] Fix copy/paste errors in federated secrets docs --- docs/user-guide/federation/secrets.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/user-guide/federation/secrets.md b/docs/user-guide/federation/secrets.md index 763b53e98e..b796dba56f 100644 --- a/docs/user-guide/federation/secrets.md +++ b/docs/user-guide/federation/secrets.md @@ -50,7 +50,7 @@ a matching secret in all underlying kubernetes clusters. You can verify this by checking each of the underlying clusters, for example: ``` shell -kubectl --context=gce-asia-east1a get rs myrs +kubectl --context=gce-asia-east1a get secret mysecret ``` The above assumes that you have a context named 'gce-asia-east1a' @@ -77,7 +77,7 @@ the federation apiserver instead of sending it to a specific Kubernetes cluster. For example, you can do that using kubectl by running: ```shell -kubectl --context=federation-cluster delete rs myrs +kubectl --context=federation-cluster delete secret mysecret ``` Note that at this point, deleting a federated secret will not delete the From 31b8ccb76d0182378e4a9c227ad805c89c641a54 Mon Sep 17 00:00:00 2001 From: Anthony Yeh Date: Wed, 30 Nov 2016 12:48:15 -0800 Subject: [PATCH 6/9] Fix TOC in Documentation Style Guide "What's next" was listed underneath "Patterns to avoid" because the template hard-codes the heading depth. Increase depth of all other headings by 1 to match the template's expectations. --- docs/contribute/style-guide.md | 40 +++++++++++++++++----------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/docs/contribute/style-guide.md b/docs/contribute/style-guide.md index 1a23c7fac3..9d65dbda9a 100644 --- a/docs/contribute/style-guide.md +++ b/docs/contribute/style-guide.md @@ -14,9 +14,9 @@ docs, follow the instructions on {% capture body %} -## Documentation formatting standards +### Documentation formatting standards -### Use Camel Case for API objects +#### Use Camel Case for API objects When you refer to an API object, use the same uppercase and lowercase letters that are used in the actual object name. Typically, the names of API @@ -38,7 +38,7 @@ leads to an awkward construction. The two ContainerStateTerminated objects ...The two ContainerStateTerminateds ... -### Use angle brackets for placeholders +#### Use angle brackets for placeholders Use angle brackets for placeholders. Tell the reader what a placeholder represents. @@ -49,7 +49,7 @@ represents. where `` is the name of one of your pods. -### Use bold for user interface elements +#### Use bold for user interface elements @@ -57,7 +57,7 @@ represents.
DoDon't
Select Other.Select 'Other'.
-### Use italics to define or introduce new terms +#### Use italics to define or introduce new terms @@ -65,7 +65,7 @@ represents.
DoDon't
These components form the control plane.These components form the control plane.
-### Use code style for filenames, directories, and paths +#### Use code style for filenames, directories, and paths @@ -74,9 +74,9 @@ represents.
DoDon't
Open the /_data/concepts.yaml file.Open the /_data/concepts.yaml file.
-## Code snippet formatting +### Code snippet formatting -### Use code style for inline code and commands +#### Use code style for inline code and commands For inline code in an HTML document, use the `` tag. In a Markdown document, use the backtick (`). @@ -87,14 +87,14 @@ document, use the backtick (`). The kubectl run command creates a Deployment.The "kubectl run" command creates a Deployment. -### Don't include the command prompt +#### Don't include the command prompt
DoDon't
kubectl get pods$ kubectl get pods
-### Separate commands from output +#### Separate commands from output Verify that the pod is running on your chosen node: @@ -116,11 +116,11 @@ A list of Kubernetes-specific terms and words to be used consistently across the {% endcomment %} -## Content best practices +### Content best practices This section contains suggested best practices for clear, concise, and consistent content. -### Use present tense +#### Use present tense @@ -130,7 +130,7 @@ This section contains suggested best practices for clear, concise, and consisten Exception: Use future or past tense if it is required to convey the correct meaning. -### Use active voice +#### Use active voice
DoDon't
@@ -140,7 +140,7 @@ meaning. Exception: Use passive voice if active voice leads to an awkward construction. -### Use simple and direct language +#### Use simple and direct language Use simple and direct language. Avoid using unnecessary phrases, such as saying "please." @@ -152,7 +152,7 @@ Use simple and direct language. Avoid using unnecessary phrases, such as saying
DoDon't
-### Address the reader as "you" +#### Address the reader as "you" @@ -160,9 +160,9 @@ Use simple and direct language. Avoid using unnecessary phrases, such as saying
DoDon't
In the preceding output, you can see...In the preceding output, we can see ...
-## Patterns to avoid +### Patterns to avoid -### Avoid using "we" +#### Avoid using "we" Using "we" in a sentence can be confusing, because the reader might not know whether they're part of the "we" you're describing. @@ -174,7 +174,7 @@ whether they're part of the "we" you're describing. This page teaches you how to use pods.In this page, we are going to learn about pods. -### Avoid jargon and idioms +#### Avoid jargon and idioms Some readers speak English as a second language. Avoid jargon and idioms to help make their understanding easier. @@ -184,13 +184,13 @@ Some readers speak English as a second language. Avoid jargon and idioms to help Create a new cluster.Turn up a new cluster. -### Avoid statements about the future +#### Avoid statements about the future Avoid making promises or giving hints about the future. If you need to talk about an alpha feature, put the text under a heading that identifies it as alpha information. -### Avoid statements that will soon be out of date +#### Avoid statements that will soon be out of date Avoid words like "currently" and "new." A feature that is new today might not be considered new in a few months. From 1d9789c65d29e3b7b1f5dc5951eb1a3b6873ad2e Mon Sep 17 00:00:00 2001 From: Janet Kuo Date: Wed, 16 Nov 2016 14:33:06 -0800 Subject: [PATCH 7/9] Add Task: upgrading from PetSet to StatefulSet --- _data/tasks.yml | 3 + docs/tasks/index.md | 2 + .../upgrade-pet-set-to-stateful-set.md | 163 ++++++++++++++++++ 3 files changed, 168 insertions(+) create mode 100644 docs/tasks/manage-stateful-set/upgrade-pet-set-to-stateful-set.md diff --git a/_data/tasks.yml b/_data/tasks.yml index 5351d1d937..8bf7810e99 100644 --- a/_data/tasks.yml +++ b/_data/tasks.yml @@ -24,3 +24,6 @@ toc: - title: Assigning Pods to Nodes path: /docs/tasks/administer-cluster/assign-pods-nodes/ - title: Managing Stateful Applications + section: + - title: Upgrading from PetSets to StatefulSets + path: /docs/tasks/manage-stateful-set/upgrade-pet-set-to-stateful-set/ diff --git a/docs/tasks/index.md b/docs/tasks/index.md index aadfc2af84..917a37b89e 100644 --- a/docs/tasks/index.md +++ b/docs/tasks/index.md @@ -23,6 +23,8 @@ The Tasks section of the Kubernetes documentation is a work in progress #### Managing Stateful Applications +* [Upgrading from PetSets to StatefulSets](/docs/tasks/manage-stateful-set/upgrade-pet-set-to-stateful-set/) + ### What's next If you would like to write a task page, see diff --git a/docs/tasks/manage-stateful-set/upgrade-pet-set-to-stateful-set.md b/docs/tasks/manage-stateful-set/upgrade-pet-set-to-stateful-set.md new file mode 100644 index 0000000000..7dd8c84ff2 --- /dev/null +++ b/docs/tasks/manage-stateful-set/upgrade-pet-set-to-stateful-set.md @@ -0,0 +1,163 @@ +--- +assignees: +- bprashanth +- enisoc +- erictune +- foxish +- janetkuo +- kow3ns +- smarterclayton + +--- + +{% capture overview %} +This page shows how to upgrade from PetSets (Kubernetes version 1.3 or 1.4) to *StatefulSets* (Kubernetes version 1.5 or later). +{% endcapture %} + +{% capture prerequisites %} + +* If you don't have PetSets in your current cluster, or you don't plan to upgrade + your master to Kubernetes 1.5 or later, you can skip this task. + +{% endcapture %} + +{% capture steps %} + +### Differences between alpha PetSets and beta StatefulSets + +PetSet was introduced as an alpha resource in Kubernetes release 1.3, and was renamed to StatefulSet as a beta resource in 1.5. +Here are some notable changes: + +* **StatefulSet is the new PetSet**: PetSet is no longer available in Kubernetes release 1.5 or later. It becomes beta StatefulSet. To understand why the name was changed, see this [discussion thread](https://github.com/kubernetes/kubernetes/issues/27430). +* **StatefulSet guards against split brain**: StatefulSets guarantee at most one Pod for a given ordinal index can be running anywhere in a cluster, to guard against split brain scenarios with distributed applications. *TODO: Link to doc about fencing.* +* **Flipped debug annotation behavior**: The default value of the debug annotation (`pod.alpha.kubernetes.io/initialized`) is now `true`. The absence of this annotation will pause PetSet operations, but will NOT pause StatefulSet operations. In most cases, you no longer need this annotation in your StatefulSet manifests. + + +### Upgrading from PetSets to StatefulSets + +Note that these steps need to be done in the specified order. You **should +NOT upgrade your Kubernetes master, nodes, or `kubectl` to Kubernetes version +1.5 or later**, until told to do so. + +#### Find all PetSets and their manifests + +First, find all existing PetSets in your cluster: + +```shell +kubectl get petsets --all-namespaces +``` + +If you don't find any existing PetSets, you can safely upgrade your cluster to +Kubernetes version 1.5 or later. + +If you find existing PetSets and you have all their manifests at hand, you can continue to the next step to prepare StatefulSet manifests. + +Otherwise, you need to save their manifests so that you can recreate them as StatefulSets later. +Here's an example command for you to save all existing PetSets as one file. + +```shell +# Save all existing PetSets in all namespaces into a single file. Only needed when you don't have their manifests at hand. +kubectl get petsets --all-namespaces -o yaml > all-petsets.yaml +``` + +#### Prepare StatefulSet manifests + +Now, for every PetSet manifest you have, prepare a corresponding StatefulSet manifest: + +1. Change `apiVersion` from `apps/v1alpha1` to `apps/v1beta1`. +2. Change `kind` from `PetSet` to `StatefulSet`. +3. If you have the debug hook annotation `pod.alpha.kubernetes.io/initialized` set to `true`, you can remove it because it's redundant. If you don't have this annotation, you should add one, with the value set to `false`, to pause StatefulSets operations. + +It's recommended that you keep both PetSet manifests and StatefulSet manifests, so that you can safely roll back and recreate your PetSets, +if you decide not to upgrade your cluster. + +#### Delete all PetSets without cascading + +If you find existing PetSets in your cluster in the previous step, you need to delete all PetSets *without cascading*. You can do this from `kubectl` with `--cascade=false`. +Note that if the flag isn't set, **cascading deletion will be performed by default**, and all Pods managed by your PetSets will be gone. + +Delete those PetSets by specifying file names. This only works when +the files contain only PetSets, but not other resources such as Services: + +```shell +# Delete all existing PetSets without cascading +# Note that should only contain PetSets that you want to delete, but not any other resources +kubectl delete -f --cascade=false +``` + +Alternatively, delete them by specifying resource names: + +```shell +# Alternatively, delete them by name and namespace without cascading +kubectl delete petsets -n= --cascade=false +``` + +Make sure you've deleted all PetSets in the system: + +```shell +# Get all PetSets again to make sure you deleted them all +# This should return nothing +kubectl get petsets --all-namespaces +``` + +At this moment, you've deleted all PetSets in your cluster, but not their Pods, Persistent Volumes, or Persistent Volume Claims. +However, since the Pods are not managed by PetSets anymore, they will be vulnerable to node failures until you finish the master upgrade and recreate StatefulSets. + +#### Upgrade your master to Kubernetes version 1.5 or later + +Now, you can [upgrade your Kubernetes master](/docs/admin/cluster-management/#upgrading-a-cluster) to Kubernetes version 1.5 or later. +Note that **you should NOT upgrade Nodes at this time**, because the Pods +(that were once managed by PetSets) are now vulnerable to node failures. + +#### Upgrade kubectl to Kubernetes version 1.5 or later + +Upgrade `kubectl` to Kubernetes version 1.5 or later, following [the steps for installing and setting up +kubectl](/docs/user-guide/prereqs/). + +#### Create StatefulSets + +Make sure you have both master and `kubectl` upgraded to Kubernetes version 1.5 +or later before continuing: + +```shell +kubectl version +``` + +The output is similar to this: + +```shell +Client Version: version.Info{Major:"1", Minor:"5", GitVersion:"v1.5.0", GitCommit:"0776eab45fe28f02bbeac0f05ae1a203051a21eb", GitTreeState:"clean", BuildDate:"2016-11-24T22:35:03Z", GoVersion:"go1.7.3", Compiler:"gc", Platform:"linux/amd64"} +Server Version: version.Info{Major:"1", Minor:"5", GitVersion:"v1.5.0", GitCommit:"0776eab45fe28f02bbeac0f05ae1a203051a21eb", GitTreeState:"clean", BuildDate:"2016-11-24T22:30:23Z", GoVersion:"go1.7.3", Compiler:"gc", Platform:"linux/amd64"} +``` + +If both `Client Version` (`kubectl` version) and `Server Version` (master +version) are 1.5 or later, you are good to go. + +Create StatefulSets to adopt the Pods belonging to the deleted PetSets with the +StatefulSet manifests generated in the previous step: + +```shell +kubectl create -f +``` + +Make sure all StatefulSets are created and running as expected in the +newly-upgraded cluster: + +```shell +kubectl get statefulsets --all-namespaces +``` + +#### Upgrade nodes to Kubernetes version 1.5 or later (optional) + +You can now [upgrade Kubernetes nodes](/docs/admin/cluster-management/#upgrading-a-cluster) +to Kubernetes version 1.5 or later. This step is optional, but needs to be done after all StatefulSets +are created to adopt PetSets' Pods. + + +{% endcapture %} + +{% capture whatsnext %} +Learn more about debugging a StatefulSet. *TODO: Link to the task for debugging a StatefulSet.* +{% endcapture %} + +{% include templates/task.md %} From 41caedc6d6f5282eea69715cf45f8fd2e4489282 Mon Sep 17 00:00:00 2001 From: Ryan Hitchman Date: Wed, 30 Nov 2016 15:10:38 -0800 Subject: [PATCH 8/9] Lowercase 'Command' and 'Args' when describing "containers" specs. They must be lowercase in json and yaml, which is the most common user-visible interface. Partially addresses #1555. --- docs/user-guide/containers.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/docs/user-guide/containers.md b/docs/user-guide/containers.md index cf05278801..83246e6fd0 100644 --- a/docs/user-guide/containers.md +++ b/docs/user-guide/containers.md @@ -14,8 +14,8 @@ should run in a container. In this case, Kubernetes runs the image's default co to run a particular command or override the image's defaults, there are two additional fields that we can use: -1. `Command`: Controls the actual command run by the image -2. `Args`: Controls the arguments passed to the command +1. `command`: Controls the actual command run by the image +2. `args`: Controls the arguments passed to the command ### How docker handles command and arguments @@ -28,20 +28,20 @@ fields as either a string array or a string and there are subtle differences in handled. We encourage the curious to check out Docker's documentation for this feature. Kubernetes allows you to override both the image's default command (docker `Entrypoint`) and args -(docker `Cmd`) with the `Command` and `Args` fields of `Container`. The rules are: +(docker `Cmd`) with the `command` and `args` fields of `container`. The rules are: -1. If you do not supply a `Command` or `Args` for a container, the defaults defined by the image - will be used -2. If you supply a `Command` but no `Args` for a container, only the supplied `Command` will be - used; the image's default arguments are ignored -3. If you supply only `Args`, the image's default command will be used with the arguments you - supply -4. If you supply a `Command` **and** `Args`, the image's defaults will be ignored and the values - you supply will be used +1. If you do not supply a `command` or `args` for a container, the defaults defined by the image + will be used. +2. If you supply a `command` but no `args` for a container, only the supplied `command` will be + used; the image's default arguments are ignored. +3. If you supply only `args`, the image's default command will be used with the arguments you + supply. +4. If you supply a `command` **and** `args`, the image's defaults will be ignored and the values + you supply will be used. Here are examples for these rules in table format -| Image `Entrypoint` | Image `Cmd` | Container `Command` | Container `Args` | Command Run | +| Image `Entrypoint` | Image `Cmd` | Container `command` | Container `args` | Command Run | |--------------------|------------------|---------------------|--------------------|------------------| | `[/ep-1]` | `[foo bar]` | <not set> | <not set> | `[ep-1 foo bar]` | | `[/ep-1]` | `[foo bar]` | `[/ep-2]` | <not set> | `[ep-2]` | From f0f6212577396b8af92fa0bcf3f2d1870ff2ef46 Mon Sep 17 00:00:00 2001 From: Zihong Zheng Date: Thu, 17 Nov 2016 20:46:09 -0800 Subject: [PATCH 9/9] Adds docs for dns horizontal autoscaling feature --- _data/tasks.yml | 2 + docs/admin/dns.md | 2 + .../dns-horizontal-autoscaler.yaml | 31 +++ .../dns-horizontal-autoscaling.md | 238 ++++++++++++++++++ docs/tasks/index.md | 1 + 5 files changed, 274 insertions(+) create mode 100644 docs/tasks/administer-cluster/dns-horizontal-autoscaler.yaml create mode 100644 docs/tasks/administer-cluster/dns-horizontal-autoscaling.md diff --git a/_data/tasks.yml b/_data/tasks.yml index 1dc775ef73..24e19c35c1 100644 --- a/_data/tasks.yml +++ b/_data/tasks.yml @@ -31,6 +31,8 @@ toc: section: - title: Assigning Pods to Nodes path: /docs/tasks/administer-cluster/assign-pods-nodes/ + - title: Autoscaling the DNS Service in a Cluster + path: /docs/tasks/administer-cluster/dns-horizontal-autoscaling/ - title: Managing Stateful Applications section: - title: Upgrading from PetSets to StatefulSets diff --git a/docs/admin/dns.md b/docs/admin/dns.md index d75acfa093..372d9a026e 100644 --- a/docs/admin/dns.md +++ b/docs/admin/dns.md @@ -356,3 +356,5 @@ for more information. - [Docs for the DNS cluster addon](http://releases.k8s.io/{{page.githubbranch}}/build-tools/kube-dns/README.md) +## What's next +- [Autoscaling the DNS Service in a Cluster](/docs/tasks/administer-cluster/dns-horizontal-autoscaling/). diff --git a/docs/tasks/administer-cluster/dns-horizontal-autoscaler.yaml b/docs/tasks/administer-cluster/dns-horizontal-autoscaler.yaml new file mode 100644 index 0000000000..ce6a7c4b09 --- /dev/null +++ b/docs/tasks/administer-cluster/dns-horizontal-autoscaler.yaml @@ -0,0 +1,31 @@ +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: kube-dns-autoscaler + namespace: kube-system + labels: + k8s-app: kube-dns-autoscaler +spec: + template: + metadata: + labels: + k8s-app: kube-dns-autoscaler + spec: + containers: + - name: autoscaler + image: gcr.io/google_containers/cluster-proportional-autoscaler-amd64:1.0.0 + resources: + requests: + cpu: "20m" + memory: "10Mi" + command: + - /cluster-proportional-autoscaler + - --namespace=kube-system + - --configmap=kube-dns-autoscaler + - --mode=linear + - --target= + # When cluster is using large nodes(with more cores), "coresPerReplica" should dominate. + # If using small nodes, "nodesPerReplica" should dominate. + - --default-params={"linear":{"coresPerReplica":256,"nodesPerReplica":16,"min":1}} + - --logtostderr=true + - --v=2 diff --git a/docs/tasks/administer-cluster/dns-horizontal-autoscaling.md b/docs/tasks/administer-cluster/dns-horizontal-autoscaling.md new file mode 100644 index 0000000000..6ccc505468 --- /dev/null +++ b/docs/tasks/administer-cluster/dns-horizontal-autoscaling.md @@ -0,0 +1,238 @@ +--- +--- + +{% capture overview %} +This page shows how to enable and configure autoscaling of the DNS service in a +Kubernetes cluster. +{% endcapture %} + +{% capture prerequisites %} + +* {% include task-tutorial-prereqs.md %} + +* Make sure the [DNS feature](/docs/admin/dns/) itself is enabled. + +* Kubernetes version 1.4.0 or later is recommended. + +{% endcapture %} + +{% capture steps %} + +### Determining whether DNS horizontal autoscaling is already enabled + +List the Deployments in your cluster in the kube-system namespace: + + kubectl get deployment --namespace=kube-system + +The output is similar to this: + + NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE + ... + kube-dns-autoscaler 1 1 1 1 ... + ... + +If you see "kube-dns-autoscaler" in the output, DNS horizontal autoscaling is +already enabled, and you can skip to +[Tuning autoscaling parameters](#tuning-autoscaling-parameters). + +### Getting the name of your DNS Deployment or ReplicationController + +List the Deployments in your cluster in the kube-system namespace: + + kubectl get deployment --namespace=kube-system + +The output is similar to this: + + NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE + ... + kube-dns 1 1 1 1 ... + ... + +In Kubernetes versions earlier than 1.5 DNS is implemented using a +ReplicationController instead of a Deployment. So if you don't see kube-dns, +or a similar name, in the preceding output, list the ReplicationControllers in +your cluster in the kube-system namespace: + + kubectl get rc --namespace=kube-system + +The output is similar to this: + + NAME DESIRED CURRENT READY AGE + ... + kube-dns-v20 1 1 1 ... + ... + +### Determining your scale target + +If you have a DNS Deployment, your scale target is: + + Deployment/ + +where is the name of your DNS Deployment. For example, if +your DNS Deployment name is kube-dns, your scale target is Deployment/kube-dns. + +If you have a DNS ReplicationController, your scale target is: + + ReplicationController/ + +where is the name of your DNS ReplicationController. For example, +if your DNS ReplicationController name is kube-dns-v20, your scale target is +ReplicationController/kube-dns-v20. + +### Enabling DNS horizontal autoscaling + +In this section, you create a Deployment. The Pods in the Deployment run a +container based on the `cluster-proportional-autoscaler-amd64` image. + +Create a file named `dns-horizontal-autoscaler.yaml` with this content: + +{% include code.html language="yaml" file="dns-horizontal-autoscaler.yaml" ghlink="/docs/tasks/administer-cluster/dns-horizontal-autoscaler.yaml" %} + +In the file, replace `` with your scale target. + +Go to the directory that contains your configuration file, and enter this +command to create the Deployment: + + kubectl create -f dns-horizontal-autoscaler.yaml + +The output of a successful command is: + + deployment "kube-dns-autoscaler" created + +DNS horizontal autoscaling is now enabled. + +### Tuning autoscaling parameters + +Verify that the kube-dns-autoscaler ConfigMap exists: + + kubectl get configmap --namespace=kube-system + +The output is similar to this: + + NAME DATA AGE + ... + kube-dns-autoscaler 1 ... + ... + +Modify the data in the ConfigMap: + + kubectl edit configmap kube-dns-autoscaler --namespace=kube-system + +Look for this line: + + linear: '{"coresPerReplica":256,"min":1,"nodesPerReplica":16}' + +Modify the fields according to your needs. The "min" field indicates the +minimal number of DNS backends. The actual number of backends number is +calculated using this equation: + + replicas = max( ceil( cores * 1/coresPerReplica ) , ceil( nodes * 1/nodesPerReplica ) ) + +Note that the values of both `coresPerReplica` and `nodesPerReplica` are +integers. + +The idea is that when a cluster is using nodes that have many cores, +`coresPerReplica` dominates. When a cluster is using nodes that have fewer +cores, `nodesPerReplica` dominates. + +There are other supported scaling patterns. For details, see +[cluster-proportional-autoscaler](https://github.com/kubernetes-incubator/cluster-proportional-autoscaler). + +### Disable DNS horizontal autoscaling + +There are a few options for turning DNS horizontal autoscaling. Which option to +use depends on different conditions. + +#### Option 1: Scale down the kube-dns-autoscaler deployment to 0 replicas + +This option works for all situations. Enter this command: + + kubectl scale deployment --replicas=0 kube-dns-autoscaler --namespace=kube-system + +The output is: + + deployment "kube-dns-autoscaler" scaled + +Verify that the replica count is zero: + + kubectl get deployment --namespace-kube-system + +The output displays 0 in the DESIRED and CURRENT columns: + + NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE + ... + kube-dns-autoscaler 0 0 0 0 ... + ... + +#### Option 2: Delete the kube-dns-autoscaler deployment + +This option works if kube-dns-autoscaler is under your own control, which means +no one will re-create it: + + kubectl delete deployment kube-dns-autoscaler --namespace=kube-system + +The output is: + + deployment "kube-dns-autoscaler" deleted + +#### Option 3: Delete the kube-dns-autoscaler manifest file from the master node + +This option works if kube-dns-autoscaler is under control of the +[Addon Manager](https://github.com/kubernetes/kubernetes/blob/master/cluster/addons/README.md)'s +control, and you have write access to the master node. + +Sign in to the master node and delete the corresponding manifest file. +The common path for this kube-dns-autoscaler is: + + /etc/kubernetes/addons/dns-horizontal-autoscaler/dns-horizontal-autoscaler.yaml + +After the manifest file is deleted, the Addon Manager will delete the +kube-dns-autoscaler Deployment. + +{% endcapture %} + +{% capture discussion %} + +### Understanding how DNS horizontal autoscaling works + +* The cluster-proportional-autoscaler application is deployed separately from +the DNS service. + +* An autoscaler Pod runs a client that polls the Kubernetes API server for the +number of nodes and cores in the cluster. + +* A desired replica count is calculated and applied to the DNS backends based on +the current schedulable nodes and cores and the given scaling parameters. + +* The scaling parameters and data points are provided via a ConfigMap to the +autoscaler, and it refreshes its parameters table every poll interval to be up +to date with the latest desired scaling parameters. + +* Changes to the scaling parameters are allowed without rebuilding or restarting +the autoscaler Pod. + +* The autoscaler provides a controller interface to support two control +patterns: *linear* and *ladder*. + +### Future enhancements + +Control patterns, in addition to linear and ladder, that consider custom metrics +are under consideration as a future development. + +Scaling of DNS backends based on DNS-specific metrics is under consideration as +a future development. The current implementation, which uses the number of nodes +and cores in cluster, is limited. + +Support for custom metrics, similar to that provided by +[Horizontal Pod Autoscaling](http://kubernetes.io/docs/user-guide/horizontal-pod-autoscaling/), +is under consideration as a future development. + +{% endcapture %} + +{% capture whatsnext %} +Learn more about the +[implementation of cluster-proportional-autoscaler](https://github.com/kubernetes-incubator/cluster-proportional-autoscaler). +{% endcapture %} + + +{% include templates/task.md %} diff --git a/docs/tasks/index.md b/docs/tasks/index.md index 486d8f4af2..d8e46cff09 100644 --- a/docs/tasks/index.md +++ b/docs/tasks/index.md @@ -26,6 +26,7 @@ single thing, typically by giving a short sequence of steps. #### Administering a Cluster * [Assigning Pods to Nodes](/docs/tasks/administer-cluster/assign-pods-nodes/) +* [Autoscaling the DNS Service in a Cluster](/docs/tasks/administer-cluster/dns-horizontal-autoscaling/) #### Managing Stateful Applications