kakakakakku blog

Weekly Tech Blog: Keep on Learning!

python-pptx を使って PowerPoint ファイルの「発表者ノート」を抽出する

PowerPoint を使ってプレゼンテーションをするときに,原稿や関連情報を「発表者ノート」に書いておく人は多いと思う.最近 PowerPoint ファイルの「発表者ノート」を抽出して別のファイルにコピーする必要があった.具体的にはプロンプターに投影する原稿を作る必要があった.

f:id:kakku22:20200905001414p:plain

ページ数が少なかったら地道にコピーしても良いけど,今回なんと「約100ページ」もあり,流石に作業効率が悪すぎた.そこで Pythonpython-pptx を使って,自動的に「発表者ノート」を抽出できるようにした.Python 3.8.5python-pptx v0.6.18 を前提にする.

github.com

サンプルコード

以下にサンプルコードを載せる.事前に pip install もしくは requirements.txt を使って python-pptx をインストールしておけば,すぐに試せる.今回は同じディレクトリに置いてある example.pptx から「スライドタイトル」「発表者ノート」を抽出する.たった9行!

from pptx import Presentation

presentation = Presentation('example.pptx')

for slide in presentation.slides:
    if slide.has_notes_slide and slide.notes_slide.notes_text_frame.text:
        print(slide.shapes.title.text)
        print(slide.notes_slide.notes_text_frame.text)
        print('-----')

動作確認

実際に上に載せたサンプルの PowerPoint ファイル example.pptx を使ってサンプルコードを実行する.期待した通り「スライドタイトル」「発表者ノート」を抽出できた.これは便利!

$ python note.py
slide title 1
a
bb
ccc
dddd
eeeee
-----
slide title 2
f
gg
hhh
iiii
jjjjj
-----

python-pptx 紹介

python-pptx を使うと,Python で PowerPoint ファイルを自由に編集できる.機能はたくさんあるけど,今回は大きく以下の API を使った.「スライドタイトル」を抽出する場合は slide.shapes.title.text のように書く.「発表者ノート」を抽出する場合は slide.notes_slide.notes_text_frame.text のように書く.読みやすいとは思う.

  • Presentation オブジェクト
  • Slides オブジェクト
  • Slide オブジェクト

なお,Slide オブジェクトで使える has_notes_slide() メソッドは「発表者ノート」の有無を True/False で返す.新しく作ったスライドだと,ちゃんと False になるけど,1度書いた後に消すと True になってしまったりして,期待した動きにならなかった.今回のサンプルコードでは「発表者ノート」として抽出した文字列のブランク判定も含めている(if 文のところ).

python-pptx.readthedocs.io

まとめ

最近 PowerPoint ファイルの「発表者ノート」を抽出して別のファイルにコピーする必要があった.作業効率も考えて Pythonpython-pptx を使って自動化した.python-pptx は他にも便利な機能があるので,また別の記事で紹介したいと思う.

Finder で開いているディレクトリを VS Code や iTerm2 ですぐに開ける「OpenInTerminal」

macOS を使っていると,Finder で開いているディレクトリを Visual Studio Code (VS Code)iTerm2 で開きたくなる.誰しもあるシチュエーションだと思う.今までは cdtoを使ったり,AppleScript を実装したこともあるけど,最近 OpenInTerminal に移行した.積極的にメンテナンスされているし,インストールも簡単だし,よりシンプルな「Lite 版」もある.個人的にとても気に入っている.

github.com

OpenInTerminal とは?

詳しくは OpenInTerminal の GitHub に機能比較表が載っているけど,正確には以下のように「3種類」のツールがある.簡単に言うと OpenInTerminal「全部入り」となり,設定画面も付いているし,Finder で開いているディレクトリパスをクリップボードにコピーする「コピーパス機能 (Copy path)」も付いている.OpenInTerminal-LiteOpenInEditor-Lite は独立して使える.

