自律型データベース(Autonomous Transaction Processing)に、Kubernetes(GolangPod)から接続

# はじめに

Oracle Cloud には、バージョンアップやチューニング、障害時の回復などの自動化を備えた マネージドデータベースサービス が存在しています。今回は、Autonomous Transaction Processing というデータベースサービスへ、KubernetesのPodからアクセスを行います。

なお、[別の記事](https://qiita.com/sugimount/items/69e11c116a895c9feb97)で、ATPの作成やGo言語からの接続方法などを解説しています。



# KubernetesからATPへ接続する

Kubernetesで稼働するコンテナが、データベースなどの外部のサービスへ接続する際に、configmapやsecretなどを利用して接続先を分岐する方法が推奨されています。具体例を出すと、ステージング環境・プロダクション環境といった2環境が存在するときに、DockerImageは同一のものを使用しつつ、環境変数を基に接続先を分岐するような方法です。

Autonomous Transaction Processingへ接続する際に、以下の4個の要素が必要となってきます

- Walletファイル (回答済みzipファイル)
- ATPのユーザID
- ATPのパスワード
- ATPの接続先名 (tnsnames)



上記4個の要素は secret を使用して、Podへ渡す方式を採用します。なお、Secret や ConfigMap は text だけではなく、1MB以下のfileも受け渡すことが出来ます。



# Docker Fileの作成

今回は、Secretへ登録するWalletは、登録を簡単にするためzipファイルをそのまま登録するインターフェースとします。
そのため、Podを起動するときの初期設定として、Secretから受け取った Wallet zipファイルを unzip する必要があります。
PodのEntryPointに bash shell script を使用することで、初期設定を行う方法を取ります。
なお、unzipしてfileに書き込むと若干セキュリティリスクが高まるので、気になる場合は、解凍後のwalletファイルから、必要なファイルをsecretへそれぞれ登録して、直接必要なDirectoryへmountする方法もあります。

Entrypoint用の bash shell script を作成します。secretから受け取った wallet ファイルをunzipして、適切な場所へ格納します。

```
string trim '
#!/bin/bash

if [ -f /opt/oracle/instantclient_18_3/network/admin/wallet.zip ]; then
  echo "wallet.zip is exist. skip unzip."
else
  cp -p /wallet/wallet.zip /opt/oracle/instantclient_18_3/network/admin/wallet.zip
  cd /opt/oracle/instantclient_18_3/network/admin/
  unzip wallet.zip
fi

/home/go-oracledb/go-oracledb-test
exit 0
' > ~/go-third-party/src/github.com/Sugi275/go-oracledb-test/entrypoint.sh
```



DockerFileを作成します。必要な前提設定を実施して、作成した entrypoint を指定します。

```
string trim '
FROM ubuntu:18.04 
MAINTAINER sugimount <https://twitter.com/sugimount>

# set working directory
WORKDIR /opt/oracle

# package install
RUN apt-get update && \
    apt-get install -y wget unzip libaio1 && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*

# instant client
RUN wget https://github.com/Sugi275/go-oracledb-test/raw/master/instantclient-basic-linux.x64-18.3.0.0.0dbru.zip && \
    unzip instantclient-basic-linux.x64-18.3.0.0.0dbru.zip && \
    rm /opt/oracle/instantclient-basic-linux.x64-18.3.0.0.0dbru.zip

# runtime linkpath
COPY oracle-instantclient.conf /etc/ld.so.conf.d/oracle-instantclient.conf
RUN ldconfig

# user add
RUN adduser --uid 1000 go-oracledb && \
    chown go-oracledb: /opt/oracle/instantclient_18_3/network/admin

# go binary
COPY ./bin/go-oracledb-test /home/go-oracledb/go-oracledb-test

# entrypoint shell
COPY entrypoint.sh /home/go-oracledb/entrypoint.sh
RUN chown go-oracledb: /home/go-oracledb/entrypoint.sh

# default user
USER 1000:1000

EXPOSE 8080
ENTRYPOINT ["sh", "/home/go-oracledb/entrypoint.sh"]
' > /home/ubuntu/go-third-party/src/github.com/Sugi275/go-oracledb-test/Dockerfile
```



Docker Image を Build します

```
cd /home/ubuntu/go-third-party/src/github.com/Sugi275/go-oracledb-test
sudo docker build --tag=sugimount/go-oracledb-test:test1.0.1 .
```



Image が出来上がっているか確認します

```
sudo docker image list
```



DockerHubへDockerImageをPushします

```
sudo docker login
sudo docker push sugimount/go-oracledb-test:test1.0.1
```



# Go言語のソースコード

以下のGitHubで公開しています。
https://github.com/Sugi275/go-oracledb-test/blob/master/src/go-oracledb-test.go

大事なポイントは、以下です。環境変数から取得し、atpへの接続文字列を生成しています

```
func getDSN() string {
    user := os.Getenv("atp_username")
    passwd := os.Getenv("atp_password")
    tsn := os.Getenv("atp_tsn")
    connect := user + "/" + passwd + "@" + tsn
    return connect
}
```



# Kubernetesで起動

## secret作成

wallet ファイルから、secretを作成

```
cd /opt/oracle/instantclient_18_3/network/admin/
kubectl create secret generic --save-config wallet --from-file Wallet_tutorial1.zip
```



ATPへ接続するための ID, Password, TSN を Secret に登録します

```
kubectl create secret generic atp-admin --from-literal=atp_username=admin --from-literal=atp_password=nsfan824u789Fjfoijoj3098j --from-literal=atp_tsn=tutorial1_low
```



Pod作成

```
string trim '
apiVersion: v1
kind: Pod
metadata:
  name: go-autonomousdb-sample
spec:
  containers:
    - name: secret-container
      image: sugimount/go-oracledb-test:test1.0.1
      volumeMounts:
      - name: wallet
        mountPath: /wallet
      envFrom:
      - secretRef:
          name: atp-admin
  volumes:
    - name: wallet
      secret:
        secretName: wallet
        items:
        - key: Wallet_tutorial1.zip
          path: wallet.zip
' > ~/test/pod.yaml
kubectl apply -f ~/test/pod.yaml
```



正常に、Podの標準出力を確認します。wallet.zipをunzipした時のlogと、ATPからデータを取得しPrintが見えています。

```
> kubectl logs go-autonomousdb-sample
Archive:  wallet.zip
  inflating: cwallet.sso
  inflating: tnsnames.ora
  inflating: truststore.jks
  inflating: ojdbc.properties
  inflating: sqlnet.ora
  inflating: ewallet.p12
  inflating: keystore.jks
empno:0000000001 empname:sugimount, gender:1
empno:0000000002 empname:helloworld, gender:0
empno:0000000003 empname:hellooracle, gender:0
empno:0000000004 empname:hellowug, gender:1
```



# debug command memo

```
sudo docker run --rm -it ubuntu:18.04 bash
```

```
sudo docker run --rm -it alpine ash
```

```
sudo docker run --entrypoint="/bin/bash" --rm -it sugimount/go-oracledb-test:0.0.1
```



# 参考URL

https://github.com/wendyeq/go-oracle-docker/blob/master/Dockerfile
https://github.com/cloudsolutionhubs/ATPDocker/blob/master/Dockerfile