์ด ๋ฌธ์์์๋ GKE Fleet ๊ด๋ฆฌํ ํด๋ฌ์คํฐ์์ Google Kubernetes Engine(GKE)์ฉ ๊ด๋ฆฌํ ์ํฌ๋ก๋ ์์ด๋ดํฐํฐ๋ฅผ ๊ตฌ์ฑํ๋ ๋ฐฉ๋ฒ์ ์ค๋ช ํฉ๋๋ค. ๋ํ ์ํฌ๋ก๋๋ฅผ ๋ฐฐํฌํ๊ณ ์ํฌ๋ก๋์ ID์ ์ธ์ฆ์๋ฅผ ํ์ธํ๋ ๋ฐฉ๋ฒ๋ ์ค๋ช ํฉ๋๋ค.
GKE์ฉ ๊ด๋ฆฌํ ์ํฌ๋ก๋ ์์ด๋ดํฐํฐ๋ฅผ ์ค์ ํ๊ณ ์ฌ์ฉํ๋ ๋จ๊ณ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
CA๋ฅผ ์ํฌ๋ก๋ ์์ด๋ดํฐํฐ ํ์ ๋ฐ์ธ๋ฉํฉ๋๋ค.
CA ํ์์ ์ธ์ฆ์๋ฅผ ์์ฒญํ๋๋ก ๊ด๋ฆฌํ ์ํฌ๋ก๋ ์์ด๋ดํฐํฐ๋ฅผ ์น์ธํฉ๋๋ค.
๊ด๋ฆฌํ ์ํฌ๋ก๋ ์์ด๋ดํฐํฐ๋ก ์ํฌ๋ก๋๋ฅผ ๋ฐฐํฌํฉ๋๋ค.
Google ๊ด๋ฆฌํ ์ํฌ๋ก๋ ์์ด๋ดํฐํฐ ํ
ํด๋ฌ์คํฐ๋ฅผ GKE Fleet์ ์ถ๊ฐํ๋ฉด Fleet์์ ํธ๋ฌ์คํธ ๋๋ฉ์ธ์ ๋ฃจํธ ์ญํ ์ ํ๋ Google ๊ด๋ฆฌํ ์ํฌ๋ก๋ ์์ด๋ดํฐํฐ ํ์ ์๋์ผ๋ก ๋ง๋ญ๋๋ค. Google ๊ด๋ฆฌํ ์ํฌ๋ก๋ ์์ด๋ดํฐํฐ ํ์๋ ๋ค์๊ณผ ๊ฐ์ ์ ์ฝ ์กฐ๊ฑด์ด ์์ต๋๋ค.
Google์์ ํ์ ์์ ํ ๊ด๋ฆฌํ๋ฏ๋ก ๋ค์์คํ์ด์ค, ID, ID ๊ณต๊ธ์ ์ฒด ๋ฑ์ ํ์ ๋ฆฌ์์ค๋ฅผ ๋ง๋ค ์ ์์ต๋๋ค.
ํ์ GKE ์ํฌ๋ก๋์๋ง ์ฌ์ฉํ ์ ์์ต๋๋ค. Compute Engine VM๊ณผ ๊ฐ์ ๋ค๋ฅธ ์ ํ์ ์ํฌ๋ก๋๋ฅผ ํ์ ์ถ๊ฐํ ์ ์์ต๋๋ค.
ํ์ ๋ชจ๋ ํด๋ฌ์คํฐ์๋ ํ์ค Kubernetes ๋ค์์คํ์ด์ค ๋์ผ์ฑ ๋ชจ๋ธ์ด ์ ์ฉ๋ฉ๋๋ค. ์ฆ, ํ์ ๋ชจ๋ ํด๋ฌ์คํฐ์ ๋์ผํ ๊ถํ์ด ๋ถ์ฌ๋ฉ๋๋ค. ํ์ ํด๋ฌ์คํฐ์์ ์คํ๋๋ ์ํฌ๋ก๋๋ ํ์ ์๋ ๋ชจ๋ ID๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
๋ค์ค ํ๋ก์ ํธ ๊ตฌ์ฑ
์ด ๋ฌธ์์์ ์ฌ์ฉํ๋Google Cloud ๋ฆฌ์์ค(์: GKE ํด๋ฌ์คํฐ, ๋ฃจํธ CA, ํ์ CA)๋ ๋ณ๋์ ํ๋ก์ ํธ์ ์์ ์ ์์ต๋๋ค. ์ด๋ฌํ ๋ฆฌ์์ค๋ฅผ ์ฐธ์กฐํ ๋๋ --project
ํ๋๊ทธ๋ฅผ ์ฌ์ฉํ์ฌ ๊ฐ ๋ฆฌ์์ค์ ์ฌ๋ฐ๋ฅธ ํ๋ก์ ํธ๋ฅผ ์ง์ ํฉ๋๋ค.
์์ํ๊ธฐ ์ ์
Create or select a Google Cloud project.
-
Create a Google Cloud project:
gcloud projects create PROJECT_ID
Replace
PROJECT_ID
with a name for the Google Cloud project you are creating. -
Select the Google Cloud project that you created:
gcloud config set project PROJECT_ID
Replace
PROJECT_ID
with your Google Cloud project name.
-
๊ด๋ฆฌํ ์ํฌ๋ก๋ ์์ด๋ดํฐํฐ๋ฅผ ์ดํดํฉ๋๋ค.
GKE ํด๋ฌ์คํฐ๊ฐ ํ๋ ์ด์ ์๋์ง ํ์ธํฉ๋๋ค. ํด๋ฌ์คํฐ์์ ๋ฒ์ 1.33.0-gke.2248000 ์ด์์ ์คํํ๋์ง ํ์ธํฉ๋๋ค.
ํด๋ฌ์คํฐ๋ฅผ GKE Fleet์ ์ถ๊ฐํฉ๋๋ค. ํด๋ฌ์คํฐ๊ฐ Autopilot ํด๋ฌ์คํฐ์ธ ๊ฒฝ์ฐ
--enable-workload-identity
๋ฅผ ์๋ตํฉ๋๋ค. Fleet์ ํธ๋ฌ์คํธ ๋๋ฉ์ธ ์ญํ ์ ํ๋ Google ๊ด๋ฆฌํ ์ํฌ๋ก๋ ์์ด๋ดํฐํฐ ํ์ ์๋์ผ๋ก ๋ง๋ญ๋๋ค.๋ค์ ๋ช ๋ น์ด๋ฅผ ์คํํ์ฌ GKE Fleet๋ฅผ ์ฌ์ฉ ์ค์ ํฉ๋๋ค.
gcloud container clusters update CLUSTER_NAME \ --workload-pool=PROJECT_ID.svc.id.goog \ --enable-fleet \ --fleet-project=PROJECT_ID
๋ค์์ ๋ฐ๊ฟ๋๋ค.
CLUSTER_NAME
: GKE Fleet์ ๋ฑ๋กํ๋ ค๋ GKE ํด๋ฌ์คํฐ์ ์ด๋ฆPROJECT_ID
: GKE Fleet ํธ์คํธ ํ๋ก์ ํธ ID
Enable the IAM and Certificate Authority Service APIs:
gcloud services enable cloudresourcemanager.googleapis.com
iam.googleapis.com privateca.googleapis.com ๊ฒฐ์ ๋ฐ ํ ๋น๋ ํ๋ก์ ํธ๋ฅผ ์ฌ์ฉํ๋๋ก Google Cloud CLI๋ฅผ ๊ตฌ์ฑํฉ๋๋ค.
gcloud config set billing/quota_project PROJECT_ID
PROJECT_ID๋ฅผ Fleet ํ๋ก์ ํธ์ ID๋ก ๋ฐ๊ฟ๋๋ค.
ํ์ํ ์ญํ
๊ด๋ฆฌํ ์ํฌ๋ก๋ ์์ด๋ดํฐํฐ๋ฅผ ๋ง๋ค๊ณ ๊ด๋ฆฌํ ์ํฌ๋ก๋ ์์ด๋ดํฐํฐ ์ธ์ฆ์๋ฅผ ํ๋ก๋น์ ๋ํ๋ ๋ฐ ํ์ํ ๊ถํ์ ์ป์ผ๋ ค๋ฉด ๊ด๋ฆฌ์์๊ฒ ํ๋ก์ ํธ์ ๋ํ ๋ค์ IAM ์ญํ ์ ๋ถ์ฌํด ๋ฌ๋ผ๊ณ ์์ฒญํ์ธ์.
-
๊ด๋ฆฌํ ์ํฌ๋ก๋ ์์ด๋ดํฐํฐ๋ฅผ ๋ง๋ค๊ณ ๊ตฌ์ฑํ๋ ค๋ฉด ๋ค์ ์๋ด๋ฅผ ๋ฐ๋ฅด์ธ์.
IAM ์ํฌ๋ก๋ ์์ด๋ดํฐํฐ ํ ๊ด๋ฆฌ์(
roles/iam.workloadIdentityPoolAdmin
) -
CA ํ์ ๋ง๋ค๊ณ ๊ตฌ์ฑํ๋ ค๋ ๊ฒฝ์ฐ: CA ์๋น์ค ๊ด๋ฆฌ์(
roles/privateca.admin
)
์ญํ ๋ถ์ฌ์ ๋ํ ์์ธํ ๋ด์ฉ์ ํ๋ก์ ํธ, ํด๋, ์กฐ์ง์ ๋ํ ์ก์ธ์ค ๊ด๋ฆฌ๋ฅผ ์ฐธ์กฐํ์ธ์.
์ปค์คํ ์ญํ ์ด๋ ๋ค๋ฅธ ์ฌ์ ์ ์๋ ์ญํ ์ ํตํด ํ์ํ ๊ถํ์ ์ป์ ์๋ ์์ต๋๋ค.
๊ด๋ฆฌํ ์ํฌ๋ก๋ ์์ด๋ดํฐํฐ์ ๋ํด ์ธ์ฆ์๋ฅผ ๋ฐ๊ธํ๋๋ก CA ์๋น์ค ๊ตฌ์ฑ
GKE์ฉ ๊ด๋ฆฌํ ์ํฌ๋ก๋ ์์ด๋ดํฐํฐ๋ฅผ ๊ตฌ์ฑํ๋ ค๋ฉด ๋จผ์ ์ธ์ฆ ๊ธฐ๊ด(CA)๊ณผ ํ๋ ์ด์์ ํ์ CA๋ฅผ ๊ตฌ์ฑํด์ผ ํฉ๋๋ค. ์ด ๊ตฌ์ฑ์ CA ๊ณ์ธต ๊ตฌ์กฐ๋ผ๊ณ ํฉ๋๋ค.
CA ์๋น์ค ํ์ ์ฌ์ฉํ์ฌ ์ด ๊ณ์ธต ๊ตฌ์กฐ๋ฅผ ์ค์ ํ ์ ์์ต๋๋ค. ์ด ๊ณ์ธต ๊ตฌ์กฐ๋ฅผ ์ฌ์ฉํ๋ฉด ํ์ CA ํ์์ ์ํฌ๋ก๋์ X.509 ์ํฌ๋ก๋ ์์ด๋ดํฐํฐ ์ธ์ฆ์๋ฅผ ๋ฐ๊ธํฉ๋๋ค.
๋ฃจํธ CA ํ ๊ตฌ์ฑ
๋ฃจํธ CA ํ์ ๋ง๋ค๋ ค๋ฉด ๋ค์์ ์ํํฉ๋๋ค.
gcloud privateca pools create
๋ฅผ ์ฌ์ฉํ์ฌ ์ํฐํ๋ผ์ด์ฆ ๋ฑ๊ธ์์ ๋ฃจํธ CA ํ์ ๋ง๋ญ๋๋ค.
์ด ๋ฑ๊ธ์ ์๊ท๋ชจ์ ์ฅ๊ธฐ ์ธ์ฆ์ ๋ฐ๊ธ์ ์ํ ๊ฒ์
๋๋ค.
gcloud privateca pools create ROOT_CA_POOL_ID \ --location=REGION \ --project=CA_PROJECT_ID \ --tier=enterprise
๋ค์์ ๋ฐ๊ฟ๋๋ค.
ROOT_CA_POOL_ID
: ๋ฃจํธ CA ํ์ ๊ณ ์ ID์ ๋๋ค. ID๋ ์ต๋ 64์์ด๋ฉฐ ์๋ฌธ์ ๋ฐ ๋๋ฌธ์ ์์ซ์ ๋ฌธ์, ๋ฐ์ค, ํ์ดํ๋ง ํฌํจํด์ผ ํฉ๋๋ค. ํ ID๋ ๋ฆฌ์ ๋ด์์ ๊ณ ์ ํด์ผ ํฉ๋๋ค.REGION
: ๋ฃจํธ CA ํ์ด ์๋ ๋ฆฌ์ ์ ๋๋ค.CA_PROJECT_ID
: ๋ฃจํธ CA๋ฅผ ๋ง๋ค ํ๋ก์ ํธ์ ID์ ๋๋ค.
CA ํ, ๋ฑ๊ธ, ๋ฆฌ์ ์ ๋ํด ์์ธํ ์์๋ณด๋ ค๋ฉด CA ํ ๋ง๋ค๊ธฐ๋ฅผ ์ฐธ์กฐํ์ธ์.
๋ฃจํธ CA ๊ตฌ์ฑ
gcloud privateca roots create
๋ฅผ ์ฌ์ฉํ์ฌ ๋ฃจํธ CA ํ์ ๋ฃจํธ CA๋ฅผ ๋ง๋ญ๋๋ค.
๋ฃจํธ CA ํ์์ ์ ์ผํ CA์ธ ๊ฒฝ์ฐ ๋ฃจํธ CA๋ฅผ ์ฌ์ฉ ์ค์ ํ๋ผ๋ ๋ฉ์์ง๊ฐ ํ์๋ ์ ์์ต๋๋ค.
๋ฃจํธ CA๋ฅผ ๋ง๋ค๋ ค๋ฉด ๋ค์ ๋ช ๋ น์ด๋ฅผ ์คํํฉ๋๋ค.
gcloud privateca roots create ROOT_CA_ID \ --pool=ROOT_CA_POOL_ID \ --subject="CN=ROOT_CA_CN, O=ROOT_CA_ORGANIZATION" \ --key-algorithm="KEY_ALGORITHM" \ --max-chain-length=1 \ --location=REGION \ --project=CA_PROJECT_ID \ --auto-enable
๋ค์์ ๋ฐ๊ฟ๋๋ค.
ROOT_CA_ID
: ๋ฃจํธ CA์ ๊ณ ์ ํ ์ด๋ฆ์ ๋๋ค. CA ์ด๋ฆ์ ์ต๋ 64์์ด๋ฉฐ ์๋ฌธ์ ๋ฐ ๋๋ฌธ์ ์์ซ์ ๋ฌธ์, ๋ฐ์ค, ํ์ดํ๋ง ํฌํจํด์ผ ํฉ๋๋ค. CA ์ด๋ฆ์ ๋ฆฌ์ ๋ด์์ ๊ณ ์ ํด์ผ ํฉ๋๋ค.ROOT_CA_POOL_ID
: ๋ฃจํธ CA ํ์ ID์ ๋๋ค.ROOT_CA_CN
: ๋ฃจํธ CA์ ์ผ๋ฐ ์ด๋ฆ์ ๋๋ค.ROOT_CA_ORGANIZATION
: ๋ฃจํธ CA์ ์กฐ์ง์ ๋๋ค.KEY_ALGORITHM
: ํค ์๊ณ ๋ฆฌ์ฆ์ ๋๋ค(์:ec-p256-sha256
).REGION
: ๋ฃจํธ CA ํ์ด ์๋ ๋ฆฌ์ ์ ๋๋ค.CA_PROJECT_ID
: ๋ฃจํธ CA๋ฅผ ๋ง๋ ํ๋ก์ ํธ์ ID์ ๋๋ค.
CA์ subject
ํ๋์ ๋ํ ์์ธํ ๋ด์ฉ์ ์ ๋ชฉ์ ์ฐธ์กฐํ์ธ์.
ํ์ํ ๊ฒฝ์ฐ ๋ฃจํธ CA ํ์ ๋ฃจํธ CA๋ฅผ ์ถ๊ฐ๋ก ๋ง๋ญ๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด ๋ฃจํธ CA ์ํ์ ์ ์ฉํ ์ ์์ต๋๋ค.
ํ์ CA ๊ตฌ์ฑ
์ํ๋ ๊ฒฝ์ฐ ํ์ CA๋ฅผ ๊ตฌ์ฑํ ์ ์์ต๋๋ค. ํ์ CA๋ฅผ ๊ตฌ์ฑํ๋ฉด ๋ค์ ์์ ์ ์ํํ ์ ์์ต๋๋ค.
๋ค์ค ์ธ์ฆ์ ๋ฐ๊ธ ์๋๋ฆฌ์ค: ์ธ์ฆ์ ๋ฐ๊ธ ์๋๋ฆฌ์ค๊ฐ ์ฌ๋ฌ ๊ฐ ์๋ ๊ฒฝ์ฐ ์๋๋ฆฌ์ค๋ง๋ค ํ์ CA๋ฅผ ๋ง๋ค ์ ์์ต๋๋ค.
๋ณด๋ค ํจ๊ณผ์ ์ธ ๋ถํ ๋ถ์ฐ: CA ํ์ ์ฌ๋ฌ ํ์ CA๋ฅผ ์ถ๊ฐํ๋ฉด ์ธ์ฆ์ ์์ฒญ์ ๋ถํ๋ฅผ ๋ ํจ๊ณผ์ ์ผ๋ก ๋ถ์ฐํ ์ ์์ต๋๋ค.
ํ์ CA ํ๊ณผ ํ์ CA๋ฅผ ๋ง๋ค๋ ค๋ฉด ๋ค์์ ์ํํฉ๋๋ค.
๋๊ท๋ชจ์ ๋จ๊ธฐ ์ธ์ฆ์ ๋ฐ๊ธ์ ์ํ DevOps ๋ฑ๊ธ์์ ํ์ CA ํ์ ๋ง๋ญ๋๋ค.
gcloud privateca pools create SUBORDINATE_CA_POOL_ID \ --location=REGION \ --project=CA_PROJECT_ID \ --tier=devops
๋ค์์ ๋ฐ๊ฟ๋๋ค.
SUBORDINATE_CA_POOL_ID
: ํ์ CA ํ์ ๊ณ ์ ID์ ๋๋ค. ID๋ ์ต๋ 64์์ด๋ฉฐ ์๋ฌธ์ ๋ฐ ๋๋ฌธ์ ์์ซ์ ๋ฌธ์, ๋ฐ์ค, ํ์ดํ๋ง ํฌํจํด์ผ ํฉ๋๋ค. ํ ID๋ ๋ฆฌ์ ๋ด์์ ๊ณ ์ ํด์ผ ํฉ๋๋ค.REGION
: ํ์ CA ํ์ ๋ง๋ค ๋ฆฌ์ ์ ๋๋ค.CA_PROJECT_ID
: ํ์ CA๋ฅผ ๋ง๋ ํ๋ก์ ํธ์ ID์ ๋๋ค.
์์ธํ ๋ด์ฉ์ CA ํ ๋ง๋ค๊ธฐ๋ฅผ ์ฐธ์กฐํ์ธ์.
ํ์ CA ํ์ ํ์ CA๋ฅผ ๋ง๋ญ๋๋ค. ๊ธฐ๋ณธ ๊ตฌ์ฑ ๊ธฐ๋ฐ ๋ฐ๊ธ ๋ชจ๋๋ฅผ ๋ณ๊ฒฝํ์ง ๋ง์ญ์์ค.
gcloud privateca subordinates create SUBORDINATE_CA_ID \ --pool=SUBORDINATE_CA_POOL_ID \ --location=REGION \ --issuer-pool=ROOT_CA_POOL_ID \ --issuer-location=REGION \ --subject="CN=SUBORDINATE_CA_CN, O=SUBORDINATE_CA_ORGANIZATION" \ --key-algorithm="KEY_ALGORITHM" \ --use-preset-profile=subordinate_mtls_pathlen_0 \ --project=CA_PROJECT_ID \ --auto-enable
๋ค์์ ๋ฐ๊ฟ๋๋ค.
SUBORDINATE_CA_ID
: ํ์ CA์ ๊ณ ์ ํ ์ด๋ฆ์ ๋๋ค. ์ด๋ฆ์ ์ต๋ 64์์ด๋ฉฐ ์๋ฌธ์ ๋ฐ ๋๋ฌธ์ ์์ซ์ ๋ฌธ์, ๋ฐ์ค, ํ์ดํ๋ง ํฌํจํด์ผ ํฉ๋๋ค. ํ ์ด๋ฆ์ ๋ฆฌ์ ๋ด์์ ๊ณ ์ ํด์ผ ํฉ๋๋ค.SUBORDINATE_CA_POOL_ID
: ํ์ CA ํ์ ์ด๋ฆ์ ๋๋ค.REGION
: ํ์ CA ํ์ด ์๋ ๋ฆฌ์ ์ ๋๋ค.ROOT_CA_POOL_ID
: ๋ฃจํธ CA ํ์ ID์ ๋๋ค.REGION
: ๋ฃจํธ CA ํ์ ๋ฆฌ์ ์ ๋๋ค.SUBORDINATE_CA_CN
: ํ์ CA์ ์ผ๋ฐ ์ด๋ฆ์ ๋๋ค.SUBORDINATE_CA_ORGANIZATION
: ํ์ CA ๋ฐ๊ธ ์กฐ์ง์ ์ด๋ฆ์ ๋๋ค.KEY_ALGORITHM
: ํค ์๊ณ ๋ฆฌ์ฆ์ ๋๋ค(์:ec-p256-sha256
).CA_PROJECT_ID
: ํ์ CA๋ฅผ ๋ง๋ ํ๋ก์ ํธ์ ID์ ๋๋ค.
CA์
subject
ํ๋์ ๋ํ ์์ธํ ๋ด์ฉ์ ์ ๋ชฉ์ ์ฐธ์กฐํ์ธ์.
์ธ์ฆ์ ๋ฐ๊ธ ๊ตฌ์ฑ ํ์ผ ๋ง๋ค๊ธฐ
CA๋ฅผ ์ํฌ๋ก๋ ์์ด๋ดํฐํฐ ํ์ ๋ฐ์ธ๋ฉํ๋ ค๋ฉด ์ธ์ฆ์ ๋ฐ๊ธ ๊ตฌ์ฑ์ด ์์ด์ผ ํฉ๋๋ค. ํ์ํ ๊ฒฝ์ฐ ์ฌ๋ฌ ํธ๋ฌ์คํธ ๋๋ฉ์ธ์์ ์ํฌ๋ก๋๋ฅผ ์ธ์ฆํ๋ ค๋ฉด ํธ๋ฌ์คํธ ๊ตฌ์ฑ ์ค์ ์ผ๋ก ํ์ ์ ๋ฐ์ดํธํ ์๋ ์์ต๋๋ค.
์ธ์ฆ์ ๋ฐ๊ธ ๊ตฌ์ฑ์ ๊ตฌ์ฑํ๋ ค๋ฉด ์ธ์ฆ์ ๋ฐ๊ธ ๊ตฌ์ฑ ํ์ผ์ ๋ง๋ญ๋๋ค. ํ์ผ์ ํ์์ ๋ค์๊ณผ ๋น์ทํฉ๋๋ค.
{ "inlineCertificateIssuanceConfig": { "caPools": { "REGION1": "projects/CA_PROJECT_NUMBER1/locations/REGION1/caPools/SUBORDINATE_CA_POOL_ID1", "REGION2": "projects/CA_PROJECT_NUMBER2/locations/REGION2/caPools/SUBORDINATE_CA_POOL_ID2" }, "lifetime": "DURATION", "rotationWindowPercentage": ROTATION_WINDOW_PERCENTAGE, "keyAlgorithm": "ALGORITHM" } }
๋ค์์ ๋ฐ๊ฟ๋๋ค.
REGION
: CA๊ฐ ์๋ ๋ฆฌ์ ์ ๋๋ค.CA_PROJECT_NUMBER
: ํ์ CA ํ์ ๋ง๋ ํ๋ก์ ํธ์ ํ๋ก์ ํธ ๋ฒํธ์ ๋๋ค. CA_PROJECT_ID ํ๋ก์ ํธ์์ ํ๋ก์ ํธ ๋ฒํธ๋ฅผ ๊ฐ์ ธ์ค๋ ค๋ฉด ๋ค์ ๋ช ๋ น์ด๋ฅผ ์คํํฉ๋๋ค.gcloud projects describe CA_PROJECT_ID --format="value(projectNumber)"
SUBORDINATE_CA_POOL_ID
: ํ์ CA ํ์ ์ด๋ฆ์ ๋๋ค.ALGORITHM
: ์ ํ์ฌํญ. ๋น๊ณต๊ฐ ํค๋ฅผ ์์ฑํ๋ ๋ฐ ์ฌ์ฉ๋๋ ์ํธํ ์๊ณ ๋ฆฌ์ฆ์ ๋๋ค. ์ ํจํ ๊ฐ์ECDSA_P256
(๊ธฐ๋ณธ๊ฐ),ECDSA_P384
,RSA_2048
,RSA_3072
,RSA_4096
์ ๋๋ค.DURATION
: ์ ํ์ฌํญ. ๋ฆฌํ ์ธ์ฆ์ ์ ํจ ๊ธฐ๊ฐ(์ด). ๊ฐ์ 86400(1์ผ)์์ 2592000(30์ผ) ์ฌ์ด์ฌ์ผ ํฉ๋๋ค. ์ง์ ํ์ง ์์ผ๋ฉด ๊ธฐ๋ณธ๊ฐ 86400(1์ผ)์ด ์ฌ์ฉ๋ฉ๋๋ค. ๋ฐ๊ธ๋ ์ธ์ฆ์์ ์ค์ ์ ํจ์ฑ ๊ฒ์ฌ๋ ๋ฐ๊ธ๋ ์ธ์ฆ์์ ์๋ช ์ ์ ํํ ์ ์์ผ๋ฏ๋ก ๋ฐ๊ธํ๋ CA์ ๋ฐ๋ผ ๋ฌ๋ผ์ง๋๋ค.ROTATION_WINDOW_PERCENTAGE
: ์ ํ์ฌํญ: ๊ฐฑ์ ์ด ํธ๋ฆฌ๊ฑฐ๋๋ ์ธ์ฆ์ ์๋ช ์ ๋ฐฑ๋ถ์จ. ๊ฐ์ 50์์ 80 ์ฌ์ด์ฌ์ผ ํฉ๋๋ค. ๊ธฐ๋ณธ๊ฐ์ 50์ ๋๋ค.
ํธ๋ฌ์คํธ ๊ตฌ์ฑ ํ์ผ ๋ง๋ค๊ธฐ
๊ธฐ๋ณธ์ ์ผ๋ก ๋์ผํ ํธ๋ฌ์คํธ ๋๋ฉ์ธ ๋ด์ ์ํฌ๋ก๋๋ ๊ด๋ฆฌํ ์ํฌ๋ก๋ ์์ด๋ดํฐํฐ๋ฅผ ์ฌ์ฉํ์ฌ ์ํธ ์ธ์ฆํ ์ ์์ต๋๋ค. ์๋ก ๋ค๋ฅธ ํธ๋ฌ์คํธ ๋๋ฉ์ธ์ ์๋ ์ํฌ๋ก๋๊ฐ ์ํธ ์ธ์ฆํ๋๋ก ํ๋ ค๋ฉด ์ํฌ๋ก๋ ์์ด๋ดํฐํฐ ํ์์ ํธ๋ฌ์คํธ ๊ด๊ณ๋ฅผ ๋ช
์์ ์ผ๋ก ์ ์ธํด์ผ ํฉ๋๋ค.
๊ฐ ๋๋ฉ์ธ์ ์ธ์ฆ์๋ฅผ ์ ๊ณตํ๋ inlineTrustConfig
๊ฐ ํฌํจ๋ ํธ๋ฌ์คํธ ๊ตฌ์ฑ ํ์ผ์ ๋ง๋ค์ด ์ด๋ฅผ ์ํํฉ๋๋ค.
ํธ๋ฌ์คํธ ๊ตฌ์ฑ ํ์ผ์๋ ๊ด๋ฆฌํ ์ํฌ๋ก๋ ์์ด๋ดํฐํฐ๊ฐ ํผ์ด ์ธ์ฆ์๋ฅผ ๊ฒ์ฆํ๋ ๋ฐ ์ฌ์ฉํ๋ ์ ๋ขฐ ์ต์ปค ์งํฉ์ด ํฌํจ๋์ด ์์ต๋๋ค. ํธ๋ฌ์คํธ ๊ตฌ์ฑ ํ์ผ์ SPIFFE ํธ๋ฌ์คํธ ๋๋ฉ์ธ์ CA ์ธ์ฆ์์ ๋งคํํฉ๋๋ค.
ํธ๋ฌ์คํธ ๊ตฌ์ฑ ํ์ผ์ ๋ง๋ค๋ ค๋ฉด ๋ค์์ ์ํํ์ธ์.
-
์ธ์ฆ์๋ฅผ ๋ค์ด๋ก๋ํฉ๋๋ค.
gcloud privateca pools get-ca-certs ROOT_CA_POOL_ID \ --output-file=CERTIFICATE_PATH \ --location=REGION
๋ค์์ ๋ฐ๊ฟ๋๋ค.
-
ROOT_CA_POOL_ID
: ๋ฃจํธ CA ํ์ ID -
CERTIFICATE_PATH
: PEM ์ธ์ฝ๋ฉ ์ธ์ฆ์๋ฅผ ์ถ๋ ฅํ ๊ฒฝ๋ก -
REGION
: ๋ฃจํธ CA ํ์ ๋ฆฌ์
-
-
PEM ํ์ ์ธ์ฆ์๊ฐ ํฌํจ๋ ์ธ๋ผ์ธ ํธ๋ฌ์คํธ ๊ตฌ์ฑ์ด ํฌํจ๋ ํ์ผ์ ๋ง๋ญ๋๋ค. ํ์ผ์ ๋ค์๊ณผ ์ ์ฌํฉ๋๋ค.
{ "inlineTrustConfig": { "additionalTrustBundles": { "TRUST_DOMAIN_NAME1": { "trustAnchors": [ { "pemCertificate": "-----BEGIN CERTIFICATE-----\nCERTIFICATE_MATERIAL1\n-----END CERTIFICATE-----" }, { "pemCertificate": "-----BEGIN CERTIFICATE-----\nCERTIFICATE_MATERIAL2\n-----END CERTIFICATE-----" } ] }, "TRUSTED_DOMAIN_NAME2": { "trustAnchors": [ { "pemCertificate": "-----BEGIN CERTIFICATE-----\nCERTIFICATE_MATERIAL3\n-----END CERTIFICATE-----" }, { "pemCertificate": "-----BEGIN CERTIFICATE-----\nCERTIFICATE_MATERIAL4\n-----END CERTIFICATE-----" } ] } } } }
๋ค์์ ๋ฐ๊ฟ๋๋ค.
-
TRUST_DOMAIN_NAME
: ๋ค์๊ณผ ๊ฐ์ ํ์์ ํธ๋ฌ์คํธ ๋๋ฉ์ธ ์ด๋ฆ์ ๋๋ค.PROJECT_ID.svc.id.goog
-
CERTIFICATE_MATERIAL
: ํธ๋ฌ์คํธ ๋๋ฉ์ธ์์ ์ธ์ฆ์๋ฅผ ๋ฐ๊ธํ ์ ์๋ ์ ๋ขฐํ ์ ์๋ PEM ํ์์ CA ์ธ์ฆ์ ์งํฉ์ ๋๋ค.
-
CA๋ฅผ ์ํฌ๋ก๋ ์์ด๋ดํฐํฐ ํ์ ๋ฐ์ธ๋ฉ
CA ๊ณ์ธต ๊ตฌ์กฐ๋ฅผ ๋ง๋ค๊ณ ๊ฐ CA์ ์ธ์ฆ์ ๋ฐ๊ธ ๊ตฌ์ฑ์ ๋ง๋ ํ CA๋ฅผ ์ํฌ๋ก๋ ์์ด๋ดํฐํฐ ํ์ ๋ฐ์ธ๋ฉํฉ๋๋ค. CA๋ฅผ ์ํฌ๋ก๋ ์์ด๋ดํฐํฐ ํ์ ๋ฐ์ธ๋ฉํ๋ ค๋ฉด CA์ ์ธ์ฆ์ ๋ฐ๊ธ ๊ตฌ์ฑ์ผ๋ก ์ํฌ๋ก๋ ์์ด๋ดํฐํฐ ํ์ ์ ๋ฐ์ดํธํฉ๋๋ค. ๊ทธ๋ฐ ๋ค์ ํ์ด ์ ๋ฐ์ดํธ๋์๋์ง ํ์ธํ ์ ์์ต๋๋ค.
์ํฌ๋ก๋ ์์ด๋ดํฐํฐ ํ ์ ๋ฐ์ดํธ
ํ์ ์ ๋ฐ์ดํธํ๋ ค๋ฉด ๋ค์ ๋ช ๋ น์ด๋ฅผ ์คํํฉ๋๋ค.
gcloud iam workload-identity-pools update TRUST_DOMAIN_NAME \ --location="global" \ --inline-certificate-issuance-config-file=CIC_JSON_FILE_PATH \ --inline-trust-config-file=TC_JSON_FILE_PATH \ --project=PROJECT_ID
๋ค์์ ๋ฐ๊ฟ๋๋ค.
TRUST_DOMAIN_NAME
: ํธ๋ฌ์คํธ ๋๋ฉ์ธ ์ด๋ฆ์ผ๋ก, ํ์์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.PROJECT_ID.svc.id.goog
CIC_JSON_FILE_PATH
: ์ด์ ์ ๋ง๋ JSON ํ์์ ์ธ์ฆ์ ๋ฐ๊ธ ๊ตฌ์ฑ ํ์ผ(cic.json
)์ ๊ฒฝ๋ก์ ๋๋ค.TC_JSON_FILE_PATH
: ์ ํ์ฌํญ. ์ด์ ์ ๋ง๋ JSON ํ์ ํธ๋ฌ์คํธ ๊ตฌ์ฑ ํ์ผ(tc.json
)์ ๊ฒฝ๋ก์ ๋๋ค. ์ํฌ๋ก๋๊ฐ ์๋ก ๋ค๋ฅธ ํธ๋ฌ์คํธ ๋๋ฉ์ธ์์ ์ธ์ฆํ๋ ๊ฒฝ์ฐ ์ด ํ์ผ์ ์ง์ ํด์ผ ํฉ๋๋ค. ๊ทธ๋ ์ง ์์ผ๋ฉด--inline-trust-config
๋ฅผ ์๋ตํด๋ ๋ฉ๋๋ค.
์ํฌ๋ก๋ ์์ด๋ดํฐํฐ ํ์ด ์ ๋ฐ์ดํธ๋์๋์ง ํ์ธ
์ํฌ๋ก๋ ์์ด๋ดํฐํฐ ํ์ด ์ธ์ฆ์ ๋ฐ๊ธ ๊ตฌ์ฑ ๋ฐ ํธ๋ฌ์คํธ ๊ตฌ์ฑ๊ณผ ํจ๊ป ์ ๋ฐ์ดํธ๋์๋์ง ํ์ธํ๋ ค๋ฉด ๋ค์ ๋ช ๋ น์ด๋ฅผ ์คํํฉ๋๋ค.
gcloud iam workload-identity-pools describe TRUST_DOMAIN_NAME \ --location="global" \ --project=PROJECT_ID
TRUST_DOMAIN_NAME
์ ์ด ๋ฌธ์ ์๋ถ๋ถ์์ ์ํฌ๋ก๋ ์์ด๋ดํฐํฐ ํ์ ์
๋ฐ์ดํธํ๋ ๋ฐ ์ฌ์ฉํ ํธ๋ฌ์คํธ ๋๋ฉ์ธ ์ด๋ฆ์ผ๋ก ๋ฐ๊ฟ๋๋ค.
๋ช ๋ น์ด ์ถ๋ ฅ์ ๋ค์๊ณผ ์ ์ฌํฉ๋๋ค.
inlineCertificateIssuanceConfig: caPools: REGION1: projects/PROJECT_NUMBER1/locations/REGION1/caPools/SUBORDINATE_CA_POOL_ID1, REGION2: projects/PROJECT_NUMBER2/locations/REGION2/caPools/SUBORDINATE_CA_POOL_ID2 keyAlgorithm: ALGORITHM lifetime: DURATION rotationWindowPercentage: ROTATION_WINDOW_PERCENTAGE inlineTrustConfig: additionalTrustBundles: example.com: trustAnchors: - pemCertificate: |- -----BEGIN CERTIFICATE----- CERTIFICATE_MATERIAL1 -----END CERTIFICATE----- - pemCertificate: |- -----BEGIN CERTIFICATE----- CERTIFICATE_MATERIAL2 -----END CERTIFICATE----- myorg.com: trustAnchors: - pemCertificate: |- -----BEGIN CERTIFICATE----- CERTIFICATE_MATERIAL3 -----END CERTIFICATE----- - pemCertificate: |- -----BEGIN CERTIFICATE----- CERTIFICATE_MATERIAL4 -----END CERTIFICATE----- name: PROJECT_ID.svc.id.goog state: ACTIVE
๋ช
๋ น์ด ์ถ๋ ฅ์ inlineCertificateIssuanceConfig
๋๋ inlineTrustConfig
๊ฐ ์์ผ๋ฉด gcloud CLI๊ฐ ๊ฒฐ์ ๋ฐ ํ ๋น๋์ ์ฌ๋ฐ๋ฅธ ํ๋ก์ ํธ๋ฅผ ์ฌ์ฉํ๋๋ก ์ฌ๋ฐ๋ฅด๊ฒ ๊ตฌ์ฑํ๋์ง ํ์ธํฉ๋๋ค.
์ต์ ๋ฒ์ ์ gcloud CLI๋ก ์
๋ฐ์ดํธํด์ผ ํ ์๋ ์์ต๋๋ค.
CA ํ์์ ์ธ์ฆ์๋ฅผ ์์ฒญํ๋๋ก ๊ด๋ฆฌํ ์ํฌ๋ก๋ ์์ด๋ดํฐํฐ๋ฅผ ์น์ธ
CA๋ฅผ ์ํฌ๋ก๋ ์์ด๋ดํฐํฐ ํ์ ๋ฐ์ธ๋ฉํ ํ ๊ด๋ฆฌํ ์ํฌ๋ก๋ ์์ด๋ดํฐํฐ๊ฐ CA ํ์์ ์ธ์ฆ์๋ฅผ ์์ฒญํ๋๋ก ์น์ธํด์ผ ํฉ๋๋ค. ์ด๋ฌํ ID๋ฅผ ์น์ธํ๋ ค๋ฉด ๋ค์์ ์ํํ์ธ์.
๊ฐ ํ์ CA ํ์์ CA Service ์ํฌ๋ก๋ ์ธ์ฆ์ ์์ฒญ์(
roles/privateca.workloadCertificateRequester
) IAM ์ญํ ์ ํธ๋ฌ์คํธ ๋๋ฉ์ธ์ ๋ถ์ฌํฉ๋๋ค. ๋ค์gcloud privateca pools add-iam-policy-binding
๋ช ๋ น์ด๋ ํธ๋ฌ์คํธ ๋๋ฉ์ธ์ด CA ์๋น์ค ์ธ์ฆ์ ์ฒด์ธ์์ ์ธ์ฆ์๋ฅผ ์์ฒญํ๋๋ก ์น์ธํฉ๋๋ค.gcloud privateca pools add-iam-policy-binding SUBORDINATE_CA_POOL_ID \ --location=REGION \ --role=roles/privateca.workloadCertificateRequester \ --member="principal://iam.googleapis.com/projects/PROJECT_NUMBER/name/locations/global/workloadIdentityPools/PROJECT_ID.svc.id.goog" \ --project=CA_PROJECT_ID
๋ค์์ ๋ฐ๊ฟ๋๋ค.
SUBORDINATE_CA_POOL_ID
: ํ์ CA ํ์ ID์ ๋๋ค.REGION
: ํ์ CA ํ์ ๋ฆฌ์ ์ ๋๋ค.PROJECT_NUMBER
: GKE ์ํฌ๋ก๋ ์์ด๋ดํฐํฐ ํ์ด ํฌํจ๋ ํ๋ก์ ํธ์ ํ๋ก์ ํธ ๋ฒํธ์ ๋๋ค.PROJECT_ID
์์PROJECT_NUMBER
๋ฅผ ๊ฐ์ ธ์ค๋ ค๋ฉด ๋ค์ ๋ช ๋ น์ด๋ฅผ ์คํํฉ๋๋ค.gcloud projects describe PROJECT_ID --format="value(projectNumber)"
PROJECT_ID
: GKE Fleet ํธ์คํธ ํ๋ก์ ํธ์ ํ๋ก์ ํธ ID์ ๋๋ค.CA_PROJECT_ID
: ํ์ CA๋ฅผ ๋ง๋ ํ๋ก์ ํธ์ ID์ ๋๋ค.
๊ด๋ฆฌํ ์ํฌ๋ก๋ ์์ด๋ดํฐํฐ์ ์ข ์ CA ํ์ ๋ํ CA ์๋น์ค ํ ๋ฆฌ๋(
roles/privateca.poolReader
) ์ญํ ์ ๋ถ์ฌํฉ๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด ๊ด๋ฆฌํ ์ํฌ๋ก๋ ์์ด๋ดํฐํฐ๊ฐ CA ์ธ์ฆ์ ์ฒด์ธ์์ ์๋ช ๋ X.509 ์ธ์ฆ์๋ฅผ ๊ฐ์ ธ์ฌ ์ ์์ต๋๋ค.gcloud privateca pools add-iam-policy-binding SUBORDINATE_CA_POOL_ID \ --location=REGION \ --role=roles/privateca.poolReader \ --member="principal://iam.googleapis.com/projects/PROJECT_NUMBER/name/locations/global/workloadIdentityPools/PROJECT_ID.svc.id.goog" \ --project=CA_PROJECT_ID
๋ค์์ ๋ฐ๊ฟ๋๋ค.
SUBORDINATE_CA_POOL_ID
: ํ์ CA ํ์ ID์ ๋๋ค.REGION
: ํ์ CA ํ์ ๋ฆฌ์ ์ ๋๋ค.PROJECT_NUMBER
: GKE ์ํฌ๋ก๋ ์์ด๋ดํฐํฐ ํ์ด ํฌํจ๋ ํ๋ก์ ํธ์ ํ๋ก์ ํธ ๋ฒํธ์ ๋๋ค.PROJECT_ID
: GKE Fleet ํธ์คํธ ํ๋ก์ ํธ์ ํ๋ก์ ํธ ID์ ๋๋ค.CA_PROJECT_ID
: ํ์ CA๋ฅผ ๋ง๋ ํ๋ก์ ํธ์ ID์ ๋๋ค.
๊ด๋ฆฌํ ์ํฌ๋ก๋ ์์ด๋ดํฐํฐ๋ก ์ํฌ๋ก๋ ๋ฐฐํฌ
๊ด๋ฆฌํ ์ํฌ๋ก๋ ์์ด๋ดํฐํฐ์ ์ธ์ฆ์๋ฅผ ๋ฐ๊ธํ๋๋ก CA ํ์ ๊ตฌ์ฑํ ํ ๊ด๋ฆฌํ ์ํฌ๋ก๋ ์์ด๋ดํฐํฐ๊ฐ ์๋ ์ํฌ๋ก๋๋ฅผ ๋ฐฐํฌํ ์ ์์ต๋๋ค.
์ด ์น์ ์์๋ ๊ด๋ฆฌํ ์ํฌ๋ก๋ ์์ด๋ดํฐํฐ๊ฐ ์๋ ํ ์คํธ ์ํฌ๋ก๋๋ฅผ ๋ฐฐํฌํ๋ ๋ฐฉ๋ฒ์ ๋ณด์ฌ์ค๋๋ค. ์ด๋ ๊ฒ ํ๋ ค๋ฉด ํฌ๋๋ฅผ ๋ฐฐํฌํ๊ณ , ์ฌ์ฉ์ ์ธ์ฆ ์ ๋ณด๊ฐ ์์ฑ๋์๋์ง ํ์ธํ๊ณ , ์ธ์ฆ์์ SPIFFE ID๋ฅผ ํ์ธํฉ๋๋ค.
ํฌ๋ ๋ฐฐํฌ
ํด๋ฌ์คํฐ์ ํ ์คํธ ํฌ๋๋ฅผ ๋ฐฐํฌํ๋ ค๋ฉด ๋ค์ ๋จ๊ณ๋ฅผ ๋ฐ๋ฅด์ธ์.
ํด๋ฌ์คํฐ ์ฌ์ฉ์ ์ธ์ฆ ์ ๋ณด๋ฅผ ๊ฐ์ ธ์ต๋๋ค.
gcloud container clusters get-credentials CLUSTER_NAME \ --location=CLUSTER_ZONE \ --project=CLUSTER_PROJECT_ID
Kubernetes ๋ค์์คํ์ด์ค๋ฅผ ๋ง๋ญ๋๋ค.
kubectl create namespace KUBERNETES_NAMESPACE
ํ ์คํธ PodSpec์ ๋ฐฐํฌํฉ๋๋ค.
cat <<EOF | kubectl apply -f - apiVersion: v1 kind: Pod metadata: namespace: KUBERNETES_NAMESPACE name: example-pod spec: containers: - name: main image: debian command: ['sleep', 'infinity'] volumeMounts: - name: fleet-spiffe-credentials mountPath: /var/run/secrets/workload-spiffe-credentials readOnly: true nodeSelector: iam.gke.io/gke-metadata-server-enabled: "true" volumes: - name: fleet-spiffe-credentials csi: driver: podcertificate.gke.io volumeAttributes: signerName: spiffe.gke.io/fleet-svid trustDomain: fleet-project/svc.id.goog EOF
์ํฌ๋ก๋ ์ฌ์ฉ์ ์ธ์ฆ ์ ๋ณด ๋์ด
์ํฌ๋ก๋ ์ฌ์ฉ์ ์ธ์ฆ ์ ๋ณด๋ฅผ ๋์ดํ๋ ค๋ฉด ๋ค์ ๋ช ๋ น์ด๋ฅผ ์คํํฉ๋๋ค. ์ฌ์ฉ์ ์ธ์ฆ ์ ๋ณด๋ฅผ ๋ง๋๋ ๋ฐ ๋ช ๋ถ ์ ๋ ๊ฑธ๋ฆด ์ ์์ต๋๋ค.
kubectl exec -it example-pod -n KUBERNETES_NAMESPACE -- ls /var/run/secrets/workload-spiffe-credentials
๋ค์๊ณผ ๊ฐ์ ์ถ๋ ฅ์ด ํ์๋ฉ๋๋ค.
ca_certificates.pem
certificates.pem
private_key.pem
trust_bundles.json
์ธ์ฆ์ ๋ณด๊ธฐ
์ธ์ฆ์๋ฅผ ๋ณด๋ ค๋ฉด ๋ค์ ๋จ๊ณ๋ฅผ ๋ฐ๋ฅด์ธ์.
์ธ์ฆ์๋ฅผ ์ธ์ฆ์ ํ์ผ๋ก ๋ด๋ณด๋ ๋๋ค.
kubectl exec -it example-pod --namespace=KUBERNETES_NAMESPACE -- cat /var/run/secrets/workload-spiffe-credentials/certificates.pem | openssl x509 -noout -text > certfile
์ธ์ฆ์ ํ์ผ์ ํ์ธํฉ๋๋ค.
cat certfile
์ธ์ฆ์์
X509v3 Subject Alternative Name
์์ฑ์๋spiffe://PROJECT_ID.svc.id.goog/ns/KUBERNETES_NAMESPACE/sa/default
ํ์์ SPIFFE ID๊ฐ ํ์๋ฉ๋๋ค.default
๋ ๊ธฐ๋ณธ Kubernetes ServiceAccount๋ฅผ ๋ํ๋ ๋๋ค.
์ํฌ๋ก๋ ๊ฐ ์ธ์ฆ ํ ์คํธ
์ํฌ๋ก๋ ๊ฐ ์ธ์ฆ์ ํ ์คํธํ๋ ค๋ฉด Go๋ฅผ ์ฌ์ฉํ์ฌ mTLS ์ธ์ฆ ํ ์คํธ๋ฅผ ์ฐธ์กฐํ์ธ์.
์ ์ฅ์์ ์ํ ์ฝ๋๋ client ๋ฐ server ์ํฌ๋ก๋๋ฅผ ๋ง๋ญ๋๋ค. ์ด ๋ฌธ์์ ์๋ถ๋ถ์์ ์์ฑํ ์ธ์ฆ์๋ฅผ ์ฌ์ฉํ์ฌ ์ํฌ๋ก๋ ๊ฐ์ ์ํธ ์ธ์ฆ์ ํ ์คํธํ ์ ์์ต๋๋ค.
๋ค์ ๋จ๊ณ
- GKE์ฉ ๊ด๋ฆฌํ ์ํฌ๋ก๋ ์์ด๋ดํฐํฐ ๋ฌธ์ ํด๊ฒฐ
- CA ํ ๋ง๋ค๊ธฐ ์์ธํ ์์๋ณด๊ธฐ
์ง์ ์ฌ์ฉํด ๋ณด๊ธฐ
Google Cloud๋ฅผ ์ฒ์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ ๊ณ์ ์ ๋ง๋ค๊ณ Google ์ ํ์ ์ค์ ์ฑ๋ฅ์ ํ๊ฐํด ๋ณด์ธ์. ์ ๊ท ๊ณ ๊ฐ์๊ฒ๋ ์ํฌ๋ก๋๋ฅผ ์คํ, ํ ์คํธ, ๋ฐฐํฌํ๋ ๋ฐ ์ฌ์ฉํ ์ ์๋ $300์ ๋ฌด๋ฃ ํฌ๋ ๋ง์ด ์ ๊ณต๋ฉ๋๋ค.
๋ฌด๋ฃ๋ก ์์ํ๊ธฐ