自分の操作に合ったツールを選べば良いと思うけど,僕は OpenInTerminal-LiteOpenInEditor-Lite の組み合わせを選んだ.個人的に「コピーパス機能」が不要だったことと,1 クリックで素早く開きたかった.筆者も「Lite 版」推しだと README.md に書いてあった.

  • OpenInTerminal
  • OpenInTerminal-Lite
  • OpenInEditor-Lite

インストールする

brew を使って簡単にインストールできる.

# OpenInTerminal なら
$ brew cask install openinterminal

# OpenInTerminal-Lite なら
$ brew cask install openinterminal-lite

# OpenInEditor-Lite なら
$ brew cask install openineditor-lite

セットアップする

インストールをしたら,アプリケーション一覧で command を押しながら Finder のメニューバーにドラッグする.初回は macOS でパーミッション許可をしておく必要もある.今回は VS CodeiTerm2 を選択した.他にも AtomIntelliJ IDEATerminal も選べる.

検索バーの隣にあるアイコンを押すと,すぐに VS CodeiTerm2 を開ける.シンプルだけど,とても便利!

f:id:kakku22:20200901185523p:plain

アイコンを変える

GitHub の Releases から icons.zip をダウンロードして設定すると,アイコンを差し替えられる.僕はダークテーマにした.

f:id:kakku22:20200901185537p:plain

まとめ

OpenInTerminal-LiteOpenInEditor-Lite を使えば,Finder で開いているディレクトリを VS CodeiTerm2 ですぐに開ける.便利!

関連機能

例えば iTerm2 には Finder で「ディレクトリを右クリック」して「New iTerm2 Tab Here」メニューを選ぶ機能がある.個人的には「ディレクトリを右クリック」するのではなく「今いるディレクトリで」iTerm2 を開きたくて,使えなかった.

www.iterm2.com

kustomize の configGeneration を使って ConfigMap リソースをデプロイする

先週の記事に続き kustomizeExamples を試していく.前回は「helloWorld」を試した.今回は ConfigMap リソースでローリングデプロイのような挙動を実現できる kustomizeconfigGeneration を試す.

kakakakakku.hatenablog.com

前提

今回も Docker Desktop for Mac "Edge" を使って,以下の Kubernetes 環境で試した.

$ kubectl version --short
Client Version: v1.18.6
Server Version: v1.18.6

$ kustomize version --short
{3.8.1  2020-07-16T05:11:04+01:00  }

Examples「configGeneration」とは?

kustomizeConfigMap リソースを書き換える方法は「2種類」ある.

  1. kustomization.yamlpatchesStrategicMerge 構文を使う(マニフェストを指定する)
  2. kustomization.yamlconfigMapGenerator 構文を使う(kustomization.yaml 自体に書く / 1. と組み合わせもある)

Examples「helloWorld」 で試したのは「1番目 (patchesStrategicMerge)」だった.ポイントは ConfigMap のリソース名で,具体的には staging-the-mapproduction-the-map など,プレフィックス以外は固定される.これ自体は全く問題ではないけど,例えば環境変数として読み込んだ ConfigMap の更新を自動的に反映できなかったりする(正確には Volume マウントをすれば,自動的に反映できる).

そこで「2番目 (configMapGenerator)」を使うことにより,ConfigMap のリソース名にハッシュを含めて,結果的にローリングデプロイのような挙動を実現できるようになる.イメージとしては DeploymentReplicaSet の関係のような感じ!さっそく試していく.

1. 事前準備

まず,作業ディレクトリと「ベースマニフェスト」を置く base ディレクトリを作る.前回と同じ.

$ DEMO_HOME=~/configGeneration
$ BASE=${DEMO_HOME}/base
$ mkdir -p ${BASE}

2. マニフェストと kustomization.yaml を作る

次に GitHub に公開されている Deployment / Service リソースのマニフェストを base ディレクトリにダウンロードする.そして,共通で使う kustomization.yaml を作り,さらに staging 環境用の overlays ディレクトリに ConfigMap のマニフェストと kustomization.yaml を作る.最終的な tree コマンドの結果も載せておく.

