🌍

Kubernetes Private ClusterにTailscaleで接続する

2024/08/01に公開

概要

Private Clusterは、Kubernetes Clusterのセキュリティ強化やネットワーク制御の向上に優れた選択肢ですが、運用のし辛さが課題となることがあります。この記事では、その課題を解決するための手法として、Tailscale Kubernetes Operator を導入する方法を紹介します。具体的な手順とその利点について解説し、運用のしやすさを向上させるポイントを示します。

イントロダクション

Private Clusterとは

Kubernetes Nodeは、内部クラスタ通信用のInternal IPと外部用のExternal IPが存在します。Kubernetes Private ClusterではNodeはInternal IPのみを利用し、External IPは利用できないようになります。また、コントロールプレーンも同様に2つIPが存在し、こちらもExternal IPを無効にすることができます。
Private Clusterにすることで、外部アクセスを遮断しより堅牢なクラスタを作成することができます。
(本記事では、KubernetesはGoogle Kubernetes Engineをベースに解説します)

About private clustersAbout private clusters

Private Clusterの課題

外部インターネット(ローカルPCなど)からkubernetes api-serverにアクセスする場合、

  • コントロールプレーンのExternal IPが無効な場合は、クラスタに対するオペレーションは同じVPC内から行う必要があり、Cloud InterconnectやCloud VPNを用いて同じVPCにVPN接続する必要があります。
  • コントロールプレーンのExternal IPが有効な場合は、Authorized Networksに特定のIPアドレスを登録し、そのIPアドレス経由でアクセスすることになります。
  • もしくは、Clusterと同じVPC内に 踏み台サーバー(Compute Engine)を立てておいて踏み台経由で操作する必要があります。

要は、ローカルからクラスタにアクセスするのはとても面倒ということです。

https://cloud.google.com/kubernetes-engine/docs/concepts/private-cluster-concept#overview

よりセキュアなクラスタにするのであれば、コントロールプレーンのExternal IPを無効化したPrivate Clusterを作るのが一番良いですが、自身のネットワークと接続するためにVPNの設定が必要であり外部アクセスの管理やネットワーク構成の複雑さが難しさとしてあります。

Tailscale Kubernetes Operatorの概要

Tailscaleとは何か

TailscaleはWireGuardをベースとしたVPNサービスです。Tailscaleアカウントが所持するデバイス,VM,コンテナ同士を Tailnet と呼ばれる仮想的なプライベートネットワーク内で高速にP2P通信することができます。
https://tailscale.com/blog/how-tailscale-works

Tailscale Kubernetes Operatorの基本機能

Tailscale Kubernetes Operator

Tailscale Kubernetes operatorを使うと、Kubernetes Operatorとしてapi-serverをproxyしてコンポーネントを操作したりパブリックインターネットを経由せずにAPIリソースにアクセスすることができるようになります。
開発者はPrivate Cluster内にあるTailscale operatorとP2Pで通信し、コントロールプレーンをInternal IP経由で操作することができるので、Cloud VPNやAuthorized Networkの設定をすることなくPrivate Clusterを実現することができます。

また、TailscaleにはTailnetの権限管理としてACLs (Access Control Lists) が機能として存在します。ACLを利用するとTailscale operatorを経由してKubernetes RBAC(Cluster Role) と連動させることが可能となり、クラスタアクセスの制御やリソース操作の権限を設定することができます。

導入

導入の前提条件と準備

セットアップは↓のツールを使います。

  • kubectl
  • Kustomize
  • Helm

※もしYamlではなく、CLI経由でセットアップする場合は以下の公式ドキュメントを参照してください。

https://tailscale.com/kb/1236/kubernetes-operator

https://tailscale.com/kb/1437/kubernetes-operator-api-server-proxy

バージョンは以下で行います。(2024/07/28)

  • GKE Cluster Version: 1.29.6-gke.1038001
  • Tailscale Operator: v1.70.0

また、Private Clusterの建て方は今回は省略します。詳しくは以下のDocumentをご確認ください。

https://cloud.google.com/kubernetes-engine/docs/how-to/private-clusters?hl=en

インストール手順

Tailscale Kubernetes Operatorには、OAuthクライアントを設定する必要があります。operatorはOAuth認証を使用して、Tailscale API経由でデバイスを管理し、自身と管理するデバイスの認証キーを作成します。

  1. Tailscale公式サイトにログインし、Admin ConsoleのAccess Controlsタブにて↓を設定します。
"tagOwners": {
   "tag:k8s-operator": [],
   "tag:k8s": ["tag:k8s-operator"],
}
  1. SettingsタブのOAuth clientsにてOAuthクライアントを作成します。

DevicesのWriteに✅を入れて、Add tagsで「k8s-operator」を登録します。
※Descriptionに作成するクラスタの名前を書いておくと後で識別する時に便利です。

Createすると以下のような画面が表示されるので、Client IDClient Secretをメモしておきます。

  1. 先ほど作成した、OAuth clientsのClient IDClient Secretをk8s Secretに登録します。
kubectl apply -f secret.yaml
secret.yaml
apiVersion: v1
kind: Secret
metadata:
    name: operator-oauth
    namespace: tailscale
data:
    client_id: ${CLIENT_ID}
    client_secret: ${CLIENT_SECRET}
Link
  1. Kustomize × Helmを用いてTailscale Operatorをインストールします。
kustomize build --enable-alpha-plugins --enable-exec --enable-helm . | kubectl apply -f -
tailscale-operator.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: tailscale
---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

