ためすう

kubesec を使ってみる (kubernetes)

2021-01-03

やったこと

Secret リソースを暗号化するため、kubesec を使ってみます。

確認環境

$ k version
Client Version: version.Info{Major:"1", Minor:"16", GitVersion:"v1.16.2", GitCommit:"c97fe5036ef3df2967d086711e6c0c405941e14b", GitTreeState:"clean", BuildDate:"2019-10-15T19:18:23Z", GoVersion:"go1.12.10", Compiler:"gc", Platform:"darwin/amd64"}
Server Version: version.Info{Major:"1", Minor:"19", GitVersion:"v1.19.3", GitCommit:"1e11e4a2108024935ecfcb2912226cedeafd99df", GitTreeState:"clean", BuildDate:"2020-10-14T12:41:49Z", GoVersion:"go1.15.2", Compiler:"gc", Platform:"linux/amd64"}

調査

インストール

kubesec のインストール

$ curl -sSL https://github.com/shyiko/kubesec/releases/download/0.9.2/kubesec-0.9.2-darwin-amd64 \
>   -o kubesec && chmod a+x kubesec && sudo mv kubesec /usr/local/bin/
Password:
$ kubesec --version
0.9.2

gpg のインストール

$ brew install gpg
$ gpg --version
gpg (GnuPG) 2.2.25
libgcrypt 1.8.7
(省略)

暗号化

secret-hoge.yaml

apiVersion: v1
kind: Secret
metadata:
  name: first-kubesec
type: Opaque
data:
  AAA: MTIz
  BBB: NDU2
  CCC: YWJj
$ gpg --gen-key
pub   rsa3072 2020-12-27 [SC] [有効期限: 2022-12-27]
      xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

※ 鍵はxに変換してあります。

標準出力
$ kubesec encrypt --key=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx secret-hoge.yaml

ファイル書き換え
$ kubesec encrypt -i --key=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx secret-hoge.yaml

※ 出力結果は省略します。

復号化

$ kubesec decrypt secret-hoge.yaml
apiVersion: v1
data:
  AAA: MTIz
  BBB: NDU2
  CCC: YWJj
kind: Secret
metadata:
  name: first-kubesec
type: Opaque

参考

ServiceのClusterIPを使ってみる (kubernetes)

2021-01-03

やったこと

Service の ClusterIP を使ってみます。

確認環境

$ k version
Client Version: version.Info{Major:"1", Minor:"16", GitVersion:"v1.16.2", GitCommit:"c97fe5036ef3df2967d086711e6c0c405941e14b", GitTreeState:"clean", BuildDate:"2019-10-15T19:18:23Z", GoVersion:"go1.12.10", Compiler:"gc", Platform:"darwin/amd64"}
Server Version: version.Info{Major:"1", Minor:"19", GitVersion:"v1.19.3", GitCommit:"1e11e4a2108024935ecfcb2912226cedeafd99df", GitTreeState:"clean", BuildDate:"2020-10-14T12:41:49Z", GoVersion:"go1.15.2", Compiler:"gc", Platform:"linux/amd64"}

調査

first-cluster-ip.yaml

apiVersion: v1
kind: Service
metadata:
  name: my-cluster-ip
spec:
  type: ClusterIP
  ports:
  - name: "hoge"
    protocol: "TCP"
    port: 8080
    targetPort: 80
  selector:
    app: sample5

sample5.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: sample5
  template:
    metadata:
      labels:
        app: sample5
    spec:
      containers:
        - name: nginx-container
          image: nginx:1.17
$ k apply -f sample5.yaml -f first-cluster-ip.yaml
deployment.apps/my-deployment created
service/my-cluster-ip created

$ k get pods -o wide
NAME                             READY   STATUS    RESTARTS   AGE   IP           NODE             NOMINATED NODE   READINESS GATES
my-deployment-5f9fb9cfc8-69w6v   1/1     Running   0          24s   10.1.0.221   docker-desktop   <none>           <none>
my-deployment-5f9fb9cfc8-c25mg   1/1     Running   0          24s   10.1.0.223   docker-desktop   <none>           <none>
my-deployment-5f9fb9cfc8-m5qnk   1/1     Running   0          24s   10.1.0.222   docker-desktop   <none>           <none>

$ k get service my-cluster-ip
NAME            TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
my-cluster-ip   ClusterIP   10.109.253.129   <none>        8080/TCP   6m32s

