Dev > Carvel > kwt
Jun 16, 2021
Jun 16, 2021
N/A Views
MD
warning
この記事は2年以上前に更新されたものです。情報が古くなっている可能性があります。

Kubernetes向け便利ツール群の Carvel の一つである kwt を使うとk8sクラスタ外から内部ドメイン名でService / Podへアクセスできます。

データベースや内部APIなどの外部に公開していないServiceに対して、ローカル上の開発環境からアクセスしたい場合や、トラブルシーティングで疎通を確認したい場合に便利です。

通常はkubectl proxykubectl port-fowardを使ってPodやServiceにアクセスすることが多いと思いますが、
kwtを使うと内部ドメイン名を使用できるのでよりk8s内の環境に近い形でアクセスできますし、個々にport forwardの設定をする必要がありません。

同様なツールに Telepresence があります。Telepresenceを使ったことはないですが、ぱっと見kwtの方がシンプルで手軽に使えそうに見えます。

ドキュメントは こちら

kwtを試すための下準備

kwtのインストール

kwtはBrewでインストールできます。

$ brew tap vmware-tanzu/carvel
$ brew install kwt

あるいは
https://github.com/vmware-tanzu/carvel-kwt/releases
からバイナリをダウンロードできます。OS XとLinuxのみサポートされています。

k8sクラスタの作成

まずはkindでk8sクラスタを作成します。

$ kind create cluster
Creating cluster "kind" ...
 ✓ Ensuring node image (kindest/node:v1.21.1) 🖼 
 ✓ Preparing nodes 📦  
 ✓ Writing configuration 📜 
 ✓ Starting control-plane 🕹️ 
 ✓ Installing CNI 🔌 
 ✓ Installing StorageClass 💾 
Set kubectl context to "kind-kind"
You can now use your cluster with:

kubectl cluster-info --context kind-kind

Thanks for using kind! 😊

アプリケーションのデプロイ

サンプルアプリケーションとしてGuestbookをデプロイします。

kubectl apply -f https://github.com/kubernetes/examples/raw/master/guestbook/all-in-one/guestbook-all-in-one.yaml

作成されるPodとServiceは次のとおりです。

$ kubectl get pod,svc
NAME                               READY   STATUS    RESTARTS   AGE
pod/frontend-6c6d6dfd4d-c5jzr      1/1     Running   0          90s
pod/frontend-6c6d6dfd4d-dc77g      1/1     Running   0          90s
pod/frontend-6c6d6dfd4d-rknb6      1/1     Running   0          90s
pod/redis-master-f46ff57fd-2dmpv   1/1     Running   0          90s
pod/redis-slave-7979cfdfb8-7wgcd   1/1     Running   0          90s
pod/redis-slave-7979cfdfb8-h227s   1/1     Running   0          90s

NAME                   TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
service/frontend       NodePort    10.96.51.181    <none>        80:32472/TCP   90s
service/kubernetes     ClusterIP   10.96.0.1       <none>        443/TCP        35m
service/redis-master   ClusterIP   10.96.66.101    <none>        6379/TCP       90s
service/redis-slave    ClusterIP   10.96.250.255   <none>        6379/TCP       90s

なお、kwt net svckwt net podコマンドで、ServiceとPodの内部DNS名一覧を取得できます。

$ kwt net svc
Services in namespace 'default'

Name          Internal DNS                            Cluster IP     Ports  
frontend      frontend.default.svc.cluster.local      10.96.51.181   80/tcp  
kubernetes    kubernetes.default.svc.cluster.local    10.96.0.1      443/tcp  
redis-master  redis-master.default.svc.cluster.local  10.96.66.101   6379/tcp  
redis-slave   redis-slave.default.svc.cluster.local   10.96.250.255  6379/tcp

4 services

Succeeded

$ kwt net pod
Pods in namespace 'default'

Name                          Internal DNS                           IP           Ports  
frontend-6c6d6dfd4d-c5jzr     10-244-0-5.default.pod.cluster.local   10.244.0.5   80/tcp  
frontend-6c6d6dfd4d-dc77g     10-244-0-9.default.pod.cluster.local   10.244.0.9   80/tcp  
frontend-6c6d6dfd4d-rknb6     10-244-0-10.default.pod.cluster.local  10.244.0.10  80/tcp  
redis-master-f46ff57fd-2dmpv  10-244-0-6.default.pod.cluster.local   10.244.0.6   6379/tcp  
redis-slave-7979cfdfb8-7wgcd  10-244-0-8.default.pod.cluster.local   10.244.0.8   6379/tcp  
redis-slave-7979cfdfb8-h227s  10-244-0-7.default.pod.cluster.local   10.244.0.7   6379/tcp

6 pods

Succeeded

kwtを使ってk8s内部にアクセス

次のコマンドを実行して、ローカル環境とk8sクラスタを繋ぎます。

sudo -E kwt net start

次のようなログが出力され、30秒ほどでReadyになります。

