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

Last reviewed 2019-07-02 UTC

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

デフォルトでは、クラスタはプライベート エンドポイントを介してコントローラにアクセスでき、承認済みネットワークは VPC ネットワーク内で定義できます。

ただし、オンプレミス ネットワークまたは他の VPC ネットワークからコントローラにアクセスするには、追加のステップが必要です。これは、コントローラをホストする VPC ネットワークは Google が所有するものであり、他の VPC ネットワーク ピアリング接続、Cloud VPN、Cloud Interconnect 経由で接続されたリソースからアクセスできないためです。

オンプレミス、または Cloud VPN か Cloud Interconnect で接続された別の VPC ネットワークからコントローラにアクセスするには、VPC ネットワークから Google 所有の VPC ネットワークへのルート エクスポートを有効にします

別の VPC ネットワーク、または別の VPC ネットワーク ピアリング(ハブアンドスポーク設計など)を介して接続されたオンプレミスからコントローラへのアクセスを有効にするには、承認済み IP アドレス空間にホストされたプロキシを作成する必要があります。これは、VPC ネットワーク ピアリングが推移的ではないためです。

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

目標

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

費用

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

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

このドキュメントに記載されているタスクの完了後、作成したリソースを削除すると、それ以上の請求は発生しません。詳細については、クリーンアップをご覧ください。

始める前に

  1. Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  2. Google Cloud Console の [プロジェクト セレクタ] ページで、Google Cloud プロジェクトを選択または作成します。

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

  3. Google Cloud プロジェクトで課金が有効になっていることを確認します

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

    API を有効にする

  5. Google Cloud Console の [プロジェクト セレクタ] ページで、Google Cloud プロジェクトを選択または作成します。

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

  6. Google Cloud プロジェクトで課金が有効になっていることを確認します

  7. Compute Engine and Google Kubernetes Engine API を有効にします。

    API を有効にする

環境設定

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

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

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

    Cloud Shell を開く

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

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

    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 限定公開クラスタを作成し、クライアント マシンにのみアクセスを許可するように master-authorized-networks を設定します。

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
    export TOKEN=$(cat /run/secrets/kubernetes.io/serviceaccount/token)
    INTERNAL_IP=$(curl -H "Authorization: Bearer $TOKEN" -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 CONTROLLER_IP=`gcloud container clusters describe frobnitz \
    --zone=us-central1-c \
    --format="get(privateClusterConfig.privateEndpoint)"`
    
  11. プロキシ経由で Kubernetes API にアクセスして、プロキシが使用可能であることを確認します。

    curl -k -x $LB_IP:8118 https://$CONTROLLER_IP/version
    
    出力は次のようになります(出力は異なる場合があります)。
    {
      "major": "1",
      "minor": "15+",
      "gitVersion": "v1.15.11-gke.5",
      "gitCommit": "a5bf731ea129336a3cf32c3375317b3a626919d7",
      "gitTreeState": "clean",
      "buildDate": "2020-03-31T02:49:49Z",
      "goVersion": "go1.12.17b4",
      "compiler": "gc",
      "platform": "linux/amd64"
    }
    
  12. https_proxy 環境変数を HTTP(S) プロキシに設定して、kubectl コマンドがどこからでも内部ロードバランサにアクセスできるようにします。

    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 アカウントに課金されないようにするには、リソースを含むプロジェクトを削除するか、プロジェクトを維持して個々のリソースを削除します。

プロジェクトの削除

  1. In the Google Cloud console, go to the Manage resources page.

    Go to Manage resources

  2. In the project list, select the project that you want to delete, and then click Delete.
  3. In the dialog, type the project ID, and then click Shut down to delete the project.

GKE クラスタの削除

プロジェクトを削除しない場合は、GKE クラスタを削除します。

gcloud container clusters delete frobnitz

次のステップ