Skip to content

chore: GCP 레지스트리 provider 스크립트 추가 & 레플리카셋 임시 조정#20

Merged
doup2001 merged 3 commits intomainfrom
chore/#12
Apr 6, 2026
Merged

chore: GCP 레지스트리 provider 스크립트 추가 & 레플리카셋 임시 조정#20
doup2001 merged 3 commits intomainfrom
chore/#12

Conversation

@doup2001
Copy link
Copy Markdown
Member

@doup2001 doup2001 commented Apr 6, 2026

📌 작업한 내용

  • GCP Artifact Registry 인증 및 이미지 관리용 provider 스크립트를 추가.
  • DB 설정을 위해 ReplicaSet 개수를 임시 조절하여 스케일링 문제 해결.

🔍 참고 사항

  • Provider 스크립트는 gcloud auth나 Service Account 키를 사용해 Artifact Registry 접근을 자동화합니다.
  • ReplicaSet 조정은 초기 배포 시 리소스 부족이나 이미지 풀 문제 해결을 위한 임시 조치입니다.
  • 스크립트 실행 후 gcloud auth configure-docker로 Docker 클라이언트 인증을 확인해야 합니다.

🖼️ 스크린샷

(해당 사항 없음)

🔗 관련 이슈

#12

✅ 체크리스트

  • 로컬에서 빌드 및 테스트 완료
  • 코드 리뷰 반영 완료
  • 문서화 필요 여부 확인

@doup2001 doup2001 added this to the [M3]K8s-구현 milestone Apr 6, 2026
@doup2001 doup2001 self-assigned this Apr 6, 2026
@doup2001 doup2001 added the chore 빌드, 배포, CI/CD 등 인프라 관련 작업 label Apr 6, 2026
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 6, 2026

Terraform Plan - prod 환경

State 버킷 변수 확인 📦 ✅

초기화 결과 ⚙️ ✅

tfvars 복원 결과 🔐 ✅

포맷 검사 결과 🖌 ✅

유효성 검사 결과 🤖 ✅

Plan 결과 📖 ✅

Plan 상세 보기
Terraform used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
  ~ update in-place
+/- create replacement and then destroy

Terraform will perform the following actions:

  # module.k8s_master_nodes.google_compute_instance_group_manager.instance_group[0] will be updated in-place
  ~ resource "google_compute_instance_group_manager" "instance_group" {
        id                             = "projects/prod-pinhouse/zones/asia-northeast3-a/instanceGroupManagers/pinhouse-prod-k8s-master-ig"
        name                           = "pinhouse-prod-k8s-master-ig"
        # (13 unchanged attributes hidden)

      ~ version {
          ~ instance_template = "https://www.googleapis.com/compute/v1/projects/prod-pinhouse/global/instanceTemplates/pinhouse-prod-k8s-master-template-20260405063418353100000001" -> (known after apply)
        }

        # (2 unchanged blocks hidden)
    }

  # module.k8s_master_nodes.google_compute_instance_template.template[0] must be replaced
