UbuntuでHomebrewを使う

概要

こちらの記事にて、HomebrewがLinuxに対応したことを知り、開発機のUbuntu18に導入してみました。Homebrew 2.0の公式ページ に記載のワンライナーで問題なく導入できました。その際の手順のメモになります。

インストール作業時のログ

$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"

※上記のコマンドを実行すると、 .profile の設定などの以降の必要な設定が親切に出力されます。

これまでは、 brew install を使った手順の際は、 apt に読み替えていたので、そのあたりが解消されると嬉しいです。暫く使ってみようと思います。

(追記) $HOME/Brewfile を作成し、 brew bundle することで、Brewfileにて定義のパッケージをまとめてインストールしてくれるようですので、導入パッケージの管理も段階的にこちらに寄せていこうと思います。(今までは、ansibleで行っていました)

$ cat $HOME/Brewfile
brew 'exa'
brew 'k9s'

2022.04. 追記:アンインストール作業時のログ

Home Brewのアンインストールに際しては、Githubの公式リポジトリにてワンライナーが提供しています。 開発環境の再構築をする必要があったため↑の手順を使ってみましたが問題なく実行できました。

GKE : ingressをpodのreadinessProbeと連携させる際の注意点

本記事の要点

GKE上で ingress のヘルスチェックに readinessProbe を利用したい場合、以下の3つのPort番号が合致するよう設定してください。ingress の新規作成時に(1)と(2)が合致しない場合、ReadinessProbe を設定していたとしても無視され、標準の / に対するヘルスチェックルールが生成され、L7LBに適用されます。

  1. NodePort 内に記載の targetPort
  2. deployment内に記載の containerPort
  3. deployment内のReadinessProbeに記載の port

Document上の該当箇所

Configure an HTTP readiness probe. Serve a response with an HTTP 200 status to GET requests on the path specified by the readiness probe. The Service exposed through an Ingress must point to the same container port on which the readiness probe is enabled.

GKE Ingress for HTTP(S) load balancing : Health checks

ingress-gceのコード上で実際の条件判定を実施していると思われる箇所

※ 2021.01.29. 現在 https://github.com/kubernetes/ingress-gce/blob/f1355599d82a164c9f6eb98d2c78b214d64cd329/pkg/controller/translator/translator.go#L392-L393

検証方法

  • 以下の3種のmanifest fileを deployment -> nodePort -> ingress の順にデプロイすると、ヘルスチェックの対象パスがデフォルトの / ではなく、readinessProbe で指定したパスになる。(画像1)
  • ↑の確認後デプロイしたk8sリソースを削除したうえで、deployment 内の containerPort を設定の行を削除、再度、deployment -> nodePort -> ingress の順にデプロイすると、ヘルスチェックの対象パスが / になることが確認できる。

画像1 : readinessProbe内のパスが正しくGCP上のヘルスチェックにコピーされた例 f:id:smatsuzaki:20200318210346p:plain

サンプルマニフェスト

deployment

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: nginx
  name: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  strategy: {}
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx
        name: nginx
        ports:
          - containerPort: 80
            protocol: TCP
        readinessProbe:
          httpGet:
            path: /index.html
            port: 80
          failureThreshold: 3
          initialDelaySeconds: 30
          periodSeconds: 10
          timeoutSeconds: 3

nodePort

apiVersion: v1
kind: Service
metadata:
  name: nodeport-test
  annotations:
    # Container-native Load Balacingを有効にすることをingress-gceに通知
    # GCP上に専用のNetwork Endpoint Group(NEG) が生成される
    # doc https://cloud.google.com/kubernetes-engine/docs/how-to/container-native-load-balancing
    # src https://github.com/kubernetes/ingress-gce/blob/fbc1bf99d8e557fb3ece891987f977fa2d139048/pkg/annotations/service.go#L37-L45
    cloud.google.com/neg: '{"ingress": true}'
spec:
  type: NodePort
  ports:
    - name: http-port
      protocol: TCP
      port: 80
      targetPort: 80
  selector:
    app: nginx

ingress

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: ingress-test
  annotations:
spec:
  rules:
  - http:
      paths:
      - backend:
          serviceName: nodeport-test
          servicePort: 80

参考:k8sのProbeは 302 を許容するが、GCE ingress200 以外は全てNGと判定する