$ curl -s -o "${BASE}/#1.yaml" "https://raw.githubusercontent.com\
/kubernetes-sigs/kustomize\
/master/examples/helloWorld\
/{deployment,service}.yaml"

$ OVERLAYS=${DEMO_HOME}/overlays
$ mkdir -p ${OVERLAYS}/staging

$ tree .
.
├── base
│   ├── deployment.yaml
│   ├── kustomization.yaml
│   └── service.yaml
└── overlays
    └── staging
        ├── kustomization.yaml
        └── map.yaml

次に,作ったマニフェストと kustomization.yaml を詳しく見ていく.

overlays/staging/map.yaml

まず,overlays/staging/map.yaml は,staging 環境用の ConfigMap リソースを管理するマニフェストで,リソース名は the-map となる.管理するキーとしては altGreetingenableRisky を定義してある.

apiVersion: v1
kind: ConfigMap
metadata:
  name: the-map
data:
  altGreeting: "Have a pineapple!"
  enableRisky: "true"

base/deployment.yaml

次に base/deployment.yamlDeployment リソースのマニフェストを確認する.ポイントは env のところで,configMapKeyRef を使って,上に載せた ConfigMap リソースの the-map を参照している.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: the-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      deployment: hello
  template:
    metadata:
      labels:
        deployment: hello
    spec:
      containers:
      - name: the-container
        image: monopole/hello:1
        command: ["/hello",
                  "--port=8080",
                  "--enableRiskyFeature=$(ENABLE_RISKY)"]
        ports:
        - containerPort: 8080
        env:
        - name: ALT_GREETING
          valueFrom:
            configMapKeyRef:
              name: the-map
              key: altGreeting
        - name: ENABLE_RISKY
          valueFrom:
            configMapKeyRef:
              name: the-map
              key: enableRisky

base/kustomization.yaml

今度は base ディレクトリに置いた base/kustomization.yaml を確認すると,configMapGenerator という構文があり nameliterals から構成されている.ConfigMap リソース名は合わせて the-map にしておく.今回は kustomize build を実行して overlaysmap.yaml で書き換えるため,literals の値は書き換えられてしまう.

commonLabels:
  app: hello
resources:
- deployment.yaml
- service.yaml
configMapGenerator:
- name: the-map
  literals:
    - altGreeting=Good Morning!
    - enableRisky="false"

configMapGenerator では,他にも behavior: [create|replace|merge]generatorOptions など,オプションは用意されているけど,今回の Examples では使わなかった.ドキュメントを載せておく.

kubernetes-sigs.github.io

overlays/staging/kustomization.yaml

最後に overlays ディレクトリに置いた overlays/staging/kustomization.yaml を確認すると,リソース名にプレフィックスとサフィックスを設定したり,前回の記事で紹介した構文が使われている.同じくドキュメントを載せておく.

namePrefix: staging-
nameSuffix: -v1
commonLabels:
  variant: staging
  org: acmeCorporation
commonAnnotations:
  note: Hello, I am staging!
resources:
- ../../base
patchesStrategicMerge:
- map.yaml

kubernetes-sigs.github.io

3. kustomize build を実行する

さっそく kustomize build ${OVERLAYS}/staging を実行すると,以下のように表示される.長くなるため,ConfigMapDeployment に限定した(それでもまだ長いけど).ポイントは ConfigMap のリソース名と Deployment の参照先となり,どちらも staging-the-map-v1-k25m8k5k5m になっている.kustomize が自動的にリソース名を作り,Deployment にも適用してくれている.

apiVersion: v1
data:
  altGreeting: Have a pineapple!
  enableRisky: "true"
kind: ConfigMap
metadata:
  annotations:
    note: Hello, I am staging!
  labels:
    app: hello
    org: acmeCorporation
    variant: staging
  name: staging-the-map-v1-k25m8k5k5m

(中略)

apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
    note: Hello, I am staging!
  labels:
    app: hello
    org: acmeCorporation
    variant: staging
  name: staging-the-deployment-v1
spec:
  replicas: 3
  selector:
    matchLabels:
      app: hello
      deployment: hello
      org: acmeCorporation
      variant: staging
  template:
    metadata:
      annotations:
        note: Hello, I am staging!
      labels:
        app: hello
        deployment: hello
        org: acmeCorporation
        variant: staging
    spec:
      containers:
      - command:
        - /hello
        - --port=8080
        - --enableRiskyFeature=$(ENABLE_RISKY)
        env:
        - name: ALT_GREETING
          valueFrom:
            configMapKeyRef:
              key: altGreeting
              name: staging-the-map-v1-k25m8k5k5m
        - name: ENABLE_RISKY
          valueFrom:
            configMapKeyRef:
              key: enableRisky
              name: staging-the-map-v1-k25m8k5k5m
        image: monopole/hello:1
        name: the-container
        ports:
        - containerPort: 8080

4. ConfigMap の値を変更する

今度は overlays/staging/map.yaml の値 Have a pineapple!Have a kiwi! に変更する.そして,もう1度 kustomize build ${OVERLAYS}/staging を実行すると,以下のように表示される.ポイントは ConfigMap のリソース名が staging-the-map-v1-k25m8k5k5m から staging-the-map-v1-cd7kdh48fd に変わった点で,これは ConfigMap のリソースを新しく作り直したと言える.さらに Deployment の参照先も更新されているため,ローリングデプロイのような挙動となる.これは便利!

apiVersion: v1
data:
  altGreeting: Have a kiwi!
  enableRisky: "true"
kind: ConfigMap
metadata:
  annotations:
    note: Hello, I am staging!
  labels:
    app: hello
    org: acmeCorporation
    variant: staging
  name: staging-the-map-v1-cd7kdh48fd

(中略)

apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
    note: Hello, I am staging!
  labels:
    app: hello
    org: acmeCorporation
    variant: staging
  name: staging-the-deployment-v1
spec:
  replicas: 3
  selector:
    matchLabels:
      app: hello
      deployment: hello
      org: acmeCorporation
      variant: staging
  template:
    metadata:
      annotations:
        note: Hello, I am staging!
      labels:
        app: hello
        deployment: hello
        org: acmeCorporation
        variant: staging
    spec:
      containers:
      - command:
        - /hello
        - --port=8080
        - --enableRiskyFeature=$(ENABLE_RISKY)
        env:
        - name: ALT_GREETING
          valueFrom:
            configMapKeyRef:
              key: altGreeting
              name: staging-the-map-v1-cd7kdh48fd
        - name: ENABLE_RISKY
          valueFrom:
            configMapKeyRef:
              key: enableRisky
              name: staging-the-map-v1-cd7kdh48fd
        image: monopole/hello:1
        name: the-container
        ports:
        - containerPort: 8080

まとめ

今回は kustomizeExamples「configGeneration」を試した.configGeneration を使って ConfigMap リソースを作ると,リソース名にハッシュを含めて,結果的にローリングデプロイのような挙動を実現できるようになる.引き続き試していくぞー!

Kubernetes の YAML をカスタマイズする kustomize の基本を学べる Examples「helloWorld」

「Kubernetes 完全ガイド 第2版」「第14章 マニフェストの汎用化を行うオープンソースソフトウェア」を読んでいたら「第1版」では紹介されていなかった(正確には名前は載っていた)kustomize の解説が新しく追加されていた.本書を読みながら概要を理解したため,GitHub に公開されている kustomizeExamples を試しながら理解を深めていく.今回は「helloWorld」を試す.

github.com

前提

今回は Docker Desktop for Mac "Edge" を使って,以下の Kubernetes 環境で試した.kustomize コマンドは brew install kustomize で使えるようにした.なお,現在は kubectl と統合されて kubectl kustomize というコマンドも使えるけど,本書にコラムが載っている通り,バージョンが異なる.

