{"id":50,"date":"2026-05-16T16:43:24","date_gmt":"2026-05-16T08:43:24","guid":{"rendered":"https:\/\/blog.kwitsukasa.top\/?p=50"},"modified":"2026-05-17T11:15:07","modified_gmt":"2026-05-17T03:15:07","slug":"%e9%a3%9e%e7%89%9b-nas-docker%e3%80%81jenkins-%e4%b8%8e-k3d-k8s-%e4%b8%80%e4%bd%93%e5%8c%96%e6%8a%80%e6%9c%af%e6%96%b9%e6%a1%88","status":"publish","type":"post","link":"https:\/\/blog.kwitsukasa.top\/?p=50","title":{"rendered":"\u98de\u725b NAS Docker\u3001Jenkins \u4e0e k3d\/K8s \u4e00\u4f53\u5316\u6280\u672f\u65b9\u6848"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\"><strong>\u8bf4\u660e\uff1a<\/strong>\u672c\u6587\u4e3a\u8131\u654f\u7248\u6280\u672f\u65b9\u6848\u3002\u9879\u76ee\u540d\u3001\u4ed3\u5e93\u5730\u5740\u3001\u7aef\u53e3\u3001\u76ee\u5f55\u3001\u57df\u540d\u3001\u5185\u7f51\u5730\u5740\u3001\u4e3b\u673a\u540d\u548c\u5bc6\u94a5\u8def\u5f84\u5747\u4f7f\u7528\u901a\u7528\u5360\u4f4d\u7b26\uff0c\u843d\u5730\u65f6\u8bf7\u66ff\u6362\u4e3a\u81ea\u5df1\u7684\u5b9e\u9645\u73af\u5883\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">1. \u65b9\u6848\u6458\u8981<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">\u672c\u65b9\u6848\u9762\u5411\u5c0f\u578b\u79c1\u6709\u5316\u90e8\u7f72\u573a\u666f\uff0c\u76ee\u6807\u662f\u5728\u98de\u725b NAS \u4e0a\u628a Docker\u3001Jenkins\u3001\u524d\u7aef\u9759\u6001\u53d1\u5e03\u548c\u540e\u7aef API \u5bb9\u5668\u53d1\u5e03\u6574\u5408\u6210\u4e00\u5957\u53ef\u6301\u7eed\u8fed\u4ee3\u7684\u6807\u51c6\u6d41\u7a0b\u3002<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u98de\u725b NAS \u4f5c\u4e3a\u5185\u7f51\u8ba1\u7b97\u4e0e\u6570\u636e\u627f\u8f7d\u8282\u70b9\u3002<\/li>\n\n\n\n<li>Docker \u627f\u8f7d Jenkins Controller\u3001Jenkins Agent\u3001\u672c\u5730 Registry\u3001Nginx\u3001\u6570\u636e\u5e93\u3001\u5bf9\u8c61\u5b58\u50a8\u7b49\u57fa\u7840\u5bb9\u5668\u3002<\/li>\n\n\n\n<li>\u540e\u7aef API \u8fc1\u5165 NAS \u672c\u673a\u7684 k3d\/K3s \u96c6\u7fa4\uff0c\u7531 Jenkins \u6784\u5efa\u955c\u50cf\u5e76\u6eda\u52a8\u53d1\u5e03\u3002<\/li>\n\n\n\n<li>\u524d\u7aef Web \u4e0e Playground \u6682\u65f6\u7ee7\u7eed\u8d70 Nginx \u9759\u6001\u76ee\u5f55\u53d1\u5e03\u3002<\/li>\n\n\n\n<li>\u516c\u7f51\u5165\u53e3\u7531\u4e91\u670d\u52a1\u5668\u4e2d\u8f6c\u8282\u70b9\u627f\u63a5\uff0c\u5bb6\u5ead NAS \u4e0d\u76f4\u63a5\u66b4\u9732 80\/443\u3002<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">\u8fd9\u662f\u4e00\u5957\u201c\u5148\u7a33\u5b9a\u3001\u518d\u6f14\u8fdb\u201d\u7684\u65b9\u6848\uff1a\u5148\u628a\u540e\u7aef API \u6807\u51c6\u5316\u63a5\u5165 K8s\uff0c\u8ba9\u53d1\u5e03\u3001\u56de\u6eda\u3001\u5bc6\u94a5\u6ce8\u5165\u3001\u8fd0\u884c\u72b6\u6001\u89c2\u6d4b\u5177\u5907\u7edf\u4e00\u5165\u53e3\uff1b\u540e\u7eed\u518d\u9010\u6b65\u628a\u524d\u7aef\u3001Ingress\u3001\u76d1\u63a7\u548c\u5907\u4efd\u7eb3\u5165\u540c\u4e00\u5957\u5e73\u53f0\u80fd\u529b\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">2. \u5efa\u8bbe\u76ee\u6807<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">2.1 \u4e1a\u52a1\u76ee\u6807<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u5f62\u6210\u540e\u7aef API \u4ece\u4ee3\u7801\u63d0\u4ea4\u5230 NAS K8s \u4e0a\u7ebf\u7684\u6807\u51c6\u6d41\u6c34\u7ebf\u3002<\/li>\n\n\n\n<li>\u4fdd\u6301\u73b0\u6709\u516c\u7f51\u8bbf\u95ee\u65b9\u5f0f\u57fa\u672c\u4e0d\u53d8\uff0c\u964d\u4f4e\u5207\u6362\u98ce\u9669\u3002<\/li>\n\n\n\n<li>\u4fdd\u7559\u524d\u7aef\u73b0\u6709 Nginx \u9759\u6001\u53d1\u5e03\u6a21\u5f0f\uff0c\u907f\u514d\u4e00\u6b21\u6027\u8fc1\u79fb\u8303\u56f4\u8fc7\u5927\u3002<\/li>\n\n\n\n<li>\u8ba9\u53d1\u5e03\u5931\u8d25\u53ef\u56de\u6eda\u3001\u8fd0\u884c\u72b6\u6001\u53ef\u6392\u67e5\u3001\u751f\u4ea7\u73af\u5883\u53d8\u91cf\u4e0d\u8fdb\u5165 Git\u3002<\/li>\n\n\n\n<li>\u8ba9\u672a\u6765\u65b0\u589e\u670d\u52a1\u53ef\u4ee5\u590d\u7528\u540c\u4e00\u5957\u547d\u540d\u3001\u76ee\u5f55\u3001\u7aef\u53e3\u3001\u955c\u50cf\u548c Jenkins \u6d41\u6c34\u7ebf\u89c4\u8303\u3002<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">2.2 \u6280\u672f\u76ee\u6807<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Jenkins \u53ea\u8d1f\u8d23 CI\/CD \u7f16\u6392\uff0c\u4e0d\u76f4\u63a5\u4fdd\u5b58\u771f\u5b9e\u751f\u4ea7\u914d\u7f6e\u3002<\/li>\n\n\n\n<li>Jenkins Agent \u5177\u5907 Node.js\u3001pnpm\u3001Docker CLI\u3001kubectl \u7b49\u6784\u5efa\u53d1\u5e03\u80fd\u529b\u3002<\/li>\n\n\n\n<li>Docker \u672c\u5730 Registry \u56fa\u5b9a\u5728 NAS\uff0c\u51cf\u5c11\u53d1\u5e03\u65f6\u5bf9\u516c\u7f51\u955c\u50cf\u4ed3\u5e93\u7684\u4f9d\u8d56\u3002<\/li>\n\n\n\n<li>K8s \u8fd0\u884c\u6001\u4f7f\u7528 Deployment + Service\uff0c\u9ed8\u8ba4\u652f\u6301\u6eda\u52a8\u66f4\u65b0\u548c <code>rollout undo<\/code>\u3002<\/li>\n\n\n\n<li>\u751f\u4ea7\u73af\u5883\u53d8\u91cf\u4ece Agent \u79c1\u6709\u6587\u4ef6\u751f\u6210 K8s Secret\uff0c\u505a\u5230 Git \u4e0e\u771f\u5b9e\u914d\u7f6e\u9694\u79bb\u3002<\/li>\n\n\n\n<li>\u6240\u6709\u4e00\u6b21\u6027\u521d\u59cb\u5316\u52a8\u4f5c\u811a\u672c\u5316\uff0c\u51cf\u5c11\u624b\u5de5\u6b65\u9aa4\u6f02\u79fb\u3002<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">3. \u603b\u4f53\u67b6\u6784<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">\u6574\u4f53\u94fe\u8def\u53ef\u4ee5\u62c6\u6210\u56db\u5c42\uff1a\u516c\u7f51\u5165\u53e3\u5c42\u3001NAS Docker \u63a7\u5236\u5c42\u3001NAS K8s \u8fd0\u884c\u5c42\u548c\u5e94\u7528\u5c42\u3002<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">\u5f00\u53d1\u8005 \/ Git push\n  -&gt; Git \u4ed3\u5e93 [GIT_REPO]\n  -&gt; Jenkins Controller\n  -&gt; Jenkins Agent\n  -&gt; pnpm install \/ lint \/ test \/ build\n  -&gt; docker build \u4e1a\u52a1\u955c\u50cf\n  -&gt; NAS \u672c\u5730 Registry\n  -&gt; kubectl apply \/ set image \/ rollout status\n  -&gt; k3d\/K3s \u96c6\u7fa4\n  -&gt; \u540e\u7aef API Pod\n  -&gt; NAS API \u7aef\u53e3\n\n\u524d\u7aef Web \/ Playground\n  -&gt; Jenkins \u6784\u5efa\u9759\u6001\u4ea7\u7269\n  -&gt; Nginx \u9759\u6001\u76ee\u5f55\n  -&gt; NAS \u524d\u7aef\u7aef\u53e3\n\n\u516c\u7f51\u8bbf\u95ee\n  -&gt; \u4e91\u670d\u52a1\u5668\u4e2d\u8f6c\u8282\u70b9\n  -&gt; VPN \u6216\u5185\u7f51\u8f6c\u53d1\u94fe\u8def\n  -&gt; NAS \u670d\u52a1\u7aef\u53e3<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">3.1 \u5206\u5c42\u804c\u8d23<\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th class=\"has-text-align-left\" data-align=\"left\">\u5c42\u7ea7<\/th><th class=\"has-text-align-left\" data-align=\"left\">\u627f\u8f7d\u5bf9\u8c61<\/th><th class=\"has-text-align-left\" data-align=\"left\">\u804c\u8d23<\/th><\/tr><\/thead><tbody><tr><td>\u516c\u7f51\u5165\u53e3\u5c42<\/td><td>\u4e91\u670d\u52a1\u5668\u4e2d\u8f6c\u8282\u70b9\u3001\u53cd\u5411\u4ee3\u7406\u3001VPN \u96a7\u9053<\/td><td>\u516c\u7f51 TLS\u3001\u57df\u540d\u5165\u53e3\u3001\u8f6c\u53d1\u5230 NAS<\/td><\/tr><tr><td>NAS Docker \u63a7\u5236\u5c42<\/td><td>Jenkins\u3001Agent\u3001Registry\u3001Nginx\u3001\u6570\u636e\u5e93\u3001\u5bf9\u8c61\u5b58\u50a8<\/td><td>\u6784\u5efa\u3001\u53d1\u5e03\u3001\u57fa\u7840\u670d\u52a1\u548c\u9759\u6001\u8d44\u6e90<\/td><\/tr><tr><td>NAS K8s \u8fd0\u884c\u5c42<\/td><td>k3d\/K3s<\/td><td>\u540e\u7aef API \u5de5\u4f5c\u8d1f\u8f7d\u3001\u6eda\u52a8\u66f4\u65b0\u3001\u56de\u6eda<\/td><\/tr><tr><td>\u5e94\u7528\u5c42<\/td><td>API\u3001Web\u3001Playground<\/td><td>\u4e1a\u52a1\u63a5\u53e3\u3001\u524d\u53f0\u5c55\u793a\u3001\u53ef\u89c6\u5316\u7f16\u8f91\u5668<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">3.2 \u4e3a\u4ec0\u4e48\u91c7\u7528 k3d\/K3s<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>NAS \u5df2\u7ecf\u4ee5 Docker \u4e3a\u4e3b\u8981\u8fd0\u884c\u73af\u5883\uff0ck3d \u53ef\u4ee5\u76f4\u63a5\u590d\u7528 Docker\uff0c\u4e0d\u9700\u8981\u989d\u5916\u865a\u62df\u673a\u3002<\/li>\n\n\n\n<li>K3s \u8f7b\u91cf\uff0c\u9002\u5408\u5bb6\u5ead NAS \u6216\u5c0f\u578b\u79c1\u6709\u5316\u90e8\u7f72\u3002<\/li>\n\n\n\n<li>k3d \u53ef\u4ee5\u628a\u96c6\u7fa4 API\u3001NodePort\u3001Registry \u6807\u51c6\u5316\u5728 Docker \u7f51\u7edc\u5185\u3002<\/li>\n\n\n\n<li>\u5bf9\u73b0\u6709 Docker \u670d\u52a1\u5f71\u54cd\u8f83\u5c0f\uff0c\u53ef\u4ee5\u5148\u8fc1\u79fb\u540e\u7aef API\uff0c\u540e\u7eed\u518d\u6269\u5c55\u5176\u4ed6\u670d\u52a1\u3002<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">4. \u547d\u540d\u4e0e\u8d44\u6e90\u89c4\u8303<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">\u516c\u5f00\u65b9\u6848\u4e2d\u4f7f\u7528\u901a\u7528\u547d\u540d\u3002\u5b9e\u9645\u843d\u5730\u65f6\u5efa\u8bae\u56fa\u5b9a\u547d\u540d\uff0c\u907f\u514d Jenkins \u53c2\u6570\u3001K8s manifest\u3001Nginx \u914d\u7f6e\u548c\u8fd0\u7ef4\u811a\u672c\u4e4b\u95f4\u51fa\u73b0\u6f02\u79fb\u3002<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th class=\"has-text-align-left\" data-align=\"left\">\u5bf9\u8c61<\/th><th class=\"has-text-align-left\" data-align=\"left\">\u793a\u4f8b\u547d\u540d<\/th><\/tr><\/thead><tbody><tr><td>Jenkins Agent \u8282\u70b9<\/td><td><code>app-node-agent<\/code><\/td><\/tr><tr><td>Jenkins Agent \u955c\u50cf<\/td><td><code>app-jenkins-agent:node22<\/code><\/td><\/tr><tr><td>k3d \u96c6\u7fa4<\/td><td><code>app-nas<\/code><\/td><\/tr><tr><td>K8s namespace<\/td><td><code>app-prod<\/code><\/td><\/tr><tr><td>\u672c\u5730 Registry<\/td><td><code>[REGISTRY_HOST]:[REGISTRY_PORT]<\/code><\/td><\/tr><tr><td>API \u955c\u50cf<\/td><td><code>[REGISTRY_HOST]:[REGISTRY_PORT]\/backend-api:&lt;tag&gt;<\/code><\/td><\/tr><tr><td>API Deployment<\/td><td><code>backend-api<\/code><\/td><\/tr><tr><td>API env Secret<\/td><td><code>backend-api-env<\/code><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">5. \u7aef\u53e3\u4e0e\u76ee\u5f55\u89c4\u8303<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">5.1 \u7aef\u53e3\u89c4\u8303<\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th class=\"has-text-align-left\" data-align=\"left\">\u670d\u52a1<\/th><th class=\"has-text-align-left\" data-align=\"left\">NAS \u7aef\u53e3<\/th><th class=\"has-text-align-left\" data-align=\"left\">\u5bb9\u5668\/K8s \u7aef\u53e3<\/th><th class=\"has-text-align-left\" data-align=\"left\">\u8bf4\u660e<\/th><\/tr><\/thead><tbody><tr><td>API<\/td><td><code>[API_HOST_PORT]<\/code><\/td><td><code>[API_CONTAINER_PORT]<\/code><\/td><td>\u7531 k3d loadbalancer \u6620\u5c04\u5230 NodePort<\/td><\/tr><tr><td>API NodePort<\/td><td><code>[API_NODE_PORT]<\/code><\/td><td><code>[API_CONTAINER_PORT]<\/code><\/td><td>K8s Service NodePort<\/td><\/tr><tr><td>Web<\/td><td><code>[WEB_HOST_PORT]<\/code><\/td><td><code>[WEB_CONTAINER_PORT]<\/code><\/td><td>Nginx \u9759\u6001\u670d\u52a1<\/td><\/tr><tr><td>Playground<\/td><td><code>[PLAYGROUND_HOST_PORT]<\/code><\/td><td><code>[PLAYGROUND_CONTAINER_PORT]<\/code><\/td><td>Nginx \u9759\u6001\u670d\u52a1<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">5.2 \u76ee\u5f55\u89c4\u8303<\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th class=\"has-text-align-left\" data-align=\"left\">\u8def\u5f84<\/th><th class=\"has-text-align-left\" data-align=\"left\">\u7528\u9014<\/th><\/tr><\/thead><tbody><tr><td><code>[DATA_ROOT]\/app-k8s<\/code><\/td><td>K8s \u6807\u51c6\u5316\u6839\u76ee\u5f55<\/td><\/tr><tr><td><code>[DATA_ROOT]\/app-k8s\/registry<\/code><\/td><td>\u672c\u5730 Registry \u6570\u636e<\/td><\/tr><tr><td><code>[DATA_ROOT]\/app-k8s\/kubeconfig<\/code><\/td><td>host \u4e0e Agent kubeconfig<\/td><\/tr><tr><td><code>[AGENT_WORKDIR]\/env\/backend-api\/.env.production<\/code><\/td><td>Agent \u5185 API \u751f\u4ea7\u73af\u5883\u53d8\u91cf<\/td><\/tr><tr><td><code>[AGENT_WORKDIR]\/kubeconfig\/app-nas.jenkins.yaml<\/code><\/td><td>Agent \u5185 kubeconfig<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">6. Jenkins \u6d41\u6c34\u7ebf\u8bbe\u8ba1<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">6.1 \u53d1\u5e03\u76ee\u6807<\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th class=\"has-text-align-left\" data-align=\"left\">DEPLOY_TARGET<\/th><th class=\"has-text-align-left\" data-align=\"left\">\u884c\u4e3a<\/th><\/tr><\/thead><tbody><tr><td><code>k8s<\/code><\/td><td>\u6807\u51c6\u6a21\u5f0f\uff0c\u6784\u5efa\u955c\u50cf\u3001\u63a8\u9001\u672c\u5730 Registry\u3001\u6eda\u52a8\u66f4\u65b0 K8s<\/td><\/tr><tr><td><code>docker<\/code><\/td><td>\u517c\u5bb9\u65e7\u6a21\u5f0f\uff0c\u6784\u5efa\u955c\u50cf\u540e\u7528 docker run \u66ff\u6362\u65e7\u5bb9\u5668<\/td><\/tr><tr><td><code>none<\/code><\/td><td>\u53ea\u505a CI\uff0c\u4e0d\u6784\u5efa\u6216\u53d1\u5e03\u955c\u50cf<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<pre class=\"wp-block-preformatted\">\u6807\u51c6\u751f\u4ea7\u53d1\u5e03\u53c2\u6570\uff1a\n\nDEPLOY_TARGET=k8s\nBUILD_DOCKER_IMAGE=true\nPUSH_DOCKER_IMAGE=true\nDOCKER_REGISTRY=[REGISTRY_HOST]:[REGISTRY_PORT]\nIMAGE_NAME=backend-api\nCONTAINER_ENV_FILE=[AGENT_WORKDIR]\/env\/backend-api\/.env.production\nKUBE_CONFIG_FILE=[AGENT_WORKDIR]\/kubeconfig\/app-nas.jenkins.yaml\nK8S_MANIFEST_FILE=k8s\/prod\/api.yaml\nK8S_NAMESPACE=app-prod\nK8S_DEPLOYMENT=backend-api\nK8S_CONTAINER=api\nK8S_ENV_SECRET=backend-api-env<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">6.2 \u6d41\u6c34\u7ebf\u9636\u6bb5<\/h3>\n\n\n\n<pre class=\"wp-block-preformatted\">Checkout\n  -&gt; Prepare\n  -&gt; Install\n  -&gt; Lint\n  -&gt; Test\n  -&gt; Build\n  -&gt; Docker Build\n  -&gt; Docker Push\n  -&gt; K8s Deploy\n  -&gt; Archive Artifacts<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">6.3 \u955c\u50cf\u6807\u7b7e\u7b56\u7565<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">\u9ed8\u8ba4\u955c\u50cf\u6807\u7b7e\u5efa\u8bae\u4f7f\u7528\u5206\u652f\u540d\u52a0 Jenkins \u6784\u5efa\u53f7\uff0c\u4fbf\u4e8e\u6392\u67e5\u548c\u56de\u6eda\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">[REGISTRY_HOST]:[REGISTRY_PORT]\/backend-api:main-28\n[REGISTRY_HOST]:[REGISTRY_PORT]\/backend-api:latest<\/pre>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u5206\u652f\u540d\u9700\u8981\u7ecf\u8fc7 Docker tag \u517c\u5bb9\u5316\u5904\u7406\u3002<\/li>\n\n\n\n<li>PR \u6784\u5efa\u4e0d\u53d1\u5e03\u5230 K8s\u3002<\/li>\n\n\n\n<li>main\u3001master\u3001release\/* \u9ed8\u8ba4\u5141\u8bb8\u53d1\u5e03\u3002<\/li>\n\n\n\n<li>latest \u53ea\u4f5c\u4e3a manifest \u9ed8\u8ba4\u955c\u50cf\u548c\u4eba\u5de5\u6392\u67e5\u8f85\u52a9\uff0c\u771f\u5b9e\u53d1\u5e03\u4ee5\u6784\u5efa tag \u4e3a\u51c6\u3002<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">7. K8s \u8fd0\u884c\u6001\u8bbe\u8ba1<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">7.1 Deployment<\/h3>\n\n\n\n<pre class=\"wp-block-preformatted\">replicas: 1\nstrategy: RollingUpdate\nmaxSurge: 1\nmaxUnavailable: 0\nrevisionHistoryLimit: 5<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">\u5355\u673a NAS \u573a\u666f\u9ed8\u8ba4\u4f7f\u7528\u5355\u526f\u672c\u3002\u672a\u6765\u5982\u679c API \u65e0\u72b6\u6001\u5316\u3001\u6570\u636e\u5e93\u8fde\u63a5\u548c\u4e0a\u4f20\u5b58\u50a8\u90fd\u7a33\u5b9a\u540e\uff0c\u53ef\u4ee5\u6269\u5c55\u5230\u4e24\u4e2a\u6216\u66f4\u591a\u526f\u672c\u3002<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">7.2 Service<\/h3>\n\n\n\n<pre class=\"wp-block-preformatted\">type: NodePort\nport: [API_CONTAINER_PORT]\ntargetPort: [API_CONTAINER_PORT]\nnodePort: [API_NODE_PORT]<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">k3d \u521b\u5efa\u96c6\u7fa4\u65f6\u5c06 NAS \u5bbf\u4e3b\u673a\u7aef\u53e3\u6620\u5c04\u5230 NodePort\u3002\u8fd9\u6837\u5916\u90e8\u4ecd\u7136\u8bbf\u95ee\u539f API \u7aef\u53e3\uff0c\u4e0d\u9700\u8981\u4fee\u6539\u4e91\u670d\u52a1\u5668\u4fa7\u8f6c\u53d1\u89c4\u5219\u3002<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">7.3 \u63a2\u9488\u4e0e\u8d44\u6e90\u9650\u5236<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">\u5f53\u524d\u53ef\u4ee5\u5148\u4f7f\u7528 TCP \u63a2\u9488\uff0c\u4fdd\u8bc1\u5bb9\u5668\u7aef\u53e3\u5df2\u76d1\u542c\u3002\u540e\u7eed\u5efa\u8bae\u65b0\u589e <code>\/health<\/code> \u4e4b\u7c7b\u7684 HTTP \u5065\u5eb7\u68c0\u67e5\u63a5\u53e3\uff0c\u518d\u628a\u63a2\u9488\u6539\u4e3a HTTP GET\u3002<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">readinessProbe: tcpSocket [API_CONTAINER_PORT]\nlivenessProbe: tcpSocket [API_CONTAINER_PORT]\n\nrequests:\n  cpu: 100m\n  memory: 256Mi\nlimits:\n  cpu: 1000m\n  memory: 768Mi<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">8. \u914d\u7f6e\u4e0e\u5bc6\u94a5\u8bbe\u8ba1<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">\u4ed3\u5e93\u53ea\u63d0\u4ea4 <code>.env.example<\/code>\u3002\u771f\u5b9e\u751f\u4ea7\u914d\u7f6e\u653e\u5728 Jenkins Agent \u79c1\u6709\u8def\u5f84\u4e2d\uff0c\u5e76\u901a\u8fc7\u6d41\u6c34\u7ebf\u751f\u6210 K8s Secret\u3002<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">[AGENT_WORKDIR]\/env\/backend-api\/.env.production\n\nkubectl -n app-prod create secret generic backend-api-env \\\n  --from-env-file=[AGENT_WORKDIR]\/env\/backend-api\/.env.production \\\n  --dry-run=client -o yaml | kubectl apply -f -<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">\u8fd9\u79cd\u65b9\u5f0f\u53ef\u4ee5\u8ba9\u73af\u5883\u53d8\u91cf\u53d8\u66f4\u4e0d\u8fdb\u5165 Git\uff0c\u540c\u65f6 Secret \u4e0e Deployment \u66f4\u65b0\u5728\u540c\u4e00\u6761\u6d41\u6c34\u7ebf\u91cc\u5b8c\u6210\u3002\u9700\u8981\u6ce8\u610f\u7684\u662f\uff0cKubernetes \u539f\u751f Secret \u9ed8\u8ba4\u53ea\u662f base64 \u7f16\u7801\uff0c\u4e0d\u7b49\u4e8e\u52a0\u5bc6\u3002\u5355\u673a\u53ef\u4fe1\u73af\u5883\u77ed\u671f\u53ef\u63a5\u53d7\uff0c\u957f\u671f\u5efa\u8bae\u63a5\u5165 SOPS\u3001SealedSecret \u6216\u5916\u90e8 Secret \u7ba1\u7406\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">9. \u521d\u59cb\u5316\u4e0e\u5207\u6362\u65b9\u6848<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">9.1 \u5b89\u5168\u521d\u59cb\u5316<\/h3>\n\n\n\n<pre class=\"wp-block-preformatted\">.\\ci\\fnos-k8s\\run-remote-bootstrap.ps1<\/pre>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u5b89\u88c5\u6216\u786e\u8ba4 k3d\u3002<\/li>\n\n\n\n<li>\u5b89\u88c5\u6216\u786e\u8ba4 kubectl\u3002<\/li>\n\n\n\n<li>\u521b\u5efa\u6807\u51c6\u6570\u636e\u76ee\u5f55\u3002<\/li>\n\n\n\n<li>\u521b\u5efa\u672c\u5730 Registry\u3002<\/li>\n\n\n\n<li>\u5982\u679c API \u7aef\u53e3\u5df2\u88ab\u65e7\u5bb9\u5668\u5360\u7528\uff0c\u5219\u505c\u6b62\u5728\u96c6\u7fa4\u521b\u5efa\u524d\u3002<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">9.2 \u6b63\u5f0f\u5207\u6362<\/h3>\n\n\n\n<pre class=\"wp-block-preformatted\">.\\ci\\fnos-k8s\\run-remote-bootstrap.ps1 -Cutover<\/pre>\n\n\n\n<ol class=\"wp-block-list\">\n<li>\u505c\u6b62\u65e7\u540e\u7aef API Docker \u5bb9\u5668\u3002<\/li>\n\n\n\n<li>\u521b\u5efa k3d \u96c6\u7fa4\uff0c\u5e76\u6620\u5c04 NAS API \u7aef\u53e3\u5230 K8s NodePort\u3002<\/li>\n\n\n\n<li>\u521b\u5efa\u751f\u4ea7 namespace\u3002<\/li>\n\n\n\n<li>\u590d\u5236 kubeconfig \u5230 Jenkins Agent\u3002<\/li>\n\n\n\n<li>\u4ece Agent env \u6587\u4ef6\u521b\u5efa K8s Secret\u3002<\/li>\n\n\n\n<li>\u7531 Jenkins \u6216\u624b\u52a8 kubectl \u90e8\u7f72 API\u3002<\/li>\n<\/ol>\n\n\n\n<h3 class=\"wp-block-heading\">9.3 \u7f51\u7edc\u95ee\u9898\u5904\u7406<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">NAS \u62c9\u53d6 GitHub\u3001Docker Hub\u3001Kubernetes \u5b98\u65b9\u4e8c\u8fdb\u5236\u53ef\u80fd\u8f83\u6162\u3002\u5efa\u8bae\u628a\u57fa\u7840\u4e8c\u8fdb\u5236\u548c\u5173\u952e\u955c\u50cf\u63d0\u524d\u7f13\u5b58\uff0c\u4e1a\u52a1\u955c\u50cf\u4f18\u5148\u63a8\u9001\u5230 NAS \u672c\u5730 Registry\u3002<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>k3d \u548c kubectl \u53ef\u4ee5\u7531\u672c\u673a\u4e0b\u8f7d\u540e\u901a\u8fc7 scp \u4e0a\u4f20\u5230 NAS\u3002<\/li>\n\n\n\n<li>K3s sandbox \u955c\u50cf\u5efa\u8bae\u5728 bootstrap \u4e2d\u4e3b\u52a8\u62c9\u53d6\u5e76\u5bfc\u5165\u96c6\u7fa4\u3002<\/li>\n\n\n\n<li>\u4e1a\u52a1\u955c\u50cf\u53d1\u5e03\u65f6\u63a8\u9001\u672c\u5730 Registry\uff0c\u907f\u514d\u6bcf\u6b21\u53d1\u5e03\u90fd\u4f9d\u8d56\u516c\u7f51\u955c\u50cf\u4ed3\u5e93\u3002<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">10. \u65e5\u5e38\u53d1\u5e03 SOP<\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n<li>\u5f00\u53d1\u8005\u63d0\u4ea4\u4ee3\u7801\u5230\u53d1\u5e03\u5206\u652f\u3002<\/li>\n\n\n\n<li>Jenkins \u591a\u5206\u652f\u6d41\u6c34\u7ebf\u62c9\u53d6\u6700\u65b0 Jenkinsfile\u3002<\/li>\n\n\n\n<li>Jenkins \u6267\u884c install\u3001lint\u3001test\u3001build\u3002<\/li>\n\n\n\n<li>Jenkins \u6784\u5efa\u4e1a\u52a1\u955c\u50cf\u5e76\u63a8\u9001 NAS \u672c\u5730 Registry\u3002<\/li>\n\n\n\n<li>Jenkins \u4ece Agent \u79c1\u6709 env \u6587\u4ef6\u91cd\u5efa K8s Secret\u3002<\/li>\n\n\n\n<li>Jenkins \u66f4\u65b0 Deployment \u955c\u50cf\u5e76\u7b49\u5f85 rollout \u6210\u529f\u3002<\/li>\n\n\n\n<li>\u8fd0\u7ef4\u4eba\u5458\u9a8c\u8bc1 API\u3001\u524d\u7aef\u5165\u53e3\u548c\u6838\u5fc3\u4e1a\u52a1\u63a5\u53e3\u3002<\/li>\n<\/ol>\n\n\n\n<pre class=\"wp-block-preformatted\">\u5e38\u7528\u9a8c\u8bc1\uff1a\n\nkubectl --kubeconfig [HOST_KUBECONFIG] -n app-prod get deploy,pod,svc -o wide\ncurl -sS -i http:\/\/127.0.0.1:[API_HOST_PORT]\/\n\nAgent \u5185\u9a8c\u8bc1\uff1a\n\ndocker exec app-node-agent sh -lc \\\n  'kubectl --kubeconfig [AGENT_KUBECONFIG] -n app-prod get deploy,pod,svc'<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">11. \u56de\u6eda\u65b9\u6848<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">11.1 K8s \u6807\u51c6\u56de\u6eda<\/h3>\n\n\n\n<pre class=\"wp-block-preformatted\">kubectl --kubeconfig [HOST_KUBECONFIG] \\\n  -n app-prod rollout history deployment\/backend-api\n\nkubectl --kubeconfig [HOST_KUBECONFIG] \\\n  -n app-prod rollout undo deployment\/backend-api\n\nkubectl --kubeconfig [HOST_KUBECONFIG] \\\n  -n app-prod rollout status deployment\/backend-api --timeout=180s<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">11.2 \u6307\u5b9a\u955c\u50cf\u56de\u6eda<\/h3>\n\n\n\n<pre class=\"wp-block-preformatted\">kubectl --kubeconfig [HOST_KUBECONFIG] \\\n  -n app-prod set image deployment\/backend-api \\\n  api=[REGISTRY_HOST]:[REGISTRY_PORT]\/backend-api:[TAG]<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">11.3 \u9000\u56de\u65e7 Docker \u6a21\u5f0f<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">\u4ec5\u5728 K8s \u96c6\u7fa4\u4e0d\u53ef\u7528\u4e14\u77ed\u671f\u65e0\u6cd5\u6062\u590d\u65f6\u4f7f\u7528\u3002\u9000\u56de Docker \u6a21\u5f0f\u9700\u8981\u5148\u91ca\u653e NAS API \u7aef\u53e3\uff0c\u518d\u7528\u65e7 Docker \u53c2\u6570\u542f\u52a8\u540e\u7aef\u5bb9\u5668\u3002\u8be5\u65b9\u5f0f\u4f1a\u7ed5\u5f00 K8s \u7684 Deployment \u56de\u6eda\u80fd\u529b\uff0c\u53ea\u5efa\u8bae\u4f5c\u4e3a\u5e94\u6025\u65b9\u6848\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">12. \u8fd0\u7ef4\u4e0e\u6392\u969c<\/h2>\n\n\n\n<pre class=\"wp-block-preformatted\">\u67e5\u770b\u670d\u52a1\u72b6\u6001\uff1a\nkubectl --kubeconfig [HOST_KUBECONFIG] -n app-prod get all\ndocker ps --format '{{.Names}} {{.Status}} {{.Ports}}'\n\n\u67e5\u770b API \u65e5\u5fd7\uff1a\nkubectl --kubeconfig [HOST_KUBECONFIG] \\\n  -n app-prod logs -l app=backend-api --tail=200\n\n\u67e5\u770b\u4e8b\u4ef6\uff1a\nkubectl --kubeconfig [HOST_KUBECONFIG] \\\n  -n app-prod get events --sort-by=.lastTimestamp<\/pre>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th class=\"has-text-align-left\" data-align=\"left\">\u95ee\u9898<\/th><th class=\"has-text-align-left\" data-align=\"left\">\u73b0\u8c61<\/th><th class=\"has-text-align-left\" data-align=\"left\">\u5904\u7406<\/th><\/tr><\/thead><tbody><tr><td>Jenkins \u53c2\u6570\u7f13\u5b58\u65e7\u503c<\/td><td>Registry \u53c2\u6570\u4e3a\u7a7a\u5bfc\u81f4\u53d1\u5e03\u5931\u8d25<\/td><td>Jenkinsfile \u8fd0\u884c\u65f6 fallback \u5230\u672c\u5730 Registry<\/td><\/tr><tr><td>Agent \u7f3a\u5c11 kubectl<\/td><td>\u90e8\u7f72\u9636\u6bb5\u627e\u4e0d\u5230 kubectl<\/td><td>\u91cd\u5efa Agent \u955c\u50cf\u6216\u628a kubectl \u6ce8\u5165\u5f53\u524d\u5bb9\u5668<\/td><\/tr><tr><td>sandbox \u955c\u50cf\u62c9\u53d6\u5931\u8d25<\/td><td>Pod \u5361\u5728 ContainerCreating<\/td><td>\u63d0\u524d\u62c9\u53d6\u5e76\u5bfc\u5165 K3s sandbox \u955c\u50cf<\/td><\/tr><tr><td>Secret \u7f3a\u5931<\/td><td>Pod \u542f\u52a8\u5931\u8d25\u6216 env \u4e0d\u5b8c\u6574<\/td><td>\u786e\u8ba4 Agent env \u6587\u4ef6\u5b58\u5728\u540e\u91cd\u8dd1 Jenkins<\/td><\/tr><tr><td>\u9ed8\u8ba4\u955c\u50cf\u4e0d\u53ef\u62c9<\/td><td>ImagePullBackOff<\/td><td>\u786e\u4fdd latest \u6216\u76ee\u6807 tag \u5df2\u63a8\u9001\u5230\u672c\u5730 Registry<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">13. \u5b89\u5168\u8fb9\u754c<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u5bb6\u5ead NAS \u4e0d\u76f4\u63a5\u66b4\u9732 80\/443\u3002<\/li>\n\n\n\n<li>\u516c\u7f51\u5165\u53e3\u7531\u4e91\u670d\u52a1\u5668\u4e2d\u8f6c\u8282\u70b9\u627f\u63a5\uff0cNAS \u901a\u8fc7\u5185\u7f51\u96a7\u9053\u6216\u8f6c\u53d1\u94fe\u8def\u63d0\u4f9b\u670d\u52a1\u3002<\/li>\n\n\n\n<li>Jenkins Agent \u901a\u8fc7 Docker socket \u63a7\u5236 NAS Docker\uff0c\u4ec5\u653e\u5728\u53ef\u4fe1\u5185\u7f51\u548c\u53ef\u4fe1 Jenkins \u4efb\u52a1\u4e2d\u4f7f\u7528\u3002<\/li>\n\n\n\n<li>\u771f\u5b9e\u751f\u4ea7 env \u4e0d\u8fdb\u5165 Git\u3002<\/li>\n\n\n\n<li>kubeconfig \u53ea\u653e\u5728 NAS \u548c Agent \u79c1\u6709\u8def\u5f84\u3002<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th class=\"has-text-align-left\" data-align=\"left\">\u98ce\u9669<\/th><th class=\"has-text-align-left\" data-align=\"left\">\u8bf4\u660e<\/th><th class=\"has-text-align-left\" data-align=\"left\">\u5f53\u524d\u7b56\u7565<\/th><th class=\"has-text-align-left\" data-align=\"left\">\u540e\u7eed\u4f18\u5316<\/th><\/tr><\/thead><tbody><tr><td>Docker socket \u6302\u8f7d<\/td><td>Agent \u62e5\u6709 NAS Docker \u63a7\u5236\u6743<\/td><td>\u4ec5\u7528\u4e8e\u53ef\u4fe1\u5185\u7f51\u6784\u5efa\u53d1\u5e03<\/td><td>\u62c6\u51fa\u4e13\u7528\u6784\u5efa\u8282\u70b9\u6216 rootless buildkit<\/td><\/tr><tr><td>K8s Secret \u975e\u52a0\u5bc6<\/td><td>\u539f\u751f Secret \u9ed8\u8ba4\u4e0d\u662f\u5f3a\u52a0\u5bc6<\/td><td>\u5355\u673a\u53ef\u4fe1\u73af\u5883\u77ed\u671f\u63a5\u53d7<\/td><td>\u5f15\u5165 SOPS \u6216 SealedSecret<\/td><\/tr><tr><td>Registry \u65e0\u9274\u6743<\/td><td>\u672c\u5730 Registry \u4e3b\u8981\u4f9b NAS \u4e0e k3d \u4f7f\u7528<\/td><td>\u9650\u5236\u5728\u672c\u673a\u548c Docker \u7f51\u7edc<\/td><td>\u589e\u52a0 registry auth \u6216\u7f51\u7edc\u9694\u79bb<\/td><\/tr><tr><td>\u5355\u673a\u96c6\u7fa4<\/td><td>NAS \u6545\u969c\u4f1a\u5f71\u54cd\u670d\u52a1<\/td><td>\u901a\u8fc7\u5907\u4efd\u548c\u51b7\u6062\u590d\u964d\u4f4e\u98ce\u9669<\/td><td>\u5efa\u7acb\u5f02\u5730\u5907\u4efd\u6216\u5907\u7528\u8282\u70b9<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">14. \u5907\u4efd\u4e0e\u6062\u590d\u5efa\u8bae<\/h2>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th class=\"has-text-align-left\" data-align=\"left\">\u5bf9\u8c61<\/th><th class=\"has-text-align-left\" data-align=\"left\">\u8def\u5f84\u6216\u6765\u6e90<\/th><\/tr><\/thead><tbody><tr><td>Registry \u6570\u636e<\/td><td><code>[DATA_ROOT]\/app-k8s\/registry<\/code><\/td><\/tr><tr><td>kubeconfig<\/td><td><code>[DATA_ROOT]\/app-k8s\/kubeconfig<\/code><\/td><\/tr><tr><td>\u751f\u4ea7 env<\/td><td><code>[AGENT_WORKDIR]\/env<\/code><\/td><\/tr><tr><td>Jenkins \u914d\u7f6e<\/td><td>Jenkins Controller volume<\/td><\/tr><tr><td>\u6570\u636e\u5e93\u6570\u636e<\/td><td>\u6570\u636e\u5e93 volume<\/td><\/tr><tr><td>\u5bf9\u8c61\u5b58\u50a8\u6570\u636e<\/td><td>\u5bf9\u8c61\u5b58\u50a8 volume<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<ol class=\"wp-block-list\">\n<li>\u6062\u590d Docker\u3001Jenkins\u3001Agent\u3001Registry\u3002<\/li>\n\n\n\n<li>\u6062\u590d\u6807\u51c6 K8s \u6570\u636e\u76ee\u5f55\u3002<\/li>\n\n\n\n<li>\u6267\u884c bootstrap \u811a\u672c\u91cd\u65b0\u521b\u5efa\u6216\u4fee\u590d k3d \u96c6\u7fa4\u3002<\/li>\n\n\n\n<li>\u7528\u672c\u5730 Registry \u4e2d\u7684\u955c\u50cf\u6062\u590d API Deployment\u3002<\/li>\n\n\n\n<li>\u9a8c\u8bc1 API\u3001Web\u3001Playground \u4e09\u7c7b\u5165\u53e3\u3002<\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\">15. \u540e\u7eed\u6f14\u8fdb\u8def\u7ebf<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">15.1 \u5de9\u56fa\u540e\u7aef K8s \u53d1\u5e03<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u7ed9\u540e\u7aef\u65b0\u589e HTTP \u5065\u5eb7\u68c0\u67e5\u63a5\u53e3\u3002<\/li>\n\n\n\n<li>\u5c06 K8s \u63a2\u9488\u4ece TCP \u6539\u4e3a HTTP\u3002<\/li>\n\n\n\n<li>\u7ed9 Jenkins \u589e\u52a0\u53d1\u5e03\u540e smoke test\u3002<\/li>\n\n\n\n<li>\u5b9a\u671f\u6e05\u7406\u672c\u5730 Registry \u65e7\u955c\u50cf\u3002<\/li>\n\n\n\n<li>\u7ed9 bootstrap \u589e\u52a0\u66f4\u6e05\u6670\u7684\u65e5\u5fd7\u548c\u5e42\u7b49\u68c0\u67e5\u3002<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">15.2 \u524d\u7aef\u3001Ingress \u4e0e\u89c2\u6d4b<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Web \u548c Playground \u7ee7\u7eed\u4fdd\u7559 Nginx \u9759\u6001\u90e8\u7f72\uff0c\u53d1\u5e03\u4ea7\u7269\u7eb3\u5165\u7248\u672c\u5316 release \u76ee\u5f55\u3002<\/li>\n\n\n\n<li>\u8bc4\u4f30\u662f\u5426\u5c06 Nginx \u4e5f\u8fc1\u5165 K8s\u3002<\/li>\n\n\n\n<li>\u5f15\u5165 Traefik \u6216 Nginx Ingress\uff0c\u7edf\u4e00\u7ba1\u7406 API\u3001Web\u3001Playground\u3002<\/li>\n\n\n\n<li>\u589e\u52a0\u57fa\u7840\u76d1\u63a7\uff1aPod \u72b6\u6001\u3001\u91cd\u542f\u6b21\u6570\u3001\u78c1\u76d8\u3001\u5185\u5b58\u3001Registry \u7a7a\u95f4\u3002<\/li>\n\n\n\n<li>\u7528 SOPS \u6216 SealedSecret \u7ba1\u7406 K8s Secret\u3002<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">16. \u9a8c\u6536\u6807\u51c6<\/h2>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th class=\"has-text-align-left\" data-align=\"left\">\u9a8c\u6536\u9879<\/th><th class=\"has-text-align-left\" data-align=\"left\">\u6807\u51c6<\/th><\/tr><\/thead><tbody><tr><td>Jenkins \u6784\u5efa<\/td><td>\u53d1\u5e03\u5206\u652f\u53ef\u5b8c\u6210 lint\/test\/build\/docker\/k8s deploy<\/td><\/tr><tr><td>K8s \u8fd0\u884c<\/td><td>\u540e\u7aef API Deployment \u4e3a 1\/1<\/td><\/tr><tr><td>\u7aef\u53e3\u8bbf\u95ee<\/td><td>NAS API \u7aef\u53e3\u53ef\u8bbf\u95ee\u5230\u540e\u7aef API<\/td><\/tr><tr><td>\u56de\u6eda\u80fd\u529b<\/td><td>rollout history \u53ef\u770b\u5230\u53d1\u5e03\u8bb0\u5f55\uff0crollout undo \u53ef\u6267\u884c<\/td><\/tr><tr><td>\u914d\u7f6e\u9694\u79bb<\/td><td>\u771f\u5b9e\u751f\u4ea7 env \u4e0d\u8fdb\u5165 Git<\/td><\/tr><tr><td>Agent \u80fd\u529b<\/td><td>Agent \u5185\u53ef\u6267\u884c node\u3001pnpm\u3001docker\u3001kubectl<\/td><\/tr><tr><td>\u672c\u5730 Registry<\/td><td>\u53ef push\/pull API \u955c\u50cf<\/td><\/tr><tr><td>\u6587\u6863\u5b8c\u6574\u6027<\/td><td>SOP\u3001\u6280\u672f\u65b9\u6848\u3001bootstrap \u811a\u672c\u5747\u5728\u4ed3\u5e93\u5185<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">17. \u6838\u5fc3\u547d\u4ee4\u901f\u67e5<\/h2>\n\n\n\n<pre class=\"wp-block-preformatted\">\u67e5\u770b\u96c6\u7fa4\uff1a\nkubectl --kubeconfig [HOST_KUBECONFIG] get nodes\n\n\u67e5\u770b API\uff1a\nkubectl --kubeconfig [HOST_KUBECONFIG] -n app-prod get deploy,pod,svc -o wide\n\n\u67e5\u770b\u65e5\u5fd7\uff1a\nkubectl --kubeconfig [HOST_KUBECONFIG] -n app-prod logs -l app=backend-api --tail=200\n\n\u624b\u52a8\u90e8\u7f72\u6307\u5b9a\u955c\u50cf\uff1a\nkubectl --kubeconfig [HOST_KUBECONFIG] -n app-prod \\\n  set image deployment\/backend-api \\\n  api=[REGISTRY_HOST]:[REGISTRY_PORT]\/backend-api:[TAG]\n\n\u56de\u6eda\uff1a\nkubectl --kubeconfig [HOST_KUBECONFIG] -n app-prod \\\n  rollout undo deployment\/backend-api<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">\u8fd9\u5957\u65b9\u6848\u9002\u5408\u4ee5 NAS \u4e3a\u6838\u5fc3\u7684\u5c0f\u578b\u79c1\u6709\u5316\u90e8\u7f72\u3002\u5b83\u4e0d\u662f\u4e3a\u4e86\u628a\u6240\u6709\u7ec4\u4ef6\u4e00\u6b21\u6027\u201c\u4e91\u539f\u751f\u5316\u201d\uff0c\u800c\u662f\u5148\u628a\u6700\u5bb9\u6613\u4ea7\u751f\u53d1\u5e03\u98ce\u9669\u7684\u540e\u7aef API \u7eb3\u5165 K8s \u6807\u51c6\u53d1\u5e03\u94fe\u8def\uff0c\u518d\u9010\u6b65\u6269\u5c55\u5230\u524d\u7aef\u3001Ingress\u3001\u76d1\u63a7\u3001\u5907\u4efd\u548c\u5bc6\u94a5\u6cbb\u7406\u3002\u8fd9\u6837\u65e2\u4fdd\u7559\u4e86 Docker \u5728 NAS \u4e0a\u7684\u7b80\u5355\u76f4\u63a5\uff0c\u4e5f\u83b7\u5f97\u4e86 K8s \u5728\u53d1\u5e03\u3001\u56de\u6eda\u548c\u8fd0\u884c\u6001\u7ba1\u7406\u4e0a\u7684\u7a33\u5b9a\u6536\u76ca\u3002<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u8bf4\u660e\uff1a\u672c\u6587\u4e3a\u8131\u654f\u7248\u6280\u672f\u65b9\u6848\u3002\u9879\u76ee\u540d\u3001\u4ed3\u5e93\u5730\u5740\u3001\u7aef\u53e3\u3001\u76ee\u5f55\u3001\u57df\u540d\u3001\u5185\u7f51\u5730\u5740\u3001\u4e3b\u673a\u540d\u548c\u5bc6\u94a5\u8def\u5f84\u5747\u4f7f\u7528\u901a\u7528\u5360\u4f4d\u7b26\uff0c\u843d [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[9],"tags":[10],"class_list":["post-50","post","type-post","status-publish","format-standard","hentry","category-nas","tag-nas"],"_links":{"self":[{"href":"https:\/\/blog.kwitsukasa.top\/index.php?rest_route=\/wp\/v2\/posts\/50","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.kwitsukasa.top\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.kwitsukasa.top\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.kwitsukasa.top\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.kwitsukasa.top\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=50"}],"version-history":[{"count":2,"href":"https:\/\/blog.kwitsukasa.top\/index.php?rest_route=\/wp\/v2\/posts\/50\/revisions"}],"predecessor-version":[{"id":52,"href":"https:\/\/blog.kwitsukasa.top\/index.php?rest_route=\/wp\/v2\/posts\/50\/revisions\/52"}],"wp:attachment":[{"href":"https:\/\/blog.kwitsukasa.top\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=50"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.kwitsukasa.top\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=50"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.kwitsukasa.top\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=50"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}