201 lines
190 KiB
HTML
201 lines
190 KiB
HTML
<!doctype html><html lang="en"><head><meta charset="utf-8"><title>Graceful shutdown in Kubernetes</title><meta name="description" content="Prevent broken connections in Kubernetes. Learn graceful Pod shutdown techniques and how to handle long-running tasks during termination."><meta name="author" content="LearnKube"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><meta name="twitter:card" content="summary"><meta name="twitter:site" content="@learnk8s"><meta property="fb:app_id" content="398212777530104"><link rel="icon" href="https://static.learnkube.com/42aedfb7aa4f77d9f4fccd385dc684df.ico"><link rel="icon" href="https://static.learnkube.com/f7e5160d4744cf05c46161170b5c11c9.svg" type="image/svg+xml" sizes="any"><link rel="apple-touch-icon" href="https://static.learnkube.com/fddc0853df06c9c0c0f9f79b96abc14d.png"><link rel="manifest" href="/manifest.webmanifest"><link rel="alternate" type="application/rss+xml" title="Subscribe to LearnKube RSS" href="/rss.xml"><meta property="og:site_name" content="LearnKube"><meta property="og:url" content="https://learnkube.com/graceful-shutdown"><meta property="og:type" content="website"><meta property="og:title" content="Graceful shutdown in Kubernetes"><meta property="og:image" content="https://static.learnkube.com/072474a3fd39da0bed6609809b22668b.png"><meta property="og:description" content="Prevent broken connections in Kubernetes. Learn graceful Pod shutdown techniques and how to handle long-running tasks during termination."><link rel="canonical" href="https://learnkube.com/graceful-shutdown"><script type="application/ld+json">{"@context":"https://schema.org","@type":"NewsArticle","headline":"Graceful shutdown in Kubernetes","image":["https://static.learnkube.com/072474a3fd39da0bed6609809b22668b.png"],"author":[{"@type":"Person","name":"Daniele Polencic"}],"publisher":{"@id":"https://learnkube.com/contact-us"},"datePublished":"2020-08-12","dateModified":"2024-04-22","mainEntityOfPage":{"@type":"SoftwareSourceCode","@id":"https://learnkube.com/graceful-shutdown"}}</script><script type="module" src="https://static.cloudflareinsights.com/beacon.min.js" data-cf-beacon="{"token": "420c6fdfc4ce4102b309ee1b61a6676c"}"></script><style>input[type=radio]:checked~.checked-reveal{display:block}.pagination-icon{stroke:currentColor;stroke-linecap:round;stroke-linejoin:round;stroke-width:.125rem;display:inline-block;width:.4rem}.mark{--mark-color:oklch(29.38% 0.07 243.72);--mark-skew:0.25em;--mark-height:1.05em;--mark-overlap:0.3em;background-color:transparent;background-image:linear-gradient(to bottom right,transparent 50%,var(--mark-color) 50%),linear-gradient(to right,var(--mark-color),var(--mark-color)),linear-gradient(to top left,transparent 50%,var(--mark-color) 50%);background-position:0 50%,50% 50%,100% 50%;background-repeat:no-repeat;background-size:var(--mark-skew) var(--mark-height),calc(100% - var(--mark-skew)*2 + 1px) var(--mark-height),var(--mark-skew) var(--mark-height);-webkit-box-decoration-break:clone;box-decoration-break:clone;margin-inline:calc(var(--mark-overlap)*-1);padding-inline:var(--mark-overlap)}.mark--primary{--mark-color:oklch(29.38% 0.07 243.72);color:#fff}
|
|
|
|
/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}h1{font-size:2em;margin:.67em 0}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent}strong{font-weight:bolder}code{font-family:monospace,monospace;font-size:1em}img{border-style:none}input{font-family:inherit;font-size:100%;line-height:1.15;margin:0;overflow:visible}[type=radio]{box-sizing:border-box;padding:0}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}a,article,aside,blockquote,body,code,div,footer,h1,h2,header,html,li,nav,ol,p,pre,section,ul{box-sizing:border-box}.bg-light-gray{background-color:#eee}.b--light-gray{border-color:#eee}.bg-near-white{background-color:#f4f4f4}.white{color:#fff}.bg-white{background-color:#fff}.b--white{border-color:#fff}.black-90{color:rgba(0,0,0,.9)}.black-80{color:rgba(0,0,0,.8)}.black-70{color:rgba(0,0,0,.7)}.b--black-70{border-color:rgba(0,0,0,.7)}.black-60{color:rgba(0,0,0,.6)}.black-50{color:rgba(0,0,0,.5)}.bg-black-10{background-color:rgba(0,0,0,.1)}.b--black-10{border-color:rgba(0,0,0,.1)}.white-80{color:hsla(0,0%,100%,.8)}.white-60{color:hsla(0,0%,100%,.6)}.b--white-60{border-color:hsla(0,0%,100%,.6)}.b--white-20{border-color:hsla(0,0%,100%,.2)}.dark-red{color:#e7040f}.bg-dark-red{background-color:#e7040f}.bg-yellow{background-color:gold}.bg-green{background-color:#19a974}.b--blue{border-color:#357edd}.navy{color:#001b44}.b--navy{border-color:#001b44}.hover-sky:focus,.hover-sky:hover{color:#569ad1}.bg-sky{background-color:#569ad1}.bg-evian{background-color:#f7f9fc}.link{text-decoration:none}.link,.link:active,.link:focus,.link:hover,.link:link,.link:visited{transition:color .15s ease-in}.link:focus{outline:1px dotted currentColor}.aspect-ratio{height:0;position:relative}.aspect-ratio--4x3{padding-bottom:75%}.aspect-ratio--5x7{padding-bottom:140%}.aspect-ratio--6x2{padding-bottom:33.33%}.aspect-ratio--1x1{padding-bottom:100%}.aspect-ratio--object{bottom:0;height:100%;left:0;position:absolute;right:0;top:0;width:100%;z-index:8}.ba{border-style:solid;border-width:1px}.bt{border-top-style:solid;border-top-width:1px}.bb{border-bottom-style:solid;border-bottom-width:1px}.bl{border-left-style:solid;border-left-width:1px}.bn{border-style:none;border-width:0}.br1{border-radius:.125rem}.br2{border-radius:.25rem}.br-100{border-radius:100%}.br--bottom{border-top-left-radius:0;border-top-right-radius:0}.br--top{border-bottom-left-radius:0;border-bottom-right-radius:0}.bw2{border-width:.25rem}.bw3{border-width:.5rem}.top-0{top:0}.right-0{right:0}.bottom-0{bottom:0}.left-0{left:0}.bottom-1{bottom:1rem}.cf:after,.cf:before{content:" ";display:table}.cf:after{clear:both}.cf{*zoom:1}.dn{display:none}.db{display:block}.dib{display:inline-block}.flex{display:flex}.flex-auto{flex:1 1 auto;min-height:0;min-width:0}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.items-center{align-items:center}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.flex-shrink-0{flex-shrink:0}.i{font-style:italic}.fs-normal{font-style:normal}.b{font-weight:700}.h1{height:1rem}.h2{height:2rem}.center{margin-left:auto;margin-right:auto}.lh-title{line-height:1.25}.lh-copy{line-height:1.5}.mw2{max-width:2rem}.mw6{max-width:32rem}.mw7{max-width:48rem}.w1{width:1rem}.w2{width:2rem}.w3{width:4rem}.w5{width:16rem}.w-20{width:20%}.w-40{width:40%}.w-60{width:60%}.w-100{width:100%}.overflow-hidden{overflow:hidden}.overflow-auto{overflow:auto}.relative{position:relative}.absolute{position:absolute}.pl0{padding-left:0}.pt0{padding-top:0}.pb0{padding-bottom:0}.mt0,.mv0{margin-top:0}.mv0{margin-bottom:0}.pa1{padding:.25rem}.pl1{padding-left:.25rem}.pv1{padding-bottom:.25rem;padding-top:.25rem}.ph1{padding-left:.25rem;padding-right:.25rem}.ml1{margin-left:.25rem}.mb1,.mv1{margin-bottom:.25rem}.mv1{margin-top:.25rem}.pr2{padding-right:.5rem}.pt2{padding-top:.5rem}.pb2,.pv2{padding-bottom:.5rem}.pv2{padding-top:.5rem}.ph2{padding-left:.5rem;padding-right:.5rem}.ml2{margin-left:.5rem}.mr2{margin-right:.5rem}.mt2{margin-top:.5rem}.mb2,.mv2{margin-bottom:.5rem}.mv2{margin-top:.5rem}.mh2{margin-left:.5rem;margin-right:.5rem}.pa3{padding:1rem}.pl3{padding-left:1rem}.pt3{padding-top:1rem}.pb3,.pv3{padding-bottom:1rem}.pv3{padding-top:1rem}.ph3{padding-left:1rem;padding-right:1rem}.mt3{margin-top:1rem}.mb3,.mv3{margin-bottom:1rem}.mv3{margin-top:1rem}.mh3{margin-left:1rem;margin-right:1rem}.pb4,.pv4{padding-bottom:2rem}.pv4{padding-top:2rem}.ph4{padding-left:2rem;padding-right:2rem}.mt4{margin-top:2rem}.mb4,.mv4{margin-bottom:2rem}.mv4{margin-top:2rem}.pt5{padding-top:4rem}.underline{text-decoration:underline}.tr{text-align:right}.tc{text-align:center}.ttu{text-transform:uppercase}.f2{font-size:2.25rem}.f3{font-size:1.5rem}.f4{font-size:1.25rem}.f5{font-size:1rem}.f6{font-size:.875rem}.f7{font-size:.75rem}.measure{max-width:30em}.measure-wide{max-width:34em}.word-wrap{word-break:break-all}.o-30{opacity:.3}.o-0{opacity:0}.sans-serif{font-family:-apple-system,BlinkMacSystemFont,avenir next,avenir,helvetica neue,helvetica,ubuntu,roboto,noto,segoe ui,arial,sans-serif}.code,code{font-family:Consolas,monaco,monospace}.underline-hover:focus,.underline-hover:hover{text-decoration:underline}.pointer:hover{cursor:pointer}img{max-width:100%}.list{list-style-type:none}.z-1{z-index:1}.z-999{z-index:999}.z-max{z-index:2147483647}.code-light-theme{-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none;padding-bottom:2ch;padding-top:2ch;-moz-tab-size:4;-o-tab-size:4;tab-size:4}.code-light-theme .code{float:left;min-width:100%}.code-light-theme .command,.code-light-theme .highlight,.code-light-theme .output,.code-light-theme .standard{box-sizing:border-box;display:block;min-width:100%;padding-left:2ch;padding-right:2ch}.code-light-theme .code .prompt.empty:after{-webkit-animation:blinking 1s step-end infinite;-moz-animation:blinking 1s step-end infinite;-ms-animation:blinking 1s step-end infinite;-o-animation:blinking 1s step-end infinite;animation:blinking 1s step-end infinite;content:"_"}.code-dark-theme{-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none;padding-bottom:2ch;padding-top:2ch;-moz-tab-size:4;-o-tab-size:4;tab-size:4}.code-dark-theme .code{float:left;min-width:100%}.code-dark-theme .command,.code-dark-theme .highlight,.code-dark-theme .output,.code-dark-theme .standard{box-sizing:border-box;display:block;min-width:100%;padding-left:2ch;padding-right:2ch}.code-dark-theme .code .prompt.empty:after{-webkit-animation:blinking 1s step-end infinite;-moz-animation:blinking 1s step-end infinite;-ms-animation:blinking 1s step-end infinite;-o-animation:blinking 1s step-end infinite;animation:blinking 1s step-end infinite;content:"_"}@keyframes blinking{0%,to{color:transparent}50%{color:#fff}}@-moz-keyframes blinking{0%,to{color:transparent}50%{color:#fff}}@-webkit-keyframes blinking{0%,to{color:transparent}50%{color:#fff}}@-ms-keyframes blinking{0%,to{color:transparent}50%{color:#fff}}@-o-keyframes blinking{0%,to{color:transparent}50%{color:#fff}}.code-light-theme{background-color:#fdf6e3;color:#657b83}.code-light-theme ::-moz-selection,.code-light-theme::-moz-selection{background:#073642}.code-light-theme ::selection,.code-light-theme::selection{background:#073642}.code-light-theme .token.comment{color:#93a1a1}.code-light-theme .token.punctuation{color:#586e75}.code-light-theme .token.boolean,.code-light-theme .token.number{color:#268bd2}.code-light-theme .token.builtin,.code-light-theme .token.string{color:#2aa198}.code-light-theme .token.atrule,.code-light-theme .token.keyword{color:#859900}.code-light-theme .token.class-name,.code-light-theme .token.function{color:#b58900}.code-light-theme .token.variable{color:#cb4b16}.code-light-theme .highlight{background:#ffe6c3}.code-dark-theme{background-color:#272822;color:#f8f8f2}.code-dark-theme .token.comment{color:#708090}.code-dark-theme .token.punctuation{color:#f8f8f2}.code-dark-theme .token.boolean,.code-dark-theme .token.number{color:#ae81ff}.code-dark-theme .token.builtin,.code-dark-theme .token.string{color:#a6e22e}.code-dark-theme .token.operator,.code-dark-theme .token.variable{color:#f8f8f2}.code-dark-theme .token.atrule,.code-dark-theme .token.class-name,.code-dark-theme .token.function{color:#e6db74}.code-dark-theme .token.keyword{color:#66d9ef}.code-dark-theme .highlight{background:#5f6155}.code-dark-theme .code .prompt{position:relative;text-indent:2ch}.code-dark-theme .code .prompt:before{content:"$";left:0;position:absolute;top:0}@media screen and (min-width:32em){.dn-ns{display:none}.db-ns{display:block}.mw4-ns{max-width:8rem}.pa4-ns{padding:2rem}.ph4-ns{padding-left:2rem;padding-right:2rem}.mt5-ns,.mv5-ns{margin-top:4rem}.mv5-ns{margin-bottom:4rem}.f1-ns{font-size:3rem}}@media screen and (min-width:64em){.bn-l{border-style:none;border-width:0}.dn-l{display:none}.flex-l{display:flex}.items-start-l{align-items:flex-start}.items-center-l{align-items:center}.justify-around-l{justify-content:space-around}.mw9-l{max-width:96rem}.mw-100-l{max-width:100%}.w-100-l{width:100%}.static-l{position:static}.sticky-l{position:sticky}.mv0-l{margin-bottom:0;margin-top:0}.pv2-l{padding-bottom:.5rem;padding-top:.5rem}.ml3-l{margin-left:1rem}.mb5-l,.mv5-l{margin-bottom:4rem}.mv5-l{margin-top:4rem}}@media screen and (max-width:64em){#main-menu .reveal{background-color:#001b44;display:none}#main-menu:target .reveal{display:inherit}}.hamburger-icon{background:#fff;border-radius:.2rem;display:inline-block;height:.213em;position:relative;width:1.625em}.hamburger-icon:after,.hamburger-icon:before{background:#fff;content:"";height:.213em;position:absolute;width:1.625em}.hamburger-icon:before{top:-.625em}.hamburger-icon:after{bottom:-.625em}.x-icon{display:inline-block;height:.213em;position:relative;width:1.625em}.x-icon:after,.x-icon:before{background:#fff;content:"";height:.213em;left:0;margin-top:-.106em;position:absolute;top:50%;width:1.625em}.x-icon:before{transform:rotate(45deg)}.x-icon:after{transform:rotate(-45deg)}#group-sigterm-go:checked~section .tab-sigterm-go{display:block}#group-sigterm-go:checked~section .tab-sigterm-c-,#group-sigterm-go:checked~section .tab-sigterm-java,#group-sigterm-go:checked~section .tab-sigterm-node-js,#group-sigterm-go:checked~section .tab-sigterm-python{display:none}#group-sigterm-go:checked~nav .tab-sigterm-go{opacity:1}#group-sigterm-python:checked~section .tab-sigterm-python{display:block}#group-sigterm-python:checked~section .tab-sigterm-c-,#group-sigterm-python:checked~section .tab-sigterm-go,#group-sigterm-python:checked~section .tab-sigterm-java,#group-sigterm-python:checked~section .tab-sigterm-node-js{display:none}#group-sigterm-python:checked~nav .tab-sigterm-python{opacity:1}#group-sigterm-node-js:checked~section .tab-sigterm-node-js{display:block}#group-sigterm-node-js:checked~section .tab-sigterm-c-,#group-sigterm-node-js:checked~section .tab-sigterm-go,#group-sigterm-node-js:checked~section .tab-sigterm-java,#group-sigterm-node-js:checked~section .tab-sigterm-python{display:none}#group-sigterm-node-js:checked~nav .tab-sigterm-node-js{opacity:1}#group-sigterm-java:checked~section .tab-sigterm-java{display:block}#group-sigterm-java:checked~section .tab-sigterm-c-,#group-sigterm-java:checked~section .tab-sigterm-go,#group-sigterm-java:checked~section .tab-sigterm-node-js,#group-sigterm-java:checked~section .tab-sigterm-python{display:none}#group-sigterm-java:checked~nav .tab-sigterm-java{opacity:1}#group-sigterm-c-:checked~section .tab-sigterm-c-{display:block}#group-sigterm-c-:checked~section .tab-sigterm-go,#group-sigterm-c-:checked~section .tab-sigterm-java,#group-sigterm-c-:checked~section .tab-sigterm-node-js,#group-sigterm-c-:checked~section .tab-sigterm-python{display:none}#group-sigterm-c-:checked~nav .tab-sigterm-c-{opacity:1}</style></head><body class="bg-near-white sans-serif" tabindex="0"><div class="cf w-100 mw9-l center bg-white"><div class="white sticky-l top-0 z-max"><nav id="main-menu" class="nav bg-sky flex items-center justify-between ph1 pv2"><a href="/" class="logo db w-40 mw2 mw4-ns ml3-l" title="LearnKube logo"><div class="dn db-ns aspect-ratio aspect-ratio--6x2"><svg viewBox="0 0 600 200" fill="none" xmlns="http://www.w3.org/2000/svg" class="aspect-ratio--object"><path d="M495.926 130.824c-7.288 2.113-18.574 1.288-26.229 1.288-7.099 0-16.946.24-21.841-5.796-2.052-2.609-3.513-5.693-4.381-9.252-.868-3.558-1.302-7.473-1.302-11.743V69.563h17.641v33.623c0 5.693.75 9.806 2.25 12.336 1.499 2.53 4.302 3.796 8.406 3.796 1.263 0 2.605-.04 4.026-.119 1.42-.158 2.683-.316 3.789-.474V69.563h17.641v61.261Z" fill="#172777"></path><path d="M403.054 92.099a458.397 458.397 0 0 0 5.328-5.931 341.965 341.965 0 0 0 5.446-6.05 622.044 622.044 0 0 0 4.854-5.812 234.17 234.17 0 0 0 4.026-4.745h20.956a795.383 795.383 0 0 1-12.313 13.879c-3.947 4.35-8.288 8.857-13.024 13.522 2.368 2.135 4.815 4.706 7.341 7.71a168.067 168.067 0 0 1 7.34 9.134 135.733 135.733 0 0 1 6.513 9.49c1.973 3.163 3.296 6.205 4.638 8.815h-20.246c-1.263-2.056-2.389-4.466-4.047-6.918a113.315 113.315 0 0 0-5.091-7.473 86.104 86.104 0 0 0-5.801-7.235c-1.974-2.294-3.947-4.231-5.92-5.813v27.439h-17.642v-59.45l17.642-3.1V92.1Zm146.116 40.012v-62.55h42.91v12.034h-28.606v13.488h25.397v11.758h-25.397v14.233h30.714v11.037H549.17Zm-30.042 0c-5.32 0-15.092 0-21.364-1.123V69.562h19.8c4.806 0 15.251.596 19.442 3.01 2.445 1.41 4.34 3.277 5.685 5.604 1.406 2.266 2.109 5.083 2.109 8.45 0 5.084-2.445 9.095-7.335 12.034 4.034 1.531 6.785 3.613 8.252 6.246 1.467 2.634 2.2 5.604 2.2 8.911 0 6.674-2.445 11.696-7.335 15.064-4.829 3.368-11.858 3.23-21.454 3.23Zm-7.427-26.745v16.442c1.039.122 2.17.214 3.392.276 1.223.061 2.568.091 4.035.091 4.278 0 7.732-.612 10.36-1.837 2.628-1.224 3.943-3.49 3.943-6.797 0-2.939-1.101-5.022-3.301-6.246-2.201-1.286-5.348-1.929-9.444-1.929h-8.985Zm0-10.931h6.968c4.401 0 7.549-.552 9.444-1.654 1.895-1.163 2.842-3 2.842-5.511 0-2.572-.978-4.379-2.934-5.42-1.956-1.04-4.829-1.561-8.618-1.561-1.223 0-2.537.03-3.943.092-1.406 0-2.659.06-3.759.183v13.87Z" fill="#172777"></path><path d="M362.572 133.21V98.054c0-5.034-.743-8.665-2.228-10.893-1.403-2.228-3.838-3.342-7.304-3.342-3.053 0-5.653.908-7.798 2.723-2.063 1.733-3.549 3.92-4.457 6.561v40.107h-16.092V71.316h12.75l1.857 8.17h.495c1.898-2.64 4.415-4.951 7.551-6.932 3.136-1.98 7.18-2.97 12.131-2.97 3.054 0 5.777.412 8.17 1.237a13.913 13.913 0 0 1 6.066 4.085c1.65 1.898 2.888 4.498 3.713 7.799.825 3.218 1.238 7.22 1.238 12.007v38.498h-16.092Zm-44.636-46.791c-2.558-.908-4.869-1.362-6.932-1.362-2.888 0-5.323.784-7.303 2.352-1.898 1.485-3.178 3.425-3.838 5.818v39.983h-16.092V71.317h12.502l1.857 8.17h.495c1.403-3.054 3.301-5.406 5.695-7.056 2.393-1.65 5.199-2.476 8.417-2.476 2.146 0 4.58.454 7.303 1.362l-2.104 15.102Zm-93.47-11.513c3.301-1.485 7.22-2.64 11.759-3.466 4.539-.907 9.284-1.361 14.236-1.361 4.291 0 7.881.536 10.769 1.609 2.889.99 5.158 2.434 6.808 4.332 1.733 1.898 2.93 4.168 3.59 6.809.743 2.64 1.114 5.611 1.114 8.912 0 3.631-.123 7.304-.371 11.017a239.105 239.105 0 0 0-.495 10.77c0 3.548.124 7.014.371 10.398.248 3.301.867 6.437 1.857 9.408h-13.121l-2.6-8.542h-.619c-1.65 2.559-3.961 4.787-6.932 6.685-2.888 1.815-6.643 2.723-11.264 2.723-2.889 0-5.488-.413-7.799-1.238-2.311-.908-4.291-2.145-5.942-3.713a17.79 17.79 0 0 1-3.837-5.695c-.908-2.228-1.362-4.703-1.362-7.427 0-3.796.825-6.973 2.476-9.531 1.733-2.641 4.167-4.745 7.303-6.313 3.219-1.65 7.015-2.765 11.389-3.343 4.456-.66 9.407-.866 14.854-.619.578-4.621.248-7.922-.99-9.903-1.238-2.063-4.003-3.094-8.294-3.094-3.218 0-6.643.33-10.274.99-3.549.66-6.478 1.527-8.789 2.6l-3.837-12.008Zm20.424 46.049c3.219 0 5.777-.702 7.675-2.104 1.898-1.486 3.301-3.054 4.209-4.704v-8.046a44.901 44.901 0 0 0-7.427-.124c-2.311.165-4.374.536-6.19 1.114-1.815.577-3.259 1.403-4.332 2.476-1.073 1.072-1.609 2.434-1.609 4.085 0 2.31.66 4.126 1.98 5.446 1.403 1.238 3.301 1.857 5.694 1.857Zm-30.923 6.932c-2.476 1.981-5.859 3.672-10.151 5.075-4.208 1.321-8.706 1.981-13.492 1.981-9.986 0-17.289-2.889-21.911-8.665-4.621-5.859-6.932-13.864-6.932-24.015 0-10.893 2.6-19.063 7.799-24.51 5.199-5.446 12.502-8.17 21.91-8.17 3.136 0 6.19.413 9.16 1.238 2.971.826 5.612 2.187 7.923 4.085 2.31 1.898 4.167 4.457 5.57 7.675 1.403 3.218 2.105 7.221 2.105 12.007 0 1.733-.124 3.59-.372 5.571a58.75 58.75 0 0 1-.866 6.189h-37.136c.247 5.199 1.568 9.119 3.961 11.76 2.476 2.641 6.437 3.961 11.883 3.961 3.384 0 6.396-.495 9.037-1.485 2.723-1.073 4.786-2.146 6.189-3.219l5.323 10.522Zm-23.024-45.43c-4.209 0-7.345 1.28-9.408 3.838-1.981 2.475-3.177 5.818-3.59 10.026h23.024c.33-4.456-.371-7.88-2.104-10.274-1.65-2.393-4.291-3.59-7.922-3.59Zm-43.814 29.957c0 2.888.371 4.993 1.114 6.313.743 1.321 1.939 1.981 3.59 1.981.99 0 1.939-.083 2.847-.248.99-.165 2.187-.536 3.59-1.114l1.733 12.626c-1.321.661-3.343 1.321-6.066 1.981-2.723.66-5.529.99-8.417.99-4.704 0-8.294-1.073-10.77-3.218-2.476-2.228-3.713-5.859-3.713-10.893V46.56h16.092v65.854Zm-30.195-15.843-50.231-50.23c-2.36-2.36-6.068-2.36-8.428 0L8.044 96.57c-2.36 2.36-2.36 6.068 0 8.428l50.231 50.231c2.36 2.36 6.068 2.36 8.428 0l50.231-50.231c2.36-2.36 2.36-6.068 0-8.428Z" fill="#225DE0"></path><path d="M50.696 114.775a193.809 193.809 0 0 1-10.113-3.708c.674-.338 1.348-1.012 1.685-1.349 3.372-2.36 6.069-9.439 10.114-20.227a192.825 192.825 0 0 1 3.708-10.114c.337.674 1.012 1.349 1.349 1.686 2.36 3.371 9.44 6.068 20.227 10.113a192.83 192.83 0 0 1 10.114 3.709c-.675.337-1.349 1.011-1.686 1.348-3.371 2.36-6.068 9.44-10.114 20.227a192.47 192.47 0 0 1-3.708 10.114c-.337-.674-1.011-1.348-1.348-1.686-2.36-3.371-9.44-6.068-20.228-10.113Zm-15.17-7.754c-2.36 0-4.383-2.023-4.383-4.045 0-2.023 2.023-4.046 4.383-4.046s4.383 2.023 4.383 4.046c0 2.022-2.023 4.045-4.383 4.045Zm28.655-37.083c2.36 0 4.046 2.023 4.046 4.045 0 2.023-2.023 4.046-4.046 4.046s-4.045-2.023-4.045-4.046c0-2.022 2.022-4.045 4.045-4.045Zm28.993 28.655c2.36 0 4.045 2.023 4.045 4.046 0 2.022-2.023 4.045-4.045 4.045-2.023 0-4.046-2.023-4.046-4.045 0-2.023 2.023-4.046 4.046-4.046Zm-28.993 37.42c-2.36 0-4.045-2.022-4.045-4.045s2.022-4.045 4.045-4.045 4.046 2.022 4.046 4.045-2.023 4.045-4.046 4.045Zm-9.44-4.382c0 5.394 4.383 9.439 9.44 9.439 5.057 0 5.057-1.011 6.743-3.034 3.37-2.36 6.068-9.439 10.113-20.227a193.13 193.13 0 0 1 3.709-10.114c1.685 2.697 4.72 4.383 8.09 4.383 5.394 0 9.44-4.383 9.44-9.439 0-5.057-1.012-5.057-3.034-6.743-2.36-3.371-9.44-6.068-20.228-10.113a192.83 192.83 0 0 1-10.113-3.709c2.697-1.685 4.382-4.72 4.382-8.09 0-5.395-4.382-9.44-9.439-9.44s-5.057 1.011-6.742 3.034c-3.371 2.36-6.069 9.44-10.114 20.227A192.825 192.825 0 0 1 43.28 97.92c-1.686-2.697-4.72-4.383-8.091-4.383-5.394 0-9.44 4.383-9.44 9.44 0 5.056 1.012 5.056 3.035 6.742 2.36 3.371 9.439 6.068 20.227 10.114a192 192 0 0 1 10.113 3.708c-2.697 1.686-4.382 4.72-4.382 8.091Z" fill="#003C84"></path><path d="M48.835 112.753a192.9 192.9 0 0 1-10.113-3.708c.674-.338 1.348-1.012 1.685-1.349 3.372-2.36 6.069-9.44 10.114-20.227a192.948 192.948 0 0 1 3.708-10.114c.337.675 1.012 1.349 1.349 1.686 2.36 3.371 9.44 6.068 20.227 10.114a192.825 192.825 0 0 1 10.113 3.708c-.674.337-1.348 1.011-1.685 1.348-3.371 2.36-6.068 9.44-10.114 20.228a192.69 192.69 0 0 1-3.708 10.113c-.337-.674-1.011-1.348-1.349-1.685-2.36-3.372-9.439-6.069-20.227-10.114Zm-15.17-7.754c-2.36 0-4.383-2.023-4.383-4.045 0-2.023 2.023-4.046 4.383-4.046s4.383 2.023 4.383 4.046c0 2.022-2.023 4.045-4.383 4.045ZM62.32 67.916c2.36 0 4.046 2.023 4.046 4.045 0 2.023-2.023 4.046-4.046 4.046s-4.045-2.023-4.045-4.046c0-2.022 2.022-4.045 4.045-4.045ZM91.312 96.57c2.36 0 4.046 2.023 4.046 4.046 0 2.022-2.023 4.045-4.046 4.045-2.022 0-4.045-2.023-4.045-4.045 0-2.023 2.023-4.046 4.045-4.046ZM62.32 133.99c-2.36 0-4.045-2.022-4.045-4.045s2.022-4.045 4.045-4.045 4.046 2.022 4.046 4.045-2.023 4.045-4.046 4.045Zm-9.44-4.382c0 5.394 4.383 9.439 9.44 9.439 5.057 0 5.057-1.011 6.742-3.034 3.372-2.36 6.069-9.439 10.114-20.227a193.221 193.221 0 0 1 3.708-10.114c1.686 2.697 4.72 4.383 8.091 4.383 5.394 0 9.44-4.383 9.44-9.439 0-5.057-1.012-5.057-3.034-6.743-2.36-3.371-9.44-6.068-20.228-10.113a192.915 192.915 0 0 1-10.113-3.709c2.697-1.685 4.382-4.72 4.382-8.09 0-5.395-4.382-9.44-9.439-9.44s-5.057 1.011-6.742 3.034c-3.372 2.36-6.069 9.44-10.114 20.227a192.825 192.825 0 0 1-3.708 10.114c-1.686-2.697-4.72-4.383-8.091-4.383-5.394 0-9.44 4.383-9.44 9.44 0 5.057 1.012 5.057 3.034 6.742 2.36 3.371 9.44 6.068 20.228 10.114a192.9 192.9 0 0 1 10.113 3.708c-2.697 1.686-4.382 4.72-4.382 8.091Z" fill="#fff"></path></svg></div><div class="dn-ns aspect-ratio aspect-ratio--1x1"><svg viewBox="0 0 200 200" fill="none" xmlns="http://www.w3.org/2000/svg" class="aspect-ratio--object"><path d="M189.091 92.674 106.527 10.11c-3.879-3.879-9.974-3.879-13.853 0L10.11 92.674c-3.879 3.879-3.879 9.974 0 13.853l82.564 82.564c3.879 3.879 9.974 3.879 13.853 0l82.564-82.564c3.879-3.879 3.879-9.974 0-13.853Z" fill="#225DE0"></path><path d="M80.217 122.595a317.013 317.013 0 0 1-16.623-6.095c1.108-.554 2.216-1.663 2.77-2.217 5.541-3.879 9.974-15.515 16.624-33.247a316.942 316.942 0 0 1 6.095-16.624c.554 1.109 1.663 2.217 2.217 2.771 3.879 5.541 15.515 9.974 33.247 16.624a316.801 316.801 0 0 1 16.623 6.095c-1.108.554-2.216 1.662-2.77 2.216-5.541 3.88-9.974 15.516-16.624 33.248a316.967 316.967 0 0 1-6.095 16.623c-.554-1.108-1.662-2.216-2.217-2.77-3.878-5.542-15.515-9.975-33.247-16.624ZM55.282 109.85c-3.879 0-7.204-3.324-7.204-6.649s3.325-6.65 7.204-6.65c3.879 0 7.203 3.325 7.203 6.65s-3.324 6.649-7.203 6.649Zm47.1-60.953c3.879 0 6.649 3.325 6.649 6.65 0 3.324-3.324 6.649-6.649 6.649s-6.65-3.325-6.65-6.65c0-3.324 3.325-6.649 6.65-6.649Zm47.654 47.1c3.879 0 6.65 3.325 6.65 6.65s-3.325 6.649-6.65 6.649c-3.324 0-6.649-3.324-6.649-6.649s3.325-6.65 6.649-6.65Zm-47.654 61.508c-3.879 0-6.65-3.325-6.65-6.65s3.325-6.649 6.65-6.649 6.649 3.324 6.649 6.649-3.324 6.65-6.649 6.65Zm-15.515-7.204c0 8.866 7.203 15.515 15.515 15.515 8.312 0 8.312-1.662 11.082-4.987 5.542-3.878 9.975-15.515 16.624-33.247a316.967 316.967 0 0 1 6.095-16.623c2.771 4.433 7.758 7.203 13.299 7.203 8.866 0 15.516-7.203 15.516-15.515 0-8.312-1.663-8.312-4.988-11.083-3.878-5.54-15.515-9.974-33.247-16.623a316.896 316.896 0 0 1-16.623-6.096c4.433-2.77 7.203-7.757 7.203-13.298 0-8.866-7.203-15.516-15.515-15.516-8.312 0-8.312 1.663-11.082 4.987-5.542 3.88-9.975 15.516-16.624 33.248a316.877 316.877 0 0 1-6.095 16.623c-2.771-4.433-7.758-7.203-13.3-7.203-8.865 0-15.515 7.203-15.515 15.515 0 8.312 1.663 8.312 4.987 11.082 3.88 5.541 15.516 9.974 33.248 16.624a317.044 317.044 0 0 1 16.623 6.095c-4.433 2.771-7.203 7.758-7.203 13.299Z" fill="#003C84"></path><path d="M77.158 119.271a316.112 316.112 0 0 1-16.623-6.095c1.108-.554 2.216-1.662 2.77-2.216 5.541-3.879 9.974-15.516 16.624-33.247a316.847 316.847 0 0 1 6.095-16.624c.554 1.108 1.662 2.216 2.217 2.77 3.878 5.542 15.515 9.975 33.247 16.624a316.887 316.887 0 0 1 16.623 6.095c-1.108.554-2.216 1.663-2.77 2.217-5.541 3.879-9.974 15.515-16.624 33.247a317.318 317.318 0 0 1-6.095 16.624c-.554-1.109-1.663-2.217-2.217-2.771-3.879-5.541-15.515-9.974-33.247-16.624Zm-24.935-12.744c-3.879 0-7.204-3.325-7.204-6.65 0-3.324 3.325-6.65 7.204-6.65 3.879 0 7.203 3.326 7.203 6.65 0 3.325-3.324 6.65-7.203 6.65Zm47.1-60.953c3.879 0 6.649 3.324 6.649 6.649s-3.324 6.65-6.65 6.65c-3.324 0-6.648-3.325-6.648-6.65s3.324-6.65 6.649-6.65Zm47.654 47.1c3.879 0 6.65 3.324 6.65 6.65 0 3.324-3.325 6.648-6.65 6.648s-6.649-3.324-6.649-6.649 3.324-6.65 6.649-6.65ZM99.323 154.18c-3.879 0-6.65-3.325-6.65-6.65 0-3.324 3.325-6.649 6.65-6.649s6.649 3.325 6.649 6.649c0 3.325-3.324 6.65-6.65 6.65Zm-15.515-7.204c0 8.866 7.203 15.516 15.515 15.516 8.312 0 8.312-1.663 11.082-4.987 5.542-3.879 9.974-15.516 16.624-33.248a316.967 316.967 0 0 1 6.095-16.623c2.771 4.433 7.758 7.203 13.299 7.203 8.866 0 15.515-7.203 15.515-15.515 0-8.312-1.662-8.312-4.987-11.082-3.878-5.541-15.515-9.974-33.247-16.624a316.801 316.801 0 0 1-16.623-6.095c4.433-2.77 7.203-7.758 7.203-13.299 0-8.866-7.203-15.515-15.515-15.515-8.312 0-8.312 1.662-11.083 4.987-5.54 3.879-9.974 15.515-16.623 33.247a317.027 317.027 0 0 1-6.095 16.624c-2.771-4.434-7.758-7.204-13.3-7.204-8.865 0-15.515 7.204-15.515 15.515 0 8.312 1.663 8.312 4.987 11.083 3.88 5.541 15.516 9.974 33.248 16.623a317.952 317.952 0 0 1 16.623 6.095c-4.433 2.771-7.203 7.758-7.203 13.299Z" fill="#fff"></path></svg></div></a><div class="relative"><a href="#main-menu" class="db h2 dn-l" title="Open menu"><span class="hamburger-icon"></span></a><a href="#" class="z-max reveal pt2 pr2 tc white absolute top-0 right-0 dn-l"><span class="x-icon"></span></a><ul class="z-999 reveal w5 list pl0 mv0 flex-l items-center-l absolute top-0 right-0 z-1 static-l w-100-l"><li class="ttu mh2 bb bn-l b--white"><a href="/training" class="white link db b ph1 pv3 pv2-l f5 underline-hover" title="Instructor-led Kubernetes training">Training</a></li><li class="ttu mh2 bb bn-l b--white"><a href="/blog" class="white link db b ph1 pv3 pv2-l f5 underline-hover" title="Blog">Blog</a></li><li class="ttu mh2 bb bn-l b--white"><a href="/for-marketers" class="white link db b ph1 pv3 pv2-l f5 underline-hover" title="Marketing to Kubernetes practitioners">For marketers</a></li><li class="ttu mh2"><a href="/contact-us" class="white link db b ph1 pv3 pv2-l f5 underline-hover" title="Contact LearnKube">Contact</a></li></ul></div></nav></div><div class="tc mb4 flex flex-wrap justify-center items-start mt4 mt5-ns"><div class="mh3 mb3"><div><a href="https://linkedin.com/in/danielepolencic" title="Daniele Polencic" class="link"><div class="center w3 mb1"><div class="aspect-ratio aspect-ratio--1x1"><img src="https://static.learnkube.com/authors/daniele_polencic-64x64.v1.jpg" srcset="https://static.learnkube.com/authors/daniele_polencic-64x64.v1.jpg 1x, https://static.learnkube.com/authors/daniele_polencic-128x128.v1.jpg 2x" alt="Daniele Polencic" class="br-100 w3 dib aspect-ratio--object"></div></div><span class="black-50 f6 db">Daniele Polencic</span></a></div></div></div><article class="lazy-article ph3 pt0 pb4 mw7 center"><h1 class="navy tc f2 f1-ns">Graceful shutdown in Kubernetes</h1><p class="f7 black-60 tc ttu b">April 2024</p><hr class="pv2 bn"><div class="aspect-ratio aspect-ratio--5x7"><a href="https://static.learnkube.com/b5dd0ff3b8c1a916f0ab2bec84598c5a.pdf"><img src="https://static.learnkube.com/1a6cec1114ea9a1981ec9cb916b2f507.png" class="aspect-ratio--object" alt="Graceful shutdown in Kubernetes"></a></div><hr class="w3 center b--navy mv4 mv5-ns"><p class="lh-copy measure-wide f4"><strong class="b">TL;DR:</strong> <em class="i">In this article, you will learn how to prevent broken connections when a Pod starts or shuts down. You will also learn how to shut down long-running tasks and connections gracefully.</em></p><p class="lh-copy measure-wide f4">In Kubernetes, creating and deleting Pods is one of the most common tasks.</p><p class="lh-copy measure-wide f4"><strong class="b">Pods are created when you execute a rolling update, scale deployments, for every new release, for every job and cron job, etc.</strong></p><p class="lh-copy measure-wide f4">However, pods are also deleted and recreated after evictions—when you mark a node as not schedulable, for example.</p><p class="lh-copy measure-wide f4"><em class="i">If the nature of those pods is so ephemeral, what happens when a pod is in the middle of responding to a request but is told to shut down?</em></p><p class="lh-copy measure-wide f4"><em class="i">Is the request completed before shutdown?</em></p><p class="lh-copy measure-wide f4"><em class="i">What about subsequent requests? Are those redirected somewhere else?</em></p><h2 class="f2 pt5 pb2 mt3" id="table-of-contents">Table of contents</h2><ul><li class="lh-copy f4 mv1 measure-wide"><a href="#what-happens-when-you-create-a-pod-in-kubernetes" target="_self" class="link navy underline hover-sky">What happens when you create a Pod in Kubernetes</a></li><li class="lh-copy f4 mv1 measure-wide"><a href="#the-kubelet-creates-and-look-after-the-pods" target="_self" class="link navy underline hover-sky">The kubelet creates and look after the pods</a></li><li class="lh-copy f4 mv1 measure-wide"><a href="#pods-services-and-endpoints" target="_self" class="link navy underline hover-sky">Pods, Services and Endpoints</a></li><li class="lh-copy f4 mv1 measure-wide"><a href="#endpoints-are-the-kubernetes-currency" target="_self" class="link navy underline hover-sky">Endpoints are the Kubernetes currency</a></li><li class="lh-copy f4 mv1 measure-wide"><a href="#what-happens-when-you-delete-a-pod" target="_self" class="link navy underline hover-sky">What happens when you delete a Pod</a></li><li class="lh-copy f4 mv1 measure-wide"><a href="#how-to-gracefully-shut-down-pods" target="_self" class="link navy underline hover-sky">How to gracefully shut down pods</a></li><li class="lh-copy f4 mv1 measure-wide"><a href="#graceful-shutdown-with-a-prestop-hook" target="_self" class="link navy underline hover-sky">Graceful shutdown with a preStop hook</a></li><li class="lh-copy f4 mv1 measure-wide"><a href="#long-graceful-shutdowns-and-cluster-autoscaling" target="_self" class="link navy underline hover-sky">Long graceful shutdowns and cluster autoscaling</a></li><li class="lh-copy f4 mv1 measure-wide"><a href="#graceful-shutdown-for-long-lived-connections-and-long-running-tasks" target="_self" class="link navy underline hover-sky">Graceful shutdown for long-lived connections and long-running tasks</a></li></ul><h2 class="f2 pt5 pb2 mt3" id="what-happens-when-you-create-a-pod-in-kubernetes">What happens when you create a Pod in Kubernetes</h2><p class="lh-copy measure-wide f4">Before discussing what happens when a Pod is deleted, it's necessary to discuss what happens when a Pod is created.</p><p class="lh-copy measure-wide f4">Let's assume you want to create the following Pod in your cluster:</p><div class="mv4 mv5-l"><header class="bg-light-gray flex pv2 pl1 br--top br2 relative"><div class="w1 h1 ml1 br-100 bg-dark-red"></div><div class="w1 h1 ml1 br-100 bg-green"></div><div class="w1 h1 ml1 br-100 bg-yellow"></div><p class="code f6 mv0 black-60 w-100 tc absolute top-0 left-0 h1 pv2">pod.yaml</p></header><pre class="code-light-theme relative overflow-auto mv0 br2 br--bottom"><code class="code lh-copy"><span class="standard"><span class="token key atrule">apiVersion</span><span class="token punctuation">:</span> v1
|
|
<span class="token key atrule">kind</span><span class="token punctuation">:</span> Pod
|
|
<span class="token key atrule">metadata</span><span class="token punctuation">:</span>
|
|
<span class="token key atrule">name</span><span class="token punctuation">:</span> my<span class="token punctuation">-</span>pod
|
|
<span class="token key atrule">spec</span><span class="token punctuation">:</span>
|
|
<span class="token key atrule">containers</span><span class="token punctuation">:</span>
|
|
<span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> web
|
|
<span class="token key atrule">image</span><span class="token punctuation">:</span> nginx
|
|
<span class="token key atrule">ports</span><span class="token punctuation">:</span>
|
|
<span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> web
|
|
<span class="token key atrule">containerPort</span><span class="token punctuation">:</span> <span class="token number">80</span></span></code></pre></div><p class="lh-copy measure-wide f4">You can submit the YAML definition to the cluster with the following command:</p><div class="mv4 mv5-l"><header class="bg-light-gray flex pv2 pl1 br--top br2 relative"><div class="w1 h1 ml1 br-100 bg-dark-red"></div><div class="w1 h1 ml1 br-100 bg-green"></div><div class="w1 h1 ml1 br-100 bg-yellow"></div><p class="code f6 mv0 black-60 w-100 tc absolute top-0 left-0 h1 pv2">bash</p></header><pre class="code-dark-theme relative overflow-auto mv0 br2 br--bottom"><code class="code lh-copy"><span class="command prompt">kubectl apply <span class="token parameter variable">-f</span> pod.yaml</span></code></pre></div><p class="lh-copy measure-wide f4">When you enter the command, kubectl submits the Pod definition to the Kubernetes API.</p><p class="lh-copy measure-wide f4"><em class="i">This is where the journey begins.</em></p><p class="lh-copy measure-wide f4">The API receives and inspects the Pod definition and subsequently <a href="https://learnkube.com/etcd-kubernetes" target="_blank" rel="noreferrer" class="link navy underline hover-sky">stored in the database — etcd.</a></p><p class="lh-copy measure-wide f4">Between receiving the request and storing it, <a href="https://learnkube.com/kubernetes-api-explained" target="_blank" rel="noreferrer" class="link navy underline hover-sky">the API server runs several checks</a> including authentication, authorization, and admission controllers.</p><p class="lh-copy measure-wide f4">The Pod is also added to <a href="https://kubernetes.io/docs/concepts/scheduling-eviction/scheduling-framework/#scheduling-cycle-binding-cycle" target="_blank" rel="noreferrer" class="link navy underline hover-sky">the Scheduler's queue.</a></p><p class="lh-copy measure-wide f4">The Scheduler:</p><ol><li class="lh-copy f4 mv1 measure-wide">Inspects the definition.</li><li class="lh-copy f4 mv1 measure-wide">Collects details about the workload, such as CPU and memory requests, and then</li><li class="lh-copy f4 mv1 measure-wide">Decides which Node is best suited to run it <a href="https://kubernetes.io/docs/concepts/scheduling-eviction/scheduling-framework/" target="_blank" rel="noreferrer" class="link navy underline hover-sky">(through a process called Filters and Predicates).</a></li></ol><p class="lh-copy measure-wide f4">At the end of the process:</p><ul><li class="lh-copy f4 mv1 measure-wide">The Pod is marked as <em class="i">Scheduled</em> in etcd.</li><li class="lh-copy f4 mv1 measure-wide">The Pod has a Node assigned to it.</li><li class="lh-copy f4 mv1 measure-wide">The state of the Pod is stored in etcd.</li></ul><p class="lh-copy measure-wide f4"><strong class="b">But the Pod still does not exist.</strong></p><div class="relative overflow-hidden"><ul class="pl0 list"><li class="mv3"><input type="radio" name="carousel-1" id="carousel-1-0" checked class="o-0 absolute bottom-0 left-0"><div class="dn checked-reveal"><div class="aspect-ratio aspect-ratio--4x3"><img src="https://static.learnkube.com/54a28f4c41dfd3abb594848af5f71eaf.svg" alt="When you submit a Pod with `kubectl apply -f`, the YAML is sent to the Kubernetes API.When you submit a Pod with kubectl apply -f, the YAML is sent to the Kubernetes API." class="aspect-ratio--object" loading="lazy"></div><div class="bt b-solid bw2 b--black-70 relative mt0"><div class="bg-black-10 br1 pa1 dib mt2 absolute bottom-1 left-0 z-999"><span class="b black-60">1</span><span class="f7 black-50">/3</span></div></div><div class="flex items-start justify-between bg-evian ph2"><div class="w-20"></div><div class="f5 lh-copy black-90 w-60 center"><p class="lh-copy measure-wide f5"></p><p class="lh-copy measure-wide f4">When you submit a Pod with <code class="code f5 lh-copy bg-near-white br2 pv1 ph2 fs-normal word-wrap">kubectl apply -f</code>, the YAML is sent to the Kubernetes API.</p><p></p></div><label class="db f6 b black-50 pv3 pointer w-20 tr ttu" for="carousel-1-1">Next <svg viewBox="0 0 10 16" xmlns="http://www.w3.org/2000/svg" class="pagination-icon ml2"><polyline fill="none" vector-effect="non-scaling-stroke" points="2,2 8,8 2,14"></polyline></svg></label></div></div></li><li class="mv3"><input type="radio" name="carousel-1" id="carousel-1-1" class="o-0 absolute bottom-0 left-0"><div class="dn checked-reveal"><div class="aspect-ratio aspect-ratio--4x3"><img src="https://static.learnkube.com/9b8aa9fec3c7effa5d064059b8a08bcc.svg" alt="The API saves the Pod in the database — etcd.The API saves the Pod in the database — etcd." class="aspect-ratio--object" loading="lazy"></div><div class="bt b-solid bw2 b--black-70 relative mt0"><div class="bg-black-10 br1 pa1 dib mt2 absolute bottom-1 left-0 z-999"><span class="b black-60">2</span><span class="f7 black-50">/3</span></div></div><div class="flex items-start justify-between bg-evian ph2"><label class="db f6 b black-50 pv3 pointer w-20 ttu" for="carousel-1-0"><svg viewBox="0 0 10 16" xmlns="http://www.w3.org/2000/svg" class="pagination-icon mr2"><polyline fill="none" vector-effect="non-scaling-stroke" points="8,2 2,8 8,14"></polyline></svg> Previous</label><div class="f5 lh-copy black-90 w-60 center"><p class="lh-copy measure-wide f5"></p><p class="lh-copy measure-wide f4">The API saves the Pod in the database — etcd.</p><p></p></div><label class="db f6 b black-50 pv3 pointer w-20 tr ttu" for="carousel-1-2">Next <svg viewBox="0 0 10 16" xmlns="http://www.w3.org/2000/svg" class="pagination-icon ml2"><polyline fill="none" vector-effect="non-scaling-stroke" points="2,2 8,8 2,14"></polyline></svg></label></div></div></li><li class="mv3"><input type="radio" name="carousel-1" id="carousel-1-2" class="o-0 absolute bottom-0 left-0"><div class="dn checked-reveal"><div class="aspect-ratio aspect-ratio--4x3"><img src="https://static.learnkube.com/2d4ee1aca891b85a40b9271cd89ff593.svg" alt="The scheduler assigns the best node for that Pod, and the Pod's status changes to _Pending_. The Pod exists only in etcd.The scheduler assigns the best node for that Pod, and the Pod's status changes to Pending. The Pod exists only in etcd." class="aspect-ratio--object" loading="lazy"></div><div class="bt b-solid bw2 b--black-70 relative mt0"><div class="bg-black-10 br1 pa1 dib mt2 absolute bottom-1 left-0 z-999"><span class="b black-60">3</span><span class="f7 black-50">/3</span></div></div><div class="flex items-start justify-between bg-evian ph2"><label class="db f6 b black-50 pv3 pointer w-20 ttu" for="carousel-1-1"><svg viewBox="0 0 10 16" xmlns="http://www.w3.org/2000/svg" class="pagination-icon mr2"><polyline fill="none" vector-effect="non-scaling-stroke" points="8,2 2,8 8,14"></polyline></svg> Previous</label><div class="f5 lh-copy black-90 w-60 center"><p class="lh-copy measure-wide f5"></p><p class="lh-copy measure-wide f4">The scheduler assigns the best node for that Pod, and the Pod's status changes to <em class="i">Pending</em>. The Pod exists only in etcd.</p><p></p></div><div class="w-20"></div></div></div></li></ul></div><p class="lh-copy measure-wide f4">The previous tasks happened in the control plane, and the state is stored in the database.</p><p class="lh-copy measure-wide f4"><em class="i">So who is creating the Pod in your Nodes?</em></p><h2 class="f2 pt5 pb2 mt3" id="the-kubelet-creates-and-look-after-the-pods">The kubelet creates and look after the pods</h2><p class="lh-copy measure-wide f4"><strong class="b">The kubelet's job is to poll the control plane for updates.</strong></p><p class="lh-copy measure-wide f4">You can imagine the kubelet relentlessly asking the control plane: <em class="i">"I look after the worker Node 1; is there any new Pod for me?".</em></p><p class="lh-copy measure-wide f4">When there is a Pod, the kubelet creates it.</p><p class="lh-copy measure-wide f4"><em class="i">Sort of.</em></p><p class="lh-copy measure-wide f4">The kubelet doesn't create the Pod by itself. Instead, it delegates the work to three other components:</p><ol><li class="lh-copy f4 mv1 measure-wide"><strong class="b">The Container Runtime Interface (CRI)</strong> creates the containers for the Pod.</li><li class="lh-copy f4 mv1 measure-wide"><strong class="b">The Container Network Interface (CNI)</strong> connects the containers to the cluster network and assigns IP addresses.</li><li class="lh-copy f4 mv1 measure-wide"><strong class="b">The Container Storage Interface (CSI)</strong> mounts volumes in your containers.</li></ol><p class="lh-copy measure-wide f4">In most cases, the Container Runtime Interface (CRI) is doing a similar job to:</p><div class="mv4 mv5-l"><header class="bg-light-gray flex pv2 pl1 br--top br2 relative"><div class="w1 h1 ml1 br-100 bg-dark-red"></div><div class="w1 h1 ml1 br-100 bg-green"></div><div class="w1 h1 ml1 br-100 bg-yellow"></div><p class="code f6 mv0 black-60 w-100 tc absolute top-0 left-0 h1 pv2">bash</p></header><pre class="code-dark-theme relative overflow-auto mv0 br2 br--bottom"><code class="code lh-copy"><span class="command prompt"><span class="token function">docker</span> run <span class="token parameter variable">-d</span> <span class="token operator"><</span>my-container-image<span class="token operator">></span></span></code></pre></div><p class="lh-copy measure-wide f4">The Container Networking Interface (CNI) is a bit more interesting because it is in charge of:</p><ol><li class="lh-copy f4 mv1 measure-wide">Generating a valid IP address for the Pod.</li><li class="lh-copy f4 mv1 measure-wide">Connecting the container to the rest of the network.</li></ol><p class="lh-copy measure-wide f4">As you can imagine, several ways exist to connect the container to the network and assign a valid IP address (you could choose between IPv4 or IPv6 or multiple IP addresses).</p><blockquote class="pl3 mh2 bl bw2 b--blue bg-evian pv1 ph4"><p class="lh-copy measure-wide f4">If you are interested in learning more about Linux network namespaces and CNIs, you should check out this article on <a href="https://learnkube.com/kubernetes-network-packets" target="_blank" rel="noreferrer" class="link navy underline hover-sky">tracing the path of network traffic in Kubernetes</a></p></blockquote><p class="lh-copy measure-wide f4">When the Container Network Interface finishes its job, the Pod is connected to the rest of the network and has a valid IP address assigned.</p><p class="lh-copy measure-wide f4"><em class="i">There's only one issue.</em></p><p class="lh-copy measure-wide f4"><strong class="b">The kubelet knows about the IP address (because it invoked the Container Network Interface), but the control plane does not.</strong></p><p class="lh-copy measure-wide f4">No one told the control plane that the Pod has an IP address assigned and it's ready to receive traffic.</p><p class="lh-copy measure-wide f4">As far as the control plane is concerned, the Pod is still being created.</p><p class="lh-copy measure-wide f4">It's the job of <strong class="b">the kubelet to collect all the details of the Pod, such as the IP address, and report them back to the control plane.</strong></p><p class="lh-copy measure-wide f4">Inspecting etcd would reveal where the Pod is running and its IP address.</p><div class="relative overflow-hidden"><ul class="pl0 list"><li class="mv3"><input type="radio" name="carousel-2" id="carousel-2-0" checked class="o-0 absolute bottom-0 left-0"><div class="dn checked-reveal"><div class="aspect-ratio aspect-ratio--4x3"><img src="https://static.learnkube.com/b8bdb7bf659fbea3d2949930093d56b1.svg" alt="The Kubelet polls the control plane for updates.The Kubelet polls the control plane for updates." class="aspect-ratio--object" loading="lazy"></div><div class="bt b-solid bw2 b--black-70 relative mt0"><div class="bg-black-10 br1 pa1 dib mt2 absolute bottom-1 left-0 z-999"><span class="b black-60">1</span><span class="f7 black-50">/5</span></div></div><div class="flex items-start justify-between bg-evian ph2"><div class="w-20"></div><div class="f5 lh-copy black-90 w-60 center"><p class="lh-copy measure-wide f5"></p><p class="lh-copy measure-wide f4">The Kubelet polls the control plane for updates.</p><p></p></div><label class="db f6 b black-50 pv3 pointer w-20 tr ttu" for="carousel-2-1">Next <svg viewBox="0 0 10 16" xmlns="http://www.w3.org/2000/svg" class="pagination-icon ml2"><polyline fill="none" vector-effect="non-scaling-stroke" points="2,2 8,8 2,14"></polyline></svg></label></div></div></li><li class="mv3"><input type="radio" name="carousel-2" id="carousel-2-1" class="o-0 absolute bottom-0 left-0"><div class="dn checked-reveal"><div class="aspect-ratio aspect-ratio--4x3"><img src="https://static.learnkube.com/be24d1001c443cdcc69c9a8757a34363.svg" alt="When a new Pod is assigned to its Node, the kubelet retrieves the details.When a new Pod is assigned to its Node, the kubelet retrieves the details." class="aspect-ratio--object" loading="lazy"></div><div class="bt b-solid bw2 b--black-70 relative mt0"><div class="bg-black-10 br1 pa1 dib mt2 absolute bottom-1 left-0 z-999"><span class="b black-60">2</span><span class="f7 black-50">/5</span></div></div><div class="flex items-start justify-between bg-evian ph2"><label class="db f6 b black-50 pv3 pointer w-20 ttu" for="carousel-2-0"><svg viewBox="0 0 10 16" xmlns="http://www.w3.org/2000/svg" class="pagination-icon mr2"><polyline fill="none" vector-effect="non-scaling-stroke" points="8,2 2,8 8,14"></polyline></svg> Previous</label><div class="f5 lh-copy black-90 w-60 center"><p class="lh-copy measure-wide f5"></p><p class="lh-copy measure-wide f4">When a new Pod is assigned to its Node, the kubelet retrieves the details.</p><p></p></div><label class="db f6 b black-50 pv3 pointer w-20 tr ttu" for="carousel-2-2">Next <svg viewBox="0 0 10 16" xmlns="http://www.w3.org/2000/svg" class="pagination-icon ml2"><polyline fill="none" vector-effect="non-scaling-stroke" points="2,2 8,8 2,14"></polyline></svg></label></div></div></li><li class="mv3"><input type="radio" name="carousel-2" id="carousel-2-2" class="o-0 absolute bottom-0 left-0"><div class="dn checked-reveal"><div class="aspect-ratio aspect-ratio--4x3"><img src="https://static.learnkube.com/5578ce556c01bcd74639f9b0afc46a95.svg" alt="The kubelet doesn't create the Pod itself. It relies on the **Container Runtime Interface**, **Container Network Interface**, and **Container Storage Interface**.The kubelet doesn't create the Pod itself. It relies on the Container Runtime Interface, Container Network Interface, and Container Storage Interface." class="aspect-ratio--object" loading="lazy"></div><div class="bt b-solid bw2 b--black-70 relative mt0"><div class="bg-black-10 br1 pa1 dib mt2 absolute bottom-1 left-0 z-999"><span class="b black-60">3</span><span class="f7 black-50">/5</span></div></div><div class="flex items-start justify-between bg-evian ph2"><label class="db f6 b black-50 pv3 pointer w-20 ttu" for="carousel-2-1"><svg viewBox="0 0 10 16" xmlns="http://www.w3.org/2000/svg" class="pagination-icon mr2"><polyline fill="none" vector-effect="non-scaling-stroke" points="8,2 2,8 8,14"></polyline></svg> Previous</label><div class="f5 lh-copy black-90 w-60 center"><p class="lh-copy measure-wide f5"></p><p class="lh-copy measure-wide f4">The kubelet doesn't create the Pod itself. It relies on the <strong class="b">Container Runtime Interface</strong>, <strong class="b">Container Network Interface</strong>, and <strong class="b">Container Storage Interface</strong>.</p><p></p></div><label class="db f6 b black-50 pv3 pointer w-20 tr ttu" for="carousel-2-3">Next <svg viewBox="0 0 10 16" xmlns="http://www.w3.org/2000/svg" class="pagination-icon ml2"><polyline fill="none" vector-effect="non-scaling-stroke" points="2,2 8,8 2,14"></polyline></svg></label></div></div></li><li class="mv3"><input type="radio" name="carousel-2" id="carousel-2-3" class="o-0 absolute bottom-0 left-0"><div class="dn checked-reveal"><div class="aspect-ratio aspect-ratio--4x3"><img src="https://static.learnkube.com/ea1cc4e3d6cc7d9693cc8478c146c64f.svg" alt="Once all three components have been completed, the Pod is _Running_ in your Node and has an IP address assigned.Once all three components have been completed, the Pod is Running in your Node and has an IP address assigned." class="aspect-ratio--object" loading="lazy"></div><div class="bt b-solid bw2 b--black-70 relative mt0"><div class="bg-black-10 br1 pa1 dib mt2 absolute bottom-1 left-0 z-999"><span class="b black-60">4</span><span class="f7 black-50">/5</span></div></div><div class="flex items-start justify-between bg-evian ph2"><label class="db f6 b black-50 pv3 pointer w-20 ttu" for="carousel-2-2"><svg viewBox="0 0 10 16" xmlns="http://www.w3.org/2000/svg" class="pagination-icon mr2"><polyline fill="none" vector-effect="non-scaling-stroke" points="8,2 2,8 8,14"></polyline></svg> Previous</label><div class="f5 lh-copy black-90 w-60 center"><p class="lh-copy measure-wide f5"></p><p class="lh-copy measure-wide f4">Once all three components have been completed, the Pod is <em class="i">Running</em> in your Node and has an IP address assigned.</p><p></p></div><label class="db f6 b black-50 pv3 pointer w-20 tr ttu" for="carousel-2-4">Next <svg viewBox="0 0 10 16" xmlns="http://www.w3.org/2000/svg" class="pagination-icon ml2"><polyline fill="none" vector-effect="non-scaling-stroke" points="2,2 8,8 2,14"></polyline></svg></label></div></div></li><li class="mv3"><input type="radio" name="carousel-2" id="carousel-2-4" class="o-0 absolute bottom-0 left-0"><div class="dn checked-reveal"><div class="aspect-ratio aspect-ratio--4x3"><img src="https://static.learnkube.com/d88792b710edf94699444f56c5d18902.svg" alt="The kubelet reports the IP address back to the control plane.The kubelet reports the IP address back to the control plane." class="aspect-ratio--object" loading="lazy"></div><div class="bt b-solid bw2 b--black-70 relative mt0"><div class="bg-black-10 br1 pa1 dib mt2 absolute bottom-1 left-0 z-999"><span class="b black-60">5</span><span class="f7 black-50">/5</span></div></div><div class="flex items-start justify-between bg-evian ph2"><label class="db f6 b black-50 pv3 pointer w-20 ttu" for="carousel-2-3"><svg viewBox="0 0 10 16" xmlns="http://www.w3.org/2000/svg" class="pagination-icon mr2"><polyline fill="none" vector-effect="non-scaling-stroke" points="8,2 2,8 8,14"></polyline></svg> Previous</label><div class="f5 lh-copy black-90 w-60 center"><p class="lh-copy measure-wide f5"></p><p class="lh-copy measure-wide f4">The kubelet reports the IP address back to the control plane.</p><p></p></div><div class="w-20"></div></div></div></li></ul></div><p class="lh-copy measure-wide f4">If the Pod isn't part of any Service, this is the journey's end.</p><p class="lh-copy measure-wide f4">The Pod has been created and is ready to use.</p><p class="lh-copy measure-wide f4"><em class="i">When the Pod is part of the Service, a few more steps are needed.</em></p><h2 class="f2 pt5 pb2 mt3" id="pods-services-and-endpoints">Pods, Services and Endpoints</h2><p class="lh-copy measure-wide f4">When you create a Service, there are usually two pieces of information that you should pay attention to:</p><ol><li class="lh-copy f4 mv1 measure-wide">The selector, which is used to specify the Pods that will receive the traffic.</li><li class="lh-copy f4 mv1 measure-wide">The <code class="code f5 lh-copy bg-near-white br2 pv1 ph2 fs-normal word-wrap">targetPort</code> — the port the Pods use to receive traffic.</li></ol><p class="lh-copy measure-wide f4">A typical YAML definition for the Service looks like this:</p><div class="mv4 mv5-l"><header class="bg-light-gray flex pv2 pl1 br--top br2 relative"><div class="w1 h1 ml1 br-100 bg-dark-red"></div><div class="w1 h1 ml1 br-100 bg-green"></div><div class="w1 h1 ml1 br-100 bg-yellow"></div><p class="code f6 mv0 black-60 w-100 tc absolute top-0 left-0 h1 pv2">service.yaml</p></header><pre class="code-light-theme relative overflow-auto mv0 br2 br--bottom"><code class="code lh-copy"><span class="standard"><span class="token key atrule">apiVersion</span><span class="token punctuation">:</span> v1
|
|
<span class="token key atrule">kind</span><span class="token punctuation">:</span> Service
|
|
<span class="token key atrule">metadata</span><span class="token punctuation">:</span>
|
|
<span class="token key atrule">name</span><span class="token punctuation">:</span> my<span class="token punctuation">-</span>service
|
|
<span class="token key atrule">spec</span><span class="token punctuation">:</span>
|
|
<span class="token key atrule">ports</span><span class="token punctuation">:</span>
|
|
<span class="token punctuation">-</span> <span class="token key atrule">port</span><span class="token punctuation">:</span> <span class="token number">80</span>
|
|
</span><span class="highlight"> <span class="token key atrule">targetPort</span><span class="token punctuation">:</span> <span class="token number">3000</span>
|
|
</span><span class="standard"> <span class="token key atrule">selector</span><span class="token punctuation">:</span>
|
|
</span><span class="highlight"> <span class="token key atrule">name</span><span class="token punctuation">:</span> app</span></code></pre></div><p class="lh-copy measure-wide f4">When you submit the Service to the cluster with <code class="code f5 lh-copy bg-near-white br2 pv1 ph2 fs-normal word-wrap">kubectl apply</code>, Kubernetes finds all the Pods that have the same label as the selector (<code class="code f5 lh-copy bg-near-white br2 pv1 ph2 fs-normal word-wrap">name: app</code>) and collects their IP addresses — but only if they passed the <a href="https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/#define-a-tcp-liveness-probe" target="_blank" rel="noreferrer" class="link navy underline hover-sky">Readiness probe</a>.</p><p class="lh-copy measure-wide f4">Then, for each IP address, it concatenates the IP address and the port.</p><p class="lh-copy measure-wide f4">If the IP address is <code class="code f5 lh-copy bg-near-white br2 pv1 ph2 fs-normal word-wrap">10.0.0.3</code> and the <code class="code f5 lh-copy bg-near-white br2 pv1 ph2 fs-normal word-wrap">targetPort</code> is <code class="code f5 lh-copy bg-near-white br2 pv1 ph2 fs-normal word-wrap">3000</code>, Kubernetes concatenates the two values and calls them an endpoint.</p><div class="mv4 mv5-l"><header class="bg-light-gray flex pv2 pl1 br--top br2 relative"><div class="w1 h1 ml1 br-100 bg-dark-red"></div><div class="w1 h1 ml1 br-100 bg-green"></div><div class="w1 h1 ml1 br-100 bg-yellow"></div></header><pre class="code-light-theme relative overflow-auto mv0 br2 br--bottom"><code class="code lh-copy"><span class="standard">IP address + port = endpoint
|
|
---------------------------------
|
|
10.0.0.3 + 3000 = 10.0.0.3:3000</span></code></pre></div><p class="lh-copy measure-wide f4">The endpoints are stored in etcd in another object called Endpoint.</p><p class="lh-copy measure-wide f4"><em class="i">Confused?</em></p><p class="lh-copy measure-wide f4">Kubernetes refers to:</p><ul><li class="lh-copy f4 mv1 measure-wide"><strong class="b">endpoint</strong> (in this article and the Learnk8s material, referred to as a lowercase <code class="code f5 lh-copy bg-near-white br2 pv1 ph2 fs-normal word-wrap">e</code> endpoint) is the IP address + port pair (<code class="code f5 lh-copy bg-near-white br2 pv1 ph2 fs-normal word-wrap">10.0.0.3:3000</code>).</li><li class="lh-copy f4 mv1 measure-wide"><strong class="b">Endpoint</strong> (in this article and the Learnk8s material this is referred to as an uppercase <code class="code f5 lh-copy bg-near-white br2 pv1 ph2 fs-normal word-wrap">E</code> Endpoint) is a collection of endpoints.</li></ul><p class="lh-copy measure-wide f4">The Endpoint object is a real object in Kubernetes, and for every Service, Kubernetes automatically creates an Endpoint object.</p><p class="lh-copy measure-wide f4">You can verify that with:</p><div class="mv4 mv5-l"><header class="bg-light-gray flex pv2 pl1 br--top br2 relative"><div class="w1 h1 ml1 br-100 bg-dark-red"></div><div class="w1 h1 ml1 br-100 bg-green"></div><div class="w1 h1 ml1 br-100 bg-yellow"></div><p class="code f6 mv0 black-60 w-100 tc absolute top-0 left-0 h1 pv2">bash</p></header><pre class="code-dark-theme relative overflow-auto mv0 br2 br--bottom"><code class="code lh-copy"><span class="command prompt">kubectl get services,endpoints
|
|
</span><span class="output">NAME TYPE CLUSTER-IP EXTERNAL-IP PORT<span class="token punctuation">(</span>S<span class="token punctuation">)</span>
|
|
service/my-service-1 ClusterIP <span class="token number">10.105</span>.17.65 <span class="token operator"><</span>none<span class="token operator">></span> <span class="token number">80</span>/TCP
|
|
service/my-service-2 ClusterIP <span class="token number">10.96</span>.0.1 <span class="token operator"><</span>none<span class="token operator">></span> <span class="token number">443</span>/TCP
|
|
|
|
NAME ENDPOINTS
|
|
endpoints/my-service-1 <span class="token number">172.17</span>.0.6:80,172.17.0.7:80
|
|
endpoints/my-service-2 <span class="token number">192.168</span>.99.100:8443</span><span class="output prompt mt3 empty"></span></code></pre></div><p class="lh-copy measure-wide f4">The Endpoint collects all the IP addresses and ports from the Pods.</p><p class="lh-copy measure-wide f4"><em class="i">But not just one time.</em></p><p class="lh-copy measure-wide f4">The Endpoint object is refreshed with a new list of endpoints when:</p><ol><li class="lh-copy f4 mv1 measure-wide">A Pod is created.</li><li class="lh-copy f4 mv1 measure-wide">A Pod is deleted.</li><li class="lh-copy f4 mv1 measure-wide">A label is modified on the Pod.</li></ol><p class="lh-copy measure-wide f4">So you can imagine that every time you create a Pod and after the kubelet posts its IP address to the control plane, Kubernetes updates all the endpoints to reflect the change:</p><div class="mv4 mv5-l"><header class="bg-light-gray flex pv2 pl1 br--top br2 relative"><div class="w1 h1 ml1 br-100 bg-dark-red"></div><div class="w1 h1 ml1 br-100 bg-green"></div><div class="w1 h1 ml1 br-100 bg-yellow"></div><p class="code f6 mv0 black-60 w-100 tc absolute top-0 left-0 h1 pv2">bash</p></header><pre class="code-dark-theme relative overflow-auto mv0 br2 br--bottom"><code class="code lh-copy"><span class="command prompt">kubectl get services,endpoints
|
|
</span><span class="output">NAME TYPE CLUSTER-IP EXTERNAL-IP PORT<span class="token punctuation">(</span>S<span class="token punctuation">)</span>
|
|
service/my-service-1 ClusterIP <span class="token number">10.105</span>.17.65 <span class="token operator"><</span>none<span class="token operator">></span> <span class="token number">80</span>/TCP
|
|
service/my-service-2 ClusterIP <span class="token number">10.96</span>.0.1 <span class="token operator"><</span>none<span class="token operator">></span> <span class="token number">443</span>/TCP
|
|
|
|
NAME ENDPOINTS
|
|
endpoints/my-service-1 <span class="token number">172.17</span>.0.6:80,172.17.0.7:80,172.17.0.8:80
|
|
endpoints/my-service-2 <span class="token number">192.168</span>.99.100:8443</span><span class="output prompt mt3 empty"></span></code></pre></div><p class="lh-copy measure-wide f4">The endpoint is stored in the control plane, and the Endpoint object was updated.</p><div class="relative overflow-hidden"><ul class="pl0 list"><li class="mv3"><input type="radio" name="carousel-3" id="carousel-3-0" checked class="o-0 absolute bottom-0 left-0"><div class="dn checked-reveal"><div class="aspect-ratio aspect-ratio--4x3"><img src="https://static.learnkube.com/5ec899bd0f7067f1e01bb1accacb35ac.svg" alt="In this picture, a single Pod is deployed in your cluster. The Pod belongs to a Service. If you were to inspect etcd, you would find the Pod's details and Service.In this picture, a single Pod is deployed in your cluster. The Pod belongs to a Service. If you were to inspect etcd, you would find the Pod's details and Service." class="aspect-ratio--object" loading="lazy"></div><div class="bt b-solid bw2 b--black-70 relative mt0"><div class="bg-black-10 br1 pa1 dib mt2 absolute bottom-1 left-0 z-999"><span class="b black-60">1</span><span class="f7 black-50">/8</span></div></div><div class="flex items-start justify-between bg-evian ph2"><div class="w-20"></div><div class="f5 lh-copy black-90 w-60 center"><p class="lh-copy measure-wide f5"></p><p class="lh-copy measure-wide f4">In this picture, a single Pod is deployed in your cluster. The Pod belongs to a Service. If you were to inspect etcd, you would find the Pod's details and Service.</p><p></p></div><label class="db f6 b black-50 pv3 pointer w-20 tr ttu" for="carousel-3-1">Next <svg viewBox="0 0 10 16" xmlns="http://www.w3.org/2000/svg" class="pagination-icon ml2"><polyline fill="none" vector-effect="non-scaling-stroke" points="2,2 8,8 2,14"></polyline></svg></label></div></div></li><li class="mv3"><input type="radio" name="carousel-3" id="carousel-3-1" class="o-0 absolute bottom-0 left-0"><div class="dn checked-reveal"><div class="aspect-ratio aspect-ratio--4x3"><img src="https://static.learnkube.com/0132fa2addf4c384d9a9b1eaf2762780.svg" alt="_What happens when a new Pod is deployed?_What happens when a new Pod is deployed?" class="aspect-ratio--object" loading="lazy"></div><div class="bt b-solid bw2 b--black-70 relative mt0"><div class="bg-black-10 br1 pa1 dib mt2 absolute bottom-1 left-0 z-999"><span class="b black-60">2</span><span class="f7 black-50">/8</span></div></div><div class="flex items-start justify-between bg-evian ph2"><label class="db f6 b black-50 pv3 pointer w-20 ttu" for="carousel-3-0"><svg viewBox="0 0 10 16" xmlns="http://www.w3.org/2000/svg" class="pagination-icon mr2"><polyline fill="none" vector-effect="non-scaling-stroke" points="8,2 2,8 8,14"></polyline></svg> Previous</label><div class="f5 lh-copy black-90 w-60 center"><p class="lh-copy measure-wide f5"></p><p class="lh-copy measure-wide f4"><em class="i">What happens when a new Pod is deployed?</em></p><p></p></div><label class="db f6 b black-50 pv3 pointer w-20 tr ttu" for="carousel-3-2">Next <svg viewBox="0 0 10 16" xmlns="http://www.w3.org/2000/svg" class="pagination-icon ml2"><polyline fill="none" vector-effect="non-scaling-stroke" points="2,2 8,8 2,14"></polyline></svg></label></div></div></li><li class="mv3"><input type="radio" name="carousel-3" id="carousel-3-2" class="o-0 absolute bottom-0 left-0"><div class="dn checked-reveal"><div class="aspect-ratio aspect-ratio--4x3"><img src="https://static.learnkube.com/91cbaeb550295a6bae985644697919fa.svg" alt="Kubernetes has to keep track of the Pod and its IP address. The Service should route traffic to the new endpoint, so the IP address and port should be propagated.Kubernetes has to keep track of the Pod and its IP address. The Service should route traffic to the new endpoint, so the IP address and port should be propagated." class="aspect-ratio--object" loading="lazy"></div><div class="bt b-solid bw2 b--black-70 relative mt0"><div class="bg-black-10 br1 pa1 dib mt2 absolute bottom-1 left-0 z-999"><span class="b black-60">3</span><span class="f7 black-50">/8</span></div></div><div class="flex items-start justify-between bg-evian ph2"><label class="db f6 b black-50 pv3 pointer w-20 ttu" for="carousel-3-1"><svg viewBox="0 0 10 16" xmlns="http://www.w3.org/2000/svg" class="pagination-icon mr2"><polyline fill="none" vector-effect="non-scaling-stroke" points="8,2 2,8 8,14"></polyline></svg> Previous</label><div class="f5 lh-copy black-90 w-60 center"><p class="lh-copy measure-wide f5"></p><p class="lh-copy measure-wide f4">Kubernetes has to keep track of the Pod and its IP address. The Service should route traffic to the new endpoint, so the IP address and port should be propagated.</p><p></p></div><label class="db f6 b black-50 pv3 pointer w-20 tr ttu" for="carousel-3-3">Next <svg viewBox="0 0 10 16" xmlns="http://www.w3.org/2000/svg" class="pagination-icon ml2"><polyline fill="none" vector-effect="non-scaling-stroke" points="2,2 8,8 2,14"></polyline></svg></label></div></div></li><li class="mv3"><input type="radio" name="carousel-3" id="carousel-3-3" class="o-0 absolute bottom-0 left-0"><div class="dn checked-reveal"><div class="aspect-ratio aspect-ratio--4x3"><img src="https://static.learnkube.com/70b461b6aef5225e57cbc5d91c0d94d2.svg" alt="What happens when _another_ Pod is deployed?What happens when another Pod is deployed?" class="aspect-ratio--object" loading="lazy"></div><div class="bt b-solid bw2 b--black-70 relative mt0"><div class="bg-black-10 br1 pa1 dib mt2 absolute bottom-1 left-0 z-999"><span class="b black-60">4</span><span class="f7 black-50">/8</span></div></div><div class="flex items-start justify-between bg-evian ph2"><label class="db f6 b black-50 pv3 pointer w-20 ttu" for="carousel-3-2"><svg viewBox="0 0 10 16" xmlns="http://www.w3.org/2000/svg" class="pagination-icon mr2"><polyline fill="none" vector-effect="non-scaling-stroke" points="8,2 2,8 8,14"></polyline></svg> Previous</label><div class="f5 lh-copy black-90 w-60 center"><p class="lh-copy measure-wide f5"></p><p class="lh-copy measure-wide f4">What happens when <em class="i">another</em> Pod is deployed?</p><p></p></div><label class="db f6 b black-50 pv3 pointer w-20 tr ttu" for="carousel-3-4">Next <svg viewBox="0 0 10 16" xmlns="http://www.w3.org/2000/svg" class="pagination-icon ml2"><polyline fill="none" vector-effect="non-scaling-stroke" points="2,2 8,8 2,14"></polyline></svg></label></div></div></li><li class="mv3"><input type="radio" name="carousel-3" id="carousel-3-4" class="o-0 absolute bottom-0 left-0"><div class="dn checked-reveal"><div class="aspect-ratio aspect-ratio--4x3"><img src="https://static.learnkube.com/f79c692910e952a61eac35de0b65a44d.svg" alt="The exact same process. A new "row" for the Pod is created in the database, and the endpoint is propagated.The exact same process. A new "row" for the Pod is created in the database, and the endpoint is propagated." class="aspect-ratio--object" loading="lazy"></div><div class="bt b-solid bw2 b--black-70 relative mt0"><div class="bg-black-10 br1 pa1 dib mt2 absolute bottom-1 left-0 z-999"><span class="b black-60">5</span><span class="f7 black-50">/8</span></div></div><div class="flex items-start justify-between bg-evian ph2"><label class="db f6 b black-50 pv3 pointer w-20 ttu" for="carousel-3-3"><svg viewBox="0 0 10 16" xmlns="http://www.w3.org/2000/svg" class="pagination-icon mr2"><polyline fill="none" vector-effect="non-scaling-stroke" points="8,2 2,8 8,14"></polyline></svg> Previous</label><div class="f5 lh-copy black-90 w-60 center"><p class="lh-copy measure-wide f5"></p><p class="lh-copy measure-wide f4">The exact same process. A new "row" for the Pod is created in the database, and the endpoint is propagated.</p><p></p></div><label class="db f6 b black-50 pv3 pointer w-20 tr ttu" for="carousel-3-5">Next <svg viewBox="0 0 10 16" xmlns="http://www.w3.org/2000/svg" class="pagination-icon ml2"><polyline fill="none" vector-effect="non-scaling-stroke" points="2,2 8,8 2,14"></polyline></svg></label></div></div></li><li class="mv3"><input type="radio" name="carousel-3" id="carousel-3-5" class="o-0 absolute bottom-0 left-0"><div class="dn checked-reveal"><div class="aspect-ratio aspect-ratio--4x3"><img src="https://static.learnkube.com/b0dc2e0cf59afaa974450b7238147ffc.svg" alt="_What happens when a Pod is deleted, though?_What happens when a Pod is deleted, though?" class="aspect-ratio--object" loading="lazy"></div><div class="bt b-solid bw2 b--black-70 relative mt0"><div class="bg-black-10 br1 pa1 dib mt2 absolute bottom-1 left-0 z-999"><span class="b black-60">6</span><span class="f7 black-50">/8</span></div></div><div class="flex items-start justify-between bg-evian ph2"><label class="db f6 b black-50 pv3 pointer w-20 ttu" for="carousel-3-4"><svg viewBox="0 0 10 16" xmlns="http://www.w3.org/2000/svg" class="pagination-icon mr2"><polyline fill="none" vector-effect="non-scaling-stroke" points="8,2 2,8 8,14"></polyline></svg> Previous</label><div class="f5 lh-copy black-90 w-60 center"><p class="lh-copy measure-wide f5"></p><p class="lh-copy measure-wide f4"><em class="i">What happens when a Pod is deleted, though?</em></p><p></p></div><label class="db f6 b black-50 pv3 pointer w-20 tr ttu" for="carousel-3-6">Next <svg viewBox="0 0 10 16" xmlns="http://www.w3.org/2000/svg" class="pagination-icon ml2"><polyline fill="none" vector-effect="non-scaling-stroke" points="2,2 8,8 2,14"></polyline></svg></label></div></div></li><li class="mv3"><input type="radio" name="carousel-3" id="carousel-3-6" class="o-0 absolute bottom-0 left-0"><div class="dn checked-reveal"><div class="aspect-ratio aspect-ratio--4x3"><img src="https://static.learnkube.com/6b924bc6f305e2f9b6a9460a7b6fe94d.svg" alt="The Service immediately removes the endpoint, and, eventually, the Pod is removed from the database too.The Service immediately removes the endpoint, and, eventually, the Pod is removed from the database too." class="aspect-ratio--object" loading="lazy"></div><div class="bt b-solid bw2 b--black-70 relative mt0"><div class="bg-black-10 br1 pa1 dib mt2 absolute bottom-1 left-0 z-999"><span class="b black-60">7</span><span class="f7 black-50">/8</span></div></div><div class="flex items-start justify-between bg-evian ph2"><label class="db f6 b black-50 pv3 pointer w-20 ttu" for="carousel-3-5"><svg viewBox="0 0 10 16" xmlns="http://www.w3.org/2000/svg" class="pagination-icon mr2"><polyline fill="none" vector-effect="non-scaling-stroke" points="8,2 2,8 8,14"></polyline></svg> Previous</label><div class="f5 lh-copy black-90 w-60 center"><p class="lh-copy measure-wide f5"></p><p class="lh-copy measure-wide f4">The Service immediately removes the endpoint, and, eventually, the Pod is removed from the database too.</p><p></p></div><label class="db f6 b black-50 pv3 pointer w-20 tr ttu" for="carousel-3-7">Next <svg viewBox="0 0 10 16" xmlns="http://www.w3.org/2000/svg" class="pagination-icon ml2"><polyline fill="none" vector-effect="non-scaling-stroke" points="2,2 8,8 2,14"></polyline></svg></label></div></div></li><li class="mv3"><input type="radio" name="carousel-3" id="carousel-3-7" class="o-0 absolute bottom-0 left-0"><div class="dn checked-reveal"><div class="aspect-ratio aspect-ratio--4x3"><img src="https://static.learnkube.com/d8b91861794c0642ae17a1081db79533.svg" alt="Kubernetes reacts to every small change in your cluster.Kubernetes reacts to every small change in your cluster." class="aspect-ratio--object" loading="lazy"></div><div class="bt b-solid bw2 b--black-70 relative mt0"><div class="bg-black-10 br1 pa1 dib mt2 absolute bottom-1 left-0 z-999"><span class="b black-60">8</span><span class="f7 black-50">/8</span></div></div><div class="flex items-start justify-between bg-evian ph2"><label class="db f6 b black-50 pv3 pointer w-20 ttu" for="carousel-3-6"><svg viewBox="0 0 10 16" xmlns="http://www.w3.org/2000/svg" class="pagination-icon mr2"><polyline fill="none" vector-effect="non-scaling-stroke" points="8,2 2,8 8,14"></polyline></svg> Previous</label><div class="f5 lh-copy black-90 w-60 center"><p class="lh-copy measure-wide f5"></p><p class="lh-copy measure-wide f4">Kubernetes reacts to every small change in your cluster.</p><p></p></div><div class="w-20"></div></div></div></li></ul></div><p class="lh-copy measure-wide f4"><em class="i">Are you ready to start using your Pod?</em></p><p class="lh-copy measure-wide f4"><strong class="b">There's more.</strong></p><p class="lh-copy measure-wide f4">A lot more!</p><aside class="mv5-l mv4 pa3 pa4-ns bg-evian br2 ba b--black-10"><div class="flex items-center"><svg viewBox="0 0 128 128" xmlns="http://www.w3.org/2000/svg" class="w2 h2"><path d="m68.05 7.23 13.46 30.7a7.047 7.047 0 0 0 5.82 4.19l32.79 2.94c3.71.54 5.19 5.09 2.5 7.71l-24.7 20.75c-2 1.68-2.91 4.32-2.36 6.87l7.18 33.61c.63 3.69-3.24 6.51-6.56 4.76L67.56 102a7.033 7.033 0 0 0-7.12 0l-28.62 16.75c-3.31 1.74-7.19-1.07-6.56-4.76l7.18-33.61c.54-2.55-.36-5.19-2.36-6.87L5.37 52.78c-2.68-2.61-1.2-7.17 2.5-7.71l32.79-2.94a7.047 7.047 0 0 0 5.82-4.19l13.46-30.7c1.67-3.36 6.45-3.36 8.11-.01z" fill="#ffe507"></path><path d="m67.07 39.77-2.28-22.62c-.09-1.26-.35-3.42 1.67-3.42 1.6 0 2.47 3.33 2.47 3.33l6.84 18.16c2.58 6.91 1.52 9.28-.97 10.68-2.86 1.6-7.08.35-7.73-6.13z" fill="#ffff8d"></path><path d="M95.28 71.51 114.9 56.2c.97-.81 2.72-2.1 1.32-3.57-1.11-1.16-4.11.51-4.11.51l-17.17 6.71c-5.12 1.77-8.52 4.39-8.82 7.69-.39 4.4 3.56 7.79 9.16 3.97z" fill="#f4b400"></path></svg><div class="ph1 flex-shrink-0"></div><div class="flex-auto"><p class="f3 b navy mv0 lh-title">Enjoying this?</p></div></div><div class="pv1"></div><p class="f4 lh-copy black-80 mv0 measure-wide">If you want to practice Kubernetes hands-on with someone walking you through it, join our <a href="/training" class="link navy b underline hover-sky">Kubernetes training</a>. The next public class starts on <span class="b">21 September 2026</span>.</p></aside><h2 class="f2 pt5 pb2 mt3" id="endpoints-are-the-kubernetes-currency">Endpoints are the Kubernetes currency</h2><p class="lh-copy measure-wide f4"><strong class="b">Endpoints are used by several components in Kubernetes.</strong></p><p class="lh-copy measure-wide f4">Kube-proxy uses the endpoints to set up iptables rules on the Nodes.</p><p class="lh-copy measure-wide f4">So, every time an Endpoint (the object) changes, kube-proxy retrieves the new list of IP addresses and ports and writes the new iptables rules.</p><div class="relative overflow-hidden"><ul class="pl0 list"><li class="mv3"><input type="radio" name="carousel-4" id="carousel-4-0" checked class="o-0 absolute bottom-0 left-0"><div class="dn checked-reveal"><div class="aspect-ratio aspect-ratio--4x3"><img src="https://static.learnkube.com/50e4746cbbda956a4550077f2954dd7a.svg" alt="Let's consider this three-node cluster with two Pods and no Services. The state of the Pods is stored in etcd.Let's consider this three-node cluster with two Pods and no Services. The state of the Pods is stored in etcd." class="aspect-ratio--object" loading="lazy"></div><div class="bt b-solid bw2 b--black-70 relative mt0"><div class="bg-black-10 br1 pa1 dib mt2 absolute bottom-1 left-0 z-999"><span class="b black-60">1</span><span class="f7 black-50">/6</span></div></div><div class="flex items-start justify-between bg-evian ph2"><div class="w-20"></div><div class="f5 lh-copy black-90 w-60 center"><p class="lh-copy measure-wide f5"></p><p class="lh-copy measure-wide f4">Let's consider this three-node cluster with two Pods and no Services. The state of the Pods is stored in etcd.</p><p></p></div><label class="db f6 b black-50 pv3 pointer w-20 tr ttu" for="carousel-4-1">Next <svg viewBox="0 0 10 16" xmlns="http://www.w3.org/2000/svg" class="pagination-icon ml2"><polyline fill="none" vector-effect="non-scaling-stroke" points="2,2 8,8 2,14"></polyline></svg></label></div></div></li><li class="mv3"><input type="radio" name="carousel-4" id="carousel-4-1" class="o-0 absolute bottom-0 left-0"><div class="dn checked-reveal"><div class="aspect-ratio aspect-ratio--4x3"><img src="https://static.learnkube.com/0bec792ac240a28af8b77223264ca803.svg" alt="_What happens when you create a Service?_What happens when you create a Service?" class="aspect-ratio--object" loading="lazy"></div><div class="bt b-solid bw2 b--black-70 relative mt0"><div class="bg-black-10 br1 pa1 dib mt2 absolute bottom-1 left-0 z-999"><span class="b black-60">2</span><span class="f7 black-50">/6</span></div></div><div class="flex items-start justify-between bg-evian ph2"><label class="db f6 b black-50 pv3 pointer w-20 ttu" for="carousel-4-0"><svg viewBox="0 0 10 16" xmlns="http://www.w3.org/2000/svg" class="pagination-icon mr2"><polyline fill="none" vector-effect="non-scaling-stroke" points="8,2 2,8 8,14"></polyline></svg> Previous</label><div class="f5 lh-copy black-90 w-60 center"><p class="lh-copy measure-wide f5"></p><p class="lh-copy measure-wide f4"><em class="i">What happens when you create a Service?</em></p><p></p></div><label class="db f6 b black-50 pv3 pointer w-20 tr ttu" for="carousel-4-2">Next <svg viewBox="0 0 10 16" xmlns="http://www.w3.org/2000/svg" class="pagination-icon ml2"><polyline fill="none" vector-effect="non-scaling-stroke" points="2,2 8,8 2,14"></polyline></svg></label></div></div></li><li class="mv3"><input type="radio" name="carousel-4" id="carousel-4-2" class="o-0 absolute bottom-0 left-0"><div class="dn checked-reveal"><div class="aspect-ratio aspect-ratio--4x3"><img src="https://static.learnkube.com/894afa71583ada1bb177c67eaf6ee9b9.svg" alt="Kubernetes created an Endpoint object and collects all the endpoints (IP address and port pairs) from the Pods.Kubernetes created an Endpoint object and collects all the endpoints (IP address and port pairs) from the Pods." class="aspect-ratio--object" loading="lazy"></div><div class="bt b-solid bw2 b--black-70 relative mt0"><div class="bg-black-10 br1 pa1 dib mt2 absolute bottom-1 left-0 z-999"><span class="b black-60">3</span><span class="f7 black-50">/6</span></div></div><div class="flex items-start justify-between bg-evian ph2"><label class="db f6 b black-50 pv3 pointer w-20 ttu" for="carousel-4-1"><svg viewBox="0 0 10 16" xmlns="http://www.w3.org/2000/svg" class="pagination-icon mr2"><polyline fill="none" vector-effect="non-scaling-stroke" points="8,2 2,8 8,14"></polyline></svg> Previous</label><div class="f5 lh-copy black-90 w-60 center"><p class="lh-copy measure-wide f5"></p><p class="lh-copy measure-wide f4">Kubernetes created an Endpoint object and collects all the endpoints (IP address and port pairs) from the Pods.</p><p></p></div><label class="db f6 b black-50 pv3 pointer w-20 tr ttu" for="carousel-4-3">Next <svg viewBox="0 0 10 16" xmlns="http://www.w3.org/2000/svg" class="pagination-icon ml2"><polyline fill="none" vector-effect="non-scaling-stroke" points="2,2 8,8 2,14"></polyline></svg></label></div></div></li><li class="mv3"><input type="radio" name="carousel-4" id="carousel-4-3" class="o-0 absolute bottom-0 left-0"><div class="dn checked-reveal"><div class="aspect-ratio aspect-ratio--4x3"><img src="https://static.learnkube.com/f6b33233527d0edd806e6e9b072ec8d5.svg" alt="Kube-proxy daemon is subscribed to changes to Endpoints.Kube-proxy daemon is subscribed to changes to Endpoints." class="aspect-ratio--object" loading="lazy"></div><div class="bt b-solid bw2 b--black-70 relative mt0"><div class="bg-black-10 br1 pa1 dib mt2 absolute bottom-1 left-0 z-999"><span class="b black-60">4</span><span class="f7 black-50">/6</span></div></div><div class="flex items-start justify-between bg-evian ph2"><label class="db f6 b black-50 pv3 pointer w-20 ttu" for="carousel-4-2"><svg viewBox="0 0 10 16" xmlns="http://www.w3.org/2000/svg" class="pagination-icon mr2"><polyline fill="none" vector-effect="non-scaling-stroke" points="8,2 2,8 8,14"></polyline></svg> Previous</label><div class="f5 lh-copy black-90 w-60 center"><p class="lh-copy measure-wide f5"></p><p class="lh-copy measure-wide f4">Kube-proxy daemon is subscribed to changes to Endpoints.</p><p></p></div><label class="db f6 b black-50 pv3 pointer w-20 tr ttu" for="carousel-4-4">Next <svg viewBox="0 0 10 16" xmlns="http://www.w3.org/2000/svg" class="pagination-icon ml2"><polyline fill="none" vector-effect="non-scaling-stroke" points="2,2 8,8 2,14"></polyline></svg></label></div></div></li><li class="mv3"><input type="radio" name="carousel-4" id="carousel-4-4" class="o-0 absolute bottom-0 left-0"><div class="dn checked-reveal"><div class="aspect-ratio aspect-ratio--4x3"><img src="https://static.learnkube.com/8ee4aa99ca6930f1950d9d9f6ac0e19f.svg" alt="When an Endpoint is added, removed or updated, kube-proxy retrieves the new list of endpoints.When an Endpoint is added, removed or updated, kube-proxy retrieves the new list of endpoints." class="aspect-ratio--object" loading="lazy"></div><div class="bt b-solid bw2 b--black-70 relative mt0"><div class="bg-black-10 br1 pa1 dib mt2 absolute bottom-1 left-0 z-999"><span class="b black-60">5</span><span class="f7 black-50">/6</span></div></div><div class="flex items-start justify-between bg-evian ph2"><label class="db f6 b black-50 pv3 pointer w-20 ttu" for="carousel-4-3"><svg viewBox="0 0 10 16" xmlns="http://www.w3.org/2000/svg" class="pagination-icon mr2"><polyline fill="none" vector-effect="non-scaling-stroke" points="8,2 2,8 8,14"></polyline></svg> Previous</label><div class="f5 lh-copy black-90 w-60 center"><p class="lh-copy measure-wide f5"></p><p class="lh-copy measure-wide f4">When an Endpoint is added, removed or updated, kube-proxy retrieves the new list of endpoints.</p><p></p></div><label class="db f6 b black-50 pv3 pointer w-20 tr ttu" for="carousel-4-5">Next <svg viewBox="0 0 10 16" xmlns="http://www.w3.org/2000/svg" class="pagination-icon ml2"><polyline fill="none" vector-effect="non-scaling-stroke" points="2,2 8,8 2,14"></polyline></svg></label></div></div></li><li class="mv3"><input type="radio" name="carousel-4" id="carousel-4-5" class="o-0 absolute bottom-0 left-0"><div class="dn checked-reveal"><div class="aspect-ratio aspect-ratio--4x3"><img src="https://static.learnkube.com/47813c337544b2f4430d9d0788ce43a7.svg" alt="Kube-proxy uses the endpoints to create iptables rules on each Node of your cluster.Kube-proxy uses the endpoints to create iptables rules on each Node of your cluster." class="aspect-ratio--object" loading="lazy"></div><div class="bt b-solid bw2 b--black-70 relative mt0"><div class="bg-black-10 br1 pa1 dib mt2 absolute bottom-1 left-0 z-999"><span class="b black-60">6</span><span class="f7 black-50">/6</span></div></div><div class="flex items-start justify-between bg-evian ph2"><label class="db f6 b black-50 pv3 pointer w-20 ttu" for="carousel-4-4"><svg viewBox="0 0 10 16" xmlns="http://www.w3.org/2000/svg" class="pagination-icon mr2"><polyline fill="none" vector-effect="non-scaling-stroke" points="8,2 2,8 8,14"></polyline></svg> Previous</label><div class="f5 lh-copy black-90 w-60 center"><p class="lh-copy measure-wide f5"></p><p class="lh-copy measure-wide f4">Kube-proxy uses the endpoints to create iptables rules on each Node of your cluster.</p><p></p></div><div class="w-20"></div></div></div></li></ul></div><p class="lh-copy measure-wide f4">The Ingress controller uses the same list of endpoints.</p><p class="lh-copy measure-wide f4"><strong class="b">The Ingress controller is that component in the cluster that routes external traffic into the cluster.</strong></p><p class="lh-copy measure-wide f4">When you set up an Ingress manifest, you usually specify the Service as the destination:</p><div class="mv4 mv5-l"><header class="bg-light-gray flex pv2 pl1 br--top br2 relative"><div class="w1 h1 ml1 br-100 bg-dark-red"></div><div class="w1 h1 ml1 br-100 bg-green"></div><div class="w1 h1 ml1 br-100 bg-yellow"></div><p class="code f6 mv0 black-60 w-100 tc absolute top-0 left-0 h1 pv2">ingress.yaml</p></header><pre class="code-light-theme relative overflow-auto mv0 br2 br--bottom"><code class="code lh-copy"><span class="standard"><span class="token key atrule">apiVersion</span><span class="token punctuation">:</span> networking.k8s.io/v1
|
|
<span class="token key atrule">kind</span><span class="token punctuation">:</span> Ingress
|
|
<span class="token key atrule">metadata</span><span class="token punctuation">:</span>
|
|
<span class="token key atrule">name</span><span class="token punctuation">:</span> my<span class="token punctuation">-</span>ingress
|
|
<span class="token key atrule">spec</span><span class="token punctuation">:</span>
|
|
<span class="token key atrule">rules</span><span class="token punctuation">:</span>
|
|
<span class="token punctuation">-</span> <span class="token key atrule">http</span><span class="token punctuation">:</span>
|
|
<span class="token key atrule">paths</span><span class="token punctuation">:</span>
|
|
<span class="token punctuation">-</span> <span class="token key atrule">backend</span><span class="token punctuation">:</span>
|
|
<span class="token key atrule">service</span><span class="token punctuation">:</span>
|
|
</span><span class="highlight"> <span class="token key atrule">name</span><span class="token punctuation">:</span> my<span class="token punctuation">-</span>service
|
|
<span class="token key atrule">port</span><span class="token punctuation">:</span>
|
|
<span class="token key atrule">number</span><span class="token punctuation">:</span> <span class="token number">80</span>
|
|
</span><span class="standard"> <span class="token key atrule">path</span><span class="token punctuation">:</span> /
|
|
<span class="token key atrule">pathType</span><span class="token punctuation">:</span> Prefix</span></code></pre></div><p class="lh-copy measure-wide f4"><em class="i">In reality, the traffic is not routed to the Service.</em></p><p class="lh-copy measure-wide f4">Instead, the Ingress controller sets up a subscription to be notified every time the endpoints for that Service change.</p><p class="lh-copy measure-wide f4"><strong class="b">The Ingress routes the traffic directly to the Pods, skipping the Service.</strong></p><p class="lh-copy measure-wide f4">As you can imagine, every time there is a change to an Endpoint (the object), the Ingress retrieves the new list of IP addresses and ports and reconfigures the controller to include the new Pods.</p><div class="relative overflow-hidden"><ul class="pl0 list"><li class="mv3"><input type="radio" name="carousel-5" id="carousel-5-0" checked class="o-0 absolute bottom-0 left-0"><div class="dn checked-reveal"><div class="aspect-ratio aspect-ratio--4x3"><img src="https://static.learnkube.com/175161d4127b2daf602b2a240190771d.svg" alt="In this picture, there's an Ingress controller with a Deployment with two replicas and a Service.In this picture, there's an Ingress controller with a Deployment with two replicas and a Service." class="aspect-ratio--object" loading="lazy"></div><div class="bt b-solid bw2 b--black-70 relative mt0"><div class="bg-black-10 br1 pa1 dib mt2 absolute bottom-1 left-0 z-999"><span class="b black-60">1</span><span class="f7 black-50">/9</span></div></div><div class="flex items-start justify-between bg-evian ph2"><div class="w-20"></div><div class="f5 lh-copy black-90 w-60 center"><p class="lh-copy measure-wide f5"></p><p class="lh-copy measure-wide f4">In this picture, there's an Ingress controller with a Deployment with two replicas and a Service.</p><p></p></div><label class="db f6 b black-50 pv3 pointer w-20 tr ttu" for="carousel-5-1">Next <svg viewBox="0 0 10 16" xmlns="http://www.w3.org/2000/svg" class="pagination-icon ml2"><polyline fill="none" vector-effect="non-scaling-stroke" points="2,2 8,8 2,14"></polyline></svg></label></div></div></li><li class="mv3"><input type="radio" name="carousel-5" id="carousel-5-1" class="o-0 absolute bottom-0 left-0"><div class="dn checked-reveal"><div class="aspect-ratio aspect-ratio--4x3"><img src="https://static.learnkube.com/d3c5ee927904dea938e931efbc95c3b4.svg" alt="If you want to route external traffic to the Pods through the Ingress, you should create an Ingress manifest (a YAML file).If you want to route external traffic to the Pods through the Ingress, you should create an Ingress manifest (a YAML file)." class="aspect-ratio--object" loading="lazy"></div><div class="bt b-solid bw2 b--black-70 relative mt0"><div class="bg-black-10 br1 pa1 dib mt2 absolute bottom-1 left-0 z-999"><span class="b black-60">2</span><span class="f7 black-50">/9</span></div></div><div class="flex items-start justify-between bg-evian ph2"><label class="db f6 b black-50 pv3 pointer w-20 ttu" for="carousel-5-0"><svg viewBox="0 0 10 16" xmlns="http://www.w3.org/2000/svg" class="pagination-icon mr2"><polyline fill="none" vector-effect="non-scaling-stroke" points="8,2 2,8 8,14"></polyline></svg> Previous</label><div class="f5 lh-copy black-90 w-60 center"><p class="lh-copy measure-wide f5"></p><p class="lh-copy measure-wide f4">If you want to route external traffic to the Pods through the Ingress, you should create an Ingress manifest (a YAML file).</p><p></p></div><label class="db f6 b black-50 pv3 pointer w-20 tr ttu" for="carousel-5-2">Next <svg viewBox="0 0 10 16" xmlns="http://www.w3.org/2000/svg" class="pagination-icon ml2"><polyline fill="none" vector-effect="non-scaling-stroke" points="2,2 8,8 2,14"></polyline></svg></label></div></div></li><li class="mv3"><input type="radio" name="carousel-5" id="carousel-5-2" class="o-0 absolute bottom-0 left-0"><div class="dn checked-reveal"><div class="aspect-ratio aspect-ratio--4x3"><img src="https://static.learnkube.com/383fcfa01eeb6148e5c84a5e424b96f7.svg" alt="As soon as you `kubectl apply -f ingress.yaml`, the Ingress controller retrieves the file from the control plane.As soon as you kubectl apply -f ingress.yaml, the Ingress controller retrieves the file from the control plane." class="aspect-ratio--object" loading="lazy"></div><div class="bt b-solid bw2 b--black-70 relative mt0"><div class="bg-black-10 br1 pa1 dib mt2 absolute bottom-1 left-0 z-999"><span class="b black-60">3</span><span class="f7 black-50">/9</span></div></div><div class="flex items-start justify-between bg-evian ph2"><label class="db f6 b black-50 pv3 pointer w-20 ttu" for="carousel-5-1"><svg viewBox="0 0 10 16" xmlns="http://www.w3.org/2000/svg" class="pagination-icon mr2"><polyline fill="none" vector-effect="non-scaling-stroke" points="8,2 2,8 8,14"></polyline></svg> Previous</label><div class="f5 lh-copy black-90 w-60 center"><p class="lh-copy measure-wide f5"></p><p class="lh-copy measure-wide f4">As soon as you <code class="code f5 lh-copy bg-near-white br2 pv1 ph2 fs-normal word-wrap">kubectl apply -f ingress.yaml</code>, the Ingress controller retrieves the file from the control plane.</p><p></p></div><label class="db f6 b black-50 pv3 pointer w-20 tr ttu" for="carousel-5-3">Next <svg viewBox="0 0 10 16" xmlns="http://www.w3.org/2000/svg" class="pagination-icon ml2"><polyline fill="none" vector-effect="non-scaling-stroke" points="2,2 8,8 2,14"></polyline></svg></label></div></div></li><li class="mv3"><input type="radio" name="carousel-5" id="carousel-5-3" class="o-0 absolute bottom-0 left-0"><div class="dn checked-reveal"><div class="aspect-ratio aspect-ratio--4x3"><img src="https://static.learnkube.com/075d6f95fb8bcbfdf3c7a71139f883d0.svg" alt="The Ingress YAML has a `serviceName` property that describes which Service it should use.The Ingress YAML has a serviceName property that describes which Service it should use." class="aspect-ratio--object" loading="lazy"></div><div class="bt b-solid bw2 b--black-70 relative mt0"><div class="bg-black-10 br1 pa1 dib mt2 absolute bottom-1 left-0 z-999"><span class="b black-60">4</span><span class="f7 black-50">/9</span></div></div><div class="flex items-start justify-between bg-evian ph2"><label class="db f6 b black-50 pv3 pointer w-20 ttu" for="carousel-5-2"><svg viewBox="0 0 10 16" xmlns="http://www.w3.org/2000/svg" class="pagination-icon mr2"><polyline fill="none" vector-effect="non-scaling-stroke" points="8,2 2,8 8,14"></polyline></svg> Previous</label><div class="f5 lh-copy black-90 w-60 center"><p class="lh-copy measure-wide f5"></p><p class="lh-copy measure-wide f4">The Ingress YAML has a <code class="code f5 lh-copy bg-near-white br2 pv1 ph2 fs-normal word-wrap">serviceName</code> property that describes which Service it should use.</p><p></p></div><label class="db f6 b black-50 pv3 pointer w-20 tr ttu" for="carousel-5-4">Next <svg viewBox="0 0 10 16" xmlns="http://www.w3.org/2000/svg" class="pagination-icon ml2"><polyline fill="none" vector-effect="non-scaling-stroke" points="2,2 8,8 2,14"></polyline></svg></label></div></div></li><li class="mv3"><input type="radio" name="carousel-5" id="carousel-5-4" class="o-0 absolute bottom-0 left-0"><div class="dn checked-reveal"><div class="aspect-ratio aspect-ratio--4x3"><img src="https://static.learnkube.com/0c2e8feb4ef8b4481e29b44320248645.svg" alt="The Ingress controller retrieves the list of endpoints from the Service and skips it. The traffic flows directly to the endpoints (Pods).The Ingress controller retrieves the list of endpoints from the Service and skips it. The traffic flows directly to the endpoints (Pods)." class="aspect-ratio--object" loading="lazy"></div><div class="bt b-solid bw2 b--black-70 relative mt0"><div class="bg-black-10 br1 pa1 dib mt2 absolute bottom-1 left-0 z-999"><span class="b black-60">5</span><span class="f7 black-50">/9</span></div></div><div class="flex items-start justify-between bg-evian ph2"><label class="db f6 b black-50 pv3 pointer w-20 ttu" for="carousel-5-3"><svg viewBox="0 0 10 16" xmlns="http://www.w3.org/2000/svg" class="pagination-icon mr2"><polyline fill="none" vector-effect="non-scaling-stroke" points="8,2 2,8 8,14"></polyline></svg> Previous</label><div class="f5 lh-copy black-90 w-60 center"><p class="lh-copy measure-wide f5"></p><p class="lh-copy measure-wide f4">The Ingress controller retrieves the list of endpoints from the Service and skips it. The traffic flows directly to the endpoints (Pods).</p><p></p></div><label class="db f6 b black-50 pv3 pointer w-20 tr ttu" for="carousel-5-5">Next <svg viewBox="0 0 10 16" xmlns="http://www.w3.org/2000/svg" class="pagination-icon ml2"><polyline fill="none" vector-effect="non-scaling-stroke" points="2,2 8,8 2,14"></polyline></svg></label></div></div></li><li class="mv3"><input type="radio" name="carousel-5" id="carousel-5-5" class="o-0 absolute bottom-0 left-0"><div class="dn checked-reveal"><div class="aspect-ratio aspect-ratio--4x3"><img src="https://static.learnkube.com/dd61511236d08272e6b4b96958323a80.svg" alt="_What happens when a new Pod is created?_What happens when a new Pod is created?" class="aspect-ratio--object" loading="lazy"></div><div class="bt b-solid bw2 b--black-70 relative mt0"><div class="bg-black-10 br1 pa1 dib mt2 absolute bottom-1 left-0 z-999"><span class="b black-60">6</span><span class="f7 black-50">/9</span></div></div><div class="flex items-start justify-between bg-evian ph2"><label class="db f6 b black-50 pv3 pointer w-20 ttu" for="carousel-5-4"><svg viewBox="0 0 10 16" xmlns="http://www.w3.org/2000/svg" class="pagination-icon mr2"><polyline fill="none" vector-effect="non-scaling-stroke" points="8,2 2,8 8,14"></polyline></svg> Previous</label><div class="f5 lh-copy black-90 w-60 center"><p class="lh-copy measure-wide f5"></p><p class="lh-copy measure-wide f4"><em class="i">What happens when a new Pod is created?</em></p><p></p></div><label class="db f6 b black-50 pv3 pointer w-20 tr ttu" for="carousel-5-6">Next <svg viewBox="0 0 10 16" xmlns="http://www.w3.org/2000/svg" class="pagination-icon ml2"><polyline fill="none" vector-effect="non-scaling-stroke" points="2,2 8,8 2,14"></polyline></svg></label></div></div></li><li class="mv3"><input type="radio" name="carousel-5" id="carousel-5-6" class="o-0 absolute bottom-0 left-0"><div class="dn checked-reveal"><div class="aspect-ratio aspect-ratio--4x3"><img src="https://static.learnkube.com/f7f74cb6e0a3c6b9f3db4cdd0b9f977b.svg" alt="You know already how Kubernetes creates the Pod and propagates the endpoint.You know already how Kubernetes creates the Pod and propagates the endpoint." class="aspect-ratio--object" loading="lazy"></div><div class="bt b-solid bw2 b--black-70 relative mt0"><div class="bg-black-10 br1 pa1 dib mt2 absolute bottom-1 left-0 z-999"><span class="b black-60">7</span><span class="f7 black-50">/9</span></div></div><div class="flex items-start justify-between bg-evian ph2"><label class="db f6 b black-50 pv3 pointer w-20 ttu" for="carousel-5-5"><svg viewBox="0 0 10 16" xmlns="http://www.w3.org/2000/svg" class="pagination-icon mr2"><polyline fill="none" vector-effect="non-scaling-stroke" points="8,2 2,8 8,14"></polyline></svg> Previous</label><div class="f5 lh-copy black-90 w-60 center"><p class="lh-copy measure-wide f5"></p><p class="lh-copy measure-wide f4">You know already how Kubernetes creates the Pod and propagates the endpoint.</p><p></p></div><label class="db f6 b black-50 pv3 pointer w-20 tr ttu" for="carousel-5-7">Next <svg viewBox="0 0 10 16" xmlns="http://www.w3.org/2000/svg" class="pagination-icon ml2"><polyline fill="none" vector-effect="non-scaling-stroke" points="2,2 8,8 2,14"></polyline></svg></label></div></div></li><li class="mv3"><input type="radio" name="carousel-5" id="carousel-5-7" class="o-0 absolute bottom-0 left-0"><div class="dn checked-reveal"><div class="aspect-ratio aspect-ratio--4x3"><img src="https://static.learnkube.com/6ed77cfdf58b6c65e060b7b0c870e80f.svg" alt="The Ingress controller subscribes to endpoint changes. Since there's an incoming change, it retrieves the new list of endpoints.The Ingress controller subscribes to endpoint changes. Since there's an incoming change, it retrieves the new list of endpoints." class="aspect-ratio--object" loading="lazy"></div><div class="bt b-solid bw2 b--black-70 relative mt0"><div class="bg-black-10 br1 pa1 dib mt2 absolute bottom-1 left-0 z-999"><span class="b black-60">8</span><span class="f7 black-50">/9</span></div></div><div class="flex items-start justify-between bg-evian ph2"><label class="db f6 b black-50 pv3 pointer w-20 ttu" for="carousel-5-6"><svg viewBox="0 0 10 16" xmlns="http://www.w3.org/2000/svg" class="pagination-icon mr2"><polyline fill="none" vector-effect="non-scaling-stroke" points="8,2 2,8 8,14"></polyline></svg> Previous</label><div class="f5 lh-copy black-90 w-60 center"><p class="lh-copy measure-wide f5"></p><p class="lh-copy measure-wide f4">The Ingress controller subscribes to endpoint changes. Since there's an incoming change, it retrieves the new list of endpoints.</p><p></p></div><label class="db f6 b black-50 pv3 pointer w-20 tr ttu" for="carousel-5-8">Next <svg viewBox="0 0 10 16" xmlns="http://www.w3.org/2000/svg" class="pagination-icon ml2"><polyline fill="none" vector-effect="non-scaling-stroke" points="2,2 8,8 2,14"></polyline></svg></label></div></div></li><li class="mv3"><input type="radio" name="carousel-5" id="carousel-5-8" class="o-0 absolute bottom-0 left-0"><div class="dn checked-reveal"><div class="aspect-ratio aspect-ratio--4x3"><img src="https://static.learnkube.com/c9b0bf9d33e94299b978cbabbda0a57e.svg" alt="The Ingress controller routes the traffic to the new Pod.The Ingress controller routes the traffic to the new Pod." class="aspect-ratio--object" loading="lazy"></div><div class="bt b-solid bw2 b--black-70 relative mt0"><div class="bg-black-10 br1 pa1 dib mt2 absolute bottom-1 left-0 z-999"><span class="b black-60">9</span><span class="f7 black-50">/9</span></div></div><div class="flex items-start justify-between bg-evian ph2"><label class="db f6 b black-50 pv3 pointer w-20 ttu" for="carousel-5-7"><svg viewBox="0 0 10 16" xmlns="http://www.w3.org/2000/svg" class="pagination-icon mr2"><polyline fill="none" vector-effect="non-scaling-stroke" points="8,2 2,8 8,14"></polyline></svg> Previous</label><div class="f5 lh-copy black-90 w-60 center"><p class="lh-copy measure-wide f5"></p><p class="lh-copy measure-wide f4">The Ingress controller routes the traffic to the new Pod.</p><p></p></div><div class="w-20"></div></div></div></li></ul></div><p class="lh-copy measure-wide f4">There are more examples of Kubernetes components that subscribe to changes to endpoints.</p><p class="lh-copy measure-wide f4">CoreDNS, the DNS component in the cluster, is another example.</p><p class="lh-copy measure-wide f4">If you use <a href="https://kubernetes.io/docs/concepts/services-networking/service/#headless-services" target="_blank" rel="noreferrer" class="link navy underline hover-sky">Services of type Headless</a>, CoreDNS will have to subscribe to changes to the endpoints and reconfigure itself every time an endpoint is added or removed.</p><p class="lh-copy measure-wide f4">The same endpoints are consumed by service meshes such as Istio or Linkerd <a href="https://thebsdbox.co.uk/2020/03/18/Creating-a-Kubernetes-cloud-doesn-t-required-boiling-the-ocean/" target="_blank" rel="noreferrer" class="link navy underline hover-sky">by cloud providers to create Services of <code class="code f5 lh-copy bg-near-white br2 pv1 ph2 fs-normal word-wrap">type:LoadBalancer</code></a> and countless operators.</p><p class="lh-copy measure-wide f4">You must remember that several components subscribe to change to endpoints and might receive notifications about endpoint updates at different times.</p><p class="lh-copy measure-wide f4"><em class="i">Is it enough, or is there something happening after you create a Pod?</em></p><p class="lh-copy measure-wide f4"><strong class="b">This time, you're done!</strong></p><p class="lh-copy measure-wide f4">Here is a quick recap of what happens when you create a Pod:</p><ol><li class="lh-copy f4 mv1 measure-wide">The Pod is stored in etcd.</li><li class="lh-copy f4 mv1 measure-wide">The scheduler assigns a Node. It writes the node in etcd.</li><li class="lh-copy f4 mv1 measure-wide">The kubelet is notified of a new and scheduled Pod.</li><li class="lh-copy f4 mv1 measure-wide">The kubelet delegates creating the container to the Container Runtime Interface (CRI).</li><li class="lh-copy f4 mv1 measure-wide">The kubelet delegates attaching the container to the Container Network Interface (CNI).</li><li class="lh-copy f4 mv1 measure-wide">The kubelet delegates mounting volumes in the container to the Container Storage Interface (CSI).</li><li class="lh-copy f4 mv1 measure-wide">The Container Network Interface assigns an IP address.</li><li class="lh-copy f4 mv1 measure-wide">The kubelet reports the IP address to the control plane.</li><li class="lh-copy f4 mv1 measure-wide">The IP address is stored in etcd.</li></ol><p class="lh-copy measure-wide f4">And if your Pod belongs to a Service:</p><ol><li class="lh-copy f4 mv1 measure-wide">The kubelet waits for a successful Readiness probe.</li><li class="lh-copy f4 mv1 measure-wide">All relevant Endpoints (objects) are notified of the change.</li><li class="lh-copy f4 mv1 measure-wide">The Endpoints add a new endpoint (IP address + port pair) to their list.</li><li class="lh-copy f4 mv1 measure-wide">Kube-proxy is notified of the Endpoint change. Kube-proxy updates the iptables rules on every node.</li><li class="lh-copy f4 mv1 measure-wide">The Ingress controller is notified of the Endpoint change. The controller routes traffic to the new IP addresses.</li><li class="lh-copy f4 mv1 measure-wide">CoreDNS is notified of the Endpoint change. If the Service is of type Headless, the DNS entry is updated.</li><li class="lh-copy f4 mv1 measure-wide">The cloud provider is notified of the Endpoint change. If the Service is of <code class="code f5 lh-copy bg-near-white br2 pv1 ph2 fs-normal word-wrap">type: LoadBalancer</code>, the new endpoint are configured as part of the load balancer pool.</li><li class="lh-copy f4 mv1 measure-wide">Any service mesh installed in the cluster is notified of the Endpoint change.</li><li class="lh-copy f4 mv1 measure-wide">Any other operator subscribed to Endpoint changes is notified, too.</li></ol><p class="lh-copy measure-wide f4"><em class="i">Such a long list for what is surprisingly a common task — creating a Pod.</em></p><p class="lh-copy measure-wide f4">The Pod is <em class="i">Running</em>.</p><p class="lh-copy measure-wide f4">It is time to discuss what happens when you delete it.</p><h2 class="f2 pt5 pb2 mt3" id="what-happens-when-you-delete-a-pod">What happens when you delete a Pod</h2><p class="lh-copy measure-wide f4">You might have guessed it already, but when the Pod is deleted, you must follow the same steps but reversely.</p><p class="lh-copy measure-wide f4">First, the endpoint should be removed from the Endpoint (object).</p><p class="lh-copy measure-wide f4"><strong class="b">This time, the Readiness probe is still active, but the endpoint is removed immediately from the control plane.</strong></p><p class="lh-copy measure-wide f4">That, in turn, fires off all the events to kube-proxy, Ingress controller, DNS, service mesh, etc.</p><p class="lh-copy measure-wide f4">Those components will update their internal state and stop routing traffic to the IP address.</p><p class="lh-copy measure-wide f4">Since the components might be busy doing something else, <strong class="b">there is no guarantee on how long it will take to remove the IP address from their internal state.</strong></p><p class="lh-copy measure-wide f4">For some, it could take less than a second; for others, it could take more.</p><div class="relative overflow-hidden"><ul class="pl0 list"><li class="mv3"><input type="radio" name="carousel-6" id="carousel-6-0" checked class="o-0 absolute bottom-0 left-0"><div class="dn checked-reveal"><div class="aspect-ratio aspect-ratio--4x3"><img src="https://static.learnkube.com/336567c1d80c8853cb6900bdf6fd30d9.svg" alt="If you delete a Pod with `kubectl delete pod,` the command reaches the Kubernetes API first.If you delete a Pod with kubectl delete pod, the command reaches the Kubernetes API first." class="aspect-ratio--object" loading="lazy"></div><div class="bt b-solid bw2 b--black-70 relative mt0"><div class="bg-black-10 br1 pa1 dib mt2 absolute bottom-1 left-0 z-999"><span class="b black-60">1</span><span class="f7 black-50">/5</span></div></div><div class="flex items-start justify-between bg-evian ph2"><div class="w-20"></div><div class="f5 lh-copy black-90 w-60 center"><p class="lh-copy measure-wide f5"></p><p class="lh-copy measure-wide f4">If you delete a Pod with <code class="code f5 lh-copy bg-near-white br2 pv1 ph2 fs-normal word-wrap">kubectl delete pod,</code> the command reaches the Kubernetes API first.</p><p></p></div><label class="db f6 b black-50 pv3 pointer w-20 tr ttu" for="carousel-6-1">Next <svg viewBox="0 0 10 16" xmlns="http://www.w3.org/2000/svg" class="pagination-icon ml2"><polyline fill="none" vector-effect="non-scaling-stroke" points="2,2 8,8 2,14"></polyline></svg></label></div></div></li><li class="mv3"><input type="radio" name="carousel-6" id="carousel-6-1" class="o-0 absolute bottom-0 left-0"><div class="dn checked-reveal"><div class="aspect-ratio aspect-ratio--4x3"><img src="https://static.learnkube.com/3aa0a5772abbf21e0a48e3e924ee13cb.svg" alt="The message is intercepted by a specific controller in the control plane: the Endpoint controller.The message is intercepted by a specific controller in the control plane: the Endpoint controller." class="aspect-ratio--object" loading="lazy"></div><div class="bt b-solid bw2 b--black-70 relative mt0"><div class="bg-black-10 br1 pa1 dib mt2 absolute bottom-1 left-0 z-999"><span class="b black-60">2</span><span class="f7 black-50">/5</span></div></div><div class="flex items-start justify-between bg-evian ph2"><label class="db f6 b black-50 pv3 pointer w-20 ttu" for="carousel-6-0"><svg viewBox="0 0 10 16" xmlns="http://www.w3.org/2000/svg" class="pagination-icon mr2"><polyline fill="none" vector-effect="non-scaling-stroke" points="8,2 2,8 8,14"></polyline></svg> Previous</label><div class="f5 lh-copy black-90 w-60 center"><p class="lh-copy measure-wide f5"></p><p class="lh-copy measure-wide f4">The message is intercepted by a specific controller in the control plane: the Endpoint controller.</p><p></p></div><label class="db f6 b black-50 pv3 pointer w-20 tr ttu" for="carousel-6-2">Next <svg viewBox="0 0 10 16" xmlns="http://www.w3.org/2000/svg" class="pagination-icon ml2"><polyline fill="none" vector-effect="non-scaling-stroke" points="2,2 8,8 2,14"></polyline></svg></label></div></div></li><li class="mv3"><input type="radio" name="carousel-6" id="carousel-6-2" class="o-0 absolute bottom-0 left-0"><div class="dn checked-reveal"><div class="aspect-ratio aspect-ratio--4x3"><img src="https://static.learnkube.com/e57e370b4878c30bfe59b44cb777e416.svg" alt="The Endpoint controller issues a command to the API to remove the IP address and port from the Endpoint object.The Endpoint controller issues a command to the API to remove the IP address and port from the Endpoint object." class="aspect-ratio--object" loading="lazy"></div><div class="bt b-solid bw2 b--black-70 relative mt0"><div class="bg-black-10 br1 pa1 dib mt2 absolute bottom-1 left-0 z-999"><span class="b black-60">3</span><span class="f7 black-50">/5</span></div></div><div class="flex items-start justify-between bg-evian ph2"><label class="db f6 b black-50 pv3 pointer w-20 ttu" for="carousel-6-1"><svg viewBox="0 0 10 16" xmlns="http://www.w3.org/2000/svg" class="pagination-icon mr2"><polyline fill="none" vector-effect="non-scaling-stroke" points="8,2 2,8 8,14"></polyline></svg> Previous</label><div class="f5 lh-copy black-90 w-60 center"><p class="lh-copy measure-wide f5"></p><p class="lh-copy measure-wide f4">The Endpoint controller issues a command to the API to remove the IP address and port from the Endpoint object.</p><p></p></div><label class="db f6 b black-50 pv3 pointer w-20 tr ttu" for="carousel-6-3">Next <svg viewBox="0 0 10 16" xmlns="http://www.w3.org/2000/svg" class="pagination-icon ml2"><polyline fill="none" vector-effect="non-scaling-stroke" points="2,2 8,8 2,14"></polyline></svg></label></div></div></li><li class="mv3"><input type="radio" name="carousel-6" id="carousel-6-3" class="o-0 absolute bottom-0 left-0"><div class="dn checked-reveal"><div class="aspect-ratio aspect-ratio--4x3"><img src="https://static.learnkube.com/60b2ec661d805db259d20d5b5c8ae228.svg" alt="_Who listens for Endpoint changes?_ Kube-proxy, the Ingress controller, CoreDNS, etc., are notified of the change.Who listens for Endpoint changes? Kube-proxy, the Ingress controller, CoreDNS, etc., are notified of the change." class="aspect-ratio--object" loading="lazy"></div><div class="bt b-solid bw2 b--black-70 relative mt0"><div class="bg-black-10 br1 pa1 dib mt2 absolute bottom-1 left-0 z-999"><span class="b black-60">4</span><span class="f7 black-50">/5</span></div></div><div class="flex items-start justify-between bg-evian ph2"><label class="db f6 b black-50 pv3 pointer w-20 ttu" for="carousel-6-2"><svg viewBox="0 0 10 16" xmlns="http://www.w3.org/2000/svg" class="pagination-icon mr2"><polyline fill="none" vector-effect="non-scaling-stroke" points="8,2 2,8 8,14"></polyline></svg> Previous</label><div class="f5 lh-copy black-90 w-60 center"><p class="lh-copy measure-wide f5"></p><p class="lh-copy measure-wide f4"><em class="i">Who listens for Endpoint changes?</em> Kube-proxy, the Ingress controller, CoreDNS, etc., are notified of the change.</p><p></p></div><label class="db f6 b black-50 pv3 pointer w-20 tr ttu" for="carousel-6-4">Next <svg viewBox="0 0 10 16" xmlns="http://www.w3.org/2000/svg" class="pagination-icon ml2"><polyline fill="none" vector-effect="non-scaling-stroke" points="2,2 8,8 2,14"></polyline></svg></label></div></div></li><li class="mv3"><input type="radio" name="carousel-6" id="carousel-6-4" class="o-0 absolute bottom-0 left-0"><div class="dn checked-reveal"><div class="aspect-ratio aspect-ratio--4x3"><img src="https://static.learnkube.com/e1d6b1c2a0da6fea4b23038465063b60.svg" alt="A few components, such as kube-proxy, might need some extra time to propagate the changes further.A few components, such as kube-proxy, might need some extra time to propagate the changes further." class="aspect-ratio--object" loading="lazy"></div><div class="bt b-solid bw2 b--black-70 relative mt0"><div class="bg-black-10 br1 pa1 dib mt2 absolute bottom-1 left-0 z-999"><span class="b black-60">5</span><span class="f7 black-50">/5</span></div></div><div class="flex items-start justify-between bg-evian ph2"><label class="db f6 b black-50 pv3 pointer w-20 ttu" for="carousel-6-3"><svg viewBox="0 0 10 16" xmlns="http://www.w3.org/2000/svg" class="pagination-icon mr2"><polyline fill="none" vector-effect="non-scaling-stroke" points="8,2 2,8 8,14"></polyline></svg> Previous</label><div class="f5 lh-copy black-90 w-60 center"><p class="lh-copy measure-wide f5"></p><p class="lh-copy measure-wide f4">A few components, such as kube-proxy, might need some extra time to propagate the changes further.</p><p></p></div><div class="w-20"></div></div></div></li></ul></div><p class="lh-copy measure-wide f4">At the same time, the status of the Pod in etcd is changed to <em class="i">Terminating</em>.</p><p class="lh-copy measure-wide f4">The kubelet is notified of the change and delegates:</p><ol><li class="lh-copy f4 mv1 measure-wide"><strong class="b">Unmounting any volumes</strong> from the container to the Container Storage Interface (CSI).</li><li class="lh-copy f4 mv1 measure-wide"><strong class="b">Detaching the container</strong> from the network and releasing the IP address to the Container Network Interface (CNI).</li><li class="lh-copy f4 mv1 measure-wide"><strong class="b">Destroying the container</strong> to the Container Runtime Interface (CRI).</li></ol><p class="lh-copy measure-wide f4">In other words, Kubernetes follows precisely the same steps to create a Pod but in reverse.</p><div class="relative overflow-hidden"><ul class="pl0 list"><li class="mv3"><input type="radio" name="carousel-7" id="carousel-7-0" checked class="o-0 absolute bottom-0 left-0"><div class="dn checked-reveal"><div class="aspect-ratio aspect-ratio--4x3"><img src="https://static.learnkube.com/dbfd8be2cd6fbc3984dbb12cfece608d.svg" alt="If you delete a Pod with `kubectl delete pod,` the command reaches the Kubernetes API first.If you delete a Pod with kubectl delete pod, the command reaches the Kubernetes API first." class="aspect-ratio--object" loading="lazy"></div><div class="bt b-solid bw2 b--black-70 relative mt0"><div class="bg-black-10 br1 pa1 dib mt2 absolute bottom-1 left-0 z-999"><span class="b black-60">1</span><span class="f7 black-50">/3</span></div></div><div class="flex items-start justify-between bg-evian ph2"><div class="w-20"></div><div class="f5 lh-copy black-90 w-60 center"><p class="lh-copy measure-wide f5"></p><p class="lh-copy measure-wide f4">If you delete a Pod with <code class="code f5 lh-copy bg-near-white br2 pv1 ph2 fs-normal word-wrap">kubectl delete pod,</code> the command reaches the Kubernetes API first.</p><p></p></div><label class="db f6 b black-50 pv3 pointer w-20 tr ttu" for="carousel-7-1">Next <svg viewBox="0 0 10 16" xmlns="http://www.w3.org/2000/svg" class="pagination-icon ml2"><polyline fill="none" vector-effect="non-scaling-stroke" points="2,2 8,8 2,14"></polyline></svg></label></div></div></li><li class="mv3"><input type="radio" name="carousel-7" id="carousel-7-1" class="o-0 absolute bottom-0 left-0"><div class="dn checked-reveal"><div class="aspect-ratio aspect-ratio--4x3"><img src="https://static.learnkube.com/a1d3c5ef9a585168515f391d2cca3870.svg" alt="When the kubelet polls the control plane for updates, it notices that the Pod was deleted.When the kubelet polls the control plane for updates, it notices that the Pod was deleted." class="aspect-ratio--object" loading="lazy"></div><div class="bt b-solid bw2 b--black-70 relative mt0"><div class="bg-black-10 br1 pa1 dib mt2 absolute bottom-1 left-0 z-999"><span class="b black-60">2</span><span class="f7 black-50">/3</span></div></div><div class="flex items-start justify-between bg-evian ph2"><label class="db f6 b black-50 pv3 pointer w-20 ttu" for="carousel-7-0"><svg viewBox="0 0 10 16" xmlns="http://www.w3.org/2000/svg" class="pagination-icon mr2"><polyline fill="none" vector-effect="non-scaling-stroke" points="8,2 2,8 8,14"></polyline></svg> Previous</label><div class="f5 lh-copy black-90 w-60 center"><p class="lh-copy measure-wide f5"></p><p class="lh-copy measure-wide f4">When the kubelet polls the control plane for updates, it notices that the Pod was deleted.</p><p></p></div><label class="db f6 b black-50 pv3 pointer w-20 tr ttu" for="carousel-7-2">Next <svg viewBox="0 0 10 16" xmlns="http://www.w3.org/2000/svg" class="pagination-icon ml2"><polyline fill="none" vector-effect="non-scaling-stroke" points="2,2 8,8 2,14"></polyline></svg></label></div></div></li><li class="mv3"><input type="radio" name="carousel-7" id="carousel-7-2" class="o-0 absolute bottom-0 left-0"><div class="dn checked-reveal"><div class="aspect-ratio aspect-ratio--4x3"><img src="https://static.learnkube.com/e889ef53f44dd44beaf693dccef3fe96.svg" alt="The kubelet delegates destroying the Pod to the Container Runtime Interface, Container Network Interface and Container Storage Interface.The kubelet delegates destroying the Pod to the Container Runtime Interface, Container Network Interface and Container Storage Interface." class="aspect-ratio--object" loading="lazy"></div><div class="bt b-solid bw2 b--black-70 relative mt0"><div class="bg-black-10 br1 pa1 dib mt2 absolute bottom-1 left-0 z-999"><span class="b black-60">3</span><span class="f7 black-50">/3</span></div></div><div class="flex items-start justify-between bg-evian ph2"><label class="db f6 b black-50 pv3 pointer w-20 ttu" for="carousel-7-1"><svg viewBox="0 0 10 16" xmlns="http://www.w3.org/2000/svg" class="pagination-icon mr2"><polyline fill="none" vector-effect="non-scaling-stroke" points="8,2 2,8 8,14"></polyline></svg> Previous</label><div class="f5 lh-copy black-90 w-60 center"><p class="lh-copy measure-wide f5"></p><p class="lh-copy measure-wide f4">The kubelet delegates destroying the Pod to the Container Runtime Interface, Container Network Interface and Container Storage Interface.</p><p></p></div><div class="w-20"></div></div></div></li></ul></div><p class="lh-copy measure-wide f4">However, there is a subtle but essential difference.</p><p class="lh-copy measure-wide f4"><strong class="b">When you terminate a Pod, removing the endpoint and the signal to the kubelet are issued simultaneously.</strong></p><p class="lh-copy measure-wide f4">When you create a Pod for the first time, Kubernetes waits for the kubelet to report the IP address and then kicks off the endpoint propagation.</p><p class="lh-copy measure-wide f4"><strong class="b">However, when you delete a Pod, the events start in parallel.</strong></p><p class="lh-copy measure-wide f4">And this could cause quite a few race conditions.</p><p class="lh-copy measure-wide f4"><em class="i">What if the Pod is deleted before the endpoint is propagated?</em></p><div class="relative overflow-hidden"><ul class="pl0 list"><li class="mv3"><input type="radio" name="carousel-8" id="carousel-8-0" checked class="o-0 absolute bottom-0 left-0"><div class="dn checked-reveal"><div class="aspect-ratio aspect-ratio--4x3"><img src="https://static.learnkube.com/e17a49eb08f03f2c2ff02b91409314fb.svg" alt="Deleting the endpoint and deleting the Pod happen simultaneously.Deleting the endpoint and deleting the Pod happen simultaneously." class="aspect-ratio--object" loading="lazy"></div><div class="bt b-solid bw2 b--black-70 relative mt0"><div class="bg-black-10 br1 pa1 dib mt2 absolute bottom-1 left-0 z-999"><span class="b black-60">1</span><span class="f7 black-50">/3</span></div></div><div class="flex items-start justify-between bg-evian ph2"><div class="w-20"></div><div class="f5 lh-copy black-90 w-60 center"><p class="lh-copy measure-wide f5"></p><p class="lh-copy measure-wide f4">Deleting the endpoint and deleting the Pod happen simultaneously.</p><p></p></div><label class="db f6 b black-50 pv3 pointer w-20 tr ttu" for="carousel-8-1">Next <svg viewBox="0 0 10 16" xmlns="http://www.w3.org/2000/svg" class="pagination-icon ml2"><polyline fill="none" vector-effect="non-scaling-stroke" points="2,2 8,8 2,14"></polyline></svg></label></div></div></li><li class="mv3"><input type="radio" name="carousel-8" id="carousel-8-1" class="o-0 absolute bottom-0 left-0"><div class="dn checked-reveal"><div class="aspect-ratio aspect-ratio--4x3"><img src="https://static.learnkube.com/977b9cae783055d138b472476c0de4d9.svg" alt="So you could end up deleting the endpoint before kube-proxy updates the iptables rules.So you could end up deleting the endpoint before kube-proxy updates the iptables rules." class="aspect-ratio--object" loading="lazy"></div><div class="bt b-solid bw2 b--black-70 relative mt0"><div class="bg-black-10 br1 pa1 dib mt2 absolute bottom-1 left-0 z-999"><span class="b black-60">2</span><span class="f7 black-50">/3</span></div></div><div class="flex items-start justify-between bg-evian ph2"><label class="db f6 b black-50 pv3 pointer w-20 ttu" for="carousel-8-0"><svg viewBox="0 0 10 16" xmlns="http://www.w3.org/2000/svg" class="pagination-icon mr2"><polyline fill="none" vector-effect="non-scaling-stroke" points="8,2 2,8 8,14"></polyline></svg> Previous</label><div class="f5 lh-copy black-90 w-60 center"><p class="lh-copy measure-wide f5"></p><p class="lh-copy measure-wide f4">So you could end up deleting the endpoint before kube-proxy updates the iptables rules.</p><p></p></div><label class="db f6 b black-50 pv3 pointer w-20 tr ttu" for="carousel-8-2">Next <svg viewBox="0 0 10 16" xmlns="http://www.w3.org/2000/svg" class="pagination-icon ml2"><polyline fill="none" vector-effect="non-scaling-stroke" points="2,2 8,8 2,14"></polyline></svg></label></div></div></li><li class="mv3"><input type="radio" name="carousel-8" id="carousel-8-2" class="o-0 absolute bottom-0 left-0"><div class="dn checked-reveal"><div class="aspect-ratio aspect-ratio--4x3"><img src="https://static.learnkube.com/c7763399ecf8ca4b7729f1458cada373.svg" alt="Or you might be luckier, and the Pod is deleted only after the endpoints are fully propagated.Or you might be luckier, and the Pod is deleted only after the endpoints are fully propagated." class="aspect-ratio--object" loading="lazy"></div><div class="bt b-solid bw2 b--black-70 relative mt0"><div class="bg-black-10 br1 pa1 dib mt2 absolute bottom-1 left-0 z-999"><span class="b black-60">3</span><span class="f7 black-50">/3</span></div></div><div class="flex items-start justify-between bg-evian ph2"><label class="db f6 b black-50 pv3 pointer w-20 ttu" for="carousel-8-1"><svg viewBox="0 0 10 16" xmlns="http://www.w3.org/2000/svg" class="pagination-icon mr2"><polyline fill="none" vector-effect="non-scaling-stroke" points="8,2 2,8 8,14"></polyline></svg> Previous</label><div class="f5 lh-copy black-90 w-60 center"><p class="lh-copy measure-wide f5"></p><p class="lh-copy measure-wide f4">Or you might be luckier, and the Pod is deleted only after the endpoints are fully propagated.</p><p></p></div><div class="w-20"></div></div></div></li></ul></div><h2 class="f2 pt5 pb2 mt3" id="how-to-gracefully-shut-down-pods">How to gracefully shut down pods</h2><p class="lh-copy measure-wide f4"><strong class="b">When a Pod is terminated before the endpoint is removed from kube-proxy or the Ingress controller, you might experience downtime.</strong></p><p class="lh-copy measure-wide f4">And, if you think about it, it makes sense.</p><p class="lh-copy measure-wide f4">Kubernetes is still routing traffic to the IP address, but the Pod is no longer there.</p><p class="lh-copy measure-wide f4">The Ingress controller, kube-proxy, CoreDNS, etc., didn't have enough time to remove the IP address from their internal state.</p><p class="lh-copy measure-wide f4">Ideally, Kubernetes should wait for all cluster components to have an updated list of endpoints before deleting the pod.</p><p class="lh-copy measure-wide f4"><em class="i">But Kubernetes doesn't work like that.</em></p><p class="lh-copy measure-wide f4">Kubernetes offers robust primitives to distribute the endpoints (i.e. the Endpoint object and more advanced abstractions such as <a href="https://kubernetes.io/docs/concepts/services-networking/endpoint-slices/" target="_blank" rel="noreferrer" class="link navy underline hover-sky">Endpoint Slices</a>).</p><p class="lh-copy measure-wide f4">However, Kubernetes does not verify that the components that subscribe to endpoint changes are up-to-date with the cluster's state.</p><p class="lh-copy measure-wide f4"><em class="i">So what can you do to avoid these race conditions and make sure that the Pod is deleted after the endpoint is propagated?</em></p><p class="lh-copy measure-wide f4"><strong class="b">You should wait.</strong></p><p class="lh-copy measure-wide f4"><strong class="b">When the Pod is about to be deleted, it receives a <code class="code f5 lh-copy bg-near-white br2 pv1 ph2 fs-normal word-wrap">SIGTERM</code> signal.</strong></p><p class="lh-copy measure-wide f4">Your application can capture that signal and start shutting down.</p><p class="lh-copy measure-wide f4">Since it's unlikely that the endpoint is immediately deleted from all components in Kubernetes, you could:</p><ol><li class="lh-copy f4 mv1 measure-wide">Wait a bit longer before exiting.</li><li class="lh-copy f4 mv1 measure-wide">Still process incoming traffic, despite the <code class="code f5 lh-copy bg-near-white br2 pv1 ph2 fs-normal word-wrap">SIGTERM</code>.</li><li class="lh-copy f4 mv1 measure-wide">Finally, <a href="https://learnkube.com/kubernetes-long-lived-connections" target="_blank" rel="noreferrer" class="link navy underline hover-sky">close existing long-lived connections</a> (perhaps a database connection or WebSockets).</li><li class="lh-copy f4 mv1 measure-wide">Terminate the process.</li></ol><p class="lh-copy measure-wide f4">Let's have a look at a few examples:</p><div class="mv4 mv5-l relative"><input type="radio" class="o-0 absolute top-0 right-0" id="group-sigterm-go" name="tab-sigterm" checked><input type="radio" class="o-0 absolute top-0 right-0" id="group-sigterm-python" name="tab-sigterm"><input type="radio" class="o-0 absolute top-0 right-0" id="group-sigterm-node-js" name="tab-sigterm"><input type="radio" class="o-0 absolute top-0 right-0" id="group-sigterm-java" name="tab-sigterm"><input type="radio" class="o-0 absolute top-0 right-0" id="group-sigterm-c-" name="tab-sigterm"><nav class="pb2"><ul class="list pl0 mv0"><label for="group-sigterm-go" class="tab-sigterm-go o-30 ph2 pv1 bg-evian ba br2 b--light-gray dib navy mr2 b f6">Go</label><label for="group-sigterm-python" class="tab-sigterm-python o-30 ph2 pv1 bg-evian ba br2 b--light-gray dib navy mr2 b f6">Python</label><label for="group-sigterm-node-js" class="tab-sigterm-node-js o-30 ph2 pv1 bg-evian ba br2 b--light-gray dib navy mr2 b f6">Node.js</label><label for="group-sigterm-java" class="tab-sigterm-java o-30 ph2 pv1 bg-evian ba br2 b--light-gray dib navy mr2 b f6">Java</label><label for="group-sigterm-c-" class="tab-sigterm-c- o-30 ph2 pv1 bg-evian ba br2 b--light-gray dib navy mr2 b f6">C#</label></ul></nav><section class=""><ul class="list pl0 mv0"><li class="tab-sigterm-go"><header class="bg-light-gray flex pv2 pl1 br--top br2 relative"><div class="w1 h1 ml1 br-100 bg-dark-red"></div><div class="w1 h1 ml1 br-100 bg-green"></div><div class="w1 h1 ml1 br-100 bg-yellow"></div></header><pre class="code-light-theme relative overflow-auto mv0 br2 br--bottom"><code class="code lh-copy"><span class="standard"><span class="token keyword">package</span> main
|
|
|
|
<span class="token keyword">import</span> <span class="token punctuation">(</span>
|
|
<span class="token string">"fmt"</span>
|
|
<span class="token string">"os"</span>
|
|
<span class="token string">"os/signal"</span>
|
|
<span class="token string">"syscall"</span>
|
|
<span class="token punctuation">)</span>
|
|
|
|
<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
|
|
|
|
sigs <span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">chan</span> os<span class="token punctuation">.</span>Signal<span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span>
|
|
done <span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">chan</span> <span class="token builtin">bool</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span>
|
|
<span class="token comment">//registers the channel</span>
|
|
signal<span class="token punctuation">.</span><span class="token function">Notify</span><span class="token punctuation">(</span>sigs<span class="token punctuation">,</span> syscall<span class="token punctuation">.</span>SIGTERM<span class="token punctuation">)</span>
|
|
|
|
<span class="token keyword">go</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
|
|
sig <span class="token operator">:=</span> <span class="token operator"><-</span>sigs
|
|
fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"Caught SIGTERM, shutting down"</span><span class="token punctuation">)</span>
|
|
<span class="token comment">// Finish any outstanding requests, then...</span>
|
|
done <span class="token operator"><-</span> <span class="token boolean">true</span>
|
|
<span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
|
|
|
|
fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"Starting application"</span><span class="token punctuation">)</span>
|
|
<span class="token comment">// Main logic goes here</span>
|
|
<span class="token operator"><-</span>done
|
|
fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"exiting"</span><span class="token punctuation">)</span>
|
|
<span class="token punctuation">}</span></span></code></pre></li><li class="tab-sigterm-python"><header class="bg-light-gray flex pv2 pl1 br--top br2 relative"><div class="w1 h1 ml1 br-100 bg-dark-red"></div><div class="w1 h1 ml1 br-100 bg-green"></div><div class="w1 h1 ml1 br-100 bg-yellow"></div></header><pre class="code-light-theme relative overflow-auto mv0 br2 br--bottom"><code class="code lh-copy"><span class="standard"><span class="token keyword">import</span> signal<span class="token punctuation">,</span> time<span class="token punctuation">,</span> os
|
|
|
|
<span class="token keyword">def</span> <span class="token function">shutdown</span><span class="token punctuation">(</span>signum<span class="token punctuation">,</span> frame<span class="token punctuation">)</span><span class="token punctuation">:</span>
|
|
<span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">'Caught SIGTERM, shutting down'</span><span class="token punctuation">)</span>
|
|
<span class="token comment"># Finish any outstanding requests, then...</span>
|
|
exit<span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span>
|
|
|
|
<span class="token keyword">if</span> __name__ <span class="token operator">==</span> <span class="token string">'__main__'</span><span class="token punctuation">:</span>
|
|
<span class="token comment"># Register handler</span>
|
|
signal<span class="token punctuation">.</span>signal<span class="token punctuation">(</span>signal<span class="token punctuation">.</span>SIGTERM<span class="token punctuation">,</span> shutdown<span class="token punctuation">)</span>
|
|
<span class="token comment"># Main logic goes here</span></span></code></pre></li><li class="tab-sigterm-node-js"><header class="bg-light-gray flex pv2 pl1 br--top br2 relative"><div class="w1 h1 ml1 br-100 bg-dark-red"></div><div class="w1 h1 ml1 br-100 bg-green"></div><div class="w1 h1 ml1 br-100 bg-yellow"></div></header><pre class="code-light-theme relative overflow-auto mv0 br2 br--bottom"><code class="code lh-copy"><span class="standard"><span class="token keyword">const</span> express <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'express'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
|
|
|
|
<span class="token keyword">const</span> app <span class="token operator">=</span> <span class="token function">express</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
|
|
|
|
app<span class="token punctuation">.</span><span class="token function">listen</span><span class="token punctuation">(</span><span class="token number">3000</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Server is up using port 3000'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
|
|
|
|
process<span class="token punctuation">.</span><span class="token function">on</span><span class="token punctuation">(</span><span class="token string">'SIGTERM'</span><span class="token punctuation">,</span> <span class="token keyword">async</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
|
|
<span class="token keyword">await</span> <span class="token function">wait</span><span class="token punctuation">(</span><span class="token number">15</span> <span class="token operator">*</span> <span class="token number">1000</span><span class="token punctuation">)</span>
|
|
app<span class="token punctuation">.</span><span class="token function">close</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// terminating the server</span>
|
|
db<span class="token punctuation">.</span><span class="token function">close</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// closing any other connection</span>
|
|
process<span class="token punctuation">.</span><span class="token function">exit</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span>
|
|
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span></code></pre></li><li class="tab-sigterm-java"><header class="bg-light-gray flex pv2 pl1 br--top br2 relative"><div class="w1 h1 ml1 br-100 bg-dark-red"></div><div class="w1 h1 ml1 br-100 bg-green"></div><div class="w1 h1 ml1 br-100 bg-yellow"></div></header><pre class="code-light-theme relative overflow-auto mv0 br2 br--bottom"><code class="code lh-copy"><span class="standard"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">App</span> <span class="token punctuation">{</span>
|
|
|
|
<span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token parameter">String<span class="token punctuation">[</span><span class="token punctuation">]</span> args</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
|
|
|
|
<span class="token keyword">var</span> shutdownListener <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Thread</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
|
|
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">run</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
|
|
<span class="token comment">// Main logic goes here</span>
|
|
<span class="token punctuation">}</span>
|
|
<span class="token punctuation">}</span><span class="token punctuation">;</span>
|
|
Runtime<span class="token punctuation">.</span><span class="token function">getRuntime</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">addShutdownHook</span><span class="token punctuation">(</span>shutdownListener<span class="token punctuation">)</span><span class="token punctuation">;</span>
|
|
<span class="token punctuation">}</span>
|
|
<span class="token punctuation">}</span></span></code></pre></li><li class="tab-sigterm-c-"><header class="bg-light-gray flex pv2 pl1 br--top br2 relative"><div class="w1 h1 ml1 br-100 bg-dark-red"></div><div class="w1 h1 ml1 br-100 bg-green"></div><div class="w1 h1 ml1 br-100 bg-yellow"></div></header><pre class="code-light-theme relative overflow-auto mv0 br2 br--bottom"><code class="code lh-copy"><span class="standard">internal <span class="token keyword">class</span> <span class="token class-name">LifetimeEventsHostedService</span><span class="token operator">:</span> <span class="token class-name">IHostedService</span> <span class="token punctuation">{</span>
|
|
<span class="token keyword">private</span> readonly <span class="token class-name">IHostApplicationLifetime</span> _appLifetime<span class="token punctuation">;</span>
|
|
|
|
<span class="token keyword">public</span> <span class="token class-name">LifetimeEventsHostedService</span><span class="token punctuation">(</span>
|
|
<span class="token class-name">ILogger</span> <span class="token generics"><span class="token punctuation"><</span> <span class="token class-name">LifetimeEventsHostedService</span> <span class="token punctuation">></span></span> logger<span class="token punctuation">,</span>
|
|
<span class="token class-name">IHostApplicationLifetime</span> appLifetime<span class="token punctuation">,</span>
|
|
<span class="token class-name">TelemetryClient</span> telemtryClient<span class="token punctuation">)</span> <span class="token punctuation">{</span>
|
|
_appLifetime <span class="token operator">=</span> appLifetime<span class="token punctuation">;</span>
|
|
<span class="token punctuation">}</span>
|
|
|
|
<span class="token keyword">public</span> <span class="token class-name">Task</span> <span class="token class-name">StartAsync</span><span class="token punctuation">(</span><span class="token class-name">CancellationToken</span> cancellationToken<span class="token punctuation">)</span> <span class="token punctuation">{</span>
|
|
_appLifetime<span class="token punctuation">.</span>ApplicationStarted<span class="token punctuation">.</span><span class="token function">Register</span><span class="token punctuation">(</span><span class="token class-name">OnStarted</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
|
|
_appLifetime<span class="token punctuation">.</span>ApplicationStopping<span class="token punctuation">.</span><span class="token function">Register</span><span class="token punctuation">(</span><span class="token class-name">OnStopping</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
|
|
_appLifetime<span class="token punctuation">.</span>ApplicationStopped<span class="token punctuation">.</span><span class="token function">Register</span><span class="token punctuation">(</span><span class="token class-name">OnStopped</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
|
|
|
|
<span class="token keyword">return</span> <span class="token class-name">Task<span class="token punctuation">.</span>CompletedTask</span><span class="token punctuation">;</span>
|
|
<span class="token punctuation">}</span>
|
|
|
|
<span class="token keyword">public</span> <span class="token class-name">Task</span> <span class="token class-name">StopAsync</span><span class="token punctuation">(</span><span class="token class-name">CancellationToken</span> cancellationToken<span class="token punctuation">)</span> <span class="token punctuation">{</span>
|
|
<span class="token keyword">return</span> <span class="token class-name">Task<span class="token punctuation">.</span>CompletedTask</span><span class="token punctuation">;</span>
|
|
<span class="token punctuation">}</span>
|
|
|
|
<span class="token keyword">private</span> <span class="token keyword">void</span> <span class="token class-name">OnStarted</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
|
|
|
|
<span class="token keyword">private</span> <span class="token keyword">void</span> <span class="token class-name">OnStopping</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
|
|
<span class="token comment">// Main logic here</span>
|
|
<span class="token punctuation">}</span>
|
|
|
|
<span class="token keyword">private</span> <span class="token keyword">void</span> <span class="token class-name">OnStopped</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
|
|
<span class="token punctuation">}</span></span></code></pre></li></ul></section></div><p class="lh-copy measure-wide f4"><em class="i">How long should you wait?</em></p><p class="lh-copy measure-wide f4"><strong class="b">By default, Kubernetes will send the <code class="code f5 lh-copy bg-near-white br2 pv1 ph2 fs-normal word-wrap">SIGTERM</code> signal and wait 30 seconds before force-killing the process.</strong></p><p class="lh-copy measure-wide f4">You could use the first 15 seconds to continue operating as if nothing happened.</p><p class="lh-copy measure-wide f4">The interval should be enough to propagate the endpoint removal to kube-proxy, Ingress controller, CoreDNS, etc.</p><p class="lh-copy measure-wide f4">Consequently, less and less traffic will reach your Pod until it stops.</p><p class="lh-copy measure-wide f4">After 15 seconds, there will be no traffic, and it's safe to close your connection with the database (or any persistent connections) and terminate the process.</p><p class="lh-copy measure-wide f4">If any component in your cluster hasn't disposed of the endpoints within 15 seconds, you should increase the delay (perhaps to 20 or 25 seconds).</p><p class="lh-copy measure-wide f4">However, you should remember that Kubernetes will forcefully kill the process after 30 seconds <a href="https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#hook-handler-execution" target="_blank" rel="noreferrer" class="link navy underline hover-sky">(unless you change the <code class="code f5 lh-copy bg-near-white br2 pv1 ph2 fs-normal word-wrap">terminationGracePeriodSeconds</code> in your Pod definition).</a></p><p class="lh-copy measure-wide f4"><em class="i">What if you can't change the code to listen for a <code class="code f5 lh-copy bg-near-white br2 pv1 ph2 fs-normal word-wrap">SIGTERM</code> and wait longer?</em></p><p class="lh-copy measure-wide f4">You could invoke a script to wait for a fixed amount of time and then let the app exit.</p><h2 class="f2 pt5 pb2 mt3" id="graceful-shutdown-with-a-prestop-hook">Graceful shutdown with a preStop hook</h2><p class="lh-copy measure-wide f4">Before the <code class="code f5 lh-copy bg-near-white br2 pv1 ph2 fs-normal word-wrap">SIGTERM</code> is invoked, Kubernetes exposes a <code class="code f5 lh-copy bg-near-white br2 pv1 ph2 fs-normal word-wrap">preStop</code> hook in the Pod.</p><p class="lh-copy measure-wide f4">You could set the <code class="code f5 lh-copy bg-near-white br2 pv1 ph2 fs-normal word-wrap">preStop</code> to hook to wait for 15 seconds.</p><p class="lh-copy measure-wide f4">Let's have a look at an example:</p><div class="mv4 mv5-l"><header class="bg-light-gray flex pv2 pl1 br--top br2 relative"><div class="w1 h1 ml1 br-100 bg-dark-red"></div><div class="w1 h1 ml1 br-100 bg-green"></div><div class="w1 h1 ml1 br-100 bg-yellow"></div><p class="code f6 mv0 black-60 w-100 tc absolute top-0 left-0 h1 pv2">pod.yaml</p></header><pre class="code-light-theme relative overflow-auto mv0 br2 br--bottom"><code class="code lh-copy"><span class="standard"><span class="token key atrule">apiVersion</span><span class="token punctuation">:</span> v1
|
|
<span class="token key atrule">kind</span><span class="token punctuation">:</span> Pod
|
|
<span class="token key atrule">metadata</span><span class="token punctuation">:</span>
|
|
<span class="token key atrule">name</span><span class="token punctuation">:</span> my<span class="token punctuation">-</span>pod
|
|
<span class="token key atrule">spec</span><span class="token punctuation">:</span>
|
|
<span class="token key atrule">containers</span><span class="token punctuation">:</span>
|
|
<span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> web
|
|
<span class="token key atrule">image</span><span class="token punctuation">:</span> nginx
|
|
<span class="token key atrule">ports</span><span class="token punctuation">:</span>
|
|
<span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> web
|
|
<span class="token key atrule">containerPort</span><span class="token punctuation">:</span> <span class="token number">80</span>
|
|
</span><span class="highlight"> <span class="token key atrule">lifecycle</span><span class="token punctuation">:</span>
|
|
<span class="token key atrule">preStop</span><span class="token punctuation">:</span>
|
|
<span class="token key atrule">exec</span><span class="token punctuation">:</span>
|
|
<span class="token key atrule">command</span><span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token string">"sleep"</span><span class="token punctuation">,</span> <span class="token string">"15"</span><span class="token punctuation">]</span></span></code></pre></div><p class="lh-copy measure-wide f4">The <code class="code f5 lh-copy bg-near-white br2 pv1 ph2 fs-normal word-wrap">preStop</code> hook is one of the <a href="https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/" target="_blank" rel="noreferrer" class="link navy underline hover-sky">Pod LifeCycle hooks</a>.</p><p class="lh-copy measure-wide f4"><strong class="b">It's important to notice that using the preStop hook and waiting for 15 seconds in the app are different.</strong></p><p class="lh-copy measure-wide f4">The preStop hook is invoked before the <code class="code f5 lh-copy bg-near-white br2 pv1 ph2 fs-normal word-wrap">SIGTERM</code> is dispatched to the app.</p><p class="lh-copy measure-wide f4">So, while the preStop is running, the app isn't aware that it is about to shut down.</p><p class="lh-copy measure-wide f4"><em class="i">But there's more.</em></p><p class="lh-copy measure-wide f4">The delay in the preStop hook is part of the <code class="code f5 lh-copy bg-near-white br2 pv1 ph2 fs-normal word-wrap">terminationGracePeriodSeconds</code> 30-second budget.</p><p class="lh-copy measure-wide f4">If you preStop hook waits for 25 seconds, as soon as it completes:</p><ul><li class="lh-copy f4 mv1 measure-wide">The container receives the <code class="code f5 lh-copy bg-near-white br2 pv1 ph2 fs-normal word-wrap">SIGTERM</code>.</li><li class="lh-copy f4 mv1 measure-wide">It has 5 seconds to terminate, or the kubelet will issue a <code class="code f5 lh-copy bg-near-white br2 pv1 ph2 fs-normal word-wrap">SIGKILL</code>.</li></ul><p class="lh-copy measure-wide f4"><em class="i">What happens when the preStop hook waits for longer than <code class="code f5 lh-copy bg-near-white br2 pv1 ph2 fs-normal word-wrap">terminationGracePeriodSeconds</code> 30 seconds?</em></p><p class="lh-copy measure-wide f4">The kubelet will send the <code class="code f5 lh-copy bg-near-white br2 pv1 ph2 fs-normal word-wrap">SIGKILL</code> signal and forcefully terminate the container — no <code class="code f5 lh-copy bg-near-white br2 pv1 ph2 fs-normal word-wrap">SIGTERM</code> signal is dispatched.</p><p class="lh-copy measure-wide f4">If you need a longer delay, consider adjusting the <code class="code f5 lh-copy bg-near-white br2 pv1 ph2 fs-normal word-wrap">terminationGracePeriodSeconds</code> to account for that.</p><div class="relative overflow-hidden"><ul class="pl0 list"><li class="mv3"><input type="radio" name="carousel-9" id="carousel-9-0" checked class="o-0 absolute bottom-0 left-0"><div class="dn checked-reveal"><div class="aspect-ratio aspect-ratio--4x3"><img src="https://static.learnkube.com/bdaa1da0be0fa3e9fe022cbf2b22bd1d.svg" alt="You already know that when a Pod is deleted, the kubelet is notified of the change.You already know that when a Pod is deleted, the kubelet is notified of the change." class="aspect-ratio--object" loading="lazy"></div><div class="bt b-solid bw2 b--black-70 relative mt0"><div class="bg-black-10 br1 pa1 dib mt2 absolute bottom-1 left-0 z-999"><span class="b black-60">1</span><span class="f7 black-50">/5</span></div></div><div class="flex items-start justify-between bg-evian ph2"><div class="w-20"></div><div class="f5 lh-copy black-90 w-60 center"><p class="lh-copy measure-wide f5"></p><p class="lh-copy measure-wide f4">You already know that when a Pod is deleted, the kubelet is notified of the change.</p><p></p></div><label class="db f6 b black-50 pv3 pointer w-20 tr ttu" for="carousel-9-1">Next <svg viewBox="0 0 10 16" xmlns="http://www.w3.org/2000/svg" class="pagination-icon ml2"><polyline fill="none" vector-effect="non-scaling-stroke" points="2,2 8,8 2,14"></polyline></svg></label></div></div></li><li class="mv3"><input type="radio" name="carousel-9" id="carousel-9-1" class="o-0 absolute bottom-0 left-0"><div class="dn checked-reveal"><div class="aspect-ratio aspect-ratio--4x3"><img src="https://static.learnkube.com/d325b21c6a561f631b53a1792e780d89.svg" alt="If the Pod has a `preStop` hook, it is invoked first.If the Pod has a preStop hook, it is invoked first." class="aspect-ratio--object" loading="lazy"></div><div class="bt b-solid bw2 b--black-70 relative mt0"><div class="bg-black-10 br1 pa1 dib mt2 absolute bottom-1 left-0 z-999"><span class="b black-60">2</span><span class="f7 black-50">/5</span></div></div><div class="flex items-start justify-between bg-evian ph2"><label class="db f6 b black-50 pv3 pointer w-20 ttu" for="carousel-9-0"><svg viewBox="0 0 10 16" xmlns="http://www.w3.org/2000/svg" class="pagination-icon mr2"><polyline fill="none" vector-effect="non-scaling-stroke" points="8,2 2,8 8,14"></polyline></svg> Previous</label><div class="f5 lh-copy black-90 w-60 center"><p class="lh-copy measure-wide f5"></p><p class="lh-copy measure-wide f4">If the Pod has a <code class="code f5 lh-copy bg-near-white br2 pv1 ph2 fs-normal word-wrap">preStop</code> hook, it is invoked first.</p><p></p></div><label class="db f6 b black-50 pv3 pointer w-20 tr ttu" for="carousel-9-2">Next <svg viewBox="0 0 10 16" xmlns="http://www.w3.org/2000/svg" class="pagination-icon ml2"><polyline fill="none" vector-effect="non-scaling-stroke" points="2,2 8,8 2,14"></polyline></svg></label></div></div></li><li class="mv3"><input type="radio" name="carousel-9" id="carousel-9-2" class="o-0 absolute bottom-0 left-0"><div class="dn checked-reveal"><div class="aspect-ratio aspect-ratio--4x3"><img src="https://static.learnkube.com/b444d2f8c8438f6c71b6c3cfb91b136e.svg" alt="When the `preStop` completes, the kubelet sends the `SIGTERM` signal to the container. From that point, the container should close all long-lived connections and prepare to terminate.When the preStop completes, the kubelet sends the SIGTERM signal to the container. From that point, the container should close all long-lived connections and prepare to terminate." class="aspect-ratio--object" loading="lazy"></div><div class="bt b-solid bw2 b--black-70 relative mt0"><div class="bg-black-10 br1 pa1 dib mt2 absolute bottom-1 left-0 z-999"><span class="b black-60">3</span><span class="f7 black-50">/5</span></div></div><div class="flex items-start justify-between bg-evian ph2"><label class="db f6 b black-50 pv3 pointer w-20 ttu" for="carousel-9-1"><svg viewBox="0 0 10 16" xmlns="http://www.w3.org/2000/svg" class="pagination-icon mr2"><polyline fill="none" vector-effect="non-scaling-stroke" points="8,2 2,8 8,14"></polyline></svg> Previous</label><div class="f5 lh-copy black-90 w-60 center"><p class="lh-copy measure-wide f5"></p><p class="lh-copy measure-wide f4">When the <code class="code f5 lh-copy bg-near-white br2 pv1 ph2 fs-normal word-wrap">preStop</code> completes, the kubelet sends the <code class="code f5 lh-copy bg-near-white br2 pv1 ph2 fs-normal word-wrap">SIGTERM</code> signal to the container. From that point, the container should close all long-lived connections and prepare to terminate.</p><p></p></div><label class="db f6 b black-50 pv3 pointer w-20 tr ttu" for="carousel-9-3">Next <svg viewBox="0 0 10 16" xmlns="http://www.w3.org/2000/svg" class="pagination-icon ml2"><polyline fill="none" vector-effect="non-scaling-stroke" points="2,2 8,8 2,14"></polyline></svg></label></div></div></li><li class="mv3"><input type="radio" name="carousel-9" id="carousel-9-3" class="o-0 absolute bottom-0 left-0"><div class="dn checked-reveal"><div class="aspect-ratio aspect-ratio--4x3"><img src="https://static.learnkube.com/b7a0400e6ebdb90e90b8cdf70c40a068.svg" alt="By default, the process has 30 seconds to exit, including the `preStop` hook. If the process isn't exited by then, the kubelet sends the SIGKILL signal and forces the process to be killed.By default, the process has 30 seconds to exit, including the preStop hook. If the process isn't exited by then, the kubelet sends the SIGKILL signal and forces the process to be killed." class="aspect-ratio--object" loading="lazy"></div><div class="bt b-solid bw2 b--black-70 relative mt0"><div class="bg-black-10 br1 pa1 dib mt2 absolute bottom-1 left-0 z-999"><span class="b black-60">4</span><span class="f7 black-50">/5</span></div></div><div class="flex items-start justify-between bg-evian ph2"><label class="db f6 b black-50 pv3 pointer w-20 ttu" for="carousel-9-2"><svg viewBox="0 0 10 16" xmlns="http://www.w3.org/2000/svg" class="pagination-icon mr2"><polyline fill="none" vector-effect="non-scaling-stroke" points="8,2 2,8 8,14"></polyline></svg> Previous</label><div class="f5 lh-copy black-90 w-60 center"><p class="lh-copy measure-wide f5"></p><p class="lh-copy measure-wide f4">By default, the process has 30 seconds to exit, including the <code class="code f5 lh-copy bg-near-white br2 pv1 ph2 fs-normal word-wrap">preStop</code> hook. If the process isn't exited by then, the kubelet sends the SIGKILL signal and forces the process to be killed.</p><p></p></div><label class="db f6 b black-50 pv3 pointer w-20 tr ttu" for="carousel-9-4">Next <svg viewBox="0 0 10 16" xmlns="http://www.w3.org/2000/svg" class="pagination-icon ml2"><polyline fill="none" vector-effect="non-scaling-stroke" points="2,2 8,8 2,14"></polyline></svg></label></div></div></li><li class="mv3"><input type="radio" name="carousel-9" id="carousel-9-4" class="o-0 absolute bottom-0 left-0"><div class="dn checked-reveal"><div class="aspect-ratio aspect-ratio--4x3"><img src="https://static.learnkube.com/6bef723861132f2b7b463ba65404b508.svg" alt="The kubelet notifies the control plane that the Pod was deleted successfully.The kubelet notifies the control plane that the Pod was deleted successfully." class="aspect-ratio--object" loading="lazy"></div><div class="bt b-solid bw2 b--black-70 relative mt0"><div class="bg-black-10 br1 pa1 dib mt2 absolute bottom-1 left-0 z-999"><span class="b black-60">5</span><span class="f7 black-50">/5</span></div></div><div class="flex items-start justify-between bg-evian ph2"><label class="db f6 b black-50 pv3 pointer w-20 ttu" for="carousel-9-3"><svg viewBox="0 0 10 16" xmlns="http://www.w3.org/2000/svg" class="pagination-icon mr2"><polyline fill="none" vector-effect="non-scaling-stroke" points="8,2 2,8 8,14"></polyline></svg> Previous</label><div class="f5 lh-copy black-90 w-60 center"><p class="lh-copy measure-wide f5"></p><p class="lh-copy measure-wide f4">The kubelet notifies the control plane that the Pod was deleted successfully.</p><p></p></div><div class="w-20"></div></div></div></li></ul></div><p class="lh-copy measure-wide f4"><em class="i">So, what is the advice on the preHook or app delay? 15, 60, 120 seconds?</em></p><p class="lh-copy measure-wide f4">It depends.</p><p class="lh-copy measure-wide f4">If you are handling graceful shutdown in spot instances, your budget will likely be constrained to 60 seconds or less.</p><p class="lh-copy measure-wide f4">If your app has to flush logs or metrics before shutting down, you might need a longer interval.</p><p class="lh-copy measure-wide f4">In general, you want to keep your waiting time restricted to 30 seconds, as longer intervals have implications for resource utilization in the cluster.</p><p class="lh-copy measure-wide f4">Let's look at an example to illustrate the scenario.</p><h2 class="f2 pt5 pb2 mt3" id="long-graceful-shutdowns-and-cluster-autoscaling">Long graceful shutdowns and cluster autoscaling</h2><p class="lh-copy measure-wide f4">Graceful shutdown applies to Pods being deleted.</p><p class="lh-copy measure-wide f4"><em class="i">But what if you don't delete the Pods?</em></p><p class="lh-copy measure-wide f4"><strong class="b">Even if you don't, Kubernetes deletes Pods all the time.</strong></p><p class="lh-copy measure-wide f4">In particular, Kubernetes creates and deletes Pods every time you deploy a newer version of your application.</p><p class="lh-copy measure-wide f4">When you change the image in your Deployment, Kubernetes rolls out the change incrementally.</p><div class="mv4 mv5-l"><header class="bg-light-gray flex pv2 pl1 br--top br2 relative"><div class="w1 h1 ml1 br-100 bg-dark-red"></div><div class="w1 h1 ml1 br-100 bg-green"></div><div class="w1 h1 ml1 br-100 bg-yellow"></div><p class="code f6 mv0 black-60 w-100 tc absolute top-0 left-0 h1 pv2">pod.yaml</p></header><pre class="code-light-theme relative overflow-auto mv0 br2 br--bottom"><code class="code lh-copy"><span class="standard"><span class="token key atrule">apiVersion</span><span class="token punctuation">:</span> apps/v1
|
|
<span class="token key atrule">kind</span><span class="token punctuation">:</span> Deployment
|
|
<span class="token key atrule">metadata</span><span class="token punctuation">:</span>
|
|
<span class="token key atrule">name</span><span class="token punctuation">:</span> app
|
|
<span class="token key atrule">spec</span><span class="token punctuation">:</span>
|
|
<span class="token key atrule">replicas</span><span class="token punctuation">:</span> <span class="token number">3</span>
|
|
<span class="token key atrule">selector</span><span class="token punctuation">:</span>
|
|
<span class="token key atrule">matchLabels</span><span class="token punctuation">:</span>
|
|
<span class="token key atrule">name</span><span class="token punctuation">:</span> app
|
|
<span class="token key atrule">template</span><span class="token punctuation">:</span>
|
|
<span class="token key atrule">metadata</span><span class="token punctuation">:</span>
|
|
<span class="token key atrule">labels</span><span class="token punctuation">:</span>
|
|
<span class="token key atrule">name</span><span class="token punctuation">:</span> app
|
|
<span class="token key atrule">spec</span><span class="token punctuation">:</span>
|
|
<span class="token key atrule">containers</span><span class="token punctuation">:</span>
|
|
<span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> app
|
|
</span><span class="highlight"> <span class="token comment"># image: nginx:1.18 OLD</span>
|
|
<span class="token key atrule">image</span><span class="token punctuation">:</span> nginx<span class="token punctuation">:</span><span class="token number">1.19</span>
|
|
</span><span class="standard"> <span class="token key atrule">ports</span><span class="token punctuation">:</span>
|
|
<span class="token punctuation">-</span> <span class="token key atrule">containerPort</span><span class="token punctuation">:</span> <span class="token number">3000</span>
|
|
<span class="token key atrule">lifecycle</span><span class="token punctuation">:</span>
|
|
<span class="token key atrule">preStop</span><span class="token punctuation">:</span>
|
|
<span class="token key atrule">exec</span><span class="token punctuation">:</span>
|
|
<span class="token key atrule">command</span><span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token string">"sleep"</span><span class="token punctuation">,</span> <span class="token string">"15"</span><span class="token punctuation">]</span></span></code></pre></div><p class="lh-copy measure-wide f4">If you have three replicas and as soon as you submit the new YAML resources, Kubernetes:</p><ul><li class="lh-copy f4 mv1 measure-wide">Creates a Pod with the new container image.</li><li class="lh-copy f4 mv1 measure-wide">Destroys an existing Pod.</li><li class="lh-copy f4 mv1 measure-wide">Waits for the Pod to be ready (i.e. a passing Readiness probe).</li></ul><p class="lh-copy measure-wide f4">It repeats the steps above until all the Pods are migrated to the newer version.</p><p class="lh-copy measure-wide f4">Kubernetes repeats each cycle only after the new Pod is ready to receive traffic (in other words, it passes the Readiness check).</p><p class="lh-copy measure-wide f4"><em class="i">Does Kubernetes wait for the Pod to be deleted before moving to the next one?</em></p><p class="lh-copy measure-wide f4"><strong class="b">No.</strong></p><p class="lh-copy measure-wide f4">If you have 10 Pods and the Pod takes 2 seconds to be ready and 20 to shut down, this is what happens:</p><ol><li class="lh-copy f4 mv1 measure-wide">The first Pod is created, and a previous Pod is terminated.</li><li class="lh-copy f4 mv1 measure-wide">The new Pod takes 2 seconds to be ready. After that, Kubernetes creates a new one.</li><li class="lh-copy f4 mv1 measure-wide">In the meantime, the Pod being terminated stays terminating for 20 seconds</li></ol><p class="lh-copy measure-wide f4">After 20 seconds, all new Pods are live (10 Pods, <em class="i">Ready</em> after 2 seconds), and all ten the previous Pods are terminating (the first <em class="i">Terminated</em> Pod is about to exit).</p><p class="lh-copy measure-wide f4">You have double the number of pods for a short time (10 <em class="i">Running</em>, 10 <em class="i">Terminating</em>).</p><img class="db pv3 center" src="https://static.learnkube.com/7934a67ff44a183254acf81a763e6c2f.svg" alt="Rolling update and graceful shutdown" loading="lazy"><p class="lh-copy measure-wide f4">The longer the graceful period compared to the Readiness probe, the more Pods you will simultaneously have <em class="i">Running</em> (and <em class="i">Terminating</em>).</p><p class="lh-copy measure-wide f4"><em class="i">Is it bad?</em></p><p class="lh-copy measure-wide f4">That is not necessarily the case since you're careful not to drop connections.</p><p class="lh-copy measure-wide f4">But let's repeat the experiment with a longer termination of 120 seconds and 40 replicas.</p><div class="mv4 mv5-l"><header class="bg-light-gray flex pv2 pl1 br--top br2 relative"><div class="w1 h1 ml1 br-100 bg-dark-red"></div><div class="w1 h1 ml1 br-100 bg-green"></div><div class="w1 h1 ml1 br-100 bg-yellow"></div><p class="code f6 mv0 black-60 w-100 tc absolute top-0 left-0 h1 pv2">pod.yaml</p></header><pre class="code-light-theme relative overflow-auto mv0 br2 br--bottom"><code class="code lh-copy"><span class="standard"><span class="token key atrule">apiVersion</span><span class="token punctuation">:</span> apps/v1
|
|
<span class="token key atrule">kind</span><span class="token punctuation">:</span> Deployment
|
|
<span class="token key atrule">metadata</span><span class="token punctuation">:</span>
|
|
<span class="token key atrule">name</span><span class="token punctuation">:</span> app
|
|
<span class="token key atrule">spec</span><span class="token punctuation">:</span>
|
|
<span class="token key atrule">replicas</span><span class="token punctuation">:</span> <span class="token number">40</span>
|
|
<span class="token key atrule">selector</span><span class="token punctuation">:</span>
|
|
<span class="token key atrule">matchLabels</span><span class="token punctuation">:</span>
|
|
<span class="token key atrule">name</span><span class="token punctuation">:</span> app
|
|
<span class="token key atrule">template</span><span class="token punctuation">:</span>
|
|
<span class="token key atrule">metadata</span><span class="token punctuation">:</span>
|
|
<span class="token key atrule">labels</span><span class="token punctuation">:</span>
|
|
<span class="token key atrule">name</span><span class="token punctuation">:</span> app
|
|
<span class="token key atrule">spec</span><span class="token punctuation">:</span>
|
|
<span class="token key atrule">containers</span><span class="token punctuation">:</span>
|
|
<span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> app
|
|
<span class="token comment"># image: nginx:1.18 OLD</span>
|
|
<span class="token key atrule">image</span><span class="token punctuation">:</span> nginx<span class="token punctuation">:</span><span class="token number">1.19</span>
|
|
<span class="token key atrule">ports</span><span class="token punctuation">:</span>
|
|
<span class="token punctuation">-</span> <span class="token key atrule">containerPort</span><span class="token punctuation">:</span> <span class="token number">3000</span>
|
|
</span><span class="highlight"> <span class="token key atrule">lifecycle</span><span class="token punctuation">:</span>
|
|
<span class="token key atrule">preStop</span><span class="token punctuation">:</span>
|
|
<span class="token key atrule">exec</span><span class="token punctuation">:</span>
|
|
<span class="token key atrule">command</span><span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token string">"sleep"</span><span class="token punctuation">,</span> <span class="token string">"120"</span><span class="token punctuation">]</span>
|
|
<span class="token key atrule">terminationGracePeriodSeconds</span><span class="token punctuation">:</span> <span class="token number">180</span></span></code></pre></div><p class="lh-copy measure-wide f4">In this case, Kubernetes will complete the rollout, but you will have 80 replicas running for 120 seconds: 40 Running and 40 Terminating.</p><p class="lh-copy measure-wide f4">Since this is a non-trivial amount of replicas, <a href="https://learnkube.com/kubernetes-autoscaling-strategies" target="_blank" rel="noreferrer" class="link navy underline hover-sky">it might trigger the cluster autoscaler and create new nodes.</a></p><p class="lh-copy measure-wide f4"><strong class="b">The same nodes must be removed and the cluster downscaled when the 40 Terminating pods are removed.</strong></p><p class="lh-copy measure-wide f4">If your graceful shutdown is quicker (i.e. less than 30 seconds), Terminating pods are deleted while new pods are created.</p><p class="lh-copy measure-wide f4">In other words, fewer pods are running at the same time.</p><p class="lh-copy measure-wide f4">But there's another reason to strive for a shorter, graceful shutdown, and it concerns endpoints.</p><p class="lh-copy measure-wide f4">If your app exposes a <code class="code f5 lh-copy bg-near-white br2 pv1 ph2 fs-normal word-wrap">/metrics</code> endpoint to collect metrics, the data is unlikely to be collected during the graceful shutdown.</p><p class="lh-copy measure-wide f4"><em class="i">Why?</em></p><p class="lh-copy measure-wide f4"><strong class="b">Tools such as Prometheus rely on Endpoints to scrape Pods in your cluster.</strong></p><p class="lh-copy measure-wide f4">However, as soon as you delete the Pod, the endpoint deletion is propagated throughout the cluster—even to Prometheus!</p><p class="lh-copy measure-wide f4">In other words, you should treat your graceful shutdown as an opportunity to terminate the pod as soon as possible rather than trying to extend its lifetime to complete the current task.</p><h2 class="f2 pt5 pb2 mt3" id="graceful-shutdown-for-long-lived-connections-and-long-running-tasks">Graceful shutdown for long-lived connections and long-running tasks</h2><p class="lh-copy measure-wide f4"><strong class="b">If your application serves long-lived connections such as WebSockets, you don't want to terminate it within 30 seconds.</strong></p><p class="lh-copy measure-wide f4">Instead, you might want to keep the connection running for as long as possible — ideally, until the client disconnects.</p><p class="lh-copy measure-wide f4">Similarly, if you are transcoding a large video, you don't want a rolling update to delete the current pod (and hours of work).</p><p class="lh-copy measure-wide f4"><em class="i">How can you avoid delaying shutting down the Pod?</em></p><p class="lh-copy measure-wide f4">You could increase the <code class="code f5 lh-copy bg-near-white br2 pv1 ph2 fs-normal word-wrap">terminationGracePeriodSeconds</code> to 3 hours in the hope that the connection will be drained by then or the job will be completed.</p><p class="lh-copy measure-wide f4">However, this has some drawbacks:</p><ul><li class="lh-copy f4 mv1 measure-wide">You won't be able to collect metrics if you rely on Prometheus to scrape them (i.e., the endpoint is removed).</li><li class="lh-copy f4 mv1 measure-wide">Debugging is more challenging since the Running and Terminating pods may be on different versions.</li><li class="lh-copy f4 mv1 measure-wide">The kubelet doesn't check the liveness probe (e.g. if your process gets stuck, it doesn't restart it).</li></ul><p class="lh-copy measure-wide f4"><strong class="b">Instead of increasing the grace period, you should consider creating a new Deployment for every release.</strong></p><p class="lh-copy measure-wide f4">When you create a brand new Deployment, the existing Deployment is left untouched.</p><p class="lh-copy measure-wide f4">The long-running jobs can continue processing the video as usual, and your long-lived connections will remain intact.</p><p class="lh-copy measure-wide f4">Once they are done, you can delete them manually.</p><p class="lh-copy measure-wide f4">If you wish to delete them automatically, consider setting up an autoscaler to scale your deployment to zero replicas when they run out of tasks.</p><p class="lh-copy measure-wide f4">An example of such Pod autoscaler is <a href="https://keda.sh" target="_blank" rel="noreferrer" class="link navy underline hover-sky">KEDA — the event-driven Kubernetes autoscaler.</a></p><p class="lh-copy measure-wide f4">The technique is sometimes referred to as <a href="https://release.com/blog/rainbow-deployment-why-and-how-to-do-it" target="_blank" rel="noreferrer" class="link navy underline hover-sky"><strong class="b">Rainbow Deployments</strong></a> and is useful whenever you have to keep the previous Pods Running longer than the grace period.</p><p class="lh-copy measure-wide f4"><strong class="b">Creating a new Deployment for every release is a less obvious but better choice.</strong></p><h2 class="f2 pt5 pb2 mt3" id="summary">Summary</h2><p class="lh-copy measure-wide f4">You should pay attention to Pods being deleted from your cluster since their IP addresses might still be used to route traffic.</p><p class="lh-copy measure-wide f4">Instead of immediately shutting down your Pods, you should consider waiting a little longer in your application or setting up a <code class="code f5 lh-copy bg-near-white br2 pv1 ph2 fs-normal word-wrap">preStop</code> hook.</p><p class="lh-copy measure-wide f4">The Pod should be removed only after all the endpoints in the cluster are propagated and removed from kube-proxy, Ingress controllers, CoreDNS, etc.</p><p class="lh-copy measure-wide f4">You should consider using rainbow deployments if your Pods run long-lived tasks such as transcoding videos or serving real-time updates with WebSockets.</p><p class="lh-copy measure-wide f4">In rainbow deployments, you create a new Deployment for every release and delete the previous one when the connection (or the tasks) is drained.</p><p class="lh-copy measure-wide f4">You can manually remove the older deployments after the long-running task is completed.</p><p class="lh-copy measure-wide f4">Or you could automatically scale your deployment to zero replicas to automate the process.</p></article><aside class="mb4 mb5-l mw7 center bg-evian br2 pa3 pa4-ns"><p class="f2 b navy mt0 mb2"><span class="mark mark--primary">Is your Kubernetes setup production-ready?</span></p><p class="lh-copy f4 measure black-70 mv0"><span class="b">Find the risks in your Kubernetes setup before they break production:</span> A LearnKube instructor reviews your Kubernetes setup with you, identifies the biggest risks, and explains what needs attention before the next change.</p><div class="pv1"></div><p class="lh-copy mv0"><a class="link navy b f4 underline" href="/production-readiness-review">Book an assessment</a></p><div class="pv4"></div><a class="link dib f3 mark mark--primary b" href="/corporate-training">Corporate training</a><div class="pv1"></div><p class="lh-copy f4 measure black-70 mv0"><span class="b">Give your team the confidence to run, troubleshoot, and evolve Kubernetes</span> with practical workshops tailored to your platform and workloads.</p><div class="pv1"></div><p class="lh-copy mv0"><a class="link navy b f4 underline" href="/corporate-training">Train your team</a></p></aside><footer class="footer ph3 ph4-ns pt3 pb3 bg-sky bt bw3 b--white-20"><section class="mw6 center mw-100-l flex-l items-start-l justify-around-l pv2"><div class=""><a href="/" class="logo db aspect-ratio aspect-ratio--6x2" title="LearnKube logo"><svg viewBox="0 0 600 200" fill="none" xmlns="http://www.w3.org/2000/svg" class="aspect-ratio--object"><path d="M495.926 130.824c-7.288 2.113-18.574 1.288-26.229 1.288-7.099 0-16.946.24-21.841-5.796-2.052-2.609-3.513-5.693-4.381-9.252-.868-3.558-1.302-7.473-1.302-11.743V69.563h17.641v33.623c0 5.693.75 9.806 2.25 12.336 1.499 2.53 4.302 3.796 8.406 3.796 1.263 0 2.605-.04 4.026-.119 1.42-.158 2.683-.316 3.789-.474V69.563h17.641v61.261Z" fill="#172777"></path><path d="M403.054 92.099a458.397 458.397 0 0 0 5.328-5.931 341.965 341.965 0 0 0 5.446-6.05 622.044 622.044 0 0 0 4.854-5.812 234.17 234.17 0 0 0 4.026-4.745h20.956a795.383 795.383 0 0 1-12.313 13.879c-3.947 4.35-8.288 8.857-13.024 13.522 2.368 2.135 4.815 4.706 7.341 7.71a168.067 168.067 0 0 1 7.34 9.134 135.733 135.733 0 0 1 6.513 9.49c1.973 3.163 3.296 6.205 4.638 8.815h-20.246c-1.263-2.056-2.389-4.466-4.047-6.918a113.315 113.315 0 0 0-5.091-7.473 86.104 86.104 0 0 0-5.801-7.235c-1.974-2.294-3.947-4.231-5.92-5.813v27.439h-17.642v-59.45l17.642-3.1V92.1Zm146.116 40.012v-62.55h42.91v12.034h-28.606v13.488h25.397v11.758h-25.397v14.233h30.714v11.037H549.17Zm-30.042 0c-5.32 0-15.092 0-21.364-1.123V69.562h19.8c4.806 0 15.251.596 19.442 3.01 2.445 1.41 4.34 3.277 5.685 5.604 1.406 2.266 2.109 5.083 2.109 8.45 0 5.084-2.445 9.095-7.335 12.034 4.034 1.531 6.785 3.613 8.252 6.246 1.467 2.634 2.2 5.604 2.2 8.911 0 6.674-2.445 11.696-7.335 15.064-4.829 3.368-11.858 3.23-21.454 3.23Zm-7.427-26.745v16.442c1.039.122 2.17.214 3.392.276 1.223.061 2.568.091 4.035.091 4.278 0 7.732-.612 10.36-1.837 2.628-1.224 3.943-3.49 3.943-6.797 0-2.939-1.101-5.022-3.301-6.246-2.201-1.286-5.348-1.929-9.444-1.929h-8.985Zm0-10.931h6.968c4.401 0 7.549-.552 9.444-1.654 1.895-1.163 2.842-3 2.842-5.511 0-2.572-.978-4.379-2.934-5.42-1.956-1.04-4.829-1.561-8.618-1.561-1.223 0-2.537.03-3.943.092-1.406 0-2.659.06-3.759.183v13.87Z" fill="#172777"></path><path d="M362.572 133.21V98.054c0-5.034-.743-8.665-2.228-10.893-1.403-2.228-3.838-3.342-7.304-3.342-3.053 0-5.653.908-7.798 2.723-2.063 1.733-3.549 3.92-4.457 6.561v40.107h-16.092V71.316h12.75l1.857 8.17h.495c1.898-2.64 4.415-4.951 7.551-6.932 3.136-1.98 7.18-2.97 12.131-2.97 3.054 0 5.777.412 8.17 1.237a13.913 13.913 0 0 1 6.066 4.085c1.65 1.898 2.888 4.498 3.713 7.799.825 3.218 1.238 7.22 1.238 12.007v38.498h-16.092Zm-44.636-46.791c-2.558-.908-4.869-1.362-6.932-1.362-2.888 0-5.323.784-7.303 2.352-1.898 1.485-3.178 3.425-3.838 5.818v39.983h-16.092V71.317h12.502l1.857 8.17h.495c1.403-3.054 3.301-5.406 5.695-7.056 2.393-1.65 5.199-2.476 8.417-2.476 2.146 0 4.58.454 7.303 1.362l-2.104 15.102Zm-93.47-11.513c3.301-1.485 7.22-2.64 11.759-3.466 4.539-.907 9.284-1.361 14.236-1.361 4.291 0 7.881.536 10.769 1.609 2.889.99 5.158 2.434 6.808 4.332 1.733 1.898 2.93 4.168 3.59 6.809.743 2.64 1.114 5.611 1.114 8.912 0 3.631-.123 7.304-.371 11.017a239.105 239.105 0 0 0-.495 10.77c0 3.548.124 7.014.371 10.398.248 3.301.867 6.437 1.857 9.408h-13.121l-2.6-8.542h-.619c-1.65 2.559-3.961 4.787-6.932 6.685-2.888 1.815-6.643 2.723-11.264 2.723-2.889 0-5.488-.413-7.799-1.238-2.311-.908-4.291-2.145-5.942-3.713a17.79 17.79 0 0 1-3.837-5.695c-.908-2.228-1.362-4.703-1.362-7.427 0-3.796.825-6.973 2.476-9.531 1.733-2.641 4.167-4.745 7.303-6.313 3.219-1.65 7.015-2.765 11.389-3.343 4.456-.66 9.407-.866 14.854-.619.578-4.621.248-7.922-.99-9.903-1.238-2.063-4.003-3.094-8.294-3.094-3.218 0-6.643.33-10.274.99-3.549.66-6.478 1.527-8.789 2.6l-3.837-12.008Zm20.424 46.049c3.219 0 5.777-.702 7.675-2.104 1.898-1.486 3.301-3.054 4.209-4.704v-8.046a44.901 44.901 0 0 0-7.427-.124c-2.311.165-4.374.536-6.19 1.114-1.815.577-3.259 1.403-4.332 2.476-1.073 1.072-1.609 2.434-1.609 4.085 0 2.31.66 4.126 1.98 5.446 1.403 1.238 3.301 1.857 5.694 1.857Zm-30.923 6.932c-2.476 1.981-5.859 3.672-10.151 5.075-4.208 1.321-8.706 1.981-13.492 1.981-9.986 0-17.289-2.889-21.911-8.665-4.621-5.859-6.932-13.864-6.932-24.015 0-10.893 2.6-19.063 7.799-24.51 5.199-5.446 12.502-8.17 21.91-8.17 3.136 0 6.19.413 9.16 1.238 2.971.826 5.612 2.187 7.923 4.085 2.31 1.898 4.167 4.457 5.57 7.675 1.403 3.218 2.105 7.221 2.105 12.007 0 1.733-.124 3.59-.372 5.571a58.75 58.75 0 0 1-.866 6.189h-37.136c.247 5.199 1.568 9.119 3.961 11.76 2.476 2.641 6.437 3.961 11.883 3.961 3.384 0 6.396-.495 9.037-1.485 2.723-1.073 4.786-2.146 6.189-3.219l5.323 10.522Zm-23.024-45.43c-4.209 0-7.345 1.28-9.408 3.838-1.981 2.475-3.177 5.818-3.59 10.026h23.024c.33-4.456-.371-7.88-2.104-10.274-1.65-2.393-4.291-3.59-7.922-3.59Zm-43.814 29.957c0 2.888.371 4.993 1.114 6.313.743 1.321 1.939 1.981 3.59 1.981.99 0 1.939-.083 2.847-.248.99-.165 2.187-.536 3.59-1.114l1.733 12.626c-1.321.661-3.343 1.321-6.066 1.981-2.723.66-5.529.99-8.417.99-4.704 0-8.294-1.073-10.77-3.218-2.476-2.228-3.713-5.859-3.713-10.893V46.56h16.092v65.854Zm-30.195-15.843-50.231-50.23c-2.36-2.36-6.068-2.36-8.428 0L8.044 96.57c-2.36 2.36-2.36 6.068 0 8.428l50.231 50.231c2.36 2.36 6.068 2.36 8.428 0l50.231-50.231c2.36-2.36 2.36-6.068 0-8.428Z" fill="#225DE0"></path><path d="M50.696 114.775a193.809 193.809 0 0 1-10.113-3.708c.674-.338 1.348-1.012 1.685-1.349 3.372-2.36 6.069-9.439 10.114-20.227a192.825 192.825 0 0 1 3.708-10.114c.337.674 1.012 1.349 1.349 1.686 2.36 3.371 9.44 6.068 20.227 10.113a192.83 192.83 0 0 1 10.114 3.709c-.675.337-1.349 1.011-1.686 1.348-3.371 2.36-6.068 9.44-10.114 20.227a192.47 192.47 0 0 1-3.708 10.114c-.337-.674-1.011-1.348-1.348-1.686-2.36-3.371-9.44-6.068-20.228-10.113Zm-15.17-7.754c-2.36 0-4.383-2.023-4.383-4.045 0-2.023 2.023-4.046 4.383-4.046s4.383 2.023 4.383 4.046c0 2.022-2.023 4.045-4.383 4.045Zm28.655-37.083c2.36 0 4.046 2.023 4.046 4.045 0 2.023-2.023 4.046-4.046 4.046s-4.045-2.023-4.045-4.046c0-2.022 2.022-4.045 4.045-4.045Zm28.993 28.655c2.36 0 4.045 2.023 4.045 4.046 0 2.022-2.023 4.045-4.045 4.045-2.023 0-4.046-2.023-4.046-4.045 0-2.023 2.023-4.046 4.046-4.046Zm-28.993 37.42c-2.36 0-4.045-2.022-4.045-4.045s2.022-4.045 4.045-4.045 4.046 2.022 4.046 4.045-2.023 4.045-4.046 4.045Zm-9.44-4.382c0 5.394 4.383 9.439 9.44 9.439 5.057 0 5.057-1.011 6.743-3.034 3.37-2.36 6.068-9.439 10.113-20.227a193.13 193.13 0 0 1 3.709-10.114c1.685 2.697 4.72 4.383 8.09 4.383 5.394 0 9.44-4.383 9.44-9.439 0-5.057-1.012-5.057-3.034-6.743-2.36-3.371-9.44-6.068-20.228-10.113a192.83 192.83 0 0 1-10.113-3.709c2.697-1.685 4.382-4.72 4.382-8.09 0-5.395-4.382-9.44-9.439-9.44s-5.057 1.011-6.742 3.034c-3.371 2.36-6.069 9.44-10.114 20.227A192.825 192.825 0 0 1 43.28 97.92c-1.686-2.697-4.72-4.383-8.091-4.383-5.394 0-9.44 4.383-9.44 9.44 0 5.056 1.012 5.056 3.035 6.742 2.36 3.371 9.439 6.068 20.227 10.114a192 192 0 0 1 10.113 3.708c-2.697 1.686-4.382 4.72-4.382 8.091Z" fill="#003C84"></path><path d="M48.835 112.753a192.9 192.9 0 0 1-10.113-3.708c.674-.338 1.348-1.012 1.685-1.349 3.372-2.36 6.069-9.44 10.114-20.227a192.948 192.948 0 0 1 3.708-10.114c.337.675 1.012 1.349 1.349 1.686 2.36 3.371 9.44 6.068 20.227 10.114a192.825 192.825 0 0 1 10.113 3.708c-.674.337-1.348 1.011-1.685 1.348-3.371 2.36-6.068 9.44-10.114 20.228a192.69 192.69 0 0 1-3.708 10.113c-.337-.674-1.011-1.348-1.349-1.685-2.36-3.372-9.439-6.069-20.227-10.114Zm-15.17-7.754c-2.36 0-4.383-2.023-4.383-4.045 0-2.023 2.023-4.046 4.383-4.046s4.383 2.023 4.383 4.046c0 2.022-2.023 4.045-4.383 4.045ZM62.32 67.916c2.36 0 4.046 2.023 4.046 4.045 0 2.023-2.023 4.046-4.046 4.046s-4.045-2.023-4.045-4.046c0-2.022 2.022-4.045 4.045-4.045ZM91.312 96.57c2.36 0 4.046 2.023 4.046 4.046 0 2.022-2.023 4.045-4.046 4.045-2.022 0-4.045-2.023-4.045-4.045 0-2.023 2.023-4.046 4.045-4.046ZM62.32 133.99c-2.36 0-4.045-2.022-4.045-4.045s2.022-4.045 4.045-4.045 4.046 2.022 4.046 4.045-2.023 4.045-4.046 4.045Zm-9.44-4.382c0 5.394 4.383 9.439 9.44 9.439 5.057 0 5.057-1.011 6.742-3.034 3.372-2.36 6.069-9.439 10.114-20.227a193.221 193.221 0 0 1 3.708-10.114c1.686 2.697 4.72 4.383 8.091 4.383 5.394 0 9.44-4.383 9.44-9.439 0-5.057-1.012-5.057-3.034-6.743-2.36-3.371-9.44-6.068-20.228-10.113a192.915 192.915 0 0 1-10.113-3.709c2.697-1.685 4.382-4.72 4.382-8.09 0-5.395-4.382-9.44-9.439-9.44s-5.057 1.011-6.742 3.034c-3.372 2.36-6.069 9.44-10.114 20.227a192.825 192.825 0 0 1-3.708 10.114c-1.686-2.697-4.72-4.383-8.091-4.383-5.394 0-9.44 4.383-9.44 9.44 0 5.057 1.012 5.057 3.034 6.742 2.36 3.371 9.44 6.068 20.228 10.114a192.9 192.9 0 0 1 10.113 3.708c-2.697 1.686-4.382 4.72-4.382 8.091Z" fill="#fff"></path></svg></a><p class="f5 white">The Kubernetes learning company.</p><ul class="pl3 mv0 f5 lh-copy white"><li><a href="/contact-us" class="link white underline-hover b">Contact us</a></li><li><a href="/about-us" class="link white underline-hover b">Team</a></li><li><a href="/careers" class="link white underline-hover b">Careers</a></li></ul><ul class="list pl0"><li class="dib"><a href="https://twitter.com/learnk8s" class="link dib w2 h2 icon" title="LearnKube on Twitter" rel="noreferrer" target="_blank"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 60 60" class=""><path fill="#ffffff" d="M50.2 12.7c-1.7 1-3.5 1.8-5.5 2.2-1.6-1.8-3.8-2.9-6.3-2.9-4.8 0-8.6 4.1-8.6 9.1 0 .7.1 1.4.2 2.1-7.2-.4-13.5-4-17.8-9.5-.7 1.3-1.2 2.9-1.2 4.6 0 3.2 1.5 5.9 3.8 7.6-1.4 0-2.7-.5-3.9-1.1v.1c0 4.4 3 8.1 6.9 8.9-.7.2-1.5.3-2.3.3-.6 0-1.1-.1-1.6-.2 1.1 3.6 4.3 6.2 8 6.3-3 2.4-6.7 3.9-10.7 3.9-.7 0-1.4 0-2.1-.1 3.8 2.6 8.3 4.1 13.2 4.1C38.4 48 47 34.2 47 22.1v-1.2c1.7-1.3 3.1-2.9 4.3-4.7-1.5.7-3.2 1.2-4.9 1.4 1.7-1 3.1-2.8 3.8-4.9z"></path></svg></a></li><li class="dib"><a href="https://www.linkedin.com/company/learnkube/" class="link dib w2 h2 icon" title="LearnKube on LinkedIn" rel="noreferrer" target="_blank"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 60 60" class=""><path fill="#ffffff" d="M14.8 10c-2.9 0-4.8 2-4.8 4.7 0 2.6 1.8 4.7 4.7 4.7h.1c2.9 0 4.8-2.1 4.8-4.7-.2-2.7-2-4.7-4.8-4.7zM11 22.8h7.8V50H11zM40.1 22.6c-4.5 0-7.3 2.7-7.8 4.5v-4.3h-8.8c.1 2.3 0 27.2 0 27.2h8.8V35.3c0-.8 0-1.6.2-2.2.6-1.6 1.9-3.3 4.2-3.3 3 0 4.4 2.5 4.4 6.2v14H50V34.9c0-8.4-4.4-12.3-9.9-12.3z"></path></svg></a></li><li class="dib"><a href="/slack" class="link dib w2 h2 icon" title="LearnKube on Slack" rel="noreferrer" target="_blank"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 60 60"><path fill="#ffffff" d="M25.913 27.84l5.88-1.968 1.904 5.69-5.88 1.968z"></path><path fill="#ffffff" d="M24 9.8C8.8 14.4 5.3 20.9 9.8 36 14.4 51.2 20.9 54.7 36 50.2 51.2 45.6 54.7 39.1 50.2 24 45.6 8.8 39.1 5.3 24 9.8zm18.5 24l-2.9 1 1 3c.4 1.2-.2 2.5-1.4 2.9-.3.1-.5.1-.8.1-.9 0-1.8-.6-2.1-1.6l-1-2.9-5.9 2 1 2.9c.4 1.2-.2 2.5-1.4 2.9-.3.1-.5.1-.8.1-.9 0-1.8-.6-2.1-1.6l-1-3-2.9 1c-.3.1-.5.1-.8.1-.9 0-1.8-.6-2.1-1.6-.4-1.2.2-2.5 1.4-2.9l2.9-1-1.9-5.7-2.9 1c-.3.1-.5.1-.8.1-.9 0-1.8-.6-2.1-1.6-.4-1.2.2-2.5 1.4-2.9l2.9-1-1-2.9c-.4-1.2.2-2.5 1.4-2.9 1.2-.4 2.5.2 2.9 1.4l1 2.9 5.9-2-1-2.9c-.4-1.2.2-2.5 1.4-2.9 1.2-.4 2.5.2 2.9 1.4l1 3 2.9-1c1.2-.4 2.5.2 2.9 1.4.4 1.2-.2 2.5-1.4 2.9l-2.9 1 1.9 5.7 2.9-1c1.2-.4 2.5.2 2.9 1.4.5 1.5-.2 2.8-1.4 3.2z"></path></svg></a></li><li class="dib"><a href="https://t.me/LearnKube" class="link dib w2 h2 icon" title="LearnKube on Telegram" rel="noreferrer" target="_blank"><svg xmlns="http://www.w3.org/2000/svg" viewBox="-6 -6 60 60" class=""><path d="M0 24c0 13.255 10.745 24 24 24s24-10.745 24-24S37.255 0 24 0 0 10.745 0 24zm19.6 11l.408-6.118 11.129-10.043c.488-.433-.107-.645-.755-.252l-13.735 8.665-5.932-1.851c-1.281-.393-1.29-1.273.287-1.906l23.118-8.914c1.056-.48 2.075.254 1.672 1.87l-3.937 18.552c-.275 1.319-1.071 1.634-2.175 1.025l-5.997-4.431L20.8 34.4l-.027.026c-.322.314-.59.574-1.173.574z" fill="#ffffff"></path></svg></a></li><li class="dib"><a class="link dib w2 h2 icon" title="LearnKube on Mastodon" rel="me" href="https://learnk8s.news/@learnk8s" target="_blank"><svg viewBox="0 0 64 64" fill="none" class="pl1" xmlns="http://www.w3.org/2000/svg"><g clip-path="url(#a)"><path d="M57.449 38.26c-.863 4.439-7.728 9.296-15.612 10.238-4.112.49-8.16.941-12.477.744-7.058-.323-12.63-1.685-12.63-1.685 0 .687.042 1.342.126 1.954.918 6.966 6.909 7.383 12.584 7.578 5.726.196 10.826-1.413 10.826-1.413l.236 5.18s-4.006 2.15-11.142 2.546c-3.935.216-8.82-.099-14.513-1.605C2.503 58.53.382 45.373.057 32.022c-.1-3.964-.038-7.701-.038-10.827 0-13.65 8.944-17.65 8.944-17.65C13.473 1.472 21.213.601 29.257.535h.197c8.045.066 15.789.937 20.299 3.008 0 0 8.944 4.001 8.944 17.651 0 0 .112 10.072-1.248 17.064Z" fill="#ffffff"></path><path d="M12.4 17.887a3.598 3.598 0 1 1 7.197 0 3.598 3.598 0 0 1-7.197 0Zm51.59 4.367v16.53h-6.548V22.74c0-3.382-1.423-5.097-4.269-5.097-3.146 0-4.724 2.037-4.724 6.062v8.781h-6.51v-8.782c0-4.027-1.577-6.062-4.723-6.062-2.846 0-4.269 1.716-4.269 5.097v16.043H26.4V22.254c0-3.377.86-6.062 2.587-8.05 1.783-1.984 4.116-3.003 7.011-3.003 3.351 0 5.89 1.288 7.566 3.864l1.632 2.734 1.631-2.734c1.678-2.576 4.216-3.864 7.567-3.864 2.895 0 5.23 1.018 7.011 3.004 1.747 1.987 2.586 4.672 2.586 8.05Z" fill="#569ad1"></path></g><defs><clippath id="a"><path fill="#fff" d="M0 0h64v64H0z"></path></clippath></defs></svg></a></li></ul></div><div class="mv4 mv0-l"><div class="f4 measure"><p class="ttu b f6 white-60 mv2">Services</p><ul class="pl3 mv0 f5 lh-copy white-60"><li><a href="/corporate-training" class="link white-80 underline-hover pointer db">Corporate training</a></li><li><a href="/production-readiness-review" class="link white-80 underline-hover pointer db">Production readiness review</a></li><li><a href="/training" class="link white-80 underline-hover pointer db">Public workshops</a></li><li><a href="/for-marketers" class="link white-80 underline-hover pointer db">For marketers</a></li></ul></div></div><div class="mv4 mv0-l"><div class="f4 measure"><p class="ttu b f6 white-60 mv2">Tools</p><ul class="pl3 mv0 f5 lh-copy white-60"><li><a href="/kubernetes-instance-calculator" class="link white-80 underline-hover pointer db">Kubernetes instance calculator</a></li><li><a href="/troubleshooting-deployments" class="link white-80 underline-hover pointer db">Troubleshooting flow chart</a></li><li><a href="/production-best-practices" class="link white-80 underline-hover pointer db">Kubernetes production best practices</a></li><li><a href="/kubernetes-resources" class="link white-80 underline-hover pointer db">See all tools</a></li></ul></div></div><div class="mv4 mv0-l"><div class="f4 measure"><p class="ttu b f6 white-60 mv2">Research</p><ul class="pl3 mv0 f5 lh-copy white-60"><li><a href="https://docs.google.com/spreadsheets/d/191WWNpjJ2za6-nbG4ZoUMXMpUK8KlCIosvQB0f-oq3k" class="link white-80 underline-hover pointer db" target="_blank" rel="noreferrer">Ingress controller comparison</a></li><li><a href="https://docs.google.com/spreadsheets/d/1RPpyDOLFmcgxMCpABDzrsBYWpPYCIBuvAoUQLwOGoQw" class="link white-80 underline-hover pointer db" target="_blank" rel="noreferrer">Managed services comparison</a></li><li><a href="https://docs.google.com/spreadsheets/d/1yhkuBJBY2iO2Ax5FcbDMdWD5QLTVO6Y_kYt_VumnEtI" class="link white-80 underline-hover pointer db" target="_blank" rel="noreferrer">Resource allocations in Kubernetes nodes</a></li><li><a href="/research" class="link white-80 underline-hover pointer db">See all research</a></li></ul></div></div><div class="mv4 mv0-l"><div class="f4 measure"><p class="ttu b f6 white-60 mv2">Our network</p><ul class="pl3 mv0 f5 lh-copy white-60"><li><a href="https://kube.fm" class="link white-80 underline-hover pointer db" target="_blank" rel="noreferrer">KubeFM</a></li><li><a href="https://kube.events" class="link white-80 underline-hover pointer db" target="_blank" rel="noreferrer">Kube Events</a></li><li><a href="https://kube.careers" class="link white-80 underline-hover pointer db" target="_blank" rel="noreferrer">Kube Careers</a></li><li><a href="https://kube.archi" class="link white-80 underline-hover pointer db" target="_blank" rel="noreferrer">Kube Architect</a></li><li><a href="https://kubesploit.io" class="link white-80 underline-hover pointer db" target="_blank" rel="noreferrer">Kubesploit</a></li><li><a href="https://kube.builders" class="link white-80 underline-hover pointer db" target="_blank" rel="noreferrer">Kube Builders</a></li><li><a href="/news-events-jobs" class="link white-80 underline-hover pointer db">See all</a></li></ul></div></div></section><section class="pt2"><p class="mv0 f7 bt b--white-60 pt2 pb0 white-80">Copyright © LearnKube 2017-2026. Made with <span class="dark-red">❤︎</span> in London. View our <a class="link white-80" href="/terms-and-conditions">Terms and Conditions</a> or <a class="link white-80" href="/privacy-policy">Privacy Policy</a>. Kubernetes is a registered trademark of The Linux Foundation.</p></section></footer></div></body></html> |