$ kubectl version --short
Client Version: v1.18.6
Server Version: v1.18.6

$ kustomize version --short
{3.8.1  2020-07-16T05:11:04+01:00  }

Examples「helloWorld」とは?

kustomizeExamples「helloWorld」 は,kustomize の第一歩として,メタデータ関連のフィールドを更新したり,Overlay(オーバーレイ)を使って環境ごとにマニフェストを作ったり,リソースにパッチを適用する流れを学ぶ.さっそく試していく!

1. 事前準備

まず,作業ディレクトリを作って,変数 DEMO_HOME に設定しておく.手順書では mktemp コマンドを使っているけど,自由に変えられる.今回は自分用のマニフェストリポジトリにした.そして,もう1つ作っている base ディレクトリは,変換元になる「ベースマニフェスト」を置く場所として使う.

$ DEMO_HOME=~/helloWorld
$ BASE=${DEMO_HOME}/base
$ mkdir -p ${BASE}

次に GitHub に公開されているマニフェストを base ディレクトリにダウンロードする.tree コマンドの結果を見ればわかる通り,ConfigMap / Deployment / Service リソースのマニフェストをダウンロードする.もう1個は kustomize の設定ファイルとして kustomization.yaml もダウンロードする.kustomization.yaml に関しては後述する.

$ curl -s -o "${BASE}/#1.yaml" "https://raw.githubusercontent.com\
/kubernetes-sigs/kustomize\
/master/examples/helloWorld\
/{configMap,deployment,kustomization,service}.yaml"

$ tree ${DEMO_HOME}
~/helloWorld
└── base
    ├── configMap.yaml
    ├── deployment.yaml
    ├── kustomization.yaml
    └── service.yaml

2. kustomize build を実行する

ダウンロードした base/service.yaml の一部を以下に載せておく.base ディレクトリに置いてあるマニフェストを直接適用するのではなく,kustomize でビルドをするため,あくまで「ベースマニフェスト」になる.

kind: Service
apiVersion: v1
metadata:
  name: the-service
spec:
  selector:
    deployment: hello
  type: LoadBalancer
  ports:
  - protocol: TCP
    port: 8666
    targetPort: 8080

次に base/kustomization.yaml を確認する.構文として commonLabelsresources の概要を以下に載せておく.簡単に言えば「3種類のマニフェストに labelsselector を追加する」と言える.

  • commonLabels : ベースマニフェストに labelsselector を追加する
  • resources : kustomize build を実行するときに含めるリソースファイルのリストを指定する
commonLabels:
  app: hello

resources:
- deployment.yaml
- service.yaml
- configMap.yaml

さっそく kustomize build を実行すると,ビルドしたマニフェストが標準出力に表示される.今回は Service リソースを抜粋した.base/service.yaml と比較すると,新しく metadata.labels.appspec.selector.app が追加されている.

$ kustomize build ${BASE}

(中略)

apiVersion: v1
kind: Service
metadata:
  labels:
    app: hello
  name: the-service
spec:
  ports:
  - port: 8666
    protocol: TCP
    targetPort: 8080
  selector:
    app: hello
    deployment: hello
  type: LoadBalancer

(中略)

3. Overlay(オーバーレイ)を追加する

さらに kustomize の良さを学んでいくため,次はリソースにパッチを適用する「Overlay(オーバーレイ)」を試す.まず,overlays ディレクトリを作り,さらに overlays/staging ディレクトリと overlays/production ディレクトリを作っておく.

$ OVERLAYS=${DEMO_HOME}/overlays
$ mkdir -p ${OVERLAYS}/staging
$ mkdir -p ${OVERLAYS}/production

base ディレクトリと overlays ディレクトリの関係はザッと以下のようになる.このように構成することにより,共通的なマニフェストを base ディレクトリに置きつつ,環境ごとに異なる設定を overlays ディレクトリに置くことができる.kustomize 便利!

