GKE Autopilot + ASM + Gateway API + Certificate Manager で nginx を動かす
はじめに
タイトルの通り、
GKE Autopilot
ASM(Anthos Service Mesh)
Gateway API
Certificate Manager
を組み合わせた環境を作り、その上で nginx
コンテナを動かしてみます。
作業は glcoud
を使用してコマンドラインベースで行います。Google Cloud
コンソールの Cloud Shell
(右上のターミナルアイコンから起動) を使用すると初期設定不要でブラウザだけで作業が完結するので、お勧めです。
コマンドによっては完了までにかなり時間がかかるものがありますが、気長に待ちましょう!
環境変数セット
色々な環境で試せるように、以降出てくるコマンドで環境変数を参照するようにしました。
実際の環境に合わせて、好きな値を入れてください。
# プロジェクトID
export PROJECT_ID=some-project-1234
# クラスタ名
export CLUSTER_NAME=test-cluster
# クラスタのリージョン
export CLUSTER_REGION=us-central1
# クラスタを操作するサービスアカウント名
export SERVICE_ACCOUNT_NAME=gke-cluster-operator
# デプロイ先の名前空間
export NAMESPACE=default
# 予約するIPにつける名前
export IP_NAME=test-cluster-ip
# 証明書につける名前
export CERT_NAME=test-cert
# 紐づけるドメイン
export DOMAIN=test.example.com
サービスアカウント作成
クラスタを作成する前に、クラスタ操作用のサービスアカウントを作っておきます。
クラスタ作成時に何も指定しなければ Compute Engine
のデフォルトサービスアカウントが使用されるのですが、公式ドキュメントによると必要最小限な権限を持つサービスアカウントを使用する事を推奨との事。
以下の通りアカウントを作成します。
gcloud iam service-accounts create ${SERVICE_ACCOUNT_NAME} \
--display-name="GKEクラスタ実行用SA"
作成後、必要なロールを付与します。
gcloud projects add-iam-policy-binding ${PROJECT_ID} \
--member "serviceAccount:${SERVICE_ACCOUNT_NAME}@${PROJECT_ID}.iam.gserviceaccount.com" \
--role roles/container.clusterAdmin
クラスタ作成
GKE Autopilot
のクラスタを作成します。
まずは Kubernetes Engine API
を有効にします。
gcloud services enable container.googleapis.com
完了後、先程作成したサービスアカウントを指定して、クラスタを作成します。
Autopilot
でなければこのタイミングでオプションで Gateway API
を有効にできるのですが、Autopilot
用の create-auto
にはそのオプションがありません。ASM
もついでにここで有効に出来ればいいのですが…こちらも現時点では出来ないようです。
gcloud container clusters create-auto ${CLUSTER_NAME} \
--region ${CLUSTER_REGION} \
--project=${PROJECT_ID} \
--service-account=${SERVICE_ACCOUNT_NAME}@${PROJECT_ID}.iam.gserviceaccount.com
ASMを有効に
Google Cloud
の(web)GUIコンソール画面からならクラスタを作成する時に同時に ASM
を有効に出来て楽なのですが、gcloud
から ASM
を有効にする場合は asmcli
というツールを使う必要があります。
記事の通りですが、DLして
curl https://storage.googleapis.com/csm-artifacts/asm/asmcli_1.15 > asmcli
実行権限をつけて
chmod +x asmcli
実行します。
./asmcli install \
--project_id ${PROJECT_ID} \
--cluster_name ${CLUSTER_NAME} \
--cluster_location ${CLUSTER_REGION} \
--verbose \
--managed \
--use-managed-cni \
--enable_all \
--enable_registration \
--ca mesh_ca
有効化したら、istio
の自動インジェクションを有効にしておきます。インストール完了のメッセージにも記載がありますね。
今回はデフォルトではなく特定の名前空間に対して有効にするので、対象の名前空間を作ります。
kubectl create namespace ${NAMESPACE}
kubectl label namespace ${NAMESPACE} istio-injection- istio.io/rev=asm-managed --overwrite
GatewayAPIを有効に
こちらも有効にしていきます。
前述の通り作成時には有効に出来ないので、 update
コマンドを使用してクラスタを更新します。
gcloud container clusters update ${CLUSTER_NAME} \
--gateway-api=standard \
--region=${CLUSTER_REGION}
IPアドレスを予約
公開用のIPアドレスを予約します。
予約しなくても自動的に割り振られるようなのですが、ドメインとの紐づけを考えて固定しておきます。
gcloud compute addresses create ${IP_NAME} \
--project=${PROJECT_ID} \
--global
予約されたIPは以下のコマンドで確認できます。
gcloud compute addresses describe ${IP_NAME} --global | grep address:
ドメインを用意
ドメインを用意し、前項で予約したIPアドレスをDNSのAレコードに登録します。この作業はドメイン取得やDNSレコード設定に使用しているサービスによるので、適宜行ってください。
証明書を用意
Certificate Manager
を使用して証明書を用意します。
まずは Certificate Manager API
を有効にする必要があります。
gcloud services enable certificatemanager.googleapis.com
有効になった後、以下のコマンドで証明書を作成します。
gcloud certificate-manager maps create ${CERT_NAME}-map
gcloud certificate-manager certificates create ${CERT_NAME} \
--domains=${DOMAIN}
gcloud certificate-manager maps entries create ${CERT_NAME}-entry \
--map=${CERT_NAME}-map \
--hostname=${DOMAIN} \
--certificates=${CERT_NAME}
nginxをデプロイ
以下のコマンドで nginx
をデプロイします。
Gateway.spec.addresses
で予約したIPアドレスを、 Gateway.metadata.annotations
で証明書を、HTTPRoute.spec.hostnames
で公開用ドメインをそれぞれ指定しています。
kubectl apply -f - <<EOF
apiVersion: v1
kind: Service
metadata:
labels:
app: nginx-test
service: nginx-test
name: nginx-test
namespace: ${NAMESPACE}
spec:
ports:
- name: http
port: 80
selector:
app: nginx-test
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx-test
name: nginx-test
namespace: ${NAMESPACE}
spec:
replicas: 1
selector:
matchLabels:
app: nginx-test
template:
metadata:
labels:
app: nginx-test
spec:
containers:
- image: nginx
imagePullPolicy: IfNotPresent
name: nginx-test
ports:
- containerPort: 80
---
apiVersion: gateway.networking.k8s.io/v1beta1
kind: Gateway
metadata:
name: nginx-test-gateway
namespace: ${NAMESPACE}
annotations:
networking.gke.io/certmap: ${CERT_NAME}-map
spec:
gatewayClassName: gke-l7-gxlb
listeners:
- name: https
port: 443
protocol: HTTPS
addresses:
- type: NamedAddress
value: ${IP_NAME}
---
apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
labels:
app: nginx-test
name: nginx-test-route
namespace: ${NAMESPACE}
spec:
hostnames:
- ${DOMAIN}
parentRefs:
- name: nginx-test-gateway
rules:
- backendRefs:
- name: nginx-test
port: 80
matches:
- path:
type: PathPrefix
value: /
EOF
導通確認する
webブラウザで設定したドメインにアクセスして、初期画面が表示されるかどうか確認します。
コマンドライン上で確認する場合はこちら。
curl https://${DOMAIN}
おわりに
個人的に動作させるまでに結構試行錯誤したり苦労したので、メモとして残しておきます。
この構成だと、今回挙げたサービスだけではなく裏で色々な機能がオンになったりするので、冒頭に書いた通り確認用のプロジェクトを作って、不要になったらそのプロジェクトごと削除すると楽かなと思います。
Discussion