🕸️

【さらば port-forward 】Twingate Kubernetes Operator で安全かつ簡単に検証環境へアクセスする

に公開

こんにちは、 Ubie で SRE をしている @guni1192 です。
普段は SRE をやったり医療機関向け事業のネットワーク基盤の運用をしています。

今回は Twingate を使った Kubernetes 上のワークロードへのアクセスを簡単にできる方法をご紹介します。

本記事は Ubie Tech Advent Calendar 2025 8日目の記事となります。
https://adventar.org/calendars/12070

はじめに

普段開発をしているときにこんな経験はありませんか?

  • ステージング環境の 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 トラバーサルの仕組みが詳しく解説されていて面白いです。

https://www.twingate.com/docs/how-twingate-works

Twingate Operator とは

Twingate Operator は、Twingate の構成を Kubernetes Custom Resource で管理できる Operator です。
インターネットに公開していない Kubernetes の API サーバーへのアクセスやワークロードへのアクセスを可能にします。

https://github.com/Twingate/kubernetes-operator

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 の作成手順などはこちらを参照してください。
https://github.com/Twingate/kubernetes-operator/wiki/Getting-Started

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 のクライアントがあれば認可されたアプリケーションにアクセスすることができます。

個人でも無料で導入して試せる機能が多いので、ゼロトラストネットワークの検証などを考えてる方は試してみても良いかもしれません。

参考

Ubie テックブログ

Discussion