jqでJSONオブジェクト/配列内の要素を一行で表示したい

TL;DR

jq--compact-output / -c オプションを使うことで、JSON 内の取得した要素を一行にまとめて表示することができる。

実行例

サンプルファイル

$ cat test.json
{
  "country_list": [ "japan", "china", "us" ],
  "num_list": [ 123, 456, 789 ],
  "mix_list": [ "red", 456, null, true ],
  "array_list": [ [ 89, 89 ], [ 46, 49 ], [ 91, 22 ] ],
  "object_list": [
    { "name": "Nick", "age": 18 },
    { "name": "Andrew", "age": 49 }
  ]
}

配列( JSONArray )の場合

# オプション無し
$ cat test.json | jq .array_list[]
[
  89,
  89
]
[
  46,
  49
]
[
  91,
  22
]

# オプション有り
$ cat test.json | jq --compact-output .array_list[]
[89,89]
[46,49]
[91,22]

オブジェクト( JSONObject )の場合

$ cat test.json | jq -c .object_list[]
{"name":"Nick","age":18}
{"name":"Andrew","age":49}

オプションの詳細

jq 1.5 manual

--compact-output / -c:

By default, jq pretty-prints JSON output. Using this option will result in more compact output by instead putting each JSON object on a single line.

Ubuntuでの開発環境を改善する

Ubuntuで開発環境の構築を行う際に実施した事項のメモです。

環境

$ cat /etc/os-release | grep VERSION
VERSION="18.04.4 LTS (Bionic Beaver)"
VERSION_ID="18.04"
VERSION_CODENAME=bionic

TIPS

1. GNOME TerminalでのThemeを変更

デフォルトのテーマだと、やや見づらいので、 Mayccoll / Gogh というカラーテーマ集で提供されているテーマに変更する。

※ 2020年3月現在、 README.md にて公開されている手順に従っています。ので、将来的に別の手順になっている可能性が有ります。

# Pre-Install
$ sudo apt-get install dconf-cli uuid-runtime

# Install
$  bash -c  "$(wget -qO- https://git.io/vQgMr)"

# 上記のワンライナーを走らせると、以下のPromptが出て入力待ちとなるので、
# 利用したいThemeの番号を入力すると適用されます
# 自分の場合は、 "Vs Code Dark Plus" が使いたかったので、 "184" を入力しENTER
Usage : Enter Desired Themes Numbers (OPTIONS) Separated By A Blank Space
        Press ENTER without options to Exit

Enter OPTION(S) : 

# ワンライナー終了後、GNOME TERMINALを終了し、再度起動するとThemaが適用され、色が変わっていることが確認できます

2. IntelliJ IDEAで使用のフォントを変更

プログラミング用に最適化された rictyフォント に変更します。

まずaptを使ってインストールします。

$ apt install fonts-ricty-diminished

Intellij IDEAの設定画面にてフォントを変更します。

f:id:smatsuzaki:20200301110152p:plain

3. IntelliJ IDEAを日本語化

4. Maven Helper PluginをIntelliJ IDEAに導入

plugins.jetbrains.com

4. Homebrewの追加

UbuntuでHomebrewを使う - まつざっきブログ

『Database Internals』Chapter1の読書メモ

オライリー社にて2019年に出版の『Database Internals』のChapter1を読んだ際の読書メモです。

Database Internals: A Deep Dive into How Distributed Data Systems Work

Database Internals: A Deep Dive into How Distributed Data Systems Work

  • 作者:Petrov, Alex
  • 発売日: 2019/10/15
  • メディア: ペーパーバック

Chapter1. Introcution and Overview

第1章で話すこと

  • DBMS Architectureの話
  • メモリvsディスクベースDBの話
  • 行志向vs列志向DBの話
  • バッファリング、不変データ、オーダリングなどのパフォーマンス最適化技術の話

DBMS Architecture

  • 以下のコンポーネント図に従い、各コンポーネントの説明がなされていく
    f:id:smatsuzaki:20200223112618p:plain:w300
    (Database Internals, Alex Petrov, 2019, Chapter1, Figure 1-1. Architecure of database management system)
  • Storage Engine の責務とそれ以外の部分の責務は頭の中で整理して明快にしておきたい
  • トランザクションとロックの責務はconcurrency controlである」的な話をしていて適格な要約だと思った。詳細は第5章で語られるとのこと。k8sでもお馴染みの楽観的ロックや、MVCCなんかの話題が出てくる模様。ここは平行システムをやるときの必須科目なので理解したい。セマフォとかクリティカルセクションとかも出てくるんだろうか