f:id:kakku22:20200817144209p:plain

次に overlays ディレクトリに置く「計4ファイル」を紹介する.

overlays/staging/kustomization.yaml

まず,staging 環境のための overlays/staging/kustomization.yaml を作る.新しく出てくる構文を紹介する.

  • namePrefix : リソース名の命名規則としてプレフィックスを追加する
  • commonAnnotations : ベースマニフェストに annotations を追加する
  • bases : resources と同じ(現在 bases は deprecated になっている)
  • patchesStrategicMerge : ベースマニフェストに適用する「パッチマニフェスト」のリストを指定する

よって,staging 環境ではリソース名に staging- プレフィックスを付けたり,labelsselectorannotations を追加する.

namePrefix: staging-
commonLabels:
  variant: staging
  org: acmeCorporation
commonAnnotations:
  note: Hello, I am staging!
bases:
- ../../base
patchesStrategicMerge:
- map.yaml

overlays/staging/map.yaml

次に patchesStrategicMerge に指定していた overlays/staging/map.yaml を作る.これは「パッチマニフェスト」として使う ConfigMap リソースのマニフェストとなり,altGreetingenableRisky の設定値を登録している.なお,kustomizeConfigMap を組み合わせた configMapGenerator 構文に関しては次回の記事に載せる予定!

apiVersion: v1
kind: ConfigMap
metadata:
  name: the-map
data:
  altGreeting: "Have a pineapple!"
  enableRisky: "true"

overlays/production/kustomization.yaml

staging 環境と同様に production 環境のための overlays/production/kustomization.yaml も作る.production 環境ではリソース名に production- プレフィックスを付ける.なお,今回の例では ConfigMap のパッチは適用せず,Deployment のパッチを適用する.

namePrefix: production-
commonLabels:
  variant: production
  org: acmeCorporation
commonAnnotations:
  note: Hello, I am production!
bases:
- ../../base
patchesStrategicMerge:
- deployment.yaml

overlays/production/deployment.yaml

最後に overlays/production/deployment.yaml を作る.一般的に production 環境は staging 環境よりも Pod を多く起動するため,以下のマニフェストでは Deployment リソースの replicas10 に更新している.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: the-deployment
spec:
  replicas: 10

最終的な構成を tree コマンドで確認すると,以下のようになる.

$ tree ${DEMO_HOME}
~/helloWorld
├── base
│   ├── configMap.yaml
│   ├── deployment.yaml
│   ├── kustomization.yaml
│   └── service.yaml
└── overlays
    ├── production
    │   ├── deployment.yaml
    │   └── kustomization.yaml
    └── staging
        ├── kustomization.yaml
        └── map.yaml

4. 環境ごとにマニフェストを適用する

Overlay の設定もしたため,最後にまた kustomize build コマンドを使って staging 環境と production 環境のマニフェストを確認する.今回はマニフェストを kubectl apply -f - にパイプすることにより,直接適用もする.

# staging
$ kustomize build ${OVERLAYS}/staging

$ kustomize build $OVERLAYS/staging | kubectl apply -f -
configmap/staging-the-map created
service/staging-the-service created
deployment.apps/staging-the-deployment created

# production
$ kustomize build ${OVERLAYS}/production

$ kustomize build $OVERLAYS/production | kubectl apply -f -
configmap/production-the-map created
service/production-the-service created
deployment.apps/production-the-deployment created

✅ プレフィックスを確認する

例えば ConfigMap を確認すると,リソース名に staging-production- が追加されている!

$ kubectl get configmaps
NAME                 DATA   AGE
production-the-map   2      5s
staging-the-map      2      20s

✅ アノテーションを確認する

例えば Pod を確認すると,アノテーションが追加されている!

$ kubectl describe pods staging-the-deployment-6cd65cfc7f-2lcts | grep Annotations
Annotations:  note: Hello, I am staging!

$ kubectl describe pods production-the-deployment-bb7fd8b65-29b52 | grep Annotations
Annotations:  note: Hello, I am production!

