はじめに
Gitpod をローカルのk8sにインストールしてみたらできなかった件の続編になります。続編のため一応母艦はmacOSではありますが実質的にLinuxでの挑戦となっています。
bindマウントでのsharedプロパゲーションに関してはhyperkit VM側で回避できるかもとも思ったのですが目的から逸脱しそうな感じだったので早々に諦めてしまいました。
元々味見してみるためにローカルで動かすのが目標でしたので「ドメインなし」「SSL証明書なし」でローカルにインストールする流れでいきたいと思います。
なお、前回タイムリーにGitLab連携ができなくなっていた部分に関しても修正されていましたのでGitLabに連携する形で試してみます。
インストール構成
今回ベースをLinuxにしてみるということで、手元にあったVirtualBox(vagrant)上のUbuntu 18_04 にKubernetesを構築してインストールを試みます。ただしブラウザーに関しては母艦のMacBook上のものを使いたかったのでDNS(dnsmasq)はMacBook側で設定し、SSHのポートフォワーディングを使ってUbuntu側のgitpodにアクセスする構成とします。
- ホストOS: macOS Catalina
- VirtualBox 6.1.16/Vagrant 2.2.9
- ゲストOS: Ubuntu 18_04
- Kubernetes: v1.20.0 (k3s)
- Gitpod: 0.6.0
Kubernetesクラスタ構築にはRancher社のk3sを使ってみました。一回つかってみたかったのとローカルへのインストールですしフットプリントは小さい方がいいかなという理由です。この選択によりあとでハマるのですが・・・。
- Kubernetes: ゲストOS上でk3sにより構築
- ドメイン: ホストOS上でdnsmasqでローカルホストDNS構築しgitpod.io-localドメインでアクセス
- HTTPS証明書: 前回HTTPでもアクセスできそうだったのでSSLは使わずHTTPで試す
- MySQL, Docker Registry: 運用では外部サービスの利用が推奨となっているがChartで自動構築されるのでそのまま利用
- HTTPS証明書が準備できない場合は外部のhttpsでアクセス可能なDocker Registryを用いた方がよいです。
- MinIO: クラウド環境の設定を追加しなくても動作可能に修正されていたのでそのまま使う
1. 前提ソフトのインストール(ホスト側)
1.1 Dnsmasqのインストール
前回と同じですので省略します。前回同様でホスト側のDNS設定を127.0.0.1に指定してdnsmasqを参照するようにします。
1.2 VirtualBox+ VagrantをインストールしてUbuntuを起動する
本筋部分ではないのでさらっとですが以下です。
$ brew cask install virtualbox
$ brew install vagrant
$ vagrant init bento/ubuntu-18.04
$ vagrant up
sshでポートフォワードしつつ接続します。ここではゲストOSのIPアドレスが10.0.2.15
であると仮定します。
なおプロンプトが$
の場合はホストOS(macOS)、プロンプトが$$
の場合はゲストOS(Ubuntu)として表記してます。
$ sudo ssh -p 2222 -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o LogLevel=ERROR -o IdentitiesOnly=yes -i ~/.vagrant.d/insecure_private_key -L 80:10.0.2.15:80 -g vagrant@127.0.0.1
最初にsudo のパスワード(macOS側の管理者パスワード)、次にvagrantによるsshログインのパスワードが聞かれるのでそれぞれ入力します。vagrantユーザのパスワードはおそらくvagrant
です。
2. 前提ソフトのインストール(ゲスト側)
2.1 k3sのインストール(兼Kubernnetesインストール)
ゲスト側でおもむろにインストールスクリプトを動かす。
$$ curl -sfL https://get.k3s.io | sh -
[INFO] Finding release for channel stable
[INFO] Using v1.20.0+k3s2 as release
[INFO] Downloading hash https://github.com/rancher/k3s/releases/download/v1.20.0+k3s2/sha256sum-amd64.txt
[INFO] Downloading binary https://github.com/rancher/k3s/releases/download/v1.20.0+k3s2/k3s
[INFO] Verifying binary download
[INFO] Installing k3s to /usr/local/bin/k3s
[INFO] Creating /usr/local/bin/kubectl symlink to k3s
[INFO] Creating /usr/local/bin/crictl symlink to k3s
[INFO] Creating /usr/local/bin/ctr symlink to k3s
[INFO] Creating killall script /usr/local/bin/k3s-killall.sh
[INFO] Creating uninstall script /usr/local/bin/k3s-uninstall.sh
[INFO] env: Creating environment file /etc/systemd/system/k3s.service.env
[INFO] systemd: Creating service file /etc/systemd/system/k3s.service
[INFO] systemd: Enabling k3s unit
Created symlink /etc/systemd/system/multi-user.target.wants/k3s.service → /etc/systemd/system/k3s.service.
[INFO] systemd: Starting k3s
以上、これだけでkubectlが叩ける状態になります・・・びっくりするほど簡単ですね。
k3sのcontainerdで正規の証明書じゃなくてもregistryにアクセスできるようにする
これはドメインも証明書も正規のものではない今回のローカル構成による独自手順です。
gitpodのインストールでは構築される各Podと連携するregistryポッドの証明書が生成されるのでPod内からregistryへのアクセスはできるのですがgitpodで実際にユーザが使うワークスペース用のPodを起動するときにノードがこのregistryからイメージをpullできる必要があります。そこで今回は証明書検証をスキップしてアクセスできるように設定します。
ちなみに正規の証明書がある場合は証明書の設定されたproxyポッド経由でregistryにアクセスするように構成されるのでこの手順は不要です。あくまでもローカルで強引に動かす場合の設定です。
ゲストOSの/etc/rancher/k3s/registries.yaml
を修正します。
configs:
"registry.gitpod.io-local":
tls:
insecure_skip_verify: true
k3sを再起動しておきましょう。
$$ systemctl restart k3s
2.2 Helm インストール
Linuxへのインストールはスクリプトが公式っぽいのでスクリプトでいれます。
$$ curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3
$$ chmod 700 get_helm.sh
$$ ./get_helm.sh
HelmとKubernetesの疎通ができているか確認します。
$$ helm list
Error: Kubernetes cluster unreachable: an error on the server ("") has prevented the request from succeeding
どうやらk3sでKubernetesを構築した場合configが/etc/rancher/k3s/k3s.yaml
に配置されるのですがHelm側が認知していない感じです。
Helmが参照するconfigをKUBECONFIG環境変数で調整します(k3sで構築しなければ不要な気がします)
export KUBECONFIG=/etc/rancher/k3s/k3s.yaml
必要に応じて.bashrc等に追記しておきましょう。
3. GitLabとの連携
の手順どおりにGitLabへの認証連携を設定します。
GitLabの画面右上のメニューからSettings --> Applicationから連携アプリを追加します。
Application ID
とSecret
を覚えておきます。
4. Gitpodのインストール
4.1 HelmでのGitpodインストール準備
前回の記事ではHelmのリポジトリからインストールしましたが、だいぶこまめにハマるのでGitHubの開発リポジトリのビルドからインストールします。
GitHubリポジトリ内のドキュメントにブランチビルドのインストール方法が書いてあります。
WerftのCIジョブをみてビルド番号をみつけて、その成果物のDockerイメージからChart一式を引っこ抜くようです。
リリース系の場合はgcr.io/gitpod-io/self-hosted/installer:0.6.0
で
ブランチビルド系の場合はeu.gcr.io/gitpod-core-dev/build/installer:master.361
のような感じになるようです。
じつはこの記事を書くために試行錯誤してる最中にv0.6.0がでたのでそれを使います。
$ docker run --entrypoint cp -v $PWD:/workspace gcr.io/gitpod-io/self-hosted/installer:0.6.0 -R /dist/helm/ /workspace
カレントディレクトリ配下に次のようなディレクトリ一式ができていると思います。
.
|-helm
|---gitpod
|-----charts
|-----config
|-------db
|---------init
|-------proxy
|---------debug
|-----secrets
|-------messagebus
|-----templates
これらをvagrantのゲストOS側にコピーします。
4.2 valuesファイルの変更
ゲストOS側でコピーした一式のフォルダのhelm/gitpodに移動して設定上書き用のファイルvalue-over.yamlを作成します。
$$ cd helm/gitpod
$$ vi value-over.yaml
同じディレクトリにvalues.yamlファイルがあるので参考にしつつvalues-over.yamlを次のようにしました。
hostname: gitpod.io-local
certificatesSecret:
# 今回はhttpでホストするので空文字指定
secretName:
authProviders:
- id: Public-GitHub
type: GitHub
description: ""
host: github.com
icon: ""
oauth:
callBackUrl: http://gitpod.io-local/auth/github/callback
clientId: <GitHubのクライアントID>
clientSecret: <GitHubのクライアントシークレット>
settingsUrl: https://github.com/settings/connections/applications/07c7d6d4b7f6ae70af91
- id: Public-GitLab
type: GitLab
description: ""
host: gitlab.com
icon: ""
oauth:
callBackUrl: http://gitpod.io-local/auth/gitlab/callback
clientId: <GitLabのアプリケーションID>
clientSecret: <GitLabのシークレット>
settingsUrl: https://gitlab.com/profile/applications
components:
wsDaemon:
containerRuntime:
containerd:
# containerdソケットを指定。利用するディストリビューションに応じて適切に
socket: /run/k3s/containerd/containerd.sock
nodeRoots:
- /var/lib
# コンテナのイメージが格納されるパスを指定
- /run/k3s/containerd/io.containerd.runtime.v2.task/k8s.io
このvalues-over.yamlファイルを利用してクラスタにインストールします。
$$ helm install gitpod -f values-over.yaml .
NAME: gitpod
LAST DEPLOYED: Thu Jan 21 17:18:27 2021
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
サービスやポッドが起動しているか確認します。
$$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.43.0.1 <none> 443/TCP 1d
registry-facade ClusterIP 10.43.79.189 <none> 3000/TCP 21h
ws-manager ClusterIP 10.43.115.21 <none> 8080/TCP 21h
theia-server ClusterIP 10.43.18.240 <none> 80/TCP 21h
messagebus ClusterIP 10.43.150.23 <none> 5672/TCP,25672/TCP,4369/TCP,15672/TCP 21h
image-builder ClusterIP 10.43.19.170 <none> 8080/TCP 21h
server ClusterIP 10.43.174.199 <none> 3000/TCP,9500/TCP 21h
dashboard ClusterIP 10.43.17.212 <none> 3001/TCP 21h
mysql ClusterIP 10.43.157.89 <none> 3306/TCP 21h
blobserve ClusterIP 10.43.119.114 <none> 4000/TCP 21h
db ClusterIP 10.43.55.222 <none> 3306/TCP 21h
minio ClusterIP 10.43.245.25 <none> 9000/TCP 21h
registry ClusterIP 10.43.139.178 <none> 443/TCP 21h
ws-proxy ClusterIP 10.43.84.175 <none> 8080/TCP 21h
proxy LoadBalancer 10.43.189.32 10.0.2.15 80:30176/TCP,443:31198/TCP 21h
$$ kubectl get pod
NAME READY STATUS RESTARTS AGE
registry-facade-bfx4n 1/1 Running 0 21h
dashboard-5fffd64d9c-4khzw 1/1 Running 0 21h
proxy-57885ffb6c-5z45f 1/1 Running 0 21h
blobserve-84ff95cb56-wdvfn 1/1 Running 0 21h
ws-manager-74d5897964-bzf9t 1/1 Running 0 21h
theia-server-7b9fc949d6-q7j87 1/1 Running 0 21h
svclb-proxy-zsqkk 2/2 Running 0 21h
image-builder-7ccb77458c-8l6mb 2/2 Running 0 21h
ws-scheduler-8488f68555-956d7 1/1 Running 0 21h
node-daemon-6zr28 1/1 Running 0 21h
ws-daemon-4j22v 1/1 Running 0 21h
ws-proxy-64cfddd46-td4d5 1/1 Running 0 21h
minio-6d7bd56fcc-pfff7 1/1 Running 0 21h
messagebus-58fdd99865-2zh5w 1/1 Running 0 21h
mysql-7cbb9c9586-stpxw 1/1 Running 0 21h
server-5b945dcfbd-csdkd 1/1 Running 0 21h
ws-manager-bridge-ffff794f6-cztpw 1/1 Running 4 21h
registry-77ccc846c-bvg8t 1/1 Running 0 21h
4.3 Dnsmasqの設定変更
registryサービスのClusterIPも10.97.219.208でふられていますので
ホスト側(macOS)側の/usr/local/etc/dnsmasq.confを次のように更新してDnsmasqを再起動します。
address=/gitpod.io-local/192.168.11.2
address=/registry.gitpod.io-local/10.43.139.178
5. 動作確認
ホスト側(macOS)でブラウザを起動して http://gitpod.io-local/ にアクセスします。
画面右上の「Login」からGitLabを選択してGitLabでログインします。
お試し用に適当なGitLabプロジェクトのURLをコピーしておいてブラウザ上でURLに以下のように打ち込みます。
http://gitpod.io-local/#<GitLabプロジェクトのURL>
初回はワークスペース用のコンテナイメージを作成するので数十分くらい待ちますが・・・うまくいけば・・・
こんな感じでワークスペースの開発画面が表示されます!
トラブルシュートメモ
ws-manager-bridgeポッドが起動しない
$$ kubectl logs ws-manager-bridge-xxxxxx
でログを確認してみてno exchange 'gitpod.ws.local' in vhost '/'
のようなエラーが発生する場合、messagebusポッドのRabbitMQを再コンフィグします。
$$ kubectl exec messagebus-58fdd99865-5vv5q --stdin --tty -- /bin/bash
bash-5.0$ /usr/local/bin/configure.sh
Waiting for pid file '/var/run/rabbitmq-pid/rabbitmq.pid' to appear
pid is 303
Waiting for erlang distribution on node 'rabbit@messagebus-58fdd99865-5vv5q' while OS process '303' is running
Waiting for applications 'rabbit_and_plugins' to start on node 'rabbit@messagebus-58fdd99865-5vv5q'
Applications 'rabbit_and_plugins' are running on node 'rabbit@messagebus-58fdd99865-5vv5q'
exchange declared
exchange declared
exchange declared
*** Not found: /api/bindings/%2F/e/gitpod.ws.local/q/gitpod.ws
exchange declared
All configuration done.
proxyサービスがPendingのまま
サービスを確認したときにproxyポッドもしくはサービスが上がってこない場合
$$ kubectl get svc
で確認してみます。proxyサービスがPending
になっている場合、
External IPがTraefikで使われているためバインドできない可能性があります。
k3sだとデフォルトでtraefikがインストールされるのでtraefikがExternal IPをバインドしていて使えないようです。
最初からtraefikを使わないモードでインストールすれば良かったのですが、ここではtraefikを削除して対応します。
$$ kubectl -n kube-system delete helmcharts.helm.cattle.io traefik
ワークスペースのコンテナが起動してこない
ws-<ワークスペースID>
のようなポッドはできているのだが起動しきらない現象で2つパターンがありました。
1つはワークスペースが空のままで、Readiness Probeが失敗するケース。gitpodで使われているKubernetesクライアントのバージョンだと今回利用したv1.20.0+k3s2だとKubernetesのバージョン(v1.20.0)が新し過ぎて一部の呼び出しがエラーになるようです。ただv0.6.0のリリース直前にクライアントライブラリのバージョンがアップされたので一応v1.20.0でも動くようになりました。
にもKubernetesのバージョンが明記されるようになったのでv0.6.0時点だと1.15 <= x <= 1.17にした方が無難そうです。
もう1つは以下のようにポッドを起動する適切なノードが見つからないエラーです。
Warning FailedScheduling 4m46s workspace-scheduler no suitable node found: zero nodes available
gitpodをインストールしたときにノードラベルが設定されて、それを目印にワークスペース用のポッドを起動するようです。一方でgitpod 0.5.0の時点でhelm uninstall
したときにノードのラベルが残ったままになるという不具合があり、同一のKubernetesクラスタで試行錯誤したので古いバージョンのノードラベルが残ったままになっていました。結果として目印が見つからない状態になっていたようです。
v0.5.0のノードラベルを消して、
$$ kubectl label node <ノード名> gitpod.io/theia.0.5.0-
$$ kubectl label node <ノード名> gitpod.io/ws-sync-
v0.6.0の新しいノードラベルを設定します。(もしくはいったんアンインストールしてインストールし直すでも可)
kubectl label node <ノード名> gitpod.io/theia.0.6.0=available
kubectl label node <ノード名> gitpod.io/ws-daemon=available
※余談ですがv0.6.0からワークスペースを準備するコンポーネントがws-syncがws-daemonに名称変更されています。
まとめ
さて、ドキュメントの構成と変えているせいもありますが今回だいぶ苦労してしまいました・・・。
学びとしては以下あたりです。
- GitHubのリポジトリをみるのがよさげ。
- Kubernetesのバージョンは気にしよう。
- ディストリビューションも気にしよう。デフォルトの設定はkubeadmかminikubeあたりがよさげです。
- registryはクラスタ外のものを利用したほうがよさげ。
というかトラブルシュートしたおかげでだいぶお勉強になりました。
参考文献
この記事は以下の情報を参考にして執筆しました。
また、
- GitLab は、GitLab B.V. の米国およびその他の国における登録商標もしくは商標です。
- GitHub は、GitHub Inc. の米国およびその他の国における登録商標もしくは商標です。
- その他の記載されている会社名、製品名、サービス名、ロゴ等は各社の商標または登録商標です。