🐕

Kubernetes(GKE)で動作するNginx IngerssのProxyを使って、外部の静的サイト(GCS)を表示する

2023/11/16に公開

記事の内容

特定のドメイン配下で、外部の静的サイトを表示する必要があり、NginxのProxyを使って実現したため、その方法を紹介します。

example.com というドメインでKubernetes上でWebサイトを運用していて、exmaple.com/blogページのみ、Kubernetesの中で動作しているサービスではなく、全く関係ない外部のブログサイトを表示するイメージです。

記事を読むと得られるもの

  • KubernetesにNginx IngressをInstallする方法
  • Kubernetesから外部サイトに対してアクセスして、表示する方法

記事の長さ

3分で読めます

Kubernetesクラスターの準備

GKEクラスターを作成する

以下のTerraformソースでGKEクラスターを作成してください。

main.tf

resource "google_project_service" "compute" {
  project = var.project_id
  service = "compute.googleapis.com"
}
resource "google_project_service" "container" {
  project = var.project_id
  service = "container.googleapis.com"
}

resource "google_compute_network" "this" {
  project                 = var.project_id
  name                    = "main-network"
  auto_create_subnetworks = false
}

resource "google_compute_subnetwork" "this" {
  project       = var.project_id
  name          = "main-subnetwork"
  ip_cidr_range = "10.2.0.0/16"
  region        = "asia-northeast1"
  network       = google_compute_network.this.id
  secondary_ip_range {
    range_name    = "pod-ip-range"
    ip_cidr_range = "10.10.0.0/16"
  }
  secondary_ip_range {
    range_name    = "service-ip-range"
    ip_cidr_range = "10.20.0.0/16"
  }
}

data "google_client_config" "default" {}

provider "kubernetes" {
  host                   = "https://${module.gke_cluster.endpoint}"
  token                  = data.google_client_config.default.access_token
  cluster_ca_certificate = base64decode(module.gke_cluster.ca_certificate)
}

module "gke_cluster" {
  source     = "terraform-google-modules/kubernetes-engine/google"
  project_id = var.project_id

  name                        = "test-cluster"
  regional                    = true
  region                      = "asia-northeast1"
  network                     = google_compute_network.this.name
  subnetwork                  = google_compute_subnetwork.this.name
  ip_range_pods               = "pod-ip-range"
  ip_range_services           = "service-ip-range"
  create_service_account      = true
  enable_cost_allocation      = true
  enable_binary_authorization = false
  gcs_fuse_csi_driver         = true

  depends_on = [
    google_project_service.compute,
    google_project_service.container,
  ]
}

上記ソースをapplyすると、GKEリソースが作成されます。

https://zenn.dev/ring_belle/articles/gcp-terraform-gke

TerraformでGKEを作ることに関しては、上記記事で解説しています。

NginxのInstall

先ほど作成したgcp上のKubernetes ClusterにNginx-IngressをInstallします。
以下のコマンドでInstallが完了します。

$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.8.2/deploy/static/provider/cloud/deploy.yaml
namespace/ingress-nginx created
serviceaccount/ingress-nginx created
serviceaccount/ingress-nginx-admission created
role.rbac.authorization.k8s.io/ingress-nginx created
role.rbac.authorization.k8s.io/ingress-nginx-admission created
clusterrole.rbac.authorization.k8s.io/ingress-nginx created
clusterrole.rbac.authorization.k8s.io/ingress-nginx-admission created
rolebinding.rbac.authorization.k8s.io/ingress-nginx created
rolebinding.rbac.authorization.k8s.io/ingress-nginx-admission created
clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx created
clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx-admission created
configmap/ingress-nginx-controller created
service/ingress-nginx-controller created
service/ingress-nginx-controller-admission created
deployment.apps/ingress-nginx-controller created
job.batch/ingress-nginx-admission-create created
job.batch/ingress-nginx-admission-patch created
ingressclass.networking.k8s.io/nginx created
validatingwebhookconfiguration.admissionregistration.k8s.io/ingress-nginx-admission created

以下のコマンドで、NginxIngressが起動していることを確認できます。

$ kubectl get pod -n ingress-nginx
NAME                                        READY   STATUS      RESTARTS   AGE
ingress-nginx-admission-create-lvx2k        0/1     Completed   0          42s
ingress-nginx-admission-patch-45n9m         0/1     Completed   2          42s
ingress-nginx-controller-778d4c6454-k9zmg   1/1     Running     0          42s

Proxyを設定する

Nginx Ingressを構築・起動します。

Nginx Proxyを実装する

---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: external-site-ingress
  namespace: ingress-nginx
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/upstream-vhost: storage.googleapis.com
    nginx.ingress.kubernetes.io/rewrite-target: /<bucket name>/$1
spec:
  rules:
  - host:
    http:
      paths:
      - path: /(.*)$
        pathType: Prefix
        backend:
          service:
            name: external-site-service
            port:
              number: 80
---
apiVersion: v1
kind: Service
metadata:
  name: external-site-service
  namespace: ingress-nginx
spec:
  type: ExternalName
  externalName: storage.googleapis.com

上記YAMLファイルをapplyすることで、全てのアクセスをGCSに送ることができます。
そして、<bucket name>の部分を自分で立ち上げたGCSのバケット名に変更することで、全てのトラフィックをGCSバケットに向けることができます。

アクセスする

以上で準備が完了しました。

以下コマンドで、ロードバランサーのIPアドレスがわかります。

$ kubectl get ingress
NAME                    CLASS    HOSTS   ADDRESS        PORTS   AGE
external-site-ingress   <none>   *       34.85.15.142   80      6m53s

GCSに画像か何かをアップロードしておく、上記IPアドレスからその画像にアクセスしてみます。

GCSに/test-1.jpgというファイルをアップロードした状態で、http://34.85.15.142/test-1.jpgにアクセスしたところ、以下のようにアップロードしたテスト画像が表示されました。

gcp-gke-nginx-proxy

これで、internet -> Kubernetes Cluster -> 外部静的サイト(GCSバケット) というアクセスが可能になりました。これで、リダイレクトせずに、特定のドメインで運用しているKubernetesに紐づいたドメイン名のまま外部の静的ページを表示させられます。

※今回はルートディレクトリ配下全てのアクセスをGCSにProxyしましたが、特定ディレクトリのみを指定すれば、/blog配下のみ外部のBlogサイトにProxyしたり、/assets配下のみGCSバケットにProxyしたりできます。

note

勉強法やキャリア構築法など、エンジニアに役立つ記事をnoteで配信しています。

https://note.com/ring_belle/membership

Discussion