metadata:
  name: tailscale-operator
namespace: tailscale

helmCharts:
- name: tailscale-operator
  repo: https://pkgs.tailscale.com/helmcharts
  releaseName: tailscale-operator
  version: 1.70.0
  namespace: tailscale
  valuesInline:
    operatorConfig:
      defaultTags:
        - "tag:k8s"
      hostname: "tailscale-operator-example" # tailscaleに登録するMachineのnameとhostname(後で使います)
    proxyConfig:
      defaultTags: "tag:k8s"
    apiServerProxyConfig:
      mode: "true" # 後のACL設定のため必要

以上でTailscale Operatorをインストールできました。他にもStatic Manifestを使った導入方法などが公式ドキュメントに書いてあるのでそちらもチェックしてみてください。

https://tailscale.com/kb/1236/kubernetes-operator

接続の確認

ローカルから接続するには、Tailscale Operatorと同じTailnetにConnectする必要があります。
そのためにはまずPCにTailscale Appをインストールする必要があります。
(今回はMacOSでの導入方法を記載します)

  1. Tailscale Appインストール

下のpkgsからMacOSの.pkgをダウンロードし、インストールします。

https://pkgs.tailscale.com/stable/#macos

  1. Tailscale Appのセットアップ

インストールすると、MacのメニューバーにTailscaleのアイコンが出てくるのでクリックし、トグルボタンを押します。

すると、ブラウザが開きTailscaleにログインを求められるので、ログインします。

TailnetにConnectします。

  1. Tailscale AppをCLIで起動できるようaliasを貼ります。
echo alias tailscale="/Applications/Tailscale.app/Contents/MacOS/Tailscale" >> ~/.zshrc
  1. 接続して確認します。
# Run tailscale
$ tailscale up

# To configure kubectl to connect to a Kubernetes cluster over Tailscale.
# 先ほどtailscale-operator.yamlで定義した hostname を入力
$ tailscale configure kubeconfig tailscale-operator-example
kubeconfig configured for "tailscale-operator-example"

# Check connect
$ kubectl get ns
tailscale                           Active   1d
...

これでTailscale経由でPrivate Clusterに接続できるようになりました🙌

  1. 接続解除
$ tailscale down

運用

ACL設定

TailscaleにはいくつかのRolesが存在し、Tailscaleの料金管理やメンバー管理などAdmin consoleへのアクセスに対する権限を設定できます。

https://tailscale.com/kb/1138/user-roles

また、TailnetのアクセスルールとしてACL(Access Control List)を設定することができ 、Roles や Groups を使ってアクセス権限を設定することができます。

https://tailscale.com/kb/1337/acl-syntax

Tailscale Kubernetes Operatorの概要でも挙げましたが、ACLを用いて Tailnet に所属する User に対して Kubernetes へのアクセス権限を設定します。

User Rolesへの権限付与

今回はUser Rolesの「Member」にKubernetes ClusterRoleの「edit」を付与します。

  1. Admin console の Access Controls タブにてgrantsを登録します。
acl
"grants": [
    {
        "src": ["autogroup:member"],
        "dst": ["tag:k8s"],
        "app": {
            "tailscale.com/cap/kubernetes": [{
                "impersonate": {
                    "groups": ["tailnet-editers"],
                },
            }],
        },
    },
],
  1. ClusterRoleBinding の作成
kubectl apply -f clusterolebinding.yaml
clusterolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  annotations:
  name: tailnet-editers-edit
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: edit
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: Group
  name: tailnet-editers

これで Member に edit を付与できました。Role: Memberのアカウントで接続の確認の手順を行うことで権限付与を確認できます。

Groupsでの権限付与

User Roles より細かく設定したい場合は Groups を使うことで特定ユーザーへの権限を付与することができます。

例: SREメンバーにClusterRole: adminを付与する場合

  1. ACLにgroup:sreを作成し、example@org.comをgroupに追加します。
acl
"groups": {
    "group:sre": [
        "example@org.com",
    ],
},

"grants": [
    {
        "src": ["group:sre"],
        "dst": ["tag:k8s"],
        "app": {
            "tailscale.com/cap/kubernetes": [{
                "impersonate": {
                    "groups": ["tailnet-admins"],
                },
            }],
        },
    },
],
  1. ClusterRoleBinding の作成
kubectl apply -f clusterolebinding.yaml
clusterolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  annotations:
  name: tailnet-admins-admin
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: admin
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: Group
  name: tailnet-admins
  1. UsersタブからUserを選択し、3点リーダーから「Edit group membership」を選択、「Add to a group」から group:sre を追加します。

まとめ

Private Clusterは高いセキュリティとネットワーク制御を提供する一方で、運用の難しさが課題となります。Tailscale Kubernetes Operatorを利用することで、これらの課題を効果的に解決し、運用のしやすさを大幅に向上させることができます。

他のVPN構築やAuthorized Networkへの追加と比べて、圧倒的な手軽さと管理コストでPrivate Clusterを実現できるのがTailscale Kubernetes Operatorの特徴で、本記事で紹介したACLだけでなく、マルチクラウド・マルチクラスタ間の通信やEgress, Ingressの設定も出来たりと機能も豊富です。

今後は上記の機能を使いながら、TailscaleのExit nodeを使ってよりフレキシブルなKubernetes Clusterを構築したいと思っています。

Gaudiy Engineers' Blog

Discussion