kakakakakku blog

Weekly Tech Blog: Keep on Learning!

kube-capacity コマンドを使って Pod のリソース値をノード別にシンプルに表示する

Kubernetes では Pod にリソース値(要求 : Requests と 制限 : Limits)を設定できる.設定値は kubectl describe コマンドを使って確認できるし,使用率は kubectl top コマンドを使って確認できるけど,今回紹介する CLI「kube-capacity」を使うと,Pod のリソース値(設定値と使用率)をまとめてシンプルに表示できる.最近使っていて便利なのでメモも兼ねて紹介する.

github.com

検証環境

インストール

「kube-capacity」HomebrewKrew を使ってインストールできる.Homebrew だと kube-capacity コマンドとなり,Krew だと kubectl resource-capacity コマンドとなる.どちらも試したけど,今回は新しいバージョン (0.5.0) が使える Homebrew を使う.

$ brew tap robscott/tap
$ brew install robscott/tap/kube-capacity

$ kube-capacity version
kube-capacity version 0.5.0

$ kubectl krew install resource-capacity
Installed plugin: resource-capacity

$ kubectl resource-capacity version
kube-capacity version 0.4.0

1. kube-capacity コマンドを実行する

まず,kind で構築した検証用 Kubernetes クラスターで kube-capacity コマンドを実行すると,ノードごとに以下の値が表示される.* の行には全てのノードの合計値が表示される.

  • CPU REQUESTS : CPU 要求 (Requests) 合計値 と 割合
  • CPU LIMITS : CPU 制限 (Limits) 合計値 と 割合
  • MEMORY REQUESTS : Memory 要求 (Requests) 合計値 と 割合
  • MEMORY LIMITS : Memory 制限 (Limits) 合計値 と 割合
$ kube-capacity
NODE                 CPU REQUESTS   CPU LIMITS   MEMORY REQUESTS   MEMORY LIMITS
*                    1150m (9%)     300m (2%)    390Mi (6%)        490Mi (8%)
kind-control-plane   950m (23%)     100m (2%)    290Mi (14%)       390Mi (19%)
kind-worker          100m (2%)      100m (2%)    50Mi (2%)         50Mi (2%)
kind-worker2         100m (2%)      100m (2%)    50Mi (2%)         50Mi (2%)

最初は表示されている 950m (23%)100m (2%) という値の裏付けが取れずに悩んだけど,デフォルトでは kube-system Namespace の値も含めて全ての Pod が対象になっている.そこで kube-capacity コマンドの --pods オプションを使って Pod レベルで表示すると,CoreDNSkube-apiserverkindnet の合計であると確認できる.

$ kube-capacity --pods
NODE                 NAMESPACE            POD                                          CPU REQUESTS   CPU LIMITS   MEMORY REQUESTS   MEMORY LIMITS
*                    *                    *                                            1150m (9%)     300m (2%)    390Mi (6%)        490Mi (8%)

kind-control-plane   *                    *                                            950m (23%)     100m (2%)    290Mi (14%)       390Mi (19%)
kind-control-plane   kube-system          coredns-74ff55c5b-5v6b8                      100m (2%)      0 (0%)       70Mi (3%)         170Mi (8%)
kind-control-plane   kube-system          coredns-74ff55c5b-xp5m7                      100m (2%)      0 (0%)       70Mi (3%)         170Mi (8%)
kind-control-plane   kube-system          etcd-kind-control-plane                      100m (2%)      0 (0%)       100Mi (5%)        0 (0%)
kind-control-plane   kube-system          kindnet-lbslz                                100m (2%)      100m (2%)    50Mi (2%)         50Mi (2%)
kind-control-plane   kube-system          kube-apiserver-kind-control-plane            250m (6%)      0 (0%)       0 (0%)            0 (0%)
kind-control-plane   kube-system          kube-controller-manager-kind-control-plane   200m (5%)      0 (0%)       0 (0%)            0 (0%)
kind-control-plane   kube-system          kube-proxy-25ltm                             0 (0%)         0 (0%)       0 (0%)            0 (0%)
kind-control-plane   kube-system          kube-scheduler-kind-control-plane            100m (2%)      0 (0%)       0 (0%)            0 (0%)
kind-control-plane   local-path-storage   local-path-provisioner-78776bfc44-cxcpk      0 (0%)         0 (0%)       0 (0%)            0 (0%)