12:56:17PM: info: KubeEntryPoint: Creating networking client secret 'kwt-net-ssh-key' in namespace 'default'...
12:56:17PM: info: KubeEntryPoint: Creating networking host secret 'kwt-net-host-key' in namespace 'default'...
12:56:20PM: info: KubeEntryPoint: Creating networking pod 'kwt-net' in namespace 'default'
12:56:20PM: info: KubeEntryPoint: Waiting for networking pod 'kwt-net' in namespace 'default' to start...
12:56:36PM: info: dns.FailoverRecursorPool: Starting with '8.8.8.8:53'
12:56:36PM: info: dns.DomainsMux: Registering cluster.local.->kube-dns
12:56:36PM: info: mdns.Server: Started mDNS resolver on 0.0.0.0:5353
12:56:36PM: info: TCPProxy: Started proxy on 127.0.0.1:51001
12:56:36PM: info: UDPProxy: Started proxy on 127.0.0.1:61048
12:56:36PM: info: dns.Server: Started DNS server on 127.0.0.1:51000 (TCP) and 127.0.0.1:57986 (UDP)
12:56:36PM: info: ForwardingProxy: Forwarding subnets: 10.244.0.5/14, 172.22.0.2/14, 10.96.51.181/14
12:56:36PM: info: ForwardingProxy: Ready!

kwt-netという名前のPodが作成されています。

$ kubectl get pod
NAME                           READY   STATUS    RESTARTS   AGE
frontend-6c6d6dfd4d-c5jzr      1/1     Running   0          7m36s
frontend-6c6d6dfd4d-dc77g      1/1     Running   0          7m36s
frontend-6c6d6dfd4d-rknb6      1/1     Running   0          7m36s
kwt-net                        1/1     Running   0          21s
redis-master-f46ff57fd-2dmpv   1/1     Running   0          7m36s
redis-slave-7979cfdfb8-7wgcd   1/1     Running   0          7m36s
redis-slave-7979cfdfb8-h227s   1/1     Running   0          7m36s

kwt-netのconfigを確認すると、実体がsshdのSOCKSサーバーであることがわかります。

$ kubectl get pod kwt-net -oyaml | kubectl neat
apiVersion: v1
kind: Pod
metadata:
  annotations:
    sidecar.istio.io/inject: "false"
  labels:
    kwt.cppforlife.com/net: "true"
  name: kwt-net
  namespace: default
spec:
  containers:
  - args:
    - -c
    - echo "$KWT_CLIENT_PUB_KEY" > /home/tom/.ssh/authorized_keys && echo "$KWT_HOST_PRIV_KEY"
      > /etc/ssh/ssh_host_rsa_key && echo "$KWT_HOST_PUB_KEY" > /etc/ssh/ssh_host_rsa_key.pub
      && echo "GatewayPorts clientspecified" >> /etc/ssh/sshd_config && exec /usr/sbin/sshd
      -D -p 2048
    command:
    - /bin/bash
    env:
    - name: KWT_CLIENT_PUB_KEY
      valueFrom:
        secretKeyRef:
          key: ssh-publickey
          name: kwt-net-ssh-key
    - name: KWT_HOST_PRIV_KEY
      valueFrom:
        secretKeyRef:
          key: ssh-privatekey
          name: kwt-net-host-key
    - name: KWT_HOST_PUB_KEY
      valueFrom:
        secretKeyRef:
          key: ssh-publickey
          name: kwt-net-host-key
    image: index.docker.io/cppforlife/sshd@sha256:6c3170c4d97f2926ec034fc237554db237076bd9014469aac91610d89a9991d1
    name: kwt-net
    ports:
    - containerPort: 2048
      name: ssh
    # ...

Guestbookのフロントエンドにアクセスしましょう。

ローカル端末上でdigコマンドを使ってfrontend.default.svc.cluster.local名前解決するとCluster IPが返ります。

$ dig frontend.default.svc.cluster.local

; <<>> DiG 9.10.6 <<>> frontend.default.svc.cluster.local
;; global options: +cmd
;; Got answer:
;; WARNING: .local is reserved for Multicast DNS
;; You are currently testing what happens when an mDNS query is leaked to DNS
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 18574
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;frontend.default.svc.cluster.local. IN	A

;; ANSWER SECTION:
frontend.default.svc.cluster.local. 0 IN A	10.96.51.181

;; Query time: 4 msec
;; SERVER: 8.8.8.8#53(8.8.8.8)
;; WHEN: Wed Jun 16 13:14:33 JST 2021
;; MSG SIZE  rcvd: 102

ブラウザでhttp://frontend.default.svc.cluster.localにアクセスします。

image

普通にアクセスできました。

"Messages"に"Hello"を入力して、Submitボタンを押せば、"Hello"が出力されます。

image

Podのうちのひとつ(例: http://10-244-0-5.default.pod.cluster.local)に直接アクセスすることもできます。

image

次にバックエンドのRedisにアクセスしてみます。

$ redis-cli -h redis-master.default.svc.cluster.local -p 6379
redis-master.default.svc.cluster.local:6379> get messages
",Hello"

ローカル環境から直接redis-cliでk8s上のRedisにアクセスできました。

kwtの停止

kwt net svcコマンドを終了すればk8sクラスタへのアクセスはできなくなります。

kwt net svcコマンドで作成されたリソースは次のコマンドで削除できます。

kwt net clean-up

Guestbookも削除しましょう。

kubectl delete -f https://github.com/kubernetes/examples/raw/master/guestbook/all-in-one/guestbook-all-in-one.yaml

kwtでk8sクラスタ外から内部ドメイン名でService / Podへアクセスする方法を紹介しました。
ローカル環境での開発やトラブルシューティングに便利ではないでしょうか。

次は"Carvel kwtでk8sクラスタ内からローカル環境へアクセスする"方法を紹介します。

懸念は最後のリリース(0.0.6)が2019年12月であること...

Found a mistake? Update the entry.
Share this article: