Db2 on CP4Dの ネットワークトレースを取得する。

Db2 on Cloud Pak for Data V4.5.3 で　TCP/IP ネットワークトレースを取得しなければならない事態となった。
Linuxでは TCP/IP ネットワークトレースを取得するために通常`tcpdump`を使用する。しかしながら、Db2のPodには `tcpdump`がなく、`tcpdump` を導入し実行しても `socket: Operation not permitted`エラーとなる。
ここでは、Db2 on Cloud Pak for Data V4.5.3で `tcpdump`を使用してTCP/IP ネットワークトレース取得することができた手順を紹介する。　

### 実施環境
- IBM Cloud VPC Gen2
- OCP  4.10.32
- CP4D 4.5.3 
  - Db2 Version 11.5.7.0-cn7
  - CP4D Namespace : zen

## 1. Db2 カスタム・セキュリティー・コンテキスト制約 (SCC) に　NET_RAW を追加する
`tcpdump`を導入する方法は後述するが　`tcpdump`を導入し実行すると　 実施した環境では`socket: Operation not permitted`エラーとなった。　これは Db2 のカスタム・セキュリティー・コンテキスト制約 (SCC) に `NET_RAW`機能が含まれていないためである。
参考: [Updating iptables and ping fails in a privileged application container](https://access.redhat.com/solutions/5699411)

Data Virtualization サービスで  `NET_RAW`機能を追加している次の文書を参考にして　作業を実行した。
[Data Virtualization service on Cloud Pak for Data appears to be unstable on a Red Hat OpenShift on Kubernetes cluster](https://www.ibm.com/support/pages/data-virtualization-service-cloud-pak-data-appears-be-unstable-red-hat-openshift-kubernetes-cluster)


### 本作業に関連するDb2サービスのリソースの確認
`tcpdump`を導入するDb2 サービス (Db2 デプロイメント ID) を db2ucluster変数に登録しておく。
```
[user99@bastion7 ~]$ db2ucluster=db2oltp-1668505262111014
[user99@bastion7 ~]$ echo ${db2ucluster}
db2oltp-1668505262111014
[user99@bastion7 ~]$
```

この環境では、Db2 をデプロイしたOpenShift プロジェクトがzen であるため　作業するOpenShift プロジェクトをzenに切り替える。
```
# 実行コマンド
oc project zen

# 実行結果例
[user99@bastion7 ~]$ oc project zen
Already on project "zen" on server "https://c101-e.jp-osa.containers.cloud.ibm.com:32291".
[user99@bastion7 ~]$
```

Db2 Podは　c-${db2ucluster}-db2u-0 ( c-db2oltp-1668505262111014-db2u-0 )となる。
```
[user99@bastion7 ~]$ oc get pod c-${db2ucluster}-db2u-0 -o wide
NAME                                READY   STATUS    RESTARTS   AGE    IP             NODE           NOMINATED NODE   READINESS GATES
c-db2oltp-1668505262111014-db2u-0   1/1     Running   0          5d19h  172.17.2.170   10.248.64.34   <none>           <none>
[user99@bastion7 ~]$
```
Db2 SCCは NAMESPACEがzen であるため zen-c-${db2ucluster}-scc ( zen-c-db2oltp-1668505262111014-scc )となる。
```
[user99@bastion7 ~]$ oc get scc zen-c-${db2ucluster}-scc
NAME                                 PRIV   CAPS                                                                                                                                                       SELINUX     RUNASUSER   FSGROUP    SUPGROUP   PRIORITY   READONLYROOTFS   VOLUMES
zen-c-db2oltp-1668505262111014-scc   true   ["FOWNER","SETGID","SETUID","CHOWN","DAC_OVERRIDE","SYS_RESOURCE","IPC_OWNER","SYS_NICE","FSETID","SETFCAP","SETPCAP","SYS_CHROOT","KILL","AUDIT_WRITE"]   MustRunAs   RunAsAny    RunAsAny   RunAsAny   10         false            ["*"]
[user99@bastion7 ~]$
```

Db2 Podの OpenShift® ステートフル・セットは c-${db2ucluster}-db2u (c-db2oltp-1668505262111014-db2u )となる。

```
[user99@bastion7 ~]$ oc get sts -l app=${db2ucluster},component=db2oltp
NAME                              READY   AGE
c-db2oltp-1668505262111014-db2u   1/1     5d19h
[user99@bastion7 ~]$
```


### (1) Db2のSCC zen-c-${db2ucluster}-scc のコピーを保存する 

```
# 実行コマンド
oc get scc zen-c-${db2ucluster}-scc -o yaml > zen-c-${db2ucluster}-scc.bak.yaml
```
SCCには次が登録されていた
```
allowedCapabilities:
- FOWNER
- SETGID
- SETUID
- CHOWN
- DAC_OVERRIDE
- SYS_RESOURCE
- IPC_OWNER
- SYS_NICE
- FSETID
- SETFCAP
- SETPCAP
- SYS_CHROOT
- KILL
- AUDIT_WRITE
```

### (2) Db2 Podの ステートフル・セットStatefulset のコピーを保存する。　

```
# 実行コマンド
oc get sts c-${db2ucluster}-db2u -o yaml > c-${db2ucluster}-db2u.bak.yaml
```
次が登録されていた。　
```
        securityContext:
          allowPrivilegeEscalation: true
          capabilities:
            add:
            - SYS_RESOURCE
            - IPC_OWNER
            - SYS_NICE
            - CHOWN
            - DAC_OVERRIDE
            - FSETID
            - FOWNER
            - SETGID
            - SETUID
            - SETFCAP
            - SETPCAP
            - SYS_CHROOT
            - KILL
            - AUDIT_WRITE
```

### (3) Db2のSCC zen-c-${db2ucluster}-scc にNET_RAWを追加する

```
# 実行コマンド
oc patch scc zen-c-${db2ucluster}-scc --type=json -p='[{"op": "add", "path": "/allowedCapabilities/0", "value":"NET_RAW" }]'
```

```
# 実行結果例
[user99@bastion7 ~]$ oc patch scc zen-c-${db2ucluster}-scc --type=json -p='[{"op": "add", "path": "/allowedCapabilities/0", "value":"NET_RAW" }]'
securitycontextconstraints.security.openshift.io/zen-c-db2oltp-1668505262111014-scc patched
[user99@bastion7 ~]$
```
`oc get scc zen-c-${db2ucluster}-scc -o yaml` を実行すると　`NET_RAW` が追加されていることが確認できる

```
 allowedCapabilities:
- NET_RAW 
- FOWNER
- SETGID
- SETUID
- CHOWN
- DAC_OVERRIDE
- SYS_RESOURCE
- IPC_OWNER
- SYS_NICE
- FSETID
- SETFCAP
- SETPCAP
- SYS_CHROOT
- KILL
- AUDIT_WRITE
```

### (4) Db2 Podの ステートフル・セットにNET_RAWを追加する

```
# 実行コマンド
oc patch sts c-${db2ucluster}-db2u --type=json -p='[{"op": "add", "path": "/spec/template/spec/containers/0/securityContext/capabilities/add/0", "value":"NET_RAW" }]'
```

```
# 実行結果例
[user99@bastion7 ~]$ oc patch sts c-${db2ucluster}-db2u --type=json -p='[{"op": "add", "path": "/spec/template/spec/containers/0/securityContext/capabilities/add/0", "value":"NET_RAW" }]'
statefulset.apps/c-db2oltp-1668505262111014-db2u patched
[user99@bastion7 ~]$
```
`oc get sts c-${db2ucluster}-db2u -o yaml`を実行すると `NET_RAW`が追加されていることが確認できる。
```
        securityContext:
          allowPrivilegeEscalation: true
          capabilities:
            add:
            - NET_RAW
            - SYS_RESOURCE
            - IPC_OWNER
            - SYS_NICE
            - CHOWN
            - DAC_OVERRIDE
            - FSETID
            - FOWNER
            - SETGID
            - SETUID
            - SETFCAP
            - SETPCAP
            - SYS_CHROOT
            - KILL
            - AUDIT_WRITE
```

## 2. tcpdump 導入
 次に、`tcpdump`を 一時的にDb2 Podに導入する。　

### (1) Db2 pod の OSとversion を確認し tpcdump のrpm を取得する。
OSにマッチしたtcpdumpを導入するために　Pod にはいって /etc の下の release を確認する。　
```
[user99@bastion7 ~]$ oc exec -it c-${db2ucluster}-db2u-0 -- bash
Defaulted container "db2u" out of: db2u, init-labels (init), init-kernel (init)
[db2uadm@c-db2oltp-1668505262111014-db2u-0 /]$ ls /etc/*release*
/etc/os-release  /etc/os-release.orig  /etc/redhat-release  /etc/system-release  /etc/system-release-cpe
[db2uadm@c-db2oltp-1668505262111014-db2u-0 /]$ cat /etc/redhat-release
Red Hat Enterprise Linux release 8.6 (Ootpa)
[db2uadm@c-db2oltp-1668505262111014-db2u-0 /]$
```
Red Hat Enterprise Linux release 8.6 (Ootpa)であることがわかる。

Red Hat Enterprise Linux release 8.6 (Ootpa)のCD imageから　`tcpdump-4.9.3-3.el8.x86_64.rpm`　を導入すればよいことがわかる。

### (2) Db2 Pod へtcpdump のrpmをコピーする
`oc`コマンドを実行している踏み台マシンに　ディレクトリー`tcpdump`を作成して `tcpdump-4.9.3-3.el8.x86_64.rpm`を保管しておく。
`oc rsync`を使用して Db2 Podへ rpmをコピーする。
```
# 実行コマンド
oc rsync . c-${db2ucluster}-db2u-0:/mnt/bludata0/scratch/tcpdump
```

```
# 実行結果例
[user99@bastion7 tcpdump]$ oc rsync . c-${db2ucluster}-db2u-0:/mnt/bludata0/scratch/tcpdump
sending incremental file list
./
tcpdump-4.9.3-3.el8.x86_64.rpm

sent 464,238 bytes  received 39 bytes  185,710.80 bytes/sec
total size is 463,984  speedup is 1.00
Defaulted container "db2u" out of: db2u, init-labels (init), init-kernel (init)
[user99@bastion7 tcpdump]$
```

### (3) Db2 Pod で tcpdump rpmを導入する
Db2 Pod に入り コピーした rpmを使用して tcpdumpを一時的に導入する。　(幸いにも　追加で必要なパッケージはなかった。)
```
[db2uadm@c-db2oltp-1668505262111014-db2u-0 /]$ cd /mnt/bludata0/scratch/tcpdump
[db2uadm@c-db2oltp-1668505262111014-db2u-0 tcpdump]$ sudo rpm -ivh tcpdump-4.9.3-3.el8.x86_64.rpm
Verifying...                          ################################# [100%]
Preparing...                          ################################# [100%]
Updating / installing...
   1:tcpdump-14:4.9.3-3.el8           ################################# [100%]
[db2uadm@c-db2oltp-1668505262111014-db2u-0 tcpdump]$
```

### (4) tcpdump を実行する
```
# 実行コマンドの例
sudo tcpdump -C 1 -Z root -w hoge.pcap
```

```
# 実行結果例
[db2uadm@c-db2oltp-1668505262111014-db2u-0 tcpdump]$ sudo tcpdump -C 1 -Z root -w hoge.pcap
dropped privs to root
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
^C369 packets captured
371 packets received by filter
0 packets dropped by kernel
[db2uadm@c-db2oltp-1668505262111014-db2u-0 tcpdump]$
```

次のようにネットワークトレースが取得できた。
```
[db2uadm@c-db2oltp-1668505262111014-db2u-0 tcpdump]$ tcpdump -r hoge.pcap 
reading from file hoge.pcap, link-type EN10MB (Ethernet)
05:35:39.084930 IP kubernetes.default.svc.cluster.local.https > c-db2oltp-1668505262111014-db2u-0.c-db2oltp-1668505262111014-db2u-internal.zen.svc.cluster.local.43064: Flags [P.], seq 1231866180:1231867499, ack 1501289196, win 355, options [nop,nop,TS val 2779181171 ecr 3461659633], length 1319
05:35:39.084942 IP c-db2oltp-1668505262111014-db2u-0.c-db2oltp-1668505262111014-db2u-internal.zen.svc.cluster.local.43064 > kubernetes.default.svc.cluster.local.https: Flags [.], ack 1319, win 353, options [nop,nop,TS val 3461661152 ecr 2779181171], length 0
(skip)
```

## 参考文献
- [Updating iptables and ping fails in a privileged application container](https://access.redhat.com/solutions/5699411)

- [Data Virtualization service on Cloud Pak for Data appears to be unstable on a Red Hat OpenShift on Kubernetes cluster](https://www.ibm.com/support/pages/data-virtualization-service-cloud-pak-data-appears-be-unstable-red-hat-openshift-kubernetes-cluster)