✅ ConfigMap のパッチを確認する

kubectl describe configmapsConfigMap の値を確認する.

$ kubectl describe configmaps staging-the-map
Name:         staging-the-map
Namespace:    default
Labels:       app=hello
              org=acmeCorporation
              variant=staging
Annotations:  note: Hello, I am staging!

Data
====
altGreeting:
----
Have a pineapple!
enableRisky:
----
true
Events:  <none>

altGreetingenableRisky の値を base/configMap.yaml と比較すると,staging 環境では値を書き換えられている!

Key base staging production
altGreeting Good Morning! Have a pineapple! Good Morning!
enableRisky false true false

✅ Deployment のレプリカ数を確認する

kubectl describe deploymentsDeployment のレプリカ数を確認する.production 環境ではレプリカ数を更新できている!

$ kubectl describe deployments | egrep 'Name:|Replicas:'
Name:                   production-the-deployment
Replicas:               10 desired | 10 updated | 10 total | 10 available | 0 unavailable
Name:                   staging-the-deployment
Replicas:               3 desired | 3 updated | 3 total | 3 available | 0 unavailable

5. リソースを削除する

手順には入っていなかったけど,試したらリソースを削除しておく.

$ kustomize build ${OVERLAYS}/staging | kubectl delete -f -
configmap "staging-the-map" deleted
service "staging-the-service" deleted
deployment.apps "staging-the-deployment" deleted

$ kustomize build ${OVERLAYS}/production | kubectl delete -f -
configmap "production-the-map" deleted
service "production-the-service" deleted
deployment.apps "production-the-deployment" deleted

まとめ

「Kubernetes 完全ガイド 第2版」で解説が新しく追加されていた kustomize を試した.GitHub に公開されている Examples「helloWorld」kustomize の基本を学べてオススメ!なお,今回は kustomization.yaml の構文として以下を使った.詳しくはドキュメントを見てみてもらえればと!

  • bases
  • commonAnnotations
  • commonLabels
  • namePrefix
  • patchesStrategicMerge
  • resources

kubernetes-sigs.github.io

Kubernetes でバイナリを ConfigMap (binaryData) に登録する

今年の4月頃に「Kubernetes 完全ガイド」を読み終えたけど,まだ書評を書いていなかった.そしたら8月に「Kubernetes 完全ガイド 第2版」が出版されたため,さっそく購入して,読み直している.読みながら気になった機能を試していく.今回は ConfigMap にする.

Kubernetes完全ガイド 第2版 (Top Gear)

Kubernetes完全ガイド 第2版 (Top Gear)

  • 作者:⻘⼭ 真也
  • 発売日: 2020/08/07
  • メディア: 単行本(ソフトカバー)

ConfigMap (binaryData)

「第7章 : Config & Storage APIs カテゴリ」ConfigMap を読み直していたら,テキスト (UTF-8) だけではなく「バイナリ」を登録する内容が新しく追加されていた.拡張子 .jpg など画像ファイルを Base64 でエンコードして,nginx コンテナから HTML と画像ファイルを配信するというサンプルだった.今まで ConfigMap「バイナリ」を登録したことがなく,動作確認のために「Kubernetes 完全ガイド 第2版」を参考にしながら試した.なお,今回試した Kubernetes 環境は以下の通り.

$ kubectl version --short
Client Version: v1.18.6
Server Version: v1.18.6

通常の Docker Desktop for Mac だと Kubernetes v1.16 になるけど,Docker Desktop for Mac "Edge" を使えば,Kubernetes v1.18 を使えるようになる.個人的には Edge を使っている.

docs.docker.com

ConfigMap を作成する

まず,マニフェストを書かずに kubectl create で直接 ConfigMap を作成する.今回は --from-literal オプションで HTML をテキストとして設定し,--from-file オプションで画像を設定している.画像のフィールド名は cat.png だけど,実際には白い猫アイコン (cat-white.png) を設定している.

