[k8s]ローカルのMac環境でHelmを使ってKubernetesの環境を構築する

最近、Kubernetes(以下、k8s)をガシガシさわっております。

k8s自体の学習については弊社ブログでチュートリアルの紹介をしているので、ぜひこちらを御覧ください。

【EKSWorkshop】EKSやkubernetes周辺を効率よく学ぶのにオススメなチュートリアル集 | DevelopersIO

k8sと戯れていると、これでもかというくらいyamlファイルを書かされます。

もうちょっと簡単にデプロイできんのかということで、Helmを使ってみたので本記事はその備忘録です。

Helmとは

公式サイトでは、「Helm helps you manage Kubernetes applications」と説明されています。

Helm Docs | Helm

一言でざっくりいうと、k8s用のパッケージ管理システムです。

k8sの様々なリソース(Deployment, Service, PersistentVolume等)を一つのパッケージ(Helmでは チャート と呼ぶ)にまとめて管理する仕組みです。

ざっくり構成図

Helmを使おうと思ったんですが、登場人物が多くて混乱しました。 全体像がなかなかよくわかりませんでした。 なので、MacでHelmを使ってk8sの環境を構築する時のざっくりとした全体像を図にします。

重要な登場人物は以下5つです。

  • Docker for Mac:k8sクラスタをMac上に作るアプリケーションです。
  • context:操作対象となるk8sクラスタを設定します。kubectlコマンドで変更できます。
  • kubectlコマンド:contextでどのk8sクラスタを操作対象にするか設定します。k8sの状態を見るのに使用します。
  • tiller:helmコマンドから命令を受けて、k8sクラスタにデプロイをします。tiller自体もk8sクラスタ上に作られます。
  • helmコマンド:tillerの作成をします。tillerに対してデプロイ命令をします。

大枠をざっくり理解できたら、チュートリアルやコマンドを実行しながら詳細な理解を深めてください。

構築手順

Docker for Macの設定

まずは公式ページからDocker for Macをインストールします。

Get started with Docker Desktop for Mac | Docker Documentation

今回はより新しいバージョンで試したかったので、Edgeバージョンをインストールしています。

Docker Desktop for Mac - Docker Hub

本記事執筆時のEdgeバージョンはこんな感じです。

インストールができたら、デフォルトではk8sが有効になっていません。Preferencesからk8sを有効にします。

「Kubernetes is running」になったら、とりあえずOKです。

kubectlの設定

インストールが楽なので、MacのパッケージマネージャーであるHomebrewを使用します。 homebrewについては、公式サイトを御覧ください。

The missing package manager for macOS (or Linux) — Homebrew

Homebrewが入っていれば、以下のコマンドでkubectlのインストールが可能です。

$ brew install kubectl
$ kubectl version
Client Version: version.Info{Major:"1", Minor:"15", GitVersion:"v1.15.0", GitCommit:"e8462b5b5dc2584fdcd18e6bcfe9f1e4d970a529", GitTreeState:"clean", BuildDate:"2019-06-20T04:49:16Z", GoVersion:"go1.12.6", Compiler:"gc", Platform:"darwin/amd64"}
Server Version: version.Info{Major:"1", Minor:"14", GitVersion:"v1.14.3", GitCommit:"5e53fd6bc17c0dec8434817e69b04a25d8ae0ff0", GitTreeState:"clean", BuildDate:"2019-06-06T01:36:19Z", GoVersion:"go1.12.5", Compiler:"gc", Platform:"linux/amd64"}

kubectlのインストールができたら、コンテキストを確認します。

$ kubectl config get-contexts
CURRENT   NAME             CLUSTER          AUTHINFO         NAMESPACE
*         docker-desktop   docker-desktop   docker-desktop 

CURRENTがdocker-desktopになっていなかった場合、使用するクラスタをdocker-desktopに切り替えます。

$ kubectl config use-context docker-desktop
Switched to context "docker-desktop".

クラスタが参照できているかどうか、とりあえずpodsを確認してみます。

$ kubectl get pods -A
NAMESPACE     NAME                                     READY   STATUS    RESTARTS   AGE
docker        compose-6c67d745f6-gntpn                 1/1     Running   0          81s
docker        compose-api-57ff65b8c7-hl8pm             1/1     Running   0          81s
kube-system   coredns-fb8b8dccf-wfqgq                  1/1     Running   0          2m21s
kube-system   coredns-fb8b8dccf-xl742                  1/1     Running   0          2m21s
kube-system   etcd-docker-desktop                      1/1     Running   0          81s
kube-system   kube-apiserver-docker-desktop            1/1     Running   0          82s
kube-system   kube-controller-manager-docker-desktop   1/1     Running   0          83s
kube-system   kube-proxy-n9st4                         1/1     Running   0          2m20s
kube-system   kube-scheduler-docker-desktop            1/1     Running   0          85s

Helmの設定

Homebrewが入っていれば、以下のコマンドでHelmがインストールできます。インストールしたら、とりあえずリポジトリのアップデートをしましょう。

$ brew install kubernetes-helm
$ helm version
Client: &version.Version{SemVer:"v2.14.1", GitCommit:"5270352a09c7e8b6e8c9593002a73535276507c0", GitTreeState:"clean"}
Server: &version.Version{SemVer:"v2.14.1", GitCommit:"5270352a09c7e8b6e8c9593002a73535276507c0", GitTreeState:"clean"}
$ helm repo update

