マスター アクセス用のネットワーク プロキシを持つ GKE 限定公開クラスタの作成

GKE 限定公開クラスタを作成してクラスタのマスター エンドポイントを限定公開にすると、そのクラスタのマスターノードは公共のインターネットからアクセスできなくなりますが、管理目的でアクセスできるようにする必要があります。

デフォルトでは、クラスタはそのプライベート エンドポイントを介してマスターにアクセスでき、承認済みネットワークは VPC 内で定義できます。ただし、マスターには、別の VPC ネットワーク ピアリング接続(ハブアンドスポーク設計など)を介してアクセスすることはできません(承認済み IP アドレス空間内に作成してホストするプロキシを介する場合を除く)。

このチュートリアルでは、GKE 限定公開クラスタ内でこのようなプロキシを構成する方法について説明します。

目標

  • 外部アクセスを許可しない GKE 限定公開クラスタを作成する。
  • Docker イメージを作成してデプロイし、プロキシを実行する。
  • プロキシにアクセスする Kubernetes Service を作成する。
  • プロキシへのアクセスをテストする。

料金

このチュートリアルでは、Google Cloud Platform の課金対象となる以下のコンポーネントを使用します。

料金計算ツールを使用すると、予想使用量に基づいて費用の見積もりを作成できます。

このチュートリアルを終了した後、作成したリソースを削除すると、それ以上の請求は発生しません。詳しくは、クリーンアップをご覧ください。

始める前に

  1. Google アカウントにログインします。

    Google アカウントをまだお持ちでない場合は、新しいアカウントを登録します。

  2. GCP プロジェクトを選択または作成します。

    プロジェクト セレクタのページに移動

  3. Google Cloud Platform プロジェクトに対して課金が有効になっていることを確認します。 詳しくは、課金を有効にする方法をご覧ください。

  4. Compute Engine と Google Kubernetes Engine API を有効にします。

    APIを有効にする

環境設定

このチュートリアルでは、Cloud Shell を使用してコマンドを入力します。Cloud Shell では GCP Console のコマンドラインにアクセスできます。また、GCP で開発を行うために必要な Cloud SDK やその他のツールも含まれています。Cloud Shell は GCP Console の下部にウィンドウとして表示されます。初期化が完了するまでに数分かかることもありますが、ウィンドウはすぐに表示されます。

Cloud Shell を使用して環境を設定するには:

  1. GCP Console で Cloud Shell を開きます。

    Cloud Shell を開く

  2. 作成または選択したプロジェクトで作業していることを確認します。[YOUR_PROJECT_ID] は GCP プロジェクトに置き換えてください。

    gcloud config set project [YOUR_PROJECT_ID]
    export PROJECT_ID=`gcloud config list --format="value(core.project)"`
    
  3. デフォルトのコンピューティング ゾーンを設定します。このチュートリアルでは、us-east1 に設定します。本番環境にデプロイする場合は、選択したリージョンにデプロイします。

    gcloud config set compute/region us-central1
    gcloud config set compute/zone us-central1-c
    export REGION=us-central1
    export ZONE=us-central1-c
    
    

VPC ネットワークとクライアント VM の作成

リソースをホストする VPC ネットワークとサブネットを作成します。

  1. VPC ネットワークを作成します。

    gcloud compute networks create k8s-proxy --subnet-mode=custom
    
  2. 新しく作成した VPC ネットワークにカスタム サブネットを作成します。

    gcloud compute networks subnets create subnet-cluster \
        --network=k8s-proxy --range=10.50.0.0/16
    
  3. Kubernetes クラスタにリソースをデプロイするために使用するクライアント VM を作成します。

    gcloud compute instances create --subnet=subnet-cluster \
        --scopes cloud-platform proxy-temp
    
  4. 新しく作成したインスタンスの内部 IP アドレスを環境変数に保存します。

    export CLIENT_IP=`gcloud compute instances describe proxy-temp \
        --format="value(networkInterfaces[0].networkIP)"`
    
  5. VPC ネットワークへの SSH アクセスを許可するファイアウォール ルールを作成します。

    gcloud compute firewall-rules create k8s-proxy-ssh --network k8s-proxy \
        --allow tcp:22
    

限定公開クラスタの作成

このチュートリアルで使用する限定公開クラスタを作成します。