kind-worker          *                    *                                            100m (2%)      100m (2%)    50Mi (2%)         50Mi (2%)
kind-worker          kube-system          kindnet-7t5kc                                100m (2%)      100m (2%)    50Mi (2%)         50Mi (2%)
kind-worker          kube-system          kube-proxy-kbzl8                             0 (0%)         0 (0%)       0 (0%)            0 (0%)
kind-worker          kube-system          metrics-server-8bbfb4bdb-qrrls               0 (0%)         0 (0%)       0 (0%)            0 (0%)

kind-worker2         *                    *                                            100m (2%)      100m (2%)    50Mi (2%)         50Mi (2%)
kind-worker2         kube-system          kindnet-ptmng                                100m (2%)      100m (2%)    50Mi (2%)         50Mi (2%)
kind-worker2         kube-system          kube-proxy-vws54                             0 (0%)         0 (0%)       0 (0%)            0 (0%)

2. Namespace を指定して kube-capacity コマンドを実行する

kube-system Namespace を無視して,特定の Namespace を指定することもできる.kube-capacity コマンドの --namespace-labels オプションを使って NamespaceLabel で指定する.今回は name=sandbox という適当な Label を付けた sandbox Namespace を作った.初期状態だとまだ何もリソースを適用していないため,全て 0 (0%) になっている.

$ kube-capacity --pods --namespace-labels name=sandbox
NODE                 NAMESPACE   POD   CPU REQUESTS   CPU LIMITS   MEMORY REQUESTS   MEMORY LIMITS
*                    *           *     0 (0%)         0 (0%)       0 (0%)            0 (0%)

kind-control-plane   *           *     0 (0%)         0 (0%)       0 (0%)            0 (0%)

kind-worker          *           *     0 (0%)         0 (0%)       0 (0%)            0 (0%)

kind-worker2         *           *     0 (0%)         0 (0%)       0 (0%)            0 (0%)

3. Deployment を適用して値を確認する

検証用に以下のようなリソース値(要求 : Requests と 制限 : Limits)を設定した Deploymentreplicas: 4 で作る.

  • requests
    • cpu : 200m
    • memory : 100Mi
  • limits
    • cpu : 1000m
    • memory : 500Mi
apiVersion: apps/v1
kind: Deployment
metadata:
  name: sandbox-kube-capacity-nginx
  namespace: sandbox
  labels:
    app: nginx
spec:
  replicas: 4
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.19-alpine
        resources:
          requests:
            cpu: 100m
            memory: 100Mi
          limits:
            cpu: 500m
            memory: 500Mi
        ports:
        - containerPort: 80

Deployment を適用してから,もう1度 kube-capacity コマンドを実行すると,設定したリソース値の合計になっていた.便利!

$ kube-capacity --pods --namespace-labels name=sandbox
NODE                 NAMESPACE   POD                                            CPU REQUESTS   CPU LIMITS    MEMORY REQUESTS   MEMORY LIMITS
*                    *           *                                              400m (3%)      2 (16%)       400Mi (6%)        2000Mi (33%)

kind-control-plane   *           *                                              0 (0%)         0 (0%)        0 (0%)            0 (0%)

kind-worker          *           *                                              100m (2%)      500m (12%)    100Mi (5%)        500Mi (25%)
kind-worker          sandbox     sandbox-kube-capacity-nginx-68fdb47b8d-8csj7   100m (2%)      500m (12%)    100Mi (5%)        500Mi (25%)

kind-worker2         *           *                                              300m (7%)      1500m (37%)   300Mi (15%)       1500Mi (75%)
kind-worker2         sandbox     sandbox-kube-capacity-nginx-68fdb47b8d-5mxnx   100m (2%)      500m (12%)    100Mi (5%)        500Mi (25%)
kind-worker2         sandbox     sandbox-kube-capacity-nginx-68fdb47b8d-6gwts   100m (2%)      500m (12%)    100Mi (5%)        500Mi (25%)
kind-worker2         sandbox     sandbox-kube-capacity-nginx-68fdb47b8d-bbnsj   100m (2%)      500m (12%)    100Mi (5%)        500Mi (25%)