以下のコマンドを実行するとクラスタにtillerを作成できます。

$ helm init

ここでもう一度podsを確認すると、tillerのpodが増えていることがわかります。

$ kubectl get pods -A
NAMESPACE     NAME                                     READY   STATUS    RESTARTS   AGE
docker        compose-6c67d745f6-gntpn                 1/1     Running   0          100s
docker        compose-api-57ff65b8c7-hl8pm             1/1     Running   0          100s
kube-system   coredns-fb8b8dccf-wfqgq                  1/1     Running   0          2m40s
kube-system   coredns-fb8b8dccf-xl742                  1/1     Running   0          2m40s
kube-system   etcd-docker-desktop                      1/1     Running   0          100s
kube-system   kube-apiserver-docker-desktop            1/1     Running   0          101s
kube-system   kube-controller-manager-docker-desktop   1/1     Running   0          102s
kube-system   kube-proxy-n9st4                         1/1     Running   0          2m39s
kube-system   kube-scheduler-docker-desktop            1/1     Running   0          104s
kube-system   tiller-deploy-66b7dd976-5d8mj            0/1     Running   0          5s

Helmパッケージ(チャート)のインストール

tillerの導入まで終わって準備ができたので、いよいよチャートのインストールをします。
どんなチャートがあるかは helm search <チャート名> で検索することができます。

$ helm search jenkins
NAME            CHART VERSION   APP VERSION     DESCRIPTION                                                 
stable/jenkins  1.3.5           lts             Open source continuous integration server. It supports mu...

とりあえずjenkinsおじさんをデプロイしてみましょう。 helm upgrade --install <リリース名> <チャート名> でk8sへのデプロイができます。

$ helm upgrade --install jenkins stable/jenkins
<<省略>>
NOTES:
1. Get your 'admin' user password by running:
  printf $(kubectl get secret --namespace default jenkins -o jsonpath="{.data.jenkins-admin-password}" | base64 --decode);echo
2. Get the Jenkins URL to visit by running these commands in the same shell:
  NOTE: It may take a few minutes for the LoadBalancer IP to be available.
        You can watch the status of by running 'kubectl get svc --namespace default -w jenkins'
  export SERVICE_IP=$(kubectl get svc --namespace default jenkins --template "{{ range (index .status.loadBalancer.ingress 0) }}{{ . }}{{ end }}")
  echo http://$SERVICE_IP:8080/login

3. Login with the password from step 1 and the username: admin


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

Helmでデプロイを行うといろいろ情報が出力されます。特に NOTES: に結構重要な情報が出力されたりします。 Jenkinsではadminパスワードの取得コマンドが載っているので、この通りに実行してパスワードを取得します。

$ printf $(kubectl get secret --namespace default jenkins -o jsonpath="{.data.jenkins-admin-password}" | base64 --decode);ech

http://localhost:8080/login にアクセスして、先程取得したパスワードを入力します。

無事Jenkinsおじさんを動かすことができました!

その他確認

helm ls コマンドで、今Helmで何がリリースされているか確認できます。

$ helm ls
NAME    REVISION        UPDATED                         STATUS          CHART           APP VERSION     NAMESPACE
jenkins 1               Mon Jul  8 14:43:09 2019        DEPLOYED        jenkins-1.3.5   lts             default 

デプロイはhelmコマンドで実施しましたが、実際はk8sで構築されているので、kubectlでpodsを確認してみると、Jenkinsのpodが動いているのがわかります。

$ kubectl get pods
NAME                       READY   STATUS    RESTARTS   AGE
jenkins-6cb57f8d68-vpbrz   1/1     Running   0          2m29s

kubectlでserviceを確認してみると、8080番ポートでlocalhostに公開されていることがわかります。

$ kubectl get service
NAME            TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
jenkins         LoadBalancer   10.101.201.235   localhost     8080:31305/TCP   3m48s
jenkins-agent   ClusterIP      10.98.107.125    <none>        50000/TCP        3m48s
kubernetes      ClusterIP      10.96.0.1        <none>        443/TCP          38m

削除方法

helm delete --purge <リリース名> で削除できます。

$ helm delete --purge jenkins
release "jenkins" deleted

ちなみに、--purge オプションを入れないと完全な削除になりません。削除したという記録が残ります。--purge オプションを入れると削除した記録も残さず完全削除になります。

$ helm delete jenkins
$ helm ls --deleted
NAME    REVISION        UPDATED                         STATUS  CHART           APP VERSION     NAMESPACE
jenkins 1               Mon Jul  8 14:51:01 2019        DELETED jenkins-1.3.5   lts             default

そのため、同じ名前でリリースしようとすると怒られます。

$ helm upgrade --install jenkins stable/jenkins
UPGRADE FAILED
Error: "jenkins" has no deployed releases
Error: UPGRADE FAILED: "jenkins" has no deployed releases

さいごに

Helmを使うことで、簡単にローカルMac環境のk8sクラスタへのデプロイをすることができました。
ローカルのk8sクラスタを使っていれば、いくらk8sクラスタを壊しても怒られません。 これで心置きなくk8sの検証を進められそうです。
k8sはまだまだわからないことだらけなので、ガンガンさわっていきたいと思います!