HelmでJenkinsをKubernetesにデプロイ


# 環境
Mac(Intel) の Docker Desktop で検証。
あらかじめ Docker Desktop の Kubernetes は有効化しています。
- Mac Big Sur 11.6
- Docker 20.10.7
- Kubernetes 1.21.1
- helm 3.7.1

# helm / chartとは
helm =　Kubernetesのパッケージマネージャ
chart = パッケージ化されたマニフェスト群

yum や apt などで mysql やそれに依存するツールを手軽にインストールできるように、
`helm install <chart_name>` の形でリポジトリに公開されているテンプレートを使って簡単にKubernetesにデプロイできる、ということみたいです。

# 構築手順
まずはhelmのインストールから。

```bash
brew install helm
helm version
version.BuildInfo{Version:"v3.7.1", GitCommit:"1d11fcb5d3f3bf00dbe6fe31b8412839a96b3dc4", GitTreeState:"clean", GoVersion:"go1.17.2"}
```

書籍やネットを見ると最初にinitせよ、とありますが、v3からhelm initは使えなくなっているので注意。（不要）

```bash
helm init
Error: unknown command "init" for "helm"

Did you mean this?
	lint

Run 'helm --help' for usage.
```

続いて、リポジトリを登録します。
[GitHubのREADME](https://github.com/jenkinsci/helm-charts/blob/main/charts/jenkins/README.md) を参考にしています。

```bash
# Jenkinsのリポジトリを登録
helm repo add jenkins https://charts.jenkins.io
helm repo update
helm repo list                                 
NAME   	URL                      
jenkins	https://charts.jenkins.io
```

`helm install`　でデプロイしてみます。
helpを見ればわかりますが、構文は `helm install [NAME] [CAHRT]` です。
Chartはインストール後にReleaseという単位で管理されます。このReleaseの名前を `NAME` に指定しますが任意の名前でOKです。`CHART` の名前（下の例だと jenkins/jenkins）をどうやって知るのかがよくわからなかったのですが、`helm search repo` で確認することができました。（これで正しいのかな？） 

```bash
# Chartの名前を確認
helm search repo jenkins                       
NAME           	CHART VERSION	APP VERSION	DESCRIPTION                                       
jenkins/jenkins	3.8.6        	2.303.2    	Jenkins - Build great things at any scale! The ...

# KubernetesにJenkinsをデプロイ
helm install jenkins jenkins/jenkins

NAME: jenkins
LAST DEPLOYED: Sat Oct 30 16:21:03 2021
NAMESPACE: default
STATUS: deployed
REVISION: 1
NOTES:
1. Get your 'admin' user password by running:
  kubectl exec --namespace default -it svc/jenkins -c jenkins -- /bin/cat /run/secrets/chart-admin-password && echo
2. Get the Jenkins URL to visit by running these commands in the same shell:
  echo http://127.0.0.1:8080
  kubectl --namespace default port-forward svc/jenkins 8080:8080

3. Login with the password from step 1 and the username: admin
4. Configure security realm and authorization strategy
5. Use Jenkins Configuration as Code by specifying configScripts in your values.yaml file, see documentation: http:///configuration-as-code and examples: https://github.com/jenkinsci/configuration-as-code-plugin/tree/master/demos

For more information on running Jenkins on Kubernetes, visit:
https://cloud.google.com/solutions/jenkins-on-container-engine

For more information about Jenkins Configuration as Code, visit:
https://jenkins.io/projects/jcasc/


NOTE: Consider using a custom image with pre-installed plugins

#　インストール済みのChart(Release)を確認
helm ls
NAME   	NAMESPACE	REVISION	UPDATED                             	STATUS  	CHART        	APP VERSION
jenkins	default  	1       	2021-10-30 16:21:03.538325 +0900 JST	deployed	jenkins-3.8.6	2.303.2

# デプロイされたKubernetesリソースを確認
kubectl get all
NAME            READY   STATUS     RESTARTS   AGE
pod/jenkins-0   0/2     Init:0/1   0          29s

NAME                    TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)     AGE
service/jenkins         ClusterIP   10.101.21.224   <none>        8080/TCP    29s
service/jenkins-agent   ClusterIP   10.102.226.9    <none>        50000/TCP   29s
service/kubernetes      ClusterIP   10.96.0.1       <none>        443/TCP     8d

NAME                       READY   AGE
statefulset.apps/jenkins   0/1     29s
```

デプロイすると上記のようにガイダンスが表示されました。これに従って進めます。
まず、admin のパスワードを確認。

```bash
kubectl exec --namespace default -it svc/jenkins -c jenkins -- /bin/cat /run/secrets/chart-admin-password && echo
Unable to connect to the server: net/http: TLS handshake timeout
```

`Unable to connect to the server: net/http: TLS handshake timeout` と表示されてエラーになる場合、メモリ不足が原因のようなので、Docker Desktop > Reference > Resources から Memory と Swap を増やします。それぞれ以下のようにMemory:4GB、Swap:2GBに設定するとコマンドが通るようになりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/402286/a7b05875-2ab8-672e-7760-330be97a840a.png)