+/- resource "google_compute_instance_template" "template" {
      ~ id                      = "projects/prod-pinhouse/global/instanceTemplates/pinhouse-prod-k8s-master-template-20260405063418353100000001" -> (known after apply)
      ~ metadata_fingerprint    = "fjoqGSXxCcA=" -> (known after apply)
      ~ metadata_startup_script = <<-EOT # forces replacement
            #!/usr/bin/env bash
            set -euxo pipefail
            
            # ========================================
            # 기본 환경 점검
            # ========================================
            if [ "$(id -u)" -ne 0 ]; then
              echo "이 스크립트는 root 권한으로 실행해야 합니다."
              exit 1
            fi
            
            export DEBIAN_FRONTEND=noninteractive
            
            # ========================================
            # Ubuntu 기본 패키지 업데이트
            # ========================================
            apt-get update -y
            apt-get upgrade -y
            apt-get install -y apt-transport-https ca-certificates curl gpg containerd
            
            # ========================================
            # swap 비활성화
            # ========================================
            swapoff -a
            sed -ri '/\sswap\s/s/^#?/#/' /etc/fstab
            
            # ========================================
            # Kubernetes 네트워크용 커널 모듈 및 sysctl 설정
            # ========================================
            mkdir -p /etc/modules-load.d /etc/sysctl.d /etc/apt/keyrings /etc/containerd
            
            cat <<'EOF' >/etc/modules-load.d/k8s.conf
            overlay
            br_netfilter
            EOF
            
            modprobe overlay
            modprobe br_netfilter
            
            cat <<'EOF' >/etc/sysctl.d/99-kubernetes-cri.conf
            net.bridge.bridge-nf-call-iptables = 1
            net.bridge.bridge-nf-call-ip6tables = 1
            net.ipv4.ip_forward = 1
            EOF
            
            sysctl --system
            
            # ========================================
            # containerd 설정
            # ========================================
            containerd config default >/etc/containerd/config.toml
            sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
            systemctl daemon-reload
            systemctl enable --now containerd
            
            # ========================================
            # Kubernetes apt 저장소 설정
            # ========================================
            curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.35/deb/Release.key | gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
            echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.35/deb/ /' >/etc/apt/sources.list.d/kubernetes.list
            
            # ========================================
            # Kubernetes 패키지 설치
            # ========================================
            apt-get update -y
            apt-get install -y kubelet kubeadm kubectl
            apt-mark hold kubelet kubeadm kubectl
            
            # ========================================
          + # kubelet Artifact Registry credential provider 설정
          + # ========================================
          + mkdir -p /etc/kubernetes /opt/image-credential-provider
          + 
          + cat <<'PROVIDER_EOF' >/opt/image-credential-provider/gcp-artifact-registry-provider
          + #!/usr/bin/env bash
          + set -euo pipefail
          + 
          + # kubelet 요청 본문은 현재 인증 계산에 사용하지 않으므로 읽고 종료합니다.
          + cat >/dev/null
          + 
          + token_response="$(curl -fsSL -H 'Metadata-Flavor: Google' \
          +   http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token)"
          + access_token="$(printf '%s' "${token_response}" | sed -n 's/.*"access_token"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p')"
          + 
          + if [ -z "${access_token}" ]; then
          +   echo "메타데이터 서버에서 Artifact Registry access token을 가져오지 못했습니다." >&2
          +   exit 1
          + fi
          + 
          + cat <<JSON_EOF
          + {
          +   "apiVersion": "credentialprovider.kubelet.k8s.io/v1",
          +   "kind": "CredentialProviderResponse",
          +   "cacheKeyType": "Registry",
          +   "auth": {
          +     "*.pkg.dev": {
          +       "username": "oauth2accesstoken",
          +       "password": "${access_token}"
          +     }
          +   }
          + }
          + JSON_EOF
          + PROVIDER_EOF
          + 
          + chmod 0755 /opt/image-credential-provider/gcp-artifact-registry-provider
          + 
          + cat <<'EOF' >/etc/kubernetes/credential-provider-config.yaml
          + apiVersion: kubelet.config.k8s.io/v1
          + kind: CredentialProviderConfig
          + providers:
          +   - name: gcp-artifact-registry-provider
          +     apiVersion: credentialprovider.kubelet.k8s.io/v1
          +     matchImages:
          +       - "*.pkg.dev"
          +     defaultCacheDuration: "30m"
          + EOF
          + 
          + cat <<'EOF' >/etc/default/kubelet
          + KUBELET_EXTRA_ARGS="--image-credential-provider-config=/etc/kubernetes/credential-provider-config.yaml --image-credential-provider-bin-dir=/opt/image-credential-provider"
          + EOF
          + 
          + # ========================================
            # 서비스 활성화
            # ========================================
            systemctl enable --now kubelet
            
            # ========================================
            # kubeadm 및 Calico 초기 설정 파일 생성
            # ========================================
            cat <<EOF >/root/kubeadm-config.yaml
            apiVersion: kubeadm.k8s.io/v1beta4
            kind: ClusterConfiguration
            networking:
              podSubnet: 192.168.0.0/16
              serviceSubnet: 10.96.0.0/12
            ---
            apiVersion: kubelet.config.k8s.io/v1beta1
            kind: KubeletConfiguration
            cgroupDriver: systemd
            EOF
            
            cat <<EOF >/root/calico-custom-resources.yaml
            apiVersion: operator.tigera.io/v1
            kind: Installation
            metadata:
              name: default
            spec:
              calicoNetwork:
                ipPools:
                  - blockSize: 26
                    cidr: 192.168.0.0/16
                    encapsulation: IPIP
                    natOutgoing: Enabled
                    nodeSelector: all()
            EOF
            
            cat <<EOF >/root/install-calico.sh
            #!/usr/bin/env bash
            set -euxo pipefail
            
            kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.31.4/manifests/operator-crds.yaml
            kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.31.4/manifests/tigera-operator.yaml
            kubectl create -f /root/calico-custom-resources.yaml
            EOF
            
            chmod +x /root/install-calico.sh
            
            # ========================================
            # 후속 작업 안내
            # ========================================
            echo "마스터 노드 초기 설정이 완료되었습니다."
            echo "1. kubeadm init --config /root/kubeadm-config.yaml --upload-certs"
            echo "2. mkdir -p \$HOME/.kube && cp /etc/kubernetes/admin.conf \$HOME/.kube/config && chown \$(id -u):\$(id -g) \$HOME/.kube/config"
            echo "3. /root/install-calico.sh"
        EOT
      ~ name                    = "pinhouse-prod-k8s-master-template-20260405063418353100000001" -> (known after apply)
      ~ region                  = "asia-northeast3" -> (known after apply)
      ~ self_link               = "https://www.googleapis.com/compute/v1/projects/prod-pinhouse/global/instanceTemplates/pinhouse-prod-k8s-master-template-20260405063418353100000001" -> (known after apply)
      ~ self_link_unique        = "https://www.googleapis.com/compute/v1/projects/prod-pinhouse/global/instanceTemplates/pinhouse-prod-k8s-master-template-20260405063418353100000001?uniqueId=3912128719065431173" -> (known after apply)
        tags                    = [
            "k8s-master",
            "prod",
        ]
      + tags_fingerprint        = (known after apply)
        # (9 unchanged attributes hidden)

      ~ disk {
          ~ device_name           = "persistent-disk-0" -> (known after apply)
          ~ interface             = "SCSI" -> (known after apply)
          - labels                = {} -> null
          ~ mode                  = "READ_WRITE" -> (known after apply)
          ~ provisioned_iops      = 0 -> (known after apply)
          - resource_manager_tags = {} -> null
          - resource_policies     = [] -> null
          ~ source_image          = "projects/ubuntu-os-cloud/global/images/family/ubuntu-2204-lts" -> "ubuntu-os-cloud/ubuntu-2204-lts"
          ~ type                  = "PERSISTENT" -> (known after apply)
            # (4 unchanged attributes hidden)
        }

      ~ network_interface {
          ~ internal_ipv6_prefix_length = 0 -> (known after apply)
          + ipv6_access_type            = (known after apply)
          + ipv6_address                = (known after apply)
          ~ name                        = "nic0" -> (known after apply)
          - queue_count                 = 0 -> null
          + stack_type                  = (known after apply)
          ~ subnetwork_project          = "prod-pinhouse" -> (known after apply)
            # (2 unchanged attributes hidden)
        }

      ~ scheduling {
          - min_node_cpus       = 0 -> null
          ~ provisioning_model  = "STANDARD" -> (known after apply)
            # (3 unchanged attributes hidden)
        }

      ~ service_account {
          ~ email  = "default" -> (known after apply)
            # (1 unchanged attribute hidden)
        }
    }

  # module.k8s_worker_nodes.google_compute_instance_group_manager.instance_group[0] will be updated in-place
  ~ resource "google_compute_instance_group_manager" "instance_group" {
        id                             = "projects/prod-pinhouse/zones/asia-northeast3-a/instanceGroupManagers/pinhouse-prod-k8s-workers-ig"
        name                           = "pinhouse-prod-k8s-workers-ig"
        # (13 unchanged attributes hidden)

      ~ version {
          ~ instance_template = "https://www.googleapis.com/compute/v1/projects/prod-pinhouse/global/instanceTemplates/pinhouse-prod-k8s-workers-template-20260405063418590200000002" -> (known after apply)
        }

        # (4 unchanged blocks hidden)
    }

  # module.k8s_worker_nodes.google_compute_instance_template.template[0] must be replaced