4. 追加で使用率も表示する

さらに kube-capacity コマンドの --util オプションを使うと「使用率」を表示できるようになる.

  • CPU UTIL : CPU 使用率
  • MEMORY UTIL : Memory 使用率
$ kube-capacity --pods --namespace-labels name=sandbox --util
NODE                 NAMESPACE   POD                                            CPU REQUESTS   CPU LIMITS    CPU UTIL          MEMORY REQUESTS   MEMORY LIMITS   MEMORY UTIL
*                    *           *                                              400m (3%)      2 (16%)       517975675n (4%)   400Mi (6%)        2000Mi (33%)    854872Ki (13%)

kind-control-plane   *           *                                              0 (0%)         0 (0%)        396547620n (9%)   0 (0%)            0 (0%)          558568Ki (27%)

kind-worker          *           *                                              100m (2%)      500m (12%)    62508437n (1%)    100Mi (5%)        500Mi (25%)     158572Ki (7%)
kind-worker          sandbox     sandbox-kube-capacity-nginx-68fdb47b8d-8csj7   100m (2%)      500m (12%)    0 (0%)            100Mi (5%)        500Mi (25%)     3960Ki (0%)

kind-worker2         *           *                                              300m (7%)      1500m (37%)   58919618n (1%)    300Mi (15%)       1500Mi (75%)    137732Ki (6%)
kind-worker2         sandbox     sandbox-kube-capacity-nginx-68fdb47b8d-5mxnx   100m (2%)      500m (12%)    0 (0%)            100Mi (5%)        500Mi (25%)     3948Ki (0%)
kind-worker2         sandbox     sandbox-kube-capacity-nginx-68fdb47b8d-6gwts   100m (2%)      500m (12%)    0 (0%)            100Mi (5%)        500Mi (25%)     3980Ki (0%)
kind-worker2         sandbox     sandbox-kube-capacity-nginx-68fdb47b8d-bbnsj   100m (2%)      500m (12%)    0 (0%)            100Mi (5%)        500Mi (25%)     4124Ki (0%)

5. オプションは他にもある

今回は --namespace-labels オプションを使ったけど,オプションは他にもある.例えば --pod-labels オプションを使えば,PodLabel で絞り込みできるし,--node-labels オプションを使えば,ノードの Label で絞り込みできる.

$ kube-capacity --pod-labels app=nginx
NODE                 CPU REQUESTS   CPU LIMITS    MEMORY REQUESTS   MEMORY LIMITS
*                    400m (3%)      2 (16%)       400Mi (6%)        2000Mi (33%)
kind-control-plane   0 (0%)         0 (0%)        0 (0%)            0 (0%)
kind-worker          100m (2%)      500m (12%)    100Mi (5%)        500Mi (25%)
kind-worker2         300m (7%)      1500m (37%)   300Mi (15%)       1500Mi (75%)

$ kube-capacity --node-labels kubernetes.io/os=linux
NODE                 CPU REQUESTS   CPU LIMITS    MEMORY REQUESTS   MEMORY LIMITS
*                    1550m (12%)    2300m (19%)   790Mi (13%)       2490Mi (41%)
kind-control-plane   950m (23%)     100m (2%)     290Mi (14%)       390Mi (19%)
kind-worker          200m (5%)      600m (15%)    150Mi (7%)        550Mi (27%)
kind-worker2         400m (10%)     1600m (40%)   350Mi (17%)       1550Mi (77%)

まとめ

「kube-capacity」を使うと,Pod のリソース値をノード別にシンプルに表示できる.インストールしておくと便利!なお,今はまだリリースされていないけど,GitHub リポジトリの master ブランチを見ると,新しく --namespace オプションが追加されている.Label を使わずにシンプルに Namespace を指定できるため,今よりも便利になると思う.

github.com

Network Policy をわかりやすく学べる「Kubernetes Network Policy Recipes」

GitHub に公開されている「Kubernetes Network Policy Recipes」を使うと,Kubernetes の Network Policy をわかりやすく学べる.現時点だと「計14種類」Network Policy レシピ(サンプル)が載っていて,実際に使う機会がありそうな設定も多くて参考になる.さらに Network Policy の YAML を読むだけだとイメージしにくかったりする Ingress と EgressAllow と Deny の関係性も図解されているのも素晴らしい!

