KonnectのData Planeの構築はWebUIから簡単に行えるが、それでもログインしたりクラスタ側でhelmコマンドを叩いたり、ある程度の作業が発生する。
今回はこれを全てGitHub Actionsに落とし込んで1クリックで作成しようと思う。
前提
以下を前提とする。
- EKSがある
- 以下のAWSに関する環境変数が設定済み
export AWS_REGION=us-east-1
export AWS_ACCESS_KEY_ID="ASIAV..."
export AWS_SECRET_ACCESS_KEY="Fh4E..."
export AWS_SESSION_TOKEN="IQoJ..."
- Konnectのトークンを発行済
準備
GitHub Actions向け変数の準備
まずはGitHub Actionsで使う変数を用意する。
個人的な好みから、先に環境変数で設定し、それを使ってGitHubのリポジトリに設定するようにする。
ここで設定する環境変数は以下となる。
環境変数 | 意味 |
---|---|
KONNECT_TOKEN | Konnectのアクセストークン。CPのIDを取得するためのAPIを発行するのに利用。 |
EKS_CLUSTER_NAME | EKSのクラスタ名 |
CP_NAME | DPを展開するCPの名前 |
KONG_REPO | DPのイメージを格納しているリポジトリ。ここではこの記事で作成したイメージを使いたいので環境変数化している。デフォルトのものを使いたい人はkong/kong-gateway を指定する |
KONG_VER | DPのバージョン |
GIT_REPO | 変数を設定するGitHubのリポジトリ |
ということで以下のように設定する。
KONNECT_TOKEN=kpat_sHa...
EKS_CLUSTER_NAME=mycluster
CP_NAME=default
KONG_REPO=ghcr.io/imurata/kong-gateway
KONG_VER=3.10.0.1
GIT_REPO=imurata/hoge
設定後、ghコマンドを使ってSecret、Variablesを設定する。
gh secret set AWS_ACCESS_KEY_ID --body $AWS_ACCESS_KEY_ID --repo $GIT_REPO
gh secret set AWS_SECRET_ACCESS_KEY --body $AWS_SECRET_ACCESS_KEY --repo $GIT_REPO
gh secret set AWS_SESSION_TOKEN --body $AWS_SESSION_TOKEN --repo $GIT_REPO
gh secret set AWS_REGION --body $AWS_REGION --repo $GIT_REPO
gh secret set KONNECT_TOKEN --body $KONNECT_TOKEN --repo $GIT_REPO
gh secret set EKS_CLUSTER_NAME --body $EKS_CLUSTER_NAME --repo $GIT_REPO
gh variable set CP_NAME --body $CP_NAME --repo $GIT_REPO
gh variable set KONG_REPO --body $KONG_REPO --repo $GIT_REPO
gh variable set KONG_VER --body $KONG_VER --repo $GIT_REPO
また、KONG_REPO
にアクセスするためのコンテナレジストリ用Secretが必要な場合は作成しておく。
(ここでは事前に作ったが、実際はパイプラインの中で作った方がいいかも)
kubectl create secret docker-registry ghcr-secret --docker-server=ghcr.io --docker-username=imurata --docker-password=$GITHUB_TOKEN -n kong
パイプラインの作成
以下のような感じでパイプラインを作成してGitにPushする。
cat <<'EOF' > ./.github/workflows/deploy_dp.yaml
name: Deploy Kong Data Plane
on:
workflow_dispatch:
jobs:
deploy-dp:
runs-on: ubuntu-latest
env:
KONNECT_API: https://us.api.konghq.com/v2
steps:
- name: Set up dependencies
run: |
sudo apt-get update
sudo apt-get install -y jq openssl
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-session-token: ${{ secrets.AWS_SESSION_TOKEN }}
aws-region: ${{ secrets.AWS_REGION }}
- name: Set up kubeconfig for EKS
run: |
aws eks update-kubeconfig --name ${{ secrets.EKS_CLUSTER_NAME }}
- name: Get Control Plane ID and upload TLS certs
id: get_cp
run: |
CP_ID=$(curl -s -X GET \
-H "Authorization: Bearer ${{ secrets.KONNECT_TOKEN }}" \
"${KONNECT_API}/control-planes" \
| jq -r --arg name "${{ vars.CP_NAME }}" '.data[] | select(.name==$name) | .id')
mkdir certs
openssl req -new -x509 -nodes -newkey rsa:2048 \
-subj "/CN=kongdp/C=US" \
-keyout ./certs/tls.key -out ./certs/tls.crt -days 3650
export CERT=$(awk 'NF {sub(/\r/, ""); printf "%s\\n",$0;}' ./certs/tls.crt)
curl -sX POST \
-H "Authorization: Bearer ${{ secrets.KONNECT_TOKEN }}" \
${KONNECT_API}/control-planes/${CP_ID}/dp-client-certificates \
--json '{"cert":"'"$CERT"'"}'
CP_ENDPOINT=$(curl -s -X GET \
-H "Authorization: Bearer ${{ secrets.KONNECT_TOKEN }}" \
"${KONNECT_API}/control-planes/${CP_ID}" \
| jq -r '.config.control_plane_endpoint')
CP_ENDPOINT=$(sed "s@https://@@" <<< $CP_ENDPOINT)
TP_ENDPOINT=$(curl -s -X GET \
-H "Authorization: Bearer ${{ secrets.KONNECT_TOKEN }}" \
"${KONNECT_API}/control-planes/${CP_ID}" \
| jq -r '.config.telemetry_endpoint')
TP_ENDPOINT=$(sed "s@https://@@" <<< $TP_ENDPOINT)
echo "tp_endpoint=$TP_ENDPOINT" >> "$GITHUB_OUTPUT"
echo "cp_endpoint=$CP_ENDPOINT" >> "$GITHUB_OUTPUT"
- name: Create Kubernetes namespace and TLS secret
run: |
kubectl create ns kong || true
kubectl create secret tls kong-cluster-cert -n kong \
--cert=./certs/tls.crt \
--key=./certs/tls.key \
--dry-run=client -o yaml | kubectl apply -f -
- name: Generate values.yaml
run: |
cat <<EOF > ./values.yaml
image:
repository: ${{ vars.KONG_REPO }}
tag: ${{ vars.KONG_VER }}
pullSecrets:
- ghcr-secret
secretVolumes:
- kong-cluster-cert
admin:
enabled: false
env:
role: data_plane
database: "off"
cluster_mtls: pki
cluster_control_plane: ${{ steps.get_cp.outputs.cp_endpoint }}:443
cluster_server_name: ${{ steps.get_cp.outputs.cp_endpoint }}
cluster_telemetry_endpoint: ${{ steps.get_cp.outputs.tp_endpoint }}:443
cluster_telemetry_server_name: ${{ steps.get_cp.outputs.tp_endpoint }}
cluster_cert: /etc/secrets/kong-cluster-cert/tls.crt
cluster_cert_key: /etc/secrets/kong-cluster-cert/tls.key
lua_ssl_trusted_certificate: system
konnect_mode: "on"
vitals: "off"
nginx_worker_processes: "1"
upstream_keepalive_max_requests: "100000"
nginx_http_keepalive_requests: "100000"
proxy_access_log: "off"
dns_stale_ttl: "3600"
router_flavor: expressions
ingressController:
enabled: false
installCRDs: false
resources:
requests:
cpu: 1
memory: "2Gi"
EOF
- name: Deploy with Helm
run: |
helm repo add kong https://charts.konghq.com
helm repo update
helm upgrade -i my-kong kong/kong -n kong --values ./values.yaml --debug --wait
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: kong-dp-config
path: |
./values.yaml
./certs/tls.crt
./certs/tls.key
EOF
git add -A
git commit -m "Initial Commit"
git push origin main
上記のコードについて、ポイントを絞って説明する。
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-session-token: ${{ secrets.AWS_SESSION_TOKEN }}
aws-region: ${{ secrets.AWS_REGION }}
- name: Set up kubeconfig for EKS
run: |
aws eks update-kubeconfig --name ${{ secrets.EKS_CLUSTER_NAME }}
上記についてはEKSを叩くためのkubeconfigを取得するために実行している。
EKSではないクラスタであれば、以下のような感じで取り込むといいと思う。
gh secret set KUBECONFIG_DATA --body $(base64 -w 0 ~/.kube/config) --repo $GIT_REPO
- name: Set up kubeconfig
run: |
echo "${{ secrets.KUBECONFIG_DATA }}" | base64 -d > $HOME/.kube/config
次に以下のstepではCPのIDを取得しTLSの証明書のアップロードやvalues.yamlに設定するためのエンドポイントを取得する。
- name: Get Control Plane ID and upload TLS certs
id: get_cp
:(省略)
過去に書いた「Konnectに繋ぐData PlaneをCLIのみで起動する」という記事で実行しているコマンドの詳細を説明しているので、ここでは説明は割愛する。
- name: Create Kubernetes namespace and TLS secret
run: |
kubectl create ns kong || true
kubectl create secret tls kong-cluster-cert -n kong \
--cert=./certs/tls.crt \
--key=./certs/tls.key \
--dry-run=client -o yaml | kubectl apply -f -
ここではNamespaceを作成し、証明書をSecretに格納する箇所となる。
UIではSecretはkubectl create
で作成するが、ここでは既にSecretがある場合を考慮し、--dry-run
でYAML形式で吐いた後にkubectl apply
で上書きするようにしている。
今回は省略したが、KONG_REPO
に対するアクセス用のpullSecrets
のためのSecretを作成するならここで作っておくとよい。
- name: Generate values.yaml
run: |
cat <<EOF > ./values.yaml
image:
repository: ${{ vars.KONG_REPO }}
tag: ${{ vars.KONG_VER }}
pullSecrets:
- ghcr-secret
:(省略)
上記以降でHelmのvalues.yamlを作成してDPをデプロイする。
KonnectのUIで提示されるvalues.yamlではpullSecrets
の項目はないが、今回は自前のリポジトリ(KONG_REPO
)にイメージがあることを想定し、そこからPullするための認証情報を引っ張るために設定する。
cluster_control_plane
、cluster_server_name
、cluster_telemetry_endpoint
、cluster_telemetry_server_name
に関してはControl Planeがないと値が設定できない部分であり事前に値を設定することが難しい。
そのため、CPのIDを取得した際にそれぞれのエンドポイントの値を覚えておいて、values.yaml作成時に反映させている。
ちなみに今回のパイプラインはHelmのインストールで終了させているが、何だったらPodの起動確認やdeckを使って簡易的な疎通確認まで実装してもよいと思う。
今回は検証目的であり省略した。
動作確認
パイプラインをworkflow_dispatch
で作成しているので、GitHub Actionsから手動で実行してDPをデプロイする。
以下のような感じでActions
からRun workflow
をクリックして実行する。
ジョブの実行が完了するとクラスタ上でPodが立っているのが分かる。
$ kubectl get pod -n kong
NAME READY STATUS RESTARTS AGE
my-kong-kong-6898888cb-8cw5l 1/1 Running 0 3m12s
以上より、1クリックでKonnectのDPを払い出せる環境が作成できた。
なお、注意点としてhelm uninstall
で削除してもKonnect側に作成した証明書は残り続けるので、helm uninstall
後は手動で削除する、もしくは削除用にまたパイプラインを用意した方がいい。