使用したいクラスタがすでにある場合、クラスタの作成手順はスキップできますが、クライアント マシンに最初にアクセスする方法を構成する必要があります。

  • Cloud Shell で、クラスタを作成します。

    gcloud container clusters create frobnitz  \
        --master-ipv4-cidr=172.16.0.64/28 \
        --network k8s-proxy \
        --subnetwork=subnet-cluster \
        --enable-ip-alias \
        --enable-private-nodes \
        --enable-private-endpoint \
        --master-authorized-networks $CLIENT_IP/32 \
        --enable-master-authorized-networks
    

    このコマンドを実行すると、frobnitz という名前の GKE 限定公開クラスタが作成され、クライアント マシンだけにアクセスを許可するようにマスター承認済みのネットワークが設定されます。

Docker イメージの作成

次の手順に沿って k8s-api-proxy, という Kubernetes API プロキシ イメージを作成します。これは、Kubernetes API サーバーへの転送プロキシとして機能します。

  1. Cloud Shell でディレクトリを作成し、そのディレクトリに移動します。

    mkdir k8s-api-proxy && cd k8s-api-proxy
  2. Dockerfile を作成します。次の構成を使用して Alpine からコンテナを作成します。Alpine は、Privoxy プロキシを含む軽量のコンテナ ディストリビューションです。Dockerfile は他にも、コンテナを初期化するために curljq をインストールし、必要な構成ファイルを追加し、ポート 8118 を GKE に内部的に公開し、起動スクリプトを追加します。

    FROM alpine
    RUN apk add -U curl privoxy jq && \ mv /etc/privoxy/templates /etc/privoxy-templates && \ rm -rf /var/cache/apk/* /etc/privoxy/* && \ mv /etc/privoxy-templates /etc/privoxy/templates ADD --chown=privoxy:privoxy config \ /etc/privoxy/ ADD --chown=privoxy:privoxy k8s-only.action \ /etc/privoxy/ ADD --chown=privoxy:privoxy k8s-rewrite-internal.filter \ /etc/privoxy/ ADD k8s-api-proxy.sh /
    EXPOSE 8118/tcp
    ENTRYPOINT ["./k8s-api-proxy.sh"]
  3. k8s-api-proxy ディレクトリに config ファイルを作成し、次の内容を追加します。

    #config directory
    confdir /etc/privoxy
    # Allow Kubernetes API access only
    actionsfile /etc/privoxy/k8s-only.action
    # Rewrite https://CLUSTER_IP to https://kubernetes.default
    filterfile /etc/privoxy/k8s-rewrite-internal.filter
    # Don't show the pod name in errors
    hostname k8s-privoxy
    # Bind to all interfaces, port :8118
    listen-address  :8118
    # User cannot click-through a block
    enforce-blocks 1
    # Allow more than one outbound connection
    tolerate-pipelining 1
    
  4. 同じディレクトリに k8s-only.action ファイルを作成し、次の内容を追加します。k8s-api-proxy.sh が実行されると、CLUSTER_IP が置き換わります。

    # Block everything...
    {+block{Not Kubernetes}}
    /
    # ... except the internal k8s endpoint, which you rewrite (see # k8s-rewrite-internal.filter). {+client-header-filter{k8s-rewrite-internal} -block{Kubernetes}} CLUSTER_IP/
  5. k8s-rewrite-internal.filter ファイルを作成し、次の内容を追加します。k8s-api-proxy.sh が実行されると、CLUSTER_IP が置き換わります。

    CLIENT-HEADER-FILTER: k8s-rewrite-internal\
     Rewrite https://CLUSTER_IP/ to https://kubernetes.default/
    s@(CONNECT) CLUSTER_IP:443\
     (HTTP/\d\.\d)@$1 kubernetes.default:443 $2@ig
    
  6. k8s-api-proxy.sh ファイルを作成し、次の内容を追加します。

    #!/bin/sh
    
    set -o errexit
    set -o pipefail
    set -o nounset
    
    # Get the internal cluster IP
    INTERNAL_IP=$(curl -k -SsL https://kubernetes.default/api |
     jq -r '.serverAddressByClientCIDRs[0].serverAddress')
    
    # Replace CLUSTER_IP in the rewrite filter and action file
    sed -i "s/CLUSTER_IP/${INTERNAL_IP}/g"\
     /etc/privoxy/k8s-rewrite-internal.filter
    sed -i "s/CLUSTER_IP/${INTERNAL_IP}/g"\
     /etc/privoxy/k8s-only.action
    
    # Start Privoxy un-daemonized
    privoxy --no-daemon /etc/privoxy/config
    
  7. k8s-api-proxy.sh を実行可能にします。

    chmod +x k8s-api-proxy.sh
  8. コンテナをビルドして、プロジェクトに push します。

    docker build -t gcr.io/$PROJECT_ID/k8s-api-proxy:0.1 .
    docker push gcr.io/$PROJECT_ID/k8s-api-proxy:0.1
    

イメージとサービスのデプロイ

  1. Cloud Shell で、作成済みのクライアント VM にログインします。

    gcloud compute ssh proxy-temp
    
  2. kubectl ツールをインストールします。

    sudo apt-get install kubectl
    
  3. プロジェクト ID を環境変数として保存します。

    export PROJECT_ID=`gcloud config list --format="value(core.project)"`
    
  4. クラスタ認証情報を取得します。

    gcloud container clusters get-credentials frobnitz \
    --zone us-central1-c --internal-ip
    
  5. 作成したコンテナを公開する Kubernetes 環境を作成します。

    kubectl run k8s-api-proxy \
        --image=gcr.io/$PROJECT_ID/k8s-api-proxy:0.1 \
        --port=8118
    
  6. 内部ロードバランサ用の ilb.yaml ファイルを作成し、次の内容をコピーします。

    apiVersion: v1
    kind: Service
    metadata:
      labels:
        run: k8s-api-proxy
      name: k8s-api-proxy
      namespace: default
      annotations:
        cloud.google.com/load-balancer-type: "Internal"
    spec:
      ports:
      - port: 8118
        protocol: TCP
        targetPort: 8118
      selector:
        run: k8s-api-proxy
      type: LoadBalancer
    
  7. 内部ロードバランサをデプロイします。

    kubectl create -f ilb.yaml
  8. サービスの IP アドレスを確認します。

    kubectl get service/k8s-api-proxy

    出力は次のようになります。外部 IP が表示されたら、プロキシの準備は完了です。

    NAME            TYPE           CLUSTER-IP     EXTERNAL-IP   PORT(S)          AGE
    k8s-api-proxy   LoadBalancer   10.24.13.129   10.24.24.3    8118:30282/TCP   2m
    

    この外部 IP アドレスはプロキシのアドレスです。

  9. ILB の IP アドレスを環境変数として保存します。

    export LB_IP=`kubectl get  service/k8s-api-proxy \
    -o jsonpath='{.status.loadBalancer.ingress[].ip}'`
    
  10. クラスタのマスター IP アドレスを環境変数に保存します。

    export MASTER_IP=`gcloud container clusters describe frobnitz \
    --zone=us-central1-c \
    --format="get(privateClusterConfig.privateEndpoint)"`
    
  11. プロキシ経由で Kubernetes API にアクセスして、プロキシが使用可能であることを確認します。

    curl -k -x $LB_IP:8118 https://$MASTER_IP/api
    
    出力は次のようになります。
    {
      "kind": "APIVersions",
      "versions": [
        "v1"
      ],
      "serverAddressByClientCIDRs": [
        {
          "clientCIDR": "0.0.0.0/0",
          "serverAddress": "172.16.0.66:443"
        }
      ]
    }
    
  12. どこからでも kubectl コマンドで内部ロードバランサに接続できるように、https_proxy 環境変数を HTTP プロキシに設定します。

    export https_proxy=$LB_IP:8118
  13. kubectl コマンドを実行して、プロキシと https_proxy 変数をテストします。

    kubectl get pods

    出力は次のようになります。これは、プロキシ経由で Kubernetes API に正常に接続されたことを意味します。

    NAME                             READY   STATUS    RESTARTS   AGE
    k8s-api-proxy-766c69dd45-mfqf4   1/1     Running   0          6m15s
    
  14. クライアント VM を終了します。

    exit

クリーンアップ

このチュートリアルで使用するリソースについて、Google Cloud Platform アカウントへの課金が発生しないようにする手順は次のとおりです。

プロジェクトを削除する

  1. GCP Console で [プロジェクト] ページに移動します。

    プロジェクト ページに移動

  2. プロジェクト リストで、削除するプロジェクトを選択し、[削除] をクリックします。
  3. ダイアログでプロジェクト ID を入力し、[シャットダウン] をクリックしてプロジェクトを削除します。

次のステップ

このページは役立ちましたか?評価をお願いいたします。

フィードバックを送信...