SonarQubeをkubernetesで動かす

#はじめに
あまりkubernetesに詳しくありませんが、SonarQubeを立てる必要があったため、手っ取り早く実施した事を記録しました。

SonarQubeは、導入が楽なDocker版を利用し、社内の他のインスタンスと整合性をとるためV7.9 LTS版を選択してます。
kubenetes環境は、諸事情によりIBM Cloudを利用しています。

最初に、dockerhubのsonarqubeのページを一読しておきましょう。
https://hub.docker.com/_/sonarqube

#kubernetesクラスターの作成
kubernetesクラスターの作成の作成は、オプションが多いためIBM Cloudの画面上から実施しました。
可用性がそこまで必要ないため、1インスタンスで稼働する想定です。SonarQube自身も、複数のインスタンスで設定やDBを共用する事はサポートされないとしています。

kubernetesのバージョンは選択可能な最新を選びました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/467288/b1e7856a-60c3-2cf3-f304-aa5f9a3332d3.png)

アジアの単一ゾーン、東京02を選択しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/467288/a6e665ec-e599-6313-a958-85a2d85d0b9e.png)

スペックも最小にものに変更し、ワーカーノードを1つに変更しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/467288/e1efdcdb-bb8e-6f3b-c7c6-52e60374aaf6.png)

あとは、デフォルト値で作成し、作成完了までしばらくまちます。

クラスター作成後、自分の端末からkubectlが実行できる環境を整えます。ここは、作成したクラスターのアクセスというページでやるべきことがおおよそわかります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/467288/abcfcb4d-6511-a79f-3ff3-88fcec564d5a.png)
CLIツールやログインを済ませたら、以下のコマンドでクラスターと接続します。

```sh

ibmcloud ks cluster config --cluster bvXXXXXXXXXXXXXXXXhg
```

#Persistent Volumeの作成
設定や情報をコンテナ外でのこすため、以下のPersistent Volumeを作成します。

 - /opt/sonarqube/conf: for Version 7.9.x only, configuration files, such as sonar.properties.
 - /opt/sonarqube/data: data files, such as the embedded H2 database and Elasticsearch indexes
 - /opt/sonarqube/logs: contains SonarQube logs about access, web process, CE process, Elasticsearch logs
 - /opt/sonarqube/extensions: plugins, such as language analyzers

pvc用のyamlの基本形が以下です。nameを変更して4つ分作成しました。

```yaml
 apiVersion: v1
 kind: PersistentVolumeClaim
 metadata:
   name: sonar-pvc-conf
 spec:
   accessModes:
     - ReadWriteMany
   resources:
     requests:
       storage: 5Gi
   storageClassName: default
```

つづいて、pvcを作成。

```sh
kubectl apply -f pvc-conf.yaml
kubectl apply -f pvc-data.yaml
kubectl apply -f pvc-logs.yaml
kubectl apply -f pvc-ext.yaml
```
4つがBound状態になるまで待ちます。

```sh
kubectl get pvc
```

#Deploymentの作成
続いて本丸のDeploymentを作成します。
なお、4つのpvcをマウントする必要がありますが、IBM Cloudでは初期状態で権限エラーとなるため、
initContainerでディレクトリ権限を変更する処理を追加しています。

```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: sonarqube-deploy
spec:
  replicas: 1
  selector:
        matchLabels:
          app: sonarqube
  template:
    metadata:
      labels:
        app: sonarqube
    spec:
      initContainers:
      - name: volume-mount-hack
        image: busybox
        command: ["sh", "-c", "chown -R 999:999 /opt/sonarqube/conf && chown -R 999:999 /opt/sonarqube/data && chown -R 999:999 /opt/sonarqube/logs && chown -R 999:999 /opt/sonarqube/extensions"]
        volumeMounts:
        - mountPath: "/opt/sonarqube/conf"
          name: sonar-pvc-conf
        - mountPath: "/opt/sonarqube/data"
          name: sonar-pvc-data
        - mountPath: "/opt/sonarqube/logs"
          name: sonar-pvc-logs
        - mountPath: "/opt/sonarqube/extensions"
          name: sonar-pvc-extensions
      containers:
      - name: sonarqube
        image: sonarqube:lts
        ports:
        - containerPort: 9000
        volumeMounts:
        - mountPath: "/opt/sonarqube/conf"
          name: sonar-pvc-conf
        - mountPath: "/opt/sonarqube/data"
          name: sonar-pvc-data
        - mountPath: "/opt/sonarqube/logs"
          name: sonar-pvc-logs
        - mountPath: "/opt/sonarqube/extensions"
          name: sonar-pvc-extensions
      volumes:
      - name: sonar-pvc-conf
        persistentVolumeClaim:
          claimName: sonar-pvc-conf
      - name: sonar-pvc-data
        persistentVolumeClaim:
          claimName: sonar-pvc-data
      - name: sonar-pvc-logs
        persistentVolumeClaim:
          claimName: sonar-pvc-logs
      - name: sonar-pvc-extensions
        persistentVolumeClaim:
          claimName: sonar-pvc-extensions
```

Deploymentを作成します。

```sh
kubectl apply -f sonar-deploy.yaml
```

Podが上がってきてSonarQubeの初期化が走るので、SonarQubeの上がったというログが出るまで待ちます。

```sh
kubectl get pods
```
でpodのidを控えて

```sh
kubectl logs <控えたid>
```
ログの最後に以下が出ていたら正常起動です。

```sh
2020.12.02 08:38:46 INFO  app[][o.s.a.SchedulerImpl] Process[ce] is up
2020.12.02 08:38:46 INFO  app[][o.s.a.SchedulerImpl] SonarQube is up
```

#(option) Serviceの作成
VPN経由でアクセスさせるべきですが、ここではSonarQubeをVPNを利用せずに外部からアクセスできるようにします。

```yaml
apiVersion: v1
kind: Service
metadata:
  labels:
    app: sonarqube
  name: sonar-lb
spec:
  ports:
    - port: 80
      protocol: TCP
      targetPort: 9000
  selector:
    app: sonarqube
  type: LoadBalancer
```
上記のyamlファイルよりServiceを作成します。

```sh
kubectl apply -f sonar-service.yaml
```

外部IPアドレスを確認します。

```sh
kubectl get svc
```

```sh
NAME         TYPE           CLUSTER-IP      EXTERNAL-IP     PORT(S)        AGE
kubernetes   ClusterIP      xxx.xx.0.1      <none>          443/TCP        141m
sonar-lb     LoadBalancer   xxx.xx.xx.xxx   yyy.yyy.yyy.yyy   80:31105/TCP   86m
```

上記の、EXTERNAL-IPの値を確認したら、ブラウザでアクセスしてみましょう。


#SonarQubeのセットアップ
SonarQubeの画面が出てきたら、最初にadminのパスワードを変更しましょう。
パスワードがバレバレなのでソースコードが盗まれてしまいます。