※ 同じクラスタ内のコンテナからアクセス

$ curl -v http://10.109.253.129:8080

何回かアクセスを繰り返すと、アクセスが振り分けられていることが分かります。

$ k logs -f my-deployment-5f9fb9cfc8-69w6v
10.1.0.1 - - [28/Dec/2020:16:10:22 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.64.0" "-"
10.1.0.1 - - [28/Dec/2020:16:17:02 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.64.0" "-"
10.1.0.1 - - [28/Dec/2020:16:17:04 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.64.0" "-"

$ k logs -f my-deployment-5f9fb9cfc8-c25mg
10.1.0.1 - - [28/Dec/2020:16:04:48 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.64.0" "-"
10.1.0.1 - - [28/Dec/2020:16:10:27 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.64.0" "-"
10.1.0.1 - - [28/Dec/2020:16:11:02 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.64.0" "-"
10.1.0.1 - - [28/Dec/2020:16:17:06 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.64.0" "-"

$ k logs -f my-deployment-5f9fb9cfc8-m5qnk
10.1.0.1 - - [28/Dec/2020:16:04:38 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.64.0" "-"
10.1.0.1 - - [28/Dec/2020:16:17:03 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.64.0" "-"

参考

ConfigMap を使ってみる (kubernetes)

2021-01-02

やったこと

ConfigMap を使ってみます。

確認環境

$ k version
Client Version: version.Info{Major:"1", Minor:"16", GitVersion:"v1.16.2", GitCommit:"c97fe5036ef3df2967d086711e6c0c405941e14b", GitTreeState:"clean", BuildDate:"2019-10-15T19:18:23Z", GoVersion:"go1.12.10", Compiler:"gc", Platform:"darwin/amd64"}
Server Version: version.Info{Major:"1", Minor:"19", GitVersion:"v1.19.3", GitCommit:"1e11e4a2108024935ecfcb2912226cedeafd99df", GitTreeState:"clean", BuildDate:"2020-10-14T12:41:49Z", GoVersion:"go1.15.2", Compiler:"gc", Platform:"linux/amd64"}

調査

今回は Volume マウントを使って情報を渡します。

ConfigMap の作成

hoge.yaml

 aaa:
   bbb: 999
 ccc:
   ddd: 888
$ k create configmap --save-config my-configmap --from-file=hoge.yaml
configmap/my-configmap created
$ k get cm
NAME           DATA   AGE
my-configmap   1      32s

Pod に Volume マウントしてファイルを渡す

sample3.yaml

apiVersion: v1
kind: Pod
metadata:
  name: first-configmap
spec:
  containers:
    - name: nginx-container
      image: nginx:1.17
      volumeMounts:
      - name: my-tmp-volume
        mountPath: /tmp
  volumes:
  - name: my-tmp-volume
    configMap:
      name: my-configmap
      items:
      - key: hoge.yaml
        path: hoge_new.yaml
$ k apply -f sample3.yaml
pod/first-configmap created
$ k get pod
NAME              READY   STATUS    RESTARTS   AGE
first-configmap   1/1     Running   0          5s

コンテナからファイルを読み込む。

$ k exec -it first-configmap -- cat /tmp/hoge_new.yaml
aaa:
  bbb: 999
ccc:
  ddd: 888

環境変数を使ってみる (kubernetes)

2021-01-01

やったこと

環境変数をコンテナに渡してみます。

確認環境

$ k version
Client Version: version.Info{Major:"1", Minor:"16", GitVersion:"v1.16.2", GitCommit:"c97fe5036ef3df2967d086711e6c0c405941e14b", GitTreeState:"clean", BuildDate:"2019-10-15T19:18:23Z", GoVersion:"go1.12.10", Compiler:"gc", Platform:"darwin/amd64"}
Server Version: version.Info{Major:"1", Minor:"19", GitVersion:"v1.19.3", GitCommit:"1e11e4a2108024935ecfcb2912226cedeafd99df", GitTreeState:"clean", BuildDate:"2020-10-14T12:41:49Z", GoVersion:"go1.15.2", Compiler:"gc", Platform:"linux/amd64"}

調査

sample.yaml

apiVersion: v1
kind: Pod
metadata:
  name: first-env
spec:
  containers:
    - name: nginx-container
      image: nginx:1.17
      env:
      - name: MY_GREETING
        value: "Warm greetings to"
      - name: MY_MEM_REQUEST
        valueFrom:
          resourceFieldRef:
            containerName: nginx-container
            resource: requests.memory

マニフェストの適用 + 環境変数の確認

$ k apply -f sample.yaml
pod/first-env created
$ k exec -it first-env -- env | grep "MY_"
MY_GREETING=Warm greetings to
MY_MEM_REQUEST=0

参考

Job を使ってみる (kubernetes)

2021-01-01

やったこと

Job を使ってみます。

確認環境

$ k version
Client Version: version.Info{Major:"1", Minor:"16", GitVersion:"v1.16.2", GitCommit:"c97fe5036ef3df2967d086711e6c0c405941e14b", GitTreeState:"clean", BuildDate:"2019-10-15T19:18:23Z", GoVersion:"go1.12.10", Compiler:"gc", Platform:"darwin/amd64"}
Server Version: version.Info{Major:"1", Minor:"19", GitVersion:"v1.19.3", GitCommit:"1e11e4a2108024935ecfcb2912226cedeafd99df", GitTreeState:"clean", BuildDate:"2020-10-14T12:41:49Z", GoVersion:"go1.15.2", Compiler:"gc", Platform:"linux/amd64"}

調査

job.yaml

apiVersion: batch/v1
kind: Job
metadata:
  name: pi
spec:
  template:
    spec:
      containers:
      - name: pi
        image: perl
        command: ["perl",  "-Mbignum=bpi", "-wle", "print bpi(20)"]
      restartPolicy: Never
  backoffLimit: 4
  parallelism: 3
  completions: 10
$ k apply -f job.yaml
job.batch/pi created
$ k get pods --watch
NAME       READY   STATUS              RESTARTS   AGE
pi-7x8sv   0/1     ContainerCreating   0          6s
pi-k6mxv   0/1     ContainerCreating   0          6s
pi-tg6cx   0/1     ContainerCreating   0          6s
pi-7x8sv   0/1     Completed           0          108s
pi-8gbgj   0/1     Pending             0          0s
pi-8gbgj   0/1     Pending             0          0s
pi-8gbgj   0/1     ContainerCreating   0          0s
pi-k6mxv   0/1     Completed           0          110s
pi-dtbll   0/1     Pending             0          0s
pi-dtbll   0/1     Pending             0          0s
pi-dtbll   0/1     ContainerCreating   0          0s
pi-tg6cx   0/1     Completed           0          119s
pi-cl6fx   0/1     Pending             0          0s
pi-cl6fx   0/1     Pending             0          0s
pi-cl6fx   0/1     ContainerCreating   0          0s
pi-8gbgj   0/1     Completed           0          17s
... (省略)

Job 終了後の結果

$ k get jobs
NAME   COMPLETIONS   DURATION   AGE
pi     10/10         2m34s      11m

参考

tcpdump を使ってみる (Unix)

2020-12-31

やったこと

man tcpdump より抜粋

tcpdump - dump traffic on a network

調査

前準備

詳細手順は省きます。webサーバーを用意します。

Webブラウザから何度かアクセス

# tcpdump port 80 -n -s 0
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes


10:40:39.662780 IP 172.26.0.1.35166 > 172.26.0.2.80: Flags [P.], seq 3330495538:3330495993, ack 2594564324, win 501, options [nop,nop,TS val 1108626414 ecr 3836588442], length 455: HTTP: GET / HTTP/1.1
10:40:39.663229 IP 172.26.0.2.80 > 172.26.0.1.35166: Flags [P.], seq 1:181, ack 455, win 501, options [nop,nop,TS val 3836620070 ecr 1108626414], length 180: HTTP: HTTP/1.1 304 Not Modified
10:40:39.663375 IP 172.26.0.1.35166 > 172.26.0.2.80: Flags [.], ack 181, win 501, options [nop,nop,TS val 1108626415 ecr 3836620070], length 0

pcap に書き出して、 Wireshark でみる

# tcpdump port 80 -n -s 0 -w hoge.pcap

hoge.pcap を TCPストリームで確認した例

GET / HTTP/1.1
Host: localhost:8080
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:83.0) Gecko/20100101 Firefox/83.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: ja,en-US;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
Connection: keep-alive
Upgrade-Insecure-Requests: 1
If-Modified-Since: Tue, 15 Dec 2020 13:59:38 GMT
If-None-Match: "11111111-264"
Cache-Control: max-age=0

HTTP/1.1 304 Not Modified
Server: nginx/1.19.6
Date: Tue, 29 Dec 2020 10:49:14 GMT
Last-Modified: Tue, 15 Dec 2020 13:59:38 GMT
Connection: keep-alive
If-None-Match: "11111111-264"

おまけ

利用したオプション

       -n     Don't convert addresses (i.e., host addresses, port numbers, etc.) to names.
       -w file
              Write the raw packets to file rather than parsing and printing them out.  They can later be printed with the -r option.  Standard output is used if file is ``-''.
       -s snaplen

StatefulSet を使ってみる (kubernetes)

2020-12-31

やったこと

StatefulSet を使ってみます。

確認環境

$ k version
Client Version: version.Info{Major:"1", Minor:"16", GitVersion:"v1.16.2", GitCommit:"c97fe5036ef3df2967d086711e6c0c405941e14b", GitTreeState:"clean", BuildDate:"2019-10-15T19:18:23Z", GoVersion:"go1.12.10", Compiler:"gc", Platform:"darwin/amd64"}
Server Version: version.Info{Major:"1", Minor:"19", GitVersion:"v1.19.3", GitCommit:"1e11e4a2108024935ecfcb2912226cedeafd99df", GitTreeState:"clean", BuildDate:"2020-10-14T12:41:49Z", GoVersion:"go1.15.2", Compiler:"gc", Platform:"linux/amd64"}

調査

StatefulSetは下記の1つ以上の項目を要求するアプリケーションにおいて最適です。

  • 安定した一意のネットワーク識別子
  • 安定した永続ストレージ
  • 規則的で安全なデプロイとスケーリング
  • 規則的で自動化されたローリングアップデート

first-stateful.yaml

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: my-statefulset
spec:
  serviceName: nginx
  replicas: 2 # by default is 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx # .spec.selector.matchLabelsの値と一致する必要があります
    spec:
      terminationGracePeriodSeconds: 10
      containers:
      - name: nginx-container
        image: nginx:1.17
        ports:
        - containerPort: 80
          name: web
        volumeMounts:
        - name: www
          mountPath: /usr/share/nginx/html
  volumeClaimTemplates:
  - metadata:
      name: www
    spec:
      accessModes:
      - ReadWriteOnce
      storageClassName: "my-storage-class"
      resources:
        requests:
          storage: 1Gi
$ k apply -f first-stateful.yaml
statefulset.apps/my-statefulset created

$ k get statefulsets
NAME             READY   AGE
my-statefulset   2/2     12m

$ k get pods -o wide
NAME               READY   STATUS    RESTARTS   AGE   IP           NODE             NOMINATED NODE   READINESS GATES
my-statefulset-0   1/1     Running   0          11m   10.1.0.180   docker-desktop   <none>           <none>
my-statefulset-1   1/1     Running   0          11m   10.1.0.181   docker-desktop   <none>           <none>

$ k get pv
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                          STORAGECLASS   REASON   AGE
pvc-0ec2bcbb-1a20-46b0-8930-5fe48601a180   1Gi        RWO            Delete           Bound    default/www-my-statefulset-1   hostpath                12m
pvc-dc6cf56f-2e32-4d53-ad5e-9fa0fd9bc365   1Gi        RWO            Delete           Bound    default/www-my-statefulset-0   hostpath                12m

$ k get pvc
NAME                   STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
www-my-statefulset-0   Bound    pvc-dc6cf56f-2e32-4d53-ad5e-9fa0fd9bc365   1Gi        RWO            hostpath       12m
www-my-statefulset-1   Bound    pvc-0ec2bcbb-1a20-46b0-8930-5fe48601a180   1Gi        RWO            hostpath       12m

永続ボリュームの動作を確認

# ファイルを設置する
$ k exec -it my-statefulset-0 -- ls /usr/share/nginx/html
$ k exec -it my-statefulset-0 -- touch /usr/share/nginx/html/hoge
$ k exec -it my-statefulset-0 -- ls /usr/share/nginx/html
hoge

# Pod を削除する
$ k delete pod my-statefulset-0
pod "my-statefulset-0" deleted

$ k get pods
NAME               READY   STATUS    RESTARTS   AGE
my-statefulset-0   1/1     Running   0          47s
my-statefulset-1   1/1     Running   0          16m

# my-statefulset-0 でファイルがあることを確認する
$ k exec -it my-statefulset-0 -- ls /usr/share/nginx/html
hoge

参考

DaemonSet を使ってみる (kubernetes)

2020-12-30

やったこと

DaemonSet を使ってみます。

確認環境

$ k version
Client Version: version.Info{Major:"1", Minor:"16", GitVersion:"v1.16.2", GitCommit:"c97fe5036ef3df2967d086711e6c0c405941e14b", GitTreeState:"clean", BuildDate:"2019-10-15T19:18:23Z", GoVersion:"go1.12.10", Compiler:"gc", Platform:"darwin/amd64"}
Server Version: version.Info{Major:"1", Minor:"19", GitVersion:"v1.19.3", GitCommit:"1e11e4a2108024935ecfcb2912226cedeafd99df", GitTreeState:"clean", BuildDate:"2020-10-14T12:41:49Z", GoVersion:"go1.15.2", Compiler:"gc", Platform:"linux/amd64"}

調査

DaemonSet は全て(またはいくつか)のNodeが単一のPodのコピーを稼働させることを保証します。

sample4.yaml

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: my-daemon-first
spec:
  selector:
    matchLabels:
      app: sample4
  template:
    metadata:
      labels:
        app: sample4
    spec:
      containers:
        - name: nginx-container
          image: nginx:1.16

マニフェストの適用

$ k apply -f sample4.yaml
daemonset.apps/my-daemon-first created
$ k get pods
NAME                    READY   STATUS    RESTARTS   AGE
my-daemon-first-fghkd   1/1     Running   0          22s
$ k get ds
NAME              DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
my-daemon-first   1         1         1       1            1           <none>          11m
$ k get pods
NAME                    READY   STATUS    RESTARTS   AGE
my-daemon-first-fghkd   1/1     Running   0          59s

sample4.yaml を編集します。

          image: nginx:1.17

更新を適用する

$ k apply -f sample4.yaml
daemonset.apps/my-daemon-first configured
$ k get ds
NAME              DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
my-daemon-first   1         1         1       0            1           <none>          12m
$ k get pods
NAME                    READY   STATUS        RESTARTS   AGE
my-daemon-first-fghkd   1/1     Terminating   0          114s

// しばらくした後
$ k get pods
NAME                    READY   STATUS    RESTARTS   AGE
my-daemon-first-nnfnm   1/1     Running   0          35s

更新戦略

$ k get ds -o jsonpath="{.items[0].spec.updateStrategy}"
map[rollingUpdate:map[maxUnavailable:1]

maxUnavailable=1 より、Terminateされてから新しいPodが起動したことが分かります。

参考

strings を使ってみる (Unix)

2020-12-30

やったこと

strings を使ってみます。

man strings より抜粋

NAME strings - find the printable strings in a object, or other binary, file

オブジェクトや、バイナリ、ファイルから、表示できる文字を表示してくれます。

調査

ls コマンドのバイナリを引数に渡してみます。

ファイル判別

$ file /bin/ls
/bin/ls: Mach-O 64-bit executable x86_64

strings 実行

$ strings /bin/ls
$FreeBSD: src/bin/ls/cmp.c,v 1.12 2002/06/30 05:13:54 obrien Exp $
@(#) Copyright (c) 1989, 1993, 1994
The Regents of the University of California.  All rights reserved.
$FreeBSD: src/bin/ls/ls.c,v 1.66 2002/09/21 01:28:36 wollman Exp $
(省略)

sortをする (Go)

2020-12-29

やったこと

Goでsortパッケージを使ってみます。

調査

package main

import (
	"fmt"
	"runtime"
	"sort"
)

func main() {
        fmt.Println("確認環境: ", runtime.Version())
	people := []struct {
		Name string
		Age  int
	}{
		{"Gopher", 7},
		{"Alice", 55},
		{"Vera", 24},
		{"Bob", 75},
	}

	sort.Slice(people, func(i, j int) bool { return people[i].Age < people[j].Age })
	fmt.Println("By age 昇順:", people)

	sort.Slice(people, func(i, j int) bool { return people[i].Age > people[j].Age })
	fmt.Println("By age 降順:", people)

	p := []int {7, 55, 24, 75}
	sort.Slice(p, func(i, j int) bool { return p[i] < p[j] })
	fmt.Println(p)

}

出力結果

確認環境:  go1.15.6
By age 昇順: [{Gopher 7} {Vera 24} {Alice 55} {Bob 75}]
By age 降順: [{Bob 75} {Alice 55} {Vera 24} {Gopher 7}]
[7 24 55 75]

参考