github.com

レシピ一覧

現時点で公開されているレシピをまとめる.日本語訳は参考程度に載せておく!

  • Basics
    • DENY all traffic to an application(アプリケーションへの全てのトラフィックを拒否する)
    • LIMIT traffic to an application(アプリケーションへのトラフィックを制限する)
    • ALLOW all traffic to an application(アプリケーションへの全てのトラフィックを許可する)
  • Namespaces
    • DENY all non-whitelisted traffic in the current namespace(現在の Namespace でホワイトリストに登録されていない全てのトラフィックを拒否する)
    • DENY all traffic from other namespaces(他の Namespace からの全てのトラフィックを拒否する)
    • ALLOW traffic to an application from all namespaces(全ての Namespace からアプリケーションへのトラフィックを許可する)
    • ALLOW all traffic from a namespace(Namespace からの全てのトラフィックを許可する)
    • ALLOW traffic from some pods in another namespace(他の Namespace の一部の Pod からのトラフィックを許可する)
  • Serving External Traffic
    • ALLOW traffic from external clients(外部クライアントからのトラフィックを許可する)
  • Advanced
    • ALLOW traffic only to certain port numbers of an application(アプリケーションの特定のポート番号へのトラフィックのみを許可する)
    • ALLOW traffic from apps using multiple selectors(複数のセレクターを使ってアプリケーションからのトラフィックを許可する)
  • Controlling Outbound (Egress) Traffic
    • DENY egress traffic from an application(アプリケーションからの外向きのトラフィックを拒否する)
    • DENY all non-whitelisted egress traffic in a namespace(現在の Namespace でホワイトリストに登録されていない全ての外向きのトラフィックを拒否する)
    • LIMIT egress traffic to the cluster(クラスターへの外向きのトラフィックを制限する)

検証環境

「Kubernetes Network Policy Recipes」の紹介も兼ねて,レシピをいくつか試してみる.今回は以下の検証環境を前提にする.なお,レシピ(手順書)に含まれている kubectl run コマンドの --generator=run-pod/v1 オプションは特に必要なく,コマンドは一部変えている.

  • Kubernetes : v1.20.1
  • Calico : v3.14.2

DENY all traffic to an application(アプリケーションへの全てのトラフィックを拒否する)

f:id:kakku22:20210314141402g:plain
GitHub - ahmetb/kubernetes-network-policy-recipes より引用

「DENY all traffic to an application」レシピでは,Label app=web を持ったアプリケーション Pod へのトラフィックを拒否する.さっそく試していく!まず,default NamespaceLabel app=web を持ったアプリケーション PodService を作る.

$ kubectl run web --image nginx --labels app=web --expose --port 80
service/web created
pod/web created

次にアプリケーション Pod に対してリクエストを送る Poddefault Namespace に作る(図だと右側にある Any container).Pod の中で wget コマンドを実行すると,正常に nginx に接続できる.

$ kubectl run --rm -it --image alpine test-$RANDOM -- sh

/ # wget -qO- http://web
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
(中略)
</html>

