{"componentChunkName":"component---src-templates-post-template-jsx","path":"/works/posts/2025-03-10--001","result":{"data":{"site":{"siteMetadata":{"title":"Blog by Eunyoung","subtitle":"작업 기록 블로그","copyright":"© All rights reserved.","author":{"name":"EunYoung","twitter":"#"},"disqusShortname":"","url":"https://ssongey.github.io"}},"markdownRemark":{"id":"ae9c249c-5d17-5231-a33c-d8c62a58da5e","html":"<h2>1. Kubernetes에서의 Graceful Termination</h2>\n<p>쿠버네티스를 사용을 한다면, 파드를 graceful 하게 종료시키기 위해 deployment 매니페스트에 preStop Hook, terminationGracePeriodSeconds 를 설정하곤 한다.</p>\n<h3>✔️ preStop Hook</h3>\n<ul>\n<li>파드가 종료를 요청받고, 컨테이너가 종료되기 직전 실행되는 훅</li>\n<li>애플리케이션이 종료 전에 필요한 작업을 완료할 수 있도록 시간을 줄 수 있으며,</li>\n<li>이는 서비스의 중단을 최소화하고, 데이터 무결성을 보장하는데 도움이 된다.</li>\n<li>시간을 길게 설정할수록 안정성은 좋아지나 애플리케이션 다운시간이 길어지는 트레이드 오프가 생긴다.</li>\n</ul>\n<br/>\n<h3>✔️ terminationGracePeriodSeconds</h3>\n<ul>\n<li>파드 내의 모든 컨테이너가 종료 작업을 완료할 수 있도록 주어지는 유예기간 (초단위)</li>\n<li>preStop Hook 과 마찬가지로 데이터 무결성 보장, 서비스 가용성 유지, 안정성 확보 등의 이점이 있다.</li>\n<li>기본값은 30초이며, 설정된 시간이 넘게되면 파드는 SIGKILL 신호로 즉시 종료된다.</li>\n</ul>\n<p><strong>예시</strong></p>\n<div class=\"gatsby-highlight\" data-language=\"yaml\"><pre class=\"language-yaml\"><code class=\"language-yaml\"><span class=\"token key atrule\">apiVersion</span><span class=\"token punctuation\">:</span> apps/v1\n<span class=\"token key atrule\">kind</span><span class=\"token punctuation\">:</span> Deployment\n<span class=\"token key atrule\">metadata</span><span class=\"token punctuation\">:</span>\n  <span class=\"token key atrule\">name</span><span class=\"token punctuation\">:</span> example<span class=\"token punctuation\">-</span>deployment\n<span class=\"token key atrule\">spec</span><span class=\"token punctuation\">:</span>\n  <span class=\"token key atrule\">replicas</span><span class=\"token punctuation\">:</span> <span class=\"token number\">3</span>\n  <span class=\"token key atrule\">selector</span><span class=\"token punctuation\">:</span>\n    <span class=\"token key atrule\">matchLabels</span><span class=\"token punctuation\">:</span>\n      <span class=\"token key atrule\">app</span><span class=\"token punctuation\">:</span> example<span class=\"token punctuation\">-</span>app\n  <span class=\"token key atrule\">template</span><span class=\"token punctuation\">:</span>\n    <span class=\"token key atrule\">metadata</span><span class=\"token punctuation\">:</span>\n      <span class=\"token key atrule\">labels</span><span class=\"token punctuation\">:</span>\n        <span class=\"token key atrule\">app</span><span class=\"token punctuation\">:</span> example<span class=\"token punctuation\">-</span>app\n    <span class=\"token key atrule\">spec</span><span class=\"token punctuation\">:</span>\n      <span class=\"token key atrule\">terminationGracePeriodSeconds</span><span class=\"token punctuation\">:</span> <span class=\"token number\">60</span>  <span class=\"token comment\"># 유예 기간을 60초로 설정</span>\n      <span class=\"token key atrule\">containers</span><span class=\"token punctuation\">:</span>\n      <span class=\"token punctuation\">-</span> <span class=\"token key atrule\">name</span><span class=\"token punctuation\">:</span> example<span class=\"token punctuation\">-</span>container\n        <span class=\"token key atrule\">image</span><span class=\"token punctuation\">:</span> example<span class=\"token punctuation\">-</span>image<span class=\"token punctuation\">:</span>latest\n        <span class=\"token key atrule\">lifecycle</span><span class=\"token punctuation\">:</span>\n          <span class=\"token key atrule\">preStop</span><span class=\"token punctuation\">:</span>\n            <span class=\"token key atrule\">exec</span><span class=\"token punctuation\">:</span>\n              <span class=\"token key atrule\">command</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">[</span><span class=\"token string\">\"sh\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"-c\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"echo 'PreStop Hook Triggered'; sleep 10\"</span><span class=\"token punctuation\">]</span>  <span class=\"token comment\"># preStop Hook 명령 설정</span>\n        <span class=\"token key atrule\">ports</span><span class=\"token punctuation\">:</span>\n        <span class=\"token punctuation\">-</span> <span class=\"token key atrule\">containerPort</span><span class=\"token punctuation\">:</span> <span class=\"token number\">80</span></code></pre></div>\n<br/>\n<h3>✔️ Kubernetes에서 파드가 종료되는 순서</h3>\n<p>그럼, 쿠버네티스에서 파드가 종료되는 순서를 알아보자.</p>\n<p><strong>1. 파드 삭제 요청</strong></p>\n<ul>\n<li>deployment rollout, scale down 등의 사용자 또는 시스템으로부터 파드 삭제 요청을 받는다.</li>\n</ul>\n<p><strong>2. 파드를 종료중 상태로 업데이트</strong></p>\n<ul>\n<li>K8S API 서버는 파드의 상태를 ‘Terminating’으로 업데이트를 하고, 해당 파드는 모든 서비스의 endpodint에서 제거된다.</li>\n<li>이 시점에 파드는 새 트래픽 수신을 중지하게되고, 실행중인 요청은 정상적으로 처리한다.</li>\n</ul>\n<p><strong>3. preStop Hook 실행</strong></p>\n<ul>\n<li>파드에 ‘preStop’ 훅이 정의되어 있으면, 종료 신호를 받았을때 정의된 명령어가 실행된다.</li>\n</ul>\n<p><strong>4. 컨테이너에 SIGTERM 신호 전송</strong></p>\n<ul>\n<li>preStop Hook 이 완료되면, K8S는 파드 내 컨테이너들에게 SIGTERM 신호를 보낸다.</li>\n<li>이때 DB연결, WebSocket 스트림 등 오래 지속되는 연결에 대한 중지가 일어난다.</li>\n</ul>\n<p><strong>5. Graceful Termination Period</strong></p>\n<ul>\n<li>K8S는 파드에 정의된 ‘terminationGracePeriodSeconds’ 동안 컨테이너가 종료되기를 기다린다.</li>\n</ul>\n<p><strong>6. 파드 제거</strong></p>\n<ul>\n<li>마지막으로 파드가 제거된다.</li>\n<li>이때, Graceful Termination Period 후에도 컨테이너가 계속 실행 중이면, SIGKILL 신호가 전송되어 강제로 컨테이너가 종료된다.</li>\n</ul>\n<p><strong>유의할점.</strong></p>\n<ul>\n<li>Graceful Termination Period 와 preStop hook, SIGTERM signal이 병렬로 발생한다.</li>\n<li>때문에 ‘애플리케이션이 종료 전에 필요한 작업을 완료할 수 있는 시간(preStop Hook 수행시간) + 애플리케이션 종료시간’ 보다  ‘terminationGracePeriodSeconds’ 시간이 커야 Graceful Termination이 보장된다고 봐야한다.</li>\n<li>정상적인 Graceful Termination</li>\n</ul>\n<p>\n  <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/devHistoryBlog/static/13d88dee915e569cbb98a1a2e41f6d7b/53639/01.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n  \n  <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 960px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 73.33333333333334%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAYAAADkmO9VAAAACXBIWXMAABYlAAAWJQFJUiTwAAAB0ElEQVQ4y31UXY+iQBDk//+ne7ncy2ou3HJowKCLChhlQVCRD2eooxuGHdm97aQyk+6eoma6GwODtW3Lq5QSQghem6ZBFEXY7XbYbre8Enzfx+FwwOPx4DwF4jCmhERSliWqqkJRFNjv99hsNiOIbL1es/9+v3Megc7QBz4RkpMUKkxN5ZHpeQQmpAQd5JwSfBfX7Umh7tRVPBFzXIzk7Nc+yoTn8xlJkiDPc1wuV5auguSj+O12gzpe3K7w394QhgEXrKnr8YNMWL5bKE+/O5ioYhMyWwCFB1xdiOQvRGoD5Lv7QPILj/0LMstCZpvInQXEnxlQlYN6unLbdPR1DzRdZVNsIwfB0UN4WvMaxf2aV1FX2bS/pxQ96qpTJz8IW/UOw1ul3QHr3cQisQa8MtzzEj9PP+BfNn2/on06N155WkUpJL4ziuv5aHvakfBzlRvI7gqy7TWovcJXbaX3JSvUx0dvZlVxNZLsk71v2vi0r7uKG7Q5Ho9wXReO4/B40Z4QBAEnkYVhCNu2Oe55HpbLJY+esjiOec4NpYCGfTabwTRNzOdzrFarUQHNKs0v+SlOxESYpulHgw83Nf43m/obUaIaAFKSZRnv6ecxfcd/isaJvC7NirMAAAAASUVORK5CYII='); background-size: cover; display: block;\"\n    >\n      <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;\"\n        alt=\"01\"\n        title=\"\"\n        src=\"/devHistoryBlog/static/13d88dee915e569cbb98a1a2e41f6d7b/d9199/01.png\"\n        srcset=\"/devHistoryBlog/static/13d88dee915e569cbb98a1a2e41f6d7b/8ff5a/01.png 240w,\n/devHistoryBlog/static/13d88dee915e569cbb98a1a2e41f6d7b/e85cb/01.png 480w,\n/devHistoryBlog/static/13d88dee915e569cbb98a1a2e41f6d7b/d9199/01.png 960w,\n/devHistoryBlog/static/13d88dee915e569cbb98a1a2e41f6d7b/53639/01.png 1358w\"\n        sizes=\"(max-width: 960px) 100vw, 960px\"\n      />\n    </span>\n  </span>\n  \n  </a>\n    </p>\n<ul>\n<li>terminationGracePeriodSeconds 시간이 충분치 않은 경우</li>\n</ul>\n<p>\n  <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/devHistoryBlog/static/3652e02db8a2b4d5715af061e14a3c48/bb543/02.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n  \n  <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 960px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 66.66666666666666%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAYAAACpUE5eAAAACXBIWXMAABYlAAAWJQFJUiTwAAABr0lEQVQ4y3VTa5OaQBDk//+q+5T7dEQsTEmMWiZw4aXACvLa3c7MCmS1vKlqB3Z7WnZ61oEVWmv7FeM4Is9zpGmKLMtMTpLE5LZt8arWeV6QUqJpGnRdh7quF8EZs6AQwogylFKLhsM/Mzh4k0Xtta+C95nLNTPfeSYpJYk0Mv0/9B28rqevWfgkaIcjab/tFXrSGAiKaqW+Sw3E7UeNcdLgNdG0iLMc57JCermgoyJuUVlV5vhO3+TI/3ioki3K+Adk/Zv+4RO4RajzHUQaoCsPpJ5AFS6KvY904yP7FSDbbVF9hvj2/o4wDE3fHYyCBEJCBHSRERTplsQCwk80BJPPO2gRQJcJUBaEM1Bd0F9yRFFkJsIc2eqUiZZ68vHXhZswvuMjpkzwMg9v6RuEbJbjM9STSZPLyoAbz6bgC3e7obkbNk/A5LKcjFkE7ZgJ9jjNHK30w8zN/Ic5nB9ezdyDGGXu0/Pcvbwpt9sNh8MBrku98jyD1WqF/X5vbgtHHMfmnQ1gR1n8dDphvV7D930URTGZYn3B8XjEZrNBEASmeBiGl3fcDr6C1+t14f0DzaLw4tOwjj8AAAAASUVORK5CYII='); background-size: cover; display: block;\"\n    >\n      <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;\"\n        alt=\"02\"\n        title=\"\"\n        src=\"/devHistoryBlog/static/3652e02db8a2b4d5715af061e14a3c48/d9199/02.png\"\n        srcset=\"/devHistoryBlog/static/3652e02db8a2b4d5715af061e14a3c48/8ff5a/02.png 240w,\n/devHistoryBlog/static/3652e02db8a2b4d5715af061e14a3c48/e85cb/02.png 480w,\n/devHistoryBlog/static/3652e02db8a2b4d5715af061e14a3c48/d9199/02.png 960w,\n/devHistoryBlog/static/3652e02db8a2b4d5715af061e14a3c48/bb543/02.png 1418w\"\n        sizes=\"(max-width: 960px) 100vw, 960px\"\n      />\n    </span>\n  </span>\n  \n  </a>\n    </p>\n<hr>\n<p><br/><br/></p>\n<h2>2. 컨테이너에서의 Graceful Termination</h2>\n<p>적당한 preStop Hook, terminationGracePeriodSeconds 설정으로 Graceful Termination 이 되었을까?<br/>\n나도 그런줄 알았지만.. 컨테이너에 함정이 숨어 있었다.<br/>\n리얼 환경 배포시에 위 설정값을 충분히 크게 줘도 <strong>DB 커넥션이 애플리케이션에서 강제로 종료되는 현상</strong>이 발생하였고, <br/>\n팀 내에서 아래 글을 발견하게 되었다.<br/>\n<a href=\"https://vinodhinic.medium.com/are-you-sure-sigterm-is-received-by-your-application-in-kubernetes-885a3ce7ae4e\">https://vinodhinic.medium.com/are-you-sure-sigterm-is-received-by-your-application-in-kubernetes-885a3ce7ae4e</a></p>\n<p>정리하면 도커는 2가지 방식, Shell과 Exec 방식을 지원하는데, <strong>도커파일에서 애플리케이션 실행 구문에 어떤 방식을 사용하냐에 따라</strong> kubelet이 보낸 <strong>SIGTERM이 실제로 애플리케이션에 수신이 되지 않는다</strong>는 점이다.</p>\n<br/>\n<h3>✔️ Shell 방식</h3>\n<ul>\n<li>컨테이너 내 shell에서 해당 명령을 실행하며, <strong>PID 1 인 프로세스는 shell</strong> 이 된다.</li>\n<li>계층 순서는 ‘파드 > 컨테이너 > <strong>shell</strong> > 애플리케이션’ 이 된다.</li>\n<li>kubelet이 SIGTERM 신호를 보내면 shell 프로세스에서 소비된다.</li>\n</ul>\n<div class=\"gatsby-highlight\" data-language=\"docker\"><pre class=\"language-docker\"><code class=\"language-docker\"><span class=\"token keyword\">ENTRYPOINT</span> java <span class=\"token punctuation\">-</span>Dspring.profiles.active=$<span class=\"token punctuation\">{</span>APP_PHASE<span class=\"token punctuation\">:</span><span class=\"token punctuation\">-</span>sandbox<span class=\"token punctuation\">}</span> <span class=\"token punctuation\">-</span>jar /app/app.jar</code></pre></div>\n<br/>\n<h3>✔️ Exec 방식</h3>\n<ul>\n<li>컨테이너에서 바로 애플리케이션이 실행되며, <strong>PID 1인 프로세스는 애플리케이션</strong>이다.</li>\n<li>계층 순서는 ‘파드 > 컨테이너 > 애플리케이션’ 이 된다.</li>\n<li>kubelet이 SIGTERM 신호를 보내면 애플리케이션 프로세스에서 소비된다.</li>\n<li><strong>최대 단점은 환경변수를 사용할 수 없다는 것</strong>이다.</li>\n</ul>\n<div class=\"gatsby-highlight\" data-language=\"docker\"><pre class=\"language-docker\"><code class=\"language-docker\"><span class=\"token keyword\">ENTRYPOINT</span> <span class=\"token punctuation\">[</span><span class=\"token string\">\"java\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"-jar\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"/app/app.jar\"</span><span class=\"token punctuation\">]</span></code></pre></div>\n<br/>\n<h3>✔️Shell 방식의 컨테이너 내 애플리케이션 종료</h3>\n<p>내가 서비스하고 있는 애플리케이션의 <strong>dockerfile 설정은 shell 방식</strong>으로 되어 있었고,</p>\n<p>kubelet에서 <strong>SIGTERM 신호를 보내도 shell 이 받아버려</strong> Graceful Termination 을 위해 세팅되었던 K8S 설정들이 무의미 했다는걸 알게 되었다.</p>\n<ul>\n<li>shell 방식의 애플리케이션 종료</li>\n</ul>\n<p>\n  <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/devHistoryBlog/static/01d4e72d63760a32a3263008e59d4fe6/0d292/03.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n  \n  <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 960px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 58.333333333333336%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAACXBIWXMAABYlAAAWJQFJUiTwAAACKUlEQVQoz21T207bQBD1/79UtFW/IX0pICgXVaoKEkEEhBpCaKxEIQ5Jk/iWtWPHe7NPZ9cY0dKVx3PWM3Nmd33WwX+GlBJKKWy3W8xmT/A8D9Pp1PrJZALf922OlOJNrWNeVVVaAq1ry/OMyHJkWYY4jhBFIdmzD0MwtrZxk9fUlKWuCR8fJwiCGFwoFIWkJE5EBRUIa5wra8Wzt5jyTGxDeVnGqUaQ30IIAcf355h6PcTRBGkypeVGKHVIvWLCsZ1bjBpXZVgbYa38l5hWCTUp4CgZwp8dYz4+wNL7ioL9QLm9QFVcALxNdgmenCOLvkPn9A03QNkh8ms67Cs8PZ5iOTtFlg5pF7ImrNJjqPALVLQLbSzeRcX2Ua73MO5+Qu/yHdybj3CvduBef8CvznsMCN+1d9C5bGEdnEGJiT0GR4qUuq6oo1m+T1tZoTJbMVvVAeZeH53zE3zbb+Fkr4XDgxaOjj7j7OwQvV4bktMxYQEpIiLkcLQu3/z6UTDE3e+feFjdww0f8LDooj/v4tbvgOWMijX+rTNzIzMnTVMrgcaMFAK2QpCuEKY+gqTGLI/hsTGSjEFwYYs3m9TmF4XBG/KFWaHppu0vbwStFXWnR4lXWGrIohY7F/xF+KaOc245qqqqhW0GYwyu69K59DAYDNDv39ubYQrMSNIET3RrlqsliT22zReLhRW8uTmGzArbgGayXq8xHA4xGo3+Imvir0dT18Qa/AdPsI5MLMsufQAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n    >\n      <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;\"\n        alt=\"03\"\n        title=\"\"\n        src=\"/devHistoryBlog/static/01d4e72d63760a32a3263008e59d4fe6/d9199/03.png\"\n        srcset=\"/devHistoryBlog/static/01d4e72d63760a32a3263008e59d4fe6/8ff5a/03.png 240w,\n/devHistoryBlog/static/01d4e72d63760a32a3263008e59d4fe6/e85cb/03.png 480w,\n/devHistoryBlog/static/01d4e72d63760a32a3263008e59d4fe6/d9199/03.png 960w,\n/devHistoryBlog/static/01d4e72d63760a32a3263008e59d4fe6/07a9c/03.png 1440w,\n/devHistoryBlog/static/01d4e72d63760a32a3263008e59d4fe6/0d292/03.png 1620w\"\n        sizes=\"(max-width: 960px) 100vw, 960px\"\n      />\n    </span>\n  </span>\n  \n  </a>\n    </p>\n<br/>\n<h3>✔️그래서 어떻게 적용해야하나?</h3>\n<p>보통은 환경변수를 통해 애플리케이션의 페이즈 등을 애플리케이션으로 전달하기 때문에, Exec 방식은 사용하기 힘들다. 그럼 어떻게 PID가 1 인 애플리케이션의 컨테이너 환경을 만들 수 있을까?</p>\n<p>아래 해결책이 있다!!</p>\n<p><strong>K8S 매니페스트에 command 와 args 필드를 이용하여 ENTRYPOINT 에 정의된 내용을 재정의 할수있다.</strong></p>\n<p><a href=\"https://stackoverflow.com/questions/44316361/difference-between-docker-entrypoint-and-kubernetes-container-spec-command\">https://stackoverflow.com/questions/44316361/difference-between-docker-entrypoint-and-kubernetes-container-spec-command</a></p>\n<p>아래는 실제 수정된 deployment.yaml 파일이다.</p>\n<p>ENTRYPOINT에 정의한 내용을 다시 정의하고 있다. 여기서는 환경변수 사용도 가능하다.</p>\n<p>\n  <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/devHistoryBlog/static/ea96b1487d97387f108435ade11f4259/1c1a4/04.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n  \n  <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 960px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 86.25%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAARCAYAAADdRIy+AAAACXBIWXMAABYlAAAWJQFJUiTwAAACMklEQVQ4y42Ti3KiQBBF+f+f2qqtbIzJ6qbiExTlzQwgCBpjFLjbPQYlKc0uVbcGmpnD7W5aC8sEsk4RIYN/jNCXIzxLHRwXFGeF1WmV14TWStKcUsKvY/hIYJchBtkMk9xBQM8sH/HHfXyOtd+dzl6kuQQMKBhiBfsYYpSbGK8djDMH08Il+El64WGwsvEcLZX+yIWCKXh9+YjmVZEK+ApKLg8SHVtH1zPwO5jjbjHB3XKKR3+GYWrDLSNY70KpAZ7BDGwcNmkt94H6OsN+mmN1zyB2yXvClr7CWsBE1ZADy32Ivlig4xj4YQzhHCUElaMNaOumQ//sMKR0Z5TmBPeU+hOl+pJYtM4xymzakal6S9I3Dj8D+XDH0fFI4K5rqBryB/rChLkLYGx81TBV/+sOk09APshNeKI6skuGPRCYxbU1tr6q6TfAtsMAPQJyp39ZUyWGzl7ZlYc5ORRXUm7Wq0B2yLXjWrJLTp/XwcqiJkWqQV4VX23QjZQXqnb3ln5Om5/ZIf/gDAu/TE3j8gxsAtb7CfhAv03XnaEXmgrGbjnGjRrSxPDUvMQWRqmjfv4RTRZ3n2ZZwCOQV0dqFhnYE3PoWw8mpW8fBc24hFNdtDyEsChuHYRa+Zn3eDzLaVUgqzfIsUV0TOFsaFMaw1wJuEWCNcX53bqlW8/M0dC6qrJEsS1QvK6x2ewg4xwyyoEa/31p+7IG6410oIP52x6GcODGGSZ2jLjYYV8Bzb5/6S8HRftCZb/Q2gAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n    >\n      <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;\"\n        alt=\"04\"\n        title=\"\"\n        src=\"/devHistoryBlog/static/ea96b1487d97387f108435ade11f4259/d9199/04.png\"\n        srcset=\"/devHistoryBlog/static/ea96b1487d97387f108435ade11f4259/8ff5a/04.png 240w,\n/devHistoryBlog/static/ea96b1487d97387f108435ade11f4259/e85cb/04.png 480w,\n/devHistoryBlog/static/ea96b1487d97387f108435ade11f4259/d9199/04.png 960w,\n/devHistoryBlog/static/ea96b1487d97387f108435ade11f4259/1c1a4/04.png 1046w\"\n        sizes=\"(max-width: 960px) 100vw, 960px\"\n      />\n    </span>\n  </span>\n  \n  </a>\n    </p>\n<p><strong>수정 전/후 PID 상태</strong></p>\n<p>\n  <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/devHistoryBlog/static/a3055c4390889ca036fc202472109311/8aace/05.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n  \n  <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 960px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 22.499999999999996%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAFCAYAAABFA8wzAAAACXBIWXMAABYlAAAWJQFJUiTwAAABIUlEQVQY01WMW07CQBiFhxDRYrlUjMa1SEy0BVrKJSqJPJhCgWJ0K/IgDwKVAm5HYloak8YO7uU4HZTow5fvnDN/hiyX73DdFVzPxxvLvv8Bz1shCAJ8rSloGHLWlDLCP/13o+xuzU3DT5AYITjJSTiWMsgICZ6Psmmk9xLIJgUcpkVOLiXiQExC2t9sURbiMX6X2t1hJBBnf5FmowHLNNExDHRaBu66XdxbFqOHh/7GltlGr93i7rKbfsfc5miPHPXb5g3I4HGA8WiM0fMIw6ch7MkEU9vGYuZsmTtTzsJxfjz99x7xOp/hZTIGkc/yuK5XcVnVUdNKaLB8VauwrKKua6iVVWgFGZoio1xQoMoXKBcLDIXtCrfOeqVUxHn+FN/qK+R9BMsKQwAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n    >\n      <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;\"\n        alt=\"05\"\n        title=\"\"\n        src=\"/devHistoryBlog/static/a3055c4390889ca036fc202472109311/d9199/05.png\"\n        srcset=\"/devHistoryBlog/static/a3055c4390889ca036fc202472109311/8ff5a/05.png 240w,\n/devHistoryBlog/static/a3055c4390889ca036fc202472109311/e85cb/05.png 480w,\n/devHistoryBlog/static/a3055c4390889ca036fc202472109311/d9199/05.png 960w,\n/devHistoryBlog/static/a3055c4390889ca036fc202472109311/07a9c/05.png 1440w,\n/devHistoryBlog/static/a3055c4390889ca036fc202472109311/29114/05.png 1920w,\n/devHistoryBlog/static/a3055c4390889ca036fc202472109311/8aace/05.png 2732w\"\n        sizes=\"(max-width: 960px) 100vw, 960px\"\n      />\n    </span>\n  </span>\n  \n  </a>\n    </p>\n<hr>\n<br/>\n<h2>3. 테스트 해보자</h2>\n<p>간단하게 DB Pool 가진 Springboot 애플리케이션을 만들어서 테스트 해본다.</p>\n<h3>✔️Exec 환경 테스트</h3>\n<ul>\n<li>Exec 방식으로 ENTRYPOINT 를 수행하여 도커 이미지를 빌드한다.</li>\n</ul>\n<div class=\"gatsby-highlight\" data-language=\"docker\"><pre class=\"language-docker\"><code class=\"language-docker\"><span class=\"token keyword\">ENTRYPOINT</span> <span class=\"token punctuation\">[</span><span class=\"token string\">\"java\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"-jar\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"-Dspring.profiles.active=docker\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"/app/check-pid-0.0.1-SNAPSHOT.jar\"</span><span class=\"token punctuation\">]</span></code></pre></div>\n<ul>\n<li>컨테이너 실행 후, PID 확인을 하면 java 가 PID 1 이다.</li>\n</ul>\n<p>\n  <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/devHistoryBlog/static/f2537a1caade4a7d2592be5c5aa11d03/bd9eb/06.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n  \n  <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 960px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 10.833333333333334%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAACCAYAAABYBvyLAAAACXBIWXMAABYlAAAWJQFJUiTwAAAAjUlEQVQI12OQ1lL+L6er9l9ZTeu/mqbuf00d/f/GZlZA2gDMV1TR/C+rIPtfSlbmv4i4zH9RCSCWhNJALCYpCxSXAtO8/EL/GYKjM/4n59b9D4rN/h8Ul/0/NCHnfwiQ9g5L/u8WEPPf1T8aSMf9dw+K/+8eGAsWcw+KA9NuQL5HcPx/Z58IMK1rYvMfAHnFQz93mcG8AAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n    >\n      <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;\"\n        alt=\"06\"\n        title=\"\"\n        src=\"/devHistoryBlog/static/f2537a1caade4a7d2592be5c5aa11d03/d9199/06.png\"\n        srcset=\"/devHistoryBlog/static/f2537a1caade4a7d2592be5c5aa11d03/8ff5a/06.png 240w,\n/devHistoryBlog/static/f2537a1caade4a7d2592be5c5aa11d03/e85cb/06.png 480w,\n/devHistoryBlog/static/f2537a1caade4a7d2592be5c5aa11d03/d9199/06.png 960w,\n/devHistoryBlog/static/f2537a1caade4a7d2592be5c5aa11d03/07a9c/06.png 1440w,\n/devHistoryBlog/static/f2537a1caade4a7d2592be5c5aa11d03/bd9eb/06.png 1442w\"\n        sizes=\"(max-width: 960px) 100vw, 960px\"\n      />\n    </span>\n  </span>\n  \n  </a>\n    </p>\n<ul>\n<li>해당 컨테이너에 SIGTERM 신호를 보내면</li>\n</ul>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\">docker <span class=\"token function\">kill</span> --signal<span class=\"token operator\">=</span>SIGTERM check-pid-exec</code></pre></div>\n<ul>\n<li>start 로그 이후에 DB Pool이 정리되는 로그가 보인다.</li>\n</ul>\n<p>\n  <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/devHistoryBlog/static/80dabbbf097b0d505cc38fa57fe59f81/b4904/07.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n  \n  <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 960px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 11.249999999999998%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAACCAYAAABYBvyLAAAACXBIWXMAABYlAAAWJQFJUiTwAAAAdElEQVQI1z2J2QrCMBQFL27dshcLfdS4pEmjpeL/f9oxXLAPw3DOUEhvTPOC+PpsTHll0vLFLWRc7hHXRypE+GIf5kLm79/8M7FpGEe44QwpWgjR4bDfoWsbKClgjUbv7LZl6c4a3kQErSSaumIbrVCdjvgBkg40dJgfgeAAAAAASUVORK5CYII='); background-size: cover; display: block;\"\n    >\n      <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;\"\n        alt=\"07\"\n        title=\"\"\n        src=\"/devHistoryBlog/static/80dabbbf097b0d505cc38fa57fe59f81/d9199/07.png\"\n        srcset=\"/devHistoryBlog/static/80dabbbf097b0d505cc38fa57fe59f81/8ff5a/07.png 240w,\n/devHistoryBlog/static/80dabbbf097b0d505cc38fa57fe59f81/e85cb/07.png 480w,\n/devHistoryBlog/static/80dabbbf097b0d505cc38fa57fe59f81/d9199/07.png 960w,\n/devHistoryBlog/static/80dabbbf097b0d505cc38fa57fe59f81/07a9c/07.png 1440w,\n/devHistoryBlog/static/80dabbbf097b0d505cc38fa57fe59f81/b4904/07.png 1768w\"\n        sizes=\"(max-width: 960px) 100vw, 960px\"\n      />\n    </span>\n  </span>\n  \n  </a>\n    </p>\n<br/>\n<h3>✔️Shell 환경 테스트</h3>\n<ul>\n<li>Shell 방식으로 ENTRYPOINT 를 수행하여 도커 이미지를 빌드한다.</li>\n</ul>\n<div class=\"gatsby-highlight\" data-language=\"docker\"><pre class=\"language-docker\"><code class=\"language-docker\"><span class=\"token keyword\">ENTRYPOINT</span> java \\\n  <span class=\"token punctuation\">-</span>Dspring.profiles.active=$<span class=\"token punctuation\">{</span>APP_PHASE<span class=\"token punctuation\">:</span><span class=\"token punctuation\">-</span>docker<span class=\"token punctuation\">}</span> \\\n  <span class=\"token punctuation\">-</span>jar /app/check<span class=\"token punctuation\">-</span>pid<span class=\"token punctuation\">-</span>0.0.1<span class=\"token punctuation\">-</span>SNAPSHOT.jar</code></pre></div>\n<ul>\n<li>컨테이너 실행 후, PID 확인을 하면 java PID는 7 이고, 이를 수행하는 /bin/sh 이 PID 1 이다.</li>\n</ul>\n<p>\n  <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/devHistoryBlog/static/a17aff22f24a98f1dfbcc4ad11572163/6fa81/08.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n  \n  <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 960px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 10%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAACCAYAAABYBvyLAAAACXBIWXMAABYlAAAWJQFJUiTwAAAAjUlEQVQI1x2L2QqCUAAF/YhKr9clbRMiCHooyjb1huaCRCvU/3/GpD4Mwxk4mvQ9DN/B9SZMgzmL5Qp/PGsIcDwXISW6sDGkg7BcDNOmr5v0BqLbpj3sbLmjzlp2+5HWX6L8gSpfJMWTzSlruBImFduo4HCp2auKXVwQqrblrI8p5+yOqj7Eza91Ur75A5SCP/5mCeTzAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n    >\n      <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;\"\n        alt=\"08\"\n        title=\"\"\n        src=\"/devHistoryBlog/static/a17aff22f24a98f1dfbcc4ad11572163/d9199/08.png\"\n        srcset=\"/devHistoryBlog/static/a17aff22f24a98f1dfbcc4ad11572163/8ff5a/08.png 240w,\n/devHistoryBlog/static/a17aff22f24a98f1dfbcc4ad11572163/e85cb/08.png 480w,\n/devHistoryBlog/static/a17aff22f24a98f1dfbcc4ad11572163/d9199/08.png 960w,\n/devHistoryBlog/static/a17aff22f24a98f1dfbcc4ad11572163/07a9c/08.png 1440w,\n/devHistoryBlog/static/a17aff22f24a98f1dfbcc4ad11572163/6fa81/08.png 1856w\"\n        sizes=\"(max-width: 960px) 100vw, 960px\"\n      />\n    </span>\n  </span>\n  \n  </a>\n    </p>\n<ul>\n<li>해당 컨테이너에 SIGTERM 신호를 보내면</li>\n</ul>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\">docker <span class=\"token function\">kill</span> --signal<span class=\"token operator\">=</span>SIGTERM check-pid-exec</code></pre></div>\n<ul>\n<li>아무런 반응이 없다. 애플리케이션 종료가 안된다.</li>\n</ul>\n<p>\n  <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/devHistoryBlog/static/ba2c636da4f737b5894a0d0a0ab3e89b/9c1e6/09.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n  \n  <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 960px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 12.5%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAADCAYAAACTWi8uAAAACXBIWXMAABYlAAAWJQFJUiTwAAAAiklEQVQI102L2wrCMBBEg9m8WhObXqCfoq2i1AvUau2D4P9/x7gbmuDDYYc5s6rtn2gvL+z5dtcJh9vMecTxPuM0fJbuDdl1vNudH2nbj99wxUkvqI0rIGTOw+YlUyGzHs7X8FUDuy1DL15Y2zwg2RV18NHJnzJEMKQDtCAdac56lXqTIMSf6P/dD7DrUgehMSidAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n    >\n      <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;\"\n        alt=\"09\"\n        title=\"\"\n        src=\"/devHistoryBlog/static/ba2c636da4f737b5894a0d0a0ab3e89b/d9199/09.png\"\n        srcset=\"/devHistoryBlog/static/ba2c636da4f737b5894a0d0a0ab3e89b/8ff5a/09.png 240w,\n/devHistoryBlog/static/ba2c636da4f737b5894a0d0a0ab3e89b/e85cb/09.png 480w,\n/devHistoryBlog/static/ba2c636da4f737b5894a0d0a0ab3e89b/d9199/09.png 960w,\n/devHistoryBlog/static/ba2c636da4f737b5894a0d0a0ab3e89b/07a9c/09.png 1440w,\n/devHistoryBlog/static/ba2c636da4f737b5894a0d0a0ab3e89b/9c1e6/09.png 1734w\"\n        sizes=\"(max-width: 960px) 100vw, 960px\"\n      />\n    </span>\n  </span>\n  \n  </a>\n    </p>\n<ul>\n<li>해당 컨테이너 종료 명령어를 수행하면</li>\n</ul>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\">docker stop check-pid-exec</code></pre></div>\n<ul>\n<li>SIGTERM 신호를 전달하고 10초간 대기 후 SIGKILL 신호를 전달하여 강제 종료한다. (start 로그 이후에 아무런 로그가 없다.)</li>\n</ul>\n<p>\n  <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/devHistoryBlog/static/882e4de08fc6b1aed471b358982a706e/baa75/10.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n  \n  <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 960px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 11.249999999999998%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAACCAYAAABYBvyLAAAACXBIWXMAABYlAAAWJQFJUiTwAAAARElEQVQI12NQ1zb8D8a6xmCsoWvyX13HCIiBbD1TIN8YzIfRakC1WvqmQGwGVQcR09QzAetlYObh+c/AxfWfgYGBKhgAc5kylKz+3/8AAAAASUVORK5CYII='); background-size: cover; display: block;\"\n    >\n      <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;\"\n        alt=\"10\"\n        title=\"\"\n        src=\"/devHistoryBlog/static/882e4de08fc6b1aed471b358982a706e/d9199/10.png\"\n        srcset=\"/devHistoryBlog/static/882e4de08fc6b1aed471b358982a706e/8ff5a/10.png 240w,\n/devHistoryBlog/static/882e4de08fc6b1aed471b358982a706e/e85cb/10.png 480w,\n/devHistoryBlog/static/882e4de08fc6b1aed471b358982a706e/d9199/10.png 960w,\n/devHistoryBlog/static/882e4de08fc6b1aed471b358982a706e/07a9c/10.png 1440w,\n/devHistoryBlog/static/882e4de08fc6b1aed471b358982a706e/baa75/10.png 1746w\"\n        sizes=\"(max-width: 960px) 100vw, 960px\"\n      />\n    </span>\n  </span>\n  \n  </a>\n    </p>\n<hr>\n<h2>4. 애플리케이션이 SIGKILL 신호를 못받으면 무엇이 문제가 될까?</h2>\n<h3>✔️ 맺고 있었던 DB 커넥션 등이 클라이언트에서 강제 종료가 된다.</h3>\n<ul>\n<li>애플리케이션(클라이언트)에서 커넥션이 강제 종료 되면, 클라이언트가 보낸 데이터가 DB에 적용되지 않을 수 있고,</li>\n<li>클라이언트가 트랜잭션을 진행 중이었다면, 해당 트랜잭션은 롤백될 수 있다.</li>\n<li>또한, 강제로 종료된 커넥션은 DB 입장에서 종료되지 않은 상태로 남아있을 수 있어 자원 누수로 이어질 수 있다.</li>\n</ul>\n<p>실제 Shell 환경 테스트를 진행해보면, DB에 클라이언트가 비정상적으로 종료된 흔적이 남는다.</p>\n<div class=\"gatsby-highlight\" data-language=\"sql\"><pre class=\"language-sql\"><code class=\"language-sql\"><span class=\"token keyword\">SHOW</span> <span class=\"token keyword\">STATUS</span> <span class=\"token operator\">LIKE</span> <span class=\"token string\">'Aborted%'</span><span class=\"token punctuation\">;</span></code></pre></div>\n<ul>\n<li><code class=\"language-text\">Aborted_clients</code>: 클라이언트가 비정상적으로 종료되어 서버가 연결을 중단한 횟수</li>\n<li><code class=\"language-text\">Aborted_connects</code>: MySQL 서버에 접속을 시도했으나 실패한 연결 횟수</li>\n</ul>\n<p>\n  <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/devHistoryBlog/static/0916035b6f88afceddebf7b9290f26ce/6e6fb/11.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n  \n  <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 618px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 52.916666666666664%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAABYlAAAWJQFJUiTwAAABVklEQVQoz3WT25KCQAxEUUREUS4iIl4QQSyf/f9va+tkd/ZhCx5SmSFJpzsZvLIsdTwetVwutd/v9Xq9lOe52fV6VV3XCsNQh8PB8larlS6Xi8Wpvd1uStNUs9lMnufJezwewqIo0ul00ufzsULOwzCo6zrFcaymaczIoylxGr7fbxVFocVi8QO4Xq8VBIF98H3/7zyfz+0Mu81mY0DEiaGGOgP4b8g8n89Gn45Iy7JMbduaFJIAAZR4VVXGGNBRwO12qyRJhAcIEM4AA8JsmBtGHHkAwnwUcLfbGQASSMQDBANi3AHDA8gokD4pGQnP59MY3e93kwQLhs42nWyakOcKJxkyu77vDZAngAeUswNlObBDiSucnCFy3GadNO4UYG7TGDnuPikZSbBgMcwMDzMkureGCr7zGgBiUcxxFJBuPB0AYMh7owns8PwRLIvv5MFwFOjXviWi+kiB0RiaAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n    >\n      <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;\"\n        alt=\"11\"\n        title=\"\"\n        src=\"/devHistoryBlog/static/0916035b6f88afceddebf7b9290f26ce/6e6fb/11.png\"\n        srcset=\"/devHistoryBlog/static/0916035b6f88afceddebf7b9290f26ce/8ff5a/11.png 240w,\n/devHistoryBlog/static/0916035b6f88afceddebf7b9290f26ce/e85cb/11.png 480w,\n/devHistoryBlog/static/0916035b6f88afceddebf7b9290f26ce/6e6fb/11.png 618w\"\n        sizes=\"(max-width: 618px) 100vw, 618px\"\n      />\n    </span>\n  </span>\n  \n  </a>\n    </p>\n<br/>\n<h3>✔️ 애플리케이션 종료 리스너가 수행하지 않는다.</h3>\n<ul>\n<li>애플리케이션이 종료될때 이벤트 리스너를 받아 필요한 로직을 수행하는 경우가 있을 것이다.</li>\n<li>애플리케이션이 강제 종료되면, 리스너 수행이 되지 않아 문제가 된다.</li>\n</ul>\n<p>\n  <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/devHistoryBlog/static/c90d1fdc8048cde5a574336e5dbebb45/f0293/12.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n  \n  <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 960px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 10%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAACCAYAAABYBvyLAAAACXBIWXMAABYlAAAWJQFJUiTwAAAAiElEQVQI1x2K6QqCQAAGe4AwSwvNMwsiCIs0j1VrNex6//eZtv0xDN8xKZuBQpELSZoL8lpyLjoy0VPfnzTDh3b4Ivo3mdpq+dLdP5fdSHUbKdoHl0pyurZMtseUeH/AcT3slaPthzFxsmPth5og2uAFEdbS0dn1AtUl6u9imBazua28YGqY/AAyMDwnLiQTRAAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n    >\n      <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;\"\n        alt=\"12\"\n        title=\"\"\n        src=\"/devHistoryBlog/static/c90d1fdc8048cde5a574336e5dbebb45/d9199/12.png\"\n        srcset=\"/devHistoryBlog/static/c90d1fdc8048cde5a574336e5dbebb45/8ff5a/12.png 240w,\n/devHistoryBlog/static/c90d1fdc8048cde5a574336e5dbebb45/e85cb/12.png 480w,\n/devHistoryBlog/static/c90d1fdc8048cde5a574336e5dbebb45/d9199/12.png 960w,\n/devHistoryBlog/static/c90d1fdc8048cde5a574336e5dbebb45/07a9c/12.png 1440w,\n/devHistoryBlog/static/c90d1fdc8048cde5a574336e5dbebb45/29114/12.png 1920w,\n/devHistoryBlog/static/c90d1fdc8048cde5a574336e5dbebb45/f0293/12.png 2250w\"\n        sizes=\"(max-width: 960px) 100vw, 960px\"\n      />\n    </span>\n  </span>\n  \n  </a>\n    </p>\n<br/>\n<h3>✔️ 기타</h3>\n<ul>\n<li>애플리케이션이 강제 종료되면, 메모리 누수, 파일 디스크립터 누수 등의 문제를 초래할 수 있고,</li>\n<li>서비스가 갑자기 중단되므로 해당 서비스의 가용성이 저하된다.</li>\n</ul>","fields":{"tagSlugs":["/tags/k-8-s/","/tags/docker/"],"slug":"/works/posts/2025-03-10--001"},"frontmatter":{"title":"당신의 파드는 graceful 하게 종료되고 있을까?","tags":["k8s","docker"],"date":"2025-03-10","description":""}}},"pageContext":{"slug":"/works/posts/2025-03-10--001"}},"staticQueryHashes":[]}