{"id":12057,"date":"2026-09-27T22:09:28","date_gmt":"2026-09-27T13:09:28","guid":{"rendered":"https:\/\/www.skyer9.pe.kr\/wordpress\/?p=12057"},"modified":"2026-10-13T18:00:22","modified_gmt":"2026-10-13T09:00:22","slug":"kubernetes-argocd-%ed%81%b4%eb%9f%ac%ec%8a%a4%ed%84%b0%ec%97%90-vault-%ec%b6%94%ea%b0%80%ed%95%98%ea%b8%b0-raft-%ec%a0%80%ec%9e%a5%ec%86%8c-aws-s3-%eb%b0%b1%ec%97%85","status":"publish","type":"post","link":"https:\/\/www.skyer9.pe.kr\/wordpress\/?p=12057","title":{"rendered":"Kubernetes \u2013 ArgoCD \ud074\ub7ec\uc2a4\ud130\uc5d0 Vault \ucd94\uac00\ud558\uae30 (Raft \uc800\uc7a5\uc18c + AWS S3 \ubc31\uc5c5)"},"content":{"rendered":"<h1>Kubernetes \u2013 ArgoCD \ud074\ub7ec\uc2a4\ud130\uc5d0 Vault \ucd94\uac00\ud558\uae30 (Raft \uc800\uc7a5\uc18c + AWS S3 \ubc31\uc5c5)<\/h1>\n<p><a href=\"https:\/\/www.skyer9.pe.kr\/wordpress\/?p=12049\">\uc774\uc804 \ubb38\uc11c<\/a>\uc5d0\uc11c \ub9cc\ub4e0 <strong>EC2 \ub2e8\uc77c \ub178\ub4dc + ArgoCD<\/strong> \ud074\ub7ec\uc2a4\ud130\uc5d0 <strong>HashiCorp Vault<\/strong> \ub97c \ucd94\uac00\ud569\ub2c8\ub2e4.<\/p>\n<ul>\n<li>\uc800\uc7a5\uc18c\ub294 Vault <strong>\ub0b4\uc7a5 Raft \uc800\uc7a5\uc18c<\/strong>(Integrated Storage)\ub97c \uc0ac\uc6a9\ud569\ub2c8\ub2e4. Consul \uac19\uc740 \uc678\ubd80 \uc800\uc7a5\uc18c\uac00 \ud544\uc694 \uc5c6\uc2b5\ub2c8\ub2e4.<\/li>\n<li>\ubc31\uc5c5\uc740 <strong>Raft \uc2a4\ub0c5\uc0f7<\/strong>\uc744 \ub9e4\uc77c \ub9cc\ub4e4\uc5b4 <strong>AWS S3<\/strong> \uc5d0 \uc62c\ub9bd\ub2c8\ub2e4. S3 \uc5c5\ub85c\ub4dc\ub294 <strong>AWS CLI<\/strong> \ub85c \ud569\ub2c8\ub2e4.<\/li>\n<li>\uc774\uc804 \ubb38\uc11c\uc640 \ub9c8\ucc2c\uac00\uc9c0\ub85c \uc124\uce58\/\ubcc0\uacbd\uc740 \ubaa8\ub450 <strong>Git push<\/strong> \ub85c \ud558\uace0, \uc218\ub3d9 \uc791\uc5c5\uc740 \ucd5c\ucd08 \ucd08\uae30\ud654(init \/ unseal)\uc640 \ube44\ubc00\uac12 \ub4f1\ub85d\ubfd0\uc785\ub2c8\ub2e4.<\/li>\n<\/ul>\n<blockquote>\n<p>Vault OSS \uc5d0\ub294 \uc790\ub3d9 \uc2a4\ub0c5\uc0f7 \uae30\ub2a5(Enterprise \uc804\uc6a9)\uc774 \uc5c6\uc2b5\ub2c8\ub2e4.<br \/>\n\uadf8\ub798\uc11c Kubernetes <strong>CronJob<\/strong> \uc73c\ub85c <code>vault operator raft snapshot save<\/code> \u2192 <code>aws s3 cp<\/code> \ub97c \uc2e4\ud589\ud569\ub2c8\ub2e4.<\/p>\n<\/blockquote>\n<hr \/>\n<h2>0. \uc804\uccb4 \uad6c\uc870<\/h2>\n<pre><code class=\"language-text\">k8s-gitops-aws\/\n\u251c\u2500\u2500 bootstrap\/root-app.yaml\n\u251c\u2500\u2500 apps\/\n\u2502   \u251c\u2500\u2500 argocd.yaml\n\u2502   \u251c\u2500\u2500 nginx.yaml\n\u2502   \u251c\u2500\u2500 local-path.yaml          # \u2605 \ucd94\uac00: PVC \ub97c \ub9cc\ub4e4\uc5b4 \uc904 StorageClass\n\u2502   \u251c\u2500\u2500 vault.yaml               # \u2605 \ucd94\uac00: Vault (Raft)\n\u2502   \u2514\u2500\u2500 vault-backup.yaml        # \u2605 \ucd94\uac00: S3 \ubc31\uc5c5 CronJob\n\u251c\u2500\u2500 values\/\n\u2502   \u251c\u2500\u2500 argocd\/values.yaml\n\u2502   \u251c\u2500\u2500 nginx\/values.yaml\n\u2502   \u251c\u2500\u2500 local-path\/values.yaml   # \u2605\n\u2502   \u251c\u2500\u2500 vault\/values.yaml        # \u2605\n\u2502   \u2514\u2500\u2500 vault-backup\/values.yaml # \u2605\n\u2514\u2500\u2500 charts\/\n    \u251c\u2500\u2500 nginx\/\n    \u2514\u2500\u2500 vault-backup\/            # \u2605 \uc790\uccb4 \ucc28\ud2b8 (CronJob + ServiceAccount)\n        \u251c\u2500\u2500 Chart.yaml\n        \u251c\u2500\u2500 values.yaml\n        \u2514\u2500\u2500 templates\/\n            \u251c\u2500\u2500 serviceaccount.yaml\n            \u2514\u2500\u2500 cronjob.yaml<\/code><\/pre>\n<pre><code class=\"language-text\">                    EC2 (\ub2e8\uc77c \ub178\ub4dc Kubernetes)\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502  namespace: vault                                        \u2502\n\u2502  \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510   snapshot   \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510  \u2502\n\u2502  \u2502 vault-0      \u2502\u25c0\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2502 CronJob vault-backup \u2502  \u2502\n\u2502  \u2502 (Raft)       \u2502  (k8s auth)  \u2502  \u2460 vault (init)      \u2502  \u2502\n\u2502  \u2502 PVC 5Gi      \u2502              \u2502  \u2461 aws-cli (upload)  \u2502\u2500\u2500\u253c\u2500\u2500\u25b6 S3 \ubc84\ud0b7\n\u2502  \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518              \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518  \u2502     vault\/vault-*.snap\n\u2502         \u2502 local-path StorageClass                        \u2502     (30\uc77c \ud6c4 \uc790\ub3d9 \uc0ad\uc81c)\n\u2502         \u25bc                                                \u2502\n\u2502  \/opt\/local-path-provisioner (EC2 \ub514\uc2a4\ud06c)                \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518<\/code><\/pre>\n<table>\n<thead>\n<tr>\n<th>\uc11c\ube44\uc2a4<\/th>\n<th>\uc811\uc18d \uc8fc\uc18c<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>ArgoCD<\/td>\n<td><code>https:\/\/&lt;EC2_PUBLIC_IP&gt;:30443\/<\/code><\/td>\n<\/tr>\n<tr>\n<td>nginx<\/td>\n<td><code>http:\/\/&lt;EC2_PUBLIC_IP&gt;:31405\/<\/code><\/td>\n<\/tr>\n<tr>\n<td>Vault UI<\/td>\n<td><code>http:\/\/&lt;EC2_PUBLIC_IP&gt;:30820\/<\/code><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<hr \/>\n<h2>1. \uc0ac\uc804 \uc900\ube44<\/h2>\n<h3>1.1 EC2 \uc0ac\uc591 \/ \ubcf4\uc548 \uadf8\ub8f9<\/h3>\n<p>Vault \ub294 \uba54\ubaa8\ub9ac\ub97c \ub9ce\uc774 \uc4f0\uc9c0 \uc54a\uc9c0\ub9cc, ArgoCD \uc640 \ud568\uaed8 \uc62c\ub9ac\ubbc0\ub85c <code>t3.medium<\/code>(4GB) \uc774 \ucd5c\uc18c\uc785\ub2c8\ub2e4.<\/p>\n<p><strong>\ubcf4\uc548 \uadf8\ub8f9 \uc778\ubc14\uc6b4\ub4dc \uaddc\uce59 \ucd94\uac00<\/strong><\/p>\n<table>\n<thead>\n<tr>\n<th>\ud3ec\ud2b8<\/th>\n<th>\uc6a9\ub3c4<\/th>\n<th>\uc18c\uc2a4<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>30820<\/td>\n<td>Vault UI<\/td>\n<td>\ub0b4 IP<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<blockquote>\n<p>\uc774 \ubb38\uc11c\ub294 \uad6c\uc131\uc744 \ub2e8\uc21c\ud558\uac8c \ud558\uae30 \uc704\ud574 Vault \ub97c <strong>TLS \uc5c6\uc774(HTTP)<\/strong> \ub744\uc6c1\ub2c8\ub2e4.<br \/>\n30820 \ud3ec\ud2b8\ub294 \ubc18\ub4dc\uc2dc <strong>\ub0b4 IP \ub85c\ub9cc<\/strong> \uc5f4\uace0, \uc6b4\uc601 \ud658\uacbd\uc5d0\uc11c\ub294 TLS \ub97c \uc801\uc6a9\ud569\ub2c8\ub2e4.<\/p>\n<\/blockquote>\n<h3>1.2 AWS CLI \uc124\uce58 (\ub85c\uceec PC)<\/h3>\n<p>AmazonS3FullAccess \uad8c\ud55c\uc744 \uac00\uc9c4 IAM \uacc4\uc815\uc744 \uc0dd\uc131\ud55c\ub2e4.<br \/>\nS3 \ubc84\ud0b7\uacfc IAM \uc0ac\uc6a9\uc790\ub97c \ub9cc\ub4e4 \ub54c \uc0ac\uc6a9\ud569\ub2c8\ub2e4.<\/p>\n<pre><code class=\"language-bash\">curl &quot;https:\/\/awscli.amazonaws.com\/awscli-exe-linux-x86_64.zip&quot; -o awscliv2.zip\nunzip awscliv2.zip\nsudo .\/aws\/install\n\naws --version\naws configure            # AmazonS3FullAccess \uad8c\ud55c\uc744 \uac00\uc9c4 IAM \uacc4\uc815 Access Key \/ Region: ap-northeast-2\naws sts get-caller-identity<\/code><\/pre>\n<blockquote>\n<p>macOS \ub294 <code>brew install awscli<\/code> \ub85c \uc124\uce58\ud574\ub3c4 \ub429\ub2c8\ub2e4.<\/p>\n<\/blockquote>\n<hr \/>\n<h2>2. S3 \ubc84\ud0b7 \/ IAM \uc0ac\uc6a9\uc790 \uc0dd\uc131 (\ub85c\uceec PC, AWS CLI)<\/h2>\n<p>\uc774\ud558 <code>&lt;BUCKET&gt;<\/code> \uc740 \uc804 \uc138\uacc4\uc5d0\uc11c \uc720\uc77c\ud55c \uc774\ub984\uc774\uc5b4\uc57c \ud569\ub2c8\ub2e4. \uc608: <code>&lt;YOUR_ID&gt;-vault-backup<\/code><\/p>\n<pre><code class=\"language-bash\">export BUCKET=&lt;YOUR_ID&gt;-vault-backup\nexport REGION=ap-northeast-2<\/code><\/pre>\n<h3>2.1 \ubc84\ud0b7 \uc0dd\uc131<\/h3>\n<pre><code class=\"language-bash\">aws s3api create-bucket \\\n  --bucket $BUCKET \\\n  --region $REGION \\\n  --create-bucket-configuration LocationConstraint=$REGION\n\n# \ud37c\ube14\ub9ad \uc811\uadfc \uc804\ubd80 \ucc28\ub2e8\naws s3api put-public-access-block \\\n  --bucket $BUCKET \\\n  --public-access-block-configuration \\\n  BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true<\/code><\/pre>\n<blockquote>\n<p>S3 \ub294 \uae30\ubcf8\uc801\uc73c\ub85c SSE-S3 \ub85c \uc554\ud638\ud654\ub418\uc5b4 \uc800\uc7a5\ub429\ub2c8\ub2e4. \ub610\ud55c Raft \uc2a4\ub0c5\uc0f7 \uc790\uccb4\ub3c4 Vault \uc758 \ud0a4\ub85c \uc554\ud638\ud654\ub418\uc5b4 \uc788\uc2b5\ub2c8\ub2e4.<\/p>\n<\/blockquote>\n<h3>2.2 \uc624\ub798\ub41c \uc2a4\ub0c5\uc0f7 \uc790\ub3d9 \uc0ad\uc81c (Lifecycle)<\/h3>\n<p><code>vault\/<\/code> \uc544\ub798 \ud30c\uc77c\uc744 <strong>30\uc77c<\/strong> \ud6c4 \uc790\ub3d9 \uc0ad\uc81c\ud569\ub2c8\ub2e4.<\/p>\n<p><code>lifecycle.json<\/code><\/p>\n<pre><code class=\"language-json\">{\n  &quot;Rules&quot;: [\n    {\n      &quot;ID&quot;: &quot;expire-vault-snapshots&quot;,\n      &quot;Filter&quot;: { &quot;Prefix&quot;: &quot;vault\/&quot; },\n      &quot;Status&quot;: &quot;Enabled&quot;,\n      &quot;Expiration&quot;: { &quot;Days&quot;: 30 },\n      &quot;AbortIncompleteMultipartUpload&quot;: { &quot;DaysAfterInitiation&quot;: 1 }\n    }\n  ]\n}<\/code><\/pre>\n<pre><code class=\"language-bash\">aws s3api put-bucket-lifecycle-configuration \\\n  --bucket $BUCKET \\\n  --lifecycle-configuration file:\/\/lifecycle.json\n\naws s3api get-bucket-lifecycle-configuration --bucket $BUCKET<\/code><\/pre>\n<h3>2.3 \ubc31\uc5c5 \uc804\uc6a9 IAM \uc0ac\uc6a9\uc790<\/h3>\n<p>\uc774\ubbf8 \ub9cc\ub4e0 \uacc4\uc815\uc758 Access Key \ub97c \uc0ac\uc6a9\ud55c\ub2e4<\/p>\n<hr \/>\n<h2>3. Git \uc800\uc7a5\uc18c \uc791\uc131 (\ub85c\uceec PC)<\/h2>\n<h3>3.1 StorageClass: local-path-provisioner<\/h3>\n<p>kubeadm \ud074\ub7ec\uc2a4\ud130\uc5d0\ub294 \uae30\ubcf8 StorageClass \uac00 \uc5c6\uc5b4\uc11c, Vault \uc758 PVC \uac00 <code>Pending<\/code> \uc5d0 \uba38\ubb45\ub2c8\ub2e4.<br \/>\nEC2 \ub85c\uceec \ub514\uc2a4\ud06c\ub97c PV \ub85c \uc4f0\uac8c \ud574 \uc8fc\ub294 <strong>local-path-provisioner<\/strong> \ub97c \uba3c\uc800 \ucd94\uac00\ud569\ub2c8\ub2e4.<\/p>\n<p>\ud3f4\ub354\ub294 \uc790\ub3d9\uc73c\ub85c \uc0dd\uc131\ub429\ub2c8\ub2e4.<br \/>\n\ub2e4\ub9cc \uc0dd\uc131 \uc2dc\uc810\uc774 \uc124\uce58\ud560 \ub54c\uac00 \uc544\ub2c8\ub77c \uccab PVC \uac00 \ub9cc\ub4e4\uc5b4\uc9c8 \ub54c\uc785\ub2c8\ub2e4.<\/p>\n<p><code>values\/local-path\/values.yaml<\/code><\/p>\n<pre><code class=\"language-yaml\">storageClass:\n  create: true\n  name: local-path\n  defaultClass: true          # \uae30\ubcf8 StorageClass \ub85c \uc9c0\uc815\n  reclaimPolicy: Retain       # PVC \ub97c \uc9c0\uc6cc\ub3c4 \ub370\uc774\ud130 \ub514\ub809\ud130\ub9ac\ub294 \ub0a8\uae40 (Vault \ub370\uc774\ud130 \ubcf4\ud638)\n\nnodePathMap:\n  - node: DEFAULT_PATH_FOR_NON_LISTED_NODES\n    paths:\n      - \/opt\/local-path-provisioner<\/code><\/pre>\n<p><code>apps\/local-path.yaml<\/code><\/p>\n<p>\uacf5\uc2dd Helm \uc800\uc7a5\uc18c\uac00 \uc5c6\uc73c\ubbc0\ub85c GitHub \uc800\uc7a5\uc18c\uc758 \ucc28\ud2b8 \uacbd\ub85c\ub97c \ud0dc\uadf8\ub85c \uace0\uc815\ud574\uc11c \uc0ac\uc6a9\ud569\ub2c8\ub2e4.<\/p>\n<pre><code class=\"language-yaml\">apiVersion: argoproj.io\/v1alpha1\nkind: Application\nmetadata:\n  name: local-path\n  namespace: argocd\nspec:\n  project: default\n  sources:\n    - repoURL: https:\/\/github.com\/rancher\/local-path-provisioner.git\n      targetRevision: v0.0.37             # \ub9b4\ub9ac\uc2a4 \ud0dc\uadf8\n      path: deploy\/chart\/local-path-provisioner\n      helm:\n        releaseName: local-path\n        valueFiles:\n          - $values\/values\/local-path\/values.yaml\n    - repoURL: https:\/\/github.com\/&lt;YOUR_ID&gt;\/k8s-gitops-aws.git\n      targetRevision: main\n      ref: values\n  destination:\n    server: https:\/\/kubernetes.default.svc\n    namespace: local-path-storage\n  syncPolicy:\n    automated:\n      prune: true\n      selfHeal: true\n    syncOptions:\n      - CreateNamespace=true<\/code><\/pre>\n<h3>3.2 Vault: values\/vault\/values.yaml<\/h3>\n<p>HA \ubaa8\ub4dc + Raft \uc800\uc7a5\uc18c\ub85c \uc124\uce58\ud558\ub418, \ub2e8\uc77c \ub178\ub4dc\uc774\ubbc0\ub85c <code>replicas: 1<\/code> \ub85c \ub461\ub2c8\ub2e4.<br \/>\n\ub098\uc911\uc5d0 \ub178\ub4dc\ub97c \ub298\ub9ac\uba74 <code>replicas<\/code> \ub9cc 3 \uc73c\ub85c \ubc14\uafb8\uace0 <code>vault operator raft join<\/code> \ud558\uba74 \ub429\ub2c8\ub2e4.<\/p>\n<pre><code class=\"language-yaml\">global:\n  enabled: true\n  tlsDisable: true\n\n# Agent Injector \ub294 \uc9c0\uae08\uc740 \uc0ac\uc6a9\ud558\uc9c0 \uc54a\uc74c \u2192 \uba54\ubaa8\ub9ac \uc808\uc57d\ninjector:\n  enabled: false\n\nserver:\n  resources:\n    requests:\n      memory: 256Mi\n      cpu: 100m\n    limits:\n      memory: 512Mi\n\n  # Raft \ub370\uc774\ud130 \uc800\uc7a5 PVC\n  dataStorage:\n    enabled: true\n    size: 5Gi\n    storageClass: local-path\n    accessMode: ReadWriteOnce\n\n  ha:\n    enabled: true\n    replicas: 1\n    raft:\n      enabled: true\n      setNodeId: true          # \ub178\ub4dc ID = \ud30c\ub4dc \uc774\ub984 (vault-0)\n      config: |\n        ui = true\n\n        listener &quot;tcp&quot; {\n          tls_disable     = 1\n          address         = &quot;[::]:8200&quot;\n          cluster_address = &quot;[::]:8201&quot;\n        }\n\n        storage &quot;raft&quot; {\n          path = &quot;\/vault\/data&quot;\n        }\n\n        service_registration &quot;kubernetes&quot; {}\n\nui:\n  enabled: true\n  serviceType: NodePort\n  serviceNodePort: 30820\n  externalPort: 8200<\/code><\/pre>\n<h3>3.3 Vault: apps\/vault.yaml<\/h3>\n<p>ArgoCD \uc640 \uac19\uc740 multi-source \ubc29\uc2dd\uc785\ub2c8\ub2e4. \ucc28\ud2b8 \ubc84\uc804\uc740 EC2 \uc5d0\uc11c \ud655\uc778\ud569\ub2c8\ub2e4.<\/p>\n<pre><code class=\"language-bash\">helm repo add hashicorp https:\/\/helm.releases.hashicorp.com\nhelm repo update\nhelm search repo hashicorp\/vault     # CHART VERSION \/ APP VERSION \ud655\uc778<\/code><\/pre>\n<pre><code class=\"language-yaml\">apiVersion: argoproj.io\/v1alpha1\nkind: Application\nmetadata:\n  name: vault\n  namespace: argocd\n  # finalizer \uc5c6\uc74c: Application \uc744 \uc2e4\uc218\ub85c \uc9c0\uc6cc\ub3c4 Vault \ub9ac\uc18c\uc2a4\ub294 \ub0a8\ub3c4\ub85d\nspec:\n  project: default\n  sources:\n    - repoURL: https:\/\/helm.releases.hashicorp.com\n      chart: vault\n      targetRevision: 0.34.0           # helm search repo \uacb0\uacfc\ub85c \ubcc0\uacbd\n      helm:\n        releaseName: vault\n        valueFiles:\n          - $values\/values\/vault\/values.yaml\n    - repoURL: https:\/\/github.com\/&lt;YOUR_ID&gt;\/k8s-gitops-aws.git\n      targetRevision: main\n      ref: values\n  destination:\n    server: https:\/\/kubernetes.default.svc\n    namespace: vault\n  syncPolicy:\n    automated:\n      prune: false                     # Vault \ub294 \uc2e4\uc218\ub85c \uc9c0\uc6cc\uc9c0\uc9c0 \uc54a\ub3c4\ub85d\n      selfHeal: true\n    syncOptions:\n      - CreateNamespace=true<\/code><\/pre>\n<h3>3.4 push<\/h3>\n<p>\ubc31\uc5c5 CronJob \uc740 Vault \ucd08\uae30\ud654\uac00 \ub05d\ub09c \ub4a4(5\uc7a5) \ucd94\uac00\ud569\ub2c8\ub2e4. \uc6b0\uc120 \uc5ec\uae30\uae4c\uc9c0 push \ud569\ub2c8\ub2e4.<\/p>\n<pre><code class=\"language-bash\">git add .\ngit commit -m &quot;local-path + vault&quot;\ngit push origin main<\/code><\/pre>\n<hr \/>\n<h2>4. Vault \ucd08\uae30\ud654 \/ Unseal (EC2)<\/h2>\n<h3>4.1 \uc0c1\ud0dc \ud655\uc778<\/h3>\n<pre><code class=\"language-bash\">kubectl get storageclass\n-------------------------------------------------------------\nNAME                   PROVISIONER             RECLAIMPOLICY\nlocal-path (default)   rancher.io\/local-path   Retain\n\nkubectl -n vault get pods,pvc<\/code><\/pre>\n<p><code>vault-0<\/code> \uc740 <strong>Running \uc774\uc9c0\ub9cc READY 0\/1<\/strong> \uc785\ub2c8\ub2e4. \uc544\uc9c1 \ucd08\uae30\ud654(init) \ubc0f \ubd09\uc778 \ud574\uc81c(unseal)\uac00 \ub418\uc9c0 \uc54a\uc558\uae30 \ub54c\ubb38\uc774\uba70, \uc815\uc0c1\uc785\ub2c8\ub2e4.<br \/>\n\uc774 \ub3d9\uc548 ArgoCD \uc5d0\uc11c <code>vault<\/code> Application \uc740 <code>Progressing<\/code> \uc73c\ub85c \ud45c\uc2dc\ub429\ub2c8\ub2e4.<\/p>\n<pre><code class=\"language-bash\">kubectl -n vault exec -it vault-0 -- vault status\n# Initialized  false\n# Sealed       true\n# Storage Type raft<\/code><\/pre>\n<h3>4.2 \ucd08\uae30\ud654<\/h3>\n<pre><code class=\"language-bash\">kubectl -n vault exec -it vault-0 -- vault operator init \\\n  -key-shares=5 -key-threshold=3<\/code><\/pre>\n<p>\ucd9c\ub825\ub418\ub294 <strong>Unseal Key 5\uac1c<\/strong>\uc640 <strong>Initial Root Token<\/strong> \uc744 \uc548\uc804\ud55c \uacf3(\ube44\ubc00\ubc88\ud638 \uad00\ub9ac\uc790 \ub4f1)\uc5d0 \ubcf4\uad00\ud569\ub2c8\ub2e4.<\/p>\n<blockquote>\n<p>\u26a0\ufe0f \uc774 \ud0a4\ub97c \uc783\uc5b4\ubc84\ub9ac\uba74 Vault \ub370\uc774\ud130\uc640 <strong>S3 \ubc31\uc5c5\uae4c\uc9c0 \ubaa8\ub450 \ubcf5\uad6c\ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.<\/strong><br \/>\nRaft \uc2a4\ub0c5\uc0f7\uc740 \uc774 \ud0a4\ub85c \uc554\ud638\ud654\ub418\uc5b4 \uc788\uc73c\ubbc0\ub85c, \ud0a4\ub294 \ubc31\uc5c5\uacfc <strong>\ubcc4\ub3c4\uc758 \uc7a5\uc18c<\/strong>\uc5d0 \ubcf4\uad00\ud569\ub2c8\ub2e4.<\/p>\n<\/blockquote>\n<h3>4.3 Unseal<\/h3>\n<p>Unseal Key 5\uac1c \uc911 <strong>\uc11c\ub85c \ub2e4\ub978 3\uac1c<\/strong>\ub97c \uc785\ub825\ud569\ub2c8\ub2e4.<\/p>\n<pre><code class=\"language-bash\">kubectl -n vault exec -it vault-0 -- vault operator unseal   # Key 1\nkubectl -n vault exec -it vault-0 -- vault operator unseal   # Key 2\nkubectl -n vault exec -it vault-0 -- vault operator unseal   # Key 3\n\nkubectl -n vault exec -it vault-0 -- vault status\n# Initialized  true\n# Sealed       false\n# HA Mode      active<\/code><\/pre>\n<p><code>vault-0<\/code> \uc774 <code>1\/1 READY<\/code> \uac00 \ub418\uace0, ArgoCD \uc758 <code>vault<\/code> \ub3c4 <code>Healthy<\/code> \uac00 \ub429\ub2c8\ub2e4.<\/p>\n<pre><code class=\"language-bash\">kubectl -n vault exec -it vault-0 -- sh -c \\\n  &#039;VAULT_TOKEN=&lt;ROOT_TOKEN&gt; vault operator raft list-peers&#039;\n--------------------------------------------------------------\nNode       Address                        State     Voter\nvault-0    vault-0.vault-internal:8201    leader    true<\/code><\/pre>\n<blockquote>\n<p><strong>\ud30c\ub4dc\uac00 \uc7ac\uc2dc\uc791\ub418\uba74 Vault \ub294 \ub2e4\uc2dc Sealed \uc0c1\ud0dc\uac00 \ub429\ub2c8\ub2e4.<\/strong> (EC2 \uc7ac\ubd80\ud305, \ub178\ub4dc \uc7ac\uc2dc\uc791 \ud3ec\ud568)<br \/>\n\uadf8\ub54c\ub9c8\ub2e4 4.3 \uc758 unseal \uc744 \ub2e4\uc2dc \ud574\uc57c \ud569\ub2c8\ub2e4. \uc790\ub3d9\ud654\ud558\ub824\uba74 <strong>AWS KMS Auto Unseal<\/strong> \uc744 \uad6c\uc131\ud569\ub2c8\ub2e4.<\/p>\n<\/blockquote>\n<h3>4.4 UI \uc811\uc18d<\/h3>\n<p><code>http:\/\/&lt;EC2_PUBLIC_IP&gt;:30820\/<\/code> \uc5d0 \uc811\uc18d\ud574\uc11c <strong>Token<\/strong> \ubc29\uc2dd\uc73c\ub85c Root Token \uc73c\ub85c \ub85c\uadf8\uc778\ud569\ub2c8\ub2e4.<\/p>\n<hr \/>\n<h2>5. S3 \ubc31\uc5c5 \uad6c\uc131<\/h2>\n<h3>5.1 Vault \uc5d0 \ubc31\uc5c5\uc6a9 \uc778\uc99d \uc124\uc815 (EC2)<\/h3>\n<p>\ubc31\uc5c5 CronJob \uc774 Root Token \uc5c6\uc774 \uc2a4\ub0c5\uc0f7\uc744 \ub9cc\ub4e4 \uc218 \uc788\ub3c4\ub85d, <strong>Kubernetes \uc778\uc99d<\/strong>\uacfc <strong>\uc2a4\ub0c5\uc0f7 \uc804\uc6a9 \uc815\ucc45<\/strong>\uc744 \ub9cc\ub4ed\ub2c8\ub2e4.<br \/>\nCronJob \ud30c\ub4dc\ub294 \uc790\uc2e0\uc758 ServiceAccount \ud1a0\ud070\uc73c\ub85c \ub85c\uadf8\uc778\ud558\ubbc0\ub85c, Vault \ud1a0\ud070\uc744 Secret \uc5d0 \uc800\uc7a5\ud560 \ud544\uc694\uac00 \uc5c6\uc2b5\ub2c8\ub2e4.<\/p>\n<pre><code class=\"language-bash\">kubectl -n vault exec -it vault-0 -- sh<\/code><\/pre>\n<p>\uc774\ud558 <code>vault-0<\/code> \ud30c\ub4dc \uc548\uc5d0\uc11c \uc2e4\ud589\ud569\ub2c8\ub2e4.<\/p>\n<pre><code class=\"language-sh\">export VAULT_TOKEN=&lt;ROOT_TOKEN&gt;\n\n# 1) Kubernetes \uc778\uc99d \ud65c\uc131\ud654\nvault auth enable kubernetes\nvault write auth\/kubernetes\/config \\\n  kubernetes_host=&quot;https:\/\/kubernetes.default.svc:443&quot;\n\n# 2) \uc2a4\ub0c5\uc0f7 \uc77d\uae30\ub9cc \uac00\ub2a5\ud55c \uc815\ucc45\nvault policy write raft-snapshot - &lt;&lt;EOF\npath &quot;sys\/storage\/raft\/snapshot&quot; {\n  capabilities = [&quot;read&quot;]\n}\nEOF\n\n# 3) vault \ub124\uc784\uc2a4\ud398\uc774\uc2a4\uc758 vault-backup ServiceAccount \uc5d0\ub9cc \uc815\ucc45 \ubd80\uc5ec\nvault write auth\/kubernetes\/role\/vault-backup \\\n  bound_service_account_names=vault-backup \\\n  bound_service_account_namespaces=vault \\\n  policies=raft-snapshot \\\n  ttl=10m\n\nexit<\/code><\/pre>\n<blockquote>\n<p>Vault \ucc28\ud2b8\ub294 \uae30\ubcf8\uc73c\ub85c <code>system:auth-delegator<\/code> \uad8c\ud55c\uc744 Vault \uc5d0 \ubd80\uc5ec\ud558\ubbc0\ub85c, \ubcc4\ub3c4\uc758 RBAC \uc124\uc815 \uc5c6\uc774 TokenReview \uac00 \ub3d9\uc791\ud569\ub2c8\ub2e4.<\/p>\n<\/blockquote>\n<h3>5.2 AWS Access Key \ub97c Secret \uc73c\ub85c \ub4f1\ub85d (EC2)<\/h3>\n<pre><code class=\"language-bash\">kubectl -n vault create secret generic vault-backup-aws \\\n  --from-literal=AWS_ACCESS_KEY_ID=&lt;ACCESS_KEY_ID&gt; \\\n  --from-literal=AWS_SECRET_ACCESS_KEY=&lt;SECRET_ACCESS_KEY&gt;<\/code><\/pre>\n<h3>5.3 \ubc31\uc5c5 \ucc28\ud2b8: charts\/vault-backup (\ub85c\uceec PC)<\/h3>\n<p>CronJob \ud558\ub098\uc5d0 \ucee8\ud14c\uc774\ub108\ub97c \ub450 \uac1c \ub461\ub2c8\ub2e4. \ubcc4\ub3c4 \uc774\ubbf8\uc9c0\ub97c \ube4c\ub4dc\ud558\uc9c0 \uc54a\uace0 \uacf5\uc2dd \uc774\ubbf8\uc9c0\ub9cc \uc0ac\uc6a9\ud569\ub2c8\ub2e4.<\/p>\n<ol>\n<li><strong>initContainer <code>snapshot<\/code><\/strong> (<code>hashicorp\/vault<\/code>) : Kubernetes \uc778\uc99d\uc73c\ub85c \ub85c\uadf8\uc778 \u2192 \uc2a4\ub0c5\uc0f7\uc744 \uacf5\uc720 \ubcfc\ub968\uc5d0 \uc800\uc7a5<\/li>\n<li><strong>container <code>upload<\/code><\/strong> (<code>amazon\/aws-cli<\/code>) : <code>aws s3 cp<\/code> \ub85c S3 \uc5c5\ub85c\ub4dc<\/li>\n<\/ol>\n<p><code>charts\/vault-backup\/Chart.yaml<\/code><\/p>\n<pre><code class=\"language-yaml\">apiVersion: v2\nname: vault-backup\ndescription: Vault raft snapshot to S3 (aws cli)\ntype: application\nversion: 0.1.0\nappVersion: &quot;1.0&quot;<\/code><\/pre>\n<p><code>charts\/vault-backup\/values.yaml<\/code> (\ucc28\ud2b8 \uae30\ubcf8\uac12)<\/p>\n<pre><code class=\"language-yaml\">schedule: &quot;0 3 * * *&quot;\ntimeZone: &quot;Asia\/Seoul&quot;\n\nserviceAccountName: vault-backup\n\nvault:\n  image: hashicorp\/vault:2.0.3        # Vault \uc11c\ubc84\uc640 \uac19\uc740 \ubc84\uc804 \uad8c\uc7a5\n  addr: http:\/\/vault-active.vault.svc:8200\n  role: vault-backup\n\naws:\n  image: amazon\/aws-cli:latest\n  region: ap-northeast-2\n  credentialsSecret: vault-backup-aws\n\ns3:\n  bucket: &quot;&quot;\n  prefix: vault\/<\/code><\/pre>\n<p><code>charts\/vault-backup\/templates\/serviceaccount.yaml<\/code><\/p>\n<pre><code class=\"language-yaml\">apiVersion: v1\nkind: ServiceAccount\nmetadata:\n  name: {{ .Values.serviceAccountName }}<\/code><\/pre>\n<p><code>charts\/vault-backup\/templates\/cronjob.yaml<\/code><\/p>\n<pre><code class=\"language-yaml\">apiVersion: batch\/v1\nkind: CronJob\nmetadata:\n  name: {{ .Release.Name }}\nspec:\n  schedule: {{ .Values.schedule | quote }}\n  timeZone: {{ .Values.timeZone | quote }}\n  concurrencyPolicy: Forbid\n  successfulJobsHistoryLimit: 3\n  failedJobsHistoryLimit: 3\n  jobTemplate:\n    spec:\n      backoffLimit: 2\n      ttlSecondsAfterFinished: 86400\n      template:\n        spec:\n          serviceAccountName: {{ .Values.serviceAccountName }}\n          restartPolicy: Never\n          volumes:\n            - name: snapshot\n              emptyDir: {}\n\n          # \u2460 Vault \uc2a4\ub0c5\uc0f7 \uc0dd\uc131\n          initContainers:\n            - name: snapshot\n              image: {{ .Values.vault.image }}\n              env:\n                - name: VAULT_ADDR\n                  value: {{ .Values.vault.addr | quote }}\n              command: [&quot;\/bin\/sh&quot;, &quot;-c&quot;]\n              args:\n                - |\n                  set -e\n                  export VAULT_TOKEN=$(vault write -field=token auth\/kubernetes\/login \\\n                    role={{ .Values.vault.role }} \\\n                    jwt=@\/var\/run\/secrets\/kubernetes.io\/serviceaccount\/token)\n                  vault operator raft snapshot save \/snapshot\/vault.snap\n                  ls -l \/snapshot\/vault.snap\n              volumeMounts:\n                - name: snapshot\n                  mountPath: \/snapshot\n\n          # \u2461 AWS CLI \ub85c S3 \uc5c5\ub85c\ub4dc\n          containers:\n            - name: upload\n              image: {{ .Values.aws.image }}\n              envFrom:\n                - secretRef:\n                    name: {{ .Values.aws.credentialsSecret }}\n              env:\n                - name: AWS_DEFAULT_REGION\n                  value: {{ .Values.aws.region | quote }}\n              command: [&quot;\/bin\/sh&quot;, &quot;-c&quot;]\n              args:\n                - |\n                  set -e\n                  KEY=&quot;{{ .Values.s3.prefix }}vault-$(date -u +%Y%m%dT%H%M%SZ).snap&quot;\n                  aws s3 cp \/snapshot\/vault.snap &quot;s3:\/\/{{ required &quot;s3.bucket is required&quot; .Values.s3.bucket }}\/${KEY}&quot;\n                  echo &quot;uploaded: s3:\/\/{{ .Values.s3.bucket }}\/${KEY}&quot;\n              volumeMounts:\n                - name: snapshot\n                  mountPath: \/snapshot\n                  readOnly: true<\/code><\/pre>\n<blockquote>\n<p><code>amazon\/aws-cli:latest<\/code> \ub300\uc2e0 \ud2b9\uc815 \ubc84\uc804 \ud0dc\uadf8\ub85c \uace0\uc815\ud558\uba74 \ub354 \uc548\uc804\ud569\ub2c8\ub2e4.<\/p>\n<\/blockquote>\n<h3>5.4 values\/vault-backup\/values.yaml (\uc774 \ud074\ub7ec\uc2a4\ud130\uc758 \uc2e4\uc81c \uc124\uc815)<\/h3>\n<pre><code class=\"language-yaml\">s3:\n  bucket: &lt;YOUR_ID&gt;-vault-backup<\/code><\/pre>\n<h3>5.5 apps\/vault-backup.yaml<\/h3>\n<pre><code class=\"language-yaml\">apiVersion: argoproj.io\/v1alpha1\nkind: Application\nmetadata:\n  name: vault-backup\n  namespace: argocd\n  finalizers:\n    - resources-finalizer.argocd.argoproj.io\nspec:\n  project: default\n  sources:\n    - repoURL: https:\/\/github.com\/&lt;YOUR_ID&gt;\/k8s-gitops-aws.git\n      targetRevision: main\n      path: charts\/vault-backup\n      helm:\n        releaseName: vault-backup\n        valueFiles:\n          - $values\/values\/vault-backup\/values.yaml\n    - repoURL: https:\/\/github.com\/&lt;YOUR_ID&gt;\/k8s-gitops-aws.git\n      targetRevision: main\n      ref: values\n  destination:\n    server: https:\/\/kubernetes.default.svc\n    namespace: vault\n  syncPolicy:\n    automated:\n      prune: true\n      selfHeal: true<\/code><\/pre>\n<p>push \uc804\uc5d0 \uacb0\uacfc\ub97c \ubbf8\ub9ac \ud655\uc778\ud569\ub2c8\ub2e4.<\/p>\n<pre><code class=\"language-bash\">helm template vault-backup charts\/vault-backup -f values\/vault-backup\/values.yaml<\/code><\/pre>\n<pre><code class=\"language-bash\">git add .\ngit commit -m &quot;vault backup to s3&quot;\ngit push origin main<\/code><\/pre>\n<hr \/>\n<h2>6. \ubc31\uc5c5 \ub3d9\uc791 \ud655\uc778 (EC2)<\/h2>\n<p>\ub9e4\uc77c 03:00(KST) \uae4c\uc9c0 \uae30\ub2e4\ub9ac\uc9c0 \uc54a\uace0, CronJob \uc5d0\uc11c Job \uc744 \ubc14\ub85c \ud558\ub098 \ub9cc\ub4e4\uc5b4 \uc2e4\ud589\ud569\ub2c8\ub2e4.<\/p>\n<pre><code class=\"language-bash\">kubectl -n vault get cronjob vault-backup\n\nkubectl -n vault create job --from=cronjob\/vault-backup vault-backup-manual\nkubectl -n vault get pods -w\n\n# \ucee8\ud14c\uc774\ub108\ubcc4 \ub85c\uadf8\nkubectl -n vault logs job\/vault-backup-manual -c snapshot\nkubectl -n vault logs job\/vault-backup-manual -c upload\n# uploaded: s3:\/\/&lt;YOUR_ID&gt;-vault-backup\/vault\/vault-20261013T081500Z.snap<\/code><\/pre>\n<p>\ub85c\uceec PC \uc5d0\uc11c S3 \ub97c \ud655\uc778\ud569\ub2c8\ub2e4.<\/p>\n<pre><code class=\"language-bash\">aws s3 ls s3:\/\/$BUCKET\/vault\/<\/code><\/pre>\n<p>\ud655\uc778\uc774 \ub05d\ub098\uba74 \uc218\ub3d9 Job \uc740 \uc0ad\uc81c\ud569\ub2c8\ub2e4.<\/p>\n<pre><code class=\"language-bash\">kubectl -n vault delete job vault-backup-manual<\/code><\/pre>\n<p><strong>\uc790\uc8fc \ub098\ub294 \uc624\ub958<\/strong><\/p>\n<table>\n<thead>\n<tr>\n<th>\ub85c\uadf8<\/th>\n<th>\uc6d0\uc778 \/ \uc870\uce58<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>permission denied<\/code> (snapshot)<\/td>\n<td>5.1 \uc758 role \/ policy \uc774\ub984, ServiceAccount \uc774\ub984 \ud655\uc778<\/td>\n<\/tr>\n<tr>\n<td><code>Vault is sealed<\/code><\/td>\n<td>4.3 unseal \ub2e4\uc2dc \uc2e4\ud589<\/td>\n<\/tr>\n<tr>\n<td><code>AccessDenied<\/code> (upload)<\/td>\n<td>IAM \uc815\ucc45\uc758 \ubc84\ud0b7 \uc774\ub984\uacfc <code>vault\/<\/code> prefix \ud655\uc778<\/td>\n<\/tr>\n<tr>\n<td><code>Unable to locate credentials<\/code> (upload)<\/td>\n<td><code>vault-backup-aws<\/code> Secret \uc774 <code>vault<\/code> \ub124\uc784\uc2a4\ud398\uc774\uc2a4\uc5d0 \uc788\ub294\uc9c0 \ud655\uc778<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<hr \/>\n<h2>7. \ubcf5\uad6c (Restore)<\/h2>\n<h3>7.1 \uc2a4\ub0c5\uc0f7 \ub2e4\uc6b4\ub85c\ub4dc (EC2)<\/h3>\n<pre><code class=\"language-bash\">sudo apt install -y unzip\ncurl &quot;https:\/\/awscli.amazonaws.com\/awscli-exe-linux-x86_64.zip&quot; -o awscliv2.zip\nunzip awscliv2.zip &amp;&amp; sudo .\/aws\/install\n\naws configure --profile vault-backup     # 2.3 \uc5d0\uc11c \ubc1c\uae09\ud55c \ud0a4, Region: ap-northeast-2\n\naws s3 ls s3:\/\/&lt;BUCKET&gt;\/vault\/ --profile vault-backup\naws s3 cp s3:\/\/&lt;BUCKET&gt;\/vault\/vault-20261013T081500Z.snap .\/restore.snap --profile vault-backup<\/code><\/pre>\n<h3>7.2 \uc2a4\ub0c5\uc0f7 \ubcf5\uc6d0<\/h3>\n<p><strong>\uac19\uc740 Vault \uc5d0 \ub418\ub3cc\ub9ac\ub294 \uacbd\uc6b0<\/strong> (\ub370\uc774\ud130\ub97c \uc2e4\uc218\ub85c \uc9c0\uc6e0\uc744 \ub54c)<\/p>\n<pre><code class=\"language-bash\">kubectl -n vault cp .\/restore.snap vault-0:\/tmp\/restore.snap\n\nkubectl -n vault exec -it vault-0 -- sh -c \\\n  &#039;VAULT_TOKEN=&lt;ROOT_TOKEN&gt; vault operator raft snapshot restore \/tmp\/restore.snap&#039;<\/code><\/pre>\n<p><strong>EC2 \ub97c \uc0c8\ub85c \ub9cc\ub4e0 \uacbd\uc6b0<\/strong> (\ud074\ub7ec\uc2a4\ud130 \uc7ac\uad6c\ucd95)<\/p>\n<ol>\n<li>\uc774\uc804 \ubb38\uc11c 2\uc7a5 \u2192 4\uc7a5, \uc774 \ubb38\uc11c 4.1 ~ 4.3 \uc744 \uc9c4\ud589\ud569\ub2c8\ub2e4. \uc774\ub54c init \uc73c\ub85c \uc0dd\uae30\ub294 <strong>\uc0c8 \ud0a4\ub294 \uc784\uc2dc\uc6a9<\/strong>\uc785\ub2c8\ub2e4.<\/li>\n<li>\uc0c8 Root Token \uc73c\ub85c <code>-force<\/code> \uc635\uc158\uc744 \ubd99\uc5ec \ubcf5\uc6d0\ud569\ub2c8\ub2e4.<\/li>\n<\/ol>\n<pre><code class=\"language-bash\">kubectl -n vault cp .\/restore.snap vault-0:\/tmp\/restore.snap\n\nkubectl -n vault exec -it vault-0 -- sh -c \\\n  &#039;VAULT_TOKEN=&lt;NEW_ROOT_TOKEN&gt; vault operator raft snapshot restore -force \/tmp\/restore.snap&#039;<\/code><\/pre>\n<ol start=\"3\">\n<li>\ubcf5\uc6d0 \ud6c4\uc5d0\ub294 <strong>\uc6d0\ub798 \ud074\ub7ec\uc2a4\ud130\uc758 Unseal Key \/ Root Token<\/strong> \uc774 \uc720\ud6a8\ud574\uc9d1\ub2c8\ub2e4. Sealed \uc0c1\ud0dc\ub77c\uba74 \uc6d0\ub798 \ud0a4\ub85c unseal \ud569\ub2c8\ub2e4.<\/li>\n<li>5.2 \uc758 AWS Secret \uc744 \ub2e4\uc2dc \ub4f1\ub85d\ud558\uba74 \ubc31\uc5c5 CronJob \ub3c4 \uadf8\ub300\ub85c \ub3d9\uc791\ud569\ub2c8\ub2e4. (Kubernetes \uc778\uc99d \uc124\uc815\uc740 \uc2a4\ub0c5\uc0f7\uc5d0 \ud3ec\ud568\ub418\uc5b4 \ud568\uaed8 \ubcf5\uc6d0\ub429\ub2c8\ub2e4.)<\/li>\n<\/ol>\n<blockquote>\n<p><code>-force<\/code> \ub294 \uc2a4\ub0c5\uc0f7\uc758 \ud0a4\ub9c1\uc774 \ud604\uc7ac Vault \uc640 \ub2e4\ub97c \ub54c \ud544\uc694\ud569\ub2c8\ub2e4. \ud604\uc7ac \ub370\uc774\ud130\ub294 \ubaa8\ub450 \ub36e\uc5b4\uc368\uc9d1\ub2c8\ub2e4.<\/p>\n<\/blockquote>\n<hr \/>\n<h2>8. \uc6b4\uc601<\/h2>\n<p><strong>Vault \ubc84\uc804 \uc5c5\uadf8\ub808\uc774\ub4dc<\/strong><\/p>\n<pre><code class=\"language-bash\">helm search repo hashicorp\/vault       # EC2 \uc5d0\uc11c \ubc84\uc804 \ud655\uc778\nvi apps\/vault.yaml                     # targetRevision \ubcc0\uacbd\nvi charts\/vault-backup\/values.yaml     # vault.image \ub3c4 \uac19\uc740 \ubc84\uc804\uc73c\ub85c\ngit commit -am &quot;vault upgrade&quot;\ngit push<\/code><\/pre>\n<p>StatefulSet \uc758 \uc5c5\ub370\uc774\ud2b8 \uc804\ub7b5\uc774 <code>OnDelete<\/code> \uc774\ubbc0\ub85c, \ubc18\uc601 \ud6c4 \ud30c\ub4dc\ub97c \uc9c1\uc811 \uc0ad\uc81c\ud574\uc57c \uc0c8 \ubc84\uc804\uc774 \ub739\ub2c8\ub2e4.<br \/>\n\uc7ac\uc2dc\uc791 \ud6c4\uc5d0\ub294 <strong>unseal \uc744 \ub2e4\uc2dc<\/strong> \ud574\uc57c \ud569\ub2c8\ub2e4.<\/p>\n<pre><code class=\"language-bash\">kubectl -n vault delete pod vault-0\n# 4.3 unseal \ubc18\ubcf5<\/code><\/pre>\n<blockquote>\n<p>\uc5c5\uadf8\ub808\uc774\ub4dc \uc804\uc5d0\ub294 6\uc7a5\uc758 \ubc29\ubc95\uc73c\ub85c \uc218\ub3d9 \ubc31\uc5c5\uc744 \uba3c\uc800 \ubc1b\uc544 \ub461\ub2c8\ub2e4.<\/p>\n<\/blockquote>\n<p><strong>\ubc31\uc5c5 \uc8fc\uae30 \/ \ubcf4\uad00 \uae30\uac04 \ubcc0\uacbd<\/strong><\/p>\n<ul>\n<li>\uc8fc\uae30: <code>values\/vault-backup\/values.yaml<\/code> \uc5d0 <code>schedule: &quot;0 *\/6 * * *&quot;<\/code> \ucc98\ub7fc \ucd94\uac00 \ud6c4 push<\/li>\n<li>\ubcf4\uad00 \uae30\uac04: 2.2 \uc758 <code>lifecycle.json<\/code> \uc5d0\uc11c <code>Days<\/code> \ub97c \ubc14\uafb8\uace0 <code>put-bucket-lifecycle-configuration<\/code> \uc7ac\uc2e4\ud589<\/li>\n<\/ul>\n<p><strong>\uc8fc\uc758\uc0ac\ud56d<\/strong><\/p>\n<ul>\n<li>Unseal Key, Root Token, AWS Access Key \ub294 <strong>Git \uc5d0 \ub123\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4.<\/strong><\/li>\n<li>Unseal Key \ub97c \uc783\uc5b4\ubc84\ub9ac\uba74 S3 \ubc31\uc5c5\ub3c4 \ubcf5\uad6c\ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4. \ud0a4\ub294 \ubc31\uc5c5\uacfc \ub2e4\ub978 \uacf3\uc5d0 \ubcf4\uad00\ud569\ub2c8\ub2e4.<\/li>\n<li>\ucd08\uae30 \uc124\uc815\uc774 \ub05d\ub098\uba74 Root Token \uc740 <code>vault token revoke &lt;ROOT_TOKEN&gt;<\/code> \uc73c\ub85c \ud3d0\uae30\ud558\uace0, \ud544\uc694\ud560 \ub54c <code>vault operator generate-root<\/code> \ub85c \ub2e4\uc2dc \ub9cc\ub4dc\ub294 \uac83\uc744 \uad8c\uc7a5\ud569\ub2c8\ub2e4.<\/li>\n<li>local-path \ub294 EC2 \ub514\uc2a4\ud06c\uc5d0 \ub370\uc774\ud130\ub97c \uc800\uc7a5\ud558\ubbc0\ub85c, <strong>EC2 \ub97c \uc885\ub8cc(terminate)\ud558\uba74 Vault \ub370\uc774\ud130\ub3c4 \uc0ac\ub77c\uc9d1\ub2c8\ub2e4.<\/strong> \ubcf5\uad6c\ub294 S3 \ubc31\uc5c5\uc73c\ub85c \ud569\ub2c8\ub2e4.<\/li>\n<\/ul>\n<hr \/>\n<h2>9. \uc815\ub9ac<\/h2>\n<table>\n<thead>\n<tr>\n<th>\ub2e8\uacc4<\/th>\n<th>\uc791\uc5c5<\/th>\n<th>\uc704\uce58<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>1<\/td>\n<td>\ubcf4\uc548 \uadf8\ub8f9 30820 \ucd94\uac00, AWS CLI \uc124\uce58<\/td>\n<td>AWS \ucf58\uc194 \/ \ub85c\uceec PC<\/td>\n<\/tr>\n<tr>\n<td>2<\/td>\n<td>S3 \ubc84\ud0b7, Lifecycle, \ubc31\uc5c5\uc6a9 IAM \uc0ac\uc6a9\uc790 \uc0dd\uc131 (AWS CLI)<\/td>\n<td>\ub85c\uceec PC<\/td>\n<\/tr>\n<tr>\n<td>3<\/td>\n<td>local-path + vault \ub97c Git \uc5d0 \ucd94\uac00 \ud6c4 push<\/td>\n<td>\ub85c\uceec PC<\/td>\n<\/tr>\n<tr>\n<td>4<\/td>\n<td><code>vault operator init<\/code> \/ <code>unseal<\/code><\/td>\n<td>EC2<\/td>\n<\/tr>\n<tr>\n<td>5<\/td>\n<td>Kubernetes \uc778\uc99d \uc124\uc815, AWS Secret \ub4f1\ub85d, \ubc31\uc5c5 \ucc28\ud2b8 push<\/td>\n<td>EC2 \/ \ub85c\uceec PC<\/td>\n<\/tr>\n<tr>\n<td>6<\/td>\n<td>\uc218\ub3d9 Job \uc73c\ub85c \ubc31\uc5c5 \ud655\uc778 \u2192 <code>aws s3 ls<\/code><\/td>\n<td>EC2 \/ \ub85c\uceec PC<\/td>\n<\/tr>\n<tr>\n<td>7<\/td>\n<td>\uc7a5\uc560 \uc2dc <code>aws s3 cp<\/code> \u2192 <code>raft snapshot restore<\/code><\/td>\n<td>EC2<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>EC2 \ub97c \uc0c8\ub85c \ub9cc\ub4e4\uc5b4\ub3c4 <strong>\uc774\uc804 \ubb38\uc11c 2\uc7a5 \u2192 4\uc7a5<\/strong>, <strong>\uc774 \ubb38\uc11c 4\uc7a5 \u2192 7.2<\/strong> \ub9cc \ud558\uba74 Vault \ub370\uc774\ud130\uae4c\uc9c0 S3 \uc5d0\uc11c \ubcf5\uc6d0\ub429\ub2c8\ub2e4.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Kubernetes \u2013 ArgoCD \ud074\ub7ec\uc2a4\ud130\uc5d0 Vault \ucd94\uac00\ud558\uae30 (Raft \uc800\uc7a5\uc18c + AWS S3 \ubc31\uc5c5) \uc774\uc804 \ubb38\uc11c\uc5d0\uc11c \ub9cc\ub4e0 EC2 \ub2e8\uc77c \ub178\ub4dc + ArgoCD \ud074\ub7ec\uc2a4\ud130\uc5d0 HashiCorp Vault \ub97c \ucd94\uac00\ud569\ub2c8\ub2e4. \uc800\uc7a5\uc18c\ub294 Vault \ub0b4\uc7a5 Raft \uc800\uc7a5\uc18c(Integrated Storage)\ub97c \uc0ac\uc6a9\ud569\ub2c8\ub2e4. Consul \uac19\uc740 \uc678\ubd80 \uc800\uc7a5\uc18c\uac00 \ud544\uc694 \uc5c6\uc2b5\ub2c8\ub2e4. \ubc31\uc5c5\uc740 Raft \uc2a4\ub0c5\uc0f7\uc744 \ub9e4\uc77c \ub9cc\ub4e4\uc5b4 AWS S3 \uc5d0 \uc62c\ub9bd\ub2c8\ub2e4. S3 \uc5c5\ub85c\ub4dc\ub294 AWS CLI \ub85c \ud569\ub2c8\ub2e4. \uc774\uc804 \ubb38\uc11c\uc640\u2026 <span class=\"read-more\"><a href=\"https:\/\/www.skyer9.pe.kr\/wordpress\/?p=12057\">Read More &raquo;<\/a><\/span><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[12],"tags":[],"class_list":["post-12057","post","type-post","status-publish","format-standard","hentry","category-devops"],"_links":{"self":[{"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/12057","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=12057"}],"version-history":[{"count":5,"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/12057\/revisions"}],"predecessor-version":[{"id":12062,"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/12057\/revisions\/12062"}],"wp:attachment":[{"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=12057"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=12057"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=12057"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}