Memory Versus Disk-Based DBMS

  • DBレコードがon memoryの場合、プログラミング言語から変数として(serializeせずに)操作したり、ポインタを使ったアクセスできて便利とのこと。そうするとRedisの場合は内部的にHashMapを持って終わりなのかなと想像した。文献探して答えあわせしたい。
  • ディスクアクセスのコストを最適化したい場合はB-treeが最適とのことだけど、これは例えばHashMapだと挿入や削除の計算量が多大になってしまうということだろうか。

Column Versus Row-oriented DBMS

Row-Oriented Data Layout / Column-Oriented Data Layout

  • 行志向と列志向の差はDisk上に実データを書き込むときに、「行」という単位でデータを同じセクタにできるだけ集中させて、局所性(locality) を持たせるのか、あるいは「列」という単位で同じことを行うのか?という違いから説明できるという話だと理解した
  • あと、行は水平的(horizontal)な概念で、列は垂直的(vertical)な概念というのは直感的に理解しやすいのでいい形容だと思う
    行志向DBの例として、MonetDB, Vertica などがあげられているがどれも初めて聞く名前

distinctions and optimizations

行志向と列志向の特性の差は、データのstore方法以外の観点でも語ることができる、とのこと。観点の具体例として、

  • キャッシュの話
  • ディスク領域資源の利用効率性
  • アクセスパターンが行なのか列なのかで最適なプロダクトが変わってくる話

など

Wide Column Stores

  • Cloud Bigtable@GCPApache Cassandra などのように、カラムファミリをもつデータベースは Wide columns store といって、普通の行志向データベースとは明確に別のものとして分類されるとのこと

  • 参考文献内にあった、2006年に書かれたBigtableの論文が面白そうだった。時間を見つけて読みたい

Data Files and Index Files

  • この辺りからRDBMSの実装の話題が増えてきて楽しくなる

  • 「モダンなDB Storageの大半はDELETE命令に対し、データをストレージ上から完全に削除するということはしない、代わりに単に deletion marker を置く」という話を聞いてApache CassandraTombstone を思い出したり。deletion and garvage collector model は頻出パターンっぽいなぁ。 k8sにもGarvage Collectorは存在する。改修されるのは、メモリではなくリソースオブジェクトだが。

  • RDBMSの話に戻ると要点は

    • data fileとindex fileは通常別々に管理される
    • fileはblock deviceサイズを持つpageに分割される? ← page が具体的にどのようなものなのか要確認

Bufering, Immutability, and Ordering

Buffering

  • LinuxにおけるディスクI/Oは通常ブロック単位で行われるため、WRITEするときに一度バッファメモリに書き込み命令をバッファリングし、1ブロック分まとめてディスクへの書き込みを実行すると、ディスクI/Oに要する時間が?最小化できる という話。目的は異なるが、MySQLのダブルライトバッファ[1] を連想した。

  • 他にはB-treeと2コンポーネントLSM treeではバッファリングの考え方がだいぶ違うという話とか

Mutability (or immutability)

  • Immutable の定義については、Javaとかで言われる Immutable Object の考え方とほぼ同様な話?
  • レコードをimmutable objectとして実装したい場合、 LSM tree みたいにアペンドオンリー方式で実装するやり方と、 copy-on-write で実現するやり方があるとのこと

Odering

  • キーと同じ並びでディスク上にデータをシーケンシャルに格納していくか否かという話題
  • 後者(シーケンシャルではなくばらばらのDisk上の領域にデータを格納する)がWRITE処理が早いこともあるとのこと。具体例としては、アペンドオンリーな方式の場合が例示されていた

[1] こちらの資料のP23がわかりやすいです https://www.slideshare.net/IIJ_PR/iomemoryatomic-write

gitのbranchの実体はポインタであるという話