+/- resource "google_compute_instance_template" "template" {
      ~ id                      = "projects/prod-pinhouse/global/instanceTemplates/pinhouse-prod-k8s-workers-template-20260405063418590200000002" -> (known after apply)
      ~ metadata_fingerprint    = "ti8UO_sDh-E=" -> (known after apply)
      ~ metadata_startup_script = <<-EOT # forces replacement
            #!/usr/bin/env bash
            set -euxo pipefail
            
            # ========================================
            # 기본 환경 점검
            # ========================================
            if [ "$(id -u)" -ne 0 ]; then
              echo "이 스크립트는 root 권한으로 실행해야 합니다."
              exit 1
            fi
            
            export DEBIAN_FRONTEND=noninteractive
            
            # ========================================
            # Ubuntu 기본 패키지 업데이트
            # ========================================
            apt-get update -y
            apt-get upgrade -y
            apt-get install -y apt-transport-https ca-certificates curl gpg containerd
            
            # ========================================
            # swap 비활성화
            # ========================================
            swapoff -a
            sed -ri '/\sswap\s/s/^#?/#/' /etc/fstab
            
            # ========================================
            # Kubernetes 네트워크용 커널 모듈 및 sysctl 설정
            # ========================================
            mkdir -p /etc/modules-load.d /etc/sysctl.d /etc/apt/keyrings /etc/containerd
            
            cat <<'EOF' >/etc/modules-load.d/k8s.conf
            overlay
            br_netfilter
            EOF
            
            modprobe overlay
            modprobe br_netfilter
            
            cat <<'EOF' >/etc/sysctl.d/99-kubernetes-cri.conf
            net.bridge.bridge-nf-call-iptables = 1
            net.bridge.bridge-nf-call-ip6tables = 1
            net.ipv4.ip_forward = 1
            EOF
            
            sysctl --system
            
            # ========================================
            # containerd 설정
            # ========================================
            containerd config default >/etc/containerd/config.toml
            sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
            systemctl daemon-reload
            systemctl enable --now containerd
            
            # ========================================
            # Kubernetes apt 저장소 설정
            # ========================================
            curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.35/deb/Release.key | gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
            echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.35/deb/ /' >/etc/apt/sources.list.d/kubernetes.list
            
            # ========================================
            # Kubernetes 패키지 설치
            # ========================================
            apt-get update -y
            apt-get install -y kubelet kubeadm
            apt-mark hold kubelet kubeadm
            
            # ========================================
          + # kubelet Artifact Registry credential provider 설정
          + # ========================================
          + mkdir -p /etc/kubernetes /opt/image-credential-provider
          + 
          + cat <<'PROVIDER_EOF' >/opt/image-credential-provider/gcp-artifact-registry-provider
          + #!/usr/bin/env bash
          + set -euo pipefail
          + 
          + # kubelet 요청 본문은 현재 인증 계산에 사용하지 않으므로 읽고 종료합니다.
          + cat >/dev/null
          + 
          + token_response="$(curl -fsSL -H 'Metadata-Flavor: Google' \
          +   http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token)"
          + access_token="$(printf '%s' "${token_response}" | sed -n 's/.*"access_token"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p')"
          + 
          + if [ -z "${access_token}" ]; then
          +   echo "메타데이터 서버에서 Artifact Registry access token을 가져오지 못했습니다." >&2
          +   exit 1
          + fi
          + 
          + cat <<JSON_EOF
          + {
          +   "apiVersion": "credentialprovider.kubelet.k8s.io/v1",
          +   "kind": "CredentialProviderResponse",
          +   "cacheKeyType": "Registry",
          +   "auth": {
          +     "*.pkg.dev": {
          +       "username": "oauth2accesstoken",
          +       "password": "${access_token}"
          +     }
          +   }
          + }
          + JSON_EOF
          + PROVIDER_EOF
          + 
          + chmod 0755 /opt/image-credential-provider/gcp-artifact-registry-provider
          + 
          + cat <<'EOF' >/etc/kubernetes/credential-provider-config.yaml
          + apiVersion: kubelet.config.k8s.io/v1
          + kind: CredentialProviderConfig
          + providers:
          +   - name: gcp-artifact-registry-provider
          +     apiVersion: credentialprovider.kubelet.k8s.io/v1
          +     matchImages:
          +       - "*.pkg.dev"
          +     defaultCacheDuration: "30m"
          + EOF
          + 
          + cat <<'EOF' >/etc/default/kubelet
          + KUBELET_EXTRA_ARGS="--image-credential-provider-config=/etc/kubernetes/credential-provider-config.yaml --image-credential-provider-bin-dir=/opt/image-credential-provider"
          + EOF
          + 
          + # ========================================
            # 서비스 활성화
            # ========================================
            systemctl enable --now kubelet
            
            # ========================================
            # 후속 작업 안내
            # ========================================
            echo "워커 노드 초기 설정이 완료되었습니다. 이후 kubeadm join 명령을 실행하세요."
        EOT
      ~ name                    = "pinhouse-prod-k8s-workers-template-20260405063418590200000002" -> (known after apply)
      ~ region                  = "asia-northeast3" -> (known after apply)
      ~ self_link               = "https://www.googleapis.com/compute/v1/projects/prod-pinhouse/global/instanceTemplates/pinhouse-prod-k8s-workers-template-20260405063418590200000002" -> (known after apply)
      ~ self_link_unique        = "https://www.googleapis.com/compute/v1/projects/prod-pinhouse/global/instanceTemplates/pinhouse-prod-k8s-workers-template-20260405063418590200000002?uniqueId=6398577993588915333" -> (known after apply)
        tags                    = [
            "k8s-worker",
            "prod",
        ]
      + tags_fingerprint        = (known after apply)
        # (9 unchanged attributes hidden)

      ~ disk {
          ~ device_name           = "persistent-disk-0" -> (known after apply)
          ~ interface             = "SCSI" -> (known after apply)
          - labels                = {} -> null
          ~ mode                  = "READ_WRITE" -> (known after apply)
          ~ provisioned_iops      = 0 -> (known after apply)
          - resource_manager_tags = {} -> null
          - resource_policies     = [] -> null
          ~ source_image          = "projects/ubuntu-os-cloud/global/images/family/ubuntu-2204-lts" -> "ubuntu-os-cloud/ubuntu-2204-lts"
          ~ type                  = "PERSISTENT" -> (known after apply)
            # (4 unchanged attributes hidden)
        }

      ~ network_interface {
          ~ internal_ipv6_prefix_length = 0 -> (known after apply)
          + ipv6_access_type            = (known after apply)
          + ipv6_address                = (known after apply)
          ~ name                        = "nic0" -> (known after apply)
          - queue_count                 = 0 -> null
          + stack_type                  = (known after apply)
          ~ subnetwork_project          = "prod-pinhouse" -> (known after apply)
            # (2 unchanged attributes hidden)
        }

      ~ scheduling {
          - min_node_cpus       = 0 -> null
          ~ provisioning_model  = "STANDARD" -> (known after apply)
            # (3 unchanged attributes hidden)
        }

      ~ service_account {
          ~ email  = "default" -> (known after apply)
            # (1 unchanged attribute hidden)
        }
    }

Plan: 2 to add, 2 to change, 2 to destroy.

실행 사용자: @doup2001, 이벤트: pull_request

@doup2001 doup2001 merged commit 1a23b0a into main Apr 6, 2026
4 checks passed
@doup2001 doup2001 deleted the chore/#12 branch April 6, 2026 07:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

chore 빌드, 배포, CI/CD 등 인프라 관련 작업

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant