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

限定公開のクラスタ マスター エンドポイントを持つ GKE 限定公開クラスタを作成すると、そのクラスタのマスターノードは一般に公開されているインターネットからはアクセスできなくなりますが、管理目的でのアクセスは可能にする必要があります。このチュートリアルでは、GKE 限定公開クラスタのマスターにネットワークの外部からはアクセスできないように構成し、例外としてプライベート IP 空間内に作成してホストするプロキシからのアクセスを許可する方法を説明します。

Kubernetes サービスをクラスタの内部ロードバランサ経由でルーティングするのではなく、プロキシを構成します。これにより、gcloud container clusters get-credentials を使用して認証情報を取得し、セキュリティで保護された接続を介してマスターにアクセスできます。

目標

  • GKE 限定公開クラスタを作成して最小限の外部アクセスを許可する。
  • Docker イメージを作成してデプロイし、プロキシを実行する。
  • プロキシにアクセスする Kubernetes サービスを作成する。
  • クラスタに対する他の外部アクセスをすべて削除する。

料金

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

このソリューションの推定費用は 1 日あたり約 $2.42 です。

始める前に

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

    [リソースの管理] ページに移動

  2. プロジェクトに対して課金が有効になっていることを確認します。

    課金を有効にする方法について

  3. 次の構成のクライアント マシンを用意します。

    • クラスタとの初期アクセスに使用する既知の外部 IP アドレス。これは一時的なもので、プロキシの設定後は CIDR 範囲にアクセスします。たとえば、外部 IP アドレスを持つ Compute Engine 仮想マシンを使用します。クラスタを作成してポッドとサービスをデプロイする権限も必要です。
    • Docker がインストールされ、gcloud auth configure-dockergcr.io の認証が行われる。

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

限定公開クラスタの作成

まず最初に、このチュートリアルで使用する限定公開クラスタを作成または選択します。

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

  1. クラスタを作成するには、次のコマンドを実行します。[YOUR_CLIENT_IP_ADDRESS] には、クライアントのルーティング可能な外部向けの IP アドレスあるいはネットブロックを指定します。

    gcloud container clusters create frobnitz  \
        --zone=us-central1-c \
        --master-ipv4-cidr=172.16.0.64/28 \
        --enable-ip-alias \
        --enable-private-nodes \
        --master-authorized-networks [YOUR_CLIENT_IP_ADDRESS]/32 \
        --enable-master-authorized-networks
    

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

  2. 既存のクラスタにアクセスを許可する場合は、次のコマンドを実行します。[YOUR_CLIENT_IP_ADDRESS] には、クライアントのルーティング可能な外部向けの IP アドレスあるいはネットブロックを指定します。[CLUSTER_NAME] は既存のクラスタの名前です。

    gcloud container clusters update [CLUSTER_NAME] \
        --zone [CLUSTER_ZONE] \
        --enable-master-authorized-networks \
        --master-authorized-networks=[YOUR_CLIENT_IP_ADDRESS]/32
    

Docker イメージの作成

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

  1. クライアント マシンでディレクトリを作成し、そのディレクトリに移動します。

    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-external.filter \ /etc/privoxy/ ADD k8s-api-proxy.sh /
    EXPOSE 8118/tcp
    ENTRYPOINT ["./k8s-api-proxy.sh"]
  3. k8s-api-proxy ディレクトリに config ファイルを作成し、次の内容を追加します。

    # Allow Kubernetes API access only
    actionsfile /etc/privoxy/k8s-only.action
    # Rewrite https://CLUSTER_IP to https://kubernetes.default
    filterfile /etc/privoxy/k8s-rewrite-external.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 external k8s endpoint, which you rewrite (see # k8s-rewrite-external.filter). {+client-header-filter{k8s-rewrite-external} -block{Kubernetes}} CLUSTER_IP/
  5. k8s-rewrite-external.filter ファイルを作成し、次の内容を追加します。k8s-api-proxy.sh が実行されると、CLUSTER_IP が置き換わります。

    CLIENT-HEADER-FILTER: k8s-rewrite-external\
     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 external cluster IP
    EXTERNAL_IP=$(curl -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/${EXTERNAL_IP}/g"\
     /etc/privoxy/k8s-rewrite-external.filter
    sed -i "s/CLUSTER_IP/${EXTERNAL_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 します。[YOUR_PROJECT] は、プロジェクト ID で置き換えます。

    docker build -t gcr.io/[YOUR_PROJECT]/k8s-api-proxy:0.1 .
    docker push gcr.io/[YOUR_PROJECT]/k8s-api-proxy:0.1
    

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

  1. 作成したコンテナを公開する Kubernetes 環境を作成します。[YOUR_PROJECT] には、プロジェクト ID を指定します。

    kubectl run k8s-api-proxy \
        --image=gcr.io/[YOUR_PROJECT]/k8s-api-proxy:0.1 \
        --port=8118
    
  2. 同じディレクトリに内部ロードバランサ用の 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
    
  3. 内部ロードバランサをデプロイします。

    kubectl create -f ilb.yaml
  4. サービスの 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 アドレスはプロキシのアドレスです。

  5. テストに使用するクラスタのマスター IP アドレスを特定します。

    gcloud container clusters list

    出力結果にあるクラスタの MASTER_IP 値を書き留めます。

    NAME      LOCATION       MASTER_VERSION  MASTER_IP       MACHINE_TYPE   NODE_VERSION  NUM_NODES  STATUS
    frobnitz  us-central1-c  1.9.7-gke.3     35.188.209.220  n1-standard-1  1.9.7-gke.3   3          RUNNING
    
  6. プロキシが使用可能かどうか確認するため、同じネットワークに Compute Engine インスタンスを作成し、SSH 経由でアクセスしてプロキシを確認します。[YOUR_SUBNET][YOUR_PROXY][MASTER_IP] には、前に取得した値を指定します。

    gcloud compute instances create \
        --subnet=[YOUR_SUBNET] proxy-test
    gcloud compute ssh proxy-test -- \
        curl -x [YOUR_PROXY]:8118 https://[MASTER_IP]/api
    
  7. どこからでも kubectl コマンドで内部ロードバランサに接続できるように、https_proxy 環境変数を HTTP プロキシに設定します。[YOUR_PROXY] には、前の手順で取得した外部 IP アドレスを指定します。

    export https_proxy=[YOUR_PROXY]:8118
  8. プロキシと https_proxy 変数のテストを行います。

    kubectl get pods

クリーンアップ

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

  • クラスタを削除する。
  • Compute Engine インスタンスに作成した外部 IP アドレスを削除する。

クラスタの削除

このチュートリアルで作成したクラスタを別の目的で使用しない場合は、クラスタを削除できます。クライアント マシンのコマンドラインで、次のコマンドを実行します。

gcloud container clusters delete frobnitz \
    --zone us-central1-c

外部 IP アドレスとインスタンスの削除

最初の外部アクセス用に Compute Engine インスタンスを作成した場合は、そのインスタンスを削除し、関連する外部 IP を削除します。

作成したインスタンスの名前を見つけて削除します。

gcloud compute instances list
gcloud compute instances delete [NAME]

同様に、予約された外部アドレスを検索して削除します。

gcloud compute addresses list
gcloud compute addresses delete [NAME]

次のステップ

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

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