【さらば port-forward 】Twingate Kubernetes Operator で安全かつ簡単に検証環境へアクセスする
こんにちは、 Ubie で SRE をしている @guni1192 です。
普段は SRE をやったり医療機関向け事業のネットワーク基盤の運用をしています。
今回は Twingate を使った Kubernetes 上のワークロードへのアクセスを簡単にできる方法をご紹介します。
本記事は Ubie Tech Advent Calendar 2025 8日目の記事となります。
はじめに
普段開発をしているときにこんな経験はありませんか?
- ステージング環境の API を検証したいだけなのに、Kubernetes アクセス権限の申請でレビュー待ち
- 久々に叩く
kubectl port-forwardが呪文過ぎて忘れる - スマホから検証環境にアクセスしてレビューしたい
- エンジニア以外のメンバーにも検証環境にアクセスして見てもらいたい
Ubie では GKE 上に大量のマイクロサービスがありますが、最小権限の Predefined Role をユーザーに Attach する場合、 roles/container.developer が必要になります。
しかしこれはかなり大きな権限で、Deployment などのリソースの作成/削除もできるので、すべてのメンバーに常時つけるのは attack surface の増大につながります。
代替案として特定の API だけ許可した Custom Role を作成し、適用するということも考えられますが、毎度 kubectl port-forward コマンドを実行させるというのも面倒です。
また、IP ベースでアクセス許可をした LB を用意し、VPN を通じてアクセスするといった手法もありますが、VPN機器の保守や設定が面倒であることや、社員の環境によっては VPN 接続できない人もいること、社員のロールに応じたアクセス制御が難しいことなどの課題がありました。
今回は Twingate を用いて、もっとお手軽に検証環境上へアクセスできる方法をご紹介します。
個人の無料アカウントでもできる (2025年12月時点) ので興味がある人は試してみてください。
Twingate とは
Twingate は Zero Trust Network を実現するためのプラットフォームです。 Identity Aware なアクセス制御を簡単に実現できます。
たとえば、
- 特定の Google Group に所属するユーザーのみアクセスを許可
- MDM の導入がされた端末のみアクセスを許可
といったように、人とデバイスレベルでアクセス制御ができます。
セキュリティポリシーは細かく設定でき、各社の IdP, MDM, EDR などと連携することで、より堅牢な環境を構築できます。
興味があれば Twingate の仕組みも読んでみてください。
TLS over QUIC や NAT トラバーサルの仕組みが詳しく解説されていて面白いです。
Twingate Operator とは
Twingate Operator は、Twingate の構成を Kubernetes Custom Resource で管理できる Operator です。
インターネットに公開していない Kubernetes の API サーバーへのアクセスやワークロードへのアクセスを可能にします。
kind で Kubernetes クラスタを構築しアクセスしてみる
必要なもの
- docker
- kind
- kubectl
- Helm
- Twingate アカウント
- Network が作成されている
- Twingate Client (今回は macOS, iOS)
kind のクラスタを構築する
kind create cluster --name twingate-k8s-demo
Kubernetes Operator のインストール
ほぼ GitHub の Getting Started の通りです。API Key の作成手順などはこちらを参照してください。
Helm の values.yaml を作成します。
twingateOperator:
apiKey: <apiKey>
network: <network name>
remoteNetworkId: <remote network id>
kubernetes-access-gateway:
enabled: false
image:
repository: twingate/kubernetes-operator
pullPolicy: IfNotPresent
tag: "v0.27.1"
imagePullSecrets: []
nameOverride: ""
fullnameOverride: ""
serviceAccount:
create: true
annotations: {}
name: ""
podAnnotations: {}
podLabels: {}
podSecurityContext:
seccompProfile:
type: RuntimeDefault
securityContext:
capabilities:
drop:
- ALL
readOnlyRootFilesystem: true
runAsNonRoot: true
allowPrivilegeEscalation: false
runAsUser: 1000
resources:
limits:
cpu: 100m
memory: 128Mi
requests:
cpu: 100m
memory: 128Mi
nodeSelector: {}
tolerations: []
affinity: {}
priorityClassName: ""
extraEnvVars: []
pdb:
create: false
rbac:
createAggregateClusterRoles: false
helm upgrade twop oci://ghcr.io/twingate/helmcharts/twingate-operator \
--create-namespace \
-n twingate-operator \
--install --wait -f ./values.yaml
Connector のデプロイ
Twingate では、Connector という概念があり、これを用いてプライベートなアプリケーションへのアクセスを可能にします。
Helm で Network 配下に配置します。
helm repo add twingate https://twingate.github.io/helm-charts
helm upgrade --install twingate-connector twingate/connector \
--create-namespace \
-n twingate-connector \
--set connector.network=[network] \
--set connector.accessToken=[accessToken] \
--set connector.refreshToken=[refreshToken]
Twingate Resource / Twingate Resource Access の作成
ここからプライベートなアプリケーションへのアクセスを可能にします。TwingateResource というカスタムリソースがあるのですが、今回はこれを直接定義するのではなく、もっとお手軽に Service にアノテーションをつけてやる方法をご紹介します。
Nginx のデプロイ
以下にサンプルアプリケーションのマニフェストを示します。
一見オーソドックスな nginx の Manifest ですが、resource.twingate.com: "true" というアノテーションをつけてやることで、Twingate からアクセスできるようになります。
Kubernetes 内の CoreDNS に設定する名前 (<service name>.<namespace>.svc.cluster.local) で直接アクセスできます。
また、resource.twingate.com/alias: "nginx.foo.local" とすることで、エイリアスも設定できます。
mkdir -p examples
examples/service.yaml
apiVersion: v1
kind: Service
metadata:
name: nginx
annotations:
resource.twingate.com: "true"
resource.twingate.com/alias: "nginx.foo.local"
spec:
selector:
app.kubernetes.io/name: nginx
type: ClusterIP
ports:
- protocol: TCP
port: 80
targetPort: 80
name: http
examples/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app.kubernetes.io/name: nginx
replicas: 1
template:
metadata:
labels:
app.kubernetes.io/name: nginx
spec:
containers:
- name: nginx
image: nginx:1.29.3
ports:
- containerPort: 80
kubectl apply -f examples/
このままではアクセスができないのでアクセス制御を設定します。
以下のように所属するグループとポリシーを指定します。
Principal とポリシーは手動で作成しています。
詳細は割愛していますが、Google Workspace との連携で Google Group を同期したり、
アクセス可能なデバイスの OS や Firewall の設定などの制限をしています。
examples/access.yaml
apiVersion: twingate.com/v1beta
kind: TwingateResourceAccess
metadata:
name: nginx-access
spec:
resourceRef:
name: nginx-resource # service 経由で作成すると <service name>-resource という名前になる
namespace: default
# https://<network name>.twingate.com/groups/<principalId>
principalId: <principalId>
# https://<network name>.twingate.com/policies/<securityPolicyId>
securityPolicyId: <securityPolicyId>

スマホからローカルの kind 上のアプリケーションにアクセスしてみる
モバイルアプリを入れればスマホからもアクセス可能になります。

おわりに
今回は Twingate Kubernetes Operator を使って kubectl port-forward なしで安全に検証環境に接続する方法についてご紹介しました。
kubectl が入っていなくとも、 Twingate のクライアントがあれば認可されたアプリケーションにアクセスすることができます。
個人でも無料で導入して試せる機能が多いので、ゼロトラストネットワークの検証などを考えてる方は試してみても良いかもしれません。
Discussion