勘違いしていたので、メモ。

  • gitにおける branch複数のcommitオブジェクトの集合体 だと思っていたが、こちらの記事 を読んで理解が誤っていたことに気が付いた
  • 実際は、gitにおける branch は任意のcommitオブジェクトの(アドレスを)指し示すポインターとして機能している

gitのデータ構造

恐らく以下のようになっている

  • HEAD はbranchに対するポインタ
  • branch はCommitオブジェクトに対するポインタ
  • Commitオブジェクト はSnapshot` [1] に対するポインタ
  • Snapshot は変更されたファイルに対応するblob全てへのポインタを持つ [2]

f:id:smatsuzaki:20200223103636p:plain:w350

公式ページの記載

gitの公式ページ でも以下のような記載があり、branch==ポインターであることが明示されている

"A branch in Git is simply a lightweight movable pointer to one of these commits."

上記の通りbranchは "movable" なポインターであり、新しくcommitを行う度に、branchが指し示すcommitオブジェクトのアドレスも、その新しく作られたcommitオブジェクトを指し示すよう、更新される

"The default branch name in Git is master. As you start making commits, you’re given a master branch that points to the last commit you made. "

参考

脚注

[1] 公式ページこちらの図 において "92ec2" と呼ばれているデータ構造のこと
[2] 公式ページでは、blobsは "each representing the contents of one of the three files" と説明されています。更新後のファイルの完全なデータ(差分ではなく完全バックアップといいますか..)だと推測しますが、詳細未確認です

cloudbuildでビルドしたgo言語ファイルがdockerのubuntuイメージ上で実行できない

問題

cloudbuildでビルドしたGo言語のプログラム(ELF形式)を、dockerコンテナ( ubuntu:latest )上で実行しようとしすると実行に失敗する。

# file myapp
myapp: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-, not stripped

# ./myapp
bash: ./myapp: No such file or directory

原因

ELFファイルを readelf すると以下のように、 ubuntu:latest 上には存在しない ld-musl-x86_64 に対しinternal linkが張られていることがわかる。

# readelf -a ./myapp  | grep Requesting
      [Requesting program interpreter: /lib/ld-musl-x86_64.so.1]

go言語のビルド設定である、 cloudbuild.yaml のビルド設定は以下のようにしていた。以下の書き方の場合、明示的にタグを指定していないため latest タグのついたイメージが取得される。

  - name: 'gcr.io/cloud-builders/go'
    id: 'GO_BUILD'
    args: ['install', '.']
    env:
      - 'PROJECT_ROOT=github.com/shinmatsuzaki/myapp'

gcr.io/cloud-builders/go の場合、latest タグはalpineベースのイメージに対し付与される。 そのために、go言語のビルドが実行される際、ELFに対しalpine linux上のライブラリがリンクされる。同名のライブラリがubuntuイメージ上にない場合、ELFの実行に失敗する。

$ gcloud container images list-tags gcr.io/cloud-builders/go | head -4
DIGEST        TAGS           TIMESTAMP
dfabdc5d6ad7  debian         2020-02-15T18:23:35
c3bf65790cab  alpine,latest  2020-02-15T18:23:12

対処

不足するライブラリをubuntuイメージにインストールする方向で、Dockerfileに RUN apt update && apt install -y musl-dev を追加。

※以下の記事のように、 cloudbuild.yaml でgoのbuildに指定するイメージとして gcr.io/cloud-builders/go:debian を指定する方法でも問題を解消できると思います。

参考

gccによるC言語ファイルのコンパイルの流れ

f:id:smatsuzaki:20200216101106p:plain

memo

  • オブジェクトファイル中には、実行コードや変数値のデータなどが格納されているが、この段階では、まだ、メモリ上の固定アドレスに割り当てられていない。実際に固定アドレスが割り当てられるのは、リンカによるリンクを行う際で、このアドレス割り当て作業のことを 再配置 ( relocation ) と呼ぶ。

  • オブジェクトファイル内の実行コードや変数値はこれを可能にするために、実際に自身がメモリ上のどこに配置されても問題なく動作するように設計されている。この状態を 再配置可能 ( relocatable ) (な状態)と呼ぶ。同様にオブジェクトファイルは、 再配置可能ファイル ( relocatable file )と呼称されることがある。[1] 

  • ELFファイル中のシンボルテーブルは、nm(1) を使用することで参照が可能。

[1] 詳細は、『リンカ・ローダ実践開発テクニック』 P26 を参照

Dockerコンテナが専用namespaceに属していることを確認する

概要

  • dockerコンテナによるLinux上の各種リソースの隔離[1] は、linuxのnamespace(名前空間)という機能を使って実現されています [2]
  • 実際にdockerコンテナを作成し、defautの名前空間とは異なる名前空間がdocker用に作成されることを確認します

ログ

# 環境
$ uname -r
5.3.0-28-generic

$ docker -v
Docker version 19.03.5, build 633a0ea838

# コンテナ起動
$ docker run -d centos tail -f /dev/null
024357195f98466deca2c6e2d6e6db24ac8efc0d7b1a442fcec3249c4193e434

# containerのPID確認
$ docker inspect 024357195f98 --format '{{.State.Pid}}'
3799

# docker containerがdefaultのnsとは別のNamespaceに所属していることを確認
$ sudo ls -l /proc/3799/ns/
合計 0
lrwxrwxrwx 1 root root 0  215 23:49 cgroup -> 'cgroup:[4026531835]'
lrwxrwxrwx 1 root root 0  215 23:49 ipc -> 'ipc:[4026532396]'
lrwxrwxrwx 1 root root 0  215 23:49 mnt -> 'mnt:[4026532394]'
lrwxrwxrwx 1 root root 0  215 23:47 net -> 'net:[4026532399]'
lrwxrwxrwx 1 root root 0  215 23:49 pid -> 'pid:[4026532397]'
lrwxrwxrwx 1 root root 0  215 23:49 pid_for_children -> 'pid:[4026532397]'
lrwxrwxrwx 1 root root 0  215 23:49 user -> 'user:[4026531837]'
lrwxrwxrwx 1 root root 0  215 23:49 uts -> 'uts:[4026532395]'

$ sudo ls -l /proc/1/ns/
合計 0
lrwxrwxrwx 1 root root 0  215 23:49 cgroup -> 'cgroup:[4026531835]'
lrwxrwxrwx 1 root root 0  215 23:49 ipc -> 'ipc:[4026531839]'
lrwxrwxrwx 1 root root 0  215 23:49 mnt -> 'mnt:[4026531840]'
lrwxrwxrwx 1 root root 0  215 23:49 net -> 'net:[4026532008]'
lrwxrwxrwx 1 root root 0  215 23:49 pid -> 'pid:[4026531836]'
lrwxrwxrwx 1 root root 0  215 23:49 pid_for_children -> 'pid:[4026531836]'
lrwxrwxrwx 1 root root 0  215 23:49 user -> 'user:[4026531837]'
lrwxrwxrwx 1 root root 0  215 23:49 uts -> 'uts:[4026531838]'

# container用のnetwork namespaceの中でip addr show
$  sudo nsenter -t 3799 -n ip addr show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever

8: eth0@if9: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever

# defaultのnamespaceの中にはeth0は存在しない
$ ip addr show eth0
Device "eth0" does not exist.

参考: containerdが実際にnamespaceを作成していることを strace で確認する

# containerdのPID確認
$ systemctl status containerd
● containerd.service - containerd container runtime
()
 Main PID: 1351 (containerd)()

# straceをcontainerd processにアタッチ
$ sudo strace -ff -e unshare -p 1351

# 再度 centos containerを作成すると...
$ docker run -d centos tail -f /dev/null

# straceのSTDOUTに以下のように出力される [3]
strace: Process 1351 attached with 20 threads

()
[pid  5004] unshare(CLONE_NEWNS|CLONE_NEWUTS|CLONE_NEWIPC|CLONE_NEWNET|CLONE_NEWPID) = 0
()

参考: ip netns list してもdockerコンテナ用に作成されたnamespaceが表示されないのはなぜか

脚注

[1] 「隔離」という言葉の具体的な意味については、以下を参照ください ※過去に開催の社内勉強会のリンクです
kubernetesソースコードリーディング 第4回 - APC 技術ブログ

[2] Kernelレベルの実装については、以下にて言及されています

[3] unshareシステムコールのmanページ
UNSHARE

Go言語入門:変数の宣言

プログラミング言語Go』(初版)の該当箇所を読んだまとめになります。 ページ番号は同書内のページ番号です。

4種類の型

  • Go言語の型は以下の4種類(P57)
    • 基本型 (basic type)
    • 合成型 (aggregate type)
    • 参照型 (reference type)
    • インターフェース型 (interface type)

変数の宣言

  • var name type = expression が基本形(P32)

    • type または expression(式) の省略が可能
      • type を省略した場合、右辺の expression(式) の評価結果に従い、型が推論される
      • expression を省略の場合、その型のゼロ値で変数が初期化される(つまり何らかの値の入った状態になる)
    • Go Playgound <- 簡単なサンプルコード@Go Pplayground
  • 省略変数宣言( short variable declaration )

    • name := expression(式) が基本形、右辺の expression(式) の評価結果に従い型推論が実行される
    • var i = 1i := 1 は同じ結果になる? (どちらも型推論が実行される)
  • ポインタ宣言

  • new関数
    • p := new(int) みたいなことができる
    • ↑のpは var p *int と同様に参照型であり、宣言時に生成の無名のint変数へのポインタを保持する(P38)

余談:expression(式) とは何か

Go言語入門:string型の使い方の確認

Go Playground - The Go Programming Language

package main

import (
    "fmt"
    "reflect"
)

func main() {

    fmt.Printf("Go言語におけるstring型は「不変(immutable)なバイト型のスライス」らしい\n")
    s := "hello, world" // 宣言

    // immutable==再代入不可なので以下は失敗する
    // s[0] = "a"

    fmt.Printf("以下はルーン数ではなく、バイト数を取得する : %d\n", len(s))
    fmt.Printf("バイト型のスライスの要素を取得するとuint8型の数値が得られる : %d\n", s[0])
    fmt.Printf("string()を使うとアルファベット(string型)に変換できる : %s\n", string(s[0]))
 
    // 実際にstring型になっていることの確認
    fmt.Println(reflect.TypeOf(string(s[0])))

    // イテレート例
    for i := 0; i < len(s); i++ {
        fmt.Println(string(s[i]))
    }
 
    // 単に全てを出力するだけなら
    fmt.Println(s[:len(s)]) // 明示的に末尾を指定
    fmt.Println(s[:])       // s[:]とすると配列全体が参照される
 
}

kubernetesのpod内でstraceをrunning processにアタッチしたい

問題

kubernetesのpod内で strace コマンドの -p オプションを使い、実行中のプロセスにアタッチしようとすると以下のエラーが出る。

# strace -p 1
strace: attach: ptrace(PTRACE_SEIZE, 1): Operation not permitted

原因

strace が内部的に利用している ptrace システムコールのコンテナ内での実行が、セキュリティ担保のためデフォルトでは禁止されている。

対処

以下のように、 spec.containers.securityContext.capabilities にて ptrace の実行を許可するとコンテナ内での srace の実行が可能になる。
※ 「原因」に記載の理由から、デバッグしたい時のみ一次的に追加するのがベターかと思います。

apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    run: nginx
  name: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      run: nginx
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        run: nginx
    spec:
      containers:
      - image: nginx
        name: nginx
        # DEBUG用
        securityContext:
          capabilities:
            add:
            - SYS_PTRACE
        resources: {}
status: {}

その他

dockerの場合は --cap-add sys_ptracedocker run 実行の際に付与することで、同様に実行可能になる。

qiita.com

『はじめての設計をやり抜くための本』の読書メモ

ずっと以前に買って積み本にしてしまっていたのですが、 昨晩に「ちょっと読んでみたい気分かも」という感じになりざっと流し読みました。

2008年に初版発行ということで、Strutsフレームワークの話題が沢山出てきたりと、 今となっては古さを感じる部分もあるのですが、一方、 「ここについては今も変わらないないなー」であったり、「なるはど、これはこういう経緯だったんだ!」[1] と思わされる記述も多く、読んでいて楽しかったです。

第5章『アーキテクチャの目的』では、良いアーキテクチャの効用として、 - 大きいシステムを小さく開発することを可能にする。それにより保守性が向上する - 要件を実現するために、どんな粒度でどの部品を作るべきか?という基本構造を提供することで、 網羅的に機能開発し要件を満たすことを容易にする の2つが重要とかかれていて、以前からあった「アーキテクチャって要するに何だろう?フレームワークとの違いは?」 みたいなもやもやがだいぶ減った気がしました。参考書として挙げられている、"Patterns of Enterprise Application Architecture" も挑戦してみたいと思います。

ソフトウェア設計に関して、広い範囲を外観できてよかったです。 類書を読んでより理解を深めたいと思います。

[1] 最近Javaを学び始めたためか、「どういう経緯でこういう言葉があるのか/こういう仕様になっているのかよくわからない。。」ということばしばしばあります。歴史的な経緯を知ると「なるほど!」となることが多かったり。

はじめての設計をやり抜くための本 概念モデリングからアプリケーション、データベース、アーキテクチャの設計まで (エンジニア道場)

『GPUを支える技術』の読書メモ

第2章

  • ゲームの話題多めで楽しい。プレステとかセガサターンとか世代的に懐かしい。バーチャファイターとかFF7ありましたねー。
  • スプライト技術は以下の動画の悪魔城の箇所を見たらイメージがついた。やはり実物を見るとイメージしやすい www.nicovideo.jp

第3章

  • 法線マッピングがめっちゃ面白い。ものの凹凸をモデリングしなくても、光の反射のシミュレーションして描画するだけでものの凹凸があるように見えてしまう。P89に適用前と適用後の画像が例示されているが、適用されると画像の解像度?がものすごく高くなったように見える。リアルな質感
  • テクスチャ = 光学迷彩なのでは、と。
  • デプスシャドウの考え方も面白い。クォータビューの起点となる「視点」と「光源」が存在する的な
  • HDRレンダリングは、落合陽一さんが著書で『我々は目というモニタで現実世界をバーチャルに見ている』とおっしゃっていたのを思い出した。それをエミュレートしようという発想に見える。
  • GPUとスパコンについての東京大学情報基盤センターの資料。よくまとまっていて素敵

第4章

  • CPUとGPUは名前は似ているが、ハードウェア的に仕組みが結構違う
  • GPUプログラミングはメモリの使い分けとかプリエンプションとか気にしないといけないことが多く、全体的にレイヤ低めな印象

コンウェイの法則の論文の解説記事

blog.acolyer.org


以下、自分用メモ

ピラミッド組織と階層的な移譲行為

  • 上位の人が全体的な方針を決める
  • 下位の人は上位方針に従い、細部の詳細を設計していく(設計行為の移譲)
  • そうすることで、上位と下位がcoherentな状態を作る
    • システムの構成要素が互いに有機的に結合される状態が維持される

システムはコミュニケーションの産物である

  • 移譲行為の連鎖を通じて作られる「設計されたシステム」は組織内コミュニケーションの産物である
    • だから、設計を営む組織もまたシステムとみなすことができる
    • システム == 全体と部分の構造を持ち有機的に結合された系
  • デザイン組織と設計されたシステムの間には写像?関係が成り立つ

設計における「移譲」の意味

  • 誰かが上位の設計として決めた事柄は、別の誰かの下位の設計時に選択可能なオプションの幅を狭めてしまう
  • だから慎重にしっかり意識を合わせながらやらないといけない
    • そのためには、上位者と下位者がダイレクトに密にコミュケーションを取ることが必要である
    • 大人数組織はコミュケーションフローの構造故にそういったコミュニケーションチャンネルをつくることが難しい

少数精鋭の機能するチームは増員の誘惑により破壊される

  • 基本的には少数精鋭で小さなものを熟考してしっかりコミュニケーションをとりながら作る方が上手くいく
  • でも、マネジメント観点で見た時に「人を増やせばもっと早くできる」という誘惑があり、それは抗い難い
    • そうしてエンジニアが増員されチームの人数が増えると、次第に互いにコミュニケーションをP2P的にとることが難しくなってくる
    • そして、ピラミッド型の組織図が導入され管理が始まる
  • 少人数でのP2P的なコミュニケーションとピラミッド型組織で上下構造を前提としたコミュニケーションとでは、性質が大きくことなる
    • それ故に組織が少数精鋭であった頃のような、エンジニア間のダイレクトなコミュニケーションを前提としたシステムの設計スタイルはもはや機能しない
/* https://sunrise033.com/entry/hatena-blog-how-to-hierarchicalize-categories */