```bash
kubectl exec --namespace default -it svc/jenkins -c jenkins -- /bin/cat /run/secrets/chart-admin-password && echo
w46K0xxxxxxxxxxxxxxxxxx
```

次にポートフォワーディングの設定です。
私はローカル環境の8080を使っていたので、8081で接続できるようにしました。

```bash
kubectl --namespace default port-forward svc/jenkins 8081:8080
Forwarding from 127.0.0.1:8081 -> 8080
Forwarding from [::1]:8081 -> 8080
Handling connection for 8081
:
```

`localhost:8081` に接続するとログイン画面が表示されるので、さきほど確認したパスワードでログインします。
[![Image from Gyazo](https://i.gyazo.com/9d593b9bc779e579a29b7c4e40fd04bd.png)]()

まだ全容がよくわかっていませんが、[Kubernetes plugin for Jenkins](https://plugins.jenkins.io/kubernetes/) が最初からインストールされていて、Jenkinsの管理 > ノードの管理 > Configure Clouds を見ると Kubernetes の設定も登録されていました。 
[![Image from Gyazo](https://i.gyazo.com/e38487c70de4debab363f2c36b4fb5f8.png)]()

[Kubernetes plugin for Jenkins](https://plugins.jenkins.io/kubernetes/) に乗っているサンプルのpipelineのジョブを実行してみると、ジョブを実行するためのPodが作成され、ジョブが終わると削除される様子が見てとれました。

```bash
kubectl get pods -w
k get pods -w
NAME        READY   STATUS    RESTARTS   AGE
jenkins-0   2/2     Running   4          19h
helm-ci-8-9ql0k-n8p68-7g7d9   0/3     Pending   0          0s
helm-ci-8-9ql0k-n8p68-7g7d9   0/3     Pending   0          0s
helm-ci-8-9ql0k-n8p68-7g7d9   0/3     ContainerCreating   0          0s
helm-ci-8-9ql0k-n8p68-7g7d9   3/3     Running             0          30s
helm-ci-8-9ql0k-n8p68-7g7d9   3/3     Terminating         0          65s
helm-ci-8-9ql0k-n8p68-7g7d9   0/3     Terminating         0          98s
helm-ci-8-9ql0k-n8p68-7g7d9   0/3     Terminating         0          110s
helm-ci-8-9ql0k-n8p68-7g7d9   0/3     Terminating         0          110s
```

今回の検証では、helm の話と Kubernetes plugin の話がごっちゃになっていますが、
Kubernetesを学ぶ上では helm の基本的な使い方が確認できて良かったです。
AWSやGCPなどのマネージドサービスにデプロイする場合も、Contextを切り替えれば helm を使って簡単にクラウドにデプロイできるのだと思います。

# 参考リンク
- [GitHub - jenkinsci/helm-charts](https://github.com/jenkinsci/helm-charts)
- [Jenkins Kubernetes Plugin](https://zenn.dev/t_ume/articles/1f0ff59bd82106)
- [Kubernetes plugin for Jenkins](https://plugins.jenkins.io/kubernetes/)
- [How to Setup Jenkins Build Agents on Kubernetes Pods](https://devopscube.com/jenkins-build-agents-kubernetes/)