ためすう

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]

参考

Deployment を使ってみる (kubernetes)

2020-12-29

やったこと

Deployment を使ってみます。

確認環境

$ 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"}

調査

sample3.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-deployment-first
spec:
  replicas: 2
  selector:
    matchLabels:
      app: sample3
  template:
    metadata:
      labels:
        app: sample3
    spec:
      containers:
        - name: nginx-container
          image: nginx:1.16

マニフェストの適用

$ k apply -f sample3.yaml
deployment.apps/my-deployment-first created
$ k get deployments
NAME                  READY   UP-TO-DATE   AVAILABLE   AGE
my-deployment-first   2/2     2            2           78s
$ k get rs
NAME                             DESIRED   CURRENT   READY   AGE
my-deployment-first-55df95dccf   2         2         2       3m37s
$ k get pods
NAME                                   READY   STATUS    RESTARTS   AGE
my-deployment-first-55df95dccf-8d9ld   1/1     Running   0          92s
my-deployment-first-55df95dccf-pcmr8   1/1     Running   0          90s

sample3.yaml を編集します。

          image: nginx:1.17
$ k apply -f sample3.yaml
deployment.apps/my-deployment-first configured
$ k get deployments
NAME                  READY   UP-TO-DATE   AVAILABLE   AGE
my-deployment-first   2/2     0            2           20m
$ k get rs
NAME                             DESIRED   CURRENT   READY   AGE
my-deployment-first-55df95dccf   2         2         2       5m19s
my-deployment-first-5b8875c9cb   1         1         0       20m
$ k get pods
NAME                                   READY   STATUS              RESTARTS   AGE
my-deployment-first-55df95dccf-8d9ld   1/1     Running             0          2m48s
my-deployment-first-55df95dccf-pcmr8   1/1     Running             0          2m46s
my-deployment-first-5b8875c9cb-qp66z   0/1     ContainerCreating   0          0s

更新戦略の確認 ( .spec.strategy )

  • Recreate
  • RollingUpdate (デフォルト)
$ k get deployment -o jsonpath="{.items[*].spec.strategy}"
map[rollingUpdate:map[maxSurge:25% maxUnavailable:25%] type:RollingUpdate]

参考

ReplicaSet を使ってみる (kubernetes)

2020-12-28

やったこと

ReplicaSet を使ってみます。

確認環境

$ 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"}

調査

sample2.yaml

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: my-replica-first
spec:
  replicas: 2
  selector:
    matchLabels:
      app: sample-pod2
  template:
    metadata:
      labels:
        app: sample-pod2
    spec:
      containers:
        - name: nginx-container
          image: nginx:1.17

マニフェストの適用

$ k apply -f sample2.yaml
replicaset.apps/my-replica-first created
$ k get replicasets -o wide
NAME               DESIRED   CURRENT   READY   AGE     CONTAINERS        IMAGES       SELECTOR
my-replica-first   2         2         2       4m50s   nginx-container   nginx:1.17   app=sample-pod2
$ k get pods
NAME                     READY   STATUS    RESTARTS   AGE
my-replica-first-9tmnq   1/1     Running   0          8m13s
my-replica-first-cqmff   1/1     Running   0          8m13s

Pod を1つ落として、セルフヒーリング機能を確かめる

$ k delete pod my-replica-first-9tmnq
pod "my-replica-first-9tmnq" deleted
$ k get pods
NAME                     READY   STATUS    RESTARTS   AGE
my-replica-first-86tk2   1/1     Running   0          10s
my-replica-first-cqmff   1/1     Running   0          8m36s
$ k describe rs my-replica-first
(省略)
Events:
  Type    Reason            Age   From                   Message
  ----    ------            ----  ----                   -------
  Normal  SuccessfulCreate  10m   replicaset-controller  Created pod: my-replica-first-cqmff
  Normal  SuccessfulCreate  10m   replicaset-controller  Created pod: my-replica-first-9tmnq
  Normal  SuccessfulCreate  101s  replicaset-controller  Created pod: my-replica-first-86tk2

scale コマンドを使ってみる

$ k scale rs my-replica-first --replicas=3
replicaset.apps/my-replica-first scaled
$ k get pods
NAME                     READY   STATUS    RESTARTS   AGE
my-replica-first-7flv6   1/1     Running   0          8s
my-replica-first-86tk2   1/1     Running   0          5m29s
my-replica-first-cqmff   1/1     Running   0          13m

削除

$ k delete rs my-replica-first
replicaset.apps "my-replica-first" deleted

mapを使う (Go)

2020-12-28

やったこと

Goでmapを使ってみます。

調査

package main

import (
	"fmt"
	"runtime"
)


func main() {
        fmt.Println("確認環境: ", runtime.Version())

	m := make(map[string]int)
	fmt.Println(m["A"])
	value, ok := m["A"]
	if ok {
	  fmt.Println("A: ", value)
	} else {
	  fmt.Println("A: 存在しない")
	}

	m["A"] = 123
	value, ok = m["A"]
	if ok {
	  fmt.Println("A: ", value)
	} else {
	  fmt.Println("A: 存在しない")
	}
}

出力結果

確認環境:  go1.15.6
0
A: 存在しない
A:  123

Pod を使ってみる (kubernetes)

2020-12-27

やったこと

Pod を立ち上げてみます。

確認環境

$ 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: sample-pod
spec:
  containers:
    - name: nginx-container
      image: nginx:1.17

マニフェストの適用

$ k apply -f sample.yaml
pod/sample-pod created

Pod取得

$ k get pod sample-pod -o wide
NAME         READY   STATUS    RESTARTS   AGE     IP           NODE             NOMINATED NODE   READINESS GATES
sample-pod   1/1     Running   0          7m22s   10.1.0.132   docker-desktop   <none>           <none>

$ k get pod --help より

-o, –output=”: Output format. One of: json|yaml|wide|name|custom-columns=…|custom-columns-file=…|go-template=…|go-template-file=…|jsonpath=…|jsonpath-file=… See custom columns [http://kubernetes.io/docs/user-guide/kubectl-overview/#custom-columns], golang template [http://golang.org/pkg/text/template/#pkg-overview] and jsonpath template [http://kubernetes.io/docs/user-guide/jsonpath].

コンテナにログイン

$ k exec -it sample-pod bash
root@sample-pod:/# ls
bin  boot  dev	etc  home  lib	lib64  media  mnt  opt	proc  root  run  sbin  srv  sys  tmp  usr  var

ホストOSからコマンド実行

$ k exec -it sample-pod -- ls
bin   dev  home  lib64	mnt  proc  run	 srv  tmp  var
boot  etc  lib	 media	opt  root  sbin  sys  usr