ここで Network Policy を作る.ポイントは大きく2点ある.

  • spec.podSelector : Network Policy を適用する対象(Label app=web を持つ Pod
  • spec.ingress : 許可する Ingress ルール(全て拒否)
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  name: web-deny-all
spec:
  podSelector:
    matchLabels:
      app: web
  ingress: []

動作確認をするため,もう1度 wget コマンドを実行すると,タイムアウトになった.期待通りに Network Policy が適用されている.

$ kubectl run --rm -it --image alpine test-$RANDOM -- sh

/ # wget -qO- --timeout=2 http://web
wget: download timed out

DENY all traffic from other namespaces(他の Namespace からの全てのトラフィックを拒否する)

f:id:kakku22:20210314141329g:plain
GitHub - ahmetb/kubernetes-network-policy-recipes より引用

「DENY all traffic from other namespaces」レシピでは,他の Namespace からのトラフィックを拒否する.さっそく試していく!まず,さっきと同じように default NamespaceLabel app=web を持ったアプリケーション PodService を作る.

$ kubectl run web --image nginx --labels app=web --expose --port 80
service/web created
pod/web created

次に Network Policy を作る.ポイントは大きく3点ある.

  • metadata.namespace : Network Policy を適用する Namespace(今回は default
  • spec.podSelector : Network Policy を適用する対象(指定なし = default Namespace の全ての Pod
  • spec.ingress : 許可する Ingress ルール(default Namespace の全ての Pod を許可)
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  namespace: default
  name: deny-from-other-namespaces
spec:
  podSelector:
    matchLabels:
  ingress:
  - from:
    - podSelector: {}

動作確認をするため,今回は default NamespacePodfoo NamespacePod のそれぞれから wget コマンドを実行する(図だと左側にある any pod と中央下にある app=db).同じ default Namespace からは正常に接続できて,別の foo Namespace からはタイムアウトになった.期待通りに Network Policy が適用されている.

$ kubectl run test-$RANDOM --namespace=default --rm -it --image alpine -- sh

/ # wget -qO- --timeout=2 http://web.default
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>

$ kubectl run test-$RANDOM --namespace=foo --rm -it --image alpine -- sh

/ # wget -qO- --timeout=2 http://web.default
wget: download timed out

ALLOW traffic only to certain port numbers of an application(アプリケーションの特定のポート番号へのトラフィックのみを許可する)

f:id:kakku22:20210314141250g:plain
GitHub - ahmetb/kubernetes-network-policy-recipes より引用

「ALLOW traffic only to certain port numbers of an application」レシピでは,特定のポートへのトラフィックを許可する.さっそく試していく!まず「5000 ポート」「8000 ポート」を許可したサンプルイメージ ahmet/app-on-two-ports を使って default NamespacePod を作る.さらに「5001 ポート」「8001 ポート」にマッピングをした Service を作る.

$ kubectl run apiserver --image ahmet/app-on-two-ports --labels app=apiserver
pod/apiserver created

$ kubectl create service clusterip apiserver \
    --tcp 8001:8000 \
    --tcp 5001:5000
service/apiserver created

次に Network Policy を作る.ポイントは大きく2点ある.

  • spec.podSelector : Network Policy を適用する対象(Label app=apiserver を持つ Pod
  • spec.ingress : 許可する Ingress ルール(Label role=monitoring を持つ Pod から 5000 ポートへの接続を許可)
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  name: api-allow-5000
spec:
  podSelector:
    matchLabels:
      app: apiserver
  ingress:
  - ports:
    - port: 5000
    from:
    - podSelector:
        matchLabels:
          role: monitoring

さっそく動作確認をしていく.まず,Label role=monitoring を持たない Pod の中で wget コマンドを実行すると「5001 (5000) ポート」「8001 (8000) ポート」もタイムアウトになる.

$ kubectl run test-$RANDOM --rm -it --image alpine -- sh


/ # wget -qO- --timeout=2 http://apiserver:5001/metrics
wget: download timed out

/ # wget -qO- --timeout=2 http://apiserver:8001
wget: download timed out

次に,Label role=monitoring を持つ Pod の中で wget コマンドを実行すると「5001 (5000) ポート」に接続できる.「8001 (8000) ポート」はタイムアウトになる.期待通りに Network Policy が適用されている.

$ kubectl run test-$RANDOM --rm -it --image alpine --labels role=monitoring -- sh

/ # wget -qO- --timeout=2 http://apiserver:5001/metrics
http.requests=1
go.goroutines=5
go.cpus=2

/ # wget -qO- --timeout=2 http://apiserver:8001
wget: download timed out

まとめ

「Kubernetes Network Policy Recipes」を使うと,Kubernetes の Network Policy をわかりやすく学べる.また Certified Kubernetes Administrator (CKA)Certified Kubernetes Application Developer (CKAD)Certified Kubernetes Security Specialist (CKS) の対策にも使える!Network Policy の YAML に苦手意識があったら(まさに僕!)試してみると良いのではないでしょうか!

github.com

マニフェストを適用する前に編集できる "kubectl create --edit" コマンド

Kubernetes のドキュメントを読んでいたら kubectl create コマンドで --edit オプションが使えると書いてあった.kubectl create -h コマンドでヘルプを確認したところ Edit the API resource before creating と書いてある.簡単に言うと kubectl create コマンドでマニフェストを適用する前に編集できる.今まで使ったことがなく試してみた!

You can use kubectl create --edit to make arbitrary changes to an object before it is created. Here's an example:
$ kubectl create service clusterip my-svc --clusterip="None" -o yaml --dry-run=client > /tmp/srv.yaml
$ kubectl create --edit -f /tmp/srv.yaml

kubernetes.io

kubectl create --edit コマンドをさっそく試す

適当に nginx イメージを replicas: 3 で設定した Deployment のマニフェスト (deployment.yaml) を準備して,以下のように kubectl create --edit -f deployment.yaml コマンドを実行する.すると kubectl edit コマンドと同じようにエディタ画面になり,適用する前にマニフェストを編集できる.

$ kubectl create --edit -f deployment.yaml

f:id:kakku22:20210305110209p:plain

今回は replicas: 3replicas: 5 に編集した.なるほど!編集できた.

$ kubectl get pods
NAME                            READY   STATUS    RESTARTS   AGE
sandbox-nginx-f9f7485cd-2xqx7   1/1     Running   0          5m
sandbox-nginx-f9f7485cd-6fm5n   1/1     Running   0          5m
sandbox-nginx-f9f7485cd-mnpz2   1/1     Running   0          5m
sandbox-nginx-f9f7485cd-qhgtp   1/1     Running   0          5m
sandbox-nginx-f9f7485cd-w5pml   1/1     Running   0          5m

kubectl create --edit コマンドの使いどころ

基本的には kubectl apply コマンドを使う機会が多いと思う.今回試した kubectl create --edit コマンドの使いどころを考えていたら,別のドキュメントに以下のように書いてあった.確かに「チュートリアル」など,一時的に試すときには便利そう.今までは wget で取得してから一部を編集していたことが多かったし!

Suppose you have the URL of an object configuration file. You can use kubectl create --edit to make changes to the configuration before the object is created. This is particularly useful for tutorials and tasks that point to a configuration file that could be modified by the reader.

kubernetes.io

当然だけど,マニフェストを GitHub 経由 (GitHub : kakakakakku/k8s-manifests) で取得して kubectl create --edit コマンドを実行しても結果は同じ.マニフェストを編集してから適用できる.

$ kubectl create --edit -f https://raw.githubusercontent.com/kakakakakku/k8s-manifests/master/sandbox-kubectl-create-edit-option/deployment.yaml
deployment.apps/sandbox-nginx created

まとめ

今まで使ったことがなかった kubectl create --edit コマンドを試した.手元にあるマニフェストを適用する前に編集できて便利な使いどころもありそう!そもそも kubectl create コマンドを使う機会は仕事だと多くはなく,1番使うのは Certified Kubernetes Administrator (CKA)Certified Kubernetes Application Developer (CKAD) を受験するときかもしれないけど!w

Automator と say コマンドを組み合わせた簡単な音声テスト

「リモート研修」「リモート会議」をするときに,機材としては Blue Microphones YeticasterBeats Studio(有線)の組み合わせを使っている.特に「リモート研修」のように1日中配信を行う場合は遅延と充電の観点から意図的に有線を選びつつ,カジュアルな場であれば Bluetooth でも問題なく AirPods Pro を使っている.

オーディオ設定の確認 🎧

そのときに「オーディオ設定(特に出力側)はちゃんと機能している?相手の声をちゃんと聞ける状態になっている?」という個人的な不安があり,休憩時間など定期的に YouTube の適当なビデオを流して,音声テストをする癖がある.特に「リモート研修」では,なぜか BlackHole に設定されてしまう場面もあったりして「お客様の声をちゃんと聞ける状態になっている?」という確認を怠らないように意識している.

「Automator」+ say コマンド 🎧

繰り返し行うこともあり,毎回 YouTube を開きたくないし,最初に流れる広告で音声テストをすることになる場面も多いし(笑)もっと簡単な手順に移行したいと考えていた.現在は Mac (macOS) で使える「Automator」say コマンドを組み合わせた手順に移行して,数ヶ月使っている.個人的には便利で満足している!他にも実現方法はあると思うけど,特に配信中は Mac の負荷も高くなるため,不要なツールを常駐させたくなく,シンプルに実現したかった.今回は簡単に設定を紹介する!

できること 🎧

  1. アプリケーションの「サービス」メニューから「音声テスト(say コマンド)」を実行できる
  2. 任意のショートカットから「音声テスト(say コマンド)」を実行できる

f:id:kakku22:20210224181007p:plain

Automator を使う 🎧

まず「Automator」を開いたら「クイックアクション」を選択する.

f:id:kakku22:20210224181319p:plain

次に「アクション」「ライブラリ」「ユーティリティ」「シェルスクリプトを実行」を選択する.特に他サービスと連携する必要はなく「ワークフローが受け取る項目」「入力なし」にしておく.「検索対象」はデフォルトのまま「すべてのアプリケーション」にしておく.シェルスクリプトは以下のように say コマンドを実行する.文章は普通すぎて避難訓練のようになってしまった...!

$ say '音声テストです!聞こえますか?'

最後に「クイックアクション名」「音声テスト」と設定したら終了!簡単!

f:id:kakku22:20210224181455p:plain

ちなみに「クイックアクション」~/Library/Services に保存されている.最初すぐに見つけられなくて困った!

$ ls -1 ~/Library/Services
音声テスト.workflow

サービスを確認する 🎧

「クイックアクション」はすぐに使える.ChromeiTerm2 など,任意のアプリケーションを開いた状態から「サービス」「音声テスト」を選択すると say コマンドを実行できる.便利!うおおおおお!

f:id:kakku22:20210224182219p:plain

ショートカットを設定する

ショートカット経由で「クイックアクション」を実行することもできる.今のところ特に競合することのなさそうな「option + command + z」に割り当てて問題なく使えている.便利!ついつい押したくなってしまう!

f:id:kakku22:20210224183012p:plain

まとめ 🎧

Mac (macOS) で使える「Automator」say コマンドを組み合わせて気軽に「音声テスト」を実行できるようにした.今まで YouTube を使っていた手順をシンプルに移行できて満足している.なお,今まで「Automator」はほとんど使ったことがなかったけど,実はイロイロと使える便利なツールかも?と思った.他にも使えそうな場面があれば検討してみよう.

おまけ : say コマンド + Rubicure

なお,今回は最終的に「音声テストです!聞こえますか?」という普通すぎる文章になってしまったけど,検証段階では id:sue445 さんの Rubicure を使って,プリキュアの必殺技を読ませていたんだけど,say コマンドの声優さんとの相性が悪かったのと,間違って「リモート研修」中に配信してしまうとヤバイため,個人利用に留めている(笑)スクリプトは雑に書き捨てたからもっとシンプルに書けるはず!

require 'rubicure'
system("say #{Precure.healingood.girls.sample.attack_messages.first.gsub(/[\r\n]/,'')}")

github.com

潜水艦の操縦士になろう / ドットインストール「Scratch で潜水艦ゲームを作ろう」を受講した

ドットインストールには昨日紹介したScratch 3.0 入門以外にもう1個「Scratch で潜水艦ゲームを作ろう」というコンテンツがある.Scratch の基本的な操作を理解した上で「より高度な操作」を学びながらゲームを作っていくことができる.とても楽しく,僕も使ったことがないブロックがあったりして,素晴らしいコンテンツだった!今回も「良さ」を紹介したいと思う.以下に載せた「全21個」の動画があり,全て3分以内で終わるので,流し見をするだけなら1時間もあれば十分!

  • 01 : 潜水艦ゲームを作ってみよう
  • 02 : 潜水艦の素材をアップロードしよう
  • 03 : コスチュームを切り替えてみよう
  • 04 : スプライトをスムーズに動かそう
  • 05 : 潜水艦を矢印キーで動かそう
  • 06 : 背景を作り込んでいこう
  • 07 : 壁と衝突したか判定しよう
  • 08 : 他のスクリプトを止めてみよう
  • 09 : メッセージを送ってみよう
  • 10 : ブロックを整理していこう
  • 11 : レベルごとに背景を作っていこう
  • 12 : ゲームクリア画面を作ろう
  • 13 : 背景が切り替わる条件を設定しよう
  • 14 : レベルアップで背景を切り替えよう
  • 15 : ゲームクリアできるようにしよう
  • 16 : 敵を作っていこう
  • 17 : 敵を上下に動かそう
  • 18 : 敵との衝突判定をしよう
  • 19 : レベル 3 だったら敵を表示しよう
  • 20 : BGM を追加しよう
  • 21 : 効果音を追加しよう

dotinstall.com

作るもの 🚢

「Scratch で潜水艦ゲームを作ろう」では,名前の通り「潜水艦ゲーム 🚢」を作る.以下に埋め込んだ Scratch プロジェクトの完成版が公開されている.簡単に言えば「潜水艦を上下に動かしながら壁にぶつからないように進んでいくゲーム」になっている.潜水艦が重力により沈んだり,ステージによってコースが違ったり,当たると爆発してしまう敵が出てきたりもする.よくでてきて普通に楽しい!わいわい!

良いところ 1 : 自作の背景と色を使った衝突判定を学べる 🚢

序盤で Scratch のペイントエディタを使って「背景」を自作する.重要なのは「壁」の部分で実はオレンジ色のペンで手描きをしている.手描きをしてしまうとスプライトにすることができず,衝突判定はどうやるんだろう?と考えていたら「もし < オレンジ色に触れた > なら」という制御で実現していた!色を衝突判定に使うアイデアは使ったことがなくて,なるほどー!と思った.以下は自分で作った「背景 : LEVEL 4」でカスタマイズして楽しむこともできる(頑張って進んでいるところww)!

f:id:kakku22:20210225165848p:plain

良いところ 2 : メッセージを学べる 🚢

Scratch で別のスプライトやステージを同期的に(実際に同期しているかどうかは別として)制御する場合「メッセージ」という機能を使う必要がある.メッセージを送る側とメッセージを受信する側で独立してワークフローを作るイメージになり,今回のコンテンツでは「リセットメッセージ」「レベルアップメッセージ」を使う.「メッセージ」を使うとより高度なワークフローを作ることができるため実際に学べるのはとても良いと思う.「変数」と組み合わせた送信先の制限など実践的な Tips は Japanese Scratch-Wiki にも載っている.

ja.scratch-wiki.info

良いところ 3 : リファクタリングを学べる 🚢

「10 : ブロックを整理していこう」では,簡単ではあるけど,重複したブロックを整理するリファクタリングを学べる.動くなら良いじゃん!と娘に言われてしまうかもしれないけど,修正箇所が増えてきたら教えてあげる良いタイミングかもしれない!「リファクタリング(整理)」という観点を学べるのも素晴らしい!今回のコンテンツでは Scratch「ブロック定義」までは使わないけど,より複雑化するなら検討すると良いと思う.

ja.scratch-wiki.info

良いところ 4 : 背景番号を使った Tips を学べる 🚢

全ての背景をクリアしたら「背景 : GAME CLEAR」を表示して,ワークフローを止める必要がある.仕組みとしては「レベルアップメッセージ」を受信したら「次の背景にする」ブロックを実行しているため,そのままだと「背景 : GAME CLEAR」で右に進むと,また「背景 : LEVEL 1」に戻ってしまう.

そこで「もし < ステージの背景 # = 4 > なら」という背景番号を使った条件でクリアを判定している.マジックナンバーに依存してしまうので,ベストプラクティスではないかもしれないけど「添字」を使うという Tips を学べるのは参考になると思う.正確には以下のように「スプライトの他のスクリプトを止める」「すべてを止める」も組み合わせてゲームを止めている.

f:id:kakku22:20210225174952p:plain

まとめ

ドットインストールで学べる「Scratch で潜水艦ゲームを作ろう」Scratch の基本的な操作を理解した上で「より高度な操作」を学びながらゲームを作れる素晴らしいコンテンツだった!是非受講してみて欲しい!今回紹介した「良いところ」以外にもいろいろと工夫されているぞ!

dotinstall.com

関連記事

Scratch に入門するならまず以下を読んでもらえると良いかと!

kakakakakku.hatenablog.com