$ kubectl create configmap sandbox-configmap-binary \
  --save-config \
  --from-literal=index.html='Hello, <img src="./cat.png">' \
  --from-file=cat.png=cat-white.png
configmap/sandbox-configmap-binary created

コマンド例はドキュメントにも載っている.

kubernetes.io

マニフェスト管理をする場合は,Base64 でエンコードをする必要はなく,kubectl create--dry-run オプションと --output オプションを追加すれば,マニフェストにリダイレクトできる.

$ kubectl create configmap sandbox-configmap-binary \
  --save-config \
  --from-literal=index.html='Hello, <img src="./cat.png">' \
  --from-file=cat.png=cat-white.png \
  --dry-run=client \
  --output=yaml > sandbox-configmap-binary.yaml

data フィールドと binaryData フィールド

リダイレクトした sandbox-configmap-binary.yaml を確認すると,以下のようにテキスト (UTF-8) の値は data フィールドに設定されて,バイナリは binaryData フィールドに設定される.なお,エンコードされた内容は長いので xxxxx と省略した.

apiVersion: v1
binaryData:
  cat.png: xxxxx
data:
  index.html: Hello, <img src="./cat.png">
kind: ConfigMap
metadata:
  creationTimestamp: null
  name: sandbox-configmap-binary

ConfigMap に変化はないけど,マニフェストを kubectl apply で適用しておく.

$ kubectl apply -f sandbox-configmap-binary.yaml
configmap/sandbox-configmap-binary configured

Pod を作成する

今度は ConfigMap を Volume マウントした nginx の Pod マニフェスト sandbox-configmap-binary-nginx.yaml を書く.目的としては nginx から ConfigMap に登録した index.htmlcat.png を配信できるようにする.

apiVersion: v1
kind: Pod
metadata:
  name: sandbox-configmap-binary-nginx
spec:
  containers:
  - name: nginx
    image: nginx:1.18
    volumeMounts:
    - name: config-volume
      mountPath: /usr/share/nginx/html
  volumes:
  - name: config-volume
    configMap:
      name: sandbox-configmap-binary

マニフェストを kubectl apply で適用し,ポートフォワードもしておく.

$ kubectl apply -f sandbox-configmap-binary-nginx.yaml
pod/sandbox-configmap-binary-nginx created

$ kubectl port-forward sandbox-configmap-binary-nginx 8888:80

さっそく http://localhost:8888/ にアクセスをすると,期待通りに index.htmlcat.png を表示できた.なお,白い猫アイコンと次に使う黒い猫アイコンは Icons8 から取得した.

f:id:kakku22:20200814214221p:plain

ConfigMap を更新する

今度は ConfigMap に登録した cat.png を 白い猫アイコン (cat-white.png) から黒い猫アイコン (cat-black.png) に変えて,マニフェストを適用する.

$ kubectl create configmap sandbox-configmap-binary \
  --save-config \
  --from-literal=index.html='Hello, <img src="./cat.png">' \
  --from-file=cat.png=cat-black.png \
  --dry-run=client \
  --output=yaml > sandbox-configmap-binary.yaml

$ kubectl apply -f sandbox-configmap-binary.yaml
configmap/sandbox-configmap-binary configured

ConfigMap を Volume マウントしている場合は,自動的に反映されるため,ブラウザを更新すると黒い猫アイコンに変わった.

f:id:kakku22:20200814214233p:plain

まとめ

8月に出版された「Kubernetes 完全ガイド 第2版」を読みながら ConfigMapbinaryData フィールドを試した.実際のワークロードでは画像を Base64 でエンコードする場面は少ないかもしれないけど,試せて良かった.引き続き,読み直していくぞ!

Kubernetes完全ガイド 第2版 (Top Gear)

Kubernetes完全ガイド 第2版 (Top Gear)

  • 作者:⻘⼭ 真也
  • 発売日: 2020/08/07
  • メディア: 単行本(ソフトカバー)